feat(back-end and front-end): back-office pazzo
All checks were successful
Build, Test and Deploy / test-backend (push) Successful in 44s
Build, Test and Deploy / build-and-push (push) Successful in 46s
Build, Test and Deploy / deploy (push) Successful in 9s

This commit is contained in:
2026-02-27 15:46:41 +01:00
parent 47553ebb82
commit ed76b13e4c
30 changed files with 2616 additions and 272 deletions

View File

@@ -1,40 +1,119 @@
<section class="section-card">
<header class="section-header">
<div>
<div class="header-copy">
<h2>Richieste di contatto</h2>
<p>Richieste preventivo personalizzato ricevute dal sito.</p>
<span class="total-pill">{{ requests.length }} richieste</span>
</div>
<button type="button" (click)="loadRequests()" [disabled]="loading">Aggiorna</button>
</header>
<p class="error" *ngIf="errorMessage">{{ errorMessage }}</p>
<div class="table-wrap" *ngIf="!loading; else loadingTpl">
<table>
<thead>
<tr>
<th>Data</th>
<th>Nome / Azienda</th>
<th>Email</th>
<th>Tipo richiesta</th>
<th>Tipo cliente</th>
<th>Stato</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let request of requests">
<td>{{ request.createdAt | date:'short' }}</td>
<td>{{ request.name || request.companyName || '-' }}</td>
<td>{{ request.email }}</td>
<td>{{ request.requestType }}</td>
<td>{{ request.customerType }}</td>
<td>{{ request.status }}</td>
</tr>
</tbody>
</table>
<div class="workspace" *ngIf="!loading; else loadingTpl">
<section class="list-panel">
<h3>Lista richieste</h3>
<div class="table-wrap">
<table class="requests-table">
<thead>
<tr>
<th>Data</th>
<th>Nome / Azienda</th>
<th>Email</th>
<th>Tipo richiesta</th>
<th>Tipo cliente</th>
<th>Stato</th>
</tr>
</thead>
<tbody>
<tr
*ngFor="let request of requests"
[class.selected]="isSelected(request.id)"
(click)="openDetails(request.id)"
>
<td class="created-at">{{ request.createdAt | date:'short' }}</td>
<td class="name-cell">
<p class="primary">{{ request.name || request.companyName || '-' }}</p>
<p class="secondary" *ngIf="request.name && request.companyName">{{ request.companyName }}</p>
</td>
<td class="email-cell">{{ request.email }}</td>
<td>
<span class="chip chip-neutral">{{ request.requestType }}</span>
</td>
<td>
<span class="chip chip-light">{{ request.customerType }}</span>
</td>
<td>
<span class="chip" [ngClass]="getStatusChipClass(request.status)">{{ request.status }}</span>
</td>
</tr>
<tr class="empty-row" *ngIf="requests.length === 0">
<td colspan="6">Nessuna richiesta presente.</td>
</tr>
</tbody>
</table>
</div>
</section>
<section class="detail-panel" *ngIf="selectedRequest">
<header class="detail-header">
<div>
<h3>Dettaglio richiesta</h3>
<p class="request-id"><span>ID</span><code>{{ selectedRequest.id }}</code></p>
</div>
<div class="detail-chips">
<span class="chip" [ngClass]="getStatusChipClass(selectedRequest.status)">{{ selectedRequest.status }}</span>
<span class="chip chip-neutral">{{ selectedRequest.requestType }}</span>
<span class="chip chip-light">{{ selectedRequest.customerType }}</span>
</div>
</header>
<p class="loading-detail" *ngIf="detailLoading">Caricamento dettaglio...</p>
<dl class="meta-grid">
<div class="meta-item"><dt>Creata</dt><dd>{{ selectedRequest.createdAt | date:'medium' }}</dd></div>
<div class="meta-item"><dt>Aggiornata</dt><dd>{{ selectedRequest.updatedAt | date:'medium' }}</dd></div>
<div class="meta-item"><dt>Email</dt><dd>{{ selectedRequest.email }}</dd></div>
<div class="meta-item"><dt>Telefono</dt><dd>{{ selectedRequest.phone || '-' }}</dd></div>
<div class="meta-item"><dt>Nome</dt><dd>{{ selectedRequest.name || '-' }}</dd></div>
<div class="meta-item"><dt>Azienda</dt><dd>{{ selectedRequest.companyName || '-' }}</dd></div>
<div class="meta-item"><dt>Referente</dt><dd>{{ selectedRequest.contactPerson || '-' }}</dd></div>
</dl>
<div class="message-box">
<h4>Messaggio</h4>
<p>{{ selectedRequest.message || '-' }}</p>
</div>
<div class="attachments">
<h4>Allegati</h4>
<div class="attachment-list" *ngIf="selectedRequest.attachments.length > 0; else noAttachmentsTpl">
<article class="attachment-item" *ngFor="let attachment of selectedRequest.attachments">
<div>
<p class="filename">{{ attachment.originalFilename }}</p>
<p class="meta">
{{ formatFileSize(attachment.fileSizeBytes) }}
<span *ngIf="attachment.mimeType"> | {{ attachment.mimeType }}</span>
<span *ngIf="attachment.createdAt"> | {{ attachment.createdAt | date:'short' }}</span>
</p>
</div>
<button type="button" class="ghost" (click)="downloadAttachment(attachment)">Scarica file</button>
</article>
</div>
</div>
</section>
<section class="detail-panel empty" *ngIf="!selectedRequest">
<h3>Nessuna richiesta selezionata</h3>
<p>Seleziona una riga dalla lista per vedere il dettaglio.</p>
</section>
</div>
</section>
<ng-template #loadingTpl>
<p>Caricamento richieste...</p>
</ng-template>
<ng-template #noAttachmentsTpl>
<p class="muted">Nessun allegato disponibile.</p>
</ng-template>