@snapdragonsnursery/react-components 1.19.7 → 1.19.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snapdragonsnursery/react-components",
3
- "version": "1.19.7",
3
+ "version": "1.19.9",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -57,6 +57,7 @@ const ChildSearchModal = ({
57
57
  const [advancedFilters, setAdvancedFilters] = useState({
58
58
  status: status || (activeOnly ? "active" : "all"),
59
59
  selectedSiteId: siteId || "",
60
+ selectedRoomId: "",
60
61
  dobFrom: dobFrom || "",
61
62
  dobTo: dobTo || "",
62
63
  ageFrom: ageFrom || "",
@@ -64,6 +65,7 @@ const ChildSearchModal = ({
64
65
  sortBy: sortBy,
65
66
  sortOrder: sortOrder,
66
67
  });
68
+ const [rooms, setRooms] = useState([]);
67
69
 
68
70
  // State for multi-select mode
69
71
  const initialSelectedChildren = useMemo(
@@ -209,6 +211,11 @@ const ChildSearchModal = ({
209
211
  params.append("active_only", "true");
210
212
  }
211
213
 
214
+ // Add room filter
215
+ if (advancedFilters.selectedRoomId) {
216
+ params.append("room_id", advancedFilters.selectedRoomId.toString());
217
+ }
218
+
212
219
  // Add date of birth filters
213
220
  if (advancedFilters.dobFrom) {
214
221
  params.append("dob_from", advancedFilters.dobFrom);
@@ -288,6 +295,31 @@ const ChildSearchModal = ({
288
295
  }
289
296
  }, [debouncedSearchTerm, pagination.page, isOpen, searchChildren]);
290
297
 
298
+ // Fetch rooms for selected site
299
+ useEffect(() => {
300
+ const fetchRooms = async () => {
301
+ if (!advancedFilters.selectedSiteId || !sites) return;
302
+
303
+ try {
304
+ // Find the selected site and extract its rooms
305
+ const selectedSite = sites.find(
306
+ (site) => site.site_id === parseInt(advancedFilters.selectedSiteId, 10)
307
+ );
308
+
309
+ if (selectedSite && selectedSite.rooms) {
310
+ setRooms(selectedSite.rooms);
311
+ } else {
312
+ setRooms([]);
313
+ }
314
+ } catch (err) {
315
+ console.error("Error fetching rooms:", err);
316
+ setRooms([]);
317
+ }
318
+ };
319
+
320
+ fetchRooms();
321
+ }, [advancedFilters.selectedSiteId, sites]);
322
+
291
323
  // Reset selection when modal opens (for multi-select mode)
292
324
  useEffect(() => {
293
325
  if (isOpen && multiSelect) {
@@ -618,6 +650,7 @@ const ChildSearchModal = ({
618
650
  setAdvancedFilters((prev) => ({
619
651
  ...prev,
620
652
  selectedSiteId: e.target.value,
653
+ selectedRoomId: "", // Reset room when site changes
621
654
  }))
622
655
  }
623
656
  className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm dark:bg-gray-600 dark:text-white"
@@ -632,6 +665,32 @@ const ChildSearchModal = ({
632
665
  </div>
633
666
  )}
634
667
 
668
+ {/* Room Filter */}
669
+ {advancedFilters.selectedSiteId && rooms && rooms.length > 0 && (
670
+ <div>
671
+ <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
672
+ Room
673
+ </label>
674
+ <select
675
+ value={advancedFilters.selectedRoomId}
676
+ onChange={(e) =>
677
+ setAdvancedFilters((prev) => ({
678
+ ...prev,
679
+ selectedRoomId: e.target.value,
680
+ }))
681
+ }
682
+ className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm dark:bg-gray-600 dark:text-white"
683
+ >
684
+ <option value="">All Rooms</option>
685
+ {rooms.map((room) => (
686
+ <option key={room.room_id} value={room.room_id}>
687
+ {room.room_name}
688
+ </option>
689
+ ))}
690
+ </select>
691
+ </div>
692
+ )}
693
+
635
694
  {/* Date of Birth Range */}
636
695
  <div>
637
696
  <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
@@ -756,6 +815,7 @@ const ChildSearchModal = ({
756
815
  setAdvancedFilters({
757
816
  status: activeOnly ? "active" : "all",
758
817
  selectedSiteId: "",
818
+ selectedRoomId: "",
759
819
  dobFrom: "",
760
820
  dobTo: "",
761
821
  ageFrom: "",
@@ -908,6 +968,14 @@ const ChildSearchModal = ({
908
968
  </div>
909
969
  <div className="mt-1 text-sm text-gray-600 dark:text-gray-300">
910
970
  <span>{child.site_name}</span>
971
+ {child.current_room_name && (
972
+ <>
973
+ <span className="mx-2">•</span>
974
+ <span className="font-medium">
975
+ {child.current_room_name}
976
+ </span>
977
+ </>
978
+ )}
911
979
  {child.date_of_birth && (
912
980
  <>
913
981
  <span className="mx-2">•</span>
@@ -82,6 +82,7 @@ const ChildSearchPage = ({
82
82
  const [advancedFilters, setAdvancedFilters] = useState({
83
83
  status: status || (activeOnly ? "active" : "all"),
84
84
  selectedSiteId: siteId || "",
85
+ selectedRoomId: "",
85
86
  dobFrom: dobFrom || "",
86
87
  dobTo: dobTo || "",
87
88
  ageFrom: ageFrom || "",
@@ -89,6 +90,7 @@ const ChildSearchPage = ({
89
90
  sortBy: sortBy,
90
91
  sortOrder: sortOrder,
91
92
  });
93
+ const [rooms, setRooms] = useState([]);
92
94
 
93
95
  // Table sorting state
94
96
  const [sorting, setSorting] = useState([]);
@@ -179,6 +181,15 @@ const ChildSearchPage = ({
179
181
  <span>{row.original.site_name}</span>
180
182
  ),
181
183
  }),
184
+ // Room column
185
+ columnHelper.accessor("current_room_name", {
186
+ header: "Room",
187
+ cell: ({ row }) => (
188
+ <span>
189
+ {row.original.current_room_name || "N/A"}
190
+ </span>
191
+ ),
192
+ }),
182
193
  // Date of Birth column - sortable
183
194
  columnHelper.accessor("date_of_birth", {
184
195
  header: createSortableHeader("date_of_birth", "Date of Birth"),
@@ -343,6 +354,11 @@ const ChildSearchPage = ({
343
354
  params.append("active_only", "true");
344
355
  }
345
356
 
357
+ // Add room filter
358
+ if (debouncedAdvancedFilters.selectedRoomId) {
359
+ params.append("room_id", debouncedAdvancedFilters.selectedRoomId.toString());
360
+ }
361
+
346
362
  // Add date of birth filters
347
363
  if (debouncedAdvancedFilters.dobFrom) {
348
364
  params.append("dob_from", debouncedAdvancedFilters.dobFrom);
@@ -468,6 +484,7 @@ const ChildSearchPage = ({
468
484
  const clearedFilters = {
469
485
  status: activeOnly ? "active" : "all",
470
486
  selectedSiteId: "",
487
+ selectedRoomId: "",
471
488
  dobFrom: "",
472
489
  dobTo: "",
473
490
  ageFrom: "",
@@ -26,12 +26,37 @@ const ChildSearchFilters = ({
26
26
  // Local state for filters that haven't been applied yet
27
27
  const [localFilters, setLocalFilters] = React.useState(filters);
28
28
  const [hasUnsavedChanges, setHasUnsavedChanges] = React.useState(false);
29
+ const [rooms, setRooms] = React.useState([]);
29
30
 
30
31
  // Update local filters when props change
31
32
  React.useEffect(() => {
32
33
  setLocalFilters(filters);
33
34
  setHasUnsavedChanges(false);
34
35
  }, [filters]);
36
+
37
+ // Fetch rooms for selected site
38
+ React.useEffect(() => {
39
+ if (!localFilters.selectedSiteId || !sites) {
40
+ setRooms([]);
41
+ return;
42
+ }
43
+
44
+ try {
45
+ // Find the selected site and extract its rooms
46
+ const selectedSite = sites.find(
47
+ (site) => site.site_id === parseInt(localFilters.selectedSiteId, 10)
48
+ );
49
+
50
+ if (selectedSite && selectedSite.rooms) {
51
+ setRooms(selectedSite.rooms);
52
+ } else {
53
+ setRooms([]);
54
+ }
55
+ } catch (err) {
56
+ console.error("Error fetching rooms:", err);
57
+ setRooms([]);
58
+ }
59
+ }, [localFilters.selectedSiteId, sites]);
35
60
  // Convert existing date strings to DateRangePicker format
36
61
  const getDateRange = () => {
37
62
  if (localFilters.dobFrom || localFilters.dobTo) {
@@ -146,7 +171,10 @@ const ChildSearchFilters = ({
146
171
  </label>
147
172
  <Select
148
173
  value={localFilters.selectedSiteId}
149
- onChange={(e) => handleFilterChange("selectedSiteId", e.target.value)}
174
+ onChange={(e) => {
175
+ handleFilterChange("selectedSiteId", e.target.value);
176
+ handleFilterChange("selectedRoomId", ""); // Reset room when site changes
177
+ }}
150
178
  className="bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-600 text-gray-900 dark:text-white"
151
179
  >
152
180
  <SelectOption value="">All Sites</SelectOption>
@@ -159,6 +187,27 @@ const ChildSearchFilters = ({
159
187
  </div>
160
188
  )}
161
189
 
190
+ {/* Room Filter */}
191
+ {localFilters.selectedSiteId && rooms && rooms.length > 0 && (
192
+ <div>
193
+ <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
194
+ Room
195
+ </label>
196
+ <Select
197
+ value={localFilters.selectedRoomId}
198
+ onChange={(e) => handleFilterChange("selectedRoomId", e.target.value)}
199
+ className="bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-600 text-gray-900 dark:text-white"
200
+ >
201
+ <SelectOption value="">All Rooms</SelectOption>
202
+ {rooms.map((room) => (
203
+ <SelectOption key={room.room_id} value={room.room_id}>
204
+ {room.room_name}
205
+ </SelectOption>
206
+ ))}
207
+ </Select>
208
+ </div>
209
+ )}
210
+
162
211
  {/* Date of Birth Range */}
163
212
  <div>
164
213
  <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
@@ -232,6 +232,7 @@ export const EmployeeSelect = ({
232
232
  </div>
233
233
  </div>
234
234
  <button
235
+ type="button"
235
236
  onClick={handleClear}
236
237
  className="ml-2 p-1 hover:bg-background rounded flex-shrink-0"
237
238
  aria-label="Clear selection"
@@ -37,6 +37,8 @@ export function DateRangePicker({
37
37
  // New: allow styling popover content and calendar for layout control
38
38
  contentClassName,
39
39
  calendarClassName,
40
+ // New: allow hiding the calendar icon
41
+ showIcon = true,
40
42
  ...props
41
43
  }) {
42
44
  const [isOpen, setIsOpen] = useState(false);
@@ -180,7 +182,7 @@ export function DateRangePicker({
180
182
  disabled={disabled}
181
183
  {...props}
182
184
  >
183
- <CalendarIcon className="mr-2 h-4 w-4" />
185
+ {showIcon && <CalendarIcon className="mr-2 h-4 w-4 shrink-0" />}
184
186
  {internalRange?.from ? (
185
187
  internalRange.to ? (
186
188
  <>
@@ -291,6 +293,8 @@ export function DatePicker({
291
293
  disabled,
292
294
  disableFuture = false,
293
295
  displayFormat = "PPP",
296
+ // New: allow hiding the calendar icon
297
+ showIcon = true,
294
298
  ...props
295
299
  }) {
296
300
  const [isOpen, setIsOpen] = useState(false);
@@ -313,7 +317,7 @@ export function DatePicker({
313
317
  disabled={disabled}
314
318
  {...props}
315
319
  >
316
- <CalendarIcon className="mr-2 h-4 w-4" />
320
+ {showIcon && <CalendarIcon className="mr-2 h-4 w-4 shrink-0" />}
317
321
  {selectedDate ? (
318
322
  format(selectedDate, displayFormat)
319
323
  ) : (