src/components/Medicine/MedicationAdministration/PrintMedicationAdministration.tsx
File `PrintMedicationAdministration.tsx` has 466 lines of code (exceeds 250 allowed). Consider refactoring.import careConfig from "@careConfig";import { useQuery } from "@tanstack/react-query";import { format } from "date-fns";import { useMemo } from "react";import { useTranslation } from "react-i18next";import { formatPhoneNumberIntl } from "react-phone-number-input"; import { cn } from "@/lib/utils"; import PrintPreview from "@/CAREUI/misc/PrintPreview"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow,} from "@/components/ui/table"; import Loading from "@/components/Common/Loading";import PrintTable from "@/components/Common/PrintTable"; import api from "@/Utils/request/api";import query from "@/Utils/request/query";import { formatPatientAge, getWeeklyIntervalsFromTodayTill,} from "@/Utils/utils";import { Encounter } from "@/types/emr/encounter";import { MedicationAdministrationRead } from "@/types/emr/medicationAdministration/medicationAdministration";import medicationAdministrationApi from "@/types/emr/medicationAdministration/medicationAdministrationApi"; Function `PrintMedicationAdministration` has 255 lines of code (exceeds 25 allowed). Consider refactoring.
Function `PrintMedicationAdministration` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.export const PrintMedicationAdministration = (props: { facilityId: string; encounterId: string; patientId: string;}) => { const { facilityId, encounterId, patientId } = props; const { t } = useTranslation(); Similar blocks of code found in 2 locations. Consider refactoring. const { data: encounter } = useQuery<Encounter>({ queryKey: ["encounter", encounterId], queryFn: query(api.encounter.get, { pathParams: { id: encounterId }, queryParams: { facility: facilityId }, }), }); const { data: medicationAdministrations, isLoading } = useQuery({ queryKey: ["medication_administrations", patientId],Similar blocks of code found in 3 locations. Consider refactoring. queryFn: query.paginated(medicationAdministrationApi.list, { pathParams: { patientId: patientId }, queryParams: { encounter: encounterId, }, pageSize: 1000, }), enabled: !!patientId, }); const administrationsByAdministrator = useMemo( () =>Similar blocks of code found in 2 locations. Consider refactoring. (medicationAdministrations?.results ?? []).reduce< Record<string, MedicationAdministrationRead[]> >((acc, administration) => { const administraterId = administration.created_by.id.toString(); if (!acc[administraterId]) { acc[administraterId] = []; } acc[administraterId].push(administration); return acc; }, {}), [medicationAdministrations], ); Similar blocks of code found in 2 locations. Consider refactoring. const hourRanges = [ { start: "00:00", end: "06:00" }, { start: "06:00", end: "12:00" }, { start: "12:00", end: "18:00" }, { start: "18:00", end: "24:00" }, ];Function `filterAdministartionsByMedicineOccurenceAndHourRange` has 68 lines of code (exceeds 25 allowed). Consider refactoring. const filterAdministartionsByMedicineOccurenceAndHourRange = ( administrations: MedicationAdministrationRead[], hourRanges: { start: string; end: string }[], dateRange?: { start?: string; end?: string }, ) => { const adminstrationsHourRangeMap = {} as { [medicineRequestId: string]: { [occurenceStartDate: string]: { [hourRangeKey: string]: MedicationAdministrationRead[]; }; }; }; administrations ?.filter((administration) => { const startDate = dateRange?.start && new Date(dateRange.start).toISOString().slice(0, 10); const endDate = dateRange?.end && new Date(dateRange.end).toISOString().slice(0, 10); const date = new Date(administration.occurrence_period_start) .toISOString() .slice(0, 10); if (startDate && endDate) { return date >= startDate && date <= endDate; } if (startDate) { return date >= startDate; } if (endDate) { return date <= endDate; } return true; }) .forEach((administration) => { const medicineRequestId = administration.request; const occurenceStartDate = new Date( administration.occurrence_period_start, ) .toISOString() .slice(0, 10); const hourRange = hourRanges.find((range) => { const startDate = new Date(administration.occurrence_period_start); const startHour = startDate.getHours(); return ( startHour >= parseInt(range.start.split(":")[0]) && startHour < parseInt(range.end.split(":")[0]) ); }); if (!hourRange) return; if (!adminstrationsHourRangeMap[medicineRequestId]) { adminstrationsHourRangeMap[medicineRequestId] = {}; } if ( !adminstrationsHourRangeMap[medicineRequestId][occurenceStartDate] ) { adminstrationsHourRangeMap[medicineRequestId][occurenceStartDate] = {}; } const hourRangeKey = `${hourRange.start}-${hourRange.end}`; if ( !adminstrationsHourRangeMap[medicineRequestId][occurenceStartDate][ hourRangeKey ] ) { adminstrationsHourRangeMap[medicineRequestId][occurenceStartDate][ hourRangeKey ] = []; } adminstrationsHourRangeMap[medicineRequestId][occurenceStartDate][ hourRangeKey ].push(administration); }); return adminstrationsHourRangeMap; }; if (isLoading) return <Loading />; if (!medicationAdministrations?.results?.length) { return ( <div className="flex h-52 items-center justify-center rounded-lg border-2 border-gray-200 border-dashed p-4 text-gray-500"> {t("no_medications_found_for_this_encounter")} </div> ); } return (Similar blocks of code found in 2 locations. Consider refactoring. <PrintPreview title={`${t("medicine_administration")} - ${encounter?.patient.name}`} disabled={!medicationAdministrations?.results?.length} > <div className="min-h-screen md:p-2 max-w-4xl mx-auto"> <div>Similar blocks of code found in 2 locations. Consider refactoring. <div className="flex flex-col sm:flex-row justify-between items-center sm:items-start mb-4 pb-2 border-b border-gray-200"> <img src={careConfig.mainLogo?.dark} alt="Care Logo" className="h-10 w-auto object-contain mb-2 sm:mb-0 sm:order-2" /> <div className="text-center sm:text-left sm:order-1"> <h1 className="text-3xl font-semibold"> {encounter?.facility?.name} </h1> <h2 className="text-gray-500 uppercase text-sm tracking-wide mt-1 font-semibold"> {t("medicine_administration")} </h2> </div> </div> Identical blocks of code found in 2 locations. Consider refactoring. <div className="grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-6 mb-8"> <div className="space-y-3"> <DetailRow label={t("patient")} value={encounter?.patient.name} isStrong /> <DetailRow label={`${t("age")} / ${t("sex")}`} value={ encounter?.patient ? `${formatPatientAge(encounter.patient, true)}, ${t(`GENDER__${encounter.patient.gender}`)}` : undefined } isStrong /> </div> <div className="space-y-3"> <DetailRow label={t("encounter_date")} value={ encounter?.period?.start && format(new Date(encounter.period.start), "dd MMM yyyy, EEEE") } isStrong /> <DetailRow label={t("mobile_number")} value={ encounter && formatPhoneNumberIntl(encounter.patient.phone_number) } isStrong /> </div> </div> <div className="flex flex-col gap-6"> {getWeeklyIntervalsFromTodayTill(encounter?.period.start).map( ({ start: weekStartDate, end: weekEndDate }) => ( <MedicationAdministrationTable key={weekStartDate.toISOString()} administrations={filterAdministartionsByMedicineOccurenceAndHourRange( medicationAdministrations.results, hourRanges, { start: weekStartDate.toISOString(), end: weekEndDate.toISOString(), }, )} dateRange={{ start: weekStartDate, end: weekEndDate, }} hourRanges={hourRanges} /> ), )} </div> <div className="mt-6"> <PrintTable headers={[ { key: "medicine" }, { key: "administered_at" }, { key: "administered_by" }, { key: "notes" }, ]} rows={medicationAdministrations?.results .sort( (a, b) => Number(new Date(a.occurrence_period_start)) - Number(new Date(b.occurrence_period_start)), ) .map((administration) => { return { medicine: administration.medication.display ?? administration.medication.code, administered_at: format( new Date(administration.occurrence_period_start), "dd MMM yyyy, hh:mm a", ), administered_by: `Dr. ${administration.created_by.first_name} ${administration.created_by.last_name}`, notes: administration.note, }; })} /> </div> <div className="mt-6 flex justify-end gap-8"> {Object.entries(administrationsByAdministrator).map( ([administraterId, administrations]) => { const administrater = administrations[0].created_by; return ( <div key={administraterId} className="text-center"> <p className="text-sm text-gray-600 font-semibold"> Dr. {administrater.first_name} {administrater.last_name} </p> </div> ); }, )} </div> Similar blocks of code found in 2 locations. Consider refactoring. <div className="mt-8 pt-2 text-[10px] text-gray-500 flex justify-between flex-wrap"> <p> {t("generated_on")} {format(new Date(), "PPP 'at' p")} </p> <p>{t("computer_generated_medication_administration")}</p> </div> </div> </div> </PrintPreview> );}; Similar blocks of code found in 3 locations. Consider refactoring.const DetailRow = ({ label, value, isStrong = false,}: { label: string; value?: string | null; isStrong?: boolean;}) => { return ( <div className="flex"> <span className="text-gray-600 w-32">{label}</span> <span className="text-gray-600">: </span> <span className={`ml-1 ${isStrong ? "font-semibold" : ""}`}> {value || "-"} </span> </div> );}; type MedicationAdministrationTableProps = { administrations: { [medicineRequestId: string]: { [occurenceStartDate: string]: { [hourRangeKey: string]: MedicationAdministrationRead[]; }; }; }; dateRange: { start: Date; end: Date }; hourRanges: { start: string; end: string }[];}; Function `MedicationAdministrationTable` has a Cognitive Complexity of 15 (exceeds 5 allowed). Consider refactoring.const MedicationAdministrationTable = ({ administrations, dateRange, hourRanges,}: MedicationAdministrationTableProps) => { const { t } = useTranslation(); const dates = useMemo(() => { const dates = []; const startDate = new Date(dateRange.start); const endDate = new Date(dateRange.end); while (startDate <= endDate) { dates.push(new Date(startDate)); startDate.setDate(startDate.getDate() + 1); } return dates; }, [dateRange]); const isMedicationAdministeredWithinDateRange = useMemo(() => { for (const date of dates) { if ( Object.values(administrations).some( (dateWiseAdministrations) => !!dateWiseAdministrations[format(date, "yyyy-MM-dd")], ) ) { return true; } } return false; }, [administrations, dates]); if (!isMedicationAdministeredWithinDateRange) return null; Function `renderMedication` has 46 lines of code (exceeds 25 allowed). Consider refactoring. const renderMedication = ( dateWiseAdministrations: MedicationAdministrationTableProps["administrations"][string], ) => { const hourWiseAdministrations = dateWiseAdministrations[Object.keys(dateWiseAdministrations)[0]]; const hourRange = Object.keys(hourWiseAdministrations)[0]; const administration = hourWiseAdministrations[hourRange][0]; return ( <div className="flex flex-col items-center gap-2"> <h5> {administration.medication.display ?? administration.medication.code} </h5> <p className="text-sm flex items-center justify-center gap-1 flex-wrap"> <span> {administration.dosage?.dose?.value}{" "} {administration.dosage?.dose?.unit.display ?? administration.dosage?.dose?.unit.code} </span>Similar blocks of code found in 3 locations. Consider refactoring. {administration.dosage?.route && ( <span> {t("administered_through_route", { route: administration.dosage?.route?.display ?? administration.dosage?.route?.code, })} </span> )}Similar blocks of code found in 3 locations. Consider refactoring. {administration.dosage?.method && ( <span> {t("administered_via_method", { method: administration.dosage?.method?.display ?? administration.dosage?.method?.code, })} </span> )}Similar blocks of code found in 3 locations. Consider refactoring. {administration.dosage?.site && ( <span> {t("administered_at_site", { site: administration.dosage?.site?.display ?? administration.dosage?.site?.code, })} </span> )} <span>{administration.dosage?.text}</span> </p> </div> ); }; return ( <div className="overflow-hidden rounded-lg border-2 border-black"> <div> <h3 className="font-semibold text-lg text-center bg-gray-200 p-2"> {t("date_range_from_till", { from: format(dates[0], "dd MMM yyyy"), till: format(dates[dates.length - 1], "dd MMM yyyy"), })} </h3> </div> <Table className="w-full"> <TableHeader> <TableRow className="bg-transparent hover:bg-transparent divide-x divide-gray border-b-gray-200"> <TableHead className="first:rounded-l-md h-auto py-1 pl-2 pr-2 text-black text-center capitalize"> {t("medication")} </TableHead> <TableHead className="first:rounded-l-md h-auto py-1 pl-2 pr-2 text-black text-center capitalize"> {t("hour")} </TableHead> {dates.map((header, index) => ( <TableHead key={index} className="first:rounded-l-md h-auto py-1 pl-2 pr-2 text-black text-center" > {format(header, "dd MMM")} </TableHead> ))} </TableRow> </TableHeader> <TableBody> {Object.values(administrations).map((dateWiseAdministrations) => hourRanges.map((hourRange, index) => ( <TableRow key={hourRange.start + hourRange.end} className={cn( "bg-transparent hover:bg-transparent divide-x", index === 0 && "border-t-2 border-t-black", )} > {index === 0 && ( <TableCell className="break-words whitespace-normal text-center" rowSpan={hourRanges.length} > {renderMedication(dateWiseAdministrations)} </TableCell> )} <TableCell className="whitespace-nowrap text-center border-x border-gray-200"> {hourRange.start} - {hourRange.end} </TableCell> {dates.map((date) => ( <TableCell key={date.toISOString()} className="break-words whitespace-normal text-center" > {dateWiseAdministrations[format(date, "yyyy-MM-dd")]?.[ `${hourRange.start}-${hourRange.end}` ]?.length || "-"} </TableCell> ))} </TableRow> )), )} </TableBody> </Table> </div> );};