fix: applied timezone to default values, removed value nesting

This commit is contained in:
2025-10-28 11:43:13 +04:00
parent 3575b9f34a
commit ea6a6df371
6 changed files with 61 additions and 56 deletions

View File

@ -26,11 +26,10 @@ const AttributeValueInput: FC<Props> = ({
}; };
const renderCheckbox = () => { const renderCheckbox = () => {
const localValue = value === undefined ? false : value;
return ( return (
<Checkbox <Checkbox
{...commonProps} {...commonProps}
checked={localValue} checked={Boolean(value)}
onChange={e => onChange(e.currentTarget.checked)} onChange={e => onChange(e.currentTarget.checked)}
/> />
); );
@ -80,7 +79,7 @@ const AttributeValueInput: FC<Props> = ({
<NumberInput <NumberInput
{...commonProps} {...commonProps}
allowDecimal={attrInfo.type.type === "float"} allowDecimal={attrInfo.type.type === "float"}
value={Number(value)} value={value ? Number(value) : undefined}
onChange={value => onChange(Number(value))} onChange={value => onChange(Number(value))}
/> />
); );

View File

@ -23,8 +23,9 @@ type Props = {
deal: DealSchema; deal: DealSchema;
}; };
type Value = { type AttrInfo = {
value?: any; value?: any;
isApplicableToGroup: boolean;
}; };
const CustomTab: FC<Props> = ({ module, deal }) => { const CustomTab: FC<Props> = ({ module, deal }) => {
@ -35,16 +36,19 @@ const CustomTab: FC<Props> = ({ module, deal }) => {
}); });
const [attributeValuesMap, setAttributeValuesMap] = useState< const [attributeValuesMap, setAttributeValuesMap] = useState<
Map<number, Value | null> Map<number, AttrInfo | null>
>(new Map()); >(new Map());
const [attributeErrorsMap, setAttributeErrorsMap] = useState< const [attributeErrorsMap, setAttributeErrorsMap] = useState<
Map<number, string> Map<number, string>
>(new Map()); >(new Map());
useEffect(() => { useEffect(() => {
const values = new Map<number, Value | null>(); const values = new Map<number, AttrInfo | null>();
for (const dealAttr of dealAttributes) { for (const dealAttr of dealAttributes) {
values.set(dealAttr.attributeId, dealAttr?.value); values.set(dealAttr.attributeId, {
...dealAttr,
value: dealAttr.value,
});
} }
setAttributeValuesMap(values); setAttributeValuesMap(values);
}, [dealAttributes]); }, [dealAttributes]);
@ -65,10 +69,10 @@ const CustomTab: FC<Props> = ({ module, deal }) => {
attributeValuesMap attributeValuesMap
.entries() .entries()
.map( .map(
([attributeId, value]) => ([attributeId, info]) =>
({ ({
attributeId, attributeId,
value, ...info,
}) as UpdateDealModuleAttributeSchema }) as UpdateDealModuleAttributeSchema
) )
.toArray(); .toArray();
@ -83,7 +87,10 @@ const CustomTab: FC<Props> = ({ module, deal }) => {
attrInfo={attribute} attrInfo={attribute}
value={attributeValuesMap.get(attribute.attributeId)?.value} value={attributeValuesMap.get(attribute.attributeId)?.value}
onChange={value => { onChange={value => {
attributeValuesMap.set(attribute.attributeId, { value }); attributeValuesMap.set(attribute.attributeId, {
...attribute,
value,
});
setAttributeValuesMap(new Map(attributeValuesMap)); setAttributeValuesMap(new Map(attributeValuesMap));
attributeErrorsMap.delete(attribute.attributeId); attributeErrorsMap.delete(attribute.attributeId);
setAttributeErrorsMap(new Map(attributeErrorsMap)); setAttributeErrorsMap(new Map(attributeErrorsMap));

View File

@ -2,6 +2,7 @@ import { Checkbox, NumberInput, TextInput } from "@mantine/core";
import { DatePickerInput, DateTimePicker } from "@mantine/dates"; import { DatePickerInput, DateTimePicker } from "@mantine/dates";
import { UseFormReturnType } from "@mantine/form"; import { UseFormReturnType } from "@mantine/form";
import { UpdateAttributeSchema } from "@/lib/client"; import { UpdateAttributeSchema } from "@/lib/client";
import { naiveDateTimeStringToUtc } from "@/utils/datetime";
type Props = { type Props = {
form: UseFormReturnType<Partial<UpdateAttributeSchema>>; form: UseFormReturnType<Partial<UpdateAttributeSchema>>;
@ -12,7 +13,7 @@ const DefaultAttributeValueInput = ({ form }: Props) => {
const label = "Значение по умолчанию"; const label = "Значение по умолчанию";
const inputName = "defaultValue"; const inputName = "defaultValue";
const value = form.getValues().defaultValue?.value; const value = form.getValues().defaultValue;
if (type === "bool") { if (type === "bool") {
return ( return (
@ -21,9 +22,7 @@ const DefaultAttributeValueInput = ({ form }: Props) => {
{...form.getInputProps(inputName, { type: "checkbox" })} {...form.getInputProps(inputName, { type: "checkbox" })}
checked={value as boolean} checked={value as boolean}
onChange={e => onChange={e =>
form.setFieldValue("defaultValue", { form.setFieldValue("defaultValue", e.currentTarget.checked)
value: e.currentTarget.checked,
})
} }
/> />
); );
@ -33,13 +32,11 @@ const DefaultAttributeValueInput = ({ form }: Props) => {
label={label} label={label}
{...form.getInputProps(inputName)} {...form.getInputProps(inputName)}
value={ value={
form.values.defaultValue?.value form.values.defaultValue
? new Date(String(form.values.defaultValue.value)) ? new Date(String(form.values.defaultValue))
: null : null
} }
onChange={value => onChange={value => form.setFieldValue("defaultValue", value)}
form.setFieldValue("defaultValue", { value })
}
clearable clearable
locale={"ru"} locale={"ru"}
valueFormat={"DD.MM.YYYY"} valueFormat={"DD.MM.YYYY"}
@ -51,13 +48,21 @@ const DefaultAttributeValueInput = ({ form }: Props) => {
label={label} label={label}
{...form.getInputProps(inputName)} {...form.getInputProps(inputName)}
value={ value={
form.values.defaultValue?.value form.values.defaultValue
? new Date(String(form.values.defaultValue.value)) ? naiveDateTimeStringToUtc(
form.values.defaultValue as string
)
: null : null
} }
onChange={value => onChange={val => {
form.setFieldValue("defaultValue", { value }) if (!val) return;
} const localDate = new Date(val.replace(" ", "T"));
const utcString = localDate
.toISOString()
.substring(0, 19)
.replace("T", " ");
form.setFieldValue("defaultValue", utcString);
}}
clearable clearable
locale={"ru"} locale={"ru"}
valueFormat={"DD.MM.YYYY HH:mm"} valueFormat={"DD.MM.YYYY HH:mm"}
@ -76,9 +81,9 @@ const DefaultAttributeValueInput = ({ form }: Props) => {
allowDecimal={type === "float"} allowDecimal={type === "float"}
label={label} label={label}
{...form.getInputProps(inputName)} {...form.getInputProps(inputName)}
value={Number(form.values.defaultValue?.value)} value={Number(form.values.defaultValue)}
onChange={value => onChange={value =>
form.setFieldValue("defaultValue", { value: Number(value) }) form.setFieldValue("defaultValue", Number(value))
} }
/> />
); );

View File

@ -7,6 +7,7 @@ import { Box } from "@mantine/core";
import useIsMobile from "@/hooks/utils/useIsMobile"; import useIsMobile from "@/hooks/utils/useIsMobile";
import { ModuleAttributeSchema } from "@/lib/client"; import { ModuleAttributeSchema } from "@/lib/client";
import { import {
naiveDateTimeStringToUtc,
utcDateTimeToLocalString, utcDateTimeToLocalString,
utcDateToLocalString, utcDateToLocalString,
} from "@/utils/datetime"; } from "@/utils/datetime";
@ -32,12 +33,14 @@ const useAttributesInnerTableColumns = () => {
accessor: "defaultValue", accessor: "defaultValue",
render: attr => { render: attr => {
if (!attr.defaultValue) return <>-</>; if (!attr.defaultValue) return <>-</>;
const value = attr.defaultValue.value; const value = attr.defaultValue;
if (value === null) return <>-</>; if (value === null) return <>-</>;
const type = attr.type.type; const type = attr.type.type;
if (type === "datetime") { if (type === "datetime") {
return utcDateTimeToLocalString(value as string); return utcDateTimeToLocalString(
naiveDateTimeStringToUtc(value as string)
);
} }
if (type === "date") { if (type === "date") {
return utcDateToLocalString(value as string); return utcDateToLocalString(value as string);

View File

@ -43,9 +43,7 @@ export type AttributeSchema = {
/** /**
* Defaultvalue * Defaultvalue
*/ */
defaultValue: { defaultValue: unknown | null;
[key: string]: unknown;
} | null;
/** /**
* Description * Description
*/ */
@ -305,9 +303,7 @@ export type CreateAttributeSchema = {
/** /**
* Defaultvalue * Defaultvalue
*/ */
defaultValue: { defaultValue: unknown | null;
[key: string]: unknown;
} | null;
/** /**
* Description * Description
*/ */
@ -1037,16 +1033,12 @@ export type DealModuleAttributeSchema = {
/** /**
* Value * Value
*/ */
value: { value: unknown | null;
[key: string]: unknown;
} | null;
type: AttributeTypeSchema; type: AttributeTypeSchema;
/** /**
* Defaultvalue * Defaultvalue
*/ */
defaultValue: { defaultValue: unknown;
[key: string]: unknown;
};
/** /**
* Description * Description
*/ */
@ -1770,9 +1762,7 @@ export type ModuleAttributeSchema = {
/** /**
* Defaultvalue * Defaultvalue
*/ */
defaultValue: { defaultValue: unknown | null;
[key: string]: unknown;
} | null;
/** /**
* Description * Description
*/ */
@ -2374,9 +2364,7 @@ export type UpdateAttributeSchema = {
/** /**
* Defaultvalue * Defaultvalue
*/ */
defaultValue?: { defaultValue?: unknown | null;
[key: string]: unknown;
} | null;
/** /**
* Description * Description
*/ */
@ -2530,12 +2518,14 @@ export type UpdateDealModuleAttributeSchema = {
* Attributeid * Attributeid
*/ */
attributeId: number; attributeId: number;
/**
* Isapplicabletogroup
*/
isApplicableToGroup: boolean;
/** /**
* Value * Value
*/ */
value: { value?: unknown | null;
[key: string]: unknown;
} | null;
}; };
/** /**

View File

@ -33,7 +33,7 @@ export const zAttributeSchema = z.object({
label: z.string(), label: z.string(),
isApplicableToGroup: z.boolean(), isApplicableToGroup: z.boolean(),
isNullable: z.boolean(), isNullable: z.boolean(),
defaultValue: z.union([z.object({}), z.null()]), defaultValue: z.union([z.unknown(), z.null()]),
description: z.string(), description: z.string(),
typeId: z.int(), typeId: z.int(),
id: z.int(), id: z.int(),
@ -141,7 +141,7 @@ export const zCreateAttributeSchema = z.object({
label: z.string(), label: z.string(),
isApplicableToGroup: z.boolean(), isApplicableToGroup: z.boolean(),
isNullable: z.boolean(), isNullable: z.boolean(),
defaultValue: z.union([z.object({}), z.null()]), defaultValue: z.union([z.unknown(), z.null()]),
description: z.string(), description: z.string(),
typeId: z.int(), typeId: z.int(),
}); });
@ -830,9 +830,9 @@ export const zDealModuleAttributeSchema = z.object({
attributeId: z.int(), attributeId: z.int(),
label: z.string(), label: z.string(),
originalLabel: z.string(), originalLabel: z.string(),
value: z.union([z.object({}), z.null()]), value: z.union([z.unknown(), z.null()]),
type: zAttributeTypeSchema, type: zAttributeTypeSchema,
defaultValue: z.object({}), defaultValue: z.unknown(),
description: z.string(), description: z.string(),
isApplicableToGroup: z.boolean(), isApplicableToGroup: z.boolean(),
isNullable: z.boolean(), isNullable: z.boolean(),
@ -1023,7 +1023,7 @@ export const zModuleAttributeSchema = z.object({
label: z.string(), label: z.string(),
isApplicableToGroup: z.boolean(), isApplicableToGroup: z.boolean(),
isNullable: z.boolean(), isNullable: z.boolean(),
defaultValue: z.union([z.object({}), z.null()]), defaultValue: z.union([z.unknown(), z.null()]),
description: z.string(), description: z.string(),
typeId: z.int(), typeId: z.int(),
id: z.int(), id: z.int(),
@ -1341,7 +1341,7 @@ export const zUpdateAttributeSchema = z.object({
label: z.optional(z.union([z.string(), z.null()])), label: z.optional(z.union([z.string(), z.null()])),
isApplicableToGroup: z.optional(z.union([z.boolean(), z.null()])), isApplicableToGroup: z.optional(z.union([z.boolean(), z.null()])),
isNullable: z.optional(z.union([z.boolean(), z.null()])), isNullable: z.optional(z.union([z.boolean(), z.null()])),
defaultValue: z.optional(z.union([z.object({}), z.null()])), defaultValue: z.optional(z.union([z.unknown(), z.null()])),
description: z.optional(z.union([z.string(), z.null()])), description: z.optional(z.union([z.string(), z.null()])),
type: z.optional(z.union([zAttributeTypeSchema, z.null()])), type: z.optional(z.union([zAttributeTypeSchema, z.null()])),
}); });
@ -1460,7 +1460,8 @@ export const zUpdateDealGroupResponse = z.object({
*/ */
export const zUpdateDealModuleAttributeSchema = z.object({ export const zUpdateDealModuleAttributeSchema = z.object({
attributeId: z.int(), attributeId: z.int(),
value: z.union([z.object({}), z.null()]), isApplicableToGroup: z.boolean(),
value: z.optional(z.union([z.unknown(), z.null()])),
}); });
/** /**