Files
personal-admin-2026/apps/frontend/src/features/wallets/components/DepositDialog.tsx
Jose Selesan 1d954217b7 feat(wallets): implement wallet management features including create, update, delete, deposit, transfer, and list movements
- Added createWallet, updateWallet, deleteWallet, depositWallet, transferWallet, and listMovements handlers.
- Created corresponding routes for wallet operations.
- Developed frontend components for wallet management including dialogs for creating, editing, depositing, adjusting balance, transferring, and viewing movements.
- Integrated wallet management into the authenticated routes.
2026-06-17 09:36:55 -03:00

129 lines
3.7 KiB
TypeScript

import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { Button } from "@/components/ui/button";
import {
ResponsiveDialog,
ResponsiveDialogContent,
ResponsiveDialogFooter,
ResponsiveDialogHeader,
ResponsiveDialogTitle,
} from "@/components/ui/responsive-dialog";
import { useDepositWallet } from "@/lib/queries";
import type { Wallet } from "@/lib/api";
const depositSchema = z.object({
amount: z.number().positive("El monto debe ser mayor a 0"),
description: z.string().max(255).optional(),
});
type DepositFormValues = z.infer<typeof depositSchema>;
interface DepositDialogProps {
wallet: Wallet;
open: boolean;
onOpenChange: (open: boolean) => void;
}
export function DepositDialog({
wallet,
open,
onOpenChange,
}: DepositDialogProps) {
const deposit = useDepositWallet();
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
reset,
} = useForm<DepositFormValues>({
resolver: zodResolver(depositSchema),
defaultValues: { amount: 0, description: "" },
});
function handleClose(open: boolean) {
onOpenChange(open);
if (!open) reset();
}
async function onSubmit(data: DepositFormValues) {
await deposit.mutateAsync({
id: wallet.id,
data: {
amount: data.amount,
description: data.description || undefined,
},
});
handleClose(false);
}
return (
<ResponsiveDialog open={open} onOpenChange={handleClose}>
<ResponsiveDialogContent>
<ResponsiveDialogHeader>
<ResponsiveDialogTitle>
Depositar en {wallet.name}
</ResponsiveDialogTitle>
</ResponsiveDialogHeader>
<form
id="deposit-form"
onSubmit={handleSubmit(onSubmit)}
className="flex flex-col gap-4"
>
<div className="flex flex-col gap-1.5">
<label htmlFor="deposit-amount" className="text-sm font-medium">
Monto
</label>
<input
id="deposit-amount"
type="number"
step="0.01"
min="0"
{...register("amount", { valueAsNumber: true })}
placeholder="1000"
className="h-8 rounded-lg border border-input bg-background px-2.5 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50"
/>
{errors.amount && (
<span className="text-xs text-destructive">
{errors.amount.message}
</span>
)}
</div>
<div className="flex flex-col gap-1.5">
<label htmlFor="deposit-desc" className="text-sm font-medium">
Descripción (opcional)
</label>
<input
id="deposit-desc"
{...register("description")}
placeholder="Ej: Sueldo"
className="h-8 rounded-lg border border-input bg-background px-2.5 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50"
/>
{errors.description && (
<span className="text-xs text-destructive">
{errors.description.message}
</span>
)}
</div>
</form>
<ResponsiveDialogFooter>
<Button
variant="outline"
onClick={() => handleClose(false)}
disabled={isSubmitting}
>
Cancelar
</Button>
<Button type="submit" form="deposit-form" disabled={isSubmitting}>
Depositar
</Button>
</ResponsiveDialogFooter>
</ResponsiveDialogContent>
</ResponsiveDialog>
);
}