feat(department): add View Department panel with row detail display

- View Department tab now shows department details (code, head, email, employees, visibility, date)
- Clicking ⋮ → View Department on a row populates the view panel
- Table hides when View tab is active (style:display reactive binding)
- Dropdown menu items rewritten with inline styles for proper spacing (4 items: View, Edit, Deactivate, Delete)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ashwin Kumar 2026-03-27 02:05:28 +01:00
parent ab487ce884
commit 1bd7fe646c

View file

@ -105,6 +105,7 @@ export default function DepartmentManagementPage() {
const [rows, setRows] = createSignal<DepartmentRecord[]>([]);
const [openMenuId, setOpenMenuId] = createSignal<string | null>(null);
const [editingId, setEditingId] = createSignal<string | null>(null);
const [viewingDept, setViewingDept] = createSignal<DepartmentRecord | null>(null);
const [name, setName] = createSignal('');
const [code, setCode] = createSignal('');
@ -285,8 +286,69 @@ export default function DepartmentManagementPage() {
))}
</div>
{/* View Department panel */}
<Show when={listTab() === 'view'}>
<Show
when={!viewingDept()}
>
<div style="margin-top:24px;border-radius:16px;border:1px solid #E5E7EB;background:white;padding:48px 24px;text-align:center">
<p style="font-size:15px;font-weight:600;color:#111827">No department selected</p>
<p style="margin-top:6px;font-size:13px;color:#6B7280">Click the <strong></strong> menu on any department row and choose <strong>View Department</strong>.</p>
</div>
</Show>
<Show when={viewingDept()}>
<div style="margin-top:24px;border-radius:16px;border:1px solid #E5E7EB;background:white;box-shadow:0 1px 4px rgba(0,0,0,0.06);overflow:hidden">
{/* Header */}
<div style="padding:20px 24px;border-bottom:1px solid #E5E7EB;display:flex;align-items:center;justify-content:space-between">
<div>
<h2 style="font-size:18px;font-weight:700;color:#111827">{viewingDept()!.name}</h2>
<p style="margin-top:2px;font-size:13px;color:#6B7280">{viewingDept()!.description || 'No description'}</p>
</div>
<StatusBadge status={viewingDept()!.status} />
</div>
{/* Details grid — 3 cols using flex rows */}
<div>
<div style="display:flex;border-bottom:1px solid #F3F4F6">
<div style="flex:1;padding:16px 24px;border-right:1px solid #F3F4F6">
<p style="font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:#9CA3AF">Department Code</p>
<p style="margin-top:4px;font-size:14px;font-weight:600;color:#111827">{viewingDept()!.code || '—'}</p>
</div>
<div style="flex:1;padding:16px 24px;border-right:1px solid #F3F4F6">
<p style="font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:#9CA3AF">Department Head</p>
<p style="margin-top:4px;font-size:14px;font-weight:600;color:#111827">{viewingDept()!.departmentHead || '—'}</p>
</div>
<div style="flex:1;padding:16px 24px">
<p style="font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:#9CA3AF">Department Email</p>
<p style="margin-top:4px;font-size:14px;font-weight:600;color:#111827">{viewingDept()!.departmentEmail || '—'}</p>
</div>
</div>
<div style="display:flex;border-bottom:1px solid #F3F4F6">
<div style="flex:1;padding:16px 24px;border-right:1px solid #F3F4F6">
<p style="font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:#9CA3AF">Total Employees</p>
<p style="margin-top:4px;font-size:14px;font-weight:600;color:#111827">{String(viewingDept()!.totalEmployees ?? 0)}</p>
</div>
<div style="flex:1;padding:16px 24px;border-right:1px solid #F3F4F6">
<p style="font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:#9CA3AF">Visibility</p>
<p style="margin-top:4px;font-size:14px;font-weight:600;color:#111827">{viewingDept()!.visibility || 'INTERNAL'}</p>
</div>
<div style="flex:1;padding:16px 24px">
<p style="font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:#9CA3AF">Created Date</p>
<p style="margin-top:4px;font-size:14px;font-weight:600;color:#111827">{viewingDept()!.createdDate?.slice(0, 10) || '—'}</p>
</div>
</div>
</div>
{/* Actions */}
<div style="display:flex;align-items:center;gap:10px;padding:14px 24px;border-top:1px solid #E5E7EB">
<button type="button" onClick={() => openEdit(viewingDept()!)} style="height:36px;border-radius:8px;background:#0D0D2A;padding:0 16px;font-size:13px;font-weight:600;color:white;border:none;cursor:pointer">Edit Department</button>
<button type="button" onClick={() => { setViewingDept(null); setListTab('all'); }} style="height:36px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 16px;font-size:13px;font-weight:600;color:#374151;cursor:pointer">Back to List</button>
</div>
</div>
</Show>
</Show>
{/* Table card */}
<div style="margin-top:1.5rem;margin-left:-24px;margin-right:-24px;border-radius:0;border-left:none;border-right:none" class="overflow-hidden border-t border-b border-[#E5E7EB] bg-white shadow-sm">
<div style:display={listTab() === 'view' ? 'none' : 'block'}>
<div style="margin-top:1.5rem;margin-left:-24px;margin-right:-24px;border-radius:0;border-left:none;border-right:none;overflow:hidden;border-top:1px solid #E5E7EB;border-bottom:1px solid #E5E7EB;background:white;box-shadow:0 1px 3px rgba(0,0,0,0.06)">
{/* Filter bar */}
<div style="display:flex;align-items:center;gap:8px;padding:14px 20px;border-bottom:1px solid #F3F4F6">
@ -394,13 +456,13 @@ export default function DepartmentManagementPage() {
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="12" cy="5" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="12" cy="19" r="1.5"/></svg>
</button>
<Show when={openMenuId() === row.id}>
<div class="absolute right-5 top-11 z-20 w-[200px] rounded-xl border border-[#E5E7EB] bg-white p-1.5 shadow-lg">
<button type="button" onClick={() => { setOpenMenuId(null); setListTab('view'); }} class="flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] font-medium text-[#374151] hover:bg-[#F9FAFB]">
<svg class="h-4 w-4 text-[#FF5E13]" 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 style="position:absolute;right:20px;top:44px;z-index:20;width:210px;border-radius:12px;border:1px solid #E5E7EB;background:white;padding:6px;box-shadow:0 4px 20px rgba(0,0,0,0.12)">
<button type="button" onClick={() => { setViewingDept(row); setOpenMenuId(null); setListTab('view'); }} style="display:flex;width:100%;align-items:center;gap:10px;border-radius:8px;padding:10px 12px;font-size:13px;font-weight:500;color:#374151;background:none;border:none;cursor:pointer;text-align:left">
<svg style="width:16px;height:16px;color:#FF5E13;flex-shrink:0" 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>
View Department
</button>
<button type="button" onClick={() => openEdit(row)} class="flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] font-medium text-[#374151] hover:bg-[#F9FAFB]">
<svg class="h-4 w-4 text-[#FF5E13]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9"/><path d="m16.5 3.5 4 4L7 21H3v-4L16.5 3.5Z"/></svg>
<button type="button" onClick={() => openEdit(row)} style="display:flex;width:100%;align-items:center;gap:10px;border-radius:8px;padding:10px 12px;font-size:13px;font-weight:500;color:#374151;background:none;border:none;cursor:pointer;text-align:left">
<svg style="width:16px;height:16px;color:#FF5E13;flex-shrink:0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9"/><path d="m16.5 3.5 4 4L7 21H3v-4L16.5 3.5Z"/></svg>
Edit Department
</button>
<button
@ -412,12 +474,12 @@ export default function DepartmentManagementPage() {
} catch (err: any) { setError(err?.message || 'Failed to update status.'); }
finally { setOpenMenuId(null); await load(); }
}}
class="flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] font-medium text-[#374151] hover:bg-[#F9FAFB]"
style="display:flex;width:100%;align-items:center;gap:10px;border-radius:8px;padding:10px 12px;font-size:13px;font-weight:500;color:#374151;background:none;border:none;cursor:pointer;text-align:left"
>
<svg class="h-4 w-4 text-[#FF5E13]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M9 12l2 2 4-4"/></svg>
<svg style="width:16px;height:16px;color:#FF5E13;flex-shrink:0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M9 12l2 2 4-4"/></svg>
{row.status === 'ACTIVE' ? 'Deactivate Department' : 'Activate Department'}
</button>
<div class="my-1 h-px bg-[#F3F4F6]" />
<div style="height:1px;background:#F3F4F6;margin:4px 0" />
<button
type="button"
onClick={async () => {
@ -428,9 +490,9 @@ export default function DepartmentManagementPage() {
} catch (err: any) { setError(err?.message || 'Failed to delete department.'); }
finally { setOpenMenuId(null); await load(); }
}}
class="flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] font-medium text-[#DC2626] hover:bg-[#FEF2F2]"
style="display:flex;width:100%;align-items:center;gap:10px;border-radius:8px;padding:10px 12px;font-size:13px;font-weight:500;color:#DC2626;background:none;border:none;cursor:pointer;text-align:left"
>
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6M10 11v6M14 11v6"/></svg>
<svg style="width:16px;height:16px;flex-shrink:0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6M10 11v6M14 11v6"/></svg>
Delete Department
</button>
</div>
@ -461,6 +523,7 @@ export default function DepartmentManagementPage() {
</Show>
</div>
</div>
</div>
</Show>
{/* ── FORM VIEW (Create / Edit) ── */}