@codesinger0/shared-components 1.1.85 → 1.1.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/dist/components 2/AccessibilityMenu.jsx +0 -474
- package/dist/components 2/AdvantagesList.jsx +0 -89
- package/dist/components 2/ArticlesList.jsx +0 -269
- package/dist/components 2/DualTextCard.jsx +0 -73
- package/dist/components 2/FloatingWhatsAppButton.jsx +0 -180
- package/dist/components 2/FullscreenCarousel.jsx +0 -292
- package/dist/components 2/Hero.jsx +0 -198
- package/dist/components 2/IconGrid.jsx +0 -144
- package/dist/components 2/IntroSection.jsx +0 -74
- package/dist/components 2/LargeItemCard.jsx +0 -267
- package/dist/components 2/MasonryItemCard.jsx +0 -247
- package/dist/components 2/Menu.d.ts +0 -26
- package/dist/components 2/Menu.jsx +0 -268
- package/dist/components 2/MyOrdersDisplay.jsx +0 -311
- package/dist/components 2/QAAccordion.jsx +0 -212
- package/dist/components 2/SmallItemCard.jsx +0 -152
- package/dist/components 2/SmallItemsGrid.jsx +0 -313
- package/dist/components 2/TextListCards.jsx +0 -107
- package/dist/components 2/ToastProvider.jsx +0 -38
- package/dist/components 2/UnderConstruction.jsx +0 -76
- package/dist/components 2/VideoCard.jsx +0 -88
- package/dist/components 2/cart/CartItem.jsx +0 -101
- package/dist/components 2/cart/FloatingCartButton.jsx +0 -49
- package/dist/components 2/cart/OrderForm.jsx +0 -960
- package/dist/components 2/cart/ShoppingCartModal.jsx +0 -229
- package/dist/components 2/clubMembership/ClubMembershipModal.jsx +0 -289
- package/dist/components 2/clubMembership/ClubPromoModal.jsx +0 -108
- package/dist/components 2/elements/CTAButton.jsx +0 -17
- package/dist/components 2/elements/FixedWidthHeroVideo.jsx +0 -92
- package/dist/components 2/elements/ImageLightbox.jsx +0 -112
- package/dist/components 2/elements/RoundButton.jsx +0 -44
- package/dist/components 2/elements/SmallButton.jsx +0 -35
- package/dist/components 2/elements/Toast.jsx +0 -37
- package/dist/components 2/elements/VideoLightbox.jsx +0 -76
- package/dist/components 2/modals/ItemDetailsModal.jsx +0 -192
- package/dist/components 2/products/CategoryList.jsx +0 -24
- package/dist/components 2/products/PriceRangeSlider.jsx +0 -162
- package/dist/components 2/products/ProductsDisplay.jsx +0 -40
- package/dist/components 2/products/ProductsSidebar.jsx +0 -46
- package/dist/components 2/products/SubcategorySection.jsx +0 -37
- package/dist/context 2/CartContext.jsx +0 -165
- package/dist/context 2/ItemModalContext.jsx +0 -40
- package/dist/hooks 2/useScrollLock.js +0 -52
- package/dist/index 2.js +0 -45
- package/dist/integrations 2/emailService.js +0 -167
- package/dist/styles 2/shared-components.css +0 -29
- package/dist/utils 2/ScrollManager.jsx +0 -85
- package/dist/utils 2/ScrollToTop.jsx +0 -14
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
2
|
-
|
|
3
|
-
const PriceRangeSlider = ({ min, max, value, onChange, className = '' }) => {
|
|
4
|
-
const [localValue, setLocalValue] = useState(value);
|
|
5
|
-
|
|
6
|
-
useEffect(() => {
|
|
7
|
-
setLocalValue(value);
|
|
8
|
-
}, [value]);
|
|
9
|
-
|
|
10
|
-
const handleMinChange = (e) => {
|
|
11
|
-
const newMin = Math.min(Number(e.target.value), localValue[1] - 1);
|
|
12
|
-
const newValue = [newMin, localValue[1]];
|
|
13
|
-
setLocalValue(newValue);
|
|
14
|
-
onChange(newValue);
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const handleMaxChange = (e) => {
|
|
18
|
-
const newMax = Math.max(Number(e.target.value), localValue[0] + 1);
|
|
19
|
-
const newValue = [localValue[0], newMax];
|
|
20
|
-
setLocalValue(newValue);
|
|
21
|
-
onChange(newValue);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const percentage = (val) => ((val - min) / (max - min)) * 100;
|
|
25
|
-
|
|
26
|
-
const minPercent = percentage(localValue[0]);
|
|
27
|
-
const maxPercent = percentage(localValue[1]);
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<div className={`relative ${className}`}>
|
|
31
|
-
<div className="relative h-6 mb-4">
|
|
32
|
-
{/* Track */}
|
|
33
|
-
<div className="absolute top-1/2 w-full h-2 bg-gray-200 rounded transform -translate-y-1/2"></div>
|
|
34
|
-
|
|
35
|
-
{/* Active range */}
|
|
36
|
-
<div
|
|
37
|
-
className="absolute top-1/2 h-2 rounded transform -translate-y-1/2"
|
|
38
|
-
style={{
|
|
39
|
-
insetInlineStart: `${minPercent}%`,
|
|
40
|
-
insetInlineEnd: `${100 - maxPercent}%`,
|
|
41
|
-
backgroundColor: 'var(--primary)'
|
|
42
|
-
}}
|
|
43
|
-
></div>
|
|
44
|
-
|
|
45
|
-
{/* Min slider - with z-index control */}
|
|
46
|
-
<input
|
|
47
|
-
type="range"
|
|
48
|
-
min={min}
|
|
49
|
-
max={max}
|
|
50
|
-
value={localValue[0]}
|
|
51
|
-
onChange={handleMinChange}
|
|
52
|
-
className="absolute w-full h-2 bg-transparent appearance-none cursor-pointer min-slider"
|
|
53
|
-
style={{
|
|
54
|
-
top: '50%',
|
|
55
|
-
transform: 'translateY(-50%)',
|
|
56
|
-
zIndex: localValue[0] > max - 100 ? 5 : 3
|
|
57
|
-
}}
|
|
58
|
-
/>
|
|
59
|
-
|
|
60
|
-
{/* Max slider */}
|
|
61
|
-
<input
|
|
62
|
-
type="range"
|
|
63
|
-
min={min}
|
|
64
|
-
max={max}
|
|
65
|
-
value={localValue[1]}
|
|
66
|
-
onChange={handleMaxChange}
|
|
67
|
-
className="absolute w-full h-2 bg-transparent appearance-none cursor-pointer max-slider"
|
|
68
|
-
style={{
|
|
69
|
-
top: '50%',
|
|
70
|
-
transform: 'translateY(-50%)',
|
|
71
|
-
zIndex: 4
|
|
72
|
-
}}
|
|
73
|
-
/>
|
|
74
|
-
</div>
|
|
75
|
-
|
|
76
|
-
{/* Values display */}
|
|
77
|
-
<div className="flex justify-between items-center text-sm content-text">
|
|
78
|
-
<span>₪{localValue[0].toLocaleString()}</span>
|
|
79
|
-
<span>₪{localValue[1].toLocaleString()}</span>
|
|
80
|
-
</div>
|
|
81
|
-
|
|
82
|
-
<style jsx>{`
|
|
83
|
-
.min-slider::-webkit-slider-thumb {
|
|
84
|
-
appearance: none;
|
|
85
|
-
width: 20px;
|
|
86
|
-
height: 20px;
|
|
87
|
-
border-radius: 50%;
|
|
88
|
-
background: var(--primary);
|
|
89
|
-
cursor: pointer;
|
|
90
|
-
border: 2px solid white;
|
|
91
|
-
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
|
|
92
|
-
position: relative;
|
|
93
|
-
z-index: 10;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.min-slider::-moz-range-thumb {
|
|
97
|
-
width: 20px;
|
|
98
|
-
height: 20px;
|
|
99
|
-
border-radius: 50%;
|
|
100
|
-
background: var(--primary);
|
|
101
|
-
cursor: pointer;
|
|
102
|
-
border: 2px solid white;
|
|
103
|
-
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
|
|
104
|
-
position: relative;
|
|
105
|
-
z-index: 10;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
.max-slider::-webkit-slider-thumb {
|
|
109
|
-
appearance: none;
|
|
110
|
-
width: 20px;
|
|
111
|
-
height: 20px;
|
|
112
|
-
border-radius: 50%;
|
|
113
|
-
background: var(--primary);
|
|
114
|
-
cursor: pointer;
|
|
115
|
-
border: 2px solid white;
|
|
116
|
-
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
|
|
117
|
-
position: relative;
|
|
118
|
-
z-index: 10;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.max-slider::-moz-range-thumb {
|
|
122
|
-
width: 20px;
|
|
123
|
-
height: 20px;
|
|
124
|
-
border-radius: 50%;
|
|
125
|
-
background: var(--primary);
|
|
126
|
-
cursor: pointer;
|
|
127
|
-
border: 2px solid white;
|
|
128
|
-
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
|
|
129
|
-
position: relative;
|
|
130
|
-
z-index: 10;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/* Only show the thumb for each slider */
|
|
134
|
-
.min-slider {
|
|
135
|
-
pointer-events: none;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
.min-slider::-webkit-slider-thumb {
|
|
139
|
-
pointer-events: auto;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.min-slider::-moz-range-thumb {
|
|
143
|
-
pointer-events: auto;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
.max-slider {
|
|
147
|
-
pointer-events: none;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.max-slider::-webkit-slider-thumb {
|
|
151
|
-
pointer-events: auto;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
.max-slider::-moz-range-thumb {
|
|
155
|
-
pointer-events: auto;
|
|
156
|
-
}
|
|
157
|
-
`}</style>
|
|
158
|
-
</div>
|
|
159
|
-
);
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
export default PriceRangeSlider
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import SubCategorySection from "./SubcategorySection";
|
|
2
|
-
|
|
3
|
-
const ProductsDisplay = ({
|
|
4
|
-
productsGroupedBySubCategory,
|
|
5
|
-
selectedCategory,
|
|
6
|
-
onProductClick,
|
|
7
|
-
onAddToCart
|
|
8
|
-
}) => {
|
|
9
|
-
const subCategoryNames = Object.keys(productsGroupedBySubCategory);
|
|
10
|
-
|
|
11
|
-
if (subCategoryNames.length === 0) {
|
|
12
|
-
return (
|
|
13
|
-
<div className="glass-card px-12 text-center">
|
|
14
|
-
<h2 className="lighterTitle mb-4">אין מוצרים זמינים</h2>
|
|
15
|
-
<p className="content-text">
|
|
16
|
-
{selectedCategory
|
|
17
|
-
? `לא נמצאו מוצרים בקטגוריה "${selectedCategory}" בטווח המחירים שנבחר`
|
|
18
|
-
: 'בחר קטגוריה כדי לראות מוצרים'
|
|
19
|
-
}
|
|
20
|
-
</p>
|
|
21
|
-
</div>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<div>
|
|
27
|
-
{subCategoryNames.map(subCategoryName => (
|
|
28
|
-
<SubCategorySection
|
|
29
|
-
key={subCategoryName}
|
|
30
|
-
subCategoryName={subCategoryName}
|
|
31
|
-
products={productsGroupedBySubCategory[subCategoryName]}
|
|
32
|
-
onProductClick={onProductClick}
|
|
33
|
-
onAddToCart={onAddToCart}
|
|
34
|
-
/>
|
|
35
|
-
))}
|
|
36
|
-
</div>
|
|
37
|
-
);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export default ProductsDisplay
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import CategoryList from "./CategoryList";
|
|
2
|
-
import PriceRangeSlider from "./PriceRangeSlider";
|
|
3
|
-
|
|
4
|
-
const ProductsSidebar = ({
|
|
5
|
-
categories,
|
|
6
|
-
selectedCategory,
|
|
7
|
-
onCategorySelect,
|
|
8
|
-
priceRange,
|
|
9
|
-
onPriceRangeChange,
|
|
10
|
-
minPrice,
|
|
11
|
-
maxPrice,
|
|
12
|
-
onResetFilters,
|
|
13
|
-
className = ''
|
|
14
|
-
}) => (
|
|
15
|
-
<div className={`space-y-6 ${className}`} dir="rtl">
|
|
16
|
-
{/* Reset Filters Button */}
|
|
17
|
-
<button
|
|
18
|
-
onClick={onResetFilters}
|
|
19
|
-
className="w-full text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition-colors duration-200"
|
|
20
|
-
>
|
|
21
|
-
אפס סינונים
|
|
22
|
-
</button>
|
|
23
|
-
|
|
24
|
-
{/* Price Range Filter */}
|
|
25
|
-
<div className="glass-card p-4">
|
|
26
|
-
<h3 className="subtitle font-semibold mb-4">סינון לפי מחיר</h3>
|
|
27
|
-
<PriceRangeSlider
|
|
28
|
-
min={minPrice}
|
|
29
|
-
max={maxPrice}
|
|
30
|
-
value={priceRange}
|
|
31
|
-
onChange={onPriceRangeChange}
|
|
32
|
-
/>
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
{/* Category Selection */}
|
|
36
|
-
<div className="glass-card p-4">
|
|
37
|
-
<CategoryList
|
|
38
|
-
categories={categories}
|
|
39
|
-
selectedCategory={selectedCategory}
|
|
40
|
-
onCategorySelect={onCategorySelect}
|
|
41
|
-
/>
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
export default ProductsSidebar
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import SmallItemsGrid from "../SmallItemsGrid";
|
|
2
|
-
|
|
3
|
-
// Subcategory Section Component
|
|
4
|
-
const SubCategorySection = ({ subCategoryName, products, onProductClick, onAddToCart }) => {
|
|
5
|
-
if (!products || products.length === 0) {
|
|
6
|
-
return (
|
|
7
|
-
<div className="mb-2">
|
|
8
|
-
<div className="p-8 text-center">
|
|
9
|
-
<span className='lighterTitle'>
|
|
10
|
-
{subCategoryName}
|
|
11
|
-
</span>
|
|
12
|
-
<p className="content-text">אין מוצרים זמינים בקטגוריה זו</p>
|
|
13
|
-
</div>
|
|
14
|
-
</div>
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Transform products to SmallItemsGrid format
|
|
19
|
-
const gridItems = products;
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<div className="mb-2">
|
|
23
|
-
<SmallItemsGrid
|
|
24
|
-
isLighter={true}
|
|
25
|
-
headerText={subCategoryName}
|
|
26
|
-
items={gridItems}
|
|
27
|
-
showMoreType="carousel"
|
|
28
|
-
autoplay={false}
|
|
29
|
-
onItemClick={onProductClick}
|
|
30
|
-
onAddToCart={onAddToCart}
|
|
31
|
-
className="bg-transparent"
|
|
32
|
-
/>
|
|
33
|
-
</div>
|
|
34
|
-
);
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export default SubCategorySection
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import React, { createContext, useContext, useState, useEffect } from 'react';
|
|
2
|
-
import { useToast } from '../components/ToastProvider';
|
|
3
|
-
|
|
4
|
-
const CART_STORAGE_KEY = 'digishop_shopping_cart';
|
|
5
|
-
|
|
6
|
-
const CartContext = createContext();
|
|
7
|
-
|
|
8
|
-
export const useCart = () => {
|
|
9
|
-
const context = useContext(CartContext);
|
|
10
|
-
if (!context) {
|
|
11
|
-
throw new Error('useCart must be used within a CartProvider');
|
|
12
|
-
}
|
|
13
|
-
return context;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const CartProvider = ({ children, user = null }) => {
|
|
17
|
-
const [cartItems, setCartItems] = useState([]);
|
|
18
|
-
const [isCartOpen, setIsCartOpen] = useState(false);
|
|
19
|
-
const [previousUser, setPreviousUser] = useState(null);
|
|
20
|
-
|
|
21
|
-
const addToast = useToast();
|
|
22
|
-
|
|
23
|
-
const totalItems = cartItems.reduce((sum, item) => sum + item.quantity, 0);
|
|
24
|
-
const totalPrice = cartItems.reduce((sum, item) => sum + (item.price * item.quantity), 0);
|
|
25
|
-
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
// If we had a user before and now we don't = logout happened
|
|
28
|
-
if (previousUser && !user) {
|
|
29
|
-
clearCart(); // Auto-clear cart on logout
|
|
30
|
-
}
|
|
31
|
-
setPreviousUser(user);
|
|
32
|
-
}, [user, previousUser]);
|
|
33
|
-
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
const savedCart = loadCartFromStorage();
|
|
36
|
-
if (savedCart.length > 0) {
|
|
37
|
-
setCartItems(savedCart);
|
|
38
|
-
}
|
|
39
|
-
}, []);
|
|
40
|
-
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
saveCartToStorage(cartItems);
|
|
43
|
-
}, [cartItems]);
|
|
44
|
-
|
|
45
|
-
const saveCartToStorage = (cartItems) => {
|
|
46
|
-
try {
|
|
47
|
-
localStorage.setItem(CART_STORAGE_KEY, JSON.stringify(cartItems));
|
|
48
|
-
} catch (error) {
|
|
49
|
-
console.error('Failed to save cart to localStorage:', error);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const loadCartFromStorage = () => {
|
|
54
|
-
try {
|
|
55
|
-
const stored = localStorage.getItem(CART_STORAGE_KEY);
|
|
56
|
-
return stored ? JSON.parse(stored) : [];
|
|
57
|
-
} catch (error) {
|
|
58
|
-
console.error('Failed to load cart from localStorage:', error);
|
|
59
|
-
return [];
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const clearCartFromStorage = () => {
|
|
64
|
-
try {
|
|
65
|
-
localStorage.removeItem(CART_STORAGE_KEY);
|
|
66
|
-
} catch (error) {
|
|
67
|
-
console.error('Failed to clear cart from localStorage:', error);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const addToCart = (product) => {
|
|
72
|
-
setCartItems(prevItems => {
|
|
73
|
-
const existingItem = prevItems.find(item => item.id === product.id);
|
|
74
|
-
|
|
75
|
-
if (existingItem) {
|
|
76
|
-
return prevItems.map(item =>
|
|
77
|
-
item.id === product.id
|
|
78
|
-
? { ...item, quantity: item.quantity + 1 }
|
|
79
|
-
: item
|
|
80
|
-
);
|
|
81
|
-
} else {
|
|
82
|
-
return [...prevItems, {
|
|
83
|
-
id: product.id,
|
|
84
|
-
name: product.name || product.title,
|
|
85
|
-
price: product.discountPrice || product.price,
|
|
86
|
-
quantity: 1,
|
|
87
|
-
imageUrl: product.imageUrl || ''
|
|
88
|
-
}];
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
addToast("המוצר נוסף לעגלה", "success");
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const removeFromCart = (itemId) => {
|
|
95
|
-
setCartItems(prevItems => prevItems.filter(item => item.id !== itemId));
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
// Update item quantity
|
|
99
|
-
const updateQuantity = (itemId, quantity) => {
|
|
100
|
-
if (quantity <= 0) {
|
|
101
|
-
removeFromCart(itemId);
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
setCartItems(prevItems =>
|
|
106
|
-
prevItems.map(item =>
|
|
107
|
-
item.id === itemId
|
|
108
|
-
? { ...item, quantity }
|
|
109
|
-
: item
|
|
110
|
-
)
|
|
111
|
-
);
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const clearCart = () => {
|
|
115
|
-
setCartItems([]);
|
|
116
|
-
clearCartFromStorage();
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const clearCartOnLogout = () => {
|
|
120
|
-
setCartItems([]);
|
|
121
|
-
clearCartFromStorage();
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
// Toggle cart visibility
|
|
125
|
-
const toggleCart = () => {
|
|
126
|
-
setIsCartOpen(prev => !prev);
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
const openCart = () => setIsCartOpen(true);
|
|
130
|
-
const closeCart = () => setIsCartOpen(false);
|
|
131
|
-
|
|
132
|
-
// Checkout handler
|
|
133
|
-
const handleCheckout = () => {
|
|
134
|
-
// TODO: Implement checkout logic
|
|
135
|
-
console.log('Proceeding to checkout with items:', cartItems);
|
|
136
|
-
console.log('Total:', totalPrice);
|
|
137
|
-
// For now, just close cart
|
|
138
|
-
closeCart();
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const value = {
|
|
142
|
-
// State
|
|
143
|
-
cartItems,
|
|
144
|
-
totalItems,
|
|
145
|
-
totalPrice,
|
|
146
|
-
isCartOpen,
|
|
147
|
-
|
|
148
|
-
// Actions
|
|
149
|
-
addToCart,
|
|
150
|
-
removeFromCart,
|
|
151
|
-
updateQuantity,
|
|
152
|
-
clearCart,
|
|
153
|
-
clearCartOnLogout,
|
|
154
|
-
toggleCart,
|
|
155
|
-
openCart,
|
|
156
|
-
closeCart,
|
|
157
|
-
handleCheckout
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
return (
|
|
161
|
-
<CartContext.Provider value={value}>
|
|
162
|
-
{children}
|
|
163
|
-
</CartContext.Provider>
|
|
164
|
-
);
|
|
165
|
-
};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// src/context/ItemModalContext.js
|
|
2
|
-
import React, { createContext, useContext, useState } from 'react';
|
|
3
|
-
|
|
4
|
-
const ItemModalContext = createContext();
|
|
5
|
-
|
|
6
|
-
export const useItemModal = () => {
|
|
7
|
-
const context = useContext(ItemModalContext);
|
|
8
|
-
if (!context) {
|
|
9
|
-
throw new Error('useItemModal must be used within an ItemModalProvider');
|
|
10
|
-
}
|
|
11
|
-
return context;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export const ItemModalProvider = ({ children }) => {
|
|
15
|
-
const [selectedItem, setSelectedItem] = useState(null);
|
|
16
|
-
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
17
|
-
|
|
18
|
-
const openModal = (item) => {
|
|
19
|
-
console.log('Opening modal for item:', item);
|
|
20
|
-
setSelectedItem(item);
|
|
21
|
-
setIsModalOpen(true);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const closeModal = () => {
|
|
25
|
-
setIsModalOpen(false);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const value = {
|
|
29
|
-
selectedItem,
|
|
30
|
-
isModalOpen,
|
|
31
|
-
openModal,
|
|
32
|
-
closeModal
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<ItemModalContext.Provider value={value}>
|
|
37
|
-
{children}
|
|
38
|
-
</ItemModalContext.Provider>
|
|
39
|
-
);
|
|
40
|
-
};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// src/hooks/useScrollLock.js
|
|
2
|
-
import { useEffect } from 'react';
|
|
3
|
-
|
|
4
|
-
const useScrollLock = (isOpen) => {
|
|
5
|
-
useEffect(() => {
|
|
6
|
-
if (isOpen) {
|
|
7
|
-
// Store original styles
|
|
8
|
-
const originalStyle = window.getComputedStyle(document.body);
|
|
9
|
-
const originalOverflow = originalStyle.overflow;
|
|
10
|
-
const originalPosition = originalStyle.position;
|
|
11
|
-
|
|
12
|
-
// Get current scroll position
|
|
13
|
-
const scrollY = window.scrollY;
|
|
14
|
-
|
|
15
|
-
// Apply scroll lock with Mobile Safari fixes
|
|
16
|
-
document.body.style.overflow = 'hidden';
|
|
17
|
-
document.body.style.position = 'fixed';
|
|
18
|
-
document.body.style.top = `-${scrollY}px`;
|
|
19
|
-
document.body.style.left = '0';
|
|
20
|
-
document.body.style.right = '0';
|
|
21
|
-
document.body.style.width = '100%';
|
|
22
|
-
|
|
23
|
-
// Mobile Safari specific: prevent viewport changes
|
|
24
|
-
const viewport = document.querySelector('meta[name="viewport"]');
|
|
25
|
-
const originalViewport = viewport?.content;
|
|
26
|
-
if (viewport) {
|
|
27
|
-
viewport.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no';
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Cleanup function
|
|
31
|
-
return () => {
|
|
32
|
-
// Restore original styles
|
|
33
|
-
document.body.style.overflow = originalOverflow;
|
|
34
|
-
document.body.style.position = originalPosition;
|
|
35
|
-
document.body.style.top = '';
|
|
36
|
-
document.body.style.left = '';
|
|
37
|
-
document.body.style.right = '';
|
|
38
|
-
document.body.style.width = '';
|
|
39
|
-
|
|
40
|
-
// Restore scroll position
|
|
41
|
-
window.scrollTo(0, scrollY);
|
|
42
|
-
|
|
43
|
-
// Restore viewport
|
|
44
|
-
if (viewport && originalViewport) {
|
|
45
|
-
viewport.content = originalViewport;
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
}, [isOpen]);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export default useScrollLock;
|
package/dist/index 2.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
export { default as RoundButton } from './components/elements/RoundButton';
|
|
2
|
-
export { default as CTAButton } from './components/elements/CTAButton';
|
|
3
|
-
export { default as SmallButton } from './components/elements/SmallButton';
|
|
4
|
-
export { default as LargeItemCard } from './components/LargeItemCard';
|
|
5
|
-
export { default as DualTextCard } from './components/DualTextCard';
|
|
6
|
-
export { default as SmallItemsGrid } from './components/SmallItemsGrid';
|
|
7
|
-
export { default as SmallItemCard } from './components/SmallItemCard';
|
|
8
|
-
export { default as MasonryItemCard } from './components/MasonryItemCard';
|
|
9
|
-
export { default as TextListCards } from './components/TextListCards';
|
|
10
|
-
export { default as ArticlesList } from './components/ArticlesList';
|
|
11
|
-
export { default as Hero } from './components/Hero'
|
|
12
|
-
export { default as IntroSection } from './components/IntroSection'
|
|
13
|
-
export { default as QAAccordion } from './components/QAAccordion'
|
|
14
|
-
export { default as AdvantagesList } from './components/AdvantagesList'
|
|
15
|
-
export { default as ShoppingCartModal } from './components/cart/ShoppingCartModal'
|
|
16
|
-
export { default as FloatingCartButton } from './components/cart/FloatingCartButton'
|
|
17
|
-
export { default as VideoCard } from './components/VideoCard'
|
|
18
|
-
export { default as IconGrid } from './components/IconGrid'
|
|
19
|
-
export { default as Menu } from './components/Menu'
|
|
20
|
-
export { default as ProductsDisplay } from './components/products/ProductsDisplay'
|
|
21
|
-
export { default as ProductsSidebar } from './components/products/ProductsSidebar'
|
|
22
|
-
export { default as MyOrdersDisplay } from './components/MyOrdersDisplay'
|
|
23
|
-
export { default as AccessibilityMenu } from './components/AccessibilityMenu'
|
|
24
|
-
export { default as FloatingWhatsAppButton } from './components/FloatingWhatsAppButton'
|
|
25
|
-
export { default as FullscreenCarousel } from './components/FullscreenCarousel'
|
|
26
|
-
export { default as UnderConstruction } from './components/UnderConstruction'
|
|
27
|
-
|
|
28
|
-
// Modals
|
|
29
|
-
export { default as ItemDetailsModal } from './components/modals/ItemDetailsModal'
|
|
30
|
-
export { default as ClubMembershipModal } from './components/clubMembership/ClubMembershipModal'
|
|
31
|
-
export { default as ClubPromoModal } from './components/clubMembership/ClubPromoModal'
|
|
32
|
-
export { default as OrderForm } from './components/cart/OrderForm'
|
|
33
|
-
|
|
34
|
-
// Context
|
|
35
|
-
export { ItemModalProvider, useItemModal } from './context/ItemModalContext';
|
|
36
|
-
export { ToastProvider, useToast } from './components/ToastProvider'
|
|
37
|
-
export { CartProvider, useCart } from './context/CartContext'
|
|
38
|
-
|
|
39
|
-
// Hooks
|
|
40
|
-
export { default as useScrollLock } from './hooks/useScrollLock'
|
|
41
|
-
|
|
42
|
-
// Utils
|
|
43
|
-
export { default as ScrollToTop } from './utils/ScrollToTop'
|
|
44
|
-
export { useScrollToAnchor } from './utils/ScrollManager'
|
|
45
|
-
export { sendEmail } from './integrations/emailService'
|