You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
371 lines
16 KiB
371 lines
16 KiB
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { MdOutlineSwitchAccount } from "react-icons/md";
|
|
import { getClientCookie, setClientCookie } from "@/lib/cookies";
|
|
|
|
export const FEMALE_TOKEN = "545f61bb3e061ccb9b19f84715eb1b1ed4740331";
|
|
export const MALE_TOKEN = "f3a7543b44ef0a713d1ee0d4f7866b3825cf1308";
|
|
export const MALE_2_TOKEN = "56cd0fceb93f7cecf7ffa84c590135026cf54a1d";
|
|
|
|
export const FEMALE_EMAIL = "m.a.ghorbani01@gmail.com";
|
|
export const MALE_EMAIL = "muhammadamin.ghorbani@gmail.com";
|
|
export const MALE_2_EMAIL = "habibwabackup@gmail.com";
|
|
|
|
const TOKEN_COOKIE_NAME = "HABIB_TOKEN";
|
|
|
|
type TokenSwitcherProps = {
|
|
variant?: "default" | "transparent";
|
|
className?: string;
|
|
};
|
|
|
|
export function TokenSwitcher({
|
|
variant = "default",
|
|
className,
|
|
}: TokenSwitcherProps) {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const [currentToken, setCurrentToken] = useState<string>("");
|
|
|
|
useEffect(() => {
|
|
if (typeof window !== "undefined") {
|
|
const token =
|
|
(window as any).HABIB_TOKEN ??
|
|
getClientCookie(TOKEN_COOKIE_NAME) ??
|
|
getClientCookie("habib_token") ??
|
|
sessionStorage.getItem(TOKEN_COOKIE_NAME) ??
|
|
process.env.NEXT_PUBLIC_DEFAULT_TOKEN ??
|
|
MALE_TOKEN;
|
|
setCurrentToken(token);
|
|
}
|
|
}, []);
|
|
|
|
const isMale = currentToken === MALE_TOKEN;
|
|
const isMale2 = currentToken === MALE_2_TOKEN;
|
|
const isFemale = currentToken === FEMALE_TOKEN;
|
|
const isNoToken = currentToken === "NO_TOKEN" || !currentToken;
|
|
|
|
const handleSelectToken = (newToken: string) => {
|
|
if (typeof window !== "undefined") {
|
|
// Clear local storage and session storage so answers and cached state from previous user are removed
|
|
try {
|
|
window.localStorage.clear();
|
|
window.sessionStorage.clear();
|
|
} catch (e) {
|
|
console.error("Failed to clear storage", e);
|
|
}
|
|
|
|
setClientCookie(TOKEN_COOKIE_NAME, newToken);
|
|
setClientCookie("habib_token", newToken);
|
|
try {
|
|
sessionStorage.setItem(TOKEN_COOKIE_NAME, newToken);
|
|
} catch (e) {
|
|
console.warn("sessionStorage is not accessible:", e);
|
|
}
|
|
(window as any).HABIB_TOKEN = newToken;
|
|
setCurrentToken(newToken);
|
|
setIsOpen(false);
|
|
|
|
// Navigate to the beginning of the flow (intro page)
|
|
window.location.href = "/";
|
|
}
|
|
};
|
|
|
|
const handleResetUser = async (userId: number | null, label: string) => {
|
|
const message =
|
|
userId !== null
|
|
? `آیا از پاک کردن تمامی اطلاعات هویتی، پاسخها و پیشرفت این کاربر (${label}) و شروع مجدد از مرحله اول آنبوردینگ مطمئن هستید؟`
|
|
: `آیا از پاک کردن تمامی اطلاعات محلی و کوکیهای مربوط به این حالت (بدون توکن) و شروع مجدد مطمئن هستید؟`;
|
|
|
|
if (!window.confirm(message)) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// 1. Clear local/session storage
|
|
if (typeof window !== "undefined") {
|
|
window.localStorage.clear();
|
|
window.sessionStorage.clear();
|
|
}
|
|
|
|
// 2. Call backend reset script via API route if it is a real DB user
|
|
if (userId !== null) {
|
|
const response = await fetch("/api/dev-reset-profile", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({ userId }),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errData = await response.json();
|
|
alert(`خطا در ریست پروفایل: ${errData.error || response.statusText}`);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// 3. Set the target token in the cookies and redirect to /
|
|
const targetToken =
|
|
userId === 17119
|
|
? MALE_TOKEN
|
|
: userId === 147714
|
|
? FEMALE_TOKEN
|
|
: userId === 146024
|
|
? MALE_2_TOKEN
|
|
: "NO_TOKEN";
|
|
|
|
setClientCookie(TOKEN_COOKIE_NAME, targetToken);
|
|
setClientCookie("habib_token", targetToken);
|
|
if (typeof window !== "undefined") {
|
|
try {
|
|
sessionStorage.setItem(TOKEN_COOKIE_NAME, targetToken);
|
|
} catch (e) {
|
|
console.warn("sessionStorage is not accessible:", e);
|
|
}
|
|
(window as any).HABIB_TOKEN = targetToken;
|
|
setCurrentToken(targetToken);
|
|
}
|
|
|
|
setIsOpen(false);
|
|
window.location.href = "/";
|
|
} catch (error) {
|
|
console.error("Failed to reset user:", error);
|
|
alert("خطایی در انجام عملیات رخ داد.");
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<button
|
|
type="button"
|
|
onClick={() => setIsOpen(true)}
|
|
aria-label="تغییر توکن کاربر (تست)"
|
|
title="تغییر توکن (آقا / خانم)"
|
|
className={[
|
|
"inline-flex items-center gap-1.5 rounded-[15px] px-3 py-2 text-xs font-bold transition-all active:scale-95 shadow-md border border-slate-200/80 dark:border-slate-700/80 backdrop-blur-md",
|
|
variant === "transparent"
|
|
? "bg-black/40 text-white hover:bg-black/50"
|
|
: "bg-white/95 text-slate-800 hover:bg-white dark:bg-slate-900/95 dark:text-slate-100",
|
|
className,
|
|
]
|
|
.filter(Boolean)
|
|
.join(" ")}
|
|
>
|
|
<MdOutlineSwitchAccount className="size-5 text-rose-500" />
|
|
<span>
|
|
{isMale
|
|
? "آقا 👨"
|
|
: isMale2
|
|
? "آقا ۲ 👨"
|
|
: isFemale
|
|
? "خانم 👩"
|
|
: isNoToken
|
|
? "بدون توکن 👤"
|
|
: "توکن 🔑"}
|
|
</span>
|
|
</button>
|
|
|
|
{isOpen && (
|
|
<div className="fixed inset-0 z-[10000] flex items-center justify-center bg-black/50 p-4 backdrop-blur-xs animate-in fade-in duration-200">
|
|
<div
|
|
className="w-full max-w-sm rounded-2xl bg-white p-5 shadow-xl dark:bg-slate-900 border border-slate-100 dark:border-slate-800"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className="flex items-center justify-between pb-3 border-b border-slate-100 dark:border-slate-800">
|
|
<h3 className="font-bold text-slate-900 dark:text-white text-base flex items-center gap-2">
|
|
<MdOutlineSwitchAccount className="text-rose-500 text-xl" />
|
|
انتخاب حساب کاربری (تست)
|
|
</h3>
|
|
<button
|
|
type="button"
|
|
onClick={() => setIsOpen(false)}
|
|
className="text-slate-400 hover:text-slate-600 dark:hover:text-slate-200 text-sm p-1"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
|
|
<div className="mt-4 flex flex-col gap-3">
|
|
{/* Male option card */}
|
|
<div
|
|
className={[
|
|
"flex items-center justify-between rounded-xl border transition-all dir-rtl overflow-hidden",
|
|
isMale
|
|
? "border-rose-500 bg-rose-50/60 dark:bg-rose-950/30 text-rose-900 dark:text-rose-100 font-semibold shadow-xs"
|
|
: "border-slate-200 dark:border-slate-800 hover:border-slate-300 dark:hover:border-slate-700 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-200",
|
|
].join(" ")}
|
|
>
|
|
<button
|
|
type="button"
|
|
onClick={() => handleSelectToken(MALE_TOKEN)}
|
|
className="flex-1 flex items-center gap-3 p-3.5 text-right min-w-0"
|
|
>
|
|
<span className="text-2xl shrink-0">👨</span>
|
|
<div className="min-w-0 flex-1">
|
|
<div className="text-sm font-bold">حساب آقا</div>
|
|
<div className="text-xs text-slate-500 dark:text-slate-400 font-medium truncate">
|
|
{MALE_EMAIL}
|
|
</div>
|
|
<div className="text-[11px] font-mono text-slate-400 dark:text-slate-500 dir-ltr text-left mt-0.5 select-all truncate">
|
|
{MALE_TOKEN}
|
|
</div>
|
|
</div>
|
|
</button>
|
|
<div className="flex items-center gap-1.5 pl-3">
|
|
{isMale && (
|
|
<span className="text-[10px] px-2 py-0.5 rounded-full bg-rose-500 text-white font-medium">
|
|
فعال
|
|
</span>
|
|
)}
|
|
<button
|
|
type="button"
|
|
onClick={() => handleResetUser(17119, "حساب آقا")}
|
|
title="پاک کردن اطلاعات و شروع مجدد"
|
|
className="p-2 text-slate-400 hover:text-rose-500 hover:bg-rose-50 dark:hover:bg-rose-950/20 rounded-lg transition-colors"
|
|
>
|
|
🗑️
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Male 2 option card */}
|
|
<div
|
|
className={[
|
|
"flex items-center justify-between rounded-xl border transition-all dir-rtl overflow-hidden",
|
|
isMale2
|
|
? "border-rose-500 bg-rose-50/60 dark:bg-rose-950/30 text-rose-900 dark:text-rose-100 font-semibold shadow-xs"
|
|
: "border-slate-200 dark:border-slate-800 hover:border-slate-300 dark:hover:border-slate-700 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-200",
|
|
].join(" ")}
|
|
>
|
|
<button
|
|
type="button"
|
|
onClick={() => handleSelectToken(MALE_2_TOKEN)}
|
|
className="flex-1 flex items-center gap-3 p-3.5 text-right min-w-0"
|
|
>
|
|
<span className="text-2xl shrink-0">👨</span>
|
|
<div className="min-w-0 flex-1">
|
|
<div className="text-sm font-bold">حساب آقا ۲</div>
|
|
<div className="text-xs text-slate-500 dark:text-slate-400 font-medium truncate">
|
|
{MALE_2_EMAIL}
|
|
</div>
|
|
<div className="text-[11px] font-mono text-slate-400 dark:text-slate-500 dir-ltr text-left mt-0.5 select-all truncate">
|
|
{MALE_2_TOKEN}
|
|
</div>
|
|
</div>
|
|
</button>
|
|
<div className="flex items-center gap-1.5 pl-3">
|
|
{isMale2 && (
|
|
<span className="text-[10px] px-2 py-0.5 rounded-full bg-rose-500 text-white font-medium">
|
|
فعال
|
|
</span>
|
|
)}
|
|
<button
|
|
type="button"
|
|
onClick={() => handleResetUser(146024, "حساب آقا ۲")}
|
|
title="پاک کردن اطلاعات و شروع مجدد"
|
|
className="p-2 text-slate-400 hover:text-rose-500 hover:bg-rose-50 dark:hover:bg-rose-950/20 rounded-lg transition-colors"
|
|
>
|
|
🗑️
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Female option card */}
|
|
<div
|
|
className={[
|
|
"flex items-center justify-between rounded-xl border transition-all dir-rtl overflow-hidden",
|
|
isFemale
|
|
? "border-rose-500 bg-rose-50/60 dark:bg-rose-950/30 text-rose-900 dark:text-rose-100 font-semibold shadow-xs"
|
|
: "border-slate-200 dark:border-slate-800 hover:border-slate-300 dark:hover:border-slate-700 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-200",
|
|
].join(" ")}
|
|
>
|
|
<button
|
|
type="button"
|
|
onClick={() => handleSelectToken(FEMALE_TOKEN)}
|
|
className="flex-1 flex items-center gap-3 p-3.5 text-right min-w-0"
|
|
>
|
|
<span className="text-2xl shrink-0">👩</span>
|
|
<div className="min-w-0 flex-1">
|
|
<div className="text-sm font-bold">حساب خانم</div>
|
|
<div className="text-xs text-slate-500 dark:text-slate-400 font-medium truncate">
|
|
{FEMALE_EMAIL}
|
|
</div>
|
|
<div className="text-[11px] font-mono text-slate-400 dark:text-slate-500 dir-ltr text-left mt-0.5 select-all truncate">
|
|
{FEMALE_TOKEN}
|
|
</div>
|
|
</div>
|
|
</button>
|
|
<div className="flex items-center gap-1.5 pl-3">
|
|
{isFemale && (
|
|
<span className="text-[10px] px-2 py-0.5 rounded-full bg-rose-500 text-white font-medium">
|
|
فعال
|
|
</span>
|
|
)}
|
|
<button
|
|
type="button"
|
|
onClick={() => handleResetUser(147714, "حساب خانم")}
|
|
title="پاک کردن اطلاعات و شروع مجدد"
|
|
className="p-2 text-slate-400 hover:text-rose-500 hover:bg-rose-50 dark:hover:bg-rose-950/20 rounded-lg transition-colors"
|
|
>
|
|
🗑️
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* No token option card */}
|
|
<div
|
|
className={[
|
|
"flex items-center justify-between rounded-xl border transition-all dir-rtl overflow-hidden",
|
|
isNoToken
|
|
? "border-rose-500 bg-rose-50/60 dark:bg-rose-950/30 text-rose-900 dark:text-rose-100 font-semibold shadow-xs"
|
|
: "border-slate-200 dark:border-slate-800 hover:border-slate-300 dark:hover:border-slate-700 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-200",
|
|
].join(" ")}
|
|
>
|
|
<button
|
|
type="button"
|
|
onClick={() => handleSelectToken("NO_TOKEN")}
|
|
className="flex-1 flex items-center gap-3 p-3.5 text-right"
|
|
>
|
|
<span className="text-2xl">👤</span>
|
|
<div>
|
|
<div className="text-sm font-bold">کاربر بدون توکن</div>
|
|
<div className="text-xs text-slate-500 dark:text-slate-400 font-medium">
|
|
حالت مهمان / بدون احراز هویت
|
|
</div>
|
|
</div>
|
|
</button>
|
|
<div className="flex items-center gap-1.5 pl-3">
|
|
{isNoToken && (
|
|
<span className="text-[10px] px-2 py-0.5 rounded-full bg-rose-500 text-white font-medium">
|
|
فعال
|
|
</span>
|
|
)}
|
|
<button
|
|
type="button"
|
|
onClick={() => handleResetUser(null, "کاربر بدون توکن")}
|
|
title="پاک کردن اطلاعات و شروع مجدد"
|
|
className="p-2 text-slate-400 hover:text-rose-500 hover:bg-rose-50 dark:hover:bg-rose-950/20 rounded-lg transition-colors"
|
|
>
|
|
🗑️
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-5 flex flex-col gap-2">
|
|
<button
|
|
type="button"
|
|
onClick={() => setIsOpen(false)}
|
|
className="w-full py-2.5 rounded-xl bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300 font-medium text-sm hover:bg-slate-200 dark:hover:bg-slate-700 transition-colors"
|
|
>
|
|
انصراف
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default TokenSwitcher;
|