193 lines
7.8 KiB
TypeScript
193 lines
7.8 KiB
TypeScript
import { mdiChartTimelineVariant } from '@mdi/js'
|
|
import Head from 'next/head'
|
|
import React, { ReactElement } from 'react'
|
|
import { Field, Form, Formik } from 'formik'
|
|
import { useRouter } from 'next/router'
|
|
|
|
import BaseButton from '../../components/BaseButton'
|
|
import BaseButtons from '../../components/BaseButtons'
|
|
import BaseDivider from '../../components/BaseDivider'
|
|
import CardBox from '../../components/CardBox'
|
|
import FormField from '../../components/FormField'
|
|
import SectionMain from '../../components/SectionMain'
|
|
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
|
|
import { SelectField } from '../../components/SelectField'
|
|
import { getPageTitle } from '../../config'
|
|
import LayoutAuthenticated from '../../layouts/Authenticated'
|
|
import { create } from '../../stores/booking_requests/booking_requestsSlice'
|
|
import { useAppDispatch, useAppSelector } from '../../stores/hooks'
|
|
|
|
const initialValues = {
|
|
tenant: '',
|
|
organization: '',
|
|
requested_by: '',
|
|
request_code: '',
|
|
status: 'submitted',
|
|
check_in_at: '',
|
|
check_out_at: '',
|
|
preferred_property: '',
|
|
preferred_unit_type: '',
|
|
preferred_bedrooms: '',
|
|
guest_count: '',
|
|
purpose_of_stay: '',
|
|
special_requirements: '',
|
|
budget_code: '',
|
|
max_budget_amount: '',
|
|
currency: 'USD',
|
|
}
|
|
|
|
const Booking_requestsNew = () => {
|
|
const dispatch = useAppDispatch()
|
|
const router = useRouter()
|
|
const { currentUser } = useAppSelector((state) => state.auth)
|
|
|
|
const canManageInternalFields = Boolean(currentUser?.app_role?.globalAccess)
|
|
const pageTitle = canManageInternalFields ? 'New Booking Request' : 'Request a Stay'
|
|
const introCopy = canManageInternalFields
|
|
? 'Create a booking request and optionally manage internal routing fields directly.'
|
|
: 'Tell us when you need accommodation and what kind of stay you need. Your organization, requester, and reference code will be attached automatically.'
|
|
|
|
const handleSubmit = async (values) => {
|
|
const payload = {
|
|
...values,
|
|
...(canManageInternalFields ? {} : { status: 'submitted' }),
|
|
}
|
|
|
|
if (!canManageInternalFields) {
|
|
delete payload.tenant
|
|
delete payload.organization
|
|
delete payload.requested_by
|
|
delete payload.request_code
|
|
}
|
|
|
|
await dispatch(create(payload))
|
|
await router.push('/booking_requests/booking_requests-list')
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Head>
|
|
<title>{getPageTitle(pageTitle)}</title>
|
|
</Head>
|
|
|
|
<SectionMain>
|
|
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={pageTitle} main>
|
|
{''}
|
|
</SectionTitleLineWithButton>
|
|
|
|
<CardBox className='mx-auto max-w-5xl'>
|
|
<div className='mb-6 rounded-2xl border border-slate-200 bg-slate-50 px-4 py-4 text-sm text-slate-600 dark:border-white/10 dark:bg-slate-900/40 dark:text-slate-300'>
|
|
{introCopy}
|
|
</div>
|
|
|
|
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
|
|
<Form>
|
|
<div className='grid gap-5 md:grid-cols-2'>
|
|
{canManageInternalFields && (
|
|
<>
|
|
<FormField label='Tenant' labelFor='tenant'>
|
|
<Field name='tenant' id='tenant' component={SelectField} options={[]} itemRef={'tenants'} />
|
|
</FormField>
|
|
|
|
<FormField label='Organization' labelFor='organization'>
|
|
<Field name='organization' id='organization' component={SelectField} options={[]} itemRef={'organizations'} />
|
|
</FormField>
|
|
|
|
<FormField label='Requested by' labelFor='requested_by'>
|
|
<Field name='requested_by' id='requested_by' component={SelectField} options={[]} itemRef={'users'} />
|
|
</FormField>
|
|
|
|
<FormField label='Request code'>
|
|
<Field name='request_code' placeholder='Request code' />
|
|
</FormField>
|
|
|
|
<FormField label='Status' labelFor='status'>
|
|
<Field name='status' id='status' component='select'>
|
|
<option value='draft'>draft</option>
|
|
<option value='submitted'>submitted</option>
|
|
<option value='in_review'>in_review</option>
|
|
<option value='changes_requested'>changes_requested</option>
|
|
<option value='approved'>approved</option>
|
|
<option value='rejected'>rejected</option>
|
|
<option value='expired'>expired</option>
|
|
<option value='converted_to_reservation'>converted_to_reservation</option>
|
|
<option value='canceled'>canceled</option>
|
|
</Field>
|
|
</FormField>
|
|
</>
|
|
)}
|
|
|
|
<FormField label='Check-in' labelFor='check_in_at'>
|
|
<Field type='datetime-local' name='check_in_at' id='check_in_at' />
|
|
</FormField>
|
|
|
|
<FormField label='Check-out' labelFor='check_out_at'>
|
|
<Field type='datetime-local' name='check_out_at' id='check_out_at' />
|
|
</FormField>
|
|
|
|
<FormField label='Preferred property' labelFor='preferred_property'>
|
|
<Field name='preferred_property' id='preferred_property' component={SelectField} options={[]} itemRef={'properties'} />
|
|
</FormField>
|
|
|
|
<FormField label='Preferred unit type' labelFor='preferred_unit_type'>
|
|
<Field name='preferred_unit_type' id='preferred_unit_type' component={SelectField} options={[]} itemRef={'unit_types'} />
|
|
</FormField>
|
|
|
|
<FormField label='Preferred bedrooms'>
|
|
<Field type='number' name='preferred_bedrooms' placeholder='Preferred bedrooms' min='0' />
|
|
</FormField>
|
|
|
|
<FormField label='Guest count'>
|
|
<Field type='number' name='guest_count' placeholder='Guest count' min='1' />
|
|
</FormField>
|
|
|
|
<FormField label='Budget code'>
|
|
<Field name='budget_code' placeholder='Budget code' />
|
|
</FormField>
|
|
|
|
<FormField label='Maximum budget amount'>
|
|
<Field type='number' name='max_budget_amount' placeholder='Maximum budget amount' min='0' step='0.01' />
|
|
</FormField>
|
|
|
|
<FormField label='Currency'>
|
|
<Field name='currency' placeholder='Currency' />
|
|
</FormField>
|
|
|
|
<div className='md:col-span-2'>
|
|
<FormField label='Purpose of stay' hasTextareaHeight>
|
|
<Field name='purpose_of_stay' as='textarea' placeholder='Describe the purpose of the stay' />
|
|
</FormField>
|
|
</div>
|
|
|
|
<div className='md:col-span-2'>
|
|
<FormField label='Special requirements' hasTextareaHeight>
|
|
<Field name='special_requirements' as='textarea' placeholder='Add guest, accessibility, or arrival details' />
|
|
</FormField>
|
|
</div>
|
|
</div>
|
|
|
|
<BaseDivider />
|
|
|
|
<BaseButtons>
|
|
<BaseButton type='submit' color='info' label={canManageInternalFields ? 'Create request' : 'Submit request'} />
|
|
<BaseButton type='reset' color='info' outline label='Reset' />
|
|
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/booking_requests/booking_requests-list')} />
|
|
</BaseButtons>
|
|
</Form>
|
|
</Formik>
|
|
</CardBox>
|
|
</SectionMain>
|
|
</>
|
|
)
|
|
}
|
|
|
|
Booking_requestsNew.getLayout = function getLayout(page: ReactElement) {
|
|
return (
|
|
<LayoutAuthenticated permission={'CREATE_BOOKING_REQUESTS'}>
|
|
{page}
|
|
</LayoutAuthenticated>
|
|
)
|
|
}
|
|
|
|
export default Booking_requestsNew
|