114 lines
2.6 KiB
TypeScript
114 lines
2.6 KiB
TypeScript
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<typeof loader>();
|
|
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 (
|
|
<Container maxW="container.md">
|
|
<Heading size="xl">Create a Link</Heading>
|
|
<FormControl isRequired mt="16px">
|
|
<FormLabel>Destination URL</FormLabel>
|
|
<Input
|
|
onChange={(e) => setDestination(e.target.value)}
|
|
type="url"
|
|
value={destination}
|
|
/>
|
|
</FormControl>
|
|
<FormControl mt="16px">
|
|
<FormLabel>Link Code</FormLabel>
|
|
<Input
|
|
maxLength={256}
|
|
onChange={(e) => setCode(e.target.value)}
|
|
placeholder="totally-not-a-rickroll"
|
|
value={code}
|
|
/>
|
|
<FormHelperText>
|
|
Your custom link code. One will be automatically generated if you do
|
|
not provide one. Max 256 characters.
|
|
</FormHelperText>
|
|
</FormControl>
|
|
</Container>
|
|
);
|
|
}
|