Files
soroush.asadi 96e73bf633
CI/CD / CI · dotnet build (push) Failing after 0s
CI/CD / Deploy · drsousan (push) Has been skipped
first commit
2026-05-31 00:42:08 +03:30

916 lines
56 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title>پنل مدیریت | دکتر سوسن آل‌طه</title>
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;600;700&display=swap" onload="this.rel='stylesheet'"/>
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
--gold:#B8955A;--gold-l:#D4B483;--gold-pale:#F5ECD8;
--bg:#F4F6F8;--white:#fff;--dark:#1E1E1E;--mid:#5A5A5A;
--light:#9A9A9A;--border:#E2E8F0;--danger:#E53935;--success:#2E7D32;
--sidebar:240px;
}
body{font-family:'Vazirmatn',Tahoma,sans-serif;background:var(--bg);color:var(--dark);direction:rtl;display:flex;min-height:100vh}
/* ── Sidebar ── */
.sidebar{width:var(--sidebar);background:var(--dark);color:#fff;display:flex;flex-direction:column;flex-shrink:0;position:fixed;top:0;right:0;bottom:0;z-index:50}
.sidebar-logo{padding:1.5rem 1.2rem;border-bottom:1px solid rgba(255,255,255,.08);font-size:.9rem;font-weight:600;color:var(--gold-l);line-height:1.4}
.sidebar-logo span{display:block;font-size:.7rem;color:rgba(255,255,255,.4);font-weight:400;margin-top:.2rem}
nav.sidebar-nav{flex:1;overflow-y:auto;padding:.8rem 0}
.nav-section{font-size:.65rem;font-weight:600;letter-spacing:.08em;color:rgba(255,255,255,.3);padding:.8rem 1.2rem .3rem;text-transform:uppercase}
.nav-item{display:flex;align-items:center;gap:.7rem;padding:.65rem 1.2rem;color:rgba(255,255,255,.65);cursor:pointer;font-size:.85rem;transition:background .2s,color .2s;border-right:3px solid transparent}
.nav-item:hover{background:rgba(255,255,255,.05);color:#fff}
.nav-item.active{background:rgba(184,149,90,.12);color:var(--gold-l);border-right-color:var(--gold)}
.nav-item svg{width:16px;height:16px;flex-shrink:0;opacity:.7}
.nav-item.active svg{opacity:1}
.sidebar-footer{padding:1rem 1.2rem;border-top:1px solid rgba(255,255,255,.08);font-size:.75rem;color:rgba(255,255,255,.35)}
/* ── Main ── */
.main{margin-right:var(--sidebar);flex:1;display:flex;flex-direction:column;min-height:100vh}
.topbar{background:var(--white);border-bottom:1px solid var(--border);padding:.75rem 2rem;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:40}
.topbar-title{font-size:1rem;font-weight:600;color:var(--dark)}
.topbar-actions{display:flex;gap:.7rem;align-items:center}
.page-content{padding:2rem;flex:1}
/* ── Cards ── */
.stat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1.2rem;margin-bottom:2rem}
.stat-card{background:var(--white);border-radius:14px;padding:1.4rem 1.6rem;border:1px solid var(--border);display:flex;flex-direction:column;gap:.4rem}
.stat-card .label{font-size:.78rem;color:var(--light)}
.stat-card .value{font-size:2rem;font-weight:700;color:var(--dark)}
.stat-card .icon{width:38px;height:38px;border-radius:10px;background:var(--gold-pale);display:flex;align-items:center;justify-content:center;margin-bottom:.4rem}
.stat-card .icon svg{width:18px;height:18px;color:var(--gold)}
.card{background:var(--white);border-radius:14px;border:1px solid var(--border);overflow:hidden;margin-bottom:1.5rem}
.card-header{padding:1.2rem 1.5rem;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between}
.card-title{font-size:.95rem;font-weight:600}
.card-body{padding:1.5rem}
/* ── Buttons ── */
.btn{display:inline-flex;align-items:center;gap:.4rem;padding:.55rem 1.1rem;border-radius:8px;font-family:inherit;font-size:.85rem;font-weight:500;cursor:pointer;border:1.5px solid transparent;transition:all .2s}
.btn-primary{background:var(--gold);color:#fff;border-color:var(--gold)}
.btn-primary:hover{background:var(--gold-l)}
.btn-secondary{background:transparent;color:var(--mid);border-color:var(--border)}
.btn-secondary:hover{border-color:var(--gold);color:var(--gold)}
.btn-danger{background:transparent;color:var(--danger);border-color:var(--danger)}
.btn-danger:hover{background:var(--danger);color:#fff}
.btn-sm{padding:.35rem .7rem;font-size:.78rem}
.btn svg{width:15px;height:15px}
/* ── Table ── */
.table-wrap{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:.85rem}
th{background:#F8FAFC;padding:.75rem 1rem;text-align:right;font-weight:600;color:var(--mid);font-size:.78rem;border-bottom:1px solid var(--border)}
td{padding:.75rem 1rem;border-bottom:1px solid var(--border);color:var(--dark);vertical-align:middle}
tr:last-child td{border-bottom:none}
tr:hover td{background:#FAFBFC}
.badge{display:inline-flex;align-items:center;padding:.2rem .65rem;border-radius:50px;font-size:.72rem;font-weight:600}
.badge-green{background:#E8F5E9;color:#2E7D32}
.badge-red{background:#FFEBEE;color:#C62828}
.badge-gold{background:var(--gold-pale);color:var(--gold)}
/* ── Forms ── */
.form-grid{display:grid;gap:1rem}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
.form-group{display:flex;flex-direction:column;gap:.35rem}
.form-group label{font-size:.82rem;font-weight:500;color:var(--dark)}
.form-group input,.form-group select,.form-group textarea{
border:1.5px solid var(--border);border-radius:8px;padding:.65rem .9rem;
font-family:inherit;font-size:.88rem;color:var(--dark);direction:rtl;
transition:border-color .2s,box-shadow .2s;outline:none;background:var(--white)
}
.form-group input:focus,.form-group select:focus,.form-group textarea:focus{border-color:var(--gold);box-shadow:0 0 0 3px rgba(184,149,90,.1)}
.form-group textarea{resize:vertical;min-height:100px}
.form-hint{font-size:.72rem;color:var(--light);margin-top:.2rem}
.seo-score{display:flex;align-items:center;gap:.5rem;padding:.6rem 1rem;border-radius:8px;font-size:.8rem}
.seo-score.good{background:#E8F5E9;color:#2E7D32}
.seo-score.ok{background:#FFF3E0;color:#E65100}
.seo-score.bad{background:#FFEBEE;color:#C62828}
/* ── Modal ── */
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:200;display:flex;align-items:center;justify-content:center;padding:1rem}
.modal-overlay.hidden{display:none}
.modal{background:var(--white);border-radius:16px;width:100%;max-width:720px;max-height:90vh;overflow-y:auto}
.modal-header{padding:1.2rem 1.5rem;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;background:var(--white);z-index:1}
.modal-title{font-size:1rem;font-weight:600}
.modal-close{background:none;border:none;cursor:pointer;padding:.4rem;color:var(--light)}
.modal-body{padding:1.5rem}
.modal-footer{padding:1rem 1.5rem;border-top:1px solid var(--border);display:flex;gap:.7rem;justify-content:flex-start}
/* ── Toast ── */
.toast-container{position:fixed;bottom:1.5rem;left:1.5rem;z-index:300;display:flex;flex-direction:column;gap:.5rem}
.toast{background:var(--dark);color:#fff;padding:.7rem 1.2rem;border-radius:10px;font-size:.85rem;animation:slideIn .3s ease;box-shadow:0 4px 20px rgba(0,0,0,.2)}
.toast.success{border-left:4px solid #4CAF50}
.toast.error{border-left:4px solid var(--danger)}
@keyframes slideIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}
/* ── Rich text editor minimal ── */
.editor-toolbar{border:1.5px solid var(--border);border-bottom:none;border-radius:8px 8px 0 0;padding:.4rem .6rem;display:flex;gap:.3rem;flex-wrap:wrap;background:#F8FAFC}
.editor-toolbar button{background:none;border:none;padding:.3rem .5rem;border-radius:4px;cursor:pointer;font-size:.82rem;font-family:inherit;color:var(--mid)}
.editor-toolbar button:hover{background:var(--gold-pale);color:var(--gold)}
.editor-content{border:1.5px solid var(--border);border-radius:0 0 8px 8px;padding:.8rem 1rem;min-height:250px;outline:none;font-size:.9rem;line-height:1.8;direction:rtl}
/* ── Pages ── */
.page{display:none}
.page.active{display:block}
/* ── Login ── */
.login-screen{position:fixed;inset:0;background:var(--dark);display:flex;align-items:center;justify-content:center;z-index:1000}
.login-box{background:var(--white);border-radius:20px;padding:2.5rem;width:380px;text-align:center}
.login-logo{font-size:1.1rem;font-weight:700;color:var(--gold);margin-bottom:.3rem}
.login-sub{font-size:.8rem;color:var(--light);margin-bottom:2rem}
.login-screen.hidden{display:none}
</style>
</head>
<body>
<!-- ══ LOGIN ══ -->
<div class="login-screen" id="loginScreen">
<div class="login-box">
<div class="login-logo">دکتر سوسن آل‌طه</div>
<div class="login-sub">پنل مدیریت محتوا</div>
<div class="form-group" style="margin-bottom:1rem">
<label>نام کاربری</label>
<input type="text" id="loginUser" value="admin" placeholder="نام کاربری"/>
</div>
<div class="form-group" style="margin-bottom:1.5rem">
<label>رمز عبور</label>
<input type="password" id="loginPass" value="admin123" placeholder="رمز عبور"/>
</div>
<button class="btn btn-primary" style="width:100%;justify-content:center" onclick="doLogin()">ورود به پنل</button>
<p id="loginErr" style="color:var(--danger);font-size:.8rem;margin-top:.8rem;display:none">نام کاربری یا رمز عبور اشتباه است</p>
</div>
</div>
<!-- ══ SIDEBAR ══ -->
<aside class="sidebar">
<div class="sidebar-logo">مدیریت سایت<span>دکتر سوسن آل‌طه</span></div>
<nav class="sidebar-nav">
<div class="nav-section">داشبورد</div>
<div class="nav-item active" onclick="showPage('dashboard',this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
داشبورد
</div>
<div class="nav-section">محتوای سایت</div>
<div class="nav-item" onclick="showPage('hero',this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>
صفحه اصلی (هرو)
</div>
<div class="nav-item" onclick="showPage('about',this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 3.6-7 8-7s8 3 8 7"/></svg>
درباره من
</div>
<div class="nav-item" onclick="showPage('contact',this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.69 13.6a19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 3.6 3h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L7.91 10.6a16 16 0 0 0 6 6l.91-.91a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
اطلاعات تماس
</div>
<div class="nav-section">بخش‌های سایت</div>
<div class="nav-item" onclick="showPage('services',this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/></svg>
خدمات
</div>
<div class="nav-item" onclick="showPage('gallery',this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
گالری
</div>
<div class="nav-item" onclick="showPage('testimonials',this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
نظرات بیماران
</div>
<div class="nav-section">وبلاگ و SEO</div>
<div class="nav-item" onclick="showPage('blogposts',this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
مقالات
</div>
<div class="nav-item" onclick="showPage('categories',this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
دسته‌بندی‌ها
</div>
<div class="nav-item" onclick="showPage('seo',this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
گزارش SEO
</div>
</nav>
<div class="sidebar-footer">API: <span id="apiLabel">localhost:5000</span></div>
</aside>
<!-- ══ MAIN ══ -->
<div class="main">
<div class="topbar">
<div class="topbar-title" id="pageTitle">داشبورد</div>
<div class="topbar-actions">
<a href="../index.html" target="_blank" class="btn btn-secondary btn-sm">مشاهده سایت</a>
<button class="btn btn-danger btn-sm" onclick="logout()">خروج</button>
</div>
</div>
<div class="page-content">
<!-- ── DASHBOARD ── -->
<div class="page active" id="page-dashboard">
<div class="stat-grid" id="dashStats">
<div class="stat-card"><div class="icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg></div><div class="label">مقالات منتشرشده</div><div class="value" id="ds-posts">-</div></div>
<div class="stat-card"><div class="icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></div><div class="label">کل بازدید مقالات</div><div class="value" id="ds-views">-</div></div>
<div class="stat-card"><div class="icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg></div><div class="label">نظرات بیماران</div><div class="value" id="ds-testimonials">-</div></div>
<div class="stat-card"><div class="icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/></svg></div><div class="label">مقالات بدون متا</div><div class="value" id="ds-nometa" style="color:var(--danger)">-</div></div>
</div>
<div class="card">
<div class="card-header"><div class="card-title">پربازدیدترین مقالات</div></div>
<div class="table-wrap"><table><thead><tr><th>عنوان</th><th>بازدید</th><th>عملیات</th></tr></thead><tbody id="topPostsTable"></tbody></table></div>
</div>
</div>
<!-- ── HERO ── -->
<div class="page" id="page-hero">
<div class="card">
<div class="card-header"><div class="card-title">ویرایش بخش هرو</div></div>
<div class="card-body">
<div class="form-grid">
<div class="form-row">
<div class="form-group"><label>نام دکتر</label><input id="hero-name"/></div>
<div class="form-group"><label>تخصص (زیر نام)</label><input id="hero-title"/></div>
</div>
<div class="form-group"><label>توضیح کوتاه</label><textarea id="hero-subtitle" rows="2"></textarea></div>
<div class="form-row">
<div class="form-group"><label>آمار ۱ - عدد</label><input id="hero-stat1_num"/></div>
<div class="form-group"><label>آمار ۱ - برچسب</label><input id="hero-stat1_lbl"/></div>
</div>
<div class="form-row">
<div class="form-group"><label>آمار ۲ - عدد</label><input id="hero-stat2_num"/></div>
<div class="form-group"><label>آمار ۲ - برچسب</label><input id="hero-stat2_lbl"/></div>
</div>
<div class="form-row">
<div class="form-group"><label>آمار ۳ - عدد</label><input id="hero-stat3_num"/></div>
<div class="form-group"><label>آمار ۳ - برچسب</label><input id="hero-stat3_lbl"/></div>
</div>
<div class="form-row">
<div class="form-group"><label>دکمه اصلی</label><input id="hero-cta_primary"/></div>
<div class="form-group"><label>دکمه ثانویه</label><input id="hero-cta_secondary"/></div>
</div>
</div>
<div style="margin-top:1.5rem"><button class="btn btn-primary" onclick="saveSection('hero')">ذخیره تغییرات</button></div>
</div>
</div>
</div>
<!-- ── ABOUT ── -->
<div class="page" id="page-about">
<div class="card">
<div class="card-header"><div class="card-title">ویرایش بخش درباره من</div></div>
<div class="card-body">
<div class="form-grid">
<div class="form-row">
<div class="form-group"><label>عنوان</label><input id="about-title"/></div>
<div class="form-group"><label>سال‌های تجربه</label><input id="about-years_exp"/></div>
</div>
<div class="form-group"><label>بیوگرافی</label><textarea id="about-bio" rows="4"></textarea></div>
<div class="form-group"><label>دستاورد ۱</label><input id="about-cred1"/></div>
<div class="form-group"><label>دستاورد ۲</label><input id="about-cred2"/></div>
<div class="form-group"><label>دستاورد ۳</label><input id="about-cred3"/></div>
<div class="form-group"><label>دستاورد ۴</label><input id="about-cred4"/></div>
<div class="form-group"><label>دستاورد ۵</label><input id="about-cred5"/></div>
</div>
<div style="margin-top:1.5rem"><button class="btn btn-primary" onclick="saveSection('about')">ذخیره تغییرات</button></div>
</div>
</div>
</div>
<!-- ── CONTACT ── -->
<div class="page" id="page-contact">
<div class="card">
<div class="card-header"><div class="card-title">اطلاعات تماس</div></div>
<div class="card-body">
<div class="form-grid">
<div class="form-row">
<div class="form-group"><label>تلفن</label><input id="contact-phone"/></div>
<div class="form-group"><label>ایمیل</label><input id="contact-email"/></div>
</div>
<div class="form-group"><label>آدرس</label><input id="contact-address"/></div>
<div class="form-group"><label>ساعات کاری</label><input id="contact-hours"/></div>
<div class="form-row">
<div class="form-group"><label>لینک اینستاگرام</label><input id="contact-instagram" dir="ltr"/></div>
<div class="form-group"><label>لینک واتساپ</label><input id="contact-whatsapp" dir="ltr"/></div>
</div>
<div class="form-group"><label>لینک تلگرام</label><input id="contact-telegram" dir="ltr"/></div>
</div>
<div style="margin-top:1.5rem"><button class="btn btn-primary" onclick="saveSection('contact')">ذخیره تغییرات</button></div>
</div>
</div>
</div>
<!-- ── SERVICES ── -->
<div class="page" id="page-services">
<div class="card">
<div class="card-header">
<div class="card-title">خدمات</div>
<button class="btn btn-primary btn-sm" onclick="openSvcModal()">+ افزودن خدمت</button>
</div>
<div class="table-wrap">
<table><thead><tr><th>#</th><th>عنوان</th><th>توضیح</th><th>وضعیت</th><th>عملیات</th></tr></thead>
<tbody id="servicesTable"></tbody></table>
</div>
</div>
</div>
<!-- ── GALLERY ── -->
<div class="page" id="page-gallery">
<div class="card">
<div class="card-header">
<div class="card-title">گالری</div>
<button class="btn btn-primary btn-sm" onclick="openGalleryModal()">+ افزودن تصویر</button>
</div>
<div class="table-wrap">
<table><thead><tr><th>دسته</th><th>توضیح</th><th>وضعیت</th><th>عملیات</th></tr></thead>
<tbody id="galleryTable"></tbody></table>
</div>
</div>
</div>
<!-- ── TESTIMONIALS ── -->
<div class="page" id="page-testimonials">
<div class="card">
<div class="card-header">
<div class="card-title">نظرات بیماران</div>
<button class="btn btn-primary btn-sm" onclick="openTestimModal()">+ افزودن نظر</button>
</div>
<div class="table-wrap">
<table><thead><tr><th>نام</th><th>متن</th><th>امتیاز</th><th>وضعیت</th><th>عملیات</th></tr></thead>
<tbody id="testimonialsTable"></tbody></table>
</div>
</div>
</div>
<!-- ── BLOG POSTS ── -->
<div class="page" id="page-blogposts">
<div class="card">
<div class="card-header">
<div class="card-title">مقالات وبلاگ</div>
<button class="btn btn-primary btn-sm" onclick="openPostEditor()">+ مقاله جدید</button>
</div>
<div class="table-wrap">
<table><thead><tr><th>عنوان</th><th>دسته</th><th>کلیدواژه</th><th>بازدید</th><th>وضعیت</th><th>عملیات</th></tr></thead>
<tbody id="postsTable"></tbody></table>
</div>
</div>
</div>
<!-- ── CATEGORIES ── -->
<div class="page" id="page-categories">
<div class="card">
<div class="card-header">
<div class="card-title">دسته‌بندی‌ها</div>
<button class="btn btn-primary btn-sm" onclick="openCatModal()">+ دسته جدید</button>
</div>
<div class="table-wrap">
<table><thead><tr><th>نام</th><th>اسلاگ</th><th>مقالات</th><th>عملیات</th></tr></thead>
<tbody id="categoriesTable"></tbody></table>
</div>
</div>
</div>
<!-- ── SEO ── -->
<div class="page" id="page-seo">
<div class="stat-grid" style="grid-template-columns:repeat(3,1fr)">
<div class="stat-card"><div class="label">مقالات منتشرشده</div><div class="value" id="seo-posts">-</div></div>
<div class="stat-card"><div class="label">کل بازدید</div><div class="value" id="seo-views">-</div></div>
<div class="stat-card"><div class="label">مقالات بدون متا</div><div class="value" id="seo-nometa" style="color:var(--danger)">-</div></div>
</div>
<div class="card">
<div class="card-header"><div class="card-title">پربازدیدترین مقالات</div></div>
<div class="table-wrap"><table><thead><tr><th>عنوان</th><th>بازدید</th></tr></thead><tbody id="seoTopPosts"></tbody></table></div>
</div>
<div class="card">
<div class="card-header"><div class="card-title">راهنمای بهبود SEO</div></div>
<div class="card-body" style="font-size:.88rem;line-height:2;color:var(--mid)">
<p>✅ هر مقاله باید <strong>MetaTitle</strong> زیر ۷۰ کاراکتر داشته باشد</p>
<p><strong>MetaDescription</strong> بین ۱۵۰-۱۶۰ کاراکتر</p>
<p><strong>کلیدواژه اصلی</strong> در عنوان، اول پاراگراف و URL وجود داشته باشد</p>
<p>✅ هر مقاله حداقل <strong>۵۰۰ کلمه</strong> داشته باشد</p>
<p>✅ از <strong>H2 و H3</strong> در ساختار مقاله استفاده کنید</p>
<p>✅ لینک‌دهی داخلی بین مقالات انجام دهید</p>
<p>✅ تصاویر دارای <strong>alt text</strong> فارسی باشند</p>
<p>🔗 <a href="../sitemap.xml" target="_blank" style="color:var(--gold)">مشاهده Sitemap</a> | <a href="../robots.txt" target="_blank" style="color:var(--gold)">مشاهده Robots.txt</a></p>
</div>
</div>
</div>
</div><!-- /page-content -->
</div><!-- /main -->
<!-- ══ MODALS ══ -->
<!-- Service Modal -->
<div class="modal-overlay hidden" id="svcModal">
<div class="modal">
<div class="modal-header"><div class="modal-title" id="svcModalTitle">افزودن خدمت</div><button class="modal-close" onclick="closeModal('svcModal')"></button></div>
<div class="modal-body">
<input type="hidden" id="svc-id"/>
<div class="form-grid">
<div class="form-group"><label>عنوان</label><input id="svc-title"/></div>
<div class="form-group"><label>توضیح</label><textarea id="svc-desc" rows="3"></textarea></div>
<div class="form-row">
<div class="form-group"><label>ترتیب</label><input type="number" id="svc-order" value="1"/></div>
<div class="form-group"><label>وضعیت</label><select id="svc-active"><option value="true">فعال</option><option value="false">غیرفعال</option></select></div>
</div>
</div>
</div>
<div class="modal-footer"><button class="btn btn-primary" onclick="saveSvc()">ذخیره</button><button class="btn btn-secondary" onclick="closeModal('svcModal')">انصراف</button></div>
</div>
</div>
<!-- Gallery Modal -->
<div class="modal-overlay hidden" id="galleryModal">
<div class="modal">
<div class="modal-header"><div class="modal-title" id="galleryModalTitle">افزودن تصویر</div><button class="modal-close" onclick="closeModal('galleryModal')"></button></div>
<div class="modal-body">
<input type="hidden" id="gal-id"/>
<div class="form-grid">
<div class="form-group"><label>آدرس تصویر اصلی</label><input id="gal-img" dir="ltr" placeholder="https://..."/></div>
<div class="form-row">
<div class="form-group"><label>آدرس تصویر قبل</label><input id="gal-before" dir="ltr" placeholder="https://..."/></div>
<div class="form-group"><label>آدرس تصویر بعد</label><input id="gal-after" dir="ltr" placeholder="https://..."/></div>
</div>
<div class="form-row">
<div class="form-group"><label>دسته‌بندی</label><input id="gal-cat" placeholder="بوتاکس، لیزر..."/></div>
<div class="form-group"><label>ترتیب</label><input type="number" id="gal-order" value="1"/></div>
</div>
<div class="form-group"><label>توضیح</label><input id="gal-caption"/></div>
<div class="form-group"><label>وضعیت</label><select id="gal-active"><option value="true">فعال</option><option value="false">غیرفعال</option></select></div>
</div>
</div>
<div class="modal-footer"><button class="btn btn-primary" onclick="saveGallery()">ذخیره</button><button class="btn btn-secondary" onclick="closeModal('galleryModal')">انصراف</button></div>
</div>
</div>
<!-- Testimonial Modal -->
<div class="modal-overlay hidden" id="testimModal">
<div class="modal">
<div class="modal-header"><div class="modal-title">افزودن / ویرایش نظر</div><button class="modal-close" onclick="closeModal('testimModal')"></button></div>
<div class="modal-body">
<input type="hidden" id="testim-id"/>
<div class="form-grid">
<div class="form-row">
<div class="form-group"><label>نام</label><input id="testim-name"/></div>
<div class="form-group"><label>ایموجی</label><input id="testim-emoji" value="👩"/></div>
</div>
<div class="form-group"><label>متن نظر</label><textarea id="testim-text" rows="3"></textarea></div>
<div class="form-row">
<div class="form-group"><label>امتیاز (۱-۵)</label><input type="number" id="testim-rating" value="5" min="1" max="5"/></div>
<div class="form-group"><label>تاریخ</label><input id="testim-date" placeholder="اردیبهشت ۱۴۰۳"/></div>
</div>
<div class="form-group"><label>وضعیت</label><select id="testim-active"><option value="true">فعال</option><option value="false">غیرفعال</option></select></div>
</div>
</div>
<div class="modal-footer"><button class="btn btn-primary" onclick="saveTestim()">ذخیره</button><button class="btn btn-secondary" onclick="closeModal('testimModal')">انصراف</button></div>
</div>
</div>
<!-- Category Modal -->
<div class="modal-overlay hidden" id="catModal">
<div class="modal" style="max-width:480px">
<div class="modal-header"><div class="modal-title" id="catModalTitle">دسته جدید</div><button class="modal-close" onclick="closeModal('catModal')"></button></div>
<div class="modal-body">
<input type="hidden" id="cat-id"/>
<div class="form-grid">
<div class="form-group"><label>نام</label><input id="cat-name"/></div>
<div class="form-group"><label>اسلاگ (خودکار)</label><input id="cat-slug" dir="ltr" placeholder="auto-generated"/></div>
<div class="form-group"><label>توضیح</label><textarea id="cat-desc" rows="2"></textarea></div>
</div>
</div>
<div class="modal-footer"><button class="btn btn-primary" onclick="saveCat()">ذخیره</button><button class="btn btn-secondary" onclick="closeModal('catModal')">انصراف</button></div>
</div>
</div>
<!-- Blog Post Editor Modal -->
<div class="modal-overlay hidden" id="postModal">
<div class="modal" style="max-width:900px">
<div class="modal-header"><div class="modal-title" id="postModalTitle">مقاله جدید</div><button class="modal-close" onclick="closeModal('postModal')"></button></div>
<div class="modal-body">
<input type="hidden" id="post-id"/>
<div class="form-grid">
<div class="form-group"><label>عنوان مقاله</label><input id="post-title" oninput="autoSlug()"/></div>
<div class="form-row">
<div class="form-group"><label>اسلاگ (URL)</label><input id="post-slug" dir="ltr"/></div>
<div class="form-group"><label>دسته‌بندی</label><select id="post-category"><option value="">انتخاب دسته...</option></select></div>
</div>
<div class="form-group"><label>خلاصه (Excerpt)</label><textarea id="post-excerpt" rows="2"></textarea></div>
<div class="form-group">
<label>محتوای مقاله</label>
<div class="editor-toolbar">
<button onclick="fmt('bold')"><b>B</b></button>
<button onclick="fmt('italic')"><i>I</i></button>
<button onclick="fmtBlock('h2')">H2</button>
<button onclick="fmtBlock('h3')">H3</button>
<button onclick="fmtBlock('p')">P</button>
<button onclick="fmt('insertUnorderedList')">• لیست</button>
<button onclick="fmt('insertOrderedList')">۱. لیست</button>
<button onclick="insLink()">🔗 لینک</button>
</div>
<div class="editor-content" id="post-content" contenteditable="true" dir="rtl"></div>
</div>
<div style="border-top:1px solid var(--border);padding-top:1rem;margin-top:.5rem">
<p style="font-size:.82rem;font-weight:600;color:var(--gold);margin-bottom:1rem">تنظیمات SEO</p>
<div class="form-group"><label>کلیدواژه اصلی (Focus Keyword)</label><input id="post-focus" oninput="checkSeo()"/><div class="form-hint">کلیدواژه‌ای که می‌خواهید برای آن رتبه بگیرید</div></div>
<div id="seoFeedback" style="margin:.5rem 0"></div>
<div class="form-group"><label>Meta Title <span style="font-weight:400;color:var(--light)" id="mtLen">(0/70)</span></label><input id="post-metatitle" oninput="updateLen('post-metatitle','mtLen',70)"/></div>
<div class="form-group"><label>Meta Description <span style="font-weight:400;color:var(--light)" id="mdLen">(0/160)</span></label><textarea id="post-metadesc" rows="2" oninput="updateLen('post-metadesc','mdLen',160)"></textarea></div>
<div class="form-group"><label>کلیدواژه‌ها (با کاما جدا کنید)</label><input id="post-keywords" placeholder="بوتاکس, جوانسازی, پوست..."/></div>
<div class="form-group"><label>تصویر شاخص</label><input id="post-image" dir="ltr" placeholder="https://..."/></div>
<div class="form-row">
<div class="form-group"><label>نوع Schema</label><select id="post-schematype"><option value="MedicalWebPage">MedicalWebPage</option><option value="Article">Article</option><option value="FAQPage">FAQPage</option></select></div>
<div class="form-group"><label>وضعیت انتشار</label><select id="post-published"><option value="false">پیش‌نویس</option><option value="true">منتشر</option></select></div>
</div>
</div>
</div>
</div>
<div class="modal-footer"><button class="btn btn-primary" onclick="savePost()">ذخیره مقاله</button><button class="btn btn-secondary" onclick="closeModal('postModal')">انصراف</button></div>
</div>
</div>
<!-- Toast container -->
<div class="toast-container" id="toastContainer"></div>
<script>
const API = 'http://localhost:5000';
let token = localStorage.getItem('dr_token') || '';
// ── Auth ──────────────────────────────────────────────────────────────────────
async function doLogin() {
const u = document.getElementById('loginUser').value;
const p = document.getElementById('loginPass').value;
const r = await fetch(`${API}/api/auth/login`, {
method:'POST', headers:{'Content-Type':'application/json'},
body: JSON.stringify({username:u, password:p})
});
if (!r.ok) { document.getElementById('loginErr').style.display='block'; return; }
const d = await r.json();
token = d.token;
localStorage.setItem('dr_token', token);
document.getElementById('loginScreen').classList.add('hidden');
init();
}
function logout() {
localStorage.removeItem('dr_token');
location.reload();
}
// ── API helper ────────────────────────────────────────────────────────────────
async function api(path, opts={}) {
const h = {'Content-Type':'application/json'};
if (token) h['Authorization'] = `Bearer ${token}`;
const r = await fetch(`${API}${path}`, {...opts, headers:{...h, ...(opts.headers||{})}});
if (r.status === 401) { logout(); return null; }
if (r.status === 204) return null;
if (!r.ok) { toast('خطا در سرور: ' + r.status, 'error'); return null; }
return r.json().catch(()=>null);
}
function toast(msg, type='success') {
const c = document.getElementById('toastContainer');
const el = document.createElement('div');
el.className = `toast ${type}`;
el.textContent = msg;
c.appendChild(el);
setTimeout(()=>el.remove(), 3500);
}
// ── Navigation ────────────────────────────────────────────────────────────────
const pageTitles = {dashboard:'داشبورد',hero:'صفحه اصلی',about:'درباره من',contact:'تماس',services:'خدمات',gallery:'گالری',testimonials:'نظرات',blogposts:'مقالات',categories:'دسته‌بندی‌ها',seo:'گزارش SEO'};
function showPage(name, el) {
document.querySelectorAll('.page').forEach(p=>p.classList.remove('active'));
document.querySelectorAll('.nav-item').forEach(n=>n.classList.remove('active'));
document.getElementById('page-'+name).classList.add('active');
el.classList.add('active');
document.getElementById('pageTitle').textContent = pageTitles[name] || name;
loadPage(name);
}
function loadPage(name) {
if (name==='dashboard') loadDashboard();
else if (name==='hero') loadSection('hero');
else if (name==='about') loadSection('about');
else if (name==='contact') loadSection('contact');
else if (name==='services') loadServices();
else if (name==='gallery') loadGallery();
else if (name==='testimonials') loadTestimonials();
else if (name==='blogposts') loadPosts();
else if (name==='categories') loadCategories();
else if (name==='seo') loadSeo();
}
// ── Dashboard ─────────────────────────────────────────────────────────────────
async function loadDashboard() {
const [seo, testims] = await Promise.all([
api('/api/seo/stats'),
api('/api/testimonials/all')
]);
if (seo) {
document.getElementById('ds-posts').textContent = seo.total;
document.getElementById('ds-views').textContent = seo.views;
document.getElementById('ds-nometa').textContent = seo.noMeta;
const tb = document.getElementById('topPostsTable');
tb.innerHTML = seo.topPosts.map(p=>`<tr><td>${p.title}</td><td><span class="badge badge-gold">${p.viewCount}</span></td><td><a href="../post.html?slug=${p.slug}" target="_blank" class="btn btn-secondary btn-sm">مشاهده</a></td></tr>`).join('');
}
if (testims) document.getElementById('ds-testimonials').textContent = testims.length;
}
// ── Section settings ──────────────────────────────────────────────────────────
async function loadSection(sec) {
const data = await api(`/api/settings/${sec}`);
if (!data) return;
Object.entries(data).forEach(([k,v])=>{
const el = document.getElementById(`${sec}-${k}`);
if (el) el.value = v;
});
}
async function saveSection(sec) {
const inputs = document.querySelectorAll(`[id^="${sec}-"]`);
const settings = {};
inputs.forEach(el=>{
const key = el.id.replace(`${sec}-`,'');
settings[key] = el.value;
});
await api(`/api/settings/${sec}`, {method:'PUT', body:JSON.stringify({settings})});
toast('تغییرات با موفقیت ذخیره شد ✓');
}
// ── Services ──────────────────────────────────────────────────────────────────
let svcs=[];
async function loadServices() {
svcs = await api('/api/services/all') || [];
document.getElementById('servicesTable').innerHTML = svcs.map(s=>`
<tr>
<td>${s.order}</td>
<td><strong>${s.title}</strong></td>
<td style="max-width:300px;color:var(--mid)">${s.description.substring(0,60)}...</td>
<td><span class="badge ${s.isActive?'badge-green':'badge-red'}">${s.isActive?'فعال':'غیرفعال'}</span></td>
<td><button class="btn btn-secondary btn-sm" onclick="editSvc(${s.id})">ویرایش</button> <button class="btn btn-danger btn-sm" onclick="deleteSvc(${s.id})">حذف</button></td>
</tr>`).join('');
}
function openSvcModal(id) {
document.getElementById('svcModalTitle').textContent = 'افزودن خدمت';
document.getElementById('svc-id').value='';
document.getElementById('svc-title').value='';
document.getElementById('svc-desc').value='';
document.getElementById('svc-order').value=svcs.length+1;
document.getElementById('svc-active').value='true';
document.getElementById('svcModal').classList.remove('hidden');
}
function editSvc(id) {
const s = svcs.find(x=>x.id===id);
document.getElementById('svcModalTitle').textContent = 'ویرایش خدمت';
document.getElementById('svc-id').value=s.id;
document.getElementById('svc-title').value=s.title;
document.getElementById('svc-desc').value=s.description;
document.getElementById('svc-order').value=s.order;
document.getElementById('svc-active').value=String(s.isActive);
document.getElementById('svcModal').classList.remove('hidden');
}
async function saveSvc() {
const id = document.getElementById('svc-id').value;
const body = {
title: document.getElementById('svc-title').value,
description: document.getElementById('svc-desc').value,
order: parseInt(document.getElementById('svc-order').value),
isActive: document.getElementById('svc-active').value==='true',
iconSvg:''
};
if (id) await api(`/api/services/${id}`,{method:'PUT',body:JSON.stringify(body)});
else await api('/api/services',{method:'POST',body:JSON.stringify(body)});
closeModal('svcModal');
toast('خدمت ذخیره شد ✓');
loadServices();
}
async function deleteSvc(id) {
if (!confirm('حذف شود؟')) return;
await api(`/api/services/${id}`,{method:'DELETE'});
toast('حذف شد','error');
loadServices();
}
// ── Gallery ───────────────────────────────────────────────────────────────────
let gals=[];
async function loadGallery() {
gals = await api('/api/gallery/all') || [];
document.getElementById('galleryTable').innerHTML = gals.map(g=>`
<tr>
<td><span class="badge badge-gold">${g.category||'—'}</span></td>
<td>${g.caption||'—'}</td>
<td><span class="badge ${g.isActive?'badge-green':'badge-red'}">${g.isActive?'فعال':'غیرفعال'}</span></td>
<td><button class="btn btn-secondary btn-sm" onclick="editGallery(${g.id})">ویرایش</button> <button class="btn btn-danger btn-sm" onclick="deleteGallery(${g.id})">حذف</button></td>
</tr>`).join('');
}
function openGalleryModal() {
['id','img','before','after','cat','caption'].forEach(k=>document.getElementById(`gal-${k}`).value='');
document.getElementById('gal-order').value=gals.length+1;
document.getElementById('gal-active').value='true';
document.getElementById('galleryModal').classList.remove('hidden');
}
function editGallery(id) {
const g=gals.find(x=>x.id===id);
document.getElementById('gal-id').value=g.id;
document.getElementById('gal-img').value=g.imageUrl;
document.getElementById('gal-before').value=g.beforeImageUrl;
document.getElementById('gal-after').value=g.afterImageUrl;
document.getElementById('gal-cat').value=g.category;
document.getElementById('gal-caption').value=g.caption;
document.getElementById('gal-order').value=g.order;
document.getElementById('gal-active').value=String(g.isActive);
document.getElementById('galleryModal').classList.remove('hidden');
}
async function saveGallery() {
const id=document.getElementById('gal-id').value;
const body={imageUrl:document.getElementById('gal-img').value,beforeImageUrl:document.getElementById('gal-before').value,afterImageUrl:document.getElementById('gal-after').value,category:document.getElementById('gal-cat').value,caption:document.getElementById('gal-caption').value,order:parseInt(document.getElementById('gal-order').value),isActive:document.getElementById('gal-active').value==='true'};
if(id) await api(`/api/gallery/${id}`,{method:'PUT',body:JSON.stringify(body)});
else await api('/api/gallery',{method:'POST',body:JSON.stringify(body)});
closeModal('galleryModal'); toast('ذخیره شد ✓'); loadGallery();
}
async function deleteGallery(id){if(!confirm('حذف؟'))return;await api(`/api/gallery/${id}`,{method:'DELETE'});toast('حذف شد','error');loadGallery();}
// ── Testimonials ──────────────────────────────────────────────────────────────
let testims=[];
async function loadTestimonials() {
testims=await api('/api/testimonials/all')||[];
document.getElementById('testimonialsTable').innerHTML=testims.map(t=>`
<tr>
<td>${t.authorEmoji} ${t.authorName}</td>
<td style="max-width:250px">${t.text.substring(0,60)}...</td>
<td>${'★'.repeat(t.rating)}</td>
<td><span class="badge ${t.isActive?'badge-green':'badge-red'}">${t.isActive?'فعال':'غیرفعال'}</span></td>
<td><button class="btn btn-secondary btn-sm" onclick="editTestim(${t.id})">ویرایش</button> <button class="btn btn-danger btn-sm" onclick="deleteTestim(${t.id})">حذف</button></td>
</tr>`).join('');
}
function openTestimModal(){['id','name','emoji','text','date'].forEach(k=>document.getElementById(`testim-${k}`).value='');document.getElementById('testim-emoji').value='👩';document.getElementById('testim-rating').value=5;document.getElementById('testim-active').value='true';document.getElementById('testimModal').classList.remove('hidden');}
function editTestim(id){const t=testims.find(x=>x.id===id);document.getElementById('testim-id').value=t.id;document.getElementById('testim-name').value=t.authorName;document.getElementById('testim-emoji').value=t.authorEmoji;document.getElementById('testim-text').value=t.text;document.getElementById('testim-rating').value=t.rating;document.getElementById('testim-date').value=t.date;document.getElementById('testim-active').value=String(t.isActive);document.getElementById('testimModal').classList.remove('hidden');}
async function saveTestim(){const id=document.getElementById('testim-id').value;const body={authorName:document.getElementById('testim-name').value,authorEmoji:document.getElementById('testim-emoji').value,text:document.getElementById('testim-text').value,rating:parseInt(document.getElementById('testim-rating').value),date:document.getElementById('testim-date').value,isActive:document.getElementById('testim-active').value==='true'};if(id)await api(`/api/testimonials/${id}`,{method:'PUT',body:JSON.stringify(body)});else await api('/api/testimonials',{method:'POST',body:JSON.stringify(body)});closeModal('testimModal');toast('ذخیره شد ✓');loadTestimonials();}
async function deleteTestim(id){if(!confirm('حذف؟'))return;await api(`/api/testimonials/${id}`,{method:'DELETE'});toast('حذف شد','error');loadTestimonials();}
// ── Blog Categories ───────────────────────────────────────────────────────────
let cats=[];
async function loadCategories(){
cats=await api('/api/blog/categories')||[];
document.getElementById('categoriesTable').innerHTML=cats.map(c=>`<tr><td><strong>${c.name}</strong></td><td dir="ltr" style="color:var(--light)">${c.slug}</td><td><span class="badge badge-gold">${c.postCount}</span></td><td><button class="btn btn-secondary btn-sm" onclick="editCat(${c.id})">ویرایش</button> <button class="btn btn-danger btn-sm" onclick="deleteCat(${c.id})">حذف</button></td></tr>`).join('');
}
function openCatModal(){document.getElementById('catModalTitle').textContent='دسته جدید';['id','name','slug','desc'].forEach(k=>document.getElementById(`cat-${k}`).value='');document.getElementById('catModal').classList.remove('hidden');}
function editCat(id){const c=cats.find(x=>x.id===id);document.getElementById('catModalTitle').textContent='ویرایش دسته';document.getElementById('cat-id').value=c.id;document.getElementById('cat-name').value=c.name;document.getElementById('cat-slug').value=c.slug;document.getElementById('cat-desc').value=c.description;document.getElementById('catModal').classList.remove('hidden');}
async function saveCat(){const id=document.getElementById('cat-id').value;const body={name:document.getElementById('cat-name').value,slug:document.getElementById('cat-slug').value,description:document.getElementById('cat-desc').value};if(id)await api(`/api/blog/categories/${id}`,{method:'PUT',body:JSON.stringify(body)});else await api('/api/blog/categories',{method:'POST',body:JSON.stringify(body)});closeModal('catModal');toast('ذخیره شد ✓');loadCategories();}
async function deleteCat(id){if(!confirm('حذف؟'))return;await api(`/api/blog/categories/${id}`,{method:'DELETE'});toast('حذف شد','error');loadCategories();}
// ── Blog Posts ────────────────────────────────────────────────────────────────
let posts=[];
async function loadPosts(){
posts=await api('/api/blog/posts/admin')||[];
document.getElementById('postsTable').innerHTML=posts.map(p=>`
<tr>
<td><strong>${p.title}</strong></td>
<td><span class="badge badge-gold">${p.category?.name||'—'}</span></td>
<td style="color:var(--gold);font-size:.8rem">${p.focusKeyword||'—'}</td>
<td>${p.viewCount}</td>
<td><span class="badge ${p.isPublished?'badge-green':'badge-red'}">${p.isPublished?'منتشر':'پیش‌نویس'}</span></td>
<td>
<button class="btn btn-secondary btn-sm" onclick="editPost(${p.id})">ویرایش</button>
<a href="../post.html?slug=${p.slug}" target="_blank" class="btn btn-secondary btn-sm">مشاهده</a>
<button class="btn btn-danger btn-sm" onclick="deletePost(${p.id})">حذف</button>
</td>
</tr>`).join('');
}
async function openPostEditor(){
if(!cats.length) await loadCategories();
const catSel=document.getElementById('post-category');
catSel.innerHTML='<option value="">انتخاب دسته...</option>'+cats.map(c=>`<option value="${c.id}">${c.name}</option>`).join('');
document.getElementById('postModalTitle').textContent='مقاله جدید';
['id','title','slug','focus','metatitle','metadesc','keywords','image'].forEach(k=>document.getElementById(`post-${k}`).value='');
document.getElementById('post-content').innerHTML='';
document.getElementById('post-excerpt').value='';
document.getElementById('post-published').value='false';
document.getElementById('post-schematype').value='MedicalWebPage';
document.getElementById('post-category').value='';
updateLen('post-metatitle','mtLen',70);
updateLen('post-metadesc','mdLen',160);
document.getElementById('postModal').classList.remove('hidden');
}
async function editPost(id){
await openPostEditor();
const p=await api(`/api/blog/posts/id/${id}`);
if(!p)return;
document.getElementById('postModalTitle').textContent='ویرایش مقاله';
document.getElementById('post-id').value=p.id;
document.getElementById('post-title').value=p.title;
document.getElementById('post-slug').value=p.slug;
document.getElementById('post-excerpt').value=p.excerpt;
document.getElementById('post-content').innerHTML=p.content;
document.getElementById('post-focus').value=p.focusKeyword;
document.getElementById('post-metatitle').value=p.metaTitle;
document.getElementById('post-metadesc').value=p.metaDescription;
document.getElementById('post-keywords').value=p.keywords;
document.getElementById('post-image').value=p.featuredImage;
document.getElementById('post-published').value=String(p.isPublished);
document.getElementById('post-schematype').value=p.articleType;
document.getElementById('post-category').value=p.categoryId||'';
updateLen('post-metatitle','mtLen',70);
updateLen('post-metadesc','mdLen',160);
checkSeo();
}
async function savePost(){
const id=document.getElementById('post-id').value;
const catId=document.getElementById('post-category').value;
const body={
title:document.getElementById('post-title').value,
slug:document.getElementById('post-slug').value,
excerpt:document.getElementById('post-excerpt').value,
content:document.getElementById('post-content').innerHTML,
featuredImage:document.getElementById('post-image').value,
author:'دکتر سوسن آل‌طه',
metaTitle:document.getElementById('post-metatitle').value,
metaDescription:document.getElementById('post-metadesc').value,
focusKeyword:document.getElementById('post-focus').value,
keywords:document.getElementById('post-keywords').value,
articleType:document.getElementById('post-schematype').value,
isPublished:document.getElementById('post-published').value==='true',
categoryId:catId?parseInt(catId):null,
ogImage:document.getElementById('post-image').value,
};
if(id) await api(`/api/blog/posts/${id}`,{method:'PUT',body:JSON.stringify(body)});
else await api('/api/blog/posts',{method:'POST',body:JSON.stringify(body)});
closeModal('postModal'); toast('مقاله ذخیره شد ✓'); loadPosts();
}
async function deletePost(id){if(!confirm('حذف مقاله؟'))return;await api(`/api/blog/posts/${id}`,{method:'DELETE'});toast('مقاله حذف شد','error');loadPosts();}
// ── SEO ───────────────────────────────────────────────────────────────────────
async function loadSeo(){
const s=await api('/api/seo/stats');
if(!s)return;
document.getElementById('seo-posts').textContent=s.total;
document.getElementById('seo-views').textContent=s.views;
document.getElementById('seo-nometa').textContent=s.noMeta;
document.getElementById('seoTopPosts').innerHTML=s.topPosts.map(p=>`<tr><td>${p.title}</td><td><span class="badge badge-gold">${p.viewCount}</span></td></tr>`).join('');
}
// ── SEO helpers ───────────────────────────────────────────────────────────────
function autoSlug(){
const t=document.getElementById('post-title').value;
const s=t.trim().replace(/\s+/g,'-').replace(/[^؀-ۿa-z0-9\-]/g,'').toLowerCase();
document.getElementById('post-slug').value=s;
checkSeo();
}
function updateLen(inputId,labelId,max){
const el=document.getElementById(inputId);
const len=el.value.length;
const label=document.getElementById(labelId);
label.textContent=`(${len}/${max})`;
label.style.color=len>max?'var(--danger)':(len>max*.8?'var(--gold)':'var(--light)');
}
function checkSeo(){
const kw=document.getElementById('post-focus').value.trim();
const title=document.getElementById('post-title').value;
const mt=document.getElementById('post-metatitle').value;
const md=document.getElementById('post-metadesc').value;
const fb=document.getElementById('seoFeedback');
if(!kw){fb.innerHTML='';return;}
const checks=[
{ok:title.includes(kw), msg:'کلیدواژه در عنوان'},
{ok:mt.includes(kw), msg:'کلیدواژه در Meta Title'},
{ok:md.includes(kw), msg:'کلیدواژه در Meta Description'},
{ok:mt.length<=70&&mt.length>0, msg:'طول Meta Title مناسب'},
{ok:md.length<=160&&md.length>100, msg:'طول Meta Description مناسب'},
];
const pass=checks.filter(c=>c.ok).length;
const cls=pass>=4?'good':pass>=2?'ok':'bad';
const emoji=pass>=4?'✅':pass>=2?'⚠️':'❌';
fb.innerHTML=`<div class="seo-score ${cls}">${emoji} امتیاز SEO: ${pass}/${checks.length}${checks.map(c=>`<span style="opacity:${c.ok?1:.4}">${c.ok?'✓':'✗'} ${c.msg}</span>`).join(' | ')}</div>`;
}
// ── Editor helpers ────────────────────────────────────────────────────────────
function fmt(cmd){document.getElementById('post-content').focus();document.execCommand(cmd);}
function fmtBlock(tag){document.getElementById('post-content').focus();document.execCommand('formatBlock',false,tag);}
function insLink(){const url=prompt('آدرس لینک:');if(url){document.getElementById('post-content').focus();document.execCommand('createLink',false,url);}}
// ── Modal helpers ─────────────────────────────────────────────────────────────
function closeModal(id){document.getElementById(id).classList.add('hidden');}
document.querySelectorAll('.modal-overlay').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.add('hidden');}));
// ── Init ──────────────────────────────────────────────────────────────────────
async function init(){
if(!token){return;}
document.getElementById('loginScreen').classList.add('hidden');
loadDashboard();
loadCategories();
}
// Auto-login if token exists
if(token) init();
</script>
</body>
</html>