Custom layout

Finally, let's make the form look exactly as before.

52
lines of code
import { ActionFunction } from '@remix-run/node'
import { z } from 'zod'
import { InputError, makeDomainFunction } from 'domain-functions'
import { Form, formAction } from 'remix-forms'

const reservationSchema = z.object({
  city: z.enum(['saltLakeCity', 'lasVegas', 'losAngeles']),
  checkIn: z.date(),
  checkOut: z.date(),
  adults: z.number().int().positive(),
  children: z.number().int(),
  bedrooms: z.number().int().positive(),
  specialRequests: z.string().optional(),
})

const makeReservation = makeDomainFunction(reservationSchema)(
  async (values) => {
    if (values.specialRequests?.match(/towels/i)) {
      throw new InputError("Don't be such a diva!", 'specialRequests')
    }

    // Here you would store data instead
    console.log(values)
  },
)

export const action: ActionFunction = async ({ request }) =>
  formAction({
    request,
    schema: reservationSchema,
    mutation: makeReservation,
    successPath: 'conf/success/09',
  })

export default function Component() {
  return (
    <Form schema={reservationSchema}>
      {({ Field, Errors, Button }) => (
        <>
          <Field name="city" />
          <div className="flex w-full space-x-4">
            <Field name="checkIn" className="flex-1" />
            <Field name="checkOut" className="flex-1" />
          </div>
          <div className="flex w-full space-x-4">
            <Field name="adults" />
            <Field name="children" />
            <Field name="bedrooms" />
          </div>
          <Field name="specialRequests" multiline />
          <Errors />
          <Button>Make reservation</Button>
        </>
      )}
    </Form>
  )
}