diff --git a/app/i18n/messages/en.json b/app/i18n/messages/en.json index ab8d77a07..0d625501c 100644 --- a/app/i18n/messages/en.json +++ b/app/i18n/messages/en.json @@ -243,6 +243,7 @@ "NotFoundPage.searchPageLink": "search page", "NotFoundPage.title": "404 Page not found", "Notifications.cannotReserveDuringMaintenance": "Cannot make reservations during maintenance.", + "Notifications.continousFreeDaysError": "You can only select a continuous period of available days", "Notifications.errorMessage": "Something went wrong. Please try again in a moment.", "Notifications.loginErrorMessage": "Failed to login. Please try again in a moment.", "Notifications.userFetchErrorMessage": "Failed to retrieve user info. Please try again in a moment.", @@ -266,6 +267,7 @@ "Overnight.legend.ownSelection": "Own selection", "Overnight.legend.reserved": "Reserved", "Overnight.nextMonth": "Next month", + "Overnight.overMaxAlert": "The selected time is over the maximum duration", "Overnight.prevMonth": "Previous month", "Partners.kaupunginkirjatoImageAlt": "Helsinki City Library", "Partners.nuorisoasiainkeskusImageAlt": "City of Helsinki – Youth Department", diff --git a/app/i18n/messages/fi.json b/app/i18n/messages/fi.json index 0b0e70420..f9d561657 100644 --- a/app/i18n/messages/fi.json +++ b/app/i18n/messages/fi.json @@ -243,6 +243,7 @@ "NotFoundPage.searchPageLink": "hakusivulta", "NotFoundPage.title": "404 Sivua ei löydy", "Notifications.cannotReserveDuringMaintenance": "Huoltotyön aikana ei voi tehdä varauksia.", + "Notifications.continousFreeDaysError": "Voit valita vain yhtenäisen jakson vapaita päiviä", "Notifications.errorMessage": "Jotain meni vikaan. Yritä hetken päästä uudelleen.", "Notifications.loginErrorMessage": "Kirjautuminen epäonnistui. Yritä hetken päästä uudelleen.", "Notifications.userFetchErrorMessage": "Käyttäjätietojen hakeminen epäonnistui. Yritä hetken päästä uudelleen.", @@ -266,6 +267,7 @@ "Overnight.legend.ownSelection": "Oma valinta", "Overnight.legend.reserved": "Varattu", "Overnight.nextMonth": "Seuraava kuukausi", + "Overnight.overMaxAlert": "Valittu aika ylittää maksimipituuden", "Overnight.prevMonth": "Edellinen kuukausi", "Partners.kaupunginkirjatoImageAlt": "Helsingin kaupunginkirjasto", "Partners.nuorisoasiainkeskusImageAlt": "Helsingin kaupunki - nuorisoasiainkeskus", diff --git a/app/i18n/messages/sv.json b/app/i18n/messages/sv.json index 67a4736ed..9cad9fb73 100644 --- a/app/i18n/messages/sv.json +++ b/app/i18n/messages/sv.json @@ -245,6 +245,7 @@ "NotFoundPage.searchPageLink": "söksidan", "NotFoundPage.title": "404 Webbplatsen hittades inte", "Notifications.cannotReserveDuringMaintenance": "Det går inte att göra reservationer under underhåll.", + "Notifications.continousFreeDaysError": "Du kan bara välja en sammanhängande period av lediga dagar", "Notifications.errorMessage": "Ett fel uppstod. Försök på nytt om en liten stund.", "Notifications.loginErrorMessage": "Inloggning misslyckades. Försök igen om en liten stund.", "Notifications.userFetchErrorMessage": "Användarinformations hämtning misslyckades. Försök igen om en liten stund.", @@ -268,6 +269,7 @@ "Overnight.legend.ownSelection": "Egen val", "Overnight.legend.reserved": "Reserverad", "Overnight.nextMonth": "Nästa månad", + "Overnight.overMaxAlert": "Den valda tiden överskrider maximal varaktighet", "Overnight.prevMonth": "Föregående månad", "Partners.kaupunginkirjatoImageAlt": "Helsingfors stadsbibliotek", "Partners.nuorisoasiainkeskusImageAlt": "Helsingfors stad - ungdomscentralen", diff --git a/app/shared/overnight-calendar/OvernightCalendar.js b/app/shared/overnight-calendar/OvernightCalendar.js index a6b5998dd..1ad281fdf 100644 --- a/app/shared/overnight-calendar/OvernightCalendar.js +++ b/app/shared/overnight-calendar/OvernightCalendar.js @@ -20,7 +20,9 @@ import { handleDisableDays, handleFormattingSelected, isDurationBelowMin, + isDurationOverMax, isReservingAllowed, + isSelectionContinous, nextDayBookedModifier, nextDayClosedModifier, prevDayBookedModifier, @@ -78,14 +80,23 @@ function OvernightCalendar({ const selectedDuration = getSelectedDuration( startDate, endDate, overnightStartTime, overnightEndTime); const isDurBelowMin = isDurationBelowMin(selectedDuration, minPeriod); - const minDurationText = getPrettifiedPeriodUnits(minPeriod, t('common.unit.time.day.short')); if (isDurBelowMin) { + const minDurationText = getPrettifiedPeriodUnits(minPeriod, t('common.unit.time.day.short')); actions.addNotification({ message: `${t('Overnight.belowMinAlert')} (${minDurationText})`, type: 'info', timeOut: 10000, }); } + const isDurOverMax = isDurationOverMax(selectedDuration, maxPeriod); + if (isDurOverMax) { + const maxDurationText = getPrettifiedPeriodUnits(maxPeriod, t('common.unit.time.day.short')); + actions.addNotification({ + message: `${t('Overnight.overMaxAlert')} (${maxDurationText})`, + type: 'info', + timeOut: 10000, + }); + } } }, [startDate, endDate]); @@ -107,20 +118,16 @@ function OvernightCalendar({ }); const validateAndSelect = (day, { booked, nextBooked, nextClosed }) => { - const isNextBlocked = !startDate && (nextBooked || nextClosed); + const isNextBlocked = (!startDate || (startDate && endDate)) && (nextBooked || nextClosed); const isDateDisabled = handleDisableDays({ day, now, reservable, reservableAfter, reservableBefore, - startDate, openingHours, reservations: filteredReservations, - maxPeriod, minPeriod, - overnightEndTime, - overnightStartTime, hasAdminBypass: isUnitManagerOrHigher, }); @@ -135,6 +142,16 @@ function OvernightCalendar({ return; } + if ((startDate && !endDate) + && !isSelectionContinous(startDate, day, filteredReservations, openingHours)) { + actions.addNotification({ + message: t('Notifications.continousFreeDaysError'), + type: 'info', + timeOut: 10000, + }); + return; + } + if (!isDateDisabled && !booked && !isNextBlocked) { handleDateSelect({ value: day, @@ -184,6 +201,9 @@ function OvernightCalendar({ const isDurBelowMin = isUnitAdminOrHigher ? false : isDurationBelowMin(selectedDuration, minPeriod); + const isDurOverMax = isUnitAdminOrHigher ? false + : isDurationOverMax(selectedDuration, maxPeriod); + return (
closedDaysModifier(day, openingHours), - booked: (day) => ( - startDate ? null : reservationsModifier(day, filteredReservations)), - nextBooked: (day) => ( - startDate ? null : nextDayBookedModifier(day, filteredReservations)), - nextBookedStartSelected: (day) => ( - startDate ? nextDayBookedModifier(day, filteredReservations) : null), + booked: (day) => reservationsModifier(day, filteredReservations), + nextBooked: (day) => nextDayBookedModifier(day, filteredReservations), nextClosed: (day) => nextDayClosedModifier(day, openingHours), - prevBooked: (day) => ( - startDate ? null : prevDayBookedModifier(day, filteredReservations)), + prevBooked: (day) => prevDayBookedModifier(day, filteredReservations), prevClosed: (day) => prevDayClosedModifier(day, openingHours), }} onDayClick={validateAndSelect} @@ -243,6 +254,8 @@ function OvernightCalendar({ endDatetime={getOvernightDatetime(endDate, overnightEndTime, t)} handleSelectDatetimes={handleSelectDatetimes} isDurationBelowMin={isDurBelowMin} + isDurationOverMax={isDurOverMax} + maxDuration={maxPeriod || ''} minDuration={minPeriod} selected={selected} startDatetime={getOvernightDatetime(startDate, overnightStartTime, t)} @@ -254,6 +267,8 @@ function OvernightCalendar({ duration={selectedDuration} endDatetime={getOvernightDatetime(endDate, overnightEndTime, t)} isDurationBelowMin={isDurBelowMin} + isDurationOverMax={isDurOverMax} + maxDuration={maxPeriod || ''} minDuration={minPeriod} onCancel={onEditCancel} onConfirm={handleSelectDatetimes} diff --git a/app/shared/overnight-calendar/OvernightEditSummary.js b/app/shared/overnight-calendar/OvernightEditSummary.js index af3f4340f..e19adbd5c 100644 --- a/app/shared/overnight-calendar/OvernightEditSummary.js +++ b/app/shared/overnight-calendar/OvernightEditSummary.js @@ -8,12 +8,15 @@ import { getPrettifiedPeriodUnits } from '../../utils/timeUtils'; function OvernightEditSummary({ startDatetime, endDatetime, selected, onCancel, onConfirm, t, - duration, minDuration, isDurationBelowMin, datesSameAsInitial + duration, minDuration, isDurationBelowMin, datesSameAsInitial, + maxDuration, isDurationOverMax }) { const timeRange = startDatetime && endDatetime ? `${startDatetime} - ${endDatetime}` : `${selected[0]} - ${selected[1]}`; const durationText = getPrettifiedPeriodUnits(duration, t('common.unit.time.day.short')); const minDurationText = getPrettifiedPeriodUnits(minDuration, t('common.unit.time.day.short')); + const maxDurationText = getPrettifiedPeriodUnits(maxDuration, t('common.unit.time.day.short')); const hasMinDurationError = !datesSameAsInitial && isDurationBelowMin; + const hasMaxDurationError = !datesSameAsInitial && isDurationOverMax; const validRange = startDatetime && endDatetime; return ( @@ -32,6 +35,9 @@ function OvernightEditSummary({ {hasMinDurationError && (

{`${t('Overnight.belowMinAlert')} (${minDurationText})`}

)} + {hasMaxDurationError && ( +

{`${t('Overnight.overMaxAlert')} (${maxDurationText})`}

+ )}