diff --git a/package-lock.json b/package-lock.json
index 7843c0b..744cf02 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "next-finances",
- "version": "1.0.1",
+ "version": "1.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "next-finances",
- "version": "1.0.1",
+ "version": "1.1.0",
"license": "MIT",
"dependencies": {
"@hookform/resolvers": "^3.3.4",
@@ -40,6 +40,7 @@
"swr": "^2.2.5",
"tailwind-merge": "^2.2.1",
"tailwindcss-animate": "^1.0.7",
+ "vaul": "^0.9.0",
"zod": "^3.22.4"
},
"devDependencies": {
@@ -6184,6 +6185,18 @@
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"devOptional": true
},
+ "node_modules/vaul": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/vaul/-/vaul-0.9.0.tgz",
+ "integrity": "sha512-bZSySGbAHiTXmZychprnX/dE0EsSige88xtyyL3/MCRbrFotRPQZo7UdydGXZWw+CKbNOw5Ow8gwAo93/nB/Cg==",
+ "dependencies": {
+ "@radix-ui/react-dialog": "^1.0.4"
+ },
+ "peerDependencies": {
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index 2cb23d4..85074f6 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "next-finances",
"description": "A finances application to keep track of my personal spendings",
"homepage": "https://github.com/MarkusThielker/next-finances",
- "version": "1.0.1",
+ "version": "1.1.0",
"license": "MIT",
"author": {
"name": "Markus Thielker"
@@ -50,6 +50,7 @@
"swr": "^2.2.5",
"tailwind-merge": "^2.2.1",
"tailwindcss-animate": "^1.0.7",
+ "vaul": "^0.9.0",
"zod": "^3.22.4"
},
"devDependencies": {
diff --git a/src/app/account/page.tsx b/src/app/account/page.tsx
index fae73de..4bc3d46 100644
--- a/src/app/account/page.tsx
+++ b/src/app/account/page.tsx
@@ -42,7 +42,7 @@ export default async function AccountPage() {
return (
-
+
Hey, {user?.username}!
This is your account overview.
@@ -81,7 +81,7 @@ export default async function AccountPage() {
-
+
{
process.env.NODE_ENV === 'development' && (
diff --git a/src/app/categories/columns.tsx b/src/app/categories/columns.tsx
index 196bcdd..bd8e60d 100644
--- a/src/app/categories/columns.tsx
+++ b/src/app/categories/columns.tsx
@@ -25,6 +25,7 @@ export const columns = (
);
},
+ size: 65,
},
{
accessorKey: 'createdAt',
diff --git a/src/app/categories/page.tsx b/src/app/categories/page.tsx
index d460ade..f7bee73 100644
--- a/src/app/categories/page.tsx
+++ b/src/app/categories/page.tsx
@@ -25,6 +25,6 @@ export default async function CategoriesPage() {
categories={categories}
onSubmit={categoryCreateUpdate}
onDelete={categoryDelete}
- className="flex flex-col justify-center space-y-4 p-10"/>
+ className="flex flex-col justify-center space-y-4"/>
);
}
diff --git a/src/app/entities/columns.tsx b/src/app/entities/columns.tsx
index a56dc66..90b3754 100644
--- a/src/app/entities/columns.tsx
+++ b/src/app/entities/columns.tsx
@@ -17,6 +17,7 @@ export const columns = (
{
accessorKey: 'type',
header: 'Type',
+ size: 100,
},
{
accessorKey: 'createdAt',
diff --git a/src/app/entities/page.tsx b/src/app/entities/page.tsx
index 8c76f29..6f41ba5 100644
--- a/src/app/entities/page.tsx
+++ b/src/app/entities/page.tsx
@@ -28,6 +28,6 @@ export default async function EntitiesPage() {
entities={entities}
onSubmit={entityCreateUpdate}
onDelete={entityDelete}
- className="flex flex-col justify-center space-y-4 p-10"/>
+ className="flex flex-col justify-center space-y-4"/>
);
}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index cac7e3c..95bd21f 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -22,10 +22,10 @@ export default function RootLayout({
-
+
{children}
-
+
);
diff --git a/src/app/page.tsx b/src/app/page.tsx
index b217abf..54450d0 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -200,7 +200,7 @@ export default async function DashboardPage(props: { searchParams?: { scope: Sco
categoryPercentages={categoryPercentages}
entityExpenses={entityExpensesFormat}
entityPercentages={entityPercentages}
- className="flex flex-col justify-center space-y-4 p-10"
+ className="flex flex-col justify-center space-y-4"
/>
);
}
diff --git a/src/app/payments/columns.tsx b/src/app/payments/columns.tsx
index 32a2157..d3b950e 100644
--- a/src/app/payments/columns.tsx
+++ b/src/app/payments/columns.tsx
@@ -18,6 +18,7 @@ export const columns = (
cell: ({row}) => {
return format(row.original.date, 'PPP');
},
+ size: 175,
},
{
accessorKey: 'amount',
@@ -28,6 +29,7 @@ export const columns = (
currency: 'EUR',
}).format(row.getValue('amount') as number / 100);
},
+ size: 70,
},
{
accessorKey: 'payorId',
@@ -36,6 +38,7 @@ export const columns = (
const entity = entities.find((entity) => entity.id === row.original.payorId);
return entity?.name ?? '-';
},
+ size: 200,
},
{
accessorKey: 'payeeId',
@@ -44,6 +47,7 @@ export const columns = (
const entity = entities.find((entity) => entity.id === row.original.payeeId);
return entity?.name ?? '-';
},
+ size: 200,
},
{
accessorKey: 'categoryId',
@@ -60,10 +64,12 @@ export const columns = (
);
},
+ size: 200,
},
{
accessorKey: 'note',
header: 'Note',
+ size: 200,
},
{
id: 'actions',
diff --git a/src/app/payments/page.tsx b/src/app/payments/page.tsx
index 38d123c..bbec906 100644
--- a/src/app/payments/page.tsx
+++ b/src/app/payments/page.tsx
@@ -58,6 +58,6 @@ export default async function PaymentsPage() {
categories={categories}
onSubmit={paymentCreateUpdate}
onDelete={paymentDelete}
- className="flex flex-col justify-center space-y-4 p-10"/>
+ className="flex flex-col justify-center space-y-4"/>
);
}
diff --git a/src/components/categoryPageClientComponents.tsx b/src/components/categoryPageClientComponents.tsx
index ac8b908..f59b3f0 100644
--- a/src/components/categoryPageClientComponents.tsx
+++ b/src/components/categoryPageClientComponents.tsx
@@ -23,6 +23,8 @@ import {
} from '@/components/ui/alert-dialog';
import { categoryFormSchema } from '@/lib/form-schemas/categoryFormSchema';
import CategoryForm from '@/components/form/categoryForm';
+import { useMediaQuery } from '@/lib/hooks/useMediaQuery';
+import { Drawer, DrawerContent, DrawerHeader, DrawerTitle, DrawerTrigger } from '@/components/ui/drawer';
export default function CategoryPageClientContent({categories, onSubmit, onDelete, className}: {
categories: Category[],
@@ -31,6 +33,7 @@ export default function CategoryPageClientContent({categories, onSubmit, onDelet
className: string,
}) {
+ const isDesktop = useMediaQuery('(min-width: 768px)');
const router = useRouter();
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
@@ -97,26 +100,51 @@ export default function CategoryPageClientContent({categories, onSubmit, onDelet
Categories
{/* Edit dialog */}
-
+ {
+ isDesktop ? (
+
+ ) : (
+
+
+
+
+
+
+ {selectedCategory?.id ? 'Update Category' : 'Create Category'}
+
+
+
+
+ )
+ }
{/* Data Table */}
diff --git a/src/components/dashboardPageClientComponents.tsx b/src/components/dashboardPageClientComponents.tsx
index 314fa5c..8f368da 100644
--- a/src/components/dashboardPageClientComponents.tsx
+++ b/src/components/dashboardPageClientComponents.tsx
@@ -49,7 +49,7 @@ export default function DashboardPageClientContent(
return (
-
+
Dashboard
diff --git a/src/components/entityPageClientComponents.tsx b/src/components/entityPageClientComponents.tsx
index 4f4a8bd..3845ee1 100644
--- a/src/components/entityPageClientComponents.tsx
+++ b/src/components/entityPageClientComponents.tsx
@@ -24,6 +24,8 @@ import {
AlertDialogFooter,
AlertDialogHeader,
} from '@/components/ui/alert-dialog';
+import { useMediaQuery } from '@/lib/hooks/useMediaQuery';
+import { Drawer, DrawerContent, DrawerHeader, DrawerTitle, DrawerTrigger } from '@/components/ui/drawer';
export default function EntityPageClientContent({entities, onSubmit, onDelete, className}: {
entities: Entity[],
@@ -32,6 +34,7 @@ export default function EntityPageClientContent({entities, onSubmit, onDelete, c
className: string,
}) {
+ const isDesktop = useMediaQuery('(min-width: 768px)');
const router = useRouter();
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
@@ -125,26 +128,51 @@ export default function EntityPageClientContent({entities, onSubmit, onDelete, c
Entities
{/* Edit dialog */}
-
+ {
+ isDesktop ? (
+
+ ) : (
+
+
+
+
+
+
+ {selectedEntity?.id ? 'Update Entity' : 'Create Entity'}
+
+
+
+
+ )
+ }
{/* Filter input */}
diff --git a/src/components/form/paymentForm.tsx b/src/components/form/paymentForm.tsx
index d6323dd..705587e 100644
--- a/src/components/form/paymentForm.tsx
+++ b/src/components/form/paymentForm.tsx
@@ -5,7 +5,7 @@ import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { Input } from '@/components/ui/input';
-import React, { useState } from 'react';
+import React, { useRef } from 'react';
import { Button } from '@/components/ui/button';
import { ActionResponse } from '@/lib/types/actionResponse';
import { useRouter } from 'next/navigation';
@@ -16,11 +16,11 @@ import { paymentFormSchema } from '@/lib/form-schemas/paymentFormSchema';
import CurrencyInput from '@/components/ui/currency-input';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { cn } from '@/lib/utils';
-import { CalendarIcon, Check, ChevronsUpDown } from 'lucide-react';
+import { CalendarIcon } from 'lucide-react';
import { format } from 'date-fns';
import { Calendar } from '@/components/ui/calendar';
-import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area';
import { Textarea } from '@/components/ui/textarea';
+import { AutoCompleteInput } from '@/components/ui/auto-complete-input';
export default function PaymentForm({value, entities, categories, onSubmit, className}: {
value: Payment | undefined,
@@ -32,12 +32,6 @@ export default function PaymentForm({value, entities, categories, onSubmit, clas
const router = useRouter();
- const [filter, setFilter] = useState
('');
-
- const [payorOpen, setPayorOpen] = useState(false);
- const [payeeOpen, setPayeeOpen] = useState(false);
- const [categoryOpen, setCategoryOpen] = useState(false);
-
const form = useForm>({
resolver: zodResolver(paymentFormSchema),
defaultValues: {
@@ -73,6 +67,10 @@ export default function PaymentForm({value, entities, categories, onSubmit, clas
};
}) ?? [];
+ const payeeRef = useRef(null);
+ const categoryRef = useRef(null);
+ const noteRef = useRef(null);
+
return (