Skip to content

Commit

Permalink
feat(FE): 한의과 약국 페이지 UI 구현 (#179)
Browse files Browse the repository at this point in the history
feat: 한의과 약국 페이지 구현
  • Loading branch information
eeseung authored Feb 21, 2025
1 parent a405104 commit 8b6ebca
Show file tree
Hide file tree
Showing 6 changed files with 1,130 additions and 1 deletion.
74 changes: 74 additions & 0 deletions frontend/src/constants/mock-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1405,3 +1405,77 @@ export const kmDiagnosisCharts = [
treatmentNote: '처방 내용',
},
];

export const kmPastCharts = [
{
chartNumber: 250101101,
presentIllness: '과거 진료 내용',
impression: '과거 진단 내용',
prescriptions: [
{
id: 1,
medicineId: 1,
medicineName: '갈근탕연조엑스(단미엑스혼합제) S02',
doseAmount: 1,
doseFrequency: 'qid',
doseDuration: 3,
doseTime: '식후',
remark: null,
medicine: {
name: '갈근탕연조엑스(단미엑스혼합제) S02',
deletedAt: new Date('2024-02-02'),
},
},
],
treatmentNote: '처방 내용',
},
{
chartNumber: 240101101,
},
{
chartNumber: 230101101,
},
];

export const kmPharmacyCharts = [
{
chartNumber: 250101104,
presentIllness: '250101104 현재 진료 내용',
impression: '250101104 현재 진단 내용',
prescriptions: [
{
id: 1,
medicineId: 1,
medicineName: '갈근탕연조엑스(단미엑스혼합제) S02',
doseAmount: 1,
doseFrequency: 'qid',
doseDuration: 3,
doseTime: '식후',
remark: null,
medicine: {
name: '갈근탕연조엑스(단미엑스혼합제) S02',
deletedAt: new Date('2024-02-02'),
},
},
],
treatmentNote: '250101104 처방 내용',
},
{
chartNumber: 250101106,
presentIllness: '250101106 현재 진료 내용',
impression: '250101106 현재 진단 내용',
prescriptions: [
{
id: 1,
medicineId: 1,
medicineName: '갈근탕연조엑스(단미엑스혼합제) S02',
doseAmount: 1,
doseFrequency: 'qid',
doseDuration: 3,
doseTime: '식후',
remark: null,
},
],
treatmentNote: '250101106 처방 내용',
},
];
130 changes: 130 additions & 0 deletions frontend/src/features/km/pharmacy/DosageSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import {
Card,
CardContent,
CardHeader,
CardTitle,
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@freemed-kit/ui';
import { PharmacyFormValues } from '@/features/km/pharmacy/usePharmacyForm';

interface DosageSectionProps {
prescriptions: PharmacyFormValues[];
}

const DosageSection = ({ prescriptions }: DosageSectionProps) => {
const dosageDays = Math.max(
7,
...prescriptions
.map((prescription) => prescription?.doseDuration)
.filter((duration) => typeof duration === 'number'),
);
const dose = {
morning: Array(dosageDays).fill(0),
lunch: Array(dosageDays).fill(0),
evening: Array(dosageDays).fill(0),
night: Array(dosageDays).fill(0),
};

for (let i = 0; i < prescriptions.length; i++) {
const { doseAmount, doseFrequency, doseDuration } = prescriptions[i];
for (let i = 0; i < (doseDuration ?? 0); i++) {
if (doseFrequency === 'qd(아침)') {
dose.morning[i] += doseAmount;
} else if (doseFrequency === 'qd(저녁)') {
dose.evening[i] += doseAmount;
} else if (doseFrequency === 'bid') {
dose.morning[i] += doseAmount;
dose.evening[i] += doseAmount;
} else if (doseFrequency === 'tid') {
dose.morning[i] += doseAmount;
dose.lunch[i] += doseAmount;
dose.evening[i] += doseAmount;
} else if (doseFrequency === 'qid') {
dose.morning[i] += doseAmount;
dose.lunch[i] += doseAmount;
dose.evening[i] += doseAmount;
dose.night[i] += doseAmount;
} else if (doseFrequency === 'hs') {
dose.night[i] += doseAmount;
}
}
}

return (
<Card>
<CardHeader className="p-4 pb-0">
<CardTitle className="text-xl">일 / 시간대 별 투약량</CardTitle>
</CardHeader>
<CardContent className="space-y-4 p-4">
<div className="rounded-md border">
<Table className="min-w-5xl table-fixed break-keep">
<TableHeader>
<TableRow className="bg-muted/50 font-mono">
<TableHead className="w-20"></TableHead>
{Array.from({ length: dosageDays }, (_, i) => i + 1).map(
(day) => (
<TableHead key={day} className="px-2 text-center">
{day}
</TableHead>
),
)}
</TableRow>
</TableHeader>
{prescriptions.length > 0 && (
<TableBody>
<TableRow className="hover:bg-background">
<TableCell className="w-20 px-2 text-center">아침</TableCell>
{dose.morning.map((dosage, index) => (
<TableCell
key={index}
className="px-2 text-center font-mono"
>
{dosage}
</TableCell>
))}
</TableRow>
<TableRow className="hover:bg-background">
<TableCell className="w-20 px-2 text-center">점심</TableCell>
{dose.lunch.map((dosage, index) => (
<TableCell
key={index}
className="px-2 text-center font-mono"
>
{dosage}
</TableCell>
))}
</TableRow>
<TableRow className="hover:bg-background">
<TableCell className="w-20 px-2 text-center">저녁</TableCell>
{dose.evening.map((dosage, index) => (
<TableCell
key={index}
className="px-2 text-center font-mono"
>
{dosage}
</TableCell>
))}
</TableRow>
<TableRow>
<TableCell className="text-center">취침</TableCell>
{dose.night.map((dosage, index) => (
<TableCell key={index} className="text-center font-mono">
{dosage}
</TableCell>
))}
</TableRow>
</TableBody>
)}
</Table>
</div>
</CardContent>
</Card>
);
};

export default DosageSection;
130 changes: 130 additions & 0 deletions frontend/src/features/km/pharmacy/PharmacyForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { Fragment } from 'react';
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
Button,
Form,
} from '@freemed-kit/ui';
import PrescriptionReadonlySection from '@/features/km/diagnosis/PrescriptionReadonlySection';
import ConsultationReadonlySection from '@/features/km/diagnosis/ConsultationReadonlySection';
import PrescriptionSection from '@/features/km/pharmacy/PrescriptionSection';
import DosageSection from '@/features/km/pharmacy/DosageSection';
import usePharmacyForm from '@/features/km/pharmacy/usePharmacyForm';
import PharmacyStepper from '@/components/ui/PharmacyStepper';
import usePatient from '@/hooks/usePatient';

const PharmacyForm = () => {
const {
chart,
form,
prescriptionAction,
editingPrescriptionId,
prescriptionDialog,
isDialogOpen,
setIsDialogOpen,
handlePrevious,
handleNext,
handleAdd,
handleCancel,
handleEdit,
handleSave,
handleDelete,
} = usePharmacyForm();
const { patient } = usePatient();

return (
<>
<div className="flex gap-x-2">
<Button
variant="secondary"
disabled={(patient?.status ?? 0) < 4 || (patient?.status ?? 0) > 5}
onClick={handlePrevious}
>
이전 단계로
</Button>
<PharmacyStepper status={patient?.status} />
<Button
variant="destructive"
disabled={(patient?.status ?? 0) < 3 || (patient?.status ?? 0) > 5}
onClick={handleNext}
>
다음 단계로
</Button>
</div>
{(patient?.status ?? 0) === 3 ? (
<>
<Form {...form}>
<form className="space-y-4">
<PrescriptionSection
defaultValues={{
prescriptions: chart?.prescriptions || [],
treatmentNote: chart?.treatmentNote ?? '',
}}
editingPrescriptionId={editingPrescriptionId}
prescriptionAction={prescriptionAction}
handleEdit={handleEdit}
handleAdd={handleAdd}
handleCancel={handleCancel}
handleSave={handleSave}
handleDelete={handleDelete}
/>
<DosageSection prescriptions={chart?.prescriptions || []} />
<ConsultationReadonlySection
defaultValues={{
presentIllness: chart?.presentIllness ?? '',
impression: chart?.impression ?? '',
}}
/>
</form>
</Form>
</>
) : (
<>
<PrescriptionReadonlySection
defaultValues={{
prescriptions: chart?.prescriptions || [],
treatmentNote: '',
}}
showPharmacopoeia
/>
<DosageSection prescriptions={chart?.prescriptions || []} />
<ConsultationReadonlySection
defaultValues={{
presentIllness: chart?.presentIllness ?? '',
impression: chart?.impression ?? '',
}}
/>
</>
)}
<AlertDialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{prescriptionDialog.title}</AlertDialogTitle>
<AlertDialogDescription>
{prescriptionDialog.description.split('\n').map((line, index) => (
<Fragment key={index}>
{line}
<br />
</Fragment>
))}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>취소</AlertDialogCancel>
<AlertDialogAction onClick={prescriptionDialog.action}>
{prescriptionDialog.actionText}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
);
};

export default PharmacyForm;
Loading

0 comments on commit 8b6ebca

Please sign in to comment.