feat(ui): Dashboard 基礎表格化重構,實裝行展開狀態管理

This commit is contained in:
2026-04-28 23:58:25 +08:00
parent cdea2ce608
commit 1c6c36b147
3 changed files with 262 additions and 82 deletions
@@ -32,6 +32,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { Plus } from 'lucide-react';
import { toast } from 'sonner';
import { createTransaction } from '@/actions/transaction';
@@ -60,6 +61,9 @@ interface Asset {
interface AddTransactionDialogProps {
assets: Asset[];
open?: boolean;
onOpenChange?: (open: boolean) => void;
defaultAssetId?: string;
}
const txTypeLabels: Record<string, string> = {
@@ -77,15 +81,23 @@ const exchangeToCurrencyMap: Record<string, string> = {
'SZSE': 'CNY',
};
export function AddTransactionDialog({ assets }: AddTransactionDialogProps) {
const [open, setOpen] = useState(false);
export function AddTransactionDialog({ assets, open: openProp, onOpenChange, defaultAssetId }: AddTransactionDialogProps) {
const [internalOpen, setInternalOpen] = useState(false);
const [isPending, startTransition] = useTransition();
const router = useRouter();
const open = openProp !== undefined ? openProp : internalOpen;
const setOpen = (value: boolean) => {
if (openProp === undefined) {
setInternalOpen(value);
}
onOpenChange?.(value);
};
const form = useForm<AddTransactionForm>({
resolver: zodResolver(addTransactionSchema),
defaultValues: {
assetId: '',
assetId: defaultAssetId || '',
txType: 'BUY' as const,
quantity: '',
price: '',
@@ -97,6 +109,12 @@ export function AddTransactionDialog({ assets }: AddTransactionDialogProps) {
const selectedAssetId = useWatch({ control: form.control, name: 'assetId' });
useEffect(() => {
if (defaultAssetId) {
form.setValue('assetId', defaultAssetId, { shouldValidate: true });
}
}, [defaultAssetId, form]);
useEffect(() => {
if (!selectedAssetId) return;
const selectedAsset = assets.find((a) => a.id === selectedAssetId);
@@ -128,13 +146,16 @@ export function AddTransactionDialog({ assets }: AddTransactionDialogProps) {
}
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button>
<Plus className="h-4 w-4 mr-2" />
</Button>
</DialogTrigger>
<>
{!openProp && (
<DialogTrigger asChild>
<Button>
<Plus className="h-4 w-4 mr-2" />
</Button>
</DialogTrigger>
)}
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent className="sm:max-w-[500px]">
<DialogHeader>
<DialogTitle></DialogTitle>
@@ -322,5 +343,6 @@ export function AddTransactionDialog({ assets }: AddTransactionDialogProps) {
</Form>
</DialogContent>
</Dialog>
</>
);
}