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,122 @@
1
+ 'use client';
2
+
3
+ import React, { useState } from 'react';
4
+ import { motion } from 'framer-motion';
5
+ import { ShoppingCart, Heart } from 'lucide-react';
6
+ import { Product } from '@/lib/types';
7
+ import { formatPrice } from '@/lib/utils/format';
8
+ import { useCart } from '@/providers/CartProvider';
9
+ import Image from 'next/image';
10
+
11
+ interface ProductCardProps {
12
+ product: Product;
13
+ onClickProduct?: (product: Product) => void;
14
+ }
15
+
16
+ export function ProductCard({ product, onClickProduct }: ProductCardProps) {
17
+ const { addToCart } = useCart();
18
+ const [isAdding, setIsAdding] = useState(false);
19
+ const [isFavorited, setIsFavorited] = useState(false);
20
+
21
+ const handleAddToCart = async (e: React.MouseEvent) => {
22
+ e.stopPropagation();
23
+ setIsAdding(true);
24
+ try {
25
+ await addToCart(product.id);
26
+ } finally {
27
+ setIsAdding(false);
28
+ }
29
+ };
30
+
31
+ const handleFavorite = (e: React.MouseEvent) => {
32
+ e.stopPropagation();
33
+ setIsFavorited(!isFavorited);
34
+ };
35
+
36
+ const discount = product.compareAtPrice
37
+ ? Math.round(((product.compareAtPrice - product.price) / product.compareAtPrice) * 100)
38
+ : 0;
39
+
40
+ return (
41
+ <motion.div
42
+ whileHover={{ y: -8 }}
43
+ className="group bg-white rounded-2xl overflow-hidden shadow-sm hover:shadow-2xl transition-all duration-300 cursor-pointer"
44
+ onClick={() => onClickProduct?.(product)}
45
+ >
46
+ {/* Image Container */}
47
+ <div className="relative aspect-square overflow-hidden bg-gray-100">
48
+ <Image
49
+ src={product.images[0] || '/placeholder-product.jpg'}
50
+ alt={product.name}
51
+ fill
52
+ className="object-cover group-hover:scale-110 transition-transform duration-500"
53
+ />
54
+
55
+ {/* Badges */}
56
+ <div className="absolute top-4 left-4 flex flex-col gap-2">
57
+ {discount > 0 && (
58
+ <span className="bg-red-500 text-white px-3 py-1 rounded-full text-sm font-bold">
59
+ -{discount}%
60
+ </span>
61
+ )}
62
+ {!product.inStock && (
63
+ <span className="bg-gray-900 text-white px-3 py-1 rounded-full text-sm font-bold">
64
+ Out of Stock
65
+ </span>
66
+ )}
67
+ </div>
68
+
69
+ {/* Favorite Button */}
70
+ <button
71
+ onClick={handleFavorite}
72
+ className="absolute top-4 right-4 p-2 bg-white/90 backdrop-blur-sm rounded-full shadow-lg opacity-0 group-hover:opacity-100 transition-all duration-300 hover:scale-110"
73
+ >
74
+ <Heart
75
+ className={`w-5 h-5 ${isFavorited ? 'fill-red-500 text-red-500' : 'text-gray-700'}`}
76
+ />
77
+ </button>
78
+
79
+ {/* Quick Add Button - Shows on hover */}
80
+ {product.inStock && (
81
+ <motion.button
82
+ onClick={handleAddToCart}
83
+ disabled={isAdding}
84
+ className="absolute bottom-4 left-4 right-4 bg-primary-600 text-white py-3 rounded-xl font-medium opacity-0 group-hover:opacity-100 transition-all duration-300 hover:bg-primary-700 flex items-center justify-center gap-2 shadow-lg"
85
+ whileTap={{ scale: 0.95 }}
86
+ >
87
+ <ShoppingCart className="w-5 h-5" />
88
+ {isAdding ? 'Adding...' : 'Quick Add'}
89
+ </motion.button>
90
+ )}
91
+ </div>
92
+
93
+ {/* Content */}
94
+ <div className="p-4">
95
+ {/* Category */}
96
+ {product.category && (
97
+ <p className="text-xs text-gray-500 uppercase tracking-wider mb-2">
98
+ {product.category}
99
+ </p>
100
+ )}
101
+
102
+ {/* Product Name */}
103
+ <h3 className="text-lg font-semibold text-gray-900 mb-2 line-clamp-2 group-hover:text-primary-600 transition-colors">
104
+ {product.name}
105
+ </h3>
106
+
107
+ {/* Price */}
108
+ <div className="flex items-baseline gap-2">
109
+ <span className="text-2xl font-bold text-gray-900">
110
+ {formatPrice(product.price)}
111
+ </span>
112
+ {product.compareAtPrice && (
113
+ <span className="text-sm text-gray-500 line-through">
114
+ {formatPrice(product.compareAtPrice)}
115
+ </span>
116
+ )}
117
+ </div>
118
+ </div>
119
+ </motion.div>
120
+ );
121
+ }
122
+
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+
3
+ interface BadgeProps {
4
+ children: React.ReactNode;
5
+ variant?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'gray';
6
+ size?: 'sm' | 'md';
7
+ className?: string;
8
+ }
9
+
10
+ export function Badge({ children, variant = 'primary', size = 'md', className = '' }: BadgeProps) {
11
+ const variants = {
12
+ primary: 'bg-primary-100 text-primary-700 border-primary-200',
13
+ secondary: 'bg-secondary-100 text-secondary-700 border-secondary-200',
14
+ success: 'bg-green-100 text-green-700 border-green-200',
15
+ warning: 'bg-yellow-100 text-yellow-700 border-yellow-200',
16
+ danger: 'bg-red-100 text-red-700 border-red-200',
17
+ gray: 'bg-gray-100 text-gray-700 border-gray-200',
18
+ };
19
+
20
+ const sizes = {
21
+ sm: 'px-2 py-1 text-xs',
22
+ md: 'px-3 py-1 text-sm',
23
+ };
24
+
25
+ return (
26
+ <span className={`inline-flex items-center font-medium rounded-full border ${variants[variant]} ${sizes[size]} ${className}`}>
27
+ {children}
28
+ </span>
29
+ );
30
+ }
31
+
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import { motion } from 'framer-motion';
3
+
4
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
5
+ variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
6
+ size?: 'sm' | 'md' | 'lg';
7
+ isLoading?: boolean;
8
+ children: React.ReactNode;
9
+ }
10
+
11
+ export function Button({
12
+ variant = 'primary',
13
+ size = 'md',
14
+ isLoading = false,
15
+ disabled,
16
+ className = '',
17
+ children,
18
+ ...props
19
+ }: ButtonProps) {
20
+ const baseStyles = 'font-medium rounded-lg transition-all duration-200 inline-flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed';
21
+
22
+ const variants = {
23
+ primary: 'bg-primary-600 text-white hover:bg-primary-700 shadow-lg shadow-primary-500/30 hover:shadow-xl hover:shadow-primary-500/40',
24
+ secondary: 'bg-secondary-600 text-white hover:bg-secondary-700 shadow-lg shadow-secondary-500/30 hover:shadow-xl hover:shadow-secondary-500/40',
25
+ outline: 'border-2 border-primary-600 text-primary-600 hover:bg-primary-50',
26
+ ghost: 'text-gray-700 hover:bg-gray-100',
27
+ };
28
+
29
+ const sizes = {
30
+ sm: 'px-4 py-2 text-sm',
31
+ md: 'px-6 py-3 text-base',
32
+ lg: 'px-8 py-4 text-lg',
33
+ };
34
+
35
+ return (
36
+ <motion.div
37
+ whileHover={{ scale: 1.02 }}
38
+ whileTap={{ scale: 0.98 }}
39
+ className="inline-block"
40
+ >
41
+ <button
42
+ className={`${baseStyles} ${variants[variant]} ${sizes[size]} ${className}`}
43
+ disabled={disabled || isLoading}
44
+ {...props}
45
+ >
46
+ {isLoading ? (
47
+ <>
48
+ <svg className="animate-spin h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
49
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
50
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
51
+ </svg>
52
+ Loading...
53
+ </>
54
+ ) : (
55
+ children
56
+ )}
57
+ </button>
58
+ </motion.div>
59
+ );
60
+ }
61
+
@@ -0,0 +1,45 @@
1
+ import React, { forwardRef } from 'react';
2
+
3
+ interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
4
+ label?: string;
5
+ error?: string;
6
+ helperText?: string;
7
+ }
8
+
9
+ export const Input = forwardRef<HTMLInputElement, InputProps>(
10
+ ({ label, error, helperText, className = '', ...props }, ref) => {
11
+ return (
12
+ <div className="w-full">
13
+ {label && (
14
+ <label className="block text-sm font-medium text-gray-700 mb-2">
15
+ {label}
16
+ </label>
17
+ )}
18
+ <input
19
+ ref={ref}
20
+ className={`
21
+ w-full px-4 py-3 rounded-lg border-2 transition-all duration-200
22
+ ${error
23
+ ? 'border-red-500 focus:border-red-600 focus:ring-red-500/20'
24
+ : 'border-gray-200 focus:border-primary-500 focus:ring-primary-500/20'
25
+ }
26
+ focus:outline-none focus:ring-4
27
+ placeholder:text-gray-400
28
+ disabled:bg-gray-50 disabled:cursor-not-allowed
29
+ ${className}
30
+ `}
31
+ {...props}
32
+ />
33
+ {error && (
34
+ <p className="mt-2 text-sm text-red-600">{error}</p>
35
+ )}
36
+ {helperText && !error && (
37
+ <p className="mt-2 text-sm text-gray-500">{helperText}</p>
38
+ )}
39
+ </div>
40
+ );
41
+ }
42
+ );
43
+
44
+ Input.displayName = 'Input';
45
+
@@ -0,0 +1,79 @@
1
+ 'use client';
2
+
3
+ import React, { useEffect } from 'react';
4
+ import { motion, AnimatePresence } from 'framer-motion';
5
+ import { X } from 'lucide-react';
6
+
7
+ interface ModalProps {
8
+ isOpen: boolean;
9
+ onClose: () => void;
10
+ title?: string;
11
+ children: React.ReactNode;
12
+ size?: 'sm' | 'md' | 'lg' | 'xl';
13
+ }
14
+
15
+ export function Modal({ isOpen, onClose, title, children, size = 'md' }: ModalProps) {
16
+ useEffect(() => {
17
+ if (isOpen) {
18
+ document.body.style.overflow = 'hidden';
19
+ } else {
20
+ document.body.style.overflow = 'unset';
21
+ }
22
+ return () => {
23
+ document.body.style.overflow = 'unset';
24
+ };
25
+ }, [isOpen]);
26
+
27
+ const sizes = {
28
+ sm: 'max-w-md',
29
+ md: 'max-w-lg',
30
+ lg: 'max-w-2xl',
31
+ xl: 'max-w-4xl',
32
+ };
33
+
34
+ return (
35
+ <AnimatePresence>
36
+ {isOpen && (
37
+ <>
38
+ {/* Backdrop */}
39
+ <motion.div
40
+ initial={{ opacity: 0 }}
41
+ animate={{ opacity: 1 }}
42
+ exit={{ opacity: 0 }}
43
+ onClick={onClose}
44
+ className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50"
45
+ />
46
+
47
+ {/* Modal */}
48
+ <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
49
+ <motion.div
50
+ initial={{ opacity: 0, scale: 0.95, y: 20 }}
51
+ animate={{ opacity: 1, scale: 1, y: 0 }}
52
+ exit={{ opacity: 0, scale: 0.95, y: 20 }}
53
+ className={`bg-white rounded-2xl shadow-2xl w-full ${sizes[size]} max-h-[90vh] overflow-hidden flex flex-col`}
54
+ >
55
+ {/* Header */}
56
+ {title && (
57
+ <div className="flex items-center justify-between p-6 border-b border-gray-200">
58
+ <h2 className="text-2xl font-bold text-gray-900">{title}</h2>
59
+ <button
60
+ onClick={onClose}
61
+ className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
62
+ >
63
+ <X className="w-5 h-5" />
64
+ </button>
65
+ </div>
66
+ )}
67
+
68
+ {/* Content */}
69
+ <div className="flex-1 overflow-y-auto p-6">
70
+ {children}
71
+ </div>
72
+ </motion.div>
73
+ </div>
74
+ </>
75
+ )}
76
+ </AnimatePresence>
77
+ );
78
+ }
79
+
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+
3
+ interface SkeletonProps {
4
+ className?: string;
5
+ }
6
+
7
+ export function Skeleton({ className = '' }: SkeletonProps) {
8
+ return (
9
+ <div className={`animate-pulse bg-gradient-to-r from-gray-200 via-gray-300 to-gray-200 bg-[length:200%_100%] rounded ${className}`} />
10
+ );
11
+ }
12
+
13
+ export function ProductCardSkeleton() {
14
+ return (
15
+ <div className="bg-white rounded-2xl overflow-hidden shadow-sm">
16
+ <Skeleton className="h-64 w-full" />
17
+ <div className="p-4 space-y-3">
18
+ <Skeleton className="h-6 w-3/4" />
19
+ <Skeleton className="h-4 w-1/2" />
20
+ <div className="flex justify-between items-center pt-2">
21
+ <Skeleton className="h-8 w-24" />
22
+ <Skeleton className="h-10 w-10 rounded-full" />
23
+ </div>
24
+ </div>
25
+ </div>
26
+ );
27
+ }
28
+
29
+ export function OrderCardSkeleton() {
30
+ return (
31
+ <div className="bg-white rounded-2xl p-6 shadow-sm">
32
+ <div className="flex justify-between items-start mb-4">
33
+ <div className="space-y-2 flex-1">
34
+ <Skeleton className="h-6 w-32" />
35
+ <Skeleton className="h-4 w-48" />
36
+ </div>
37
+ <Skeleton className="h-6 w-20 rounded-full" />
38
+ </div>
39
+ <div className="space-y-3">
40
+ <Skeleton className="h-4 w-full" />
41
+ <Skeleton className="h-4 w-2/3" />
42
+ </div>
43
+ </div>
44
+ );
45
+ }
46
+
@@ -0,0 +1,98 @@
1
+ import { useState, useEffect, useCallback } from 'react';
2
+ import { Order } from '@/lib/types';
3
+ import { ordersApi } from '@/lib/api/orders';
4
+
5
+ export function useOrders(page: number = 1, limit: number = 10) {
6
+ const [orders, setOrders] = useState<Order[]>([]);
7
+ const [isLoading, setIsLoading] = useState(true);
8
+ const [error, setError] = useState<Error | null>(null);
9
+ const [pagination, setPagination] = useState({
10
+ page: 1,
11
+ limit: 10,
12
+ total: 0,
13
+ totalPages: 0,
14
+ });
15
+
16
+ const fetchOrders = useCallback(async () => {
17
+ setIsLoading(true);
18
+ setError(null);
19
+ try {
20
+ const response = await ordersApi.getOrders(page, limit);
21
+ setOrders(response.data);
22
+ setPagination(response.pagination);
23
+ } catch (err) {
24
+ setError(err as Error);
25
+ } finally {
26
+ setIsLoading(false);
27
+ }
28
+ }, [page, limit]);
29
+
30
+ useEffect(() => {
31
+ fetchOrders();
32
+ }, [fetchOrders]);
33
+
34
+ return {
35
+ orders,
36
+ isLoading,
37
+ error,
38
+ pagination,
39
+ refetch: fetchOrders,
40
+ };
41
+ }
42
+
43
+ export function useOrder(id: string) {
44
+ const [order, setOrder] = useState<Order | null>(null);
45
+ const [isLoading, setIsLoading] = useState(true);
46
+ const [error, setError] = useState<Error | null>(null);
47
+
48
+ const fetchOrder = useCallback(async () => {
49
+ setIsLoading(true);
50
+ setError(null);
51
+ try {
52
+ const response = await ordersApi.getOrder(id);
53
+ if (response.success) {
54
+ setOrder(response.data);
55
+ }
56
+ } catch (err) {
57
+ setError(err as Error);
58
+ } finally {
59
+ setIsLoading(false);
60
+ }
61
+ }, [id]);
62
+
63
+ useEffect(() => {
64
+ if (id) {
65
+ fetchOrder();
66
+ }
67
+ }, [id, fetchOrder]);
68
+
69
+ return { order, isLoading, error, refetch: fetchOrder };
70
+ }
71
+
72
+ export function useCurrentOrders() {
73
+ const [orders, setOrders] = useState<Order[]>([]);
74
+ const [isLoading, setIsLoading] = useState(true);
75
+ const [error, setError] = useState<Error | null>(null);
76
+
77
+ const fetchCurrentOrders = useCallback(async () => {
78
+ setIsLoading(true);
79
+ setError(null);
80
+ try {
81
+ const response = await ordersApi.getCurrentOrders();
82
+ if (response.success) {
83
+ setOrders(response.data);
84
+ }
85
+ } catch (err) {
86
+ setError(err as Error);
87
+ } finally {
88
+ setIsLoading(false);
89
+ }
90
+ }, []);
91
+
92
+ useEffect(() => {
93
+ fetchCurrentOrders();
94
+ }, [fetchCurrentOrders]);
95
+
96
+ return { orders, isLoading, error, refetch: fetchCurrentOrders };
97
+ }
98
+
@@ -0,0 +1,125 @@
1
+ import { useState, useEffect, useCallback } from 'react';
2
+ import { Product, ProductFilters, Category } from '@/lib/types';
3
+ import { productsApi } from '@/lib/api/products';
4
+
5
+ export function useProducts(filters?: ProductFilters, page: number = 1, limit: number = 20) {
6
+ const [products, setProducts] = useState<Product[]>([]);
7
+ const [isLoading, setIsLoading] = useState(true);
8
+ const [error, setError] = useState<Error | null>(null);
9
+ const [pagination, setPagination] = useState({
10
+ page: 1,
11
+ limit: 20,
12
+ total: 0,
13
+ totalPages: 0,
14
+ });
15
+
16
+ const fetchProducts = useCallback(async () => {
17
+ setIsLoading(true);
18
+ setError(null);
19
+ try {
20
+ const response = await productsApi.getProducts(filters, page, limit);
21
+ setProducts(response.data);
22
+ setPagination(response.pagination);
23
+ } catch (err) {
24
+ setError(err as Error);
25
+ } finally {
26
+ setIsLoading(false);
27
+ }
28
+ }, [filters, page, limit]);
29
+
30
+ useEffect(() => {
31
+ fetchProducts();
32
+ }, [fetchProducts]);
33
+
34
+ return {
35
+ products,
36
+ isLoading,
37
+ error,
38
+ pagination,
39
+ refetch: fetchProducts,
40
+ };
41
+ }
42
+
43
+ export function useProduct(id: string) {
44
+ const [product, setProduct] = useState<Product | null>(null);
45
+ const [isLoading, setIsLoading] = useState(true);
46
+ const [error, setError] = useState<Error | null>(null);
47
+
48
+ useEffect(() => {
49
+ const fetchProduct = async () => {
50
+ setIsLoading(true);
51
+ setError(null);
52
+ try {
53
+ const response = await productsApi.getProduct(id);
54
+ if (response.success) {
55
+ setProduct(response.data);
56
+ }
57
+ } catch (err) {
58
+ setError(err as Error);
59
+ } finally {
60
+ setIsLoading(false);
61
+ }
62
+ };
63
+
64
+ if (id) {
65
+ fetchProduct();
66
+ }
67
+ }, [id]);
68
+
69
+ return { product, isLoading, error };
70
+ }
71
+
72
+ export function useFeaturedProducts(limit: number = 8) {
73
+ const [products, setProducts] = useState<Product[]>([]);
74
+ const [isLoading, setIsLoading] = useState(true);
75
+ const [error, setError] = useState<Error | null>(null);
76
+
77
+ useEffect(() => {
78
+ const fetchFeaturedProducts = async () => {
79
+ setIsLoading(true);
80
+ setError(null);
81
+ try {
82
+ const response = await productsApi.getFeaturedProducts(limit);
83
+ if (response.success) {
84
+ setProducts(response.data);
85
+ }
86
+ } catch (err) {
87
+ setError(err as Error);
88
+ } finally {
89
+ setIsLoading(false);
90
+ }
91
+ };
92
+
93
+ fetchFeaturedProducts();
94
+ }, [limit]);
95
+
96
+ return { products, isLoading, error };
97
+ }
98
+
99
+ export function useCategories() {
100
+ const [categories, setCategories] = useState<Category[]>([]);
101
+ const [isLoading, setIsLoading] = useState(true);
102
+ const [error, setError] = useState<Error | null>(null);
103
+
104
+ useEffect(() => {
105
+ const fetchCategories = async () => {
106
+ setIsLoading(true);
107
+ setError(null);
108
+ try {
109
+ const response = await productsApi.getCategories();
110
+ if (response.success) {
111
+ setCategories(response.data);
112
+ }
113
+ } catch (err) {
114
+ setError(err as Error);
115
+ } finally {
116
+ setIsLoading(false);
117
+ }
118
+ };
119
+
120
+ fetchCategories();
121
+ }, []);
122
+
123
+ return { categories, isLoading, error };
124
+ }
125
+
package/src/index.ts ADDED
@@ -0,0 +1,71 @@
1
+ // Main Provider
2
+ export { EcommerceProvider } from './providers/EcommerceProvider';
3
+
4
+ // Individual Providers
5
+ export { ThemeProvider, useTheme } from './providers/ThemeProvider';
6
+ export { AuthProvider, useAuth } from './providers/AuthProvider';
7
+ export { CartProvider, useCart } from './providers/CartProvider';
8
+
9
+ // Screens
10
+ export { ShopScreen } from './screens/ShopScreen';
11
+ export { ProductDetailScreen } from './screens/ProductDetailScreen';
12
+ export { CartScreen } from './screens/CartScreen';
13
+ export { CheckoutScreen } from './screens/CheckoutScreen';
14
+ export { LoginScreen } from './screens/LoginScreen';
15
+ export { RegisterScreen } from './screens/RegisterScreen';
16
+ export { ProfileScreen } from './screens/ProfileScreen';
17
+ export { OrdersScreen } from './screens/OrdersScreen';
18
+ export { CurrentOrdersScreen } from './screens/CurrentOrdersScreen';
19
+
20
+ // Components
21
+ export { Header } from './components/Header';
22
+ export { Footer } from './components/Footer';
23
+ export { ProductCard } from './components/ProductCard';
24
+ export { CartItem } from './components/CartItem';
25
+ export { OrderCard } from './components/OrderCard';
26
+ export { EmptyState } from './components/EmptyState';
27
+
28
+ // UI Components
29
+ export { Button } from './components/ui/Button';
30
+ export { Input } from './components/ui/Input';
31
+ export { Badge } from './components/ui/Badge';
32
+ export { Modal } from './components/ui/Modal';
33
+ export { Skeleton, ProductCardSkeleton, OrderCardSkeleton } from './components/ui/Skeleton';
34
+
35
+ // Hooks
36
+ export { useProducts, useProduct, useFeaturedProducts, useCategories } from './hooks/useProducts';
37
+ export { useOrders, useOrder, useCurrentOrders } from './hooks/useOrders';
38
+
39
+ // API
40
+ export { productsApi } from './lib/api/products';
41
+ export { authApi } from './lib/api/auth';
42
+ export { cartApi } from './lib/api/cart';
43
+ export { ordersApi } from './lib/api/orders';
44
+
45
+ // API Adapter (for advanced usage)
46
+ export { initializeApiAdapter, getApiConfiguration } from './lib/api-adapter';
47
+
48
+ // Types
49
+ export type {
50
+ EcommerceConfig,
51
+ Product,
52
+ ProductFilters,
53
+ Category,
54
+ CartItem as CartItemType,
55
+ Cart,
56
+ Order,
57
+ OrderItem,
58
+ OrderStatus,
59
+ Address,
60
+ User,
61
+ AuthTokens,
62
+ LoginCredentials,
63
+ RegisterData,
64
+ ApiResponse,
65
+ PaginatedResponse,
66
+ } from './lib/types';
67
+
68
+ // Utils
69
+ export { formatPrice, formatDate, truncate, getInitials } from './lib/utils/format';
70
+ export { generateColorShades, hexToRgb } from './lib/utils/colors';
71
+