Version 1.0 - Stable

This commit is contained in:
Afonso Clerigo Mendes de Sousa 2026-01-06 16:59:05 +00:00
parent 8de538cc29
commit 81b497517e
9 changed files with 7038 additions and 7068 deletions

View File

@ -1,13 +1,16 @@
// app/api/events/[id]/results/route.ts
// app/api/events/[event_id]/results/route.ts
import { query } from '@/lib/db';
import { NextResponse } from 'next/server';
import { NextResponse, NextRequest } from 'next/server';
export const dynamic = 'force-dynamic';
export async function GET(
request: Request,
{ params }: { params: { id: string } }
request: NextRequest,
context: { params: Promise<{ event_id: string }> }
) {
const { event_id } = await context.params;
try {
const standingsSql = `
SELECT
@ -35,7 +38,7 @@ export async function GET(
ORDER BY tcs.total_points DESC, tcs.best_finish ASC
`;
const standings = await query(standingsSql, [params.id]);
const standings = await query(standingsSql, [event_id]);
return NextResponse.json({ standings });
} catch (error) {

View File

@ -6,6 +6,61 @@ import { Event, EventRegistration } from '@/types/racing';
import { notFound } from 'next/navigation';
import { TrophyIcon, MapPinIcon, UsersIcon, ClockIcon, CalendarIcon } from '@/components/ui/icons';
import EventRegistrationForm from '@/components/events/EventRegistrationForm';
import EventResultClient from '@/components/events/EventResultsClient';
export const dynamic = "force-dynamic";
async function getEventResults(eventId: number) {
if (eventId == undefined) {
return { event: null, standings: [] };
}
// Get event info
const eventSql = `
SELECT
event_id,
event_name,
event_track,
event_date,
event_status
FROM events
WHERE event_id = $1
`;
const events = await query(eventSql, [String(eventId)]);
const event = events[0];
// Get team standings with driver details
const standingsSql = `
SELECT
tcs.team_id,
t.name as team_name,
tcs.total_points,
tcs.races_participated,
tcs.best_finish,
json_agg(
json_build_object(
'driver_guid', u.driver_guid,
'driver_name', u.driver_name,
'position', er.position,
'points_awarded', er.points_awarded,
'laps_completed', er.laps_completed,
'dnf', er.dnf
) ORDER BY er.position ASC
) as drivers
FROM team_championship_standings tcs
JOIN teams t ON tcs.team_id = t.id
LEFT JOIN event_results er ON tcs.event_id = er.event_id AND tcs.team_id = er.team_id
LEFT JOIN users u ON er.driver_guid = u.driver_guid
WHERE tcs.event_id = $1
GROUP BY tcs.team_id, t.name, tcs.total_points, tcs.races_participated, tcs.best_finish
ORDER BY tcs.total_points DESC, tcs.best_finish ASC
`;
const standings = await query(standingsSql, [eventId]);
return { event, standings };
}
async function getEvent(eventId: number): Promise<Event | null> {
const sql = `
@ -49,18 +104,20 @@ function formatDate(date: Date): string {
export default async function EventDetailPage({
params,
}: {
params: Promise<{ event_id: string }>;
params: Promise<{ event_id: number }>;
}) {
const { event_id } = await params;
const eventId = parseInt(event_id, 10);
const event: any = await getEvent(eventId);
const event: any = await getEvent(event_id);
if (!event) {
notFound();
}
const registrations = await getEventRegistrations(eventId);
const registrations = await getEventRegistrations(event_id);
// Fetch initial event results/standings
const { standings } = await getEventResults(event_id);
const isOpen = event.event_status === 'OPEN';
const isFull = event.registrations_count >= event.max_participants;
@ -118,6 +175,12 @@ export default async function EventDetailPage({
{deadlinePassed && !isFull && 'Registration deadline has passed.'}
{event.event_status === 'CLOSED' && !isFull && !deadlinePassed && 'Registration is closed for this event.'}
</p>
<div className="mt-6">
<EventResultClient
eventId={event_id}
initialStandings={standings}
/>
</div>
</div>
)}

View File

@ -1,4 +1,4 @@
// app/events/[id]/results/page.tsx
// app/events/[event_id]/results/page.tsx
// Event championship results page with auto-refresh
import { query } from '@/lib/db';
@ -22,7 +22,11 @@ interface TeamStanding {
}[];
}
async function getEventResults(eventId: string) {
async function getEventResults(eventId: number) {
if (eventId == undefined) {
return { event: null, standings: [] };
}
// Get event info
const eventSql = `
SELECT
@ -34,7 +38,7 @@ async function getEventResults(eventId: string) {
FROM events
WHERE event_id = $1
`;
const events = await query(eventSql, [eventId]);
const events = await query(eventSql, [String(eventId)]);
const event = events[0];
// Get team standings with driver details
@ -76,8 +80,18 @@ function getPositionColor(position: number): string {
return 'bg-white/5 border-white/10 text-white/60';
}
export default async function EventResultsPage({ params }: { params: { id: string } }) {
const { event, standings } = await getEventResults(params.id);
export default async function EventResultsPage({
params,
}: {
params: Promise<{ event_id: number }>;
}) {
const { event_id } = await params;
console.log('Fetching results for event ID:', event_id);
const { event, standings } = await getEventResults(event_id);
if (!event) {
return (
@ -96,7 +110,7 @@ export default async function EventResultsPage({ params }: { params: { id: strin
<div className="max-w-7xl mx-auto px-6 py-16">
<div className="space-y-4">
<Link
href={`/events/${params.id}`}
href={`/events/${event_id}`}
className="inline-flex items-center space-x-2 text-white/60 hover:text-white transition-colors text-sm"
>
<span></span>
@ -104,7 +118,6 @@ export default async function EventResultsPage({ params }: { params: { id: strin
</Link>
<div className="flex items-center space-x-3">
<TrophyIcon className="w-12 h-12 text-yellow-500" />
<div>
<h1 className="text-5xl font-bold tracking-tight">
CHAMPIONSHIP RESULTS
@ -120,101 +133,22 @@ export default async function EventResultsPage({ params }: { params: { id: strin
{/* Team Championship Standings */}
<div className="max-w-7xl mx-auto px-6 py-12">
{standings.length === 0 ? (
<div className="border border-white/10 p-16 text-center bg-black">
<TrophyIcon className="w-16 h-16 mx-auto mb-6 text-white/20" />
<p className="text-white/40 text-base tracking-wider">NO RESULTS YET</p>
<p className="text-white/20 text-sm mt-2">Results will appear after the event concludes</p>
</div>
) : (
<div className="space-y-4">
{standings.map((team: TeamStanding, index: number) => (
<div
key={team.team_id}
className={`border p-6 transition-all ${getPositionColor(index + 1)}`}
>
<div className="flex items-start justify-between mb-4">
<div className="flex items-center space-x-4">
{/* Position Badge */}
<div className="w-16 h-16 border-2 flex items-center justify-center">
<span className="text-3xl font-bold">
{index + 1}
</span>
</div>
{/* Team Info */}
<div>
<h2 className="text-2xl font-bold tracking-tight">
{team.team_name}
</h2>
<div className="flex items-center space-x-4 mt-2 text-sm text-white/60">
<div className="flex items-center space-x-1">
<UsersIcon className="w-4 h-4" />
<span>{team.drivers.length} {team.drivers.length === 1 ? 'Driver' : 'Drivers'}</span>
</div>
<div className="flex items-center space-x-1">
<FlagIcon className="w-4 h-4" />
<span>Best Finish: P{team.best_finish}</span>
</div>
</div>
</div>
</div>
{/* Total Points */}
<div className="text-right">
<div className="text-5xl font-bold tracking-tight">
{team.total_points}
</div>
<div className="text-sm text-white/60 tracking-wider">POINTS</div>
</div>
</div>
{/* Driver Results */}
<div className="border-t border-white/10 pt-4 mt-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
{team.drivers.map((driver: any) => (
<div
key={driver.driver_guid}
className="flex items-center justify-between p-3 bg-black/30 border border-white/5"
>
<div className="flex items-center space-x-3">
<div className={`w-8 h-8 border flex items-center justify-center text-xs font-bold ${
driver.position <= 3 ? 'border-white/30' : 'border-white/10'
}`}>
P{driver.position}
</div>
<div>
<div className="font-semibold text-sm">{driver.driver_name}</div>
{driver.dnf && (
<div className="text-xs text-red-400">DNF</div>
)}
</div>
</div>
<div className="text-right">
<div className="font-bold text-lg">{driver.points_awarded}</div>
<div className="text-xs text-white/40">pts</div>
</div>
</div>
))}
</div>
</div>
</div>
))}
</div>
)}
<EventResultsClient
eventId={event_id}
initialStandings={standings}
/>
{/* Points System Info */}
<div className="mt-8 border border-white/10 p-6 bg-black">
<h3 className="text-sm font-bold tracking-wider text-white/60 mb-4">POINTS SYSTEM</h3>
<div className="grid grid-cols-2 md:grid-cols-5 gap-4 text-sm">
<div><span className="font-mono text-white/80">P1:</span> <span className="font-bold">25 pts</span></div>
<div><span className="font-mono text-white/80">P2:</span> <span className="font-bold">18 pts</span></div>
<div><span className="font-mono text-white/80">P3:</span> <span className="font-bold">15 pts</span></div>
<div><span className="font-mono text-white/80">P4:</span> <span className="font-bold">12 pts</span></div>
<div><span className="font-mono text-white/80">P5:</span> <span className="font-bold">10 pts</span></div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
<div><span className="font-mono text-white/80">P1:</span> <span className="font-bold">5 pts</span></div>
<div><span className="font-mono text-white/80">P2:</span> <span className="font-bold">3 pts</span></div>
<div><span className="font-mono text-white/80">P3:</span> <span className="font-bold">2 pts</span></div>
<div><span className="font-mono text-white/80">P4...:</span> <span className="font-bold">1 pts</span></div>
</div>
<p className="text-xs text-white/40 mt-4">
Team points are the sum of all driver points from that team in the event
Team points are the sum of all driver points from that team in the event Updates every 5 seconds
</p>
</div>
</div>

View File

@ -76,7 +76,7 @@ export default async function EventsPage() {
<div key={event.event_id} className="border border-white/10 sharp-border bg-black">
<img
src="https://openwheels.racing/files/img/EnduranceEvents1-1.png?fckcache=999"
src={`https://openwheels.racing/files/img/EnduranceEvents1-${event.event_id}.png?fckcache=999`}
alt={event.event_name}
className="w-full h-48 object-cover object-[50%_0%] border-b border-white/10 grayscale hover:grayscale-0 transition duration-300"
/>

View File

@ -30,7 +30,7 @@ export default function EventResultsClient({
eventId,
initialStandings
}: {
eventId: string;
eventId: number;
initialStandings: TeamStanding[]
}) {
const [standings, setStandings] = useState<TeamStanding[]>(initialStandings);

View File

@ -136,14 +136,7 @@ function parseMapIni(iniText: string): TrackMapConfig {
};
}
/**
* Convert world coordinates to map pixel coordinates using AC's formula
* Trying with coordinate rotation
*/
/**
* Convert world coordinates to map pixel coordinates
* Based on working formula with potential rotation fix
*/
export function worldToMapCoords(
worldX: number,
worldY: number,
@ -153,7 +146,8 @@ export function worldToMapCoords(
var aspectRatio = config.width / config.height;
// Add offsets to player position
console.log("config" , config);
console.log("aspectRatio:", aspectRatio);
if (aspectRatio < 1) {
worldX = worldX * aspectRatio;
} else {

View File

@ -1,24 +0,0 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
// Use standalone output for server deployment
output: 'standalone',
// Image optimization
images: {
unoptimized: true,
remotePatterns: [
{
protocol: 'https',
hostname: 'openwheels.racing',
},
],
},
// Type checking during build
typescript: {
ignoreBuildErrors: false,
},
};
module.exports = nextConfig;

104
package-lock.json generated
View File

@ -10,10 +10,10 @@
"dependencies": {
"axios": "^1.12.2",
"date-fns": "^4.1.0",
"next": "16.0.0",
"next": "^16.0.10",
"pg": "^8.16.3",
"react": "19.2.0",
"react-dom": "19.2.0",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"socket.io-client": "^4.8.1"
},
"devDependencies": {
@ -1002,9 +1002,9 @@
}
},
"node_modules/@next/env": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.0.tgz",
"integrity": "sha512-s5j2iFGp38QsG1LWRQaE2iUY3h1jc014/melHFfLdrsMJPqxqDQwWNwyQTcNoUSGZlCVZuM7t7JDMmSyRilsnA==",
"version": "16.0.10",
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.10.tgz",
"integrity": "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang==",
"license": "MIT"
},
"node_modules/@next/eslint-plugin-next": {
@ -1018,9 +1018,9 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.0.tgz",
"integrity": "sha512-/CntqDCnk5w2qIwMiF0a9r6+9qunZzFmU0cBX4T82LOflE72zzH6gnOjCwUXYKOBlQi8OpP/rMj8cBIr18x4TA==",
"version": "16.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.10.tgz",
"integrity": "sha512-4XgdKtdVsaflErz+B5XeG0T5PeXKDdruDf3CRpnhN+8UebNa5N2H58+3GDgpn/9GBurrQ1uWW768FfscwYkJRg==",
"cpu": [
"arm64"
],
@ -1034,9 +1034,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.0.tgz",
"integrity": "sha512-hB4GZnJGKa8m4efvTGNyii6qs76vTNl+3dKHTCAUaksN6KjYy4iEO3Q5ira405NW2PKb3EcqWiRaL9DrYJfMHg==",
"version": "16.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.10.tgz",
"integrity": "sha512-spbEObMvRKkQ3CkYVOME+ocPDFo5UqHb8EMTS78/0mQ+O1nqE8toHJVioZo4TvebATxgA8XMTHHrScPrn68OGw==",
"cpu": [
"x64"
],
@ -1050,9 +1050,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.0.tgz",
"integrity": "sha512-E2IHMdE+C1k+nUgndM13/BY/iJY9KGCphCftMh7SXWcaQqExq/pJU/1Hgn8n/tFwSoLoYC/yUghOv97tAsIxqg==",
"version": "16.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.10.tgz",
"integrity": "sha512-uQtWE3X0iGB8apTIskOMi2w/MKONrPOUCi5yLO+v3O8Mb5c7K4Q5KD1jvTpTF5gJKa3VH/ijKjKUq9O9UhwOYw==",
"cpu": [
"arm64"
],
@ -1066,9 +1066,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.0.tgz",
"integrity": "sha512-xzgl7c7BVk4+7PDWldU+On2nlwnGgFqJ1siWp3/8S0KBBLCjonB6zwJYPtl4MUY7YZJrzzumdUpUoquu5zk8vg==",
"version": "16.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.10.tgz",
"integrity": "sha512-llA+hiDTrYvyWI21Z0L1GiXwjQaanPVQQwru5peOgtooeJ8qx3tlqRV2P7uH2pKQaUfHxI/WVarvI5oYgGxaTw==",
"cpu": [
"arm64"
],
@ -1082,9 +1082,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.0.tgz",
"integrity": "sha512-sdyOg4cbiCw7YUr0F/7ya42oiVBXLD21EYkSwN+PhE4csJH4MSXUsYyslliiiBwkM+KsuQH/y9wuxVz6s7Nstg==",
"version": "16.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.10.tgz",
"integrity": "sha512-AK2q5H0+a9nsXbeZ3FZdMtbtu9jxW4R/NgzZ6+lrTm3d6Zb7jYrWcgjcpM1k8uuqlSy4xIyPR2YiuUr+wXsavA==",
"cpu": [
"x64"
],
@ -1098,9 +1098,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.0.tgz",
"integrity": "sha512-IAXv3OBYqVaNOgyd3kxR4L3msuhmSy1bcchPHxDOjypG33i2yDWvGBwFD94OuuTjjTt/7cuIKtAmoOOml6kfbg==",
"version": "16.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.10.tgz",
"integrity": "sha512-1TDG9PDKivNw5550S111gsO4RGennLVl9cipPhtkXIFVwo31YZ73nEbLjNC8qG3SgTz/QZyYyaFYMeY4BKZR/g==",
"cpu": [
"x64"
],
@ -1114,9 +1114,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.0.tgz",
"integrity": "sha512-bmo3ncIJKUS9PWK1JD9pEVv0yuvp1KPuOsyJTHXTv8KDrEmgV/K+U0C75rl9rhIaODcS7JEb6/7eJhdwXI0XmA==",
"version": "16.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.10.tgz",
"integrity": "sha512-aEZIS4Hh32xdJQbHz121pyuVZniSNoqDVx1yIr2hy+ZwJGipeqnMZBJHyMxv2tiuAXGx6/xpTcQJ6btIiBjgmg==",
"cpu": [
"arm64"
],
@ -1130,9 +1130,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.0.tgz",
"integrity": "sha512-O1cJbT+lZp+cTjYyZGiDwsOjO3UHHzSqobkPNipdlnnuPb1swfcuY6r3p8dsKU4hAIEO4cO67ZCfVVH/M1ETXA==",
"version": "16.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.10.tgz",
"integrity": "sha512-E+njfCoFLb01RAFEnGZn6ERoOqhK1Gl3Lfz1Kjnj0Ulfu7oJbuMyvBKNj/bw8XZnenHDASlygTjZICQW+rYW1Q==",
"cpu": [
"x64"
],
@ -4542,9 +4542,9 @@
"license": "MIT"
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -5103,12 +5103,12 @@
"license": "MIT"
},
"node_modules/next": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/next/-/next-16.0.0.tgz",
"integrity": "sha512-nYohiNdxGu4OmBzggxy9rczmjIGI+TpR5vbKTsE1HqYwNm1B+YSiugSrFguX6omMOKnDHAmBPY4+8TNJk0Idyg==",
"version": "16.0.10",
"resolved": "https://registry.npmjs.org/next/-/next-16.0.10.tgz",
"integrity": "sha512-RtWh5PUgI+vxlV3HdR+IfWA1UUHu0+Ram/JBO4vWB54cVPentCD0e+lxyAYEsDTqGGMg7qpjhKh6dc6aW7W/sA==",
"license": "MIT",
"dependencies": {
"@next/env": "16.0.0",
"@next/env": "16.0.10",
"@swc/helpers": "0.5.15",
"caniuse-lite": "^1.0.30001579",
"postcss": "8.4.31",
@ -5121,14 +5121,14 @@
"node": ">=20.9.0"
},
"optionalDependencies": {
"@next/swc-darwin-arm64": "16.0.0",
"@next/swc-darwin-x64": "16.0.0",
"@next/swc-linux-arm64-gnu": "16.0.0",
"@next/swc-linux-arm64-musl": "16.0.0",
"@next/swc-linux-x64-gnu": "16.0.0",
"@next/swc-linux-x64-musl": "16.0.0",
"@next/swc-win32-arm64-msvc": "16.0.0",
"@next/swc-win32-x64-msvc": "16.0.0",
"@next/swc-darwin-arm64": "16.0.10",
"@next/swc-darwin-x64": "16.0.10",
"@next/swc-linux-arm64-gnu": "16.0.10",
"@next/swc-linux-arm64-musl": "16.0.10",
"@next/swc-linux-x64-gnu": "16.0.10",
"@next/swc-linux-x64-musl": "16.0.10",
"@next/swc-win32-arm64-msvc": "16.0.10",
"@next/swc-win32-x64-msvc": "16.0.10",
"sharp": "^0.34.4"
},
"peerDependencies": {
@ -5666,24 +5666,24 @@
"license": "MIT"
},
"node_modules/react": {
"version": "19.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
"version": "19.2.3",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
"version": "19.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
"version": "19.2.3",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
"license": "MIT",
"dependencies": {
"scheduler": "^0.27.0"
},
"peerDependencies": {
"react": "^19.2.0"
"react": "^19.2.3"
}
},
"node_modules/react-is": {

View File

@ -11,10 +11,10 @@
"dependencies": {
"axios": "^1.12.2",
"date-fns": "^4.1.0",
"next": "16.0.0",
"next": "^16.0.10",
"pg": "^8.16.3",
"react": "19.2.0",
"react-dom": "19.2.0",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"socket.io-client": "^4.8.1"
},
"devDependencies": {