207 lines
7.1 KiB
TypeScript
207 lines
7.1 KiB
TypeScript
import { ActionIcon, Button, Flex, Input, Loader, LoadingOverlay, Modal, Overlay, Table, Tabs, TextInput, useMantineColorScheme } from "@mantine/core";
|
||
import { IconMathMax, IconPlus, IconTableMinus, IconTablePlus } from "@tabler/icons-react";
|
||
import { FuelExpenseDto, FuelExpenseDtoHeaders, FuelLimitDto, FuelLimitDtoHeaders } from "../dto/fuel/fuel.dto";
|
||
import useSWR from "swr";
|
||
import { fetcher } from "../http/axiosInstanceNest";
|
||
import { useEffect, useState } from "react";
|
||
import { useDisclosure } from "@mantine/hooks";
|
||
import { DateInput, DatePicker } from '@mantine/dates'
|
||
import { SubmitHandler, useForm } from "react-hook-form";
|
||
|
||
import { AgGridReact } from "ag-grid-react";
|
||
import { AllCommunityModule, ColDef, ModuleRegistry } from 'ag-grid-community'
|
||
|
||
ModuleRegistry.registerModules([AllCommunityModule])
|
||
|
||
type FieldType = 'text' | 'number' | 'select' | 'date'
|
||
|
||
interface IPostInclude {
|
||
field: string
|
||
field_type: FieldType
|
||
}
|
||
|
||
interface ITableSchema {
|
||
label: string
|
||
value: string
|
||
get: string
|
||
post: string
|
||
headers: { [key: string]: string }
|
||
post_include: IPostInclude[]
|
||
icon: JSX.Element
|
||
}
|
||
|
||
export default function FuelPage() {
|
||
const tables: ITableSchema[] = [
|
||
{
|
||
label: 'Расходы',
|
||
value: 'expenses',
|
||
get: '/fuel/expenses',
|
||
post: '/fuel/expenses',
|
||
headers: FuelExpenseDtoHeaders,
|
||
post_include: [
|
||
{
|
||
field: 'id_boiler',
|
||
field_type: 'text'
|
||
},
|
||
{
|
||
field: 'id_fuel',
|
||
field_type: 'text'
|
||
},
|
||
{
|
||
field: 'date',
|
||
field_type: 'date'
|
||
},
|
||
{
|
||
field: 'value',
|
||
field_type: 'text'
|
||
}
|
||
],
|
||
icon: <IconTableMinus size={12} />
|
||
},
|
||
{
|
||
label: 'Лимиты',
|
||
value: 'limits',
|
||
get: '/fuel/limits',
|
||
post: '/fuel/limits',
|
||
headers: FuelLimitDtoHeaders,
|
||
post_include: [
|
||
{
|
||
field: 'id_boiler',
|
||
field_type: 'text'
|
||
},
|
||
{
|
||
field: 'id_fuel',
|
||
field_type: 'text'
|
||
},
|
||
{
|
||
field: 'month',
|
||
field_type: 'number'
|
||
},
|
||
{
|
||
field: 'year',
|
||
field_type: 'number'
|
||
},
|
||
{
|
||
field: 'value',
|
||
field_type: 'text'
|
||
}
|
||
],
|
||
icon: <IconMathMax size={12} />,
|
||
}
|
||
]
|
||
|
||
const [currentTab, setCurrentTab] = useState(tables[0])
|
||
|
||
const { data, isLoading } = useSWR(currentTab.get, () => fetcher(currentTab.get), { revalidateOnFocus: false })
|
||
|
||
const [openedCreateModal, { open: openCreateModal, close: closeCreateModal }] = useDisclosure(false)
|
||
|
||
const { colorScheme } = useMantineColorScheme()
|
||
|
||
useEffect(() => {
|
||
if (colorScheme === 'dark') {
|
||
document.body.dataset.agThemeMode = 'dark'
|
||
} else {
|
||
document.body.dataset.agThemeMode = 'light'
|
||
}
|
||
}, [colorScheme])
|
||
|
||
return (
|
||
<>
|
||
<ModalCreate openedCreateModal={openedCreateModal} closeCreateModal={closeCreateModal} currentTab={currentTab} />
|
||
|
||
<Tabs defaultValue={tables[0].value} w='100%' onChange={(tab) => setCurrentTab(tables.find(table => table.value === tab) || tables[0])}>
|
||
<Tabs.List>
|
||
{tables.map((table, index) => (
|
||
<Tabs.Tab key={index} value={table.value} leftSection={table.icon}>
|
||
{table.label}
|
||
</Tabs.Tab>
|
||
))}
|
||
</Tabs.List>
|
||
|
||
<Flex p='sm'>
|
||
<Button leftSection={<IconPlus />} onClick={openCreateModal}>
|
||
Добавить
|
||
</Button>
|
||
</Flex>
|
||
|
||
{tables.map((table, index) => (
|
||
<Tabs.Panel key={index} value={table.value} w='100%' h='100%'>
|
||
{isLoading ?
|
||
<Flex w='100%' justify={'center'} p='md'>
|
||
<Loader />
|
||
</Flex>
|
||
:
|
||
<>
|
||
<AgGridReact
|
||
//rowData={data}
|
||
rowData={[
|
||
Object.keys(table.headers).reduce((obj, key) => ({ ...obj, [key]: 'test' }), {}),
|
||
Object.keys(table.headers).reduce((obj, key) => ({ ...obj, [key]: 'test' }), {})
|
||
]}
|
||
columnDefs={Object.keys(table.headers).map((header) => ({
|
||
field: header
|
||
})) as ColDef[]}
|
||
defaultColDef={{
|
||
flex: 1,
|
||
}}
|
||
/>
|
||
</>
|
||
}
|
||
</Tabs.Panel>
|
||
))}
|
||
</Tabs>
|
||
</>
|
||
)
|
||
}
|
||
|
||
const ModalCreate = ({
|
||
openedCreateModal,
|
||
closeCreateModal,
|
||
currentTab
|
||
}: {
|
||
openedCreateModal: boolean
|
||
closeCreateModal: () => void
|
||
currentTab: ITableSchema
|
||
}) => {
|
||
const { register, handleSubmit, reset, watch, formState: { errors, isSubmitting, dirtyFields, isValid } } = useForm({
|
||
mode: 'onChange',
|
||
})
|
||
|
||
const onSubmit: SubmitHandler<any> = async (values: any) => {
|
||
console.log('Values to submit:', values)
|
||
}
|
||
|
||
return (
|
||
<Modal withinPortal opened={openedCreateModal} onClose={closeCreateModal}>
|
||
<LoadingOverlay visible={isSubmitting} />
|
||
|
||
<Flex direction='column' gap='sm' component='form' onSubmit={handleSubmit(onSubmit)}>
|
||
{currentTab.post_include.map((header, index) => {
|
||
switch (header.field_type) {
|
||
case 'date':
|
||
return (
|
||
<DateInput label={header.field} />
|
||
)
|
||
case 'text':
|
||
return (
|
||
<TextInput key={index} label={header.field} {...register(header.field, {
|
||
required: true
|
||
})} />
|
||
)
|
||
default:
|
||
return (
|
||
<TextInput key={index} label={header.field} {...register(header.field, {
|
||
required: true
|
||
})} />
|
||
)
|
||
}
|
||
})}
|
||
|
||
<Button mt='xl' type='submit'>
|
||
Добавить
|
||
</Button>
|
||
</Flex>
|
||
</Modal>
|
||
)
|
||
} |