hey-pharmacist-ecommerce 1.1.13 → 1.1.15
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.d.mts +2 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.js +1039 -857
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1039 -856
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/components/AccountAddressesTab.tsx +209 -0
- package/src/components/AccountOrdersTab.tsx +151 -0
- package/src/components/AccountOverviewTab.tsx +209 -0
- package/src/components/AccountPaymentTab.tsx +116 -0
- package/src/components/AccountSavedItemsTab.tsx +76 -0
- package/src/components/AccountSettingsTab.tsx +116 -0
- package/src/components/AddressFormModal.tsx +23 -10
- package/src/components/CartItem.tsx +60 -56
- package/src/components/Header.tsx +69 -16
- package/src/components/Notification.tsx +148 -0
- package/src/components/ProductCard.tsx +215 -178
- package/src/components/QuickViewModal.tsx +314 -0
- package/src/components/TabNavigation.tsx +48 -0
- package/src/components/ui/Button.tsx +1 -1
- package/src/components/ui/ConfirmModal.tsx +84 -0
- package/src/hooks/usePaymentMethods.ts +58 -0
- package/src/index.ts +0 -1
- package/src/providers/CartProvider.tsx +22 -6
- package/src/providers/EcommerceProvider.tsx +8 -7
- package/src/providers/FavoritesProvider.tsx +10 -3
- package/src/providers/NotificationProvider.tsx +79 -0
- package/src/providers/WishlistProvider.tsx +34 -9
- package/src/screens/AddressesScreen.tsx +72 -61
- package/src/screens/CartScreen.tsx +48 -32
- package/src/screens/ChangePasswordScreen.tsx +155 -0
- package/src/screens/CheckoutScreen.tsx +162 -125
- package/src/screens/EditProfileScreen.tsx +165 -0
- package/src/screens/LoginScreen.tsx +59 -72
- package/src/screens/NewAddressScreen.tsx +16 -10
- package/src/screens/ProductDetailScreen.tsx +334 -234
- package/src/screens/ProfileScreen.tsx +190 -200
- package/src/screens/RegisterScreen.tsx +51 -70
- package/src/screens/SearchResultsScreen.tsx +2 -1
- package/src/screens/ShopScreen.tsx +260 -384
- package/src/screens/WishlistScreen.tsx +226 -224
- package/src/styles/globals.css +9 -0
- package/src/screens/CategoriesScreen.tsx +0 -122
- package/src/screens/HomeScreen.tsx +0 -211
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { useState } from 'react';
|
|
4
4
|
import { motion } from 'framer-motion';
|
|
5
|
-
import { useForm } from 'react-hook-form';
|
|
6
|
-
import { zodResolver } from '@hookform/resolvers/zod';
|
|
7
|
-
import { z } from 'zod';
|
|
8
5
|
import Link from 'next/link';
|
|
9
6
|
import { useRouter } from 'next/navigation';
|
|
10
7
|
import {
|
|
8
|
+
ArrowRight,
|
|
11
9
|
Heart,
|
|
12
10
|
HeartPulse,
|
|
13
11
|
LogOut,
|
|
@@ -20,60 +18,32 @@ import {
|
|
|
20
18
|
User,
|
|
21
19
|
} from 'lucide-react';
|
|
22
20
|
import { Button } from '@/components/ui/Button';
|
|
23
|
-
import { Input } from '@/components/ui/Input';
|
|
24
21
|
import { useAuth } from '@/providers/AuthProvider';
|
|
25
|
-
import { toast } from 'sonner';
|
|
26
22
|
import { getInitials } from '@/lib/utils/format';
|
|
27
23
|
import { useBasePath } from '@/providers/BasePathProvider';
|
|
28
24
|
|
|
29
|
-
const profileSchema = z.object({
|
|
30
|
-
firstName: z.string().min(2, 'First name is required'),
|
|
31
|
-
lastName: z.string().min(2, 'Last name is required'),
|
|
32
|
-
email: z.string().email('Enter a valid email address'),
|
|
33
|
-
phone: z.string().optional(),
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
type ProfileFormData = z.infer<typeof profileSchema>;
|
|
37
|
-
|
|
38
25
|
export function ProfileScreen() {
|
|
39
26
|
const router = useRouter();
|
|
40
|
-
const { user,
|
|
27
|
+
const { user, logout, isLoading } = useAuth();
|
|
41
28
|
const { buildPath } = useBasePath();
|
|
42
|
-
const [
|
|
29
|
+
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
|
30
|
+
const [logoutError, setLogoutError] = useState<string | null>(null);
|
|
43
31
|
|
|
44
|
-
const {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
formState: { errors },
|
|
48
|
-
} = useForm<ProfileFormData>({
|
|
49
|
-
resolver: zodResolver(profileSchema),
|
|
50
|
-
defaultValues: {
|
|
51
|
-
firstName: user?.firstname || '',
|
|
52
|
-
lastName: user?.lastname || '',
|
|
53
|
-
email: user?.email || '',
|
|
54
|
-
phone: user?.phoneNumber || '',
|
|
55
|
-
},
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const onSubmit = async (data: ProfileFormData) => {
|
|
59
|
-
setIsSubmitting(true);
|
|
32
|
+
const handleLogout = async () => {
|
|
33
|
+
setIsLoggingOut(true);
|
|
34
|
+
setLogoutError(null);
|
|
60
35
|
try {
|
|
61
|
-
await
|
|
62
|
-
|
|
36
|
+
await logout();
|
|
37
|
+
router.push(buildPath('/'));
|
|
63
38
|
} catch (error: any) {
|
|
64
|
-
|
|
39
|
+
setLogoutError(error?.response?.data?.message || 'Failed to logout. Please try again.');
|
|
65
40
|
} finally {
|
|
66
|
-
|
|
41
|
+
setIsLoggingOut(false);
|
|
67
42
|
}
|
|
68
43
|
};
|
|
69
44
|
|
|
70
|
-
const handleLogout = async () => {
|
|
71
|
-
await logout();
|
|
72
|
-
toast.success('Logged out successfully');
|
|
73
|
-
router.push(buildPath('/'));
|
|
74
|
-
};
|
|
75
|
-
|
|
76
45
|
if (!user) {
|
|
46
|
+
if (isLoading) return null;
|
|
77
47
|
router.push(buildPath('/login'));
|
|
78
48
|
return null;
|
|
79
49
|
}
|
|
@@ -81,8 +51,8 @@ export function ProfileScreen() {
|
|
|
81
51
|
const quickLinks = [
|
|
82
52
|
{
|
|
83
53
|
icon: Package,
|
|
84
|
-
label: '
|
|
85
|
-
description: 'Track shipments and
|
|
54
|
+
label: 'Orders & invoices',
|
|
55
|
+
description: 'Track shipments, invoices, and receipts',
|
|
86
56
|
href: buildPath('/orders'),
|
|
87
57
|
},
|
|
88
58
|
{
|
|
@@ -100,188 +70,208 @@ export function ProfileScreen() {
|
|
|
100
70
|
];
|
|
101
71
|
|
|
102
72
|
return (
|
|
103
|
-
<div className="min-h-screen bg-slate-50">
|
|
104
|
-
<
|
|
105
|
-
<div className="
|
|
106
|
-
|
|
73
|
+
<div className="min-h-screen bg-slate-50 text-slate-900">
|
|
74
|
+
<div className="relative container mx-auto px-4 pb-16 pt-10">
|
|
75
|
+
<div className="rounded-3xl border border-slate-200 bg-white/95 p-8 shadow-xl shadow-primary-50 backdrop-blur">
|
|
76
|
+
<div className="mb-6 flex flex-wrap items-center justify-between gap-3">
|
|
77
|
+
<div className="text-sm text-slate-500">
|
|
78
|
+
Stay signed in to keep prescriptions and deliveries synced.
|
|
79
|
+
</div>
|
|
80
|
+
<div className="flex items-center gap-3">
|
|
81
|
+
{logoutError && (
|
|
82
|
+
<div className="flex items-start gap-2 rounded-xl border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700">
|
|
83
|
+
<ShieldCheck className="mt-[1px] h-4 w-4 text-red-500" />
|
|
84
|
+
<span>{logoutError}</span>
|
|
85
|
+
</div>
|
|
86
|
+
)}
|
|
87
|
+
<Button
|
|
88
|
+
type="button"
|
|
89
|
+
variant="outline"
|
|
90
|
+
size="sm"
|
|
91
|
+
className="border-red-200 text-red-600 hover:bg-red-50"
|
|
92
|
+
onClick={handleLogout}
|
|
93
|
+
disabled={isLoggingOut}
|
|
94
|
+
>
|
|
95
|
+
<LogOut className="h-4 w-4" />
|
|
96
|
+
{isLoggingOut ? 'Logging out...' : 'Log out'}
|
|
97
|
+
</Button>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
107
100
|
<motion.div
|
|
108
|
-
initial={{ opacity: 0, y:
|
|
101
|
+
initial={{ opacity: 0, y: 18 }}
|
|
109
102
|
animate={{ opacity: 1, y: 0 }}
|
|
110
|
-
className="
|
|
103
|
+
className="grid gap-8 md:grid-cols-[minmax(0,1.1fr)_minmax(0,0.9fr)] md:items-center"
|
|
111
104
|
>
|
|
112
|
-
<div className="space-y-
|
|
113
|
-
<
|
|
105
|
+
<div className="space-y-4">
|
|
106
|
+
<div className="inline-flex items-center gap-2 rounded-full bg-slate-900 text-white px-4 py-1 text-xs font-semibold uppercase tracking-[0.32em]">
|
|
114
107
|
<HeartPulse className="h-4 w-4" />
|
|
115
|
-
|
|
116
|
-
</
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
108
|
+
Account
|
|
109
|
+
</div>
|
|
110
|
+
<div>
|
|
111
|
+
<h1 className="text-4xl font-semibold md:text-5xl">
|
|
112
|
+
Welcome back, {user.firstname} {user.lastname}
|
|
113
|
+
</h1>
|
|
114
|
+
<p className="mt-3 max-w-2xl text-base text-slate-600">
|
|
115
|
+
Keep your identity and delivery details accurate for smoother refills, faster
|
|
116
|
+
shipping, and timely pharmacist guidance.
|
|
117
|
+
</p>
|
|
118
|
+
</div>
|
|
119
|
+
<div className="flex flex-wrap gap-3 text-sm text-slate-600">
|
|
120
|
+
<span className="inline-flex items-center gap-2 rounded-full border border-slate-200 bg-slate-50 px-3 py-2">
|
|
121
|
+
<ShieldCheck className="h-4 w-4 text-primary-600" />
|
|
122
|
+
Secure login enabled
|
|
123
|
+
</span>
|
|
124
|
+
<span className="inline-flex items-center gap-2 rounded-full border border-slate-200 bg-slate-50 px-3 py-2">
|
|
125
|
+
<Mail className="h-4 w-4 text-primary-600" />
|
|
126
|
+
{user.email}
|
|
127
|
+
</span>
|
|
128
|
+
<span className="inline-flex items-center gap-2 rounded-full border border-slate-200 bg-slate-50 px-3 py-2">
|
|
129
|
+
<Phone className="h-4 w-4 text-primary-600" />
|
|
130
|
+
{user.phoneNumber || 'Add phone for urgent updates'}
|
|
128
131
|
</span>
|
|
129
132
|
</div>
|
|
130
133
|
</div>
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
+
|
|
135
|
+
<div className="flex flex-col gap-4 rounded-2xl border border-slate-200 bg-slate-50/70 p-6 shadow-sm">
|
|
136
|
+
<div className="flex items-center gap-4">
|
|
137
|
+
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-white text-2xl font-semibold text-slate-900 shadow-sm">
|
|
138
|
+
{getInitials(user?.firstname || '', user?.lastname || '') || ''}
|
|
139
|
+
</div>
|
|
140
|
+
<div className="space-y-1">
|
|
141
|
+
<p className="text-sm text-slate-500">Signed in as</p>
|
|
142
|
+
<p className="text-lg font-semibold text-slate-900">{user.firstname}</p>
|
|
143
|
+
<p className="text-sm text-slate-500">{user.email}</p>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
<div className="grid gap-3 sm:grid-cols-2">
|
|
147
|
+
<Button
|
|
148
|
+
variant="outline"
|
|
149
|
+
size="md"
|
|
150
|
+
className="border-slate-300 text-slate-800 hover:bg-white"
|
|
151
|
+
onClick={() => router.push(buildPath('/account/edit'))}
|
|
152
|
+
>
|
|
153
|
+
Edit profile
|
|
154
|
+
</Button>
|
|
155
|
+
<Button
|
|
156
|
+
variant="ghost"
|
|
157
|
+
size="md"
|
|
158
|
+
className="text-slate-700 hover:bg-white"
|
|
159
|
+
onClick={() => router.push(buildPath('/account/change-password'))}
|
|
160
|
+
>
|
|
161
|
+
Change password
|
|
162
|
+
</Button>
|
|
134
163
|
</div>
|
|
135
|
-
<p className="text-sm text-white/80">{user.email}</p>
|
|
136
|
-
<Button
|
|
137
|
-
variant="ghost"
|
|
138
|
-
className="text-white hover:bg-white/20"
|
|
139
|
-
onClick={() => router.push(buildPath('/account/change-password'))}
|
|
140
|
-
>
|
|
141
|
-
Change password
|
|
142
|
-
</Button>
|
|
143
164
|
</div>
|
|
144
165
|
</motion.div>
|
|
145
166
|
</div>
|
|
146
|
-
</section>
|
|
147
167
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
</h2>
|
|
161
|
-
<Sparkles className="h-5 w-5 text-primary-500" />
|
|
168
|
+
<div className="mt-10 grid gap-8 lg:grid-cols-[minmax(0,1.08fr)_minmax(0,0.92fr)] items-stretch">
|
|
169
|
+
<motion.div
|
|
170
|
+
initial={{ opacity: 0, y: 18 }}
|
|
171
|
+
animate={{ opacity: 1, y: 0 }}
|
|
172
|
+
className="space-y-6"
|
|
173
|
+
>
|
|
174
|
+
<section className="rounded-3xl border border-slate-200 bg-white p-7 shadow-lg shadow-primary-50/40 min-h-[420px] h-full flex flex-col">
|
|
175
|
+
<div className="flex items-center justify-between gap-3">
|
|
176
|
+
<div>
|
|
177
|
+
<p className="text-xs font-semibold uppercase tracking-[0.3em] text-slate-400">
|
|
178
|
+
Essentials
|
|
179
|
+
</p>
|
|
180
|
+
<h2 className="mt-1 text-xl font-semibold text-slate-900">Profile snapshot</h2>
|
|
162
181
|
</div>
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
label="Email address"
|
|
184
|
-
placeholder="you@example.com"
|
|
185
|
-
className="pl-10"
|
|
186
|
-
{...register('email')}
|
|
187
|
-
error={errors.email?.message}
|
|
188
|
-
/>
|
|
189
|
-
<Mail className="absolute left-3 top-[38px] h-4 w-4 text-slate-400" />
|
|
190
|
-
</div>
|
|
191
|
-
|
|
192
|
-
<div className="relative">
|
|
193
|
-
<Input
|
|
194
|
-
type="tel"
|
|
195
|
-
label="Phone number"
|
|
196
|
-
placeholder="+1 (555) 123-4567"
|
|
197
|
-
className="pl-10"
|
|
198
|
-
{...register('phone')}
|
|
199
|
-
error={errors.phone?.message}
|
|
200
|
-
/>
|
|
201
|
-
<Phone className="absolute left-3 top-[38px] h-4 w-4 text-slate-400" />
|
|
182
|
+
<Sparkles className="h-5 w-5 text-primary-500" />
|
|
183
|
+
</div>
|
|
184
|
+
<div className="mt-6 grid gap-4 md:grid-cols-2">
|
|
185
|
+
<div className="rounded-2xl border border-slate-200 bg-slate-50/70 p-5">
|
|
186
|
+
<p className="text-xs font-semibold uppercase tracking-[0.28em] text-slate-500">
|
|
187
|
+
Contact
|
|
188
|
+
</p>
|
|
189
|
+
<div className="mt-3 space-y-2 text-sm text-slate-600">
|
|
190
|
+
<p className="flex items-center gap-2 font-semibold text-slate-900">
|
|
191
|
+
<User className="h-4 w-4 text-primary-500" />
|
|
192
|
+
{user.firstname} {user.lastname}
|
|
193
|
+
</p>
|
|
194
|
+
<p className="flex items-center gap-2">
|
|
195
|
+
<Mail className="h-4 w-4 text-primary-500" />
|
|
196
|
+
{user.email}
|
|
197
|
+
</p>
|
|
198
|
+
<p className="flex items-center gap-2">
|
|
199
|
+
<Phone className="h-4 w-4 text-primary-500" />
|
|
200
|
+
{user.phoneNumber || 'Not provided'}
|
|
201
|
+
</p>
|
|
202
202
|
</div>
|
|
203
|
+
<Button
|
|
204
|
+
variant="outline"
|
|
205
|
+
size="md"
|
|
206
|
+
className="mt-4 w-full border-slate-300 text-slate-800 hover:bg-white"
|
|
207
|
+
onClick={() => router.push(buildPath('/account/edit'))}
|
|
208
|
+
>
|
|
209
|
+
Update information
|
|
210
|
+
</Button>
|
|
211
|
+
</div>
|
|
203
212
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
>
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
variant="outline"
|
|
215
|
-
size="lg"
|
|
216
|
-
onClick={() => router.push(buildPath('/orders'))}
|
|
217
|
-
>
|
|
218
|
-
View recent orders
|
|
219
|
-
</Button>
|
|
213
|
+
<div className="rounded-2xl border border-slate-200 bg-slate-50/70 p-5">
|
|
214
|
+
<p className="text-xs font-semibold uppercase tracking-[0.28em] text-slate-500">
|
|
215
|
+
Security
|
|
216
|
+
</p>
|
|
217
|
+
<div className="mt-3 space-y-2 text-sm text-slate-600">
|
|
218
|
+
<p className="flex items-center gap-2 font-semibold text-slate-900">
|
|
219
|
+
<ShieldCheck className="h-4 w-4 text-primary-500" />
|
|
220
|
+
Multi-factor ready
|
|
221
|
+
</p>
|
|
222
|
+
<p>Protect your account with a fresh password and keep notifications on.</p>
|
|
220
223
|
</div>
|
|
221
|
-
|
|
222
|
-
|
|
224
|
+
<Button
|
|
225
|
+
variant="primary"
|
|
226
|
+
size="md"
|
|
227
|
+
className="mt-4 w-full"
|
|
228
|
+
onClick={() => router.push(buildPath('/account/change-password'))}
|
|
229
|
+
>
|
|
230
|
+
Change password
|
|
231
|
+
</Button>
|
|
232
|
+
</div>
|
|
233
|
+
</div>
|
|
234
|
+
</section>
|
|
235
|
+
</motion.div>
|
|
223
236
|
|
|
224
|
-
|
|
237
|
+
<motion.aside
|
|
238
|
+
initial={{ opacity: 0, y: 18 }}
|
|
239
|
+
animate={{ opacity: 1, y: 0 }}
|
|
240
|
+
transition={{ delay: 0.05 }}
|
|
241
|
+
className="space-y-4 h-full"
|
|
242
|
+
>
|
|
243
|
+
<section className="rounded-3xl border border-slate-200 bg-white p-6 shadow-sm min-h-[420px] h-full flex flex-col">
|
|
244
|
+
<div className="flex items-center justify-between">
|
|
245
|
+
<div>
|
|
246
|
+
<p className="text-xs font-semibold uppercase tracking-[0.3em] text-slate-400">
|
|
247
|
+
Quick links
|
|
248
|
+
</p>
|
|
249
|
+
<h3 className="mt-1 text-lg font-semibold text-slate-900">Next steps</h3>
|
|
250
|
+
</div>
|
|
251
|
+
<Heart className="h-5 w-5 text-primary-500" />
|
|
252
|
+
</div>
|
|
253
|
+
<div className="mt-5 grid gap-3">
|
|
225
254
|
{quickLinks.map((item) => (
|
|
226
255
|
<Link
|
|
227
256
|
key={item.href}
|
|
228
257
|
href={item.href}
|
|
229
|
-
className="group rounded-
|
|
258
|
+
className="group relative flex items-start gap-3 rounded-2xl border border-slate-200 bg-slate-50/70 p-4 transition duration-200 hover:-translate-y-0.5 hover:border-primary-200 hover:bg-white hover:shadow-md"
|
|
230
259
|
>
|
|
231
|
-
<
|
|
232
|
-
<
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
<
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
</div>
|
|
260
|
+
<span className="flex h-11 w-11 items-center justify-center rounded-xl bg-white text-primary-600 shadow-sm group-hover:bg-primary-600 group-hover:text-white">
|
|
261
|
+
<item.icon className="h-5 w-5" />
|
|
262
|
+
</span>
|
|
263
|
+
<div className="flex-1">
|
|
264
|
+
<p className="flex items-center gap-2 text-base font-semibold text-slate-900 group-hover:text-primary-700">
|
|
265
|
+
{item.label}
|
|
266
|
+
<ArrowRight className="h-4 w-4 opacity-0 transition group-hover:opacity-100" />
|
|
267
|
+
</p>
|
|
268
|
+
<p className="text-sm text-slate-500">{item.description}</p>
|
|
241
269
|
</div>
|
|
242
270
|
</Link>
|
|
243
271
|
))}
|
|
244
|
-
</section>
|
|
245
|
-
</motion.div>
|
|
246
|
-
|
|
247
|
-
<motion.aside
|
|
248
|
-
initial={{ opacity: 0, y: 24 }}
|
|
249
|
-
animate={{ opacity: 1, y: 0 }}
|
|
250
|
-
transition={{ delay: 0.1 }}
|
|
251
|
-
className="space-y-6"
|
|
252
|
-
>
|
|
253
|
-
<div className="rounded-3xl border border-slate-100 bg-white p-6 shadow-lg shadow-primary-50">
|
|
254
|
-
<h3 className="text-lg font-semibold text-slate-900">Care preferences</h3>
|
|
255
|
-
<p className="mt-3 text-sm text-slate-600">
|
|
256
|
-
Customize how we support you. Set refill reminders or manage communication
|
|
257
|
-
preferences to stay aligned with your wellness goals.
|
|
258
|
-
</p>
|
|
259
|
-
<Button
|
|
260
|
-
variant="outline"
|
|
261
|
-
className="mt-4 w-full"
|
|
262
|
-
onClick={() => router.push(buildPath('/account/preferences'))}
|
|
263
|
-
>
|
|
264
|
-
Manage preferences
|
|
265
|
-
</Button>
|
|
266
272
|
</div>
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
<p className="font-semibold uppercase tracking-[0.3em]">Pharmacist tip</p>
|
|
270
|
-
<p className="mt-3 leading-relaxed">
|
|
271
|
-
Keep your phone number current so pharmacists can reach you quickly with dosage
|
|
272
|
-
advice or time-sensitive updates about your order.
|
|
273
|
-
</p>
|
|
274
|
-
</div>
|
|
275
|
-
|
|
276
|
-
<button
|
|
277
|
-
onClick={handleLogout}
|
|
278
|
-
className="flex w-full items-center justify-center gap-2 rounded-3xl border border-red-200 bg-red-50 px-4 py-3 text-sm font-semibold text-red-600 transition hover:bg-red-100"
|
|
279
|
-
>
|
|
280
|
-
<LogOut className="h-4 w-4" />
|
|
281
|
-
Log out
|
|
282
|
-
</button>
|
|
283
|
-
</motion.aside>
|
|
284
|
-
</div>
|
|
273
|
+
</section>
|
|
274
|
+
</motion.aside>
|
|
285
275
|
</div>
|
|
286
276
|
</div>
|
|
287
277
|
</div>
|