diff --git a/frontend/src/lib/components/AdventureCard.svelte b/frontend/src/lib/components/AdventureCard.svelte index 3aeb6bc..dbdf5e4 100644 --- a/frontend/src/lib/components/AdventureCard.svelte +++ b/frontend/src/lib/components/AdventureCard.svelte @@ -321,11 +321,8 @@ .line-clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; + line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } - - .shadow-3xl { - box-shadow: 0 35px 60px -12px rgba(0, 0, 0, 0.25); - } diff --git a/frontend/src/lib/components/ChecklistCard.svelte b/frontend/src/lib/components/ChecklistCard.svelte index 37a024f..cb30b45 100644 --- a/frontend/src/lib/components/ChecklistCard.svelte +++ b/frontend/src/lib/components/ChecklistCard.svelte @@ -62,43 +62,53 @@ on:confirm={deleteChecklist} /> {/if} -
-
-
-

- {checklist.name} -

+
+ +
+

{checklist.name}

+
+
{$t('adventures.checklist')}
+ {#if unlinked} +
{$t('adventures.out_of_range')}
+ {/if} +
-
{$t('adventures.checklist')}
+ + {#if checklist.items.length > 0} -

+

{checklist.items.length} {checklist.items.length > 1 ? $t('checklist.items') : $t('checklist.item')}

{/if} - {#if unlinked} -
{$t('adventures.out_of_range')}
- {/if} + + {#if checklist.date && checklist.date !== ''} -
- +
+

{new Date(checklist.date).toLocaleDateString(undefined, { timeZone: 'UTC' })}

{/if} -
- - {#if checklist.user_id == user?.uuid || (collection && user && collection.shared_with && collection.shared_with.includes(user.uuid))} + {#if checklist.user_id == user?.uuid || (collection && user && collection.shared_with?.includes(user.uuid))} (isWarningModalOpen = true)} > + + {$t('adventures.delete')} + {/if}
diff --git a/frontend/src/lib/components/CityCard.svelte b/frontend/src/lib/components/CityCard.svelte index 6be3b9e..8d4ee35 100644 --- a/frontend/src/lib/components/CityCard.svelte +++ b/frontend/src/lib/components/CityCard.svelte @@ -41,25 +41,40 @@
-
-

{city.name}

+
+ +

{city.name}

+ +
{city.region_name}, {city.country_name}
-
{city.region}
+
Region ID: {city.region}
-
- {#if !visited} - + + +
+ {#if visited === false} + {/if} - {#if visited} - + {#if visited === true} + {/if}
+ + diff --git a/frontend/src/lib/components/CollectionCard.svelte b/frontend/src/lib/components/CollectionCard.svelte index 33e1d29..9a505e9 100644 --- a/frontend/src/lib/components/CollectionCard.svelte +++ b/frontend/src/lib/components/CollectionCard.svelte @@ -84,99 +84,156 @@ {/if}
- -
-
- -
-
-
+ +
+ + + +
+
{collection.is_public ? $t('adventures.public') : $t('adventures.private')}
{#if collection.is_archived} -
{$t('adventures.archived')}
+
+ {$t('adventures.archived')} +
{/if}
-

{collection.adventures.length} {$t('navbar.adventures')}

- {#if collection.start_date && collection.end_date} -

- {$t('adventures.dates')}: {new Date(collection.start_date).toLocaleDateString(undefined, { - timeZone: 'UTC' - })} - - {new Date(collection.end_date).toLocaleDateString(undefined, { timeZone: 'UTC' })} -

- -

- {$t('adventures.duration')}: {Math.floor( - (new Date(collection.end_date).getTime() - new Date(collection.start_date).getTime()) / - (1000 * 60 * 60 * 24) - ) + 1}{' '} - days -

{/if} +
-
+ +
+ +
+ + + +

+ {collection.adventures.length} + {$t('navbar.adventures')} +

+ + + {#if collection.start_date && collection.end_date} +

+ {$t('adventures.dates')}: + {new Date(collection.start_date).toLocaleDateString(undefined, { timeZone: 'UTC' })} – + {new Date(collection.end_date).toLocaleDateString(undefined, { timeZone: 'UTC' })} +

+

+ {$t('adventures.duration')}: {Math.floor( + (new Date(collection.end_date).getTime() - new Date(collection.start_date).getTime()) / + (1000 * 60 * 60 * 24) + ) + 1} days +

+ {/if} +
+ + +
{#if type == 'link'} - {:else} -
{/if}
+ + diff --git a/frontend/src/lib/components/CountryCard.svelte b/frontend/src/lib/components/CountryCard.svelte index 3894631..a9b3d12 100644 --- a/frontend/src/lib/components/CountryCard.svelte +++ b/frontend/src/lib/components/CountryCard.svelte @@ -5,6 +5,7 @@ import { t } from 'svelte-i18n'; import MapMarkerStar from '~icons/mdi/map-marker-star'; + import Launch from '~icons/mdi/launch'; export let country: Country; @@ -14,24 +15,31 @@
+
- - No image available + {`Flag
-
-

{country.name}

+ + +
+ +

{country.name}

+ +
{#if country.subregion}
{country.subregion}
{/if} {#if country.capital} -
- {country.capital} +
+ + {country.capital}
{/if} - {#if country.num_visits > 0 && country.num_visits != country.num_regions} + + {#if country.num_visits > 0 && country.num_visits !== country.num_regions}
Visited {country.num_visits} Region{country.num_visits > 1 ? 's' : ''}
@@ -42,9 +50,20 @@ {/if}
-
- - + +
+
+ + diff --git a/frontend/src/lib/components/LodgingCard.svelte b/frontend/src/lib/components/LodgingCard.svelte index 7b7395c..148e42a 100644 --- a/frontend/src/lib/components/LodgingCard.svelte +++ b/frontend/src/lib/components/LodgingCard.svelte @@ -7,6 +7,7 @@ import { t } from 'svelte-i18n'; import DeleteWarning from './DeleteWarning.svelte'; import { LODGING_TYPES_ICONS } from '$lib'; + import { formatDateInTimezone } from '$lib/dateUtils'; const dispatch = createEventDispatcher(); @@ -17,24 +18,6 @@ return '🏨'; } } - - function formatDateInTimezone(utcDate: string, timezone?: string): string { - if (!utcDate) return ''; - try { - return new Intl.DateTimeFormat(undefined, { - timeZone: timezone, - year: 'numeric', - month: 'short', - day: 'numeric', - hour: '2-digit', - minute: '2-digit', - hour12: true - }).format(new Date(utcDate)); - } catch { - return new Date(utcDate).toLocaleString(); - } - } - export let lodging: Lodging; export let user: User | null = null; export let collection: Collection | null = null; @@ -109,64 +92,71 @@ {/if}
-
- -

{lodging.name}

-
-
- {$t(`lodging.${lodging.type}`) + ' ' + getLodgingIcon(lodging.type)} +
+ +
+

{lodging.name}

+
+
+ {$t(`lodging.${lodging.type}`)} + {getLodgingIcon(lodging.type)} +
+ {#if unlinked} +
{$t('adventures.out_of_range')}
+ {/if}
- {#if unlinked} -
{$t('adventures.out_of_range')}
- {/if}
- +
{#if lodging.location}
- {$t('adventures.location')}: -

{lodging.location}

+ {$t('adventures.location')}: +

{lodging.location}

{/if} {#if lodging.check_in && lodging.check_out}
- {$t('adventures.dates')}: -

- {formatDateInTimezone(lodging.check_in ?? '', lodging.timezone ?? undefined)} – - {formatDateInTimezone(lodging.check_out ?? '', lodging.timezone ?? undefined)} + {$t('adventures.dates')}: +

+ {formatDateInTimezone(lodging.check_in, lodging.timezone)} – + {formatDateInTimezone(lodging.check_out, lodging.timezone)} {#if lodging.timezone} - ({lodging.timezone}) + ({lodging.timezone}) {/if}

{/if} - {#if lodging.user_id == user?.uuid || (collection && user && collection.shared_with && collection.shared_with.includes(user.uuid))} +
+ + + {#if lodging.user_id == user?.uuid || (collection && user && collection.shared_with?.includes(user.uuid))} +
{#if lodging.reservation_number}
- {$t('adventures.reservation_number')}: -

{lodging.reservation_number}

+ {$t('adventures.reservation_number')}: +

{lodging.reservation_number}

{/if} {#if lodging.price}
- {$t('adventures.price')}: -

{lodging.price}

+ {$t('adventures.price')}: +

{lodging.price}

{/if} - {/if} -
+
+ {/if} - {#if lodging.user_id == user?.uuid || (collection && user && collection.shared_with && collection.shared_with.includes(user.uuid))} -
+ {#if lodging.user_id == user?.uuid || (collection && user && collection.shared_with?.includes(user.uuid))} +
- {#if note.user_id == user?.uuid || (collection && user && collection.shared_with && collection.shared_with.includes(user.uuid))} + {#if note.user_id == user?.uuid || (collection && user && collection.shared_with?.includes(user.uuid))} (isWarningModalOpen = true)} > + + {$t('adventures.delete')} + {/if}
diff --git a/frontend/src/lib/components/RegionCard.svelte b/frontend/src/lib/components/RegionCard.svelte index 9d14133..f90b9db 100644 --- a/frontend/src/lib/components/RegionCard.svelte +++ b/frontend/src/lib/components/RegionCard.svelte @@ -50,36 +50,47 @@
-
-

{region.name}

-
-
-

{region.country_name}

-
-
-

{region.num_cities} {$t('worldtravel.cities')}

-
-
-

{region.id}

+
+ +

{region.name}

+ + +
+
{region.country_name}
+
+ {region.num_cities} + {$t('worldtravel.cities')}
+
ID: {region.id}
-
- - {#if !visited && visited !== undefined} - + + +
+ {#if visited === false} + {/if} - {#if visited && visited !== undefined} - + {#if visited === true} + {/if} {#if region.num_cities > 0} - + {/if}
+ + diff --git a/frontend/src/lib/components/ShareModal.svelte b/frontend/src/lib/components/ShareModal.svelte index e3dbc6a..80f995e 100644 --- a/frontend/src/lib/components/ShareModal.svelte +++ b/frontend/src/lib/components/ShareModal.svelte @@ -89,47 +89,73 @@ - - +
-

{$t('share.not_shared_with')}

-
    - {#each notSharedWithUsers as user} -
    - share(event.detail)} - on:unshare={(event) => unshare(event.detail)} - /> + + +
    +

    {$t('share.not_shared_with')}

    + {#if notSharedWithUsers.length > 0} +
    + {#each notSharedWithUsers as user} + share(event.detail)} + on:unshare={(event) => unshare(event.detail)} + /> + {/each}
    - {/each} - {#if notSharedWithUsers.length === 0} -

    {$t('share.no_users_shared')}

    + {:else} +

    {$t('share.no_users_shared')}

    {/if} -
- +
+ + +
+ +
diff --git a/frontend/src/lib/components/TransportationCard.svelte b/frontend/src/lib/components/TransportationCard.svelte index 9eea0a0..586c099 100644 --- a/frontend/src/lib/components/TransportationCard.svelte +++ b/frontend/src/lib/components/TransportationCard.svelte @@ -8,6 +8,7 @@ import DeleteWarning from './DeleteWarning.svelte'; // import ArrowDownThick from '~icons/mdi/arrow-down-thick'; import { TRANSPORTATION_TYPES_ICONS } from '$lib'; + import { formatDateInTimezone } from '$lib/dateUtils'; function getTransportationIcon(type: string) { if (type in TRANSPORTATION_TYPES_ICONS) { @@ -18,23 +19,6 @@ } const dispatch = createEventDispatcher(); - function formatDateInTimezone(utcDate: string, timezone?: string): string { - if (!utcDate) return ''; - try { - return new Intl.DateTimeFormat(undefined, { - timeZone: timezone, - year: 'numeric', - month: 'short', - day: 'numeric', - hour: '2-digit', - minute: '2-digit', - hour12: true - }).format(new Date(utcDate)); - } catch { - return new Date(utcDate).toLocaleString(); - } - } - export let transportation: Transportation; export let user: User | null = null; export let collection: Collection | null = null; @@ -123,66 +107,62 @@ {/if}
-
- -

{transportation.name}

-
-
- {$t(`transportation.modes.${transportation.type}`) + - ' ' + - getTransportationIcon(transportation.type)} +
+ +
+

{transportation.name}

+
+
+ {$t(`transportation.modes.${transportation.type}`)} + {' '}{getTransportationIcon(transportation.type)} +
+ {#if transportation.type === 'plane' && transportation.flight_number} +
{transportation.flight_number}
+ {/if} + {#if unlinked} +
{$t('adventures.out_of_range')}
+ {/if}
- {#if transportation.type == 'plane' && transportation.flight_number} -
{transportation.flight_number}
- {/if} - {#if unlinked} -
{$t('adventures.out_of_range')}
- {/if}
- +
{#if transportation.from_location}
- {$t('adventures.from')}: -

{transportation.from_location}

+ {$t('adventures.from')}: +

{transportation.from_location}

{/if} {#if transportation.date}
- {$t('adventures.start')}: -

- {formatDateInTimezone(transportation.date, transportation.start_timezone ?? undefined)} + {$t('adventures.start')}: +

+ {formatDateInTimezone(transportation.date, transportation.start_timezone)} {#if transportation.start_timezone} - ({transportation.start_timezone}) + ({transportation.start_timezone}) {/if}

{/if}
- +
{#if transportation.to_location} -
- {$t('adventures.to')}: - -

{transportation.to_location}

+ {$t('adventures.to')}: +

{transportation.to_location}

{/if} {#if transportation.end_date}
- {$t('adventures.end')}: -

- {formatDateInTimezone( - transportation.end_date, - transportation.end_timezone || undefined - )} + {$t('adventures.end')}: +

+ {formatDateInTimezone(transportation.end_date, transportation.end_timezone)} {#if transportation.end_timezone} - ({transportation.end_timezone}) + ({transportation.end_timezone}) {/if}

@@ -190,20 +170,20 @@
- {#if transportation.user_id == user?.uuid || (collection && user && collection.shared_with && collection.shared_with.includes(user.uuid))} -
+ {#if transportation.user_id == user?.uuid || (collection && user && collection.shared_with?.includes(user.uuid))} +
{:else if shared_with && !shared_with.includes(user.uuid)} - + {:else} - + {/if}
diff --git a/frontend/src/lib/dateUtils.ts b/frontend/src/lib/dateUtils.ts index 3eccaa5..38bba60 100644 --- a/frontend/src/lib/dateUtils.ts +++ b/frontend/src/lib/dateUtils.ts @@ -118,6 +118,23 @@ export function validateDateRange( return { valid: true }; } +export function formatDateInTimezone(utcDate: string, timezone: string | null): string { + if (!utcDate) return ''; + try { + return new Intl.DateTimeFormat(undefined, { + timeZone: timezone || undefined, + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit', + hour12: true + }).format(new Date(utcDate)); + } catch { + return new Date(utcDate).toLocaleString(); + } +} + /** * Format UTC date for display * @param utcDate - UTC date in ISO format diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 0e47e4f..c10dda4 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -258,6 +258,8 @@ "hide": "Hide", "clear_location": "Clear Location", "starting_airport": "Starting Airport", + "view_profile": "View Profile", + "joined": "Joined", "ending_airport": "Ending Airport", "no_location_found": "No location found", "from": "From", diff --git a/frontend/src/locales/es.json b/frontend/src/locales/es.json index 024ab30..858c7c8 100644 --- a/frontend/src/locales/es.json +++ b/frontend/src/locales/es.json @@ -319,7 +319,9 @@ "timed": "Cronometrado", "distance": "Distancia", "all_linked_items": "Todos los artículos vinculados", - "itinerary": "Itinerario" + "itinerary": "Itinerario", + "joined": "Unido", + "view_profile": "Ver perfil" }, "worldtravel": { "all": "Todo", diff --git a/frontend/src/locales/fr.json b/frontend/src/locales/fr.json index dfdd496..54c4f73 100644 --- a/frontend/src/locales/fr.json +++ b/frontend/src/locales/fr.json @@ -271,7 +271,9 @@ "timed": "Chronométré", "distance": "Distance", "all_linked_items": "Tous les éléments liés", - "itinerary": "Itinéraire" + "itinerary": "Itinéraire", + "joined": "Joint", + "view_profile": "Afficher le profil" }, "home": { "desc_1": "Découvrez, planifiez et explorez en toute simplicité", diff --git a/frontend/src/locales/it.json b/frontend/src/locales/it.json index fd606dd..0da8696 100644 --- a/frontend/src/locales/it.json +++ b/frontend/src/locales/it.json @@ -271,7 +271,9 @@ "timed": "A tempo", "distance": "Distanza", "all_linked_items": "Tutti gli elementi collegati", - "itinerary": "Itinerario" + "itinerary": "Itinerario", + "joined": "Partecipato", + "view_profile": "Visualizza il profilo" }, "home": { "desc_1": "Scopri, pianifica ed esplora con facilità", diff --git a/frontend/src/locales/ko.json b/frontend/src/locales/ko.json index 60754f9..206bc88 100644 --- a/frontend/src/locales/ko.json +++ b/frontend/src/locales/ko.json @@ -271,7 +271,9 @@ "timed": "시간이 정해졌습니다", "distance": "거리", "all_linked_items": "모든 링크 된 항목", - "itinerary": "여정" + "itinerary": "여정", + "joined": "가입", + "view_profile": "프로필을 봅니다" }, "auth": { "both_passwords_required": "두 암호 모두 필요합니다", diff --git a/frontend/src/locales/nl.json b/frontend/src/locales/nl.json index 6f071f3..ec167bf 100644 --- a/frontend/src/locales/nl.json +++ b/frontend/src/locales/nl.json @@ -271,7 +271,9 @@ "timed": "Getimed", "distance": "Afstand", "all_linked_items": "Alle gekoppelde items", - "itinerary": "Routebeschrijving" + "itinerary": "Routebeschrijving", + "joined": "Samengevoegd", + "view_profile": "Bekijk profiel" }, "home": { "desc_1": "Ontdek, plan en verken met gemak", diff --git a/frontend/src/locales/no.json b/frontend/src/locales/no.json index ca4d959..29f760f 100644 --- a/frontend/src/locales/no.json +++ b/frontend/src/locales/no.json @@ -319,7 +319,9 @@ "timed": "Tidsbestemt", "distance": "Avstand", "all_linked_items": "Alle koblede varer", - "itinerary": "Reiserute" + "itinerary": "Reiserute", + "joined": "Ble med", + "view_profile": "Vis profil" }, "worldtravel": { "country_list": "Liste over land", diff --git a/frontend/src/locales/pl.json b/frontend/src/locales/pl.json index 05ced8a..e3551e3 100644 --- a/frontend/src/locales/pl.json +++ b/frontend/src/locales/pl.json @@ -319,7 +319,9 @@ "timed": "Czas", "distance": "Dystans", "all_linked_items": "Wszystkie połączone elementy", - "itinerary": "Trasa" + "itinerary": "Trasa", + "joined": "Dołączył", + "view_profile": "Zobacz profil" }, "worldtravel": { "country_list": "Lista krajów", diff --git a/frontend/src/locales/sv.json b/frontend/src/locales/sv.json index 409df01..fd39824 100644 --- a/frontend/src/locales/sv.json +++ b/frontend/src/locales/sv.json @@ -271,7 +271,9 @@ "timed": "Tidsinställd", "distance": "Avstånd", "all_linked_items": "Alla länkade objekt", - "itinerary": "Resväg" + "itinerary": "Resväg", + "joined": "Gick med i", + "view_profile": "Visa profil" }, "home": { "desc_1": "Upptäck, planera och utforska med lätthet", diff --git a/frontend/src/locales/zh.json b/frontend/src/locales/zh.json index 8a0176e..fbee109 100644 --- a/frontend/src/locales/zh.json +++ b/frontend/src/locales/zh.json @@ -319,7 +319,9 @@ "timed": "时间", "distance": "距离", "all_linked_items": "所有链接的项目", - "itinerary": "行程" + "itinerary": "行程", + "joined": "加入", + "view_profile": "查看个人资料" }, "auth": { "forgot_password": "忘记密码?",