Merge pull request #46 from Lapikud/development

React 19 update changed the way ref works. Removed redundant packages and updated markdown to use Bun
pull/56/head
Voltages 4 months ago committed by GitHub
commit 5b464e9f6a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 19
      next.config.ts
  2. 2
      package.json
  3. 53
      src/app/kodukord/page.tsx
  4. 184
      src/app/messiala/page.tsx
  5. 114
      src/app/reeglid/[slug]/page.tsx
  6. 36
      src/app/reeglid/page.tsx
  7. 210
      src/app/striim/page.tsx
  8. 58
      src/app/turniirid/page.tsx
  9. 30
      src/components/ui/button.tsx
  10. 5
      src/data/rules/cs2.md

@ -1,7 +1,24 @@
import type { NextConfig } from "next";
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;

@ -27,7 +27,6 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"drizzle-orm": "^0.44.2",
"gray-matter": "^4.0.3",
"lucide-react": "^0.522.0",
"material-symbols": "^0.31.8",
"next": "15.3.0",
@ -36,7 +35,6 @@
"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"

@ -1,17 +1,11 @@
// app/kodukord/page.tsx (App Router)
import fs from "node:fs";
import path from "node:path";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import {vipnagorgialla} from "@/components/Vipnagorgialla";
import ReactMarkdown, { Components } from "react-markdown";
import { vipnagorgialla } from "@/components/Vipnagorgialla";
import SectionDivider from "@/components/SectionDivider";
export const runtime = "nodejs"; // ensure fs is available (not Edge)
export const dynamic = "force-static"; // read at build time
export default function Page() {
const filePath = path.join(process.cwd(), "src/data", "kodukord.md");
const content = fs.readFileSync(filePath, "utf8");
export default async function Page() {
const file = Bun.file("src/data/kodukord.md");
const content = await file.text();
return (
<div>
@ -25,31 +19,38 @@ export default function Page() {
<div className="prose prose-lg dark:prose-invert max-w-none">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
components={{
h1: ({node, ...props}) => (
<h1 className="text-3xl md:text-4xl font-bold my-4" {...props} />
),
h2: ({node, ...props}) => (
<h2 className="text-2xl md:text-3xl font-semibold my-3" {...props} />
components={
{
h1: (props) => (
<h1 className="text-3xl md:text-4xl font-bold my-4">
{props.children}
</h1>
),
ol: ({node, ...props}) => (
<ol className="list-decimal ml-6 md:text-xl" {...props} />
h2: (props) => (
<h2 className="text-2xl md:text-3xl font-semibold my-3">
{props.children}
</h2>
),
ul: ({node, ...props}) => (
<ul className="list-disc ml-6 md:text-xl" {...props} />
ol: (props) => (
<ol className="list-decimal ml-6 md:text-xl">
{props.children}
</ol>
),
p: ({node, ...props}) => (
<p className="md:text-xl" {...props} />
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/>
<SectionDivider />
</div>
);
}

@ -1,10 +1,9 @@
"use client";
import {vipnagorgialla} from "@/components/Vipnagorgialla";
import { vipnagorgialla } from "@/components/Vipnagorgialla";
import * as THREE from "three";
import {useEffect, useRef, useState} from "react";
import {EyeClosed, Eye} from "lucide-react";
import SectionDivider from "@/components/SectionDivider";
import { useEffect, useRef, useState } from "react";
import { EyeClosed, Eye } from "lucide-react";
// Define interface for the ref with toggle function
interface MountRefCurrent extends HTMLDivElement {
@ -14,7 +13,7 @@ interface MountRefCurrent extends HTMLDivElement {
export default function Expo() {
const mountRef = useRef<MountRefCurrent | null>(null);
const [hoveredRoom, setHoveredRoom] = useState<string | null>(null);
const [mousePosition, setMousePosition] = useState({x: 0, y: 0});
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
const [showDividers, setShowDividers] = useState<boolean>(true);
useEffect(() => {
@ -31,17 +30,17 @@ export default function Expo() {
// Get responsive dimensions
const getResponsiveDimensions = () => {
const container = mountRef.current;
if (!container) return {width: 800, height: 600};
if (!container) return { width: 800, height: 600 };
const containerWidth = container.offsetWidth;
const maxWidth = Math.min(containerWidth, 800);
const width = Math.max(maxWidth, 300); // Minimum width
const height = (width * 600) / 800; // Maintain aspect ratio
return {width, height};
return { width, height };
};
const {width, height} = getResponsiveDimensions();
const { width, height } = getResponsiveDimensions();
// Isometric camera setup with responsive sizing
const aspect = width / height;
@ -61,7 +60,7 @@ export default function Expo() {
camera.lookAt(-1.4, 0, 0);
// Renderer
const renderer = new THREE.WebGLRenderer({antialias: true});
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(width, height);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
@ -84,23 +83,15 @@ export default function Expo() {
// Room colors and names
const roomColors = [
0xff6b35, // Orange - Mänguklubi
0x343434, // Gray - Lauamängude ala
0x4ecdc4, // Turquoise - Baariala
0xffe66d, // Yellow - EVAL
0xe74c3c, // Red - Redbull
0x9b59b6, // Purple - Võitlusmängu ala
0xff6600, // Orange - Redbull Sim Racing
0xff1493, // Deep Pink - Võitlusmängu ala
0x3498db, // Blue - Sony
0x2ecc71, // Green - Chillimisala
];
const roomNames = [
"Mänguklubi",
"Baariala",
"EVAL",
"Redbull",
"Võitlusmängu ala",
"Sony",
"Chillimisala",
0x2ecc71, // Green - Lava
0x080682, // Dark Blue - LVLup!
0xc02841, // Red - RedBull
];
// Create individual rooms as rectangles with custom positions
@ -122,62 +113,80 @@ export default function Expo() {
x: 2.5,
z: 4,
color: roomColors[0],
name: roomNames[0],
}, // Mänguklubi
// {
// width: 2.5,
// height: 0.7,
// depth: 0.7,
// x: 1,
// z: 0,
// color: roomColors[1],
// name: roomNames[1],
// }, // Baariala
name: "Lauamängude ala",
},
{
width: 3.5,
height: 0.7,
depth: 1.2,
x: 0.7,
z: -0.3,
color: roomColors[1],
name: "Baariala",
},
{
width: 1.8,
height: 0.7,
depth: 1.5,
x: 2.5,
x: 1,
z: -3.5,
color: roomColors[2],
name: roomNames[2],
}, // EVAL
name: "EVAL",
},
{
width: 2.2,
width: 2,
height: 0.7,
depth: 4.5,
x: 5,
x: 5.2,
z: -2,
color: roomColors[3],
name: roomNames[3],
}, // Redbull
name: "Red Bull Sim Racing",
},
{
width: 3,
height: 0.7,
depth: 1.3,
x: 0,
depth: 1.5,
x: -1.7,
z: -3.5,
color: roomColors[4],
name: roomNames[4],
}, // Võitlusmängu ala
name: "Võitlusmängu ala",
},
// {
// width: 1.8,
// height: 0.7,
// depth: 1.5,
// x: -4.3,
// z: -3.5,
// color: roomColors[5],
// name: "Sony",
// },
{
width: 3,
height: 0.7,
depth: 1.7,
x: -3.5,
z: -0.5,
color: roomColors[7],
name: "LVLup!",
},
//{
// width: 2,
// height: 0.7,
// depth: 4,
// x: -6.4,
// z: -2.3,
// color: roomColors[6],
// name: "Lava",
//},
{
width: 1.8,
height: 0.7,
depth: 1.5,
x: -2.55,
x: 3,
z: -3.5,
color: roomColors[5],
name: roomNames[5],
}, // Sony
{
width: 4,
height: 0.7,
depth: 4,
x: -5.5,
z: -2.3,
color: roomColors[6],
name: roomNames[6],
}, // Chillimisala
color: roomColors[8],
name: "Red Bull",
},
];
roomDefinitions.forEach((roomDef) => {
@ -194,7 +203,7 @@ export default function Expo() {
room.position.set(roomDef.x, roomDef.height / 2, roomDef.z);
room.castShadow = true;
room.receiveShadow = true;
room.userData = {name: roomDef.name, originalColor: roomDef.color};
room.userData = { name: roomDef.name, originalColor: roomDef.color };
scene.add(room);
rooms.push(room);
@ -230,14 +239,14 @@ export default function Expo() {
// Add strategic dividers between major areas
createTogglableDivider(10, 2, 2, -2.5, 1.5); // Wall between main entrance
createTogglableDivider(2, 2, 2, 5.5, 1.5); // Wall right next to Mänguklubi & Redbull
createTogglableDivider(2, 2, 2, 5.5, 1.5); // Wall right next to Lauamängud & Redbull Sim Racing
// Store dividers reference for later access
dividersRef = [...dividers];
// Ground plane
const groundGeometry = new THREE.PlaneGeometry(14, 10.5);
const groundMaterial = new THREE.MeshLambertMaterial({color: 0xcccccc});
const groundMaterial = new THREE.MeshLambertMaterial({ color: 0xcccccc });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.position.x = -1.1;
@ -259,7 +268,7 @@ export default function Expo() {
// Resize handler
const handleResize = () => {
const {width: newWidth, height: newHeight} = getResponsiveDimensions();
const { width: newWidth, height: newHeight } = getResponsiveDimensions();
// Update camera
const newAspect = newWidth / newHeight;
@ -286,14 +295,14 @@ export default function Expo() {
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
// Update mouse position for tooltip
setMousePosition({x: event.clientX, y: event.clientY});
setMousePosition({ x: event.clientX, y: event.clientY });
// Update raycaster
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(rooms);
// Reset all rooms to original state
roomData.forEach(({mesh, originalColor, originalScale}) => {
roomData.forEach(({ mesh, originalColor, originalScale }) => {
(mesh.material as THREE.MeshLambertMaterial).color.setHex(
originalColor,
);
@ -370,7 +379,6 @@ export default function Expo() {
}, [showDividers]);
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 text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 md:mt-16 mb-4 uppercase`}
@ -385,52 +393,61 @@ export default function Expo() {
<div className="flex items-center gap-2">
<div
className="w-4 h-4 border border-gray-300"
style={{backgroundColor: "#ff6b35"}}
style={{ backgroundColor: "#4ecdc4" }}
></div>
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
Mänguklubi
Baariala
</span>
</div>
<div className="items-center gap-2 hidden">
<div className="flex items-center gap-2">
<div
className="w-4 h-4 border border-gray-300"
style={{backgroundColor: "#4ecdc4"}}
style={{ backgroundColor: "#ffe66d" }}
></div>
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
Baariala
EVAL
</span>
</div>
<div className="flex items-center gap-2">
<div
className="w-4 h-4 border border-gray-300"
style={{backgroundColor: "#ffe66d"}}
style={{ backgroundColor: "#343434" }}
></div>
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
EVAL
Lauamängude ala
</span>
</div>
<div className="flex items-center gap-2">
<div
className="w-4 h-4 border border-gray-300"
style={{backgroundColor: "#e74c3c"}}
style={{ backgroundColor: "#080682" }}
></div>
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
Redbull
LVLup!
</span>
</div>
<div className="flex items-center gap-2">
<div
className="w-4 h-4 border border-gray-300"
style={{backgroundColor: "#9b59b6"}}
style={{ backgroundColor: "#C02841" }}
></div>
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
Võitlusmängu ala
Red Bull
</span>
</div>
<div className="flex items-center gap-2">
<div
className="w-4 h-4 border border-gray-300"
style={{backgroundColor: "#3498db"}}
style={{ backgroundColor: "#ff6600" }}
></div>
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
Red Bull Sim Racing
</span>
</div>
<div className="items-center gap-2 hidden">
<div
className="w-4 h-4 border border-gray-300"
style={{ backgroundColor: "#3498db" }}
></div>
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
Sony
@ -439,24 +456,24 @@ export default function Expo() {
<div className="flex items-center gap-2">
<div
className="w-4 h-4 border border-gray-300"
style={{backgroundColor: "#2ecc71"}}
style={{ backgroundColor: "#ff1493" }}
></div>
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
Chillimisala
Võitlusmängu ala
</span>
</div>
</div>
<div className="flex flex-col lg:flex-row gap-8 items-start">
<div className="flex-shrink-0 border-3 border-[#1F5673] w-full max-w-[800px] relative">
<div ref={mountRef} className="w-full"/>
<div ref={mountRef} className="w-full" />
<button
onClick={() => setShowDividers(!showDividers)}
className={`absolute top-2 right-2 px-3 py-2 bg-[#1F5673] text-white hover:bg-[#2A7A9B] ${vipnagorgialla.className} uppercase italic text-sm font-semibold flex items-center transition-colors shadow-lg z-10`}
>
{showDividers ? (
<EyeClosed className="w-6 h-6 mr-2"/>
<EyeClosed className="w-6 h-6 mr-2" />
) : (
<Eye className="w-6 h-6 mr-2"/>
<Eye className="w-6 h-6 mr-2" />
)}
{showDividers ? "Peida" : "Näita"}
@ -478,8 +495,5 @@ export default function Expo() {
)}
</div>
</div>
<SectionDivider />
</div>
);
}

@ -1,49 +1,103 @@
import {vipnagorgialla} from "@/components/Vipnagorgialla";
import path from "node:path";
import fs from "node:fs/promises";
import ReactMarkdown from "react-markdown";
import { notFound } from "next/navigation";
import ReactMarkdown, { Components } from "react-markdown";
import { vipnagorgialla } from "@/components/Vipnagorgialla";
import SectionDivider from "@/components/SectionDivider";
type Props = {
// Map of valid slugs to their corresponding file paths and titles
const rulesMap = {
lol: {
filePath: "src/data/rules/lol.md",
title: "LOL Reeglid",
},
cs2: {
filePath: "src/data/rules/cs2.md",
title: "CS2 Reeglid",
},
} as const;
type RuleSlug = keyof typeof rulesMap;
interface PageProps {
params: Promise<{ slug: string }>;
};
}
export default async function RulePage({params}: Props) {
const {slug} = await params;
async function getRuleContent(slug: string) {
if (!Object.keys(rulesMap).includes(slug)) {
return null;
}
const filePath = path.join(process.cwd(), "src/data/rules", `${slug}.md`);
let file: string;
const ruleConfig = rulesMap[slug as RuleSlug];
try {
file = await fs.readFile(filePath, "utf8");
} catch {
file = `# ${slug.toUpperCase()} REEGLID\n\nSisu hetkel puudub.`;
const file = Bun.file(ruleConfig.filePath);
const content = await file.text();
return {
content,
title: ruleConfig.title,
};
} catch (error) {
console.error(`Error reading rule file for slug ${slug}:`, error);
return null;
}
}
export default async function RulePage({ params }: PageProps) {
const { slug } = await params;
const ruleData = await getRuleContent(slug);
if (!ruleData) {
notFound();
}
const data = {title: undefined as string | undefined};
const headingStyle = `text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold uppercase italic text-[#2A2C3F] dark:text-[#EEE5E5]`;
return (
<>
<div className="mb-16">
<h1
className={`not-prose ${vipnagorgialla.className} font-bold italic uppercase text-[64px] leading-[96px] tracking-[-0.02em] text-[#2A2C3F] dark:text-[#EEE5E5] mx-auto mt-16 mb-6 px-8`}
>
{data.title || `${slug.toUpperCase()} REEGLID`}
<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`}>
{ruleData.title}
</h1>
<div
className={`mx-auto px-8 font-worksans
[&_ol]:ml-6
[&_ol_ol]:ml-10
[&_ol_ol_ol]:ml-14
[&_h2]:font-bold
`}
<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
}
>
<ReactMarkdown>{file}</ReactMarkdown>
{ruleData.content}
</ReactMarkdown>
</div>
</div>
<SectionDivider/>
</>
<SectionDivider />
</div>
);
}
export async function generateStaticParams() {
return Object.keys(rulesMap).map((slug) => ({
slug,
}));
}

@ -1,9 +1,9 @@
import {vipnagorgialla} from "@/components/Vipnagorgialla";
import { vipnagorgialla } from "@/components/Vipnagorgialla";
import Link from "next/link";
import SectionDivider from "@/components/SectionDivider";
export default function RulesMenu() {
const headingStyle = `text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold italic text-[#2A2C3F] dark:text-[#EEE5E5]`;
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]`;
@ -14,51 +14,39 @@ export default function RulesMenu() {
return (
<div>
<div className="flex flex-col md:m-16">
<h1 className={`${headingStyle} mt-8 md:mt-16`}>
<h1 className={`${headingStyle} ml-3 mt-24 md:ml-0 md:mt-16 mb-4 px-4`}>
REEGLID
</h1>
<div className='flex flex-wrap flex-row lg:mt-16 justify-center lg:items-start gap-12 flex-grow mb-8'>
<div className="flex flex-wrap flex-row lg:mt-16 justify-center lg:items-start gap-12 flex-grow mb-8">
<Link href="/kodukord">
<div className={`${boxStyle} bg-[#007CAB] py-20`}>
<h2 className={`${boxTextStyle}`}>
Kodukord
</h2>
<div className={`${boxStyle} bg-[#007CAB] py-20 px-8`}>
<h2 className={`${boxTextStyle}`}>Kodukord</h2>
</div>
</Link>
<Link href="/reeglid/cs2">
<div className={`${boxStyle} bg-[#1F5673] py-20`}>
<h2 className={`${boxTextStyle}`}>
CS2 reeglid
</h2>
<div className={`${boxStyle} bg-[#1F5673] py-20 px-8`}>
<h2 className={`${boxTextStyle}`}>CS2 reeglid</h2>
</div>
</Link>
<Link href="reeglid/lol">
<div className={`${boxStyle} bg-[#007CAB] py-20`}>
<h2 className={`${boxTextStyle}`}>
LoL reeglid
</h2>
<div className={`${boxStyle} bg-[#007CAB] py-20 px-8`}>
<h2 className={`${boxTextStyle}`}>LoL reeglid</h2>
</div>
</Link>
{/* Minitourn. link coming soon*/}
{/*<Link href="">*/}
<div
className={`${boxStyle} bg-[#1F5673] py-16`}>
<h2 className={`${boxTextStyle}`}>
Miniturniiride reeglid
</h2>
<div className={`${boxStyle} bg-[#1F5673] py-16 px-8`}>
<h2 className={`${boxTextStyle}`}>Miniturniiride reeglid</h2>
</div>
{/*</Link>*/}
</div>
</div>
<SectionDivider />
</div>
);
}

@ -0,0 +1,210 @@
import { vipnagorgialla } from "@/components/Vipnagorgialla";
import Link from "next/link";
import Image from "next/image";
export default function Home() {
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]`}
>
Ajakava
</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">
TipiLAN on pungil põnevatest turniiridest, mini-võistlustest ja
paljust muust.
</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 uppercase dark:text-[#EEE5E5] text-[#2A2C3F] dark:group-hover:text-[#2A2C3F] group-hover:text-black`}
>
Turniirid
</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">
TipiLANil toimuvad suurejoonelised CS2 ja LoL turniirid, mille
auhinnafond on 10 000.
</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`}
>
Messiala
</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">
TipiLANi messialal paiknevad ettevõtted, lisategevused ja toimuvad
loengud.
</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">
Bro&shy;neeri oma koht juba täna!
</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]">
24.-26. okt.
</h2>
</Link>
{/* Sponsors */}
<div
className={`p-12 flex flex-col ${vipnagorgialla.className} font-bold italic border-b-3 border-[#1F5673]`}
>
<div className="text-left flex flex-col justify-between xl:justify-start">
<h3 className="text-4xl md:text-5xl dark:text-[#EEE5E5] text-[#2A2C3F] group-hover:text-black pb-8">
TipiLANi tõmbab käima...
</h3>
<div className="flex flex-row flex-wrap gap-8 md:gap-18 items-center">
<Link href="https://taltech.ee" target="_blank">
<Image
src="/sponsors/taltech-color.png"
alt="Taltech (Tallinna Tehnikaülikool)"
width={192}
height={192}
className="object-contain"
/>
</Link>
<Link href="https://www.redbull.com/ee-et/" target="_blank">
<Image
src="/sponsors/redbull.png"
alt="Redbull"
width={80}
height={80}
className="object-contain"
/>
</Link>
<Link href="https://www.alecoq.ee" target="_blank">
<Image
src="/sponsors/alecoq.svg"
alt="Alecoq"
width={200}
height={200}
className="object-contain"
/>
</Link>
<Link href="https://www.simracing.ee/" target="_blank">
<Image
src="/sponsors/EVAL.png"
alt="EVAL"
width={200}
height={200}
className="object-contain"
/>
</Link>
<Link href="https://balsnack.ee" target="_blank">
<Image
src="/sponsors/balsnack.svg"
alt="Balsnack"
width={200}
height={200}
className="object-contain"
/>
</Link>
<Link
href="https://www.rara.ee/sundmused/interaktiivne-videomangude-muuseum-lvlup/"
target="_blank"
>
<Image
src="/sponsors/lvlup_logo_export.svg"
alt="LVLup!"
width={192}
height={192}
className="object-contain"
/>
</Link>
<Link href="https://www.facebook.com/bfglOfficial" target="_blank">
<Image
src="/sponsors/BFGL.png"
alt="BFGL"
width={192}
height={192}
className="object-contain"
/>
</Link>
</div>
</div>
</div>
</div>
);
}

@ -25,36 +25,34 @@ export default function Tourney() {
{/* CS2 turniir */}
<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}`}>
CS2 turniir
</h2>
<h2 className={`${headingStyle}`}>CS2 turniir</h2>
<p className={"text-2xl mb-4 text-neutral-500"}>
Toimumisaeg veel selgumisel
</p>
<p className="text-balance">
TipiLANil toimub Eesti ühe suurima auhinnafondiga CS2 turniire juba sel sügisel. Haara kaasa
sõbrad ja
saa osa adrenaliinirohkest kogemusest!
TipiLANil toimub Eesti ühe suurima auhinnafondiga CS2 turniire
juba sel sügisel. Haara kaasa sõbrad ja saa osa adrenaliinirohkest
kogemusest!
</p>
<br />
<p className="text-balance">
Auhinnafond on suuruses 5250, mis jaotatakse TOP3 meeskonna vahel ära. Iga tiimiliige saab
vastavalt
saavutatud kohale auhinnaks kas 600, 300 või 150.
Auhinnafond on suuruses 5250, mis jaotatakse TOP3 meeskonna vahel
ära. Iga tiimiliige saab vastavalt saavutatud kohale auhinnaks kas
600, 300 või 150.
</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`}
className={`px-4 py-2 bg-[#1F5673] cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
>
LOE REEGLEID
</button>
</Link>
<a href="https://fienta.com/et/tipilan" target="_blank">
<button
className={`px-4 py-2 bg-[#007CAB] cursor-pointer ${vipnagorgialla.className} font-bold italic`}
className={`px-4 py-2 bg-[#007CAB] cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
>
OSTA PILET
</button>
@ -90,40 +88,38 @@ export default function Tourney() {
</div>
</div>
<div className="flex-auto text-right -skew-x-2 md:-skew-x-5">
<h2 className={`${headingStyle}`}>
LoL turniir
</h2>
<h2 className={`${headingStyle}`}>LoL turniir</h2>
<p className={"text-2xl mb-4 text-neutral-500"}>
Toimumisaeg veel selgumisel
</p>
<p className="text-balance">
TipiLANil toimub Eesti ühe suurima auhinnafondiga LoL turniire juba sel sügisel.
Haara kaasa sõbrad ja saa osa adrenaliinirohkest kogemusest!
TipiLANil toimub Eesti ühe suurima auhinnafondiga LoL turniire
juba sel sügisel. Haara kaasa sõbrad ja saa osa adrenaliinirohkest
kogemusest!
</p>
<br />
<p className="text-balance">
Auhinnafond on suuruses 3500, mis jaotatakse TOP3 meeskonna vahel ära. Iga tiimiliige saab
vastavalt saavutatud kohale auhinnaks kas 400, 200 või 100.
Auhinnafond on suuruses 3500, mis jaotatakse TOP3 meeskonna vahel
ära. Iga tiimiliige saab vastavalt saavutatud kohale auhinnaks kas
400, 200 või 100.
</p>
<br />
<div className="flex flex-row flex-wrap gap-4 md:gap-8 justify-end">
<Link href="/kodukord" target="_blank">
<button
className={`px-4 py-2 bg-[#1F5673] cursor-pointer ${vipnagorgialla.className} font-bold italic`}
className={`px-4 py-2 bg-[#1F5673] cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
>
LOE REEGLEID
</button>
</Link>
<a href="https://fienta.com/et/tipilan" target="_blank">
<button
className={`px-4 py-2 bg-[#007CAB] cursor-pointer ${vipnagorgialla.className} font-bold italic`}
className={`px-4 py-2 bg-[#007CAB] cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
>
OSTA PILET
</button>
</a>
</div>
</div>
</div>
@ -132,33 +128,33 @@ export default function Tourney() {
{/* Mini-turniirid */}
<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}`}>
Mini&shy;turniirid
</h2>
<h2 className={`${headingStyle}`}>Mini&shy;turniirid</h2>
<p className={"text-2xl mb-4 text-neutral-500"}>
Toimumisaeg veel selgumisel
</p>
<p className="text-balance">
TipiLANil toimub mitmeid erinevaid lõbusaid ja võistlushimu tekitavaid miniturniire.
Miniturniirid toimuvad järgnevates mängudes: SimRacing, Tekken, FIFA, Minecraft Bedwars,
Buckshot Roulette, LostGamer ja palju muud.
TipiLANil toimub mitmeid erinevaid lõbusaid ja võistlushimu
tekitavaid miniturniire. Miniturniirid toimuvad järgnevates
mängudes: SimRacing, Tekken, FIFA, Minecraft Bedwars, Buckshot
Roulette, LostGamer ja palju muud.
</p>
<br />
<p className="text-balance">
Auhinnafond on kõigi turniiride peale 1250 ja reeglina saab rahalise auhinna miniturniiri võitja.
Auhinnafond on kõigi turniiride peale 1250 ja reeglina saab
rahalise auhinna miniturniiri võitja.
</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`}
className={`px-4 py-2 bg-[#1F5673] cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
>
LOE REEGLEID
</button>
</Link>
<a href="https://fienta.com/et/tipilan" target="_blank">
<button
className={`px-4 py-2 bg-[#007CAB] cursor-pointer ${vipnagorgialla.className} font-bold italic`}
className={`px-4 py-2 bg-[#007CAB] cursor-pointer ${vipnagorgialla.className} font-bold italic text-[#ECE5E5]`}
>
OSTA PILET
</button>

@ -1,8 +1,8 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
@ -32,8 +32,8 @@ const buttonVariants = cva(
variant: "default",
size: "default",
},
}
)
},
);
function Button({
className,
@ -43,17 +43,25 @@ function Button({
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean
asChild?: boolean;
}) {
const Comp = asChild ? Slot : "button"
if (asChild) {
return (
<Slot
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
{...(props as React.ComponentProps<typeof Slot>)}
/>
);
}
return (
<Comp
<button
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
{...props}
/>
)
);
}
export { Button, buttonVariants }
export { Button, buttonVariants };

@ -0,0 +1,5 @@
## Tulekul
CS2 turniiri reeglid on hetkel ettevalmistamisel ja avaldatakse peagi.
Jälgige meie discordi!
Loading…
Cancel
Save