[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:
@ -86,9 +86,15 @@ function buildTree(rows: PeListItem[]): YearNode[] {
|
|||||||
export function PipelineTreePanel({
|
export function PipelineTreePanel({
|
||||||
currentStage,
|
currentStage,
|
||||||
className,
|
className,
|
||||||
|
bodyMaxHClass,
|
||||||
}: {
|
}: {
|
||||||
currentStage: PipelineStageNo
|
currentStage: PipelineStageNo
|
||||||
className?: string
|
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 100vh−16rem 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 { canPe, buildStages } = usePipelineStages()
|
||||||
const [search, setSearch] = useState('')
|
const [search, setSearch] = useState('')
|
||||||
@ -212,7 +218,7 @@ export function PipelineTreePanel({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</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 && (
|
{!canPe && (
|
||||||
<p className="px-3 py-4 text-[12px] text-slate-500">
|
<p className="px-3 py-4 text-[12px] text-slate-500">
|
||||||
Bạn chưa có quyền xem phiếu Duyệt NCC nên cây toàn trình chưa hiển thị được.
|
Bạn chưa có quyền xem phiếu Duyệt NCC nên cây toàn trình chưa hiển thị được.
|
||||||
|
|||||||
@ -14,9 +14,10 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { useQuery } from '@tanstack/react-query'
|
import { useQuery } from '@tanstack/react-query'
|
||||||
import { useNavigate, useSearchParams } from 'react-router-dom'
|
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 { ContractDetailContent } from '@/components/contracts/ContractDetailContent'
|
||||||
import { WorkflowHistoryPanel } from '@/components/contracts/WorkflowHistoryPanel'
|
import { WorkflowHistoryPanel } from '@/components/contracts/WorkflowHistoryPanel'
|
||||||
|
import { PipelineTreePanel } from '@/components/pipeline/PipelineTreePanel'
|
||||||
import { PhaseBadge } from '@/components/PhaseBadge'
|
import { PhaseBadge } from '@/components/PhaseBadge'
|
||||||
import { SlaTimer } from '@/components/SlaTimer'
|
import { SlaTimer } from '@/components/SlaTimer'
|
||||||
import { EmptyState } from '@/components/EmptyState'
|
import { EmptyState } from '@/components/EmptyState'
|
||||||
@ -240,12 +241,12 @@ export function ContractsListPage() {
|
|||||||
|
|
||||||
{/* Panel 3 — Workflow + history */}
|
{/* Panel 3 — Workflow + history */}
|
||||||
<aside className="hidden overflow-y-auto border-l border-slate-200 bg-white p-4 lg:block">
|
<aside className="hidden overflow-y-auto border-l border-slate-200 bg-white p-4 lg:block">
|
||||||
{!selectedId && (
|
{/* [S168 GĐ3-D — owner slot (63) chốt D] Chưa chọn HĐ ⇒ cây toàn trình (GĐ3)
|
||||||
<div className="rounded-lg border border-dashed border-slate-200 p-6 text-center text-sm text-slate-400">
|
thế chỗ ô trống; chọn HĐ thì nhường chỗ cho quy trình duyệt. Trade-off D
|
||||||
<X className="mx-auto mb-2 h-5 w-5" />
|
(cây rời panel khi chọn HĐ) — sub-implfe-gd3.md §1. */}
|
||||||
Quy trình duyệt sẽ hiện khi chọn HĐ.
|
{/* [gate F-1/F-2] Panel-3 TỰ CUỘN ⇒ thân cây `lg:max-h-none` giữ đúng 1 thanh cuộn;
|
||||||
</div>
|
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} />}
|
{selectedId && detail.data && <WorkflowHistoryPanel contract={detail.data} />}
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -86,9 +86,15 @@ function buildTree(rows: PeListItem[]): YearNode[] {
|
|||||||
export function PipelineTreePanel({
|
export function PipelineTreePanel({
|
||||||
currentStage,
|
currentStage,
|
||||||
className,
|
className,
|
||||||
|
bodyMaxHClass,
|
||||||
}: {
|
}: {
|
||||||
currentStage: PipelineStageNo
|
currentStage: PipelineStageNo
|
||||||
className?: string
|
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 100vh−16rem 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 { canPe, buildStages } = usePipelineStages()
|
||||||
const [search, setSearch] = useState('')
|
const [search, setSearch] = useState('')
|
||||||
@ -212,7 +218,7 @@ export function PipelineTreePanel({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</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 && (
|
{!canPe && (
|
||||||
<p className="px-3 py-4 text-[12px] text-slate-500">
|
<p className="px-3 py-4 text-[12px] text-slate-500">
|
||||||
Bạn chưa có quyền xem phiếu Duyệt NCC nên cây toàn trình chưa hiển thị được.
|
Bạn chưa có quyền xem phiếu Duyệt NCC nên cây toàn trình chưa hiển thị được.
|
||||||
|
|||||||
@ -7,9 +7,10 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { useQuery } from '@tanstack/react-query'
|
import { useQuery } from '@tanstack/react-query'
|
||||||
import { useNavigate, useSearchParams } from 'react-router-dom'
|
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 { ContractDetailContent } from '@/components/contracts/ContractDetailContent'
|
||||||
import { WorkflowHistoryPanel } from '@/components/contracts/WorkflowHistoryPanel'
|
import { WorkflowHistoryPanel } from '@/components/contracts/WorkflowHistoryPanel'
|
||||||
|
import { PipelineTreePanel } from '@/components/pipeline/PipelineTreePanel'
|
||||||
import { PhaseBadge } from '@/components/PhaseBadge'
|
import { PhaseBadge } from '@/components/PhaseBadge'
|
||||||
import { SlaTimer } from '@/components/SlaTimer'
|
import { SlaTimer } from '@/components/SlaTimer'
|
||||||
import { EmptyState } from '@/components/EmptyState'
|
import { EmptyState } from '@/components/EmptyState'
|
||||||
@ -338,12 +339,13 @@ export function InboxPage() {
|
|||||||
|
|
||||||
{/* Panel 3 — Workflow + history */}
|
{/* Panel 3 — Workflow + history */}
|
||||||
<aside className="hidden overflow-y-auto border-l border-slate-200 bg-white p-4 lg:block">
|
<aside className="hidden overflow-y-auto border-l border-slate-200 bg-white p-4 lg:block">
|
||||||
{!selectedId && (
|
{/* [S168 GĐ3-D — owner slot (63) chốt D] Chưa chọn HĐ ⇒ cây toàn trình (GĐ3)
|
||||||
<div className="rounded-lg border border-dashed border-slate-200 p-6 text-center text-sm text-slate-400">
|
thế chỗ ô trống; chọn HĐ thì nhường chỗ cho quy trình duyệt. Trade-off D
|
||||||
<X className="mx-auto mb-2 h-5 w-5" />
|
(cây rời panel khi chọn HĐ) — sub-implfe-gd3.md §1. */}
|
||||||
Quy trình duyệt sẽ hiện khi chọn HĐ.
|
{/* [gate F-1/F-2] Panel-3 TỰ CUỘN ⇒ thân cây `lg:max-h-none` giữ đúng 1 thanh cuộn
|
||||||
</div>
|
(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} />}
|
{selectedId && detail.data && <WorkflowHistoryPanel contract={detail.data} />}
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -7,9 +7,10 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { useQuery } from '@tanstack/react-query'
|
import { useQuery } from '@tanstack/react-query'
|
||||||
import { useNavigate, useSearchParams } from 'react-router-dom'
|
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 { ContractDetailContent } from '@/components/contracts/ContractDetailContent'
|
||||||
import { WorkflowHistoryPanel } from '@/components/contracts/WorkflowHistoryPanel'
|
import { WorkflowHistoryPanel } from '@/components/contracts/WorkflowHistoryPanel'
|
||||||
|
import { PipelineTreePanel } from '@/components/pipeline/PipelineTreePanel'
|
||||||
import { PhaseBadge } from '@/components/PhaseBadge'
|
import { PhaseBadge } from '@/components/PhaseBadge'
|
||||||
import { SlaTimer } from '@/components/SlaTimer'
|
import { SlaTimer } from '@/components/SlaTimer'
|
||||||
import { EmptyState } from '@/components/EmptyState'
|
import { EmptyState } from '@/components/EmptyState'
|
||||||
@ -216,12 +217,12 @@ export function MyContractsPage() {
|
|||||||
|
|
||||||
{/* Panel 3 — Workflow + history */}
|
{/* Panel 3 — Workflow + history */}
|
||||||
<aside className="hidden overflow-y-auto border-l border-slate-200 bg-white p-4 lg:block">
|
<aside className="hidden overflow-y-auto border-l border-slate-200 bg-white p-4 lg:block">
|
||||||
{!selectedId && (
|
{/* [S168 GĐ3-D — owner slot (63) chốt D] Chưa chọn HĐ ⇒ cây toàn trình (GĐ3)
|
||||||
<div className="rounded-lg border border-dashed border-slate-200 p-6 text-center text-sm text-slate-400">
|
thế chỗ ô trống; chọn HĐ thì nhường chỗ cho quy trình duyệt. Trade-off D
|
||||||
<X className="mx-auto mb-2 h-5 w-5" />
|
(cây rời panel khi chọn HĐ) — sub-implfe-gd3.md §1. */}
|
||||||
Quy trình duyệt sẽ hiện khi chọn HĐ.
|
{/* [gate F-1/F-2] Panel-3 TỰ CUỘN ⇒ thân cây `lg:max-h-none` giữ đúng 1 thanh cuộn;
|
||||||
</div>
|
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} />}
|
{selectedId && detail.data && <WorkflowHistoryPanel contract={detail.data} />}
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user