diff --git a/package-lock.json b/package-lock.json index 3f4b995..442c158 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,36 +8,45 @@ "name": "drive-booker", "version": "0.1.0", "dependencies": { - "@hookform/resolvers": "^3.9.1", + "@hookform/resolvers": "^3.10.0", "@radix-ui/react-checkbox": "^1.1.2", - "@radix-ui/react-dialog": "^1.1.5", - "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-dialog": "^1.1.4", + "@radix-ui/react-label": "^2.1.1", + "@radix-ui/react-popover": "^1.1.4", + "@radix-ui/react-scroll-area": "^1.2.2", "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-tabs": "^1.1.1", - "@tanstack/react-query": "^5.59.20", + "@tanstack/react-query": "^5.64.2", "axios": "^1.7.7", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "date-fns": "^3.6.0", "iron-session": "^8.0.4", "lucide-react": "^0.454.0", + "moment": "^2.30.1", "next": "^15.1.4", "react": "19.0.0-rc-02c0e824-20241028", + "react-big-calendar": "^1.17.1", + "react-day-picker": "^8.10.1", "react-dom": "19.0.0-rc-02c0e824-20241028", "react-hook-form": "^7.54.2", + "react-hook-form": "^7.54.2", "react-icons": "^5.3.0", "react-toastify": "^10.0.6", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7", - "zod": "^3.23.8" + "zod": "^3.24.1" }, "devDependencies": { + "@tanstack/react-query-devtools": "^5.64.2", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.0.1", "@testing-library/user-event": "^14.5.2", "@types/node": "^20", "@types/react": "^18", + "@types/react-big-calendar": "^1.16.0", "@types/react-dom": "^18", "@typescript-eslint/eslint-plugin": "^8.13.0", "@typescript-eslint/parser": "^8.13.0", @@ -362,7 +371,6 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", - "dev": true, "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -531,9 +539,9 @@ "license": "MIT" }, "node_modules/@hookform/resolvers": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.9.1.tgz", - "integrity": "sha512-ud2HqmGBM0P0IABqoskKWI6PEf6ZDDBZkFqe2Vnl+mTHCEHzr3ISjjZyCwTjC/qpL25JC9aIDkloQejvMeq0ug==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.10.0.tgz", + "integrity": "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==", "license": "MIT", "peerDependencies": { "react-hook-form": "^7.0.0" @@ -887,6 +895,16 @@ "node": ">=14" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@radix-ui/number": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", @@ -1042,15 +1060,15 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.5.tgz", - "integrity": "sha512-LaO3e5h/NOEL4OfXjxD43k9Dx+vn+8n+PCFt6uhX/BADFflllyv3WJG6rgvvSVBxpTch938Qq/LGc2MMxipXPw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz", + "integrity": "sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.4", + "@radix-ui/react-dismissable-layer": "1.1.3", "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.1", "@radix-ui/react-id": "1.1.0", @@ -1059,8 +1077,8 @@ "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-slot": "1.1.1", "@radix-ui/react-use-controllable-state": "1.1.0", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.2" + "aria-hidden": "^1.1.1", + "react-remove-scroll": "^2.6.1" }, "peerDependencies": { "@types/react": "*", @@ -1099,9 +1117,9 @@ } }, "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.4.tgz", - "integrity": "sha512-XDUI0IVYVSwjMXxM6P4Dfti7AH+Y4oS/TB+sglZ/EXc7cqLwGAmp1NlMrcUjj7ks6R5WTZuWKv44FBbLpwU3sA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz", + "integrity": "sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.1", @@ -1322,12 +1340,284 @@ } }, "node_modules/@radix-ui/react-label": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz", - "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.1.tgz", + "integrity": "sha512-UUw5E4e/2+4kFMH7+YxORXGWggtY6sM8WIwh5RZchhLuUg2H1hc98Py+pr8HMz6rdaYrK2t296ZEjYLOCO5uUw==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.0" + "@radix-ui/react-primitive": "2.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", + "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.4.tgz", + "integrity": "sha512-aUACAkXx8LaFymDma+HQVji7WhvEhpFJ7+qPz17Nf4lLZqtreGOFRiNQWQmhzp7kEWg9cOyyQJpdIMUMPc/CPw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.3", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.1", + "@radix-ui/react-portal": "1.1.3", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-slot": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "^2.6.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", + "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-arrow": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz", + "integrity": "sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz", + "integrity": "sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz", + "integrity": "sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-popper": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz", + "integrity": "sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-rect": "1.1.0", + "@radix-ui/react-use-size": "1.1.0", + "@radix-ui/rect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-popper/node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-portal": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.3.tgz", + "integrity": "sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-presence": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", + "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-primitive": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", + "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -1452,13 +1742,108 @@ } } }, - "node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", + "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.2.tgz", + "integrity": "sha512-EFI1N/S3YxZEW/lJ/H1jY3njlvTd8tBmgKEn4GHi51+aMm94i6NmAJstsm5cu3yJwYqYc93gpCPm21FeAbFk6g==", "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.1.0" + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -1475,14 +1860,17 @@ } } }, - "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", + "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" - }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -1493,21 +1881,14 @@ } } }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", - "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", + "node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-presence": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", + "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-collection": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0" + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -1524,18 +1905,26 @@ } } }, - "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-context": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", - "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-primitive": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", + "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.1" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, @@ -2148,9 +2537,20 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.59.20", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.59.20.tgz", - "integrity": "sha512-e8vw0lf7KwfGe1if4uPFhvZRWULqHjFcz3K8AebtieXvnMOz5FSzlZe3mTLlPuUBcydCnBRqYs2YJ5ys68wwLg==", + "version": "5.64.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.64.2.tgz", + "integrity": "sha512-hdO8SZpWXoADNTWXV9We8CwTkXU88OVWRBcsiFrk7xJQnhm6WRlweDzMD+uH+GnuieTBVSML6xFa17C2cNV8+g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-devtools": { + "version": "5.64.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.64.2.tgz", + "integrity": "sha512-3DautR5UpVZdk/qNIhioZVF7g8fdQZ1U98sBEEk4Tzz3tihSBNMPgwlP40nzgbPEDBIrn/j/oyyvNBVSo083Vw==", + "dev": true, "license": "MIT", "funding": { "type": "github", @@ -2158,18 +2558,36 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.59.20", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.59.20.tgz", - "integrity": "sha512-Zly0egsK0tFdfSbh5/mapSa+Zfc3Et0Zkar7Wo5sQkFzWyB3p3uZWOHR2wrlAEEV2L953eLuDBtbgFvMYiLvUw==", + "version": "5.64.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.64.2.tgz", + "integrity": "sha512-3pakNscZNm8KJkxmovvtZ4RaXLyiYYobwleTMvpIGUoKRa8j8VlrQKNl5W8VUEfVfZKkikvXVddLuWMbcSCA1Q==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.64.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@tanstack/react-query-devtools": { + "version": "5.64.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.64.2.tgz", + "integrity": "sha512-+ZjJVnPzc8BUV/Eklu2k9T/IAyAyvwoCHqOaOrk2sbU33LFhM52BpX4eyENXn0bx5LwV3DJZgEQlIzucoemfGQ==", + "dev": true, "license": "MIT", "dependencies": { - "@tanstack/query-core": "5.59.20" + "@tanstack/query-devtools": "5.64.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" }, "peerDependencies": { + "@tanstack/react-query": "^5.64.2", "react": "^18 || ^19" } }, @@ -2339,6 +2757,13 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/date-arithmetic": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@types/date-arithmetic/-/date-arithmetic-4.1.4.tgz", + "integrity": "sha512-p9eZ2X9B80iKiTW4ukVj8B4K6q9/+xFtQ5MGYA5HWToY9nL4EkhV9+6ftT2VHpVMEZb5Tv00Iel516bVdO+yRw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -2364,19 +2789,29 @@ "node_modules/@types/prop-types": { "version": "15.7.13", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", - "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", - "devOptional": true + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" }, "node_modules/@types/react": { "version": "18.3.12", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", - "devOptional": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" } }, + "node_modules/@types/react-big-calendar": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@types/react-big-calendar/-/react-big-calendar-1.16.0.tgz", + "integrity": "sha512-1w2GXAJWlGmaPZOd9J9cyWA/XBNOGRZ4MmRNypEQhwEMIIL9cfd1UdcvzSrQsnBm0qYF/scqmsISNbUzPBE1vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/date-arithmetic": "*", + "@types/prop-types": "*", + "@types/react": "*" + } + }, "node_modules/@types/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", @@ -2386,6 +2821,12 @@ "@types/react": "*" } }, + "node_modules/@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", @@ -3593,8 +4034,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -3667,6 +4107,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-arithmetic": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-arithmetic/-/date-arithmetic-4.1.0.tgz", + "integrity": "sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg==", + "license": "MIT" + }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -3755,7 +4217,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -3805,6 +4266,16 @@ "dev": true, "license": "MIT" }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -4945,6 +5416,11 @@ "node": ">=10.13.0" } }, + "node_modules/globalize": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/globalize/-/globalize-0.1.1.tgz", + "integrity": "sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA==" + }, "node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -6063,7 +6539,12 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", "license": "MIT" }, "node_modules/lodash.merge": { @@ -6243,6 +6724,15 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" } }, + "node_modules/luxon": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -6263,6 +6753,12 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -6376,6 +6872,27 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.46", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz", + "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==", + "license": "MIT", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -7173,7 +7690,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -7222,6 +7738,104 @@ "node": ">=0.10.0" } }, + "node_modules/react-big-calendar": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.17.1.tgz", + "integrity": "sha512-LltUAMSGODWQBKx4013bRe6R0jaINV9hrs970+F860KedpozwRGGMT66esV9mA3mAhfSKoazF/QH1WCyLkXYZA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.7", + "clsx": "^1.2.1", + "date-arithmetic": "^4.1.0", + "dayjs": "^1.11.7", + "dom-helpers": "^5.2.1", + "globalize": "^0.1.1", + "invariant": "^2.2.4", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "luxon": "^3.2.1", + "memoize-one": "^6.0.0", + "moment": "^2.29.4", + "moment-timezone": "^0.5.40", + "prop-types": "^15.8.1", + "react-overlays": "^5.2.1", + "uncontrollable": "^7.2.1" + }, + "peerDependencies": { + "react": "^16.14.0 || ^17 || ^18", + "react-dom": "^16.14.0 || ^17 || ^18" + } + }, + "node_modules/react-big-calendar/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react-big-calendar/node_modules/react-overlays": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz", + "integrity": "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.8", + "@popperjs/core": "^2.11.6", + "@restart/hooks": "^0.4.7", + "@types/warning": "^3.0.0", + "dom-helpers": "^5.2.0", + "prop-types": "^15.7.2", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.3.0", + "react-dom": ">=16.3.0" + } + }, + "node_modules/react-big-calendar/node_modules/react-overlays/node_modules/@restart/hooks": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz", + "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/react-big-calendar/node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, + "node_modules/react-day-picker": { + "version": "8.10.1", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz", + "integrity": "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==", + "license": "MIT", + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/gpbl" + }, + "peerDependencies": { + "date-fns": "^2.28.0 || ^3.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-dom": { "version": "19.0.0-rc-02c0e824-20241028", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0-rc-02c0e824-20241028.tgz", @@ -7234,6 +7848,9 @@ } }, "node_modules/react-hook-form": { + "version": "7.54.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz", + "integrity": "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==", "version": "7.54.2", "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz", "integrity": "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==", @@ -7260,8 +7877,13 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", + "license": "MIT" }, "node_modules/react-refresh": { "version": "0.14.2", @@ -7274,16 +7896,16 @@ } }, "node_modules/react-remove-scroll": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", - "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.2.tgz", + "integrity": "sha512-KmONPx5fnlXYJQqC62Q+lwIeAk64ws/cUw6omIumRzMRPqgnYqhSSti99nbj0Ry13bv7dF+BKn7NB+OqkdZGTw==", "license": "MIT", "dependencies": { "react-remove-scroll-bar": "^2.3.7", - "react-style-singleton": "^2.2.3", + "react-style-singleton": "^2.2.1", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", - "use-sidecar": "^1.1.3" + "use-sidecar": "^1.1.2" }, "engines": { "node": ">=10" @@ -7413,7 +8035,6 @@ "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, "license": "MIT" }, "node_modules/regexp.prototype.flags": { @@ -8691,6 +9312,49 @@ } } }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -8857,6 +9521,15 @@ "node": ">=18" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -9187,9 +9860,9 @@ } }, "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index 6b039bf..fda5704 100644 --- a/package.json +++ b/package.json @@ -14,36 +14,44 @@ "prepare": "husky" }, "dependencies": { - "@hookform/resolvers": "^3.9.1", + "@hookform/resolvers": "^3.10.0", "@radix-ui/react-checkbox": "^1.1.2", - "@radix-ui/react-dialog": "^1.1.5", - "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-dialog": "^1.1.4", + "@radix-ui/react-label": "^2.1.1", + "@radix-ui/react-popover": "^1.1.4", + "@radix-ui/react-scroll-area": "^1.2.2", "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-tabs": "^1.1.1", - "@tanstack/react-query": "^5.59.20", + "@tanstack/react-query": "^5.64.2", "axios": "^1.7.7", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "date-fns": "^3.6.0", "iron-session": "^8.0.4", "lucide-react": "^0.454.0", + "moment": "^2.30.1", "next": "^15.1.4", "react": "19.0.0-rc-02c0e824-20241028", + "react-big-calendar": "^1.17.1", + "react-day-picker": "^8.10.1", "react-dom": "19.0.0-rc-02c0e824-20241028", "react-hook-form": "^7.54.2", "react-icons": "^5.3.0", "react-toastify": "^10.0.6", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7", - "zod": "^3.23.8" + "zod": "^3.24.1" }, "devDependencies": { + "@tanstack/react-query-devtools": "^5.64.2", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.0.1", "@testing-library/user-event": "^14.5.2", "@types/node": "^20", "@types/react": "^18", + "@types/react-big-calendar": "^1.16.0", "@types/react-dom": "^18", "@typescript-eslint/eslint-plugin": "^8.13.0", "@typescript-eslint/parser": "^8.13.0", diff --git a/src/app/dashboard/_components/SideMenu.tsx b/src/app/dashboard/_components/SideMenu.tsx index e28a007..62aa04e 100644 --- a/src/app/dashboard/_components/SideMenu.tsx +++ b/src/app/dashboard/_components/SideMenu.tsx @@ -48,9 +48,13 @@ const SideMenu = () => {
  • - - Kalendarz - + + + Kalendarz + +
  • diff --git a/src/app/dashboard/calendar/_components/AddEventDialog.tsx b/src/app/dashboard/calendar/_components/AddEventDialog.tsx new file mode 100644 index 0000000..0375846 --- /dev/null +++ b/src/app/dashboard/calendar/_components/AddEventDialog.tsx @@ -0,0 +1,170 @@ +'use client'; + +import { Button } from '@/components/ui/button'; +import { DateTimePicker } from '@/components/ui/dateTimePicker'; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { getQueryClient } from '@/lib/getQueryClient'; +import { sendEvent } from '@/services/events/sendEvent'; +import { Driver, Event } from '@/services/events/types'; +import { useMutation } from '@tanstack/react-query'; +import { useState } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { toast } from 'react-toastify'; + +export default function AddEventDialog({ drivers }: { drivers: Driver[] }) { + const [open, setOpen] = useState(false); + const queryClient = getQueryClient(); + const methods = useForm({ + defaultValues: { + title: '', + driverId: '', + start: new Date(), + end: new Date(), + }, + }); + + const { mutate } = useMutation({ + mutationFn: sendEvent, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['events'] }); + toast.success('Wydarzenie zostało dodane'); + setOpen(false); + methods.reset(); + }, + onError: (error: Error) => { + console.error('Error creating event:', error); + toast.error('wystąpił błąd'); + }, + }); + + const onSubmit = (data: Event) => { + const { title, driverId, start, end } = data; + if (!title || !driverId || !start || !end) { + toast.info('Please fill in all fields'); + return; + } + mutate({ + title, + driverId, + start: start, + end: end, + }); + }; + + const selectedDriver = methods.watch('driverId'); + + return ( + + + + + + + Dodaj nowe wydarzenie + + Wprowadź szczegóły wydarzenia. Zapisz zmiany gdy skończysz. + + + +
    +
    +
    + + +
    +
    + +
    + +
    +
    +
    + +
    + methods.setValue('start', date)} + /> +
    +
    +
    + +
    + methods.setValue('end', date)} + /> +
    +
    +
    + + + + + + +
    +
    +
    +
    + ); +} diff --git a/src/app/dashboard/calendar/_components/BigCalendar/BigCalendar.tsx b/src/app/dashboard/calendar/_components/BigCalendar/BigCalendar.tsx new file mode 100644 index 0000000..0ea7eea --- /dev/null +++ b/src/app/dashboard/calendar/_components/BigCalendar/BigCalendar.tsx @@ -0,0 +1,70 @@ +'use client'; +import { messages } from '@/constants/calendar'; +import { getEventsQueryOptions } from '@/services/events/fetchEvents'; +import { Event } from '@/services/events/types'; +import { useSuspenseQuery } from '@tanstack/react-query'; +import moment from 'moment'; +import 'moment/locale/pl'; +import { useState } from 'react'; +import { Calendar, momentLocalizer, View, Views } from 'react-big-calendar'; +import './bigCalendarStyling.css'; +import { SelectEventDialog } from './SelectEventDialog'; + +const BigCalendar = ({ endpoint }: { endpoint: string }) => { + const eventsQueryOptions = getEventsQueryOptions(endpoint); + const { data: events } = useSuspenseQuery(eventsQueryOptions); + const [view, setView] = useState(Views.WEEK); + const [date, setDate] = useState(new Date()); + const [popoverOpen, setPopoverOpen] = useState(false); + const [selectedEvent, setSelectedEvent] = useState(); + + moment.locale('pl'); + const localizer = momentLocalizer(moment); + + const handleNavigate = (newDate: Date) => { + setDate(newDate); + }; + + const handleViewChange = (newView: View) => { + setView(newView); + }; + + const handleSelectEvent = (event: Event) => { + setSelectedEvent(event); + setPopoverOpen(true); + }; + + return ( +
    + { + return ( + moment(start).format('DD-MM-YYYY') + + ' — ' + + moment(end).format('DD-MM-YYYY') + ); + }, + }} + /> + {selectedEvent && ( + + )} +
    + ); +}; +export default BigCalendar; diff --git a/src/app/dashboard/calendar/_components/BigCalendar/SelectEventDialog.tsx b/src/app/dashboard/calendar/_components/BigCalendar/SelectEventDialog.tsx new file mode 100644 index 0000000..fadc0ff --- /dev/null +++ b/src/app/dashboard/calendar/_components/BigCalendar/SelectEventDialog.tsx @@ -0,0 +1,157 @@ +'use client'; +import { Button } from '@/components/ui/button'; +import { DateTimePicker } from '@/components/ui/dateTimePicker'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { getQueryClient } from '@/lib/getQueryClient'; +import { deleteEvent } from '@/services/events/deleteEvent'; +import { Event } from '@/services/events/types'; +import { updateEvent } from '@/services/events/updateEvent'; +import { useMutation } from '@tanstack/react-query'; +import { useEffect } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { toast } from 'react-toastify'; + +interface SelectEventDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; + event: Event; +} + +export const SelectEventDialog: React.FC = ({ + open, + onOpenChange, + event, +}) => { + const queryClient = getQueryClient(); + const methods = useForm({ + defaultValues: { + title: event.title, + start: event.start, + end: event.end, + }, + }); + + useEffect(() => { + if (event) { + methods.reset({ + title: event.title, + start: new Date(event.start), + end: new Date(event.end), + }); + } + }, [event, methods]); + + const { mutate: mutateDeleteEvent } = useMutation({ + mutationFn: deleteEvent, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['events'] }); + toast.success('Wydarzenie zostało usunięte'); + onOpenChange(false); + }, + onError: (error: Error) => { + console.error('Error deleting event:', error); + toast.error('Wystąpił błąd podczas usuwania wydarzenia'); + }, + }); + + const { mutate } = useMutation({ + mutationFn: updateEvent, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['events'] }); + toast.success('Wydarzenie zostało zaktualizowane'); + onOpenChange(false); + methods.reset(); + }, + onError: (error: Error) => { + console.error('Error updating event:', error); + toast.error('wystąpił błąd'); + }, + }); + + const onSubmit = (data: Event) => { + const { title, start, end } = data; + if (!title || !start || !end) { + toast.info('Please fill in all fields'); + return; + } + console.log(start); + console.log(end); + mutate({ + id: event.id, + title, + start: start, + end: end, + }); + }; + return ( + + + + {event.title} + + Edytuj lub usuń wydarzenie. Zapisz zmiany gdy skończysz. + + + +
    +
    +
    + + +
    +
    + +
    + methods.setValue('start', date)} + /> +
    +
    +
    + +
    + methods.setValue('end', date)} + /> +
    +
    +
    + + + + +
    +
    +
    +
    + ); +}; diff --git a/src/app/dashboard/calendar/_components/BigCalendar/bigCalendarStyling.css b/src/app/dashboard/calendar/_components/BigCalendar/bigCalendarStyling.css new file mode 100644 index 0000000..0d9d841 --- /dev/null +++ b/src/app/dashboard/calendar/_components/BigCalendar/bigCalendarStyling.css @@ -0,0 +1,676 @@ +.rbc-btn { + color: inherit; + font: inherit; + margin: 0; +} +button.rbc-btn { + overflow: visible; + text-transform: none; + -webkit-appearance: button; + cursor: pointer; +} +button[disabled].rbc-btn { + cursor: not-allowed; +} +button.rbc-input::-moz-focus-inner { + border: 0; + padding: 0; +} +.rbc-calendar { + box-sizing: border-box; + height: 100%; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: stretch; + -ms-flex-align: stretch; + align-items: stretch; +} +.rbc-calendar *, +.rbc-calendar *:before, +.rbc-calendar *:after { + box-sizing: inherit; +} +.rbc-abs-full, +.rbc-row-bg { + overflow: visible; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} +.rbc-ellipsis, +.rbc-event-label, +.rbc-row-segment .rbc-event-content, +.rbc-show-more { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.rbc-rtl { + direction: rtl; +} +.rbc-off-range { + color: hsl(var(--muted-foreground)); +} +.rbc-off-range-bg { + background: hsl(var(--muted)); +} +.rbc-header { + overflow: hidden; + -webkit-flex: 1 0 0%; + -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 hsl(var(--border)); + border-right: 1px solid hsl(var(--border)); +} +.rbc-rtl .rbc-header + .rbc-header { + border-left-width: 0; + border-right: 1px solid hsl(var(--border)); +} +.rbc-header > a, +.rbc-header > a:active, +.rbc-header > a:visited { + color: inherit; + text-decoration: none; +} +.rbc-row-content { + position: relative; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-user-select: none; + z-index: 4; +} +.rbc-today { + background-color: hsl(var(--accent)); +} +.rbc-toolbar { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + margin-bottom: 10px; + font-size: 16px; + justify-content: center; +} +.rbc-toolbar .rbc-toolbar-label { + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + margin: 0 0.25rem; + text-align: center; + font-weight: 700; + min-width: 200px; +} +.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; +} +.rbc-btn-group > button:last-child:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.rbc-rtl .rbc-btn-group > button:first-child:not(:last-child) { + border-radius: var(--radius); + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.rbc-rtl .rbc-btn-group > button:last-child:not(:first-child) { + border-radius: var(--radius); + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.rbc-btn-group > button:not(:first-child):not(:last-child) { + border-radius: 0; +} +.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; +} +.rbc-event { + background-color: hsl(var(--primary)); + color: hsl(var(--primary-foreground)); + padding: 5px; + border-radius: var(--radius); + cursor: pointer; +} +.rbc-slot-selecting .rbc-event { + cursor: inherit; + pointer-events: none; +} +.rbc-event-label { + font-size: 50%; +} +.rbc-event-overlaps { + 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-event-continues-day-after { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +.rbc-event-continues-day-prior { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.rbc-row { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -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; + white-space: nowrap; +} +.rbc-month-view { + position: relative; + border: 1px solid hsl(var(--border)); + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-flex: 1 0 0; + -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-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; +} +.rbc-month-row { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-flex: 1 0 0; + -ms-flex: 1 0 0px; + flex: 1 0 0; + -webkit-flex-basis: 0px; + -ms-flex-preferred-size: 0px; + flex-basis: 0px; + overflow: hidden; + height: 100%; +} +.rbc-month-row + .rbc-month-row { + border-top: 1px solid hsl(var(--border)); +} +.rbc-date-cell { + -webkit-flex: 1 1 0; + -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-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-flex: 1 0 0; + -ms-flex: 1 0 0px; + flex: 1 0 0; + overflow: hidden; +} +.rbc-day-bg { + -webkit-flex: 1 0 0%; + -ms-flex: 1 0 0%; + flex: 1 0 0%; +} +.rbc-rtl .rbc-day-bg + .rbc-day-bg { + border-left-width: 0; + border-right: 1px solid hsl(var(--border)); +} +.rbc-overlay { + position: absolute; + z-index: 5; + border: 1px solid hsl(var(--border)); + background-color: hsl(var(--card)); + padding: 10px; +} +.rbc-overlay > * + * { + margin-top: 1px; +} +.rbc-overlay-header { + border-bottom: 1px solid hsl(var(--border)); + margin: -10px -10px 5px -10px; + padding: 2px 10px; +} +.rbc-agenda-view { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-flex: 1 0 0; + -ms-flex: 1 0 0px; + flex: 1 0 0; + overflow: auto; +} +.rbc-agenda-view table.rbc-agenda-table { + width: 100%; + border-bottom: 1px solid hsl(var(--border)); + 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 { + border-left: 1px solid hsl(var(--border)); +} +.rbc-rtl .rbc-agenda-view table.rbc-agenda-table tbody > tr > td + td { + border-left-width: 0; + border-right: 1px solid hsl(var(--border)); +} +.rbc-agenda-view table.rbc-agenda-table tbody > tr + tr { + border-top: 1px solid hsl(var(--border)); +} +.rbc-agenda-view table.rbc-agenda-table thead > tr > th { + padding: 3px 5px; + text-align: left; + border-bottom: 1px solid hsl(var(--border)); +} +.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-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + min-height: 100%; +} +.rbc-time-column .rbc-timeslot-group { + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; +} +.rbc-timeslot-group { + border-bottom: 1px solid hsl(var(--border)); + min-height: 40px; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-flow: column nowrap; + -ms-flex-flow: column nowrap; + flex-flow: column nowrap; +} +.rbc-time-gutter, +.rbc-header-gutter { + -webkit-flex: none; + -ms-flex: none; + flex: none; +} +.rbc-label { + padding: 0 5px; +} +.rbc-day-slot { + position: relative; +} +.rbc-day-slot .rbc-events-container { + bottom: 0; + left: 0; + position: absolute; + right: 10px; + top: 0; +} +.rbc-day-slot .rbc-events-container.rbc-is-rtl { + left: 10px; + right: 0; +} +.rbc-day-slot .rbc-event { + border: 1px solid hsla(var(--primary), 0.9); + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + max-height: 100%; + min-height: 20px; + -webkit-flex-flow: column wrap; + -ms-flex-flow: column wrap; + flex-flow: column wrap; + -webkit-align-items: flex-start; + -ms-flex-align: start; + align-items: flex-start; + overflow: scroll; + position: absolute; +} +.rbc-day-slot .rbc-event-label { + -webkit-flex: none; + -ms-flex: none; + flex: none; + padding-right: 5px; + width: auto; +} +.rbc-day-slot .rbc-event-content { + width: 100%; + -webkit-flex: 1 1 0; + -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 hsla(var(--border), 0.5); +} +.rbc-time-slot { + -webkit-flex: 1 0 0; + -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-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + width: 100%; + border: 1px solid hsl(var(--border)); + min-height: 0; +} +.rbc-time-view .rbc-time-gutter { + white-space: nowrap; +} +.rbc-time-view .rbc-allday-cell { + box-sizing: content-box; + width: 100%; + position: relative; +} +.rbc-time-view .rbc-allday-events { + position: relative; + z-index: 4; +} +.rbc-time-view .rbc-row { + box-sizing: border-box; + min-height: 20px; +} +.rbc-time-header { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; +} +.rbc-rtl .rbc-time-header.rbc-overflowing { + border-right-width: 0; + border-left: 1px solid hsl(var(--border)); +} +.rbc-time-header > .rbc-row:first-child { + border-bottom: 1px solid hsl(var(--border)); +} +.rbc-time-header > .rbc-row.rbc-row-resource { + border-bottom: 1px solid hsl(var(--border)); +} +.rbc-time-header-content { + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + min-width: 0; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + border-left: 1px solid hsl(var(--border)); +} +.rbc-rtl .rbc-time-header-content { + border-left-width: 0; + border-right: 1px solid hsl(var(--border)); +} +.rbc-time-content { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex: 1 0 0%; + -ms-flex: 1 0 0%; + flex: 1 0 0%; + -webkit-align-items: flex-start; + -ms-flex-align: start; + align-items: flex-start; + width: 100%; + border-top: 2px solid hsl(var(--border)); + overflow-y: auto; + position: relative; +} +.rbc-time-content > .rbc-time-gutter { + -webkit-flex: none; + -ms-flex: none; + flex: none; +} +.rbc-time-content > * + * > * { + border-left: 1px solid hsl(var(--border)); +} +.rbc-rtl .rbc-time-content > * + * > * { + border-left-width: 0; + border-right: 1px solid hsl(var(--border)); +} +.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 { + border-top: 2px solid hsl(var(--destructive)) !important; + width: 100%; + z-index: 10; + position: absolute; + pointer-events: none; +} +.rbc-calendar { + background-color: hsl(var(--background)); + border-radius: var(--radius); + color: hsl(var(--foreground)); + border: solid 1px hsl(var(--border)); + overflow: hidden; +} +.rbc-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + font-size: 16px; + padding: 0 0.25rem 0 0.25rem; + border-bottom: solid 1px hsl(var(--border)); + margin-bottom: 0; +} +.rbc-toolbar button { + background-color: transparent; + border: none; + height: 40px; + padding: 8px 16px; + border-radius: var(--radius); + cursor: pointer; + transition: none; + margin-top: 0.25rem; + margin-bottom: 0.25rem; + box-shadow: none !important; + color: hsl(var(--foreground)) !important; +} +.rbc-toolbar button.rbc-active { + color: hsl(var(--accent-foreground)) !important; + background-color: hsl(var(--accent)) !important; +} +.rbc-toolbar button:hover { + background-color: hsl(var(--accent)) !important; + color: hsl(var(--accent-foreground)); +} +.rbc-time-view { + margin-top: 0; + border: none; +} +.rbc-time-header { + background-color: hsl(var(--card)); + border-bottom: 1px solid hsl(var(--border)); +} +.rbc-time-gutter { + background-color: hsl(var(--card)); +} +.rbc-day-bg { + background-color: hsl(var(--card)); + border-right: 1px solid hsl(var(--border)); +} +.rbc-month-view { + border: none; +} +.rbc-event:hover { + background-color: hsl(var(--ring)); +} +.event-component { + background-color: hsl(var(--primary)); + color: hsl(var(--primary-foreground)); + padding: 5px; + border-radius: var(--radius); + font-size: 14px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.rbc-current-time-indicator { + background-color: 2px solid hsl(var(--destructive)) !important; + z-index: 3; + position: absolute; + pointer-events: none; + height: 1px; +} +.rbc-agenda-empty { + color: hsl(var(--muted-foreground)); + display: flex; + height: 100%; + align-items: center; + justify-content: center; +} diff --git a/src/app/dashboard/calendar/page.tsx b/src/app/dashboard/calendar/page.tsx new file mode 100644 index 0000000..267495d --- /dev/null +++ b/src/app/dashboard/calendar/page.tsx @@ -0,0 +1,42 @@ +import { checkUserRole } from '@/actions/checkUserRole'; +import { RoleGuard } from '@/components/shared/RoleGuard'; +import { Skeleton } from '@/components/ui/skeleton'; +import { getQueryClient } from '@/lib/getQueryClient'; +import { fetchDrivers } from '@/services/events/fetchDrivers'; +import { getEventsQueryOptions } from '@/services/events/fetchEvents'; +import { HydrationBoundary, dehydrate } from '@tanstack/react-query'; +import { Suspense } from 'react'; +import AddEventDialog from './_components/AddEventDialog'; +import BigCalendar from './_components/BigCalendar/BigCalendar'; + +export default async function CalendarPage() { + const queryClient = getQueryClient(); + + // Determine role from session + const { hasRole } = await checkUserRole(); + const endpoint = hasRole(['instructor']) ? 'instructor' : 'driver'; + const drivers = hasRole(['instructor']) ? await fetchDrivers() : []; + + // Prefetch the events on the server side + await queryClient.prefetchQuery(getEventsQueryOptions(endpoint)); + + return ( +
    + + + + + } + > + + + + + + + +
    + ); +} diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx index 68755ee..c987e1c 100644 --- a/src/app/dashboard/layout.tsx +++ b/src/app/dashboard/layout.tsx @@ -1,6 +1,5 @@ import SideMenu from '@/app/dashboard/_components/SideMenu'; import { ReactNode } from 'react'; -import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; export default async function DashboardLayout({ @@ -14,7 +13,6 @@ export default async function DashboardLayout({ {/* CONTENT */}
    {children}
    - ); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 1c24b11..098e3ac 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,6 @@ +import Providers from '@/providers'; import type { Metadata } from 'next'; import { ReactNode } from 'react'; -import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; import './globals.css'; @@ -15,13 +15,10 @@ export default function RootLayout({ children: ReactNode; }>) { return ( - <> - - - {children} - - - - + + + {children} + + ); } diff --git a/src/components/ui/calendar.tsx b/src/components/ui/calendar.tsx new file mode 100644 index 0000000..0299293 --- /dev/null +++ b/src/components/ui/calendar.tsx @@ -0,0 +1,112 @@ +'use client'; + +import { buttonVariants } from '@/components/ui/button'; +import { ScrollArea } from '@/components/ui/scroll-area'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { cn } from '@/lib/utils'; +import { ChevronLeft, ChevronRight } from 'lucide-react'; +import * as React from 'react'; +import { DayPicker, DropdownProps } from 'react-day-picker'; + +export type CalendarProps = React.ComponentProps; + +function Calendar({ + className, + classNames, + showOutsideDays = true, + ...props +}: CalendarProps) { + return ( + { + const options = React.Children.toArray( + children, + ) as React.ReactElement>[]; + const selected = options.find((child) => child.props.value === value); + const handleChange = (value: string) => { + const changeEvent = { + target: { value }, + } as React.ChangeEvent; + onChange?.(changeEvent); + }; + return ( + + ); + }, + IconLeft: () => , + IconRight: () => , + }} + {...props} + /> + ); +} +Calendar.displayName = 'Calendar'; + +export { Calendar }; diff --git a/src/components/ui/dateTimePicker.tsx b/src/components/ui/dateTimePicker.tsx new file mode 100644 index 0000000..d5831ef --- /dev/null +++ b/src/components/ui/dateTimePicker.tsx @@ -0,0 +1,101 @@ +'use client'; + +import { cn } from '@/lib/utils'; +import { format } from 'date-fns'; +import { CalendarIcon } from 'lucide-react'; +import { useState } from 'react'; +import { Button } from './button'; +import { Calendar } from './calendar'; +import { Popover, PopoverContent, PopoverTrigger } from './popover'; +import { ScrollArea } from './scroll-area'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from './select'; + +type DateTimePickerProps = { + value: Date; + onChange: (value: Date) => void; +}; + +export function DateTimePicker({ value, onChange }: DateTimePickerProps) { + const [isOpen, setIsOpen] = useState(false); + + const initialTime = `${value.getHours().toString().padStart(2, '0')}:${value + .getMinutes() + .toString() + .padStart(2, '0')}`; + + const [time, setTime] = useState(initialTime); + const [date, setDate] = useState(value); + + return ( + + + + + + { + if (!selectedDate) return; + const [hours, minutes] = time.split(':'); + selectedDate?.setHours(parseInt(hours), parseInt(minutes)); + setDate(selectedDate); + onChange(selectedDate); + }} + fromYear={2000} + toYear={new Date().getFullYear()} + disabled={(date) => + Number(date) < Date.now() - 1000 * 60 * 60 * 24 || + Number(date) > Date.now() + 1000 * 60 * 60 * 24 * 30 + } + /> + + + + ); +} diff --git a/src/components/ui/form.tsx b/src/components/ui/form.tsx new file mode 100644 index 0000000..6b5c3bb --- /dev/null +++ b/src/components/ui/form.tsx @@ -0,0 +1,179 @@ +'use client'; + +import * as React from 'react'; +import * as LabelPrimitive from '@radix-ui/react-label'; +import { Slot } from '@radix-ui/react-slot'; +import { + Controller, + ControllerProps, + FieldPath, + FieldValues, + FormProvider, + useFormContext, +} from 'react-hook-form'; + +import { cn } from '@/lib/utils'; +import { Label } from '@/components/ui/label'; + +const Form = FormProvider; + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath, +> = { + name: TName; +}; + +const FormFieldContext = React.createContext( + {} as FormFieldContextValue, +); + +const FormField = < + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath, +>({ + ...props +}: ControllerProps) => { + return ( + + + + ); +}; + +const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext); + const itemContext = React.useContext(FormItemContext); + const { getFieldState, formState } = useFormContext(); + + const fieldState = getFieldState(fieldContext.name, formState); + + if (!fieldContext) { + throw new Error('useFormField should be used within '); + } + + const { id } = itemContext; + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + }; +}; + +type FormItemContextValue = { + id: string; +}; + +const FormItemContext = React.createContext( + {} as FormItemContextValue, +); + +const FormItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const id = React.useId(); + + return ( + +
    + + ); +}); +FormItem.displayName = 'FormItem'; + +const FormLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + const { error, formItemId } = useFormField(); + + return ( +