From f040e8f160d2f7a19900df44dfcc1c7f9a5ab92a Mon Sep 17 00:00:00 2001 From: Regalijan Date: Fri, 1 Nov 2024 03:33:10 -0400 Subject: [PATCH] Create short link creation page --- app/routes/short-links_.create.tsx | 113 +++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 app/routes/short-links_.create.tsx diff --git a/app/routes/short-links_.create.tsx b/app/routes/short-links_.create.tsx new file mode 100644 index 0000000..930c504 --- /dev/null +++ b/app/routes/short-links_.create.tsx @@ -0,0 +1,113 @@ +import { + Container, + FormControl, + FormHelperText, + FormLabel, + Heading, + Input, + useToast, +} from "@chakra-ui/react"; +import { useLoaderData } from "@remix-run/react"; +import { useState } from "react"; + +export function meta() { + return [ + { + title: "Create a Short Link", + }, + ]; +} + +export async function loader({ context }: { context: RequestContext }) { + const userId = context.data.current_user?.id; + + if (!userId) + throw new Response(null, { + status: 401, + }); + + if ( + ![0, 2, 4, 5, 6, 7, 9, 10, 11, 12].find( + (i) => context.data.current_user.permissions & (1 << i), + ) + ) + throw new Response(null, { + status: 403, + }); + + return null; +} + +export default function () { + useLoaderData(); + const [destination, setDestination] = useState(""); + const [code, setCode] = useState(""); + const toast = useToast(); + + async function createLink() { + // Create random 14 character string if no code is provided + const linkCode = + code || + Array.from(Array(14), () => + Math.floor(Math.random() * 36).toString(36), + ).join(""); + + const createResp = await fetch("/api/short-links/new", { + body: JSON.stringify({ destination, path: linkCode }), + headers: { + "content-type": "application/json", + }, + method: "POST", + }); + + if (!createResp.ok) { + let error = "Unknown error"; + + try { + error = ((await createResp.json()) as { error: string }).error; + } catch {} + + toast({ + description: error, + status: "error", + title: "Failed to create link", + }); + + return; + } + + toast({ + description: "You will momentarily be redirected to the short links page", + onCloseComplete: () => location.assign("/short-links"), + status: "success", + title: "Link created", + }); + } + + return ( + + Create a Link + + Destination URL + setDestination(e.target.value)} + type="url" + value={destination} + /> + + + Link Code + setCode(e.target.value)} + placeholder="totally-not-a-rickroll" + value={code} + /> + + Your custom link code. One will be automatically generated if you do + not provide one. Max 256 characters. + + + + ); +}