mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 13:21:46 +00:00
* feat(days): reorder whole days and insert a day at a position Adds reorderDays + insertDay to the day service and a PUT /days/reorder route (plus an optional position on create). Day rows stay stable so a day's assignments, notes, bookings and accommodations ride along by id; on a dated trip the calendar dates stay pinned to their slots while the content moves across them, and each booking's date is re-stamped onto its day's new date (time-of-day preserved) so day_id stays consistent. Renumbering uses the two-phase write to avoid the UNIQUE(trip_id, day_number) collision, and a move that would invert an accommodation's check-in/out span is rejected. * feat(planner): reorder days from a toolbar popup, and add days A new toolbar button opens a popup listing the days; drag a row by its grip or use the up/down arrows to reorder, and add a day from there. Reorders apply optimistically with rollback and sync over WebSocket; the day headers are left untouched, so the existing place drop-targets are unaffected. * i18n: add day-reorder strings across all languages
This commit is contained in:
@@ -49,9 +49,17 @@ export type Day = z.infer<typeof daySchema>;
|
||||
export const dayCreateRequestSchema = z.object({
|
||||
date: z.string().optional(),
|
||||
notes: z.string().optional(),
|
||||
// 1-based slot to insert a new empty day at (omit to append at the end).
|
||||
position: z.number().int().positive().optional(),
|
||||
});
|
||||
export type DayCreateRequest = z.infer<typeof dayCreateRequestSchema>;
|
||||
|
||||
/** Reorder whole days: the desired full sequence of this trip's day ids. */
|
||||
export const dayReorderRequestSchema = z.object({
|
||||
orderedIds: z.array(z.number()),
|
||||
});
|
||||
export type DayReorderRequest = z.infer<typeof dayReorderRequestSchema>;
|
||||
|
||||
export const dayUpdateRequestSchema = z.object({
|
||||
notes: z.string().optional(),
|
||||
title: z.string().nullable().optional(),
|
||||
|
||||
@@ -45,5 +45,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.allAssigned': 'All places assigned', // en-fallback
|
||||
'dayplan.mobile.noMatch': 'No match', // en-fallback
|
||||
'dayplan.mobile.createNew': 'Create new place', // en-fallback
|
||||
'dayplan.reorderDays': 'إعادة ترتيب الأيام',
|
||||
'dayplan.reorderTitle': 'إعادة ترتيب الأيام',
|
||||
'dayplan.reorderHint': 'تنتقل أماكن اليوم وملاحظاته وحجوزاته معه.',
|
||||
'dayplan.addDay': 'إضافة يوم',
|
||||
'dayplan.moveUp': 'تحريك لأعلى',
|
||||
'dayplan.moveDown': 'تحريك لأسفل',
|
||||
'dayplan.reorderUndo': 'إعادة ترتيب الأيام',
|
||||
'dayplan.reorderError': 'تعذّر إعادة ترتيب الأيام',
|
||||
'dayplan.addDayError': 'تعذّر إضافة يوم',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -48,5 +48,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': 'Criar novo lugar',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': 'Reordenar dias',
|
||||
'dayplan.reorderTitle': 'Reordenar dias',
|
||||
'dayplan.reorderHint': 'Os lugares, notas e reservas de um dia se movem junto com ele.',
|
||||
'dayplan.addDay': 'Adicionar dia',
|
||||
'dayplan.moveUp': 'Mover para cima',
|
||||
'dayplan.moveDown': 'Mover para baixo',
|
||||
'dayplan.reorderUndo': 'Reordenar dias',
|
||||
'dayplan.reorderError': 'Falha ao reordenar os dias',
|
||||
'dayplan.addDayError': 'Falha ao adicionar o dia',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -48,5 +48,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': 'Vytvořit nové místo',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': 'Změnit pořadí dnů',
|
||||
'dayplan.reorderTitle': 'Změnit pořadí dnů',
|
||||
'dayplan.reorderHint': 'Místa, poznámky a rezervace daného dne se přesunou spolu s ním.',
|
||||
'dayplan.addDay': 'Přidat den',
|
||||
'dayplan.moveUp': 'Posunout nahoru',
|
||||
'dayplan.moveDown': 'Posunout dolů',
|
||||
'dayplan.reorderUndo': 'Změnit pořadí dnů',
|
||||
'dayplan.reorderError': 'Nepodařilo se změnit pořadí dnů',
|
||||
'dayplan.addDayError': 'Nepodařilo se přidat den',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -47,5 +47,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.allAssigned': 'Alle Orte zugeordnet',
|
||||
'dayplan.mobile.noMatch': 'Kein Treffer',
|
||||
'dayplan.mobile.createNew': 'Neuen Ort erstellen',
|
||||
'dayplan.reorderDays': 'Tage neu anordnen',
|
||||
'dayplan.reorderTitle': 'Tage neu anordnen',
|
||||
'dayplan.reorderHint': 'Orte, Notizen und Buchungen eines Tages werden mitverschoben.',
|
||||
'dayplan.addDay': 'Tag hinzufügen',
|
||||
'dayplan.moveUp': 'Nach oben',
|
||||
'dayplan.moveDown': 'Nach unten',
|
||||
'dayplan.reorderUndo': 'Tage neu anordnen',
|
||||
'dayplan.reorderError': 'Tage konnten nicht neu angeordnet werden',
|
||||
'dayplan.addDayError': 'Tag konnte nicht hinzugefügt werden',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -47,5 +47,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.allAssigned': 'All places assigned',
|
||||
'dayplan.mobile.noMatch': 'No match',
|
||||
'dayplan.mobile.createNew': 'Create new place',
|
||||
'dayplan.reorderDays': 'Reorder days',
|
||||
'dayplan.reorderTitle': 'Reorder days',
|
||||
'dayplan.reorderHint': "A day's places, notes and bookings move with it.",
|
||||
'dayplan.addDay': 'Add day',
|
||||
'dayplan.moveUp': 'Move up',
|
||||
'dayplan.moveDown': 'Move down',
|
||||
'dayplan.reorderUndo': 'Reorder days',
|
||||
'dayplan.reorderError': 'Failed to reorder days',
|
||||
'dayplan.addDayError': 'Failed to add day',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -47,5 +47,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': 'Crear nuevo lugar',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': 'Reordenar días',
|
||||
'dayplan.reorderTitle': 'Reordenar días',
|
||||
'dayplan.reorderHint': 'Los lugares, las notas y las reservas de un día se mueven con él.',
|
||||
'dayplan.addDay': 'Añadir día',
|
||||
'dayplan.moveUp': 'Subir',
|
||||
'dayplan.moveDown': 'Bajar',
|
||||
'dayplan.reorderUndo': 'Reordenar días',
|
||||
'dayplan.reorderError': 'No se pudieron reordenar los días',
|
||||
'dayplan.addDayError': 'No se pudo añadir el día',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -49,5 +49,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': 'Créer un nouveau lieu',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': 'Réorganiser les jours',
|
||||
'dayplan.reorderTitle': 'Réorganiser les jours',
|
||||
'dayplan.reorderHint': 'Les lieux, notes et réservations d\'un jour le suivent.',
|
||||
'dayplan.addDay': 'Ajouter un jour',
|
||||
'dayplan.moveUp': 'Monter',
|
||||
'dayplan.moveDown': 'Descendre',
|
||||
'dayplan.reorderUndo': 'Réorganiser les jours',
|
||||
'dayplan.reorderError': 'Échec de la réorganisation des jours',
|
||||
'dayplan.addDayError': 'Échec de l\'ajout du jour',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -49,5 +49,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.allAssigned': 'Όλες οι τοποθεσίες έχουν ανατεθεί',
|
||||
'dayplan.mobile.noMatch': 'Καμία αντιστοιχία',
|
||||
'dayplan.mobile.createNew': 'Δημιουργία νέας τοποθεσίας',
|
||||
'dayplan.reorderDays': 'Αναδιάταξη ημερών',
|
||||
'dayplan.reorderTitle': 'Αναδιάταξη ημερών',
|
||||
'dayplan.reorderHint': 'Τα μέρη, οι σημειώσεις και οι κρατήσεις μιας ημέρας μετακινούνται μαζί της.',
|
||||
'dayplan.addDay': 'Προσθήκη ημέρας',
|
||||
'dayplan.moveUp': 'Μετακίνηση πάνω',
|
||||
'dayplan.moveDown': 'Μετακίνηση κάτω',
|
||||
'dayplan.reorderUndo': 'Αναδιάταξη ημερών',
|
||||
'dayplan.reorderError': 'Η αναδιάταξη των ημερών απέτυχε',
|
||||
'dayplan.addDayError': 'Η προσθήκη ημέρας απέτυχε',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -48,5 +48,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': 'Új helyszín létrehozása',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': 'Napok átrendezése',
|
||||
'dayplan.reorderTitle': 'Napok átrendezése',
|
||||
'dayplan.reorderHint': 'A nap helyei, jegyzetei és foglalásai együtt mozognak vele.',
|
||||
'dayplan.addDay': 'Nap hozzáadása',
|
||||
'dayplan.moveUp': 'Mozgatás felfelé',
|
||||
'dayplan.moveDown': 'Mozgatás lefelé',
|
||||
'dayplan.reorderUndo': 'Napok átrendezése',
|
||||
'dayplan.reorderError': 'Nem sikerült átrendezni a napokat',
|
||||
'dayplan.addDayError': 'Nem sikerült napot hozzáadni',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -48,5 +48,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': 'Buat tempat baru',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': 'Atur ulang hari',
|
||||
'dayplan.reorderTitle': 'Atur ulang hari',
|
||||
'dayplan.reorderHint': 'Tempat, catatan, dan pesanan pada suatu hari ikut berpindah.',
|
||||
'dayplan.addDay': 'Tambah hari',
|
||||
'dayplan.moveUp': 'Pindah ke atas',
|
||||
'dayplan.moveDown': 'Pindah ke bawah',
|
||||
'dayplan.reorderUndo': 'Atur ulang hari',
|
||||
'dayplan.reorderError': 'Gagal mengatur ulang hari',
|
||||
'dayplan.addDayError': 'Gagal menambah hari',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -49,5 +49,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': 'Crea nuovo luogo',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': 'Riordina i giorni',
|
||||
'dayplan.reorderTitle': 'Riordina i giorni',
|
||||
'dayplan.reorderHint': 'I luoghi, le note e le prenotazioni di un giorno si spostano insieme a esso.',
|
||||
'dayplan.addDay': 'Aggiungi giorno',
|
||||
'dayplan.moveUp': 'Sposta su',
|
||||
'dayplan.moveDown': 'Sposta giù',
|
||||
'dayplan.reorderUndo': 'Riordina i giorni',
|
||||
'dayplan.reorderError': 'Riordino dei giorni non riuscito',
|
||||
'dayplan.addDayError': 'Aggiunta del giorno non riuscita',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -42,5 +42,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.allAssigned': 'すべて割り当て済み',
|
||||
'dayplan.mobile.noMatch': '一致なし',
|
||||
'dayplan.mobile.createNew': '新しい場所を作成',
|
||||
'dayplan.reorderDays': '日付を並べ替え',
|
||||
'dayplan.reorderTitle': '日付を並べ替え',
|
||||
'dayplan.reorderHint': 'その日のスポット、メモ、予約も一緒に移動します。',
|
||||
'dayplan.addDay': '日付を追加',
|
||||
'dayplan.moveUp': '上へ移動',
|
||||
'dayplan.moveDown': '下へ移動',
|
||||
'dayplan.reorderUndo': '日付を並べ替え',
|
||||
'dayplan.reorderError': '日付の並べ替えに失敗しました',
|
||||
'dayplan.addDayError': '日付の追加に失敗しました',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -45,5 +45,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.allAssigned': '모든 장소가 배정되었습니다',
|
||||
'dayplan.mobile.noMatch': '일치 없음',
|
||||
'dayplan.mobile.createNew': '새 장소 만들기',
|
||||
'dayplan.reorderDays': '날짜 순서 변경',
|
||||
'dayplan.reorderTitle': '날짜 순서 변경',
|
||||
'dayplan.reorderHint': '해당 날짜의 장소, 메모, 예약이 함께 이동합니다.',
|
||||
'dayplan.addDay': '날짜 추가',
|
||||
'dayplan.moveUp': '위로 이동',
|
||||
'dayplan.moveDown': '아래로 이동',
|
||||
'dayplan.reorderUndo': '날짜 순서 변경',
|
||||
'dayplan.reorderError': '날짜 순서를 변경하지 못했습니다',
|
||||
'dayplan.addDayError': '날짜를 추가하지 못했습니다',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -48,5 +48,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': 'Nieuwe plaats aanmaken',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': 'Dagen herordenen',
|
||||
'dayplan.reorderTitle': 'Dagen herordenen',
|
||||
'dayplan.reorderHint': 'De plaatsen, notities en boekingen van een dag gaan mee.',
|
||||
'dayplan.addDay': 'Dag toevoegen',
|
||||
'dayplan.moveUp': 'Omhoog',
|
||||
'dayplan.moveDown': 'Omlaag',
|
||||
'dayplan.reorderUndo': 'Dagen herordenen',
|
||||
'dayplan.reorderError': 'Dagen herordenen mislukt',
|
||||
'dayplan.addDayError': 'Dag toevoegen mislukt',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -48,5 +48,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': 'Utwórz nowe miejsce',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': 'Zmień kolejność dni',
|
||||
'dayplan.reorderTitle': 'Zmień kolejność dni',
|
||||
'dayplan.reorderHint': 'Miejsca, notatki i rezerwacje danego dnia przenoszą się razem z nim.',
|
||||
'dayplan.addDay': 'Dodaj dzień',
|
||||
'dayplan.moveUp': 'Przenieś w górę',
|
||||
'dayplan.moveDown': 'Przenieś w dół',
|
||||
'dayplan.reorderUndo': 'Zmień kolejność dni',
|
||||
'dayplan.reorderError': 'Nie udało się zmienić kolejności dni',
|
||||
'dayplan.addDayError': 'Nie udało się dodać dnia',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -48,5 +48,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': 'Создать новое место',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': 'Изменить порядок дней',
|
||||
'dayplan.reorderTitle': 'Изменить порядок дней',
|
||||
'dayplan.reorderHint': 'Места, заметки и бронирования дня перемещаются вместе с ним.',
|
||||
'dayplan.addDay': 'Добавить день',
|
||||
'dayplan.moveUp': 'Вверх',
|
||||
'dayplan.moveDown': 'Вниз',
|
||||
'dayplan.reorderUndo': 'Изменить порядок дней',
|
||||
'dayplan.reorderError': 'Не удалось изменить порядок дней',
|
||||
'dayplan.addDayError': 'Не удалось добавить день',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -47,5 +47,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.allAssigned': 'Tüm yerler atandı',
|
||||
'dayplan.mobile.noMatch': 'Eşleşme yok',
|
||||
'dayplan.mobile.createNew': 'Yeni yer oluştur',
|
||||
'dayplan.reorderDays': 'Günleri yeniden sırala',
|
||||
'dayplan.reorderTitle': 'Günleri yeniden sırala',
|
||||
'dayplan.reorderHint': 'Bir günün yerleri, notları ve rezervasyonları onunla birlikte taşınır.',
|
||||
'dayplan.addDay': 'Gün ekle',
|
||||
'dayplan.moveUp': 'Yukarı taşı',
|
||||
'dayplan.moveDown': 'Aşağı taşı',
|
||||
'dayplan.reorderUndo': 'Günleri yeniden sırala',
|
||||
'dayplan.reorderError': 'Günler yeniden sıralanamadı',
|
||||
'dayplan.addDayError': 'Gün eklenemedi',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -47,5 +47,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.allAssigned': 'Усі місця розподілені',
|
||||
'dayplan.mobile.noMatch': 'Немає збігів',
|
||||
'dayplan.mobile.createNew': 'Створити нове місце',
|
||||
'dayplan.reorderDays': 'Змінити порядок днів',
|
||||
'dayplan.reorderTitle': 'Змінити порядок днів',
|
||||
'dayplan.reorderHint': 'Місця, нотатки та бронювання дня переміщуються разом із ним.',
|
||||
'dayplan.addDay': 'Додати день',
|
||||
'dayplan.moveUp': 'Перемістити вгору',
|
||||
'dayplan.moveDown': 'Перемістити вниз',
|
||||
'dayplan.reorderUndo': 'Змінити порядок днів',
|
||||
'dayplan.reorderError': 'Не вдалося змінити порядок днів',
|
||||
'dayplan.addDayError': 'Не вдалося додати день',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -42,5 +42,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': '建立新地點',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': '重新排序日期',
|
||||
'dayplan.reorderTitle': '重新排序日期',
|
||||
'dayplan.reorderHint': '該日的地點、筆記和預訂都會一併移動。',
|
||||
'dayplan.addDay': '新增日期',
|
||||
'dayplan.moveUp': '上移',
|
||||
'dayplan.moveDown': '下移',
|
||||
'dayplan.reorderUndo': '重新排序日期',
|
||||
'dayplan.reorderError': '重新排序日期失敗',
|
||||
'dayplan.addDayError': '新增日期失敗',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
@@ -42,5 +42,14 @@ const dayplan: TranslationStrings = {
|
||||
'dayplan.mobile.createNew': '创建新地点',
|
||||
'dayplan.expandAll': 'Expand all days', // en-fallback
|
||||
'dayplan.collapseAll': 'Collapse all days', // en-fallback
|
||||
'dayplan.reorderDays': '调整日期顺序',
|
||||
'dayplan.reorderTitle': '调整日期顺序',
|
||||
'dayplan.reorderHint': '该天的地点、备注和预订会随之一起移动。',
|
||||
'dayplan.addDay': '添加一天',
|
||||
'dayplan.moveUp': '上移',
|
||||
'dayplan.moveDown': '下移',
|
||||
'dayplan.reorderUndo': '调整日期顺序',
|
||||
'dayplan.reorderError': '调整日期顺序失败',
|
||||
'dayplan.addDayError': '添加一天失败',
|
||||
};
|
||||
export default dayplan;
|
||||
|
||||
Reference in New Issue
Block a user