Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018BAUeCFpDkRD6tU5wGsc1C
60 lines
2.3 KiB
TypeScript
60 lines
2.3 KiB
TypeScript
import { NotificationType } from '../entities/notification.entity';
|
|
|
|
/**
|
|
* Ou mene une notification.
|
|
*
|
|
* Une notification n'est pas un message : c'est un pointeur vers quelque chose
|
|
* qui a change. Le lien est donc derive du type et des metadonnees, ici et nulle
|
|
* part ailleurs — l'interface se contente de suivre.
|
|
*
|
|
* Les liens etaient jusqu'ici ecrits a la main a chaque appel, et deux d'entre
|
|
* eux visaient des routes qui n'existent pas : `/bookings/{id}` (la vraie route
|
|
* est `/dashboard/bookings/{id}`) et `/dashboard/admin/organizations` (l'espace
|
|
* d'administration a depuis son propre segment `/admin`). Les regrouper permet
|
|
* de les eprouver contre les routes reelles, en une seule fois.
|
|
*
|
|
* Les liens sont **relatifs et sans prefixe de langue** : le frontend est
|
|
* localise (`/fr`, `/en`) et ajoute le sien.
|
|
*/
|
|
export function notificationTarget(
|
|
type: NotificationType,
|
|
metadata: Record<string, unknown> | undefined
|
|
): string | null {
|
|
const bookingId = asId(metadata?.bookingId);
|
|
|
|
switch (type) {
|
|
// Toutes les notifications de reservation menent au dossier concerne.
|
|
case NotificationType.BOOKING_CREATED:
|
|
case NotificationType.BOOKING_UPDATED:
|
|
case NotificationType.BOOKING_CONFIRMED:
|
|
case NotificationType.BOOKING_CANCELLED:
|
|
case NotificationType.CSV_BOOKING_ACCEPTED:
|
|
case NotificationType.CSV_BOOKING_REJECTED:
|
|
case NotificationType.CSV_BOOKING_REQUEST_SENT:
|
|
case NotificationType.DOCUMENT_UPLOADED:
|
|
return bookingId ? `/dashboard/bookings/${bookingId}` : '/dashboard/bookings';
|
|
|
|
case NotificationType.RATE_QUOTE_EXPIRING:
|
|
return '/dashboard/search-advanced';
|
|
|
|
case NotificationType.USER_INVITED:
|
|
return '/dashboard/settings/users';
|
|
|
|
case NotificationType.ORGANIZATION_UPDATE:
|
|
return '/dashboard/settings/organization';
|
|
|
|
// Une annonce ne pointe vers rien : la ligne ne doit pas se presenter comme
|
|
// cliquable pour n'aboutir nulle part.
|
|
case NotificationType.SYSTEM_ANNOUNCEMENT:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** Un identifiant utilisable dans une URL, ou rien. */
|
|
function asId(value: unknown): string | null {
|
|
if (typeof value !== 'string') return null;
|
|
const trimmed = value.trim();
|
|
// Les metadonnees sont du JSON libre : refuser ce qui sortirait du segment.
|
|
return trimmed && /^[A-Za-z0-9_-]{1,64}$/.test(trimmed) ? trimmed : null;
|
|
}
|