diff --git a/geneit_app/package-lock.json b/geneit_app/package-lock.json index 174d238..8622b02 100644 --- a/geneit_app/package-lock.json +++ b/geneit_app/package-lock.json @@ -23,6 +23,7 @@ "@mui/lab": "^5.0.0-alpha.140", "@mui/material": "^5.15.17", "@mui/x-data-grid": "^7.1.1", + "@mui/x-date-pickers": "^7.7.0", "@mui/x-tree-view": "^7.4.0", "@testing-library/jest-dom": "^6.4.5", "@testing-library/react": "^16.0.0", @@ -32,6 +33,7 @@ "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.2.1", "date-and-time": "^3.2.0", + "dayjs": "^1.11.11", "email-validator": "^2.0.4", "filesize": "^10.1.2", "jspdf": "^2.5.1", @@ -1579,6 +1581,71 @@ "react-dom": "^17.0.0 || ^18.0.0" } }, + "node_modules/@mui/x-date-pickers": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.7.0.tgz", + "integrity": "sha512-huyoA22Vi8iCkee6ro0sX7CcFIcPV/Fl7ZGWwaQC8PTAheXhz823DjMYAiwRU/imF+UFYfUInWQ4XZCIkM+2Dw==", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@mui/base": "^5.0.0-beta.40", + "@mui/system": "^5.15.15", + "@mui/utils": "^5.15.14", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14", + "date-fns": "^2.25.0 || ^3.2.0", + "date-fns-jalali": "^2.13.0-0 || ^3.2.0-0", + "dayjs": "^1.10.7", + "luxon": "^3.0.2", + "moment": "^2.29.4", + "moment-hijri": "^2.1.2", + "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "date-fns": { + "optional": true + }, + "date-fns-jalali": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + }, + "moment-hijri": { + "optional": true + }, + "moment-jalaali": { + "optional": true + } + } + }, "node_modules/@mui/x-tree-view": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/@mui/x-tree-view/-/x-tree-view-7.7.0.tgz", @@ -2552,6 +2619,11 @@ "integrity": "sha512-UguWfh9LkUecVrGSE0B7SpAnGRMPATmpwSoSij24/lDnwET3A641abfDBD/TdL0T+E04f8NWlbMkD9BscVvIZg==", "license": "MIT" }, + "node_modules/dayjs": { + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", diff --git a/geneit_app/package.json b/geneit_app/package.json index ce72f20..f7872ec 100644 --- a/geneit_app/package.json +++ b/geneit_app/package.json @@ -19,6 +19,7 @@ "@mui/lab": "^5.0.0-alpha.140", "@mui/material": "^5.15.17", "@mui/x-data-grid": "^7.1.1", + "@mui/x-date-pickers": "^7.7.0", "@mui/x-tree-view": "^7.4.0", "@testing-library/jest-dom": "^6.4.5", "@testing-library/react": "^16.0.0", @@ -28,6 +29,7 @@ "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.2.1", "date-and-time": "^3.2.0", + "dayjs": "^1.11.11", "email-validator": "^2.0.4", "filesize": "^10.1.2", "jspdf": "^2.5.1", diff --git a/geneit_app/src/dialogs/accommodations/CreateAccommodationCalendarURLDialog.tsx b/geneit_app/src/dialogs/accommodations/CreateAccommodationCalendarURLDialog.tsx index f1fe0b8..d95abf0 100644 --- a/geneit_app/src/dialogs/accommodations/CreateAccommodationCalendarURLDialog.tsx +++ b/geneit_app/src/dialogs/accommodations/CreateAccommodationCalendarURLDialog.tsx @@ -9,9 +9,9 @@ import React from "react"; import { ServerApi } from "../../api/ServerApi"; import { NewCalendarURL } from "../../api/accommodations/AccommodationsCalendarURLApi"; import { checkConstraint } from "../../utils/from_utils"; +import { useAccommodations } from "../../widgets/accommodations/BaseAccommodationsRoute"; import { PropEdit } from "../../widgets/forms/PropEdit"; import { PropSelect } from "../../widgets/forms/PropSelect"; -import { useAccommodations } from "../../widgets/accommodations/BaseAccommodationsRoute"; export function CreateAccommodationCalendarURLDialog(p: { open: boolean; diff --git a/geneit_app/src/dialogs/accommodations/UpdateReservationDialog.tsx b/geneit_app/src/dialogs/accommodations/UpdateReservationDialog.tsx index 75fc5e4..841aae9 100644 --- a/geneit_app/src/dialogs/accommodations/UpdateReservationDialog.tsx +++ b/geneit_app/src/dialogs/accommodations/UpdateReservationDialog.tsx @@ -8,6 +8,7 @@ import { import React from "react"; import { UpdateAccommodationReservation } from "../../api/accommodations/AccommodationsReservationsApi"; import { useAccommodations } from "../../widgets/accommodations/BaseAccommodationsRoute"; +import { PropDateInput } from "../../widgets/forms/PropDateInput"; import { PropSelect } from "../../widgets/forms/PropSelect"; export function UpdateReservationDialog(p: { @@ -41,6 +42,8 @@ export function UpdateReservationDialog(p: { if (!reservation) setReservation(p.reservation); }, [p.open, p.reservation]); + // TODO : check availability + return ( @@ -66,6 +69,31 @@ export function UpdateReservationDialog(p: { value={reservation?.accommodation_id?.toString()} /> + { + setReservation((r) => { + return { ...r!, start: s ?? -1 }; + }); + }} + /> + + { + setReservation((r) => { + return { ...r!, end: s ?? -1 }; + }); + }} + /> + + {/* Constraint start and end */} + {/* TODO : la suite */} diff --git a/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx b/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx index 2fa5c6e..5d979a8 100644 --- a/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx +++ b/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx @@ -65,8 +65,8 @@ export function AccommodationsReservationsRoute(): React.ReactElement { updateReservation( { accommodation_id: -1, - start: Math.floor(d.start.getDate() / 1000), - end: Math.floor(d.end.getDate() / 1000), + start: Math.floor(d.start.getTime() / 1000), + end: Math.floor(d.end.getTime() / 1000), }, true ); diff --git a/geneit_app/src/utils/time_utils.ts b/geneit_app/src/utils/time_utils.ts new file mode 100644 index 0000000..aea8b50 --- /dev/null +++ b/geneit_app/src/utils/time_utils.ts @@ -0,0 +1,6 @@ +/** + * Get formatted UNIX date + */ +export function fmtUnixDate(time: number): string { + return new Date(time * 1000).toLocaleString("fr-FR"); +} diff --git a/geneit_app/src/widgets/forms/PropDateInput.tsx b/geneit_app/src/widgets/forms/PropDateInput.tsx new file mode 100644 index 0000000..914de98 --- /dev/null +++ b/geneit_app/src/widgets/forms/PropDateInput.tsx @@ -0,0 +1,53 @@ +import { LocalizationProvider } from "@mui/x-date-pickers"; +import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; +import { DatePicker } from "@mui/x-date-pickers/DatePicker"; +import dayjs from "dayjs"; +import { fmtUnixDate } from "../../utils/time_utils"; +import { PropEdit } from "./PropEdit"; + +export function PropDateInput(p: { + editable: boolean; + label: string; + value: number | undefined; + onChange: (v: number | undefined) => void; + lastSecOfDay?: boolean; +}): React.ReactElement { + let shiftV = p.value; + if (shiftV && p.lastSecOfDay) { + const d = new Date(shiftV * 1000); + if (d.getHours() === 0) { + shiftV -= 1; + } + } + + if (!p.editable) { + if (!shiftV) return <>; + + return ( + + ); + } + + const value = dayjs( + shiftV && p.value! > 0 ? new Date(shiftV * 1000) : undefined + ); + + return ( +
+ + { + if (v && p.lastSecOfDay) { + v.set("hours", 23); + v.set("minutes", 59); + v.set("seconds", 59); + } + p.onChange?.(v ? v.unix() : undefined); + }} + /> + +
+ ); +}