diff --git a/package-lock.json b/package-lock.json index 2562b2b..9782efd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,8 @@ "name": "web-frontend", "version": "0.0.0", "dependencies": { - "@picocss/pico": "^1.5.10" + "@picocss/pico": "^1.5.10", + "moment": "^2.29.4" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^2.4.2", @@ -1059,6 +1060,14 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", diff --git a/package.json b/package.json index a1e60c1..fe7278b 100644 --- a/package.json +++ b/package.json @@ -1,25 +1,25 @@ { - "name": "web-frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview", - "check": "svelte-check --tsconfig ./tsconfig.json" - }, - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^2.4.2", - "@tsconfig/svelte": "^5.0.0", - "svelte": "^4.0.5", - "svelte-check": "^3.4.6", - "svelte-routing": "^2.5.0", - "tslib": "^2.6.0", - "typescript": "^5.0.2", - "vite": "^4.4.5" - }, - "dependencies": { - "@picocss/pico": "^1.5.10" - } + "name": "web-frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "check": "svelte-check --tsconfig ./tsconfig.json" + }, + "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^2.4.2", + "@tsconfig/svelte": "^5.0.0", + "svelte": "^4.0.5", + "svelte-check": "^3.4.6", + "svelte-routing": "^2.5.0", + "tslib": "^2.6.0", + "typescript": "^5.0.2", + "vite": "^4.4.5" + }, + "dependencies": { + "@picocss/pico": "^1.5.10" + } } diff --git a/src/model/reservation.model.ts b/src/model/reservation.model.ts index 13bc351..e8363cf 100644 --- a/src/model/reservation.model.ts +++ b/src/model/reservation.model.ts @@ -14,7 +14,12 @@ export interface Reservation extends StartEndTime { owner: string; } -export type ReservationStoreData = Reservation[] | null; +export interface ReservationStore { + reservations: Reservation[]; + for: Date; +} + +export type ReservationStoreData = ReservationStore | null; export const mapDtoToReservation = (dto: ReservationDto): Reservation => { return { diff --git a/src/model/reservation.store.ts b/src/model/reservation.store.ts index 3dd1550..e76a264 100644 --- a/src/model/reservation.store.ts +++ b/src/model/reservation.store.ts @@ -20,13 +20,25 @@ const mockedReservations: ReservationDto[] = [ start_time: '2023-10-30T12:00:00.00+01:00', end_time: '2023-10-30T13:00:00.00+01:00', }, + { + id: '3', + owner: '3', + start_time: '2023-10-29T15:00:00.00+01:00', + end_time: '2023-10-29T16:00:00.00+01:00', + }, + { + id: '4', + owner: '4', + start_time: '2023-10-29T10:00:00.00+01:00', + end_time: '2023-10-29T12:00:00.00+01:00', + }, ]; export const reservationStore = writable(null); const sortReservations = (reservations: Reservation[]): Reservation[] => { return reservations?.sort((reservationA, reservationB) => - reservationA.startTime.isAfter(reservationB.startTime) ? -1 : 1 + reservationA.startTime.isBefore(reservationB.startTime) ? -1 : 1 ); }; @@ -36,7 +48,7 @@ const filterReservations = const now = new Date(); let isValid = dateToFilterFor.isSameDay(reservation.startTime); if (now.isSameDay(dateToFilterFor)) { - isValid = isValid && reservation.startTime.isAfter(now); + isValid = isValid && reservation.startTime.isBefore(now); } return isValid; }; @@ -49,7 +61,7 @@ export const loadReservationsForDay = (date: Date): void => { .map(mapDtoToReservation) .filter(filterReservations(date)) ); - reservationStore.set(reservations); + reservationStore.set({ reservations, for: date }); }; export const createReservation = async ( @@ -62,12 +74,17 @@ export const createReservation = async ( start_time: startTime.toISOString(), end_time: endTime.toISOString(), }).then((json) => { - reservationStore.update((reservations) => { - const newReservations = !!reservations ? reservations : []; - return sortReservations([ - ...newReservations, - mapDtoToReservation(json), - ]); + reservationStore.update((storeData) => { + if (storeData) { + return { + ...storeData, + reservations: sortReservations([ + ...(storeData?.reservations ?? []), + mapDtoToReservation(json), + ]), + }; + } + return null; }); }); }; diff --git a/src/routes/calendar/Calendar.svelte b/src/routes/calendar/Calendar.svelte index b960318..d7c978b 100644 --- a/src/routes/calendar/Calendar.svelte +++ b/src/routes/calendar/Calendar.svelte @@ -19,10 +19,11 @@ $: if (selecedDate) loadReservationsForDay(selecedDate); - reservationStore.subscribe((allReservations) => { - hasReservations = !!allReservations && allReservations?.length > 0; + reservationStore.subscribe((storeData) => { + hasReservations = !!storeData && storeData?.reservations.length > 0; + selecedDate = storeData?.for; if (hasReservations) { - reservations = allReservations!; + reservations = storeData!.reservations; } }); @@ -30,7 +31,7 @@ let defaultEnd = getSelectedDateWithTime(DEFAULT_DAY_END); if (index < reservations.length) { - const nextReservation = reservations.at(index + 1); + const nextReservation = reservations.at(index); return nextReservation?.startTime ?? defaultEnd; } @@ -42,8 +43,13 @@ }; const getSelectedDateWithTime = (time: number): Date => { - let date = new Date(selecedDate!); - date.setHours(time); + let date = new Date(); + if (selecedDate?.isToday()) { + date.setHours(date.getHours(), date.getMinutes() + 1, 0); + } else { + date = new Date(selecedDate!); + date.setHours(time, 0); + } return date; }; @@ -54,13 +60,18 @@
{#if hasReservations}

Reservations for: {selecedDate.toWeekdayString()}

+ {#each reservations as reservation, i (i)} - {#if showBookingButton(reservation.endTime, getAvailableUntil(i))} + {#if showBookingButton(reservation.endTime, getAvailableUntil(i + 1))} {/if} {/each} diff --git a/src/routes/calendar/components/BookingTimeSelection.svelte b/src/routes/calendar/components/BookingTimeSelection.svelte index 7f1b695..f59e103 100644 --- a/src/routes/calendar/components/BookingTimeSelection.svelte +++ b/src/routes/calendar/components/BookingTimeSelection.svelte @@ -19,8 +19,6 @@ $: if (timeStr) startTime = newDateWithTime(selecedDate, timeStr); $: if (startTime) endTime = new Date(startTime).addHours(DEFAULT_BOOKING_HOURS); - $: invalid = - startTime?.isAfter(availableFrom) || endTime?.isBefore(availableUntil); const cancelBooking = () => dispatch('cancelBooking'); const addBooking = () => { @@ -32,14 +30,12 @@
- {$userStore?.id} @@ -48,7 +44,7 @@ {/if}
- +
diff --git a/src/routes/calendar/components/DateSelector.svelte b/src/routes/calendar/components/DateSelector.svelte index 81b086c..2463387 100644 --- a/src/routes/calendar/components/DateSelector.svelte +++ b/src/routes/calendar/components/DateSelector.svelte @@ -2,7 +2,7 @@ import Datepicker from '../../../lib/Datepicker.svelte'; export let selecedDate: Date | undefined; - let pickedDate: string; + let pickedDate: string = selecedDate?.toShortISOString() ?? ''; $: selecedDate = !!pickedDate ? new Date(pickedDate) : undefined; diff --git a/src/routes/home/BookingSelection.svelte b/src/routes/home/BookingSelection.svelte index a651f06..0d503d5 100644 --- a/src/routes/home/BookingSelection.svelte +++ b/src/routes/home/BookingSelection.svelte @@ -1,8 +1,12 @@

When would you like to wash?

- - + + diff --git a/src/utils/date.extenstions.ts b/src/utils/date.extenstions.ts index ee1137a..299f31a 100644 --- a/src/utils/date.extenstions.ts +++ b/src/utils/date.extenstions.ts @@ -1,3 +1,5 @@ +import moment from 'moment'; + export {}; declare global { @@ -5,6 +7,7 @@ declare global { addHours(hours: number): Date; addDays(days: number): Date; isSameDay(otherDate: Date): boolean; + isToday(): boolean; toWeekdayString(): string; toTime(): string; toShortISOString(): string; @@ -30,6 +33,15 @@ Date.prototype.isSameDay = function (otherDate: Date): boolean { return thisDateStr === otherDateStr; }; +Date.prototype.isToday = function (): boolean { + const today = new Date(); + return ( + this.getDate() == today.getDate() && + this.getMonth() == today.getMonth() && + this.getFullYear() == today.getFullYear() + ); +}; + Date.prototype.toWeekdayString = function (): string { return this.toLocaleDateString('en-us', { day: '2-digit', @@ -46,11 +58,11 @@ Date.prototype.toTime = function (): string { }; Date.prototype.isAfter = function (otherDate: Date): boolean { - return this.getTime() < otherDate.getTime(); + return moment(this).isAfter(otherDate); }; Date.prototype.isBefore = function (otherDate: Date): boolean { - return this.getTime() > otherDate.getTime(); + return moment(this).isBefore(otherDate); }; Date.prototype.toShortISOString = function (): string {