Files
print-calculator/frontend/src/app/features/admin/pages/admin-dashboard.component.html

331 lines
10 KiB
HTML

<section class="admin-dashboard ui-section-card">
<header class="dashboard-header ui-section-header">
<div class="ui-section-header__copy">
<h1 class="ui-section-header__title">Ordini</h1>
<p class="ui-section-header__description">
Seleziona un ordine a sinistra e gestiscilo nel dettaglio a destra.
</p>
</div>
<div class="header-actions">
<button
type="button"
class="ui-button"
(click)="loadOrders()"
[disabled]="loading"
>
Aggiorna
</button>
</div>
</header>
<p class="error" *ngIf="errorMessage">{{ errorMessage }}</p>
<div class="workspace ui-split-workspace" *ngIf="!loading; else loadingTpl">
<section class="list-panel">
<h2>Lista ordini</h2>
<div class="list-toolbar">
<label class="toolbar-field" for="order-search">
<span>Cerca UUID</span>
<input
class="ui-form-control"
id="order-search"
type="search"
[ngModel]="orderSearchTerm"
(ngModelChange)="onSearchChange($event)"
placeholder="UUID completo o prefisso (es. 738131d8)"
/>
</label>
<label class="toolbar-field" for="payment-status-filter">
<span>Stato pagamento</span>
<select
class="ui-form-control"
id="payment-status-filter"
[ngModel]="paymentStatusFilter"
(ngModelChange)="onPaymentStatusFilterChange($event)"
>
<option
*ngFor="let option of paymentStatusFilterOptions"
[ngValue]="option"
>
{{ option }}
</option>
</select>
</label>
<label class="toolbar-field" for="order-status-filter">
<span>Stato ordine</span>
<select
class="ui-form-control"
id="order-status-filter"
[ngModel]="orderStatusFilter"
(ngModelChange)="onOrderStatusFilterChange($event)"
>
<option
*ngFor="let option of orderStatusFilterOptions"
[ngValue]="option"
>
{{ option }}
</option>
</select>
</label>
</div>
<div class="table-wrap ui-table-wrap">
<table class="ui-data-table">
<thead>
<tr>
<th>Ordine</th>
<th>Email</th>
<th>Pagamento</th>
<th>Stato ordine</th>
<th>Totale</th>
</tr>
</thead>
<tbody>
<tr
*ngFor="let order of filteredOrders"
[class.selected]="isSelected(order.id)"
(click)="openDetails(order.id)"
>
<td>{{ order.orderNumber }}</td>
<td>{{ order.customerEmail }}</td>
<td>{{ order.paymentStatus || "PENDING" }}</td>
<td>{{ order.status }}</td>
<td>
{{ order.totalChf | currency: "CHF" : "symbol" : "1.2-2" }}
</td>
</tr>
<tr class="no-results" *ngIf="filteredOrders.length === 0">
<td colspan="5">
Nessun ordine trovato per i filtri selezionati.
</td>
</tr>
</tbody>
</table>
</div>
</section>
<section class="detail-panel ui-detail-panel" *ngIf="selectedOrder">
<div class="detail-header">
<h2>Dettaglio ordine {{ selectedOrder.orderNumber }}</h2>
<p class="order-uuid">
UUID:
<code
class="ui-code-pill"
[title]="selectedOrder.id"
[appCopyOnClick]="selectedOrder.id"
>{{ selectedOrder.id }}</code
>
</p>
<p *ngIf="detailLoading">Caricamento dettaglio...</p>
</div>
<div class="meta-grid ui-meta-grid">
<div class="ui-meta-item">
<strong>Cliente</strong><span>{{ selectedOrder.customerEmail }}</span>
</div>
<div class="ui-meta-item">
<strong>Stato pagamento</strong
><span>{{ selectedOrder.paymentStatus || "PENDING" }}</span>
</div>
<div class="ui-meta-item">
<strong>Stato ordine</strong><span>{{ selectedOrder.status }}</span>
</div>
<div class="ui-meta-item">
<strong>Totale</strong
><span>{{
selectedOrder.totalChf | currency: "CHF" : "symbol" : "1.2-2"
}}</span>
</div>
</div>
<div class="actions-block">
<div class="status-editor">
<label for="order-status">Stato ordine</label>
<select
class="ui-form-control"
id="order-status"
[value]="selectedStatus"
(change)="onStatusChange($event)"
>
<option *ngFor="let option of orderStatusOptions" [value]="option">
{{ option }}
</option>
</select>
<button
class="ui-button"
type="button"
(click)="updateStatus()"
[disabled]="updatingStatus"
>
{{ updatingStatus ? "Salvataggio..." : "Aggiorna stato" }}
</button>
</div>
<div class="status-editor">
<label for="payment-method">Metodo pagamento</label>
<select
class="ui-form-control"
id="payment-method"
[value]="selectedPaymentMethod"
(change)="onPaymentMethodChange($event)"
>
<option
*ngFor="let option of paymentMethodOptions"
[value]="option"
>
{{ option }}
</option>
</select>
<button
class="ui-button"
type="button"
(click)="updatePaymentMethod()"
[disabled]="confirmingPayment"
>
{{
confirmingPayment ? "Salvataggio..." : "Cambia metodo pagamento"
}}
</button>
</div>
</div>
<div class="doc-actions">
<button
type="button"
class="ui-button ui-button--ghost"
(click)="downloadConfirmation()"
>
Scarica conferma + QR bill
</button>
<button
type="button"
class="ui-button ui-button--ghost"
(click)="downloadInvoice()"
>
Scarica fattura
</button>
<button
type="button"
class="ui-button ui-button--ghost"
(click)="openPrintDetails()"
>
Dettagli stampa
</button>
</div>
<div class="items">
<div class="item" *ngFor="let item of selectedOrder.items">
<div class="item-main">
<p class="file-name">
<strong>{{ item.originalFilename }}</strong>
</p>
<p class="item-meta">
Qta: {{ item.quantity }} | Materiale:
{{ getItemMaterialLabel(item) }} | Colore:
<span
class="color-swatch"
*ngIf="getItemColorHex(item) as colorHex"
[style.background-color]="colorHex"
></span>
<span>
{{ getItemColorLabel(item) }}
<ng-container *ngIf="getItemColorCodeSuffix(item) as colorCode">
({{ colorCode }})
</ng-container>
</span>
| Nozzle: {{ item.nozzleDiameterMm ?? "-" }} mm | Layer:
{{ item.layerHeightMm ?? "-" }} mm | Infill:
{{ item.infillPercent ?? "-" }}% | Supporti:
{{ formatSupports(item.supportsEnabled) }}
| Riga:
{{ item.lineTotalChf | currency: "CHF" : "symbol" : "1.2-2" }}
</p>
</div>
<button
type="button"
class="ui-button ui-button--ghost"
(click)="downloadItemFile(item.id, item.originalFilename)"
>
Scarica file
</button>
</div>
</div>
</section>
<section
class="detail-panel ui-detail-panel ui-detail-panel--empty"
*ngIf="!selectedOrder"
>
<h2>Nessun ordine selezionato</h2>
<p>Seleziona un ordine dalla lista per vedere i dettagli.</p>
</section>
</div>
</section>
<ng-template #loadingTpl>
<p>Caricamento ordini...</p>
</ng-template>
<div
class="modal-backdrop"
*ngIf="showPrintDetails && selectedOrder"
(click)="closePrintDetails()"
>
<div class="modal-card" (click)="$event.stopPropagation()">
<header class="modal-header">
<h3>Dettagli stampa ordine {{ selectedOrder.orderNumber }}</h3>
<button
type="button"
class="ui-button ui-button--ghost close-btn"
(click)="closePrintDetails()"
>
Chiudi
</button>
</header>
<div class="modal-grid ui-meta-grid">
<div class="ui-meta-item">
<strong>Qualità</strong
><span>{{ getQualityLabel(selectedOrder.printLayerHeightMm) }}</span>
</div>
<div class="ui-meta-item">
<strong>Materiale</strong
><span>{{ selectedOrder.printMaterialCode || "-" }}</span>
</div>
<div class="ui-meta-item">
<strong>Layer height</strong
><span>{{ selectedOrder.printLayerHeightMm || "-" }} mm</span>
</div>
<div class="ui-meta-item">
<strong>Nozzle</strong
><span>{{ selectedOrder.printNozzleDiameterMm || "-" }} mm</span>
</div>
<div class="ui-meta-item">
<strong>Infill pattern</strong
><span>{{ selectedOrder.printInfillPattern || "-" }}</span>
</div>
<div class="ui-meta-item">
<strong>Infill %</strong
><span>{{ selectedOrder.printInfillPercent ?? "-" }}</span>
</div>
<div class="ui-meta-item">
<strong>Supporti</strong
><span>{{ selectedOrder.printSupportsEnabled ? "Sì" : "No" }}</span>
</div>
</div>
<h4>Parametri per file</h4>
<div class="file-color-list">
<div class="file-color-row" *ngFor="let item of selectedOrder.items">
<span class="filename">{{ item.originalFilename }}</span>
<span class="file-color">
{{ getItemMaterialLabel(item) }} | Colore:
{{ getItemColorLabel(item) }} | {{ item.nozzleDiameterMm ?? "-" }} mm
| {{ item.layerHeightMm ?? "-" }} mm |
{{ item.infillPercent ?? "-" }}% | {{ item.infillPattern || "-" }} |
{{ formatSupportsState(item.supportsEnabled) }}
</span>
</div>
</div>
</div>
</div>