119 lines
3.7 KiB
TypeScript
119 lines
3.7 KiB
TypeScript
export type PreviewAuthUser = {
|
|
id: number;
|
|
name: string | null;
|
|
email: string;
|
|
};
|
|
|
|
type StoredPreviewUser = PreviewAuthUser & {
|
|
password: string;
|
|
created_at: string;
|
|
};
|
|
|
|
const STORE_USERS_KEY = "extra_preview_users";
|
|
const STORE_AUTH_SALT = "extra_preview_auth_v1";
|
|
export const PREVIEW_ADMIN_TOKEN = "preview_admin_token";
|
|
|
|
const DEMO_PREVIEW_USER: StoredPreviewUser = {
|
|
id: 1,
|
|
name: "عميل تجريبي",
|
|
email: "demo@extra.sa",
|
|
password: "Extra123",
|
|
created_at: "2026-03-28T00:00:00.000Z",
|
|
};
|
|
|
|
function readUsers(): StoredPreviewUser[] {
|
|
if (typeof localStorage === "undefined") return [DEMO_PREVIEW_USER];
|
|
try {
|
|
const parsed = JSON.parse(localStorage.getItem(STORE_USERS_KEY) || "[]");
|
|
const users = Array.isArray(parsed) ? parsed : [];
|
|
return users.some((user) => user.email === DEMO_PREVIEW_USER.email) ? users : [DEMO_PREVIEW_USER, ...users];
|
|
} catch {
|
|
return [DEMO_PREVIEW_USER];
|
|
}
|
|
}
|
|
|
|
function writeUsers(users: StoredPreviewUser[]) {
|
|
if (typeof localStorage === "undefined") return;
|
|
localStorage.setItem(STORE_USERS_KEY, JSON.stringify(users));
|
|
}
|
|
|
|
function normalizeEmail(email: string) {
|
|
return email.trim().toLowerCase();
|
|
}
|
|
|
|
function makeToken(userId: number) {
|
|
return `preview_user_${userId}_${STORE_AUTH_SALT}`;
|
|
}
|
|
|
|
export function isJsonResponse(res: Response) {
|
|
const contentType = res.headers.get("content-type") || "";
|
|
return contentType.includes("application/json");
|
|
}
|
|
|
|
export function registerPreviewStoreUser(input: {
|
|
name?: string;
|
|
email: string;
|
|
password: string;
|
|
confirm_password?: string;
|
|
}) {
|
|
const email = normalizeEmail(input.email);
|
|
const name = input.name?.trim() || null;
|
|
const password = input.password || "";
|
|
const confirm = input.confirm_password || "";
|
|
|
|
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
|
throw new Error("البريد الإلكتروني غير صحيح");
|
|
}
|
|
if (password.length < 8) {
|
|
throw new Error("كلمة المرور يجب أن تكون 8 أحرف على الأقل");
|
|
}
|
|
if (!/[A-Z]/.test(password)) {
|
|
throw new Error("كلمة المرور يجب أن تحتوي على حرف كبير");
|
|
}
|
|
if (!/[0-9]/.test(password)) {
|
|
throw new Error("كلمة المرور يجب أن تحتوي على رقم");
|
|
}
|
|
if (password !== confirm) {
|
|
throw new Error("كلمة المرور وتأكيدها غير متطابقين");
|
|
}
|
|
|
|
const users = readUsers();
|
|
if (users.some((user) => user.email === email)) {
|
|
throw new Error("البريد الإلكتروني مستخدم بالفعل");
|
|
}
|
|
|
|
const id = users.reduce((max, user) => Math.max(max, user.id), 0) + 1;
|
|
const newUser: StoredPreviewUser = {
|
|
id,
|
|
name,
|
|
email,
|
|
password,
|
|
created_at: new Date().toISOString(),
|
|
};
|
|
users.push(newUser);
|
|
writeUsers(users);
|
|
|
|
const user: PreviewAuthUser = { id: newUser.id, name: newUser.name, email: newUser.email };
|
|
return { user, token: makeToken(user.id) };
|
|
}
|
|
|
|
export function loginPreviewStoreUser(input: { email: string; password: string }) {
|
|
const email = normalizeEmail(input.email);
|
|
const users = readUsers();
|
|
const user = users.find((entry) => entry.email === email && entry.password === input.password);
|
|
if (!user) {
|
|
throw new Error("البريد الإلكتروني أو كلمة المرور غير صحيحة");
|
|
}
|
|
return {
|
|
user: { id: user.id, name: user.name, email: user.email },
|
|
token: makeToken(user.id),
|
|
};
|
|
}
|
|
|
|
export function loginPreviewAdmin(input: { username: string; password: string }) {
|
|
if (input.username === "admin" && input.password === "admin123") {
|
|
return { token: PREVIEW_ADMIN_TOKEN, username: "admin" };
|
|
}
|
|
throw new Error("بيانات الدخول غير صحيحة");
|
|
}
|