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 };