fix(bookings): bookings, transports and stays saved offline wait in the queue and sync once the connection is back

Every booking and stay write went straight to the API, so offline a new
booking failed with "Network Error" and was lost, and a status tick, the
travellers or a moved transport snapped back. Bookings (add, edit, status,
travellers, delete, day order) and stays (add, edit, delete) now go through
reservationRepo and accommodationRepo and the mutation queue like places and
costs: a temporary row offline, held behind an older queued write online,
since neither carries a version token. Desktop, the phone sheets, the day
plan, the road trip nights and the PDF all write and read through them.

The replay reads the booking from `reservation` only, so the travellers
answer ({ travelers, reservation }) lands on the booking it names. A booking
or its stay that names a place or stay created offline is sent with the real
id once that one has synced, inside create_accommodation too, so an imported
hotel reviewed offline can be linked to a place made for it.

What only works online says so instead of failing: an AirTrail import, a
booking file import, the AI retry and an attachment on a saved booking show
that they need a connection, and a save with newly picked files is stopped
with a hint, since an upload cannot wait in the queue.

Refs #2601
This commit is contained in:
Maurice
2026-10-12 19:07:33 +02:00
parent 5dbcc4af40
commit 64ceecefb3
60 changed files with 1011 additions and 82 deletions
+3
View File
@@ -286,5 +286,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'نسخ رمز الحجز',
'reservations.copyFailed': 'تعذّر النسخ',
'reservations.showInFiles': 'عرض في الملفات',
'reservations.filesNeedConnection':
'يحتاج رفع الملفات إلى اتصال. أزل الملفات الجديدة لحفظ الحجز دون اتصال، أو احفظ عندما تعود متصلاً.',
'reservations.needsConnection': 'يتطلب هذا اتصالاً. حاول مرة أخرى عندما يعود TREK للاتصال.',
};
export default reservations;
+3
View File
@@ -292,6 +292,9 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Rezervasiya kodunu kopyala',
'reservations.copyFailed': 'Kopyalamaq alınmadı',
'reservations.showInFiles': 'Fayllarda göstər',
'reservations.filesNeedConnection':
'Faylların yüklənməsi üçün bağlantı lazımdır. Rezervasiyanı oflayn saxlamaq üçün yeni faylları silin və ya yenidən onlayn olduqda saxlayın.',
'reservations.needsConnection': 'Bunun üçün bağlantı lazımdır. TREK yenidən onlayn olduqda bir daha cəhd edin.',
};
export default reservations;
+3
View File
@@ -258,5 +258,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Copiar código da reserva',
'reservations.copyFailed': 'Não foi possível copiar',
'reservations.showInFiles': 'Mostrar nos arquivos',
'reservations.filesNeedConnection':
'Os arquivos precisam de conexão para serem enviados. Remova os novos para salvar a reserva offline, ou salve quando estiver online de novo.',
'reservations.needsConnection': 'Isso precisa de conexão. Tente de novo quando o TREK voltar a ficar online.',
};
export default reservations;
+3
View File
@@ -261,5 +261,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Copiar el codi de reserva',
'reservations.copyFailed': "No s'ha pogut copiar",
'reservations.showInFiles': 'Mostrar als fitxers',
'reservations.filesNeedConnection':
'Els fitxers necessiten connexió per pujar-se. Treu els nous per desar la reserva sense connexió, o desa quan tornis a estar en línia.',
'reservations.needsConnection': 'Això necessita connexió. Torna-ho a provar quan TREK torni a estar en línia.',
};
export default reservations;
+3
View File
@@ -265,5 +265,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Kopírovat rezervační kód',
'reservations.copyFailed': 'Kopírování se nezdařilo',
'reservations.showInFiles': 'Zobrazit v souborech',
'reservations.filesNeedConnection':
'Soubory potřebují k nahrání připojení. Odeber nové, abys rezervaci uložil offline, nebo ulož, až budeš znovu online.',
'reservations.needsConnection': 'Na tohle je potřeba připojení. Zkus to znovu, až bude TREK zase online.',
};
export default reservations;
+3
View File
@@ -261,5 +261,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Buchungscode kopieren',
'reservations.copyFailed': 'Kopieren hat nicht geklappt',
'reservations.showInFiles': 'In Dateien zeigen',
'reservations.filesNeedConnection':
'Dateien brauchen zum Hochladen eine Verbindung. Entferne die neuen, um die Buchung offline zu speichern, oder speichere, sobald du wieder online bist.',
'reservations.needsConnection': 'Dafür braucht es eine Verbindung. Versuch es noch einmal, sobald TREK wieder online ist.',
};
export default reservations;
+3
View File
@@ -260,5 +260,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Copy booking code',
'reservations.copyFailed': 'Could not copy',
'reservations.showInFiles': 'Show in files',
'reservations.filesNeedConnection':
'Files need a connection to upload. Remove the new ones to save the booking offline, or save once you are back online.',
'reservations.needsConnection': 'This needs a connection. Try again once TREK is back online.',
};
export default reservations;
+3
View File
@@ -261,5 +261,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Copiar código de reserva',
'reservations.copyFailed': 'No se pudo copiar',
'reservations.showInFiles': 'Mostrar en archivos',
'reservations.filesNeedConnection':
'Los archivos necesitan conexión para subirse. Quita los nuevos para guardar la reserva sin conexión, o guarda cuando vuelvas a estar en línea.',
'reservations.needsConnection': 'Esto necesita conexión. Vuelve a intentarlo cuando TREK esté de nuevo en línea.',
};
export default reservations;
+3
View File
@@ -260,5 +260,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Kopeeri broneerimiskood',
'reservations.copyFailed': 'Kopeerimine ebaõnnestus',
'reservations.showInFiles': 'Näita failides',
'reservations.filesNeedConnection':
'Failide üleslaadimiseks on vaja ühendust. Eemalda uued, et broneering võrguühenduseta salvestada, või salvesta, kui oled taas võrgus.',
'reservations.needsConnection': 'Selleks on vaja ühendust. Proovi uuesti, kui TREK on taas võrgus.',
};
export default reservations;
+3
View File
@@ -264,5 +264,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Copier le code de réservation',
'reservations.copyFailed': 'Impossible de copier',
'reservations.showInFiles': 'Afficher dans les fichiers',
'reservations.filesNeedConnection':
"Les fichiers ont besoin d'une connexion pour être envoyés. Retire les nouveaux pour enregistrer la réservation hors ligne, ou enregistre une fois de retour en ligne.",
'reservations.needsConnection': 'Cela nécessite une connexion. Réessaie dès que TREK sera de nouveau en ligne.',
};
export default reservations;
+3
View File
@@ -262,5 +262,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Αντιγραφή κωδικού κράτησης',
'reservations.copyFailed': 'Η αντιγραφή απέτυχε',
'reservations.showInFiles': 'Εμφάνιση στα αρχεία',
'reservations.filesNeedConnection':
'Τα αρχεία χρειάζονται σύνδεση για να ανέβουν. Αφαίρεσε τα νέα για να αποθηκεύσεις την κράτηση εκτός σύνδεσης ή αποθήκευσε όταν είσαι ξανά online.',
'reservations.needsConnection': 'Αυτό χρειάζεται σύνδεση. Δοκίμασε ξανά μόλις το TREK συνδεθεί ξανά.',
};
export default reservations;
+3
View File
@@ -262,5 +262,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Foglalási kód másolása',
'reservations.copyFailed': 'Nem sikerült másolni',
'reservations.showInFiles': 'Megjelenítés a fájlokban',
'reservations.filesNeedConnection':
'A fájlok feltöltéséhez kapcsolat kell. Távolítsd el az újakat, hogy offline mentsd a foglalást, vagy ments, amikor újra online vagy.',
'reservations.needsConnection': 'Ehhez kapcsolat kell. Próbáld újra, amint a TREK újra online lesz.',
};
export default reservations;
+3
View File
@@ -251,5 +251,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Salin kode pemesanan',
'reservations.copyFailed': 'Tidak dapat menyalin',
'reservations.showInFiles': 'Tampilkan di File',
'reservations.filesNeedConnection':
'File perlu koneksi untuk diunggah. Hapus file baru untuk menyimpan pemesanan secara offline, atau simpan saat kamu kembali online.',
'reservations.needsConnection': 'Ini memerlukan koneksi. Coba lagi begitu TREK kembali online.',
};
export default reservations;
+3
View File
@@ -259,5 +259,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Copia codice prenotazione',
'reservations.copyFailed': 'Impossibile copiare',
'reservations.showInFiles': 'Mostra nei file',
'reservations.filesNeedConnection':
'I file hanno bisogno di una connessione per essere caricati. Rimuovi quelli nuovi per salvare la prenotazione offline, oppure salva quando sei di nuovo online.',
'reservations.needsConnection': 'Serve una connessione. Riprova quando TREK tornerà online.',
};
export default reservations;
+3
View File
@@ -251,5 +251,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': '予約コードをコピー',
'reservations.copyFailed': 'コピーできませんでした',
'reservations.showInFiles': 'ファイルで表示',
'reservations.filesNeedConnection':
'ファイルのアップロードには接続が必要です。オフラインで予約を保存するには新しいファイルを外すか、オンラインに戻ってから保存してください。',
'reservations.needsConnection': 'この操作には接続が必要です。TREK がオンラインに戻ってから、もう一度お試しください。',
};
export default reservations;
+3
View File
@@ -251,5 +251,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': '예약 코드 복사',
'reservations.copyFailed': '복사하지 못했습니다',
'reservations.showInFiles': '파일에서 보기',
'reservations.filesNeedConnection':
'파일을 업로드하려면 연결이 필요합니다. 오프라인으로 예약을 저장하려면 새 파일을 제거하거나, 다시 온라인이 되면 저장하세요.',
'reservations.needsConnection': '연결이 필요한 작업입니다. TREK가 다시 온라인이 되면 다시 시도하세요.',
};
export default reservations;
+3
View File
@@ -260,5 +260,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Boekingscode kopiëren',
'reservations.copyFailed': 'Kopiëren is mislukt',
'reservations.showInFiles': 'Tonen in bestanden',
'reservations.filesNeedConnection':
'Bestanden hebben een verbinding nodig om te uploaden. Verwijder de nieuwe om de boeking offline op te slaan, of sla op zodra je weer online bent.',
'reservations.needsConnection': 'Hiervoor is een verbinding nodig. Probeer het opnieuw zodra TREK weer online is.',
};
export default reservations;
+3
View File
@@ -273,5 +273,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Kopiuj kod rezerwacji',
'reservations.copyFailed': 'Nie udało się skopiować',
'reservations.showInFiles': 'Pokaż w plikach',
'reservations.filesNeedConnection':
'Pliki wymagają połączenia do przesłania. Usuń nowe, aby zapisać rezerwację offline, albo zapisz po powrocie online.',
'reservations.needsConnection': 'To wymaga połączenia. Spróbuj ponownie, gdy TREK znów będzie online.',
};
export default reservations;
+3
View File
@@ -272,5 +272,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Копировать код бронирования',
'reservations.copyFailed': 'Не удалось скопировать',
'reservations.showInFiles': 'Показать в файлах',
'reservations.filesNeedConnection':
'Для загрузки файлов нужно подключение. Удалите новые, чтобы сохранить бронирование офлайн, или сохраните, когда снова будете онлайн.',
'reservations.needsConnection': 'Для этого нужно подключение. Попробуйте ещё раз, когда TREK снова будет онлайн.',
};
export default reservations;
+3
View File
@@ -268,5 +268,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Kopírovať rezervačný kód',
'reservations.copyFailed': 'Kopírovanie zlyhalo',
'reservations.showInFiles': 'Zobraziť v súboroch',
'reservations.filesNeedConnection':
'Súbory potrebujú na nahratie pripojenie. Odstráň nové, aby si rezerváciu uložil offline, alebo ulož, keď budeš znova online.',
'reservations.needsConnection': 'Na toto je potrebné pripojenie. Skús to znova, keď bude TREK opäť online.',
};
export default reservations;
+3
View File
@@ -259,5 +259,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Kopiera bokningskod',
'reservations.copyFailed': 'Kunde inte kopiera',
'reservations.showInFiles': 'Visa i filer',
'reservations.filesNeedConnection':
'Filer behöver en anslutning för att laddas upp. Ta bort de nya för att spara bokningen offline, eller spara när du är online igen.',
'reservations.needsConnection': 'Det här kräver en anslutning. Försök igen när TREK är online igen.',
};
export default reservations;
+3
View File
@@ -253,5 +253,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'คัดลอกรหัสการจอง',
'reservations.copyFailed': 'คัดลอกไม่สำเร็จ',
'reservations.showInFiles': 'แสดงในไฟล์',
'reservations.filesNeedConnection':
'การอัปโหลดไฟล์ต้องใช้การเชื่อมต่อ ลบไฟล์ใหม่ออกเพื่อบันทึกการจองแบบออฟไลน์ หรือบันทึกเมื่อกลับมาออนไลน์',
'reservations.needsConnection': 'การทำงานนี้ต้องใช้การเชื่อมต่อ ลองอีกครั้งเมื่อ TREK กลับมาออนไลน์',
};
export default reservations;
+3
View File
@@ -260,5 +260,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Rezervasyon kodunu kopyala',
'reservations.copyFailed': 'Kopyalanamadı',
'reservations.showInFiles': 'Dosyalarda göster',
'reservations.filesNeedConnection':
'Dosyaların yüklenmesi için bağlantı gerekir. Rezervasyonu çevrimdışı kaydetmek için yenilerini kaldır ya da tekrar çevrimiçi olduğunda kaydet.',
'reservations.needsConnection': 'Bunun için bağlantı gerekiyor. TREK yeniden çevrimiçi olduğunda tekrar dene.',
};
export default reservations;
+3
View File
@@ -272,5 +272,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Копіювати код бронювання',
'reservations.copyFailed': 'Не вдалося скопіювати',
'reservations.showInFiles': 'Показати у файлах',
'reservations.filesNeedConnection':
"Для завантаження файлів потрібне з'єднання. Видаліть нові, щоб зберегти бронювання офлайн, або збережіть, коли знову будете онлайн.",
'reservations.needsConnection': "Для цього потрібне з'єднання. Спробуйте ще раз, коли TREK знову буде онлайн.",
};
export default reservations;
+3
View File
@@ -254,5 +254,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': 'Sao chép mã đặt chỗ',
'reservations.copyFailed': 'Không thể sao chép',
'reservations.showInFiles': 'Hiện trong Tập tin',
'reservations.filesNeedConnection':
'Cần có kết nối để tải tệp lên. Gỡ các tệp mới để lưu đặt chỗ khi ngoại tuyến, hoặc lưu khi bạn trực tuyến trở lại.',
'reservations.needsConnection': 'Thao tác này cần kết nối. Hãy thử lại khi TREK trực tuyến trở lại.',
};
export default reservations;
+3
View File
@@ -250,5 +250,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': '複製預訂碼',
'reservations.copyFailed': '無法複製',
'reservations.showInFiles': '在檔案中顯示',
'reservations.filesNeedConnection':
'上傳檔案需要網路連線。移除新檔案即可離線儲存這筆預訂,或在恢復連線後再儲存。',
'reservations.needsConnection': '此操作需要網路連線。請在 TREK 恢復連線後再試一次。',
};
export default reservations;
+3
View File
@@ -250,5 +250,8 @@ const reservations: TranslationStrings = {
'reservations.copyCode': '复制预订码',
'reservations.copyFailed': '无法复制',
'reservations.showInFiles': '在文件中显示',
'reservations.filesNeedConnection':
'上传文件需要网络连接。移除新文件即可离线保存这条预订,或在恢复联网后再保存。',
'reservations.needsConnection': '此操作需要网络连接。请在 TREK 恢复联网后重试。',
};
export default reservations;