source: frontend/src/components/ExistingTherapyList.tsx@ 700e2f9

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

Init

  • Property mode set to 100644
File size: 7.1 KB
RevLine 
[700e2f9]1import { type Component, createSignal, For, Show } from "solid-js";
2import { formatDate } from "@/utils";
3import {
4 type Therapy,
5 therapyApi,
6 type UpdateTherapyRequest,
7} from "@/api/therapy";
8
9interface ExistingTherapyListProps {
10 consultationId: number;
11 therapies: Therapy[];
12 onTherapiesChange: (therapies: Therapy[]) => void;
13 readOnly?: boolean;
14}
15
16const ExistingTherapyList: Component<ExistingTherapyListProps> = (props) => {
17 const [editingId, setEditingId] = createSignal<number | null>(null);
18 const [formData, setFormData] = createSignal({
19 name: "",
20 dose: "",
21 expDate: "",
22 });
23
24 const startEditing = (therapy: Therapy) => {
25 setFormData({
26 name: therapy.name,
27 dose: therapy.dose,
28 expDate: therapy.expDate,
29 });
30 setEditingId(therapy.idTherapy);
31 };
32
33 const cancelEdit = () => {
34 setEditingId(null);
35 setFormData({ name: "", dose: "", expDate: "" });
36 };
37
38 const handleUpdate = async () => {
39 const data = formData();
40
41 if (!data.name.trim() || !data.dose.trim() || !data.expDate) {
42 alert("Please fill in all therapy fields");
43 return;
44 }
45
46 try {
47 const updateData: UpdateTherapyRequest = {
48 name: data.name,
49 dose: data.dose,
50 expDate: data.expDate,
51 };
52 await therapyApi.updateTherapy(editingId()!, updateData);
53
54 const updated = props.therapies.map((t) =>
55 t.idTherapy === editingId()
56 ? { ...t, name: data.name, dose: data.dose, expDate: data.expDate }
57 : t,
58 );
59 props.onTherapiesChange(updated);
60 cancelEdit();
61 } catch (error: any) {
62 alert(error.message || "Failed to update therapy");
63 }
64 };
65
66 const handleDelete = async (therapyId: number) => {
67 if (!confirm("Are you sure you want to delete this therapy?")) return;
68
69 try {
70 await therapyApi.deleteTherapy(therapyId);
71
72 const filtered = props.therapies.filter((t) => t.idTherapy !== therapyId);
73 props.onTherapiesChange(filtered);
74 } catch (error: any) {
75 alert(error.message || "Failed to delete therapy");
76 }
77 };
78
79 return (
80 <Show
81 when={props.therapies.length > 0}
82 fallback={
83 <p class="text-sm text-gray-500 italic">No existing therapies.</p>
84 }
85 >
86 <div class="space-y-2">
87 <For each={props.therapies}>
88 {(therapy) => (
89 <Show
90 when={editingId() === therapy.idTherapy}
91 fallback={
92 <div class="p-3 bg-blue-50 border border-blue-200 rounded-lg hover:shadow-sm transition">
93 <div class="flex justify-between items-start">
94 <div class="flex-1">
95 <h4 class="font-semibold text-gray-900">
96 {therapy.name}
97 </h4>
98 <div class="text-sm text-gray-600 mt-1">
99 <span class="font-medium">Dose:</span> {therapy.dose}
100 </div>
101 <div class="text-xs text-gray-500 mt-1">
102 <span class="font-medium">Expires:</span>{" "}
103 {formatDate(therapy.expDate)}
104 </div>
105 </div>
106 <Show when={!props.readOnly}>
107 <div class="flex space-x-2 ml-4">
108 <button
109 type="button"
110 onClick={() => startEditing(therapy)}
111 class="text-xs text-blue-600 hover:text-blue-800 cursor-pointer"
112 >
113 Edit
114 </button>
115 <button
116 type="button"
117 onClick={() => handleDelete(therapy.idTherapy)}
118 class="text-xs text-red-600 hover:text-red-800 cursor-pointer"
119 >
120 Delete
121 </button>
122 </div>
123 </Show>
124 </div>
125 </div>
126 }
127 >
128 <div class="p-4 bg-blue-50 border-2 border-blue-400 rounded-lg">
129 <div class="grid grid-cols-2 gap-3 mb-3">
130 <div>
131 <label class="block text-xs font-medium text-gray-700 mb-1">
132 Name
133 </label>
134 <input
135 type="text"
136 class="w-full px-2 py-1 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent"
137 value={formData().name}
138 onChange={(e) =>
139 setFormData({
140 ...formData(),
141 name: e.currentTarget.value,
142 })
143 }
144 required
145 />
146 </div>
147 <div>
148 <label class="block text-xs font-medium text-gray-700 mb-1">
149 Dose
150 </label>
151 <input
152 type="text"
153 class="w-full px-2 py-1 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent"
154 value={formData().dose}
155 onChange={(e) =>
156 setFormData({
157 ...formData(),
158 dose: e.currentTarget.value,
159 })
160 }
161 required
162 />
163 </div>
164 </div>
165 <div class="mb-3">
166 <label class="block text-xs font-medium text-gray-700 mb-1">
167 Expiration Date
168 </label>
169 <input
170 type="date"
171 class="w-full px-2 py-1 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent"
172 value={formData().expDate}
173 onChange={(e) =>
174 setFormData({
175 ...formData(),
176 expDate: e.currentTarget.value,
177 })
178 }
179 required
180 />
181 </div>
182 <div class="flex justify-end space-x-2">
183 <button
184 type="button"
185 onClick={cancelEdit}
186 class="px-3 py-1 text-sm border border-gray-300 rounded text-gray-700 hover:bg-gray-50 transition cursor-pointer"
187 >
188 Cancel
189 </button>
190 <button
191 type="button"
192 onClick={handleUpdate}
193 class="px-3 py-1 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 transition cursor-pointer"
194 >
195 Update
196 </button>
197 </div>
198 </div>
199 </Show>
200 )}
201 </For>
202 </div>
203 </Show>
204 );
205};
206
207export default ExistingTherapyList;
Note: See TracBrowser for help on using the repository browser.