Files
universal_is/client/src/pages/Fuel.tsx
popovspiridon99 145827ab6d nestjs rewrite
2025-08-01 11:08:33 +09:00

207 lines
7.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
)
}