mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
fix(bookings): an end time before the start time on the same day shows a warning in the booking dialog
A booking saved with 18:00 to 09:00 and no end date was stored as ending earlier on its start day without a word. The dialog now says that the end time lies before the start time and that an end date is needed if it ends the next day, on desktop and on the phone. It only warns and does not block the save, since time zones can make such times correct. Refs #2604
This commit is contained in:
@@ -80,7 +80,7 @@ export function ReservationModal({ isOpen, onClose, onSave, reservation, days, p
|
||||
|
||||
const {
|
||||
form, setForm, set, isSaving, setIsSaving, pendingFiles, setPendingFiles, travelerIds, setTravelerIds, toggleTraveler,
|
||||
isEndBeforeStart, dateBounds: tripDateRange, startDate, startTime, setStartDate, setStartTime, takeStopDay,
|
||||
isEndBeforeStart, endTimeBeforeStartTime, dateBounds: tripDateRange, startDate, startTime, setStartDate, setStartTime, takeStopDay,
|
||||
pickPlace, pickHotelPlace, pickHotelStart, pickHotelEnd, saveData: buildSaveData,
|
||||
} = useReservationForm(EMPTY_FORM, days, places)
|
||||
const attach = useBookingFileAttach({ reservation, files, onFileUpload, setPendingFiles, toast, t })
|
||||
@@ -277,7 +277,10 @@ export function ReservationModal({ isOpen, onClose, onSave, reservation, days, p
|
||||
max={tripDateRange.max}
|
||||
/>
|
||||
</EditorField>
|
||||
<EditorField label={t('reservations.endTime')}>
|
||||
<EditorField
|
||||
label={t('reservations.endTime')}
|
||||
hint={endTimeBeforeStartTime ? <span className="text-warning">{t('reservations.validation.endTimeBeforeStartTime')}</span> : undefined}
|
||||
>
|
||||
<CustomTimePicker value={form.reservation_end_time} onChange={v => set('reservation_end_time', v)} />
|
||||
</EditorField>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// FE-PLANNER-RESFORM-001 to -015: the booking form both the desktop ReservationModal
|
||||
// FE-PLANNER-RESFORM-001 to -016: the booking form both the desktop ReservationModal
|
||||
// and the phone's booking sheet save through.
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { BookingReviewDraft } from './parsedItemToDraft';
|
||||
import {
|
||||
RESERVATION_TYPE_OPTIONS,
|
||||
type ReservationFields,
|
||||
endTimeBeforeStartTime,
|
||||
isEndBeforeStart,
|
||||
reservationFieldsFrom,
|
||||
reservationFieldsFromPrefill,
|
||||
@@ -175,6 +176,24 @@ describe('reservation dates', () => {
|
||||
expect(isEndBeforeStart(form({ end_date: '2026-07-01' }))).toBe(false);
|
||||
});
|
||||
|
||||
it('FE-PLANNER-RESFORM-016: an end time before the start time without an end date warns but does not block (#2604)', () => {
|
||||
const overnight = form({ reservation_time: '2026-11-24T18:00', reservation_end_time: '09:00' });
|
||||
expect(endTimeBeforeStartTime(overnight)).toBe(true);
|
||||
// Time zones can make a booking end "before" it starts, so the save stays open.
|
||||
expect(isEndBeforeStart(overnight)).toBe(false);
|
||||
expect(endTimeBeforeStartTime(form({ reservation_time: '2026-11-24T09:00', reservation_end_time: '18:00' }))).toBe(false);
|
||||
expect(endTimeBeforeStartTime(form({ reservation_time: '2026-11-24T18:00', reservation_end_time: '18:00' }))).toBe(false);
|
||||
// With the next day as end date the times are fine, and an end date of its own is checked by isEndBeforeStart.
|
||||
expect(
|
||||
endTimeBeforeStartTime(form({ reservation_time: '2026-11-24T18:00', end_date: '2026-11-25', reservation_end_time: '09:00' }))
|
||||
).toBe(false);
|
||||
expect(endTimeBeforeStartTime(form({ reservation_time: '2026-11-24', reservation_end_time: '09:00' }))).toBe(false);
|
||||
expect(endTimeBeforeStartTime(form({ reservation_end_time: '09:00' }))).toBe(false);
|
||||
expect(
|
||||
endTimeBeforeStartTime(form({ type: 'hotel', reservation_time: '2026-11-24T18:00', reservation_end_time: '09:00' }))
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('FE-PLANNER-RESFORM-006: the start is edited as a date and a time', () => {
|
||||
expect(startParts('2026-07-02T10:00')).toEqual({ date: '2026-07-02', time: '10:00' });
|
||||
expect(startParts('')).toEqual({ date: '', time: '' });
|
||||
|
||||
@@ -164,6 +164,17 @@ export function isEndBeforeStart(form: DateFields): boolean {
|
||||
return `${form.end_date}T${endTime}` <= `${startDate}T${startTime}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether an end time without an end date comes before the start time, which saves
|
||||
* as an end earlier on the start day. That only warns: with time zones (a flight
|
||||
* landing "before" it took off) the times can be right as they are (#2604).
|
||||
*/
|
||||
export function endTimeBeforeStartTime(form: DateFields): boolean {
|
||||
if (form.type === 'hotel' || form.end_date || !form.reservation_end_time) return false;
|
||||
const startTime = (form.reservation_time || '').split('T')[1] || '';
|
||||
return !!startTime && form.reservation_end_time < startTime;
|
||||
}
|
||||
|
||||
/** The start's date and time as the two pickers show them. */
|
||||
export function startParts(reservationTime: string): { date: string; time: string } {
|
||||
const [date, time] = (reservationTime || '').split('T');
|
||||
|
||||
@@ -91,4 +91,15 @@ describe('useReservationForm', () => {
|
||||
endpoints: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('FE-PLANNER-RESFORMHOOK-006: an end time before the start time on the same day raises the warning (#2604)', () => {
|
||||
const { result } = renderHook(() => useReservationForm(EMPTY, days, places));
|
||||
act(() => result.current.setStartTime('18:00', '2026-07-01'));
|
||||
expect(result.current.endTimeBeforeStartTime).toBe(false);
|
||||
act(() => result.current.set('reservation_end_time', '09:00'));
|
||||
expect(result.current.endTimeBeforeStartTime).toBe(true);
|
||||
expect(result.current.isEndBeforeStart).toBe(false);
|
||||
act(() => result.current.set('end_date', '2026-07-02'));
|
||||
expect(result.current.endTimeBeforeStartTime).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { Day, Place } from '../../types';
|
||||
import { toggledTraveler } from './bookingFormModel';
|
||||
import {
|
||||
type CheckInEndField,
|
||||
endTimeBeforeStartTime,
|
||||
isEndBeforeStart,
|
||||
type ReservationFields,
|
||||
reservationSaveData,
|
||||
@@ -56,6 +57,7 @@ export function useReservationForm<F extends ReservationFields & CheckInEndField
|
||||
setTravelerIds,
|
||||
toggleTraveler,
|
||||
isEndBeforeStart: isEndBeforeStart(form),
|
||||
endTimeBeforeStartTime: endTimeBeforeStartTime(form),
|
||||
dateBounds,
|
||||
startDate: start.date,
|
||||
startTime: start.time,
|
||||
|
||||
@@ -59,7 +59,7 @@ export default function MReservationSheet({ planner, onOpenExpense }: MReservati
|
||||
|
||||
const {
|
||||
form, setForm, set, isSaving, setIsSaving, pendingFiles, setPendingFiles, travelerIds, setTravelerIds, toggleTraveler,
|
||||
isEndBeforeStart, dateBounds, startDate, startTime, setStartDate, setStartTime, takeStopDay,
|
||||
isEndBeforeStart, endTimeBeforeStartTime, dateBounds, startDate, startTime, setStartDate, setStartTime, takeStopDay,
|
||||
pickPlace, pickHotelPlace, pickHotelStart, pickHotelEnd, saveData: buildSaveData,
|
||||
} = useReservationForm(EMPTY, days, places)
|
||||
const assignmentOptions = useMemo(
|
||||
@@ -252,6 +252,11 @@ export default function MReservationSheet({ planner, onOpenExpense }: MReservati
|
||||
{t('reservations.validation.endBeforeStart')}
|
||||
</div>
|
||||
)}
|
||||
{endTimeBeforeStartTime && (
|
||||
<div className="mt-[6px] text-[0.6875rem] text-[color:var(--m-st-pending)]">
|
||||
{t('reservations.validation.endTimeBeforeStartTime')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* PLACE / ACTIVITY */}
|
||||
<Eyebrow className="mb-[5px] mt-3 uppercase">{t('reservations.meta.linkPlace')}</Eyebrow>
|
||||
|
||||
@@ -131,6 +131,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'النهاية',
|
||||
'reservations.span.ongoing': 'جارٍ',
|
||||
'reservations.validation.endBeforeStart': 'يجب أن يكون تاريخ/وقت الانتهاء بعد تاريخ/وقت البدء',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'وقت الانتهاء قبل وقت البدء. إذا كان ينتهي في اليوم التالي، فحدّد تاريخ انتهاء.',
|
||||
'reservations.addBooking': 'إضافة حجز',
|
||||
'reservations.import.title': 'استيراد تأكيدات الحجز',
|
||||
'reservations.import.cta': 'استيراد من ملف',
|
||||
|
||||
@@ -159,6 +159,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.ongoing': 'Davam edir',
|
||||
|
||||
'reservations.validation.endBeforeStart': 'Bitmə tarixi və vaxtı başlanğıc tarixi və vaxtından sonra olmalıdır',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Bitmə vaxtı başlanğıc vaxtından əvvəldir. Növbəti gün bitirsə, bitmə tarixi təyin edin.',
|
||||
|
||||
'reservations.addBooking': 'Rezervasiya əlavə et',
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Fim',
|
||||
'reservations.span.ongoing': 'Em andamento',
|
||||
'reservations.validation.endBeforeStart': 'A data/hora final deve ser posterior à data/hora inicial',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'O horário final é anterior ao inicial. Se terminar no dia seguinte, defina uma data final.',
|
||||
'reservations.addBooking': 'Adicionar reserva',
|
||||
'reservations.import.title': 'Importar confirmações de reserva',
|
||||
'reservations.import.cta': 'Importar de arquivo',
|
||||
|
||||
@@ -100,6 +100,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Fi',
|
||||
'reservations.span.ongoing': 'En curs',
|
||||
'reservations.validation.endBeforeStart': "La data/hora de fi ha de ser posterior a la d'inici",
|
||||
'reservations.validation.endTimeBeforeStartTime': "L'hora de fi és anterior a la d'inici. Si acaba l'endemà, indica una data de fi.",
|
||||
'reservations.addBooking': 'Afegeix una reserva',
|
||||
'reservations.meta.airline': 'Aerolínia',
|
||||
'reservations.meta.flightNumber': 'Núm. de vol',
|
||||
|
||||
@@ -131,6 +131,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Konec',
|
||||
'reservations.span.ongoing': 'Probíhá',
|
||||
'reservations.validation.endBeforeStart': 'Datum/čas konce musí být po datu/čase začátku',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Čas konce je dříve než čas začátku. Pokud končí následující den, nastavte datum konce.',
|
||||
'reservations.addBooking': 'Přidat rezervaci',
|
||||
'reservations.import.title': 'Importovat potvrzení rezervace',
|
||||
'reservations.import.cta': 'Importovat ze souboru',
|
||||
|
||||
@@ -134,6 +134,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Ende',
|
||||
'reservations.span.ongoing': 'Laufend',
|
||||
'reservations.validation.endBeforeStart': 'Enddatum/-zeit muss nach dem Startdatum/-zeit liegen',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Die Endzeit liegt vor der Startzeit. Endet die Buchung am nächsten Tag, wähle ein Enddatum.',
|
||||
'reservations.addBooking': 'Buchung hinzufügen',
|
||||
'reservations.import.title': 'Buchungsbestätigungen importieren',
|
||||
'reservations.import.cta': 'Aus Datei importieren',
|
||||
|
||||
@@ -136,6 +136,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'End',
|
||||
'reservations.span.ongoing': 'Ongoing',
|
||||
'reservations.validation.endBeforeStart': 'End date/time must be after start date/time',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'The end time is before the start time. If it ends the next day, set an end date.',
|
||||
'reservations.addBooking': 'Add booking',
|
||||
'reservations.import.title': 'Import booking confirmations',
|
||||
'reservations.import.cta': 'Import from file',
|
||||
|
||||
@@ -100,6 +100,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Fin',
|
||||
'reservations.span.ongoing': 'En curso',
|
||||
'reservations.validation.endBeforeStart': 'La fecha/hora de fin debe ser posterior a la de inicio',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'La hora de fin es anterior a la de inicio. Si termina al día siguiente, indica una fecha de fin.',
|
||||
'reservations.addBooking': 'Añadir reserva',
|
||||
'reservations.meta.airline': 'Aerolínea',
|
||||
'reservations.meta.flightNumber': 'N° de vuelo',
|
||||
|
||||
@@ -136,6 +136,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Lõpp',
|
||||
'reservations.span.ongoing': 'Käimas',
|
||||
'reservations.validation.endBeforeStart': 'Lõppkuupäev ja -aeg peavad olema algusest hilisemad',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Lõpuaeg on enne algusaega. Kui see lõpeb järgmisel päeval, määra lõppkuupäev.',
|
||||
'reservations.addBooking': 'Lisa broneering',
|
||||
'reservations.import.title': 'Impordi broneeringukinnitused',
|
||||
'reservations.import.cta': 'Impordi failist',
|
||||
|
||||
@@ -133,6 +133,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Fin',
|
||||
'reservations.span.ongoing': 'En cours',
|
||||
'reservations.validation.endBeforeStart': 'La date/heure de fin doit être postérieure à la date/heure de début',
|
||||
'reservations.validation.endTimeBeforeStartTime': "L'heure de fin est antérieure à l'heure de début. Si elle se termine le lendemain, indiquez une date de fin.",
|
||||
'reservations.addBooking': 'Ajouter une réservation',
|
||||
'reservations.import.title': 'Importer des confirmations de réservation',
|
||||
'reservations.import.cta': 'Importer depuis un fichier',
|
||||
|
||||
@@ -133,6 +133,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Λήξη',
|
||||
'reservations.span.ongoing': 'Σε εξέλιξη',
|
||||
'reservations.validation.endBeforeStart': 'Η ημερομηνία/ώρα λήξης πρέπει να είναι μετά την ημερομηνία/ώρα έναρξης',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Η ώρα λήξης είναι πριν από την ώρα έναρξης. Αν λήγει την επόμενη μέρα, ορίστε ημερομηνία λήξης.',
|
||||
'reservations.addBooking': 'Προσθήκη κράτησης',
|
||||
'reservations.import.title': 'Εισαγωγή επιβεβαιώσεων κράτησης',
|
||||
'reservations.import.cta': 'Εισαγωγή από αρχείο',
|
||||
|
||||
@@ -132,6 +132,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Vége',
|
||||
'reservations.span.ongoing': 'Folyamatban',
|
||||
'reservations.validation.endBeforeStart': 'A befejezés dátuma/időpontja a kezdés utáni kell legyen',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'A befejezés időpontja a kezdés előtt van. Ha a következő napon ér véget, adj meg befejezési dátumot.',
|
||||
'reservations.addBooking': 'Foglalás hozzáadása',
|
||||
'reservations.import.title': 'Foglalási visszaigazolások importálása',
|
||||
'reservations.import.cta': 'Importálás fájlból',
|
||||
|
||||
@@ -132,6 +132,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Selesai',
|
||||
'reservations.span.ongoing': 'Berlangsung',
|
||||
'reservations.validation.endBeforeStart': 'Tanggal/waktu selesai harus setelah tanggal/waktu mulai',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Waktu selesai lebih awal dari waktu mulai. Jika berakhir keesokan harinya, atur tanggal selesai.',
|
||||
'reservations.addBooking': 'Tambah pemesanan',
|
||||
'reservations.import.title': 'Impor konfirmasi pemesanan',
|
||||
'reservations.import.cta': 'Impor dari file',
|
||||
|
||||
@@ -132,6 +132,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Fine',
|
||||
'reservations.span.ongoing': 'In corso',
|
||||
'reservations.validation.endBeforeStart': 'La data/ora di fine deve essere successiva alla data/ora di inizio',
|
||||
'reservations.validation.endTimeBeforeStartTime': "L'ora di fine è precedente all'ora di inizio. Se termina il giorno dopo, imposta una data di fine.",
|
||||
'reservations.addBooking': 'Aggiungi prenotazione',
|
||||
'reservations.import.title': 'Importa conferme di prenotazione',
|
||||
'reservations.import.cta': 'Importa da file',
|
||||
|
||||
@@ -131,6 +131,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': '終了',
|
||||
'reservations.span.ongoing': '進行中',
|
||||
'reservations.validation.endBeforeStart': '終了日時は開始日時より後である必要があります',
|
||||
'reservations.validation.endTimeBeforeStartTime': '終了時刻が開始時刻より前です。翌日に終わる場合は終了日を設定してください。',
|
||||
'reservations.addBooking': '予約を追加',
|
||||
'reservations.import.title': '予約確認書のインポート',
|
||||
'reservations.import.cta': 'ファイルからインポート',
|
||||
|
||||
@@ -131,6 +131,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': '종료',
|
||||
'reservations.span.ongoing': '진행 중',
|
||||
'reservations.validation.endBeforeStart': '종료 날짜/시간은 시작 날짜/시간 이후여야 합니다',
|
||||
'reservations.validation.endTimeBeforeStartTime': '종료 시간이 시작 시간보다 이릅니다. 다음 날 끝나면 종료 날짜를 설정하세요.',
|
||||
'reservations.addBooking': '예약 추가',
|
||||
'reservations.import.title': '예약 확인서 가져오기',
|
||||
'reservations.import.cta': '파일에서 가져오기',
|
||||
|
||||
@@ -132,6 +132,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Einde',
|
||||
'reservations.span.ongoing': 'Lopend',
|
||||
'reservations.validation.endBeforeStart': 'Einddatum/-tijd moet na de startdatum/-tijd liggen',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'De eindtijd ligt vóór de starttijd. Eindigt het de volgende dag, kies dan een einddatum.',
|
||||
'reservations.addBooking': 'Boeking toevoegen',
|
||||
'reservations.import.title': 'Boekingsbevestigingen importeren',
|
||||
'reservations.import.cta': 'Importeren vanuit bestand',
|
||||
|
||||
@@ -132,6 +132,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Koniec',
|
||||
'reservations.span.ongoing': 'W trakcie',
|
||||
'reservations.validation.endBeforeStart': 'Data/godzina zakończenia musi być późniejsza niż data/godzina rozpoczęcia',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Godzina zakończenia jest wcześniejsza niż godzina rozpoczęcia. Jeśli kończy się następnego dnia, ustaw datę zakończenia.',
|
||||
'reservations.addBooking': 'Dodaj rezerwację',
|
||||
'reservations.import.title': 'Importuj potwierdzenia rezerwacji',
|
||||
'reservations.import.cta': 'Importuj z pliku',
|
||||
|
||||
@@ -131,6 +131,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Конец',
|
||||
'reservations.span.ongoing': 'Продолжается',
|
||||
'reservations.validation.endBeforeStart': 'Дата/время окончания должны быть позже даты/времени начала',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Время окончания раньше времени начала. Если бронирование заканчивается на следующий день, укажите дату окончания.',
|
||||
'reservations.addBooking': 'Добавить бронирование',
|
||||
'reservations.import.title': 'Импорт подтверждений бронирования',
|
||||
'reservations.import.cta': 'Импортировать из файла',
|
||||
|
||||
@@ -137,6 +137,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Koniec',
|
||||
'reservations.span.ongoing': 'Prebieha',
|
||||
'reservations.validation.endBeforeStart': 'Dátum/čas konca musí byť po dátume/čase začiatku',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Čas konca je skôr ako čas začiatku. Ak končí nasledujúci deň, nastavte dátum konca.',
|
||||
'reservations.addBooking': 'Pridať rezerváciu',
|
||||
'reservations.import.title': 'Importovať potvrdenia rezervácií',
|
||||
'reservations.import.cta': 'Importovať zo súboru',
|
||||
|
||||
@@ -132,6 +132,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Slut',
|
||||
'reservations.span.ongoing': 'Pågår',
|
||||
'reservations.validation.endBeforeStart': 'Slutdatum och -tid måste ligga efter startdatum och -tid',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Sluttiden ligger före starttiden. Om den slutar nästa dag, ange ett slutdatum.',
|
||||
'reservations.addBooking': 'Lägg till bokning',
|
||||
'reservations.import.title': 'Importera bokningsbekräftelser',
|
||||
'reservations.import.cta': 'Importera från fil',
|
||||
|
||||
@@ -136,6 +136,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'สิ้นสุด',
|
||||
'reservations.span.ongoing': 'กำลังดำเนินการอยู่',
|
||||
'reservations.validation.endBeforeStart': 'วันที่/เวลาสิ้นสุดต้องอยู่หลังวันที่/เวลาเริ่มต้น',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'เวลาสิ้นสุดอยู่ก่อนเวลาเริ่มต้น หากสิ้นสุดในวันถัดไป ให้กำหนดวันที่สิ้นสุด',
|
||||
'reservations.addBooking': 'เพิ่มการจอง',
|
||||
'reservations.import.title': 'นำเข้าการยืนยันการจอง',
|
||||
'reservations.import.cta': 'นำเข้าจากไฟล์',
|
||||
|
||||
@@ -132,6 +132,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Son',
|
||||
'reservations.span.ongoing': 'Devam ediyor',
|
||||
'reservations.validation.endBeforeStart': 'Bitiş tarihi/saati başlangıçtan sonra olmalı',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Bitiş saati başlangıç saatinden önce. Ertesi gün bitiyorsa bir bitiş tarihi belirleyin.',
|
||||
'reservations.addBooking': 'Rezervasyon ekle',
|
||||
'reservations.import.title': 'Rezervasyon onaylarını içe aktar',
|
||||
'reservations.import.cta': 'Dosyadan içe aktar',
|
||||
|
||||
@@ -131,6 +131,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Кінець',
|
||||
'reservations.span.ongoing': 'Триває',
|
||||
'reservations.validation.endBeforeStart': 'Дата/час закінчення повинен бути пізніше дати/часу початку',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Час закінчення раніший за час початку. Якщо бронювання закінчується наступного дня, вкажіть дату закінчення.',
|
||||
'reservations.addBooking': 'Додати бронювання',
|
||||
'reservations.import.title': 'Імпорт підтверджень бронювання',
|
||||
'reservations.import.cta': 'Імпортувати з файлу',
|
||||
|
||||
@@ -132,6 +132,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': 'Kết thúc',
|
||||
'reservations.span.ongoing': 'Đang thực hiện',
|
||||
'reservations.validation.endBeforeStart': 'Ngày/giờ kết thúc phải sau ngày/giờ bắt đầu',
|
||||
'reservations.validation.endTimeBeforeStartTime': 'Giờ kết thúc sớm hơn giờ bắt đầu. Nếu kết thúc vào ngày hôm sau, hãy đặt ngày kết thúc.',
|
||||
'reservations.addBooking': 'Thêm đặt chỗ',
|
||||
'reservations.import.title': 'Nhập xác nhận đặt chỗ',
|
||||
'reservations.import.cta': 'Nhập từ tập tin',
|
||||
|
||||
@@ -131,6 +131,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': '結束',
|
||||
'reservations.span.ongoing': '進行中',
|
||||
'reservations.validation.endBeforeStart': '結束日期/時間必須晚於開始日期/時間',
|
||||
'reservations.validation.endTimeBeforeStartTime': '結束時間早於開始時間。如果在隔天結束,請設定結束日期。',
|
||||
'reservations.addBooking': '新增預訂',
|
||||
'reservations.import.title': '匯入訂位確認',
|
||||
'reservations.import.cta': '從檔案匯入',
|
||||
|
||||
@@ -131,6 +131,7 @@ const reservations: TranslationStrings = {
|
||||
'reservations.span.end': '结束',
|
||||
'reservations.span.ongoing': '进行中',
|
||||
'reservations.validation.endBeforeStart': '结束日期/时间必须晚于开始日期/时间',
|
||||
'reservations.validation.endTimeBeforeStartTime': '结束时间早于开始时间。如果在次日结束,请设置结束日期。',
|
||||
'reservations.addBooking': '添加预订',
|
||||
'reservations.import.title': '导入预订确认',
|
||||
'reservations.import.cta': '从文件导入',
|
||||
|
||||
Reference in New Issue
Block a user