Add a button to download a PDF file with all QR codes
All checks were successful
Add copyright notice / copyright_notice (pull_request) Successful in 29s
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m34s
Build Nginx-based docker image / build-static-assets (push) Successful in 3m17s
Playwright Tests / test (pull_request) Successful in 4m18s

This commit is contained in:
Manuel Bustillo 2025-07-01 17:49:49 +02:00
parent d390d6e055
commit b4ec903ce0
3 changed files with 29 additions and 2 deletions

View File

@ -3,6 +3,7 @@
import { Entity } from '@/app/lib/definitions'; import { Entity } from '@/app/lib/definitions';
import { getCsrfToken, getSlug } from '@/app/lib/utils'; import { getCsrfToken, getSlug } from '@/app/lib/utils';
export interface Api<T extends Entity> { export interface Api<T extends Entity> {
getAll(serializable: Serializable<T>, callback: (objets: T[]) => void): void; getAll(serializable: Serializable<T>, callback: (objets: T[]) => void): void;
get(serializable: Serializable<T>, id: string, callback: (object: T) => void): void; get(serializable: Serializable<T>, id: string, callback: (object: T) => void): void;
@ -30,6 +31,18 @@ export class AbstractApi<T extends Entity> implements Api<T> {
}); });
} }
getAllPdf(serializable: Serializable<T>, callback: () => void): void {
fetch(`/api/${getSlug()}/${serializable.apiPath()}`, {
headers: {
'Accept': 'application/pdf',
}
}).then(res => res.blob())
.then(blob => {
var file = window.URL.createObjectURL(blob);
window.location.assign(file);
});
}
get(serializable: Serializable<T>, id: (string | undefined), callback: (object: T) => void): void { get(serializable: Serializable<T>, id: (string | undefined), callback: (object: T) => void): void {
const endpoint = id ? `/api/${getSlug()}/${serializable.apiPath()}/${id}` : `/api/${getSlug()}/${serializable.apiPath()}`; const endpoint = id ? `/api/${getSlug()}/${serializable.apiPath()}/${id}` : `/api/${getSlug()}/${serializable.apiPath()}`;
fetch(endpoint) fetch(endpoint)

View File

@ -5,7 +5,7 @@ import clsx from "clsx";
type ButtonColor = 'primary' | 'blue' | 'green' | 'red' | 'yellow' | 'gray'; type ButtonColor = 'primary' | 'blue' | 'green' | 'red' | 'yellow' | 'gray';
export function classNames(type: ButtonColor) { export function classNames(type: ButtonColor) {
return (clsx("text-white py-1 px-2 mx-1 rounded disabled:opacity-50 disabled:cursor-not-allowed", { return (clsx("text-white py-1 px-2 m-2 rounded disabled:opacity-50 disabled:cursor-not-allowed", {
'bg-blue-400 hover:bg-blue-600': type === 'primary' || type === 'blue', 'bg-blue-400 hover:bg-blue-600': type === 'primary' || type === 'blue',
'bg-green-500 hover:bg-green-600': type === 'green', 'bg-green-500 hover:bg-green-600': type === 'green',
'bg-red-500 hover:bg-red-600': type === 'red', 'bg-red-500 hover:bg-red-600': type === 'red',

View File

@ -10,6 +10,7 @@ import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-d
import { LinkIcon, TrashIcon } from "@heroicons/react/24/outline"; import { LinkIcon, TrashIcon } from "@heroicons/react/24/outline";
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import { useState } from "react"; import { useState } from "react";
import { classNames } from "../components/button";
function InvitationCard({ invitation, allGuests, onGuestAdded, onDestroy }: { function InvitationCard({ invitation, allGuests, onGuestAdded, onDestroy }: {
invitation: Invitation, invitation: Invitation,
@ -144,6 +145,12 @@ export default function InvitationsBoard({ guests, invitations: originalInvitati
}); });
} }
function handleDownloadQrCodes() {
api.getAllPdf(serializer, () => {
console.log("QR codes downloaded");
});
}
return ( return (
<div className="flex h-screen"> <div className="flex h-screen">
{/* Left Column: Guests */} {/* Left Column: Guests */}
@ -164,11 +171,18 @@ export default function InvitationsBoard({ guests, invitations: originalInvitati
<button <button
onClick={handleCreateInvitation} onClick={handleCreateInvitation}
className="mb-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600" className={classNames('primary')}
> >
Create New Invitation Create New Invitation
</button> </button>
<button
onClick={handleDownloadQrCodes}
className={classNames('primary')}
>
Download QR codes
</button>
<div className="grid grid-cols-4 gap-6"> <div className="grid grid-cols-4 gap-6">