Chart Drawer

This commit is contained in:
Sedat Öztürk 2026-02-08 10:02:35 +03:00
parent 01ad6ffa60
commit 5d7db888ec
2 changed files with 62 additions and 54 deletions

View file

@ -247,29 +247,29 @@ export const chartPaletteExtensionModeOptions = [
] ]
export const chartSeriesTypeOptions = [ export const chartSeriesTypeOptions = [
{ value: 'line', label: 'Line' }, { value: 'line', label: 'Line', icon: '📈' },
{ value: 'stepline', label: 'Stepline' }, { value: 'stepline', label: 'Stepline', icon: '📉' },
{ value: 'bar', label: 'Bar' }, { value: 'bar', label: 'Bar', icon: '📊' },
{ value: 'fullstackedbar', label: 'Fullstackedbar' }, { value: 'fullstackedbar', label: 'Fullstacked Bar', icon: '📚' },
{ value: 'rangebar', label: 'Rangebar' }, { value: 'rangebar', label: 'Range Bar', icon: '📐' },
{ value: 'rangearea', label: 'Rangearea' }, { value: 'rangearea', label: 'Range Area', icon: '🗺️' },
{ value: 'fullstackedarea', label: 'Fullstackedarea' }, { value: 'fullstackedarea', label: 'Fullstacked Area', icon: '⛰️' },
{ value: 'area', label: 'Area' }, { value: 'area', label: 'Area', icon: '🏔️' },
{ value: 'bubble', label: 'Bubble' }, { value: 'bubble', label: 'Bubble', icon: '🫧' },
{ value: 'candlestick', label: 'Candlestick' }, { value: 'candlestick', label: 'Candlestick', icon: '🕯️' },
{ value: 'fullstackedline', label: 'Fullstackedline' }, { value: 'fullstackedline', label: 'Fullstacked Line', icon: '📶' },
{ value: 'fullstackedspline', label: 'Fullstackedspline' }, { value: 'fullstackedspline', label: 'Fullstacked Spline', icon: '〰️📶' },
{ value: 'fullstackedsplinearea', label: 'Fullstackedsplinearea' }, { value: 'fullstackedsplinearea', label: 'Fullstacked Spline Area', icon: '⛰️〰' },
{ value: 'scatter', label: 'Scatter' }, { value: 'scatter', label: 'Scatter', icon: '🔵' },
{ value: 'spline', label: 'Spline' }, { value: 'spline', label: 'Spline', icon: '〰️' },
{ value: 'splinearea', label: 'Splinearea' }, { value: 'splinearea', label: 'Spline Area', icon: '🌄' },
{ value: 'stackedarea', label: 'Stackedarea' }, { value: 'stackedarea', label: 'Stacked Area', icon: '🧱⛰️' },
{ value: 'stackedbar', label: 'Stackedbar' }, { value: 'stackedbar', label: 'Stacked Bar', icon: '🧱📊' },
{ value: 'stackedline', label: 'Stackedline' }, { value: 'stackedline', label: 'Stacked Line', icon: '🧱📈' },
{ value: 'stackedspline', label: 'Stackedspline' }, { value: 'stackedspline', label: 'Stacked Spline', icon: '🧱〰️' },
{ value: 'stackedsplinearea', label: 'Stackedsplinearea' }, { value: 'stackedsplinearea', label: 'Stacked Spline Area', icon: '🧱🌄' },
{ value: 'steparea', label: 'Steparea' }, { value: 'steparea', label: 'Step Area', icon: '🪜' },
{ value: 'stock', label: 'Stock' }, { value: 'stock', label: 'Stock', icon: '💹' },
] ]
export const chartSeriesSelectionModeOptions = [ export const chartSeriesSelectionModeOptions = [

View file

@ -2,7 +2,7 @@ import { Button, FormContainer, Input, Notification, Select, toast } from '@/com
import { Field, FieldArray, Form, Formik, FieldProps } from 'formik' import { Field, FieldArray, Form, Formik, FieldProps } from 'formik'
import { FaMinus, FaPlus, FaTimes, FaSave } from 'react-icons/fa' import { FaMinus, FaPlus, FaTimes, FaSave } from 'react-icons/fa'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { columnSummaryTypeListOptions } from '../admin/listForm/edit/options' import { chartSeriesTypeOptions, columnSummaryTypeListOptions } from '../admin/listForm/edit/options'
import { ChartSeriesDto } from '@/proxy/admin/charts/models' import { ChartSeriesDto } from '@/proxy/admin/charts/models'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { useStoreState } from '@/store/store' import { useStoreState } from '@/store/store'
@ -35,24 +35,15 @@ const ChartDrawer = ({
series: array().of( series: array().of(
object().shape({ object().shape({
name: string().required(translate('::App.Platform.ChartDrawer.NameRequired')), name: string().required(translate('::App.Platform.ChartDrawer.NameRequired')),
argumentField: string().required(translate('::App.Platform.ChartDrawer.ArgumentFieldRequired')), argumentField: string().required(
translate('::App.Platform.ChartDrawer.ArgumentFieldRequired'),
),
valueField: string().required(translate('::App.Platform.ChartDrawer.ValueFieldRequired')), valueField: string().required(translate('::App.Platform.ChartDrawer.ValueFieldRequired')),
summaryType: string().required(translate('::App.Platform.ChartDrawer.SummaryTypeRequired')), summaryType: string().required(translate('::App.Platform.ChartDrawer.SummaryTypeRequired')),
}), }),
), ),
}) })
// Chart type icons
const chartTypeIcons = [
{ type: 'line', label: 'Line', icon: '📈' },
{ type: 'bar', label: 'Bar', icon: '📊' },
{ type: 'area', label: 'Area', icon: '🏔️' },
{ type: 'scatter', label: 'Scatter', icon: '🔵' },
{ type: 'spline', label: 'Spline', icon: '〰️' },
{ type: 'stackedbar', label: 'Stacked Bar', icon: '📚' },
{ type: 'stackedarea', label: 'Stacked Area', icon: '⛰️' },
]
const newSeriesValue = () => { const newSeriesValue = () => {
return { return {
index: -1, index: -1,
@ -111,9 +102,14 @@ const ChartDrawer = ({
onSubmit={async (values, { setSubmitting }) => { onSubmit={async (values, { setSubmitting }) => {
try { try {
await onSave(values.series) await onSave(values.series)
toast.push(<Notification type="success">{translate('::App.Platform.ChartDrawer.ChartSaved')}</Notification>, { toast.push(
<Notification type="success">
{translate('::App.Platform.ChartDrawer.ChartSaved')}
</Notification>,
{
placement: 'top-end', placement: 'top-end',
}) },
)
onClose() onClose()
} catch (error: any) { } catch (error: any) {
toast.push( toast.push(
@ -186,7 +182,9 @@ const ChartDrawer = ({
> >
{/* Header */} {/* Header */}
<div className="flex items-center justify-between mb-3"> <div className="flex items-center justify-between mb-3">
<span className="font-semibold text-sm">{translate('::App.Platform.ChartDrawer.Series')} #{index + 1}</span> <span className="font-semibold text-sm">
{translate('::App.Platform.ChartDrawer.Series')} #{index + 1}
</span>
<Button <Button
type="button" type="button"
size="xs" size="xs"
@ -201,7 +199,9 @@ const ChartDrawer = ({
{/* Chart Type Selector */} {/* Chart Type Selector */}
<div className="mb-3"> <div className="mb-3">
<label className="text-xs font-medium mb-1 block">{translate('::App.Platform.ChartDrawer.ChartType')}</label> <label className="text-xs font-medium mb-1 block">
{translate('::App.Platform.ChartDrawer.ChartType')}
</label>
<Field name={`series[${index}].type`}> <Field name={`series[${index}].type`}>
{({ field, form }: FieldProps) => ( {({ field, form }: FieldProps) => (
<div className="relative"> <div className="relative">
@ -215,33 +215,33 @@ const ChartDrawer = ({
className="w-full px-3 py-2 text-left border rounded hover:bg-white flex items-center gap-2 transition-colors" className="w-full px-3 py-2 text-left border rounded hover:bg-white flex items-center gap-2 transition-colors"
> >
<span className="text-xl"> <span className="text-xl">
{chartTypeIcons.find((t) => t.type === field.value) {chartSeriesTypeOptions.find((t) => t.label === field.value)
?.icon || '📊'} ?.icon || '📊'}
</span> </span>
<span className="text-sm font-medium"> <span className="text-sm font-medium">
{chartTypeIcons.find((t) => t.type === field.value) {chartSeriesTypeOptions.find((t) => t.label === field.value)
?.label || field.value} ?.label || field.value}
</span> </span>
</button> </button>
{selectedSeriesIndex === index && ( {selectedSeriesIndex === index && (
<div className="absolute z-50 mt-1 w-full bg-white border rounded-lg shadow-xl p-2"> <div className="absolute z-50 mt-1 w-full bg-white border rounded-lg shadow-xl p-2">
<div className="grid grid-cols-2 gap-2"> <div className="grid grid-cols-2 gap-2">
{chartTypeIcons.map((chartType) => ( {chartSeriesTypeOptions.map((chartType) => (
<button <button
key={chartType.type} key={chartType.label}
type="button" type="button"
onClick={() => { onClick={() => {
form.setFieldValue(field.name, chartType.type) form.setFieldValue(field.name, chartType.label)
setSelectedSeriesIndex(-1) setSelectedSeriesIndex(-1)
}} }}
className={`p-3 rounded-lg hover:bg-blue-50 flex flex-col items-center gap-1 transition-all ${ className={`p-2 rounded-lg hover:bg-blue-50 flex items-center gap-2 transition-all ${
field.value === chartType.type field.value === chartType.label
? 'bg-blue-100 ring-2 ring-blue-400' ? 'bg-blue-100 ring-2 ring-blue-400'
: 'bg-gray-50' : 'bg-gray-50'
}`} }`}
> >
<span className="text-2xl">{chartType.icon}</span> <span className="text-xl">{chartType.icon}</span>
<span className="text-xs font-medium text-center"> <span className="text-xs font-medium">
{chartType.label} {chartType.label}
</span> </span>
</button> </button>
@ -256,7 +256,9 @@ const ChartDrawer = ({
{/* Name */} {/* Name */}
<div className="mb-3"> <div className="mb-3">
<label className="text-xs font-medium mb-1 block">{translate('::App.Platform.ChartDrawer.Name')}</label> <label className="text-xs font-medium mb-1 block">
{translate('::App.Platform.ChartDrawer.Name')}
</label>
<Field <Field
size="sm" size="sm"
name={`series[${index}].name`} name={`series[${index}].name`}
@ -284,7 +286,9 @@ const ChartDrawer = ({
onChange={(option) => { onChange={(option) => {
form.setFieldValue(field.name, option?.value) form.setFieldValue(field.name, option?.value)
}} }}
placeholder={translate('::App.Platform.ChartDrawer.SelectField')} placeholder={translate(
'::App.Platform.ChartDrawer.SelectField',
)}
/> />
)} )}
</Field> </Field>
@ -308,7 +312,9 @@ const ChartDrawer = ({
onChange={(option) => { onChange={(option) => {
form.setFieldValue(field.name, option?.value) form.setFieldValue(field.name, option?.value)
}} }}
placeholder={translate('::App.Platform.ChartDrawer.SelectField')} placeholder={translate(
'::App.Platform.ChartDrawer.SelectField',
)}
/> />
)} )}
</Field> </Field>
@ -351,7 +357,9 @@ const ChartDrawer = ({
<Button variant="solid" loading={isSubmitting} type="submit" className="flex-1"> <Button variant="solid" loading={isSubmitting} type="submit" className="flex-1">
<div className="flex items-center justify-center gap-2"> <div className="flex items-center justify-center gap-2">
<FaSave /> <FaSave />
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::App.Platform.ChartDrawer.Save')} {isSubmitting
? translate('::SavingWithThreeDot')
: translate('::App.Platform.ChartDrawer.Save')}
</div> </div>
</Button> </Button>
</div> </div>