@snapdragonsnursery/react-components 1.1.10 → 1.1.12
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
package/src/ChildSearchPage.jsx
CHANGED
|
@@ -32,17 +32,16 @@ import {
|
|
|
32
32
|
PaginationPrevious,
|
|
33
33
|
} from "./components/ui/pagination";
|
|
34
34
|
import {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
} from "lucide-react";
|
|
35
|
+
MagnifyingGlassIcon,
|
|
36
|
+
FunnelIcon,
|
|
37
|
+
ChevronDownIcon,
|
|
38
|
+
ChevronUpIcon,
|
|
39
|
+
UserIcon,
|
|
40
|
+
MapPinIcon,
|
|
41
|
+
CalendarIcon,
|
|
42
|
+
CheckCircleIcon,
|
|
43
|
+
XCircleIcon,
|
|
44
|
+
} from "@heroicons/react/24/outline";
|
|
46
45
|
import { cn } from "./lib/utils";
|
|
47
46
|
|
|
48
47
|
const ChildSearchPage = ({
|
|
@@ -132,7 +131,7 @@ const ChildSearchPage = ({
|
|
|
132
131
|
header: "Name",
|
|
133
132
|
cell: ({ row }) => (
|
|
134
133
|
<div className="flex items-center space-x-2">
|
|
135
|
-
<
|
|
134
|
+
<UserIcon className="h-4 w-4 text-gray-400" />
|
|
136
135
|
<div>
|
|
137
136
|
<div className="font-medium">{row.original.full_name}</div>
|
|
138
137
|
<div className="text-sm text-gray-500">
|
|
@@ -147,7 +146,7 @@ const ChildSearchPage = ({
|
|
|
147
146
|
header: "Site",
|
|
148
147
|
cell: ({ row }) => (
|
|
149
148
|
<div className="flex items-center space-x-2">
|
|
150
|
-
<
|
|
149
|
+
<MapPinIcon className="h-4 w-4 text-gray-400" />
|
|
151
150
|
<span>{row.original.site_name}</span>
|
|
152
151
|
</div>
|
|
153
152
|
),
|
|
@@ -157,7 +156,7 @@ const ChildSearchPage = ({
|
|
|
157
156
|
header: "Date of Birth",
|
|
158
157
|
cell: ({ row }) => (
|
|
159
158
|
<div className="flex items-center space-x-2">
|
|
160
|
-
<
|
|
159
|
+
<CalendarIcon className="h-4 w-4 text-gray-400" />
|
|
161
160
|
<span>
|
|
162
161
|
{row.original.date_of_birth
|
|
163
162
|
? new Date(row.original.date_of_birth).toLocaleDateString("en-GB")
|
|
@@ -177,7 +176,7 @@ const ChildSearchPage = ({
|
|
|
177
176
|
: "N/A";
|
|
178
177
|
return (
|
|
179
178
|
<div className="flex items-center space-x-2">
|
|
180
|
-
<
|
|
179
|
+
<span className="text-gray-400 font-mono">#</span>
|
|
181
180
|
<span>{ageText}</span>
|
|
182
181
|
</div>
|
|
183
182
|
);
|
|
@@ -189,9 +188,9 @@ const ChildSearchPage = ({
|
|
|
189
188
|
cell: ({ row }) => (
|
|
190
189
|
<div className="flex items-center space-x-2">
|
|
191
190
|
{row.original.is_active ? (
|
|
192
|
-
<
|
|
191
|
+
<CheckCircleIcon className="h-4 w-4 text-green-500" />
|
|
193
192
|
) : (
|
|
194
|
-
<
|
|
193
|
+
<XCircleIcon className="h-4 w-4 text-red-500" />
|
|
195
194
|
)}
|
|
196
195
|
<span
|
|
197
196
|
className={cn(
|
|
@@ -357,6 +356,13 @@ const ChildSearchPage = ({
|
|
|
357
356
|
searchChildren();
|
|
358
357
|
}, [debouncedSearchTerm, pagination.page, searchChildren]);
|
|
359
358
|
|
|
359
|
+
// Initial search on component mount
|
|
360
|
+
useEffect(() => {
|
|
361
|
+
if (instance && accounts[0]) {
|
|
362
|
+
searchChildren();
|
|
363
|
+
}
|
|
364
|
+
}, [instance, accounts, searchChildren]);
|
|
365
|
+
|
|
360
366
|
const handlePageChange = (newPage) => {
|
|
361
367
|
setPagination((prev) => ({ ...prev, page: newPage }));
|
|
362
368
|
};
|
|
@@ -401,6 +407,10 @@ const ChildSearchPage = ({
|
|
|
401
407
|
});
|
|
402
408
|
};
|
|
403
409
|
|
|
410
|
+
// Calculate pagination display values
|
|
411
|
+
const startItem = pagination.totalCount > 0 ? (pagination.page - 1) * pagination.pageSize + 1 : 0;
|
|
412
|
+
const endItem = Math.min(pagination.page * pagination.pageSize, pagination.totalCount);
|
|
413
|
+
|
|
404
414
|
return (
|
|
405
415
|
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
|
|
406
416
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
@@ -424,7 +434,7 @@ const ChildSearchPage = ({
|
|
|
424
434
|
<div className="p-6">
|
|
425
435
|
{/* Search Input */}
|
|
426
436
|
<div className="relative mb-4">
|
|
427
|
-
<
|
|
437
|
+
<MagnifyingGlassIcon className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
|
|
428
438
|
<Input
|
|
429
439
|
type="text"
|
|
430
440
|
placeholder="Search by name or child ID..."
|
|
@@ -440,12 +450,12 @@ const ChildSearchPage = ({
|
|
|
440
450
|
onClick={() => setIsAdvancedFiltersOpen(!isAdvancedFiltersOpen)}
|
|
441
451
|
className="flex items-center space-x-2 text-sm text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300"
|
|
442
452
|
>
|
|
443
|
-
<
|
|
453
|
+
<FunnelIcon className="h-4 w-4" />
|
|
444
454
|
<span>Advanced Filters</span>
|
|
445
455
|
{isAdvancedFiltersOpen ? (
|
|
446
|
-
<
|
|
456
|
+
<ChevronUpIcon className="h-4 w-4" />
|
|
447
457
|
) : (
|
|
448
|
-
<
|
|
458
|
+
<ChevronDownIcon className="h-4 w-4" />
|
|
449
459
|
)}
|
|
450
460
|
</button>
|
|
451
461
|
<button
|
|
@@ -646,14 +656,9 @@ const ChildSearchPage = ({
|
|
|
646
656
|
<div className="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
|
|
647
657
|
<div className="flex items-center justify-between">
|
|
648
658
|
<div className="text-sm text-gray-600 dark:text-gray-400">
|
|
649
|
-
{
|
|
659
|
+
{pagination.totalCount === 0
|
|
650
660
|
? "No children found"
|
|
651
|
-
: `Showing ${
|
|
652
|
-
(pagination.page - 1) * pagination.pageSize + 1
|
|
653
|
-
} to ${Math.min(
|
|
654
|
-
pagination.page * pagination.pageSize,
|
|
655
|
-
pagination.totalCount
|
|
656
|
-
)} of ${pagination.totalCount} children`}
|
|
661
|
+
: `Showing ${startItem} to ${endItem} of ${pagination.totalCount} children`}
|
|
657
662
|
</div>
|
|
658
663
|
</div>
|
|
659
664
|
</div>
|
|
@@ -721,75 +726,88 @@ const ChildSearchPage = ({
|
|
|
721
726
|
)}
|
|
722
727
|
|
|
723
728
|
{/* Pagination */}
|
|
724
|
-
{pagination.
|
|
729
|
+
{pagination.totalCount > 0 && (
|
|
725
730
|
<div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700">
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
731
|
+
{/* Pagination Info */}
|
|
732
|
+
<div className="flex items-center justify-between mb-4">
|
|
733
|
+
<div className="text-sm text-gray-600 dark:text-gray-400">
|
|
734
|
+
Page {pagination.page} of {pagination.totalPages}
|
|
735
|
+
</div>
|
|
736
|
+
<div className="text-sm text-gray-600 dark:text-gray-400">
|
|
737
|
+
{pagination.totalCount} total children
|
|
738
|
+
</div>
|
|
739
|
+
</div>
|
|
740
|
+
|
|
741
|
+
{/* Pagination Controls */}
|
|
742
|
+
{pagination.totalPages > 1 && (
|
|
743
|
+
<Pagination>
|
|
744
|
+
<PaginationContent>
|
|
745
|
+
<PaginationItem>
|
|
746
|
+
<PaginationPrevious
|
|
747
|
+
onClick={() => handlePageChange(pagination.page - 1)}
|
|
748
|
+
className={cn(
|
|
749
|
+
!pagination.hasPreviousPage &&
|
|
750
|
+
"pointer-events-none opacity-50"
|
|
751
|
+
)}
|
|
752
|
+
/>
|
|
753
|
+
</PaginationItem>
|
|
754
|
+
|
|
755
|
+
{/* Page numbers */}
|
|
756
|
+
{Array.from(
|
|
757
|
+
{ length: pagination.totalPages },
|
|
758
|
+
(_, i) => i + 1
|
|
759
|
+
)
|
|
760
|
+
.filter((page) => {
|
|
761
|
+
const current = pagination.page;
|
|
762
|
+
const total = pagination.totalPages;
|
|
754
763
|
return (
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
</PaginationItem>
|
|
759
|
-
<PaginationItem>
|
|
760
|
-
<PaginationLink
|
|
761
|
-
onClick={() => handlePageChange(page)}
|
|
762
|
-
isActive={page === pagination.page}
|
|
763
|
-
>
|
|
764
|
-
{page}
|
|
765
|
-
</PaginationLink>
|
|
766
|
-
</PaginationItem>
|
|
767
|
-
</React.Fragment>
|
|
764
|
+
page === 1 ||
|
|
765
|
+
page === total ||
|
|
766
|
+
(page >= current - 1 && page <= current + 1)
|
|
768
767
|
);
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
768
|
+
})
|
|
769
|
+
.map((page, index, array) => {
|
|
770
|
+
if (index > 0 && array[index - 1] !== page - 1) {
|
|
771
|
+
return (
|
|
772
|
+
<React.Fragment key={`ellipsis-${page}`}>
|
|
773
|
+
<PaginationItem>
|
|
774
|
+
<PaginationEllipsis />
|
|
775
|
+
</PaginationItem>
|
|
776
|
+
<PaginationItem>
|
|
777
|
+
<PaginationLink
|
|
778
|
+
onClick={() => handlePageChange(page)}
|
|
779
|
+
isActive={page === pagination.page}
|
|
780
|
+
>
|
|
781
|
+
{page}
|
|
782
|
+
</PaginationLink>
|
|
783
|
+
</PaginationItem>
|
|
784
|
+
</React.Fragment>
|
|
785
|
+
);
|
|
786
|
+
}
|
|
787
|
+
return (
|
|
788
|
+
<PaginationItem key={page}>
|
|
789
|
+
<PaginationLink
|
|
790
|
+
onClick={() => handlePageChange(page)}
|
|
791
|
+
isActive={page === pagination.page}
|
|
792
|
+
>
|
|
793
|
+
{page}
|
|
794
|
+
</PaginationLink>
|
|
795
|
+
</PaginationItem>
|
|
796
|
+
);
|
|
797
|
+
})}
|
|
798
|
+
|
|
799
|
+
<PaginationItem>
|
|
800
|
+
<PaginationNext
|
|
801
|
+
onClick={() => handlePageChange(pagination.page + 1)}
|
|
802
|
+
className={cn(
|
|
803
|
+
!pagination.hasNextPage &&
|
|
804
|
+
"pointer-events-none opacity-50"
|
|
805
|
+
)}
|
|
806
|
+
/>
|
|
807
|
+
</PaginationItem>
|
|
808
|
+
</PaginationContent>
|
|
809
|
+
</Pagination>
|
|
810
|
+
)}
|
|
793
811
|
</div>
|
|
794
812
|
)}
|
|
795
813
|
</>
|
|
@@ -39,7 +39,7 @@ const Button = React.forwardRef(
|
|
|
39
39
|
const Comp = asChild ? "span" : "button";
|
|
40
40
|
return (
|
|
41
41
|
<Comp
|
|
42
|
-
className={cn(buttonVariants({ variant, size, className }))}
|
|
42
|
+
className={cn(buttonVariants({ variant, size, className }), "cursor-pointer")}
|
|
43
43
|
ref={ref}
|
|
44
44
|
{...props}
|
|
45
45
|
/>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { cn } from "../../lib/utils";
|
|
6
6
|
import { Button } from "./button";
|
|
7
|
-
import {
|
|
7
|
+
import { ChevronLeftIcon, ChevronRightIcon, EllipsisHorizontalIcon } from "@heroicons/react/24/outline";
|
|
8
8
|
|
|
9
9
|
const Pagination = ({ className, ...props }) => (
|
|
10
10
|
<nav
|
|
@@ -37,7 +37,7 @@ const PaginationLink = React.forwardRef(
|
|
|
37
37
|
variant={isActive ? "outline" : "ghost"}
|
|
38
38
|
size={size}
|
|
39
39
|
ref={ref}
|
|
40
|
-
className={cn("", className)}
|
|
40
|
+
className={cn("cursor-pointer", className)}
|
|
41
41
|
{...props}
|
|
42
42
|
/>
|
|
43
43
|
)
|
|
@@ -52,7 +52,7 @@ const PaginationPrevious = React.forwardRef(({ className, ...props }, ref) => (
|
|
|
52
52
|
className={cn("gap-1 pl-2.5", className)}
|
|
53
53
|
{...props}
|
|
54
54
|
>
|
|
55
|
-
<
|
|
55
|
+
<ChevronLeftIcon className="h-4 w-4" />
|
|
56
56
|
<span>Previous</span>
|
|
57
57
|
</PaginationLink>
|
|
58
58
|
));
|
|
@@ -67,7 +67,7 @@ const PaginationNext = React.forwardRef(({ className, ...props }, ref) => (
|
|
|
67
67
|
{...props}
|
|
68
68
|
>
|
|
69
69
|
<span>Next</span>
|
|
70
|
-
<
|
|
70
|
+
<ChevronRightIcon className="h-4 w-4" />
|
|
71
71
|
</PaginationLink>
|
|
72
72
|
));
|
|
73
73
|
PaginationNext.displayName = "PaginationNext";
|
|
@@ -78,7 +78,7 @@ const PaginationEllipsis = ({ className, ...props }) => (
|
|
|
78
78
|
className={cn("flex h-9 w-9 items-center justify-center", className)}
|
|
79
79
|
{...props}
|
|
80
80
|
>
|
|
81
|
-
<
|
|
81
|
+
<EllipsisHorizontalIcon className="h-4 w-4" />
|
|
82
82
|
<span className="sr-only">More pages</span>
|
|
83
83
|
</span>
|
|
84
84
|
);
|