feat:update all page

This commit is contained in:
TuanVT
2026-05-26 16:43:42 +07:00
parent bce004352c
commit 56e2733d8f
18 changed files with 480 additions and 262 deletions
@@ -25,6 +25,7 @@ import CustomButton from "@/components/customs/custom-button";
import { useRouter } from "next/navigation";
import InputForm from "@/components/utils/FormCustom/components/InputForm";
import GridColumn from "@/components/layouts/GridColumn";
import { toastWarn } from "@/common/funcs/toast";
const CreateConsultation = () => {
const router = useRouter();
@@ -111,6 +112,9 @@ const CreateConsultation = () => {
});
const handleSubmit = () => {
if (!form?.patientId) {
return toastWarn({ msg: "Vui lòng chọn bệnh nhân" });
}
createConsultationMutation.mutate();
};
@@ -118,14 +122,14 @@ const CreateConsultation = () => {
<FormCustom form={form} setForm={setForm} onSubmit={handleSubmit}>
<div
className="
relative
max-w-[95vw]
rounded-3xl
h-[485px]
border
rounded-lg
bg-white
shadow-xl
flex
flex-col
overflow-hidden
"
>
<div className="flex items-center justify-between">
@@ -139,56 +143,13 @@ const CreateConsultation = () => {
"
>
<h2 className="text-[30px] font-semibold text-[#111827]">
Thêm phiên khám
Tạo phiên khám
</h2>
</div>
<div
className="
shrink-0
border-t
bg-white
px-7
py-5
flex
items-center
justify-end
gap-3
"
>
<CustomButton
variant="grey"
rounded="md"
onClick={() => router.back()}
>
Hủy bỏ
</CustomButton>
<CustomButton
disabled={
!form.patientId ||
// !form.chiefComplaint ||
// !form.diagnosis ||
// !form.doctorNotes ||
// !form.symptomsText ||
// !form.treatmentPlan ||
// !form.vitalSigns ||
createConsultationMutation.isPending
}
variant="midnightBlue"
rounded="md"
fullWidth={false}
className="min-w-[180px] "
onClick={handleSubmit}
>
{createConsultationMutation.isPending
? "Đang tạo..."
: "Tạo phiên khám"}
</CustomButton>
</div>
</div>
{/* BODY */}
<div className="flex-1 overflow-y-auto px-7 py-5">
<div className="flex-1 px-7 py-5">
<div className="space-y-5 mb-2">
<SelectForm
label={
@@ -219,63 +180,50 @@ const CreateConsultation = () => {
getOptionValue={(item: PatientItem) => item.id}
/>
</div>
{/* <GridColumn col={3}>
<InputForm
label="Lý do khám"
name="chiefComplaint"
type="text"
value={form.chiefComplaint}
placeholder="Nhập lý do khám"
isRequired
/>
<InputForm
type="text"
label="Triệu chứng"
name="symptomsText"
placeholder="Nhập triệu chứng"
isRequired
value={form.symptomsText}
/>
<InputForm
type="text"
label="Nhiệt độ cơ thể"
name="vitalSigns"
placeholder="Nhập nhiệt độ cơ thể"
value={form.vitalSigns}
isRequired
/>
<InputForm
type="text"
label="Chẩn đoán"
name="diagnosis"
placeholder="Nhập chẩn đoán"
value={form.diagnosis}
isRequired
/>
<InputForm
type="text"
label="Kế hoạch điều trị"
name="treatmentPlan"
placeholder="Nhập kế hoạch điều trị"
value={form.treatmentPlan}
isRequired
/>
<InputForm
type="text"
label="Ghi chú bác sĩ"
name="doctorNotes"
placeholder="Nhập ghi chú"
value={form.doctorNotes}
isRequired
/>
</GridColumn> */}
</div>
{/* FOOTER */}
<div
className="
shrink-0
border-t
bg-white
px-7
py-5
flex
items-center
justify-end
gap-3
"
>
<CustomButton
variant="grey"
rounded="md"
onClick={() => router.back()}
>
Hủy bỏ
</CustomButton>
<CustomButton
disabled={
!form.patientId ||
// !form.chiefComplaint ||
// !form.diagnosis ||
// !form.doctorNotes ||
// !form.symptomsText ||
// !form.treatmentPlan ||
// !form.vitalSigns ||
createConsultationMutation.isPending
}
variant="midnightBlue"
rounded="md"
onClick={handleSubmit}
>
{createConsultationMutation.isPending
? "Đang tạo..."
: "Tạo phiên khám"}
</CustomButton>
</div>
</div>
</FormCustom>
);
@@ -272,20 +272,6 @@ const MainPageConsultation = () => {
rowKey={(item) => item.id}
data={consultationData}
column={[
{
fixedLeft: true,
title: "ID PHIÊN KHÁM",
render: (item: ConsultationItem) => (
<Link
href={`/consultation/${item.id}`}
className="text-blue-500 hover:underline"
>
{item.id}
</Link>
),
},
{
title: "TÊN BỆNH NHÂN",
@@ -296,9 +282,14 @@ const MainPageConsultation = () => {
{
title: "MÃ PHIÊN KHÁM",
fixedLeft: true,
render: (item: ConsultationItem) => (
<span>{item.sessionCode}</span>
<Link
href={`/consultation/${item.id}`}
className="text-blue-500 hover:underline"
>
{item.sessionCode}
</Link>
),
},
@@ -0,0 +1,196 @@
"use client";
import React from "react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useQuery } from "@tanstack/react-query";
import Link from "next/link";
import consultationServices, {
ConsultationItem,
ConsultationResponse,
} from "@/services/consultationServices";
import { httpRequest } from "@/services";
import { QUERY_KEY, TYPE_STATUS } from "@/constant/config/enum";
import DataWrapper from "@/components/customs/DataWrapper";
import Table from "@/components/customs/custom-table";
import StateActive from "@/components/customs/StateActive";
import Pagination from "@/components/customs/custom-pagination";
import Search from "@/components/customs/custom-search";
const TableHistoryPatient = () => {
const searchParams = useSearchParams();
const router = useRouter();
const pathname = usePathname();
const patientId = searchParams.get("_id");
const consultationQuery = useQuery<ConsultationResponse>({
queryKey: [QUERY_KEY.table_list_consultation, patientId, "full-history"],
enabled: !!patientId,
queryFn: async () => {
const res = await httpRequest<ConsultationResponse>({
showMessageFailed: true,
http: consultationServices.getConsultations({
Page: 1,
PageSize: 1000,
PatientId: patientId || "",
}),
});
return (
res || {
items: [],
page: 1,
pageSize: 10,
total: 0,
totalPages: 0,
}
);
},
});
const _page = searchParams.get("_page");
const _pageSize = searchParams.get("_pageSize");
const _keyword = searchParams.get("_keyword");
const page = _page ? Number(_page) : 1;
const pageSize = _pageSize ? Number(_pageSize) : 10;
const updateQuery = (key: string, value: string | number) => {
const params = new URLSearchParams(searchParams.toString());
if (!value || value === "" || (key === "_page" && value === 1)) {
params.delete(key);
} else {
params.set(key, String(value));
}
if (key === "_pageSize") {
params.delete("_page");
}
const queryString = params.toString();
router.push(queryString ? `?${queryString}` : pathname);
};
const data = consultationQuery.data?.items || [];
// lấy tên bệnh nhân từ record đầu tiên (nếu backend có trả)
const patientName = data?.[0]?.patientName || "Bệnh nhân";
return (
<div className="rounded-2xl border border-gray-200 bg-white p-6 shadow-sm">
<div className="flex items-center justify-between mb-4">
<h2 className="text-xl font-semibold">
Lịch sử phiên khám của {patientName}
</h2>
<button
onClick={() => router.back()}
className="text-blue-500 hover:underline"
>
Quay lại
</button>
</div>
<div className="flex items-center justify-between gap-4">
<div className="w-full md:min-w-[400px]">
<Search
keyword={_keyword ?? ""}
setKeyword={(value) => updateQuery("_keyword", value)}
placeholder="Tìm kiếm phiên khám..."
/>
</div>
</div>
<DataWrapper
data={data}
loading={consultationQuery.isLoading}
title="Không có dữ liệu"
note="Bệnh nhân chưa có lịch sử khám"
>
<Table
rowKey={(item: ConsultationItem) => item.id}
data={data}
column={[
{
title: "MÃ PHIÊN KHÁM",
render: (item: ConsultationItem) => (
<Link
href={`/consultation/${item.id}`}
className="text-blue-500 hover:underline"
>
{item.sessionCode}
</Link>
),
},
{
title: "NGÀY KHÁM",
render: (item: ConsultationItem) => <span>{item.visitDate}</span>,
},
{
title: "DẤU HIỆU",
render: (item: ConsultationItem) => (
<span>{item.symptomsText || "---"}</span>
),
},
{
title: "CHẨN ĐOÁN",
render: (item: ConsultationItem) => (
<span>{item.diagnosis || "---"}</span>
),
},
{
title: "TRẠNG THÁI",
render: (item: ConsultationItem) => (
<StateActive
stateActive={item.status}
listState={[
{
state: TYPE_STATUS.Draft,
text: "Đang chờ",
textColor: "#000",
backgroundColor: "#FFE4C4",
},
{
state: TYPE_STATUS.InProgress,
text: "Đang thực hiện",
textColor: "#000",
backgroundColor: "#ff3300",
},
{
state: TYPE_STATUS.Completed,
text: "Hoàn thành",
textColor: "#000",
backgroundColor: "#3d69eb",
},
{
state: TYPE_STATUS.Cancelled,
text: "Đã hủy",
textColor: "#000",
backgroundColor: "#cccccc",
},
]}
/>
),
},
]}
/>
</DataWrapper>
<Pagination
total={data.length}
page={page}
pageSize={pageSize}
onSetPage={(value) => updateQuery("_page", value)}
onSetPageSize={(value) => updateQuery("_pageSize", value)}
dependencies={[_pageSize, _keyword]}
/>
</div>
);
};
export default TableHistoryPatient;
@@ -0,0 +1 @@
export { default } from "./TableHistoryPatient";
@@ -174,34 +174,12 @@ const UpdateConsultation = () => {
<div className="flex items-center justify-between border-b pb-5">
<div>
<h2 className="text-[28px] font-semibold text-[#111827]">
Chỉnh sửa phiên khám
Phiên khám
</h2>
<p className="mt-1 text-sm text-[#697586]">
Cập nhật thông tin chi tiết quá trình khám bệnh
</p>
</div>
<div className="flex items-center gap-3">
<CustomButton
type="button"
variant="grey"
rounded="md"
onClick={() => router.back()}
className="min-w-[120px]"
>
Hủy bỏ
</CustomButton>
<CustomButton
type="submit"
variant="midnightBlue"
rounded="md"
disabled={isLoading || !id || id === "undefined"}
className="min-w-[140px]"
>
{updateConsultationMutation.isPending
? "Đang cập nhật..."
: "Cập nhật"}
</CustomButton>
</div>
</div>
{/* GENERAL INFO (PATIENT) */}
@@ -251,9 +229,9 @@ const UpdateConsultation = () => {
<InputForm
type="text"
label="Nhiệt độ cơ thể"
label="Chỉ số huyết áp, chỉ số mạch"
name="vitalSigns"
placeholder="Nhập nhiệt độ cơ thể"
placeholder="Nhập chỉ số huyết áp, chỉ số mạch"
value={form.vitalSigns}
isRequired
onChangeValue={(v) =>
@@ -297,6 +275,28 @@ const UpdateConsultation = () => {
}
/>
</GridColumn>
<div className="flex items-center gap-3">
<CustomButton
type="button"
variant="grey"
rounded="md"
onClick={() => router.back()}
className="min-w-[120px]"
>
Hủy bỏ
</CustomButton>
<CustomButton
type="submit"
variant="midnightBlue"
rounded="md"
disabled={isLoading || !id || id === "undefined"}
className="min-w-[140px]"
>
{updateConsultationMutation.isPending
? "Đang cập nhật..."
: "Cập nhật"}
</CustomButton>
</div>
</div>
</FormCustom>
);