feat(share): the public trip page in the planner's design

The page a share link opens is rebuilt from top bar to footer: the
planner's light top bar with the language picker, the trip as a hero
made of its cover, a tab bar that stays in reach, the days as the
planner's cards beside a map that stays in view, bookings as the
booking cards, packing and costs as cards with their progress and
shares, the chat as bubbles, and empty states for sections the owner
shared with nothing in them yet.

The map picks its day in a select with a step back and forth instead
of a row of chips a three-week trip did not fit into.
This commit is contained in:
Maurice
2026-09-28 14:40:34 +02:00
parent 21c068eb43
commit bbf8d94f9f
44 changed files with 1804 additions and 1463 deletions
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'تمت المشاركة عبر',
'shared.confirmed': 'مؤكد',
'shared.pending': 'قيد الانتظار',
'shared.footerTagline': 'مخطط الرحلات الذي تستضيفه بنفسك. مفتوح المصدر.',
'shared.emptyBookings': 'لا توجد حجوزات مشتركة بعد',
'shared.emptyPacking': 'قائمة الأمتعة لا تزال فارغة',
'shared.emptyCosts': 'لا توجد نفقات بعد',
'shared.emptyChat': 'لا توجد رسائل بعد',
'shared.wholeTrip': 'الرحلة كاملة',
};
export default shared;
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Paylaşım vasitəsi:',
'shared.confirmed': 'Təsdiqlənib',
'shared.pending': 'Gözləyir',
'shared.footerTagline': 'Özünüz host etdiyiniz səyahət planlayıcısı. Açıq mənbə.',
'shared.emptyBookings': 'Hələ paylaşılan bron yoxdur',
'shared.emptyPacking': 'Əşya siyahısı hələ boşdur',
'shared.emptyCosts': 'Hələ xərc yoxdur',
'shared.emptyChat': 'Hələ mesaj yoxdur',
'shared.wholeTrip': 'Bütün səyahət',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Compartilhado via',
'shared.confirmed': 'Confirmado',
'shared.pending': 'Pendente',
'shared.footerTagline': 'O planejador de viagens que você mesmo hospeda. Código aberto.',
'shared.emptyBookings': 'Nenhuma reserva compartilhada ainda',
'shared.emptyPacking': 'A lista de bagagem ainda está vazia',
'shared.emptyCosts': 'Nenhuma despesa ainda',
'shared.emptyChat': 'Nenhuma mensagem ainda',
'shared.wholeTrip': 'Viagem inteira',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Compartit via',
'shared.confirmed': 'Confirmat',
'shared.pending': 'Pendent',
'shared.footerTagline': 'El planificador de viatges que allotges tu mateix. Codi obert.',
'shared.emptyBookings': "Encara no s'ha compartit cap reserva",
'shared.emptyPacking': "La llista d'equipatge encara és buida",
'shared.emptyCosts': 'Encara no hi ha despeses',
'shared.emptyChat': 'Encara no hi ha missatges',
'shared.wholeTrip': 'Tot el viatge',
};
export default shared;
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Sdíleno přes',
'shared.confirmed': 'Potvrzeno',
'shared.pending': 'Čeká na potvrzení',
'shared.footerTagline': 'Plánovač cest, který si hostujete sami. Open source.',
'shared.emptyBookings': 'Zatím nejsou sdíleny žádné rezervace',
'shared.emptyPacking': 'Seznam věcí k zabalení je zatím prázdný',
'shared.emptyCosts': 'Zatím žádné výdaje',
'shared.emptyChat': 'Zatím žádné zprávy',
'shared.wholeTrip': 'Celá cesta',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Geteilt über',
'shared.confirmed': 'Bestätigt',
'shared.pending': 'Ausstehend',
'shared.footerTagline': 'Der Reiseplaner, den du selbst hostest. Open Source.',
'shared.emptyBookings': 'Noch keine Buchungen geteilt',
'shared.emptyPacking': 'Die Packliste ist noch leer',
'shared.emptyCosts': 'Noch keine Ausgaben',
'shared.emptyChat': 'Noch keine Nachrichten',
'shared.wholeTrip': 'Ganze Reise',
};
export default shared;
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Shared via',
'shared.confirmed': 'Confirmed',
'shared.pending': 'Pending',
'shared.footerTagline': 'The travel planner you host yourself. Open source.',
'shared.emptyBookings': 'No bookings shared yet',
'shared.emptyPacking': 'The packing list is still empty',
'shared.emptyCosts': 'No expenses yet',
'shared.emptyChat': 'No messages yet',
'shared.wholeTrip': 'Whole trip',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Compartido vía',
'shared.confirmed': 'Confirmado',
'shared.pending': 'Pendiente',
'shared.footerTagline': 'El planificador de viajes que alojas tú mismo. Código abierto.',
'shared.emptyBookings': 'Aún no se han compartido reservas',
'shared.emptyPacking': 'La lista de equipaje aún está vacía',
'shared.emptyCosts': 'Aún no hay gastos',
'shared.emptyChat': 'Aún no hay mensajes',
'shared.wholeTrip': 'Todo el viaje',
};
export default shared;
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Jagatud rakendusega',
'shared.confirmed': 'Kinnitatud',
'shared.pending': 'Ootel',
'shared.footerTagline': 'Reisiplaneerija, mida majutad ise. Avatud lähtekoodiga.',
'shared.emptyBookings': 'Broneeringuid pole veel jagatud',
'shared.emptyPacking': 'Pakkimisnimekiri on veel tühi',
'shared.emptyCosts': 'Kulusid pole veel',
'shared.emptyChat': 'Sõnumeid pole veel',
'shared.wholeTrip': 'Kogu reis',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Partagé via',
'shared.confirmed': 'Confirmé',
'shared.pending': 'En attente',
'shared.footerTagline': 'Le planificateur de voyage que vous hébergez vous-même. Open source.',
'shared.emptyBookings': 'Aucune réservation partagée pour le moment',
'shared.emptyPacking': 'La liste de bagages est encore vide',
'shared.emptyCosts': 'Aucune dépense pour le moment',
'shared.emptyChat': 'Aucun message pour le moment',
'shared.wholeTrip': 'Tout le voyage',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Κοινοποιήθηκε μέσω',
'shared.confirmed': 'Επιβεβαιωμένο',
'shared.pending': 'Σε εκκρεμότητα',
'shared.footerTagline': 'Ο σχεδιαστής ταξιδιών που φιλοξενείτε μόνοι σας. Ανοιχτού κώδικα.',
'shared.emptyBookings': 'Δεν έχουν κοινοποιηθεί κρατήσεις ακόμη',
'shared.emptyPacking': 'Η λίστα αποσκευών είναι ακόμη άδεια',
'shared.emptyCosts': 'Δεν υπάρχουν έξοδα ακόμη',
'shared.emptyChat': 'Δεν υπάρχουν μηνύματα ακόμη',
'shared.wholeTrip': 'Όλο το ταξίδι',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Megosztva:',
'shared.confirmed': 'Megerősítve',
'shared.pending': 'Függőben',
'shared.footerTagline': 'Az utazástervező, amelyet te magad üzemeltetsz. Nyílt forráskódú.',
'shared.emptyBookings': 'Még nincs megosztott foglalás',
'shared.emptyPacking': 'A csomaglista még üres',
'shared.emptyCosts': 'Még nincsenek kiadások',
'shared.emptyChat': 'Még nincsenek üzenetek',
'shared.wholeTrip': 'Teljes utazás',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Dibagikan via',
'shared.confirmed': 'Dikonfirmasi',
'shared.pending': 'Menunggu',
'shared.footerTagline': 'Perencana perjalanan yang Anda hosting sendiri. Sumber terbuka.',
'shared.emptyBookings': 'Belum ada pemesanan yang dibagikan',
'shared.emptyPacking': 'Daftar barang bawaan masih kosong',
'shared.emptyCosts': 'Belum ada pengeluaran',
'shared.emptyChat': 'Belum ada pesan',
'shared.wholeTrip': 'Seluruh perjalanan',
};
export default shared;
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Condiviso tramite',
'shared.confirmed': 'Confermato',
'shared.pending': 'In attesa',
'shared.footerTagline': 'Il pianificatore di viaggi che ospiti tu stesso. Open source.',
'shared.emptyBookings': 'Nessuna prenotazione condivisa finora',
'shared.emptyPacking': 'La lista bagagli è ancora vuota',
'shared.emptyCosts': 'Nessuna spesa finora',
'shared.emptyChat': 'Nessun messaggio finora',
'shared.wholeTrip': 'Tutto il viaggio',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': '共有元',
'shared.confirmed': '確定',
'shared.pending': '保留',
'shared.footerTagline': '自分でホストする旅行プランナー。オープンソース。',
'shared.emptyBookings': '共有された予約はまだありません',
'shared.emptyPacking': '持ち物リストはまだ空です',
'shared.emptyCosts': 'まだ支出はありません',
'shared.emptyChat': 'まだメッセージはありません',
'shared.wholeTrip': '旅行全体',
};
export default shared;
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': '공유 경로',
'shared.confirmed': '확정됨',
'shared.pending': '대기 중',
'shared.footerTagline': '직접 호스팅하는 여행 플래너. 오픈 소스.',
'shared.emptyBookings': '아직 공유된 예약이 없습니다',
'shared.emptyPacking': '짐 목록이 아직 비어 있습니다',
'shared.emptyCosts': '아직 지출이 없습니다',
'shared.emptyChat': '아직 메시지가 없습니다',
'shared.wholeTrip': '전체 여행',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Gedeeld via',
'shared.confirmed': 'Bevestigd',
'shared.pending': 'In afwachting',
'shared.footerTagline': 'De reisplanner die je zelf host. Open source.',
'shared.emptyBookings': 'Nog geen boekingen gedeeld',
'shared.emptyPacking': 'De paklijst is nog leeg',
'shared.emptyCosts': 'Nog geen uitgaven',
'shared.emptyChat': 'Nog geen berichten',
'shared.wholeTrip': 'Hele reis',
};
export default shared;
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Udostępnione przez',
'shared.confirmed': 'Potwierdzone',
'shared.pending': 'Oczekujące',
'shared.footerTagline': 'Planer podróży, który hostujesz sam. Open source.',
'shared.emptyBookings': 'Nie udostępniono jeszcze żadnych rezerwacji',
'shared.emptyPacking': 'Lista pakowania jest jeszcze pusta',
'shared.emptyCosts': 'Brak wydatków',
'shared.emptyChat': 'Brak wiadomości',
'shared.wholeTrip': 'Cała podróż',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Поделено через',
'shared.confirmed': 'Подтверждено',
'shared.pending': 'Ожидает',
'shared.footerTagline': 'Планировщик путешествий, который вы размещаете сами. Открытый исходный код.',
'shared.emptyBookings': 'Бронирований пока нет',
'shared.emptyPacking': 'Список вещей пока пуст',
'shared.emptyCosts': 'Расходов пока нет',
'shared.emptyChat': 'Сообщений пока нет',
'shared.wholeTrip': 'Всё путешествие',
};
export default shared;
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Zdieľané cez',
'shared.confirmed': 'Potvrdené',
'shared.pending': 'Čaká na potvrdenie',
'shared.footerTagline': 'Plánovač ciest, ktorý si hostujete sami. Open source.',
'shared.emptyBookings': 'Zatiaľ nie sú zdieľané žiadne rezervácie',
'shared.emptyPacking': 'Zoznam vecí na zbalenie je zatiaľ prázdny',
'shared.emptyCosts': 'Zatiaľ žiadne výdavky',
'shared.emptyChat': 'Zatiaľ žiadne správy',
'shared.wholeTrip': 'Celá cesta',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Delad via',
'shared.confirmed': 'Godkänt',
'shared.pending': 'Väntande',
'shared.footerTagline': 'Reseplaneraren du driver själv. Öppen källkod.',
'shared.emptyBookings': 'Inga bokningar delade ännu',
'shared.emptyPacking': 'Packlistan är fortfarande tom',
'shared.emptyCosts': 'Inga utgifter ännu',
'shared.emptyChat': 'Inga meddelanden ännu',
'shared.wholeTrip': 'Hela resan',
};
export default shared;
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': "แชร์ผ่าน",
'shared.confirmed': "ยืนยันแล้ว",
'shared.pending': "รอดำเนินการ",
'shared.footerTagline': 'เครื่องมือวางแผนการเดินทางที่คุณโฮสต์เอง โอเพนซอร์ส',
'shared.emptyBookings': 'ยังไม่มีการจองที่แชร์',
'shared.emptyPacking': 'รายการของที่ต้องแพ็กยังว่างอยู่',
'shared.emptyCosts': 'ยังไม่มีค่าใช้จ่าย',
'shared.emptyChat': 'ยังไม่มีข้อความ',
'shared.wholeTrip': 'ทั้งทริป',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Şununla paylaşıldı:',
'shared.confirmed': 'Onaylandı',
'shared.pending': 'Beklemede',
'shared.footerTagline': 'Kendi sunucunda barındırdığın seyahat planlayıcısı. Açık kaynak.',
'shared.emptyBookings': 'Henüz paylaşılan rezervasyon yok',
'shared.emptyPacking': 'Bavul listesi henüz boş',
'shared.emptyCosts': 'Henüz harcama yok',
'shared.emptyChat': 'Henüz mesaj yok',
'shared.wholeTrip': 'Tüm seyahat',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Поділено через',
'shared.confirmed': 'Підтверджено',
'shared.pending': 'Очікує',
'shared.footerTagline': 'Планувальник подорожей, який ви розміщуєте самі. Відкритий код.',
'shared.emptyBookings': 'Бронювань поки немає',
'shared.emptyPacking': 'Список речей поки порожній',
'shared.emptyCosts': 'Витрат поки немає',
'shared.emptyChat': 'Повідомлень поки немає',
'shared.wholeTrip': 'Уся подорож',
};
export default shared;
+6
View File
@@ -21,5 +21,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': 'Được chia sẻ qua',
'shared.confirmed': 'Đã xác nhận',
'shared.pending': 'Chưa giải quyết',
'shared.footerTagline': 'Trình lập kế hoạch du lịch do bạn tự lưu trữ. Mã nguồn mở.',
'shared.emptyBookings': 'Chưa có đặt chỗ nào được chia sẻ',
'shared.emptyPacking': 'Danh sách hành lý vẫn còn trống',
'shared.emptyCosts': 'Chưa có khoản chi nào',
'shared.emptyChat': 'Chưa có tin nhắn nào',
'shared.wholeTrip': 'Cả chuyến đi',
};
export default shared;
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': '透過以下分享',
'shared.confirmed': '已確認',
'shared.pending': '待確認',
'shared.footerTagline': '由你自行架設的旅行規劃工具。開源。',
'shared.emptyBookings': '尚未分享任何預訂',
'shared.emptyPacking': '行李清單還是空的',
'shared.emptyCosts': '尚無支出',
'shared.emptyChat': '尚無訊息',
'shared.wholeTrip': '整趟旅程',
};
export default shared;
+6
View File
@@ -20,5 +20,11 @@ const shared: TranslationStrings = {
'shared.sharedVia': '通过以下分享',
'shared.confirmed': '已确认',
'shared.pending': '待确认',
'shared.footerTagline': '由你自己托管的旅行规划工具。开源。',
'shared.emptyBookings': '尚未共享任何预订',
'shared.emptyPacking': '行李清单还是空的',
'shared.emptyCosts': '暂无支出',
'shared.emptyChat': '暂无消息',
'shared.wholeTrip': '整个行程',
};
export default shared;