diff --git a/package.json b/package.json index e18c3c4..fb4a2c1 100644 --- a/package.json +++ b/package.json @@ -56,20 +56,25 @@ "next-auth": "^5.0.0-beta.25", "next-swagger-doc": "^0.4.1", "next-themes": "^0.4.6", - "react": "^19.0.0", + "react": "^19.1.0", + "react-big-calendar": "^1.18.0", + "react-datepicker": "^8.4.0", "react-day-picker": "^9.7.0", "react-dom": "^19.0.0", + "react-error-boundary": "^6.0.0", "react-hook-form": "^7.56.4", "sonner": "^2.0.5", "swagger-ui-react": "^5.24.1", "tailwind-merge": "^3.2.0", - "zod": "^3.25.60" + "zod": "^3.25.60", + "zod-validation-error": "^3.5.2" }, "devDependencies": { "@eslint/eslintrc": "3.3.1", "@tailwindcss/postcss": "4.1.10", "@types/node": "22.15.33", "@types/react": "19.1.8", + "@types/react-big-calendar": "^1", "@types/react-dom": "19.1.6", "@types/swagger-ui-react": "5", "@types/webpack-env": "1.18.8", diff --git a/src/app/(main)/home/page.tsx b/src/app/(main)/home/page.tsx index 66a97d8..1cf8a90 100644 --- a/src/app/(main)/home/page.tsx +++ b/src/app/(main)/home/page.tsx @@ -1,22 +1,17 @@ 'use client'; -import { RedirectButton } from '@/components/buttons/redirect-button'; +import Calendar from '@/components/calendar'; import { useGetApiUserMe } from '@/generated/api/user/user'; export default function Home() { - const { data, isLoading } = useGetApiUserMe(); + const { data } = useGetApiUserMe(); return ( -
-
-

- Hello{' '} - {isLoading ? 'Loading...' : data?.data.user?.name || 'Unknown User'} -

- - - -
+
+
); } diff --git a/src/app/api/user/[user]/calendar/route.ts b/src/app/api/user/[user]/calendar/route.ts index f6b6098..62142e9 100644 --- a/src/app/api/user/[user]/calendar/route.ts +++ b/src/app/api/user/[user]/calendar/route.ts @@ -136,15 +136,15 @@ export const GET = auth(async function GET(req, { params }) { start_time: 'asc', }, select: { - id: requestUserId === requestedUserId ? true : false, - reason: requestUserId === requestedUserId ? true : false, + id: true, + reason: true, start_time: true, end_time: true, - is_recurring: requestUserId === requestedUserId ? true : false, - recurrence_end_date: requestUserId === requestedUserId ? true : false, - rrule: requestUserId === requestedUserId ? true : false, - created_at: requestUserId === requestedUserId ? true : false, - updated_at: requestUserId === requestedUserId ? true : false, + is_recurring: true, + recurrence_end_date: true, + rrule: true, + created_at: true, + updated_at: true, }, }, }, @@ -167,6 +167,7 @@ export const GET = auth(async function GET(req, { params }) { calendar.push({ ...event.meeting, type: 'event' }); } else { calendar.push({ + id: event.meeting.id, start_time: event.meeting.start_time, end_time: event.meeting.end_time, type: 'blocked_private', @@ -182,6 +183,7 @@ export const GET = auth(async function GET(req, { params }) { calendar.push({ ...event, type: 'event' }); } else { calendar.push({ + id: event.id, start_time: event.start_time, end_time: event.end_time, type: 'blocked_private', @@ -190,23 +192,35 @@ export const GET = auth(async function GET(req, { params }) { } for (const slot of requestedUser.blockedSlots) { - calendar.push({ - start_time: slot.start_time, - end_time: slot.end_time, - id: slot.id, - reason: slot.reason, - is_recurring: slot.is_recurring, - recurrence_end_date: slot.recurrence_end_date, - rrule: slot.rrule, - created_at: slot.created_at, - updated_at: slot.updated_at, - type: - requestUserId === requestedUserId ? 'blocked_owned' : 'blocked_private', - }); + if (requestUserId === requestedUserId) { + calendar.push({ + start_time: slot.start_time, + end_time: slot.end_time, + id: slot.id, + reason: slot.reason, + is_recurring: slot.is_recurring, + recurrence_end_date: slot.recurrence_end_date, + rrule: slot.rrule, + created_at: slot.created_at, + updated_at: slot.updated_at, + type: 'blocked_owned', + }); + } else { + calendar.push({ + start_time: slot.start_time, + end_time: slot.end_time, + id: slot.id, + type: 'blocked_private', + }); + } } return returnZodTypeCheckedResponse(UserCalendarResponseSchema, { success: true, - calendar, + calendar: calendar.filter( + (event, index, self) => + self.findIndex((e) => e.id === event.id && e.type === event.type) === + index, + ), }); }); diff --git a/src/app/api/user/[user]/calendar/validation.ts b/src/app/api/user/[user]/calendar/validation.ts index a0d179f..1572793 100644 --- a/src/app/api/user/[user]/calendar/validation.ts +++ b/src/app/api/user/[user]/calendar/validation.ts @@ -13,23 +13,28 @@ export const BlockedSlotSchema = zod start_time: eventStartTimeSchema, end_time: eventEndTimeSchema, type: zod.literal('blocked_private'), + id: zod.string(), }) .openapi('BlockedSlotSchema', { description: 'Blocked time slot in the user calendar', }); -export const OwnedBlockedSlotSchema = BlockedSlotSchema.extend({ - id: zod.string(), - reason: zod.string().nullish(), - is_recurring: zod.boolean().default(false), - recurrence_end_date: zod.date().nullish(), - rrule: zod.string().nullish(), - created_at: zod.date().nullish(), - updated_at: zod.date().nullish(), - type: zod.literal('blocked_owned'), -}).openapi('OwnedBlockedSlotSchema', { - description: 'Blocked slot owned by the user', -}); +export const OwnedBlockedSlotSchema = zod + .object({ + start_time: eventStartTimeSchema, + end_time: eventEndTimeSchema, + id: zod.string(), + reason: zod.string().nullish(), + is_recurring: zod.boolean().default(false), + recurrence_end_date: zod.date().nullish(), + rrule: zod.string().nullish(), + created_at: zod.date().nullish(), + updated_at: zod.date().nullish(), + type: zod.literal('blocked_owned'), + }) + .openapi('OwnedBlockedSlotSchema', { + description: 'Blocked slot owned by the user', + }); export const VisibleSlotSchema = EventSchema.omit({ organizer: true, diff --git a/src/components/calendar.tsx b/src/components/calendar.tsx new file mode 100644 index 0000000..a8d6005 --- /dev/null +++ b/src/components/calendar.tsx @@ -0,0 +1,256 @@ +'use client'; + +import { Calendar as RBCalendar, momentLocalizer } from 'react-big-calendar'; +import withDragAndDrop from 'react-big-calendar/lib/addons/dragAndDrop'; +import moment from 'moment'; +import '@/components/react-big-calendar.css'; +import 'react-big-calendar/lib/addons/dragAndDrop/styles.css'; +import CustomToolbar from '@/components/custom-toolbar'; +import React from 'react'; +import { useGetApiUserUserCalendar } from '@/generated/api/user/user'; +import { useRouter } from 'next/navigation'; +import { usePatchApiEventEventID } from '@/generated/api/event/event'; +import { useSession } from 'next-auth/react'; +import { UserCalendarSchemaItem } from '@/generated/api/meetup.schemas'; +import { QueryErrorResetBoundary } from '@tanstack/react-query'; +import { ErrorBoundary } from 'react-error-boundary'; +import { Button } from '@/components/ui/button'; +import { fromZodIssue } from 'zod-validation-error/v4'; +import type { $ZodIssue } from 'zod/v4/core'; + +moment.updateLocale('en', { + week: { + dow: 1, + doy: 4, + }, +}); + +const DaDRBCalendar = withDragAndDrop< + { + id: string; + start: Date; + end: Date; + type: UserCalendarSchemaItem['type']; + }, + { + id: string; + title: string; + type: UserCalendarSchemaItem['type']; + } +>(RBCalendar); + +const localizer = momentLocalizer(moment); + +export default function Calendar({ + userId, + height, +}: { + userId?: string; + height: string; +}) { + return ( + + {({ reset }) => ( + ( +
+ There was an error! +

+ {typeof error === 'string' + ? error + : error.errors + .map((e: $ZodIssue) => fromZodIssue(e).toString()) + .join(', ')} +

+ +
+ )} + > + {userId ? ( + + ) : ( + + )} +
+ )} +
+ ); +} + +function CalendarWithUserEvents({ + userId, + height, +}: { + userId: string; + height: string; +}) { + const sesstion = useSession(); + const [currentView, setCurrentView] = React.useState< + 'month' | 'week' | 'day' | 'agenda' | 'work_week' + >('week'); + const [currentDate, setCurrentDate] = React.useState(new Date()); + const router = useRouter(); + + const { data, refetch, error, isError } = useGetApiUserUserCalendar( + userId, + { + start: moment(currentDate) + .startOf( + currentView === 'agenda' + ? 'month' + : currentView === 'work_week' + ? 'week' + : currentView, + ) + .toISOString(), + end: moment(currentDate) + .endOf( + currentView === 'agenda' + ? 'month' + : currentView === 'work_week' + ? 'week' + : currentView, + ) + .toISOString(), + }, + { + query: { + refetchOnWindowFocus: true, + refetchOnReconnect: true, + refetchOnMount: true, + }, + }, + ); + + if (isError) { + throw error.response?.data || 'Failed to fetch calendar data'; + } + + const { mutate: patchEvent } = usePatchApiEventEventID({ + mutation: { + throwOnError(error) { + throw error.response?.data || 'Failed to update event'; + }, + }, + }); + + return ( + { + setCurrentDate(date); + }} + events={ + data?.data.calendar.map((event) => ({ + id: event.id, + title: event.type === 'event' ? event.title : 'Blocker', + start: new Date(event.start_time), + end: new Date(event.end_time), + type: event.type, + })) ?? [] + } + onSelectEvent={(event) => { + router.push(`/events/${event.id}`); + }} + onSelectSlot={(slotInfo) => { + router.push( + `/events/new?start=${slotInfo.start.toISOString()}&end=${slotInfo.end.toISOString()}`, + ); + }} + resourceIdAccessor={(event) => event.id} + resourceTitleAccessor={(event) => event.title} + startAccessor={(event) => event.start} + endAccessor={(event) => event.end} + selectable={sesstion.data?.user?.id === userId} + onEventDrop={(event) => { + const { start, end, event: droppedEvent } = event; + if (droppedEvent.type === 'blocked_private') return; + const startISO = new Date(start).toISOString(); + const endISO = new Date(end).toISOString(); + patchEvent( + { + eventID: droppedEvent.id, + data: { + start_time: startISO, + end_time: endISO, + }, + }, + { + onSuccess: () => { + refetch(); + }, + onError: (error) => { + console.error('Error updating event:', error); + }, + }, + ); + }} + onEventResize={(event) => { + const { start, end, event: resizedEvent } = event; + if (resizedEvent.type === 'blocked_private') return; + const startISO = new Date(start).toISOString(); + const endISO = new Date(end).toISOString(); + if (startISO === endISO) { + console.warn('Start and end times are the same, skipping resize.'); + return; + } + patchEvent( + { + eventID: resizedEvent.id, + data: { + start_time: startISO, + end_time: endISO, + }, + }, + { + onSuccess: () => { + refetch(); + }, + onError: (error) => { + console.error('Error resizing event:', error); + }, + }, + ); + }} + /> + ); +} + +function CalendarWithoutUserEvents({ height }: { height: string }) { + const [currentView, setCurrentView] = React.useState< + 'month' | 'week' | 'day' | 'agenda' | 'work_week' + >('week'); + const [currentDate, setCurrentDate] = React.useState(new Date()); + + return ( + { + setCurrentDate(date); + }} + /> + ); +} diff --git a/src/components/custom-toolbar.css b/src/components/custom-toolbar.css new file mode 100644 index 0000000..3fba69f --- /dev/null +++ b/src/components/custom-toolbar.css @@ -0,0 +1,114 @@ +/* Container der Toolbar */ +.custom-toolbar { + display: flex; + flex-direction: column; + gap: 12px; + padding: calc(var(--spacing) * 2); + padding-left: calc(50px + var(--spacing)); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; +} + +/* Anzeige des aktuellen Datums (Monat und Jahr) */ +.custom-toolbar .current-date { + font-weight: bold; + font-size: 12px; + text-align: center; + color: #ffffff; + background-color: #717171; + height: 37px; + border-radius: 11px; +} + +/* Navigationsbereich (Today, Prev, Next) */ +.custom-toolbar .navigation-controls { + display: flex; + gap: 8px; + justify-content: center; +} + +.custom-toolbar .navigation-controls button { + padding: 8px 12px; + color: #ffffff; + border: none; + border-radius: 11px; + font-size: 12px; + cursor: pointer; + transition: background-color 0.2s; +} + +.custom-toolbar .navigation-controls button:hover { + background-color: #1976d2; +} + +.custom-toolbar .navigation-controls button:active { + background-color: #1565c0; +} + +/* Dropdown-Bereich für Woche und Jahr */ +.custom-toolbar .dropdowns { + display: flex; + gap: 8px; + justify-content: center; + height: 30px; + font-size: 10px; + margin-top: 3.5px; + border-radius: 11px; +} + +.custom-toolbar .dropdowns select { + padding: 8px 12px; + border-radius: 11px; + font-size: 10px; + background-color: #555555; + color: #ffffff; + cursor: pointer; + transition: border-color 0.2s; +} + +.custom-toolbar .dropdowns select:hover { + border-color: #999; +} + +.right-section, +.view-switcher { + background-color: #717171; + height: 48px; + border-radius: 11px; + justify-items: center; + align-items: center; +} + +.custom-toolbar .navigation-controls .handleWeek button { + background-color: #717171; + height: 30px; + width: 30px; + margin-bottom: 3.5px; +} + +.view-change, +.right-section { + background-color: #717171; + height: 48px; + padding: 0 8px; + border-radius: 11px; + justify-items: center; +} + +.right-section .datepicker-box { + color: #000000; + background-color: #c6c6c6; + height: 36px; + border-radius: 11px; + font-size: 12px; + align-self: center; +} + +.datepicker { + text-align: center; + height: 30px; +} + +.datepicker-box { + z-index: 5; +} diff --git a/src/components/custom-toolbar.tsx b/src/components/custom-toolbar.tsx new file mode 100644 index 0000000..36c8fff --- /dev/null +++ b/src/components/custom-toolbar.tsx @@ -0,0 +1,260 @@ +import React, { useState, useEffect } from 'react'; +import './custom-toolbar.css'; +import { Button } from '@/components/ui/button'; +import DatePicker from 'react-datepicker'; +import 'react-datepicker/dist/react-datepicker.css'; +import { NavigateAction } from 'react-big-calendar'; + +interface CustomToolbarProps { + //Aktuell angezeigtes Datum + date: Date; + //Aktuelle Ansicht + view: 'month' | 'week' | 'day' | 'agenda' | 'work_week'; + + onNavigate: (action: NavigateAction, newDate?: Date) => void; + //Ansichtwechsel + onView: (newView: 'month' | 'week' | 'day' | 'agenda' | 'work_week') => void; +} + +const CustomToolbar: React.FC = ({ + date, + view, + onNavigate, + onView, +}) => { + //ISO-Wochennummer eines Datums ermitteln + const getISOWeek = (date: Date): number => { + const tmp = new Date(date.getTime()); + //Datum so verschieben, dass der nächste Donnerstag erreicht wird (ISO: Woche beginnt am Montag) + tmp.setDate(tmp.getDate() + 4 - (tmp.getDay() || 7)); + const yearStart = new Date(tmp.getFullYear(), 0, 1); + const weekNo = Math.ceil( + ((tmp.getTime() - yearStart.getTime()) / 86400000 + 1) / 7, + ); + return weekNo; + }; + + //ISO-Wochenjahr eines Datums ermitteln + const getISOWeekYear = (date: Date): number => { + const tmp = new Date(date.getTime()); + tmp.setDate(tmp.getDate() + 4 - (tmp.getDay() || 7)); + return tmp.getFullYear(); + }; + + //Ermittlung der Anzahl der Wochen im Jahr + const getISOWeeksInYear = (year: number): number => { + const d = new Date(year, 11, 31); + const week = getISOWeek(d); + return week === 1 ? getISOWeek(new Date(year, 11, 24)) : week; + }; + + const getDateOfISOWeek = (week: number, year: number): Date => { + const jan1 = new Date(year, 0, 1); + const dayOfWeek = jan1.getDay(); + const isoDayOfWeek = dayOfWeek === 0 ? 7 : dayOfWeek; + let firstMonday: Date; + if (isoDayOfWeek <= 4) { + //1. Januar gehört zur ersten ISO-Woche (Montag dieser Woche bestimmen) + firstMonday = new Date(year, 0, 1 - isoDayOfWeek + 1); + } else { + //Ansonsten liegt der erste Montag in der darauffolgenden Woche + firstMonday = new Date(year, 0, 1 + (8 - isoDayOfWeek)); + } + firstMonday.setDate(firstMonday.getDate() + (week - 1) * 7); + return firstMonday; + }; + + //Lokaler State für Woche und ISO-Wochenjahr (statt des reinen Kalenderjahrs) + const [selectedWeek, setSelectedWeek] = useState(getISOWeek(date)); + const [selectedYear, setSelectedYear] = useState( + getISOWeekYear(date), + ); + + //Auswahl aktualisieren, wenn sich die Prop "date" ändert + useEffect(() => { + setSelectedWeek(getISOWeek(date)); + setSelectedYear(getISOWeekYear(date)); + }, [date]); + + //Start (Montag) und Ende (Sonntag) der aktuell angezeigten Woche berechnen + const weekStartDate = getDateOfISOWeek(selectedWeek, selectedYear); + const weekEndDate = new Date(weekStartDate); + weekEndDate.setDate(weekStartDate.getDate() + 6); + + //Ansichtwechsel + const handleViewChange = (newView: 'month' | 'week' | 'day' | 'agenda') => { + onView(newView); + }; + + //Today-Button aktualisiert das Datum im DatePicker auf das heutige + const handleToday = () => { + const today = new Date(); + setSelectedDate(today); + setSelectedWeek(getISOWeek(today)); + setSelectedYear(getISOWeekYear(today)); + onNavigate('TODAY', today); + }; + + //Pfeiltaste nach Vorne + const handleNext = () => { + let newDate: Date; + if (view === 'day' || view === 'agenda') { + newDate = new Date(date); + newDate.setDate(newDate.getDate() + 1); + } else if (view === 'week') { + let newWeek = selectedWeek + 1; + let newYear = selectedYear; + if (newWeek > getISOWeeksInYear(selectedYear)) { + newYear = selectedYear + 1; + newWeek = 1; + } + setSelectedWeek(newWeek); + setSelectedYear(newYear); + newDate = getDateOfISOWeek(newWeek, newYear); + } else if (view === 'month') { + newDate = new Date(date.getFullYear(), date.getMonth() + 1, 1); + } else { + newDate = new Date(date); + } + //Datum im DatePicker aktualisieren + setSelectedDate(newDate); + onNavigate('DATE', newDate); + }; + + //Pfeiltaste nach Hinten + const handlePrev = () => { + let newDate: Date; + if (view === 'day' || view === 'agenda') { + newDate = new Date(date); + newDate.setDate(newDate.getDate() - 1); + } else if (view === 'week') { + let newWeek = selectedWeek - 1; + let newYear = selectedYear; + if (newWeek < 1) { + newYear = selectedYear - 1; + newWeek = getISOWeeksInYear(newYear); + } + setSelectedWeek(newWeek); + setSelectedYear(newYear); + newDate = getDateOfISOWeek(newWeek, newYear); + } else if (view === 'month') { + newDate = new Date(date.getFullYear(), date.getMonth() - 1, 1); + } else { + newDate = new Date(date); + } + //Datum im DatePicker aktualisieren + setSelectedDate(newDate); + onNavigate('DATE', newDate); + }; + + const [selectedDate, setSelectedDate] = useState(new Date()); + + const handleDateChange = (date: Date | null) => { + setSelectedDate(date); + if (date) { + if (view === 'week') { + const newWeek = getISOWeek(date); + const newYear = getISOWeekYear(date); + setSelectedWeek(newWeek); + setSelectedYear(newYear); + const newDate = getDateOfISOWeek(newWeek, newYear); + onNavigate('DATE', newDate); + } else if (view === 'day') { + onNavigate('DATE', date); + } else if (view === 'month') { + const newDate = new Date(date.getFullYear(), date.getMonth(), 1); + onNavigate('DATE', newDate); + } else if (view === 'agenda') { + onNavigate('DATE', date); + } + } + }; + + return ( +
+
+
+ + + + +
+
+ +
+
+
+ + +
+
+ +
+
+ +
+ +
+
+
+ ); +}; + +export default CustomToolbar; diff --git a/src/components/misc/header.tsx b/src/components/misc/header.tsx index ed53953..dd9e36d 100644 --- a/src/components/misc/header.tsx +++ b/src/components/misc/header.tsx @@ -45,7 +45,7 @@ export default function Header({ -
{children}
+
{children}
); } diff --git a/src/components/react-big-calendar.css b/src/components/react-big-calendar.css new file mode 100644 index 0000000..675898c --- /dev/null +++ b/src/components/react-big-calendar.css @@ -0,0 +1,930 @@ +@charset "UTF-8"; +.rbc-btn { + color: inherit; + font: inherit; + margin: 0; +} + +button.rbc-btn { + overflow: visible; + text-transform: none; + -webkit-appearance: button; + -moz-appearance: button; + appearance: button; + cursor: pointer; +} + +button[disabled].rbc-btn { + cursor: not-allowed; +} + +button.rbc-input::-moz-focus-inner { + border: 0; + padding: 0; +} + +.rbc-calendar { + -webkit-box-sizing: border-box; + box-sizing: border-box; + height: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; +} + +.rbc-m-b-negative-3 { + margin-bottom: -3px; +} + +.rbc-h-full { + height: 100%; +} + +.rbc-calendar *, +.rbc-calendar *:before, +.rbc-calendar *:after { + -webkit-box-sizing: inherit; + box-sizing: inherit; +} + +.rbc-abs-full, +.rbc-row-bg { + overflow: hidden; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.rbc-ellipsis, +.rbc-show-more, +.rbc-row-segment .rbc-event-content, +.rbc-event-label { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.rbc-rtl { + direction: rtl; +} + +.rbc-off-range { + color: #999999; +} + +.rbc-off-range-bg { + background: #e6e6e6; +} + +.rbc-header { + overflow: hidden; + -webkit-box-flex: 1; + -ms-flex: 1 0 0%; + flex: 1 0 0%; + text-overflow: ellipsis; + white-space: nowrap; + padding: 0 3px; + text-align: center; + vertical-align: middle; + font-weight: bold; + font-size: 90%; + min-height: 0; + border-bottom: 1px solid #ddd; +} +.rbc-header + .rbc-header { + border-left: 1px solid #c6c6c6; /*#ddd*/ +} +.rbc-rtl .rbc-header + .rbc-header { + border-left-width: 0; + border-right: 1px solid #ddd; +} +.rbc-header > a, +.rbc-header > a:active, +.rbc-header > a:visited { + color: inherit; + text-decoration: none; +} + +.rbc-button-link { + color: inherit; + background: none; + margin: 0; + padding: 0; + border: none; + cursor: pointer; + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.rbc-row-content { + position: relative; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-user-select: none; + z-index: 4; +} + +.rbc-row-content-scrollable { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + height: 100%; +} +.rbc-row-content-scrollable .rbc-row-content-scroll-container { + height: 100%; + overflow-y: scroll; + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + /* Hide scrollbar for Chrome, Safari and Opera */ +} +.rbc-row-content-scrollable + .rbc-row-content-scroll-container::-webkit-scrollbar { + display: none; +} + +.rbc-today { + background-color: #5770ff; /*#eaf6ff*/ +} +/*Own changes 10*/ +.rbc-allday-cell .rbc-row-bg .rbc-day-bg.rbc-today { + background-color: transparent !important; + /*border: none !important;*/ +} +/*Own changes 10*/ + +/*Own changes 11*/ +.rbc-time-header-cell .rbc-header:first-child.rbc-today { + border-top-left-radius: 11px !important; +} + +.rbc-time-header-cell .rbc-header:last-child.rbc-today { + border-top-right-radius: 11px !important; +} +/*Own changes 11*/ + +.rbc-toolbar { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-bottom: 10px; + font-size: 16px; +} +.rbc-toolbar .rbc-toolbar-label { + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + padding: 0 10px; + text-align: center; + + /*Own changes 01*/ + background-color: #717171; + color: #ffffff; + /*Own changes 01*/ +} +.rbc-toolbar button { + color: #373a3c; + display: inline-block; + margin: 0; + text-align: center; + vertical-align: middle; + background: none; + background-image: none; + border: 1px solid #ccc; + padding: 0.375rem 1rem; + border-radius: 4px; + line-height: normal; + white-space: nowrap; +} +.rbc-toolbar button:active, +.rbc-toolbar button.rbc-active { + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + background-color: #e6e6e6; + border-color: #adadad; +} +.rbc-toolbar button:active:hover, +.rbc-toolbar button:active:focus, +.rbc-toolbar button.rbc-active:hover, +.rbc-toolbar button.rbc-active:focus { + color: #373a3c; + background-color: #d4d4d4; + border-color: #8c8c8c; +} +.rbc-toolbar button:focus { + color: #373a3c; + background-color: #e6e6e6; + border-color: #adadad; +} +.rbc-toolbar button:hover { + color: #373a3c; + cursor: pointer; + background-color: #e6e6e6; + border-color: #adadad; +} + +.rbc-btn-group { + display: inline-block; + white-space: nowrap; +} +.rbc-btn-group > button:first-child:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + + /*Own changes 02*/ + background-color: #c6c6c6; + color: #000000; + /*Own changes 02*/ +} +.rbc-btn-group > button:last-child:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + + /*Own changes 03*/ + background-color: #c6c6c6; + color: #000000; + /*Own changes 03*/ +} +.rbc-rtl .rbc-btn-group > button:first-child:not(:last-child) { + border-radius: 4px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.rbc-rtl .rbc-btn-group > button:last-child:not(:first-child) { + border-radius: 4px; + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.rbc-btn-group > button:not(:first-child):not(:last-child) { + border-radius: 0; + + /*Own changes 04*/ + background-color: #c6c6c6; + color: #000000; + /*Own changes 04*/ +} +.rbc-btn-group button + button { + margin-left: -1px; +} +.rbc-rtl .rbc-btn-group button + button { + margin-left: 0; + margin-right: -1px; +} +.rbc-btn-group + .rbc-btn-group, +.rbc-btn-group + button { + margin-left: 10px; +} + +@media (max-width: 767px) { + .rbc-toolbar { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + } +} +.rbc-event, +.rbc-day-slot .rbc-background-event { + border: none; + -webkit-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: none; + box-shadow: none; + margin: 0; + padding: 2px 5px; + background-color: #3174ad; + border-radius: 5px; + color: #fff; + cursor: pointer; + width: 100%; + text-align: left; +} +.rbc-slot-selecting .rbc-event, +.rbc-slot-selecting .rbc-day-slot .rbc-background-event, +.rbc-day-slot .rbc-slot-selecting .rbc-background-event { + cursor: inherit; + pointer-events: none; +} +.rbc-event.rbc-selected, +.rbc-day-slot .rbc-selected.rbc-background-event { + background-color: #265985; +} +.rbc-event:focus, +.rbc-day-slot .rbc-background-event:focus { + outline: 5px auto #3b99fc; +} + +.rbc-event-label { + font-size: 80%; +} + +.rbc-event-overlaps { + -webkit-box-shadow: -1px 1px 5px 0px rgba(51, 51, 51, 0.5); + box-shadow: -1px 1px 5px 0px rgba(51, 51, 51, 0.5); +} + +.rbc-event-continues-prior { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.rbc-event-continues-after { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.rbc-event-continues-earlier { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.rbc-event-continues-later { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.rbc-row { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; +} + +.rbc-row-segment { + padding: 0 1px 1px 1px; +} +.rbc-selected-cell { + background-color: rgba(0, 0, 0, 0.1); +} + +.rbc-show-more { + background-color: rgba(255, 255, 255, 0.3); + z-index: 4; + font-weight: bold; + font-size: 85%; + height: auto; + line-height: normal; + color: #3174ad; +} +.rbc-show-more:hover, +.rbc-show-more:focus { + color: #265985; +} + +.rbc-month-view { + position: relative; + border: 1px solid #ddd; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-flex: 1; + -ms-flex: 1 0 0px; + flex: 1 0 0; + width: 100%; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-user-select: none; + height: 100%; +} + +.rbc-month-header { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; +} + +.rbc-month-row { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + position: relative; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-flex: 1; + -ms-flex: 1 0 0px; + flex: 1 0 0; + -ms-flex-preferred-size: 0px; + flex-basis: 0px; + overflow: hidden; + height: 100%; +} +.rbc-month-row + .rbc-month-row { + border-top: 1px solid #ddd; +} + +.rbc-date-cell { + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0; + min-width: 0; + padding-right: 5px; + text-align: right; +} +.rbc-date-cell.rbc-now { + font-weight: bold; +} +.rbc-date-cell > a, +.rbc-date-cell > a:active, +.rbc-date-cell > a:visited { + color: inherit; + text-decoration: none; +} + +.rbc-row-bg { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-flex: 1; + -ms-flex: 1 0 0px; + flex: 1 0 0; + overflow: hidden; + right: 1px; +} + +.rbc-day-bg { + -webkit-box-flex: 1; + -ms-flex: 1 0 0%; + flex: 1 0 0%; +} +.rbc-day-bg + .rbc-day-bg { + border-left: 1px solid #ddd; +} +.rbc-rtl .rbc-day-bg + .rbc-day-bg { + border-left-width: 0; + border-right: 1px solid #ddd; +} + +.rbc-overlay { + position: absolute; + z-index: 5; + border: 1px solid #e5e5e5; + background-color: #fff; + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.25); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.25); + padding: 10px; +} +.rbc-overlay > * + * { + margin-top: 1px; +} + +.rbc-overlay-header { + border-bottom: 1px solid #e5e5e5; + margin: -10px -10px 5px -10px; + padding: 2px 10px; +} + +.rbc-agenda-view { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-flex: 1; + -ms-flex: 1 0 0px; + flex: 1 0 0; + overflow: auto; +} +.rbc-agenda-view table.rbc-agenda-table { + width: 100%; + border: 1px solid #ddd; + border-spacing: 0; + border-collapse: collapse; +} +.rbc-agenda-view table.rbc-agenda-table tbody > tr > td { + padding: 5px 10px; + vertical-align: top; +} +.rbc-agenda-view table.rbc-agenda-table .rbc-agenda-time-cell { + padding-left: 15px; + padding-right: 15px; + text-transform: lowercase; +} +.rbc-agenda-view table.rbc-agenda-table tbody > tr > td + td, +.rbc-agenda-view table.rbc-agenda-table tbody > tr > td.rbc-agenda-time-cell { + border-left: 1px solid #ddd; +} +.rbc-rtl .rbc-agenda-view table.rbc-agenda-table tbody > tr > td + td { + border-left-width: 0; + border-right: 1px solid #ddd; +} +.rbc-agenda-view table.rbc-agenda-table tbody > tr + tr { + border-top: 1px solid #ddd; +} +.rbc-agenda-view table.rbc-agenda-table thead > tr > th { + padding: 3px 5px; + text-align: left; + border-bottom: 1px solid #ddd; +} +.rbc-rtl .rbc-agenda-view table.rbc-agenda-table thead > tr > th { + text-align: right; +} + +.rbc-agenda-time-cell { + text-transform: lowercase; +} +.rbc-agenda-time-cell .rbc-continues-after:after { + content: ' »'; +} +.rbc-agenda-time-cell .rbc-continues-prior:before { + content: '« '; +} + +.rbc-agenda-date-cell, +.rbc-agenda-time-cell { + white-space: nowrap; +} + +.rbc-agenda-event-cell { + width: 100%; +} + +.rbc-time-column { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + min-height: 100%; + + /*Own changes 06*/ + background-color: #383838; + /*Own changes 06*/ +} +.rbc-time-column .rbc-timeslot-group { + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; +} + +.rbc-timeslot-group { + border-bottom: 1px solid #8d8d8d; /*#ddd*/ + min-height: 40px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column nowrap; + flex-flow: column nowrap; +} + +.rbc-time-gutter, +.rbc-header-gutter { + -webkit-box-flex: 0; + -ms-flex: none; + flex: none; + + /*Own changes 07*/ + background-color: #8d8d8d; + /*Own changes 07*/ +} + +.rbc-label { + padding: 0 5px; +} + +.rbc-day-slot { + position: relative; +} +.rbc-day-slot .rbc-events-container { + bottom: 0; + left: 0; + position: absolute; + right: 0; + margin-right: 10px; + top: 0; +} +.rbc-day-slot .rbc-events-container.rbc-rtl { + left: 10px; + right: 0; +} +.rbc-day-slot .rbc-event, +.rbc-day-slot .rbc-background-event { + border: 1px solid #265985; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + max-height: 100%; + min-height: 20px; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-flow: column wrap; + flex-flow: column wrap; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + overflow: hidden; + position: absolute; +} +.rbc-day-slot .rbc-background-event { + opacity: 0.75; +} +.rbc-day-slot .rbc-event-label { + -webkit-box-flex: 0; + -ms-flex: none; + flex: none; + padding-right: 5px; + width: auto; +} +.rbc-day-slot .rbc-event-content { + width: 100%; + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0; + word-wrap: break-word; + line-height: 1; + height: 100%; + min-height: 1em; +} +.rbc-day-slot .rbc-time-slot { + border-top: 1px solid #383838; /*#f7f7f7*/ +} + +.rbc-time-view-resources .rbc-time-gutter, +.rbc-time-view-resources .rbc-time-header-gutter { + position: sticky; + left: 0; + background-color: white; + border-right: 1px solid #ddd; + z-index: 10; + margin-right: -1px; +} +.rbc-time-view-resources .rbc-time-header { + overflow: hidden; +} +.rbc-time-view-resources .rbc-time-header-content { + min-width: auto; + -webkit-box-flex: 1; + -ms-flex: 1 0 0px; + flex: 1 0 0; + -ms-flex-preferred-size: 0px; + flex-basis: 0px; +} +.rbc-time-view-resources .rbc-time-header-cell-single-day { + display: none; +} +.rbc-time-view-resources .rbc-day-slot { + min-width: 140px; +} +.rbc-time-view-resources .rbc-header, +.rbc-time-view-resources .rbc-day-bg { + width: 140px; + -webkit-box-flex: 1; + -ms-flex: 1 1 0px; + flex: 1 1 0; + -ms-flex-preferred-size: 0 px; + flex-basis: 0 px; +} + +.rbc-time-header-content + .rbc-time-header-content { + margin-left: -1px; +} + +.rbc-time-slot { + -webkit-box-flex: 1; + -ms-flex: 1 0 0px; + flex: 1 0 0; +} +.rbc-time-slot.rbc-now { + font-weight: bold; +} + +.rbc-day-header { + text-align: center; +} + +.rbc-slot-selection { + z-index: 10; + position: absolute; + background-color: rgba(0, 0, 0, 0.5); + color: white; + font-size: 75%; + width: 100%; + padding: 3px; +} + +.rbc-slot-selecting { + cursor: move; +} + +.rbc-time-view { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; + width: 100%; + min-height: 0; +} +.rbc-time-view .rbc-time-gutter { + white-space: nowrap; + text-align: right; +} +.rbc-time-view .rbc-allday-cell { + -webkit-box-sizing: content-box; + box-sizing: content-box; + width: 100%; + height: 100%; + position: relative; + + /*Own changes 05*/ + background-color: #555555; + /*Own changes 05*/ +} +.rbc-time-view .rbc-allday-cell + .rbc-allday-cell { + border-left: 1px solid #ddd; +} +.rbc-time-view .rbc-allday-events { + position: relative; + z-index: 4; +} +.rbc-time-view .rbc-row { + -webkit-box-sizing: border-box; + box-sizing: border-box; + min-height: 20px; +} + +.rbc-time-header { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; +} +.rbc-rtl .rbc-time-header.rbc-overflowing { + border-right-width: 0; + border-left: 1px solid #ddd; +} +.rbc-time-header > .rbc-row:first-child { + border-bottom: 1px solid #ddd; +} +.rbc-time-header > .rbc-row.rbc-row-resource { + border-bottom: 1px solid #ddd; +} + +.rbc-time-header-cell-single-day { + display: none; +} + +.rbc-time-header-content { + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + min-width: 0; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + border-left: 1px solid #ddd; + + /*Own changes 08*/ + background-color: #c6c6c6; + color: #000000; + border-top-left-radius: 11px; + border-top-right-radius: 11px; + /*Own changes 08*/ +} +.rbc-rtl .rbc-time-header-content { + border-left-width: 0; + border-right: 1px solid #ddd; +} +.rbc-time-header-content > .rbc-row.rbc-row-resource { + border-bottom: 1px solid #ddd; + -ms-flex-negative: 0; + flex-shrink: 0; +} + +.rbc-time-content { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 1; + -ms-flex: 1 0 0%; + flex: 1 0 0%; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + width: 100%; + overflow-y: auto; + position: relative; +} + +.rbc-time-header-content { + border-bottom: 2px solid #717171; /*#ddd*/ +} + +.rbc-time-column :last-child { + border-bottom: 0; +} + +.rbc-time-content > .rbc-time-gutter { + -webkit-box-flex: 0; + -ms-flex: none; + flex: none; + + /*Own changes 09*/ + border-top-left-radius: 11px; + border-bottom-left-radius: 11px; + /*Own changes 09*/ +} +.rbc-time-content > * + * > * { + border-left: 1px solid #c6c6c6; /*#ddd*/ +} +.rbc-rtl .rbc-time-content > * + * > * { + border-left-width: 0; + border-right: 1px solid #ddd; +} +.rbc-time-content > .rbc-day-slot { + width: 100%; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-user-select: none; +} + +.rbc-current-time-indicator { + position: absolute; + z-index: 3; + left: 0; + right: 0; + height: 1px; + background-color: #74ad31; + pointer-events: none; +} + +.rbc-resource-grouping.rbc-time-header-content { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; +} +.rbc-resource-grouping .rbc-row .rbc-header { + width: 141px; +} + +/*# sourceMappingURL=react-big-calendar.css.map */ diff --git a/yarn.lock b/yarn.lock index 5ef4d93..74ff1df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -156,7 +156,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.3.1": +"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.7": version: 7.27.6 resolution: "@babel/runtime@npm:7.27.6" checksum: 10c0/89726be83f356f511dcdb74d3ea4d873a5f0cf0017d4530cb53aa27380c01ca102d573eff8b8b77815e624b1f8c24e7f0311834ad4fb632c90a770fda00bd4c8 @@ -539,7 +539,7 @@ __metadata: languageName: node linkType: hard -"@floating-ui/react-dom@npm:^2.0.0": +"@floating-ui/react-dom@npm:^2.0.0, @floating-ui/react-dom@npm:^2.1.3": version: 2.1.3 resolution: "@floating-ui/react-dom@npm:2.1.3" dependencies: @@ -551,6 +551,20 @@ __metadata: languageName: node linkType: hard +"@floating-ui/react@npm:^0.27.3": + version: 0.27.12 + resolution: "@floating-ui/react@npm:0.27.12" + dependencies: + "@floating-ui/react-dom": "npm:^2.1.3" + "@floating-ui/utils": "npm:^0.2.9" + tabbable: "npm:^6.0.0" + peerDependencies: + react: ">=17.0.0" + react-dom: ">=17.0.0" + checksum: 10c0/da453965074bd4ded8e3de97ceb2c0833df8df2ecd9eff5ae4d336413443ea5abde5c9e37b092956901b97e7b47f9138d51d4896fa82da68e77eb0090289bf64 + languageName: node + linkType: hard + "@floating-ui/utils@npm:^0.2.9": version: 0.2.9 resolution: "@floating-ui/utils@npm:0.2.9" @@ -1267,6 +1281,13 @@ __metadata: languageName: node linkType: hard +"@popperjs/core@npm:^2.11.6": + version: 2.11.8 + resolution: "@popperjs/core@npm:2.11.8" + checksum: 10c0/4681e682abc006d25eb380d0cf3efc7557043f53b6aea7a5057d0d1e7df849a00e281cd8ea79c902a35a414d7919621fc2ba293ecec05f413598e0b23d5a1e63 + languageName: node + linkType: hard + "@prisma/client@npm:^6.9.0": version: 6.10.1 resolution: "@prisma/client@npm:6.10.1" @@ -2175,6 +2196,17 @@ __metadata: languageName: node linkType: hard +"@restart/hooks@npm:^0.4.7": + version: 0.4.16 + resolution: "@restart/hooks@npm:0.4.16" + dependencies: + dequal: "npm:^2.0.3" + peerDependencies: + react: ">=16.8.0" + checksum: 10c0/b6a0f1db046cdec28737092ab5defdfb25fad498d37d218646f7f123aed02a5078b1c89ae631bda14d9ee35f7bb8c9e0f15379b1a45003144dc30cd15e8ba668 + languageName: node + linkType: hard + "@rtsao/scc@npm:^1.1.0": version: 1.1.0 resolution: "@rtsao/scc@npm:1.1.0" @@ -3282,6 +3314,13 @@ __metadata: languageName: node linkType: hard +"@types/date-arithmetic@npm:*": + version: 4.1.4 + resolution: "@types/date-arithmetic@npm:4.1.4" + checksum: 10c0/4ee68b5a422bd5f1cf08923d18a08db558e653bbdc597677e0465a330f1e807da0e79b06b72651b62b19b4b922a779470f84657cbd765805f84f33af518b408f + languageName: node + linkType: hard + "@types/es-aggregate-error@npm:^1.0.2": version: 1.0.6 resolution: "@types/es-aggregate-error@npm:1.0.6" @@ -3348,6 +3387,13 @@ __metadata: languageName: node linkType: hard +"@types/prop-types@npm:*": + version: 15.7.15 + resolution: "@types/prop-types@npm:15.7.15" + checksum: 10c0/b59aad1ad19bf1733cf524fd4e618196c6c7690f48ee70a327eb450a42aab8e8a063fbe59ca0a5701aebe2d92d582292c0fb845ea57474f6a15f6994b0e260b2 + languageName: node + linkType: hard + "@types/ramda@npm:~0.30.0": version: 0.30.2 resolution: "@types/ramda@npm:0.30.2" @@ -3357,6 +3403,17 @@ __metadata: languageName: node linkType: hard +"@types/react-big-calendar@npm:^1": + version: 1.16.2 + resolution: "@types/react-big-calendar@npm:1.16.2" + dependencies: + "@types/date-arithmetic": "npm:*" + "@types/prop-types": "npm:*" + "@types/react": "npm:*" + checksum: 10c0/a2ea4116b999cf8dac014fdc4a9f0c10fb2fd9d9886857e93649c0a601057e93e73e3d9096a756b76e227e08f68e4c979f91bf4cfd96692aea3ab7f3df0745d0 + languageName: node + linkType: hard + "@types/react-dom@npm:19.1.6": version: 19.1.6 resolution: "@types/react-dom@npm:19.1.6" @@ -3366,7 +3423,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:*, @types/react@npm:19.1.8": +"@types/react@npm:*, @types/react@npm:19.1.8, @types/react@npm:>=16.9.11": version: 19.1.8 resolution: "@types/react@npm:19.1.8" dependencies: @@ -3440,6 +3497,13 @@ __metadata: languageName: node linkType: hard +"@types/warning@npm:^3.0.0": + version: 3.0.3 + resolution: "@types/warning@npm:3.0.3" + checksum: 10c0/82c1235bd05d7f6940f80012404844e225d589ad338aa4585b231a2c8deacc695b683f4168757c82c10047b81854cbeaaeefd60536dd67bb48f8a65e20410652 + languageName: node + linkType: hard + "@types/webpack-env@npm:1.18.8": version: 1.18.8 resolution: "@types/webpack-env@npm:1.18.8" @@ -4521,6 +4585,13 @@ __metadata: languageName: node linkType: hard +"clsx@npm:^1.2.1": + version: 1.2.1 + resolution: "clsx@npm:1.2.1" + checksum: 10c0/34dead8bee24f5e96f6e7937d711978380647e936a22e76380290e35486afd8634966ce300fc4b74a32f3762c7d4c0303f442c3e259f4ce02374eb0c82834f27 + languageName: node + linkType: hard + "clsx@npm:^2.1.1": version: 2.1.1 resolution: "clsx@npm:2.1.1" @@ -4809,6 +4880,13 @@ __metadata: languageName: node linkType: hard +"date-arithmetic@npm:^4.1.0": + version: 4.1.0 + resolution: "date-arithmetic@npm:4.1.0" + checksum: 10c0/697774a1a6a1b226004b5527326599c01a095bf715a0d43089e0493a565a91e7f4342b1b73b855c0e7b0caaf4bc947a61bc35ec60d162d52ef3c3c08eab26b6e + languageName: node + linkType: hard + "date-fns-jalali@npm:4.1.0-0": version: 4.1.0-0 resolution: "date-fns-jalali@npm:4.1.0-0" @@ -4823,7 +4901,7 @@ __metadata: languageName: node linkType: hard -"dayjs@npm:^1.10.4": +"dayjs@npm:^1.10.4, dayjs@npm:^1.11.7": version: 1.11.13 resolution: "dayjs@npm:1.11.13" checksum: 10c0/a3caf6ac8363c7dade9d1ee797848ddcf25c1ace68d9fe8678ecf8ba0675825430de5d793672ec87b24a69bf04a1544b176547b2539982275d5542a7955f35b7 @@ -4908,6 +4986,13 @@ __metadata: languageName: node linkType: hard +"dequal@npm:^2.0.3": + version: 2.0.3 + resolution: "dequal@npm:2.0.3" + checksum: 10c0/f98860cdf58b64991ae10205137c0e97d384c3a4edc7f807603887b7c4b850af1224a33d88012009f150861cbee4fa2d322c4cc04b9313bee312e47f6ecaa888 + languageName: node + linkType: hard + "detect-libc@npm:^2.0.3, detect-libc@npm:^2.0.4": version: 2.0.4 resolution: "detect-libc@npm:2.0.4" @@ -4956,6 +5041,16 @@ __metadata: languageName: node linkType: hard +"dom-helpers@npm:^5.2.0, dom-helpers@npm:^5.2.1": + version: 5.2.1 + resolution: "dom-helpers@npm:5.2.1" + dependencies: + "@babel/runtime": "npm:^7.8.7" + csstype: "npm:^3.0.2" + checksum: 10c0/f735074d66dd759b36b158fa26e9d00c9388ee0e8c9b16af941c38f014a37fc80782de83afefd621681b19ac0501034b4f1c4a3bff5caa1b8667f0212b5e124c + languageName: node + linkType: hard + "dompurify@npm:=3.2.4": version: 3.2.4 resolution: "dompurify@npm:3.2.4" @@ -6211,6 +6306,13 @@ __metadata: languageName: node linkType: hard +"globalize@npm:^0.1.1": + version: 0.1.1 + resolution: "globalize@npm:0.1.1" + checksum: 10c0/6d4687e7c52a38e7f16f77339aef9b3364c34ce8cc1c8b8495b76418013252eaf5b2453fbc2d8bb9e6e56c739262665484dc7ac51b729501ff0a3b822730116b + languageName: node + linkType: hard + "globals@npm:^14.0.0": version: 14.0.0 resolution: "globals@npm:14.0.0" @@ -6526,7 +6628,7 @@ __metadata: languageName: node linkType: hard -"invariant@npm:^2.2.2": +"invariant@npm:^2.2.2, invariant@npm:^2.2.4": version: 2.2.4 resolution: "invariant@npm:2.2.4" dependencies: @@ -7318,6 +7420,13 @@ __metadata: languageName: node linkType: hard +"lodash-es@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash-es@npm:4.17.21" + checksum: 10c0/fb407355f7e6cd523a9383e76e6b455321f0f153a6c9625e21a8827d10c54c2a2341bd2ae8d034358b60e07325e1330c14c224ff582d04612a46a4f0479ff2f2 + languageName: node + linkType: hard + "lodash.debounce@npm:^4": version: 4.0.8 resolution: "lodash.debounce@npm:4.0.8" @@ -7489,6 +7598,13 @@ __metadata: languageName: node linkType: hard +"luxon@npm:^3.2.1": + version: 3.6.1 + resolution: "luxon@npm:3.6.1" + checksum: 10c0/906d57a9dc4d1de9383f2e9223e378c298607c1b4d17b6657b836a3cd120feb1c1de3b5d06d846a3417e1ca764de8476e8c23b3cd4083b5cdb870adcb06a99d5 + languageName: node + linkType: hard + "magic-string@npm:^0.30.17": version: 0.30.17 resolution: "magic-string@npm:0.30.17" @@ -7586,6 +7702,7 @@ __metadata: "@tanstack/react-query": "npm:^5.80.7" "@types/node": "npm:22.15.33" "@types/react": "npm:19.1.8" + "@types/react-big-calendar": "npm:^1" "@types/react-dom": "npm:19.1.6" "@types/swagger-ui-react": "npm:5" "@types/webpack-env": "npm:1.18.8" @@ -7608,9 +7725,12 @@ __metadata: postcss: "npm:8.5.6" prettier: "npm:3.5.3" prisma: "npm:6.10.1" - react: "npm:^19.0.0" + react: "npm:^19.1.0" + react-big-calendar: "npm:^1.18.0" + react-datepicker: "npm:^8.4.0" react-day-picker: "npm:^9.7.0" react-dom: "npm:^19.0.0" + react-error-boundary: "npm:^6.0.0" react-hook-form: "npm:^7.56.4" sonner: "npm:^2.0.5" swagger-ui-react: "npm:^5.24.1" @@ -7621,9 +7741,17 @@ __metadata: tw-animate-css: "npm:1.3.4" typescript: "npm:^5.8.3" zod: "npm:^3.25.60" + zod-validation-error: "npm:^3.5.2" languageName: unknown linkType: soft +"memoize-one@npm:^6.0.0": + version: 6.0.0 + resolution: "memoize-one@npm:6.0.0" + checksum: 10c0/45c88e064fd715166619af72e8cf8a7a17224d6edf61f7a8633d740ed8c8c0558a4373876c9b8ffc5518c2b65a960266adf403cc215cb1e90f7e262b58991f54 + languageName: node + linkType: hard + "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -7808,6 +7936,22 @@ __metadata: languageName: node linkType: hard +"moment-timezone@npm:^0.5.40": + version: 0.5.48 + resolution: "moment-timezone@npm:0.5.48" + dependencies: + moment: "npm:^2.29.4" + checksum: 10c0/ab14ec9d94bc33f29ac18e5417b7f8aca0b17130b952c5cc9697b8fea839e5ece9313af5fd3c9703a05db472b1560ddbfc7ad2aa24aac9afd047d6da6c3c6033 + languageName: node + linkType: hard + +"moment@npm:^2.29.4": + version: 2.30.1 + resolution: "moment@npm:2.30.1" + checksum: 10c0/865e4279418c6de666fca7786607705fd0189d8a7b7624e2e56be99290ac846f90878a6f602e34b4e0455c549b85385b1baf9966845962b313699e7cb847543a + languageName: node + linkType: hard + "ms@npm:^2.1.1, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" @@ -8657,7 +8801,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:^15.8.1": +"prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" dependencies: @@ -8773,6 +8917,33 @@ __metadata: languageName: node linkType: hard +"react-big-calendar@npm:^1.18.0": + version: 1.19.4 + resolution: "react-big-calendar@npm:1.19.4" + dependencies: + "@babel/runtime": "npm:^7.20.7" + clsx: "npm:^1.2.1" + date-arithmetic: "npm:^4.1.0" + dayjs: "npm:^1.11.7" + dom-helpers: "npm:^5.2.1" + globalize: "npm:^0.1.1" + invariant: "npm:^2.2.4" + lodash: "npm:^4.17.21" + lodash-es: "npm:^4.17.21" + luxon: "npm:^3.2.1" + memoize-one: "npm:^6.0.0" + moment: "npm:^2.29.4" + moment-timezone: "npm:^0.5.40" + prop-types: "npm:^15.8.1" + react-overlays: "npm:^5.2.1" + uncontrollable: "npm:^7.2.1" + peerDependencies: + react: ^16.14.0 || ^17 || ^18 || ^19 + react-dom: ^16.14.0 || ^17 || ^18 || ^19 + checksum: 10c0/78730e6396c06a27b24af860fa64d063f6407ccd12546116eb8cb2f274d827891c68a701b9c83f9903f63e5dea03fb6a3dd46d6a0a9186b3ab2f7e1d994fe86b + languageName: node + linkType: hard + "react-copy-to-clipboard@npm:5.1.0": version: 5.1.0 resolution: "react-copy-to-clipboard@npm:5.1.0" @@ -8785,6 +8956,20 @@ __metadata: languageName: node linkType: hard +"react-datepicker@npm:^8.4.0": + version: 8.4.0 + resolution: "react-datepicker@npm:8.4.0" + dependencies: + "@floating-ui/react": "npm:^0.27.3" + clsx: "npm:^2.1.1" + date-fns: "npm:^4.1.0" + peerDependencies: + react: ^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc + react-dom: ^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc + checksum: 10c0/e96ba4f2b54476f66bfa33aa0c21729095c83d293671b07a9ddd96ab48dad85b6530acc5ca016e83ef8907feeebfefb7133bf7a02dc550175c48c5d9f66d70ac + languageName: node + linkType: hard + "react-day-picker@npm:^9.7.0": version: 9.7.0 resolution: "react-day-picker@npm:9.7.0" @@ -8821,6 +9006,17 @@ __metadata: languageName: node linkType: hard +"react-error-boundary@npm:^6.0.0": + version: 6.0.0 + resolution: "react-error-boundary@npm:6.0.0" + dependencies: + "@babel/runtime": "npm:^7.12.5" + peerDependencies: + react: ">=16.13.1" + checksum: 10c0/1914d600dee95a14f14af4afe9867b0d35c26c4f7826d23208800ba2a99728659029aad60a6ef95e13430b4d79c2c4c9b3585f50bf508450478760d2e4e732d8 + languageName: node + linkType: hard + "react-hook-form@npm:^7.56.4": version: 7.58.1 resolution: "react-hook-form@npm:7.58.1" @@ -8868,6 +9064,32 @@ __metadata: languageName: node linkType: hard +"react-lifecycles-compat@npm:^3.0.4": + version: 3.0.4 + resolution: "react-lifecycles-compat@npm:3.0.4" + checksum: 10c0/1d0df3c85af79df720524780f00c064d53a9dd1899d785eddb7264b378026979acbddb58a4b7e06e7d0d12aa1494fd5754562ee55d32907b15601068dae82c27 + languageName: node + linkType: hard + +"react-overlays@npm:^5.2.1": + version: 5.2.1 + resolution: "react-overlays@npm:5.2.1" + dependencies: + "@babel/runtime": "npm:^7.13.8" + "@popperjs/core": "npm:^2.11.6" + "@restart/hooks": "npm:^0.4.7" + "@types/warning": "npm:^3.0.0" + dom-helpers: "npm:^5.2.0" + prop-types: "npm:^15.7.2" + uncontrollable: "npm:^7.2.1" + warning: "npm:^4.0.3" + peerDependencies: + react: ">=16.3.0" + react-dom: ">=16.3.0" + checksum: 10c0/61836490040cfcdebc792b6eddcfac47b7b7e159f99304165371e9eb389a6875f20ddba3433421413ccfb918e8da6042ab2829f9b1f6f5dd9f8476aa16ddcfbe + languageName: node + linkType: hard + "react-redux@npm:^9.2.0": version: 9.2.0 resolution: "react-redux@npm:9.2.0" @@ -8954,7 +9176,7 @@ __metadata: languageName: node linkType: hard -"react@npm:^19.0.0": +"react@npm:^19.1.0": version: 19.1.0 resolution: "react@npm:19.1.0" checksum: 10c0/530fb9a62237d54137a13d2cfb67a7db6a2156faed43eecc423f4713d9b20c6f2728b026b45e28fcd72e8eadb9e9ed4b089e99f5e295d2f0ad3134251bdd3698 @@ -10041,6 +10263,13 @@ __metadata: languageName: node linkType: hard +"tabbable@npm:^6.0.0": + version: 6.2.0 + resolution: "tabbable@npm:6.2.0" + checksum: 10c0/ced8b38f05f2de62cd46836d77c2646c42b8c9713f5bd265daf0e78ff5ac73d3ba48a7ca45f348bafeef29b23da7187c72250742d37627883ef89cbd7fa76898 + languageName: node + linkType: hard + "tailwind-merge@npm:^3.2.0": version: 3.3.1 resolution: "tailwind-merge@npm:3.3.1" @@ -10510,6 +10739,20 @@ __metadata: languageName: node linkType: hard +"uncontrollable@npm:^7.2.1": + version: 7.2.1 + resolution: "uncontrollable@npm:7.2.1" + dependencies: + "@babel/runtime": "npm:^7.6.3" + "@types/react": "npm:>=16.9.11" + invariant: "npm:^2.2.4" + react-lifecycles-compat: "npm:^3.0.4" + peerDependencies: + react: ">=15.0.0" + checksum: 10c0/81473e892027a99f1ead6b9afd16db65097651cd36c4b6db710728f206f1fc4b82ba9170ecb4a1127a23857e01ba51c0194d0a7cfeecfea61ba9418e0276cb56 + languageName: node + linkType: hard + "undici-types@npm:~6.21.0": version: 6.21.0 resolution: "undici-types@npm:6.21.0" @@ -10737,6 +10980,15 @@ __metadata: languageName: node linkType: hard +"warning@npm:^4.0.3": + version: 4.0.3 + resolution: "warning@npm:4.0.3" + dependencies: + loose-envify: "npm:^1.0.0" + checksum: 10c0/aebab445129f3e104c271f1637fa38e55eb25f968593e3825bd2f7a12bd58dc3738bb70dc8ec85826621d80b4acfed5a29ebc9da17397c6125864d72301b937e + languageName: node + linkType: hard + "web-streams-polyfill@npm:^3.0.3": version: 3.3.3 resolution: "web-streams-polyfill@npm:3.3.3" @@ -11035,6 +11287,15 @@ __metadata: languageName: node linkType: hard +"zod-validation-error@npm:^3.5.2": + version: 3.5.2 + resolution: "zod-validation-error@npm:3.5.2" + peerDependencies: + zod: ^3.25.0 + checksum: 10c0/da50926ec91c7ad2880bacc5010a53c42de58f73f7c4629baad8132695c4daf74dd68620787198da81aca85134471182ed4c566b5fc9bc5349aefd8540946d57 + languageName: node + linkType: hard + "zod@npm:^3.25.60": version: 3.25.67 resolution: "zod@npm:3.25.67"