'use client' import { useState, useEffect } from 'react' import axios from 'axios' import { BuildingOffice2Icon, CalendarIcon, ClipboardDocumentListIcon, ChartBarIcon, UserGroupIcon, WrenchScrewdriverIcon, CheckCircleIcon, XCircleIcon, ClockIcon, EnvelopeIcon, DocumentTextIcon, TrashIcon, CheckIcon, XMarkIcon } from '@heroicons/react/24/outline' interface Room { id: number name: string capacity: number equipment: string | null description: string | null } interface Reservation { id: number room_id: number room_name?: string user_name: string user_email: string reservation_date: string start_time: string end_time: string purpose: string created_at: string } export default function Home() { const [rooms, setRooms] = useState([]) const [reservations, setReservations] = useState([]) const [selectedRoom, setSelectedRoom] = useState(null) const [loading, setLoading] = useState(false) const [activeTab, setActiveTab] = useState<'rooms' | 'reservations' | 'planning'>('planning') const [selectedDate, setSelectedDate] = useState(new Date().toISOString().split('T')[0]) // Formulaire de réservation const [formData, setFormData] = useState({ user_name: '', user_email: '', reservation_date: '', start_time: '', end_time: '', purpose: '' }) const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://141.253.118.141:8001' useEffect(() => { fetchRooms() fetchReservations() }, []) const fetchRooms = async () => { try { const response = await axios.get(`${API_URL}/rooms`) setRooms(response.data) } catch (error) { console.error('Erreur lors du chargement des salles:', error) } } const fetchReservations = async () => { try { const response = await axios.get(`${API_URL}/reservations`) setReservations(response.data) } catch (error) { console.error('Erreur lors du chargement des réservations:', error) } } const fetchReservationsByDate = async (date: string) => { try { const response = await axios.get(`${API_URL}/reservations/date/${date}`) return response.data } catch (error) { console.error('Erreur lors du chargement des réservations par date:', error) return [] } } const getReservationsForRoom = (roomId: number, date: string) => { return reservations.filter(r => r.room_id === roomId && r.reservation_date === date ) } const isSlotAvailable = (roomId: number, date: string, startTime: string, endTime: string) => { const roomReservations = getReservationsForRoom(roomId, date) for (const reservation of roomReservations) { const resStart = reservation.start_time const resEnd = reservation.end_time // Vérifie s'il y a chevauchement if ((startTime < resEnd && endTime > resStart)) { return false } } return true } const handleReservation = async (e: React.FormEvent) => { e.preventDefault() if (!selectedRoom) { alert('Veuillez sélectionner une salle') return } setLoading(true) try { await axios.post(`${API_URL}/reservations`, { room_id: selectedRoom, ...formData }) alert('Réservation effectuée avec succès !') setFormData({ user_name: '', user_email: '', reservation_date: '', start_time: '', end_time: '', purpose: '' }) setSelectedRoom(null) fetchReservations() } catch (error: any) { if (error.response?.status === 409) { alert('Cette salle est déjà réservée pour ce créneau horaire') } else { alert('Erreur lors de la réservation: ' + (error.response?.data?.detail || error.message)) } } finally { setLoading(false) } } const handleDeleteReservation = async (id: number) => { if (!confirm('Voulez-vous vraiment annuler cette réservation ?')) return try { await axios.delete(`${API_URL}/reservations/${id}`) fetchReservations() alert('Réservation annulée avec succès') } catch (error) { console.error('Erreur lors de l\'annulation:', error) alert('Erreur lors de l\'annulation de la réservation') } } return (
{/* Header */}

Expernet

Centre de Formation - Réservation de Salles

{/* Tabs */}
{/* Onglet Planning */} {activeTab === 'planning' && (

Planning des Salles

setSelectedDate(e.target.value)} className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" />
{/* Grille de planning */}
{Array.from({ length: 14 }, (_, i) => i + 8).map((hour) => ( ))} {rooms.map((room) => { const roomReservations = getReservationsForRoom(room.id, selectedDate) return ( {Array.from({ length: 14 }, (_, i) => i + 8).map((hour) => { const hourStart = `${hour.toString().padStart(2, '0')}:00` const hourEnd = `${(hour + 1).toString().padStart(2, '0')}:00` // Trouver les réservations qui couvrent cette heure const overlappingReservations = roomReservations.filter(res => { return res.start_time < hourEnd && res.end_time > hourStart }) const isOccupied = overlappingReservations.length > 0 const reservation = overlappingReservations[0] return ( ) })} ) })}
Salle {hour}h
{room.name}
{room.capacity} pers.
{isOccupied ? (
{reservation.user_name}
) : (
)}
{/* Légende */}
Disponible
Réservé
{/* Liste des réservations du jour */}

Réservations du {new Date(selectedDate).toLocaleDateString('fr-FR')}

{reservations.filter(r => r.reservation_date === selectedDate).length === 0 ? (

Aucune réservation pour cette date

) : (
{reservations .filter(r => r.reservation_date === selectedDate) .sort((a, b) => a.start_time.localeCompare(b.start_time)) .map((reservation) => (
{reservation.room_name} {reservation.start_time} - {reservation.end_time}
{reservation.user_name}
{reservation.purpose}
))}
)}
)} {/* Onglet Réservation */} {activeTab === 'rooms' && (
{/* Liste des salles */}

Nos Salles Disponibles

{rooms.map((room) => (
setSelectedRoom(room.id)} className={`border-2 rounded-lg p-4 cursor-pointer transition-all ${ selectedRoom === room.id ? 'border-indigo-600 bg-indigo-50' : 'border-gray-200 hover:border-indigo-300' }`} >

{room.name}

Capacité: {room.capacity} personnes

{room.equipment && (

{room.equipment}

)} {room.description && (

{room.description}

)}
{selectedRoom === room.id && (
)}
))}
{/* Formulaire de réservation */}

Formulaire de Réservation

{!selectedRoom ? (

Sélectionnez une salle pour continuer

) : (
setFormData({ ...formData, user_name: e.target.value })} required className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" placeholder="Jean Dupont" />
setFormData({ ...formData, user_email: e.target.value })} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" placeholder="jean.dupont@expernet.fr" />
setFormData({ ...formData, reservation_date: e.target.value })} required min={new Date().toISOString().split('T')[0]} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" />
setFormData({ ...formData, start_time: e.target.value })} required className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" />
setFormData({ ...formData, end_time: e.target.value })} required className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" />