Audit fixes: VIP self-grant, draft leak, onboarding flag, hero personalization, gated downloads
Deploy GitHub Pages / deploy (push) Canceled after 0s

This commit is contained in:
AHMED
2026-10-09 16:20:55 +03:00
parent c34611dc36
commit 5ee706ebd6
150 changed files with 24054 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
/* Western digits everywhere for consistency with reading times, prices and code. */
const dateFormat = new Intl.DateTimeFormat('ar-u-nu-latn', { day: 'numeric', month: 'long', year: 'numeric' })
const numberFormat = new Intl.NumberFormat('en-US')
export function formatDate(value: string | Date | null | undefined): string {
if (!value) return ''
const date = value instanceof Date ? value : new Date(value)
return Number.isNaN(date.getTime()) ? '' : dateFormat.format(date)
}
export const formatNumber = (value: number | null | undefined) => numberFormat.format(value ?? 0)
/* Single source for the displayed membership price. */
export const MEMBERSHIP_PRICE = '$10'
/* Arabic count agreement for «دليل»: 1 دليل، 2 دليلان، 3–10 أدلة، 11+ دليلاً. */
export function guidesLabel(n: number): string {
if (n === 0) return 'لا أدلة'
if (n === 1) return 'دليل واحد'
if (n === 2) return 'دليلان'
return `${formatNumber(n)} ${n <= 10 ? 'أدلة' : 'دليلاً'}`
}
export function minutesLabel(n: number | null | undefined): string {
const value = n ?? 0
if (value === 1) return 'دقيقة واحدة'
if (value === 2) return 'دقيقتان'
return `${formatNumber(value)} ${value % 100 >= 3 && value % 100 <= 10 ? 'دقائق' : 'دقيقة'}`
}