mirror of
https://github.com/Lapikud/tipilan.git
synced 2026-03-24 05:44:20 +00:00
Initial commit
This commit is contained in:
@@ -1,77 +0,0 @@
|
||||
"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 (
|
||||
<div>
|
||||
<div className="flex flex-col min-h-[90vh] m-6 mt-16 md:m-16">
|
||||
<h1
|
||||
className={`text-4xl md:text-5xl lg:text-6xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 md:mt-16 mb-8`}
|
||||
>
|
||||
{t("schedule.title")}
|
||||
</h1>
|
||||
|
||||
{/* Tab menu */}
|
||||
<div className="flex gap-4 mb-8 flex-wrap">
|
||||
{tabs.map((tab) => (
|
||||
<button
|
||||
key={tab}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
className={`${vipnagorgialla.className} cursor-pointer uppercase italic px-4 py-2 text-lg font-semibold ${
|
||||
activeTab === tab
|
||||
? "bg-[#00A3E0] text-white"
|
||||
: "bg-[#007CAB] dark:bg-[#007CAB] text-[#EEE5E5] hover:bg-[#00A3E0] dark:hover:bg-[#007CAB]"
|
||||
} transition-colors`}
|
||||
>
|
||||
{t(`schedule.${tab}`)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Schedule entries */}
|
||||
<div className="space-y-6">
|
||||
{schedule.map((item, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="border-l-3 border-[#007CAB] pl-4 flex flex-col sm:flex-row flex-wrap gap-2 sm:gap-5 items-stretch"
|
||||
>
|
||||
<div
|
||||
className={`${vipnagorgialla.className} md:w-[180px] w-30 text-[#00A3E0] text-3xl md:text-4xl font-bold italic flex-shrink-0 flex items-center sm:justify-center`}
|
||||
>
|
||||
{item.time}
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col justify-center min-w-0 sm:min-h-[120px]">
|
||||
<div
|
||||
className={`${vipnagorgialla.className} text-2xl md:text-3xl italic font-bold text-[#2A2C3F] dark:text-[#EEE5E5] text-balance`}
|
||||
>
|
||||
{t(item.titleKey)}
|
||||
</div>
|
||||
{item.description && (
|
||||
<div className="text-xl md:text-2xl text-[#938BA1] dark:text-[#938BA1] text-balance">
|
||||
{item.description}
|
||||
</div>
|
||||
)}
|
||||
<div className="text-xl md:text-2xl text-[#938BA1] dark:text-[#938BA1] text-balance">
|
||||
{t(item.locationKey)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SectionDivider />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
// Fonts
|
||||
import { vipnagorgialla } from "@/components/Vipnagorgialla";
|
||||
|
||||
// Database
|
||||
import { db } from "@/db/drizzle";
|
||||
|
||||
// Types
|
||||
import type { TeamWithMembers, MemberWithUser } from "@/types/database";
|
||||
|
||||
import { Link } from "@/i18n/routing";
|
||||
import { getTranslations, setRequestLocale } from "next-intl/server";
|
||||
|
||||
// User interface
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
|
||||
// Function to translate roles using i18n
|
||||
function translateRole(role: string, t: (key: string) => string): string {
|
||||
switch (role) {
|
||||
case "CAPTAIN":
|
||||
return t("admin.roles.captain");
|
||||
case "TEAMMATE":
|
||||
return t("admin.roles.teammate");
|
||||
default:
|
||||
return role;
|
||||
}
|
||||
}
|
||||
|
||||
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: {
|
||||
members: {
|
||||
with: {
|
||||
user: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-[90vh] m-6 mt-16 md:m-16">
|
||||
<div className="flex items-center gap-4">
|
||||
<Link href={"/haldus"}>
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] !font-bold text-[#007CAB] dark:text-[#00A3E0] translate-y-2.5 hover:-translate-x-2 dark:hover:text-[#EEE5E5] hover:text-[#2A2C3F] transition">
|
||||
arrow_left_alt
|
||||
</span>
|
||||
</Link>
|
||||
<h1
|
||||
className={`text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 mb-4`}
|
||||
>
|
||||
{t("admin.title")} - {t("admin.teams")}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="text-2xl text-[#2A2C3F] dark:text-[#EEE5E5]">
|
||||
<div>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[100px]">ID</TableHead>
|
||||
<TableHead>{t("admin.table.name")}</TableHead>
|
||||
<TableHead>{t("admin.table.members")}</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{teams.map((team: TeamWithMembers) => (
|
||||
<TableRow key={team.id}>
|
||||
<TableCell className="font-medium">{team.id}</TableCell>
|
||||
<TableCell>{team.name}</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex flex-col gap-1">
|
||||
{team.members && team.members.length > 0 ? (
|
||||
team.members.map((member: MemberWithUser) => (
|
||||
<div
|
||||
key={member.id}
|
||||
className="flex items-center gap-2 text-sm"
|
||||
>
|
||||
<span className="font-semibold">
|
||||
{member.user.firstName} {member.user.lastName}
|
||||
</span>
|
||||
<span className="text-gray-500">
|
||||
({translateRole(member.role, t)})
|
||||
</span>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<span className="text-gray-500">
|
||||
{t("admin.table.noMembers")}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
// Fonts
|
||||
import { vipnagorgialla } from "@/components/Vipnagorgialla";
|
||||
|
||||
// Database
|
||||
import { db } from "@/db/drizzle";
|
||||
import { syncFientaEvent } from "@/lib/fienta";
|
||||
|
||||
// Enviornment variables
|
||||
import("dotenv");
|
||||
|
||||
// User interface
|
||||
import {
|
||||
Users,
|
||||
IdCardLanyard,
|
||||
DatabaseBackup,
|
||||
CheckCircle2Icon,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
|
||||
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";
|
||||
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||
|
||||
import { DataTable } from "@/components/haldus/data-table";
|
||||
import { columns } from "@/components/haldus/columns";
|
||||
|
||||
async function syncAction() {
|
||||
"use server";
|
||||
await syncFientaEvent(process.env.EVENT_ID!, process.env.FIENTA_API_KEY!);
|
||||
|
||||
// Revalidate due to data change
|
||||
revalidatePath("/haldus");
|
||||
redirect("/haldus?success=true");
|
||||
}
|
||||
|
||||
async function dismissAlert() {
|
||||
"use server";
|
||||
redirect("/haldus", RedirectType.replace);
|
||||
}
|
||||
|
||||
const SuccessAlertDB = ({ t }: { t: (key: string) => string }) => {
|
||||
return (
|
||||
<Alert className="flex items-start mt-8">
|
||||
<CheckCircle2Icon className="mt-0.5" />
|
||||
<div className="flex-1">
|
||||
<AlertTitle>{t("admin.success.title")}</AlertTitle>
|
||||
<AlertDescription>{t("admin.success.description")}</AlertDescription>
|
||||
</div>
|
||||
<form action={dismissAlert} className="ml-2">
|
||||
<Button
|
||||
type="submit"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<X className="" />
|
||||
</Button>
|
||||
</form>
|
||||
</Alert>
|
||||
);
|
||||
};
|
||||
|
||||
export default async function Admin({
|
||||
params,
|
||||
searchParams,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
setRequestLocale(locale);
|
||||
const t = await getTranslations({ locale });
|
||||
const alarmStatus = await searchParams;
|
||||
const showSuccess = alarmStatus.success === "true";
|
||||
|
||||
// Fetch users
|
||||
const usersData = await db.query.users.findMany({
|
||||
with: {
|
||||
members: {
|
||||
with: {
|
||||
team: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const teamsData = await db.query.teams.findMany();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-[90vh] m-6 mt-16 md:m-16">
|
||||
{showSuccess && <SuccessAlertDB t={t} />}
|
||||
<div className="flex items-center gap-4">
|
||||
<NextLink href={"/"}>
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] !font-bold text-[#007CAB] dark:text-[#00A3E0] translate-y-2.5 hover:-translate-x-2 dark:hover:text-[#EEE5E5] hover:text-[#2A2C3F] transition">
|
||||
arrow_left_alt
|
||||
</span>
|
||||
</NextLink>
|
||||
<h1
|
||||
className={`text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 mb-4`}
|
||||
>
|
||||
{t("admin.title")}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="text-2xl text-[#2A2C3F] dark:text-[#EEE5E5]">
|
||||
<div className="pl-2 flex gap-8 pb-4">
|
||||
<div className="flex text-lg md:text-2xl flex-row items-center">
|
||||
<Users className="mr-2" />
|
||||
{t("admin.users")}: {usersData.length}
|
||||
</div>
|
||||
<NextLink href="/haldus/meeskonnad" className="flex items-center">
|
||||
<div className="flex text-lg md:text-2xl flex-row items-center">
|
||||
<IdCardLanyard className="mr-2" />
|
||||
{t("admin.teams")}: {teamsData.length}
|
||||
</div>
|
||||
</NextLink>
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<div className="ml-auto">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="size-12 cursor-pointer"
|
||||
>
|
||||
<DatabaseBackup className="scale-150" />
|
||||
</Button>
|
||||
</div>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogTitle>{t("admin.sync.title")}</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
{t("admin.sync.description1")}{" "}
|
||||
<span className="text-red-600 font-semibold">
|
||||
{t("admin.sync.all")}
|
||||
</span>{" "}
|
||||
{t("admin.sync.description2")}
|
||||
<br />
|
||||
<br />
|
||||
{t("admin.sync.warning")}
|
||||
</AlertDialogDescription>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel className="cursor-pointer">
|
||||
{t("common.cancel")}
|
||||
</AlertDialogCancel>
|
||||
<form action={syncAction}>
|
||||
<AlertDialogAction type="submit" className="cursor-pointer">
|
||||
{t("admin.sync.update")}
|
||||
</AlertDialogAction>
|
||||
</form>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
<div>
|
||||
<DataTable columns={columns} data={usersData} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
// app/kodukord/page.tsx (App Router)
|
||||
import ReactMarkdown, { Components } from "react-markdown";
|
||||
import { vipnagorgialla } from "@/components/Vipnagorgialla";
|
||||
import SectionDivider from "@/components/SectionDivider";
|
||||
import { getTranslations, setRequestLocale } from "next-intl/server";
|
||||
import { loadRulesBun } from "@/lib/loadRules";
|
||||
|
||||
export default async function Page({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
setRequestLocale(locale);
|
||||
const t = await getTranslations({ locale });
|
||||
const content = await loadRulesBun("kodukord", locale as "et" | "en");
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex flex-col min-h-[90vh] m-6 mt-16 md:m-16">
|
||||
{/* Page title (separate from markdown headings) */}
|
||||
<h1
|
||||
className={`text-4xl md:text-5xl lg:text-6xl ${vipnagorgialla.className} font-bold italic text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 md:mt-16 mb-4 uppercase`}
|
||||
>
|
||||
{t("rules.houseRules")}
|
||||
</h1>
|
||||
|
||||
<div className="prose prose-lg dark:prose-invert max-w-none">
|
||||
<ReactMarkdown
|
||||
components={
|
||||
{
|
||||
h1: (props) => (
|
||||
<h1 className="text-3xl md:text-4xl font-bold my-4">
|
||||
{props.children}
|
||||
</h1>
|
||||
),
|
||||
h2: (props) => (
|
||||
<h2 className="text-2xl md:text-3xl font-semibold my-3">
|
||||
{props.children}
|
||||
</h2>
|
||||
),
|
||||
ol: (props) => (
|
||||
<ol className="list-decimal ml-6 md:text-xl">
|
||||
{props.children}
|
||||
</ol>
|
||||
),
|
||||
ul: (props) => (
|
||||
<ul className="list-disc ml-6 md:text-xl">
|
||||
{props.children}
|
||||
</ul>
|
||||
),
|
||||
p: (props) => <p className="md:text-xl">{props.children}</p>,
|
||||
} as Components
|
||||
}
|
||||
>
|
||||
{content}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SectionDivider />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
import { NextIntlClientProvider } from "next-intl";
|
||||
import { setRequestLocale, getMessages } from "next-intl/server";
|
||||
import { ThemeProvider } from "@/components/Theme-provider";
|
||||
import SidebarParent from "@/components/SidebarParent";
|
||||
import Footer from "@/components/Footer";
|
||||
|
||||
export default async function LocaleLayout({
|
||||
children,
|
||||
@@ -22,16 +19,7 @@ export default async function LocaleLayout({
|
||||
return (
|
||||
<div lang={locale}>
|
||||
<NextIntlClientProvider messages={messages}>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="system"
|
||||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<SidebarParent />
|
||||
{children}
|
||||
<Footer />
|
||||
</ThemeProvider>
|
||||
{children}
|
||||
</NextIntlClientProvider>
|
||||
</div>
|
||||
);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,14 @@
|
||||
import { vipnagorgialla } from "@/components/Vipnagorgialla";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
|
||||
export default async function NotFound() {
|
||||
const t = await getTranslations("notFound");
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-[90vh] p-12 justify-center items-center">
|
||||
<h1
|
||||
className={`text-7xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 mb-4`}
|
||||
>
|
||||
<div className="flex flex-col min-h-dvh p-12 justify-center items-center bg-bg-dark text-text-light">
|
||||
<h1 className="text-title">
|
||||
{t("title")}
|
||||
</h1>
|
||||
<p className="text-2xl text-[#2A2C3F] dark:text-[#EEE5E5] mb-8">
|
||||
<p className="text-p-lg mt-4">
|
||||
{t("message")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { vipnagorgialla } from "@/components/Vipnagorgialla";
|
||||
import Sponsors from "@/components/Sponsors";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import { getTranslations, setRequestLocale } from "next-intl/server";
|
||||
import Image from "next/image";
|
||||
import { setRequestLocale } from "next-intl/server";
|
||||
import TeaserPage from "@/components/TeaserPage";
|
||||
|
||||
export default async function Home({
|
||||
params,
|
||||
@@ -11,150 +8,6 @@ export default async function Home({
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
setRequestLocale(locale);
|
||||
const t = await getTranslations({ locale });
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* Title */}
|
||||
<div className="border-b-3 border-[#1F5673] grid grid-cols-1 md:grid-cols-[2fr_1fr] items-center justify-between mt-18 gap-12 py-8">
|
||||
<Image
|
||||
src="/tipilan-white.svg"
|
||||
width={850}
|
||||
height={120}
|
||||
alt="TipiLAN Logo"
|
||||
className="px-8 py-8 md:px-12 md:py-14 dark:hidden w-[max(300px,min(100%,850px))] h-auto"
|
||||
/>
|
||||
<Image
|
||||
src="/tipilan-dark.svg"
|
||||
width={850}
|
||||
height={120}
|
||||
alt="TipiLAN Logo"
|
||||
className="px-8 py-8 md:px-12 md:py-14 not-dark:hidden w-[max(300px,min(100%,850px))] h-auto2"
|
||||
/>
|
||||
<div className="pr-12 hidden md:block text-right">
|
||||
<h3
|
||||
className={`text-[clamp(1.25rem,0.75rem+2.5vw,3.75rem)] ${vipnagorgialla.className} leading-[90%] font-bold italic uppercase dark:text-[#EEE5E5] text-[#2A2C3F]`}
|
||||
>
|
||||
{t("tournaments.prizePool")}
|
||||
</h3>
|
||||
<h2
|
||||
className={`text-[clamp(2rem,1.2rem+4vw,6rem)] ${vipnagorgialla.className} leading-[90%] font-bold italic text-[#007CAB] dark:text-[#00A3E0]`}
|
||||
>
|
||||
10 000€
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Farewell message */}
|
||||
<div>
|
||||
<section
|
||||
className={`p-8 md:p-12 flex flex-col ${vipnagorgialla.className} font-bold italic border-b-3 border-[#1F5673] hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] group transition`}
|
||||
>
|
||||
<h2 className="text-[clamp(2rem,1.5rem+0.5vw,3rem)] text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5]">
|
||||
{t("home.sections.farewellMessage")} <span className="not-italic">🩵</span>
|
||||
</h2>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{/* Grid of buttons */}
|
||||
<div className="grid grid-cols-1 xl:grid-cols-3 border-[#1F5673]">
|
||||
<Link
|
||||
href="/ajakava"
|
||||
className="px-8 md:px-12 py-8 flex flex-col gap-4 border-b-3 lg:border-r-3 group border-[#1F5673] hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] transition"
|
||||
>
|
||||
<div className="cursor-pointer flex flex-row justify-between gap-4 items-center">
|
||||
<h2
|
||||
className={`text-[clamp(2rem,1.8rem+1vw,3rem)] ${vipnagorgialla.className} font-bold italic uppercase dark:text-[#EEE5E5] text-[#2A2C3F] group-hover:text-black dark:group-hover:text-[#2A2C3F]`}
|
||||
>
|
||||
{t("navigation.schedule")}
|
||||
</h2>
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] !font-bold text-[#007CAB] dark:text-[#00A3E0] group-hover:translate-x-2 dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] transition">
|
||||
arrow_right_alt
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5]">
|
||||
event_note
|
||||
</span>
|
||||
<p className="text-[clamp(0.875rem,0.75rem+0.5vw,1.25rem)] tracking-[-0.045rem] dark:group-hover:text-[#2A2C3F] group-hover:text-black">
|
||||
{t("home.sections.schedule.description")}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
<Link
|
||||
href="/turniirid"
|
||||
className="px-8 md:px-12 py-8 flex flex-col gap-4 border-b-3 lg:border-r-3 group border-[#1F5673] hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] transition"
|
||||
>
|
||||
<div className="cursor-pointer flex flex-row justify-between gap-4 items-center">
|
||||
<h2
|
||||
className={`text-[clamp(2rem,1.8rem+1vw,3rem)] ${vipnagorgialla.className} font-bold italic break-normal uppercase dark:text-[#EEE5E5] text-[#2A2C3F] dark:group-hover:text-[#2A2C3F] group-hover:text-black`}
|
||||
>
|
||||
{t("navigation.tournaments")}
|
||||
</h2>
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] !font-bold text-[#007CAB] dark:text-[#00A3E0] group-hover:translate-x-2 dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] transition">
|
||||
arrow_right_alt
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5]">
|
||||
trophy
|
||||
</span>
|
||||
<p className="text-[clamp(0.875rem,0.75rem+0.5vw,1.25rem)] tracking-[-0.045rem] dark:group-hover:text-[#2A2C3F] group-hover:text-black">
|
||||
{t("home.sections.tournaments.description")}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
<Link
|
||||
href="/messiala"
|
||||
className="px-8 md:px-12 py-8 flex flex-col gap-4 border-b-3 border-[#1F5673] group hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] transition-all"
|
||||
>
|
||||
<div className="cursor-pointer flex flex-row justify-between gap-4 items-center">
|
||||
<h2
|
||||
className={`text-[clamp(2rem,1.8rem+1vw,3rem)] ${vipnagorgialla.className} font-bold italic uppercase dark:text-[#EEE5E5] text-[#2A2C3F] dark:group-hover:text-[#2A2C3F] group-hover:text-black`}
|
||||
>
|
||||
{t("navigation.expo")}
|
||||
</h2>
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] !font-bold text-[#007CAB] dark:text-[#00A3E0] group-hover:translate-x-2 dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] transition">
|
||||
arrow_right_alt
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5]">
|
||||
weekend
|
||||
</span>
|
||||
<p className="text-[clamp(0.875rem,0.75rem+0.5vw,1.25rem)] tracking-[-0.045rem] dark:group-hover:text-[#2A2C3F] group-hover:text-black">
|
||||
{t("home.sections.expo.description")}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Section preserved for next year development */}
|
||||
{/* Date */}
|
||||
{/* <div>*/}
|
||||
{/* <Link*/}
|
||||
{/* href="/piletid"*/}
|
||||
{/* className={`p-8 md:p-12 flex flex-col ${vipnagorgialla.className} font-bold italic border-b-3 border-[#1F5673] hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] group transition`}*/}
|
||||
{/* >*/}
|
||||
{/* <div className="cursor-pointer text-left flex flex-row justify-between xl:justify-start gap-8">*/}
|
||||
{/* <h3 className="text-4xl md:text-5xl dark:text-[#EEE5E5] dark:group-hover:text-[#2A2C3F] text-[#2A2C3F] group-hover:text-black">*/}
|
||||
{/* {t("home.sections.reserveSpot")}*/}
|
||||
{/* </h3>*/}
|
||||
{/* <span*/}
|
||||
{/* className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] !font-bold text-[#007CAB] dark:text-[#00A3E0] hidden md:block group-hover:translate-x-2 group-hover:text-[#EEE5E5] dark:group-hover:text-[#EEE5E5] transition">*/}
|
||||
{/* arrow_right_alt*/}
|
||||
{/* </span>*/}
|
||||
{/* </div>*/}
|
||||
{/* <h2 className="text-[clamp(2.5rem,2.25rem+1.25vw,3.75rem)] text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5]">*/}
|
||||
{/* {t("home.sections.dateAndLocation")}*/}
|
||||
{/* </h2>*/}
|
||||
{/* </Link>*/}
|
||||
{/* </div>*/}
|
||||
|
||||
{/* Sponsors */}
|
||||
<Sponsors />
|
||||
|
||||
</div>
|
||||
);
|
||||
return <TeaserPage />;
|
||||
}
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
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 (
|
||||
<div>
|
||||
<div className="flex flex-col min-h-[90vh] m-6 mt-16 md:m-16">
|
||||
<h1
|
||||
className={`text-4xl wrap-break-word md:text-5xl lg:text-6xl ${vipnagorgialla.className} font-bold italic text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 md:mt-16 mb-4`}
|
||||
>
|
||||
{t("tickets.title")}
|
||||
</h1>
|
||||
|
||||
<div className="flex justify-center lg:items-center flex-col lg:flex-row gap-8 md:gap-12 flex-grow mb-16 md:mt-8 lg:mt-0">
|
||||
<div className="bg-[#007CAB] -skew-x-2 md:-skew-x-5 text-white italic px-8 md:px-12 py-16 hover:scale-103 transition-all duration-150 w-full md:w-xl lg:w-[400px]">
|
||||
<h2
|
||||
className={`text-6xl ${vipnagorgialla.className} font-bold text-[#EEE5E5] pb-2`}
|
||||
>
|
||||
{t("tickets.visitor.latePrice")}
|
||||
</h2>
|
||||
<h3
|
||||
className={`text-3xl ${vipnagorgialla.className} font-bold text-[#EEE5E5] pb-4`}
|
||||
>
|
||||
{t("tickets.visitor.title")}
|
||||
</h3>
|
||||
<ul className="pl-4 mb-8 list-[square] marker:text-[#1F5673]">
|
||||
{t
|
||||
.raw("tickets.visitor.features")
|
||||
.map((feature: string, index: number) => (
|
||||
<li key={index} className="text-xl">
|
||||
{feature}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Link href="https://fienta.com/et/tipilan" target="_blank">
|
||||
<button
|
||||
className={`px-4 py-2 bg-[#1F5673] cursor-pointer ${vipnagorgialla.className} font-bold`}
|
||||
>
|
||||
{t("tickets.buyTicket")}
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="bg-[#007CAB] -skew-x-2 md:-skew-x-5 text-white italic px-8 md:px-12 py-16 hover:scale-103 transition-all duration-150 w-full md:w-xl lg:w-[400px]">
|
||||
<h2
|
||||
className={`text-6xl ${vipnagorgialla.className} font-bold text-[#EEE5E5] pb-2`}
|
||||
>
|
||||
{t("tickets.computerParticipant.latePrice")}
|
||||
</h2>
|
||||
<h3
|
||||
className={`text-3xl ${vipnagorgialla.className} font-bold text-[#EEE5E5] pb-4`}
|
||||
>
|
||||
{t("tickets.computerParticipant.title")}
|
||||
</h3>
|
||||
<ul className="pl-4 mb-8 list-[square] marker:text-[#1F5673]">
|
||||
{t
|
||||
.raw("tickets.computerParticipant.features")
|
||||
.map((feature: string, index: number) => (
|
||||
<li key={index} className="text-xl">
|
||||
{feature}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Link href="https://fienta.com/et/tipilan" target="_blank">
|
||||
<button
|
||||
className={`px-4 py-2 bg-[#1F5673] cursor-pointer ${vipnagorgialla.className} font-bold`}
|
||||
>
|
||||
{t("tickets.buyTicket")}
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div className="bg-[#1F5673] -skew-x-2 md:-skew-x-5 text-gray-400 italic px-8 md:px-12 py-16 w-full md:w-xl lg:w-[400px]">
|
||||
<h2
|
||||
className={`text-4xl ${vipnagorgialla.className} font-bold pb-2`}
|
||||
>
|
||||
<s>{t("tickets.competitor.price")}</s>
|
||||
</h2>
|
||||
<h3
|
||||
className={`text-2xl ${vipnagorgialla.className} font-bold pb-4`}
|
||||
>
|
||||
<s>{t("tickets.competitor.title")}</s>
|
||||
</h3>
|
||||
<ul className="pl-4 mb-8 list-[square] marker:text-[#007CAB]">
|
||||
{t
|
||||
.raw("tickets.competitor.features")
|
||||
.map((feature: string, index: number) => (
|
||||
<li key={index} className="text-sm">
|
||||
{feature}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{/*<Link href="https://fienta.com/et/tipilan" target="_blank">*/}
|
||||
<button
|
||||
className={`px-4 py-2 bg-[#007CAB] text-white ${vipnagorgialla.className} font-bold text-xl uppercase opacity-55`}
|
||||
>
|
||||
{t("tickets.soldOut")}!
|
||||
</button>
|
||||
{/*</Link>*/}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SectionDivider />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
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";
|
||||
import { loadRulesBun } from "@/lib/loadRules";
|
||||
|
||||
// Map of valid slugs to their translation keys
|
||||
const rulesMap = {
|
||||
lol: {
|
||||
titleKey: "rules.lolRules",
|
||||
},
|
||||
cs2: {
|
||||
titleKey: "rules.cs2Rules",
|
||||
},
|
||||
} as const;
|
||||
|
||||
type RuleSlug = keyof typeof rulesMap;
|
||||
|
||||
interface PageProps {
|
||||
params: Promise<{ slug: string; locale: string }>;
|
||||
}
|
||||
|
||||
async function getRuleContent(slug: string, locale: string) {
|
||||
if (!Object.keys(rulesMap).includes(slug)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const ruleConfig = rulesMap[slug as RuleSlug];
|
||||
|
||||
try {
|
||||
const content = await loadRulesBun(
|
||||
slug as "cs2" | "lol",
|
||||
locale as "et" | "en",
|
||||
);
|
||||
return {
|
||||
content,
|
||||
titleKey: ruleConfig.titleKey,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error reading rule file for slug ${slug} in locale ${locale}:`,
|
||||
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, locale);
|
||||
|
||||
if (!ruleData) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const headingStyle = `text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold uppercase italic text-[#2A2C3F] dark:text-[#EEE5E5]`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex flex-col min-h-[90vh] m-6 mt-16 md:m-16">
|
||||
<h1 className={`${headingStyle} mt-8 md:mt-16 mb-4`}>
|
||||
{t(ruleData.titleKey)}
|
||||
</h1>
|
||||
|
||||
<div className="prose prose-lg dark:prose-invert max-w-none">
|
||||
<ReactMarkdown
|
||||
components={
|
||||
{
|
||||
h1: (props) => (
|
||||
<h1 className="text-3xl md:text-4xl font-bold my-4">
|
||||
{props.children}
|
||||
</h1>
|
||||
),
|
||||
h2: (props) => (
|
||||
<h2 className="text-2xl md:text-3xl font-semibold my-3">
|
||||
{props.children}
|
||||
</h2>
|
||||
),
|
||||
ol: (props) => (
|
||||
<ol className="list-none ml-6 md:text-xl">
|
||||
{props.children}
|
||||
</ol>
|
||||
),
|
||||
ul: (props) => (
|
||||
<ul className="list-disc ml-6 md:text-xl">
|
||||
{props.children}
|
||||
</ul>
|
||||
),
|
||||
p: (props) => <p className="md:text-xl">{props.children}</p>,
|
||||
} as Components
|
||||
}
|
||||
>
|
||||
{ruleData.content}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SectionDivider />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
return Object.keys(rulesMap).map((slug) => ({
|
||||
slug,
|
||||
}));
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
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-2xl md:text-3xl ${vipnagorgialla.className} font-bold uppercase text-[#EEE5E5] pb-2 break-normal whitespace-pre-line`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex flex-col md:m-16">
|
||||
<h1 className={`${headingStyle} ml-3 mt-24 md:ml-0 md:mt-16 mb-4 px-4`}>
|
||||
{t("rules.title")}
|
||||
</h1>
|
||||
|
||||
<div className="flex flex-wrap flex-row lg:mt-16 justify-center lg:items-start gap-12 flex-grow mb-8">
|
||||
<NextLink href="/kodukord">
|
||||
<div className={`${boxStyle} bg-[#007CAB] py-20 px-8`}>
|
||||
<h2 className={`${boxTextStyle}`}>{t("rules.houseRules")}</h2>
|
||||
</div>
|
||||
</NextLink>
|
||||
|
||||
<NextLink href="/reeglid/cs2">
|
||||
<div className={`${boxStyle} bg-[#1F5673] py-20 px-8`}>
|
||||
<h2 className={`${boxTextStyle}`}>{t("rules.cs2Rules")}</h2>
|
||||
</div>
|
||||
</NextLink>
|
||||
|
||||
<NextLink href="reeglid/lol">
|
||||
<div className={`${boxStyle} bg-[#007CAB] py-20 px-8`}>
|
||||
<h2 className={`${boxTextStyle}`}>{t("rules.lolRules")}</h2>
|
||||
</div>
|
||||
</NextLink>
|
||||
|
||||
{/* Minitourn. link coming soon*/}
|
||||
{/*<Link href="">*/}
|
||||
{/* ajutine div. kui asendate lingiga, siis saab selle ära võtta */}
|
||||
<div className="cursor-not-allowed">
|
||||
<div
|
||||
className={`${boxStyle} bg-[#1F5673] py-16 px-8 opacity-50 pointer-events-none`}
|
||||
>
|
||||
<h2 className={`${boxTextStyle}`}>{t("rules.miniRules")}</h2>
|
||||
</div>
|
||||
</div>
|
||||
{/*</Link>*/}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SectionDivider />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
import { vipnagorgialla } from "@/components/Vipnagorgialla";
|
||||
import Sponsors from "@/components/Sponsors";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import { getTranslations, setRequestLocale } from "next-intl/server";
|
||||
import Image from "next/image";
|
||||
|
||||
export default async function Home({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
setRequestLocale(locale);
|
||||
const t = await getTranslations({ locale });
|
||||
return (
|
||||
<div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2">
|
||||
{/* Title */}
|
||||
<div className="grid grid-cols-1 items-center justify-between mt-18 gap-12 pt-8">
|
||||
<Image
|
||||
src="/tipilan-white.svg"
|
||||
width={850}
|
||||
height={120}
|
||||
alt="TipiLAN Logo"
|
||||
className="px-8 py-8 md:px-12 md:py-14 dark:hidden w-[max(300px,min(100%,850px))] h-auto"
|
||||
/>
|
||||
<Image
|
||||
src="/tipilan-dark.svg"
|
||||
width={850}
|
||||
height={120}
|
||||
alt="TipiLAN Logo"
|
||||
className="px-8 py-8 md:px-12 md:py-14 not-dark:hidden w-[max(300px,min(100%,850px))] h-auto2"
|
||||
/>
|
||||
<Link
|
||||
href="/ajakava"
|
||||
className="px-8 md:px-12 py-8 flex flex-col gap-4 border-b-3 border-t-3 group border-[#1F5673] hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] transition"
|
||||
>
|
||||
<div className="cursor-pointer flex flex-row justify-between gap-4 items-center">
|
||||
<h2
|
||||
className={`text-[clamp(2rem,1.8rem+1vw,3rem)] ${vipnagorgialla.className} font-bold italic uppercase dark:text-[#EEE5E5] text-[#2A2C3F] group-hover:text-black dark:group-hover:text-[#2A2C3F]`}
|
||||
>
|
||||
{t("navigation.schedule")}
|
||||
</h2>
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] !font-bold text-[#007CAB] dark:text-[#00A3E0] group-hover:translate-x-2 dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] transition">
|
||||
arrow_right_alt
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5]">
|
||||
event_note
|
||||
</span>
|
||||
<p className="text-[clamp(0.875rem,0.75rem+0.5vw,1.25rem)] tracking-[-0.045rem] dark:group-hover:text-[#2A2C3F] group-hover:text-black">
|
||||
{t("home.sections.schedule.description")}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
{/* Stream iframe from Twitch */}
|
||||
<div className="border-[#1F5673] -ml-0.75 border-l-0 md:border-l-3 border-b-3 h-full pt-0 md:pt-16">
|
||||
<iframe
|
||||
src="https://player.twitch.tv/?channel=tipilan_ee&parent=localhost&parent=tipilan.ee"
|
||||
height="100%"
|
||||
width="100%"
|
||||
className="w-full h-full min-h-[400px]"
|
||||
allow="autoplay; encrypted-media"
|
||||
></iframe>
|
||||
</div>
|
||||
</div>
|
||||
{/* Grid of buttons */}
|
||||
<div className="grid grid-cols-1 xl:grid-cols-2 border-[#1F5673]">
|
||||
<Link
|
||||
href="/turniirid"
|
||||
className="px-8 md:px-12 py-8 flex flex-col gap-4 border-b-3 lg:border-r-3 group border-[#1F5673] hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] transition"
|
||||
>
|
||||
<div className="cursor-pointer flex flex-row justify-between gap-4 items-center">
|
||||
<h2
|
||||
className={`text-[clamp(2rem,1.8rem+1vw,3rem)] ${vipnagorgialla.className} font-bold italic break-normal uppercase dark:text-[#EEE5E5] text-[#2A2C3F] dark:group-hover:text-[#2A2C3F] group-hover:text-black`}
|
||||
>
|
||||
{t("navigation.tournaments")}
|
||||
</h2>
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] !font-bold text-[#007CAB] dark:text-[#00A3E0] group-hover:translate-x-2 dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] transition">
|
||||
arrow_right_alt
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5]">
|
||||
trophy
|
||||
</span>
|
||||
<p className="text-[clamp(0.875rem,0.75rem+0.5vw,1.25rem)] tracking-[-0.045rem] dark:group-hover:text-[#2A2C3F] group-hover:text-black">
|
||||
{t("home.sections.tournaments.description")}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
<Link
|
||||
href="/messiala"
|
||||
className="px-8 md:px-12 py-8 flex flex-col gap-4 border-b-3 border-[#1F5673] group hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] transition-all"
|
||||
>
|
||||
<div className="cursor-pointer flex flex-row justify-between gap-4 items-center">
|
||||
<h2
|
||||
className={`text-[clamp(2rem,1.8rem+1vw,3rem)] ${vipnagorgialla.className} font-bold italic uppercase dark:text-[#EEE5E5] text-[#2A2C3F] dark:group-hover:text-[#2A2C3F] group-hover:text-black`}
|
||||
>
|
||||
{t("navigation.expo")}
|
||||
</h2>
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] !font-bold text-[#007CAB] dark:text-[#00A3E0] group-hover:translate-x-2 dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] transition">
|
||||
arrow_right_alt
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5]">
|
||||
weekend
|
||||
</span>
|
||||
<p className="text-[clamp(0.875rem,0.75rem+0.5vw,1.25rem)] tracking-[-0.045rem] dark:group-hover:text-[#2A2C3F] group-hover:text-black">
|
||||
{t("home.sections.expo.description")}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
{/* Date */}
|
||||
<Link
|
||||
href="/piletid"
|
||||
className={`p-8 md:p-12 flex flex-col ${vipnagorgialla.className} font-bold italic border-b-3 border-[#1F5673] hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] group transition`}
|
||||
>
|
||||
<div className="cursor-pointer text-left flex flex-row justify-between xl:justify-start gap-8">
|
||||
<h3 className="text-4xl md:text-5xl dark:text-[#EEE5E5] dark:group-hover:text-[#2A2C3F] text-[#2A2C3F] group-hover:text-black">
|
||||
{t("home.sections.reserveSpot")}
|
||||
</h3>
|
||||
<span className="material-symbols-outlined !text-[clamp(2rem,1.5rem+1.5vw,3.5rem)] !font-bold text-[#007CAB] dark:text-[#00A3E0] hidden md:block group-hover:translate-x-2 group-hover:text-[#EEE5E5] dark:group-hover:text-[#EEE5E5] transition">
|
||||
arrow_right_alt
|
||||
</span>
|
||||
</div>
|
||||
<h2 className="text-[clamp(2.5rem,2.25rem+1.25vw,3.75rem)] text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5]">
|
||||
{t("home.sections.dateAndLocation")}
|
||||
</h2>
|
||||
</Link>
|
||||
{/* Sponsors */}
|
||||
<Sponsors />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,264 +0,0 @@
|
||||
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 break-normal`;
|
||||
|
||||
const miniTournaments: {
|
||||
name: string;
|
||||
prize: string;
|
||||
image: string;
|
||||
objectPosition?: string;
|
||||
bgClass?: string;
|
||||
}[] = [
|
||||
{
|
||||
name: "Tekken 8",
|
||||
prize: "200€",
|
||||
image: "/images/miniturniirid/tekken8.jpg",
|
||||
objectPosition: "object-center",
|
||||
},
|
||||
{
|
||||
name: "WRC",
|
||||
prize: "350€",
|
||||
image: "/images/miniturniirid/wrc.jpg",
|
||||
objectPosition: "object-center",
|
||||
},
|
||||
{
|
||||
name: "Street Fighter 6",
|
||||
prize: "150€",
|
||||
image: "/images/miniturniirid/street_fighter.jpg",
|
||||
objectPosition: "object-center",
|
||||
},
|
||||
{
|
||||
name: "Gran Turismo",
|
||||
prize: "200€",
|
||||
image: "/images/miniturniirid/gran_turismo.jpg",
|
||||
objectPosition: "object-center",
|
||||
},
|
||||
{
|
||||
name: "FC 26",
|
||||
prize: "100€",
|
||||
image: "/images/miniturniirid/fc26.jpg",
|
||||
objectPosition: "object-center",
|
||||
},
|
||||
{
|
||||
name: "Dwarf Escape",
|
||||
prize: "50€",
|
||||
image: "/images/miniturniirid/dwarf_escape.png",
|
||||
objectPosition: "object-center",
|
||||
bgClass: "bg-black",
|
||||
},
|
||||
{
|
||||
name: "Buckshot Roulette",
|
||||
prize: "Merch",
|
||||
image: "/images/miniturniirid/buckshot_tournament.png",
|
||||
objectPosition: "object-center",
|
||||
bgClass: "bg-black",
|
||||
},
|
||||
{
|
||||
name: "2XKO",
|
||||
prize: "100€",
|
||||
image: "/images/miniturniirid/2xko.png",
|
||||
objectPosition: "object-top",
|
||||
},
|
||||
{
|
||||
name: "Super Smash Bros. Ultimate",
|
||||
prize: "100€",
|
||||
image: "/images/miniturniirid/super_smash_bros.jpg",
|
||||
objectPosition: "object-top",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-[90vh] mt-16">
|
||||
<h1
|
||||
className={`text-4xl md:text-5xl lg:text-6xl ${vipnagorgialla.className} font-bold italic uppercase
|
||||
text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 md:mt-16 mb-8 m-6 md:m-16`}
|
||||
>
|
||||
{t("tournaments.title")}
|
||||
</h1>
|
||||
|
||||
<div className="flex flex-col">
|
||||
|
||||
{/* Mini-turniirid */}
|
||||
<div className="hover:bg-[#007CAB] py-8 md:py-16 border-b-[3px] border-[#1F5673] transition group">
|
||||
<div className="mx-8 md:mx-16 lg:mx-32 xl:mx-48">
|
||||
<div className="-skew-x-2 md:-skew-x-5 mb-8">
|
||||
<h2 className={`${headingStyle}`}>
|
||||
{t("tournaments.mini.title")}
|
||||
</h2>
|
||||
<p
|
||||
className={
|
||||
"text-2xl mb-4 text-neutral-500 group-hover:text-black"
|
||||
}
|
||||
>
|
||||
{t("tournaments.mini.timing")}
|
||||
</p>
|
||||
<p className="text-balance">
|
||||
{t("tournaments.mini.description1")}
|
||||
</p>
|
||||
<p className="text-balance">
|
||||
{t("tournaments.mini.description2")}
|
||||
</p>
|
||||
<br />
|
||||
<div className="flex flex-row flex-wrap gap-4 md:gap-8">
|
||||
<Link href="/kodukord" target="_blank">
|
||||
<button
|
||||
className={`px-4 py-2 bg-[#1F5673] cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
|
||||
>
|
||||
{t("tournaments.mini.readRules")}
|
||||
</button>
|
||||
</Link>
|
||||
<a href="https://fienta.com/et/tipilan" target="_blank">
|
||||
<button
|
||||
className={`px-4 py-2 bg-[#00A3E0] group-hover:bg-black cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
|
||||
>
|
||||
{t("tournaments.mini.buyTicket")}
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-8">
|
||||
{miniTournaments.map((tournament) => (
|
||||
<div key={tournament.name} className="text-center">
|
||||
<Image
|
||||
src={tournament.image}
|
||||
alt={tournament.name}
|
||||
width={400}
|
||||
height={300}
|
||||
className={`outline-10 outline-[#007CAB] bg-black object-cover w-full aspect-video -skew-x-2 md:-skew-x-5 ${
|
||||
tournament.objectPosition || "object-center"
|
||||
}`}
|
||||
/>
|
||||
<div className="-skew-x-2 md:-skew-x-5">
|
||||
<p className="mt-2 font-semibold">{tournament.name} - {tournament.prize}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* CS2 turniir */}
|
||||
<div className="hover:bg-[#007CAB] py-8 md:py-16 transition group">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-16 items-center mx-8 md:mx-16 lg:mx-32 xl:mx-48">
|
||||
<div className="-skew-x-2 md:-skew-x-5">
|
||||
<h2 className={`${headingStyle}`}>
|
||||
{t("tournaments.cs2.title")}
|
||||
</h2>
|
||||
<p
|
||||
className={
|
||||
"text-2xl mb-4 text-neutral-500 group-hover:text-black"
|
||||
}
|
||||
>
|
||||
{t("tournaments.cs2.timing")}
|
||||
</p>
|
||||
<p className="text-balance">
|
||||
{t("tournaments.cs2.description1")}
|
||||
</p>
|
||||
<br />
|
||||
<p className="text-balance">
|
||||
{t("tournaments.cs2.description2")}
|
||||
</p>
|
||||
<p className="text-balance">
|
||||
{t("tournaments.cs2.description3")}
|
||||
</p>
|
||||
<br />
|
||||
|
||||
<div className={"flex flex-row flex-wrap gap-8"}>
|
||||
<Link href="/reeglid/cs2" target="_blank">
|
||||
<button
|
||||
className={`px-4 py-2 bg-[#1F5673] cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
|
||||
>
|
||||
{t("tournaments.cs2.readRules")}
|
||||
</button>
|
||||
</Link>
|
||||
<a href="https://fienta.com/et/tipilan" target="_blank">
|
||||
<button
|
||||
className={`px-4 py-2 bg-[#00A3E0] group-hover:bg-black cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
|
||||
>
|
||||
{t("tournaments.cs2.buyTicket")}
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="hidden md:block">
|
||||
<div>
|
||||
{/* Outside div needs to remain so that overflow won't occur*/}
|
||||
<Image
|
||||
src="/images/cs2_tournament_logo.png"
|
||||
alt="CS2 tournament"
|
||||
width={600}
|
||||
height={400}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* LoL turniir */}
|
||||
<div className="hover:bg-[#007CAB] py-8 md:py-16 border-t-[3px] border-b-[3px] border-[#1F5673] transition group">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-16 items-center mx-8 md:mx-16 lg:mx-32 xl:mx-48">
|
||||
<div className="hidden md:block">
|
||||
<div>
|
||||
{/* Outside div needs to remain so that overflow won't occur*/}
|
||||
<Image
|
||||
src="/images/lol_tournament_logo.png"
|
||||
alt="LoL tournament"
|
||||
width={600}
|
||||
height={400}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-auto text-right -skew-x-2 md:-skew-x-5">
|
||||
<h2 className={`${headingStyle}`}>
|
||||
{t("tournaments.lol.title")}
|
||||
</h2>
|
||||
<p
|
||||
className={
|
||||
"text-2xl mb-4 text-neutral-500 group-hover:text-black"
|
||||
}
|
||||
>
|
||||
{t("tournaments.lol.timing")}
|
||||
</p>
|
||||
<p className="text-balance">
|
||||
{t("tournaments.lol.description1")}
|
||||
</p>
|
||||
<br />
|
||||
<p className="text-balance">
|
||||
{t("tournaments.lol.description2")}
|
||||
</p>
|
||||
<br />
|
||||
<div className="flex flex-row flex-wrap gap-4 md:gap-8 justify-end">
|
||||
<Link href="/reeglid/lol" target="_blank">
|
||||
<button
|
||||
className={`px-4 py-2 bg-[#1F5673] cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
|
||||
>
|
||||
{t("tournaments.lol.readRules")}
|
||||
</button>
|
||||
</Link>
|
||||
<a href="https://fienta.com/et/tipilan" target="_blank">
|
||||
<button
|
||||
className={`px-4 py-2 bg-[#00A3E0] group-hover:bg-black cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
|
||||
>
|
||||
{t("tournaments.lol.buyTicket")}
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,137 +1,158 @@
|
||||
@import 'tailwindcss';
|
||||
@import "tw-animate-css";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
/* ===== TipiLAN 2026 Design Tokens ===== */
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-ring: var(--ring);
|
||||
--color-input: var(--input);
|
||||
--color-border: var(--border);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-card: var(--card);
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
@font-face {
|
||||
font-family: 'Vipnagorgialla';
|
||||
src: url('/fonts/vipnagorgialla/Vipnagorgialla-Rg.otf') format('opentype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@theme {
|
||||
--breakpoint-xs: 30rem;
|
||||
@font-face {
|
||||
font-family: 'Vipnagorgialla';
|
||||
src: url('/fonts/vipnagorgialla/Vipnagorgialla-Rg-It.otf') format('opentype');
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Vipnagorgialla';
|
||||
src: url('/fonts/vipnagorgialla/Vipnagorgialla-Bd.otf') format('opentype');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Vipnagorgialla';
|
||||
src: url('/fonts/vipnagorgialla/Vipnagorgialla-Bd-It.otf') format('opentype');
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/* ===== 2026 Color & Font Theme ===== */
|
||||
@theme inline {
|
||||
--color-bg-dark: #0A121F;
|
||||
--color-primary: #00A3E0;
|
||||
--color-primary-50: rgba(0, 163, 224, 0.5);
|
||||
--color-text-light: #FFFFFF;
|
||||
--color-stroke: #00A3E0;
|
||||
|
||||
--font-heading: 'Vipnagorgialla', sans-serif;
|
||||
--font-body: 'Work Sans', Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Work Sans", Arial, Helvetica, sans-serif;
|
||||
font-family: var(--font-body);
|
||||
max-width: 100vw;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: var(--color-bg-dark);
|
||||
color: var(--color-text-light);
|
||||
}
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.205 0 0);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.708 0 0);
|
||||
/* ===== 2026 Typography Utilities ===== */
|
||||
@utility text-title {
|
||||
font-family: var(--font-heading);
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-size: clamp(48px, 8vw, 96px);
|
||||
line-height: 100%;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.922 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.556 0 0);
|
||||
@utility text-subtitle {
|
||||
font-family: var(--font-heading);
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-size: clamp(36px, 5vw, 64px);
|
||||
line-height: 100%;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
@utility text-h1 {
|
||||
font-family: var(--font-heading);
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-size: clamp(28px, 4vw, 48px);
|
||||
line-height: 100%;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@utility text-btn-lg {
|
||||
font-family: var(--font-heading);
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-size: 24px;
|
||||
line-height: 100%;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@utility text-p-lg {
|
||||
font-family: var(--font-body);
|
||||
font-weight: 400;
|
||||
font-size: clamp(18px, 2.5vw, 28px);
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
@utility text-p {
|
||||
font-family: var(--font-body);
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
@utility text-countdown {
|
||||
font-family: var(--font-heading);
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-size: clamp(32px, 5vw, 48px);
|
||||
line-height: 100%;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@utility text-countdown-label {
|
||||
font-family: var(--font-heading);
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-size: 16px;
|
||||
line-height: 100%;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* ===== 2026 Effect Utilities ===== */
|
||||
@utility shadow-teaser {
|
||||
filter: drop-shadow(0px 0px 20px rgba(0, 0, 0, 0.5));
|
||||
}
|
||||
|
||||
@utility text-shadow-teaser {
|
||||
text-shadow: 0px 0px 20px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
/* ===== 2026 Button Utility ===== */
|
||||
@utility btn-primary-lg {
|
||||
background-color: var(--color-primary);
|
||||
color: var(--color-bg-dark);
|
||||
padding: 16px;
|
||||
min-width: 56px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
/* ===== Scrollbar hidden utility ===== */
|
||||
@utility scrollbar-hidden {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
|
||||
.material-symbols-outlined {
|
||||
font-variation-settings: 'FILL' 1, 'wght' 700, 'GRAD' 0, 'opsz' 24;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Work_Sans } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import "material-symbols";
|
||||
|
||||
const workSans = Work_Sans({
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "TipiLAN 2025",
|
||||
description: "TipiLAN 2025 – Eesti suurim tudengite korraldatud LAN!",
|
||||
title: "TipiLAN 2026",
|
||||
description: "TipiLAN 2026 – Eesti suurim tudengite korraldatud LAN!",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
@@ -18,9 +17,9 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html suppressHydrationWarning>
|
||||
<html lang="et">
|
||||
<body
|
||||
className={`${workSans.className} antialiased bg-[#EEE5E5] dark:bg-[#0E0F19]`}
|
||||
className={`${workSans.className} antialiased bg-bg-dark text-text-light`}
|
||||
>
|
||||
{children}
|
||||
</body>
|
||||
|
||||
@@ -1,29 +1,11 @@
|
||||
import { vipnagorgialla } from "@/components/Vipnagorgialla";
|
||||
import { ThemeProvider } from "@/components/Theme-provider";
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="system"
|
||||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<div className="flex flex-col min-h-[90vh] p-12 justify-center items-center">
|
||||
<h1
|
||||
className={`text-7xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 mb-4`}
|
||||
>
|
||||
404
|
||||
</h1>
|
||||
<div className="text-center">
|
||||
<p className="text-2xl text-[#2A2C3F] dark:text-[#EEE5E5] mb-2">
|
||||
Lehte ei leitud!
|
||||
</p>
|
||||
<p className="text-lg text-[#2A2C3F]/80 dark:text-[#EEE5E5]/80">
|
||||
Page not found!
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col min-h-dvh p-12 justify-center items-center bg-bg-dark text-text-light">
|
||||
<h1 className="text-title">404</h1>
|
||||
<div className="text-center mt-4">
|
||||
<p className="text-p-lg">Lehte ei leitud!</p>
|
||||
<p className="text-p mt-2 opacity-80">Page not found!</p>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user