feat: Custom Calendar Toolbar
Add Custom Calendar Toolbar
This commit is contained in:
parent
6a2215b9d5
commit
b05d2be1ac
5 changed files with 395 additions and 113 deletions
|
@ -33,6 +33,7 @@
|
|||
"@radix-ui/react-tabs": "^1.1.11",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-react": "^0.511.0",
|
||||
"next": "15.3.3",
|
||||
"next-auth": "^5.0.0-beta.25",
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Calendar, momentLocalizer } from 'react-big-calendar';
|
|||
import moment from 'moment';
|
||||
import 'react-big-calendar/lib/css/react-big-calendar.css';
|
||||
import 'react-big-calendar/lib/addons/dragAndDrop/styles.css';
|
||||
import CustomToolbar from '@/components/custom-toolbar';
|
||||
|
||||
moment.updateLocale('en', {
|
||||
week: {
|
||||
|
@ -24,6 +25,12 @@ const MyCalendar = (props) => (
|
|||
style={{ height: 500 }}
|
||||
culture="de-DE"
|
||||
defaultView='week'
|
||||
|
||||
/*CustomToolbar*/
|
||||
components={{
|
||||
toolbar: CustomToolbar
|
||||
}}
|
||||
/*CustomToolbar*/
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
139
src/components/custom-toolbar.css
Normal file
139
src/components/custom-toolbar.css
Normal file
|
@ -0,0 +1,139 @@
|
|||
/* custom-toolbar.css */
|
||||
|
||||
/* Container der Toolbar */
|
||||
.custom-toolbar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #e0e0e0;
|
||||
/*border-radius: 8px;*/
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
/* Style für den Bereich, in dem die Ansichten (Month, Week, etc.) gewechselt werden */
|
||||
.custom-toolbar .view-change .view-switcher {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.custom-toolbar .view-change .view-switcher button {
|
||||
padding: 8px 16px;
|
||||
background-color: #c1830d;
|
||||
/*border: 1px solid #ccc;*/
|
||||
border-radius: 11px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s, border-color 0.2s;
|
||||
height: 30px;
|
||||
margin-top: 3.5px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.custom-toolbar .view-change .view-switcher button:hover:not(:disabled) {
|
||||
background-color: #e0e0e0;
|
||||
border-color: #999;
|
||||
}
|
||||
|
||||
.custom-toolbar .view-change .view-switcher button:disabled {
|
||||
background-color: #d0d0d0;
|
||||
border-color: #aaa;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* Anzeige des aktuellen Datums (Monat und Jahr) */
|
||||
.custom-toolbar .current-date {
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
margin: 4px 0;
|
||||
background-color: #717171;
|
||||
width: 178px;
|
||||
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;
|
||||
/*background-color: #2196F3;*/
|
||||
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: 1px solid #ccc;*/
|
||||
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 {
|
||||
background-color: #717171;
|
||||
width: 393px;
|
||||
height: 37px;
|
||||
border-radius: 11px;
|
||||
}
|
||||
|
||||
.custom-toolbar .navigation-controls .handleWeek button {
|
||||
background-color: #717171;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
margin-bottom: 3.5px;
|
||||
}
|
||||
|
||||
.custom-toolbar .navigation-controls .today button {
|
||||
background-color: #c6c6c6;
|
||||
height: 30px;
|
||||
width: 100px;
|
||||
color: #000000;
|
||||
margin-top: 3.5px;
|
||||
}
|
||||
|
||||
.view-change {
|
||||
background-color: #717171;
|
||||
height: 37px;
|
||||
width: 290px;
|
||||
border-radius: 11px;
|
||||
}
|
218
src/components/custom-toolbar.tsx
Normal file
218
src/components/custom-toolbar.tsx
Normal file
|
@ -0,0 +1,218 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { format } from 'date-fns';
|
||||
import './custom-toolbar.css';
|
||||
|
||||
interface CustomToolbarProps {
|
||||
// Das aktuell angezeigte Datum (wird z. B. von der Calendar-Komponente geliefert)
|
||||
date: Date;
|
||||
// Aktuelle Ansicht: "month", "week", "day" oder "agenda"
|
||||
view: 'month' | 'week' | 'day' | 'agenda';
|
||||
/**
|
||||
* onNavigate ermöglicht das Wechseln des angezeigten Datums.
|
||||
* Action kann bspw. 'TODAY' oder 'SET_DATE' sein; newDate wird übergeben, wenn benötigt.
|
||||
*/
|
||||
onNavigate: (action: string, newDate?: Date) => void;
|
||||
// onView wechselt die Ansicht
|
||||
onView: (newView: 'month' | 'week' | 'day' | 'agenda') => void;
|
||||
}
|
||||
|
||||
const CustomToolbar: React.FC<CustomToolbarProps> = ({ date, view, onNavigate, onView }) => {
|
||||
|
||||
// Hilfsfunktion, um die ISO-Wochennummer eines Datums zu ermitteln
|
||||
const getISOWeek = (date: Date): number => {
|
||||
const tmp = new Date(date.getTime());
|
||||
// Verschiebe das Datum so, 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;
|
||||
};
|
||||
|
||||
// Neue Funktion: Ermittelt das ISO-Wochenjahr eines Datums.
|
||||
// Das ISO-Wochenjahr entspricht dem Jahr des Donnerstags in dieser Woche.
|
||||
const getISOWeekYear = (date: Date): number => {
|
||||
const tmp = new Date(date.getTime());
|
||||
tmp.setDate(tmp.getDate() + 4 - (tmp.getDay() || 7));
|
||||
return tmp.getFullYear();
|
||||
};
|
||||
|
||||
// Ermittelt die Anzahl der ISO-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;
|
||||
};
|
||||
|
||||
/*
|
||||
Berechnet den Montag der gewünschten ISO-Woche eines Jahres.
|
||||
Wir ermitteln zunächst den ersten Montag der ersten ISO-Woche und addieren dann (week - 1) * 7 Tage.
|
||||
*/
|
||||
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) {
|
||||
// Jan 1 gehört zur ersten ISO-Woche – bestimme den Montag dieser Woche
|
||||
firstMonday = new Date(year, 0, 1 - isoDayOfWeek + 1);
|
||||
} else {
|
||||
// Andernfalls 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<number>(getISOWeek(date));
|
||||
const [selectedYear, setSelectedYear] = useState<number>(getISOWeekYear(date));
|
||||
|
||||
// Aktualisiere die Auswahl, wenn sich die Prop "date" ändert
|
||||
useEffect(() => {
|
||||
setSelectedWeek(getISOWeek(date));
|
||||
setSelectedYear(getISOWeekYear(date));
|
||||
}, [date]);
|
||||
|
||||
// Für die Dropdown-Liste der Wochen: Liste von 1 bis totalWeeks
|
||||
const totalWeeks = getISOWeeksInYear(selectedYear);
|
||||
const weekOptions = Array.from({ length: totalWeeks }, (_, i) => i + 1);
|
||||
|
||||
// Beispielhafte Jahresliste: aktuelles ISO-Wochenjahr ± 10
|
||||
const yearOptions = Array.from({ length: 21 }, (_, i) => selectedYear - 10 + i);
|
||||
|
||||
// Berechne den Start (Montag) und das Ende (Sonntag) der aktuell angezeigten Woche
|
||||
const weekStartDate = getDateOfISOWeek(selectedWeek, selectedYear);
|
||||
const weekEndDate = new Date(weekStartDate);
|
||||
weekEndDate.setDate(weekStartDate.getDate() + 6);
|
||||
|
||||
// Ermittele Monat und Jahr von Start- und Enddatum (normales Kalenderjahr)
|
||||
const monthStart = format(weekStartDate, 'MMMM');
|
||||
const monthEnd = format(weekEndDate, 'MMMM');
|
||||
const yearAtStart = format(weekStartDate, 'yyyy');
|
||||
const yearAtEnd = format(weekEndDate, 'yyyy');
|
||||
|
||||
// Erstelle das Label:
|
||||
// 1. Falls der Wochenanfang und das Wochenende in unterschiedlichen Jahren liegen,
|
||||
// wird z. B. "Dezember 2025 - Januar 2026" angezeigt.
|
||||
// 2. Liegen beide im gleichen Jahr, wird unterschieden zwischen gleichem Monat und unterschiedlichem Monat.
|
||||
let dateLabel: string;
|
||||
if (yearAtStart !== yearAtEnd) {
|
||||
dateLabel = `${monthStart} ${yearAtStart} - ${monthEnd} ${yearAtEnd}`;
|
||||
} else if (monthStart !== monthEnd) {
|
||||
dateLabel = `${monthStart} - ${monthEnd} ${yearAtStart}`;
|
||||
} else {
|
||||
dateLabel = `${monthStart} ${yearAtStart}`;
|
||||
}
|
||||
|
||||
// Handler zum Wechseln der Ansicht
|
||||
const handleViewChange = (newView: 'month' | 'week' | 'day' | 'agenda') => {
|
||||
onView(newView);
|
||||
};
|
||||
|
||||
// "Today"-Button: setzt das Datum auf das heutige Datum (unter Verwendung des ISO-Wochenjahrs)
|
||||
const handleToday = () => {
|
||||
const today = new Date();
|
||||
setSelectedWeek(getISOWeek(today));
|
||||
setSelectedYear(getISOWeekYear(today));
|
||||
onNavigate('TODAY', today);
|
||||
};
|
||||
|
||||
// Wechselt zur vorherigen Woche. Bei Woche < 1, wird ins Vorjahr gewechselt.
|
||||
const handlePrevWeek = () => {
|
||||
let newWeek = selectedWeek - 1;
|
||||
let newYear = selectedYear;
|
||||
if (newWeek < 1) {
|
||||
newYear = selectedYear - 1;
|
||||
newWeek = getISOWeeksInYear(newYear);
|
||||
}
|
||||
setSelectedWeek(newWeek);
|
||||
setSelectedYear(newYear);
|
||||
const newDate = getDateOfISOWeek(newWeek, newYear);
|
||||
onNavigate('SET_DATE', newDate);
|
||||
};
|
||||
|
||||
// Wechselt zur nächsten Woche. Überschreitet die Woche die maximale Zahl, wechselt ins nächste Jahr.
|
||||
const handleNextWeek = () => {
|
||||
let newWeek = selectedWeek + 1;
|
||||
let newYear = selectedYear;
|
||||
if (newWeek > getISOWeeksInYear(selectedYear)) {
|
||||
newYear = selectedYear + 1;
|
||||
newWeek = 1;
|
||||
}
|
||||
setSelectedWeek(newWeek);
|
||||
setSelectedYear(newYear);
|
||||
const newDate = getDateOfISOWeek(newWeek, newYear);
|
||||
onNavigate('SET_DATE', newDate);
|
||||
};
|
||||
|
||||
// Handler, wenn der Nutzer über das Dropdown eine Woche auswählt
|
||||
const handleWeekChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const newWeek = parseInt(event.target.value, 10);
|
||||
setSelectedWeek(newWeek);
|
||||
const newDate = getDateOfISOWeek(newWeek, selectedYear);
|
||||
onNavigate('SET_DATE', newDate);
|
||||
};
|
||||
|
||||
// Handler, wenn der Nutzer über das Dropdown ein Jahr auswählt
|
||||
const handleYearChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const newYear = parseInt(event.target.value, 10);
|
||||
setSelectedYear(newYear);
|
||||
const totalWeeksInNewYear = getISOWeeksInYear(newYear);
|
||||
const newWeek = Math.min(selectedWeek, totalWeeksInNewYear);
|
||||
setSelectedWeek(newWeek);
|
||||
const newDate = getDateOfISOWeek(newWeek, newYear);
|
||||
onNavigate('SET_DATE', newDate);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="custom-toolbar" style={{ display: 'flex', flexDirection: 'initial', gap: '8px' }}>
|
||||
{/* Anzeige des Datums-Labels */}
|
||||
<div className="current-date" style={{ fontWeight: 'bold' }}>
|
||||
{dateLabel}
|
||||
</div>
|
||||
|
||||
{/* Ansicht wechseln */}
|
||||
<div className='view-change'>
|
||||
<div className="view-switcher" style={{ display: 'flex', gap: '8px' }}>
|
||||
<button disabled={view === 'month'} onClick={() => handleViewChange('month')}>Month</button>
|
||||
<button disabled={view === 'week'} onClick={() => handleViewChange('week')}>Week</button>
|
||||
<button disabled={view === 'day'} onClick={() => handleViewChange('day')}>Day</button>
|
||||
<button disabled={view === 'agenda'} onClick={() => handleViewChange('agenda')}>Agenda</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="right-section" style={{ display: 'flex', flexDirection: 'initial', gap: '8px' }}>
|
||||
{/* Navigationsbuttons */}
|
||||
<div className="navigation-controls" style={{ display: 'flex', gap: '8px' }}>
|
||||
<div className="handleWeek">
|
||||
<button onClick={handlePrevWeek}><</button>
|
||||
<button onClick={handleNextWeek}>></button>
|
||||
</div>
|
||||
<div className="today">
|
||||
<button onClick={handleToday}>Today</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* DropDowns für Woche und Jahr */}
|
||||
<div className="dropdowns" style={{ display: 'flex', gap: '8px' }}>
|
||||
<select value={selectedWeek} onChange={handleWeekChange}>
|
||||
{weekOptions.map((week) => (
|
||||
<option key={week} value={week}>
|
||||
Week {week}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<select value={selectedYear} onChange={handleYearChange}>
|
||||
{yearOptions.map((year) => (
|
||||
<option key={year} value={year}>
|
||||
{year}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CustomToolbar;
|
143
yarn.lock
143
yarn.lock
|
@ -2232,33 +2232,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"bytes@npm:3.1.2, bytes@npm:^3.1.2":
|
||||
version: 3.1.2
|
||||
resolution: "bytes@npm:3.1.2"
|
||||
checksum: 10c0/76d1c43cbd602794ad8ad2ae94095cddeb1de78c5dddaa7005c51af10b0176c69971a6d88e805a90c2b6550d76636e43c40d8427a808b8645ede885de4a0358e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cacache@npm:^19.0.1":
|
||||
version: 19.0.1
|
||||
resolution: "cacache@npm:19.0.1"
|
||||
dependencies:
|
||||
"@npmcli/fs": "npm:^4.0.0"
|
||||
fs-minipass: "npm:^3.0.0"
|
||||
glob: "npm:^10.2.2"
|
||||
lru-cache: "npm:^10.0.1"
|
||||
minipass: "npm:^7.0.3"
|
||||
minipass-collect: "npm:^2.0.1"
|
||||
minipass-flush: "npm:^1.0.5"
|
||||
minipass-pipeline: "npm:^1.2.4"
|
||||
p-map: "npm:^7.0.2"
|
||||
ssri: "npm:^12.0.0"
|
||||
tar: "npm:^7.4.3"
|
||||
unique-filename: "npm:^4.0.0"
|
||||
checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "call-bind-apply-helpers@npm:1.0.2"
|
||||
|
@ -2338,6 +2311,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"
|
||||
|
@ -2453,6 +2433,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"date-fns@npm:^4.1.0":
|
||||
version: 4.1.0
|
||||
resolution: "date-fns@npm:4.1.0"
|
||||
checksum: 10c0/b79ff32830e6b7faa009590af6ae0fb8c3fd9ffad46d930548fbb5acf473773b4712ae887e156ba91a7b3dc30591ce0f517d69fd83bd9c38650fdc03b4e0bac8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dayjs@npm:^1.11.7":
|
||||
version: 1.11.13
|
||||
resolution: "dayjs@npm:1.11.13"
|
||||
|
@ -3249,15 +3236,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"get-user-locale@npm:^2.2.1":
|
||||
version: 2.3.2
|
||||
resolution: "get-user-locale@npm:2.3.2"
|
||||
dependencies:
|
||||
mem: "npm:^8.0.0"
|
||||
checksum: 10c0/2796b3fc3782b1f4826f31e899642cf72eeb23e296e1cf55280aab5caf7a25f4b906491ee1508a001519d6a410902ccf8fa8edaa895b7aee5dfd422ffe5523b9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"glob-parent@npm:^5.1.2":
|
||||
version: 5.1.2
|
||||
resolution: "glob-parent@npm:5.1.2"
|
||||
|
@ -3951,7 +3929,14 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"loose-envify@npm:^1.4.0":
|
||||
"lodash@npm:^4.17.21":
|
||||
version: 4.17.21
|
||||
resolution: "lodash@npm:4.17.21"
|
||||
checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"loose-envify@npm:^1.0.0, loose-envify@npm:^1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "loose-envify@npm:1.4.0"
|
||||
dependencies:
|
||||
|
@ -3987,25 +3972,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"make-fetch-happen@npm:^14.0.3":
|
||||
version: 14.0.3
|
||||
resolution: "make-fetch-happen@npm:14.0.3"
|
||||
dependencies:
|
||||
"@npmcli/agent": "npm:^3.0.0"
|
||||
cacache: "npm:^19.0.1"
|
||||
http-cache-semantics: "npm:^4.1.1"
|
||||
minipass: "npm:^7.0.2"
|
||||
minipass-fetch: "npm:^4.0.0"
|
||||
minipass-flush: "npm:^1.0.5"
|
||||
minipass-pipeline: "npm:^1.2.4"
|
||||
negotiator: "npm:^1.0.0"
|
||||
proc-log: "npm:^5.0.0"
|
||||
promise-retry: "npm:^2.0.1"
|
||||
ssri: "npm:^12.0.0"
|
||||
checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"math-intrinsics@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "math-intrinsics@npm:1.1.0"
|
||||
|
@ -4041,6 +4007,7 @@ __metadata:
|
|||
"@types/react-dom": "npm:19.1.6"
|
||||
class-variance-authority: "npm:^0.7.1"
|
||||
clsx: "npm:^2.1.1"
|
||||
date-fns: "npm:^4.1.0"
|
||||
dotenv-cli: "npm:8.0.0"
|
||||
eslint: "npm:9.28.0"
|
||||
eslint-config-next: "npm:15.3.3"
|
||||
|
@ -4051,8 +4018,9 @@ __metadata:
|
|||
next-themes: "npm:^0.4.6"
|
||||
postcss: "npm:8.5.4"
|
||||
prettier: "npm:3.5.3"
|
||||
prisma: "npm:6.7.0"
|
||||
react: "npm:^19.0.0"
|
||||
prisma: "npm:6.8.2"
|
||||
react: "npm:^19.1.0"
|
||||
react-big-calendar: "npm:^1.18.0"
|
||||
react-dom: "npm:^19.0.0"
|
||||
tailwind-merge: "npm:^3.2.0"
|
||||
tailwindcss: "npm:4.1.8"
|
||||
|
@ -4061,10 +4029,10 @@ __metadata:
|
|||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"merge-descriptors@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "merge-descriptors@npm:2.0.0"
|
||||
checksum: 10c0/95389b7ced3f9b36fbdcf32eb946dc3dd1774c2fdf164609e55b18d03aa499b12bd3aae3a76c1c7185b96279e9803525550d3eb292b5224866060a288f335cb3
|
||||
"memoize-one@npm:^6.0.0":
|
||||
version: 6.0.0
|
||||
resolution: "memoize-one@npm:6.0.0"
|
||||
checksum: 10c0/45c88e064fd715166619af72e8cf8a7a17224d6edf61f7a8633d740ed8c8c0558a4373876c9b8ffc5518c2b65a960266adf403cc215cb1e90f7e262b58991f54
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
@ -4085,22 +4053,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"mime-db@npm:^1.54.0":
|
||||
version: 1.54.0
|
||||
resolution: "mime-db@npm:1.54.0"
|
||||
checksum: 10c0/8d907917bc2a90fa2df842cdf5dfeaf509adc15fe0531e07bb2f6ab15992416479015828d6a74200041c492e42cce3ebf78e5ce714388a0a538ea9c53eece284
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"mime-types@npm:^3.0.0, mime-types@npm:^3.0.1":
|
||||
version: 3.0.1
|
||||
resolution: "mime-types@npm:3.0.1"
|
||||
dependencies:
|
||||
mime-db: "npm:^1.54.0"
|
||||
checksum: 10c0/bd8c20d3694548089cf229016124f8f40e6a60bbb600161ae13e45f793a2d5bb40f96bbc61f275836696179c77c1d6bf4967b2a75e0a8ad40fe31f4ed5be4da5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minimatch@npm:^3.1.2":
|
||||
version: 3.1.2
|
||||
resolution: "minimatch@npm:3.1.2"
|
||||
|
@ -4406,13 +4358,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"p-defer@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "p-defer@npm:1.0.0"
|
||||
checksum: 10c0/ed603c3790e74b061ac2cb07eb6e65802cf58dce0fbee646c113a7b71edb711101329ad38f99e462bd2e343a74f6e9366b496a35f1d766c187084d3109900487
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"p-limit@npm:^3.0.2":
|
||||
version: 3.1.0
|
||||
resolution: "p-limit@npm:3.1.0"
|
||||
|
@ -4612,25 +4557,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-calendar@npm:^5.1.0":
|
||||
version: 5.1.0
|
||||
resolution: "react-calendar@npm:5.1.0"
|
||||
dependencies:
|
||||
"@wojtekmaj/date-utils": "npm:^1.1.3"
|
||||
clsx: "npm:^2.0.0"
|
||||
get-user-locale: "npm:^2.2.1"
|
||||
warning: "npm:^4.0.0"
|
||||
peerDependencies:
|
||||
"@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
peerDependenciesMeta:
|
||||
"@types/react":
|
||||
optional: true
|
||||
checksum: 10c0/27673f639c5d6296342a2a888436b31a5d602faeaae01be83b2beb98ff568b0a3d1514f5cc50fcacf3ac50b9c0b9d2fb423b0c001a8f5f1a22816671409e2616
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-dom@npm:^19.0.0":
|
||||
version: 19.1.0
|
||||
resolution: "react-dom@npm:19.1.0"
|
||||
|
@ -5560,15 +5486,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"warning@npm:^4.0.0":
|
||||
version: 4.0.3
|
||||
resolution: "warning@npm:4.0.3"
|
||||
dependencies:
|
||||
loose-envify: "npm:^1.0.0"
|
||||
checksum: 10c0/aebab445129f3e104c271f1637fa38e55eb25f968593e3825bd2f7a12bd58dc3738bb70dc8ec85826621d80b4acfed5a29ebc9da17397c6125864d72301b937e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"which-boxed-primitive@npm:^1.1.0, which-boxed-primitive@npm:^1.1.1":
|
||||
version: 1.1.1
|
||||
resolution: "which-boxed-primitive@npm:1.1.1"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue