From 2c4cde6df884e7ef57fcf630af57e80c746fc2a2 Mon Sep 17 00:00:00 2001 From: Rene Arumetsa Date: Fri, 1 May 2026 19:18:52 +0300 Subject: [PATCH] expo and timetable pages --- src/app/[locale]/ajakava/page.tsx | 90 +-- src/app/[locale]/messiala/page.tsx | 1076 +--------------------------- translations/en.json | 2 + translations/et.json | 2 + 4 files changed, 45 insertions(+), 1125 deletions(-) diff --git a/src/app/[locale]/ajakava/page.tsx b/src/app/[locale]/ajakava/page.tsx index b132a01..0fc3bc7 100644 --- a/src/app/[locale]/ajakava/page.tsx +++ b/src/app/[locale]/ajakava/page.tsx @@ -1,77 +1,27 @@ -"use client"; - -import { useState } from "react"; import { vipnagorgialla } from "@/components/Vipnagorgialla"; -import { scheduleData } from "@/data/timetable"; -import SectionDivider from "@/components/SectionDivider"; -import { useTranslations } from "next-intl"; +import { getTranslations, setRequestLocale } from "next-intl/server"; -const tabs = Object.keys(scheduleData); - -export default function Timetable() { - const [activeTab, setActiveTab] = useState(tabs[0]); - const schedule = scheduleData[activeTab]; - const t = useTranslations(); +export default async function Timetable({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); return ( -
-
-

- {t("schedule.title")} -

- - {/* Tab menu */} -
- {tabs.map((tab) => ( - - ))} -
- - {/* Schedule entries */} -
- {schedule.map((item, idx) => ( -
-
- {item.time} -
-
-
- {t(item.titleKey)} -
- {item.description && ( -
- {item.description} -
- )} -
- {t(item.locationKey)} -
-
-
- ))} -
-
- - +
+

+ {t("schedule.title")} +

+

+ {t("schedule.comingSoon")} +

); } diff --git a/src/app/[locale]/messiala/page.tsx b/src/app/[locale]/messiala/page.tsx index 8cc4424..a0ea252 100644 --- a/src/app/[locale]/messiala/page.tsx +++ b/src/app/[locale]/messiala/page.tsx @@ -1,1061 +1,27 @@ -"use client"; - import { vipnagorgialla } from "@/components/Vipnagorgialla"; -import * as THREE from "three"; -import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; -import { useEffect, useRef, useState, useMemo } from "react"; -import { EyeClosed, Eye } from "lucide-react"; -import SectionDivider from "@/components/SectionDivider"; -import { useTranslations } from "next-intl"; -import { - roomNameKeys, - staticRoomNames, - roomMeta, - RoomNameKey, -} from "@/data/roomNames"; -import gamedevData from "@/data/gamedev.json"; - -// Define interface for the ref with toggle function -interface MountRefCurrent extends HTMLDivElement { - toggleDividers?: (show: boolean) => void; - switchView?: (view: "tudengimaja" | "fuajee") => 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); - const [currentView, setCurrentView] = useState<"tudengimaja" | "fuajee">( - "fuajee", - ); - const currentViewRef = useRef<"tudengimaja" | "fuajee">("fuajee"); - const t = useTranslations(); - - // Room names using translations and staticRoomNames - const roomNames = useMemo(() => { - const names: Record = {} as never; - roomNameKeys.forEach((key) => { - if (staticRoomNames[key]) { - names[key] = staticRoomNames[key]!; - } else { - // fallback to translation key or just key - names[key] = t(`expo.areas.${key}`, { default: key }); - } - }); - return names; - }, [t]); - - useEffect(() => { - if (!mountRef.current) return; - - // Copy ref to variable to avoid stale closure in cleanup - const mountElement = mountRef.current; - let dividersRef: THREE.Mesh[] = []; - const fuajeeMeshes: THREE.Mesh[] = []; - let tudengimajaObjects: THREE.Object3D[] = []; - let fuajeeMesh: THREE.Group | null = null; - const fuajeeRooms: 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 = baseFrustumSize; // Keep consistent frustum size - const camera = new THREE.OrthographicCamera( - (frustumSize * aspect) / -2, - (frustumSize * aspect) / 2, - frustumSize / 2, - frustumSize / -2, - 1, - 1000, - ); - - // Camera positions for different views - const cameraPositions = { - tudengimaja: { - position: new THREE.Vector3(10, 10, 14), - lookAt: new THREE.Vector3(-1.4, 0, 0), - }, - fuajee: { - position: new THREE.Vector3(30, 20, 15), - lookAt: new THREE.Vector3(0, 0, 0), - }, - }; - - // Position camera for isometric view (default to fuajee) - camera.position.copy(cameraPositions.fuajee.position); - camera.lookAt(cameraPositions.fuajee.lookAt); - - // 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); - - // Create individual rooms as rectangles with custom positions using roomMeta - const rooms: THREE.Mesh[] = []; - const roomData: Array<{ - mesh: THREE.Mesh; - name: string; - originalColor: number; - originalScale: THREE.Vector3; - view: "tudengimaja" | "fuajee"; - }> = []; - const dividers: THREE.Mesh[] = []; - - // Generate rooms for tudengimaja and fuajee using roomMeta - roomNameKeys.forEach((key) => { - const metas = roomMeta[key]; - if (!metas) return; - metas.forEach((meta) => { - if (meta.view !== "tudengimaja") return; - const geometry = new THREE.BoxGeometry( - meta.size.width, - meta.size.height, - meta.size.depth, - ); - const material = new THREE.MeshLambertMaterial({ - color: meta.color, - }); - const room = new THREE.Mesh(geometry, material); - room.position.set(meta.position.x, meta.position.y, meta.position.z); - room.castShadow = true; - room.receiveShadow = true; - room.userData = { name: roomNames[key], originalColor: meta.color }; - - scene.add(room); - rooms.push(room); - - roomData.push({ - mesh: room, - name: roomNames[key], - originalColor: meta.color, - originalScale: room.scale.clone(), - view: "tudengimaja", - }); - }); - }); - - // 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: 0x2e5570, - // 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(2, 2, 1, -6.5, 1); // Wall behind photowall - createTogglableDivider(4, 2, 2, -3.5, 1.5); // Wall between main entrance - createTogglableDivider(2, 2, 1, -0.5, 1.5); // Wall behind bar - createTogglableDivider(2, 2, 2, 1.5, 1.5); // Wall between main entrance - - // 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 ground2 = new THREE.Mesh(groundGeometry2, groundMaterial); - ground2.rotation.x = -Math.PI / 2; - ground2.position.x = -12.2; - ground2.position.y = -5; - ground2.receiveShadow = true; - scene.add(ground2); - - // Store tudengimaja objects (rooms, ground, dividers) - tudengimajaObjects = [...rooms, ground, ground2, ...dividers]; - - // Set initial visibility for fuajee default view - tudengimajaObjects.forEach((obj) => (obj.visible = false)); - - // Load fuajee GLTF model - const loader = new GLTFLoader(); - loader.load( - "/spaces/fuajeeTalTech.glb", - (gltf) => { - fuajeeMesh = gltf.scene; - fuajeeMesh.position.set(-1.5, 1, 0); - fuajeeMesh.scale.set(0.3, 0.3, 0.3); - fuajeeMesh.visible = true; // Initially visible for fuajee default - - // Traverse the model to collect meshes - fuajeeMesh.traverse((child) => { - if (child instanceof THREE.Mesh) { - child.castShadow = true; - child.receiveShadow = true; - fuajeeMeshes.push(child); - } - }); - - scene.add(fuajeeMesh); - - // Create example rooms for fuajee after the model loads - createfuajeeRooms(); - - // Set initial visibility for fuajee view - tudengimajaObjects.forEach((obj) => (obj.visible = false)); - fuajeeMesh.visible = true; - fuajeeRooms.forEach((room) => (room.visible = true)); - }, - (progress) => { - console.log( - "Loading progress:", - (progress.loaded / progress.total) * 100 + "%", - ); - }, - (error) => { - console.error("Error loading GLTF:", error); - }, - ); - - // Function to create rooms for fuajee using roomMeta - const createfuajeeRooms = () => { - roomNameKeys.forEach((key) => { - const metas = roomMeta[key]; - if (!metas) return; - metas.forEach((meta) => { - if (meta.view !== "fuajee") return; - const geometry = new THREE.BoxGeometry( - meta.size.width, - meta.size.height, - meta.size.depth, - ); - const material = new THREE.MeshLambertMaterial({ - color: meta.color, - }); - - const room = new THREE.Mesh(geometry, material); - room.position.set(meta.position.x, meta.position.y, meta.position.z); - room.castShadow = true; - room.receiveShadow = true; - room.userData = { name: roomNames[key], originalColor: meta.color }; - room.visible = true; // Initially visible for fuajee default - - scene.add(room); - fuajeeRooms.push(room); - - roomData.push({ - mesh: room, - name: roomNames[key], - originalColor: meta.color, - originalScale: room.scale.clone(), - view: "fuajee", - }); - }); - }); - }; - - // Resize handler - const handleResize = () => { - const { width: newWidth, height: newHeight } = getResponsiveDimensions(); - - // Update camera - const newAspect = newWidth / newHeight; - const newFrustumSize = 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 }); - - // Handle mouse interactions based on current view - if (currentViewRef.current === "tudengimaja") { - // Update raycaster - raycaster.setFromCamera(mouse, camera); - const intersects = raycaster.intersectObjects(rooms); - - // Reset all tudengimaja rooms to original state - roomData - .filter((r) => r.view === "tudengimaja") - .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); - } - } else if (currentViewRef.current === "fuajee") { - // Update raycaster for fuajee rooms - raycaster.setFromCamera(mouse, camera); - const intersects = raycaster.intersectObjects(fuajeeRooms); - - // Reset all fuajee rooms to original state - roomData - .filter((r) => r.view === "fuajee") - .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 with better visibility - (hoveredMesh.material as THREE.MeshLambertMaterial).color.setHex( - 0xffffff, - ); - - hoveredMesh.scale.multiplyScalar(1.1); - setHoveredRoom(roomInfo.name); - } - } else { - setHoveredRoom(null); - } - } else { - setHoveredRoom(null); - } - }; - - // Add mouse event listener - renderer.domElement.addEventListener("mousemove", onMouseMove); - - // Function to switch camera views - const switchView = (view: "tudengimaja" | "fuajee") => { - const targetPosition = cameraPositions[view].position; - const targetLookAt = cameraPositions[view].lookAt; - - // Animate camera transition - const startPosition = camera.position.clone(); - const startLookAt = new THREE.Vector3(); - camera.getWorldDirection(startLookAt); - startLookAt.multiplyScalar(-1).add(camera.position); - - let progress = 0; - const animateCamera = () => { - progress += 0.05; - if (progress >= 1) { - progress = 1; - } - - // Smooth interpolation - const easeProgress = 1 - Math.cos(progress * Math.PI * 0.5); - - camera.position.lerpVectors( - startPosition, - targetPosition, - easeProgress, - ); - const currentLookAt = new THREE.Vector3().lerpVectors( - startLookAt, - targetLookAt, - easeProgress, - ); - camera.lookAt(currentLookAt); - - if (progress < 1) { - requestAnimationFrame(animateCamera); - } - }; - - animateCamera(); - - // Reset hover state when switching views - setHoveredRoom(null); - - // Reset all room states to original - roomData.forEach(({ mesh, originalColor, originalScale }) => { - (mesh.material as THREE.MeshLambertMaterial).color.setHex( - originalColor, - ); - mesh.scale.copy(originalScale); - }); - - // Toggle visibility of objects based on view - if (view === "fuajee") { - tudengimajaObjects.forEach((obj) => (obj.visible = false)); - if (fuajeeMesh) { - fuajeeMesh.visible = true; - } - fuajeeRooms.forEach((room) => (room.visible = true)); - } else { - tudengimajaObjects.forEach((obj) => (obj.visible = true)); - if (fuajeeMesh) { - fuajeeMesh.visible = false; - } - fuajeeRooms.forEach((room) => (room.visible = false)); - // Re-apply divider visibility state - if (mountElement.toggleDividers) { - mountElement.toggleDividers(showDividers); - } - } - }; - - // Animation loop - const animate = () => { - requestAnimationFrame(animate); - - // Gentle floating animation for rooms - if (currentViewRef.current === "tudengimaja") { - 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; - }); - } else if (currentViewRef.current === "fuajee") { - fuajeeRooms.forEach((room, index) => { - const originalY = 2.25; // height / 2 for the room height of 0.5 + 2 offset - 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 functions to parent scope - mountElement.toggleDividers = toggleDividers; - mountElement.switchView = switchView; - - // Cleanup - return () => { - window.removeEventListener("resize", handleResize); - renderer.domElement.removeEventListener("mousemove", onMouseMove); - if (mountElement && renderer.domElement) { - mountElement.removeChild(renderer.domElement); - } - renderer.dispose(); - }; - }, [roomNames]); - - // Update dividers when showDividers state changes - useEffect(() => { - if (mountRef.current?.toggleDividers) { - mountRef.current.toggleDividers(showDividers); - } - }, [showDividers]); - - // Handle view switching - const handleViewSwitch = (view: "tudengimaja" | "fuajee") => { - setCurrentView(view); - currentViewRef.current = view; // Update ref immediately - setHoveredRoom(null); // Clear any existing hover state - if (mountRef.current?.switchView) { - mountRef.current.switchView(view); - } - }; +import { getTranslations, setRequestLocale } from "next-intl/server"; + +export default async function Expo({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); return ( -
-
-

- {t("expo.title")} -

-
-

- {currentView === "tudengimaja" - ? t("schedule.locations.studentHouse") - : t("schedule.locations.entranceHall")} -

- - {currentView === "tudengimaja" && ( -
- {/* Bar */} -
-
- - {t("expo.areas.bar")} - -
- {/* EVAL */} -
-
- - EVAL - -
- {/* LVLup */} -
-
- - LVLup! - -
- {/* Red Bull */} -
-
- - Red Bull - -
- {/* Sim Racing */} -
-
- - {t("expo.areas.simRacing")} - -
- {/* Fighting */} -
-
- - {t("expo.areas.fighting")} - -
- {/* K-space */} -
-
- - K-space.ee - -
- {/* Photowall */} -
-
- - {t("expo.areas.photowall")} - -
- {/* Buckshot Roulette */} -
-
- - Buckshot Roulette - -
- {/* Chill Area */} -
-
- - {t("expo.areas.chillArea")} - -
- {/* Alzgamer */} -
-
- - Alzgamer - -
- {/* WC */} -
-
- - WC - -
-
- )} - - {currentView === "fuajee" && ( -
-
-
- - {t("expo.areas.estoniagamedev")} - -
-
-
- - {t("expo.areas.gameup")} - -
-
-
- - {t("expo.areas.info")} - -
-
-
- - {t("expo.areas.ittk")} - -
-
-
- - {t("expo.areas.studentformula")} - -
-
-
- - {t("expo.areas.tartuyk")} - -
-
-
- - {t("expo.areas.tly")} - -
-
- )} - -
-
-
-
- {/* Left Arrow - Only show when on fuajee to go back to tudengimaja */} - {currentView === "fuajee" && ( - - )} - - {/* Right Arrow - Only show when on tudengimaja to go to fuajee */} - {currentView === "tudengimaja" && ( - - )} - - {currentView === "tudengimaja" && ( - - )} -
-
-
- - {/* Tooltip - only show for current view */} - {hoveredRoom && - ((currentView === "tudengimaja" && - [ - roomNames.boardGames, - roomNames.bar, - roomNames.eval, - roomNames.simRacing, - roomNames.fighting, - roomNames.lvlup, - roomNames.redbull, - roomNames.kspace, - roomNames.photowall, - roomNames.buckshotroulette, - roomNames.wc, - roomNames.chillArea, - roomNames.alzgamer, - ].includes(hoveredRoom)) || - (currentView === "fuajee" && - [ - roomNames.tartuyk, - roomNames.estoniagamedev, - roomNames.info, - roomNames.tly, - roomNames.ittk, - roomNames.gameup, - roomNames.studentformula, - ].includes(hoveredRoom))) && ( -
- {hoveredRoom} -
- )} -
-
- - - - {/* MINITURNIIRID Section */} -
-
-

- MINITURNIIRID -

-

- TipiLANil toimub mitmeid erinevaid lõbusaid ja võistlushimu - tekitavaid miniturniire. Osaleda saavad ka niisama külastajad! - Auhinnafond on kõigi turniiride peale 1250€. -

-
-
- Miniturniirid logo -
-
- - - - {/* PUHKA JA MÄNGI Section */} -
-

- PUHKA JA MÄNGI -

- -
- {/* Card 1 - Chill-ala */} -
-
-
- Chill-ala -
-
-

- Chill-ala koos turniiride otseülekandega -

-
- - {/* Card 2 - Mänguklubi */} -
-
-
- Mänguklubi -
-
-

- Mänguklubi lauamängud ja konsoolid -

-
- - {/* Card 3 - Baariala */} -
-
-
- Baariala -
-
-

- Baariala jookide ja snäkkidega -

-
-
-
- - - - {/* EESTI MÄNGUARENDAJAD Section */} -
-

- Eesti mänguarendajad -

- -
- {gamedevData.games.map((game) => ( -
-
- {game.name} -
-

- {game.name} -

-

- {game.developer} -

-
- ))} -
-
- - - - {/* ÜLIKOOLID Section */} -
-

- Ülikoolid -

- - {/* First 12 games in 3x4 grid */} -
- {gamedevData.universities?.slice(0, 12).map((university) => ( -
-
- {university.name} -
-

- {university.name} -

-

- {university.university} -

-
- ))} -
- - {/* Remaining games in new grid */} - {gamedevData.universities && gamedevData.universities.length > 12 && ( -
- {gamedevData.universities.slice(12).map((university) => ( -
-
- {university.name} -
-

- {university.name} -

-

- {university.university} -

-
- ))} -
- )} -
- - +
+

+ {t("expo.title")} +

+

+ {t("expo.comingSoon")} +

); } diff --git a/translations/en.json b/translations/en.json index 5b07545..47e5667 100644 --- a/translations/en.json +++ b/translations/en.json @@ -448,6 +448,7 @@ }, "schedule": { "title": "Schedule", + "comingSoon": "Coming soon", "day": "Day", "time": "Time", "event": "Event", @@ -517,6 +518,7 @@ }, "expo": { "title": "Expo Area", + "comingSoon": "Coming soon", "description": "The TipiLAN expo area hosts companies, additional activities and lectures.", "areas": { "bar": "Bar", diff --git a/translations/et.json b/translations/et.json index fe08671..456f178 100644 --- a/translations/et.json +++ b/translations/et.json @@ -449,6 +449,7 @@ }, "schedule": { "title": "Ajakava", + "comingSoon": "Tuleb hiljem", "day": "Päev", "time": "Aeg", "event": "Sündmus", @@ -518,6 +519,7 @@ }, "expo": { "title": "Messiala", + "comingSoon": "Tuleb hiljem", "description": "TipiLANi messialal paiknevad ettevõtted, lisategevused ja toimuvad loengud.", "areas": { "bar": "Baar",