hey-pharmacist-ecommerce 1.1.11 → 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.
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
 
3
- import React, { useEffect, useMemo, useRef, useState } from 'react';
4
- import { AnimatePresence, motion } from 'framer-motion';
5
- import { CalendarDays, ChevronLeft, ChevronRight, CreditCard, Filter, Package, Sparkles } from 'lucide-react';
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 bg-slate-50">
79
- <section className="relative overflow-hidden bg-gradient-to-br from-[rgb(var(--header-from))] via-[rgb(var(--header-via))] to-[rgb(var(--header-to))] text-white mb-8">
80
- <div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,_rgba(255,255,255,0.35),_transparent_60%)]" />
81
- <div className="relative container mx-auto px-4 py-16">
82
- <motion.div
83
- initial={{ opacity: 0, y: 24 }}
84
- animate={{ opacity: 1, y: 0 }}
85
- className="space-y-6"
86
- >
87
- <span className="inline-flex items-center gap-2 rounded-full bg-white/15 px-3 py-1 text-sm font-semibold uppercase tracking-[0.35em] text-white/70 backdrop-blur">
88
- <CalendarDays className="h-4 w-4" />
89
- Order history
90
- </span>
91
- <div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
92
- <div className="space-y-4">
93
- <h1 className="text-4xl font-bold md:text-5xl">All of your pharmacy orders</h1>
94
- <p className="max-w-2xl text-white/80 md:text-lg">
95
- Access receipts, shipping statuses, and reorder suggestions in one organized
96
- timeline curated by our pharmacists.
97
- </p>
98
- </div>
99
- <div className="rounded-3xl bg-white/15 p-6 backdrop-blur">
100
- <p className="text-sm font-semibold uppercase tracking-[0.35em] text-white/70">
101
- Quick tip
102
- </p>
103
- <p className="mt-3 text-sm text-white/80">
104
- Use filters to review previous prescriptions, reorder favorites, or download
105
- invoices for insurance claims.
106
- </p>
107
- </div>
108
- </div>
109
- </motion.div>
110
- </div>
111
- </section>
112
-
113
- <div className="relative -mt-16 pb-16 container mx-auto px-4">
114
- <div className="container mx-auto px-4">
115
- <motion.div
116
- initial={{ opacity: 0, y: 24 }}
117
- animate={{ opacity: 1, y: 0 }}
118
- className="rounded-3xl border border-slate-100 bg-white p-6 shadow-lg shadow-primary-50"
119
- >
120
- <div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
121
- <div className="flex items-center gap-3 text-sm text-slate-500">
122
- <Sparkles className="h-4 w-4 text-primary-500" />
123
- <span>Explore your complete order archive with pharmacist notes.</span>
124
- </div>
125
- <div className="flex flex-col gap-4 md:items-end">
126
- <FilterChips
127
- label="Status filters"
128
- icon={Filter}
129
- filters={STATUS_FILTERS}
130
- selected={selectedFilter}
131
- onSelect={(value) => {
132
- setSelectedFilter(value as any);
133
- setPage(1);
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
- </motion.div>
196
- </div>
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
  );