NewTeamForm

Shows a form for creating a new team within Basejump. Primarily used within the AccountSelector component, but can also be used to create your own interfaces.

The <NewTeamForm /> component is powered by shadcn, meaning the code and all it's components are local to your codebase for easy customization. The inspiration for the component design was borrowed heavily from the shadcn dashboard example app.

Preview

NewTeamForm

Usage

This component is nothing but a basic react-hook-form component built using shadcn. It's made to be used inside of other components, such as the <AccountSelector>, but you can also leverage it in your own interfaces.

Optional parameters

  • Name
    afterCreate
    Type
    function
    Description

    A function that gets called after a team has been created. It gets passed the new team as a function input.

    import NewTeamForm from "@/components/basejump/NewTeamForm.tsx";

    export default function NewTeamFormDemo() {
        return (
            <NewTeamForm afterCreate={(account) => alert(`Welcome, ${account.name}`)}/>
        )
    }
    

Installation

This assumes that you've followed the react or nextjs getting started guide and have a working shadcn installation.

1. Install required shadcn components

npx shadcn-ui@latest add form input label button

2. Copy / Paste the <NewTeamForm /> component into your codebase

@/components/basejump/NewTeamForm.tsx
"use client"

import {zodResolver} from "@hookform/resolvers/zod"
import {useForm} from "react-hook-form"
import * as z from "zod"

import {Button} from "@/components/ui/button"
import {Form, FormControl, FormField, FormItem, FormLabel, FormMessage,} from "@/components/ui/form"
import {Input} from "@/components/ui/input"
import {CreateAccountResponse} from "@usebasejump/next";
import {createClient} from "@/utils/supabase/client.ts";

const FormSchema = z.object({
    slug: z.string().min(2, {
        message: "Account slug must be at least 2 characters.",
    }),
    name: z.string().min(2, {
        message: "Account name must be at least 2 characters.",
    })
})

interface Props {
    afterCreate?: (account: CreateAccountResponse) => void;
}

export default function NewTeamForm({afterCreate}: Props) {
    const form = useForm<z.infer<typeof FormSchema>>({
        resolver: zodResolver(FormSchema),
        defaultValues: {
            slug: "",
            name: "",
        },
    });

    const supabaseClient = createClient();

    async function onSubmit(data: z.infer<typeof FormSchema>) {
        const {data: newTeam, error} = await supabaseClient.rpc("create_account", {
            name: data.name,
            slug: data.slug,
        });

        if (error) {
            form.setError("slug", {
                type: "custom",
                message: error.message,
            });
            return;
        }

        if (afterCreate) {
            afterCreate(newTeam);
        }

        form.reset();
    }

    return (
        <Form {...form}>
            <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
                <FormField
                    control={form.control}
                    name="name"
                    render={({field}) => (
                        <FormItem>
                            <FormLabel>Team Name</FormLabel>
                            <FormControl>
                                <Input placeholder="My Team" {...field} />
                            </FormControl>
                            <FormMessage/>
                        </FormItem>
                    )}
                />
                <FormField
                    control={form.control}
                    name="slug"
                    render={({field}) => (
                        <FormItem>
                            <FormLabel>Unique identifier</FormLabel>
                            <div className="flex items-center space-x-2">
                                <span className="text-sm leading-none">
                                    https://usebasejump.com/
                                </span>
                                <FormControl>
                                    <Input placeholder="my-team" {...field} />
                                </FormControl>
                            </div>
                            <FormMessage/>
                        </FormItem>
                    )}
                />
                <Button type="submit" disabled={form.formState.isSubmitting}>{form.formState.isSubmitting ? "Creating..." : "Create Team"}</Button>
            </form>
        </Form>
    )
}