+
+ 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
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+ {/* 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 REGISTREERIMINE
-
-
-
-
- 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 REGISTREERIMINE
+
+
+
+
+ 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}
+
+
+
+
+ >
+ );
}