<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>آزمون شخصیت شناسی MBTI</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-font-face.css" rel="stylesheet" type="text/css" />
<style>
body { font-family: 'Vazirmatn', sans-serif; background-color: #f3f4f6; }
.fade-in { animation: fadeIn 0.5s ease-in-out; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.option-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); }
.loading-overlay { position: fixed; inset: 0; background: rgba(255,255,255,0.8); display: flex; justify-content: center; align-items: center; z-index: 100; }
</style>
</head>
<body class="text-gray-800 min-h-screen flex flex-col">
<!-- Loading Spinner -->
<div id="loading" class="loading-overlay hidden">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-indigo-700"></div>
</div>
<!-- Header -->
<header class="bg-indigo-700 text-white shadow-lg sticky top-0 z-50">
<div class="container mx-auto px-4 py-4 flex justify-between items-center">
<h1 class="text-xl font-bold flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" /></svg>
آزمون جامع MBTI
</h1>
<div id="user-header-info" class="hidden text-sm md:text-base flex items-center gap-2">
<span id="header-username"></span>
<button onclick="logout()" class="bg-indigo-800 hover:bg-indigo-900 px-3 py-1 rounded text-xs transition">خروج</button>
</div>
</div>
</header>
<main id="app" class="flex-grow container mx-auto px-4 py-8 max-w-4xl"></main>
<footer class="bg-gray-800 text-white py-6 mt-auto">
<div class="container mx-auto px-4 text-center text-sm text-gray-400">
<p>© 2024 MBTI Professional Test - Powered by Cloudflare D1</p>
</div>
</footer>
<script>
// --- CONFIGURATION ---
// آدرس ورکر خود را اینجا وارد کنید
// مثال: https://mbti-worker.YOUR-SUBDOMAIN.workers.dev
const WORKER_URL = "https://mbti-worker.h-ghobadi1377.workers.dev/";
// --- DATA ---
const questions = [
{ id: 1, text: "در مهمانیها معمولاً...", options: [{ text: "با افراد زیادی، از جمله غریبهها صحبت میکنم", score: { E: 2, I: 0 } }, { text: "فقط با چند نفر از دوستان نزدیکم وقت میگذرانم", score: { E: 0, I: 2 } }] },
{ id: 2, text: "بیشتر واقعبین هستید یا خیالباف؟", options: [{ text: "واقعبین و عملی", score: { S: 2, N: 0 } }, { text: "خیالباف و آیندهنگر", score: { S: 0, N: 2 } }] },
{ id: 3, text: "در تصمیمگیریها بیشتر...", options: [{ text: "از منطق و اصول پیروی میکنم", score: { T: 2, F: 0 } }, { text: "به احساسات و ارزشهای انسانی توجه دارم", score: { T: 0, F: 2 } }] },
{ id: 4, text: "آیا ترجیح میدهید کارهایتان...", options: [{ text: "برنامهریزی شده و سازمانیافته باشد", score: { J: 2, P: 0 } }, { text: "منعطف و بدون ساختار سفت و سخت باشد", score: { J: 0, P: 2 } }] },
{ id: 5, text: "وقتی تلفن زنگ میزند...", options: [{ text: "سریع پاسخ میدهم", score: { E: 2, I: 0 } }, { text: "امیدوارم کس دیگری پاسخ دهد", score: { E: 0, I: 2 } }] },
{ id: 6, text: "آیا بیشتر به جزئیات توجه میکنید یا کلیات؟", options: [{ text: "جزئیات دقیق", score: { S: 2, N: 0 } }, { text: "تصویر کلی و معانی", score: { S: 0, N: 2 } }] },
{ id: 7, text: "کدام برای شما مهمتر است؟", options: [{ text: "عدالت و حقیقت", score: { T: 2, F: 0 } }, { text: "همدردی و مهربانی", score: { T: 0, F: 2 } }] },
{ id: 8, text: "انجام کارها در دقیقه نود...", options: [{ text: "برایم استرسزا است", score: { J: 2, P: 0 } }, { text: "گاهی باعث خلاقیتم میشود", score: { J: 0, P: 2 } }] },
{ id: 9, text: "پس از گذراندن وقت با گروه زیادی از مردم...", options: [{ text: "احساس انرژی و سرزندگی میکنم", score: { E: 2, I: 0 } }, { text: "احساس خستگی میکنم و نیاز به تنهایی دارم", score: { E: 0, I: 2 } }] },
{ id: 10, text: "به نظر شما کدام بدتر است؟", options: [{ text: "رویاپردازی بدون عمل", score: { S: 2, N: 0 } }, { text: "زندگی روزمره و بدون هیجان", score: { S: 0, N: 2 } }] }
];
const personalityTypes = {
"ISTJ": { title: "بازرس", desc: "مسئولیتپذیر، واقعبین و سازمانیافته.", careers: ["حسابدار", "افسر نظامی", "قاضی", "مدیر سیستم"], famous: ["آنگلا مرکل (سیاستمدار)", "جورج واشنگتن (سیاستمدار)", "وارن بافت (اقتصاددان)", "ناتالی پورتمن (بازیگر)", "آنتونی هاپکینز (بازیگر)"] },
"ISFJ": { title: "مدافع", desc: "گرم، فداکار و دقیق در جزئیات.", careers: ["پرستار", "معلم", "مددکار اجتماعی", "دندانپزشک"], famous: ["مادر ترزا (چهره مذهبی)", "کیت میدلتون (خاندان سلطنتی)", "تایگر وودز (ورزشکار)", "سلنا گومز (هنرمند)", "بیانسه (هنرمند)"] },
"INFJ": { title: "حامی", desc: "آیندهنگر، با بینش عمیق و ایدهآلگرا.", careers: ["روانشناس", "نویسنده", "مشاور", "هنرمند"], famous: ["نلسون ماندلا (سیاستمدار)", "مارتین لوتر کینگ (فعال اجتماعی)", "نیکول کیدمن (بازیگر)", "افلاطون (فیلسوف)", "لیدی گاگا (هنرمند)"] },
"INTJ": { title: "معمار", desc: "متفکر استراتژیک، مستقل و منطقی.", careers: ["دانشمند", "مهندس نرمافزار", "استراتژیست", "استاد دانشگاه"], famous: ["ایلان ماسک (کارآفرین)", "مارک زاکربرگ (کارآفرین)", "کریستوفر نولان (کارگردان)", "ایزاک نیوتون (دانشمند)", "ولادیمیر پوتین (سیاستمدار)"] },
"ISTP": { title: "چیرهدست", desc: "جسور، عملی و ماهر در استفاده از ابزار.", careers: ["خلبان", "مهندس مکانیک", "آتشنشان", "تحلیلگر داده"], famous: ["مایکل جردن (ورزشکار)", "تام کروز (بازیگر)", "کلینت ایستوود (کارگردان)", "ولادیمیر پوتین (سیاستمدار)", "بروس لی (رزمیکار)"] },
"ISFP": { title: "ماجراجو", desc: "هنرمند، حساس و دوستدار تجربههای جدید.", careers: ["طراح مد", "موسیقیدان", "آشپز", "گرافیست"], famous: ["مایکل جکسون (هنرمند)", "دیوید بکهام (ورزشکار)", "لانا دل ری (خواننده)", "فریدا کالو (نقاش)", "برد پیت (بازیگر)"] },
"INFP": { title: "میانجی", desc: "شاعرمسلک، مهربان و نوعدوست.", careers: ["نویسنده", "شاعر", "گرافیست", "مشاور تحصیلی"], famous: ["ویلیام شکسپیر (نویسنده)", "جی.آر.آر تالکین (نویسنده)", "جانی دپ (بازیگر)", "کیانو ریوز (بازیگر)", "پرنسس دایانا (خاندان سلطنتی)"] },
"INTP": { title: "منطقدان", desc: "مخترع، کنجکاو و تشنه دانش.", careers: ["برنامهنویس", "ریاضیدان", "فیلسوف", "محقق"], famous: ["آلبرت انیشتین (دانشمند)", "بیل گیتس (کارآفرین)", "لری پیج (کارآفرین)", "آبراهام لینکلن (سیاستمدار)", "کریستن استوارت (بازیگر)"] },
"ESTP": { title: "کارآفرین", desc: "هوشمند، پرانرژی و اهل ریسک.", careers: ["فروشنده", "کارآفرین", "پلییس", "ورزشکار حرفهای"], famous: ["دونالد ترامپ (سیاستمدار)", "مدونا (هنرمند)", "ساموئل ال جکسون (بازیگر)", "چرچیل (سیاستمدار)", "ادی مورفی (کمدین)"] },
"ESFP": { title: "سرگرمکننده", desc: "خودجوش، پرانرژی و مشتاق زندگی.", careers: ["بازیگر", "مجری", "طراح داخلی", "مهماندار"], famous: ["الویس پریسلی (خواننده)", "مریلین مونرو (بازیگر)", "کریستیانو رونالدو (ورزشکار)", "ادل (خواننده)", "بیل کلینتون (سیاستمدار)"] },
"ENFP": { title: "پیکارگر", desc: "مشتاق، خلاق و اجتماعی.", careers: ["خبرنگار", "مدیر تبلیغات", "بازیگر", "سیاستمدار"], famous: ["رابرت داونی جونیور (بازیگر)", "ویل اسمیت (بازیگر)", "رابین ویلیامز (کمدین)", "کوئنتین تارانتینو (کارگردان)", "والت دیزنی (کارآفرین)"] },
"ENTP": { title: "مجادلهگر", desc: "زیرک، کنجکاو و عاشق چالشهای فکری.", careers: ["وکیل", "کارآفرین", "مشاور مدیریت", "سیاستمدار"], famous: ["توماس ادیسون (مخترع)", "لئوناردو داوینچی (دانشمند/هنرمند)", "استیو جابز (کارآفرین)", "باراک اوباما (سیاستمدار)", "رایان رینولدز (بازیگر)"] },
"ESTJ": { title: "مجری", desc: "مدیر عالی، بینظیر در اداره امور.", careers: ["مدیر پروژه", "افسر پلیس", "قاضی", "مدیر مالی"], famous: ["سونیا سوتومایور (قاضی)", "جان دی. راکفلر (اقتصاددان)", "فرانک سیناترا (هنرمند)", "مارتا استوارت (کارآفرین)", "جورج بوش (سیاستمدار)"] },
"ESFJ": { title: "سفیر", desc: "بسیار دلسوز، اجتماعی و محبوب.", careers: ["معلم", "پرستار", "مدیر روابط عمومی", "مشاور املاک"], famous: ["تیلور سوئیفت (هنرمند)", "جو بایدن (سیاستمدار)", "جنیفر لوپز (هنرمند)", "هیو جکمن (بازیگر)", "شاهزاده ویلیام (خاندان سلطنتی)"] },
"ENFJ": { title: "قهرمان", desc: "رهبری کاریزماتیک و الهامبخش.", careers: ["معلم", "سیاستمدار", "مدیر منابع انسانی", "مربی"], famous: ["باراک اوباما (سیاستمدار)", "اپرا وینفری (مجری)", "آبراهام مزلو (روانشناس)", "شین دایک (کارگردان)", "مورگان فریمن (بازیگر)"] },
"ENTJ": { title: "فرمانده", desc: "رهبرانی جسور، با اراده و قوی.", careers: ["مدیر عامل", "قاضی", "کارآفرین", "استاد دانشگاه"], famous: ["استیو جابز (کارآفرین)", "گوردون رمزی (آشپز/کارآفرین)", "مارگارت تاچر (سیاستمدار)", "جیم کری (کمدین)", "هریسون فورد (بازیگر)"] }
};
const educationMap = { "diploma": "دیپلم", "bachelor": "لیسانس", "master": "فوق لیسانس", "phd": "دکترا" };
let appState = {
view: 'login',
currentUser: null,
answers: {},
currentQuestionIndex: 0
};
// --- CLOUDFLARE CONNECTED API ---
const db = {
login: async (email, name) => {
try {
const res = await fetch(`${WORKER_URL}/api/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, name })
});
if (!res.ok) throw new Error('Login failed');
return await res.json();
} catch (e) {
console.error(e);
alert("خطا در ارتباط با سرور. لطفا اتصال اینترنت خود را بررسی کنید.");
}
},
updateProfile: async (email, data) => {
try {
const res = await fetch(`${WORKER_URL}/api/profile`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, data })
});
if (!res.ok) throw new Error('Update failed');
return await res.json();
} catch (e) {
alert("خطا در ذخیره پروفایل.");
}
},
saveResult: async (email, result) => {
try {
const res = await fetch(`${WORKER_URL}/api/result`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, result, title: personalityTypes[result.type].title })
});
if (res.status === 403) {
alert("شما از ۳ فرصت رایگان خود استفاده کردهاید.");
return null;
}
return await res.json();
} catch (e) {
alert("خطا در ذخیره نتیجه.");
}
}
};
// --- LOGIC ---
function init() {
// Check session only to keep logged in state, actual data syncs on actions
const savedUser = sessionStorage.getItem('current_mbti_user');
if (savedUser) {
appState.currentUser = JSON.parse(savedUser);
renderView(appState.currentUser.profileComplete ? 'dashboard' : 'profile');
} else {
renderView('login');
}
}
async function handleGoogleLogin() {
showLoading(true);
const mockGoogleUser = { email: "user@example.com", name: "کاربر تستی" };
const user = await db.login(mockGoogleUser.email, mockGoogleUser.name);
if(user) {
appState.currentUser = user;
sessionStorage.setItem('current_mbti_user', JSON.stringify(user));
updateHeader();
renderView(user.profileComplete ? 'dashboard' : 'profile');
}
showLoading(false);
}
async function handleProfileSubmit(e) {
e.preventDefault();
showLoading(true);
const formData = new FormData(e.target);
const birthDate = `${formData.get('year')}/${formData.get('month')}/${formData.get('day')}`;
const imageFile = formData.get('profile_image');
let imageBase64 = null;
if (imageFile && imageFile.size > 0) {
if (imageFile.size > 500 * 1024) {
alert("حجم عکس نباید بیشتر از ۵۰۰ کیلوبایت باشد.");
showLoading(false);
return;
}
imageBase64 = await new Promise((resolve) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.readAsDataURL(imageFile);
});
} else if (appState.currentUser.profileImage) {
imageBase64 = appState.currentUser.profileImage;
}
const data = {
name: formData.get('name'),
birthDate: birthDate,
education: formData.get('education'),
mobile: formData.get('mobile'),
profileImage: imageBase64
};
const updatedUser = await db.updateProfile(appState.currentUser.email, data);
if (updatedUser) {
appState.currentUser = updatedUser;
sessionStorage.setItem('current_mbti_user', JSON.stringify(updatedUser));
renderView('dashboard');
}
showLoading(false);
}
function startQuiz() {
if (appState.currentUser.attempts >= 3) {
alert("شما از ۳ فرصت رایگان خود استفاده کردهاید.");
return;
}
appState.currentQuestionIndex = 0;
appState.answers = { E:0, I:0, S:0, N:0, T:0, F:0, J:0, P:0 };
renderView('quiz');
}
function answerQuestion(scores) {
for (let key in scores) appState.answers[key] += scores[key];
appState.currentQuestionIndex++;
if (appState.currentQuestionIndex < questions.length) {
renderView('quiz');
} else {
calculateAndShowResult();
}
}
async function calculateAndShowResult() {
showLoading(true);
const s = appState.answers;
let type = "";
type += s.E >= s.I ? "E" : "I";
type += s.S >= s.N ? "S" : "N";
type += s.T >= s.F ? "T" : "F";
type += s.J >= s.P ? "J" : "P";
const updatedUser = await db.saveResult(appState.currentUser.email, { type });
if (updatedUser) {
appState.currentUser = updatedUser;
sessionStorage.setItem('current_mbti_user', JSON.stringify(updatedUser));
appState.lastResultType = type;
renderView('result');
} else {
// If limit reached or error, go back to dashboard
renderView('dashboard');
}
showLoading(false);
}
function logout() {
sessionStorage.removeItem('current_mbti_user');
appState.currentUser = null;
updateHeader();
renderView('login');
}
// --- RENDER FUNCTIONS (Almost same as before) ---
function showLoading(show) {
document.getElementById('loading').classList.toggle('hidden', !show);
}
function updateHeader() {
const infoDiv = document.getElementById('user-header-info');
const nameSpan = document.getElementById('header-username');
if (appState.currentUser) {
infoDiv.classList.remove('hidden');
nameSpan.textContent = appState.currentUser.name || appState.currentUser.email;
} else {
infoDiv.classList.add('hidden');
}
}
function generateDateSelects() {
const months = ['فروردین','اردیبهشت','خرداد','تیر','مرداد','شهریور','مهر','آبان','آذر','دی','بهمن','اسفند'];
let daysOptions = ''; for(let i=1; i<=31; i++) daysOptions += `<option value="${i}">${i}</option>`;
let monthsOptions = months.map((m, i) => `<option value="${i+1}">${m}</option>`).join('');
let yearsOptions = ''; for(let i=1403; i>=1300; i--) yearsOptions += `<option value="${i}">${i}</option>`;
return `<div class="grid grid-cols-3 gap-2"><select name="day" class="px-2 py-2 border rounded-lg bg-white">${daysOptions}</select><select name="month" class="px-2 py-2 border rounded-lg bg-white">${monthsOptions}</select><select name="year" class="px-2 py-2 border rounded-lg bg-white">${yearsOptions}</select></div>`;
}
function renderView(viewName) {
appState.view = viewName;
const app = document.getElementById('app');
app.innerHTML = '';
if (viewName === 'login') {
app.innerHTML = `<div class="fade-in max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden p-8 text-center mt-10"><div class="mb-6"><div class="w-20 h-20 bg-indigo-100 text-indigo-600 rounded-full flex items-center justify-center mx-auto mb-4"><svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" /></svg></div><h2 class="text-2xl font-bold text-gray-800">ورود به حساب کاربری</h2><p class="text-gray-500 mt-2">برای شرکت در آزمون و ذخیره نتایج وارد شوید</p></div><button onclick="handleGoogleLogin()" class="w-full bg-white border border-gray-300 text-gray-700 py-3 px-4 rounded-lg flex items-center justify-center gap-3 hover:bg-gray-50 transition shadow-sm font-medium"><img src="https://www.google.com/favicon.ico" alt="Google" class="w-5 h-5">ورود با حساب گوگل</button></div>`;
} else if (viewName === 'profile') {
app.innerHTML = `<div class="fade-in max-w-lg mx-auto bg-white rounded-xl shadow-md p-8"><h2 class="text-2xl font-bold text-gray-800 mb-6 text-center">تکمیل پروفایل</h2><form onsubmit="handleProfileSubmit(event)" class="space-y-4"><div class="flex justify-center mb-6"><div class="relative w-24 h-24"><div class="w-24 h-24 rounded-full bg-gray-100 border-2 border-dashed border-gray-300 flex items-center justify-center overflow-hidden" id="image-preview"><svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z" /><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 13a3 3 0 11-6 0 3 3 0 016 0z" /></svg></div><input type="file" name="profile_image" accept="image/*" class="absolute inset-0 w-full h-full opacity-0 cursor-pointer" onchange="previewImage(this)"></div></div><p class="text-xs text-center text-gray-500 mt-[-1rem] mb-4">عکس پروفایل (حداکثر ۵۰۰ کیلوبایت)</p><div><label class="block text-sm font-medium text-gray-700 mb-1">نام و نام خانوادگی</label><input type="text" name="name" value="${appState.currentUser.name || ''}" required class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 outline-none"></div><div><label class="block text-sm font-medium text-gray-700 mb-1">تاریخ تولد</label>${generateDateSelects()}</div><div><label class="block text-sm font-medium text-gray-700 mb-1">تحصیلات</label><select name="education" class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 outline-none"><option value="diploma">دیپلم</option><option value="bachelor">لیسانس</option><option value="master">فوق لیسانس</option><option value="phd">دکترا</option></select></div><div><label class="block text-sm font-medium text-gray-700 mb-1">شماره موبایل</label><input type="tel" name="mobile" required class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 outline-none"></div><div class="pt-4"><button type="submit" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 rounded-lg transition">ذخیره و ادامه</button></div></form></div>`;
} else if (viewName === 'dashboard') {
const user = appState.currentUser;
const remaining = 3 - user.attempts;
const historyHTML = user.history.length === 0 ? `<div class="text-center text-gray-500 py-8 bg-gray-50 rounded-lg">هنوز در آزمونی شرکت نکردهاید.</div>` : user.history.map(h => `<div class="flex justify-between items-center bg-gray-50 p-4 rounded-lg mb-2"><div><span class="font-bold text-indigo-700 text-lg ml-2">${h.type}</span><span class="text-gray-600 text-sm">(${h.title})</span></div><span class="text-gray-400 text-xs">${h.date}</span></div>`).join('');
const userImage = user.profileImage ? `<img src="${user.profileImage}" class="w-full h-full object-cover">` : `<div class="w-full h-full flex items-center justify-center text-2xl font-bold text-gray-500">${user.name ? user.name.charAt(0) : 'U'}</div>`;
app.innerHTML = `<div class="fade-in grid md:grid-cols-3 gap-6"><div class="md:col-span-1"><div class="bg-white rounded-xl shadow p-6 text-center"><div class="w-24 h-24 bg-gray-200 rounded-full mx-auto mb-4 overflow-hidden border-2 border-gray-100">${userImage}</div><h3 class="font-bold text-lg">${user.name}</h3><p class="text-gray-500 text-sm mb-4">${user.email}</p><div class="border-t pt-4 text-right text-sm space-y-2"><div class="flex justify-between"><span>تولد:</span> <span>${user.birthDate || '-'}</span></div><div class="flex justify-between"><span>تحصیلات:</span> <span>${educationMap[user.education] || '-'}</span></div><div class="flex justify-between"><span>آزمونها:</span> <span>${user.attempts} / 3</span></div></div></div></div><div class="md:col-span-2 space-y-6"><div class="bg-gradient-to-r from-indigo-600 to-purple-600 rounded-xl shadow-lg p-6 text-white flex justify-between items-center"><div><h2 class="text-2xl font-bold mb-1">آزمون جدید</h2><p class="opacity-90 text-sm">شما ${remaining} فرصت رایگان باقیمانده دارید.</p></div>${remaining > 0 ? `<button onclick="startQuiz()" class="bg-white text-indigo-700 font-bold px-6 py-3 rounded-lg hover:bg-gray-100 transition shadow">شروع آزمون</button>` : `<button disabled class="bg-gray-300 text-gray-500 font-bold px-6 py-3 rounded-lg cursor-not-allowed">پایان اعتبار</button>`}</div><div class="bg-white rounded-xl shadow p-6"><h3 class="font-bold text-lg mb-4 border-b pb-2 flex items-center gap-2">تاریخچه نتایج</h3><div>${historyHTML}</div></div></div></div>`;
} else if (viewName === 'quiz') {
const q = questions[appState.currentQuestionIndex];
const progress = ((appState.currentQuestionIndex) / questions.length) * 100;
app.innerHTML = `<div class="fade-in max-w-2xl mx-auto bg-white rounded-xl shadow-lg p-8"><div class="w-full bg-gray-200 rounded-full h-2.5 mb-6"><div class="bg-indigo-600 h-2.5 rounded-full transition-all duration-300" style="width: ${progress}%"></div></div><div class="mb-8 text-center"><span class="text-xs font-bold text-indigo-500 uppercase tracking-wide">سوال ${appState.currentQuestionIndex + 1} از ${questions.length}</span><h2 class="text-2xl font-bold mt-3 text-gray-800 leading-relaxed">${q.text}</h2></div><div class="space-y-4">${q.options.map(opt => `<button onclick='answerQuestion(${JSON.stringify(opt.score)})' class="option-btn w-full text-right p-4 border-2 border-gray-200 rounded-xl hover:border-indigo-500 hover:bg-indigo-50 transition duration-200 group"><div class="flex items-center gap-4"><div class="w-6 h-6 rounded-full border-2 border-gray-300 group-hover:border-indigo-500 flex-shrink-0"></div><span class="text-lg font-medium text-gray-700 group-hover:text-indigo-700">${opt.text}</span></div></button>`).join('')}</div></div>`;
} else if (viewName === 'result') {
const typeCode = appState.lastResultType;
const typeInfo = personalityTypes[typeCode];
app.innerHTML = `<div class="fade-in space-y-8"><div class="bg-white rounded-xl shadow-lg overflow-hidden text-center relative"><div class="bg-indigo-700 h-32 absolute w-full top-0 left-0"></div><div class="relative pt-12 pb-8 px-4"><div class="w-32 h-32 bg-white rounded-full flex items-center justify-center text-4xl font-black text-indigo-700 mx-auto shadow-xl border-4 border-white mb-4">${typeCode}</div><h1 class="text-3xl font-bold text-gray-800">${typeInfo.title}</h1><p class="text-gray-600 mt-2 max-w-lg mx-auto text-lg">${typeInfo.desc}</p></div></div><div class="grid md:grid-cols-2 gap-6"><div class="bg-white rounded-xl shadow p-6 border-t-4 border-green-500"><h3 class="font-bold text-xl mb-4 flex items-center gap-2">شغلهای مناسب شما</h3><div class="flex flex-wrap gap-2">${typeInfo.careers.map(c => `<span class="bg-green-100 text-green-800 px-3 py-1 rounded-full text-sm font-medium">${c}</span>`).join('')}</div></div><div class="bg-white rounded-xl shadow p-6 border-t-4 border-purple-500"><h3 class="font-bold text-xl mb-4 flex items-center gap-2">افراد مشهور همتیپ شما</h3><ul class="space-y-2">${typeInfo.famous.map(p => { const [name, role] = p.split('('); return `<li class="flex justify-between items-center text-sm border-b border-gray-100 last:border-0 pb-1 last:pb-0"><span class="font-medium text-gray-800">${name}</span><span class="text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded">${role ? role.replace(')', '') : ''}</span></li>` }).join('')}</ul></div></div><div class="text-center pt-4 pb-8"><button onclick="renderView('dashboard')" class="bg-gray-800 text-white px-8 py-3 rounded-lg hover:bg-gray-900 transition font-bold shadow-lg">بازگشت به پروفایل</button></div></div>`;
}
}
function previewImage(input) { if (input.files && input.files[0]) { const reader = new FileReader(); reader.onload = function(e) { document.getElementById('image-preview').innerHTML = `<img src="${e.target.result}" class="w-full h-full object-cover">`; }; reader.readAsDataURL(input.files[0]); } }
document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>