hey-pharmacist-ecommerce 1.1.12 → 1.1.13
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/dist/index.js +84 -115
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +85 -116
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/FilterChips.tsx +54 -80
- package/src/components/OrderCard.tsx +89 -56
- package/src/hooks/useOrders.ts +1 -0
- package/src/screens/OrdersScreen.tsx +91 -148
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import React, {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import React, { useMemo, useState } from 'react';
|
|
4
|
+
import { motion } from 'framer-motion';
|
|
5
|
+
import { ChevronLeft, ChevronRight, CreditCard, Filter, Package } from 'lucide-react';
|
|
6
6
|
import { OrderCard } from '@/components/OrderCard';
|
|
7
7
|
import { OrderCardSkeleton } from '@/components/ui/Skeleton';
|
|
8
8
|
import { EmptyState } from '@/components/EmptyState';
|
|
@@ -30,9 +30,6 @@ export function OrdersScreen() {
|
|
|
30
30
|
selectedFilter,
|
|
31
31
|
selectedPaymentFilter
|
|
32
32
|
);
|
|
33
|
-
const [isOverflowOpen, setIsOverflowOpen] = useState(false);
|
|
34
|
-
const [filterSearchTerm, setFilterSearchTerm] = useState('');
|
|
35
|
-
const overflowMenuRef = useRef<HTMLDivElement | null>(null);
|
|
36
33
|
|
|
37
34
|
const filteredOrders = useMemo(() => {
|
|
38
35
|
return orders.filter((order) => {
|
|
@@ -50,150 +47,96 @@ export function OrdersScreen() {
|
|
|
50
47
|
const hasOrders = filteredOrders.length > 0;
|
|
51
48
|
const MAX_VISIBLE_FILTERS = 4;
|
|
52
49
|
|
|
53
|
-
// Removed local overflow/search logic in favor of reusable FilterChips
|
|
54
|
-
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
if (!isOverflowOpen) {
|
|
57
|
-
setFilterSearchTerm('');
|
|
58
|
-
}
|
|
59
|
-
}, [isOverflowOpen]);
|
|
60
|
-
|
|
61
|
-
useEffect(() => {
|
|
62
|
-
function handleClickOutside(event: MouseEvent) {
|
|
63
|
-
if (overflowMenuRef.current && !overflowMenuRef.current.contains(event.target as Node)) {
|
|
64
|
-
setIsOverflowOpen(false);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (isOverflowOpen) {
|
|
69
|
-
document.addEventListener('mousedown', handleClickOutside);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return () => {
|
|
73
|
-
document.removeEventListener('mousedown', handleClickOutside);
|
|
74
|
-
};
|
|
75
|
-
}, [isOverflowOpen]);
|
|
76
|
-
|
|
77
50
|
return (
|
|
78
|
-
<div className="min-h-screen
|
|
79
|
-
<
|
|
80
|
-
<div
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
>
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
maxVisible={MAX_VISIBLE_FILTERS}
|
|
136
|
-
variant="primary"
|
|
137
|
-
/>
|
|
138
|
-
|
|
139
|
-
<FilterChips
|
|
140
|
-
label="Payment status"
|
|
141
|
-
icon={CreditCard}
|
|
142
|
-
filters={PAYMENT_FILTERS}
|
|
143
|
-
selected={selectedPaymentFilter}
|
|
144
|
-
onSelect={(value) => {
|
|
145
|
-
setSelectedPaymentFilter(value as any);
|
|
146
|
-
setPage(1);
|
|
147
|
-
}}
|
|
148
|
-
maxVisible={MAX_VISIBLE_FILTERS}
|
|
149
|
-
variant="primary"
|
|
150
|
-
/>
|
|
151
|
-
</div>
|
|
152
|
-
</div>
|
|
153
|
-
|
|
154
|
-
<div className="mt-6 space-y-4">
|
|
155
|
-
{isLoading ? (
|
|
156
|
-
Array.from({ length: 3 }).map((_, index) => <OrderCardSkeleton key={index} />)
|
|
157
|
-
) : hasOrders ? (
|
|
158
|
-
filteredOrders.map((order) => <OrderCard key={order.id} order={order} />)
|
|
159
|
-
) : (
|
|
160
|
-
<EmptyState
|
|
161
|
-
icon={Package}
|
|
162
|
-
title="No orders found for these filters"
|
|
163
|
-
description="Adjust the status or payment filters, or browse the shop for new essentials."
|
|
164
|
-
actionLabel="Shop products"
|
|
165
|
-
onAction={() => router.push(buildPath('/shop'))}
|
|
166
|
-
/>
|
|
167
|
-
)}
|
|
168
|
-
</div>
|
|
169
|
-
|
|
170
|
-
{!isLoading && pagination.totalPages > 1 && hasOrders && (
|
|
171
|
-
<div className="mt-10 flex flex-wrap items-center justify-center gap-4">
|
|
172
|
-
<Button
|
|
173
|
-
variant="outline"
|
|
174
|
-
onClick={() => setPage((current) => Math.max(1, current - 1))}
|
|
175
|
-
disabled={page === 1}
|
|
176
|
-
>
|
|
177
|
-
<ChevronLeft className="h-5 w-5" />
|
|
178
|
-
Previous
|
|
179
|
-
</Button>
|
|
180
|
-
<span className="text-sm font-semibold text-slate-600">
|
|
181
|
-
Page {page} of {pagination.totalPages}
|
|
182
|
-
</span>
|
|
183
|
-
<Button
|
|
184
|
-
variant="outline"
|
|
185
|
-
onClick={() =>
|
|
186
|
-
setPage((current) => Math.min(pagination.totalPages, current + 1))
|
|
187
|
-
}
|
|
188
|
-
disabled={page === pagination.totalPages}
|
|
189
|
-
>
|
|
190
|
-
Next
|
|
191
|
-
<ChevronRight className="h-5 w-5" />
|
|
192
|
-
</Button>
|
|
193
|
-
</div>
|
|
51
|
+
<div className="min-h-screen bg-white">
|
|
52
|
+
<div className="container mx-auto px-4 py-8 max-w-6xl">
|
|
53
|
+
<motion.div
|
|
54
|
+
initial={{ opacity: 0, y: 24 }}
|
|
55
|
+
animate={{ opacity: 1, y: 0 }}
|
|
56
|
+
className="space-y-6"
|
|
57
|
+
>
|
|
58
|
+
<div className="mb-6">
|
|
59
|
+
<h1 className="text-2xl font-bold text-slate-900">Orders</h1>
|
|
60
|
+
<p className="text-sm text-gray-500 mt-1">
|
|
61
|
+
{filteredOrders.length} {filteredOrders.length === 1 ? 'order' : 'orders'}
|
|
62
|
+
</p>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
{/* Filters */}
|
|
66
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
67
|
+
<FilterChips
|
|
68
|
+
label="Order Status"
|
|
69
|
+
icon={Filter}
|
|
70
|
+
filters={STATUS_FILTERS}
|
|
71
|
+
selected={selectedFilter}
|
|
72
|
+
onSelect={(value) => {
|
|
73
|
+
setSelectedFilter(value as any);
|
|
74
|
+
setPage(1);
|
|
75
|
+
}}
|
|
76
|
+
maxVisible={MAX_VISIBLE_FILTERS}
|
|
77
|
+
variant="primary"
|
|
78
|
+
/>
|
|
79
|
+
|
|
80
|
+
<FilterChips
|
|
81
|
+
label="Payment Status"
|
|
82
|
+
icon={CreditCard}
|
|
83
|
+
filters={PAYMENT_FILTERS}
|
|
84
|
+
selected={selectedPaymentFilter}
|
|
85
|
+
onSelect={(value) => {
|
|
86
|
+
setSelectedPaymentFilter(value as any);
|
|
87
|
+
setPage(1);
|
|
88
|
+
}}
|
|
89
|
+
maxVisible={MAX_VISIBLE_FILTERS}
|
|
90
|
+
variant="primary"
|
|
91
|
+
/>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
{/* Orders List */}
|
|
95
|
+
<div className="space-y-4">
|
|
96
|
+
{isLoading ? (
|
|
97
|
+
Array.from({ length: 3 }).map((_, index) => <OrderCardSkeleton key={index} />)
|
|
98
|
+
) : hasOrders ? (
|
|
99
|
+
filteredOrders.map((order) => <OrderCard key={order.id} order={order} />)
|
|
100
|
+
) : (
|
|
101
|
+
<EmptyState
|
|
102
|
+
icon={Package}
|
|
103
|
+
title="No orders found for these filters"
|
|
104
|
+
description="Adjust the status or payment filters, or browse the shop for new essentials."
|
|
105
|
+
actionLabel="Shop products"
|
|
106
|
+
onAction={() => router.push(buildPath('/shop'))}
|
|
107
|
+
/>
|
|
194
108
|
)}
|
|
195
|
-
</
|
|
196
|
-
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
{/* Pagination */}
|
|
112
|
+
{!isLoading && pagination.totalPages > 1 && hasOrders && (
|
|
113
|
+
<div className="mt-8 flex flex-wrap items-center justify-center gap-4 pt-6 border-t border-gray-200">
|
|
114
|
+
<Button
|
|
115
|
+
variant="outline"
|
|
116
|
+
onClick={() => setPage((current) => Math.max(1, current - 1))}
|
|
117
|
+
disabled={page === 1}
|
|
118
|
+
className="rounded-full border-2 border-slate-200 bg-white px-4 py-2 text-sm font-medium text-slate-700 hover:bg-gray-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
|
119
|
+
>
|
|
120
|
+
<ChevronLeft className="h-4 w-4 mr-2" />
|
|
121
|
+
Previous
|
|
122
|
+
</Button>
|
|
123
|
+
<span className="text-sm font-medium text-slate-600">
|
|
124
|
+
Page {page} of {pagination.totalPages}
|
|
125
|
+
</span>
|
|
126
|
+
<Button
|
|
127
|
+
variant="outline"
|
|
128
|
+
onClick={() =>
|
|
129
|
+
setPage((current) => Math.min(pagination.totalPages, current + 1))
|
|
130
|
+
}
|
|
131
|
+
disabled={page === pagination.totalPages}
|
|
132
|
+
className="rounded-full border-2 border-slate-200 bg-white px-4 py-2 text-sm font-medium text-slate-700 hover:bg-gray-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
|
133
|
+
>
|
|
134
|
+
Next
|
|
135
|
+
<ChevronRight className="h-4 w-4 ml-2" />
|
|
136
|
+
</Button>
|
|
137
|
+
</div>
|
|
138
|
+
)}
|
|
139
|
+
</motion.div>
|
|
197
140
|
</div>
|
|
198
141
|
</div>
|
|
199
142
|
);
|