feat:update

This commit is contained in:
TuanVT
2026-06-04 15:59:39 +07:00
parent 77dd05932e
commit 7791e1d6a8
19 changed files with 572 additions and 678 deletions
@@ -1,6 +1,6 @@
"use client";
import React, { useEffect, useMemo } from "react";
import React, { useEffect, useMemo, useState } from "react";
import { useParams, useRouter, useSearchParams } from "next/navigation";
import { useQuery } from "@tanstack/react-query";
@@ -10,6 +10,7 @@ import { QUERY_KEY, TYPE_STATUS } from "@/constant/config/enum";
import { ArrowLeft, Pencil } from "lucide-react";
import consultationServices, {
AttachmentFile,
ConsultationDetail,
} from "@/services/consultationServices";
@@ -20,6 +21,7 @@ import GridColumn from "@/components/layouts/GridColumn";
import DataWrapper from "@/components/customs/DataWrapper";
import Table from "@/components/customs/custom-table";
import CustomButton from "@/components/customs/custom-button";
import Pagination from "@/components/customs/custom-pagination";
const DetailConsultation = () => {
const params = useParams();
@@ -29,6 +31,9 @@ const DetailConsultation = () => {
const consultationId = params?.id as string;
const [prescriptionPage, setPrescriptionPage] = useState<number>(1);
const [prescriptionPageSize, setPrescriptionPageSize] = useState<number>(10);
const consulDetailQuery = useQuery<ConsultationDetail>({
queryKey: [QUERY_KEY.chi_tiet_phien_kham, consultationId],
@@ -77,6 +82,17 @@ const DetailConsultation = () => {
})) || []
);
}, [consultation?.specialtyClinics, consultationId]);
// Tính toán cắt mảng dữ liệu thuốc để hiển thị phân trang trên Client
const paginatedPrescriptionItems = useMemo(() => {
const items = consultation?.aggregatedPrescriptionItems || [];
const startIndex = (prescriptionPage - 1) * prescriptionPageSize;
const endIndex = startIndex + prescriptionPageSize;
return items.slice(startIndex, endIndex);
}, [
consultation?.aggregatedPrescriptionItems,
prescriptionPage,
prescriptionPageSize,
]);
const specialtyClinics = consultation?.specialtyClinics;
const selectedSpecialty = useMemo(() => {
@@ -104,6 +120,17 @@ const DetailConsultation = () => {
type PrescriptionItem =
ConsultationDetail["aggregatedPrescriptionItems"][number];
const getFileInfo = (file: AttachmentFile | string, index: number) => {
if (typeof file === "string") {
return {
fileName: file.split("/").pop() || `File ${index + 1}`,
path: file,
};
}
return file;
};
return (
<div className="flex flex-col gap-4">
<div className="flex flex-row gap-4">
@@ -122,16 +149,17 @@ const DetailConsultation = () => {
</h2>
</div>
{consultation.status === TYPE_STATUS.PendingPrescription && canUpdateConsultation && (
<CustomButton
variant="midnightBlue"
fullWidth={false}
icon={<Pencil />}
href={`/consultation/update?_id=${consultation.id}`}
>
Cập nhật tổng quát
</CustomButton>
)}
{consultation.status === TYPE_STATUS.PendingPrescription &&
canUpdateConsultation && (
<CustomButton
variant="midnightBlue"
fullWidth={false}
icon={<Pencil />}
href={`/consultation/update?_id=${consultation.id}`}
>
Cập nhật tổng quát
</CustomButton>
)}
</div>
<GridColumn col={3}>
@@ -283,6 +311,61 @@ const DetailConsultation = () => {
.join(", ") || "---"}
</p>
</div>
<div className="space-y-1">
<p className="text-[14px] font-medium text-[#697586]">
FILE UPLOAD
</p>
{consultation.generalAttachmentUrls?.length > 0 ? (
<ul className="space-y-2">
{consultation.generalAttachmentUrls.map((item, index) => {
const file = getFileInfo(item, index);
const extension =
file.fileName.split(".").pop()?.toLowerCase() || "";
const isImage = [
"jpg",
"jpeg",
"png",
"gif",
"webp",
"bmp",
"svg",
].includes(extension);
return (
<li key={index}>
{isImage ? (
<a
href={file.path}
target="_blank"
rel="noopener noreferrer"
className="text-blue-500 hover:underline"
>
🖼 {file.fileName}
</a>
) : (
<a
href={file.path}
download={file.fileName}
className="text-green-600 hover:underline"
>
📄 {file.fileName}
</a>
)}
</li>
);
})}
</ul>
) : (
<p className="text-gray-500">
Không file nào đưc tải lên.
</p>
)}
</div>
<div className="space-y-1">
<p className="text-[14px] font-medium text-[#697586]">
TRẠNG THÁI
@@ -341,6 +424,7 @@ const DetailConsultation = () => {
Danh sách đơn thuốc
</h2>
</div>
<DataWrapper
data={consultation.aggregatedPrescriptionItems}
loading={consulDetailQuery.isLoading}
@@ -348,13 +432,20 @@ const DetailConsultation = () => {
note="Vui lòng thử lại sau"
>
<Table
rowKey={(item) => item.id}
data={consultation.aggregatedPrescriptionItems}
// Nếu item không có thuộc tính id, bạn có thể đổi thành (item, index) => String(index)
rowKey={(item: PrescriptionItem) => {
// Tìm vị trí của item hiện tại trong mảng paginatedPrescriptionItems
const idx = paginatedPrescriptionItems.indexOf(item);
return item.id || String(idx);
}}
data={paginatedPrescriptionItems} // Hiển thị dữ liệu trang hiện tại
column={[
{
title: "Tên thuốc",
render: (item: PrescriptionItem) => (
<span>{item.medicineName}</span>
<span className="font-medium text-gray-900">
{item.medicineName}
</span>
),
},
{
@@ -378,12 +469,29 @@ const DetailConsultation = () => {
{
title: "Hướng dẫn",
render: (item: PrescriptionItem) => (
<span>{item.instructions || "---"}</span>
<span className="text-sm text-gray-500">
{item.instructions || "---"}
</span>
),
},
]}
/>
</DataWrapper>
{/* Chỉ hiển thị phân trang khi tổng số lượng thuốc lớn hơn 10 phần tử */}
{(consultation.aggregatedPrescriptionItems?.length || 0) > 10 && (
<Pagination
total={consultation.aggregatedPrescriptionItems?.length || 0}
page={prescriptionPage}
pageSize={prescriptionPageSize}
onSetPage={(value) => setPrescriptionPage(value)}
onSetPageSize={(value) => {
setPrescriptionPageSize(value);
setPrescriptionPage(1); // Reset về trang 1 khi thay đổi kích thước hiển thị hàng
}}
dependencies={[prescriptionPage, prescriptionPageSize]}
/>
)}
</div>
</div>
</div>
@@ -437,6 +545,58 @@ const DetailConsultation = () => {
<p>{selectedSpecialty.procedureNotes || "---"}</p>
</div>
<div className="space-y-1">
<p className="text-[14px] font-medium text-[#697586]">
FILE UPLOAD
</p>
{selectedSpecialty.attachmentUrls?.length > 0 ? (
<ul className="space-y-2">
{selectedSpecialty.attachmentUrls.map((item, index) => {
const file = getFileInfo(item, index);
const extension =
file.fileName.split(".").pop()?.toLowerCase() || "";
const isImage = [
"jpg",
"jpeg",
"png",
"gif",
"webp",
"bmp",
"svg",
].includes(extension);
return (
<li key={index}>
{isImage ? (
<a
href={file.path}
target="_blank"
rel="noopener noreferrer"
className="text-blue-500 hover:underline"
>
🖼 {file.fileName}
</a>
) : (
<a
href={file.path}
download={file.fileName}
className="text-green-600 hover:underline"
>
📄 {file.fileName}
</a>
)}
</li>
);
})}
</ul>
) : (
<p className="text-gray-500">Không file nào đưc tải lên.</p>
)}
</div>
{selectedSpecialty.glassRequired && (
<>
<div>