import { ORG_DESCRIPTION_MAX_LENGTH, ORG_NAME_MAX_LENGTH, ORG_SLUG_MAX_LENGTH } from "@issue/shared"; import { type FormEvent, useState } from "react"; import { useAuthenticatedSession } from "@/components/session-provider"; import { Button } from "@/components/ui/button"; import { Dialog, DialogClose, DialogContent, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Field } from "@/components/ui/field"; import { Label } from "@/components/ui/label"; import { organisation } from "@/lib/server"; import { cn } from "@/lib/utils"; const slugify = (value: string) => value .trim() .toLowerCase() .replace(/[^a-z0-9]+/g, "-") .replace(/^-+/, "") .replace(/-{2,}/g, "-"); export function CreateOrganisation({ trigger, completeAction, }: { trigger?: React.ReactNode; completeAction?: (organisationId: number) => void | Promise; }) { const { user } = useAuthenticatedSession(); const [open, setOpen] = useState(false); const [name, setName] = useState(""); const [slug, setSlug] = useState(""); const [description, setDescription] = useState(""); const [slugManuallyEdited, setSlugManuallyEdited] = useState(false); const [submitAttempted, setSubmitAttempted] = useState(false); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(null); const reset = () => { setName(""); setSlug(""); setDescription(""); setSlugManuallyEdited(false); setSubmitAttempted(false); setSubmitting(false); setError(null); }; const onOpenChange = (nextOpen: boolean) => { setOpen(nextOpen); if (!nextOpen) { reset(); } }; const handleSubmit = async (e: FormEvent) => { e.preventDefault(); setError(null); setSubmitAttempted(true); if (name.trim() === "" || name.trim().length > ORG_NAME_MAX_LENGTH) return; if (slug.trim() === "" || slug.trim().length > ORG_SLUG_MAX_LENGTH) return; if (description.trim().length > ORG_DESCRIPTION_MAX_LENGTH) return; if (!user.id) { setError("you must be logged in to create an organisation"); return; } setSubmitting(true); try { await organisation.create({ name, slug, description, userId: user.id, onSuccess: async (data) => { setOpen(false); reset(); try { await completeAction?.(data.id); } catch (actionErr) { console.error(actionErr); } }, onError: (err) => { setError(err || "failed to create organisation"); setSubmitting(false); }, }); } catch (err) { console.error(err); setError("failed to create organisation"); setSubmitting(false); } }; return ( {trigger || } Create Organisation {/* Enter the details for the new organisation. */}
{ const nextName = e.target.value; setName(nextName); if (!slugManuallyEdited) { setSlug(slugify(nextName)); } }} validate={(v) => { if (v.trim() === "") return "Cannot be empty"; if (v.trim().length > ORG_NAME_MAX_LENGTH) { return `Too long (${ORG_NAME_MAX_LENGTH} character limit)`; } return undefined; }} submitAttempted={submitAttempted} placeholder="Demo Organisation" maxLength={ORG_NAME_MAX_LENGTH} /> { setSlug(slugify(e.target.value)); setSlugManuallyEdited(true); }} validate={(v) => { if (v.trim() === "") return "Cannot be empty"; if (v.trim().length > ORG_SLUG_MAX_LENGTH) { return `Too long (${ORG_SLUG_MAX_LENGTH} character limit)`; } return undefined; }} submitAttempted={submitAttempted} placeholder="demo-organisation" maxLength={ORG_SLUG_MAX_LENGTH} /> setDescription(e.target.value)} validate={(v) => { if (v.trim().length > ORG_DESCRIPTION_MAX_LENGTH) { return `Too long (${ORG_DESCRIPTION_MAX_LENGTH} character limit)`; } return undefined; }} submitAttempted={submitAttempted} placeholder="What is this organisation for?" maxLength={ORG_DESCRIPTION_MAX_LENGTH} />
{error ? ( ) : ( )}
{/* */} {/* */}
); }