diff --git a/app/components/talks/PlanningOverview.tsx b/app/components/talks/PlanningOverview.tsx index 2d5f02d..6224a89 100644 --- a/app/components/talks/PlanningOverview.tsx +++ b/app/components/talks/PlanningOverview.tsx @@ -1,39 +1,55 @@ -'use client'; +import React, { useState, useEffect, useMemo } from 'react'; -import { useEffect, useState } from 'react'; -import type { Talk } from '@/lib/types'; - -interface Room { - roomId: number; +// Define types for schedule and nested room +export interface Room { + id: number; name: string; + capacity: number; + description: string; + created_at: string; } -interface ScheduledSlot { +export interface ScheduledSlot { id: number; - roomId: number; - startTime: string; - endTime: string; - talk: Talk; -} - -interface PlanningOverviewProps { - rooms: Room[]; - date: Date; + talk_id: number; + room_id: number; + start_time: string; + end_time: string; + created_at: string; + updated_at: string; + rooms: Room; } -export default function PlanningOverview({ rooms, date }: PlanningOverviewProps) { +const PlanningTable: React.FC = () => { + const [date, setDate] = useState(new Date()); + const [rooms, setRooms] = useState([]); const [scheduledSlots, setScheduledSlots] = useState([]); - const hours = Array.from({ length: 9 }, (_, i) => 9 + i); // 09–10 … 17–18 + // Fetch rooms on mount useEffect(() => { - const dateParam = date.toISOString().slice(0, 10); // "YYYY-MM-DD" + fetch('/api/rooms') + .then((res) => { + if (!res.ok) throw new Error('Impossible de charger les salles'); + return res.json(); + }) + .then((data: { rooms: Room[] }) => { + setRooms(data.rooms); + }) + .catch((err) => { + console.error(err); + alert(err.message); + }); + }, []); + + // Fetch schedules whenever the date changes + useEffect(() => { + const dateParam = date.toISOString().slice(0, 10); fetch(`/api/schedules?date=${dateParam}`) .then((res) => { if (!res.ok) throw new Error('Impossible de charger le planning'); return res.json(); }) .then((data: { schedules: ScheduledSlot[] }) => { - // console.log('schedules from API:', data.schedules); setScheduledSlots(data.schedules); }) .catch((err) => { @@ -42,35 +58,77 @@ export default function PlanningOverview({ rooms, date }: PlanningOverviewProps) }); }, [date]); + // Build all possible timeslots from 09:00 to 19:00 + const timeSlots = useMemo(() => { + const slots: { start: Date; end: Date; label: string }[] = []; + const day = date.toISOString().slice(0, 10); + for (let hour = 9; hour < 19; hour++) { + const start = new Date(`${day}T${String(hour).padStart(2, '0')}:00:00`); + const end = new Date(`${day}T${String(hour + 1).padStart(2, '0')}:00:00`); + const startLabel = `${String(start.getHours()).padStart(2, '0')}:${String(start.getMinutes()).padStart(2, '0')}`; + const endLabel = `${String(end.getHours()).padStart(2, '0')}:${String(end.getMinutes()).padStart(2, '0')}`; + const label = `${startLabel} - ${endLabel}`; + slots.push({ start, end, label }); + } + return slots; + }, [date]); + + const handleDateChange = (e: React.ChangeEvent) => { + setDate(new Date(e.target.value)); + }; + return ( -
- - +
+
+ + +
+ +
+ - - {hours.map((h) => ( - + {timeSlots.map((slot) => ( + ))} - + {rooms.map((room) => ( - - - {hours.map((h) => { - const slot = scheduledSlots.find( - (s) => s.roomId === room.roomId && new Date(s.startTime).getHours() === h, - ); + + + {timeSlots.map((slot) => { + const match = scheduledSlots.find((s) => { + const slotStart = new Date(s.start_time); + return ( + s.room_id === room.id && + slotStart.getFullYear() === slot.start.getFullYear() && + slotStart.getMonth() === slot.start.getMonth() && + slotStart.getDate() === slot.start.getDate() && + slotStart.getHours() === slot.start.getHours() + ); + }); return ( - ); })} @@ -80,4 +138,6 @@ export default function PlanningOverview({ rooms, date }: PlanningOverviewProps)
Salle / Heure - {`${h}:00–${h + 1}:00`} + + Salle + + {slot.label}
{room.name}
{room.name} - {slot ? ( -
- {slot.talk.title} - Speaker #{slot.talk.speakerId} -
- ) : null} +
+ {match ? match.talk_id : '-'}
); -} +}; + +export default PlanningTable; diff --git a/app/components/talks/TalksList.tsx b/app/components/talks/TalksList.tsx index 125ef6d..0fd950b 100644 --- a/app/components/talks/TalksList.tsx +++ b/app/components/talks/TalksList.tsx @@ -223,7 +223,7 @@ export default function TalksList({ if (session.data?.user.id === talk.speakerId) { return true; } - return talk.status === 'accepted'; + return talk.status === 'scheduled'; }) // .map(({ talk }) => ( .map((talk) => ( diff --git a/app/components/talks/TalksSchedule.tsx b/app/components/talks/TalksSchedule.tsx index 941e291..de5e834 100644 --- a/app/components/talks/TalksSchedule.tsx +++ b/app/components/talks/TalksSchedule.tsx @@ -20,7 +20,7 @@ import { Calendar as CalendarIcon } from 'lucide-react'; import { cn } from '@/lib/utils'; import { isOrganizer } from '@/utils/auth.utils'; import type { Talk } from '@/lib/types'; -import PlanningOverview from './PlanningOverview'; +import PlanningTable from './PlanningOverview'; // // Define the shape coming back from /api/rooms/availability @@ -288,10 +288,7 @@ export default function TalksSchedule({ talks, onScheduleTalk }: TalksSchedulePr - ({ roomId, name }))} - date={selectedDate} - /> + ); }