Badges : permettre d'agrandir le badge proportionnellement à l'image
Le format déduit de l'image importée (300 dpi supposés, étape
précédente) donne un badge minuscule pour une image à résolution web —
ajout d'un contrôle « largeur du badge (mm) » dans l'écran de
personnalisation : la hauteur suit proportionnellement (ratio de
l'image). PUT /editions/{id}/badges/template/size écrase la taille
déduite de l'image ; la réimporter la recalcule à nouveau.
Vérifié : pytest (250 passés), ruff, tsc --noEmit, eslint, vite build,
smoke — tous verts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
bc165757ca
commit
55c5d539a8
@@ -19,6 +19,7 @@ import type {
|
||||
AvailabilitySet,
|
||||
BadgeFieldsSet,
|
||||
BadgeGenerateRequest,
|
||||
BadgeSizeUpdate,
|
||||
DayPartCreate,
|
||||
DayPartUpdate,
|
||||
EditionUpdate,
|
||||
@@ -535,6 +536,16 @@ export function useSetBadgeFields() {
|
||||
});
|
||||
}
|
||||
|
||||
/** Redimensionne le badge indépendamment de l'image (agrandissement
|
||||
* proportionnel d'une image importée trop petite). */
|
||||
export function useSetBadgeSize() {
|
||||
const invalidate = useInvalidateBadgeTemplate();
|
||||
return useMutation({
|
||||
mutationFn: (body: BadgeSizeUpdate) => api.badges.setSize(edition, body),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
}
|
||||
|
||||
/** Génère la planche PDF ; ne fait que retourner le fichier (le composant
|
||||
* appelant déclenche le téléchargement). */
|
||||
export function useGenerateBadges() {
|
||||
|
||||
@@ -9,6 +9,7 @@ import type {
|
||||
AvailabilitySet,
|
||||
BadgeFieldsSet,
|
||||
BadgeGenerateRequest,
|
||||
BadgeSizeUpdate,
|
||||
DayPartCreate,
|
||||
DayPartUpdate,
|
||||
EditionUpdate,
|
||||
@@ -247,6 +248,11 @@ export function createHttpApi(baseUrl: string): PlanningApi {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
setSize: (editionId, body: BadgeSizeUpdate) =>
|
||||
request(`${base(editionId)}/badges/template/size`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
generate: async (editionId, body: BadgeGenerateRequest) => {
|
||||
const blob = await requestBlob(`${base(editionId)}/badges/generate`, {
|
||||
method: 'POST',
|
||||
|
||||
@@ -13,6 +13,7 @@ import type {
|
||||
BadgeFieldRead,
|
||||
BadgeFieldsSet,
|
||||
BadgeGenerateRequest,
|
||||
BadgeSizeUpdate,
|
||||
BadgeTemplateRead,
|
||||
DayPartCreate,
|
||||
DayPartRead,
|
||||
@@ -1401,6 +1402,21 @@ export function createMockApi(): PlanningApi {
|
||||
state.badgeTemplate.fields = fields;
|
||||
return delay(fields);
|
||||
},
|
||||
setSize: (_edition, body: BadgeSizeUpdate) => {
|
||||
if (body.badge_width_mm <= 0 || body.badge_height_mm <= 0) {
|
||||
throw new ApiError(422, 'badge.invalid_size');
|
||||
}
|
||||
state.badgeTemplate.frontImageWidthMm = body.badge_width_mm;
|
||||
state.badgeTemplate.frontImageHeightMm = body.badge_height_mm;
|
||||
return delay<BadgeTemplateRead>({
|
||||
edition_id: state.edition.id,
|
||||
has_front_image: state.badgeTemplate.frontImage !== null,
|
||||
has_back_image: state.badgeTemplate.backImage !== null,
|
||||
badge_width_mm: body.badge_width_mm,
|
||||
badge_height_mm: body.badge_height_mm,
|
||||
fields: state.badgeTemplate.fields,
|
||||
});
|
||||
},
|
||||
generate: (_edition, body: BadgeGenerateRequest) => {
|
||||
if (state.badgeTemplate.fields.length === 0) {
|
||||
throw new ApiError(422, 'badge.no_fields');
|
||||
|
||||
@@ -458,6 +458,13 @@ export interface BadgeGenerateRequest {
|
||||
volunteer_ids?: string[] | null;
|
||||
}
|
||||
|
||||
/** Redimensionne le badge indépendamment d'un nouvel import d'image — ex.
|
||||
* agrandir proportionnellement une image importée à basse résolution. */
|
||||
export interface BadgeSizeUpdate {
|
||||
badge_width_mm: number;
|
||||
badge_height_mm: number;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------- //
|
||||
// Authentification //
|
||||
// --------------------------------------------------------------------------- //
|
||||
|
||||
@@ -16,6 +16,7 @@ import type {
|
||||
BadgeFieldRead,
|
||||
BadgeFieldsSet,
|
||||
BadgeGenerateRequest,
|
||||
BadgeSizeUpdate,
|
||||
BadgeTemplateRead,
|
||||
DayPartCreate,
|
||||
DayPartRead,
|
||||
@@ -146,6 +147,9 @@ export interface PlanningApi {
|
||||
backImageBlob(editionId: string): Promise<Blob | null>;
|
||||
/** Remplace l'intégralité des champs du recto. */
|
||||
setFields(editionId: string, body: BadgeFieldsSet): Promise<BadgeFieldRead[]>;
|
||||
/** Redimensionne le badge indépendamment de l'image (agrandissement
|
||||
* proportionnel d'une image importée trop petite). */
|
||||
setSize(editionId: string, body: BadgeSizeUpdate): Promise<BadgeTemplateRead>;
|
||||
/** Génère la planche PDF (recto personnalisé + verso fixe). */
|
||||
generate(editionId: string, body: BadgeGenerateRequest): Promise<Blob>;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user