165 lines
6.6 KiB
TypeScript
165 lines
6.6 KiB
TypeScript
import { mdiChartTimelineVariant } from '@mdi/js'
|
|
import Head from 'next/head'
|
|
import { uniqueId } from 'lodash';
|
|
import React, { ReactElement, useState } from 'react'
|
|
import CardBox from '../../components/CardBox'
|
|
import LayoutAuthenticated from '../../layouts/Authenticated'
|
|
import SectionMain from '../../components/SectionMain'
|
|
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
|
|
import { getPageTitle } from '../../config'
|
|
import TableBooking_requests from '../../components/Booking_requests/TableBooking_requests'
|
|
import BaseButton from '../../components/BaseButton'
|
|
import BaseButtons from '../../components/BaseButtons'
|
|
import axios from "axios";
|
|
import {useAppDispatch, useAppSelector} from "../../stores/hooks";
|
|
import CardBoxModal from "../../components/CardBoxModal";
|
|
import DragDropFilePicker from "../../components/DragDropFilePicker";
|
|
import {setRefetch, uploadCsv} from '../../stores/booking_requests/booking_requestsSlice';
|
|
|
|
|
|
import {hasPermission} from "../../helpers/userPermissions";
|
|
import { humanize } from "../../helpers/humanize";
|
|
|
|
|
|
|
|
const Booking_requestsTablesPage = () => {
|
|
const [filterItems, setFilterItems] = useState([]);
|
|
const [csvFile, setCsvFile] = useState<File | null>(null);
|
|
const [isModalActive, setIsModalActive] = useState(false);
|
|
|
|
const { currentUser } = useAppSelector((state) => state.auth);
|
|
const dispatch = useAppDispatch();
|
|
|
|
const [filters] = useState(([{label: 'Requestcode', title: 'request_code'},{label: 'Purposeofstay', title: 'purpose_of_stay'},{label: 'Specialrequirements', title: 'special_requirements'},{label: 'Budgetcode', title: 'budget_code'},{label: 'Currency', title: 'currency'},
|
|
{label: 'Preferredbedrooms', title: 'preferred_bedrooms', number: 'true'},{label: 'Guestcount', title: 'guest_count', number: 'true'},
|
|
{label: 'Maxbudgetamount', title: 'max_budget_amount', number: 'true'},
|
|
{label: 'Check-inat', title: 'check_in_at', date: 'true'},{label: 'Check-outat', title: 'check_out_at', date: 'true'},
|
|
{label: 'Tenant', title: 'tenant'},
|
|
{label: 'Requestedby', title: 'requested_by'},
|
|
{label: 'Preferredproperty', title: 'preferred_property'},
|
|
{label: 'Preferredunittype', title: 'preferred_unit_type'},
|
|
{label: 'Travelers', title: 'travelers'},{label: 'Approvalsteps', title: 'approval_steps'},{label: 'Documents', title: 'documents'},{label: 'Comments', title: 'comments'},
|
|
{label: 'Status', title: 'status', type: 'enum', options: ['draft','submitted','in_review','changes_requested','approved','rejected','expired','converted_to_reservation','canceled']},
|
|
]).map((filter) => ({ ...filter, label: humanize(filter.title) })));
|
|
|
|
const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_BOOKING_REQUESTS');
|
|
|
|
const addFilter = () => {
|
|
const newItem = {
|
|
id: uniqueId(),
|
|
fields: {
|
|
filterValue: '',
|
|
filterValueFrom: '',
|
|
filterValueTo: '',
|
|
selectedField: '',
|
|
},
|
|
};
|
|
newItem.fields.selectedField = filters[0].title;
|
|
setFilterItems([...filterItems, newItem]);
|
|
};
|
|
|
|
const getBooking_requestsCSV = async () => {
|
|
const response = await axios({url: '/booking_requests?filetype=csv', method: 'GET',responseType: 'blob'});
|
|
const type = response.headers['content-type']
|
|
const blob = new Blob([response.data], { type: type })
|
|
const link = document.createElement('a')
|
|
link.href = window.URL.createObjectURL(blob)
|
|
link.download = 'booking_requestsCSV.csv'
|
|
link.click()
|
|
};
|
|
|
|
const onModalConfirm = async () => {
|
|
if (!csvFile) return;
|
|
await dispatch(uploadCsv(csvFile));
|
|
dispatch(setRefetch(true));
|
|
setCsvFile(null);
|
|
setIsModalActive(false);
|
|
};
|
|
|
|
const onModalCancel = () => {
|
|
setCsvFile(null);
|
|
setIsModalActive(false);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Head>
|
|
<title>{getPageTitle('Booking Requests')}</title>
|
|
</Head>
|
|
<SectionMain>
|
|
<SectionTitleLineWithButton
|
|
icon={mdiChartTimelineVariant}
|
|
title="Booking Requests"
|
|
subtitle="A lighter intake board for incoming stay demand, approvals, and next actions."
|
|
main
|
|
/>
|
|
|
|
<CardBox className='mb-6 border border-white/10 shadow-none'>
|
|
<div className='flex flex-col gap-4 xl:flex-row xl:items-center xl:justify-between'>
|
|
<div>
|
|
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-slate-400'>Working view</p>
|
|
<h2 className='mt-1 text-lg font-semibold text-white'>Keep demand moving</h2>
|
|
<p className='mt-1 text-sm text-slate-400'>Create, filter, export, or switch to table view from one calm action strip.</p>
|
|
</div>
|
|
|
|
<div className='flex flex-col gap-3 xl:items-end'>
|
|
<BaseButtons
|
|
type='justify-start xl:justify-end'
|
|
mb='mb-0'
|
|
classAddon='mr-2 mb-2 last:mr-0'
|
|
>
|
|
{hasCreatePermission ? (
|
|
<BaseButton href={'/booking_requests/booking_requests-new'} color='info' label='New request' />
|
|
) : null}
|
|
<BaseButton color='whiteDark' outline label='Add filter' onClick={addFilter} />
|
|
<BaseButton color='whiteDark' outline label='Export CSV' onClick={getBooking_requestsCSV} />
|
|
{hasCreatePermission ? (
|
|
<BaseButton color='whiteDark' outline label='Import CSV' onClick={() => setIsModalActive(true)} />
|
|
) : null}
|
|
<BaseButton href={'/booking_requests/booking_requests-table'} color='whiteDark' outline label='Table view' />
|
|
</BaseButtons>
|
|
|
|
<div className='flex min-h-[40px] items-center justify-start xl:justify-end'>
|
|
<div id='delete-rows-button'></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CardBox>
|
|
|
|
<TableBooking_requests
|
|
filterItems={filterItems}
|
|
setFilterItems={setFilterItems}
|
|
filters={filters}
|
|
showGrid={false}
|
|
/>
|
|
</SectionMain>
|
|
<CardBoxModal
|
|
title='Upload CSV'
|
|
buttonColor='info'
|
|
buttonLabel={'Confirm'}
|
|
isActive={isModalActive}
|
|
onConfirm={onModalConfirm}
|
|
onCancel={onModalCancel}
|
|
>
|
|
<DragDropFilePicker
|
|
file={csvFile}
|
|
setFile={setCsvFile}
|
|
formats={'.csv'}
|
|
/>
|
|
</CardBoxModal>
|
|
</>
|
|
)
|
|
}
|
|
|
|
Booking_requestsTablesPage.getLayout = function getLayout(page: ReactElement) {
|
|
return (
|
|
<LayoutAuthenticated
|
|
permission={'READ_BOOKING_REQUESTS'}
|
|
>
|
|
{page}
|
|
</LayoutAuthenticated>
|
|
)
|
|
}
|
|
|
|
export default Booking_requestsTablesPage
|