hey-pharmacist-ecommerce 1.0.0

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.
Files changed (287) hide show
  1. package/README.md +269 -0
  2. package/dist/index.d.mts +564 -0
  3. package/dist/index.d.ts +564 -0
  4. package/dist/index.js +7541 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.mjs +7485 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +70 -0
  9. package/src/components/CartItem.tsx +103 -0
  10. package/src/components/EmptyState.tsx +27 -0
  11. package/src/components/Footer.tsx +147 -0
  12. package/src/components/Header.tsx +151 -0
  13. package/src/components/OrderCard.tsx +98 -0
  14. package/src/components/ProductCard.tsx +122 -0
  15. package/src/components/ui/Badge.tsx +31 -0
  16. package/src/components/ui/Button.tsx +61 -0
  17. package/src/components/ui/Input.tsx +45 -0
  18. package/src/components/ui/Modal.tsx +79 -0
  19. package/src/components/ui/Skeleton.tsx +46 -0
  20. package/src/hooks/useOrders.ts +98 -0
  21. package/src/hooks/useProducts.ts +125 -0
  22. package/src/index.ts +71 -0
  23. package/src/lib/Apis/api.ts +46 -0
  24. package/src/lib/Apis/apis/addresses-api.ts +1461 -0
  25. package/src/lib/Apis/apis/auth-api.ts +945 -0
  26. package/src/lib/Apis/apis/blogs-api.ts +582 -0
  27. package/src/lib/Apis/apis/cart-api.ts +456 -0
  28. package/src/lib/Apis/apis/categories-api.ts +725 -0
  29. package/src/lib/Apis/apis/chats-api.ts +1101 -0
  30. package/src/lib/Apis/apis/contact-us-api.ts +394 -0
  31. package/src/lib/Apis/apis/discounts-api.ts +763 -0
  32. package/src/lib/Apis/apis/drafts-api.ts +448 -0
  33. package/src/lib/Apis/apis/events-api.ts +1311 -0
  34. package/src/lib/Apis/apis/file-proccesor-api.ts +293 -0
  35. package/src/lib/Apis/apis/health-api.ts +119 -0
  36. package/src/lib/Apis/apis/images-api.ts +271 -0
  37. package/src/lib/Apis/apis/inventory-api.ts +375 -0
  38. package/src/lib/Apis/apis/marketing-api.ts +3099 -0
  39. package/src/lib/Apis/apis/notifications-api.ts +843 -0
  40. package/src/lib/Apis/apis/open-aiapi.ts +513 -0
  41. package/src/lib/Apis/apis/orders-api.ts +1343 -0
  42. package/src/lib/Apis/apis/payment-methods-api.ts +411 -0
  43. package/src/lib/Apis/apis/payments-api.ts +469 -0
  44. package/src/lib/Apis/apis/product-attributes-api.ts +538 -0
  45. package/src/lib/Apis/apis/product-favorite-list-api.ts +321 -0
  46. package/src/lib/Apis/apis/product-variants-api.ts +648 -0
  47. package/src/lib/Apis/apis/products-api.ts +1442 -0
  48. package/src/lib/Apis/apis/review-api.ts +1383 -0
  49. package/src/lib/Apis/apis/roles-api.ts +614 -0
  50. package/src/lib/Apis/apis/shipping-api.ts +703 -0
  51. package/src/lib/Apis/apis/statistics-api.ts +234 -0
  52. package/src/lib/Apis/apis/stores-api.ts +1519 -0
  53. package/src/lib/Apis/apis/sub-categories-api.ts +1208 -0
  54. package/src/lib/Apis/apis/user-groups-api.ts +1198 -0
  55. package/src/lib/Apis/apis/users-api.ts +1403 -0
  56. package/src/lib/Apis/apis/web-hooks-api.ts +198 -0
  57. package/src/lib/Apis/base.ts +70 -0
  58. package/src/lib/Apis/configuration.ts +75 -0
  59. package/src/lib/Apis/index.ts +17 -0
  60. package/src/lib/Apis/models/add-contact-to-list-dto.ts +33 -0
  61. package/src/lib/Apis/models/add-message-dto.ts +56 -0
  62. package/src/lib/Apis/models/address-created-request.ts +134 -0
  63. package/src/lib/Apis/models/address.ts +164 -0
  64. package/src/lib/Apis/models/allow-user-credit-dto.ts +27 -0
  65. package/src/lib/Apis/models/appointment.ts +75 -0
  66. package/src/lib/Apis/models/available-dates-dto.ts +33 -0
  67. package/src/lib/Apis/models/available-suggested-dates-dto.ts +33 -0
  68. package/src/lib/Apis/models/blog.ts +75 -0
  69. package/src/lib/Apis/models/browser-stats-response-dto.ts +40 -0
  70. package/src/lib/Apis/models/bulk-move-subcategories-dto.ts +33 -0
  71. package/src/lib/Apis/models/bulk-unassign-subcategories-dto.ts +27 -0
  72. package/src/lib/Apis/models/campaign-content-response-dto.ts +40 -0
  73. package/src/lib/Apis/models/campaign-draft-dto.ts +175 -0
  74. package/src/lib/Apis/models/campaign-draft-response-dto.ts +40 -0
  75. package/src/lib/Apis/models/campaign-draft-schedule-dto.ts +49 -0
  76. package/src/lib/Apis/models/campaign-draft-schedule-response-dto.ts +40 -0
  77. package/src/lib/Apis/models/campaign-draft-sending-dto.ts +43 -0
  78. package/src/lib/Apis/models/campaign-draft-sending-response-dto.ts +40 -0
  79. package/src/lib/Apis/models/cart-body-dto.ts +40 -0
  80. package/src/lib/Apis/models/cart-body-populated.ts +47 -0
  81. package/src/lib/Apis/models/cart-item-populated.ts +41 -0
  82. package/src/lib/Apis/models/cart-item.ts +33 -0
  83. package/src/lib/Apis/models/cart-response-dto.ts +70 -0
  84. package/src/lib/Apis/models/categories-paginated-response-dto.ts +52 -0
  85. package/src/lib/Apis/models/category-filters.ts +40 -0
  86. package/src/lib/Apis/models/category-populated.ts +106 -0
  87. package/src/lib/Apis/models/category-sub-category-populated.ts +51 -0
  88. package/src/lib/Apis/models/category.ts +99 -0
  89. package/src/lib/Apis/models/categorys-headlines-response-dto.ts +40 -0
  90. package/src/lib/Apis/models/change-user-email-dto.ts +27 -0
  91. package/src/lib/Apis/models/chat.ts +33 -0
  92. package/src/lib/Apis/models/check-notifications-response-dto.ts +33 -0
  93. package/src/lib/Apis/models/contact-aggregated-stats-response-dto.ts +40 -0
  94. package/src/lib/Apis/models/contact-full-dto.ts +93 -0
  95. package/src/lib/Apis/models/contact-full-response-dto.ts +40 -0
  96. package/src/lib/Apis/models/contact-list-stats-response-dto.ts +40 -0
  97. package/src/lib/Apis/models/contact-lists-response-dto.ts +40 -0
  98. package/src/lib/Apis/models/contact-us.ts +81 -0
  99. package/src/lib/Apis/models/country-stats-response-dto.ts +40 -0
  100. package/src/lib/Apis/models/create-address-dto.ts +134 -0
  101. package/src/lib/Apis/models/create-blog-dto.ts +45 -0
  102. package/src/lib/Apis/models/create-category-dto.ts +45 -0
  103. package/src/lib/Apis/models/create-chat-dto.ts +39 -0
  104. package/src/lib/Apis/models/create-contact-dto.ts +39 -0
  105. package/src/lib/Apis/models/create-contact-list-dto.ts +27 -0
  106. package/src/lib/Apis/models/create-discount-dto.ts +208 -0
  107. package/src/lib/Apis/models/create-draft-dto.ts +67 -0
  108. package/src/lib/Apis/models/create-email-template-dto.ts +51 -0
  109. package/src/lib/Apis/models/create-event-dto.ts +52 -0
  110. package/src/lib/Apis/models/create-marketing-campaign-dto.ts +81 -0
  111. package/src/lib/Apis/models/create-message-dto.ts +57 -0
  112. package/src/lib/Apis/models/create-notification-dto.ts +75 -0
  113. package/src/lib/Apis/models/create-product-attribute-dto.ts +33 -0
  114. package/src/lib/Apis/models/create-product-dto.ts +94 -0
  115. package/src/lib/Apis/models/create-review-dto.ts +63 -0
  116. package/src/lib/Apis/models/create-role-dto.ts +57 -0
  117. package/src/lib/Apis/models/create-single-variant-product-dto.ts +155 -0
  118. package/src/lib/Apis/models/create-store-address-dto.ts +134 -0
  119. package/src/lib/Apis/models/create-store-dto.ts +105 -0
  120. package/src/lib/Apis/models/create-sub-category-dto.ts +45 -0
  121. package/src/lib/Apis/models/create-user-dto.ts +89 -0
  122. package/src/lib/Apis/models/create-user-group-dto.ts +39 -0
  123. package/src/lib/Apis/models/create-variant-dto.ts +119 -0
  124. package/src/lib/Apis/models/create-zone-dto.ts +82 -0
  125. package/src/lib/Apis/models/custom-product-dto.ts +63 -0
  126. package/src/lib/Apis/models/default-payment-method-request-dto.ts +27 -0
  127. package/src/lib/Apis/models/delete-file-dto.ts +27 -0
  128. package/src/lib/Apis/models/delete-many-files-dto.ts +27 -0
  129. package/src/lib/Apis/models/discount-paginated-response.ts +52 -0
  130. package/src/lib/Apis/models/discount.ts +245 -0
  131. package/src/lib/Apis/models/discounts-insights-dto.ts +57 -0
  132. package/src/lib/Apis/models/draft.ts +79 -0
  133. package/src/lib/Apis/models/email-invoice-dto.ts +45 -0
  134. package/src/lib/Apis/models/email-template-response-dto.ts +117 -0
  135. package/src/lib/Apis/models/event.ts +76 -0
  136. package/src/lib/Apis/models/extended-product-dto.ts +204 -0
  137. package/src/lib/Apis/models/fileproccesor-upload-body.ts +27 -0
  138. package/src/lib/Apis/models/forget-password.ts +27 -0
  139. package/src/lib/Apis/models/frequently-bought-product-dto.ts +71 -0
  140. package/src/lib/Apis/models/general-stats-response-dto.ts +40 -0
  141. package/src/lib/Apis/models/generate-day-slots-dto.ts +51 -0
  142. package/src/lib/Apis/models/generate-month-slots-dto.ts +57 -0
  143. package/src/lib/Apis/models/generate-week-slots-dto.ts +57 -0
  144. package/src/lib/Apis/models/google-analytics-request-dto.ts +55 -0
  145. package/src/lib/Apis/models/google-analytics-response-dto.ts +39 -0
  146. package/src/lib/Apis/models/group-with-no-users-dto.ts +75 -0
  147. package/src/lib/Apis/models/group-with-users-dto.ts +76 -0
  148. package/src/lib/Apis/models/images-upload-body.ts +27 -0
  149. package/src/lib/Apis/models/index.ts +197 -0
  150. package/src/lib/Apis/models/inventory-paginated-response.ts +75 -0
  151. package/src/lib/Apis/models/link-stats-response-dto.ts +40 -0
  152. package/src/lib/Apis/models/login-dto.ts +33 -0
  153. package/src/lib/Apis/models/manual-discount.ts +49 -0
  154. package/src/lib/Apis/models/manual-order-dto.ts +133 -0
  155. package/src/lib/Apis/models/manual-shipping-dto.ts +45 -0
  156. package/src/lib/Apis/models/marketing-campaign-content-dto.ts +27 -0
  157. package/src/lib/Apis/models/marketing-list-contact-dto.ts +51 -0
  158. package/src/lib/Apis/models/move-subcategory-dto.ts +27 -0
  159. package/src/lib/Apis/models/my-favorite-list-dto.ts +52 -0
  160. package/src/lib/Apis/models/notification.ts +93 -0
  161. package/src/lib/Apis/models/object-id.ts +21 -0
  162. package/src/lib/Apis/models/open-api.ts +33 -0
  163. package/src/lib/Apis/models/order-paginated-response.ts +52 -0
  164. package/src/lib/Apis/models/order.ts +214 -0
  165. package/src/lib/Apis/models/orders-insights-dto.ts +69 -0
  166. package/src/lib/Apis/models/paginated-products-dto.ts +52 -0
  167. package/src/lib/Apis/models/payment-method-data.ts +34 -0
  168. package/src/lib/Apis/models/payment-method.ts +51 -0
  169. package/src/lib/Apis/models/payment-time-line-dto.ts +56 -0
  170. package/src/lib/Apis/models/payment.ts +182 -0
  171. package/src/lib/Apis/models/payments-insights-dto.ts +69 -0
  172. package/src/lib/Apis/models/payments-paginated-response.ts +52 -0
  173. package/src/lib/Apis/models/pick-type-class.ts +51 -0
  174. package/src/lib/Apis/models/populated-chat-dto.ts +95 -0
  175. package/src/lib/Apis/models/populated-discount.ts +246 -0
  176. package/src/lib/Apis/models/populated-order.ts +209 -0
  177. package/src/lib/Apis/models/prefered-pick-or-delivery-time-dto.ts +33 -0
  178. package/src/lib/Apis/models/price-range.ts +33 -0
  179. package/src/lib/Apis/models/product-attribute.ts +57 -0
  180. package/src/lib/Apis/models/product-variant.ts +167 -0
  181. package/src/lib/Apis/models/product.ts +136 -0
  182. package/src/lib/Apis/models/products-insights-dto.ts +45 -0
  183. package/src/lib/Apis/models/rate-dto.ts +123 -0
  184. package/src/lib/Apis/models/refill-request-dto.ts +75 -0
  185. package/src/lib/Apis/models/refill-request.ts +105 -0
  186. package/src/lib/Apis/models/register-or-login-with-gmail.ts +27 -0
  187. package/src/lib/Apis/models/reserve-appointment.ts +261 -0
  188. package/src/lib/Apis/models/review.ts +93 -0
  189. package/src/lib/Apis/models/role.ts +69 -0
  190. package/src/lib/Apis/models/schedule-campaign-draft-dto.ts +27 -0
  191. package/src/lib/Apis/models/send-test-email-dto.ts +28 -0
  192. package/src/lib/Apis/models/shallow-parent-category-dto.ts +33 -0
  193. package/src/lib/Apis/models/shipment-details-dto.ts +88 -0
  194. package/src/lib/Apis/models/shipment-status-dto.ts +117 -0
  195. package/src/lib/Apis/models/shipment-with-order.ts +105 -0
  196. package/src/lib/Apis/models/shipment.ts +104 -0
  197. package/src/lib/Apis/models/shipping-info.ts +88 -0
  198. package/src/lib/Apis/models/single-browser-stats-dto.ts +45 -0
  199. package/src/lib/Apis/models/single-contact-aggregated-stats-dto.ts +129 -0
  200. package/src/lib/Apis/models/single-contact-list-stats-dto.ts +117 -0
  201. package/src/lib/Apis/models/single-country-stats-dto.ts +39 -0
  202. package/src/lib/Apis/models/single-general-stats.ts +153 -0
  203. package/src/lib/Apis/models/single-link-stats-dto.ts +39 -0
  204. package/src/lib/Apis/models/single-message-populated.ts +59 -0
  205. package/src/lib/Apis/models/single-notification-dto.ts +99 -0
  206. package/src/lib/Apis/models/single-product-media.ts +74 -0
  207. package/src/lib/Apis/models/single-recipient-dto.ts +33 -0
  208. package/src/lib/Apis/models/single-suggest-attribute.ts +33 -0
  209. package/src/lib/Apis/models/statistic-dto.ts +171 -0
  210. package/src/lib/Apis/models/store-entity.ts +117 -0
  211. package/src/lib/Apis/models/store.ts +135 -0
  212. package/src/lib/Apis/models/sub-category-headlines-only-response-dto.ts +39 -0
  213. package/src/lib/Apis/models/sub-category.ts +93 -0
  214. package/src/lib/Apis/models/suggest-attributes.ts +28 -0
  215. package/src/lib/Apis/models/suggested-slot.ts +33 -0
  216. package/src/lib/Apis/models/table-cell-dto.ts +33 -0
  217. package/src/lib/Apis/models/table-dto.ts +34 -0
  218. package/src/lib/Apis/models/tadmin-session-data.ts +47 -0
  219. package/src/lib/Apis/models/track-dto.ts +94 -0
  220. package/src/lib/Apis/models/tracking-status-location-base.ts +45 -0
  221. package/src/lib/Apis/models/tracking-status-substatus.ts +39 -0
  222. package/src/lib/Apis/models/tracking-status.ts +71 -0
  223. package/src/lib/Apis/models/transfere-patient-request.ts +123 -0
  224. package/src/lib/Apis/models/transfere-patients-request-dto.ts +99 -0
  225. package/src/lib/Apis/models/tuser-session-data.ts +34 -0
  226. package/src/lib/Apis/models/update-address-dto.ts +134 -0
  227. package/src/lib/Apis/models/update-blog-dto.ts +45 -0
  228. package/src/lib/Apis/models/update-campaign-draft-content-dto.ts +27 -0
  229. package/src/lib/Apis/models/update-category-dto.ts +45 -0
  230. package/src/lib/Apis/models/update-discount-dto.ts +208 -0
  231. package/src/lib/Apis/models/update-event-dto.ts +52 -0
  232. package/src/lib/Apis/models/update-items-order-dto.ts +27 -0
  233. package/src/lib/Apis/models/update-marketing-camp-draft-dto.ts +81 -0
  234. package/src/lib/Apis/models/update-message-dto.ts +57 -0
  235. package/src/lib/Apis/models/update-product-attribute-dto.ts +33 -0
  236. package/src/lib/Apis/models/update-product-dto.ts +96 -0
  237. package/src/lib/Apis/models/update-product-variant-dto.ts +119 -0
  238. package/src/lib/Apis/models/update-refill-request-dto.ts +75 -0
  239. package/src/lib/Apis/models/update-review-dto.ts +63 -0
  240. package/src/lib/Apis/models/update-role-dto.ts +57 -0
  241. package/src/lib/Apis/models/update-store-dto.ts +105 -0
  242. package/src/lib/Apis/models/update-sub-category-dto.ts +45 -0
  243. package/src/lib/Apis/models/update-transfere-patients-request-dto.ts +99 -0
  244. package/src/lib/Apis/models/update-user-dto.ts +239 -0
  245. package/src/lib/Apis/models/update-user-group-dto.ts +39 -0
  246. package/src/lib/Apis/models/update-zone-dto.ts +82 -0
  247. package/src/lib/Apis/models/upload-pdf-body.ts +27 -0
  248. package/src/lib/Apis/models/used-by.ts +87 -0
  249. package/src/lib/Apis/models/user-entity.ts +220 -0
  250. package/src/lib/Apis/models/user-group.ts +75 -0
  251. package/src/lib/Apis/models/user-insights-dto.ts +39 -0
  252. package/src/lib/Apis/models/user-with-no-id.ts +226 -0
  253. package/src/lib/Apis/models/user.ts +232 -0
  254. package/src/lib/Apis/models/users-paginated-response.ts +52 -0
  255. package/src/lib/Apis/models/verify-email-dto.ts +33 -0
  256. package/src/lib/Apis/models/zone-single-size.ts +51 -0
  257. package/src/lib/Apis/models/zone.ts +106 -0
  258. package/src/lib/Apis/wrapper.ts +37 -0
  259. package/src/lib/api/auth.ts +81 -0
  260. package/src/lib/api/cart.ts +42 -0
  261. package/src/lib/api/client.ts +118 -0
  262. package/src/lib/api/orders.ts +53 -0
  263. package/src/lib/api/products.ts +51 -0
  264. package/src/lib/api-adapter/auth-adapter.ts +196 -0
  265. package/src/lib/api-adapter/cart-adapter.ts +193 -0
  266. package/src/lib/api-adapter/config.ts +76 -0
  267. package/src/lib/api-adapter/index.ts +13 -0
  268. package/src/lib/api-adapter/mappers.ts +147 -0
  269. package/src/lib/api-adapter/orders-adapter.ts +195 -0
  270. package/src/lib/api-adapter/products-adapter.ts +194 -0
  271. package/src/lib/types/index.ts +152 -0
  272. package/src/lib/utils/colors.ts +51 -0
  273. package/src/lib/utils/format.ts +48 -0
  274. package/src/providers/AuthProvider.tsx +117 -0
  275. package/src/providers/CartProvider.tsx +131 -0
  276. package/src/providers/EcommerceProvider.tsx +34 -0
  277. package/src/providers/ThemeProvider.tsx +57 -0
  278. package/src/screens/CartScreen.tsx +140 -0
  279. package/src/screens/CheckoutScreen.tsx +340 -0
  280. package/src/screens/CurrentOrdersScreen.tsx +85 -0
  281. package/src/screens/LoginScreen.tsx +149 -0
  282. package/src/screens/OrdersScreen.tsx +86 -0
  283. package/src/screens/ProductDetailScreen.tsx +255 -0
  284. package/src/screens/ProfileScreen.tsx +211 -0
  285. package/src/screens/RegisterScreen.tsx +200 -0
  286. package/src/screens/ShopScreen.tsx +233 -0
  287. package/src/styles/globals.css +51 -0
@@ -0,0 +1,211 @@
1
+ 'use client';
2
+
3
+ import React, { useState } from 'react';
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
+ import { User, Mail, Phone, LogOut, Package, Heart } from 'lucide-react';
9
+ import { Button } from '@/components/ui/Button';
10
+ import { Input } from '@/components/ui/Input';
11
+ import { useAuth } from '@/providers/AuthProvider';
12
+ import { useRouter } from 'next/navigation';
13
+ import { toast } from 'sonner';
14
+ import { getInitials } from '@/lib/utils/format';
15
+ import Link from 'next/link';
16
+
17
+ const profileSchema = z.object({
18
+ firstName: z.string().min(2, 'First name is required'),
19
+ lastName: z.string().min(2, 'Last name is required'),
20
+ email: z.string().email('Invalid email address'),
21
+ phone: z.string().optional(),
22
+ });
23
+
24
+ type ProfileFormData = z.infer<typeof profileSchema>;
25
+
26
+ export function ProfileScreen() {
27
+ const router = useRouter();
28
+ const { user, updateUser, logout } = useAuth();
29
+ const [isSubmitting, setIsSubmitting] = useState(false);
30
+
31
+ const {
32
+ register,
33
+ handleSubmit,
34
+ formState: { errors },
35
+ } = useForm<ProfileFormData>({
36
+ resolver: zodResolver(profileSchema),
37
+ defaultValues: {
38
+ firstName: user?.firstName || '',
39
+ lastName: user?.lastName || '',
40
+ email: user?.email || '',
41
+ phone: user?.phone || '',
42
+ },
43
+ });
44
+
45
+ const onSubmit = async (data: ProfileFormData) => {
46
+ setIsSubmitting(true);
47
+ try {
48
+ await updateUser(data);
49
+ toast.success('Profile updated successfully!');
50
+ } catch (error: any) {
51
+ toast.error(error.response?.data?.message || 'Failed to update profile');
52
+ } finally {
53
+ setIsSubmitting(false);
54
+ }
55
+ };
56
+
57
+ const handleLogout = async () => {
58
+ await logout();
59
+ toast.success('Logged out successfully');
60
+ router.push('/');
61
+ };
62
+
63
+ if (!user) {
64
+ router.push('/login');
65
+ return null;
66
+ }
67
+
68
+ const menuItems = [
69
+ {
70
+ icon: Package,
71
+ label: 'My Orders',
72
+ href: '/orders',
73
+ description: 'View and track your orders',
74
+ },
75
+ {
76
+ icon: Heart,
77
+ label: 'Wishlist',
78
+ href: '/wishlist',
79
+ description: 'Your saved products',
80
+ },
81
+ ];
82
+
83
+ return (
84
+ <div className="min-h-screen bg-gray-50 py-12">
85
+ <div className="container mx-auto px-4 max-w-4xl">
86
+ {/* Header */}
87
+ <motion.div
88
+ initial={{ opacity: 0, y: 20 }}
89
+ animate={{ opacity: 1, y: 0 }}
90
+ className="mb-8"
91
+ >
92
+ <h1 className="text-4xl font-bold text-gray-900 mb-2">My Account</h1>
93
+ <p className="text-gray-600">Manage your profile and preferences</p>
94
+ </motion.div>
95
+
96
+ <div className="grid md:grid-cols-3 gap-8">
97
+ {/* Sidebar */}
98
+ <div className="md:col-span-1">
99
+ <motion.div
100
+ initial={{ opacity: 0, y: 20 }}
101
+ animate={{ opacity: 1, y: 0 }}
102
+ transition={{ delay: 0.1 }}
103
+ className="bg-white rounded-2xl p-6 shadow-sm"
104
+ >
105
+ {/* Avatar */}
106
+ <div className="flex flex-col items-center mb-6">
107
+ <div className="w-24 h-24 bg-gradient-to-br from-primary-500 to-secondary-500 rounded-full flex items-center justify-center text-white text-3xl font-bold mb-4">
108
+ {getInitials(user.firstName, user.lastName)}
109
+ </div>
110
+ <h3 className="text-xl font-bold text-gray-900">
111
+ {user.firstName} {user.lastName}
112
+ </h3>
113
+ <p className="text-gray-600">{user.email}</p>
114
+ </div>
115
+
116
+ {/* Menu Items */}
117
+ <nav className="space-y-2">
118
+ {menuItems.map((item) => (
119
+ <Link
120
+ key={item.href}
121
+ href={item.href}
122
+ className="flex items-start gap-3 p-3 rounded-lg hover:bg-gray-50 transition-colors group"
123
+ >
124
+ <item.icon className="w-5 h-5 text-gray-500 group-hover:text-primary-600 mt-0.5" />
125
+ <div>
126
+ <p className="font-medium text-gray-900 group-hover:text-primary-600">
127
+ {item.label}
128
+ </p>
129
+ <p className="text-sm text-gray-500">{item.description}</p>
130
+ </div>
131
+ </Link>
132
+ ))}
133
+ </nav>
134
+
135
+ {/* Logout Button */}
136
+ <button
137
+ onClick={handleLogout}
138
+ className="w-full mt-6 flex items-center justify-center gap-2 p-3 text-red-600 hover:bg-red-50 rounded-lg transition-colors font-medium"
139
+ >
140
+ <LogOut className="w-5 h-5" />
141
+ Logout
142
+ </button>
143
+ </motion.div>
144
+ </div>
145
+
146
+ {/* Main Content */}
147
+ <div className="md:col-span-2">
148
+ <motion.div
149
+ initial={{ opacity: 0, y: 20 }}
150
+ animate={{ opacity: 1, y: 0 }}
151
+ transition={{ delay: 0.2 }}
152
+ className="bg-white rounded-2xl p-8 shadow-sm"
153
+ >
154
+ <h2 className="text-2xl font-bold text-gray-900 mb-6">
155
+ Personal Information
156
+ </h2>
157
+
158
+ <form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
159
+ <div className="grid grid-cols-2 gap-4">
160
+ <Input
161
+ label="First Name"
162
+ {...register('firstName')}
163
+ error={errors.firstName?.message}
164
+ />
165
+ <Input
166
+ label="Last Name"
167
+ {...register('lastName')}
168
+ error={errors.lastName?.message}
169
+ />
170
+ </div>
171
+
172
+ <Input
173
+ type="email"
174
+ label="Email Address"
175
+ {...register('email')}
176
+ error={errors.email?.message}
177
+ />
178
+
179
+ <Input
180
+ type="tel"
181
+ label="Phone Number"
182
+ {...register('phone')}
183
+ error={errors.phone?.message}
184
+ />
185
+
186
+ <div className="flex gap-4">
187
+ <Button
188
+ type="submit"
189
+ size="lg"
190
+ isLoading={isSubmitting}
191
+ >
192
+ Save Changes
193
+ </Button>
194
+ <Button
195
+ type="button"
196
+ variant="outline"
197
+ size="lg"
198
+ onClick={() => router.push('/account/change-password')}
199
+ >
200
+ Change Password
201
+ </Button>
202
+ </div>
203
+ </form>
204
+ </motion.div>
205
+ </div>
206
+ </div>
207
+ </div>
208
+ </div>
209
+ );
210
+ }
211
+
@@ -0,0 +1,200 @@
1
+ 'use client';
2
+
3
+ import React, { useState } from 'react';
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
+ import { UserPlus, Eye, EyeOff } from 'lucide-react';
9
+ import { Button } from '@/components/ui/Button';
10
+ import { Input } from '@/components/ui/Input';
11
+ import { useAuth } from '@/providers/AuthProvider';
12
+ import { useRouter } from 'next/navigation';
13
+ import { toast } from 'sonner';
14
+ import Link from 'next/link';
15
+
16
+ const registerSchema = z.object({
17
+ firstName: z.string().min(2, 'First name is required'),
18
+ lastName: z.string().min(2, 'Last name is required'),
19
+ email: z.string().email('Invalid email address'),
20
+ phone: z.string().optional(),
21
+ password: z.string().min(6, 'Password must be at least 6 characters'),
22
+ confirmPassword: z.string(),
23
+ }).refine((data) => data.password === data.confirmPassword, {
24
+ message: "Passwords don't match",
25
+ path: ['confirmPassword'],
26
+ });
27
+
28
+ type RegisterFormData = z.infer<typeof registerSchema>;
29
+
30
+ export function RegisterScreen() {
31
+ const router = useRouter();
32
+ const { register: registerUser } = useAuth();
33
+ const [showPassword, setShowPassword] = useState(false);
34
+ const [showConfirmPassword, setShowConfirmPassword] = useState(false);
35
+ const [isSubmitting, setIsSubmitting] = useState(false);
36
+
37
+ const {
38
+ register,
39
+ handleSubmit,
40
+ formState: { errors },
41
+ } = useForm<RegisterFormData>({
42
+ resolver: zodResolver(registerSchema),
43
+ });
44
+
45
+ const onSubmit = async (data: RegisterFormData) => {
46
+ setIsSubmitting(true);
47
+ try {
48
+ const { confirmPassword, ...registerData } = data;
49
+ await registerUser(registerData);
50
+ toast.success('Account created successfully!');
51
+ router.push('/');
52
+ } catch (error: any) {
53
+ toast.error(error.response?.data?.message || 'Failed to create account');
54
+ } finally {
55
+ setIsSubmitting(false);
56
+ }
57
+ };
58
+
59
+ return (
60
+ <div className="min-h-screen bg-gradient-to-br from-primary-600 via-primary-700 to-secondary-600 flex items-center justify-center p-4">
61
+ <motion.div
62
+ initial={{ opacity: 0, y: 20 }}
63
+ animate={{ opacity: 1, y: 0 }}
64
+ className="w-full max-w-md"
65
+ >
66
+ <div className="bg-white rounded-3xl shadow-2xl p-8">
67
+ {/* Header */}
68
+ <div className="text-center mb-8">
69
+ <div className="w-16 h-16 bg-primary-100 rounded-full flex items-center justify-center mx-auto mb-4">
70
+ <UserPlus className="w-8 h-8 text-primary-600" />
71
+ </div>
72
+ <h1 className="text-3xl font-bold text-gray-900 mb-2">Create Account</h1>
73
+ <p className="text-gray-600">Join us and start shopping</p>
74
+ </div>
75
+
76
+ {/* Form */}
77
+ <form onSubmit={handleSubmit(onSubmit)} className="space-y-5">
78
+ <div className="grid grid-cols-2 gap-4">
79
+ <Input
80
+ label="First Name"
81
+ placeholder="John"
82
+ {...register('firstName')}
83
+ error={errors.firstName?.message}
84
+ />
85
+ <Input
86
+ label="Last Name"
87
+ placeholder="Doe"
88
+ {...register('lastName')}
89
+ error={errors.lastName?.message}
90
+ />
91
+ </div>
92
+
93
+ <Input
94
+ type="email"
95
+ label="Email Address"
96
+ placeholder="you@example.com"
97
+ {...register('email')}
98
+ error={errors.email?.message}
99
+ />
100
+
101
+ <Input
102
+ type="tel"
103
+ label="Phone Number (Optional)"
104
+ placeholder="+1 (555) 000-0000"
105
+ {...register('phone')}
106
+ error={errors.phone?.message}
107
+ />
108
+
109
+ <div className="relative">
110
+ <Input
111
+ type={showPassword ? 'text' : 'password'}
112
+ label="Password"
113
+ placeholder="••••••••"
114
+ {...register('password')}
115
+ error={errors.password?.message}
116
+ />
117
+ <button
118
+ type="button"
119
+ onClick={() => setShowPassword(!showPassword)}
120
+ className="absolute right-3 top-[42px] text-gray-500 hover:text-gray-700"
121
+ >
122
+ {showPassword ? (
123
+ <EyeOff className="w-5 h-5" />
124
+ ) : (
125
+ <Eye className="w-5 h-5" />
126
+ )}
127
+ </button>
128
+ </div>
129
+
130
+ <div className="relative">
131
+ <Input
132
+ type={showConfirmPassword ? 'text' : 'password'}
133
+ label="Confirm Password"
134
+ placeholder="••••••••"
135
+ {...register('confirmPassword')}
136
+ error={errors.confirmPassword?.message}
137
+ />
138
+ <button
139
+ type="button"
140
+ onClick={() => setShowConfirmPassword(!showConfirmPassword)}
141
+ className="absolute right-3 top-[42px] text-gray-500 hover:text-gray-700"
142
+ >
143
+ {showConfirmPassword ? (
144
+ <EyeOff className="w-5 h-5" />
145
+ ) : (
146
+ <Eye className="w-5 h-5" />
147
+ )}
148
+ </button>
149
+ </div>
150
+
151
+ <div className="flex items-start gap-2">
152
+ <input
153
+ type="checkbox"
154
+ required
155
+ className="w-4 h-4 text-primary-600 rounded mt-1"
156
+ />
157
+ <label className="text-sm text-gray-700">
158
+ I agree to the{' '}
159
+ <Link href="/terms" className="text-primary-600 hover:text-primary-700">
160
+ Terms of Service
161
+ </Link>{' '}
162
+ and{' '}
163
+ <Link href="/privacy" className="text-primary-600 hover:text-primary-700">
164
+ Privacy Policy
165
+ </Link>
166
+ </label>
167
+ </div>
168
+
169
+ <Button
170
+ type="submit"
171
+ size="lg"
172
+ isLoading={isSubmitting}
173
+ className="w-full"
174
+ >
175
+ Create Account
176
+ </Button>
177
+ </form>
178
+
179
+ {/* Divider */}
180
+ <div className="relative my-8">
181
+ <div className="absolute inset-0 flex items-center">
182
+ <div className="w-full border-t border-gray-200"></div>
183
+ </div>
184
+ <div className="relative flex justify-center text-sm">
185
+ <span className="px-4 bg-white text-gray-500">Already have an account?</span>
186
+ </div>
187
+ </div>
188
+
189
+ {/* Login Link */}
190
+ <Link href="/login">
191
+ <Button variant="outline" size="lg" className="w-full">
192
+ Sign In
193
+ </Button>
194
+ </Link>
195
+ </div>
196
+ </motion.div>
197
+ </div>
198
+ );
199
+ }
200
+
@@ -0,0 +1,233 @@
1
+ 'use client';
2
+
3
+ import React, { useState } from 'react';
4
+ import { motion } from 'framer-motion';
5
+ import { Search, SlidersHorizontal, X } from 'lucide-react';
6
+ import { ProductCard } from '@/components/ProductCard';
7
+ import { ProductCardSkeleton } from '@/components/ui/Skeleton';
8
+ import { EmptyState } from '@/components/EmptyState';
9
+ import { Button } from '@/components/ui/Button';
10
+ import { Input } from '@/components/ui/Input';
11
+ import { useProducts, useCategories } from '@/hooks/useProducts';
12
+ import { ProductFilters } from '@/lib/types';
13
+ import { Package } from 'lucide-react';
14
+ import { useRouter } from 'next/navigation';
15
+
16
+ export function ShopScreen() {
17
+ const router = useRouter();
18
+ const [filters, setFilters] = useState<ProductFilters>({});
19
+ const [page, setPage] = useState(1);
20
+ const [showFilters, setShowFilters] = useState(false);
21
+ const [searchQuery, setSearchQuery] = useState('');
22
+
23
+ const { products, isLoading, pagination } = useProducts(filters, page, 20);
24
+ const { categories } = useCategories();
25
+
26
+ const handleSearch = (e: React.FormEvent) => {
27
+ e.preventDefault();
28
+ setFilters({ ...filters, search: searchQuery });
29
+ setPage(1);
30
+ };
31
+
32
+ const handleCategoryChange = (category: string) => {
33
+ setFilters({ ...filters, category: category === filters.category ? undefined : category });
34
+ setPage(1);
35
+ };
36
+
37
+ const handleClearFilters = () => {
38
+ setFilters({});
39
+ setSearchQuery('');
40
+ setPage(1);
41
+ };
42
+
43
+ const hasActiveFilters = Object.keys(filters).length > 0;
44
+
45
+ return (
46
+ <div className="min-h-screen bg-gray-50">
47
+ {/* Hero Section */}
48
+ <section className="bg-gradient-to-br from-primary-600 via-primary-700 to-secondary-600 text-white py-20">
49
+ <div className="container mx-auto px-4">
50
+ <motion.div
51
+ initial={{ opacity: 0, y: 20 }}
52
+ animate={{ opacity: 1, y: 0 }}
53
+ className="max-w-3xl mx-auto text-center"
54
+ >
55
+ <h1 className="text-5xl md:text-6xl font-bold mb-6">
56
+ Discover Amazing Products
57
+ </h1>
58
+ <p className="text-xl text-primary-100 mb-8">
59
+ Browse our curated collection of quality products at great prices
60
+ </p>
61
+
62
+ {/* Search Bar */}
63
+ <form onSubmit={handleSearch} className="max-w-2xl mx-auto">
64
+ <div className="relative">
65
+ <Input
66
+ type="search"
67
+ placeholder="Search for products..."
68
+ value={searchQuery}
69
+ onChange={(e) => setSearchQuery(e.target.value)}
70
+ className="pr-12 text-lg"
71
+ />
72
+ <button
73
+ type="submit"
74
+ className="absolute right-2 top-1/2 -translate-y-1/2 p-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors"
75
+ >
76
+ <Search className="w-5 h-5" />
77
+ </button>
78
+ </div>
79
+ </form>
80
+ </motion.div>
81
+ </div>
82
+ </section>
83
+
84
+ {/* Main Content */}
85
+ <div className="container mx-auto px-4 py-12">
86
+ <div className="flex gap-8">
87
+ {/* Sidebar Filters - Desktop */}
88
+ <aside className="hidden lg:block w-64 flex-shrink-0">
89
+ <div className="bg-white rounded-2xl p-6 shadow-sm sticky top-24">
90
+ <div className="flex items-center justify-between mb-6">
91
+ <h3 className="text-lg font-bold text-gray-900">Filters</h3>
92
+ {hasActiveFilters && (
93
+ <button
94
+ onClick={handleClearFilters}
95
+ className="text-sm text-primary-600 hover:text-primary-700 font-medium"
96
+ >
97
+ Clear All
98
+ </button>
99
+ )}
100
+ </div>
101
+
102
+ {/* Categories */}
103
+ <div className="space-y-4">
104
+ <h4 className="font-semibold text-gray-900">Categories</h4>
105
+ <div className="space-y-2">
106
+ {categories.map((category) => (
107
+ <label
108
+ key={category.id}
109
+ className="flex items-center gap-3 cursor-pointer hover:bg-gray-50 p-2 rounded-lg transition-colors"
110
+ >
111
+ <input
112
+ type="checkbox"
113
+ checked={filters.category === category.slug}
114
+ onChange={() => handleCategoryChange(category.slug)}
115
+ className="w-5 h-5 text-primary-600 rounded"
116
+ />
117
+ <span className="text-gray-700">{category.name}</span>
118
+ <span className="ml-auto text-sm text-gray-500">
119
+ ({category.productCount})
120
+ </span>
121
+ </label>
122
+ ))}
123
+ </div>
124
+ </div>
125
+
126
+ {/* Stock Status */}
127
+ <div className="space-y-4 mt-8">
128
+ <h4 className="font-semibold text-gray-900">Availability</h4>
129
+ <label className="flex items-center gap-3 cursor-pointer hover:bg-gray-50 p-2 rounded-lg transition-colors">
130
+ <input
131
+ type="checkbox"
132
+ checked={filters.inStock === true}
133
+ onChange={(e) =>
134
+ setFilters({ ...filters, inStock: e.target.checked ? true : undefined })
135
+ }
136
+ className="w-5 h-5 text-primary-600 rounded"
137
+ />
138
+ <span className="text-gray-700">In Stock Only</span>
139
+ </label>
140
+ </div>
141
+ </div>
142
+ </aside>
143
+
144
+ {/* Products Grid */}
145
+ <div className="flex-1">
146
+ {/* Mobile Filter Button */}
147
+ <div className="lg:hidden mb-6">
148
+ <Button
149
+ variant="outline"
150
+ onClick={() => setShowFilters(!showFilters)}
151
+ className="w-full"
152
+ >
153
+ <SlidersHorizontal className="w-5 h-5" />
154
+ Filters
155
+ {hasActiveFilters && (
156
+ <span className="ml-2 px-2 py-0.5 bg-primary-600 text-white text-xs rounded-full">
157
+ Active
158
+ </span>
159
+ )}
160
+ </Button>
161
+ </div>
162
+
163
+ {/* Results Header */}
164
+ <div className="flex items-center justify-between mb-6">
165
+ <p className="text-gray-600">
166
+ {isLoading ? (
167
+ 'Loading...'
168
+ ) : (
169
+ <>
170
+ Showing {products.length} of {pagination.total} products
171
+ </>
172
+ )}
173
+ </p>
174
+ </div>
175
+
176
+ {/* Products Grid */}
177
+ {isLoading ? (
178
+ <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
179
+ {Array.from({ length: 6 }).map((_, i) => (
180
+ <ProductCardSkeleton key={i} />
181
+ ))}
182
+ </div>
183
+ ) : products.length > 0 ? (
184
+ <>
185
+ <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
186
+ {products.map((product) => (
187
+ <ProductCard
188
+ key={product.id}
189
+ product={product}
190
+ onClickProduct={(p) => router.push(`/products/${p.id}`)}
191
+ />
192
+ ))}
193
+ </div>
194
+
195
+ {/* Pagination */}
196
+ {pagination.totalPages > 1 && (
197
+ <div className="flex justify-center items-center gap-2 mt-12">
198
+ <Button
199
+ variant="outline"
200
+ onClick={() => setPage(page - 1)}
201
+ disabled={page === 1}
202
+ >
203
+ Previous
204
+ </Button>
205
+ <span className="px-4 text-gray-700">
206
+ Page {page} of {pagination.totalPages}
207
+ </span>
208
+ <Button
209
+ variant="outline"
210
+ onClick={() => setPage(page + 1)}
211
+ disabled={page === pagination.totalPages}
212
+ >
213
+ Next
214
+ </Button>
215
+ </div>
216
+ )}
217
+ </>
218
+ ) : (
219
+ <EmptyState
220
+ icon={Package}
221
+ title="No products found"
222
+ description="Try adjusting your filters or search query"
223
+ actionLabel={hasActiveFilters ? 'Clear Filters' : undefined}
224
+ onAction={hasActiveFilters ? handleClearFilters : undefined}
225
+ />
226
+ )}
227
+ </div>
228
+ </div>
229
+ </div>
230
+ </div>
231
+ );
232
+ }
233
+
@@ -0,0 +1,51 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ * {
7
+ @apply border-gray-200;
8
+ }
9
+
10
+ body {
11
+ @apply bg-gray-50 text-gray-900 antialiased;
12
+ }
13
+ }
14
+
15
+ @layer utilities {
16
+ .animate-gradient {
17
+ animation: gradient 3s ease infinite;
18
+ background-size: 200% 200%;
19
+ }
20
+
21
+ @keyframes gradient {
22
+ 0% {
23
+ background-position: 0% 50%;
24
+ }
25
+ 50% {
26
+ background-position: 100% 50%;
27
+ }
28
+ 100% {
29
+ background-position: 0% 50%;
30
+ }
31
+ }
32
+ }
33
+
34
+ /* Custom scrollbar */
35
+ ::-webkit-scrollbar {
36
+ width: 8px;
37
+ height: 8px;
38
+ }
39
+
40
+ ::-webkit-scrollbar-track {
41
+ @apply bg-gray-100;
42
+ }
43
+
44
+ ::-webkit-scrollbar-thumb {
45
+ @apply bg-gray-300 rounded-full;
46
+ }
47
+
48
+ ::-webkit-scrollbar-thumb:hover {
49
+ @apply bg-gray-400;
50
+ }
51
+