mirror of
https://github.com/Lapikud/tipilan.git
synced 2026-03-23 21:34:21 +00:00
Merge pull request #46 from Lapikud/development
React 19 update changed the way ref works. Removed redundant packages and updated markdown to use Bun
This commit is contained in:
@@ -1,7 +1,24 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
/* config options here */
|
async headers() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: "/(.*)",
|
||||||
|
headers: [
|
||||||
|
{
|
||||||
|
key: "Content-Security-Policy",
|
||||||
|
value:
|
||||||
|
"frame-src 'self' https://tipilan.ee https://player.twitch.tv https://embed.twitch.tv; frame-ancestors 'self' https://tipilan.ee;",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "X-Frame-Options",
|
||||||
|
value: "SAMEORIGIN",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"drizzle-orm": "^0.44.2",
|
"drizzle-orm": "^0.44.2",
|
||||||
"gray-matter": "^4.0.3",
|
|
||||||
"lucide-react": "^0.522.0",
|
"lucide-react": "^0.522.0",
|
||||||
"material-symbols": "^0.31.8",
|
"material-symbols": "^0.31.8",
|
||||||
"next": "15.3.0",
|
"next": "15.3.0",
|
||||||
@@ -36,7 +35,6 @@
|
|||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-markdown": "^10.1.0",
|
"react-markdown": "^10.1.0",
|
||||||
"remark-gfm": "^4.0.1",
|
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
"three": "^0.178.0",
|
"three": "^0.178.0",
|
||||||
"tw-animate-css": "^1.3.4"
|
"tw-animate-css": "^1.3.4"
|
||||||
|
|||||||
@@ -1,17 +1,11 @@
|
|||||||
// app/kodukord/page.tsx (App Router)
|
// app/kodukord/page.tsx (App Router)
|
||||||
import fs from "node:fs";
|
import ReactMarkdown, { Components } from "react-markdown";
|
||||||
import path from "node:path";
|
import { vipnagorgialla } from "@/components/Vipnagorgialla";
|
||||||
import ReactMarkdown from "react-markdown";
|
|
||||||
import remarkGfm from "remark-gfm";
|
|
||||||
import {vipnagorgialla} from "@/components/Vipnagorgialla";
|
|
||||||
import SectionDivider from "@/components/SectionDivider";
|
import SectionDivider from "@/components/SectionDivider";
|
||||||
|
|
||||||
export const runtime = "nodejs"; // ensure fs is available (not Edge)
|
export default async function Page() {
|
||||||
export const dynamic = "force-static"; // read at build time
|
const file = Bun.file("src/data/kodukord.md");
|
||||||
|
const content = await file.text();
|
||||||
export default function Page() {
|
|
||||||
const filePath = path.join(process.cwd(), "src/data", "kodukord.md");
|
|
||||||
const content = fs.readFileSync(filePath, "utf8");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -25,31 +19,38 @@ export default function Page() {
|
|||||||
|
|
||||||
<div className="prose prose-lg dark:prose-invert max-w-none">
|
<div className="prose prose-lg dark:prose-invert max-w-none">
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
remarkPlugins={[remarkGfm]}
|
components={
|
||||||
components={{
|
{
|
||||||
h1: ({node, ...props}) => (
|
h1: (props) => (
|
||||||
<h1 className="text-3xl md:text-4xl font-bold my-4" {...props} />
|
<h1 className="text-3xl md:text-4xl font-bold my-4">
|
||||||
|
{props.children}
|
||||||
|
</h1>
|
||||||
),
|
),
|
||||||
h2: ({node, ...props}) => (
|
h2: (props) => (
|
||||||
<h2 className="text-2xl md:text-3xl font-semibold my-3" {...props} />
|
<h2 className="text-2xl md:text-3xl font-semibold my-3">
|
||||||
|
{props.children}
|
||||||
|
</h2>
|
||||||
),
|
),
|
||||||
ol: ({node, ...props}) => (
|
ol: (props) => (
|
||||||
<ol className="list-decimal ml-6 md:text-xl" {...props} />
|
<ol className="list-decimal ml-6 md:text-xl">
|
||||||
|
{props.children}
|
||||||
|
</ol>
|
||||||
),
|
),
|
||||||
ul: ({node, ...props}) => (
|
ul: (props) => (
|
||||||
<ul className="list-disc ml-6 md:text-xl" {...props} />
|
<ul className="list-disc ml-6 md:text-xl">
|
||||||
|
{props.children}
|
||||||
|
</ul>
|
||||||
),
|
),
|
||||||
p: ({node, ...props}) => (
|
p: (props) => <p className="md:text-xl">{props.children}</p>,
|
||||||
<p className="md:text-xl" {...props} />
|
} as Components
|
||||||
),
|
}
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{content}
|
{content}
|
||||||
</ReactMarkdown>
|
</ReactMarkdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SectionDivider/>
|
<SectionDivider />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import {vipnagorgialla} from "@/components/Vipnagorgialla";
|
import { vipnagorgialla } from "@/components/Vipnagorgialla";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import {useEffect, useRef, useState} from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import {EyeClosed, Eye} from "lucide-react";
|
import { EyeClosed, Eye } from "lucide-react";
|
||||||
import SectionDivider from "@/components/SectionDivider";
|
|
||||||
|
|
||||||
// Define interface for the ref with toggle function
|
// Define interface for the ref with toggle function
|
||||||
interface MountRefCurrent extends HTMLDivElement {
|
interface MountRefCurrent extends HTMLDivElement {
|
||||||
@@ -14,7 +13,7 @@ interface MountRefCurrent extends HTMLDivElement {
|
|||||||
export default function Expo() {
|
export default function Expo() {
|
||||||
const mountRef = useRef<MountRefCurrent | null>(null);
|
const mountRef = useRef<MountRefCurrent | null>(null);
|
||||||
const [hoveredRoom, setHoveredRoom] = useState<string | 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);
|
const [showDividers, setShowDividers] = useState<boolean>(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -31,17 +30,17 @@ export default function Expo() {
|
|||||||
// Get responsive dimensions
|
// Get responsive dimensions
|
||||||
const getResponsiveDimensions = () => {
|
const getResponsiveDimensions = () => {
|
||||||
const container = mountRef.current;
|
const container = mountRef.current;
|
||||||
if (!container) return {width: 800, height: 600};
|
if (!container) return { width: 800, height: 600 };
|
||||||
|
|
||||||
const containerWidth = container.offsetWidth;
|
const containerWidth = container.offsetWidth;
|
||||||
const maxWidth = Math.min(containerWidth, 800);
|
const maxWidth = Math.min(containerWidth, 800);
|
||||||
const width = Math.max(maxWidth, 300); // Minimum width
|
const width = Math.max(maxWidth, 300); // Minimum width
|
||||||
const height = (width * 600) / 800; // Maintain aspect ratio
|
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
|
// Isometric camera setup with responsive sizing
|
||||||
const aspect = width / height;
|
const aspect = width / height;
|
||||||
@@ -61,7 +60,7 @@ export default function Expo() {
|
|||||||
camera.lookAt(-1.4, 0, 0);
|
camera.lookAt(-1.4, 0, 0);
|
||||||
|
|
||||||
// Renderer
|
// Renderer
|
||||||
const renderer = new THREE.WebGLRenderer({antialias: true});
|
const renderer = new THREE.WebGLRenderer({ antialias: true });
|
||||||
renderer.setSize(width, height);
|
renderer.setSize(width, height);
|
||||||
renderer.shadowMap.enabled = true;
|
renderer.shadowMap.enabled = true;
|
||||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||||||
@@ -84,23 +83,15 @@ export default function Expo() {
|
|||||||
|
|
||||||
// Room colors and names
|
// Room colors and names
|
||||||
const roomColors = [
|
const roomColors = [
|
||||||
0xff6b35, // Orange - Mänguklubi
|
0x343434, // Gray - Lauamängude ala
|
||||||
0x4ecdc4, // Turquoise - Baariala
|
0x4ecdc4, // Turquoise - Baariala
|
||||||
0xffe66d, // Yellow - EVAL
|
0xffe66d, // Yellow - EVAL
|
||||||
0xe74c3c, // Red - Redbull
|
0xff6600, // Orange - Redbull Sim Racing
|
||||||
0x9b59b6, // Purple - Võitlusmängu ala
|
0xff1493, // Deep Pink - Võitlusmängu ala
|
||||||
0x3498db, // Blue - Sony
|
0x3498db, // Blue - Sony
|
||||||
0x2ecc71, // Green - Chillimisala
|
0x2ecc71, // Green - Lava
|
||||||
];
|
0x080682, // Dark Blue - LVLup!
|
||||||
|
0xc02841, // Red - RedBull
|
||||||
const roomNames = [
|
|
||||||
"Mänguklubi",
|
|
||||||
"Baariala",
|
|
||||||
"EVAL",
|
|
||||||
"Redbull",
|
|
||||||
"Võitlusmängu ala",
|
|
||||||
"Sony",
|
|
||||||
"Chillimisala",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Create individual rooms as rectangles with custom positions
|
// Create individual rooms as rectangles with custom positions
|
||||||
@@ -122,62 +113,80 @@ export default function Expo() {
|
|||||||
x: 2.5,
|
x: 2.5,
|
||||||
z: 4,
|
z: 4,
|
||||||
color: roomColors[0],
|
color: roomColors[0],
|
||||||
name: roomNames[0],
|
name: "Lauamängude ala",
|
||||||
}, // Mänguklubi
|
},
|
||||||
// {
|
{
|
||||||
// width: 2.5,
|
width: 3.5,
|
||||||
// height: 0.7,
|
height: 0.7,
|
||||||
// depth: 0.7,
|
depth: 1.2,
|
||||||
// x: 1,
|
x: 0.7,
|
||||||
// z: 0,
|
z: -0.3,
|
||||||
// color: roomColors[1],
|
color: roomColors[1],
|
||||||
// name: roomNames[1],
|
name: "Baariala",
|
||||||
// }, // Baariala
|
},
|
||||||
{
|
{
|
||||||
width: 1.8,
|
width: 1.8,
|
||||||
height: 0.7,
|
height: 0.7,
|
||||||
depth: 1.5,
|
depth: 1.5,
|
||||||
x: 2.5,
|
x: 1,
|
||||||
z: -3.5,
|
z: -3.5,
|
||||||
color: roomColors[2],
|
color: roomColors[2],
|
||||||
name: roomNames[2],
|
name: "EVAL",
|
||||||
}, // EVAL
|
},
|
||||||
{
|
{
|
||||||
width: 2.2,
|
width: 2,
|
||||||
height: 0.7,
|
height: 0.7,
|
||||||
depth: 4.5,
|
depth: 4.5,
|
||||||
x: 5,
|
x: 5.2,
|
||||||
z: -2,
|
z: -2,
|
||||||
color: roomColors[3],
|
color: roomColors[3],
|
||||||
name: roomNames[3],
|
name: "Red Bull Sim Racing",
|
||||||
}, // Redbull
|
},
|
||||||
{
|
{
|
||||||
width: 3,
|
width: 3,
|
||||||
height: 0.7,
|
height: 0.7,
|
||||||
depth: 1.3,
|
depth: 1.5,
|
||||||
x: 0,
|
x: -1.7,
|
||||||
z: -3.5,
|
z: -3.5,
|
||||||
color: roomColors[4],
|
color: roomColors[4],
|
||||||
name: roomNames[4],
|
name: "Võitlusmängu ala",
|
||||||
}, // 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,
|
width: 1.8,
|
||||||
height: 0.7,
|
height: 0.7,
|
||||||
depth: 1.5,
|
depth: 1.5,
|
||||||
x: -2.55,
|
x: 3,
|
||||||
z: -3.5,
|
z: -3.5,
|
||||||
color: roomColors[5],
|
color: roomColors[8],
|
||||||
name: roomNames[5],
|
name: "Red Bull",
|
||||||
}, // Sony
|
},
|
||||||
{
|
|
||||||
width: 4,
|
|
||||||
height: 0.7,
|
|
||||||
depth: 4,
|
|
||||||
x: -5.5,
|
|
||||||
z: -2.3,
|
|
||||||
color: roomColors[6],
|
|
||||||
name: roomNames[6],
|
|
||||||
}, // Chillimisala
|
|
||||||
];
|
];
|
||||||
|
|
||||||
roomDefinitions.forEach((roomDef) => {
|
roomDefinitions.forEach((roomDef) => {
|
||||||
@@ -194,7 +203,7 @@ export default function Expo() {
|
|||||||
room.position.set(roomDef.x, roomDef.height / 2, roomDef.z);
|
room.position.set(roomDef.x, roomDef.height / 2, roomDef.z);
|
||||||
room.castShadow = true;
|
room.castShadow = true;
|
||||||
room.receiveShadow = true;
|
room.receiveShadow = true;
|
||||||
room.userData = {name: roomDef.name, originalColor: roomDef.color};
|
room.userData = { name: roomDef.name, originalColor: roomDef.color };
|
||||||
|
|
||||||
scene.add(room);
|
scene.add(room);
|
||||||
rooms.push(room);
|
rooms.push(room);
|
||||||
@@ -230,14 +239,14 @@ export default function Expo() {
|
|||||||
|
|
||||||
// Add strategic dividers between major areas
|
// Add strategic dividers between major areas
|
||||||
createTogglableDivider(10, 2, 2, -2.5, 1.5); // Wall between main entrance
|
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
|
// Store dividers reference for later access
|
||||||
dividersRef = [...dividers];
|
dividersRef = [...dividers];
|
||||||
|
|
||||||
// Ground plane
|
// Ground plane
|
||||||
const groundGeometry = new THREE.PlaneGeometry(14, 10.5);
|
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);
|
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
|
||||||
ground.rotation.x = -Math.PI / 2;
|
ground.rotation.x = -Math.PI / 2;
|
||||||
ground.position.x = -1.1;
|
ground.position.x = -1.1;
|
||||||
@@ -259,7 +268,7 @@ export default function Expo() {
|
|||||||
|
|
||||||
// Resize handler
|
// Resize handler
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
const {width: newWidth, height: newHeight} = getResponsiveDimensions();
|
const { width: newWidth, height: newHeight } = getResponsiveDimensions();
|
||||||
|
|
||||||
// Update camera
|
// Update camera
|
||||||
const newAspect = newWidth / newHeight;
|
const newAspect = newWidth / newHeight;
|
||||||
@@ -286,14 +295,14 @@ export default function Expo() {
|
|||||||
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
||||||
|
|
||||||
// Update mouse position for tooltip
|
// Update mouse position for tooltip
|
||||||
setMousePosition({x: event.clientX, y: event.clientY});
|
setMousePosition({ x: event.clientX, y: event.clientY });
|
||||||
|
|
||||||
// Update raycaster
|
// Update raycaster
|
||||||
raycaster.setFromCamera(mouse, camera);
|
raycaster.setFromCamera(mouse, camera);
|
||||||
const intersects = raycaster.intersectObjects(rooms);
|
const intersects = raycaster.intersectObjects(rooms);
|
||||||
|
|
||||||
// Reset all rooms to original state
|
// Reset all rooms to original state
|
||||||
roomData.forEach(({mesh, originalColor, originalScale}) => {
|
roomData.forEach(({ mesh, originalColor, originalScale }) => {
|
||||||
(mesh.material as THREE.MeshLambertMaterial).color.setHex(
|
(mesh.material as THREE.MeshLambertMaterial).color.setHex(
|
||||||
originalColor,
|
originalColor,
|
||||||
);
|
);
|
||||||
@@ -370,7 +379,6 @@ export default function Expo() {
|
|||||||
}, [showDividers]);
|
}, [showDividers]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
|
||||||
<div className="flex flex-col min-h-[90vh] m-6 mt-16 md:m-16">
|
<div className="flex flex-col min-h-[90vh] m-6 mt-16 md:m-16">
|
||||||
<h1
|
<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`}
|
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,16 +393,7 @@ export default function Expo() {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div
|
<div
|
||||||
className="w-4 h-4 border border-gray-300"
|
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
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="items-center gap-2 hidden">
|
|
||||||
<div
|
|
||||||
className="w-4 h-4 border border-gray-300"
|
|
||||||
style={{backgroundColor: "#4ecdc4"}}
|
|
||||||
></div>
|
></div>
|
||||||
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
||||||
Baariala
|
Baariala
|
||||||
@@ -403,7 +402,7 @@ export default function Expo() {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div
|
<div
|
||||||
className="w-4 h-4 border border-gray-300"
|
className="w-4 h-4 border border-gray-300"
|
||||||
style={{backgroundColor: "#ffe66d"}}
|
style={{ backgroundColor: "#ffe66d" }}
|
||||||
></div>
|
></div>
|
||||||
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
||||||
EVAL
|
EVAL
|
||||||
@@ -412,25 +411,43 @@ export default function Expo() {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div
|
<div
|
||||||
className="w-4 h-4 border border-gray-300"
|
className="w-4 h-4 border border-gray-300"
|
||||||
style={{backgroundColor: "#e74c3c"}}
|
style={{ backgroundColor: "#343434" }}
|
||||||
></div>
|
></div>
|
||||||
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
||||||
Redbull
|
Lauamängude ala
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div
|
<div
|
||||||
className="w-4 h-4 border border-gray-300"
|
className="w-4 h-4 border border-gray-300"
|
||||||
style={{backgroundColor: "#9b59b6"}}
|
style={{ backgroundColor: "#080682" }}
|
||||||
></div>
|
></div>
|
||||||
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
||||||
Võitlusmängu ala
|
LVLup!
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div
|
<div
|
||||||
className="w-4 h-4 border border-gray-300"
|
className="w-4 h-4 border border-gray-300"
|
||||||
style={{backgroundColor: "#3498db"}}
|
style={{ backgroundColor: "#C02841" }}
|
||||||
|
></div>
|
||||||
|
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
||||||
|
Red Bull
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div
|
||||||
|
className="w-4 h-4 border border-gray-300"
|
||||||
|
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>
|
></div>
|
||||||
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
||||||
Sony
|
Sony
|
||||||
@@ -439,24 +456,24 @@ export default function Expo() {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div
|
<div
|
||||||
className="w-4 h-4 border border-gray-300"
|
className="w-4 h-4 border border-gray-300"
|
||||||
style={{backgroundColor: "#2ecc71"}}
|
style={{ backgroundColor: "#ff1493" }}
|
||||||
></div>
|
></div>
|
||||||
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
<span className="text-sm text-[#2A2C3F] dark:text-[#EEE5E5]">
|
||||||
Chillimisala
|
Võitlusmängu ala
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col lg:flex-row gap-8 items-start">
|
<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 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
|
<button
|
||||||
onClick={() => setShowDividers(!showDividers)}
|
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`}
|
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 ? (
|
{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"}
|
{showDividers ? "Peida" : "Näita"}
|
||||||
@@ -478,8 +495,5 @@ export default function Expo() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SectionDivider />
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,103 @@
|
|||||||
import {vipnagorgialla} from "@/components/Vipnagorgialla";
|
import { notFound } from "next/navigation";
|
||||||
import path from "node:path";
|
import ReactMarkdown, { Components } from "react-markdown";
|
||||||
import fs from "node:fs/promises";
|
import { vipnagorgialla } from "@/components/Vipnagorgialla";
|
||||||
import ReactMarkdown from "react-markdown";
|
|
||||||
import SectionDivider from "@/components/SectionDivider";
|
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 }>;
|
params: Promise<{ slug: string }>;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default async function RulePage({params}: Props) {
|
async function getRuleContent(slug: string) {
|
||||||
const {slug} = await params;
|
if (!Object.keys(rulesMap).includes(slug)) {
|
||||||
|
return null;
|
||||||
const filePath = path.join(process.cwd(), "src/data/rules", `${slug}.md`);
|
|
||||||
let file: string;
|
|
||||||
|
|
||||||
try {
|
|
||||||
file = await fs.readFile(filePath, "utf8");
|
|
||||||
} catch {
|
|
||||||
file = `# ${slug.toUpperCase()} REEGLID\n\nSisu hetkel puudub.`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {title: undefined as string | undefined};
|
const ruleConfig = rulesMap[slug as RuleSlug];
|
||||||
|
|
||||||
|
try {
|
||||||
|
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 headingStyle = `text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold uppercase italic text-[#2A2C3F] dark:text-[#EEE5E5]`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div>
|
||||||
<div className="mb-16">
|
<div className="flex flex-col min-h-[90vh] m-6 mt-16 md:m-16">
|
||||||
<h1
|
<h1 className={`${headingStyle} mt-8 md:mt-16 mb-4`}>
|
||||||
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`}
|
{ruleData.title}
|
||||||
>
|
|
||||||
{data.title || `${slug.toUpperCase()} REEGLID`}
|
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div
|
<div className="prose prose-lg dark:prose-invert max-w-none">
|
||||||
className={`mx-auto px-8 font-worksans
|
<ReactMarkdown
|
||||||
[&_ol]:ml-6
|
components={
|
||||||
[&_ol_ol]:ml-10
|
{
|
||||||
[&_ol_ol_ol]:ml-14
|
h1: (props) => (
|
||||||
[&_h2]:font-bold
|
<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>
|
||||||
</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 Link from "next/link";
|
||||||
import SectionDivider from "@/components/SectionDivider";
|
import SectionDivider from "@/components/SectionDivider";
|
||||||
|
|
||||||
export default function RulesMenu() {
|
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]`;
|
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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="flex flex-col md:m-16">
|
<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
|
REEGLID
|
||||||
</h1>
|
</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">
|
<Link href="/kodukord">
|
||||||
<div className={`${boxStyle} bg-[#007CAB] py-20`}>
|
<div className={`${boxStyle} bg-[#007CAB] py-20 px-8`}>
|
||||||
<h2 className={`${boxTextStyle}`}>
|
<h2 className={`${boxTextStyle}`}>Kodukord</h2>
|
||||||
Kodukord
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link href="/reeglid/cs2">
|
<Link href="/reeglid/cs2">
|
||||||
<div className={`${boxStyle} bg-[#1F5673] py-20`}>
|
<div className={`${boxStyle} bg-[#1F5673] py-20 px-8`}>
|
||||||
<h2 className={`${boxTextStyle}`}>
|
<h2 className={`${boxTextStyle}`}>CS2 reeglid</h2>
|
||||||
CS2 reeglid
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
|
||||||
<Link href="reeglid/lol">
|
<Link href="reeglid/lol">
|
||||||
<div className={`${boxStyle} bg-[#007CAB] py-20`}>
|
<div className={`${boxStyle} bg-[#007CAB] py-20 px-8`}>
|
||||||
<h2 className={`${boxTextStyle}`}>
|
<h2 className={`${boxTextStyle}`}>LoL reeglid</h2>
|
||||||
LoL reeglid
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* Minitourn. link coming soon*/}
|
{/* Minitourn. link coming soon*/}
|
||||||
{/*<Link href="">*/}
|
{/*<Link href="">*/}
|
||||||
<div
|
<div className={`${boxStyle} bg-[#1F5673] py-16 px-8`}>
|
||||||
className={`${boxStyle} bg-[#1F5673] py-16`}>
|
<h2 className={`${boxTextStyle}`}>Miniturniiride reeglid</h2>
|
||||||
<h2 className={`${boxTextStyle}`}>
|
|
||||||
Miniturniiride reeglid
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
{/*</Link>*/}
|
{/*</Link>*/}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SectionDivider />
|
<SectionDivider />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
210
src/app/striim/page.tsx
Normal file
210
src/app/striim/page.tsx
Normal file
@@ -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­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 */}
|
{/* 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="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">
|
<div className="-skew-x-2 md:-skew-x-5">
|
||||||
<h2 className={`${headingStyle}`}>
|
<h2 className={`${headingStyle}`}>CS2 turniir</h2>
|
||||||
CS2 turniir
|
|
||||||
</h2>
|
|
||||||
<p className={"text-2xl mb-4 text-neutral-500"}>
|
<p className={"text-2xl mb-4 text-neutral-500"}>
|
||||||
Toimumisaeg veel selgumisel
|
Toimumisaeg veel selgumisel
|
||||||
</p>
|
</p>
|
||||||
<p className="text-balance">
|
<p className="text-balance">
|
||||||
TipiLANil toimub Eesti ühe suurima auhinnafondiga CS2 turniire juba sel sügisel. Haara kaasa
|
TipiLANil toimub Eesti ühe suurima auhinnafondiga CS2 turniire
|
||||||
sõbrad ja
|
juba sel sügisel. Haara kaasa sõbrad ja saa osa adrenaliinirohkest
|
||||||
saa osa adrenaliinirohkest kogemusest!
|
kogemusest!
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<p className="text-balance">
|
<p className="text-balance">
|
||||||
Auhinnafond on suuruses 5250€, mis jaotatakse TOP3 meeskonna vahel ära. Iga tiimiliige saab
|
Auhinnafond on suuruses 5250€, mis jaotatakse TOP3 meeskonna vahel
|
||||||
vastavalt
|
ära. Iga tiimiliige saab vastavalt saavutatud kohale auhinnaks kas
|
||||||
saavutatud kohale auhinnaks kas 600€, 300€ või 150€.
|
600€, 300€ või 150€.
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<div className={"flex flex-row flex-wrap gap-8"}>
|
<div className={"flex flex-row flex-wrap gap-8"}>
|
||||||
<Link href="/reeglid/cs2" target="_blank">
|
<Link href="/reeglid/cs2" target="_blank">
|
||||||
<button
|
<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
|
LOE REEGLEID
|
||||||
</button>
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
<a href="https://fienta.com/et/tipilan" target="_blank">
|
<a href="https://fienta.com/et/tipilan" target="_blank">
|
||||||
<button
|
<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
|
OSTA PILET
|
||||||
</button>
|
</button>
|
||||||
@@ -90,40 +88,38 @@ export default function Tourney() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-auto text-right -skew-x-2 md:-skew-x-5">
|
<div className="flex-auto text-right -skew-x-2 md:-skew-x-5">
|
||||||
<h2 className={`${headingStyle}`}>
|
<h2 className={`${headingStyle}`}>LoL turniir</h2>
|
||||||
LoL turniir
|
|
||||||
</h2>
|
|
||||||
<p className={"text-2xl mb-4 text-neutral-500"}>
|
<p className={"text-2xl mb-4 text-neutral-500"}>
|
||||||
Toimumisaeg veel selgumisel
|
Toimumisaeg veel selgumisel
|
||||||
</p>
|
</p>
|
||||||
<p className="text-balance">
|
<p className="text-balance">
|
||||||
TipiLANil toimub Eesti ühe suurima auhinnafondiga LoL turniire juba sel sügisel.
|
TipiLANil toimub Eesti ühe suurima auhinnafondiga LoL turniire
|
||||||
Haara kaasa sõbrad ja saa osa adrenaliinirohkest kogemusest!
|
juba sel sügisel. Haara kaasa sõbrad ja saa osa adrenaliinirohkest
|
||||||
|
kogemusest!
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<p className="text-balance">
|
<p className="text-balance">
|
||||||
Auhinnafond on suuruses 3500€, mis jaotatakse TOP3 meeskonna vahel ära. Iga tiimiliige saab
|
Auhinnafond on suuruses 3500€, mis jaotatakse TOP3 meeskonna vahel
|
||||||
vastavalt saavutatud kohale auhinnaks kas 400€, 200€ või 100€.
|
ära. Iga tiimiliige saab vastavalt saavutatud kohale auhinnaks kas
|
||||||
|
400€, 200€ või 100€.
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<div className="flex flex-row flex-wrap gap-4 md:gap-8 justify-end">
|
<div className="flex flex-row flex-wrap gap-4 md:gap-8 justify-end">
|
||||||
<Link href="/kodukord" target="_blank">
|
<Link href="/kodukord" target="_blank">
|
||||||
<button
|
<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
|
LOE REEGLEID
|
||||||
</button>
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
<a href="https://fienta.com/et/tipilan" target="_blank">
|
<a href="https://fienta.com/et/tipilan" target="_blank">
|
||||||
<button
|
<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
|
OSTA PILET
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -132,33 +128,33 @@ export default function Tourney() {
|
|||||||
{/* Mini-turniirid */}
|
{/* 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="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">
|
<div className="-skew-x-2 md:-skew-x-5">
|
||||||
<h2 className={`${headingStyle}`}>
|
<h2 className={`${headingStyle}`}>Mini­turniirid</h2>
|
||||||
Mini­turniirid
|
|
||||||
</h2>
|
|
||||||
<p className={"text-2xl mb-4 text-neutral-500"}>
|
<p className={"text-2xl mb-4 text-neutral-500"}>
|
||||||
Toimumisaeg veel selgumisel
|
Toimumisaeg veel selgumisel
|
||||||
</p>
|
</p>
|
||||||
<p className="text-balance">
|
<p className="text-balance">
|
||||||
TipiLANil toimub mitmeid erinevaid lõbusaid ja võistlushimu tekitavaid miniturniire.
|
TipiLANil toimub mitmeid erinevaid lõbusaid ja võistlushimu
|
||||||
Miniturniirid toimuvad järgnevates mängudes: SimRacing, Tekken, FIFA, Minecraft Bedwars,
|
tekitavaid miniturniire. Miniturniirid toimuvad järgnevates
|
||||||
Buckshot Roulette, LostGamer ja palju muud.
|
mängudes: SimRacing, Tekken, FIFA, Minecraft Bedwars, Buckshot
|
||||||
|
Roulette, LostGamer ja palju muud.
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<p className="text-balance">
|
<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>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<div className="flex flex-row flex-wrap gap-4 md:gap-8">
|
<div className="flex flex-row flex-wrap gap-4 md:gap-8">
|
||||||
<Link href="/kodukord" target="_blank">
|
<Link href="/kodukord" target="_blank">
|
||||||
<button
|
<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
|
LOE REEGLEID
|
||||||
</button>
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
<a href="https://fienta.com/et/tipilan" target="_blank">
|
<a href="https://fienta.com/et/tipilan" target="_blank">
|
||||||
<button
|
<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
|
OSTA PILET
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
import { Slot } from "@radix-ui/react-slot"
|
import { Slot } from "@radix-ui/react-slot";
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
import { cva, type VariantProps } from "class-variance-authority";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
const buttonVariants = cva(
|
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",
|
"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",
|
variant: "default",
|
||||||
size: "default",
|
size: "default",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
)
|
);
|
||||||
|
|
||||||
function Button({
|
function Button({
|
||||||
className,
|
className,
|
||||||
@@ -43,17 +43,25 @@ function Button({
|
|||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"button"> &
|
}: React.ComponentProps<"button"> &
|
||||||
VariantProps<typeof buttonVariants> & {
|
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 (
|
return (
|
||||||
<Comp
|
<button
|
||||||
data-slot="button"
|
data-slot="button"
|
||||||
className={cn(buttonVariants({ variant, size, className }))}
|
className={cn(buttonVariants({ variant, size, className }))}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Button, buttonVariants }
|
export { Button, buttonVariants };
|
||||||
|
|||||||
5
src/data/rules/cs2.md
Normal file
5
src/data/rules/cs2.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
## Tulekul
|
||||||
|
|
||||||
|
CS2 turniiri reeglid on hetkel ettevalmistamisel ja avaldatakse peagi.
|
||||||
|
|
||||||
|
Jälgige meie discordi!
|
||||||
Reference in New Issue
Block a user