193 lines
6.5 KiB
HTML
193 lines
6.5 KiB
HTML
<section class="workspace-page">
|
|
<header class="page-header">
|
|
<div>
|
|
<h1>Listen</h1>
|
|
<p>Deine persönlichen Listify-Listen.</p>
|
|
</div>
|
|
|
|
<a mat-flat-button routerLink="/lists/new">
|
|
<mat-icon aria-hidden="true">add</mat-icon>
|
|
Neue Liste
|
|
</a>
|
|
</header>
|
|
|
|
@if (loading()) {
|
|
<mat-card class="state-card" appearance="outlined">
|
|
<mat-card-content>
|
|
<mat-progress-spinner mode="indeterminate" diameter="40" />
|
|
<h2>Listen werden geladen</h2>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
} @else if (errorMessage()) {
|
|
<mat-card class="state-card error-state" appearance="outlined">
|
|
<mat-card-content>
|
|
<mat-icon aria-hidden="true">error</mat-icon>
|
|
<h2>Listen konnten nicht geladen werden</h2>
|
|
<p>{{ errorMessage() }}</p>
|
|
<button mat-stroked-button type="button" (click)="loadLists()">
|
|
<mat-icon aria-hidden="true">refresh</mat-icon>
|
|
Erneut laden
|
|
</button>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
} @else if (hasLists()) {
|
|
<section class="list-controls" aria-label="Listen filtern und sortieren">
|
|
<mat-form-field appearance="outline" class="search-field">
|
|
<mat-label>Listen suchen</mat-label>
|
|
<mat-icon matPrefix aria-hidden="true">search</mat-icon>
|
|
<input
|
|
matInput
|
|
type="search"
|
|
[value]="searchTerm()"
|
|
(input)="searchTerm.set($any($event.target).value)"
|
|
/>
|
|
@if (searchTerm()) {
|
|
<button
|
|
mat-icon-button
|
|
matSuffix
|
|
type="button"
|
|
aria-label="Suche löschen"
|
|
(click)="searchTerm.set('')"
|
|
>
|
|
<mat-icon aria-hidden="true">close</mat-icon>
|
|
</button>
|
|
}
|
|
</mat-form-field>
|
|
|
|
<div class="filter-row">
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Typ</mat-label>
|
|
<mat-select
|
|
[value]="kindFilter()"
|
|
(selectionChange)="kindFilter.set($event.value)"
|
|
>
|
|
@for (option of kindOptions; track option.value) {
|
|
<mat-option [value]="option.value">{{ option.label }}</mat-option>
|
|
}
|
|
</mat-select>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Sortierung</mat-label>
|
|
<mat-select
|
|
[value]="sortOption()"
|
|
(selectionChange)="sortOption.set($event.value)"
|
|
>
|
|
@for (option of sortOptions; track option.value) {
|
|
<mat-option [value]="option.value">{{ option.label }}</mat-option>
|
|
}
|
|
</mat-select>
|
|
</mat-form-field>
|
|
</div>
|
|
|
|
<div class="status-row">
|
|
<mat-button-toggle-group
|
|
[value]="statusFilter()"
|
|
(change)="statusFilter.set($event.value)"
|
|
aria-label="Statusfilter"
|
|
>
|
|
<mat-button-toggle value="all">Alle</mat-button-toggle>
|
|
<mat-button-toggle value="open">Offen</mat-button-toggle>
|
|
<mat-button-toggle value="completed">Erledigt</mat-button-toggle>
|
|
</mat-button-toggle-group>
|
|
|
|
@if (activeFilterCount() > 0 || sortOption() !== 'updated-desc') {
|
|
<button mat-button type="button" (click)="resetFilters()">
|
|
<mat-icon aria-hidden="true">restart_alt</mat-icon>
|
|
Zurücksetzen
|
|
</button>
|
|
}
|
|
</div>
|
|
</section>
|
|
|
|
@if (!hasVisibleLists()) {
|
|
<mat-card class="state-card" appearance="outlined">
|
|
<mat-card-content>
|
|
<mat-icon aria-hidden="true">filter_alt_off</mat-icon>
|
|
<h2>Keine Treffer</h2>
|
|
<p>Mit den aktuellen Filtern wurde keine Liste gefunden.</p>
|
|
<button mat-stroked-button type="button" (click)="resetFilters()">
|
|
<mat-icon aria-hidden="true">restart_alt</mat-icon>
|
|
Filter zurücksetzen
|
|
</button>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
} @else {
|
|
<p class="result-count">
|
|
{{ visibleLists().length }} von {{ lists().length }} Listen
|
|
</p>
|
|
|
|
<div class="template-grid">
|
|
@for (list of visibleLists(); track list.id) {
|
|
<mat-card class="template-card" appearance="outlined">
|
|
<mat-card-header>
|
|
<mat-card-title>{{ list.name }}</mat-card-title>
|
|
<mat-card-subtitle>
|
|
{{ kindLabel(list.kind) }} - {{ progressLabel(list) }}
|
|
@if (list.accessRole === 'collaborator') {
|
|
- geteilt von {{ list.ownerName || list.ownerEmail || 'Owner' }}
|
|
}
|
|
</mat-card-subtitle>
|
|
</mat-card-header>
|
|
|
|
<mat-card-content>
|
|
@if (list.description) {
|
|
<p class="template-description">{{ list.description }}</p>
|
|
}
|
|
|
|
<div class="template-meta">
|
|
<span>
|
|
<mat-icon aria-hidden="true">done_all</mat-icon>
|
|
{{ checkedCount(list) }} / {{ list.items.length }} erledigt
|
|
</span>
|
|
<span>
|
|
<mat-icon aria-hidden="true">schedule</mat-icon>
|
|
{{ list.updatedAt | date: 'dd.MM.yyyy' }}
|
|
</span>
|
|
@if (list.collaborators.length > 0) {
|
|
<span>
|
|
<mat-icon aria-hidden="true">group</mat-icon>
|
|
{{ list.collaborators.length }} Mitwirkende
|
|
</span>
|
|
}
|
|
</div>
|
|
|
|
@if (list.items.length > 0) {
|
|
<ul class="template-items">
|
|
@for (item of previewItems(list); track item.id) {
|
|
<li>
|
|
<mat-icon aria-hidden="true">
|
|
{{ item.checked ? 'check_circle' : 'radio_button_unchecked' }}
|
|
</mat-icon>
|
|
<span>{{ item.title }}</span>
|
|
</li>
|
|
}
|
|
</ul>
|
|
}
|
|
</mat-card-content>
|
|
|
|
<mat-card-actions align="end">
|
|
<a
|
|
mat-button
|
|
[routerLink]="['/lists', list.id]"
|
|
[attr.data-onboarding]="onboarding.isListOpenTarget(list.id) ? 'open-list' : null"
|
|
>
|
|
<mat-icon aria-hidden="true">open_in_new</mat-icon>
|
|
Öffnen
|
|
</a>
|
|
</mat-card-actions>
|
|
</mat-card>
|
|
}
|
|
</div>
|
|
}
|
|
} @else {
|
|
<mat-card class="state-card" appearance="outlined">
|
|
<mat-card-content>
|
|
<mat-icon aria-hidden="true">format_list_bulleted</mat-icon>
|
|
<h2>Noch keine Listen</h2>
|
|
<p>Erstelle eine Liste aus einem Template oder lege eine neue Liste an.</p>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
}
|
|
</section>
|