import React, { useEffect, useState } from 'react'; import FullCalendar, { EventInput } from '@fullcalendar/react'; import dayGridPlugin from '@fullcalendar/daygrid'; import timeGridPlugin from '@fullcalendar/timegrid'; import interactionPlugin from '@fullcalendar/interaction'; import '../styles/Calendar.css'; // Define colors for each beamline const beamlineColors: { [key: string]: string } = { PXI: '#FF5733', PXII: '#33FF57', PXIII: '#3357FF', Unknown: '#CCCCCC', // Gray color for unknown beamlines }; // Custom event interface interface CustomEvent extends EventInput { beamline: string; beamtime_shift: string; isSubmitted?: boolean; // Track if information is submitted } // Define experiment modes const experimentModes = ['SDU-Scheduled', 'SDU-queued', 'Remote', 'In-person']; // Utility function to darken a hex color const darkenColor = (color: string, percent: number): string => { const num = parseInt(color.slice(1), 16); // Convert hex to number const amt = Math.round(2.55 * percent); // Calculate amount to darken const r = (num >> 16) + amt; // Red const g = (num >> 8 & 0x00FF) + amt; // Green const b = (num & 0x0000FF) + amt; // Blue // Ensure values stay within 0-255 range const newColor = (0x1000000 + (r < 255 ? (r < 0 ? 0 : r) : 255) * 0x10000 + (g < 255 ? (g < 0 ? 0 : g) : 255) * 0x100 + (b < 255 ? (b < 0 ? 0 : b) : 255)).toString(16).slice(1); return `#${newColor}`; }; const Calendar: React.FC = () => { const [events, setEvents] = useState([]); const [selectedEventId, setSelectedEventId] = useState(null); const [eventDetails, setEventDetails] = useState(null); const [userDetails, setUserDetails] = useState({ name: '', firstName: '', phone: '', email: '', extAccount: '', experimentMode: experimentModes[0], }); const [shipments, setShipments] = useState([]); // State for shipments const [selectedDewars, setSelectedDewars] = useState([]); // Track selected dewars for the experiment useEffect(() => { const fetchEvents = async () => { try { const response = await fetch('/beamtimedb.json'); const data = await response.json(); const events: CustomEvent[] = []; data.beamtimes.forEach((beamtime: any) => { const date = new Date(beamtime.date); beamtime.shifts.forEach((shift: any) => { const beamline = shift.beamline || 'Unknown'; const beamtime_shift = shift.beamtime_shift || 'morning'; const event: CustomEvent = { id: `${beamline}-${date.toISOString()}-${beamtime_shift}`, start: new Date(date.setHours(0, 0, 0)), end: new Date(date.setHours(23, 59, 59)), title: `${beamline}: ${beamtime_shift}`, beamline, beamtime_shift, isSubmitted: false, }; events.push(event); }); }); console.log('Fetched events array:', events); setEvents(events); } catch (error) { console.error('Error fetching events:', error); } }; const fetchShipments = async () => { try { const response = await fetch('/shipmentdb.json'); // Check for HTTP errors if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } // Parse the JSON response const data = await response.json(); const availableDewars: any[] = []; data.shipments.forEach(shipment => { if (shipment.shipment_status === "In Transit") { shipment.dewars.forEach(dewar => { if (dewar.shippingStatus === "shipped" && dewar.returned === "") { availableDewars.push(dewar); } }); } }); console.log('Available Dewars:', availableDewars); setShipments(availableDewars); } catch (error) { console.error('Error fetching shipments:', error); // Optionally display the error to the user in the UI } }; fetchEvents(); fetchShipments(); }, []); const handleEventClick = (eventInfo: any) => { const clickedEventId = eventInfo.event.id; setSelectedEventId(clickedEventId); const selectedEvent = events.find(event => event.id === clickedEventId) || null; setEventDetails(selectedEvent); }; const handleInputChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setUserDetails(prevDetails => ({ ...prevDetails, [name]: value, })); }; const handleDewarSelection = (dewarId: string) => { setSelectedDewars(prevSelectedDewars => { if (prevSelectedDewars.includes(dewarId)) { return prevSelectedDewars.filter(id => id !== dewarId); // Remove if already selected } else { return [...prevSelectedDewars, dewarId]; // Add if not selected } }); }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (eventDetails) { const updatedEvents = events.map(event => event.id === eventDetails.id ? { ...event, isSubmitted: true, selectedDewars } // Associate selected dewars : event ); setEvents(updatedEvents); } console.log('User Details:', userDetails); console.log('Selected Dewars:', selectedDewars); // Reset user details and selected dewars after submission setUserDetails({ name: '', firstName: '', phone: '', email: '', extAccount: '', experimentMode: experimentModes[0], }); setSelectedDewars([]); // Reset selected dewars }; const eventContent = (eventInfo: any) => { const beamline = eventInfo.event.extendedProps.beamline || 'Unknown'; const isSelected = selectedEventId === eventInfo.event.id; const isSubmitted = eventInfo.event.extendedProps.isSubmitted; const backgroundColor = isSubmitted ? darkenColor(beamlineColors[beamline] || beamlineColors.Unknown, -20) : isSelected ? '#FFD700' : (beamlineColors[beamline] || beamlineColors.Unknown); return (
{eventInfo.event.title}
); }; return (

Beamline Calendar

{eventDetails && (

Event Details

Beamline: {eventDetails.beamline}

Shift: {eventDetails.beamtime_shift}

Select Dewars

    {shipments.map(dewar => (
  • handleDewarSelection(dewar.id)} />
  • ))}

User Information







)}
); }; export default Calendar;