feat(back-end and front-end) email for request
All checks were successful
PR Checks / prettier-autofix (pull_request) Successful in 18s
PR Checks / security-sast (pull_request) Successful in 33s
PR Checks / test-backend (pull_request) Successful in 27s
PR Checks / test-frontend (pull_request) Successful in 1m8s

This commit is contained in:
2026-03-04 12:15:23 +01:00
parent 1b3f0b16ff
commit 767b65008b
20 changed files with 493 additions and 55 deletions

View File

@@ -5,11 +5,12 @@ import {
AdminQuoteSession,
AdminQuoteSessionDetail,
} from '../services/admin-operations.service';
import { CopyOnClickDirective } from '../../../shared/directives/copy-on-click.directive';
@Component({
selector: 'app-admin-sessions',
standalone: true,
imports: [CommonModule],
imports: [CommonModule, CopyOnClickDirective],
templateUrl: './admin-sessions.component.html',
styleUrl: './admin-sessions.component.scss',
})
@@ -135,42 +136,6 @@ export class AdminSessionsComponent implements OnInit {
return `${hours}h ${minutes}m`;
}
copySessionUuid(sessionId: string): void {
if (!sessionId) {
return;
}
if (navigator.clipboard?.writeText) {
navigator.clipboard.writeText(sessionId).then(
() => {
this.errorMessage = null;
this.successMessage = 'UUID sessione copiato.';
},
() => {
this.errorMessage = 'Impossibile copiare UUID sessione.';
},
);
return;
}
// Fallback for older browsers.
const textarea = document.createElement('textarea');
textarea.value = sessionId;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand('copy');
this.errorMessage = null;
this.successMessage = 'UUID sessione copiato.';
} catch {
this.errorMessage = 'Impossibile copiare UUID sessione.';
} finally {
document.body.removeChild(textarea);
}
}
private extractErrorMessage(error: unknown, fallback: string): string {
const err = error as { error?: { message?: string } };
return err?.error?.message || fallback;