feat:update
This commit is contained in:
parent
b4568e1c8c
commit
42cb08f0d0
@ -108,6 +108,45 @@ export function getTextAddress(detailAddress: any, address?: string): string {
|
||||
return parts.length ? parts.join(", ") : "---";
|
||||
}
|
||||
|
||||
export const formatDateOfBirth = (value: string) => {
|
||||
const digits = value.replace(/\D/g, "").slice(0, 8);
|
||||
if (digits.length <= 2) return digits;
|
||||
if (digits.length <= 4) return `${digits.slice(0, 2)}/${digits.slice(2)}`;
|
||||
return `${digits.slice(0, 2)}/${digits.slice(2, 4)}/${digits.slice(4)}`;
|
||||
};
|
||||
|
||||
export const parseDateOfBirth = (value: string) => {
|
||||
const match = value.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
|
||||
if (!match) return null;
|
||||
|
||||
const day = Number(match[1]);
|
||||
const month = Number(match[2]);
|
||||
const year = Number(match[3]);
|
||||
|
||||
const parsedDate = new Date(year, month - 1, day);
|
||||
|
||||
if (
|
||||
parsedDate.getFullYear() !== year ||
|
||||
parsedDate.getMonth() !== month - 1 ||
|
||||
parsedDate.getDate() !== day
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parsedDate;
|
||||
};
|
||||
|
||||
export const formatToISODate = (date: Date | null): string => {
|
||||
if (!date) return "";
|
||||
|
||||
const year = date.getFullYear();
|
||||
// Đảm bảo tháng và ngày luôn có 2 chữ số (VD: 02, 12)
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
|
||||
return `${year}-${month}-${day}`; // Kết quả: "2001-02-12"
|
||||
};
|
||||
|
||||
export function numberToWords(number: number) {
|
||||
if (typeof number !== "number" || isNaN(number)) {
|
||||
return "Không hợp lệ";
|
||||
|
||||
@ -78,6 +78,11 @@ export default function MainLogin() {
|
||||
// Kiểm tra nhanh điều kiện dữ liệu trước khi trigger API
|
||||
if (!form.username || !form.password) return;
|
||||
|
||||
// if (form.password.length < 6) {
|
||||
// alert("Mật khẩu phải có ít nhất 6 ký tự");
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (isRememberPassword) {
|
||||
store.dispatch(
|
||||
setDataLoginStorage({
|
||||
@ -136,6 +141,7 @@ export default function MainLogin() {
|
||||
onClean
|
||||
isRequired
|
||||
isBlur
|
||||
min={6}
|
||||
showDone
|
||||
icon={<ShieldPlus size={22} />}
|
||||
/>
|
||||
|
||||
@ -154,6 +154,7 @@ export default function MainRegister() {
|
||||
onClean
|
||||
isRequired
|
||||
isBlur
|
||||
min={6}
|
||||
showDone
|
||||
icon={<ShieldPlus size={22} />}
|
||||
/>
|
||||
|
||||
@ -1,26 +1,16 @@
|
||||
"use client";
|
||||
|
||||
import React, { useMemo, useState } from "react";
|
||||
|
||||
import { X } from "lucide-react";
|
||||
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import FormCustom from "@/components/utils/FormCustom/FormCustom";
|
||||
|
||||
import SelectForm from "@/components/utils/FormCustom/components/SelectForm";
|
||||
|
||||
import { httpRequest } from "@/services";
|
||||
|
||||
import consultationServices from "@/services/consultationServices";
|
||||
|
||||
import patientServices, {
|
||||
PatientItem,
|
||||
PatientResponse,
|
||||
} from "@/services/patientServices";
|
||||
|
||||
import { QUERY_KEY } from "@/constant/config/enum";
|
||||
|
||||
import CustomButton from "@/components/customs/custom-button";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import InputForm from "@/components/utils/FormCustom/components/InputForm";
|
||||
@ -137,6 +127,9 @@ const CreateConsultation = () => {
|
||||
if (!form?.patientId) {
|
||||
return toastWarn({ msg: "Vui lòng chọn bệnh nhân" });
|
||||
}
|
||||
if (!form?.specialtyIds) {
|
||||
return toastWarn({ msg: "Vui lòng chọn chuyên khoa" });
|
||||
}
|
||||
createConsultationMutation.mutate();
|
||||
};
|
||||
|
||||
@ -174,7 +167,7 @@ const CreateConsultation = () => {
|
||||
<div className="space-y-5 mb-2">
|
||||
<SelectForm
|
||||
label={
|
||||
<span className="text-[14px] font-medium text-[#374151]">
|
||||
<span>
|
||||
Bệnh nhân
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
@ -205,7 +198,11 @@ const CreateConsultation = () => {
|
||||
<div className="space-y-5 mb-2">
|
||||
<GridColumn col={3}>
|
||||
<InputForm
|
||||
label="Lý do khám"
|
||||
label={
|
||||
<span>
|
||||
Lý do khám <span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="chiefComplaint"
|
||||
type="text"
|
||||
value={form.chiefComplaint}
|
||||
@ -217,7 +214,11 @@ const CreateConsultation = () => {
|
||||
/>
|
||||
<InputForm
|
||||
type="text"
|
||||
label="Triệu chứng"
|
||||
label={
|
||||
<span>
|
||||
Triệu chứng <span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="symptomsText"
|
||||
placeholder="Nhập triệu chứng"
|
||||
isRequired
|
||||
@ -229,7 +230,12 @@ const CreateConsultation = () => {
|
||||
|
||||
<InputForm
|
||||
type="text"
|
||||
label="Chỉ số huyết áp, chỉ số mạch"
|
||||
label={
|
||||
<span>
|
||||
Chỉ số huyết áp, chỉ số mạch{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="vitalSigns"
|
||||
placeholder="Nhập chỉ số huyết áp, chỉ số mạch"
|
||||
value={form.vitalSigns}
|
||||
@ -242,7 +248,12 @@ const CreateConsultation = () => {
|
||||
</div>
|
||||
<div className="space-y-5 mb2">
|
||||
<SelectMany<SpecialtyItem>
|
||||
label="Chuyên khoa"
|
||||
label={
|
||||
<span>
|
||||
Chuyên khoa
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
text="chuyên khoa"
|
||||
title="Chọn chuyên khoa"
|
||||
placeholder="Chọn nhiều chuyên khoa..."
|
||||
|
||||
@ -575,26 +575,34 @@ const DetailConsultation = () => {
|
||||
<GridColumn col={3}>
|
||||
<div>
|
||||
<p className="text-sm text-[#697586]">CHUYÊN KHOA</p>
|
||||
|
||||
<p>{selectedSpecialty.specialtyName || "---"}</p>
|
||||
{/* Thêm class để bọc text */}
|
||||
<p className="break-words overflow-hidden">
|
||||
{selectedSpecialty.specialtyName || "---"}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-sm text-[#697586]">CHẨN ĐOÁN</p>
|
||||
|
||||
<p>{selectedSpecialty.diagnosis || "---"}</p>
|
||||
{/* Thêm class để bọc text */}
|
||||
<p className="break-words overflow-hidden">
|
||||
{selectedSpecialty.diagnosis || "---"}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-sm text-[#697586]">GHI CHÚ KHÁM</p>
|
||||
|
||||
<p>{selectedSpecialty.specialtyNotes || "---"}</p>
|
||||
{/* Thêm class để bọc text */}
|
||||
<p className="break-words overflow-hidden">
|
||||
{selectedSpecialty.specialtyNotes || "---"}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-sm text-[#697586]">THỦ THUẬT</p>
|
||||
|
||||
<p>{selectedSpecialty.procedureNotes || "---"}</p>
|
||||
{/* Thêm class để bọc text */}
|
||||
<p className="break-words overflow-hidden">
|
||||
{selectedSpecialty.procedureNotes || "---"}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
|
||||
@ -352,7 +352,7 @@ const MainPageConsultation = () => {
|
||||
},
|
||||
{
|
||||
uuid: TYPE_STATUS.PendingPrescription,
|
||||
name: "Chờ nhận thuốc/kính",
|
||||
name: "Chờ nhận thuốc",
|
||||
},
|
||||
{
|
||||
uuid: TYPE_STATUS.Completed,
|
||||
|
||||
@ -18,6 +18,7 @@ import consultationServices, {
|
||||
import uploadServices from "@/services/uploadServices";
|
||||
import UploadMultipleFile from "@/components/utils/UploadMultipleFile";
|
||||
import TextArea from "@/components/utils/FormCustom/components/TextArea";
|
||||
import { toastWarn } from "@/common/funcs/toast";
|
||||
|
||||
/* =========================
|
||||
TYPES
|
||||
@ -247,7 +248,11 @@ const UpdateConsultation = () => {
|
||||
|
||||
{/* GENERAL INFO (PATIENT) */}
|
||||
<InputForm
|
||||
label="Bệnh nhân"
|
||||
label={
|
||||
<span>
|
||||
Bệnh nhân <span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="patientInfo"
|
||||
type="text"
|
||||
// Hiển thị Tên bệnh nhân - SĐT hoặc CCCD dựa trên API detail trả về
|
||||
@ -268,7 +273,11 @@ const UpdateConsultation = () => {
|
||||
|
||||
<GridColumn col={3}>
|
||||
<InputForm
|
||||
label="Lý do khám"
|
||||
label={
|
||||
<span>
|
||||
Lý do khám <span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="chiefComplaint"
|
||||
type="text"
|
||||
value={form.chiefComplaint}
|
||||
@ -280,7 +289,11 @@ const UpdateConsultation = () => {
|
||||
/>
|
||||
<InputForm
|
||||
type="text"
|
||||
label="Triệu chứng"
|
||||
label={
|
||||
<span>
|
||||
Triệu chứng <span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="symptomsText"
|
||||
placeholder="Nhập triệu chứng"
|
||||
isRequired
|
||||
@ -292,7 +305,12 @@ const UpdateConsultation = () => {
|
||||
|
||||
<InputForm
|
||||
type="text"
|
||||
label="Chỉ số huyết áp, chỉ số mạch"
|
||||
label={
|
||||
<span>
|
||||
Chỉ số huyết áp, chỉ số mạch{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="vitalSigns"
|
||||
placeholder="Nhập chỉ số huyết áp, chỉ số mạch"
|
||||
value={form.vitalSigns}
|
||||
@ -304,7 +322,11 @@ const UpdateConsultation = () => {
|
||||
|
||||
<InputForm
|
||||
type="text"
|
||||
label="Chẩn đoán"
|
||||
label={
|
||||
<span>
|
||||
Chẩn đoán <span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="diagnosis"
|
||||
placeholder="Nhập chẩn đoán"
|
||||
value={form.diagnosis}
|
||||
@ -316,7 +338,11 @@ const UpdateConsultation = () => {
|
||||
|
||||
<InputForm
|
||||
type="text"
|
||||
label="Kế hoạch điều trị"
|
||||
label={
|
||||
<span>
|
||||
Kế hoạch điều trị <span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="treatmentPlan"
|
||||
placeholder="Nhập kế hoạch điều trị"
|
||||
value={form.treatmentPlan}
|
||||
@ -328,7 +354,11 @@ const UpdateConsultation = () => {
|
||||
|
||||
<InputForm
|
||||
type="text"
|
||||
label="Ghi chú bác sĩ"
|
||||
label={
|
||||
<span>
|
||||
Ghi chú bác sĩ <span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="doctorNotes"
|
||||
placeholder="Nhập ghi chú"
|
||||
value={form.doctorNotes}
|
||||
@ -372,7 +402,12 @@ const UpdateConsultation = () => {
|
||||
<TextArea
|
||||
name="glassType"
|
||||
placeholder="Nhập thông số chi tiết loại kính được chỉ định"
|
||||
label="Thông số / Loại kính chỉ định"
|
||||
label={
|
||||
<span>
|
||||
Thông số / loại kính chỉ định
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
value={form.glassType}
|
||||
isRequired
|
||||
readOnly
|
||||
@ -408,10 +443,18 @@ const UpdateConsultation = () => {
|
||||
Hủy bỏ
|
||||
</CustomButton>
|
||||
<CustomButton
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
variant="midnightBlue"
|
||||
rounded="md"
|
||||
disabled={isLoading || !id || id === "undefined"}
|
||||
disabled={
|
||||
!form.chiefComplaint ||
|
||||
!form.symptomsText ||
|
||||
!form.vitalSigns ||
|
||||
!form.diagnosis ||
|
||||
!form.treatmentPlan ||
|
||||
!form.doctorNotes ||
|
||||
updateConsultationMutation.isPending
|
||||
}
|
||||
className="min-w-[140px]"
|
||||
>
|
||||
{updateConsultationMutation.isPending
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { toastWarn } from "@/common/funcs/toast";
|
||||
import CustomButton from "@/components/customs/custom-button";
|
||||
import GridColumn from "@/components/layouts/GridColumn";
|
||||
import FormCustom from "@/components/utils/FormCustom";
|
||||
@ -170,6 +171,16 @@ const UpdateSpecialtyClinicId = () => {
|
||||
});
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!form.specialtyNotes || !form.diagnosis || !form.procedureNotes) {
|
||||
return toastWarn({ msg: "Vui lòng nhập đầy đủ các trường!" });
|
||||
}
|
||||
|
||||
if (isEyeClinic && form.glassRequired === true && !form.glassType) {
|
||||
return toastWarn({
|
||||
msg: "Vui lòng nhập thông số / Loại kính chỉ định!",
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const currentImage = images
|
||||
.filter((item) => !!item.img)
|
||||
@ -277,7 +288,12 @@ const UpdateSpecialtyClinicId = () => {
|
||||
|
||||
<GridColumn col={isEyeClinic ? 4 : 3}>
|
||||
<InputForm
|
||||
label="Ghi chú chuyên khoa"
|
||||
label={
|
||||
<span>
|
||||
Ghi chú chuyên khoa
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="specialtyNotes"
|
||||
type="text"
|
||||
value={form.specialtyNotes}
|
||||
@ -289,7 +305,12 @@ const UpdateSpecialtyClinicId = () => {
|
||||
/>
|
||||
<InputForm
|
||||
type="text"
|
||||
label="Chẩn đoán chuyên khoa"
|
||||
label={
|
||||
<span>
|
||||
Chẩn đoán chuyên khoa
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="diagnosis"
|
||||
placeholder="Nhập chẩn đoán chuyên khoa"
|
||||
isRequired
|
||||
@ -300,7 +321,12 @@ const UpdateSpecialtyClinicId = () => {
|
||||
/>
|
||||
<InputForm
|
||||
type="text"
|
||||
label="Ghi chú thủ thuật / can thiệp"
|
||||
label={
|
||||
<span>
|
||||
Ghi chú thủ thuật / can thiệp
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="procedureNotes"
|
||||
placeholder="Nhập ghi chú thủ thuật / can thiệp"
|
||||
value={form.procedureNotes}
|
||||
@ -359,7 +385,12 @@ const UpdateSpecialtyClinicId = () => {
|
||||
<TextArea
|
||||
name="glassType"
|
||||
placeholder="Nhập thông số chi tiết loại kính được chỉ định (Cận, viễn, loạn, độ kính...)"
|
||||
label="Thông số / Loại kính chỉ định"
|
||||
label={
|
||||
<span>
|
||||
Thông số / Loại kính chỉ định
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
value={form.glassType}
|
||||
isRequired
|
||||
isBlur
|
||||
@ -432,10 +463,10 @@ const UpdateSpecialtyClinicId = () => {
|
||||
Hủy bỏ
|
||||
</CustomButton>
|
||||
<CustomButton
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
variant="midnightBlue"
|
||||
rounded="md"
|
||||
disabled={isLoading || !consultationId}
|
||||
disabled={specialtyResultsMutation.isPending}
|
||||
className="min-w-[140px]"
|
||||
>
|
||||
{specialtyResultsMutation.isPending
|
||||
|
||||
@ -225,7 +225,7 @@ const MainPagePatient = () => {
|
||||
<Search
|
||||
keyword={_keyword ?? ""}
|
||||
setKeyword={(value) => updateQuery("_keyword", value)}
|
||||
placeholder="Tìm kiếm theo tên người dùng, ID"
|
||||
placeholder="Tìm kiếm theo tên bệnh nhân, ID"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -15,7 +15,11 @@ import { httpRequest } from "@/services";
|
||||
|
||||
import patientServices from "@/services/patientServices";
|
||||
import { toastWarn } from "@/common/funcs/toast";
|
||||
import { timeSubmit } from "@/common/funcs/optionConvert";
|
||||
import {
|
||||
formatDateOfBirth,
|
||||
parseDateOfBirth,
|
||||
formatToISODate,
|
||||
} from "@/common/funcs/optionConvert";
|
||||
|
||||
export interface ICreatePatient {
|
||||
identificationNumber: string;
|
||||
@ -31,11 +35,6 @@ export interface PropsPopupCreatePatient {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
/* QUERY KEY */
|
||||
// export const QUERY_KEY = {
|
||||
// table_list_patient: "table_list_patient",
|
||||
// };
|
||||
|
||||
const PopupCreatePatient = ({ onClose }: PropsPopupCreatePatient) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
@ -59,7 +58,8 @@ const PopupCreatePatient = ({ onClose }: PropsPopupCreatePatient) => {
|
||||
http: patientServices.createPatient({
|
||||
identificationNumber: form.identificationNumber,
|
||||
fullName: form.fullName,
|
||||
dateOfBirth: form.dateOfBirth,
|
||||
dateOfBirth:
|
||||
formatToISODate(parseDateOfBirth(form.dateOfBirth)) || "",
|
||||
gender: form.gender,
|
||||
phone: form.phone,
|
||||
email: form.email,
|
||||
@ -68,6 +68,14 @@ const PopupCreatePatient = ({ onClose }: PropsPopupCreatePatient) => {
|
||||
});
|
||||
},
|
||||
|
||||
onError(error: any) {
|
||||
// Lấy message lỗi từ backend trả về
|
||||
const message = error?.response?.data?.error?.message || error?.message;
|
||||
|
||||
// Bật thông báo Toast dạng cảnh báo
|
||||
toastWarn({ msg: message });
|
||||
},
|
||||
|
||||
onSuccess() {
|
||||
/* REFRESH LIST */
|
||||
queryClient.invalidateQueries({
|
||||
@ -79,15 +87,30 @@ const PopupCreatePatient = ({ onClose }: PropsPopupCreatePatient) => {
|
||||
});
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!form.dateOfBirth) {
|
||||
return toastWarn({ msg: "Vui lòng nhập ngày sinh!" });
|
||||
}
|
||||
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
const birthDay = parseDateOfBirth(form.dateOfBirth);
|
||||
|
||||
if (!birthDay) {
|
||||
return toastWarn({
|
||||
msg: "Ngày sinh phải theo định dạng ngày/tháng/năm!",
|
||||
});
|
||||
}
|
||||
|
||||
birthDay.setHours(0, 0, 0, 0);
|
||||
|
||||
if (birthDay.getTime() > today.getTime()) {
|
||||
return toastWarn({ msg: "Ngày sinh không hợp lệ!" });
|
||||
}
|
||||
|
||||
if (!form.gender) {
|
||||
return toastWarn({ msg: "Vui lòng chọn giới tính!" });
|
||||
}
|
||||
const today = new Date(timeSubmit(new Date())!);
|
||||
const birthDay = new Date(form.dateOfBirth);
|
||||
|
||||
if (today < birthDay) {
|
||||
return toastWarn({ msg: "Ngày sinh không hợp lệ!" });
|
||||
}
|
||||
|
||||
createPatientMutation.mutate();
|
||||
};
|
||||
@ -116,7 +139,7 @@ const PopupCreatePatient = ({ onClose }: PropsPopupCreatePatient) => {
|
||||
absolute
|
||||
right-5
|
||||
top-5
|
||||
z-10
|
||||
z-30
|
||||
text-gray-400
|
||||
transition
|
||||
hover:text-gray-600
|
||||
@ -161,6 +184,8 @@ const PopupCreatePatient = ({ onClose }: PropsPopupCreatePatient) => {
|
||||
name="identificationNumber"
|
||||
type="number"
|
||||
isNumber
|
||||
min={12}
|
||||
max={12}
|
||||
value={form.identificationNumber}
|
||||
isRequired
|
||||
/>
|
||||
@ -238,11 +263,16 @@ const PopupCreatePatient = ({ onClose }: PropsPopupCreatePatient) => {
|
||||
<span className="text-red-500"> *</span>
|
||||
</span>
|
||||
}
|
||||
placeholder="Ngày sinh"
|
||||
placeholder="DD/MM/YYYY"
|
||||
name="dateOfBirth"
|
||||
type="Date"
|
||||
type="text"
|
||||
value={form.dateOfBirth}
|
||||
isRequired
|
||||
onChangeValue={(value) =>
|
||||
setForm((prev) => ({
|
||||
...prev,
|
||||
dateOfBirth: formatDateOfBirth(String(value)),
|
||||
}))
|
||||
}
|
||||
/>
|
||||
|
||||
<InputForm
|
||||
@ -254,8 +284,10 @@ const PopupCreatePatient = ({ onClose }: PropsPopupCreatePatient) => {
|
||||
}
|
||||
placeholder="Số điện thoại"
|
||||
name="phone"
|
||||
type="phone"
|
||||
isPhone
|
||||
type="number"
|
||||
isNumber
|
||||
min={8}
|
||||
max={11}
|
||||
value={form.phone}
|
||||
isRequired
|
||||
/>
|
||||
|
||||
@ -238,7 +238,9 @@ const PopupUpdatePatient = ({ onClose, id }: PopupUpdatePatientProps) => {
|
||||
|
||||
{/* GENDER */}
|
||||
<div>
|
||||
<label className="text-base font-medium">Giới tính</label>
|
||||
<label className="text-base font-medium">
|
||||
Giới tính <span className="text-red-500">*</span>
|
||||
</label>
|
||||
|
||||
<div className="mt-2 flex items-center gap-6">
|
||||
{/* NAM */}
|
||||
@ -293,7 +295,11 @@ const PopupUpdatePatient = ({ onClose, id }: PopupUpdatePatientProps) => {
|
||||
/>
|
||||
|
||||
<InputForm
|
||||
label={<span>Email</span>}
|
||||
label={
|
||||
<span>
|
||||
Email<span className="text-red-500"> *</span>
|
||||
</span>
|
||||
}
|
||||
placeholder="Email"
|
||||
name="email"
|
||||
type="email"
|
||||
@ -304,7 +310,12 @@ const PopupUpdatePatient = ({ onClose, id }: PopupUpdatePatientProps) => {
|
||||
<TextArea
|
||||
name="address"
|
||||
placeholder="Địa chỉ"
|
||||
label="Địa chỉ"
|
||||
label={
|
||||
<span>
|
||||
Địa chỉ
|
||||
<span className="text-red-500"> *</span>
|
||||
</span>
|
||||
}
|
||||
value={form.address}
|
||||
isRequired
|
||||
isBlur
|
||||
@ -313,7 +324,12 @@ const PopupUpdatePatient = ({ onClose, id }: PopupUpdatePatientProps) => {
|
||||
|
||||
<InputForm
|
||||
isRequired
|
||||
label="Người liên hệ khẩn cấp"
|
||||
label={
|
||||
<span>
|
||||
Người liên hệ khẩn cấp
|
||||
<span className="text-red-500"> *</span>
|
||||
</span>
|
||||
}
|
||||
placeholder="Người liên hệ khẩn cấp"
|
||||
name="emergencyContactName"
|
||||
type="text"
|
||||
@ -321,19 +337,32 @@ const PopupUpdatePatient = ({ onClose, id }: PopupUpdatePatientProps) => {
|
||||
/>
|
||||
|
||||
<InputForm
|
||||
label="SĐT khẩn cấp"
|
||||
label={
|
||||
<span>
|
||||
SĐT khẩn cấp
|
||||
<span className="text-red-500"> *</span>
|
||||
</span>
|
||||
}
|
||||
placeholder="SĐT khẩn cấp"
|
||||
name="emergencyContactPhone"
|
||||
type="phone"
|
||||
type="number"
|
||||
min={8}
|
||||
max={11}
|
||||
isRequired
|
||||
isPhone
|
||||
// isPhone
|
||||
value={form.emergencyContactPhone}
|
||||
/>
|
||||
|
||||
<TextArea
|
||||
name="allergyNotes"
|
||||
label={
|
||||
<span>
|
||||
Dị ứng
|
||||
<span className="text-red-500"> *</span>
|
||||
</span>
|
||||
}
|
||||
isRequired
|
||||
placeholder="Dị ứng"
|
||||
label="Dị ứng"
|
||||
value={form.allergyNotes}
|
||||
isBlur
|
||||
max={5000}
|
||||
@ -342,14 +371,25 @@ const PopupUpdatePatient = ({ onClose, id }: PopupUpdatePatientProps) => {
|
||||
<TextArea
|
||||
name="chronicDiseaseNotes"
|
||||
placeholder="Bệnh nền"
|
||||
label="Bệnh nền"
|
||||
label={
|
||||
<span>
|
||||
Bệnh nền
|
||||
<span className="text-red-500"> *</span>
|
||||
</span>
|
||||
}
|
||||
isRequired
|
||||
value={form.chronicDiseaseNotes}
|
||||
isBlur
|
||||
max={5000}
|
||||
/>
|
||||
|
||||
<InputForm
|
||||
label="Số bảo hiểm"
|
||||
label={
|
||||
<span>
|
||||
Số bảo hiểm
|
||||
<span className="text-red-500"> *</span>
|
||||
</span>
|
||||
}
|
||||
placeholder="Số bảo hiểm"
|
||||
name="insuranceNumber"
|
||||
type="text"
|
||||
@ -359,8 +399,8 @@ const PopupUpdatePatient = ({ onClose, id }: PopupUpdatePatientProps) => {
|
||||
|
||||
<TextArea
|
||||
name="notes"
|
||||
label={<span>Ghi chú</span>}
|
||||
placeholder="Ghi chú"
|
||||
label="Ghi chú"
|
||||
value={form.notes}
|
||||
isBlur
|
||||
max={5000}
|
||||
|
||||
@ -57,7 +57,6 @@ const CreatePrescription = () => {
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const queryKeys = [QUERY_KEY.table_list_consultation];
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [folderName, setFolderName] = useState("prescriptions");
|
||||
|
||||
const [form, setForm] = useState<PrescriptionForm>({
|
||||
examinationSessionSpecialtyId: "",
|
||||
@ -393,11 +392,16 @@ const CreatePrescription = () => {
|
||||
|
||||
{/* NOTES */}
|
||||
<TextArea
|
||||
label="Ghi chú"
|
||||
label={
|
||||
<span>
|
||||
Ghi chú<span style={{ color: "red" }}>*</span>
|
||||
</span>
|
||||
}
|
||||
name="notes"
|
||||
placeholder="Nhập ghi chú"
|
||||
value={form.notes}
|
||||
isBlur
|
||||
isRequired
|
||||
max={5000}
|
||||
onChangeValue={(value) =>
|
||||
setForm((prev) => ({
|
||||
@ -455,10 +459,15 @@ const CreatePrescription = () => {
|
||||
{/* INPUTS */}
|
||||
<div className="grid grid-cols-2 gap-5">
|
||||
<InputForm
|
||||
label="Tên thuốc"
|
||||
label={
|
||||
<span>
|
||||
Tên thuốc<span style={{ color: "red" }}>*</span>
|
||||
</span>
|
||||
}
|
||||
name={`items.${index}.medicineName`}
|
||||
placeholder="Nhập tên thuốc"
|
||||
value={medicine.medicineName}
|
||||
isRequired
|
||||
type="text"
|
||||
onChangeValue={(value) =>
|
||||
handleChangeMedicine(index, "medicineName", String(value))
|
||||
@ -466,18 +475,28 @@ const CreatePrescription = () => {
|
||||
/>
|
||||
|
||||
<InputForm
|
||||
label="Liều lượng"
|
||||
label={
|
||||
<span>
|
||||
Liều lượng<span style={{ color: "red" }}>*</span>
|
||||
</span>
|
||||
}
|
||||
name={`items.${index}.dosage`}
|
||||
placeholder="Ví dụ: 500mg"
|
||||
value={medicine.dosage}
|
||||
type="text"
|
||||
isRequired
|
||||
onChangeValue={(value) =>
|
||||
handleChangeMedicine(index, "dosage", String(value))
|
||||
}
|
||||
/>
|
||||
|
||||
<InputForm
|
||||
label="Tần suất"
|
||||
label={
|
||||
<span>
|
||||
Tần xuất<span style={{ color: "red" }}>*</span>
|
||||
</span>
|
||||
}
|
||||
isRequired
|
||||
name={`items.${index}.frequency`}
|
||||
placeholder="Ví dụ: 2 lần/ngày"
|
||||
value={medicine.frequency}
|
||||
@ -488,7 +507,12 @@ const CreatePrescription = () => {
|
||||
/>
|
||||
|
||||
<InputForm
|
||||
label="Thời gian dùng"
|
||||
label={
|
||||
<span>
|
||||
Thời gian dùng<span style={{ color: "red" }}>*</span>
|
||||
</span>
|
||||
}
|
||||
isRequired
|
||||
name={`items.${index}.duration`}
|
||||
placeholder="Ví dụ: 7 ngày"
|
||||
value={medicine.duration}
|
||||
@ -502,7 +526,12 @@ const CreatePrescription = () => {
|
||||
{/* INSTRUCTION */}
|
||||
<div className="mt-5">
|
||||
<TextArea
|
||||
label="Hướng dẫn sử dụng"
|
||||
label={
|
||||
<span>
|
||||
Hướng dẫn sử dụng<span style={{ color: "red" }}>*</span>
|
||||
</span>
|
||||
}
|
||||
isRequired
|
||||
name={`items.${index}.instructions`}
|
||||
placeholder="Nhập hướng dẫn sử dụng thuốc"
|
||||
value={medicine.instructions}
|
||||
|
||||
@ -25,7 +25,12 @@ import { ContextFormCustom } from "@/components/utils/FormCustom/contexts";
|
||||
import InputForm from "@/components/utils/FormCustom/components/InputForm";
|
||||
import FormCustom from "@/components/utils/FormCustom/FormCustom";
|
||||
import moment from "moment";
|
||||
import { timeSubmit } from "@/common/funcs/optionConvert";
|
||||
import {
|
||||
formatDateOfBirth,
|
||||
formatToISODate,
|
||||
parseDateOfBirth,
|
||||
timeSubmit,
|
||||
} from "@/common/funcs/optionConvert";
|
||||
import CustomButton from "@/components/customs/custom-button";
|
||||
|
||||
function MainUpdateProfile() {
|
||||
@ -91,7 +96,7 @@ function MainUpdateProfile() {
|
||||
phone: currentUserProfile.phone || "",
|
||||
// Định dạng input date HTML yêu cầu format YYYY-MM-DD
|
||||
birthDate: currentUserProfile.birthDate
|
||||
? moment(currentUserProfile.birthDate).format("YYYY-MM-DD")
|
||||
? moment(currentUserProfile.birthDate).format("DD/MM/YYYY")
|
||||
: "",
|
||||
avatarUrl: currentUserProfile.avatarUrl || "",
|
||||
});
|
||||
@ -112,7 +117,7 @@ function MainUpdateProfile() {
|
||||
fullName: form.fullName,
|
||||
email: form.email,
|
||||
phone: form.phone,
|
||||
birthDate: form.birthDate,
|
||||
birthDate: formatToISODate(parseDateOfBirth(form.birthDate)),
|
||||
avatarUrl: body.path || form.avatarUrl,
|
||||
}), // Lưu ý: Hãy cập nhật đúng service update của user profile tại đây
|
||||
}),
|
||||
@ -243,7 +248,12 @@ function MainUpdateProfile() {
|
||||
placeholder="Nhập họ và tên"
|
||||
name="fullName"
|
||||
value={form.fullName}
|
||||
label="Họ và tên"
|
||||
label={
|
||||
<span>
|
||||
Họ Và Tên
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
isRequired
|
||||
onChangeValue={(v) =>
|
||||
setForm((prev) => ({ ...prev, fullName: String(v) }))
|
||||
@ -251,13 +261,22 @@ function MainUpdateProfile() {
|
||||
/>
|
||||
|
||||
<InputForm
|
||||
type="date"
|
||||
type="text"
|
||||
placeholder="Nhập ngày sinh"
|
||||
name="birthDate"
|
||||
label="Ngày sinh"
|
||||
isRequired
|
||||
label={
|
||||
<span>
|
||||
Ngày sinh
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
value={form.birthDate}
|
||||
onChangeValue={(v) =>
|
||||
setForm((prev) => ({ ...prev, birthDate: String(v) }))
|
||||
setForm((prev) => ({
|
||||
...prev,
|
||||
birthDate: formatDateOfBirth(String(v)),
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
@ -268,8 +287,14 @@ function MainUpdateProfile() {
|
||||
placeholder="Nhập email"
|
||||
name="email"
|
||||
type="email"
|
||||
isEmail
|
||||
value={form.email}
|
||||
label="Email"
|
||||
label={
|
||||
<span>
|
||||
Email
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
isRequired
|
||||
onChangeValue={(v) =>
|
||||
setForm((prev) => ({ ...prev, email: String(v) }))
|
||||
@ -280,9 +305,16 @@ function MainUpdateProfile() {
|
||||
placeholder="Nhập số điện thoại"
|
||||
name="phone"
|
||||
type="number"
|
||||
isNumber
|
||||
value={form.phone}
|
||||
label="Số điện thoại"
|
||||
isRequired
|
||||
min={8}
|
||||
max={11}
|
||||
label={
|
||||
<span>
|
||||
Số điện thoại
|
||||
<span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
onChangeValue={(v) =>
|
||||
setForm((prev) => ({ ...prev, phone: String(v) }))
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ export default function Providers({ children }: Props) {
|
||||
|
||||
<SplashScreen />
|
||||
|
||||
<ToastContainer autoClose={3000} />
|
||||
<ToastContainer autoClose={3000} style={{ zIndex: 10002 }} />
|
||||
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user