[CLAUDE] FE-User+FE-Admin: Plan AG6 — Compact PE card 3 row gọn đẹp
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m21s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m21s
Anh feedback 2026-05-21: "Cho thông tin bên trong này nó gọn đẹp lại nhé". PE card hiện 4-5 row hơi dài. Compact xuống 3 row tightly packed: Row 1: [Tên gói thầu] [Status badge] Row 2: PE/2026/A/035 · 10:40 19/05/2026 Row 3: 👤 Drafter · Phòng ban [✓ HĐ if any] Changes: - py-2.5 → py-2 (compact vertical padding) - Drop Type label "Duyệt NCC" badge redundant (page header đã hiện) - Combine maPhieu + createdAt vào 1 row với separator · - Combine drafter + department + contract badge vào 1 row (conditional render) - "✓ Đã tạo HĐ" → "✓ HĐ" short label inline cuối row 3 - Separator color slate-300 nhẹ hơn slate-500 Verify: - npm build fe-user PASS 0 TS err 1292.66 KB (gzip 337.19 KB) - npm build fe-admin PASS 0 TS err 1404.01 KB (gzip 357.70 KB) - 2 file SHA256 IDENTICAL 3645307C... (mirror §3.9) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -343,23 +343,13 @@ export function PurchaseEvaluationsListPage() {
|
|||||||
<button
|
<button
|
||||||
onClick={() => selectRow(p.id)}
|
onClick={() => selectRow(p.id)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'block w-full px-3 py-2.5 text-left transition hover:bg-slate-50',
|
'block w-full px-3 py-2 text-left transition hover:bg-slate-50',
|
||||||
selectedId === p.id && 'bg-brand-50 ring-1 ring-inset ring-brand-200',
|
selectedId === p.id && 'bg-brand-50 ring-1 ring-inset ring-brand-200',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
{/* Plan AG6 — compact card 3 row: title+badge / mã+time / drafter+dept+contract */}
|
||||||
<div className="flex items-start justify-between gap-2">
|
<div className="flex items-start justify-between gap-2">
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1 truncate text-[13px] font-medium text-slate-900">{p.tenGoiThau}</div>
|
||||||
<div className="truncate text-[13px] font-medium text-slate-900">{p.tenGoiThau}</div>
|
|
||||||
<div className="mt-0.5 flex items-center gap-1.5 text-[11px] text-slate-500">
|
|
||||||
<span className="font-mono">{p.maPhieu ?? '—'}</span>
|
|
||||||
</div>
|
|
||||||
{(p.drafterName || p.departmentName) && (
|
|
||||||
<div className="mt-0.5 truncate text-[11px] text-slate-500">
|
|
||||||
<span>👤 {p.drafterName ?? '—'}</span>
|
|
||||||
{p.departmentName && <span className="text-slate-400"> · {p.departmentName}</span>}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
'shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium',
|
'shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium',
|
||||||
@ -369,21 +359,26 @@ export function PurchaseEvaluationsListPage() {
|
|||||||
{PeDisplayStatusLabel[getPeDisplayStatus(p.phase)]}
|
{PeDisplayStatusLabel[getPeDisplayStatus(p.phase)]}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-1 flex items-center justify-between text-[11px] text-slate-500">
|
<div className="mt-0.5 flex items-center gap-1.5 text-[11px] text-slate-500">
|
||||||
<span className="rounded bg-slate-100 px-1.5 py-0.5 text-slate-600">
|
<span className="font-mono">{p.maPhieu ?? '—'}</span>
|
||||||
{PurchaseEvaluationTypeLabel[p.type]}
|
<span className="text-slate-300">·</span>
|
||||||
</span>
|
{/* S23 t2 UAT: BE list sort theo UpdatedAt DESC (fallback CreatedAt). */}
|
||||||
{/* S23 t2 UAT: BE list sort theo UpdatedAt DESC (fallback CreatedAt) —
|
<span title={`Tạo lúc ${new Date(p.createdAt).toLocaleString('vi-VN')}`}>
|
||||||
phiếu vừa update (Tạo / Gửi duyệt / Trả lại) đưa lên đầu list. */}
|
|
||||||
<span className="font-medium text-slate-600" title={`Tạo lúc ${new Date(p.createdAt).toLocaleString('vi-VN')}`}>
|
|
||||||
{new Date(p.createdAt).toLocaleString('vi-VN', {
|
{new Date(p.createdAt).toLocaleString('vi-VN', {
|
||||||
day: '2-digit', month: '2-digit', year: 'numeric',
|
day: '2-digit', month: '2-digit', year: 'numeric',
|
||||||
hour: '2-digit', minute: '2-digit',
|
hour: '2-digit', minute: '2-digit',
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{p.contractId && (
|
{(p.drafterName || p.departmentName || p.contractId) && (
|
||||||
<div className="mt-1 text-[10px] text-brand-600">✓ Đã tạo HĐ</div>
|
<div className="mt-0.5 flex items-center justify-between gap-2 text-[11px]">
|
||||||
|
<span className="min-w-0 flex-1 truncate text-slate-500">
|
||||||
|
{p.drafterName && <>👤 {p.drafterName}</>}
|
||||||
|
{p.drafterName && p.departmentName && <span className="text-slate-300"> · </span>}
|
||||||
|
{p.departmentName && <span className="text-slate-400">{p.departmentName}</span>}
|
||||||
|
</span>
|
||||||
|
{p.contractId && <span className="shrink-0 text-[10px] font-medium text-brand-600">✓ HĐ</span>}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@ -343,23 +343,13 @@ export function PurchaseEvaluationsListPage() {
|
|||||||
<button
|
<button
|
||||||
onClick={() => selectRow(p.id)}
|
onClick={() => selectRow(p.id)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'block w-full px-3 py-2.5 text-left transition hover:bg-slate-50',
|
'block w-full px-3 py-2 text-left transition hover:bg-slate-50',
|
||||||
selectedId === p.id && 'bg-brand-50 ring-1 ring-inset ring-brand-200',
|
selectedId === p.id && 'bg-brand-50 ring-1 ring-inset ring-brand-200',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
{/* Plan AG6 — compact card 3 row: title+badge / mã+time / drafter+dept+contract */}
|
||||||
<div className="flex items-start justify-between gap-2">
|
<div className="flex items-start justify-between gap-2">
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1 truncate text-[13px] font-medium text-slate-900">{p.tenGoiThau}</div>
|
||||||
<div className="truncate text-[13px] font-medium text-slate-900">{p.tenGoiThau}</div>
|
|
||||||
<div className="mt-0.5 flex items-center gap-1.5 text-[11px] text-slate-500">
|
|
||||||
<span className="font-mono">{p.maPhieu ?? '—'}</span>
|
|
||||||
</div>
|
|
||||||
{(p.drafterName || p.departmentName) && (
|
|
||||||
<div className="mt-0.5 truncate text-[11px] text-slate-500">
|
|
||||||
<span>👤 {p.drafterName ?? '—'}</span>
|
|
||||||
{p.departmentName && <span className="text-slate-400"> · {p.departmentName}</span>}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
'shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium',
|
'shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium',
|
||||||
@ -369,21 +359,26 @@ export function PurchaseEvaluationsListPage() {
|
|||||||
{PeDisplayStatusLabel[getPeDisplayStatus(p.phase)]}
|
{PeDisplayStatusLabel[getPeDisplayStatus(p.phase)]}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-1 flex items-center justify-between text-[11px] text-slate-500">
|
<div className="mt-0.5 flex items-center gap-1.5 text-[11px] text-slate-500">
|
||||||
<span className="rounded bg-slate-100 px-1.5 py-0.5 text-slate-600">
|
<span className="font-mono">{p.maPhieu ?? '—'}</span>
|
||||||
{PurchaseEvaluationTypeLabel[p.type]}
|
<span className="text-slate-300">·</span>
|
||||||
</span>
|
{/* S23 t2 UAT: BE list sort theo UpdatedAt DESC (fallback CreatedAt). */}
|
||||||
{/* S23 t2 UAT: BE list sort theo UpdatedAt DESC (fallback CreatedAt) —
|
<span title={`Tạo lúc ${new Date(p.createdAt).toLocaleString('vi-VN')}`}>
|
||||||
phiếu vừa update (Tạo / Gửi duyệt / Trả lại) đưa lên đầu list. */}
|
|
||||||
<span className="font-medium text-slate-600" title={`Tạo lúc ${new Date(p.createdAt).toLocaleString('vi-VN')}`}>
|
|
||||||
{new Date(p.createdAt).toLocaleString('vi-VN', {
|
{new Date(p.createdAt).toLocaleString('vi-VN', {
|
||||||
day: '2-digit', month: '2-digit', year: 'numeric',
|
day: '2-digit', month: '2-digit', year: 'numeric',
|
||||||
hour: '2-digit', minute: '2-digit',
|
hour: '2-digit', minute: '2-digit',
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{p.contractId && (
|
{(p.drafterName || p.departmentName || p.contractId) && (
|
||||||
<div className="mt-1 text-[10px] text-brand-600">✓ Đã tạo HĐ</div>
|
<div className="mt-0.5 flex items-center justify-between gap-2 text-[11px]">
|
||||||
|
<span className="min-w-0 flex-1 truncate text-slate-500">
|
||||||
|
{p.drafterName && <>👤 {p.drafterName}</>}
|
||||||
|
{p.drafterName && p.departmentName && <span className="text-slate-300"> · </span>}
|
||||||
|
{p.departmentName && <span className="text-slate-400">{p.departmentName}</span>}
|
||||||
|
</span>
|
||||||
|
{p.contractId && <span className="shrink-0 text-[10px] font-medium text-brand-600">✓ HĐ</span>}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
Reference in New Issue
Block a user