feat(scheduling): rename 完成→年度达标, add sort by 客户日均/年度达标 to list
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { ArrowRightLeft, ChevronRight } from 'lucide-react';
|
||||
import { useState, useMemo } from 'react';
|
||||
import { ArrowRightLeft, ChevronRight, ArrowDown, ArrowUp, ArrowUpDown } from 'lucide-react';
|
||||
import { motion } from 'motion/react';
|
||||
import type { SchedulingSuggestion } from './types';
|
||||
import Blur from '../../components/Blur';
|
||||
@@ -12,7 +13,27 @@ function fmtRate(rate: number): string {
|
||||
return (rate * 100).toFixed(1) + '%';
|
||||
}
|
||||
|
||||
type SortKey = 'default' | 'avgDaily' | 'completion';
|
||||
type SortDir = 'asc' | 'desc';
|
||||
|
||||
export default function SuggestionList({ suggestions, onSelect }: Props) {
|
||||
const [sortKey, setSortKey] = useState<SortKey>('default');
|
||||
const [sortDir, setSortDir] = useState<SortDir>('desc');
|
||||
|
||||
const toggleSort = (key: SortKey) => {
|
||||
if (sortKey === key) { setSortDir(d => d === 'desc' ? 'asc' : 'desc'); }
|
||||
else { setSortKey(key); setSortDir('desc'); }
|
||||
};
|
||||
|
||||
const sorted = useMemo(() => {
|
||||
if (sortKey === 'default') return suggestions;
|
||||
return [...suggestions].sort((a, b) => {
|
||||
const va = sortKey === 'avgDaily' ? a.currentVehicle.customerAvgDaily : a.currentVehicle.completionRate;
|
||||
const vb = sortKey === 'avgDaily' ? b.currentVehicle.customerAvgDaily : b.currentVehicle.completionRate;
|
||||
return sortDir === 'desc' ? vb - va : va - vb;
|
||||
});
|
||||
}, [suggestions, sortKey, sortDir]);
|
||||
|
||||
if (suggestions.length === 0) {
|
||||
return (
|
||||
<div className="py-16 text-center">
|
||||
@@ -23,8 +44,33 @@ export default function SuggestionList({ suggestions, onSelect }: Props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* Sort controls */}
|
||||
<div className="px-4 py-2 border-b border-slate-50 flex items-center gap-2">
|
||||
<button
|
||||
onClick={() => toggleSort('avgDaily')}
|
||||
className={`text-[10px] px-2 py-1 rounded-lg border flex items-center gap-1 cursor-pointer transition-colors ${
|
||||
sortKey === 'avgDaily' ? 'border-blue-300 bg-blue-50 text-blue-700' : 'border-slate-200 text-slate-500'
|
||||
}`}
|
||||
>
|
||||
客户日均
|
||||
{sortKey === 'avgDaily' && (sortDir === 'desc' ? <ArrowDown size={10} /> : <ArrowUp size={10} />)}
|
||||
{sortKey !== 'avgDaily' && <ArrowUpDown size={10} />}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => toggleSort('completion')}
|
||||
className={`text-[10px] px-2 py-1 rounded-lg border flex items-center gap-1 cursor-pointer transition-colors ${
|
||||
sortKey === 'completion' ? 'border-blue-300 bg-blue-50 text-blue-700' : 'border-slate-200 text-slate-500'
|
||||
}`}
|
||||
>
|
||||
年度达标
|
||||
{sortKey === 'completion' && (sortDir === 'desc' ? <ArrowDown size={10} /> : <ArrowUp size={10} />)}
|
||||
{sortKey !== 'completion' && <ArrowUpDown size={10} />}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="divide-y divide-slate-50">
|
||||
{suggestions.map((s, idx) => {
|
||||
{sorted.map((s, idx) => {
|
||||
const isRescue = s.type === 'rescue_hopeless';
|
||||
const v = s.currentVehicle;
|
||||
|
||||
@@ -60,7 +106,7 @@ export default function SuggestionList({ suggestions, onSelect }: Props) {
|
||||
{v.manager && <span className="flex-shrink-0 text-slate-500">{v.manager}</span>}
|
||||
<span className="truncate max-w-[35%] flex-shrink"><Blur>{v.customer || '-'}</Blur></span>
|
||||
<span className="flex-shrink-0">日均 <span className="text-slate-600 font-medium">{Math.round(v.customerAvgDaily)}</span></span>
|
||||
<span className="flex-shrink-0">完成 <span className={`font-medium ${v.completionRate >= 1 ? 'text-emerald-600' : v.completionRate >= 0.5 ? 'text-amber-600' : 'text-rose-500'}`}>{fmtRate(v.completionRate)}</span></span>
|
||||
<span className="flex-shrink-0">年度达标 <span className={`font-medium ${v.completionRate >= 1 ? 'text-emerald-600' : v.completionRate >= 0.5 ? 'text-amber-600' : 'text-rose-500'}`}>{fmtRate(v.completionRate)}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -73,5 +119,6 @@ export default function SuggestionList({ suggestions, onSelect }: Props) {
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user