diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..132aa30
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,11 @@
+FROM node:18-alpine
+
+WORKDIR /app
+
+COPY package.json ./
+
+RUN yarn install
+
+COPY . .
+
+CMD ["yarn", "start"]
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..f694431
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,11 @@
+services:
+ parafiaborzeta:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ container_name: parafiaborzeta
+ ports:
+ - '3000:3000'
+ volumes:
+ - .:/app
+ - /app/node_modules
\ No newline at end of file
diff --git a/src/app/components/navigation_bar.component.tsx b/src/app/components/navigation_bar.component.tsx
deleted file mode 100644
index 91416d6..0000000
--- a/src/app/components/navigation_bar.component.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-export default function NavigationBar() {
- return
-}
\ No newline at end of file
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 84644e9..ad872a2 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,23 +1,56 @@
+'use client'
+
import { Montserrat } from "next/font/google";
-import type { Metadata } from "next";
+import { useState, useEffect } from "react";
+
+import NavigationBar from "@/components/navigation_bar.component";
+import { ThemeProvider } from "@/providers/theme.provider";
+import { GlobalLayout, MainBlock } from "@/styles";
+import Loader from "@/components/loader.component";
const inter = Montserrat({ subsets: ["latin"] });
-export const metadata: Metadata = {
- title: "Parafia pw. Niepokalanego Serca NMP w Borzęcie",
- description: "Parafia pw. Niepokalanego Serca NMP w Borzęcie",
-};
-
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
- return (
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ const handleComplete = () => setLoading(false);
+
+ // simulate loading delay
+ const timer = setTimeout(handleComplete, 1000);
+ return () => clearTimeout(timer);
+ }, []);
+
+ return <>
+ {/*
+ can't use next.Metadata,
+ because 'use client' + styled components are
+ preventing it.
+
+ next/head wouldn't work too, so legacy solution is used
+ */}
+
+ Parafia pw. Niepokalanego Serca NMP w Borzęcie
+
+
- {children}
+
+
+ {loading
+ ?
+ : <>
+
+
+ {children}
+
+ >}
+
- );
+ >;
}
\ No newline at end of file
diff --git a/src/app/page.tsx b/src/app/page.tsx
index aa73995..1934cc5 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,26 +1,17 @@
'use client'
-import { ThemeProvider } from "styled-components";
-
-import { Button, GlobalLayout, MainBlock } from "./styles";
-import { Theme, darkTheme, lightTheme } from "./themes";
-import useLocalStorage from "./utils/local_storage";
-
-const themes: Record = {
- light: lightTheme,
- dark: darkTheme
-}
+import { useTheme } from "@/providers/theme.provider";
+import { Button } from "../styles";
export default function Home() {
- const [theme, setTheme] = useLocalStorage("theme", "light");
+ const { theme, toggleTheme } = useTheme();
- return
-
-
- Parafia w Borzęcie
- Już wkrótce powstanie tutaj świeża strona parafii pod wezwaniem Niepokalanego Serca Maryi w Borzęcie.
- zadzwoń do proboszcza
-
-
- ;
+ return <>
+ Parafia w Borzęcie
+ Już wkrótce powstanie tutaj świeża strona parafii pod wezwaniem Niepokalanego Serca Maryi w Borzęcie.
+ zadzwoń do proboszcza
+
+ Aktualny motyw: {theme}
+
+ >;
}
\ No newline at end of file
diff --git a/src/app/themes.tsx b/src/app/themes.tsx
index 57bc4de..6ed032c 100644
--- a/src/app/themes.tsx
+++ b/src/app/themes.tsx
@@ -1,17 +1,18 @@
+export type ThemeMode = 'light' | 'dark'
export interface Theme {
background: string,
- padding: number,
+ space_px: number,
text: string
}
export const darkTheme: Theme = {
- padding: 10,
+ space_px: 10,
background: "#2f3136",
text: "#fff"
}
export const lightTheme: Theme = {
- padding: 10,
+ space_px: 10,
background: "#eee",
text: "#000"
}
\ No newline at end of file
diff --git a/src/components/loader.component.tsx b/src/components/loader.component.tsx
new file mode 100644
index 0000000..e283e97
--- /dev/null
+++ b/src/components/loader.component.tsx
@@ -0,0 +1,34 @@
+import styled, { keyframes } from "styled-components";
+
+const spin = keyframes`
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+`;
+
+const LoaderOverlay = styled.div`
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(255, 255, 255, 0.8);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 1000;
+`;
+
+const Spinner = styled.div`
+ border: 8px solid ${({ theme }) => theme.text};
+ border-top: 8px solid ${({ theme }) => theme.background};
+ border-radius: 50%;
+ width: 50px;
+ height: 50px;
+ animation: ${spin} 1s linear infinite;
+`;
+
+export default function Loader() {
+ return
+
+
+};
\ No newline at end of file
diff --git a/src/components/navigation_bar.component.tsx b/src/components/navigation_bar.component.tsx
new file mode 100644
index 0000000..333581f
--- /dev/null
+++ b/src/components/navigation_bar.component.tsx
@@ -0,0 +1,33 @@
+import styled from "styled-components"
+import Link from "next/link"
+
+export default function NavigationBar() {
+ return
+ Parafia w Borzęcie
+
+ Strona główna
+ Kontakt
+
+
+}
+
+const Navigation = styled.nav`
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ padding: ${({ theme }) => theme.space_px}px;
+ position: fixed;
+ width: 100%;
+ left: 0;
+ top: 0;
+`
+
+const NavigationLinks = styled.ul`
+ list-style-type: none;
+ li {
+ margin: ${({ theme }) => theme.space_px}px;
+ display: block;
+ float: left;
+ }
+`
\ No newline at end of file
diff --git a/src/providers/theme.provider.tsx b/src/providers/theme.provider.tsx
new file mode 100644
index 0000000..5184308
--- /dev/null
+++ b/src/providers/theme.provider.tsx
@@ -0,0 +1,41 @@
+import { createContext, useContext, useMemo, PropsWithChildren } from "react";
+import { ThemeProvider as StyledThemeProvider } from "styled-components";
+
+import { ThemeMode, lightTheme, darkTheme } from "@/app/themes";
+import useLocalStorage from "@/utils/local_storage";
+
+const ThemeContext = createContext({
+ theme: "light",
+ toggleTheme: () => { },
+} as {
+ theme: ThemeMode,
+ toggleTheme: () => void
+});
+
+export const ThemeProvider = ({ children }: PropsWithChildren) => {
+ const [theme, setTheme] = useLocalStorage("theme", "light");
+
+ const toggleTheme = () => {
+ setTheme(previous => previous === "light" ? "dark" : "light");
+ };
+
+ const value = useMemo(() => ({ theme, toggleTheme }), [theme]);
+
+ return (
+
+
+ {children}
+
+
+ );
+};
+
+export const useTheme = () => {
+ const context = useContext(ThemeContext);
+
+ if (!context) {
+ throw new Error("useTheme must be used within a ThemeProvider");
+ }
+
+ return context;
+};
\ No newline at end of file
diff --git a/src/app/styles.tsx b/src/styles.tsx
similarity index 92%
rename from src/app/styles.tsx
rename to src/styles.tsx
index 52376a8..0df1e2d 100644
--- a/src/app/styles.tsx
+++ b/src/styles.tsx
@@ -39,7 +39,8 @@ export const MainBlock = styled.main`
export const Button = styled.button`
border: none;
outline: none;
- padding: ${({ theme }) => theme.padding}px;
+ cursor: pointer;
+ padding: ${({ theme }) => theme.space_px}px;
color: ${({ theme }) => theme.background};
background-color: ${({ theme }) => theme.text};
`;
\ No newline at end of file
diff --git a/src/app/types/styled-components.d.ts b/src/types/styled-components.d.ts
similarity index 100%
rename from src/app/types/styled-components.d.ts
rename to src/types/styled-components.d.ts
diff --git a/src/app/utils/local_storage.ts b/src/utils/local_storage.ts
similarity index 95%
rename from src/app/utils/local_storage.ts
rename to src/utils/local_storage.ts
index 7c23baf..1ff60c8 100644
--- a/src/app/utils/local_storage.ts
+++ b/src/utils/local_storage.ts
@@ -9,8 +9,9 @@ export default function useLocalStorage(
useEffect(() => {
const item = window.localStorage.getItem(key)
+
if (item) {
- setValue(JSON.parse(item))
+ setValue(JSON.parse(item))
}
return () => {