feat:update push
This commit is contained in:
@@ -6,6 +6,8 @@ import { Plus, Trash2 } from "lucide-react";
|
||||
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import CustomButton from "@/components/customs/custom-button";
|
||||
|
||||
import FormCustom from "@/components/utils/FormCustom";
|
||||
@@ -16,6 +18,8 @@ import TextArea from "@/components/utils/FormCustom/components/TextArea";
|
||||
|
||||
import SelectForm from "@/components/utils/FormCustom/components/SelectForm";
|
||||
|
||||
import UploadImage from "@/components/utils/UploadImage";
|
||||
|
||||
import { httpRequest } from "@/services";
|
||||
|
||||
import prescriptionServices from "@/services/prescriptionServices";
|
||||
@@ -26,10 +30,14 @@ import consultationServices, {
|
||||
} from "@/services/consultationServices";
|
||||
|
||||
import { QUERY_KEY } from "@/constant/config/enum";
|
||||
|
||||
import { toastWarn } from "@/common/funcs/toast";
|
||||
|
||||
import { PATH } from "@/constant/config";
|
||||
import { useRouter } from "next/navigation";
|
||||
import UploadImage from "@/components/utils/UploadImage";
|
||||
|
||||
/* =========================
|
||||
TYPES
|
||||
========================= */
|
||||
|
||||
interface PrescriptionItem {
|
||||
medicineName: string;
|
||||
@@ -42,16 +50,12 @@ interface PrescriptionItem {
|
||||
interface PrescriptionForm {
|
||||
examinationSessionId: string;
|
||||
notes: string;
|
||||
PrescriptionFile: string;
|
||||
items: PrescriptionItem[];
|
||||
}
|
||||
|
||||
interface UploadImageItem {
|
||||
url?: string;
|
||||
path?: string;
|
||||
file?: File;
|
||||
img?: string;
|
||||
}
|
||||
/* =========================
|
||||
DEFAULT
|
||||
========================= */
|
||||
|
||||
const defaultMedicine: PrescriptionItem = {
|
||||
medicineName: "",
|
||||
@@ -61,36 +65,25 @@ const defaultMedicine: PrescriptionItem = {
|
||||
instructions: "",
|
||||
};
|
||||
|
||||
const convertFileToBase64 = (file: File): Promise<string> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
reader.onload = () => {
|
||||
resolve(reader.result as string);
|
||||
};
|
||||
|
||||
reader.onerror = (error) => {
|
||||
reject(error);
|
||||
};
|
||||
});
|
||||
};
|
||||
/* =========================
|
||||
COMPONENT
|
||||
========================= */
|
||||
|
||||
const CreatePrescription = () => {
|
||||
const router = useRouter();
|
||||
const [file, setFile] = useState<any>(null);
|
||||
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
|
||||
const [form, setForm] = useState<PrescriptionForm>({
|
||||
examinationSessionId: "",
|
||||
notes: "",
|
||||
PrescriptionFile: "",
|
||||
items: [defaultMedicine],
|
||||
});
|
||||
|
||||
/**
|
||||
* GET EXAMINATION SESSION
|
||||
*/
|
||||
/* =========================
|
||||
GET EXAMINATION SESSION
|
||||
========================= */
|
||||
|
||||
const examinationSessionQuery = useQuery<ConsultationResponse>({
|
||||
queryKey: [QUERY_KEY.table_list_consultation],
|
||||
|
||||
@@ -120,30 +113,50 @@ const CreatePrescription = () => {
|
||||
|
||||
const examinationSessionOptions = examinationSessionQuery.data?.items || [];
|
||||
|
||||
/* =========================
|
||||
CREATE MUTATION
|
||||
========================= */
|
||||
|
||||
const createPrescriptionMutation = useMutation({
|
||||
mutationFn: async (body: { PrescriptionFile: string }) => {
|
||||
mutationFn: async () => {
|
||||
const formData = new FormData();
|
||||
|
||||
formData.append("examinationSessionId", form.examinationSessionId);
|
||||
|
||||
formData.append("notes", form.notes);
|
||||
|
||||
/**
|
||||
* FILE
|
||||
*/
|
||||
if (file) {
|
||||
formData.append("PrescriptionFile", file);
|
||||
}
|
||||
|
||||
/**
|
||||
* MEDICINE ITEMS
|
||||
*/
|
||||
form.items
|
||||
.filter((x) => x.medicineName.trim() !== "")
|
||||
.forEach((item, index) => {
|
||||
formData.append(`items[${index}].medicineName`, item.medicineName);
|
||||
|
||||
formData.append(`items[${index}].dosage`, item.dosage);
|
||||
|
||||
formData.append(`items[${index}].frequency`, item.frequency);
|
||||
|
||||
formData.append(`items[${index}].duration`, item.duration);
|
||||
|
||||
formData.append(`items[${index}].instructions`, item.instructions);
|
||||
});
|
||||
|
||||
return await httpRequest({
|
||||
showMessageFailed: true,
|
||||
|
||||
showMessageSuccess: true,
|
||||
|
||||
msgSuccess: "Tạo đơn thuốc thành công!",
|
||||
|
||||
http: prescriptionServices.createPrescription({
|
||||
examinationSessionId: form.examinationSessionId,
|
||||
|
||||
notes: form.notes,
|
||||
|
||||
PrescriptionFile: body.PrescriptionFile,
|
||||
|
||||
items: form.items
|
||||
.filter((x) => x.medicineName.trim() !== "")
|
||||
.map((x) => ({
|
||||
medicineName: x.medicineName,
|
||||
dosage: x.dosage,
|
||||
frequency: x.frequency,
|
||||
duration: x.duration,
|
||||
instructions: x.instructions,
|
||||
})),
|
||||
}),
|
||||
http: prescriptionServices.createPrescription(formData),
|
||||
});
|
||||
},
|
||||
|
||||
@@ -152,23 +165,21 @@ const CreatePrescription = () => {
|
||||
},
|
||||
|
||||
onError: (error: any) => {
|
||||
// 👇 BACKEND ERROR HERE
|
||||
const message =
|
||||
error?.message || error?.error?.message || "Có lỗi xảy ra";
|
||||
|
||||
const code = error?.code || error?.error?.code;
|
||||
error?.response?.data?.message || error?.message || "Có lỗi xảy ra";
|
||||
|
||||
toastWarn({
|
||||
msg: message,
|
||||
});
|
||||
|
||||
console.log("ERROR CODE:", code);
|
||||
console.log("CREATE PRESCRIPTION ERROR:", error);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* CHANGE MEDICINE FIELD
|
||||
*/
|
||||
/* =========================
|
||||
CHANGE MEDICINE FIELD
|
||||
========================= */
|
||||
|
||||
const handleChangeMedicine = (
|
||||
index: number,
|
||||
key: keyof PrescriptionItem,
|
||||
@@ -187,9 +198,10 @@ const CreatePrescription = () => {
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* ADD MEDICINE
|
||||
*/
|
||||
/* =========================
|
||||
ADD MEDICINE
|
||||
========================= */
|
||||
|
||||
const handleAddMedicine = () => {
|
||||
setForm((prev) => ({
|
||||
...prev,
|
||||
@@ -207,9 +219,10 @@ const CreatePrescription = () => {
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* REMOVE MEDICINE
|
||||
*/
|
||||
/* =========================
|
||||
REMOVE MEDICINE
|
||||
========================= */
|
||||
|
||||
const handleRemoveMedicine = (index: number) => {
|
||||
const newItems = form.items.filter((_, i) => i !== index);
|
||||
|
||||
@@ -219,63 +232,30 @@ const CreatePrescription = () => {
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
/**
|
||||
* VALIDATE
|
||||
*/
|
||||
if (!form.examinationSessionId) {
|
||||
return toastWarn({
|
||||
msg: "Vui lòng chọn phiên khám",
|
||||
});
|
||||
}
|
||||
/* =========================
|
||||
SUBMIT
|
||||
========================= */
|
||||
|
||||
if (!file) {
|
||||
return toastWarn({
|
||||
msg: "Vui lòng chọn ảnh đơn thuốc",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UPLOAD IMAGE
|
||||
*/
|
||||
let uploadedImage = "";
|
||||
|
||||
if (file) {
|
||||
const formData = new FormData();
|
||||
|
||||
formData.append("file", file);
|
||||
|
||||
/**
|
||||
* API UPLOAD
|
||||
* SỬA uploadServices theo project của bạn
|
||||
*/
|
||||
const uploadRes: any = await httpRequest({
|
||||
showMessageFailed: true,
|
||||
|
||||
http: prescriptionServices.uploadImage(formData),
|
||||
});
|
||||
|
||||
/**
|
||||
* BACKEND RESPONSE
|
||||
*/
|
||||
uploadedImage =
|
||||
uploadRes?.url || uploadRes?.path || uploadRes?.data?.url || "";
|
||||
}
|
||||
|
||||
/**
|
||||
* CREATE PRESCRIPTION
|
||||
*/
|
||||
createPrescriptionMutation.mutate({
|
||||
PrescriptionFile: uploadedImage,
|
||||
});
|
||||
} catch (error: any) {
|
||||
toastWarn({
|
||||
msg: error?.message || "Upload ảnh thất bại",
|
||||
const handleSubmit = () => {
|
||||
if (!form.examinationSessionId) {
|
||||
return toastWarn({
|
||||
msg: "Vui lòng chọn phiên khám",
|
||||
});
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
return toastWarn({
|
||||
msg: "Vui lòng chọn ảnh đơn thuốc",
|
||||
});
|
||||
}
|
||||
|
||||
createPrescriptionMutation.mutate();
|
||||
};
|
||||
|
||||
/* =========================
|
||||
UI
|
||||
========================= */
|
||||
|
||||
return (
|
||||
<FormCustom form={form} setForm={setForm} onSubmit={handleSubmit}>
|
||||
<div className="flex flex-col gap-6 rounded-2xl bg-white p-6 shadow">
|
||||
@@ -290,11 +270,13 @@ const CreatePrescription = () => {
|
||||
Tạo mới đơn thuốc cho bệnh nhân
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<CustomButton
|
||||
type="submit"
|
||||
variant="midnightBlue"
|
||||
disabled={createPrescriptionMutation.isPending}
|
||||
className="min-w-[180px]"
|
||||
>
|
||||
{createPrescriptionMutation.isPending
|
||||
? "Đang tạo..."
|
||||
@@ -333,9 +315,7 @@ const CreatePrescription = () => {
|
||||
examinationSessionId: "",
|
||||
}))
|
||||
}
|
||||
getOptionLabel={(item: ConsultationItem) =>
|
||||
`${item.sessionCode} `
|
||||
}
|
||||
getOptionLabel={(item: ConsultationItem) => `${item.sessionCode}`}
|
||||
getOptionValue={(item: ConsultationItem) => item.id}
|
||||
/>
|
||||
|
||||
@@ -350,7 +330,7 @@ const CreatePrescription = () => {
|
||||
name="PrescriptionFile"
|
||||
file={file}
|
||||
setFile={setFile}
|
||||
path={""}
|
||||
path=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -378,6 +358,7 @@ const CreatePrescription = () => {
|
||||
<h3 className="text-lg font-semibold text-[#111827]">
|
||||
Danh sách thuốc
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<CustomButton
|
||||
type="button"
|
||||
@@ -413,7 +394,7 @@ const CreatePrescription = () => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* FORM */}
|
||||
{/* INPUTS */}
|
||||
<div className="grid grid-cols-2 gap-5">
|
||||
<InputForm
|
||||
label="Tên thuốc"
|
||||
@@ -460,6 +441,7 @@ const CreatePrescription = () => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* INSTRUCTION */}
|
||||
<div className="mt-5">
|
||||
<TextArea
|
||||
label="Hướng dẫn sử dụng"
|
||||
|
||||
Reference in New Issue
Block a user