Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions dash/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
"dependencies": {
"@fireworks-js/react": "^2.10.8",
"@headlessui/react": "2.2.0",
"@react-three/drei": "^10.0.5",
"@react-three/fiber": "^9.1.0",
"@react-three/uikit": "^0.8.14",
"@types/three": "^0.174.0",
"clsx": "2.1.1",
"framer-motion": "11.11.17",
"geist": "1.3.1",
Expand All @@ -21,6 +25,7 @@
"react": "18.3.1",
"react-dom": "18.3.1",
"sharp": "0.33.5",
"three": "^0.174.0",
"zod": "3.23.8",
"zustand": "5.0.1"
},
Expand Down
19 changes: 12 additions & 7 deletions dash/src/app/(nav)/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
"use client";

import { useEffect, useState } from "react";
import { motion } from "framer-motion";
import Image from "next/image";
import { useEffect, useState } from "react";

import xIcon from "public/icons/xmark.svg";

import type { Driver } from "@/types/state.type";

import SegmentedControls from "@/components/SegmentedControls";
import SelectMultiple from "@/components/SelectMultiple";
import DriverTag from "@/components/driver/DriverTag";
import DelayInput from "@/components/DelayInput";
import Button from "@/components/Button";
import Toggle from "@/components/Toggle";
import DelayInput from "@/components/DelayInput";
import Footer from "@/components/Footer";
import Slider from "@/components/Slider";
import Input from "@/components/Input";
import SegmentedControls from "@/components/SegmentedControls";
import SelectMultiple from "@/components/SelectMultiple";
import Slider from "@/components/Slider";
import Toggle from "@/components/Toggle";
import DriverTag from "@/components/driver/DriverTag";

import { useSettingsStore } from "@/stores/useSettingsStore";

Expand Down Expand Up @@ -78,6 +78,11 @@ export default function SettingsPage() {
</div>
)}

<div className="flex gap-2">
<Toggle enabled={settings.use3DMap} setEnabled={(v) => settings.setUse3DMap(v)} />
<p className="text-zinc-500">(Experimental) Use 3D Map</p>
</div>

<h2 className="my-4 text-2xl">Favorite Drivers</h2>

<p className="mb-4">Select your favorite drivers to highlight them on the dashboard.</p>
Expand Down
22 changes: 11 additions & 11 deletions dash/src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
"use client";

import { useEffect, useRef } from "react";
import clsx from "clsx";
import { useEffect, useRef } from "react";

import Fireworks, { FireworksHandlers } from "@fireworks-js/react";

import { useDataStore } from "@/stores/useDataStore";

import SessionInfo from "@/components/SessionInfo";
import WeatherInfo from "@/components/WeatherInfo";
import TrackInfo from "@/components/TrackInfo";
import Footer from "@/components/Footer";
import LapCount from "@/components/LapCount";
import LeaderBoard from "@/components/LeaderBoard";
import Map from "@/components/map/Map";
import Map3D from "@/components/map/Map3D";
import Qualifying from "@/components/Qualifying";
import RaceControl from "@/components/RaceControl";
import SessionInfo from "@/components/SessionInfo";
import TeamRadios from "@/components/TeamRadios";
import Footer from "@/components/Footer";
import Map from "@/components/Map";
import LapCount from "@/components/LapCount";
import TrackInfo from "@/components/TrackInfo";
import WeatherInfo from "@/components/WeatherInfo";
import { useSettingsStore } from "@/stores/useSettingsStore";

export default function Page() {
const fireworksRef = useRef<FireworksHandlers>(null);
const fireworksPlayed = useRef<boolean>(false);

const settings = useSettingsStore();
const sessionType = useDataStore((state) => state.sessionInfo?.type);

const raceControlMessages = useDataStore((state) => state.raceControlMessages?.messages);
Expand Down Expand Up @@ -83,9 +85,7 @@ export default function Page() {
</div>
)}

<div className="hidden w-full xl:block">
<Map />
</div>
<div className="hidden w-full xl:block">{settings.use3DMap ? <Map3D /> : <Map />}</div>

<div
className={clsx(
Expand Down
16 changes: 12 additions & 4 deletions dash/src/components/TrackInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@ import clsx from "clsx";

import { useDataStore } from "@/stores/useDataStore";

import { getTrackStatusMessage } from "@/lib/getTrackStatusMessage";
import { getComputedFlagStyle, getTrackStatusMessage } from "@/lib/getTrackStatusMessage";
import { useMemo } from "react";

export default function TrackInfo() {
const lapCount = useDataStore((state) => state.lapCount);
const track = useDataStore((state) => state.trackStatus);

const currentTrackStatus = getTrackStatusMessage(track?.status ? parseInt(track?.status) : undefined);
const currentTrackStatus = useMemo(
() => getTrackStatusMessage(track?.status ? parseInt(track?.status) : undefined),
[track],
);
const computedTrackStyle = useMemo(
() => (currentTrackStatus ? getComputedFlagStyle(currentTrackStatus.flagType) : null),
[currentTrackStatus],
);

return (
<div className="flex w-fit flex-row items-center gap-4">
Expand All @@ -22,9 +30,9 @@ export default function TrackInfo() {

{!!currentTrackStatus ? (
<div
className={clsx("flex h-8 items-center truncate rounded-md px-2", currentTrackStatus.color)}
className={clsx("flex h-8 items-center truncate rounded-md px-2", computedTrackStyle?.bg)}
style={{
boxShadow: `0 0 60px 10px ${currentTrackStatus.hex}`,
boxShadow: `0 0 60px 10px ${computedTrackStyle?.flagHex}`,
}}
>
<p className="text-xl font-semibold">{currentTrackStatus.message}</p>
Expand Down
35 changes: 35 additions & 0 deletions dash/src/components/map/CornerNumber3D.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useLookAt } from "@/hooks/useLookAt";
import { theme } from "@/styles/tailwindTheme";
import { Text as Text3D } from "@react-three/drei";
import { useThree } from "@react-three/fiber";
import { useRef } from "react";

import { Mesh } from "three";

type CornerNumberProps = {
number: number;
x: number;
y: number;
};

export default function CornerNumber({ number, x, y }: CornerNumberProps) {
const { camera } = useThree();

const mesh = useRef<Mesh | null>();

useLookAt({ object: mesh.current, target: camera.position });

return (
<Text3D
color={theme.colors.zinc[600]}
ref={mesh}
position={[x, 0, y]}
fontSize={300}
fontWeight="semibold"
anchorX="center"
anchorY="middle"
>
{number}
</Text3D>
);
}
Loading