Fix mobile validation, cascade delete for businesses/categories, and DB error handling.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-21 14:20:46 +03:30
co-authored by Cursor
parent 97abb808b8
commit 2d6bae2ba1
14 changed files with 237 additions and 26 deletions
+39
View File
@@ -0,0 +1,39 @@
const PERSIAN_DIGITS = '۰۱۲۳۴۵۶۷۸۹';
const ARABIC_DIGITS = '٠١٢٣٤٥٦٧٨٩';
const INVISIBLE_CHARS = /[\u200c\u200d\u202a-\u202e\ufeff]/g;
export const IRAN_MOBILE_REGEX = /^09\d{9}$/;
function toAsciiDigits(value: string): string {
return value.replace(/[۰-۹٠-٩]/g, (ch) => {
const persian = PERSIAN_DIGITS.indexOf(ch);
if (persian >= 0) return String(persian);
const arabic = ARABIC_DIGITS.indexOf(ch);
if (arabic >= 0) return String(arabic);
return ch;
});
}
/** Normalize Iranian mobile to 09xxxxxxxxx (11 digits). */
export function normalizeIranMobile(raw: string): string {
let mobile = toAsciiDigits(String(raw ?? '').trim());
mobile = mobile.replace(INVISIBLE_CHARS, '');
let digits = mobile.replace(/\D/g, '');
if (!digits) return '';
if (digits.startsWith('0098')) {
digits = digits.slice(2);
}
if (digits.startsWith('98') && digits.length >= 12) {
digits = `0${digits.slice(2)}`;
} else if (digits.startsWith('9') && digits.length === 10) {
digits = `0${digits}`;
}
return digits;
}
export function isValidIranMobile(mobile: string): boolean {
return IRAN_MOBILE_REGEX.test(mobile);
}