From e6bd09616f1ff2546889327210ec07c77c2e2754 Mon Sep 17 00:00:00 2001 From: SwagMuffin88 Date: Tue, 12 Aug 2025 11:17:11 +0300 Subject: [PATCH 01/22] fix image skew on tourn page --- src/app/turniirid/page.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/app/turniirid/page.tsx b/src/app/turniirid/page.tsx index e4c3c27..68daef5 100644 --- a/src/app/turniirid/page.tsx +++ b/src/app/turniirid/page.tsx @@ -19,6 +19,7 @@ export default function Tourney() { {/* Kui tahate oma oskusi proovile panna, siis vaadake siia tagasi! Rohkem*/} {/* infot lähiajal.*/} {/*

*/} +
{/* CS2 turniir */}
@@ -59,8 +60,8 @@ export default function Tourney() {
-
- {/* Image needs to be the div that has the skew. Outside div needs to remain so that overflow wont occur*/} +
+ {/* Outside div needs to remain so that overflow won't occur*/} CS2 tournament
-
- {/* Image needs to be the div that has the skew. Outside div needs to remain so that overflow wont occur*/} +
+ {/* Outside div needs to remain so that overflow won't occur*/} LoL tournament
-
- {/* Image needs to be the div that has the skew. Outside div needs to remain so that overflow wont occur*/} +
+ {/* Outside div needs to remain so that overflow won't occur*/} mini tournaments Date: Tue, 12 Aug 2025 11:37:58 +0300 Subject: [PATCH 02/22] fix heading skew in tourn --- src/app/turniirid/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/turniirid/page.tsx b/src/app/turniirid/page.tsx index 68daef5..ae96352 100644 --- a/src/app/turniirid/page.tsx +++ b/src/app/turniirid/page.tsx @@ -3,7 +3,7 @@ import Link from "next/link"; import Image from "next/image"; export default function Tourney() { - const headingStyle = `text-3xl md:text-5xl lg:text-5xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] dark:text-[#EEE5E5] -skew-x-2 md:-skew-x-5`; + 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`; const SectionDivider = () =>
; From e1baa116eaa72041f11ffcd6d00d5c09ba261c4d Mon Sep 17 00:00:00 2001 From: Rene Arumetsa Date: Thu, 14 Aug 2025 18:27:27 +0300 Subject: [PATCH 03/22] Update kodukord, not hardcoded anymor, but as a .md file --- src/app/kodukord/page.tsx | 89 +++++++++++++++++---------------------- src/data/kodukord.md | 30 +++++++++++++ 2 files changed, 68 insertions(+), 51 deletions(-) create mode 100644 src/data/kodukord.md diff --git a/src/app/kodukord/page.tsx b/src/app/kodukord/page.tsx index f5e597e..73a380f 100644 --- a/src/app/kodukord/page.tsx +++ b/src/app/kodukord/page.tsx @@ -1,63 +1,50 @@ +// 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"; -export default function Rulebook() { +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"); + return (
+ {/* Page title (separate from markdown headings) */}

Kodukord

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

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

+ +
+ ( +

+ ), + h2: ({node, ...props}) => ( +

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

      + ), + }} + > + {content} + +

); } diff --git a/src/data/kodukord.md b/src/data/kodukord.md new file mode 100644 index 0000000..d70e5c0 --- /dev/null +++ b/src/data/kodukord.md @@ -0,0 +1,30 @@ +Üritusel osalemise kodukord kehtib kõigile, nii külastajatele kui võistlejatele. Kodukorra rikkumisel jätab TipiLAN endale õiguse osaleja ürituselt eemaldada ning vajadusel teavitada politseid. Alaealise osaleja puhul teavitame raskema kodukorra eiramise puhul tema vanemaid või eestkostjaid. + +# Osaleja meelespea + +1. Tulles vaheta oma pilet käepaela vastu. +2. Osaleja peab olema vähemalt 16-aastane. Pileti kontrollija võib küsida Sinult dokumenti. +3. Üritust pildistatakse ning filmitakse ja ürituse sisu kajastatakse erinevates meediakanalites. +4. Kui Sul on ette nähtud TipiLANi poolne majutus, anna sellest teada pileti käepaela vastu vahetamisel. +5. Kui tuled oma arvutiga, juhendatakse Sind käepaela saades, kuhu saad selle üles panna. + +# Ürituse kodukord + +1. Osaleja kohustub käituma viisakalt ning väärikalt ja austama teisi üritusel osalejaid. +2. TipiLAN ei tolereeri: + 2.1. Vihakõnet rahvusliku, rassilise, soolise, seksuaalse või religioosse kuuluvuse, puude, välimuse või vanuse kohta; ahistamist, ähvardavat, solvavat või agressiivset käitumist, sellele õhutamist või selle pooldamist + 2.2. See kehtib nii ürituse alal (IRL) kui ka üritusega seotud online-keskkondades. +3. Osaleja kohustub käituma ürituse hoone, inventari ja sisustuse suhtes heaperemehelikult. Keelatud on lõhkuda, määrida või viia mujale esemeid, mis ei kuulu osalejale. + 3.1. Kui osalejal on ette nähtud korraldajapoolne majutus, siis majutusalal on osalejal kohustus olla vaikselt ning lubada kaaslastel puhata. + 3.2. Majutusalale ei või kaasa kutsuda isikuid, kellel ei ole seal majutust ette nähtud. +4. TipiLAN ei vastuta osaleja isikliku vara eest. + 4.1. Korraldajapoolne majutusala on lukustatav ning kõrvalisi isikuid sinna ei lubata, kuid sellest sõltumata tasub oma väärisesemetel silma peal hoida. + 4.2. Kui on tekkinud kahtlus, et on toimunud vargus, tuleb sellest koheselt teavitada korraldajat. + 4.3. Kaotatud asjade leidmisel palume anda need korraldajale või viia need *lost & found’i* (Merchilauda). +5. Ürituse alal on keelatud suitsetada ning kasutada vape’i. Selleks on õues ette nähtud suitsetamise kohad. +6. Üritusele ei tohi kaasa võtta illegaalseid aineid või ravimeid, terariistu, tulirelvi, lõhke- või süüteained ning muid esemeid, mis võivad osalejatele või teistele viga teha. +7. Alaealisel osalejal on keelatud tarbida alkoholi või kasutada nikotiini sisaldavaid tooteid. + 7.1. Olles baarist alkoholi ostmas, on osalejal baaritöötaja nõudmisel kohustus näidata isikuttõendavat dokumenti. +8. Osaleja kohustub käituma alkoholi suhtes vastutustundlikult. +9. Keelatud on igasugune hasartmäng nii raha kui muude hüvede peale. + From f0be2711cedec5551c380a66369b9876fcd12198 Mon Sep 17 00:00:00 2001 From: SwagMuffin88 Date: Fri, 15 Aug 2025 10:51:35 +0300 Subject: [PATCH 04/22] create separate component for SectionDivider --- src/components/SectionDivider.tsx | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/components/SectionDivider.tsx diff --git a/src/components/SectionDivider.tsx b/src/components/SectionDivider.tsx new file mode 100644 index 0000000..dc88b17 --- /dev/null +++ b/src/components/SectionDivider.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +export default function SectionDivider() { + return ( +
+ ); +}; From 5a7f4d87ee094b4e45ee69a5b6e849258f5fabe7 Mon Sep 17 00:00:00 2001 From: SwagMuffin88 Date: Fri, 15 Aug 2025 10:53:22 +0300 Subject: [PATCH 05/22] add SectionDivider component to all pages --- src/app/ajakava/page.tsx | 125 ++--- src/app/kodukord/page.tsx | 79 +-- src/app/messiala/page.tsx | 911 ++++++++++++++++---------------- src/app/piletid/page.tsx | 189 +++---- src/app/reeglid/[slug]/page.tsx | 77 +-- 5 files changed, 705 insertions(+), 676 deletions(-) diff --git a/src/app/ajakava/page.tsx b/src/app/ajakava/page.tsx index ce78a6c..8bd1850 100644 --- a/src/app/ajakava/page.tsx +++ b/src/app/ajakava/page.tsx @@ -1,72 +1,77 @@ "use client"; -import { useState } from "react"; -import { vipnagorgialla } from "@/components/Vipnagorgialla"; -import { scheduleData } from "@/data/timetable"; +import {useState} from "react"; +import {vipnagorgialla} from "@/components/Vipnagorgialla"; +import {scheduleData} from "@/data/timetable"; +import SectionDivider from "@/components/SectionDivider"; const tabs = Object.keys(scheduleData); export default function Timetable() { - const [activeTab, setActiveTab] = useState(tabs[0]); - const schedule = scheduleData[activeTab]; + const [activeTab, setActiveTab] = useState(tabs[0]); + const schedule = scheduleData[activeTab]; - return ( -
-

- Ajakava -

+ return ( +
+
+

+ Ajakava +

- {/* Tab menu */} -
- {tabs.map((tab) => ( - - ))} -
- - {/* Schedule entries */} -
- {schedule.map((item, idx) => ( -
-
- {item.time} -
-
-
- {item.title} -
- {item.description && ( -
- {item.description} + {/* Tab menu */} +
+ {tabs.map((tab) => ( + + ))}
- )} - {item.location && ( -
- {item.location} + + {/* Schedule entries */} +
+ {schedule.map((item, idx) => ( +
+
+ {item.time} +
+
+
+ {item.title} +
+ {item.description && ( +
+ {item.description} +
+ )} + {item.location && ( +
+ {item.location} +
+ )} +
+
+ ))}
- )}
-
- ))} -
-
- ); + + +
+ ); } diff --git a/src/app/kodukord/page.tsx b/src/app/kodukord/page.tsx index 73a380f..68cb8a1 100644 --- a/src/app/kodukord/page.tsx +++ b/src/app/kodukord/page.tsx @@ -3,48 +3,53 @@ 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 {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"); + const filePath = path.join(process.cwd(), "src/data", "kodukord.md"); + const content = fs.readFileSync(filePath, "utf8"); - return ( -
- {/* Page title (separate from markdown headings) */} -

- Kodukord -

+ return ( +
+
+ {/* Page title (separate from markdown headings) */} +

+ Kodukord +

-
- ( -

- ), - h2: ({node, ...props}) => ( -

- ), - ol: ({node, ...props}) => ( -
    - ), - ul: ({node, ...props}) => ( -
      - ), - p: ({node, ...props}) => ( -

      - ), - }} - > - {content} - -

-
- ); +
+ ( +

+ ), + h2: ({node, ...props}) => ( +

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

      + ), + }} + > + {content} + +

+
+ + +
+ ); } diff --git a/src/app/messiala/page.tsx b/src/app/messiala/page.tsx index f95322d..c74a105 100644 --- a/src/app/messiala/page.tsx +++ b/src/app/messiala/page.tsx @@ -1,480 +1,485 @@ "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 {useEffect, useRef, useState} from "react"; +import {EyeClosed, Eye} from "lucide-react"; +import SectionDivider from "@/components/SectionDivider"; // Define interface for the ref with toggle function interface MountRefCurrent extends HTMLDivElement { - toggleDividers?: (show: boolean) => void; + toggleDividers?: (show: boolean) => void; } export default function Expo() { - const mountRef = useRef(null); - const [hoveredRoom, setHoveredRoom] = useState(null); - const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }); - const [showDividers, setShowDividers] = useState(true); - - useEffect(() => { - if (!mountRef.current) return; - - // Copy ref to variable to avoid stale closure in cleanup - const mountElement = mountRef.current; - let dividersRef: THREE.Mesh[] = []; - - // Scene setup - const scene = new THREE.Scene(); - scene.background = new THREE.Color(0x0e0f19); - - // Get responsive dimensions - const getResponsiveDimensions = () => { - const container = mountRef.current; - 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 }; - }; - - const { width, height } = getResponsiveDimensions(); - - // Isometric camera setup with responsive sizing - const aspect = width / height; - const baseFrustumSize = 14; - const frustumSize = width < 600 ? baseFrustumSize * 0.8 : baseFrustumSize; // Smaller frustum for mobile - const camera = new THREE.OrthographicCamera( - (frustumSize * aspect) / -2, - (frustumSize * aspect) / 2, - frustumSize / 2, - frustumSize / -2, - 1, - 1000, - ); - - // Position camera for isometric view - camera.position.set(10, 10, 14); - camera.lookAt(-1.4, 0, 0); - - // Renderer - const renderer = new THREE.WebGLRenderer({ antialias: true }); - renderer.setSize(width, height); - renderer.shadowMap.enabled = true; - renderer.shadowMap.type = THREE.PCFSoftShadowMap; - mountElement.appendChild(renderer.domElement); - - // Raycaster for mouse interactions - const raycaster = new THREE.Raycaster(); - const mouse = new THREE.Vector2(); - - // Lighting - const ambientLight = new THREE.AmbientLight(0x404040, 1.2); - scene.add(ambientLight); - - const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5); - directionalLight.position.set(10, 10, 5); - directionalLight.castShadow = false; - directionalLight.shadow.mapSize.width = 2048; - directionalLight.shadow.mapSize.height = 2048; - scene.add(directionalLight); - - // Room colors and names - const roomColors = [ - 0xff6b35, // Orange - Mänguklubi - 0x4ecdc4, // Turquoise - Baariala - 0xffe66d, // Yellow - EVAL - 0xe74c3c, // Red - Redbull - 0x9b59b6, // Purple - Võitlusmängu ala - 0x3498db, // Blue - Sony - 0x2ecc71, // Green - Chillimisala - ]; - - const roomNames = [ - "Mänguklubi", - "Baariala", - "EVAL", - "Redbull", - "Võitlusmängu ala", - "Sony", - "Chillimisala", - ]; - - // Create individual rooms as rectangles with custom positions - const rooms: THREE.Mesh[] = []; - const roomData: Array<{ - mesh: THREE.Mesh; - name: string; - originalColor: number; - originalScale: THREE.Vector3; - }> = []; - const dividers: THREE.Mesh[] = []; - - // Define rooms with custom positions, sizes and colors - const roomDefinitions = [ - { - width: 7, - height: 0.7, - depth: 3, - 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 - { - width: 1.8, - height: 0.7, - depth: 1.5, - x: 2.5, - z: -3.5, - color: roomColors[2], - name: roomNames[2], - }, // EVAL - { - width: 2.2, - height: 0.7, - depth: 4.5, - x: 5, - z: -2, - color: roomColors[3], - name: roomNames[3], - }, // Redbull - { - width: 3, - height: 0.7, - depth: 1.3, - x: 0, - z: -3.5, - color: roomColors[4], - name: roomNames[4], - }, // Võitlusmängu ala - { - width: 1.8, - height: 0.7, - depth: 1.5, - x: -2.55, - 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 - ]; - - roomDefinitions.forEach((roomDef) => { - const geometry = new THREE.BoxGeometry( - roomDef.width, - roomDef.height, - roomDef.depth, - ); - const material = new THREE.MeshLambertMaterial({ - color: roomDef.color, - }); - - const room = new THREE.Mesh(geometry, material); - room.position.set(roomDef.x, roomDef.height / 2, roomDef.z); - room.castShadow = true; - room.receiveShadow = true; - room.userData = { name: roomDef.name, originalColor: roomDef.color }; - - scene.add(room); - rooms.push(room); - roomData.push({ - mesh: room, - name: roomDef.name, - originalColor: roomDef.color, - originalScale: room.scale.clone(), - }); - }); - - // Create toggleable room dividers - const createTogglableDivider = ( - width: number, - height: number, - depth: number, - x: number, - z: number, - ) => { - const wallGeometry = new THREE.BoxGeometry(width, height, depth); - const wallMaterial = new THREE.MeshLambertMaterial({ - color: 0x555555, - transparent: true, - opacity: 0, - }); - - const wall = new THREE.Mesh(wallGeometry, wallMaterial); - wall.position.set(x, height / 2, z); - wall.visible = false; - scene.add(wall); - dividers.push(wall); - }; - - // 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 - - // 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 ground = new THREE.Mesh(groundGeometry, groundMaterial); - ground.rotation.x = -Math.PI / 2; - ground.position.x = -1.1; - ground.position.y = -0.5; - ground.receiveShadow = true; - scene.add(ground); - - // Second ground plane - const groundGeometry2 = new THREE.PlaneGeometry(2, 7); - const groundMaterial2 = new THREE.MeshLambertMaterial({ - color: 0xcccccc, - }); - const ground2 = new THREE.Mesh(groundGeometry2, groundMaterial2); - ground2.rotation.x = -Math.PI / 2; - ground2.position.x = -12.2; - ground2.position.y = -5; - ground2.receiveShadow = true; - scene.add(ground2); - - // Resize handler - const handleResize = () => { - const { width: newWidth, height: newHeight } = getResponsiveDimensions(); - - // Update camera - const newAspect = newWidth / newHeight; - const newFrustumSize = - newWidth < 600 ? baseFrustumSize * 0.8 : baseFrustumSize; - - camera.left = (newFrustumSize * newAspect) / -2; - camera.right = (newFrustumSize * newAspect) / 2; - camera.top = newFrustumSize / 2; - camera.bottom = newFrustumSize / -2; - camera.updateProjectionMatrix(); - - // Update renderer - renderer.setSize(newWidth, newHeight); - }; - - // Add resize event listener - window.addEventListener("resize", handleResize); - - // Mouse event handlers - const onMouseMove = (event: MouseEvent) => { - const rect = renderer.domElement.getBoundingClientRect(); - mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; - mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; - - // Update mouse position for tooltip - 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 }) => { - (mesh.material as THREE.MeshLambertMaterial).color.setHex( - originalColor, + const mountRef = useRef(null); + const [hoveredRoom, setHoveredRoom] = useState(null); + const [mousePosition, setMousePosition] = useState({x: 0, y: 0}); + const [showDividers, setShowDividers] = useState(true); + + useEffect(() => { + if (!mountRef.current) return; + + // Copy ref to variable to avoid stale closure in cleanup + const mountElement = mountRef.current; + let dividersRef: THREE.Mesh[] = []; + + // Scene setup + const scene = new THREE.Scene(); + scene.background = new THREE.Color(0x0e0f19); + + // Get responsive dimensions + const getResponsiveDimensions = () => { + const container = mountRef.current; + 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}; + }; + + const {width, height} = getResponsiveDimensions(); + + // Isometric camera setup with responsive sizing + const aspect = width / height; + const baseFrustumSize = 14; + const frustumSize = width < 600 ? baseFrustumSize * 0.8 : baseFrustumSize; // Smaller frustum for mobile + const camera = new THREE.OrthographicCamera( + (frustumSize * aspect) / -2, + (frustumSize * aspect) / 2, + frustumSize / 2, + frustumSize / -2, + 1, + 1000, ); - mesh.scale.copy(originalScale); - }); - - if (intersects.length > 0) { - const hoveredMesh = intersects[0].object as THREE.Mesh; - const roomInfo = roomData.find((r) => r.mesh === hoveredMesh); - - if (roomInfo) { - // Apply hover effects - (hoveredMesh.material as THREE.MeshLambertMaterial).color.setHex( - 0xffffff, - ); - hoveredMesh.scale.multiplyScalar(1.02); - setHoveredRoom(roomInfo.name); + + // Position camera for isometric view + camera.position.set(10, 10, 14); + camera.lookAt(-1.4, 0, 0); + + // Renderer + const renderer = new THREE.WebGLRenderer({antialias: true}); + renderer.setSize(width, height); + renderer.shadowMap.enabled = true; + renderer.shadowMap.type = THREE.PCFSoftShadowMap; + mountElement.appendChild(renderer.domElement); + + // Raycaster for mouse interactions + const raycaster = new THREE.Raycaster(); + const mouse = new THREE.Vector2(); + + // Lighting + const ambientLight = new THREE.AmbientLight(0x404040, 1.2); + scene.add(ambientLight); + + const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5); + directionalLight.position.set(10, 10, 5); + directionalLight.castShadow = false; + directionalLight.shadow.mapSize.width = 2048; + directionalLight.shadow.mapSize.height = 2048; + scene.add(directionalLight); + + // Room colors and names + const roomColors = [ + 0xff6b35, // Orange - Mänguklubi + 0x4ecdc4, // Turquoise - Baariala + 0xffe66d, // Yellow - EVAL + 0xe74c3c, // Red - Redbull + 0x9b59b6, // Purple - Võitlusmängu ala + 0x3498db, // Blue - Sony + 0x2ecc71, // Green - Chillimisala + ]; + + const roomNames = [ + "Mänguklubi", + "Baariala", + "EVAL", + "Redbull", + "Võitlusmängu ala", + "Sony", + "Chillimisala", + ]; + + // Create individual rooms as rectangles with custom positions + const rooms: THREE.Mesh[] = []; + const roomData: Array<{ + mesh: THREE.Mesh; + name: string; + originalColor: number; + originalScale: THREE.Vector3; + }> = []; + const dividers: THREE.Mesh[] = []; + + // Define rooms with custom positions, sizes and colors + const roomDefinitions = [ + { + width: 7, + height: 0.7, + depth: 3, + 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 + { + width: 1.8, + height: 0.7, + depth: 1.5, + x: 2.5, + z: -3.5, + color: roomColors[2], + name: roomNames[2], + }, // EVAL + { + width: 2.2, + height: 0.7, + depth: 4.5, + x: 5, + z: -2, + color: roomColors[3], + name: roomNames[3], + }, // Redbull + { + width: 3, + height: 0.7, + depth: 1.3, + x: 0, + z: -3.5, + color: roomColors[4], + name: roomNames[4], + }, // Võitlusmängu ala + { + width: 1.8, + height: 0.7, + depth: 1.5, + x: -2.55, + 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 + ]; + + roomDefinitions.forEach((roomDef) => { + const geometry = new THREE.BoxGeometry( + roomDef.width, + roomDef.height, + roomDef.depth, + ); + const material = new THREE.MeshLambertMaterial({ + color: roomDef.color, + }); + + const room = new THREE.Mesh(geometry, material); + room.position.set(roomDef.x, roomDef.height / 2, roomDef.z); + room.castShadow = true; + room.receiveShadow = true; + room.userData = {name: roomDef.name, originalColor: roomDef.color}; + + scene.add(room); + rooms.push(room); + roomData.push({ + mesh: room, + name: roomDef.name, + originalColor: roomDef.color, + originalScale: room.scale.clone(), + }); + }); + + // Create toggleable room dividers + const createTogglableDivider = ( + width: number, + height: number, + depth: number, + x: number, + z: number, + ) => { + const wallGeometry = new THREE.BoxGeometry(width, height, depth); + const wallMaterial = new THREE.MeshLambertMaterial({ + color: 0x555555, + transparent: true, + opacity: 0, + }); + + const wall = new THREE.Mesh(wallGeometry, wallMaterial); + wall.position.set(x, height / 2, z); + wall.visible = false; + scene.add(wall); + dividers.push(wall); + }; + + // 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 + + // 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 ground = new THREE.Mesh(groundGeometry, groundMaterial); + ground.rotation.x = -Math.PI / 2; + ground.position.x = -1.1; + ground.position.y = -0.5; + ground.receiveShadow = true; + scene.add(ground); + + // Second ground plane + const groundGeometry2 = new THREE.PlaneGeometry(2, 7); + const groundMaterial2 = new THREE.MeshLambertMaterial({ + color: 0xcccccc, + }); + const ground2 = new THREE.Mesh(groundGeometry2, groundMaterial2); + ground2.rotation.x = -Math.PI / 2; + ground2.position.x = -12.2; + ground2.position.y = -5; + ground2.receiveShadow = true; + scene.add(ground2); + + // Resize handler + const handleResize = () => { + const {width: newWidth, height: newHeight} = getResponsiveDimensions(); + + // Update camera + const newAspect = newWidth / newHeight; + const newFrustumSize = + newWidth < 600 ? baseFrustumSize * 0.8 : baseFrustumSize; + + camera.left = (newFrustumSize * newAspect) / -2; + camera.right = (newFrustumSize * newAspect) / 2; + camera.top = newFrustumSize / 2; + camera.bottom = newFrustumSize / -2; + camera.updateProjectionMatrix(); + + // Update renderer + renderer.setSize(newWidth, newHeight); + }; + + // Add resize event listener + window.addEventListener("resize", handleResize); + + // Mouse event handlers + const onMouseMove = (event: MouseEvent) => { + const rect = renderer.domElement.getBoundingClientRect(); + mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; + mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; + + // Update mouse position for tooltip + 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}) => { + (mesh.material as THREE.MeshLambertMaterial).color.setHex( + originalColor, + ); + mesh.scale.copy(originalScale); + }); + + if (intersects.length > 0) { + const hoveredMesh = intersects[0].object as THREE.Mesh; + const roomInfo = roomData.find((r) => r.mesh === hoveredMesh); + + if (roomInfo) { + // Apply hover effects + (hoveredMesh.material as THREE.MeshLambertMaterial).color.setHex( + 0xffffff, + ); + hoveredMesh.scale.multiplyScalar(1.02); + setHoveredRoom(roomInfo.name); + } + } else { + setHoveredRoom(null); + } + }; + + // Add mouse event listener + renderer.domElement.addEventListener("mousemove", onMouseMove); + + // Animation loop + const animate = () => { + requestAnimationFrame(animate); + + // Gentle floating animation for rooms + rooms.forEach((room, index) => { + const originalY = 0.25; // height / 2 for the room height of 0.5 + const baseY = originalY + Math.sin(Date.now() * 0.001 + index) * 0.05; + + // Maintain current scale while updating Y position + room.position.y = baseY; + }); + + renderer.render(scene, camera); + }; + + animate(); + + // Function to toggle dividers + const toggleDividers = (show: boolean) => { + dividersRef.forEach((divider) => { + divider.visible = show; + (divider.material as THREE.MeshLambertMaterial).opacity = show + ? 0.4 + : 0; + }); + }; + + // Expose toggle function to parent scope + mountElement.toggleDividers = toggleDividers; + + // Cleanup + return () => { + window.removeEventListener("resize", handleResize); + renderer.domElement.removeEventListener("mousemove", onMouseMove); + if (mountElement && renderer.domElement) { + mountElement.removeChild(renderer.domElement); + } + renderer.dispose(); + }; + }, []); + + // Update dividers when showDividers state changes + useEffect(() => { + if (mountRef.current?.toggleDividers) { + mountRef.current.toggleDividers(showDividers); } - } else { - setHoveredRoom(null); - } - }; - - // Add mouse event listener - renderer.domElement.addEventListener("mousemove", onMouseMove); - - // Animation loop - const animate = () => { - requestAnimationFrame(animate); - - // Gentle floating animation for rooms - rooms.forEach((room, index) => { - const originalY = 0.25; // height / 2 for the room height of 0.5 - const baseY = originalY + Math.sin(Date.now() * 0.001 + index) * 0.05; - - // Maintain current scale while updating Y position - room.position.y = baseY; - }); - - renderer.render(scene, camera); - }; - - animate(); - - // Function to toggle dividers - const toggleDividers = (show: boolean) => { - dividersRef.forEach((divider) => { - divider.visible = show; - (divider.material as THREE.MeshLambertMaterial).opacity = show - ? 0.4 - : 0; - }); - }; - - // Expose toggle function to parent scope - mountElement.toggleDividers = toggleDividers; - - // Cleanup - return () => { - window.removeEventListener("resize", handleResize); - renderer.domElement.removeEventListener("mousemove", onMouseMove); - if (mountElement && renderer.domElement) { - mountElement.removeChild(renderer.domElement); - } - renderer.dispose(); - }; - }, []); - - // Update dividers when showDividers state changes - useEffect(() => { - if (mountRef.current?.toggleDividers) { - mountRef.current.toggleDividers(showDividers); - } - }, [showDividers]); - - return ( -
-

- Messiala -

-
-

- Tudengimaja -

-
-
-
- + }, [showDividers]); + + return ( +
+
+

+ Messiala +

+
+

+ Tudengimaja +

+
+
+
+ Mänguklubi -
-
-
- +
+
+
+ Baariala -
-
-
- +
+
+
+ EVAL -
-
-
- +
+
+
+ Redbull -
-
-
- +
+
+
+ Võitlusmängu ala -
-
-
- +
+
+
+ Sony -
-
-
- +
+
+
+ Chillimisala -
+
+
+
+
+
+ +
+
+ + {/* Tooltip */} + {hoveredRoom && ( +
+ {hoveredRoom} +
+ )} +
+
+ +
-
-
-
- -
-
- - {/* Tooltip */} - {hoveredRoom && ( -
- {hoveredRoom} -
- )} -
-
- ); + ); } diff --git a/src/app/piletid/page.tsx b/src/app/piletid/page.tsx index 4707f69..63da5c6 100644 --- a/src/app/piletid/page.tsx +++ b/src/app/piletid/page.tsx @@ -1,96 +1,105 @@ -import { vipnagorgialla } from "@/components/Vipnagorgialla"; +import {vipnagorgialla} from "@/components/Vipnagorgialla"; import Link from "next/link"; +import SectionDivider from "@/components/SectionDivider"; export default function Tickets() { - return ( -
-

- PILETID JA REGIS­TREERIMINE -

-
-
-

- 8€ -

-

- Arvutiga osaleja -

-
    -
  • - Isiklik laud, voolu- ja internetiühendus -
  • -
  • Ligipääs demoalale
  • -
  • Turniiride pealt vaatamine
  • -
  • Võimalus osaleda miniturniiridel
  • -
- - - -
-
-

- 12-15€ -

-

- Võistleja -

-
    -
  • Võimalus osaleda CS2 või LoL turniiril
  • -
  • - Isiklik laud, voolu- ja internetiühendus -
  • -
  • Ligipääs demoalale
  • -
  • Turniiride pealt vaatamine
  • -
  • Võimalus osaleda miniturniiridel
  • -
- - - -
+ return ( +
+
+

+ PILETID JA REGIS­TREERIMINE +

+
+
+

+ 8€ +

+

+ Arvutiga osaleja +

+
    +
  • + Isiklik laud, voolu- ja internetiühendus +
  • +
  • Ligipääs demoalale
  • +
  • Turniiride pealt vaatamine
  • +
  • Võimalus osaleda miniturniiridel
  • +
+ + + +
+
+

+ 12-15€ +

+

+ Võistleja +

+
    +
  • Võimalus osaleda CS2 või LoL turniiril
  • +
  • + Isiklik laud, voolu- ja internetiühendus +
  • +
  • Ligipääs demoalale
  • +
  • Turniiride pealt vaatamine
  • +
  • Võimalus osaleda miniturniiridel
  • +
+ + + +
-
-

- 6€ -

-

- Külastaja -

-
    -
  • Ligipääs demoalale
  • -
  • Turniiride pealt vaatamine
  • -
  • Võimalus osaleda miniturniiridel
  • -
- - - +
+

+ 6€ +

+

+ Külastaja +

+
    +
  • Ligipääs demoalale
  • +
  • Turniiride pealt vaatamine
  • +
  • Võimalus osaleda miniturniiridel
  • +
+ + + +
+
+
+ +
-
-
- ); + ); } diff --git a/src/app/reeglid/[slug]/page.tsx b/src/app/reeglid/[slug]/page.tsx index 843905f..5e4f735 100644 --- a/src/app/reeglid/[slug]/page.tsx +++ b/src/app/reeglid/[slug]/page.tsx @@ -1,44 +1,49 @@ -import { vipnagorgialla } from "@/components/Vipnagorgialla"; +import {vipnagorgialla} from "@/components/Vipnagorgialla"; import path from "node:path"; import fs from "node:fs/promises"; import ReactMarkdown from "react-markdown"; +import SectionDivider from "@/components/SectionDivider"; type Props = { - params: Promise<{ slug: string }>; + params: Promise<{ slug: string }>; }; -export default async function RulePage({ params }: Props) { - const { slug } = await params; - - 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 }; - - return ( - <> -

- {data.title || `${slug.toUpperCase()} REEGLID`} -

- -
- {file} -
- - ); +export default async function RulePage({params}: Props) { + const {slug} = await params; + + 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}; + + return ( + <> +
+

+ {data.title || `${slug.toUpperCase()} REEGLID`} +

+ +
+ {file} +
+
+ + + + ); } From f26e4b3d11116b82bbd0b97b196f5cb5d5f76c27 Mon Sep 17 00:00:00 2001 From: SwagMuffin88 Date: Fri, 15 Aug 2025 10:57:08 +0300 Subject: [PATCH 06/22] replace divider const with component --- src/app/reeglid/page.tsx | 3 ++- src/app/turniirid/page.tsx | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/app/reeglid/page.tsx b/src/app/reeglid/page.tsx index 9339faf..4afaf1e 100644 --- a/src/app/reeglid/page.tsx +++ b/src/app/reeglid/page.tsx @@ -1,5 +1,6 @@ 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]`; @@ -8,7 +9,7 @@ export default function RulesMenu() { const boxTextStyle = `text-3xl ${vipnagorgialla.className} font-bold uppercase text-[#EEE5E5] pb-2`; - const SectionDivider = () =>
; + // const SectionDivider = () =>
; return (
diff --git a/src/app/turniirid/page.tsx b/src/app/turniirid/page.tsx index a254a60..dfaa889 100644 --- a/src/app/turniirid/page.tsx +++ b/src/app/turniirid/page.tsx @@ -1,11 +1,12 @@ import { vipnagorgialla } from "@/components/Vipnagorgialla"; import Link from "next/link"; import Image from "next/image"; +import SectionDivider from "@/components/SectionDivider"; export default function Tourney() { 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`; - const SectionDivider = () =>
; + // const SectionDivider = () =>
; return (
@@ -74,8 +75,7 @@ export default function Tourney() {
- - + {/* LoL turniir */}
From 018c7c53e5d719a84083dd2e819d9a0b11107f9d Mon Sep 17 00:00:00 2001 From: v4ltages Date: Mon, 18 Aug 2025 21:22:16 +0300 Subject: [PATCH 07/22] Messiala & stream --- next.config.ts | 19 +- src/app/messiala/page.tsx | 940 +++++++++++++++++++------------------- src/app/striim/page.tsx | 210 +++++++++ 3 files changed, 705 insertions(+), 464 deletions(-) create mode 100644 src/app/striim/page.tsx diff --git a/next.config.ts b/next.config.ts index e9ffa30..582bf3e 100644 --- a/next.config.ts +++ b/next.config.ts @@ -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://player.twitch.tv https://embed.twitch.tv; frame-ancestors 'self';", + }, + { + key: "X-Frame-Options", + value: "SAMEORIGIN", + }, + ], + }, + ]; + }, }; export default nextConfig; diff --git a/src/app/messiala/page.tsx b/src/app/messiala/page.tsx index c74a105..383344f 100644 --- a/src/app/messiala/page.tsx +++ b/src/app/messiala/page.tsx @@ -1,485 +1,499 @@ "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 { - toggleDividers?: (show: boolean) => void; + toggleDividers?: (show: boolean) => void; } export default function Expo() { - const mountRef = useRef(null); - const [hoveredRoom, setHoveredRoom] = useState(null); - const [mousePosition, setMousePosition] = useState({x: 0, y: 0}); - const [showDividers, setShowDividers] = useState(true); - - useEffect(() => { - if (!mountRef.current) return; - - // Copy ref to variable to avoid stale closure in cleanup - const mountElement = mountRef.current; - let dividersRef: THREE.Mesh[] = []; - - // Scene setup - const scene = new THREE.Scene(); - scene.background = new THREE.Color(0x0e0f19); - - // Get responsive dimensions - const getResponsiveDimensions = () => { - const container = mountRef.current; - 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}; - }; - - const {width, height} = getResponsiveDimensions(); - - // Isometric camera setup with responsive sizing - const aspect = width / height; - const baseFrustumSize = 14; - const frustumSize = width < 600 ? baseFrustumSize * 0.8 : baseFrustumSize; // Smaller frustum for mobile - const camera = new THREE.OrthographicCamera( - (frustumSize * aspect) / -2, - (frustumSize * aspect) / 2, - frustumSize / 2, - frustumSize / -2, - 1, - 1000, - ); + const mountRef = useRef(null); + const [hoveredRoom, setHoveredRoom] = useState(null); + const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }); + const [showDividers, setShowDividers] = useState(true); + + useEffect(() => { + if (!mountRef.current) return; + + // Copy ref to variable to avoid stale closure in cleanup + const mountElement = mountRef.current; + let dividersRef: THREE.Mesh[] = []; + + // Scene setup + const scene = new THREE.Scene(); + scene.background = new THREE.Color(0x0e0f19); + + // Get responsive dimensions + const getResponsiveDimensions = () => { + const container = mountRef.current; + 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 }; + }; + + const { width, height } = getResponsiveDimensions(); + + // Isometric camera setup with responsive sizing + const aspect = width / height; + const baseFrustumSize = 14; + const frustumSize = width < 600 ? baseFrustumSize * 0.8 : baseFrustumSize; // Smaller frustum for mobile + const camera = new THREE.OrthographicCamera( + (frustumSize * aspect) / -2, + (frustumSize * aspect) / 2, + frustumSize / 2, + frustumSize / -2, + 1, + 1000, + ); - // Position camera for isometric view - camera.position.set(10, 10, 14); - camera.lookAt(-1.4, 0, 0); - - // Renderer - const renderer = new THREE.WebGLRenderer({antialias: true}); - renderer.setSize(width, height); - renderer.shadowMap.enabled = true; - renderer.shadowMap.type = THREE.PCFSoftShadowMap; - mountElement.appendChild(renderer.domElement); - - // Raycaster for mouse interactions - const raycaster = new THREE.Raycaster(); - const mouse = new THREE.Vector2(); - - // Lighting - const ambientLight = new THREE.AmbientLight(0x404040, 1.2); - scene.add(ambientLight); - - const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5); - directionalLight.position.set(10, 10, 5); - directionalLight.castShadow = false; - directionalLight.shadow.mapSize.width = 2048; - directionalLight.shadow.mapSize.height = 2048; - scene.add(directionalLight); - - // Room colors and names - const roomColors = [ - 0xff6b35, // Orange - Mänguklubi - 0x4ecdc4, // Turquoise - Baariala - 0xffe66d, // Yellow - EVAL - 0xe74c3c, // Red - Redbull - 0x9b59b6, // Purple - Võitlusmängu ala - 0x3498db, // Blue - Sony - 0x2ecc71, // Green - Chillimisala - ]; - - const roomNames = [ - "Mänguklubi", - "Baariala", - "EVAL", - "Redbull", - "Võitlusmängu ala", - "Sony", - "Chillimisala", - ]; - - // Create individual rooms as rectangles with custom positions - const rooms: THREE.Mesh[] = []; - const roomData: Array<{ - mesh: THREE.Mesh; - name: string; - originalColor: number; - originalScale: THREE.Vector3; - }> = []; - const dividers: THREE.Mesh[] = []; - - // Define rooms with custom positions, sizes and colors - const roomDefinitions = [ - { - width: 7, - height: 0.7, - depth: 3, - 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 - { - width: 1.8, - height: 0.7, - depth: 1.5, - x: 2.5, - z: -3.5, - color: roomColors[2], - name: roomNames[2], - }, // EVAL - { - width: 2.2, - height: 0.7, - depth: 4.5, - x: 5, - z: -2, - color: roomColors[3], - name: roomNames[3], - }, // Redbull - { - width: 3, - height: 0.7, - depth: 1.3, - x: 0, - z: -3.5, - color: roomColors[4], - name: roomNames[4], - }, // Võitlusmängu ala - { - width: 1.8, - height: 0.7, - depth: 1.5, - x: -2.55, - 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 - ]; - - roomDefinitions.forEach((roomDef) => { - const geometry = new THREE.BoxGeometry( - roomDef.width, - roomDef.height, - roomDef.depth, - ); - const material = new THREE.MeshLambertMaterial({ - color: roomDef.color, - }); - - const room = new THREE.Mesh(geometry, material); - room.position.set(roomDef.x, roomDef.height / 2, roomDef.z); - room.castShadow = true; - room.receiveShadow = true; - room.userData = {name: roomDef.name, originalColor: roomDef.color}; - - scene.add(room); - rooms.push(room); - roomData.push({ - mesh: room, - name: roomDef.name, - originalColor: roomDef.color, - originalScale: room.scale.clone(), - }); - }); - - // Create toggleable room dividers - const createTogglableDivider = ( - width: number, - height: number, - depth: number, - x: number, - z: number, - ) => { - const wallGeometry = new THREE.BoxGeometry(width, height, depth); - const wallMaterial = new THREE.MeshLambertMaterial({ - color: 0x555555, - transparent: true, - opacity: 0, - }); - - const wall = new THREE.Mesh(wallGeometry, wallMaterial); - wall.position.set(x, height / 2, z); - wall.visible = false; - scene.add(wall); - dividers.push(wall); - }; - - // 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 - - // 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 ground = new THREE.Mesh(groundGeometry, groundMaterial); - ground.rotation.x = -Math.PI / 2; - ground.position.x = -1.1; - ground.position.y = -0.5; - ground.receiveShadow = true; - scene.add(ground); - - // Second ground plane - const groundGeometry2 = new THREE.PlaneGeometry(2, 7); - const groundMaterial2 = new THREE.MeshLambertMaterial({ - color: 0xcccccc, - }); - const ground2 = new THREE.Mesh(groundGeometry2, groundMaterial2); - ground2.rotation.x = -Math.PI / 2; - ground2.position.x = -12.2; - ground2.position.y = -5; - ground2.receiveShadow = true; - scene.add(ground2); - - // Resize handler - const handleResize = () => { - const {width: newWidth, height: newHeight} = getResponsiveDimensions(); - - // Update camera - const newAspect = newWidth / newHeight; - const newFrustumSize = - newWidth < 600 ? baseFrustumSize * 0.8 : baseFrustumSize; - - camera.left = (newFrustumSize * newAspect) / -2; - camera.right = (newFrustumSize * newAspect) / 2; - camera.top = newFrustumSize / 2; - camera.bottom = newFrustumSize / -2; - camera.updateProjectionMatrix(); - - // Update renderer - renderer.setSize(newWidth, newHeight); - }; - - // Add resize event listener - window.addEventListener("resize", handleResize); - - // Mouse event handlers - const onMouseMove = (event: MouseEvent) => { - const rect = renderer.domElement.getBoundingClientRect(); - mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; - mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; - - // Update mouse position for tooltip - 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}) => { - (mesh.material as THREE.MeshLambertMaterial).color.setHex( - originalColor, - ); - mesh.scale.copy(originalScale); - }); - - if (intersects.length > 0) { - const hoveredMesh = intersects[0].object as THREE.Mesh; - const roomInfo = roomData.find((r) => r.mesh === hoveredMesh); - - if (roomInfo) { - // Apply hover effects - (hoveredMesh.material as THREE.MeshLambertMaterial).color.setHex( - 0xffffff, - ); - hoveredMesh.scale.multiplyScalar(1.02); - setHoveredRoom(roomInfo.name); - } - } else { - setHoveredRoom(null); - } - }; - - // Add mouse event listener - renderer.domElement.addEventListener("mousemove", onMouseMove); - - // Animation loop - const animate = () => { - requestAnimationFrame(animate); - - // Gentle floating animation for rooms - rooms.forEach((room, index) => { - const originalY = 0.25; // height / 2 for the room height of 0.5 - const baseY = originalY + Math.sin(Date.now() * 0.001 + index) * 0.05; - - // Maintain current scale while updating Y position - room.position.y = baseY; - }); - - renderer.render(scene, camera); - }; - - animate(); - - // Function to toggle dividers - const toggleDividers = (show: boolean) => { - dividersRef.forEach((divider) => { - divider.visible = show; - (divider.material as THREE.MeshLambertMaterial).opacity = show - ? 0.4 - : 0; - }); - }; - - // Expose toggle function to parent scope - mountElement.toggleDividers = toggleDividers; - - // Cleanup - return () => { - window.removeEventListener("resize", handleResize); - renderer.domElement.removeEventListener("mousemove", onMouseMove); - if (mountElement && renderer.domElement) { - mountElement.removeChild(renderer.domElement); - } - renderer.dispose(); - }; - }, []); - - // Update dividers when showDividers state changes - useEffect(() => { - if (mountRef.current?.toggleDividers) { - mountRef.current.toggleDividers(showDividers); + // Position camera for isometric view + camera.position.set(10, 10, 14); + camera.lookAt(-1.4, 0, 0); + + // Renderer + const renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize(width, height); + renderer.shadowMap.enabled = true; + renderer.shadowMap.type = THREE.PCFSoftShadowMap; + mountElement.appendChild(renderer.domElement); + + // Raycaster for mouse interactions + const raycaster = new THREE.Raycaster(); + const mouse = new THREE.Vector2(); + + // Lighting + const ambientLight = new THREE.AmbientLight(0x404040, 1.2); + scene.add(ambientLight); + + const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5); + directionalLight.position.set(10, 10, 5); + directionalLight.castShadow = false; + directionalLight.shadow.mapSize.width = 2048; + directionalLight.shadow.mapSize.height = 2048; + scene.add(directionalLight); + + // Room colors and names + const roomColors = [ + 0x343434, // Gray - Lauamängude ala + 0x4ecdc4, // Turquoise - Baariala + 0xffe66d, // Yellow - EVAL + 0xff6600, // Orange - Redbull Sim Racing + 0xff1493, // Deep Pink - Võitlusmängu ala + 0x3498db, // Blue - Sony + 0x2ecc71, // Green - Lava + 0x080682, // Dark Blue - LVLup! + 0xc02841, // Red - RedBull + ]; + + // Create individual rooms as rectangles with custom positions + const rooms: THREE.Mesh[] = []; + const roomData: Array<{ + mesh: THREE.Mesh; + name: string; + originalColor: number; + originalScale: THREE.Vector3; + }> = []; + const dividers: THREE.Mesh[] = []; + + // Define rooms with custom positions, sizes and colors + const roomDefinitions = [ + { + width: 7, + height: 0.7, + depth: 3, + x: 2.5, + z: 4, + color: roomColors[0], + 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: 1, + z: -3.5, + color: roomColors[2], + name: "EVAL", + }, + { + width: 2, + height: 0.7, + depth: 4.5, + x: 5.2, + z: -2, + color: roomColors[3], + name: "Red Bull Sim Racing", + }, + { + width: 3, + height: 0.7, + depth: 1.5, + x: -1.7, + z: -3.5, + color: roomColors[4], + 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: 3, + z: -3.5, + color: roomColors[8], + name: "Red Bull", + }, + ]; + + roomDefinitions.forEach((roomDef) => { + const geometry = new THREE.BoxGeometry( + roomDef.width, + roomDef.height, + roomDef.depth, + ); + const material = new THREE.MeshLambertMaterial({ + color: roomDef.color, + }); + + const room = new THREE.Mesh(geometry, material); + room.position.set(roomDef.x, roomDef.height / 2, roomDef.z); + room.castShadow = true; + room.receiveShadow = true; + room.userData = { name: roomDef.name, originalColor: roomDef.color }; + + scene.add(room); + rooms.push(room); + roomData.push({ + mesh: room, + name: roomDef.name, + originalColor: roomDef.color, + originalScale: room.scale.clone(), + }); + }); + + // Create toggleable room dividers + const createTogglableDivider = ( + width: number, + height: number, + depth: number, + x: number, + z: number, + ) => { + const wallGeometry = new THREE.BoxGeometry(width, height, depth); + const wallMaterial = new THREE.MeshLambertMaterial({ + color: 0x555555, + transparent: true, + opacity: 0, + }); + + const wall = new THREE.Mesh(wallGeometry, wallMaterial); + wall.position.set(x, height / 2, z); + wall.visible = false; + scene.add(wall); + dividers.push(wall); + }; + + // 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 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 ground = new THREE.Mesh(groundGeometry, groundMaterial); + ground.rotation.x = -Math.PI / 2; + ground.position.x = -1.1; + ground.position.y = -0.5; + ground.receiveShadow = true; + scene.add(ground); + + // Second ground plane + const groundGeometry2 = new THREE.PlaneGeometry(2, 7); + const groundMaterial2 = new THREE.MeshLambertMaterial({ + color: 0xcccccc, + }); + const ground2 = new THREE.Mesh(groundGeometry2, groundMaterial2); + ground2.rotation.x = -Math.PI / 2; + ground2.position.x = -12.2; + ground2.position.y = -5; + ground2.receiveShadow = true; + scene.add(ground2); + + // Resize handler + const handleResize = () => { + const { width: newWidth, height: newHeight } = getResponsiveDimensions(); + + // Update camera + const newAspect = newWidth / newHeight; + const newFrustumSize = + newWidth < 600 ? baseFrustumSize * 0.8 : baseFrustumSize; + + camera.left = (newFrustumSize * newAspect) / -2; + camera.right = (newFrustumSize * newAspect) / 2; + camera.top = newFrustumSize / 2; + camera.bottom = newFrustumSize / -2; + camera.updateProjectionMatrix(); + + // Update renderer + renderer.setSize(newWidth, newHeight); + }; + + // Add resize event listener + window.addEventListener("resize", handleResize); + + // Mouse event handlers + const onMouseMove = (event: MouseEvent) => { + const rect = renderer.domElement.getBoundingClientRect(); + mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; + mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; + + // Update mouse position for tooltip + 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 }) => { + (mesh.material as THREE.MeshLambertMaterial).color.setHex( + originalColor, + ); + mesh.scale.copy(originalScale); + }); + + if (intersects.length > 0) { + const hoveredMesh = intersects[0].object as THREE.Mesh; + const roomInfo = roomData.find((r) => r.mesh === hoveredMesh); + + if (roomInfo) { + // Apply hover effects + (hoveredMesh.material as THREE.MeshLambertMaterial).color.setHex( + 0xffffff, + ); + hoveredMesh.scale.multiplyScalar(1.02); + setHoveredRoom(roomInfo.name); } - }, [showDividers]); - - return ( -
-
-

- Messiala -

-
-

- Tudengimaja -

-
-
-
- - Mänguklubi - -
-
-
- + } else { + setHoveredRoom(null); + } + }; + + // Add mouse event listener + renderer.domElement.addEventListener("mousemove", onMouseMove); + + // Animation loop + const animate = () => { + requestAnimationFrame(animate); + + // Gentle floating animation for rooms + rooms.forEach((room, index) => { + const originalY = 0.25; // height / 2 for the room height of 0.5 + const baseY = originalY + Math.sin(Date.now() * 0.001 + index) * 0.05; + + // Maintain current scale while updating Y position + room.position.y = baseY; + }); + + renderer.render(scene, camera); + }; + + animate(); + + // Function to toggle dividers + const toggleDividers = (show: boolean) => { + dividersRef.forEach((divider) => { + divider.visible = show; + (divider.material as THREE.MeshLambertMaterial).opacity = show + ? 0.4 + : 0; + }); + }; + + // Expose toggle function to parent scope + mountElement.toggleDividers = toggleDividers; + + // Cleanup + return () => { + window.removeEventListener("resize", handleResize); + renderer.domElement.removeEventListener("mousemove", onMouseMove); + if (mountElement && renderer.domElement) { + mountElement.removeChild(renderer.domElement); + } + renderer.dispose(); + }; + }, []); + + // Update dividers when showDividers state changes + useEffect(() => { + if (mountRef.current?.toggleDividers) { + mountRef.current.toggleDividers(showDividers); + } + }, [showDividers]); + + return ( +
+

+ Messiala +

+
+

+ Tudengimaja +

+
+
+
+ Baariala -
-
-
- +
+
+
+ EVAL -
-
-
- - Redbull +
+
+
+ + Lauamängude ala -
-
-
- - Võitlusmängu ala +
+
+
+ + LVLup! + +
+
+
+ + Red Bull -
-
-
- +
+
+
+ + Red Bull Sim Racing + +
+
+
+ Sony -
-
-
- - Chillimisala +
+
+
+ + Võitlusmängu ala -
-
-
-
-
- -
-
- - {/* Tooltip */} - {hoveredRoom && ( -
- {hoveredRoom} -
- )} -
-
- - +
- ); +
+
+
+ +
+
+ + {/* Tooltip */} + {hoveredRoom && ( +
+ {hoveredRoom} +
+ )} +
+
+ ); } diff --git a/src/app/striim/page.tsx b/src/app/striim/page.tsx new file mode 100644 index 0000000..a3384b7 --- /dev/null +++ b/src/app/striim/page.tsx @@ -0,0 +1,210 @@ +import { vipnagorgialla } from "@/components/Vipnagorgialla"; +import Link from "next/link"; +import Image from "next/image"; + +export default function Home() { + return ( +
+
+ {/* Title */} +
+ TipiLAN Logo + TipiLAN Logo + +
+

+ Ajakava +

+ + arrow_right_alt + +
+
+ + event_note + +

+ TipiLAN on pungil põnevatest turniiridest, mini-võistlustest ja + paljust muust. +

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

+ Turniirid +

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

+ TipiLANil toimuvad suurejoonelised CS2 ja LoL turniirid, mille + auhinnafond on 10 000€. +

+
+ + +
+

+ Messiala +

+ + arrow_right_alt + +
+
+ + weekend + +

+ TipiLANi messialal paiknevad ettevõtted, lisategevused ja toimuvad + loengud. +

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

+ Bro­neeri oma koht juba täna! +

+ + arrow_right_alt + +
+

+ 24.-26. okt. +

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

+ TipiLANi tõmbab käima... +

+
+ + Taltech (Tallinna Tehnikaülikool) + + + Redbull + + + Alecoq + + + EVAL + + + Balsnack + + + LVLup! + + + BFGL + +
+
+
+
+ ); +} From deb07df3973b80a5849cf3bb3d3d8a6a1b12a119 Mon Sep 17 00:00:00 2001 From: v4ltages Date: Tue, 19 Aug 2025 05:29:15 +0300 Subject: [PATCH 08/22] React19 update broke components using ref --- next.config.ts | 2 +- package.json | 2 - src/app/kodukord/page.tsx | 97 +++++----- src/app/reeglid/[slug]/page.tsx | 146 +++++++++----- src/app/reeglid/page.tsx | 90 ++++----- src/app/striim/page.tsx | 2 +- src/app/turniirid/page.tsx | 332 ++++++++++++++++---------------- src/components/ui/button.tsx | 30 +-- src/data/rules/cs2.md | 5 + 9 files changed, 378 insertions(+), 328 deletions(-) create mode 100644 src/data/rules/cs2.md diff --git a/next.config.ts b/next.config.ts index 582bf3e..d6a1ca2 100644 --- a/next.config.ts +++ b/next.config.ts @@ -9,7 +9,7 @@ const nextConfig: NextConfig = { { key: "Content-Security-Policy", value: - "frame-src 'self' https://player.twitch.tv https://embed.twitch.tv; frame-ancestors 'self';", + "frame-src 'self' https://tipilan.ee https://player.twitch.tv https://embed.twitch.tv; frame-ancestors 'self' https://tipilan.ee;", }, { key: "X-Frame-Options", diff --git a/package.json b/package.json index 7c55e31..5f2e22a 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/src/app/kodukord/page.tsx b/src/app/kodukord/page.tsx index 68cb8a1..fe6428d 100644 --- a/src/app/kodukord/page.tsx +++ b/src/app/kodukord/page.tsx @@ -1,55 +1,56 @@ // 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 async function Page() { + 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 ( +
+
+ {/* Page title (separate from markdown headings) */} +

+ Kodukord +

- return ( -
-
- {/* Page title (separate from markdown headings) */} -

- Kodukord -

- -
- ( -

- ), - h2: ({node, ...props}) => ( -

- ), - ol: ({node, ...props}) => ( -
    - ), - ul: ({node, ...props}) => ( -
      - ), - p: ({node, ...props}) => ( -

      - ), - }} - > - {content} - -

-
- - +
+ ( +

+ {props.children} +

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

+ {props.children} +

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

{props.children}

, + } as Components + } + > + {content} +
- ); +
+ + +
+ ); } diff --git a/src/app/reeglid/[slug]/page.tsx b/src/app/reeglid/[slug]/page.tsx index 5e4f735..d58f47e 100644 --- a/src/app/reeglid/[slug]/page.tsx +++ b/src/app/reeglid/[slug]/page.tsx @@ -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 = { - params: Promise<{ slug: string }>; -}; - -export default async function RulePage({params}: Props) { - const {slug} = await params; - - 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}; - - return ( - <> -
-

- {data.title || `${slug.toUpperCase()} REEGLID`} -

- -
- {file} -
-
- - - - ); +// 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 }>; +} + +async function getRuleContent(slug: string) { + if (!Object.keys(rulesMap).includes(slug)) { + return null; + } + + const ruleConfig = rulesMap[slug as RuleSlug]; + + try { + const file = Bun.file(ruleConfig.filePath); + const content = await file.text(); + return { + content, + 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 ( +
+
+

+ {ruleData.title} +

+ +
+ ( +

+ {props.children} +

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

+ {props.children} +

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

{props.children}

, + } as Components + } + > + {ruleData.content} +
+
+
+ + +
+ ); +} + +export async function generateStaticParams() { + return Object.keys(rulesMap).map((slug) => ({ + slug, + })); } diff --git a/src/app/reeglid/page.tsx b/src/app/reeglid/page.tsx index 4afaf1e..167893e 100644 --- a/src/app/reeglid/page.tsx +++ b/src/app/reeglid/page.tsx @@ -1,64 +1,52 @@ -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 boxStyle = `-skew-x-2 md:-skew-x-5 text-white md:px-12 hover:scale-103 transition-all duration-150 w-full md:w-xl lg:w-[400px]`; - - const boxTextStyle = `text-3xl ${vipnagorgialla.className} font-bold uppercase text-[#EEE5E5] pb-2`; + const headingStyle = `text-4xl md:text-5xl lg:text-6xl ${vipnagorgialla.className} font-bold italic text-[#2A2C3F] dark:text-[#EEE5E5] uppercase`; - // const SectionDivider = () =>
; + 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]`; - return ( -
-
-

- REEGLID -

+ const boxTextStyle = `text-3xl ${vipnagorgialla.className} font-bold uppercase text-[#EEE5E5] pb-2`; -
- -
-

- Kodukord -

-
- + // const SectionDivider = () =>
; - -
-

- CS2 reeglid -

-
- + return ( +
+
+

+ REEGLID +

+
+ +
+

Kodukord

+
+ - -
-

- LoL reeglid -

-
- + +
+

CS2 reeglid

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

- Miniturniiride reeglid -

-
- {/**/} - -
+ +
+

LoL reeglid

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

Miniturniiride reeglid

+
+ {/**/}
- ); -} \ No newline at end of file +
+ + +
+ ); +} diff --git a/src/app/striim/page.tsx b/src/app/striim/page.tsx index a3384b7..1d1d7bf 100644 --- a/src/app/striim/page.tsx +++ b/src/app/striim/page.tsx @@ -50,7 +50,7 @@ export default function Home() { {/* Stream iframe from Twitch */}