diff --git a/next.config.ts b/next.config.ts index e9ffa30..d71ac07 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,27 @@ import type { NextConfig } from "next"; +import createNextIntlPlugin from "next-intl/plugin"; + +const withNextIntl = createNextIntlPlugin("./src/i18n/request.ts"); const nextConfig: NextConfig = { - /* config options here */ + async headers() { + return [ + { + source: "/(.*)", + headers: [ + { + key: "Content-Security-Policy", + value: + "frame-src 'self' https://tipilan.ee https://player.twitch.tv https://embed.twitch.tv; frame-ancestors 'self' https://tipilan.ee;", + }, + { + key: "X-Frame-Options", + value: "SAMEORIGIN", + }, + ], + }, + ]; + }, }; -export default nextConfig; +export default withNextIntl(nextConfig); diff --git a/package.json b/package.json index 7c55e31..7ecec4f 100644 --- a/package.json +++ b/package.json @@ -15,47 +15,46 @@ "drizzle:studio": "drizzle-kit studio" }, "dependencies": { - "@libsql/client": "^0.15.9", + "@libsql/client": "^0.15.12", "@paralleldrive/cuid2": "^2.2.2", - "@radix-ui/react-alert-dialog": "^1.1.14", - "@radix-ui/react-dropdown-menu": "^2.1.15", - "@radix-ui/react-select": "^2.2.5", + "@radix-ui/react-alert-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-slot": "^1.2.3", - "@radix-ui/react-tooltip": "^1.2.7", + "@radix-ui/react-tooltip": "^1.2.8", "@tanstack/react-table": "^8.21.3", "@types/three": "^0.178.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "drizzle-orm": "^0.44.2", - "gray-matter": "^4.0.3", + "drizzle-orm": "^0.44.4", "lucide-react": "^0.522.0", - "material-symbols": "^0.31.8", + "material-symbols": "^0.31.9", "next": "15.3.0", + "next-intl": "^4.3.4", "next-themes": "^0.4.6", "react": "^19.1.1", "react-dom": "^19.1.1", "react-icons": "^5.5.0", "react-markdown": "^10.1.0", - "remark-gfm": "^4.0.1", "tailwind-merge": "^3.3.1", "three": "^0.178.0", - "tw-animate-css": "^1.3.4" + "tw-animate-css": "^1.3.7" }, "devDependencies": { "@eslint/eslintrc": "^3.3.1", - "@tailwindcss/postcss": "^4.1.10", - "@types/bun": "^1.2.18", - "@types/node": "^20.19.1", - "@types/react": "^19.1.9", + "@tailwindcss/postcss": "^4.1.12", + "@types/bun": "^1.2.20", + "@types/node": "^20.19.11", + "@types/react": "^19.1.10", "@types/react-dom": "^19.1.7", "autoprefixer": "^10.4.21", - "dotenv": "^16.3.1", + "dotenv": "^16.6.1", "drizzle-kit": "^0.31.4", - "eslint": "^9.29.0", + "eslint": "^9.33.0", "eslint-config-next": "15.3.0", "postcss": "^8.5.6", - "tailwindcss": "^4.1.10", + "tailwindcss": "^4.1.12", "ts-node": "^10.9.2", - "typescript": "^5.8.3" + "typescript": "^5.9.2" } } diff --git a/public/spaces/fuajeeTalTech.glb b/public/spaces/fuajeeTalTech.glb new file mode 100644 index 0000000..04d3eff Binary files /dev/null and b/public/spaces/fuajeeTalTech.glb differ diff --git a/public/sponsors/tallinnaharidusamet.jpg b/public/sponsors/tallinnaharidusamet.jpg new file mode 100644 index 0000000..c8ff4ad Binary files /dev/null and b/public/sponsors/tallinnaharidusamet.jpg differ diff --git a/src/app/[locale]/ajakava/page.tsx b/src/app/[locale]/ajakava/page.tsx new file mode 100644 index 0000000..bc608ab --- /dev/null +++ b/src/app/[locale]/ajakava/page.tsx @@ -0,0 +1,77 @@ +"use client"; + +import { useState } from "react"; +import { vipnagorgialla } from "@/components/Vipnagorgialla"; +import { scheduleData } from "@/data/timetable"; +import SectionDivider from "@/components/SectionDivider"; +import { useTranslations } from "next-intl"; + +const tabs = Object.keys(scheduleData); + +export default function Timetable() { + const [activeTab, setActiveTab] = useState(tabs[0]); + const schedule = scheduleData[activeTab]; + const t = useTranslations(); + + return ( +
+
+

+ {t("schedule.title")} +

+ + {/* Tab menu */} +
+ {tabs.map((tab) => ( + + ))} +
+ + {/* Schedule entries */} +
+ {schedule.map((item, idx) => ( +
+
+ {item.time} +
+
+
+ {t(item.titleKey)} +
+ {item.description && ( +
+ {item.description} +
+ )} +
+ {t(item.locationKey)} +
+
+
+ ))} +
+
+ + +
+ ); +} diff --git a/src/app/haldus/meeskonnad/page.tsx b/src/app/[locale]/haldus/meeskonnad/page.tsx similarity index 75% rename from src/app/haldus/meeskonnad/page.tsx rename to src/app/[locale]/haldus/meeskonnad/page.tsx index d86a6a3..7dfe269 100644 --- a/src/app/haldus/meeskonnad/page.tsx +++ b/src/app/[locale]/haldus/meeskonnad/page.tsx @@ -7,7 +7,8 @@ import { db } from "@/db/drizzle"; // Types import type { TeamWithMembers, MemberWithUser } from "@/types/database"; -import Link from "next/link"; +import { Link } from "@/i18n/routing"; +import { getTranslations, setRequestLocale } from "next-intl/server"; // User interface import { @@ -19,19 +20,26 @@ import { TableRow, } from "@/components/ui/table"; -// Later on we can use a i8 solution? -function translateRole(role: string): string { +// Function to translate roles using i18n +function translateRole(role: string, t: (key: string) => string): string { switch (role) { case "CAPTAIN": - return "Kapten"; + return t("admin.roles.captain"); case "TEAMMATE": - return "Meeskonnaliige"; + return t("admin.roles.teammate"); default: return role; } } -export default async function AdminTeams() { +export default async function AdminTeams({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); // Fetch teams with their members and member users const teams = await db.query.teams.findMany({ with: { @@ -54,7 +62,7 @@ export default async function AdminTeams() {

- Haldus - Meeskonnad + {t("admin.title")} - {t("admin.teams")}

@@ -63,8 +71,8 @@ export default async function AdminTeams() { ID - Nimi - Liikmed + {t("admin.table.name")} + {t("admin.table.members")} @@ -84,12 +92,14 @@ export default async function AdminTeams() { {member.user.firstName} {member.user.lastName} - ({translateRole(member.role)}) + ({translateRole(member.role, t)})
)) ) : ( - Liikmeid puuduvad + + {t("admin.table.noMembers")} + )} diff --git a/src/app/haldus/page.tsx b/src/app/[locale]/haldus/page.tsx similarity index 77% rename from src/app/haldus/page.tsx rename to src/app/[locale]/haldus/page.tsx index bccd5b6..ee04ea7 100644 --- a/src/app/haldus/page.tsx +++ b/src/app/[locale]/haldus/page.tsx @@ -17,9 +17,10 @@ import { X, } from "lucide-react"; -import Link from "next/link"; +import { getTranslations, setRequestLocale } from "next-intl/server"; import { revalidatePath } from "next/cache"; import { redirect, RedirectType } from "next/navigation"; +import NextLink from "next/link"; import { Button } from "@/components/ui/button"; @@ -53,13 +54,13 @@ async function dismissAlert() { redirect("/haldus", RedirectType.replace); } -const SuccessAlertDB = () => { +const SuccessAlertDB = ({ t }: { t: (key: string) => string }) => { return (
- Toiming oli edukas! - Andmebaasi andmed on uuendatud. + {t("admin.success.title")} + {t("admin.success.description")}
+ )} + + {/* Right Arrow - Only show when on tudengimaja to go to fuajee */} + {currentView === "tudengimaja" && ( + + )} + + {currentView === "tudengimaja" && ( + + )} + + + + + {/* Tooltip - only show for current view */} + {hoveredRoom && + ((currentView === "tudengimaja" && + [ + roomNames.boardGames, + roomNames.bar, + roomNames.eval, + roomNames.simRacing, + roomNames.fighting, + roomNames.lvlup, + roomNames.redbull, + ].includes(hoveredRoom)) || + (currentView === "fuajee" && + [ + roomNames.ityk, + roomNames.tartuyk, + roomNames.estoniagamedev, + roomNames.info, + roomNames.tly, + roomNames.ittk, + roomNames.photobooth, + roomNames.gameup, + ].includes(hoveredRoom))) && ( +
+ {hoveredRoom} +
+ )} + + + + + + ); +} diff --git a/src/app/[locale]/not-found.tsx b/src/app/[locale]/not-found.tsx new file mode 100644 index 0000000..8330bb3 --- /dev/null +++ b/src/app/[locale]/not-found.tsx @@ -0,0 +1,19 @@ +import { vipnagorgialla } from "@/components/Vipnagorgialla"; +import { getTranslations } from "next-intl/server"; + +export default async function NotFound() { + const t = await getTranslations("notFound"); + + return ( +
+

+ {t("title")} +

+

+ {t("message")} +

+
+ ); +} diff --git a/src/app/page.tsx b/src/app/[locale]/page.tsx similarity index 81% rename from src/app/page.tsx rename to src/app/[locale]/page.tsx index e4ecb0c..809bb26 100644 --- a/src/app/page.tsx +++ b/src/app/[locale]/page.tsx @@ -1,8 +1,18 @@ import { vipnagorgialla } from "@/components/Vipnagorgialla"; -import Link from "next/link"; +import { Link } from "@/i18n/routing"; +import { getTranslations, setRequestLocale } from "next-intl/server"; import Image from "next/image"; +import NextLink from "next/link"; + +export default async function Home({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); -export default function Home() { return (
{/* Title */} @@ -25,7 +35,7 @@ export default function Home() {

- Auhinnafond + {t("tournaments.prizePool")}

- Ajakava + {t("navigation.schedule")}

arrow_right_alt @@ -55,8 +65,7 @@ export default function Home() { event_note

- TipiLAN on pungil põnevatest turniiridest, mini-võistlustest ja - paljust muust. + {t("home.sections.schedule.description")}

@@ -66,9 +75,9 @@ export default function Home() { >

- Turniirid + {t("navigation.tournaments")}

arrow_right_alt @@ -80,8 +89,7 @@ export default function Home() { trophy

- TipiLANil toimuvad suurejoonelised CS2 ja LoL turniirid, mille - auhinnafond on 10 000€. + {t("home.sections.tournaments.description")}

@@ -93,7 +101,7 @@ export default function Home() {

- Messiala + {t("navigation.expo")}

arrow_right_alt @@ -104,8 +112,7 @@ export default function Home() { weekend

- TipiLANi messialal paiknevad ettevõtted, lisategevused ja toimuvad - loengud. + {t("home.sections.expo.description")}

@@ -117,7 +124,7 @@ export default function Home() { >

- Bro­neeri oma koht juba täna! + {t("home.sections.reserveSpot")}

arrow_right_alt @@ -133,10 +140,10 @@ export default function Home() { >

- TipiLANi tõmbab käima... + {t("home.sections.poweredBy")}

-
- +
+ Taltech (Tallinna Tehnikaülikool) - - + + Redbull - - + + Alecoq - - + + EVAL - - + + Balsnack - - + @@ -192,8 +199,11 @@ export default function Home() { height={192} className="object-contain" /> - - + + BFGL - + + + Tallinna Haridusamet +
diff --git a/src/app/[locale]/piletid/page.tsx b/src/app/[locale]/piletid/page.tsx new file mode 100644 index 0000000..2174b4c --- /dev/null +++ b/src/app/[locale]/piletid/page.tsx @@ -0,0 +1,114 @@ +import { vipnagorgialla } from "@/components/Vipnagorgialla"; +import Link from "next/link"; +import SectionDivider from "@/components/SectionDivider"; +import { getTranslations, setRequestLocale } from "next-intl/server"; + +export default async function Tickets({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + return ( +
+
+

+ {t("tickets.title")} +

+
+
+

+ {t("tickets.computerParticipant.price")} +

+

+ {t("tickets.computerParticipant.title")} +

+
    + {t + .raw("tickets.computerParticipant.features") + .map((feature: string, index: number) => ( +
  • + {feature} +
  • + ))} +
+ + + +
+
+

+ {t("tickets.competitor.price")} +

+

+ {t("tickets.competitor.title")} +

+
    + {t + .raw("tickets.competitor.features") + .map((feature: string, index: number) => ( +
  • + {feature} +
  • + ))} +
+ + + +
+ +
+

+ {t("tickets.visitor.price")} +

+

+ {t("tickets.visitor.title")} +

+
    + {t + .raw("tickets.visitor.features") + .map((feature: string, index: number) => ( +
  • + {feature} +
  • + ))} +
+ + + +
+
+
+ + +
+ ); +} diff --git a/src/app/[locale]/reeglid/[slug]/page.tsx b/src/app/[locale]/reeglid/[slug]/page.tsx new file mode 100644 index 0000000..3cdaaf0 --- /dev/null +++ b/src/app/[locale]/reeglid/[slug]/page.tsx @@ -0,0 +1,106 @@ +import { notFound } from "next/navigation"; +import ReactMarkdown, { Components } from "react-markdown"; +import { vipnagorgialla } from "@/components/Vipnagorgialla"; +import SectionDivider from "@/components/SectionDivider"; +import { getTranslations, setRequestLocale } from "next-intl/server"; + +// Map of valid slugs to their corresponding file paths and translation keys +const rulesMap = { + lol: { + filePath: "src/data/rules/lol.md", + titleKey: "rules.lolRules", + }, + cs2: { + filePath: "src/data/rules/cs2.md", + titleKey: "rules.cs2Rules", + }, +} as const; + +type RuleSlug = keyof typeof rulesMap; + +interface PageProps { + params: Promise<{ slug: string; locale: string }>; +} + +async function getRuleContent(slug: string) { + if (!Object.keys(rulesMap).includes(slug)) { + return null; + } + + const ruleConfig = rulesMap[slug as RuleSlug]; + + try { + const file = Bun.file(ruleConfig.filePath); + const content = await file.text(); + return { + content, + titleKey: ruleConfig.titleKey, + }; + } catch (error) { + console.error(`Error reading rule file for slug ${slug}:`, error); + return null; + } +} + +export default async function RulePage({ params }: PageProps) { + const { slug, locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + const ruleData = await getRuleContent(slug); + + if (!ruleData) { + notFound(); + } + + const headingStyle = `text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold uppercase italic text-[#2A2C3F] dark:text-[#EEE5E5]`; + + return ( +
+
+

+ {t(ruleData.titleKey)} +

+ +
+ ( +

+ {props.children} +

+ ), + h2: (props) => ( +

+ {props.children} +

+ ), + ol: (props) => ( +
    + {props.children} +
+ ), + ul: (props) => ( +
    + {props.children} +
+ ), + p: (props) =>

{props.children}

, + } as Components + } + > + {ruleData.content} +
+
+
+ + +
+ ); +} + +export async function generateStaticParams() { + return Object.keys(rulesMap).map((slug) => ({ + slug, + })); +} diff --git a/src/app/[locale]/reeglid/page.tsx b/src/app/[locale]/reeglid/page.tsx new file mode 100644 index 0000000..0886779 --- /dev/null +++ b/src/app/[locale]/reeglid/page.tsx @@ -0,0 +1,63 @@ +import { vipnagorgialla } from "@/components/Vipnagorgialla"; +import SectionDivider from "@/components/SectionDivider"; +import { getTranslations, setRequestLocale } from "next-intl/server"; +import NextLink from "next/link"; + +export default async function RulesMenu({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + + setRequestLocale(locale); + + const t = await getTranslations({ locale }); + + const headingStyle = `text-4xl md:text-5xl lg:text-6xl ${vipnagorgialla.className} font-bold italic text-[#2A2C3F] dark:text-[#EEE5E5] uppercase`; + + const boxStyle = `-skew-x-2 md:-skew-x-5 text-white md:px-12 hover:scale-103 transition-all duration-150 w-full md:w-xl lg:w-[400px]`; + + const boxTextStyle = `text-3xl ${vipnagorgialla.className} font-bold uppercase text-[#EEE5E5] pb-2`; + + return ( +
+
+

+ {t("rules.title")} +

+ +
+ +
+

{t("rules.houseRules")}

+
+
+ + +
+

{t("rules.cs2Rules")}

+
+
+ + +
+

{t("rules.lolRules")}

+
+
+ + {/* Minitourn. link coming soon*/} + {/**/} +
+

+ {t("rules.miniRules")} +

+
+ {/**/} +
+
+ + +
+ ); +} diff --git a/src/app/[locale]/striim/page.tsx b/src/app/[locale]/striim/page.tsx new file mode 100644 index 0000000..04a8fe2 --- /dev/null +++ b/src/app/[locale]/striim/page.tsx @@ -0,0 +1,224 @@ +import { vipnagorgialla } from "@/components/Vipnagorgialla"; +import Link from "next/link"; +import Image from "next/image"; +import { getTranslations, setRequestLocale } from "next-intl/server"; + +export default async function Home({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + return ( +
+
+ {/* Title */} +
+ TipiLAN Logo + TipiLAN Logo + +
+

+ {t("navigation.schedule")} +

+ + arrow_right_alt + +
+
+ + event_note + +

+ {t("home.sections.schedule.description")} +

+
+ +
+ {/* Stream iframe from Twitch */} +
+ +
+
+ {/* Grid of buttons */} +
+ +
+

+ {t("navigation.tournaments")} +

+ + arrow_right_alt + +
+ +
+ + trophy + +

+ {t("home.sections.tournaments.description")} +

+
+ + +
+

+ {t("navigation.expo")} +

+ + arrow_right_alt + +
+
+ + weekend + +

+ {t("home.sections.expo.description")} +

+
+ +
+ {/* Date */} + +
+

+ {t("home.sections.reserveSpot")} +

+ + arrow_right_alt + +
+

+ 24.-26. okt. +

+ + {/* Sponsors */} +
+
+

+ {t("home.sections.poweredBy")} +

+
+ + Taltech (Tallinna Tehnikaülikool) + + + Redbull + + + Alecoq + + + EVAL + + + Balsnack + + + LVLup! + + + BFGL + + + Tallinna Haridusamet + +
+
+
+
+ ); +} diff --git a/src/app/[locale]/turniirid/page.tsx b/src/app/[locale]/turniirid/page.tsx new file mode 100644 index 0000000..045cc24 --- /dev/null +++ b/src/app/[locale]/turniirid/page.tsx @@ -0,0 +1,188 @@ +import { vipnagorgialla } from "@/components/Vipnagorgialla"; +import Link from "next/link"; +import Image from "next/image"; +import { getTranslations, setRequestLocale } from "next-intl/server"; + +export default async function Tourney({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + const headingStyle = `text-3xl md:text-5xl lg:text-5xl ${vipnagorgialla.className} font-bold uppercase text-[#2A2C3F] dark:text-[#EEE5E5] -skew-x-2 md:-skew-x-5`; + + return ( +
+

+ {t("tournaments.title")} +

+ +
+ {/* CS2 turniir */} +
+
+
+

+ {t("tournaments.cs2.title")} +

+

+ {t("tournaments.cs2.timing")} +

+

+ {t("tournaments.cs2.description1")} +

+
+

+ {t("tournaments.cs2.description2")} +

+
+ +
+ + + + + + +
+
+
+
+ {/* Outside div needs to remain so that overflow won't occur*/} + CS2 tournament +
+
+
+
+ + {/* LoL turniir */} +
+
+
+
+ {/* Outside div needs to remain so that overflow won't occur*/} + LoL tournament +
+
+
+

+ {t("tournaments.lol.title")} +

+

+ {t("tournaments.lol.timing")} +

+

+ {t("tournaments.lol.description1")} +

+
+

+ {t("tournaments.lol.description2")} +

+
+
+ + + + + + +
+
+
+
+ + {/* Mini-turniirid */} +
+
+
+

+ {t("tournaments.mini.title")} +

+

+ {t("tournaments.mini.timing")} +

+

+ {t("tournaments.mini.description1")} +

+
+

+ {t("tournaments.mini.description2")} +

+
+
+ + + + + + +
+
+
+
+ {/* Outside div needs to remain so that overflow won't occur*/} + mini tournaments +
+
+
+
+
+
+ ); +} diff --git a/src/app/ajakava/page.tsx b/src/app/ajakava/page.tsx deleted file mode 100644 index ce78a6c..0000000 --- a/src/app/ajakava/page.tsx +++ /dev/null @@ -1,72 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { vipnagorgialla } from "@/components/Vipnagorgialla"; -import { scheduleData } from "@/data/timetable"; - -const tabs = Object.keys(scheduleData); - -export default function Timetable() { - const [activeTab, setActiveTab] = useState(tabs[0]); - const schedule = scheduleData[activeTab]; - - return ( -
-

- Ajakava -

- - {/* Tab menu */} -
- {tabs.map((tab) => ( - - ))} -
- - {/* Schedule entries */} -
- {schedule.map((item, idx) => ( -
-
- {item.time} -
-
-
- {item.title} -
- {item.description && ( -
- {item.description} -
- )} - {item.location && ( -
- {item.location} -
- )} -
-
- ))} -
-
- ); -} diff --git a/src/app/kodukord/page.tsx b/src/app/kodukord/page.tsx deleted file mode 100644 index f5e597e..0000000 --- a/src/app/kodukord/page.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { vipnagorgialla } from "@/components/Vipnagorgialla"; - -export default function Rulebook() { - return ( -
-

- Kodukord -

-
    -
  1. - Keelatud on: -
      -
    1. alkoholi ja uimastite omamine ja tarbimine ürituse vältel
    2. -
    3. alkoholijoobes või uimastite mõju all viibimine üritusel
    4. -
    5. - suitsetamine (ka e-sigaret) selleks mitte ettenähtud kohtades – - suitsetada võib suitsuruumis või õues vastava prügikasti juures -
        -
      • suitsetamine alaealistel
      • -
      • mokatubaka kasutamine TalTech-i territooriumil
      • -
      -
    6. -
    7. külm- ja imitatsioonrelvad
    8. -
    9. - ürituse alal igasuguse vägivalla kasutamine teiste ja teiste vara - suhtes -
    10. -
    11. teiste vara omavoliline kasutamine, näppimine
    12. -
    13. turniiri reeglitele mittevastavalt mängimine
    14. -
    15. - omavoliline taristu (võrgu) näppimine – võrguprobleemidega tuleb - pöörduda korraldajate poole -
    16. -
    17. - mängimiseks ebavajalike seadmete ühendamine vooluvõrku (nt - veekeetja, puhur, sirgendaja) -
    18. -
    -
  2. -
  3. Iga külastaja vastutab enda asjade ja vara eest ise
  4. -
  5. - Korraldajale varalise kahju tekitanud külastaja on kohustatud korvama - täies ulatuses tekitatud kahju -
  6. -
  7. - Magamiseks ettenähtud ajal ja magamiseks ettenähtud ruumis tuleb olla - vaikselt ja võimaldada kaas mängijatel magada -
  8. -
  9. Korraldajad ei vastuta külastajate eest
  10. -
  11. - Mängijad on TipiLAN-il kohustatud kinni pidama mängule seatud - vanusepiirangutest -
  12. -
-

- NB! Reeglite rikkumise puhul on korraldajatel õigus mängija (koos tema - meeskonnaga) eemaldada ja rakendada edasist keeldu TipiLAN-i üritustelt. -

-
- ); -} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3b9c9c3..70e4eb3 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,18 +1,8 @@ -// Head metadata import type { Metadata } from "next"; -import Head from "next/head"; - -// Provides the theme context to the app -import { ThemeProvider } from "@/components/Theme-provider"; +import { Work_Sans } from "next/font/google"; import "./globals.css"; import "material-symbols"; -// Fonts -import { Work_Sans } from "next/font/google"; - -import SidebarParent from "@/components/SidebarParent"; -import Footer from "@/components/Footer"; - const workSans = Work_Sans({ subsets: ["latin"], }); @@ -24,32 +14,15 @@ export const metadata: Metadata = { export default function RootLayout({ children, -}: Readonly<{ +}: { children: React.ReactNode; -}>) { +}) { return ( - - - TipiLAN - - - + - - - {children} -