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
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { motion } from 'framer-motion';
|
|
5
|
-
import { Package, Sparkles } from 'lucide-react';
|
|
6
|
-
import { EmptyState } from '@/components/EmptyState';
|
|
7
|
-
import { useCategories } from '@/hooks/useProducts';
|
|
8
|
-
import Image from 'next/image';
|
|
9
|
-
import Link from 'next/link';
|
|
10
|
-
import { useRouter } from 'next/navigation';
|
|
11
|
-
import { useBasePath } from '@/providers/BasePathProvider';
|
|
12
|
-
|
|
13
|
-
export function CategoriesScreen() {
|
|
14
|
-
const { categories, isLoading } = useCategories();
|
|
15
|
-
const router = useRouter();
|
|
16
|
-
const { buildPath } = useBasePath();
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<div className="min-h-screen bg-slate-50">
|
|
20
|
-
<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">
|
|
21
|
-
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,_rgba(255,255,255,0.35),_transparent_60%)]" />
|
|
22
|
-
<div className="relative container mx-auto px-4 py-16">
|
|
23
|
-
<motion.div
|
|
24
|
-
initial={{ opacity: 0, y: 24 }}
|
|
25
|
-
animate={{ opacity: 1, y: 0 }}
|
|
26
|
-
className="space-y-6"
|
|
27
|
-
>
|
|
28
|
-
<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">
|
|
29
|
-
<Package className="h-4 w-4" />
|
|
30
|
-
Product Categories
|
|
31
|
-
</span>
|
|
32
|
-
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
|
33
|
-
<div className="space-y-4">
|
|
34
|
-
<h1 className="text-4xl font-bold md:text-5xl">Browse Our Product Range</h1>
|
|
35
|
-
<p className="max-w-2xl text-white/80 md:text-lg">
|
|
36
|
-
Explore our comprehensive selection of healthcare products, carefully curated by our pharmacists to meet all your wellness needs.
|
|
37
|
-
</p>
|
|
38
|
-
</div>
|
|
39
|
-
<div className="rounded-3xl bg-white/15 p-6 backdrop-blur">
|
|
40
|
-
<p className="text-sm font-semibold uppercase tracking-[0.35em] text-white/70">
|
|
41
|
-
Quick tip
|
|
42
|
-
</p>
|
|
43
|
-
<p className="mt-3 text-sm text-white/80">
|
|
44
|
-
Use the categories below to quickly find the products you're looking for, or use the search function for specific items.
|
|
45
|
-
</p>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
</motion.div>
|
|
49
|
-
</div>
|
|
50
|
-
</section>
|
|
51
|
-
|
|
52
|
-
<div className="relative -mt-16 pb-16">
|
|
53
|
-
<div className="container mx-auto px-4">
|
|
54
|
-
<motion.div
|
|
55
|
-
initial={{ opacity: 0, y: 24 }}
|
|
56
|
-
animate={{ opacity: 1, y: 0 }}
|
|
57
|
-
className="rounded-3xl border border-slate-100 bg-white p-6 shadow-lg shadow-primary-50"
|
|
58
|
-
>
|
|
59
|
-
<div className="flex items-center gap-3 text-sm text-slate-500 mb-6">
|
|
60
|
-
<Sparkles className="h-4 w-4 text-primary-500" />
|
|
61
|
-
<span>Browse our complete product catalog organized by categories.</span>
|
|
62
|
-
</div>
|
|
63
|
-
|
|
64
|
-
{isLoading ? (
|
|
65
|
-
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
|
|
66
|
-
{[...Array(8)].map((_, i) => (
|
|
67
|
-
<div key={i} className="animate-pulse">
|
|
68
|
-
<div className="bg-gray-200 rounded-lg aspect-square mb-2"></div>
|
|
69
|
-
<div className="h-4 bg-gray-200 rounded w-3/4 mb-1"></div>
|
|
70
|
-
<div className="h-3 bg-gray-200 rounded w-1/2"></div>
|
|
71
|
-
</div>
|
|
72
|
-
))}
|
|
73
|
-
</div>
|
|
74
|
-
) : categories.length > 0 ? (
|
|
75
|
-
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
|
|
76
|
-
{categories.map((category) => (
|
|
77
|
-
<Link
|
|
78
|
-
key={category.id}
|
|
79
|
-
href={buildPath(`/shop?category=${category.name}`)}
|
|
80
|
-
className="group block overflow-hidden rounded-xl border border-gray-100 bg-white p-4 text-center transition hover:shadow-lg hover:border-primary-500"
|
|
81
|
-
>
|
|
82
|
-
<div className="relative aspect-square w-full overflow-hidden rounded-lg bg-gray-50 mb-3">
|
|
83
|
-
{category.image ? (
|
|
84
|
-
<Image
|
|
85
|
-
src={category.image}
|
|
86
|
-
alt={category.name || 'Category Image'}
|
|
87
|
-
fill
|
|
88
|
-
className="object-cover transition-transform group-hover:scale-105"
|
|
89
|
-
sizes="(max-width: 768px) 50vw, (max-width: 1200px) 33vw, 25vw"
|
|
90
|
-
/>
|
|
91
|
-
) : (
|
|
92
|
-
<div className="flex h-full w-full items-center justify-center bg-gray-100 text-gray-400">
|
|
93
|
-
<Package className="h-12 w-12" />
|
|
94
|
-
</div>
|
|
95
|
-
)}
|
|
96
|
-
</div>
|
|
97
|
-
<h3 className="text-lg font-semibold text-gray-900 group-hover:text-primary-600 transition-colors">
|
|
98
|
-
{category.name}
|
|
99
|
-
</h3>
|
|
100
|
-
{category.productCount > 0 && (
|
|
101
|
-
<p className="mt-1 text-sm text-gray-500">
|
|
102
|
-
{category.productCount} {category.productCount === 1 ? 'product' : 'products'}
|
|
103
|
-
</p>
|
|
104
|
-
)}
|
|
105
|
-
</Link>
|
|
106
|
-
))}
|
|
107
|
-
</div>
|
|
108
|
-
) : (
|
|
109
|
-
<EmptyState
|
|
110
|
-
title="No categories found"
|
|
111
|
-
description="There are currently no product categories available."
|
|
112
|
-
icon={Package}
|
|
113
|
-
actionLabel="Shop products"
|
|
114
|
-
onAction={() => router.push(buildPath('/shop'))}
|
|
115
|
-
/>
|
|
116
|
-
)}
|
|
117
|
-
</motion.div>
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
);
|
|
122
|
-
}
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { motion } from 'framer-motion';
|
|
5
|
-
import { ArrowRight, ShoppingBag, Truck, Shield, CreditCard } from 'lucide-react';
|
|
6
|
-
import { Button } from '@/components/ui/Button';
|
|
7
|
-
import { ProductCard } from '@/components/ProductCard';
|
|
8
|
-
import { useWishlist } from '@/providers/WishlistProvider';
|
|
9
|
-
import { ProductCardSkeleton } from '@/components/ui/Skeleton';
|
|
10
|
-
import { useRouter } from 'next/navigation';
|
|
11
|
-
import { useBasePath } from '@/providers/BasePathProvider';
|
|
12
|
-
import { useProducts } from '@/hooks/useProducts';
|
|
13
|
-
|
|
14
|
-
export default function HomeScreen() {
|
|
15
|
-
const router = useRouter();
|
|
16
|
-
const { buildPath } = useBasePath();
|
|
17
|
-
const { products, isLoading } = useProducts();
|
|
18
|
-
const { isInWishlist } = useWishlist();
|
|
19
|
-
|
|
20
|
-
const features = [
|
|
21
|
-
{
|
|
22
|
-
icon: Truck,
|
|
23
|
-
title: 'Free Shipping',
|
|
24
|
-
description: 'On orders over $50',
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
icon: Shield,
|
|
28
|
-
title: 'Secure Payment',
|
|
29
|
-
description: '100% secure transactions',
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
icon: CreditCard,
|
|
33
|
-
title: 'Easy Returns',
|
|
34
|
-
description: '30-day money back guarantee',
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
icon: ShoppingBag,
|
|
38
|
-
title: 'Quality Products',
|
|
39
|
-
description: 'Handpicked for you',
|
|
40
|
-
},
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<div>
|
|
45
|
-
{/* Hero Section */}
|
|
46
|
-
<section className="relative bg-gradient-to-br from-primary-600 via-primary-700 to-secondary-600 text-white py-32 overflow-hidden">
|
|
47
|
-
<div className="absolute inset-0 opacity-10">
|
|
48
|
-
<div className="absolute inset-0" style={{
|
|
49
|
-
backgroundImage: 'radial-gradient(circle at 2px 2px, white 1px, transparent 0)',
|
|
50
|
-
backgroundSize: '40px 40px',
|
|
51
|
-
}} />
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
<div className="container mx-auto px-4 relative z-10">
|
|
55
|
-
<motion.div
|
|
56
|
-
initial={{ opacity: 0, y: 30 }}
|
|
57
|
-
animate={{ opacity: 1, y: 0 }}
|
|
58
|
-
transition={{ duration: 0.8 }}
|
|
59
|
-
className="max-w-3xl mx-auto text-center"
|
|
60
|
-
>
|
|
61
|
-
<h1 className="text-6xl md:text-7xl font-bold mb-6">
|
|
62
|
-
Shop the Best Products
|
|
63
|
-
</h1>
|
|
64
|
-
<p className="text-xl md:text-2xl text-primary-100 mb-10">
|
|
65
|
-
Discover our curated collection of high-quality products at unbeatable prices
|
|
66
|
-
</p>
|
|
67
|
-
<div className="flex flex-wrap gap-4 justify-center">
|
|
68
|
-
<Button
|
|
69
|
-
size="lg"
|
|
70
|
-
variant="secondary"
|
|
71
|
-
onClick={() => router.push(buildPath('/shop'))}
|
|
72
|
-
className="text-lg px-8 py-4"
|
|
73
|
-
>
|
|
74
|
-
Shop Now
|
|
75
|
-
<ArrowRight className="w-6 h-6" />
|
|
76
|
-
</Button>
|
|
77
|
-
<Button
|
|
78
|
-
size="lg"
|
|
79
|
-
variant="outline"
|
|
80
|
-
onClick={() => router.push(buildPath('/about'))}
|
|
81
|
-
className="text-lg px-8 py-4 bg-white/10 backdrop-blur-sm border-white text-white hover:bg-white/20"
|
|
82
|
-
>
|
|
83
|
-
Learn More
|
|
84
|
-
</Button>
|
|
85
|
-
</div>
|
|
86
|
-
</motion.div>
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
{/* Decorative Elements */}
|
|
90
|
-
<div className="absolute bottom-0 left-0 right-0">
|
|
91
|
-
<svg viewBox="0 0 1440 120" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
92
|
-
<path d="M0 120L60 110C120 100 240 80 360 70C480 60 600 60 720 65C840 70 960 80 1080 85C1200 90 1320 90 1380 90L1440 90V120H1380C1320 120 1200 120 1080 120C960 120 840 120 720 120C600 120 480 120 360 120C240 120 120 120 60 120H0Z" fill="rgb(249, 250, 251)" />
|
|
93
|
-
</svg>
|
|
94
|
-
</div>
|
|
95
|
-
</section>
|
|
96
|
-
|
|
97
|
-
{/* Features Section */}
|
|
98
|
-
<section className="py-20 bg-gray-50">
|
|
99
|
-
<div className="container mx-auto px-4">
|
|
100
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
|
101
|
-
{features.map((feature, index) => (
|
|
102
|
-
<motion.div
|
|
103
|
-
key={feature.title}
|
|
104
|
-
initial={{ opacity: 0, y: 20 }}
|
|
105
|
-
whileInView={{ opacity: 1, y: 0 }}
|
|
106
|
-
transition={{ delay: index * 0.1 }}
|
|
107
|
-
viewport={{ once: true }}
|
|
108
|
-
className="text-center"
|
|
109
|
-
>
|
|
110
|
-
<div className="w-16 h-16 bg-primary-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
111
|
-
<feature.icon className="w-8 h-8 text-primary-600" />
|
|
112
|
-
</div>
|
|
113
|
-
<h3 className="text-xl font-bold text-gray-900 mb-2">
|
|
114
|
-
{feature.title}
|
|
115
|
-
</h3>
|
|
116
|
-
<p className="text-gray-600">{feature.description}</p>
|
|
117
|
-
</motion.div>
|
|
118
|
-
))}
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
</section>
|
|
122
|
-
|
|
123
|
-
{/* Featured Products Section */}
|
|
124
|
-
<section className="py-20 bg-white">
|
|
125
|
-
<div className="container mx-auto px-4">
|
|
126
|
-
<motion.div
|
|
127
|
-
initial={{ opacity: 0, y: 20 }}
|
|
128
|
-
whileInView={{ opacity: 1, y: 0 }}
|
|
129
|
-
viewport={{ once: true }}
|
|
130
|
-
className="text-center mb-12"
|
|
131
|
-
>
|
|
132
|
-
<h2 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
|
|
133
|
-
Featured Products
|
|
134
|
-
</h2>
|
|
135
|
-
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
|
|
136
|
-
Check out our handpicked selection of trending products
|
|
137
|
-
</p>
|
|
138
|
-
</motion.div>
|
|
139
|
-
|
|
140
|
-
{isLoading ? (
|
|
141
|
-
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
142
|
-
{Array.from({ length: 8 }).map((_, i) => (
|
|
143
|
-
<ProductCardSkeleton key={i} />
|
|
144
|
-
))}
|
|
145
|
-
</div>
|
|
146
|
-
) : (
|
|
147
|
-
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
148
|
-
{products.map((product, index) => {
|
|
149
|
-
|
|
150
|
-
return (
|
|
151
|
-
<motion.div
|
|
152
|
-
key={product.id}
|
|
153
|
-
initial={{ opacity: 0, y: 20 }}
|
|
154
|
-
whileInView={{ opacity: 1, y: 0 }}
|
|
155
|
-
transition={{ delay: index * 0.1 }}
|
|
156
|
-
viewport={{ once: true }}
|
|
157
|
-
>
|
|
158
|
-
<ProductCard
|
|
159
|
-
product={product}
|
|
160
|
-
isFavorited={isInWishlist(product.id)}
|
|
161
|
-
onClickProduct={(p) => router.push(buildPath(`/products/${p.id}`))}
|
|
162
|
-
/>
|
|
163
|
-
</motion.div>
|
|
164
|
-
);
|
|
165
|
-
})}
|
|
166
|
-
</div>
|
|
167
|
-
)}
|
|
168
|
-
|
|
169
|
-
<div className="text-center mt-12">
|
|
170
|
-
<Button
|
|
171
|
-
size="lg"
|
|
172
|
-
onClick={() => router.push(buildPath('/shop'))}
|
|
173
|
-
>
|
|
174
|
-
View All Products
|
|
175
|
-
<ArrowRight className="w-5 h-5" />
|
|
176
|
-
</Button>
|
|
177
|
-
</div>
|
|
178
|
-
</div>
|
|
179
|
-
</section>
|
|
180
|
-
|
|
181
|
-
{/* CTA Section */}
|
|
182
|
-
<section className="py-20 bg-gradient-to-br from-primary-600 to-secondary-600 text-white">
|
|
183
|
-
<div className="container mx-auto px-4">
|
|
184
|
-
<motion.div
|
|
185
|
-
initial={{ opacity: 0, y: 20 }}
|
|
186
|
-
whileInView={{ opacity: 1, y: 0 }}
|
|
187
|
-
viewport={{ once: true }}
|
|
188
|
-
className="max-w-3xl mx-auto text-center"
|
|
189
|
-
>
|
|
190
|
-
<h2 className="text-4xl md:text-5xl font-bold mb-6">
|
|
191
|
-
Ready to Start Shopping?
|
|
192
|
-
</h2>
|
|
193
|
-
<p className="text-xl text-primary-100 mb-10">
|
|
194
|
-
Join thousands of satisfied customers and discover amazing products today
|
|
195
|
-
</p>
|
|
196
|
-
<Button
|
|
197
|
-
size="lg"
|
|
198
|
-
variant="secondary"
|
|
199
|
-
onClick={() => router.push(buildPath('/register'))}
|
|
200
|
-
className="text-lg px-8 py-4"
|
|
201
|
-
>
|
|
202
|
-
Create an Account
|
|
203
|
-
<ArrowRight className="w-6 h-6" />
|
|
204
|
-
</Button>
|
|
205
|
-
</motion.div>
|
|
206
|
-
</div>
|
|
207
|
-
</section>
|
|
208
|
-
</div>
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
|