feat: add download and share functionality for selected tickets
This commit is contained in:
@@ -30,4 +30,14 @@ export class TicketService {
|
||||
this.http.get<{ data: TicketResponse[] }>(`${this.tenantService.getTenantApiUrl()}/tickets`),
|
||||
).then((response) => response.data ?? []);
|
||||
}
|
||||
|
||||
downloadPdf(ticketIds: number[]): Promise<Blob> {
|
||||
return firstValueFrom(
|
||||
this.http.post(
|
||||
`${this.tenantService.getTenantApiUrl()}/tickets/pdf`,
|
||||
{ ticket_ids: ticketIds },
|
||||
{ responseType: 'blob' },
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,19 @@
|
||||
|
||||
<div class="tickets-list__bulk-actions">
|
||||
<span class="tickets-list__bulk-action">
|
||||
<app-icon-button variant="download" ariaLabel="Descargar tickets seleccionados" />
|
||||
<app-icon-button
|
||||
variant="download"
|
||||
ariaLabel="Descargar tickets seleccionados"
|
||||
(clicked)="downloadSelected()"
|
||||
/>
|
||||
<small>Descargar</small>
|
||||
</span>
|
||||
<span class="tickets-list__bulk-action">
|
||||
<app-icon-button variant="share" ariaLabel="Compartir tickets seleccionados" />
|
||||
<app-icon-button
|
||||
variant="share"
|
||||
ariaLabel="Compartir tickets seleccionados"
|
||||
(clicked)="shareSelected()"
|
||||
/>
|
||||
<small>Compartir</small>
|
||||
</span>
|
||||
</div>
|
||||
@@ -62,6 +70,8 @@
|
||||
[selected]="isSelected(ticket.id)"
|
||||
(selectedChange)="toggleTicket(ticket.id, $event)"
|
||||
(viewQr)="viewQr(ticket)"
|
||||
(download)="downloadTicket(ticket)"
|
||||
(share)="shareTicket(ticket)"
|
||||
/>
|
||||
}
|
||||
|
||||
|
||||
@@ -86,4 +86,77 @@ export class TicketsPage implements OnInit {
|
||||
ticket: ticket.ticket,
|
||||
});
|
||||
}
|
||||
|
||||
protected async downloadTicket(ticket: TicketResponse): Promise<void> {
|
||||
await this.downloadTickets([ticket]);
|
||||
}
|
||||
|
||||
protected async downloadSelected(): Promise<void> {
|
||||
const tickets = this.activeTickets().filter((ticket) => this.selectedIds().has(ticket.id));
|
||||
|
||||
if (!tickets.length) {
|
||||
this.toastService.danger('Seleccioná al menos un ticket para descargar.');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.downloadTickets(tickets);
|
||||
}
|
||||
|
||||
protected async shareTicket(ticket: TicketResponse): Promise<void> {
|
||||
await this.shareTickets([ticket]);
|
||||
}
|
||||
|
||||
protected async shareSelected(): Promise<void> {
|
||||
const tickets = this.activeTickets().filter((ticket) => this.selectedIds().has(ticket.id));
|
||||
|
||||
if (!tickets.length) {
|
||||
this.toastService.danger('Seleccioná al menos un ticket para compartir.');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.shareTickets(tickets);
|
||||
}
|
||||
|
||||
private async downloadTickets(tickets: TicketResponse[]): Promise<void> {
|
||||
try {
|
||||
const pdf = await this.ticketService.downloadPdf(tickets.map((ticket) => ticket.id));
|
||||
this.downloadPdf(pdf);
|
||||
} catch {
|
||||
this.toastService.danger('No se pudo generar el PDF de los tickets.');
|
||||
}
|
||||
}
|
||||
|
||||
private async shareTickets(tickets: TicketResponse[]): Promise<void> {
|
||||
try {
|
||||
const pdf = await this.ticketService.downloadPdf(tickets.map((ticket) => ticket.id));
|
||||
const file = new File([pdf], 'mis-tickets.pdf', { type: 'application/pdf' });
|
||||
|
||||
if (navigator.canShare?.({ files: [file] })) {
|
||||
await navigator.share({
|
||||
files: [file],
|
||||
title: 'Mis tickets',
|
||||
text: 'Te comparto mis tickets digitales.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.downloadPdf(pdf);
|
||||
this.toastService.success('Tu navegador no permite compartir archivos; descargamos el PDF.');
|
||||
} catch (error) {
|
||||
if (error instanceof DOMException && error.name === 'AbortError') return;
|
||||
|
||||
this.toastService.danger('No se pudo generar el PDF de los tickets.');
|
||||
}
|
||||
}
|
||||
|
||||
private downloadPdf(pdf: Blob): void {
|
||||
const url = URL.createObjectURL(pdf);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = 'mis-tickets.pdf';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
window.setTimeout(() => URL.revokeObjectURL(url), 0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user