feat: patient management system + health landing page
CI/CD / CI · dotnet build (push) Successful in 59s
CI/CD / Deploy · drsousan (push) Successful in 1m33s

Backend:
- Patient model: name, phone, email, age, weight, height, gender,
  blood type, disease history, allergies, medications, notes, category
- PatientVisit model: title, content, prescription, visit type,
  visit/next-visit dates, linked to patient (cascade delete)
- HealthRequest model: public form submissions for beauty/health care
- Runtime SQLite migrations for all 3 new tables
- Full CRUD API: /api/patients, /api/patients/{id}/visits,
  /api/health-requests (public POST + admin GET/PUT/DELETE)

Admin panel:
- 'پرونده بیماران' page: list, search, filter by category (beauty/health)
- Patient profile page: personal info + medical history + visits timeline
- Add/edit patient modal with all medical fields
- Add visit modal: type, date, clinical notes, prescription, next visit
- 'درخواست‌ها' page: manage public health requests, mark as handled
- Badge counter for unhandled requests in sidebar

Frontend (SEO):
- New #health-care section with Schema.org MedicalClinic markup
- Two category cards: زیبایی پوست and سلامت عمومی
- Feature lists with checkmarks per category
- Inline request form that submits to /api/health-request
- Mobile responsive (single column on small screens)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-02 12:27:16 +03:30
parent 0765d5d3cd
commit 3780dcccf2
5 changed files with 685 additions and 2 deletions
+136
View File
@@ -172,6 +172,29 @@
.faq-item[open] summary::after { content:""; }
.faq-answer { padding:0 1.5rem 1.25rem; color:var(--mid); font-size:0.92rem; line-height:1.85; border-top:1px solid var(--border); }
/* ─── Contact ──────────────────────────────────────────────── */
/* ─── Health Care Landing ─────────────────────────────────── */
#health-care { background:var(--section-bg); }
.health-header { text-align:center; margin-bottom:3rem; }
.health-cats { display:grid; grid-template-columns:1fr 1fr; gap:2rem; margin-bottom:2.5rem; }
.health-cat-card { background:var(--white); border-radius:24px; padding:2.2rem; border:1px solid var(--border); display:flex; flex-direction:column; gap:1rem; }
.health-cat-icon { width:60px; height:60px; border-radius:18px; display:flex; align-items:center; justify-content:center; }
.health-cat-icon svg { width:28px; height:28px; }
.health-cat-icon.beauty { background:#FCE4EC; color:#C2185B; }
.health-cat-icon.health { background:#E3F2FD; color:#1565C0; }
.health-cat-card h3 { font-size:1.15rem; font-weight:700; color:var(--dark); }
.health-cat-card p { font-size:.88rem; color:var(--mid); line-height:1.8; }
.health-cat-list { list-style:none; padding:0; display:flex; flex-direction:column; gap:.45rem; flex:1; }
.health-cat-list li { font-size:.85rem; color:var(--mid); padding-right:1.2rem; position:relative; }
.health-cat-list li::before { content:"✓"; position:absolute; right:0; color:var(--gold); font-weight:700; }
.health-cta-btn { background:var(--gold); color:#fff; border:none; border-radius:12px; padding:.85rem 1.5rem; font-family:'Vazirmatn',sans-serif; font-size:.9rem; font-weight:600; cursor:pointer; transition:background .25s; margin-top:auto; }
.health-cta-btn:hover { background:#a07840; }
.health-cta-btn.health-btn { background:#1565C0; }
.health-cta-btn.health-btn:hover { background:#0d47a1; }
.health-form-wrap { margin-top:1rem; }
.health-form-card { background:var(--white); border-radius:24px; padding:2.5rem; border:1px solid var(--border); max-width:680px; margin:0 auto; }
.health-form-card h3 { font-size:1.1rem; font-weight:700; margin-bottom:.5rem; }
#health-care .hidden { display:none; }
/* ─── Contact ─────────────────────────────────────────────── */
#contact { background:var(--white); }
.contact-grid { display:grid; grid-template-columns:1fr 1.4fr; gap:4rem; align-items:start; }
.contact-info-list { display:flex; flex-direction:column; gap:1.5rem; margin-top:2rem; }
@@ -227,6 +250,7 @@
.about-image-wrap { text-align:center; }
.testimonials-grid { grid-template-columns:1fr; }
.section-title { font-size:1.5rem; }
.health-cats { grid-template-columns:1fr; }
.faq-item summary { font-size:.9rem; padding:1rem 1.2rem; }
.faq-answer { padding:0 1.2rem 1rem; font-size:.88rem; }
}
@@ -581,6 +605,72 @@
</div>
</section>
<!-- ══════ HEALTH CARE LANDING ══════ -->
<section id="health-care" itemscope itemtype="https://schema.org/MedicalClinic">
<div class="container">
<div class="health-header fade-in">
<span class="section-label">مراقبت سلامت</span>
<h2 class="section-title" itemprop="name">خدمات پزشکی دکتر آل‌طه</h2>
<div class="divider"></div>
<p class="section-desc" itemprop="description">ما در دو حوزه تخصصی <strong>زیبایی پوست</strong> و <strong>سلامت عمومی</strong> در کنار شما هستیم. از مشاوره اولیه تا پیگیری درمان، تیم ما آماده پاسخگویی است.</p>
</div>
<!-- Category Cards -->
<div class="health-cats fade-in">
<div class="health-cat-card" itemprop="availableService" itemscope itemtype="https://schema.org/MedicalTherapy">
<div class="health-cat-icon beauty">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
</div>
<h3 itemprop="name">زیبایی پوست</h3>
<p itemprop="description">بوتاکس، فیلر، لیزر، مزوتراپی، پاکسازی عمیق پوست و درمان تخصصی انواع مشکلات پوستی توسط متخصص.</p>
<ul class="health-cat-list">
<li>تزریق بوتاکس و فیلر</li>
<li>لیزر موهای زائد و جوانسازی</li>
<li>مزوتراپی و PRP</li>
<li>درمان جای جوش و لک</li>
<li>پاکسازی عمیق پوست</li>
</ul>
<button class="health-cta-btn" onclick="openHealthForm('beauty')">درخواست مشاوره زیبایی</button>
</div>
<div class="health-cat-card" itemprop="availableService" itemscope itemtype="https://schema.org/MedicalTherapy">
<div class="health-cat-icon health">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>
</div>
<h3 itemprop="name">سلامت عمومی</h3>
<p itemprop="description">معاینه، تشخیص و پیگیری بیماری‌های عمومی، مشاوره تغذیه، مدیریت وزن و برنامه‌ریزی سلامت فردی.</p>
<ul class="health-cat-list">
<li>معاینه و ویزیت تخصصی</li>
<li>مشاوره و مدیریت وزن</li>
<li>پیگیری بیماری‌های مزمن</li>
<li>برنامه سلامت شخصی‌سازی‌شده</li>
<li>آزمایشات تخصصی</li>
</ul>
<button class="health-cta-btn health-btn" onclick="openHealthForm('health')">درخواست مراقبت سلامت</button>
</div>
</div>
<!-- Health Request Form -->
<div class="health-form-wrap fade-in hidden" id="healthFormWrap">
<div class="health-form-card">
<h3 id="healthFormTitle">درخواست مشاوره</h3>
<p style="color:var(--mid);font-size:.88rem;margin-bottom:1.5rem">فرم زیر را تکمیل کنید. تیم ما در اسرع وقت با شما تماس می‌گیرد.</p>
<input type="hidden" id="hf-category"/>
<div class="form-row">
<div class="form-group"><label>نام و نام خانوادگی *</label><input id="hf-name" placeholder="نام شما" required/></div>
<div class="form-group"><label>شماره موبایل *</label><input id="hf-phone" type="tel" placeholder="09xx-xxx-xxxx" required/></div>
</div>
<div class="form-group"><label>ایمیل (اختیاری)</label><input id="hf-email" type="email" placeholder="email@example.com"/></div>
<div class="form-group"><label>شرح درخواست یا مشکل</label><textarea id="hf-message" rows="4" placeholder="لطفاً مشکل یا درخواست خود را بنویسید ..."></textarea></div>
<div style="display:flex;gap:.8rem;flex-wrap:wrap">
<button class="form-submit" id="hf-submit" onclick="submitHealthForm()" style="flex:1">ارسال درخواست</button>
<button onclick="document.getElementById('healthFormWrap').classList.add('hidden')" style="background:transparent;border:1.5px solid var(--border);border-radius:12px;padding:.8rem 1.5rem;cursor:pointer;font-family:inherit;font-size:.9rem">انصراف</button>
</div>
</div>
</div>
</div>
</section>
<!-- ══════ CONTACT ══════ -->
<section id="contact">
<div class="container">
@@ -758,6 +848,52 @@
}, 3000);
}
// Health care request form
function openHealthForm(category) {
document.getElementById('hf-category').value = category;
document.getElementById('healthFormTitle').textContent =
category === 'health' ? 'درخواست مراقبت سلامت عمومی' : 'درخواست مشاوره زیبایی پوست';
const wrap = document.getElementById('healthFormWrap');
wrap.classList.remove('hidden');
setTimeout(() => wrap.scrollIntoView({behavior:'smooth', block:'center'}), 100);
}
async function submitHealthForm() {
const name = document.getElementById('hf-name').value.trim();
const phone = document.getElementById('hf-phone').value.trim();
if (!name || !phone) { alert('نام و شماره تلفن الزامی است'); return; }
const btn = document.getElementById('hf-submit');
btn.textContent = '...در حال ارسال';
btn.disabled = true;
try {
const body = {
fullName: name,
phoneNumber: phone,
email: document.getElementById('hf-email').value,
message: document.getElementById('hf-message').value,
category: document.getElementById('hf-category').value
};
const res = await fetch('/api/health-request', {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify(body)
});
if (!res.ok) throw new Error();
btn.textContent = '✓ درخواست شما ثبت شد';
btn.style.background = '#2D7A4F';
['hf-name','hf-phone','hf-email','hf-message'].forEach(id => document.getElementById(id).value='');
setTimeout(() => {
document.getElementById('healthFormWrap').classList.add('hidden');
btn.textContent = 'ارسال درخواست';
btn.style.background = '';
btn.disabled = false;
}, 3000);
} catch {
btn.textContent = 'خطا — دوباره تلاش کنید';
btn.style.background = '#c62828';
setTimeout(() => { btn.textContent='ارسال درخواست'; btn.style.background=''; btn.disabled=false; }, 2500);
}
}
// Active nav link on scroll
const sections = document.querySelectorAll('section[id]');
window.addEventListener('scroll', () => {