[CLAUDE] Contract: GD3-D cay toan trinh vao Panel-3 (slot 63 owner chot D + "mo rong" = ca 3 trang) + prop bodyMaxHClass (gate F-1)

- Owner @S168: (63)(b)=D cay-thay-Panel-3 · (a) "cu mo rong" -> ca 3 trang 3-panel {fe-user MyContractsPage + InboxPage · fe-admin ContractsListPage}; WorkflowMatrixViewPage KHONG ap (trang bang full-width 0-Panel-3 — khai chu dich, gate F-8 phan lead DUNG)
- Panel-3 khi CHUA chon HD: PipelineTreePanel currentStage=3 the cho o trong "Quy trinh duyet se hien khi chon HD"; chon HD -> nhuong cho WorkflowHistoryPanel (trade-off D khai)
- Gate PASS-WITH-FLAGS-10 (1 MAJOR/6 MINOR/3 INFO, 0 blocker) — disposition tung dong trong sub-reviewer-gate-gd3d.md
- F-1 MAJOR va: khuon +prop bodyMaxHClass (default GIU NGUYEN — 3 host giay-cuon cu 0 doi), 3 host Panel-3 pass lg:max-h-none => panel giu dung 1 thanh cuon (max-h khuon vuot cho /inbox ~26px -> 2 cuon long) — mirror x2 app SHA-pair 7baf6247
- Go X unused import 3 trang (control-am grep co rang)
- build x2 PASS · suite 642/0 (45D+597I)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-08-01 16:49:46 +07:00
parent a2b37dcccc
commit 081557b441
5 changed files with 39 additions and 23 deletions

View File

@ -86,9 +86,15 @@ function buildTree(rows: PeListItem[]): YearNode[] {
export function PipelineTreePanel({
currentStage,
className,
bodyMaxHClass,
}: {
currentStage: PipelineStageNo
className?: string
// [S168 GĐ3-D gate F-1] Host 3-panel (Panel-3 TỰ CUỘN) truyền class trần riêng cho THÂN
// cây (vd `lg:max-h-none` — panel giữ đúng 1 thanh cuộn; max-h mặc định 100vh16rem là
// hiệu-chỉnh cho trang giấy-cuộn, vượt chỗ Panel-3 /inbox ~26px ⇒ 2 cuộn lồng nhau).
// Mặc định giữ nguyên — 3 host giấy-cuộn cũ không đổi hành vi.
bodyMaxHClass?: string
}) {
const { canPe, buildStages } = usePipelineStages()
const [search, setSearch] = useState('')
@ -212,7 +218,7 @@ export function PipelineTreePanel({
/>
</div>
<div className="max-h-[28rem] overflow-y-auto lg:max-h-[calc(100vh-16rem)]">
<div className={cn('overflow-y-auto', bodyMaxHClass ?? 'max-h-[28rem] lg:max-h-[calc(100vh-16rem)]')}>
{!canPe && (
<p className="px-3 py-4 text-[12px] text-slate-500">
Bạn chưa quyền xem phiếu Duyệt NCC nên cây toàn trình chưa hiển thị đưc.

View File

@ -14,9 +14,10 @@
import { useMemo } from 'react'
import { useQuery } from '@tanstack/react-query'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { FileText, Search, X } from 'lucide-react'
import { FileText, Search } from 'lucide-react'
import { ContractDetailContent } from '@/components/contracts/ContractDetailContent'
import { WorkflowHistoryPanel } from '@/components/contracts/WorkflowHistoryPanel'
import { PipelineTreePanel } from '@/components/pipeline/PipelineTreePanel'
import { PhaseBadge } from '@/components/PhaseBadge'
import { SlaTimer } from '@/components/SlaTimer'
import { EmptyState } from '@/components/EmptyState'
@ -240,12 +241,12 @@ export function ContractsListPage() {
{/* Panel 3 — Workflow + history */}
<aside className="hidden overflow-y-auto border-l border-slate-200 bg-white p-4 lg:block">
{!selectedId && (
<div className="rounded-lg border border-dashed border-slate-200 p-6 text-center text-sm text-slate-400">
<X className="mx-auto mb-2 h-5 w-5" />
Quy trình duyệt sẽ hiện khi chọn .
</div>
)}
{/* [S168 GĐ3-D — owner slot (63) chốt D] Chưa chọn HĐ ⇒ cây toàn trình (GĐ3)
thế chỗ ô trống; chọn HĐ thì nhường chỗ cho quy trình duyệt. Trade-off D
(cây rời panel khi chọn HĐ) — sub-implfe-gd3.md §1. */}
{/* [gate F-1/F-2] Panel-3 TỰ CUỘN ⇒ thân cây `lg:max-h-none` giữ đúng 1 thanh cuộn;
sticky/self-start của khuôn vô hiệu ở host display:block này — by-design. */}
{!selectedId && <PipelineTreePanel currentStage={3} bodyMaxHClass="max-h-[28rem] lg:max-h-none" />}
{selectedId && detail.data && <WorkflowHistoryPanel contract={detail.data} />}
</aside>
</div>

View File

@ -86,9 +86,15 @@ function buildTree(rows: PeListItem[]): YearNode[] {
export function PipelineTreePanel({
currentStage,
className,
bodyMaxHClass,
}: {
currentStage: PipelineStageNo
className?: string
// [S168 GĐ3-D gate F-1] Host 3-panel (Panel-3 TỰ CUỘN) truyền class trần riêng cho THÂN
// cây (vd `lg:max-h-none` — panel giữ đúng 1 thanh cuộn; max-h mặc định 100vh16rem là
// hiệu-chỉnh cho trang giấy-cuộn, vượt chỗ Panel-3 /inbox ~26px ⇒ 2 cuộn lồng nhau).
// Mặc định giữ nguyên — 3 host giấy-cuộn cũ không đổi hành vi.
bodyMaxHClass?: string
}) {
const { canPe, buildStages } = usePipelineStages()
const [search, setSearch] = useState('')
@ -212,7 +218,7 @@ export function PipelineTreePanel({
/>
</div>
<div className="max-h-[28rem] overflow-y-auto lg:max-h-[calc(100vh-16rem)]">
<div className={cn('overflow-y-auto', bodyMaxHClass ?? 'max-h-[28rem] lg:max-h-[calc(100vh-16rem)]')}>
{!canPe && (
<p className="px-3 py-4 text-[12px] text-slate-500">
Bạn chưa quyền xem phiếu Duyệt NCC nên cây toàn trình chưa hiển thị đưc.

View File

@ -7,9 +7,10 @@
import { useMemo } from 'react'
import { useQuery } from '@tanstack/react-query'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { Inbox, AlertTriangle, Clock, FileText, Search, X, ClipboardList } from 'lucide-react'
import { Inbox, AlertTriangle, Clock, FileText, Search, ClipboardList } from 'lucide-react'
import { ContractDetailContent } from '@/components/contracts/ContractDetailContent'
import { WorkflowHistoryPanel } from '@/components/contracts/WorkflowHistoryPanel'
import { PipelineTreePanel } from '@/components/pipeline/PipelineTreePanel'
import { PhaseBadge } from '@/components/PhaseBadge'
import { SlaTimer } from '@/components/SlaTimer'
import { EmptyState } from '@/components/EmptyState'
@ -338,12 +339,13 @@ export function InboxPage() {
{/* Panel 3 — Workflow + history */}
<aside className="hidden overflow-y-auto border-l border-slate-200 bg-white p-4 lg:block">
{!selectedId && (
<div className="rounded-lg border border-dashed border-slate-200 p-6 text-center text-sm text-slate-400">
<X className="mx-auto mb-2 h-5 w-5" />
Quy trình duyệt sẽ hiện khi chọn .
</div>
)}
{/* [S168 GĐ3-D — owner slot (63) chốt D] Chưa chọn HĐ ⇒ cây toàn trình (GĐ3)
thế chỗ ô trống; chọn HĐ thì nhường chỗ cho quy trình duyệt. Trade-off D
(cây rời panel khi chọn HĐ) — sub-implfe-gd3.md §1. */}
{/* [gate F-1/F-2] Panel-3 TỰ CUỘN ⇒ thân cây `lg:max-h-none` giữ đúng 1 thanh cuộn
(chính /inbox là trang THIẾU ~26px vì dải stats + banner vai trò); sticky/self-start
của khuôn vô hiệu ở host display:block này — by-design. */}
{!selectedId && <PipelineTreePanel currentStage={3} bodyMaxHClass="max-h-[28rem] lg:max-h-none" />}
{selectedId && detail.data && <WorkflowHistoryPanel contract={detail.data} />}
</aside>
</div>

View File

@ -7,9 +7,10 @@
import { useMemo } from 'react'
import { useQuery } from '@tanstack/react-query'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { FileText, Plus, Search, X } from 'lucide-react'
import { FileText, Plus, Search } from 'lucide-react'
import { ContractDetailContent } from '@/components/contracts/ContractDetailContent'
import { WorkflowHistoryPanel } from '@/components/contracts/WorkflowHistoryPanel'
import { PipelineTreePanel } from '@/components/pipeline/PipelineTreePanel'
import { PhaseBadge } from '@/components/PhaseBadge'
import { SlaTimer } from '@/components/SlaTimer'
import { EmptyState } from '@/components/EmptyState'
@ -216,12 +217,12 @@ export function MyContractsPage() {
{/* Panel 3 — Workflow + history */}
<aside className="hidden overflow-y-auto border-l border-slate-200 bg-white p-4 lg:block">
{!selectedId && (
<div className="rounded-lg border border-dashed border-slate-200 p-6 text-center text-sm text-slate-400">
<X className="mx-auto mb-2 h-5 w-5" />
Quy trình duyệt sẽ hiện khi chọn .
</div>
)}
{/* [S168 GĐ3-D — owner slot (63) chốt D] Chưa chọn HĐ ⇒ cây toàn trình (GĐ3)
thế chỗ ô trống; chọn HĐ thì nhường chỗ cho quy trình duyệt. Trade-off D
(cây rời panel khi chọn HĐ) — sub-implfe-gd3.md §1. */}
{/* [gate F-1/F-2] Panel-3 TỰ CUỘN ⇒ thân cây `lg:max-h-none` giữ đúng 1 thanh cuộn;
sticky/self-start của khuôn vô hiệu ở host display:block này — by-design. */}
{!selectedId && <PipelineTreePanel currentStage={3} bodyMaxHClass="max-h-[28rem] lg:max-h-none" />}
{selectedId && detail.data && <WorkflowHistoryPanel contract={detail.data} />}
</aside>
</div>