finances/src/components/paymentPageClientComponents.tsx
2024-03-17 00:42:19 +01:00

187 lines
7.3 KiB
TypeScript

'use client';
import React, { useState } from 'react';
import { CellContext } from '@tanstack/table-core';
import { Button } from '@/components/ui/button';
import { Edit, Trash } from 'lucide-react';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
import { DataTable } from '@/components/ui/data-table';
import { z } from 'zod';
import { ActionResponse } from '@/lib/types/actionResponse';
import { useRouter } from 'next/navigation';
import { toast } from 'sonner';
import { sonnerContent } from '@/components/ui/sonner';
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogFooter,
AlertDialogHeader,
} from '@/components/ui/alert-dialog';
import { paymentFormSchema } from '@/lib/form-schemas/paymentFormSchema';
import { Category, Entity, Payment } from '@prisma/client';
import PaymentForm from '@/components/form/paymentForm';
import { columns } from '@/app/payments/columns';
import { Drawer, DrawerContent, DrawerHeader, DrawerTitle, DrawerTrigger } from '@/components/ui/drawer';
import { useMediaQuery } from '@/lib/hooks/useMediaQuery';
export default function PaymentPageClientContent({
payments,
entities,
categories,
onSubmit,
onDelete,
className,
}: {
payments: Payment[],
entities: Entity[],
categories: Category[],
onSubmit: (data: z.infer<typeof paymentFormSchema>) => Promise<ActionResponse>,
onDelete: (id: number) => Promise<ActionResponse>,
className: string,
}) {
const isDesktop = useMediaQuery('(min-width: 768px)');
const router = useRouter();
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
const [selectedPayment, setSelectedPayment] = useState<Payment | undefined>(undefined);
async function handleSubmit(data: z.infer<typeof paymentFormSchema>) {
const response = await onSubmit(data);
router.refresh();
setIsEditDialogOpen(false);
return response;
}
async function handleDelete(id: number | undefined) {
if (!id) {
return;
}
const response = await onDelete(id);
toast(sonnerContent(response));
if (response.redirect) {
router.push(response.redirect);
}
router.refresh();
setIsDeleteDialogOpen(false);
return response;
}
const actionCell = ({row}: CellContext<Payment, unknown>) => {
const payment = row.original as Payment;
return (
<div className="flex items-center space-x-4">
<Button
variant="ghost"
className="h-8 w-8 p-0"
onClick={() => {
setSelectedPayment(payment);
setIsEditDialogOpen(true);
}}>
<span className="sr-only">Edit payment</span>
<Edit className="h-4 w-4"/>
</Button>
<Button
variant="ghost"
className="h-8 w-8 p-0"
onClick={() => {
setSelectedPayment(payment);
setIsDeleteDialogOpen(true);
}}
>
<span className="sr-only">Delete payment</span>
<Trash className="h-4 w-4"/>
</Button>
</div>
);
};
return (
<div className={className}>
<div className="flex items-center justify-between w-full">
<p className="text-3xl font-semibold">Payments</p>
{/* Edit dialog */}
{
isDesktop ? (
<Dialog open={isEditDialogOpen} onOpenChange={setIsEditDialogOpen}>
<DialogTrigger asChild>
<Button
onClick={() => {
setSelectedPayment(undefined);
setIsEditDialogOpen(true);
}}>
Create Payment
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>{selectedPayment?.id ? 'Update Payment' : 'Create Payment'}</DialogTitle>
</DialogHeader>
<PaymentForm
value={selectedPayment}
entities={entities}
categories={categories}
onSubmit={handleSubmit}
className="grid grid-cols-1 md:grid-cols-2 gap-4 py-4"/>
</DialogContent>
</Dialog>
) : (
<Drawer open={isEditDialogOpen} onOpenChange={setIsEditDialogOpen}>
<DrawerTrigger asChild>
<Button
onClick={() => {
setSelectedPayment(undefined);
setIsEditDialogOpen(true);
}}>
Create Payment
</Button>
</DrawerTrigger>
<DrawerContent className="p-4">
<DrawerHeader>
<DrawerTitle>{selectedPayment?.id ? 'Update Payment' : 'Create Payment'}</DrawerTitle>
</DrawerHeader>
<PaymentForm
value={selectedPayment}
entities={entities}
categories={categories}
onSubmit={handleSubmit}
className="grid grid-cols-1 md:grid-cols-2 gap-4 py-4"/>
</DrawerContent>
</Drawer>
)
}
</div>
{/* Data Table */}
<DataTable
className="w-full"
columns={columns(actionCell, entities, categories)}
data={payments}
pagination/>
{/* Delete confirmation dialog */}
<AlertDialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
<AlertDialogContent>
<AlertDialogHeader>Delete Payment?</AlertDialogHeader>
<p>Are your sure you want to delete the payment?</p>
<AlertDialogFooter>
<AlertDialogCancel>
Cancel
</AlertDialogCancel>
<AlertDialogAction onClick={() => handleDelete(selectedPayment?.id)}>
Delete
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
);
}