source: frontend/src/components/ConsultationModal.tsx

main
Last change on this file was 700e2f9, checked in by 186079 <matej.milevski@…>, 5 days ago

Init

  • Property mode set to 100644
File size: 8.5 KB
Line 
1import { type Component, For, Show } from "solid-js";
2import TherapyList from "@/components/TherapyList";
3import ExistingTherapyList from "@/components/ExistingTherapyList";
4import type { Consultation } from "@/api/consultation";
5import type { Patient } from "@/api/patient";
6import type { Therapy } from "@/api/therapy";
7
8interface ConsultationFormData {
9 patientId: number;
10 date: string;
11 price: number;
12 advice: string;
13 dateOfPayment: string | null;
14}
15
16interface ConsultationModalProps {
17 editingConsultation: Consultation | null;
18 formData: ConsultationFormData;
19 patients: Patient[];
20 newTherapies: Therapy[];
21 existingTherapies: Therapy[];
22 onClose: () => void;
23 onSubmit: (e: Event) => void;
24 onFormChange: (data: ConsultationFormData) => void;
25 onNewTherapiesChange: (therapies: Therapy[]) => void;
26 onExistingTherapiesChange: (therapies: Therapy[]) => void;
27 readOnly?: boolean;
28}
29
30const ConsultationModal: Component<ConsultationModalProps> = (props) => (
31 <div
32 class="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
33 onClick={props.onClose}
34 >
35 <div
36 class="bg-white rounded-lg p-6 w-full max-w-2xl max-h-[90vh] overflow-y-auto"
37 onClick={(e) => e.stopPropagation()}
38 >
39 <h2 class="text-2xl font-bold mb-4">
40 {props.readOnly
41 ? "Consultation Details"
42 : props.editingConsultation
43 ? "Edit Consultation"
44 : "Log New Consultation"}
45 </h2>
46
47 <form onSubmit={props.onSubmit}>
48 <div class="space-y-4">
49 <Show when={!props.editingConsultation}>
50 <div>
51 <label class="block text-sm font-medium text-gray-700 mb-1">
52 Patient
53 </label>
54 <select
55 class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
56 value={props.formData.patientId}
57 onChange={(e) =>
58 props.onFormChange({
59 ...props.formData,
60 patientId: Number.parseInt(e.currentTarget.value),
61 })
62 }
63 required
64 disabled={props.readOnly}
65 >
66 <For each={props.patients}>
67 {(patient) => (
68 <option value={patient.userId}>
69 {patient.firstName} {patient.lastName}
70 </option>
71 )}
72 </For>
73 </select>
74 </div>
75 </Show>
76
77 <div>
78 <label class="block text-sm font-medium text-gray-700 mb-1">
79 Consultation Date
80 </label>
81 <input
82 type="date"
83 class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
84 value={props.formData.date}
85 onChange={(e) =>
86 props.onFormChange({
87 ...props.formData,
88 date: e.currentTarget.value,
89 })
90 }
91 required
92 disabled={props.readOnly}
93 />
94 </div>
95
96 <div>
97 <label class="block text-sm font-medium text-gray-700 mb-1">
98 Price
99 </label>
100 <input
101 type="number"
102 step="0.01"
103 min="0"
104 class={`w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent ${props.readOnly ? "[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none" : ""}`}
105 value={props.formData.price}
106 onChange={(e) =>
107 props.onFormChange({
108 ...props.formData,
109 price: Number.parseFloat(e.currentTarget.value),
110 })
111 }
112 required
113 disabled={props.readOnly}
114 />
115 </div>
116
117 <div>
118 <label class="block text-sm font-medium text-gray-700 mb-1">
119 Advice / Notes
120 </label>
121 <textarea
122 class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
123 rows="4"
124 value={props.formData.advice}
125 onChange={(e) =>
126 props.onFormChange({
127 ...props.formData,
128 advice: e.currentTarget.value,
129 })
130 }
131 placeholder="Enter any advice or notes from the consultation..."
132 disabled={props.readOnly}
133 />
134 </div>
135
136 <Show when={!props.readOnly}>
137 <div>
138 <label class="flex items-center space-x-2 cursor-pointer">
139 <input
140 type="checkbox"
141 class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500 cursor-pointer"
142 checked={props.formData.dateOfPayment !== null}
143 onChange={(e) => {
144 if (e.currentTarget.checked) {
145 props.onFormChange({
146 ...props.formData,
147 dateOfPayment: new Date().toISOString().split("T")[0],
148 });
149 } else {
150 props.onFormChange({
151 ...props.formData,
152 dateOfPayment: null,
153 });
154 }
155 }}
156 />
157 <span class="text-sm font-medium text-gray-700">
158 Mark as paid
159 </span>
160 </label>
161 </div>
162 </Show>
163
164 <Show when={props.formData.dateOfPayment !== null && !props.readOnly}>
165 <div>
166 <label class="block text-sm font-medium text-gray-700 mb-1">
167 Payment Date
168 </label>
169 <input
170 type="date"
171 class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
172 value={props.formData.dateOfPayment || ""}
173 onChange={(e) =>
174 props.onFormChange({
175 ...props.formData,
176 dateOfPayment: e.currentTarget.value,
177 })
178 }
179 disabled={props.readOnly}
180 />
181 </div>
182 </Show>
183 </div>
184
185 <Show when={props.editingConsultation}>
186 <div class="mt-6">
187 <h3 class="text-lg font-semibold text-gray-900 mb-3">
188 {props.readOnly ? "Prescribed Therapies" : "Existing Therapies"}
189 </h3>
190 <ExistingTherapyList
191 consultationId={props.editingConsultation!.idConsultation}
192 therapies={props.existingTherapies}
193 onTherapiesChange={props.onExistingTherapiesChange}
194 readOnly={props.readOnly}
195 />
196 </div>
197 </Show>
198
199 <Show when={!props.readOnly}>
200 <div class="mt-6">
201 <h3 class="text-lg font-semibold text-gray-900 mb-3">
202 <Show when={props.editingConsultation} fallback={<>Therapies</>}>
203 New Therapies to Add
204 </Show>
205 </h3>
206 <TherapyList
207 therapies={props.newTherapies}
208 onPendingTherapiesChange={props.onNewTherapiesChange}
209 readOnly={props.readOnly}
210 />
211 </div>
212 </Show>
213
214 <div class="mt-6 flex justify-end space-x-3">
215 <Show
216 when={!props.readOnly}
217 fallback={
218 <button
219 type="button"
220 onClick={props.onClose}
221 class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition cursor-pointer"
222 >
223 Close
224 </button>
225 }
226 >
227 <button
228 type="button"
229 onClick={props.onClose}
230 class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 transition cursor-pointer"
231 >
232 Cancel
233 </button>
234 <button
235 type="submit"
236 class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition cursor-pointer"
237 >
238 {props.editingConsultation ? "Update" : "Create"}
239 </button>
240 </Show>
241 </div>
242 </form>
243 </div>
244 </div>
245);
246
247export default ConsultationModal;
Note: See TracBrowser for help on using the repository browser.