refactor: simplify order sidebar
This commit is contained in:
@@ -207,7 +207,6 @@ export function Dashboard() {
|
||||
selectedOrderId={selectedOrder.id}
|
||||
search={search}
|
||||
activeOrder={selectedOrder}
|
||||
showProjectDossier={orders.length === 1}
|
||||
onSearchChange={setSearch}
|
||||
onSelectOrder={handleSelectOrder}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { renderToStaticMarkup } from 'react-dom/server'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { createMockOrders } from '@/data/mock-data'
|
||||
import { OrderSidebar } from './OrderSidebar'
|
||||
|
||||
describe('OrderSidebar', () => {
|
||||
const sourceOrders = createMockOrders()
|
||||
const activeOrder = sourceOrders[0]
|
||||
|
||||
it('keeps the order list and active BOM dossier without legacy filters or pagination', () => {
|
||||
const markup = renderToStaticMarkup(
|
||||
<OrderSidebar
|
||||
orders={sourceOrders.slice(0, 3)}
|
||||
activeOrder={activeOrder}
|
||||
selectedOrderId={activeOrder.id}
|
||||
search=""
|
||||
onSearchChange={() => undefined}
|
||||
onSelectOrder={() => undefined}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(markup).toContain('订单列表')
|
||||
expect(markup).toContain('项目 BOM 档案')
|
||||
expect(markup).not.toContain('筛选订单')
|
||||
expect(markup).not.toContain('全部状态')
|
||||
expect(markup).not.toContain('全部产线')
|
||||
expect(markup).not.toContain('订单分页')
|
||||
})
|
||||
|
||||
it('keeps the active BOM dossier when the search result is empty', () => {
|
||||
const markup = renderToStaticMarkup(
|
||||
<OrderSidebar
|
||||
orders={[]}
|
||||
activeOrder={activeOrder}
|
||||
selectedOrderId={activeOrder.id}
|
||||
search="missing"
|
||||
onSearchChange={() => undefined}
|
||||
onSelectOrder={() => undefined}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(markup).toContain('没有匹配订单')
|
||||
expect(markup).toContain('修改搜索关键词后重试')
|
||||
expect(markup).toContain('项目 BOM 档案')
|
||||
})
|
||||
})
|
||||
@@ -1,16 +1,12 @@
|
||||
import { useMemo } from 'react'
|
||||
import {
|
||||
Boxes,
|
||||
ChevronDown,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
DatabaseZap,
|
||||
GitBranch,
|
||||
Layers3,
|
||||
PackageOpen,
|
||||
Search,
|
||||
ShieldAlert,
|
||||
SlidersHorizontal,
|
||||
} from 'lucide-react'
|
||||
import type { OrderSummary, RiskLevel } from '@/types'
|
||||
import { calculateOrderTreeStats, riskMeta, statusMeta } from '@/lib/production'
|
||||
@@ -21,7 +17,6 @@ import { RingProgress, TechVisual } from './TechVisual'
|
||||
interface OrderSidebarProps {
|
||||
orders: OrderSummary[]
|
||||
activeOrder: OrderSummary
|
||||
showProjectDossier: boolean
|
||||
selectedOrderId: string
|
||||
search: string
|
||||
onSearchChange: (value: string) => void
|
||||
@@ -31,39 +26,24 @@ interface OrderSidebarProps {
|
||||
export function OrderSidebar({
|
||||
orders,
|
||||
activeOrder,
|
||||
showProjectDossier,
|
||||
selectedOrderId,
|
||||
search,
|
||||
onSearchChange,
|
||||
onSelectOrder,
|
||||
}: OrderSidebarProps) {
|
||||
return (
|
||||
<aside className={`dashboard-panel sidebar-panel ${showProjectDossier ? 'has-project-dossier' : ''}`}>
|
||||
<aside className="dashboard-panel sidebar-panel has-project-dossier">
|
||||
<div className="sidebar-heading">
|
||||
<PanelTitle icon={<Boxes />} title="订单总览" subtitle={`${orders.length} 个订单`} />
|
||||
<button type="button" className="icon-tool-button" aria-label="筛选订单">
|
||||
<SlidersHorizontal />
|
||||
<span>筛选</span>
|
||||
</button>
|
||||
<PanelTitle icon={<Boxes />} title="订单列表" subtitle={`${orders.length} 个订单`} />
|
||||
</div>
|
||||
|
||||
<div className="sidebar-filter-card">
|
||||
<div className="select-row">
|
||||
<button type="button" className="select-chip">
|
||||
<span>全部状态</span>
|
||||
<ChevronDown />
|
||||
</button>
|
||||
<button type="button" className="select-chip">
|
||||
<span>全部产线</span>
|
||||
<ChevronDown />
|
||||
</button>
|
||||
</div>
|
||||
<label className="search-field">
|
||||
<Search aria-hidden="true" />
|
||||
<Input
|
||||
value={search}
|
||||
onChange={(event) => onSearchChange(event.target.value)}
|
||||
placeholder="搜索订单号/产品"
|
||||
placeholder="搜索订单号/产品/产线"
|
||||
aria-label="搜索订单"
|
||||
/>
|
||||
</label>
|
||||
@@ -113,24 +93,12 @@ export function OrderSidebar({
|
||||
<div className="empty-state">
|
||||
<ShieldAlert aria-hidden="true" />
|
||||
<strong>没有匹配订单</strong>
|
||||
<span>调整搜索或筛选条件后重试</span>
|
||||
<span>修改搜索关键词后重试</span>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{showProjectDossier ? <ProjectDossier order={activeOrder} /> : (
|
||||
<div className="sidebar-pagination" aria-label="订单分页">
|
||||
<button type="button" aria-label="上一页"><ChevronLeft /></button>
|
||||
<button type="button" className="is-active">1</button>
|
||||
<button type="button">2</button>
|
||||
<button type="button">3</button>
|
||||
<button type="button">4</button>
|
||||
<button type="button">5</button>
|
||||
<span>...</span>
|
||||
<button type="button">22</button>
|
||||
<button type="button" aria-label="下一页"><ChevronRight /></button>
|
||||
</div>
|
||||
)}
|
||||
<ProjectDossier order={activeOrder} />
|
||||
</aside>
|
||||
)
|
||||
}
|
||||
|
||||
+6
-67
@@ -859,10 +859,7 @@ svg {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.icon-tool-button,
|
||||
.select-chip,
|
||||
.flow-toolbar button,
|
||||
.sidebar-pagination button {
|
||||
.flow-toolbar button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -880,24 +877,12 @@ svg {
|
||||
background 180ms ease;
|
||||
}
|
||||
|
||||
.icon-tool-button {
|
||||
padding: 0 9px;
|
||||
font-family: var(--font-sans);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.icon-tool-button svg,
|
||||
.select-chip svg,
|
||||
.flow-toolbar svg,
|
||||
.sidebar-pagination svg {
|
||||
.flow-toolbar svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.icon-tool-button:hover,
|
||||
.select-chip:hover,
|
||||
.flow-toolbar button:hover,
|
||||
.sidebar-pagination button:hover {
|
||||
.flow-toolbar button:hover {
|
||||
color: var(--foreground);
|
||||
border-color: var(--border-strong);
|
||||
background:
|
||||
@@ -911,24 +896,10 @@ svg {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.select-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 7px;
|
||||
}
|
||||
|
||||
.select-chip {
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 0 10px;
|
||||
font-family: var(--font-sans);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.search-field {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin-top: 7px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.search-field svg {
|
||||
@@ -1103,36 +1074,6 @@ svg {
|
||||
height: 43px;
|
||||
}
|
||||
|
||||
.sidebar-pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
min-height: 28px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.sidebar-pagination button {
|
||||
min-width: 25px;
|
||||
min-height: 25px;
|
||||
padding: 0 6px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.sidebar-pagination button.is-active {
|
||||
color: #ecfeff;
|
||||
border-color: var(--cyan);
|
||||
background: linear-gradient(180deg, rgba(47, 148, 255, 0.78), rgba(19, 200, 246, 0.34));
|
||||
}
|
||||
|
||||
.sidebar-pagination span {
|
||||
color: var(--muted);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.flow-panel-head {
|
||||
position: relative;
|
||||
justify-content: space-between;
|
||||
@@ -3229,8 +3170,8 @@ svg {
|
||||
}
|
||||
|
||||
.has-project-dossier .order-list {
|
||||
flex: 0 0 auto;
|
||||
max-height: 96px;
|
||||
flex: 0 1 auto;
|
||||
max-height: 42%;
|
||||
}
|
||||
|
||||
.has-project-dossier .order-row {
|
||||
@@ -4067,7 +4008,6 @@ svg {
|
||||
.panel-title h2,
|
||||
.mini-panel-head h2,
|
||||
.flow-panel-head h2 { font-size: var(--text-panel); }
|
||||
.has-project-dossier .order-list { max-height: 110px; }
|
||||
.has-project-dossier .order-row { height: 100px; }
|
||||
.project-stat-grid > div { min-height: 44px; }
|
||||
}
|
||||
@@ -4112,7 +4052,6 @@ svg {
|
||||
.mini-panel-head p { font-size: 14px; }
|
||||
.sidebar-panel,
|
||||
.detail-panel { padding: 12px; }
|
||||
.has-project-dossier .order-list { max-height: 136px; }
|
||||
.has-project-dossier .order-row { height: 122px; }
|
||||
.order-row-main { height: 86px; grid-template-rows: repeat(4, minmax(18px, auto)); }
|
||||
.order-row-titleline strong { font-size: 15px; }
|
||||
|
||||
Reference in New Issue
Block a user