💄 Shared Trip: add checklist and support

This commit is contained in:
itskovacs 2025-08-20 18:18:15 +02:00
parent 7f44896ddb
commit cec801f793
2 changed files with 75 additions and 38 deletions

View File

@ -3,8 +3,8 @@
<section class="mt-4">
<div class="p-4 print:p-0 flex items-center justify-between">
<div class="flex items-center gap-2">
<div class="flex flex-col max-w-[55vw] md:max-w-full">
<h1 class="font-medium tracking-tight text-2xl truncate">{{ trip.name }}</h1>
<div class="pl-2 flex flex-col max-w-[55vw] md:max-w-full min-w-0">
<h1 class="font-medium tracking-tight text-xl md:text-2xl truncate">{{ trip.name }}</h1>
<span class="text-xs text-gray-500">{{ trip.days.length }} {{ trip.days!.length > 1 ? 'days' : 'day'}}</span>
</div>
</div>
@ -14,6 +14,7 @@
<div class="flex gap-2 items-center text-xs text-gray-500"><i class="pi pi-github"></i>itskovacs/trip</div>
</div>
<div class="flex items-center gap-2 print:hidden">
<p-button pTooltip="Checklist" text (click)="openChecklist()" icon="pi pi-check-square" severity="help" />
<p-button pTooltip="Packing list" tooltipPosition="left" text (click)="openPackingList()" icon="pi pi-briefcase"
severity="help" />
<span
@ -354,6 +355,10 @@
p.price || '-'
}} {{ currency$ | async }}</span>
@if (trip.collaborators.length) {
<span class="bg-gray-100 text-gray-800 text-sm me-2 px-2.5 py-0.5 rounded dark:bg-gray-100/85">{{ p.user
}}</span>
}
</div>
</div>
</div>
@ -415,41 +420,18 @@
</div>
<div class="p-4 shadow rounded-md w-full min-h-20">
<div class="group relative p-2 mb-2 flex flex-col items-start">
<h1 class="font-semibold tracking-tight text-xl">Watchlist</h1>
<span class="text-xs text-gray-500 line-clamp-1">{{ trip.name }} pending/constraints</span>
<div
class="bg-white rounded py-2 absolute top-1/2 -translate-y-1/2 left-0 hidden group-hover:block slide-x dark:bg-surface-900">
<p-button [icon]="collapsedTripStatuses ? 'pi pi-chevron-down' : 'pi pi-chevron-up'" text
(click)="collapsedTripStatuses = !collapsedTripStatuses" />
</div>
<div class="p-2 mb-2 flex justify-between items-center">
<h1 class="font-semibold tracking-tight text-xl">About</h1>
<div class="flex items-center gap-1 text-gray-500"><i class="pi pi-github"></i> itskovacs/trip</div>
</div>
@if (!collapsedTripStatuses) {
<div [class.max-h-40!]="!isExpanded" class="max-h-[340px] overflow-y-auto">
@defer {
@for (item of getWatchlistData; track item.id) {
<div class="flex items-center gap-2 h-10 px-4 py-2 w-full max-w-full">
<div class="flex flex-none">
<span [style.background]="item.status.color+'1A'" [style.color]="item.status.color"
class="text-xs font-medium me-2 px-2.5 py-0.5 rounded">{{
item.status.label }}</span>
<div class="max-w-[85%] text-center mx-auto flex flex-col items-center gap-4">
<div>TRIP is free and always will be. Building it takes a lot of time and effort, and since I'm committed to
keeping it free, your support simply helps keep the project going. Thank you! ❤️</div>
<a href="https://ko-fi.com/itskovacs" target="_blank" class="custom-button flex items-center">Buy me
a coffee</a>
</div>
<div class="line-clamp-1">{{ item.text }}</div>
</div>
} @empty {
<p class="p-4 font-light text-gray-500">
Nothing there
</p>
}
} @placeholder (minimum 0.4s) {
<div class="h-16">
<p-skeleton height="100%" />
</div>
}
</div>
}
</div>
}
</div>
@ -506,3 +488,39 @@
</div>
</section>
</p-dialog>
<p-dialog header="Checklist" [draggable]="false" [dismissableMask]="true" [modal]="true"
[(visible)]="checklistDialogVisible" styleClass="w-[95%] md:w-[50%] lg:w-[30%]">
<section class="p-4 max-w-full max-h-[80%] md:max-h-[600px]">
<div class="grid grid-cols-2 md:grid-cols-3 gap-2 mt-4 pb-4">
@for (item of checklistItems; track item.id) {
<div class="relative group flex items-center gap-3 rounded-md p-2 hover:bg-gray-100 dark:hover:bg-white/5">
<label [for]="item.id" [class.line-through]="item.checked"
class="flex items-center gap-2 w-full cursor-pointer">
<p-checkbox disabled [binary]="true" [inputId]="item.id.toString()" [(ngModel)]="item.checked" />
<div class="pr-6 md:pr-0 truncate select-none flex-1">
<span>{{ item.text }}</span>
</div>
</label>
</div>
}
</div>
<div class="grid grid-cols-2 md:grid-cols-3 gap-2 mt-4 pb-4">
@for (item of getWatchlistData; track item.id) {
<div class="flex items-center gap-3 rounded-md p-2 hover:bg-gray-100 dark:hover:bg-white/5">
<label [for]="item.id" class="flex items-center gap-2 w-full">
<div class="relative">
@if (item.status) {<div class="z-50 block absolute top-0 left-3 size-2.5 rounded-full"
[style.background]="item.status.color"></div>}
<p-checkbox disabled />
</div>
<div class="pr-6 md:pr-0 truncate select-none flex-1">
<span>{{ item.text }}</span>
</div>
</label>
</div>
}
</div>
</section>
</p-dialog>

View File

@ -12,6 +12,7 @@ import {
TripItem,
TripStatus,
PackingItem,
ChecklistItem,
} from "../../types/trip";
import { Place } from "../../types/poi";
import {
@ -72,12 +73,14 @@ export class SharedTripComponent implements AfterViewInit {
totalPrice = 0;
collapsedTripDays = false;
collapsedTripPlaces = false;
collapsedTripStatuses = false;
packingDialogVisible = false;
isExpanded = false;
isFilteringMode = false;
packingList: PackingItem[] = [];
dispPackingList: Record<string, PackingItem[]> = {};
checklistDialogVisible = false;
checklistItems: ChecklistItem[] = [];
dispchecklist: ChecklistItem[] = [];
map?: L.Map;
markerClusterGroup?: L.MarkerClusterGroup;
@ -94,14 +97,15 @@ export class SharedTripComponent implements AfterViewInit {
label: "Packing",
icon: "pi pi-briefcase",
command: () => {
// this.toggleArchiveTrip();
this.openPackingList();
},
},
{
label: "Reminders",
label: "Checklist",
icon: "pi pi-check-square",
iconClass: "text-purple-500!",
command: () => {
// this.toggleArchiveTrip();
this.openChecklist();
},
},
],
@ -719,4 +723,19 @@ export class SharedTripComponent implements AfterViewInit {
{},
);
}
openChecklist() {
if (!this.trip) return;
if (!this.checklistItems.length)
this.apiService
.getChecklist(this.trip.id)
.pipe(take(1))
.subscribe({
next: (items) => {
this.checklistItems = [...items];
},
});
this.checklistDialogVisible = true;
}
}