[CLAUDE] FE-Admin·FE-User: badge "✅ Đã được CEO duyệt" cho phiếu đi hết lên CEO (anh Kiệt FDC UAT)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m13s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m13s
- PeFinalizeChip (single-source-of-truth pill): +nhánh phase===DaDuyet && !endsBeforeCeo → "✅ Đã được CEO duyệt" (đối xứng chip "⚑ Kết thúc · X" cho endsBeforeCeo=true) - Wire phase ở 6 call-site (PeListPanel + PurchaseEvaluationsListPage ×2 app + Inbox + Dashboard user) - FE-only, tận dụng endsBeforeCeo runtime (Mig 60 fix-3), no BE/mig; mirror 2-app SHA da9c3ed9, build ×2 PASS 0-TS-err Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -1,17 +1,34 @@
|
||||
// PE — chip "Quy trình kết thúc tại cấp này" (không trình CEO). Hiện khi quy
|
||||
// trình của phiếu có cấp bật AllowApproverFinalize (Mig 58, anh Kiệt FDC S89).
|
||||
// SINGLE SOURCE OF TRUTH cho pill này dùng ở MỌI danh sách phiếu (cây danh sách
|
||||
// + picker workspace/chờ-duyệt + inbox) để mọi người NẮM ngay "phiếu này duyệt
|
||||
// đến đây là xong, không lên CEO" mà KHÔNG cần mở phiếu. Shape khớp PeUrgentChips.
|
||||
// PE — chip trạng thái cuối phiếu ở MỌI danh sách (cây danh sách + picker + inbox):
|
||||
// [S89] "⚑ Kết thúc · X" khi quy trình có cấp AllowApproverFinalize (kết thúc, không lên CEO).
|
||||
// [S97 anh Kiệt FDC] "✅ Đã được CEO duyệt" khi phiếu ĐÃ DUYỆT đi HẾT lên CEO (endsBeforeCeo=false).
|
||||
// SINGLE SOURCE OF TRUTH — mọi người NẮM ngay trạng thái mà KHÔNG cần mở phiếu.
|
||||
|
||||
import { PurchaseEvaluationPhase } from '@/types/purchaseEvaluation'
|
||||
|
||||
export function PeFinalizeChip({
|
||||
endsBeforeCeo,
|
||||
finalizeStepName,
|
||||
phase,
|
||||
}: {
|
||||
endsBeforeCeo: boolean
|
||||
finalizeStepName: string | null
|
||||
// PeListItem.phase là number (mirror BE) → prop nhận number, so khớp literal DaDuyet.
|
||||
phase?: number
|
||||
}) {
|
||||
if (!endsBeforeCeo) return null
|
||||
// [S97 anh Kiệt FDC] Phiếu đã duyệt KHÔNG kết thúc sớm = đi hết lên CEO/Ban Giám đốc.
|
||||
if (!endsBeforeCeo) {
|
||||
if (phase === PurchaseEvaluationPhase.DaDuyet) {
|
||||
return (
|
||||
<span
|
||||
className="inline-flex shrink-0 items-center rounded bg-emerald-100 px-1.5 py-0.5 text-[11px] font-semibold text-emerald-800"
|
||||
title="Phiếu đã được CEO / Ban Giám đốc duyệt (đi hết quy trình, không kết thúc sớm ở cấp dưới)"
|
||||
>
|
||||
✅ Đã được CEO duyệt
|
||||
</span>
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<span
|
||||
className="inline-flex shrink-0 items-center rounded bg-violet-100 px-1.5 py-0.5 text-[11px] font-semibold text-violet-800"
|
||||
|
||||
@ -159,7 +159,7 @@ export function PeListPanel({
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex min-w-0 items-center gap-1 text-[13px] font-medium text-slate-900">
|
||||
<PeUrgentChips isUrgentByPro={p.isUrgentByPro} isUrgentByCcm={p.isUrgentByCcm} />
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} />
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} phase={p.phase} />
|
||||
<span className="truncate">{p.tenGoiThau}</span>
|
||||
</div>
|
||||
<div className="mt-0.5 flex items-center gap-1.5 text-[11px] text-slate-500">
|
||||
|
||||
@ -489,7 +489,7 @@ export function PurchaseEvaluationsListPage() {
|
||||
<div className="flex min-w-0 flex-1 items-center gap-1 truncate text-[13px] font-medium text-slate-900">
|
||||
{/* S77 — cờ gấp PILL đồng bộ mọi danh sách: 🔴 GẤP (PRO) / 🟢 GẤP (CCM). */}
|
||||
<PeUrgentChips isUrgentByPro={p.isUrgentByPro} isUrgentByCcm={p.isUrgentByCcm} />
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} />
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} phase={p.phase} />
|
||||
<span className="truncate">{p.tenGoiThau}</span>
|
||||
</div>
|
||||
<span
|
||||
|
||||
@ -1,17 +1,34 @@
|
||||
// PE — chip "Quy trình kết thúc tại cấp này" (không trình CEO). Hiện khi quy
|
||||
// trình của phiếu có cấp bật AllowApproverFinalize (Mig 58, anh Kiệt FDC S89).
|
||||
// SINGLE SOURCE OF TRUTH cho pill này dùng ở MỌI danh sách phiếu (cây danh sách
|
||||
// + picker workspace/chờ-duyệt + inbox) để mọi người NẮM ngay "phiếu này duyệt
|
||||
// đến đây là xong, không lên CEO" mà KHÔNG cần mở phiếu. Shape khớp PeUrgentChips.
|
||||
// PE — chip trạng thái cuối phiếu ở MỌI danh sách (cây danh sách + picker + inbox):
|
||||
// [S89] "⚑ Kết thúc · X" khi quy trình có cấp AllowApproverFinalize (kết thúc, không lên CEO).
|
||||
// [S97 anh Kiệt FDC] "✅ Đã được CEO duyệt" khi phiếu ĐÃ DUYỆT đi HẾT lên CEO (endsBeforeCeo=false).
|
||||
// SINGLE SOURCE OF TRUTH — mọi người NẮM ngay trạng thái mà KHÔNG cần mở phiếu.
|
||||
|
||||
import { PurchaseEvaluationPhase } from '@/types/purchaseEvaluation'
|
||||
|
||||
export function PeFinalizeChip({
|
||||
endsBeforeCeo,
|
||||
finalizeStepName,
|
||||
phase,
|
||||
}: {
|
||||
endsBeforeCeo: boolean
|
||||
finalizeStepName: string | null
|
||||
// PeListItem.phase là number (mirror BE) → prop nhận number, so khớp literal DaDuyet.
|
||||
phase?: number
|
||||
}) {
|
||||
if (!endsBeforeCeo) return null
|
||||
// [S97 anh Kiệt FDC] Phiếu đã duyệt KHÔNG kết thúc sớm = đi hết lên CEO/Ban Giám đốc.
|
||||
if (!endsBeforeCeo) {
|
||||
if (phase === PurchaseEvaluationPhase.DaDuyet) {
|
||||
return (
|
||||
<span
|
||||
className="inline-flex shrink-0 items-center rounded bg-emerald-100 px-1.5 py-0.5 text-[11px] font-semibold text-emerald-800"
|
||||
title="Phiếu đã được CEO / Ban Giám đốc duyệt (đi hết quy trình, không kết thúc sớm ở cấp dưới)"
|
||||
>
|
||||
✅ Đã được CEO duyệt
|
||||
</span>
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<span
|
||||
className="inline-flex shrink-0 items-center rounded bg-violet-100 px-1.5 py-0.5 text-[11px] font-semibold text-violet-800"
|
||||
|
||||
@ -159,7 +159,7 @@ export function PeListPanel({
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex min-w-0 items-center gap-1 text-[13px] font-medium text-slate-900">
|
||||
<PeUrgentChips isUrgentByPro={p.isUrgentByPro} isUrgentByCcm={p.isUrgentByCcm} />
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} />
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} phase={p.phase} />
|
||||
<span className="truncate">{p.tenGoiThau}</span>
|
||||
</div>
|
||||
<div className="mt-0.5 flex items-center gap-1.5 text-[11px] text-slate-500">
|
||||
|
||||
@ -289,7 +289,7 @@ export function InboxPage() {
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex min-w-0 items-center gap-1 text-[13px] font-medium text-slate-900">
|
||||
<PeUrgentChips isUrgentByPro={p.isUrgentByPro} isUrgentByCcm={p.isUrgentByCcm} />
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} />
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} phase={p.phase} />
|
||||
<span className="truncate">{p.tenGoiThau}</span>
|
||||
</div>
|
||||
<div className="mt-0.5 flex items-center gap-1.5 text-[11px] text-slate-500">
|
||||
|
||||
@ -283,7 +283,7 @@ export function UserDashboardPage() {
|
||||
<span className="truncate text-sm font-medium text-slate-900">
|
||||
{p.tenGoiThau}
|
||||
</span>
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} />
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} phase={p.phase} />
|
||||
<span
|
||||
className={cn(
|
||||
'shrink-0 rounded-full px-2 py-0.5 text-[10px] font-semibold ring-1 ring-inset ring-current/15',
|
||||
|
||||
@ -489,7 +489,7 @@ export function PurchaseEvaluationsListPage() {
|
||||
<div className="flex min-w-0 flex-1 items-center gap-1 truncate text-[13px] font-medium text-slate-900">
|
||||
{/* S77 — cờ gấp PILL đồng bộ mọi danh sách: 🔴 GẤP (PRO) / 🟢 GẤP (CCM). */}
|
||||
<PeUrgentChips isUrgentByPro={p.isUrgentByPro} isUrgentByCcm={p.isUrgentByCcm} />
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} />
|
||||
<PeFinalizeChip endsBeforeCeo={p.endsBeforeCeo} finalizeStepName={p.finalizeStepName} phase={p.phase} />
|
||||
<span className="truncate">{p.tenGoiThau}</span>
|
||||
</div>
|
||||
<span
|
||||
|
||||
Reference in New Issue
Block a user