feat(sgw): Implement Create or Update Banzone functionality with map integration
This commit is contained in:
399
src/pages/Slave/SGW/Manager/Fish/component/AddOrUpdateFish.tsx
Normal file
399
src/pages/Slave/SGW/Manager/Fish/component/AddOrUpdateFish.tsx
Normal file
@@ -0,0 +1,399 @@
|
||||
import { HTTPSTATUS } from '@/constants';
|
||||
import {
|
||||
apiCreateFishSpecies,
|
||||
apiUpdateFishSpecies,
|
||||
} from '@/services/slave/sgw/FishController';
|
||||
import {
|
||||
apiDeletePhoto,
|
||||
apiUploadPhoto,
|
||||
} from '@/services/slave/sgw/PhotoController';
|
||||
import {
|
||||
ModalForm,
|
||||
ProForm,
|
||||
ProFormInstance,
|
||||
ProFormSelect,
|
||||
ProFormText,
|
||||
ProFormTextArea,
|
||||
ProFormUploadButton,
|
||||
} from '@ant-design/pro-components';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { MessageInstance } from 'antd/es/message/interface';
|
||||
import type { UploadFile } from 'antd/es/upload/interface';
|
||||
import { useRef, useState } from 'react';
|
||||
|
||||
export type AddOrUpdateFishProps = {
|
||||
type: 'create' | 'update';
|
||||
fish?: SgwModel.Fish;
|
||||
isOpen?: boolean;
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
message: MessageInstance;
|
||||
onReload?: (isSuccess: boolean) => void;
|
||||
};
|
||||
const AddOrUpdateFish = ({
|
||||
type,
|
||||
fish,
|
||||
isOpen,
|
||||
setIsOpen,
|
||||
message,
|
||||
onReload,
|
||||
}: AddOrUpdateFishProps) => {
|
||||
const formRef = useRef<ProFormInstance<SgwModel.Fish>>();
|
||||
const [fileList, setFileList] = useState<UploadFile[]>([]);
|
||||
const [originalFileList, setOriginalFileList] = useState<UploadFile[]>([]);
|
||||
const intl = useIntl();
|
||||
// Check ảnh có thay đổi so với ban đầu không
|
||||
const hasImageChanged = () => {
|
||||
const currentHasImage = fileList.length > 0;
|
||||
const originalHasImage = originalFileList.length > 0;
|
||||
|
||||
// Nếu số lượng ảnh khác nhau → có thay đổi
|
||||
if (currentHasImage !== originalHasImage) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Nếu cả 2 đều rỗng → không thay đổi
|
||||
if (!currentHasImage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Nếu có ảnh, check xem file có phải là file mới upload không
|
||||
// (file gốc có uid = '-1', file mới upload có uid khác)
|
||||
const currentFile = fileList[0];
|
||||
const isOriginalImage =
|
||||
currentFile.uid === '-1' && currentFile.status === 'done';
|
||||
|
||||
return !isOriginalImage;
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalForm<SgwModel.Fish>
|
||||
key={fish?.id || 'new'}
|
||||
open={isOpen}
|
||||
formRef={formRef}
|
||||
title={
|
||||
type === 'create'
|
||||
? intl.formatMessage({
|
||||
id: 'fish.create.title',
|
||||
defaultMessage: 'Thêm cá mới',
|
||||
})
|
||||
: intl.formatMessage({
|
||||
id: 'fish.update.title',
|
||||
defaultMessage: 'Cập nhật cá',
|
||||
})
|
||||
}
|
||||
onOpenChange={setIsOpen}
|
||||
layout="vertical"
|
||||
modalProps={{
|
||||
destroyOnHidden: true,
|
||||
}}
|
||||
request={async () => {
|
||||
if (type === 'update' && fish) {
|
||||
return fish;
|
||||
}
|
||||
setFileList([]);
|
||||
setOriginalFileList([]);
|
||||
return {};
|
||||
}}
|
||||
onFinish={async (values) => {
|
||||
// 1. Cập nhật thông tin cá
|
||||
if (type === 'create') {
|
||||
// TODO: Gọi API tạo cá mới
|
||||
// const result = await apiCreateFish(values);
|
||||
console.log('Create fish:', values);
|
||||
try {
|
||||
const resp = await apiCreateFishSpecies(values);
|
||||
if (resp.status === HTTPSTATUS.HTTP_SUCCESS) {
|
||||
message.success(
|
||||
intl.formatMessage({
|
||||
id: 'fish.create.success',
|
||||
defaultMessage: 'Tạo cá thành công',
|
||||
}),
|
||||
);
|
||||
onReload?.(true);
|
||||
const id = resp.data.name_ids![0];
|
||||
if (fileList.length > 0 && fileList[0].originFileObj && id) {
|
||||
// TODO: Sau khi có result.id từ API create
|
||||
// await apiUploadPhoto('fish', result.id, fileList[0].originFileObj);
|
||||
console.log('Upload photo for new fish');
|
||||
try {
|
||||
const resp = await apiUploadPhoto(
|
||||
'fish',
|
||||
id.toString(),
|
||||
fileList[0].originFileObj,
|
||||
);
|
||||
if (resp.status === HTTPSTATUS.HTTP_SUCCESS) {
|
||||
message.success(
|
||||
intl.formatMessage({
|
||||
id: 'fish.create.image.success',
|
||||
defaultMessage: 'Thêm ảnh cá thành công',
|
||||
}),
|
||||
);
|
||||
onReload?.(true);
|
||||
} else {
|
||||
throw new Error('Thêm ảnh thất bại');
|
||||
}
|
||||
} catch (error) {
|
||||
message.error(
|
||||
intl.formatMessage({
|
||||
id: 'fish.create.image.fail',
|
||||
defaultMessage: 'Thêm ảnh cá thất bại',
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Error('Tạo cá thất bại');
|
||||
}
|
||||
} catch (error) {
|
||||
message.error(
|
||||
intl.formatMessage({
|
||||
id: 'fish.create.fail',
|
||||
defaultMessage: 'Tạo cá thất bại',
|
||||
}),
|
||||
);
|
||||
}
|
||||
// 2. Upload ảnh (nếu có chọn ảnh)
|
||||
onReload?.(true);
|
||||
} else {
|
||||
// TODO: Gọi API cập nhật cá
|
||||
// await apiUpdateFish(fish!.id!, values);
|
||||
console.log('Update fish:', fish?.id, values);
|
||||
|
||||
// Check nếu dữ liệu có thay đổi so với ban đầu
|
||||
const hasDataChanged =
|
||||
fish!.name !== values.name ||
|
||||
fish!.scientific_name !== values.scientific_name ||
|
||||
fish!.group_name !== values.group_name ||
|
||||
fish!.rarity_level !== values.rarity_level ||
|
||||
fish!.note !== values.note;
|
||||
|
||||
if (hasDataChanged) {
|
||||
try {
|
||||
const body = { ...values, id: fish!.id! };
|
||||
const resp = await apiUpdateFishSpecies(body);
|
||||
if (resp.status === HTTPSTATUS.HTTP_SUCCESS) {
|
||||
message.success(
|
||||
intl.formatMessage({
|
||||
id: 'fish.update.success',
|
||||
defaultMessage: 'Cập nhật cá thành công',
|
||||
}),
|
||||
);
|
||||
onReload?.(true);
|
||||
} else {
|
||||
throw new Error('Cập nhật cá thất bại');
|
||||
}
|
||||
} catch (error) {
|
||||
message.error(
|
||||
intl.formatMessage({
|
||||
id: 'fish.update.fail',
|
||||
defaultMessage: 'Cập nhật cá thất bại',
|
||||
}),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
console.log('Dữ liệu không thay đổi, bỏ qua API update');
|
||||
}
|
||||
// 2. Upload ảnh (chỉ khi ảnh có thay đổi)
|
||||
if (hasImageChanged()) {
|
||||
if (fileList.length > 0 && fileList[0].originFileObj) {
|
||||
// TODO: Upload ảnh mới
|
||||
// await apiUploadPhoto('fish', fish!.id!, fileList[0].originFileObj);
|
||||
try {
|
||||
const resp = await apiUploadPhoto(
|
||||
'fish',
|
||||
fish!.id!.toString(),
|
||||
fileList[0].originFileObj,
|
||||
);
|
||||
if (resp.status === HTTPSTATUS.HTTP_SUCCESS) {
|
||||
message.success(
|
||||
intl.formatMessage({
|
||||
id: 'fish.update.image.success',
|
||||
defaultMessage: 'Cập nhật ảnh cá thành công',
|
||||
}),
|
||||
);
|
||||
onReload?.(true);
|
||||
} else {
|
||||
throw new Error('Cập nhật ảnh thất bại');
|
||||
}
|
||||
} catch (error) {
|
||||
message.error(
|
||||
intl.formatMessage({
|
||||
id: 'fish.update.image.fail',
|
||||
defaultMessage: 'Cập nhật ảnh cá thất bại',
|
||||
}),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// TODO: Xóa ảnh (nếu có API delete)
|
||||
console.log('Remove photo');
|
||||
const resp = await apiDeletePhoto('fish', fish!.id!);
|
||||
if (resp.status === HTTPSTATUS.HTTP_SUCCESS) {
|
||||
message.success(
|
||||
intl.formatMessage({
|
||||
id: 'fish.delete.image.success',
|
||||
defaultMessage: 'Xóa ảnh cá thành công',
|
||||
}),
|
||||
);
|
||||
onReload?.(true);
|
||||
} else {
|
||||
message.error(
|
||||
intl.formatMessage({
|
||||
id: 'fish.delete.image.fail',
|
||||
defaultMessage: 'Xóa ảnh cá thất bại',
|
||||
}),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}}
|
||||
>
|
||||
{type === 'create' && (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
marginBottom: 16,
|
||||
}}
|
||||
>
|
||||
<ProFormUploadButton
|
||||
name="upload"
|
||||
label={null}
|
||||
title="Chọn ảnh"
|
||||
accept="image/*"
|
||||
max={1}
|
||||
transform={(value) => ({ upload: value })}
|
||||
fieldProps={{
|
||||
onChange(info) {
|
||||
setFileList(info.fileList);
|
||||
},
|
||||
listType: 'picture-card',
|
||||
fileList: fileList,
|
||||
onRemove: () => {
|
||||
setFileList([]);
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<ProForm.Group>
|
||||
<ProFormText
|
||||
name="name"
|
||||
width="md"
|
||||
label={intl.formatMessage({
|
||||
id: 'common.name',
|
||||
defaultMessage: 'Tên',
|
||||
})}
|
||||
tooltip={intl.formatMessage({
|
||||
id: 'fish.name.tooltip',
|
||||
defaultMessage: 'Tên loài cá',
|
||||
})}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'fish.name.placeholder',
|
||||
defaultMessage: 'Nhập tên cá',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'fish.name.required',
|
||||
defaultMessage: 'Tên cá không được để trống',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormText
|
||||
name="scientific_name"
|
||||
width="md"
|
||||
label={intl.formatMessage({
|
||||
id: 'fish.specific_name',
|
||||
defaultMessage: 'Tên khoa học',
|
||||
})}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'fish.specific_name.placeholder',
|
||||
defaultMessage: 'Nhập tên khoa học',
|
||||
})}
|
||||
/>
|
||||
</ProForm.Group>
|
||||
<ProForm.Group>
|
||||
<ProFormText
|
||||
name="group_name"
|
||||
label={intl.formatMessage({
|
||||
id: 'fish.fish_group',
|
||||
defaultMessage: 'Nhóm',
|
||||
})}
|
||||
width="md"
|
||||
tooltip={intl.formatMessage({
|
||||
id: 'fish.fish_group.tooltip',
|
||||
defaultMessage: 'Nhóm cá',
|
||||
})}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'fish.fish_group.placeholder',
|
||||
defaultMessage: 'Nhập nhóm cá',
|
||||
})}
|
||||
/>
|
||||
|
||||
<ProFormSelect
|
||||
name="rarity_level"
|
||||
label={intl.formatMessage({
|
||||
id: 'fish.rarity',
|
||||
defaultMessage: 'Độ hiếm',
|
||||
})}
|
||||
width="md"
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'fish.rarity.placeholder',
|
||||
defaultMessage: 'Chọn độ hiếm',
|
||||
})}
|
||||
options={[
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'fish.rarity.normal',
|
||||
defaultMessage: 'Phổ biến',
|
||||
}),
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'fish.rarity.sensitive',
|
||||
defaultMessage: 'Dễ bị tổn thương',
|
||||
}),
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'fish.rarity.near_threatened',
|
||||
defaultMessage: 'Gần bị đe dọa',
|
||||
}),
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'fish.rarity.endangered',
|
||||
defaultMessage: 'Nguy cấp',
|
||||
}),
|
||||
value: 4,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</ProForm.Group>
|
||||
<ProFormTextArea
|
||||
name="note"
|
||||
label={intl.formatMessage({
|
||||
id: 'common.description',
|
||||
defaultMessage: 'Ghi chú',
|
||||
})}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'common.description.placeholder',
|
||||
defaultMessage: 'Nhập ghi chú',
|
||||
})}
|
||||
/>
|
||||
</ModalForm>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddOrUpdateFish;
|
||||
Reference in New Issue
Block a user