feat: health request detail modal + view button always visible
CI/CD / CI · dotnet build (push) Successful in 3m21s
CI/CD / Deploy · drsousan (push) Successful in 29s

- Every row now has a 'مشاهده' button regardless of handled status
- Opens a modal with: name, phone, email, category, date, status,
  and full message text (no truncation)
- Modal includes 'علامت‌گذاری' button if request is still pending
- Message column in table kept short (truncated) as a preview only

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-02 16:15:01 +03:30
parent e73d47a875
commit 772df0698c
+45 -6
View File
@@ -777,6 +777,17 @@ tr:hover td{background:#FAFBFC}
</div>
<!-- Visit Modal -->
<!-- Health Request Detail Modal -->
<div class="modal-overlay hidden" id="reqDetailModal">
<div class="modal" style="max-width:560px">
<div class="modal-header">
<div class="modal-title">جزئیات درخواست</div>
<button class="modal-close" onclick="closeModal('reqDetailModal')"></button>
</div>
<div class="modal-body" id="reqDetailBody"></div>
</div>
</div>
<div class="modal-overlay hidden" id="visitModal">
<div class="modal">
<div class="modal-header">
@@ -1225,28 +1236,56 @@ async function saveVisit() {
async function deleteVisit(vid){if(!confirm('حذف ویزیت؟'))return;await api(`/api/patients/visits/${vid}`,{method:'DELETE'});toast('حذف شد','error');openProfile(currentPatientId);}
// ── Health Requests ───────────────────────────────────────────────────────────
let _allReqs = [];
async function loadHealthRequests() {
const filter = document.getElementById('reqFilter').value;
const params = filter !== '' ? `?handled=${filter}` : '';
const reqs = await api('/api/health-requests' + params) || [];
const pending = reqs.filter(r=>!r.isHandled).length;
_allReqs = await api('/api/health-requests' + params) || [];
const pending = _allReqs.filter(r=>!r.isHandled).length;
const badge = document.getElementById('healthreqBadge');
if(pending>0){badge.textContent=pending;badge.style.display='inline';}else{badge.style.display='none';}
const catLabel = {beauty:'زیبایی پوست', health:'سلامت عمومی'};
document.getElementById('healthreqTable').innerHTML = reqs.map(r=>`
<tr style="${!r.isHandled?'font-weight:600':'opacity:.7'}">
document.getElementById('healthreqTable').innerHTML = _allReqs.map(r=>`
<tr style="${!r.isHandled?'font-weight:600':'opacity:.75'}">
<td>${r.fullName}</td>
<td dir="ltr">${r.phoneNumber}</td>
<td>${catLabel[r.category]||r.category}</td>
<td style="max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="${r.message}">${r.message}</td>
<td style="max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--mid);font-size:.85rem">${r.message||'—'}</td>
<td>${new Date(r.createdAt).toLocaleDateString('fa-IR')}</td>
<td><span style="background:${r.isHandled?'#E8F5E9':'#FFEBEE'};color:${r.isHandled?'#388E3C':'#C62828'};padding:2px 8px;border-radius:20px;font-size:.72rem">${r.isHandled?'بررسی شده':'جدید'}</span></td>
<td>
<td style="white-space:nowrap">
<button class="btn btn-secondary btn-sm" onclick="viewReq(${r.id})">مشاهده</button>
${!r.isHandled?`<button class="btn btn-secondary btn-sm" onclick="handleReq(${r.id})">✓ بررسی شد</button>`:''}
<button class="btn btn-danger btn-sm" onclick="deleteReq(${r.id})">حذف</button>
</td>
</tr>`).join('') || '<tr><td colspan="7" style="text-align:center;color:var(--light);padding:2rem">درخواستی وجود ندارد</td></tr>';
}
function viewReq(id) {
const r = _allReqs.find(x=>x.id===id); if(!r) return;
const catLabel = {beauty:'زیبایی پوست', health:'سلامت عمومی'};
document.getElementById('reqDetailBody').innerHTML = `
<div style="display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1.2rem">
<div><span style="font-size:.75rem;color:var(--light);display:block;margin-bottom:.25rem">نام</span><strong>${r.fullName}</strong></div>
<div><span style="font-size:.75rem;color:var(--light);display:block;margin-bottom:.25rem">تلفن</span><strong dir="ltr">${r.phoneNumber}</strong></div>
<div><span style="font-size:.75rem;color:var(--light);display:block;margin-bottom:.25rem">ایمیل</span><span>${r.email||'—'}</span></div>
<div><span style="font-size:.75rem;color:var(--light);display:block;margin-bottom:.25rem">دسته</span>
<span style="background:${r.category==='health'?'#E3F2FD':'var(--gold-pale)'};color:${r.category==='health'?'#1565C0':'var(--gold)'};padding:3px 10px;border-radius:20px;font-size:.78rem">${catLabel[r.category]||r.category}</span>
</div>
<div><span style="font-size:.75rem;color:var(--light);display:block;margin-bottom:.25rem">تاریخ ثبت</span><span>${new Date(r.createdAt).toLocaleDateString('fa-IR')}</span></div>
<div><span style="font-size:.75rem;color:var(--light);display:block;margin-bottom:.25rem">وضعیت</span>
<span style="background:${r.isHandled?'#E8F5E9':'#FFEBEE'};color:${r.isHandled?'#388E3C':'#C62828'};padding:3px 10px;border-radius:20px;font-size:.78rem">${r.isHandled?'بررسی شده':'جدید'}</span>
</div>
</div>
<div><span style="font-size:.75rem;color:var(--light);display:block;margin-bottom:.5rem">پیام / شرح درخواست</span>
<div style="background:var(--section-bg);border-radius:12px;padding:1rem 1.2rem;line-height:2;font-size:.9rem;white-space:pre-wrap;min-height:60px">${r.message||'—'}</div>
</div>
${!r.isHandled?`<div style="margin-top:1.2rem"><button class="btn btn-primary" onclick="handleReq(${r.id});closeModal('reqDetailModal')">✓ علامت‌گذاری به عنوان بررسی شده</button></div>`:''}
`;
document.getElementById('reqDetailModal').classList.remove('hidden');
}
async function handleReq(id){await api(`/api/health-requests/${id}`,{method:'PUT'});toast('علامت‌گذاری شد ✓');loadHealthRequests();}
async function deleteReq(id){if(!confirm('حذف؟'))return;await api(`/api/health-requests/${id}`,{method:'DELETE'});toast('حذف شد','error');loadHealthRequests();}