[CLAUDE] FE-User: tab strip 4 giai doan tren phieu PE + menu 4-GD + danh so 01-07 nhom HD (UAT anh Kiet)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m44s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m44s
- PePipelineStrip moi (mirror x2 app md5-identical): Duyet NCC | Ke hoach ky ket HD | Duyet hop dong | Hop dong cung — chen dau PeDetailTabs (GD1 active) - Menu 4-GD: rename 2 root (PurchaseEvaluations->Duyet NCC, Contracts->Duyet hop dong) + 2 root placeholder KeHoachKyKet/HopDongCung (ngoai MenuKeys.All, staticMap -> /dashboard) — prod da SQL truc tiep cung ngay, seeder+labelBackfill giu hoi tu (gotcha #11) - Danh so 01.-07. nhom HD: prod prepend-only 0-VN-over-wire (renamed=7), seeder typeLabels + labelBackfill 7 entry - Dong bo nhan 4-GD tren dashboard (3 title + 3 group aria) - reviewKeys += 2 placeholder CanRead-only; test 562 PASS; build fe x2 PASS Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@ -18,6 +18,7 @@ import { getErrorMessage } from '@/lib/apiError'
|
||||
import { cn } from '@/lib/cn'
|
||||
import { useAuth } from '@/contexts/AuthContext'
|
||||
import { AttachmentPreviewDialog, isPreviewable } from './AttachmentPreviewDialog'
|
||||
import { PePipelineStrip } from './PePipelineStrip'
|
||||
import {
|
||||
PeAttachmentPurpose,
|
||||
PeAttachmentPurposeLabel,
|
||||
@ -272,6 +273,8 @@ export function PeDetailTabs({
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border border-slate-200 bg-white shadow-sm">
|
||||
{/* [S159] dải 4 giai đoạn toàn trình — owner vẽ tab lên ảnh phiếu (phiếu PE ⇒ GĐ1 active) */}
|
||||
<PePipelineStrip current={1} />
|
||||
<div className="flex flex-wrap items-center justify-between gap-2 border-b border-slate-200 px-5 py-3">
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
65
fe-admin/src/components/pe/PePipelineStrip.tsx
Normal file
65
fe-admin/src/components/pe/PePipelineStrip.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
// PePipelineStrip — dải 4 giai đoạn toàn trình, đặt trên đầu detail phiếu Duyệt NCC.
|
||||
// [S159 2026-07-29] Owner vẽ tab strip trực tiếp lên ảnh phiếu + chốt tên qua chat:
|
||||
// "Duyệt NCC | Kế hoạch ký kết HĐ | Duyệt hợp đồng | Hợp đồng cứng"
|
||||
// (2 chỉnh verbatim: "Trình ký Hợp đồng đổi thành Duyệt hợp đồng, ký cứng -> Hợp đồng cứng").
|
||||
// MIRROR ×2 app BYTE-IDENTICAL (cùng họ PeDetailTabs md5-parity) — sửa file này
|
||||
// thì sửa CẢ HAI, verify md5 trước commit.
|
||||
// v1: phiếu PE ⇒ giai đoạn 1 active. GĐ2/GĐ4 chưa có module (badge "Sắp");
|
||||
// GĐ3 có module HĐ nhưng CHƯA nối per-phiếu (cầu PE→KHKK→HĐ ship ở wave GĐ2)
|
||||
// ⇒ mọi stage không-active đều KHÔNG click được — hiển thị lộ trình, không giả link.
|
||||
import { Check } from 'lucide-react'
|
||||
import { cn } from '@/lib/cn'
|
||||
|
||||
const STAGES = [
|
||||
{ n: 1, label: 'Duyệt NCC', soon: false },
|
||||
{ n: 2, label: 'Kế hoạch ký kết HĐ', soon: true },
|
||||
{ n: 3, label: 'Duyệt hợp đồng', soon: false },
|
||||
{ n: 4, label: 'Hợp đồng cứng', soon: true },
|
||||
] as const
|
||||
|
||||
export function PePipelineStrip({ current = 1 }: { current?: number }) {
|
||||
return (
|
||||
<div
|
||||
role="list"
|
||||
aria-label="Toàn trình 4 giai đoạn"
|
||||
className="flex items-stretch gap-1 overflow-x-auto rounded-t-lg border-b border-slate-200 bg-slate-50/70 px-2 py-1.5"
|
||||
>
|
||||
{STAGES.map((s, i) => {
|
||||
const active = s.n === current
|
||||
return (
|
||||
<div key={s.n} role="listitem" className="flex min-w-0 flex-1 items-center gap-1">
|
||||
<div
|
||||
aria-current={active ? 'step' : undefined}
|
||||
title={
|
||||
active
|
||||
? 'Giai đoạn hiện tại'
|
||||
: s.soon
|
||||
? 'Sắp triển khai'
|
||||
: 'Sẽ nối khi giai đoạn trước hoàn tất'
|
||||
}
|
||||
className={cn(
|
||||
'flex w-full min-w-0 items-center justify-center gap-1.5 rounded-md px-2 py-1.5 text-center text-[11px] font-medium leading-tight',
|
||||
active
|
||||
? 'bg-brand-600 text-white shadow-sm'
|
||||
: 'border border-dashed border-slate-300 bg-white text-slate-500',
|
||||
)}
|
||||
>
|
||||
{active && <Check aria-hidden className="h-3 w-3 shrink-0" />}
|
||||
<span className="truncate">{s.label}</span>
|
||||
{s.soon && !active && (
|
||||
<span className="shrink-0 rounded bg-slate-100 px-1 text-[9px] font-semibold uppercase tracking-wide text-slate-400">
|
||||
Sắp
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{i < STAGES.length - 1 && (
|
||||
<span aria-hidden className="shrink-0 px-0.5 text-slate-300">
|
||||
→
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user