remix-demo

react router (remix) demo

git clone https://9o.is/git/remix-demo.git

foodEntry.server.ts

(4542B)


      1 import { Role } from "@prisma/client";
      2 import type { Params } from "@remix-run/react";
      3 import { json } from "@remix-run/server-runtime";
      4 import { withZod } from "@remix-validated-form/with-zod";
      5 import { validationError } from "remix-validated-form";
      6 import {
      7   createFoodEntry,
      8   deleteFoodEntry,
      9   getAllFoodEntries,
     10   getFoodEntries,
     11   getFoodEntry,
     12   updateFoodEntry,
     13 } from "~/models/foodEntry.server";
     14 import { userExists } from "~/models/user.server";
     15 import { requireAdmin, requireUser } from "~/session.server";
     16 import {
     17   foodEntryAdminSchema,
     18   foodEntryUserValidator,
     19 } from "~/schemas/foodEntry";
     20 
     21 async function get(request: Request, params: Params) {
     22   await requireAdmin(request);
     23   const foodId = params.id;
     24 
     25   if (!foodId) {
     26     return json(
     27       { error: { id: "Food ID parameter is missing" } },
     28       { status: 422 }
     29     );
     30   }
     31 
     32   const food = await getFoodEntry(foodId);
     33 
     34   if (!food) {
     35     return json({ error: { id: "Food ID does not exist" } }, { status: 404 });
     36   }
     37 
     38   return json(food);
     39 }
     40 
     41 async function getAll(request: Request) {
     42   try {
     43     const user = await requireUser(request);
     44     const foodEntries = await (user.role === Role.ADMIN
     45       ? getAllFoodEntries()
     46       : getFoodEntries(user.id));
     47 
     48     return json(foodEntries);
     49   } catch (error) {
     50     console.error("Food entry DB getAll failed:", error);
     51     return json({ error: "Get all good entries failed" }, { status: 500 });
     52   }
     53 }
     54 
     55 async function create(request: Request) {
     56   const user = await requireUser(request);
     57 
     58   if (user.role === Role.ADMIN) return createAsAdmin(request);
     59 
     60   const { error, data } = await foodEntryUserValidator.validate(
     61     await request.formData()
     62   );
     63 
     64   if (error) return validationError(error);
     65 
     66   try {
     67     return json(
     68       await createFoodEntry({
     69         userId: user.id,
     70         name: data.name,
     71         calories: Number(data.calories),
     72         consumed: new Date(data.consumed),
     73       })
     74     );
     75   } catch (error) {
     76     console.error("Food entry DB create failed:", error);
     77     return json({ error: "Create food entry failed" }, { status: 500 });
     78   }
     79 }
     80 
     81 async function update(request: Request, params: Params) {
     82   await requireAdmin(request);
     83   const foodId = params.id;
     84 
     85   if (!foodId) {
     86     return json(
     87       { error: { id: "Food ID parameter is missing" } },
     88       { status: 422 }
     89     );
     90   }
     91 
     92   const serverValidator = withZod(
     93     foodEntryAdminSchema.partial().refine(
     94       async (data) => {
     95         if (!data.userId) return true;
     96         return await userExists(data.userId);
     97       },
     98       {
     99         message: "User ID does not exist",
    100         path: ["userId"],
    101       }
    102     )
    103   );
    104 
    105   const { error, data } = await serverValidator.validate(
    106     await request.formData()
    107   );
    108 
    109   if (error) return validationError(error);
    110 
    111   try {
    112     await updateFoodEntry(foodId, {
    113       ...data,
    114       calories: data.calories ? Number(data.calories) : undefined,
    115       consumed: data.consumed ? new Date(data.consumed) : undefined,
    116     });
    117   } catch (error) {
    118     console.error("Food entry DB update failed:", error);
    119     return json({ error: "Update food entry failed" }, { status: 500 });
    120   }
    121 
    122   return json(null, { status: 204 });
    123 }
    124 
    125 async function remove(request: Request, params: Params) {
    126   await requireAdmin(request);
    127   const foodId = params.id;
    128 
    129   if (!foodId) {
    130     return json(
    131       { error: { id: "Food ID parameter is missing" } },
    132       { status: 422 }
    133     );
    134   }
    135 
    136   try {
    137     const batch = await deleteFoodEntry(foodId);
    138     if (batch.count !== 1) throw new Error("Delete batch size: " + batch.count);
    139   } catch (error) {
    140     console.error("Food entry DB delete failed:", error);
    141     return json({ error: "Delete food entry failed" }, { status: 500 });
    142   }
    143 
    144   return json(null, { status: 200 });
    145 }
    146 
    147 async function createAsAdmin(request: Request) {
    148   const serverValidator = withZod(
    149     foodEntryAdminSchema.refine(async (data) => userExists(data.userId), {
    150       message: "User ID does not exist",
    151       path: ["userId"],
    152     })
    153   );
    154 
    155   const { error, data } = await serverValidator.validate(
    156     await request.formData()
    157   );
    158 
    159   if (error) return validationError(error);
    160 
    161   try {
    162     return json(
    163       await createFoodEntry({
    164         userId: data.userId,
    165         name: data.name,
    166         calories: Number(data.calories),
    167         consumed: new Date(data.consumed),
    168       })
    169     );
    170   } catch (error) {
    171     console.error("Food entry DB create failed:", error);
    172     return json({ error: "Create food entry failed" }, { status: 500 });
    173   }
    174 }
    175 
    176 export default {
    177   get,
    178   getAll,
    179   create,
    180   update,
    181   remove,
    182 };