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