@pradip1995/theme-sahsha 3.1.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 (65) hide show
  1. package/README.md +29 -0
  2. package/assets/hero-desktop.svg +10 -0
  3. package/assets/hero-mobile.svg +9 -0
  4. package/assets/logo.svg +3 -0
  5. package/package.json +60 -0
  6. package/src/blocks/home/Features/index.tsx +87 -0
  7. package/src/blocks/home/Hero/index.tsx +98 -0
  8. package/src/blocks/home/LovedByMoms/bestsellers-carousel.tsx +1 -0
  9. package/src/blocks/home/LovedByMoms/index.tsx +43 -0
  10. package/src/blocks/home/LovedByMoms/loved-by-moms-section.tsx +46 -0
  11. package/src/blocks/home/NewArrivals/index.tsx +91 -0
  12. package/src/blocks/home/PromotionalBanners/index.tsx +81 -0
  13. package/src/blocks/home/ShopByAge/collections-showcase-client.tsx +131 -0
  14. package/src/blocks/home/ShopByAge/collections-showcase-types.ts +4 -0
  15. package/src/blocks/home/ShopByAge/index.tsx +168 -0
  16. package/src/blocks/home/ShopByCategory/index.tsx +111 -0
  17. package/src/blocks/home/Testimonials/index.tsx +25 -0
  18. package/src/blocks/home/Testimonials/reviews-scroll.tsx +122 -0
  19. package/src/blocks/home/Testimonials/testimonials-client.tsx +127 -0
  20. package/src/blocks/home/WhyChooseUs/index.tsx +39 -0
  21. package/src/components/product-carousel.tsx +79 -0
  22. package/src/layouts/MainLayoutShell.tsx +14 -0
  23. package/src/primitives/Button.tsx +31 -0
  24. package/src/primitives/Card.tsx +32 -0
  25. package/src/primitives/index.ts +2 -0
  26. package/src/slots/account/ForgotPassword/index.tsx +1 -0
  27. package/src/slots/account/GoogleLogin/index.tsx +28 -0
  28. package/src/slots/account/Login/index.tsx +1 -0
  29. package/src/slots/account/LoginTemplate/index.tsx +12 -0
  30. package/src/slots/account/LoginTemplate/login-template-client.tsx +83 -0
  31. package/src/slots/account/Register/index.tsx +1 -0
  32. package/src/slots/cart/CartItem/index.tsx +11 -0
  33. package/src/slots/cart/CartSummary/index.tsx +8 -0
  34. package/src/slots/checkout/CheckoutForm/index.tsx +1 -0
  35. package/src/slots/checkout/CheckoutSummary/index.tsx +1 -0
  36. package/src/slots/layout/Footer/index.tsx +95 -0
  37. package/src/slots/layout/Nav/index.tsx +50 -0
  38. package/src/slots/layout/Nav/nav-categories-dropdown.tsx +74 -0
  39. package/src/slots/layout/Nav/nav-collections-dropdown.tsx +106 -0
  40. package/src/slots/layout/Nav/nav-header-content.tsx +165 -0
  41. package/src/slots/layout/Nav/nav-header-shell.tsx +47 -0
  42. package/src/slots/layout/Nav/nav-link-luxury.tsx +15 -0
  43. package/src/slots/layout/PromoBar/index.tsx +9 -0
  44. package/src/slots/layout/PromoBar/promo-bar-content.tsx +118 -0
  45. package/src/slots/order/OrderDetails/index.tsx +12 -0
  46. package/src/slots/product/ProductActions/ProductCTASection.tsx +232 -0
  47. package/src/slots/product/ProductActions/ProductDetailsSection.tsx +200 -0
  48. package/src/slots/product/ProductActions/ProductFeaturePanel.tsx +150 -0
  49. package/src/slots/product/ProductActions/ProductHighlightsSection.tsx +112 -0
  50. package/src/slots/product/ProductActions/ProductOptionsSection.tsx +215 -0
  51. package/src/slots/product/ProductActions/ProductPriceSection.tsx +53 -0
  52. package/src/slots/product/ProductActions/ProductTrustSection.tsx +84 -0
  53. package/src/slots/product/ProductActions/SizeChartPanel.tsx +93 -0
  54. package/src/slots/product/ProductActions/index.tsx +156 -0
  55. package/src/slots/product/ProductActions/product-metadata-fields.ts +503 -0
  56. package/src/slots/product/ProductActions/size-chart-data.ts +108 -0
  57. package/src/slots/product/ProductCard/index.tsx +258 -0
  58. package/src/slots/product/ProductInfo/index.tsx +35 -0
  59. package/src/templates/CollectionsPage/index.tsx +72 -0
  60. package/src/templates/StorePage/index.tsx +134 -0
  61. package/src/tokens/colors.ts +21 -0
  62. package/src/tokens/fonts.ts +16 -0
  63. package/src/tokens/index.ts +3 -0
  64. package/src/tokens/spacing.ts +9 -0
  65. package/src/tokens/theme.css +12754 -0
@@ -0,0 +1,232 @@
1
+ "use client"
2
+
3
+ import { useRouter } from "next/navigation"
4
+ import { HttpTypes } from "@medusajs/types"
5
+ import type { ProductOptions } from "@core/domain/product/variant-selection"
6
+
7
+ export type ProductCTASectionProps = {
8
+ product: HttpTypes.StoreProduct
9
+ selectedVariant?: HttpTypes.StoreProductVariant
10
+ options: ProductOptions
11
+ isValidVariant: boolean
12
+ disabled?: boolean
13
+ inStock: boolean
14
+ inventoryLimit: number | null
15
+ quantity: number
16
+ setQuantity: (value: number) => void
17
+ quantityInCart: number
18
+ variantInCart: HttpTypes.StoreCartLineItem | undefined
19
+ isAdding: boolean
20
+ isBuyingNow: boolean
21
+ showNotifyMessage: boolean
22
+ setShowNotifyMessage: (v: boolean) => void
23
+ handleAddToCart: () => void
24
+ handleBuyNow: () => void
25
+ handleIncreaseQuantity: () => void
26
+ handleDecreaseQuantity: () => void
27
+ }
28
+
29
+ const btnBase =
30
+ "product-cta-btn h-12 flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed"
31
+
32
+ export function ProductCTASection(props: ProductCTASectionProps) {
33
+ const router = useRouter()
34
+ const {
35
+ product,
36
+ selectedVariant,
37
+ options,
38
+ isValidVariant,
39
+ disabled,
40
+ inStock,
41
+ inventoryLimit,
42
+ quantity,
43
+ setQuantity,
44
+ quantityInCart,
45
+ variantInCart,
46
+ isAdding,
47
+ isBuyingNow,
48
+ showNotifyMessage,
49
+ setShowNotifyMessage,
50
+ handleAddToCart,
51
+ handleBuyNow,
52
+ handleIncreaseQuantity,
53
+ handleDecreaseQuantity,
54
+ } = props
55
+
56
+ if (!inStock && selectedVariant) {
57
+ return (
58
+ <div className="flex flex-col gap-4 w-full">
59
+ <p className="text-sm font-medium text-brand-sale uppercase tracking-[var(--letter-spacing-nav)]">
60
+ Sold out
61
+ </p>
62
+
63
+ {showNotifyMessage ? (
64
+ <div className="border border-[var(--color-header-border)] p-5 flex flex-col gap-3">
65
+ <p className="text-sm text-body">
66
+ We&apos;ll notify you when this item is back in stock.
67
+ </p>
68
+ <button
69
+ onClick={() => {
70
+ const relatedSection = document.getElementById("related-products")
71
+ if (relatedSection) {
72
+ relatedSection.scrollIntoView({ behavior: "smooth" })
73
+ } else {
74
+ router.push("/store")
75
+ }
76
+ }}
77
+ className="text-sm font-medium underline underline-offset-4 text-heading hover:opacity-70 w-fit"
78
+ >
79
+ Browse similar products
80
+ </button>
81
+ </div>
82
+ ) : (
83
+ <button
84
+ onClick={() => setShowNotifyMessage(true)}
85
+ className={`${btnBase} w-full bg-brand-accent text-inverse hover:bg-brand-accent-hover`}
86
+ >
87
+ Notify me when available
88
+ </button>
89
+ )}
90
+ </div>
91
+ )
92
+ }
93
+
94
+ return (
95
+ <div className="flex flex-col gap-3 w-full">
96
+ {inventoryLimit !== null && inventoryLimit > 0 && inventoryLimit <= 5 && (
97
+ <p className="text-[10px] sm:text-xs font-bold uppercase tracking-wider text-orange-600 text-right">
98
+ Hurry! Only {inventoryLimit} left
99
+ </p>
100
+ )}
101
+
102
+ <div className="flex items-stretch gap-3 w-full">
103
+ {variantInCart ? (
104
+ <div className="flex h-12 shrink-0 w-[120px] border border-brand-accent rounded-full overflow-hidden">
105
+ <button
106
+ onClick={handleDecreaseQuantity}
107
+ disabled={isAdding}
108
+ className="w-10 flex items-center justify-center hover:bg-surface-muted transition-colors disabled:opacity-50"
109
+ aria-label="Decrease quantity"
110
+ >
111
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
112
+ <line x1="5" y1="12" x2="19" y2="12" />
113
+ </svg>
114
+ </button>
115
+ <div className="flex-1 flex items-center justify-center text-sm font-semibold text-heading">
116
+ {variantInCart.quantity}
117
+ </div>
118
+ <button
119
+ onClick={handleIncreaseQuantity}
120
+ disabled={isAdding || !inStock}
121
+ className="w-10 flex items-center justify-center hover:bg-surface-muted transition-colors disabled:opacity-50"
122
+ aria-label="Increase quantity"
123
+ >
124
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
125
+ <line x1="12" y1="5" x2="12" y2="19" />
126
+ <line x1="5" y1="12" x2="19" y2="12" />
127
+ </svg>
128
+ </button>
129
+ </div>
130
+ ) : (
131
+ <div className="flex h-12 shrink-0 w-[120px] items-center border border-[var(--color-header-border)] rounded-full overflow-hidden bg-surface">
132
+ <button
133
+ type="button"
134
+ onClick={() => setQuantity(Math.max(1, quantity - 1))}
135
+ disabled={quantity <= 1}
136
+ className="w-10 h-full flex items-center justify-center hover:bg-gray-50 disabled:opacity-50"
137
+ >
138
+
139
+ </button>
140
+ <span className="flex-1 text-center font-semibold text-gray-900">
141
+ {quantity}
142
+ </span>
143
+ <button
144
+ type="button"
145
+ onClick={() => {
146
+ if (inventoryLimit === null || quantity < inventoryLimit) {
147
+ setQuantity(quantity + 1)
148
+ }
149
+ }}
150
+ disabled={inventoryLimit !== null && quantity >= inventoryLimit}
151
+ className="w-10 h-full flex items-center justify-center hover:bg-gray-50 disabled:opacity-50"
152
+ >
153
+ +
154
+ </button>
155
+ </div>
156
+ )}
157
+
158
+ {!variantInCart && (
159
+ <button
160
+ onClick={handleAddToCart}
161
+ disabled={
162
+ !inStock ||
163
+ !!disabled ||
164
+ isAdding ||
165
+ isBuyingNow ||
166
+ (!isValidVariant && product.options?.every((opt) => options[opt.id]))
167
+ }
168
+ className={`${btnBase} flex-1 min-w-0 product-cta-btn--secondary`}
169
+ data-testid="add-product-button"
170
+ data-ga-event="add_to_bag_click"
171
+ data-ga-label={product.title || "Product"}
172
+ >
173
+ {isAdding ? (
174
+ <span className="product-cta-btn__label">
175
+ <Spinner />
176
+ </span>
177
+ ) : (
178
+ <span className="product-cta-btn__label">
179
+ {!selectedVariant || !isValidVariant
180
+ ? product.options?.every((opt) => options[opt.id])
181
+ ? "Unavailable"
182
+ : "Select options"
183
+ : !inStock
184
+ ? inventoryLimit !== null &&
185
+ inventoryLimit + quantityInCart > 0 &&
186
+ quantity > inventoryLimit
187
+ ? inventoryLimit <= 0
188
+ ? "Sold out"
189
+ : "Max quantity reached"
190
+ : "Sold out"
191
+ : `Add to Cart${quantity > 1 ? ` (${quantity})` : ""}`}
192
+ </span>
193
+ )}
194
+ </button>
195
+ )}
196
+ </div>
197
+
198
+ <button
199
+ onClick={handleBuyNow}
200
+ disabled={
201
+ !inStock ||
202
+ !!disabled ||
203
+ isAdding ||
204
+ isBuyingNow ||
205
+ (!isValidVariant && product.options?.every((opt) => options[opt.id]))
206
+ }
207
+ className={`${btnBase} w-full product-cta-btn--primary`}
208
+ >
209
+ {isBuyingNow ? (
210
+ <span className="product-cta-btn__label">
211
+ <Spinner />
212
+ </span>
213
+ ) : (
214
+ <span className="product-cta-btn__label">Buy It Now</span>
215
+ )}
216
+ </button>
217
+ </div>
218
+ )
219
+ }
220
+
221
+ function Spinner() {
222
+ return (
223
+ <svg className="animate-spin h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
224
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
225
+ <path
226
+ className="opacity-75"
227
+ fill="currentColor"
228
+ 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"
229
+ />
230
+ </svg>
231
+ )
232
+ }
@@ -0,0 +1,200 @@
1
+ "use client"
2
+
3
+ import { useState } from "react"
4
+ import { HttpTypes } from "@medusajs/types"
5
+ import RatingsTab from "@modules/products/components/product-tabs/ratings-tab"
6
+ import {
7
+ getProductDetailsNarratives,
8
+ getProductMetadataEntries,
9
+ hasProductDetailsContent,
10
+ } from "./product-metadata-fields"
11
+
12
+ function AccordionItem({
13
+ title,
14
+ isOpen,
15
+ onToggle,
16
+ children,
17
+ }: {
18
+ title: string
19
+ isOpen: boolean
20
+ onToggle: () => void
21
+ children: React.ReactNode
22
+ }) {
23
+ return (
24
+ <div className="product-accordion__item border-t border-[var(--color-header-border)]">
25
+ <button
26
+ onClick={onToggle}
27
+ className="product-accordion__trigger flex items-center justify-between w-full py-4 text-left"
28
+ >
29
+ <h3 className="product-accordion__title">{title}</h3>
30
+ <svg
31
+ width="14"
32
+ height="14"
33
+ viewBox="0 0 24 24"
34
+ fill="none"
35
+ stroke="currentColor"
36
+ strokeWidth="2"
37
+ className={`transition-transform text-heading ${isOpen ? "rotate-180" : ""}`}
38
+ >
39
+ <polyline points="6 9 12 15 18 9" />
40
+ </svg>
41
+ </button>
42
+ {isOpen && (
43
+ <div className="pb-5 text-sm text-body leading-relaxed">{children}</div>
44
+ )}
45
+ </div>
46
+ )
47
+ }
48
+
49
+ function NarrativeBlock({
50
+ title,
51
+ items,
52
+ }: {
53
+ title: string
54
+ items: string[]
55
+ }) {
56
+ return (
57
+ <div className="product-details__block">
58
+ <h4 className="product-details__block-title">{title}</h4>
59
+ {items.length === 1 ? (
60
+ <p className="product-details__block-text">{items[0]}</p>
61
+ ) : (
62
+ <ul className="product-details__list">
63
+ {items.map((item, index) => (
64
+ <li key={index}>{item}</li>
65
+ ))}
66
+ </ul>
67
+ )}
68
+ </div>
69
+ )
70
+ }
71
+
72
+ export function ProductDetailsSection({ product }: { product: HttpTypes.StoreProduct }) {
73
+ const metadataEntries = getProductMetadataEntries(product.metadata)
74
+ const narrativeSections = getProductDetailsNarratives(product.metadata)
75
+ const careGuide = product.metadata?.care_guide
76
+ const hasCareGuide =
77
+ careGuide !== null &&
78
+ careGuide !== undefined &&
79
+ String(careGuide).trim() !== ""
80
+ const showProductDetails = hasProductDetailsContent(product)
81
+ const [isDetailsOpen, setIsDetailsOpen] = useState(false)
82
+ const [isDescriptionOpen, setIsDescriptionOpen] = useState(false)
83
+ const [isCareGuideOpen, setIsCareGuideOpen] = useState(false)
84
+
85
+ return (
86
+ <div className="product-details-section mt-2">
87
+ {showProductDetails && (
88
+ <AccordionItem
89
+ title="Product details"
90
+ isOpen={isDetailsOpen}
91
+ onToggle={() => setIsDetailsOpen(!isDetailsOpen)}
92
+ >
93
+ {product.title && (
94
+ <p className="product-details__product-title">{product.title}</p>
95
+ )}
96
+
97
+ {narrativeSections.map((section) => (
98
+ <NarrativeBlock
99
+ key={section.key}
100
+ title={section.title}
101
+ items={section.items}
102
+ />
103
+ ))}
104
+
105
+ {metadataEntries.length > 0 && (
106
+ <>
107
+ <p className="product-details__spec-heading">Specifications</p>
108
+ <div className="product-details__grid">
109
+ {metadataEntries.map((entry) => (
110
+ <div key={entry.key} className="product-details__item">
111
+ <span className="product-details__label">{entry.label}</span>
112
+ <span className="product-details__value">{entry.value}</span>
113
+ </div>
114
+ ))}
115
+ </div>
116
+ </>
117
+ )}
118
+ </AccordionItem>
119
+ )}
120
+
121
+ {product.description && (
122
+ <AccordionItem
123
+ title="Description"
124
+ isOpen={isDescriptionOpen}
125
+ onToggle={() => setIsDescriptionOpen(!isDescriptionOpen)}
126
+ >
127
+ <div
128
+ className="mb-3 whitespace-pre-line"
129
+ dangerouslySetInnerHTML={{
130
+ __html: product.description
131
+ ? product.description.replace(/\n/g, "<br />")
132
+ : "",
133
+ }}
134
+ />
135
+ {(() => {
136
+ const features = product.metadata?.features
137
+ if (!features) return null
138
+
139
+ if (typeof features === "string") {
140
+ return (
141
+ <ul className="list-disc list-inside space-y-1">
142
+ {features.split(",").map((feature: string, index: number) => (
143
+ <li key={index}>{feature.trim()}</li>
144
+ ))}
145
+ </ul>
146
+ )
147
+ }
148
+
149
+ if (Array.isArray(features)) {
150
+ return (
151
+ <ul className="list-disc list-inside space-y-1">
152
+ {(features as string[]).map((feature: string, index: number) => (
153
+ <li key={index}>{feature}</li>
154
+ ))}
155
+ </ul>
156
+ )
157
+ }
158
+
159
+ return null
160
+ })()}
161
+ </AccordionItem>
162
+ )}
163
+
164
+ {hasCareGuide && (
165
+ <AccordionItem
166
+ title="Care guide"
167
+ isOpen={isCareGuideOpen}
168
+ onToggle={() => setIsCareGuideOpen(!isCareGuideOpen)}
169
+ >
170
+ {(() => {
171
+ const careGuideStr =
172
+ typeof careGuide === "string" ? careGuide : String(careGuide)
173
+
174
+ const items = careGuideStr.includes(",")
175
+ ? careGuideStr.split(",").map((item) => item.trim()).filter(Boolean)
176
+ : careGuideStr.includes("\n")
177
+ ? careGuideStr.split("\n").map((item) => item.trim()).filter(Boolean)
178
+ : [careGuideStr]
179
+
180
+ if (items.length > 1) {
181
+ return (
182
+ <ul className="list-disc list-inside space-y-1">
183
+ {items.map((item: string, index: number) => (
184
+ <li key={index}>{item}</li>
185
+ ))}
186
+ </ul>
187
+ )
188
+ }
189
+
190
+ return <p>{careGuideStr}</p>
191
+ })()}
192
+ </AccordionItem>
193
+ )}
194
+
195
+ <div className="product-reviews-section border-t border-[var(--color-header-border)] pt-4 pb-2">
196
+ <RatingsTab product={product} />
197
+ </div>
198
+ </div>
199
+ )
200
+ }
@@ -0,0 +1,150 @@
1
+ "use client"
2
+
3
+ import SidePanel from "@modules/common/components/side-panel"
4
+ import { SizeChartPanel } from "./SizeChartPanel"
5
+
6
+ type ProductFeaturePanelProps = {
7
+ activeFeature: string | null
8
+ onClose: () => void
9
+ }
10
+
11
+ export function ProductFeaturePanel({ activeFeature, onClose }: ProductFeaturePanelProps) {
12
+ return (
13
+ <SidePanel
14
+ isOpen={!!activeFeature}
15
+ onClose={() => onClose()}
16
+ title={
17
+ activeFeature === 'return' ? '7 Days Easy Return' :
18
+ activeFeature === 'delivery' ? 'Fast Delivery' :
19
+ activeFeature === 'cod' ? 'Cash On Delivery' :
20
+ activeFeature === 'size_chart' ? 'Size Guide' : ''
21
+ }
22
+ >
23
+ {activeFeature === 'return' && (
24
+ <div className="space-y-6">
25
+ <div className="bg-purple-50 p-4 rounded-xl border border-purple-100">
26
+ <p className="text-sm text-purple-900 leading-relaxed font-medium">
27
+ We offer a hassle-free 7-day return policy for all our customers. If you're not satisfied with your purchase, we're here to help!
28
+ </p>
29
+ </div>
30
+ <div className="space-y-4">
31
+ <div className="flex gap-4">
32
+ <div className="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center flex-shrink-0">
33
+ <span className="font-bold text-gray-700">1</span>
34
+ </div>
35
+ <div>
36
+ <h4 className="font-bold text-gray-900 mb-1">Unused Conditions</h4>
37
+ <p className="text-sm text-gray-600">Items must be returned in their original condition, unused, and with all tags intact.</p>
38
+ </div>
39
+ </div>
40
+ <div className="flex gap-4">
41
+ <div className="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center flex-shrink-0">
42
+ <span className="font-bold text-gray-700">2</span>
43
+ </div>
44
+ <div>
45
+ <h4 className="font-bold text-gray-900 mb-1">Easy Process</h4>
46
+ <p className="text-sm text-gray-600">Raise a return request from your account or contact our support team directly.</p>
47
+ </div>
48
+ </div>
49
+ <div className="flex gap-4">
50
+ <div className="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center flex-shrink-0">
51
+ <span className="font-bold text-gray-700">3</span>
52
+ </div>
53
+ <div>
54
+ <h4 className="font-bold text-gray-900 mb-1">Quick Refund</h4>
55
+ <p className="text-sm text-gray-600">Once the quality check is completed, your refund will be processed within 24–48 hours. The amount may take a few business days to reflect in your account depending on your bank.</p>
56
+ </div>
57
+ </div>
58
+ </div>
59
+ </div>
60
+ )}
61
+
62
+ {activeFeature === 'delivery' && (
63
+ <div className="space-y-6">
64
+ <div className="bg-blue-50 p-4 rounded-xl border border-blue-100">
65
+ <p className="text-sm text-blue-900 leading-relaxed font-medium">
66
+ We prioritize your excitement! Our fast delivery network ensures your order reaches you as soon as possible.
67
+ </p>
68
+ </div>
69
+ <div className="space-y-6">
70
+ <div>
71
+ <h4 className="font-bold text-gray-900 mb-2 flex items-center gap-2">
72
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="text-blue-500">
73
+ <path d="M12 2v20m10-10H2"></path>
74
+ </svg>
75
+ Order Processing
76
+ </h4>
77
+ <p className="text-sm text-gray-600 pl-7">Most orders are processed and dispatched within 24 hours of placement.</p>
78
+ </div>
79
+ <div>
80
+ <h4 className="font-bold text-gray-900 mb-2 flex items-center gap-2">
81
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="text-blue-500">
82
+ <circle cx="12" cy="12" r="10"></circle>
83
+ <polyline points="12 6 12 12 16 14"></polyline>
84
+ </svg>
85
+ Average Timelines
86
+ </h4>
87
+ <ul className="text-sm text-gray-600 pl-7 space-y-2 list-disc">
88
+ <li>Metro Cities: 2-3 business days</li>
89
+ <li>Tier 2 Cities: 4-5 business days</li>
90
+ <li>Rest of India: 5-7 business days</li>
91
+ </ul>
92
+ </div>
93
+ <div>
94
+ <h4 className="font-bold text-gray-900 mb-2 flex items-center gap-2">
95
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="text-blue-500">
96
+ <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
97
+ <circle cx="12" cy="10" r="3"></circle>
98
+ </svg>
99
+ Live Tracking
100
+ </h4>
101
+ <p className="text-sm text-gray-600 pl-7">You will receive a real-time tracking link via Email & WhatsApp once your order is shipped.</p>
102
+ </div>
103
+ </div>
104
+ </div>
105
+ )}
106
+
107
+ {activeFeature === 'cod' && (
108
+ <div className="space-y-6">
109
+ <div className="bg-green-50 p-4 rounded-xl border border-green-100">
110
+ <p className="text-sm text-green-900 leading-relaxed font-medium">
111
+ Shop with confidence! Pay only when you receive your package at your doorstep.
112
+ </p>
113
+ </div>
114
+ <div className="space-y-5">
115
+ <div className="flex gap-4 p-4 bg-gray-50 rounded-lg">
116
+ <div className="w-10 h-10 flex items-center justify-center bg-page-bg rounded-lg shadow-sm flex-shrink-0">
117
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#22c55e" strokeWidth="2">
118
+ <rect x="2" y="5" width="20" height="14" rx="2"></rect>
119
+ <line x1="2" y1="10" x2="22" y2="10"></line>
120
+ </svg>
121
+ </div>
122
+ <div>
123
+ <h4 className="font-bold text-gray-900">Zero Upfront Cost</h4>
124
+ <p className="text-xs text-gray-500">No need for credit cards or online payments to place your order.</p>
125
+ </div>
126
+ </div>
127
+ <div className="flex gap-4 p-4 bg-gray-50 rounded-lg">
128
+ <div className="w-10 h-10 flex items-center justify-center bg-page-bg rounded-lg shadow-sm flex-shrink-0">
129
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#22c55e" strokeWidth="2">
130
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
131
+ </svg>
132
+ </div>
133
+ <div>
134
+ <h4 className="font-bold text-gray-900">Safe & Secure</h4>
135
+ <p className="text-xs text-gray-500">Verify your package and then pay our delivery partner directly.</p>
136
+ </div>
137
+ </div>
138
+ <ul className="text-xs text-gray-500 italic space-y-1 pl-4 list-disc">
139
+ <li>Available for orders up to ₹10,000.</li>
140
+ <li>Please keep the exact change ready for a smoother experience.</li>
141
+ <li>Only cash payments are accepted for COD.</li>
142
+ </ul>
143
+ </div>
144
+ </div>
145
+ )}
146
+
147
+ {activeFeature === 'size_chart' && <SizeChartPanel />}
148
+ </SidePanel>
149
+ )
150
+ }