Files
dukang/apps/mini-user/src/components/CategoryPicker.tsx
T

160 lines
4.4 KiB
TypeScript

import { useEffect, useMemo, useState } from 'react';
import { View, Text, ScrollView } from '@tarojs/components';
export type StoreCategoryNode = {
id: string;
name: string;
children?: StoreCategoryNode[];
};
export type CategorySelection = {
parentId: string;
parentName: string;
childId: string;
childName: string;
};
export const EMPTY_CATEGORY: CategorySelection = {
parentId: '',
parentName: '',
childId: '',
childName: '',
};
export function formatCategoryLabel(sel: CategorySelection): string {
if (sel.childName) return sel.childName;
if (sel.parentName) return sel.parentName;
return '全部分类';
}
type CategoryPickerProps = {
open: boolean;
tree: StoreCategoryNode[];
value: CategorySelection;
onClose: () => void;
onConfirm: (next: CategorySelection) => void;
};
type TabKey = 'parent' | 'child';
export default function CategoryPicker({
open,
tree,
value,
onClose,
onConfirm,
}: CategoryPickerProps) {
const [draft, setDraft] = useState<CategorySelection>(value);
const [activeTab, setActiveTab] = useState<TabKey>('parent');
useEffect(() => {
if (!open) return;
setDraft(value);
setActiveTab(value.parentId ? 'child' : 'parent');
}, [open, value]);
const children = useMemo(() => {
const parent = tree.find((n) => n.id === draft.parentId);
return parent?.children ?? [];
}, [tree, draft.parentId]);
if (!open) return null;
function selectParent(node: StoreCategoryNode | null) {
if (!node) {
setDraft(EMPTY_CATEGORY);
return;
}
setDraft({
parentId: node.id,
parentName: node.name,
childId: '',
childName: '',
});
setActiveTab('child');
}
function selectChild(node: StoreCategoryNode | null) {
if (!node) {
setDraft((prev) => ({ ...prev, childId: '', childName: '' }));
return;
}
setDraft((prev) => ({
...prev,
childId: node.id,
childName: node.name,
}));
}
function handleConfirm() {
onConfirm(draft);
onClose();
}
return (
<View className="region-picker-overlay" onClick={onClose}>
<View className="region-picker-sheet" onClick={(e) => e.stopPropagation()}>
<View className="region-picker-toolbar">
<View className="region-picker-tabs">
<Text
className={`region-picker-tab${activeTab === 'parent' ? ' active' : ''}`}
onClick={() => setActiveTab('parent')}
>
{draft.parentName || '大类'}
</Text>
<Text
className={`region-picker-tab${activeTab === 'child' ? ' active' : ''}${!draft.parentId ? ' disabled' : ''}`}
onClick={() => draft.parentId && setActiveTab('child')}
>
{draft.childName || '细类'}
</Text>
</View>
<Text className="region-picker-confirm ready" onClick={handleConfirm}>
确定
</Text>
</View>
<ScrollView className="region-picker-list" scrollY showScrollbar={false}>
{activeTab === 'parent' ? (
<>
<View
className={`region-picker-option${!draft.parentId ? ' selected' : ''} region-picker-option--all`}
onClick={() => selectParent(null)}
>
<Text>全部分类</Text>
</View>
{tree.map((item) => (
<View
key={item.id}
className={`region-picker-option${draft.parentId === item.id ? ' selected' : ''}`}
onClick={() => selectParent(item)}
>
<Text>{item.name}</Text>
</View>
))}
</>
) : (
<>
<View
className={`region-picker-option${!draft.childId ? ' selected' : ''} region-picker-option--all`}
onClick={() => selectChild(null)}
>
<Text>全部细类</Text>
</View>
{children.map((item) => (
<View
key={item.id}
className={`region-picker-option${draft.childId === item.id ? ' selected' : ''}`}
onClick={() => selectChild(item)}
>
<Text>{item.name}</Text>
</View>
))}
</>
)}
</ScrollView>
</View>
</View>
);
}