diff --git a/src/app/features/store/pages/account-page/pages/tickets-page/ticket.service.ts b/src/app/features/store/pages/account-page/pages/tickets-page/ticket.service.ts index 66ce995..de64472 100644 --- a/src/app/features/store/pages/account-page/pages/tickets-page/ticket.service.ts +++ b/src/app/features/store/pages/account-page/pages/tickets-page/ticket.service.ts @@ -30,4 +30,14 @@ export class TicketService { this.http.get<{ data: TicketResponse[] }>(`${this.tenantService.getTenantApiUrl()}/tickets`), ).then((response) => response.data ?? []); } + + downloadPdf(ticketIds: number[]): Promise { + return firstValueFrom( + this.http.post( + `${this.tenantService.getTenantApiUrl()}/tickets/pdf`, + { ticket_ids: ticketIds }, + { responseType: 'blob' }, + ), + ); + } } diff --git a/src/app/features/store/pages/account-page/pages/tickets-page/tickets-page.html b/src/app/features/store/pages/account-page/pages/tickets-page/tickets-page.html index 8f3885e..f58632c 100644 --- a/src/app/features/store/pages/account-page/pages/tickets-page/tickets-page.html +++ b/src/app/features/store/pages/account-page/pages/tickets-page/tickets-page.html @@ -15,11 +15,19 @@
- + Descargar - + Compartir
@@ -62,6 +70,8 @@ [selected]="isSelected(ticket.id)" (selectedChange)="toggleTicket(ticket.id, $event)" (viewQr)="viewQr(ticket)" + (download)="downloadTicket(ticket)" + (share)="shareTicket(ticket)" /> } diff --git a/src/app/features/store/pages/account-page/pages/tickets-page/tickets-page.ts b/src/app/features/store/pages/account-page/pages/tickets-page/tickets-page.ts index 257d355..9a73e5b 100644 --- a/src/app/features/store/pages/account-page/pages/tickets-page/tickets-page.ts +++ b/src/app/features/store/pages/account-page/pages/tickets-page/tickets-page.ts @@ -86,4 +86,77 @@ export class TicketsPage implements OnInit { ticket: ticket.ticket, }); } + + protected async downloadTicket(ticket: TicketResponse): Promise { + await this.downloadTickets([ticket]); + } + + protected async downloadSelected(): Promise { + 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 { + await this.shareTickets([ticket]); + } + + protected async shareSelected(): Promise { + 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 { + 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 { + 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); + } }