[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:
@ -57,6 +57,11 @@ function resolvePath(key: string): string | null {
|
||||
Dashboard: '/dashboard',
|
||||
Contracts: '/my-contracts',
|
||||
PurchaseEvaluations: '/purchase-evaluations',
|
||||
// [S159 2026-07-29] 2 root placeholder giai đoạn 2/4 (owner: menu hiển thị đúng 4 GĐ
|
||||
// như tab strip). Module chưa build → trỏ về Tổng quan pipeline (khung "Sắp triển khai").
|
||||
// LESSON gotcha #50: key DB mới PHẢI có route ở đây, không thì sidebar drop SILENT.
|
||||
KeHoachKyKet: '/dashboard',
|
||||
HopDongCung: '/dashboard',
|
||||
// [Plan CA Hotfix 1 S29 2026-05-22] 4 master + 4 catalog leaf moved từ
|
||||
// fe-admin → fe-user. resolvePath PHẢI có route mapping nếu không
|
||||
// MenuLeaf line 238 `if (!path) return null` → sidebar drop silent.
|
||||
|
||||
@ -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-user/src/components/pe/PePipelineStrip.tsx
Normal file
65
fe-user/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>
|
||||
)
|
||||
}
|
||||
@ -2,9 +2,9 @@
|
||||
// [S159 2026-07-29 — owner chốt qua AskUser] Hero = dải pipeline 4 GIAI ĐOẠN xuyên
|
||||
// suốt quy trình mua sắm → ký kết hợp đồng:
|
||||
// GĐ1 Duyệt NCC (bước 1 → 6, CEO chốt) 🟢 LIVE — module PE
|
||||
// GĐ2 Đề xuất ký kết hợp đồng (bước 7 → 12) ⏳ sắp triển khai
|
||||
// GĐ3 Duyệt Hợp đồng (bước 13 → 18) 🟢 LIVE — module Contract
|
||||
// GĐ4 Ký cứng & phát hành (bước 19 → 21) ⏳ sắp triển khai
|
||||
// GĐ2 Kế hoạch ký kết HĐ (bước 7 → 12) ⏳ sắp triển khai
|
||||
// GĐ3 Duyệt hợp đồng (bước 13 → 18) 🟢 LIVE — module Contract
|
||||
// GĐ4 Hợp đồng cứng (bước 19 → 21) ⏳ sắp triển khai
|
||||
// Dưới hero GIỮ nguyên KPI cá nhân + 2 danh sách gần đây (chỉ redesign cho hài hoà).
|
||||
// fe-user ONLY — KHÔNG mirror sang fe-admin (trang này là UX riêng của user).
|
||||
//
|
||||
@ -473,7 +473,7 @@ export function UserDashboardPage() {
|
||||
<StageArrow />
|
||||
|
||||
{/* GĐ2 — sắp triển khai */}
|
||||
<StageCard index={2} title="Đề xuất ký kết hợp đồng" stepRange="Bước 7 → 12" icon={FileSignature}>
|
||||
<StageCard index={2} title="Kế hoạch ký kết HĐ" stepRange="Bước 7 → 12" icon={FileSignature}>
|
||||
<StageSoon
|
||||
description="Phiếu nối tiếp từ phiếu Duyệt NCC đã duyệt — chốt giá trị ký kết."
|
||||
hint={
|
||||
@ -489,14 +489,14 @@ export function UserDashboardPage() {
|
||||
{/* GĐ3 — LIVE */}
|
||||
<StageCard
|
||||
index={3}
|
||||
title="Duyệt Hợp đồng"
|
||||
title="Duyệt hợp đồng"
|
||||
stepRange="Bước 13 → 18"
|
||||
icon={FileText}
|
||||
tone="teal"
|
||||
>
|
||||
<div className="space-y-0.5">
|
||||
<StageStatRow
|
||||
group="Duyệt Hợp đồng"
|
||||
group="Duyệt hợp đồng"
|
||||
label="Tổng hợp đồng"
|
||||
value={recent.data?.total}
|
||||
tone="teal"
|
||||
@ -505,7 +505,7 @@ export function UserDashboardPage() {
|
||||
onClick={() => navigate('/my-contracts')}
|
||||
/>
|
||||
<StageStatRow
|
||||
group="Duyệt Hợp đồng"
|
||||
group="Duyệt hợp đồng"
|
||||
label="Chờ tôi duyệt"
|
||||
value={s?.pendingMyApproval}
|
||||
tone="teal"
|
||||
@ -515,7 +515,7 @@ export function UserDashboardPage() {
|
||||
onClick={() => navigate('/inbox')}
|
||||
/>
|
||||
<StageStatRow
|
||||
group="Duyệt Hợp đồng"
|
||||
group="Duyệt hợp đồng"
|
||||
label="Đã quá hạn"
|
||||
value={s?.overdue}
|
||||
tone="teal"
|
||||
@ -531,7 +531,7 @@ export function UserDashboardPage() {
|
||||
<StageArrow />
|
||||
|
||||
{/* GĐ4 — sắp triển khai */}
|
||||
<StageCard index={4} title="Ký cứng & phát hành" stepRange="Bước 19 → 21" icon={Stamp}>
|
||||
<StageCard index={4} title="Hợp đồng cứng" stepRange="Bước 19 → 21" icon={Stamp}>
|
||||
<StageSoon description="Tải lên bản hợp đồng đã ký cứng." />
|
||||
</StageCard>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user