Organizing imports in the frontend.

Signed-off-by: Cliff Hill <xlorep@darkhelm.org>
This commit is contained in:
2025-09-08 17:01:21 -04:00
parent d4c064e2f7
commit 7a1bfd6687
12 changed files with 262 additions and 32 deletions

View File

@@ -6,9 +6,9 @@
* Author: Cliff Hill
* Last updated: 2025-09-05
*/
import { logger } from "./utils/logger";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import { logger } from "./utils/logger";
import LandingPage from "./pages/LandingPage";
import BookingPage from "./pages/BookingPage";
import ConfirmationPage from "./pages/ConfirmationPage";

View File

@@ -14,9 +14,9 @@
* @param {BookingConfirmationProps} props - Component props
* @returns {JSX.Element} Confirmation UI
*/
import React from "react";
import { Box, Button } from "@mui/material";
import type { BookingConfirmationProps } from "../schemas";
/**

View File

@@ -6,13 +6,15 @@
* Author: Cliff Hill
* Last updated: 2025-09-05
*/
import React, { useState, useEffect, useRef } from "react";
import { useNavigate } from "react-router-dom";
import {
formatLocalDateTimeInput,
roundToStrictlyFutureQuarter,
} from "../utils/date";
getRoomBookings,
createBooking,
updateBooking,
deleteBooking,
} from "../apis/bookings";
import { getEditBookingRoomId, formatBookingError } from "../helpers/booking";
import {
validateRoomId,
@@ -23,11 +25,9 @@ import {
validateRoomAvailability,
} from "../helpers/validation";
import {
getRoomBookings,
createBooking,
updateBooking,
deleteBooking,
} from "../apis/bookings";
formatLocalDateTimeInput,
roundToStrictlyFutureQuarter,
} from "../utils/date";
import { connectRoomsAvailabilityStream } from "../apis/sse";
import { getInvitees, addInvitee, removeInvitee } from "../apis/invitees";
import { getAvailableUsers } from "../apis/users";

View File

@@ -9,7 +9,6 @@
import React from "react";
import { List, Typography, ListItemButton } from "@mui/material";
// ...existing code...
import {
sortBookingsByStartTime,
formatBookingTime,

View File

@@ -10,16 +10,17 @@
* CalendarView component.
* Renders calendar with events, tooltips, and slot selection.
*/
import React from "react";
import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import { EventInput } from "@fullcalendar/core";
import timeGridPlugin from "@fullcalendar/timegrid";
import Tooltip from "@mui/material/Tooltip";
import Typography from "@mui/material/Typography";
import "../styles/CalendarView.css";
import { EventInput } from "@fullcalendar/core";
import { getEventDisplayText, getRoomClass } from "../helpers/calendar";
import "../styles/CalendarView.css";
/**
* Props for CalendarView.

View File

@@ -6,6 +6,7 @@
* Author: Cliff Hill
* Last updated: 2025-09-05
*/
import React from "react";
import {
Dialog,
@@ -16,7 +17,6 @@ import {
Typography,
Box,
} from "@mui/material";
import type { RoomDetailsModalProps } from "../schemas";
const RoomDetailsModal: React.FC<RoomDetailsModalProps> = ({

View File

@@ -12,6 +12,7 @@
*/
import React from "react";
import { FC } from "react";
import {
Card,
CardContent,
@@ -22,9 +23,8 @@ import {
ListItemButton,
} from "@mui/material";
import MeetingRoomIcon from "@mui/icons-material/MeetingRoom";
import { FC } from "react";
import type { RoomListProps } from "../schemas";
import { getRoomListItemStyles, getRoomSecondaryText } from "../helpers/room";
import type { RoomListProps } from "../schemas";
/**
* Renders a list of conference rooms with their details.

View File

@@ -5,16 +5,17 @@
* Author: Cliff Hill
* Last updated: 2025-09-05
*/
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import axios from "axios";
import { ThemeProvider } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import App from "./App";
import theme from "./theme";
import reportWebVitals from "./reportWebVitals";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import axios from "axios";
import "./index.css";
// Global error handler to catch unhandled errors and prevent reloads
window.onerror = function (message, source, lineno, colno, error) {

View File

@@ -6,12 +6,9 @@
* Author: Cliff Hill
* Last updated: 2025-09-05
*/
import React, { useMemo, useState, useEffect, useRef } from "react";
import { useQuery } from "@tanstack/react-query";
import { getRooms } from "../apis/rooms";
import { getUsers } from "../apis/users";
import { getRoomBookings } from "../apis/bookings";
import { connectRoomsAvailabilityStream } from "../apis/sse";
import {
Button,
MenuItem,
@@ -20,8 +17,12 @@ import {
FormControl,
Box,
} from "@mui/material";
import CalendarView from "../components/CalendarView";
import { EventInput } from "@fullcalendar/core";
import { getRooms } from "../apis/rooms";
import { getUsers } from "../apis/users";
import { getRoomBookings } from "../apis/bookings";
import { connectRoomsAvailabilityStream } from "../apis/sse";
import CalendarView from "../components/CalendarView";
import BookingForm from "../components/BookingForm";
import RoomDetailsModal from "../components/RoomDetailsModal";
import { logger } from "../utils/logger";

View File

@@ -6,14 +6,15 @@
* Author: Cliff Hill
* Last updated: 2025-09-05
*/
import React, { useState } from "react";
import { Box } from "@mui/material";
import BookingConfirmation from "../components/BookingConfirmation";
import BookingForm from "../components/BookingForm";
import { useNavigate, useLocation } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import { getRooms } from "../apis/rooms";
import { connectRoomsAvailabilityStream } from "../apis/sse";
import BookingConfirmation from "../components/BookingConfirmation";
import BookingForm from "../components/BookingForm";
// This page expects booking data to be passed via location.state
const ConfirmationPage: React.FC = () => {

View File

@@ -7,6 +7,7 @@
* Author: Cliff Hill
* Last updated: 2025-09-05
*/
import React, { FC, useEffect, useState } from "react";
import {
Typography,
@@ -16,6 +17,7 @@ import {
Card,
CardContent,
} from "@mui/material";
import EventNoteIcon from "@mui/icons-material/EventNote";
import { useNavigate } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import { getRooms } from "../apis/rooms";
@@ -24,9 +26,8 @@ import RoomList from "../components/RoomList";
import BookingList from "../components/BookingList";
import type { ConferenceRoom } from "../schemas";
import type { Booking } from "../schemas";
import EventNoteIcon from "@mui/icons-material/EventNote";
// import "./LandingPage.css";
import { logger } from "../utils/logger";
// import "./LandingPage.css";
/**
* LandingPage component

View File

@@ -0,0 +1,226 @@
/*
* CalendarView.css
* Styles for the calendar view component, including event colors and non-business hours.
*
* Author: Cliff Hill
* Last updated: 2025-09-05
*/
/* Non-business hours styling for FullCalendar */
.fc-timegrid-col-bg .fc-non-business,
.fc-non-business {
background: #888 !important;
opacity: 0.5 !important;
}
/* Room color classes for calendar events */
.room-color-0 {
background: #1976d2 !important;
color: #fff !important;
}
.room-color-1 {
background: #388e3c !important;
color: #fff !important;
}
.room-color-2 {
background: #fbc02d !important;
color: #fff !important;
}
.room-color-3 {
background: #d32f2f !important;
color: #fff !important;
}
.room-color-4 {
background: #7b1fa2 !important;
color: #fff !important;
}
.room-color-5 {
background: #0288d1 !important;
color: #fff !important;
}
.room-color-6 {
background: #c2185b !important;
color: #fff !important;
}
.room-color-7 {
background: #ffa000 !important;
color: #fff !important;
}
/* Truncate and ellipsis for event content and titles */
.fc-event-title-ellipsis,
.fc-event .fc-event-main > div,
.fc-event-title,
.fc-event-main,
.fc-event .fc-event-main-frame,
.fc-event .fc-event-title,
.fc-event .fc-event-title-container,
.fc-event .fc-event-time,
.fc-event .fc-event-title,
.fc-event .fc-event-title-container,
.fc-event .fc-event-main {
white-space: nowrap !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
max-width: 100% !important;
display: block !important;
width: 100%;
min-width: 0;
}
/* Weekend all-day and time slots: unified non-business color, lighter border */
.fc .fc-daygrid-day.fc-day-sat .fc-daygrid-day-frame,
.fc .fc-daygrid-day.fc-day-sun .fc-daygrid-day-frame,
.fc .fc-timegrid-col.fc-day-sat,
.fc .fc-timegrid-col.fc-day-sun {
background: #888 !important; /* unified non-business color */
border-color: #bbb !important;
}
.fc .fc-daygrid-day.fc-day-sat .fc-daygrid-day-number,
.fc .fc-daygrid-day.fc-day-sun .fc-daygrid-day-number {
color: #e0e0e0 !important;
font-weight: 500 !important;
opacity: 0.7 !important;
}
/* Weekday non-business hours: same as weekend background */
.fc .fc-non-business {
background: #888 !important;
opacity: 0.5 !important;
}
/* Workday all-day and time slots: match all-day workday background */
.fc .fc-daygrid-day .fc-daygrid-day-frame,
.fc .fc-timegrid-col {
background: #c0c0c0 !important;
}
/* Lighter border for all-day row on weekends */
.fc .fc-daygrid-day.fc-day-sat,
.fc .fc-daygrid-day.fc-day-sun {
border-color: #bbb !important;
}
/* Out-of-month days: distinct but not too dark */
.fc .fc-daygrid-day.fc-day-other .fc-daygrid-day-frame {
background: #aaa !important;
opacity: 1 !important;
}
/* Calendar cell backgrounds use CSS variables */
:root {
--fc-page-bg-color: #a0a0a0;
--fc-neutral-bg-color: #e3f2fd;
--fc-today-bg-color: #e3f2fd;
--fc-event-bg-color: #1976d2;
--fc-border-color: #707070;
}
.calendarContainer {
padding: 2rem;
background: #f8fafc !important;
border-radius: 16px !important;
box-shadow: 0 4px 24px rgba(30, 64, 175, 0.08) !important;
/* Responsive container, no fixed height */
}
.calendar-scroll-area {
flex: 1 1 auto;
overflow-y: auto;
min-height: 0;
}
.fc {
font-family: "Inter", "Roboto", Arial, sans-serif !important;
box-shadow: none !important;
}
.fc .fc-toolbar {
background: #1976d2 !important;
color: #fff !important;
border-radius: 12px 12px 0 0 !important;
padding: 0.5rem 1rem !important;
}
.fc .fc-toolbar-title {
font-size: 1.5rem !important;
font-weight: 600 !important;
}
.fc .fc-button {
background: #1976d2 !important;
color: #fff !important;
border: none !important;
border-radius: 6px !important;
padding: 0.3rem 0.8rem !important;
margin: 0 0.2rem !important;
font-weight: 500 !important;
transition: background 0.2s !important;
}
.fc .fc-button:hover,
.fc .fc-button:focus {
background: #1565c0 !important;
}
.fc .fc-daygrid-day {
box-shadow: 0 1px 4px rgba(30, 64, 175, 0.08) !important;
transition: box-shadow 0.2s !important;
}
.fc .fc-daygrid-day:hover {
box-shadow: 0 4px 12px rgba(30, 64, 175, 0.16) !important;
background: #e3f2fd !important;
}
.fc .fc-daygrid-day-number {
font-weight: 600 !important;
color: #1976d2 !important;
}
.fc .fc-event {
background: #1976d2 !important;
color: #fff !important;
padding: 2px 6px !important;
font-size: 0.95rem !important;
box-shadow: 0 2px 8px rgba(30, 64, 175, 0.12) !important;
}
.fc .fc-event:hover {
background: #1565c0 !important;
}
.fc .fc-day-today {
background: #e3f2fd !important;
border-radius: 8px !important;
}
.fc .fc-daygrid-day .fc-daygrid-day-frame {
background: #c0c0c0 !important;
box-shadow: 0 1px 4px rgba(30, 64, 175, 0.08) !important;
transition: box-shadow 0.2s !important;
}
.fc .fc-daygrid-day.fc-day-today .fc-daygrid-day-frame {
background: #d0d0d0 !important;
box-shadow: 0 4px 12px rgba(30, 64, 175, 0.16) !important;
}
.fc .fc-daygrid-day.fc-day-other .fc-daygrid-day-frame {
background: #aaa !important;
opacity: 1 !important;
}
.fc .fc-daygrid-day.fc-day-other .fc-daygrid-day-number {
color: #fff !important;
opacity: 1 !important;
font-weight: 600 !important;
}
.fc .fc-daygrid-day:hover .fc-daygrid-day-frame {
background: #e3f2fd !important;
box-shadow: 0 4px 12px rgba(30, 64, 175, 0.16) !important;
}
.fc,
.fc-toolbar.fc-header-toolbar {
margin-bottom: 0px !important;
}