import { isPublicEventSlug } from '@/lib/routing/eventRoute' export const EVENT_SLUG_MAX_LENGTH = 220 export const EVENT_SLUG_FALLBACK = 'event' /** Previous wizard default: `event-` + first 8 chars of a UUID. */ const RANDOM_PLACEHOLDER_SLUG = /^event-[0-9a-f]{8}$/i // Same single-pass map as backend/src/modules/events/event-slug.util.ts. const PERSIAN_TRANSLIT_FROM = 'ابپتثجچحخدذرزژسشصضطظعغفقکگلمنوهیآأإئءؤةيك ' const PERSIAN_TRANSLIT_TO = 'abptsjchxdzrzjsssztzaqfqkglmnvhyaaaeaotyk-' const PERSIAN_DIGITS = '۰۱۲۳۴۵۶۷۸۹' export function slugifyEventTitle(title: string): string { const trimmed = title.trim() if (!trimmed) return '' let withLatinDigits = '' for (const char of trimmed) { const digit = PERSIAN_DIGITS.indexOf(char) withLatinDigits += digit === -1 ? char : String(digit) } let raw = '' for (const char of withLatinDigits) { const index = PERSIAN_TRANSLIT_FROM.indexOf(char) raw += index === -1 ? char : PERSIAN_TRANSLIT_TO[index] } const slug = raw .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/-+/g, '-') .replace(/(^-+|-+$)/g, '') .slice(0, EVENT_SLUG_MAX_LENGTH) .replace(/-+$/g, '') if (!slug || !isPublicEventSlug(slug)) return EVENT_SLUG_FALLBACK return slug } /** * True when the slug field should keep tracking the title: empty, leftover * random placeholder, or still equal to the slug generated from `title`. */ export function shouldAutogenerateEventSlug(currentSlug: string, title: string): boolean { const slug = currentSlug.trim() if (!slug) return true if (RANDOM_PLACEHOLDER_SLUG.test(slug)) return true return slug === slugifyEventTitle(title) }