realbox edit components
This commit is contained in:
@@ -1,69 +1,57 @@
|
||||
'use client';
|
||||
|
||||
import BaseButton from '@/components/ui-kit/BaseButton';
|
||||
import BaseIconButton from '@/components/ui-kit/BaseIconButton';
|
||||
import { party_requests } from '@/data/party/party.requests';
|
||||
import { box_requests } from '@/data/box/box.requests';
|
||||
import { real_box_requests } from '@/data/real-box/real-box.requests';
|
||||
import { pageLinks } from '@/helpers/constants';
|
||||
import { notifyUnknownError } from '@/services/notification';
|
||||
import { Box, FormHelperText, Grid, Stack, Typography, styled } from '@mui/material';
|
||||
import { AddCircleRounded, Close } from '@mui/icons-material';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Controller, useFieldArray, useForm } from 'react-hook-form';
|
||||
import BaseIconButton from '@/components/ui-kit/BaseIconButton';
|
||||
import { AddCircleRounded, Close } from '@mui/icons-material';
|
||||
import useRequest from '@/hooks/useRequest';
|
||||
import { useMyTranslation } from '@/hooks/useMyTranslation';
|
||||
import AsyncSelect from 'react-select/async';
|
||||
import { selectDefaultStyles } from '@/components/ui-kit/BaseReactSelect';
|
||||
import { useAuthContext } from '@/context/auth-context';
|
||||
import { useMyNavigation } from '@/hooks/useMyNavigation';
|
||||
import AsyncSelect from 'react-select/async';
|
||||
import { box_requests } from '@/data/box/box.requests';
|
||||
import { real_box_requests } from '@/data/real-box/real-box.requests';
|
||||
|
||||
import { useMyTranslation } from '@/hooks/useMyTranslation';
|
||||
import { FormValues, RealCreateBoxBodyType, UpdateRealBoxBodyType } from '@/data/real-box/real-box.model';
|
||||
import get from 'lodash.get';
|
||||
import useRequest from '@/hooks/useRequest';
|
||||
|
||||
const StyledCreateBox = styled(Box)`
|
||||
.item-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
}
|
||||
.item-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
& > * {
|
||||
flex: 1 1 1;
|
||||
}
|
||||
& > * {
|
||||
flex: 1 1 1;
|
||||
}
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
interface Props {
|
||||
partiesData?: { value: number; label: string }[];
|
||||
initialValues?: {
|
||||
id: number;
|
||||
boxId: string;
|
||||
box_name: string;
|
||||
partyId: number;
|
||||
partyName: string;
|
||||
packetId: string;
|
||||
products_list: {
|
||||
id: number;
|
||||
price: number | string;
|
||||
cargoId: string;
|
||||
trekId: string;
|
||||
name: string;
|
||||
nameRu: string;
|
||||
amount: number;
|
||||
weight: number;
|
||||
}[];
|
||||
id?: number;
|
||||
boxId?: string;
|
||||
partyId?: number;
|
||||
partyName?: string;
|
||||
paketIds?: Array<{ id: number; packetName: string }>;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
const { user, isAdmin: isAdminUser } = useAuthContext();
|
||||
const editMode = !!initialValues && !!initialValues.id;
|
||||
const isAdmin = isAdminUser && editMode;
|
||||
const editMode = !!initialValues?.id;
|
||||
const t = useMyTranslation();
|
||||
const params = useSearchParams();
|
||||
const navigation = useMyNavigation();
|
||||
const [partyId, setPartyId] = useState<number | string>("");
|
||||
const { push } = useMyNavigation();
|
||||
const [partyId, setPartyId] = useState<number | string>('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const helperRef = useRef<{
|
||||
finished: boolean;
|
||||
@@ -82,20 +70,41 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
control,
|
||||
handleSubmit,
|
||||
setValue,
|
||||
reset,
|
||||
formState: { errors },
|
||||
} = useForm<any>({
|
||||
} = useForm<FormValues>({
|
||||
defaultValues: {
|
||||
partyId: params.get('party_id') ? +params.get('party_id')! : '',
|
||||
paketIds: editMode
|
||||
? [{ id: initialValues?.partyId }]
|
||||
partyName: initialValues?.partyName || '',
|
||||
paketIds: initialValues?.paketIds
|
||||
? initialValues.paketIds.map((paket) => ({ id: paket.id }))
|
||||
: params.get('party_id')
|
||||
? [{ id: +params.get('party_id')! }]
|
||||
: [{ id: '' }],
|
||||
...initialValues,
|
||||
id: initialValues?.id,
|
||||
boxId: initialValues?.boxId,
|
||||
partyId: initialValues?.partyId,
|
||||
},
|
||||
});
|
||||
|
||||
const pakets = useFieldArray({
|
||||
// Reset form when initialValues change (for edit mode)
|
||||
useEffect(() => {
|
||||
if (initialValues) {
|
||||
reset({
|
||||
partyName: initialValues.partyName || '',
|
||||
paketIds: initialValues.paketIds
|
||||
? initialValues.paketIds.map((paket) => ({ id: paket.id }))
|
||||
: [{ id: '' }],
|
||||
id: initialValues.id,
|
||||
boxId: initialValues.boxId,
|
||||
partyId: initialValues.partyId,
|
||||
});
|
||||
if (initialValues.partyId) {
|
||||
setPartyId(initialValues.partyId);
|
||||
}
|
||||
}
|
||||
}, [initialValues, reset]);
|
||||
|
||||
const { fields, append, remove } = useFieldArray({
|
||||
control,
|
||||
name: 'paketIds',
|
||||
keyName: 'key',
|
||||
@@ -109,54 +118,52 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
partyId: partyId,
|
||||
}),
|
||||
{
|
||||
selectData(data) {
|
||||
return data?.data?.data;
|
||||
},
|
||||
}
|
||||
selectData: (data) => data?.data?.data ?? [],
|
||||
enabled: !!partyId,
|
||||
},
|
||||
);
|
||||
|
||||
const { data: list } = useMemo(() => {
|
||||
if (getBoxesQuery.data?.data) {
|
||||
return {
|
||||
data: getBoxesQuery.data.data.filter((box: any) => box.status === 'READY_TO_INVOICE'),
|
||||
};
|
||||
}
|
||||
return { data: [] };
|
||||
}, [getBoxesQuery, partyId]);
|
||||
const list = useMemo(() => {
|
||||
return getBoxesQuery.data?.data.filter((box: any) => box.status === 'READY_TO_INVOICE') ?? [];
|
||||
}, [getBoxesQuery.data]);
|
||||
|
||||
useEffect(() => {
|
||||
if (partyId) {
|
||||
getBoxesQuery.refetch();
|
||||
}
|
||||
}, [partyId]);
|
||||
}, [partyId, getBoxesQuery.refetch]);
|
||||
|
||||
const { data: defaultParties } = useRequest(() => party_requests.getAll({ status: 'COLLECTING' }), {
|
||||
enabled: true,
|
||||
selectData(data) {
|
||||
return data.data.data.data.map(p => ({ value: p.id, label: p.name }));
|
||||
const { data: defaultParties } = useRequest(
|
||||
() => party_requests.getAll({ status: 'COLLECTING' }),
|
||||
{
|
||||
enabled: true,
|
||||
selectData: (data) =>
|
||||
data.data.data.data.map((p: any) => ({ value: p.id, label: p.name })),
|
||||
onSuccess: (data) => {
|
||||
if (!editMode && data?.data?.data?.data?.[0]) {
|
||||
const defaultParty = data.data.data.data[0];
|
||||
helperRef.current.settedDefaultParty = defaultParty;
|
||||
setValue('partyName', defaultParty.name);
|
||||
setValue('paketIds.0.id', defaultParty.id); // Use dot notation
|
||||
setPartyId(defaultParty.id);
|
||||
}
|
||||
helperRef.current.partyFinished = true;
|
||||
if (helperRef.current.clientFinished) {
|
||||
helperRef.current.finished = true;
|
||||
}
|
||||
},
|
||||
placeholderData: [],
|
||||
},
|
||||
onSuccess(data) {
|
||||
if (!editMode && data?.data?.data?.data?.[0]) {
|
||||
helperRef.current.settedDefaultParty = data.data.data.data[0];
|
||||
setValue('partyId', data.data.data.data[0].id);
|
||||
setValue('paketIds[0].id', data.data.data.data[0].id);
|
||||
}
|
||||
helperRef.current.partyFinished = true;
|
||||
if (helperRef.current.clientFinished) {
|
||||
helperRef.current.finished = true;
|
||||
}
|
||||
},
|
||||
placeholderData: [],
|
||||
});
|
||||
);
|
||||
|
||||
const onSubmit = handleSubmit(async values => {
|
||||
const onSubmit = handleSubmit(async (values) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const packetDtos = values.paketIds.map((paket: any) => paket.id).filter((id: any) => id);
|
||||
const packetDtos = values.paketIds.map((paket) => Number(paket.id)).filter((id) => id);
|
||||
|
||||
if (editMode) {
|
||||
const updateBody: UpdateRealBoxBodyType = {
|
||||
boxId: initialValues?.boxId,
|
||||
boxId: initialValues!.boxId!,
|
||||
partyName: values.partyName,
|
||||
packetDtos,
|
||||
};
|
||||
@@ -169,7 +176,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
await real_box_requests.create(createBody);
|
||||
}
|
||||
|
||||
navigation.push(pageLinks.dashboard.boxes.index);
|
||||
push(pageLinks.dashboard.real_boxes.index);
|
||||
} catch (error) {
|
||||
notifyUnknownError(error);
|
||||
} finally {
|
||||
@@ -177,18 +184,25 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
}
|
||||
});
|
||||
|
||||
const partyOptions = (inputValue: string) => {
|
||||
return party_requests.getAll({ status: 'COLLECTING', partyName: inputValue }).then(res => {
|
||||
return res.data.data.data.map(p => ({ label: p.name, value: p.id }));
|
||||
});
|
||||
const partyOptions = async (inputValue: string) => {
|
||||
try {
|
||||
const res = await party_requests.getAll({
|
||||
status: 'COLLECTING',
|
||||
partyName: inputValue,
|
||||
});
|
||||
return res.data.data.data.map((p: any) => ({ label: p.name, value: p.id }));
|
||||
} catch (error) {
|
||||
notifyUnknownError(error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const appendPaket = () => {
|
||||
pakets.append({ id: '' });
|
||||
append({ id: '' });
|
||||
};
|
||||
|
||||
const removePaket = (index: number) => {
|
||||
pakets.remove(index);
|
||||
remove(index);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -201,31 +215,31 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
backgroundColor: '#fff',
|
||||
}}
|
||||
>
|
||||
<Box component={'form'} onSubmit={onSubmit}>
|
||||
<Typography variant='h5' mb={3.5}>
|
||||
<Box component="form" onSubmit={onSubmit}>
|
||||
<Typography variant="h5" mb={3.5}>
|
||||
{editMode ? t('update_box') : t('create_box')}
|
||||
</Typography>
|
||||
|
||||
<Grid container columnSpacing={2.5} rowSpacing={3} mb={3.5}>
|
||||
<Grid item xs={12}>
|
||||
<Typography fontSize={'18px'} fontWeight={500} color='#5D5850' mb={2}>
|
||||
<Typography fontSize="18px" fontWeight={500} color="#5D5850" mb={2}>
|
||||
{t('party_name')}
|
||||
</Typography>
|
||||
<Controller
|
||||
name='partyId'
|
||||
name="partyName"
|
||||
control={control}
|
||||
rules={{ required: requiredText }}
|
||||
render={({ field }) => (
|
||||
<AsyncSelect
|
||||
onChange={(newValue: any) => {
|
||||
field.onChange(newValue.value);
|
||||
setPartyId(newValue.value);
|
||||
field.onChange(newValue?.label ?? '');
|
||||
setPartyId(newValue?.value ?? '');
|
||||
}}
|
||||
defaultValue={
|
||||
editMode
|
||||
? {
|
||||
value: initialValues.partyId,
|
||||
label: initialValues.partyName,
|
||||
value: initialValues?.partyId,
|
||||
label: initialValues?.partyName,
|
||||
}
|
||||
: partiesData?.length
|
||||
? {
|
||||
@@ -239,12 +253,15 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
loadingMessage={() => t('loading')}
|
||||
onBlur={field.onBlur}
|
||||
name={field.name}
|
||||
defaultOptions={defaultParties!}
|
||||
defaultOptions={defaultParties ?? []}
|
||||
loadOptions={partyOptions}
|
||||
placeholder={t('enter_party_name_to_find')}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{!!errors.partyName && (
|
||||
<FormHelperText sx={{ color: 'red' }}>{requiredText}</FormHelperText>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
@@ -256,10 +273,10 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
padding: '24px',
|
||||
}}
|
||||
>
|
||||
<Typography fontSize={'18px'} fontWeight={500} color='#5D5850' mb={2}>
|
||||
<Typography fontSize="18px" fontWeight={500} color="#5D5850" mb={2}>
|
||||
{t('packet')}
|
||||
</Typography>
|
||||
{pakets.fields.map((field, index) => (
|
||||
{fields.map((field, index) => (
|
||||
<Box key={field.key} className="item-row" mb={2}>
|
||||
<Box className="item-row-field" flex={1}>
|
||||
<Controller
|
||||
@@ -269,13 +286,15 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
render={({ field: paketField }) => (
|
||||
<AsyncSelect
|
||||
onChange={(newValue: any) => {
|
||||
paketField.onChange(newValue?.value);
|
||||
paketField.onChange(newValue?.value ?? '');
|
||||
}}
|
||||
defaultValue={
|
||||
editMode && index === 0 && initialValues.packetId
|
||||
editMode && initialValues?.paketIds?.[index]
|
||||
? {
|
||||
value: initialValues.packetId,
|
||||
label: initialValues.box_name || `Box ${initialValues.packetId}`,
|
||||
value: initialValues.paketIds[index].id,
|
||||
label:
|
||||
initialValues.paketIds[index].packetName ||
|
||||
`Box ${initialValues.paketIds[index].id}`,
|
||||
}
|
||||
: null
|
||||
}
|
||||
@@ -284,19 +303,15 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
loadingMessage={() => t('loading')}
|
||||
onBlur={paketField.onBlur}
|
||||
name={paketField.name}
|
||||
defaultOptions={
|
||||
list.length > 0
|
||||
? list.map((box: any) => ({
|
||||
value: box.id,
|
||||
label: box.box_name || box.name || `Box ${box.id}`,
|
||||
}))
|
||||
: []
|
||||
}
|
||||
defaultOptions={list.map((box: any) => ({
|
||||
value: box.id,
|
||||
label: box.box_name || box.name || `Box ${box.id}`,
|
||||
}))}
|
||||
loadOptions={async (inputValue: string) => {
|
||||
if (!partyId || partyId === '') return [];
|
||||
if (!partyId) return [];
|
||||
try {
|
||||
const res = await box_requests.getAll({
|
||||
partyId: partyId,
|
||||
partyId,
|
||||
});
|
||||
return res.data.data.data.map((box: any) => ({
|
||||
label: box.box_name || box.name || `Box ${box.id}`,
|
||||
@@ -315,7 +330,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
<FormHelperText sx={{ color: 'red' }}>{requiredText}</FormHelperText>
|
||||
)}
|
||||
</Box>
|
||||
{pakets.fields.length > 1 && (
|
||||
{fields.length > 1 && (
|
||||
<Box className="item-row-field">
|
||||
<BaseIconButton
|
||||
size="small"
|
||||
@@ -329,7 +344,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
)}
|
||||
</Box>
|
||||
))}
|
||||
<Stack alignItems={'center'} mt={2}>
|
||||
<Stack alignItems="center" mt={2}>
|
||||
<BaseButton
|
||||
sx={{ backgroundColor: '#239D5F' }}
|
||||
startIcon={<AddCircleRounded />}
|
||||
@@ -342,7 +357,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<BaseButton type='submit' colorVariant='blue' loading={loading}>
|
||||
<BaseButton type="submit" colorVariant="blue" loading={loading}>
|
||||
{editMode ? t('update') : t('create')}
|
||||
</BaseButton>
|
||||
</Box>
|
||||
@@ -350,15 +365,4 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default DashboardCreateRealBoxPage;
|
||||
|
||||
export type RealCreateBoxBodyType = {
|
||||
partyName: string;
|
||||
packetDtos: number[];
|
||||
};
|
||||
|
||||
export type UpdateRealBoxBodyType = {
|
||||
boxId: string;
|
||||
partyName: string;
|
||||
packetDtos: number[];
|
||||
};
|
||||
export default DashboardCreateRealBoxPage;
|
||||
Reference in New Issue
Block a user