diff --git a/src/lib/actions/categoryCreateUpdate.ts b/src/lib/actions/categoryCreateUpdate.ts new file mode 100644 index 0000000..4248bd3 --- /dev/null +++ b/src/lib/actions/categoryCreateUpdate.ts @@ -0,0 +1,65 @@ +import { z } from 'zod'; +import { ActionResponse } from '@/lib/types/ActionResponse'; +import { prismaClient } from '@/prisma'; +import { getUser } from '@/auth'; +import { URL_SIGN_IN } from '@/lib/constants'; +import { categoryFormSchema } from '@/lib/form-schemas/categoryFormSchema'; + +export default async function categoryCreateUpdate({ + id, + name, + color, +}: z.infer): Promise { + 'use server'; + + // check that user is logged in + const user = await getUser(); + if (!user) { + return { + type: 'error', + message: 'You must be logged in to create/update an category.', + redirect: URL_SIGN_IN, + }; + } + + // create/update category + try { + if (id) { + await prismaClient.category.update({ + where: { + id: id, + }, + data: { + name: name, + color: color, + }, + }, + ); + + // return success + return { + type: 'success', + message: `'${name}' updated`, + }; + } else { + await prismaClient.category.create({ + data: { + userId: user.id, + name: name, + color: color, + }, + }); + + // return success + return { + type: 'success', + message: `'${name}' created`, + }; + } + } catch (e) { + return { + type: 'error', + message: 'Failed creating/updating category', + }; + } +} diff --git a/src/lib/actions/categoryDelete.ts b/src/lib/actions/categoryDelete.ts new file mode 100644 index 0000000..1a7f55b --- /dev/null +++ b/src/lib/actions/categoryDelete.ts @@ -0,0 +1,62 @@ +import { ActionResponse } from '@/lib/types/ActionResponse'; +import { prismaClient } from '@/prisma'; +import { getUser } from '@/auth'; +import { URL_SIGN_IN } from '@/lib/constants'; + +export default async function categoryDelete(id: number): Promise { + 'use server'; + + // check that id is a number + if (!id || isNaN(id)) { + return { + type: 'error', + message: 'Invalid category ID', + }; + } + + // check that user is logged in + const user = await getUser(); + if (!user) { + return { + type: 'error', + message: 'You must be logged in to delete an category.', + redirect: URL_SIGN_IN, + }; + } + + // check that category is associated with user + const category = await prismaClient.category.findFirst({ + where: { + id: id, + userId: user.id, + }, + }); + if (!category) { + return { + type: 'error', + message: 'Category not found', + }; + } + + // delete category + try { + await prismaClient.category.delete({ + where: { + id: category.id, + userId: user.id, + }, + }, + ); + } catch (e) { + return { + type: 'error', + message: 'Failed deleting category', + }; + } + + // return success + return { + type: 'success', + message: `'${category.name}' deleted`, + }; +} diff --git a/src/lib/form-schemas/categoryFormSchema.ts b/src/lib/form-schemas/categoryFormSchema.ts new file mode 100644 index 0000000..256ad89 --- /dev/null +++ b/src/lib/form-schemas/categoryFormSchema.ts @@ -0,0 +1,11 @@ +import { z } from 'zod'; + +export const categoryFormSchema = z.object({ + id: z.number().positive().optional(), + name: z.string().min(1).max(32), + color: z.string() + .min(7) + .max(7) + .startsWith('#') + .refine(value => value.split('#')[1].match(/^[0-9a-fA-F]{6}$/)), +});