
22 | 23 | 24 | Alternative Stack 25 | 26 | 27 |
28 |29 | A Remix Stack using Hyper as a services tier 30 |
31 |32 | Check the README.md file for instructions on how to get this project deployed. 33 |
34 |29 | A Remix Stack using Hyper as a services tier 30 |
31 |32 | Check the README.md file for instructions on how to get this project deployed. 33 |
34 |{user.email}
32 | 40 |No notes yet
52 | ) : ( 53 |{data.note.body}
73 |6 | No note selected. Select a note on the left, or{" "} 7 | 8 | create a new note. 9 | 10 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /app/routes/notes/new.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import type { ActionFunction } from "@remix-run/node"; 3 | import { json, redirect } from "@remix-run/node"; 4 | import { Form, useActionData } from "@remix-run/react"; 5 | import { z } from "zod"; 6 | 7 | import type { LoaderContext } from "~/types"; 8 | 9 | type ActionData = { 10 | errors?: { 11 | title?: string; 12 | body?: string; 13 | }; 14 | }; 15 | 16 | const FormDataSchema = z.object({ 17 | title: z.string().min(1), 18 | body: z.string().min(1), 19 | }); 20 | 21 | export const action: ActionFunction = async ({ request, context }) => { 22 | const { SessionServer, NoteServer } = context as LoaderContext; 23 | 24 | const parent = await SessionServer.requireUserId(request); 25 | 26 | const formData = await request.formData(); 27 | 28 | const parsed = FormDataSchema.safeParse({ 29 | title: formData.get("title") ?? null, 30 | body: formData.get("body") ?? null, 31 | }); 32 | 33 | if (!parsed.success) { 34 | const errors = parsed.error.format(); 35 | return json