erp-platform/ui/src/views/list/ChartSeriesDialog.tsx
2025-11-09 13:30:15 +03:00

279 lines
11 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 { Button, FormContainer, Input, Notification, Select, Dialog, toast } from '@/components/ui'
import { Field, FieldArray, Form, Formik, FieldProps } from 'formik'
import { FaMinus, FaPlus } from 'react-icons/fa'
import { SelectBoxOption } from '@/types/shared'
import {
chartSeriesTypeOptions,
columnSummaryTypeListOptions,
} from '../admin/listForm/edit/options'
import { ChartSeriesDto } from '@/proxy/admin/charts/models'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { useStoreState } from '@/store/store'
import { object, array, string } from 'yup'
import { SummaryTypeEnum } from '@/proxy/form/models'
interface ChartSeriesDialogProps {
open: boolean
onClose: () => void
initialSeries: ChartSeriesDto[]
fieldList: SelectBoxOption[]
onSave: (series: ChartSeriesDto[]) => void
}
const schema = object().shape({
series: array().of(
object().shape({
name: string().required('Name Required'),
argumentField: string().required('Argument Field Required'),
valueField: string().required('Value Field Required'),
summaryType: string().required('Summary Type Required'),
}),
),
})
const ChartSeriesDialog = ({
open,
onClose,
initialSeries,
fieldList,
onSave,
}: ChartSeriesDialogProps) => {
const { translate } = useLocalization()
// State UserId güncellemesi için
const { userName } = useStoreState((s) => s.auth.user)
const newSeriesValue = () => {
return {
index: -1,
type: 'line',
name: '',
argumentField: '',
valueField: '',
summaryType: SummaryTypeEnum.Sum,
axis: '',
barOverlapGroup: '',
barPadding: 0,
barWidth: 0,
color: '',
cornerRadius: 0,
dashStyle: 'solid',
ignoreEmptyPoints: false,
pane: '',
rangeValue1Field: '',
rangeValue2Field: '',
selectionMode: 'none',
showInLegend: true,
visible: true,
width: 2,
label: {
visible: true,
backgroundColor: '#f05b41',
customizeText: '',
format: 'decimal',
font: {
color: '#FFFFFF',
family: '"Segoe UI", "Helvetica Neue", "Trebuchet MS", Verdana, sans-serif',
size: 12,
weight: 400,
},
},
userId: userName ?? '',
}
}
return (
<Dialog isOpen={open} onClose={onClose} width={1200}>
<div className="flex flex-col bg-white p-4 h-[600px]">
<Formik
enableReinitialize
initialValues={{
series: initialSeries && initialSeries.length > 0 ? initialSeries : [newSeriesValue()],
}}
validationSchema={schema}
onSubmit={(values, { setSubmitting }) => {
try {
onSave(values.series)
toast.push(<Notification type="success">{'Chart güncellendi'}</Notification>, {
placement: 'top-end',
})
onClose()
} catch (error: any) {
toast.push(
<Notification type="danger">
Hata
<code>{error}</code>
</Notification>,
{ placement: 'top-end' },
)
} finally {
setSubmitting(false)
}
}}
>
{({ setFieldValue, values, isSubmitting }) => (
<Form className="flex flex-col h-full">
<FormContainer size="sm" className="flex flex-col h-full">
{/* Header */}
<div className="mb-2 pb-2 border-b flex items-center justify-between">
<Button
variant="default"
shape="circle"
type="button"
size="xs"
onClick={() => setFieldValue('series', [...values.series, newSeriesValue()])}
>
<div className="flex items-center gap-1">
<FaPlus /> Seri Ekle
</div>
</Button>
</div>
{/* Kaydırılabilir içerik */}
<div className="flex-1 overflow-y-auto p-1">
<FieldArray name="series">
{({ remove }) => (
<div>
<div className="grid grid-cols-12 gap-2 font-semibold text-xs py-2">
<div className="text-center col-span-1">#</div>
<div className="text-center col-span-2">Type</div>
<div className="text-center col-span-2">Name</div>
<div className="text-center col-span-2">Argument Field</div>
<div className="text-center col-span-2">Value Field</div>
<div className="text-center col-span-2">Summary Type</div>
<div className="text-center col-span-1">#</div>
</div>
{values.series.map((_, index) => (
<div key={index} className="border-b py-1">
<div className="grid grid-cols-12 gap-1 items-center">
<div className="text-center text-xs col-span-1">
{values.series[index].index}
</div>
<div className="text-xs col-span-2">
<Field name={`series[${index}].type`}>
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={chartSeriesTypeOptions}
isClearable
value={chartSeriesTypeOptions.find(
(option) => option.value === field.value,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value)
}
/>
)}
</Field>
</div>
<div className="text-xs col-span-2">
<Field
size="sm"
name={`series[${index}].name`}
type="text"
component={Input}
className="text-xs px-1 py-0 grid-cols-2"
/>
</div>
<div className="text-xs col-span-2">
<Field type="text" name={`series[${index}].argumentField`}>
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
isClearable={true}
options={fieldList}
value={fieldList?.find(
(option) => option.value === field.value,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value)
}
menuPlacement="auto"
maxMenuHeight={150}
/>
)}
</Field>
</div>
<div className="text-xs col-span-2">
<Field type="text" name={`series[${index}].valueField`}>
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
isClearable={true}
options={fieldList}
value={fieldList?.find(
(option) => option.value === field.value,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value)
}
menuPlacement="auto"
maxMenuHeight={150}
/>
)}
</Field>
</div>
<div className="text-xs col-span-2">
<Field type="text" name={`series[${index}].summaryType`}>
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
isClearable={true}
options={columnSummaryTypeListOptions}
value={columnSummaryTypeListOptions.find(
(option) => option.value === field.value,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value)
}
/>
)}
</Field>
</div>
<div className="flex items-center justify-center gap-1 col-span-1">
<Button
shape="circle"
type="button"
size="xs"
icon={<FaMinus />}
className="bg-slate-100 hover:bg-red-100"
onClick={() => remove(index)}
/>
</div>
</div>
</div>
))}
</div>
)}
</FieldArray>
</div>
{/* Footer */}
<div className="flex gap-2 mt-auto pt-2 border-t text-right justify-end">
<Button
variant="solid"
loading={isSubmitting}
type="submit"
className="ml-auto px-4 py-1 text-sm rounded"
>
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
</div>
</FormContainer>
</Form>
)}
</Formik>
</div>
</Dialog>
)
}
export default ChartSeriesDialog