import { json } from '@remix-run/node'; import { redirect } from '@remix-run/node'; import { auth, getSignedInUser, sessionStorage } from '../auth.server'; import { z } from 'zod'; import { useState } from 'react'; import { Form, useActionData, useLoaderData, useNavigation } from '@remix-run/react'; import { TextInput } from '../components/TextInput'; import OptionSelect from '../components/OptionSelect'; import { Button } from '../components/Button'; import { validateFormData } from '../utils/utils'; import { createTeam, NO_TEAM_MARKER } from '../data/zippo.server'; import { Alert } from '../components/Alert'; import type { ActionArgs, LoaderArgs, MetaFunction } from '@remix-run/node'; import type { Option } from '../components/OptionSelect'; export const meta: MetaFunction = () => { return { title: 'Create Team | 0x', description: 'Create a team on 0x', }; }; const optionValues = z.enum(['cex', 'dex', 'self-custody-wallet', 'fintech', 'other']); const options: Option[] = [ { label: 'CEX', value: 'cex' }, { label: 'DEX', value: 'dex' }, { label: 'Self-custody Wallet', value: 'self-custody-wallet' }, { label: 'Fintech', value: 'fintech' }, { label: 'Other', value: 'other' }, ]; const zodTeamVerifyModel = z.object({ teamName: z .string() .min(1, 'Please enter a valid team name') .regex(/^[a-zA-Z0-9].*/, 'Team name must start with a letter or number'), teamCategory: optionValues, teamCategoryOthers: z.string().optional(), }); type ActionInput = z.TypeOf; type Errors = Partial<{ general: string } & Record>; export async function loader({ request }: LoaderArgs) { const [user, headers] = await getSignedInUser(request); // if the user doesn't exist, we want to redirect them to the create account page if (!user) { throw redirect('/create-account', { headers }); } // if the user has a team, we don't want them to be able to create a new team if (user.teamName !== NO_TEAM_MARKER) { throw redirect('/apps', { headers }); } return { email: user.email }; } export async function action({ request }: ActionArgs) { const [user, headers] = await getSignedInUser(request); // if the user doesn't exist, we want to redirect them to the create account page if (!user) { throw redirect('/create-account', { headers }); } // if the user has a team, we don't want them to be able to create a new team if (user.teamName !== NO_TEAM_MARKER) { throw redirect('/apps', { headers }); } const formData = await request.formData(); const { body, errors } = validateFormData({ formData: formData, schema: zodTeamVerifyModel, }); if (errors || (body.teamCategory === 'other' && !body.teamCategoryOthers)) { return json( { errors: { ...(errors || {}), teamCategoryOthers: body.teamCategory === 'other' && !body.teamCategoryOthers ? 'Please enter a valid team category' : undefined, } as Errors, values: body, }, { headers }, ); } const session = await sessionStorage.getSession(request.headers.get('Cookie')); const result = await createTeam({ userId: user.id, teamName: body.teamName, productType: body.teamCategory === 'other' ? (body.teamCategoryOthers as string) : body.teamCategory, }); if (result.result === 'ERROR') { return json( { errors: { general: result.error.message, } as Errors, }, { headers }, ); } const authSession = session.get(auth.sessionKey); authSession.teamName = result.data; session.set(auth.sessionKey, authSession); headers.append('Set-Cookie', await sessionStorage.commitSession(session)); throw redirect('/apps', { headers }); } function StandardCopy() { return (

You’re creating a team on 0x. You will need to share this account with your teammates pending when invitations are enabled.

); } function TeamNameInputCopy({ name }: { name: string }) { return (

You’re creating the {name} team on 0x. You will need to share this account with your teammates pending when invitations are enabled.

); } export default function CreateTeam() { const actionData = useActionData(); const { email } = useLoaderData(); const [teamName, setTeamName] = useState(''); const [teamType, setTeamType] = useState(''); const navigation = useNavigation(); return (
{actionData?.errors?.general && ( {actionData?.errors?.general} )}

Create a team

{teamName ? : }
setTeamName(val.currentTarget.value)} error={actionData?.errors?.teamName} /> setTeamType(val)} /> {teamType === 'other' && ( )}
); }