Skip to content

Commit

Permalink
N-FIN-12: add sample data generation for development (#14)
Browse files Browse the repository at this point in the history
Resolves #12
  • Loading branch information
MarkusThielker authored Mar 11, 2024
2 parents d45f6bf + 63c2ea5 commit c1359db
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 4 deletions.
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-scroll-area": "^1.0.5",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2",
"@tanstack/react-table": "^8.13.2",
"class-variance-authority": "^0.7.0",
Expand Down
52 changes: 51 additions & 1 deletion src/app/account/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
import SignOutForm from '@/components/form/signOutForm';
import { URL_SIGN_IN } from '@/lib/constants';
import GenerateSampleDataForm from '@/components/form/generateSampleDataForm';
import generateSampleData from '@/lib/actions/generateSampleData';
import { prismaClient } from '@/prisma';

export default async function AccountPage() {

Expand All @@ -16,6 +19,28 @@ export default async function AccountPage() {
redirect(URL_SIGN_IN);
}

let paymentCount = 0;
let entityCount = 0;
let categoryCount = 0;

if (process.env.NODE_ENV === 'development') {
paymentCount = await prismaClient.payment.count({
where: {
userId: user.id,
},
});
entityCount = await prismaClient.entity.count({
where: {
userId: user.id,
},
});
categoryCount = await prismaClient.category.count({
where: {
userId: user.id,
},
});
}

return (
<div className="flex flex-col items-center">
<Card className="w-full max-w-md mt-12">
Expand All @@ -36,8 +61,33 @@ export default async function AccountPage() {
disabled
value={user?.username}/>
</div>
<div className="flex flex-row items-center space-x-4">
<div>
<Label>Payments</Label>
<Input
disabled
value={paymentCount}/>
</div>
<div>
<Label>Entities</Label>
<Input
disabled
value={entityCount}/>
</div>
<div>
<Label>Categories</Label>
<Input
disabled
value={categoryCount}/>
</div>
</div>
</CardContent>
<CardFooter>
<CardFooter className="space-x-4">
{
process.env.NODE_ENV === 'development' && (
<GenerateSampleDataForm onSubmit={generateSampleData}/>
)
}
<SignOutForm onSubmit={signOut}/>
</CardFooter>
</Card>
Expand Down
2 changes: 1 addition & 1 deletion src/app/auth/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default function AuthLayout({
children: React.ReactNode;
}>) {
return (
<div className="flex min-h-screen items-center justify-center">
<div className="flex justify-center">
{children}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/app/auth/signin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { URL_SIGN_UP } from '@/lib/constants';

export default async function SignInPage() {
return (
<Card className="w-full max-w-md">
<Card className="w-full max-w-md mt-12">
<CardHeader>
<CardTitle>Sign in</CardTitle>
<CardDescription>Sign into your existing account</CardDescription>
Expand Down
2 changes: 1 addition & 1 deletion src/app/auth/signup/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { URL_SIGN_IN } from '@/lib/constants';

export default async function SignUpPage() {
return (
<Card className="w-full max-w-md">
<Card className="w-full max-w-md mt-12">
<CardHeader>
<CardTitle>Sign up</CardTitle>
<CardDescription>Create a new account.</CardDescription>
Expand Down
23 changes: 23 additions & 0 deletions src/components/form/generateSampleDataForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use client';

import { Button } from '@/components/ui/button';
import React from 'react';
import { useRouter } from 'next/navigation';
import { toast } from 'sonner';
import { sonnerContent } from '@/components/ui/sonner';
import { ActionResponse } from '@/lib/types/ActionResponse';

export default function GenerateSampleDataForm({onSubmit}: { onSubmit: () => Promise<ActionResponse> }) {

const router = useRouter();

const handleSubmit = async () => {
const response = await onSubmit();
toast(sonnerContent(response));
router.refresh();
};

return (
<Button className="w-full" variant="outline" onClick={handleSubmit}>Generate sample data</Button>
);
}
31 changes: 31 additions & 0 deletions src/components/ui/separator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use client';

import * as React from 'react';
import * as SeparatorPrimitive from '@radix-ui/react-separator';

import { cn } from '@/lib/utils';

const Separator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(
(
{className, orientation = 'horizontal', decorative = true, ...props},
ref,
) => (
<SeparatorPrimitive.Root
ref={ref}
decorative={decorative}
orientation={orientation}
className={cn(
'shrink-0 bg-border',
orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
className,
)}
{...props}
/>
),
);
Separator.displayName = SeparatorPrimitive.Root.displayName;

export { Separator };
190 changes: 190 additions & 0 deletions src/lib/actions/generateSampleData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { prismaClient } from '@/prisma';
import type { Category, Entity } from '@prisma/client';
import { EntityType } from '@prisma/client';
import { getUser } from '@/auth';
import { URL_SIGN_IN } from '@/lib/constants';
import { ActionResponse } from '@/lib/types/ActionResponse';

export default async function generateSampleData(): Promise<ActionResponse> {
'use server';

const user = await getUser();

if (!user) {
return {
type: 'error',
message: 'You must be logged in to create/update an category.',
redirect: URL_SIGN_IN,
};
}

// Categories: create sample data
const categories: Category[] = await prismaClient.category.findMany({where: {userId: user.id}});
if (await prismaClient.category.count({where: {userId: user.id}}) == 0) {

console.log('Creating sample categories...');

categories.push(await prismaClient.category.create({
data: {
userId: user.id,
name: 'Groceries',
color: '#FFBEAC',
},
}));

categories.push(await prismaClient.category.create({
data: {
userId: user.id,
name: 'Drugstore items',
color: '#9CBCFF',
},
}));

categories.push(await prismaClient.category.create({
data: {
userId: user.id,
name: 'Going out',
color: '#F1ADFF',
},
}));

categories.push(await prismaClient.category.create({
data: {
userId: user.id,
name: 'Random stuff',
color: '#C1FFA9',
},
}));

categories.push(await prismaClient.category.create({
data: {
userId: user.id,
name: 'Salary',
color: '#FFF787',
},
}));

console.log('Sample categories created.');
}
console.log(categories);

// Entities: create sample data
const entities: Entity[] = await prismaClient.entity.findMany({where: {userId: user.id}});
if (await prismaClient.entity.count({where: {userId: user.id}}) == 0) {

console.log('Creating sample entities...');

entities.push(await prismaClient.entity.create({
data: {
userId: user.id,
name: 'Main Account',
type: EntityType.Account,
},
}));

entities.push(await prismaClient.entity.create({
data: {
userId: user.id,
name: 'Company',
type: EntityType.Entity,
},
}));

entities.push(await prismaClient.entity.create({
data: {
userId: user.id,
name: 'Supermarket 1',
type: EntityType.Entity,
},
}));

entities.push(await prismaClient.entity.create({
data: {
userId: user.id,
name: 'Supermarket 2',
type: EntityType.Entity,
},
}));

entities.push(await prismaClient.entity.create({
data: {
userId: user.id,
name: 'Supermarket 3',
type: EntityType.Entity,
},
}));

entities.push(await prismaClient.entity.create({
data: {
userId: user.id,
name: 'Supermarket 4',
type: EntityType.Entity,
},
}));

console.log('Sample entities created.');
}
console.log(entities);

// Payments: create sample data
console.log('Creating sample payments...');

if (await prismaClient.payment.count({where: {userId: user.id}}) == 0) {
for (let i = 0; i < 4; i++) {

const date = new Date();
date.setDate(1);
date.setMonth(date.getMonth() - i);

await prismaClient.payment.create({
data: {
userId: user.id,
amount: 200000,
date: date,
payorId: entities[1].id,
payeeId: entities[0].id,
categoryId: 5,
createdAt: date,
updatedAt: date,
},
});
}
}

let minAmount = 200; // 2€
let maxAmount = 3000; // 30€
let minPayee = entities[2].id;
let maxPayee = entities[entities.length - 1].id;
let minCategory = categories[0].id;
let maxCategory = categories[categories.length - 1].id;
let payments = 196;

for (let i = 0; i < payments; i++) {

const date = new Date(
new Date().getTime() - Math.floor(Math.random() * 10000000000));

await prismaClient.payment.create({
data: {
userId: user.id,
amount: Math.floor(
Math.random() * (maxAmount - minAmount) + minAmount),
date: date,
payorId: 1,
payeeId: Math.floor(
Math.random() * (maxPayee - minPayee) + minPayee),
categoryId: Math.floor(
Math.random() * (maxCategory - minCategory) + minCategory),
createdAt: date,
updatedAt: date,
},
});
}

console.log('Sample payments created.');

return {
type: 'success',
message: 'Sample data created',
};
}

0 comments on commit c1359db

Please sign in to comment.