funuicss 3.8.7 → 3.8.9
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/css/fun.css +702 -87
- package/index.d.ts +3 -0
- package/index.js +8 -2
- package/package.json +1 -1
- package/ui/button/Button.d.ts +6 -5
- package/ui/button/Button.js +190 -84
- package/ui/div/Div.d.ts +3 -1
- package/ui/div/Div.js +2 -2
- package/ui/feature/Feature.d.ts +9 -38
- package/ui/feature/Feature.js +62 -147
- package/ui/flex/Flex.d.ts +11 -10
- package/ui/flex/Flex.js +102 -6
- package/ui/form/Form.d.ts +77 -0
- package/ui/form/Form.js +724 -0
- package/ui/input/FileUpload.js +370 -21
- package/ui/input/Input.d.ts +44 -15
- package/ui/input/Input.js +1145 -369
- package/ui/products/CartModal.d.ts +0 -2
- package/ui/products/CartModal.js +59 -39
- package/ui/products/ProductCard.js +9 -22
- package/ui/products/ProductDetail.js +136 -97
- package/ui/products/ProductLoader.d.ts +3 -0
- package/ui/products/ProductLoader.js +22 -0
- package/ui/products/Store.d.ts +32 -7
- package/ui/products/Store.js +393 -94
- package/ui/progress/Bar.js +2 -2
- package/ui/sidebar/SideBar.js +1 -2
- package/ui/specials/CircleGroup.d.ts +2 -1
- package/ui/specials/CircleGroup.js +3 -3
- package/ui/theme/theme.d.ts +4 -0
- package/ui/theme/theme.js +336 -133
package/ui/products/CartModal.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// components/products/CartModal.tsx
|
|
3
2
|
'use client';
|
|
4
3
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -15,71 +14,92 @@ var Div_1 = __importDefault(require("../div/Div"));
|
|
|
15
14
|
var Button_1 = __importDefault(require("../button/Button"));
|
|
16
15
|
var Circle_1 = __importDefault(require("../specials/Circle"));
|
|
17
16
|
var Flex_1 = __importDefault(require("../flex/Flex"));
|
|
18
|
-
var
|
|
17
|
+
var ImageScaler_1 = __importDefault(require("../components/ImageScaler"));
|
|
18
|
+
var tb_1 = require("react-icons/tb");
|
|
19
|
+
var Empty_1 = __importDefault(require("../empty/Empty"));
|
|
20
|
+
var generateCartItemId = function (item) {
|
|
21
|
+
var _a;
|
|
19
22
|
var parts = [
|
|
20
|
-
product.id,
|
|
21
|
-
(
|
|
22
|
-
|
|
23
|
+
item.product.id,
|
|
24
|
+
((_a = item.variant) === null || _a === void 0 ? void 0 : _a.id) || '',
|
|
25
|
+
item.selectedColor || '',
|
|
26
|
+
item.selectedSize || ''
|
|
23
27
|
].filter(Boolean);
|
|
24
28
|
return parts.join('_');
|
|
25
29
|
};
|
|
26
30
|
var CartModal = function (_a) {
|
|
27
|
-
var cart = _a.cart, isOpen = _a.isOpen, setIsOpen = _a.setIsOpen, _b = _a.currency, currency = _b === void 0 ? '$' : _b, updateQuantity = _a.updateQuantity, removeFromCart = _a.removeFromCart, clearCart = _a.clearCart, handleCheckout = _a.handleCheckout, _c = _a.cartBadgeColor, cartBadgeColor = _c === void 0 ? 'error' : _c, _d = _a.checkoutText, checkoutText = _d === void 0 ? 'Checkout' : _d, checkoutIcon = _a.checkoutIcon, _e = _a.
|
|
31
|
+
var cart = _a.cart, isOpen = _a.isOpen, setIsOpen = _a.setIsOpen, _b = _a.currency, currency = _b === void 0 ? '$' : _b, updateQuantity = _a.updateQuantity, removeFromCart = _a.removeFromCart, clearCart = _a.clearCart, handleCheckout = _a.handleCheckout, _c = _a.cartBadgeColor, cartBadgeColor = _c === void 0 ? 'error' : _c, _d = _a.checkoutText, checkoutText = _d === void 0 ? 'Checkout' : _d, checkoutIcon = _a.checkoutIcon, _e = _a.persistCart, persistCart = _e === void 0 ? true : _e;
|
|
28
32
|
var totalItems = cart.reduce(function (sum, item) { return sum + item.quantity; }, 0);
|
|
29
|
-
var subtotal = cart.reduce(function (sum, item) {
|
|
33
|
+
var subtotal = cart.reduce(function (sum, item) {
|
|
34
|
+
var _a;
|
|
35
|
+
var price = ((_a = item.variant) === null || _a === void 0 ? void 0 : _a.price) || item.product.price;
|
|
36
|
+
return sum + (price * item.quantity);
|
|
37
|
+
}, 0);
|
|
38
|
+
// Calculate total savings from discounts
|
|
39
|
+
var totalSavings = cart.reduce(function (sum, item) {
|
|
40
|
+
var _a;
|
|
41
|
+
var originalPrice = item.originalPrice || item.product.comparePrice || item.product.price;
|
|
42
|
+
var currentPrice = ((_a = item.variant) === null || _a === void 0 ? void 0 : _a.price) || item.product.price;
|
|
43
|
+
var savings = originalPrice !== currentPrice ? (originalPrice - currentPrice) * item.quantity : 0;
|
|
44
|
+
return sum + savings;
|
|
45
|
+
}, 0);
|
|
30
46
|
var handleRemoveItem = function (item) {
|
|
31
|
-
var cartItemId = generateCartItemId(item
|
|
32
|
-
color: item.selectedColor,
|
|
33
|
-
size: item.selectedSize
|
|
34
|
-
});
|
|
47
|
+
var cartItemId = generateCartItemId(item);
|
|
35
48
|
removeFromCart(cartItemId);
|
|
36
49
|
};
|
|
37
50
|
var handleUpdateQuantity = function (item, newQuantity) {
|
|
38
|
-
var cartItemId = generateCartItemId(item
|
|
39
|
-
color: item.selectedColor,
|
|
40
|
-
size: item.selectedSize
|
|
41
|
-
});
|
|
51
|
+
var cartItemId = generateCartItemId(item);
|
|
42
52
|
updateQuantity(cartItemId, newQuantity);
|
|
43
53
|
};
|
|
44
|
-
return (react_1.default.createElement(Modal_1.default, { animation: "
|
|
45
|
-
react_1.default.createElement(
|
|
54
|
+
return (react_1.default.createElement(Modal_1.default, { animation: "SlideDown", duration: 0.3, open: isOpen, setOpen: setIsOpen, maxWidth: '600px', title: react_1.default.createElement(Text_1.default, { text: "Your Cart", size: "h3" }), body: react_1.default.createElement(Div_1.default, { funcss: "pt pb" }, cart.length === 0 ? (react_1.default.createElement(Div_1.default, null,
|
|
55
|
+
react_1.default.createElement(Empty_1.default, { title: "Your cart is empty", showCta: true, description: "Add items to your cart to checkout", ctaText: "Continue Shopping", ctaOnClick: function () { return setIsOpen(false); }, ctaIcon: react_1.default.createElement(pi_1.PiBag, null) }))) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
46
56
|
cart.map(function (item, index) {
|
|
47
|
-
var _a;
|
|
48
|
-
var cartItemId = generateCartItemId(item
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
var _a, _b, _c;
|
|
58
|
+
var cartItemId = generateCartItemId(item);
|
|
59
|
+
var currentPrice = ((_a = item.variant) === null || _a === void 0 ? void 0 : _a.price) || item.product.price;
|
|
60
|
+
var originalPrice = item.originalPrice || item.product.comparePrice || currentPrice;
|
|
61
|
+
var hasDiscount = originalPrice > currentPrice;
|
|
62
|
+
var isFirst = index === 0;
|
|
63
|
+
var isLast = index === cart.length - 1;
|
|
64
|
+
return (react_1.default.createElement(Flex_1.default, { key: "".concat(cartItemId, "-").concat(index), funcss: "bt pt pb ".concat(isLast ? "bb" : ""), alignItems: "center", justify: 'space-between', gap: 1, width: '100%' },
|
|
65
|
+
react_1.default.createElement(Div_1.default, { funcss: " width-80 height-80" }, ((_b = item.product.images) === null || _b === void 0 ? void 0 : _b[0]) ? (react_1.default.createElement(ImageScaler_1.default, { src: item.product.images[0], size: '80px' })) : (react_1.default.createElement(Div_1.default, { funcss: "w-80 h-80 flex central" },
|
|
54
66
|
react_1.default.createElement(Text_1.default, { text: "No Image", color: "text-light", size: "sm" })))),
|
|
55
|
-
react_1.default.createElement(Div_1.default, { funcss:
|
|
56
|
-
react_1.default.createElement(Text_1.default, { text: item.product.name, block: true }),
|
|
57
|
-
(item.
|
|
58
|
-
react_1.default.createElement(Text_1.default, { text: "".concat(item.
|
|
67
|
+
react_1.default.createElement(Div_1.default, { funcss: 'w-200' },
|
|
68
|
+
react_1.default.createElement(Text_1.default, { text: item.product.name, block: true, weight: 600 }),
|
|
69
|
+
((_c = item.variant) === null || _c === void 0 ? void 0 : _c.name) && (react_1.default.createElement(Text_1.default, { text: item.variant.name, size: 'sm', color: "text-light" })),
|
|
70
|
+
(item.selectedColor || item.selectedSize) && (react_1.default.createElement(Text_1.default, { text: "".concat(item.selectedColor ? "Color: ".concat(item.selectedColor) : '', " ").concat(item.selectedSize ? "Size: ".concat(item.selectedSize) : ''), size: 'sm', color: "text-light" })),
|
|
71
|
+
react_1.default.createElement(Flex_1.default, { gap: 0.2 },
|
|
72
|
+
hasDiscount && (react_1.default.createElement(Text_1.default, { text: "".concat(currency).concat(originalPrice.toFixed(2)), size: 'sm', color: "text-light", style: { textDecoration: 'line-through' } })),
|
|
73
|
+
react_1.default.createElement(Text_1.default, { text: "".concat(currency).concat(currentPrice.toFixed(2)).concat(hasDiscount ? " (Save ".concat(currency).concat((originalPrice - currentPrice).toFixed(2), ")") : ''), color: hasDiscount ? 'success' : 'text', size: 'xs' }))),
|
|
59
74
|
react_1.default.createElement("div", { className: "col" },
|
|
60
75
|
react_1.default.createElement(Flex_1.default, { width: '100%', gap: 0.5, alignItems: 'center' },
|
|
61
|
-
react_1.default.createElement(Circle_1.default, { size:
|
|
62
|
-
react_1.default.createElement("div", { className: "w-
|
|
76
|
+
react_1.default.createElement(Circle_1.default, { size: 1.5, bg: 'lighter', body: react_1.default.createElement(pi_1.PiMinus, { size: 12 }), onClick: function () { return handleUpdateQuantity(item, item.quantity - 1); }, "aria-label": "Decrease quantity of ".concat(item.product.name) }),
|
|
77
|
+
react_1.default.createElement("div", { className: "w-70" },
|
|
63
78
|
react_1.default.createElement(Input_1.default, { type: "number", value: item.quantity, onChange: function (e) {
|
|
64
79
|
var value = parseInt(e.target.value);
|
|
65
80
|
if (!isNaN(value)) {
|
|
66
81
|
handleUpdateQuantity(item, Math.max(1, value));
|
|
67
82
|
}
|
|
68
|
-
}, fullWidth: true, bordered: true })),
|
|
69
|
-
react_1.default.createElement(Circle_1.default, { bg: '
|
|
70
|
-
|
|
83
|
+
}, fullWidth: true, bordered: true, "aria-label": "Quantity for ".concat(item.product.name) })),
|
|
84
|
+
react_1.default.createElement(Circle_1.default, { bg: 'lighter', size: 1.5, body: react_1.default.createElement(pi_1.PiPlus, { size: 12 }), onClick: function () { return handleUpdateQuantity(item, item.quantity + 1); }, "aria-label": "Increase quantity of ".concat(item.product.name) }),
|
|
85
|
+
react_1.default.createElement("div", null),
|
|
86
|
+
react_1.default.createElement(Circle_1.default, { size: 1.5, body: react_1.default.createElement(pi_1.PiTrash, { size: 12 }), onClick: function () { return handleRemoveItem(item); }, bg: 'error', "aria-label": "Remove ".concat(item.product.name, " from cart") })))));
|
|
71
87
|
}),
|
|
72
|
-
react_1.default.createElement(
|
|
73
|
-
|
|
74
|
-
react_1.default.createElement(Text_1.default, { text: "Subtotal", color: "text-light" }),
|
|
75
|
-
react_1.default.createElement(Text_1.default, { text: "".concat(currency).concat(subtotal.toFixed(2)) })),
|
|
88
|
+
react_1.default.createElement("div", { className: "section" }, persistCart && (react_1.default.createElement(Button_1.default, { text: "Clear Cart", onClick: clearCart, startIcon: react_1.default.createElement(tb_1.TbShoppingBagX, null), bg: "error-light", color: "error", funcss: "full-width" }))),
|
|
89
|
+
react_1.default.createElement(Div_1.default, { funcss: 'mt' },
|
|
76
90
|
react_1.default.createElement(RowFlex_1.default, { justify: "space-between" },
|
|
77
91
|
react_1.default.createElement(Text_1.default, { text: "Items", color: "text-light" }),
|
|
78
|
-
react_1.default.createElement(Text_1.default, { text: totalItems.toString() }))
|
|
92
|
+
react_1.default.createElement(Text_1.default, { text: totalItems.toString() })),
|
|
93
|
+
totalSavings > 0 && (react_1.default.createElement(RowFlex_1.default, { justify: "space-between" },
|
|
94
|
+
react_1.default.createElement(Text_1.default, { text: "Total Savings", color: "text-light" }),
|
|
95
|
+
react_1.default.createElement(Text_1.default, { text: "-".concat(currency).concat(totalSavings.toFixed(2)), color: "success" }))),
|
|
96
|
+
react_1.default.createElement(RowFlex_1.default, { justify: "space-between" },
|
|
97
|
+
react_1.default.createElement(Text_1.default, { text: "Subtotal", color: "text-light" }),
|
|
98
|
+
react_1.default.createElement(Text_1.default, { text: "".concat(currency).concat(subtotal.toFixed(2)) })))))), footer: cart.length > 0 ? (react_1.default.createElement(Div_1.default, { funcss: "pt pb" },
|
|
79
99
|
react_1.default.createElement(RowFlex_1.default, { justify: "space-between", alignItems: "center" },
|
|
80
100
|
react_1.default.createElement(Div_1.default, null,
|
|
81
101
|
react_1.default.createElement(Text_1.default, { text: "Total", color: "text-light", size: "sm", block: true }),
|
|
82
102
|
react_1.default.createElement(Text_1.default, { text: "".concat(currency).concat(subtotal.toFixed(2)), size: "h4" })),
|
|
83
|
-
react_1.default.createElement(Button_1.default, { text: checkoutText, bg: "primary", raised: true, onClick: handleCheckout, funcss: "padding-x-30", startIcon: checkoutIcon
|
|
103
|
+
react_1.default.createElement(Button_1.default, { text: checkoutText, bg: "primary", raised: true, onClick: handleCheckout, funcss: "padding-x-30", startIcon: checkoutIcon })))) : react_1.default.createElement(react_1.default.Fragment, null) }));
|
|
84
104
|
};
|
|
85
105
|
exports.default = CartModal;
|
|
@@ -15,42 +15,29 @@ var ProductCard = function (_a) {
|
|
|
15
15
|
var discountPercent = hasDiscount
|
|
16
16
|
? Math.round(((product.comparePrice - product.price) / product.comparePrice) * 100)
|
|
17
17
|
: 0;
|
|
18
|
-
var stockAvailable = product.stock === undefined || product.stock > 0;
|
|
19
18
|
var handleClick = function () {
|
|
20
19
|
onClick === null || onClick === void 0 ? void 0 : onClick(product);
|
|
21
20
|
};
|
|
22
|
-
var handleAddToCart = function (e) {
|
|
23
|
-
e.stopPropagation();
|
|
24
|
-
onAddToCart === null || onAddToCart === void 0 ? void 0 : onAddToCart(product);
|
|
25
|
-
};
|
|
26
21
|
var getDisplayPrice = function () {
|
|
27
22
|
var price = product.price || 0;
|
|
28
23
|
var productCurrency = product.currency || currency;
|
|
29
24
|
return "".concat(productCurrency).concat(price.toFixed(2));
|
|
30
25
|
};
|
|
31
26
|
return (react_1.default.createElement(Div_1.default, { funcss: "funui_store_product-card ".concat(className, " ").concat(funcss), onClick: handleClick, customStyle: { cursor: 'pointer' } },
|
|
32
|
-
react_1.default.createElement(Div_1.default, { funcss: "funui_store_image-container" },
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
product.isNew && (react_1.default.createElement(Text_1.default, { size: 'xs', color: 'success', weight: 600 }, "New"))),
|
|
40
|
-
react_1.default.createElement(Flex_1.default, { gap: 0.5, direction: 'column', width: '100%' },
|
|
41
|
-
react_1.default.createElement(Text_1.default, { block: true, size: 'lg', truncate: 2 }, product.name),
|
|
42
|
-
react_1.default.createElement(Flex_1.default, { width: '100%', gap: 1, justify: 'space-between' },
|
|
27
|
+
react_1.default.createElement(Div_1.default, { funcss: "funui_store_image-container round-edge" }, ((_b = product.images) === null || _b === void 0 ? void 0 : _b[0]) ? (react_1.default.createElement("img", { src: product.images[0], alt: product.name, loading: "lazy", className: "funui_store_product-image" })) : (react_1.default.createElement(Div_1.default, { funcss: "funui_store_no-image" },
|
|
28
|
+
react_1.default.createElement(Text_1.default, { text: "No Image", color: "text-muted", size: "sm" })))),
|
|
29
|
+
react_1.default.createElement(Div_1.default, { funcss: "funui_store_product-info " },
|
|
30
|
+
product.category && (react_1.default.createElement(Text_1.default, { size: 'xs', opacity: 4, uppercase: true }, product.category)),
|
|
31
|
+
react_1.default.createElement(Flex_1.default, { width: '100%', gap: 0.5, direction: 'column' },
|
|
32
|
+
react_1.default.createElement(Text_1.default, { block: true, weight: 500, truncate: 2 }, product.name),
|
|
33
|
+
react_1.default.createElement(Flex_1.default, { width: '100%', gap: 1, justify: 'space-between', alignItems: 'center' },
|
|
43
34
|
react_1.default.createElement(Flex_1.default, { gap: 0.5, alignItems: 'center' },
|
|
44
|
-
react_1.default.createElement("span", { className: "
|
|
35
|
+
react_1.default.createElement("span", { className: "block" }, getDisplayPrice()),
|
|
45
36
|
hasDiscount && (react_1.default.createElement(Text_1.default, { size: 'xs', color: 'info', weight: 600 },
|
|
46
37
|
discountPercent,
|
|
47
38
|
"% Off"))),
|
|
48
39
|
hasDiscount && (react_1.default.createElement(Text_1.default, { size: "sm", opacity: 4, textDecoration: 'line-through' },
|
|
49
40
|
product.currency || currency,
|
|
50
|
-
product.comparePrice.toFixed(2))))
|
|
51
|
-
!stockAvailable ? (react_1.default.createElement("span", { className: "funui_store_stock-info out text-xs" }, "Out of Stock")) : product.stock !== undefined && product.stock > 0 && product.stock < 10 ? (react_1.default.createElement("span", { className: "funui_store_stock-info low text-xs" },
|
|
52
|
-
"Only ",
|
|
53
|
-
product.stock,
|
|
54
|
-
" left")) : stockAvailable && (react_1.default.createElement("span", { className: "funui_store_stock-info in text-xs" }, "In Stock"))))));
|
|
41
|
+
product.comparePrice.toFixed(2))))))));
|
|
55
42
|
};
|
|
56
43
|
exports.default = ProductCard;
|
|
@@ -57,8 +57,6 @@ var Text_1 = __importDefault(require("../text/Text"));
|
|
|
57
57
|
var Flex_1 = __importDefault(require("../flex/Flex"));
|
|
58
58
|
var Button_1 = __importDefault(require("../button/Button"));
|
|
59
59
|
var RowFlex_1 = __importDefault(require("../specials/RowFlex"));
|
|
60
|
-
var Input_1 = __importDefault(require("../input/Input"));
|
|
61
|
-
var Circle_1 = __importDefault(require("../specials/Circle"));
|
|
62
60
|
var Carousel_1 = __importDefault(require("../carousel/Carousel"));
|
|
63
61
|
var Select_1 = __importDefault(require("../select/Select"));
|
|
64
62
|
var io5_1 = require("react-icons/io5");
|
|
@@ -68,25 +66,43 @@ var ProductDetail = function (_a) {
|
|
|
68
66
|
var _c = (0, react_1.useState)(0), selectedImageIndex = _c[0], setSelectedImageIndex = _c[1];
|
|
69
67
|
var _d = (0, react_1.useState)(''), selectedColor = _d[0], setSelectedColor = _d[1];
|
|
70
68
|
var _e = (0, react_1.useState)(''), selectedSize = _e[0], setSelectedSize = _e[1];
|
|
71
|
-
var _f = (0, react_1.useState)(
|
|
72
|
-
var _g = (0, react_1.useState)(false),
|
|
69
|
+
var _f = (0, react_1.useState)(false), showFullDescription = _f[0], setShowFullDescription = _f[1];
|
|
70
|
+
var _g = (0, react_1.useState)(false), canAddToCart = _g[0], setCanAddToCart = _g[1];
|
|
73
71
|
var hasDiscount = product.comparePrice && product.comparePrice > product.price;
|
|
74
72
|
var discountPercent = hasDiscount
|
|
75
73
|
? Math.round(((product.comparePrice - product.price) / product.comparePrice) * 100)
|
|
76
74
|
: 0;
|
|
75
|
+
// Stock information logic
|
|
76
|
+
var stockAvailable = product.stock === undefined || product.stock > 0;
|
|
77
|
+
var lowStock = product.stock !== undefined && product.stock > 0 && product.stock < 10;
|
|
77
78
|
var getDisplayPrice = function () {
|
|
78
79
|
var price = product.price || 0;
|
|
79
80
|
var productCurrency = product.currency || currency;
|
|
80
81
|
return "".concat(productCurrency).concat(price.toFixed(2));
|
|
81
82
|
};
|
|
82
83
|
var handleAddToCart = function () {
|
|
83
|
-
|
|
84
|
+
// Always add with quantity 1
|
|
85
|
+
onAddToCart === null || onAddToCart === void 0 ? void 0 : onAddToCart(product, 1, {
|
|
84
86
|
color: selectedColor,
|
|
85
87
|
size: selectedSize,
|
|
86
88
|
});
|
|
87
89
|
setOpen(false);
|
|
88
90
|
};
|
|
89
|
-
|
|
91
|
+
// Validate if all required selections are made
|
|
92
|
+
(0, react_1.useEffect)(function () {
|
|
93
|
+
var isValid = true;
|
|
94
|
+
// Check if color selection is required and selected
|
|
95
|
+
if (product.colors && product.colors.length > 0) {
|
|
96
|
+
isValid = isValid && selectedColor !== '';
|
|
97
|
+
}
|
|
98
|
+
// Check if size selection is required and selected
|
|
99
|
+
if (product.sizes && product.sizes.length > 0) {
|
|
100
|
+
isValid = isValid && selectedSize !== '';
|
|
101
|
+
}
|
|
102
|
+
// Also check stock availability
|
|
103
|
+
isValid = isValid && stockAvailable;
|
|
104
|
+
setCanAddToCart(isValid);
|
|
105
|
+
}, [selectedColor, selectedSize, stockAvailable, product.colors, product.sizes]);
|
|
90
106
|
// Function to safely process description
|
|
91
107
|
var processDescription = function (description) {
|
|
92
108
|
if (!description)
|
|
@@ -143,107 +159,130 @@ var ProductDetail = function (_a) {
|
|
|
143
159
|
return (react_1.default.createElement(Modal_1.default, { animation: "SlideDown", open: open, setOpen: setOpen, maxWidth: '1000px', title: react_1.default.createElement(react_1.default.Fragment, null), body: react_1.default.createElement(Flex_1.default, { width: '100%', gap: 2 },
|
|
144
160
|
react_1.default.createElement("div", { className: "w-400" }, product.images && product.images.length > 0 && (react_1.default.createElement(Div_1.default, { funcss: "margin-bottom-20" },
|
|
145
161
|
react_1.default.createElement(Div_1.default, { funcss: "funui_products_main_image_container mb-3" },
|
|
146
|
-
react_1.default.createElement(ImageScaler_1.default, { src: product.images[selectedImageIndex], size: "
|
|
162
|
+
react_1.default.createElement(ImageScaler_1.default, { src: product.images[selectedImageIndex], size: "400px", funcss: 'round-edge' })),
|
|
147
163
|
product.images.length > 1 && (react_1.default.createElement(Carousel_1.default, { gap: 1 }, product.images.map(function (image, index) { return (react_1.default.createElement(Div_1.default, { key: index, funcss: "funui_products_thumbnail rounde-edge ".concat(selectedImageIndex === index ? 'funui_products_thumbnail-active' : ''), onClick: function () { return setSelectedImageIndex(index); } },
|
|
148
|
-
react_1.default.createElement(ImageScaler_1.default, { src: image, size: "100px" }))); })))))),
|
|
164
|
+
react_1.default.createElement(ImageScaler_1.default, { src: image, size: "100px", funcss: 'round-edge' }))); })))))),
|
|
149
165
|
react_1.default.createElement("div", { className: "col" },
|
|
150
|
-
react_1.default.createElement(Flex_1.default, { direction: 'column', gap: 2, alignItems: 'flex-start', justify: 'flex-start' },
|
|
151
|
-
react_1.default.createElement("div",
|
|
152
|
-
react_1.default.createElement(Text_1.default, { text: product.name, size: "2xl", block: true }),
|
|
166
|
+
react_1.default.createElement(Flex_1.default, { direction: 'column', gap: 2, alignItems: 'flex-start', justify: 'flex-start', width: '100%' },
|
|
167
|
+
react_1.default.createElement("div", { className: "w-full" },
|
|
153
168
|
react_1.default.createElement(Flex_1.default, { justify: "space-between", alignItems: "center", width: '100%' },
|
|
154
|
-
react_1.default.createElement(
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
react_1.default.createElement(
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
react_1.default.createElement(Flex_1.default, { gap: 1, alignItems: "center" },
|
|
170
|
+
product.category && (react_1.default.createElement(Text_1.default, { size: 'xs', opacity: 4, uppercase: true, weight: 500, color: "text-muted" }, product.category)),
|
|
171
|
+
product.isNew && (react_1.default.createElement(Div_1.default, { funcss: "badge-new" },
|
|
172
|
+
react_1.default.createElement(Text_1.default, { size: 'xs', color: 'white', weight: 600 }, "NEW"))),
|
|
173
|
+
product.isSale && (react_1.default.createElement(Div_1.default, { funcss: "badge-sale" },
|
|
174
|
+
react_1.default.createElement(Text_1.default, { size: 'xs', color: 'white', weight: 600 }, "SALE")))),
|
|
175
|
+
!stockAvailable ? (react_1.default.createElement(Text_1.default, { size: 'xs', color: 'error', weight: 600 }, "Out of Stock")) : lowStock ? (react_1.default.createElement(Text_1.default, { size: 'xs', color: 'warning', weight: 600 },
|
|
176
|
+
"Only ",
|
|
177
|
+
product.stock,
|
|
178
|
+
" left")) : (react_1.default.createElement(Text_1.default, { size: 'xs', color: 'success', weight: 600 }, "In Stock"))),
|
|
179
|
+
react_1.default.createElement(Text_1.default, { text: product.name, size: "2xl", block: true, weight: 600, funcss: "mb-3" }),
|
|
180
|
+
react_1.default.createElement(Flex_1.default, { justify: "space-between", alignItems: "center", width: '100%', funcss: "mb-3" },
|
|
181
|
+
react_1.default.createElement(Flex_1.default, { gap: 1, alignItems: "baseline" },
|
|
182
|
+
react_1.default.createElement(Text_1.default, { text: getDisplayPrice(), size: "xl", weight: 700, color: "primary" }),
|
|
183
|
+
hasDiscount && (react_1.default.createElement(Div_1.default, { funcss: "discount-percent" },
|
|
184
|
+
react_1.default.createElement(Text_1.default, { size: 'sm', color: 'white', weight: 600 },
|
|
185
|
+
"-",
|
|
186
|
+
discountPercent,
|
|
187
|
+
"%")))),
|
|
188
|
+
(hasDiscount || product.comparePrice) && (react_1.default.createElement(Text_1.default, { text: "".concat(product.currency || currency).concat(product.comparePrice.toFixed(2)), textDecoration: 'line-through', size: "sm", color: "text-muted" })))),
|
|
189
|
+
product.stock !== undefined && (react_1.default.createElement(Div_1.default, null,
|
|
190
|
+
react_1.default.createElement(Text_1.default, { size: 'xs', opacity: 4 },
|
|
191
|
+
product.stock,
|
|
192
|
+
" units available"))),
|
|
193
|
+
((product.colors && product.colors.length > 0) || (product.sizes && product.sizes.length > 0)) && (react_1.default.createElement(Flex_1.default, { width: '100%', gap: 1, direction: "column" },
|
|
194
|
+
product.colors && product.colors.length > 0 && (react_1.default.createElement("div", { className: "col" },
|
|
195
|
+
react_1.default.createElement(Text_1.default, { size: "sm", weight: 500, funcss: "mb-1" },
|
|
196
|
+
"Color",
|
|
197
|
+
react_1.default.createElement(Text_1.default, { size: "xs", color: "error", funcss: "margin-left-1" }, "*")),
|
|
198
|
+
react_1.default.createElement(Select_1.default, { fullWidth: true, options: __spreadArray([
|
|
199
|
+
{ text: 'Select Color', value: '' }
|
|
200
|
+
], product.colors.map(function (color) { return ({
|
|
201
|
+
text: color.name,
|
|
202
|
+
value: color.name,
|
|
203
|
+
prefix: (react_1.default.createElement(Div_1.default, { funcss: "color-preview", customStyle: {
|
|
204
|
+
width: "20px",
|
|
205
|
+
height: "20px",
|
|
206
|
+
borderRadius: "50%",
|
|
207
|
+
backgroundColor: color.code,
|
|
208
|
+
border: selectedColor === color.name ? '2px solid var(--primary)' : '1px solid var(--border)'
|
|
209
|
+
} }))
|
|
210
|
+
}); }), true), value: selectedColor, onChange: function (e) { return setSelectedColor(e); }, bordered: true }),
|
|
211
|
+
selectedColor === '' && (react_1.default.createElement(Text_1.default, { size: "xs", color: "error", funcss: "margin-top-1" }, "Please select a color")))),
|
|
212
|
+
product.sizes && product.sizes.length > 0 && (react_1.default.createElement("div", { className: "col" },
|
|
213
|
+
react_1.default.createElement(Text_1.default, { size: "sm", weight: 500, funcss: "mb-1" },
|
|
214
|
+
"Size",
|
|
215
|
+
react_1.default.createElement(Text_1.default, { size: "xs", color: "error", funcss: "margin-left-1" }, "*")),
|
|
216
|
+
react_1.default.createElement(Select_1.default, { fullWidth: true, options: __spreadArray([
|
|
217
|
+
{ text: 'Select Size', value: '' }
|
|
218
|
+
], product.sizes.map(function (size) { return ({ text: size, value: size }); }), true), value: selectedSize, onChange: function (e) { return setSelectedSize(e); }, bordered: true }),
|
|
219
|
+
selectedSize === '' && (react_1.default.createElement(Text_1.default, { size: "xs", color: "error", funcss: "margin-top-1" }, "Please select a size")))))),
|
|
220
|
+
processedDescription && (react_1.default.createElement(Div_1.default, null,
|
|
221
|
+
react_1.default.createElement(Text_1.default, { text: "Description", size: "lg", weight: 600, funcss: "margin-bottom-1" }),
|
|
172
222
|
react_1.default.createElement("div", { className: "article text-sm ".concat(hasHTML ? '' : 'whitespace-pre-wrap'), dangerouslySetInnerHTML: { __html: displayDescription } }),
|
|
173
|
-
shouldTruncate && (react_1.default.createElement(Button_1.default, { text: showFullDescription ? 'Show Less' : 'Read More', onClick: function () { return setShowFullDescription(!showFullDescription); }, small: true, bg: 'lighter', startIcon: showFullDescription ? react_1.default.createElement(pi_1.PiCaretUp, null) : react_1.default.createElement(pi_1.PiCaretDown, null) })))),
|
|
174
|
-
react_1.default.createElement("
|
|
223
|
+
shouldTruncate && (react_1.default.createElement(Button_1.default, { text: showFullDescription ? 'Show Less' : 'Read More', onClick: function () { return setShowFullDescription(!showFullDescription); }, small: true, bg: 'lighter', startIcon: showFullDescription ? react_1.default.createElement(pi_1.PiCaretUp, null) : react_1.default.createElement(pi_1.PiCaretDown, null), funcss: "mt-2" })))),
|
|
224
|
+
react_1.default.createElement(Div_1.default, { funcss: "product-details-grid" },
|
|
175
225
|
react_1.default.createElement(Flex_1.default, { gap: 3, width: '100%' },
|
|
176
|
-
product.
|
|
177
|
-
react_1.default.createElement(
|
|
178
|
-
react_1.default.createElement(
|
|
179
|
-
react_1.default.createElement(
|
|
180
|
-
react_1.default.createElement(Text_1.default, { text: "
|
|
181
|
-
react_1.default.createElement(Text_1.default, { text: product.
|
|
182
|
-
product.
|
|
183
|
-
react_1.default.createElement(
|
|
226
|
+
product.brand && (react_1.default.createElement(Flex_1.default, { gap: 0.3, funcss: "detail-item" },
|
|
227
|
+
react_1.default.createElement(Div_1.default, null,
|
|
228
|
+
react_1.default.createElement(si_1.SiBlackmagicdesign, { className: 'text-primary' })),
|
|
229
|
+
react_1.default.createElement(Div_1.default, null,
|
|
230
|
+
react_1.default.createElement(Text_1.default, { text: "Brand", size: "xs", opacity: 4, block: true }),
|
|
231
|
+
react_1.default.createElement(Text_1.default, { text: product.brand, size: "sm", block: true, lineHeight: '1', weight: 500 })))),
|
|
232
|
+
product.sku && (react_1.default.createElement(Flex_1.default, { gap: 0.3, funcss: "detail-item" },
|
|
233
|
+
react_1.default.createElement(Div_1.default, null,
|
|
234
|
+
react_1.default.createElement(pi_1.PiTag, { className: 'text-primary' })),
|
|
235
|
+
react_1.default.createElement(Div_1.default, null,
|
|
236
|
+
react_1.default.createElement(Text_1.default, { text: "SKU", size: "xs", opacity: 4, block: true }),
|
|
237
|
+
react_1.default.createElement(Text_1.default, { text: product.sku, size: "sm", block: true, lineHeight: '1', weight: 500 })))),
|
|
238
|
+
product.rating && (react_1.default.createElement(Flex_1.default, { gap: 0.3, funcss: "detail-item" },
|
|
239
|
+
react_1.default.createElement(Div_1.default, null,
|
|
240
|
+
react_1.default.createElement(tfi_1.TfiComments, { className: 'text-primary' })),
|
|
241
|
+
react_1.default.createElement(Div_1.default, null,
|
|
242
|
+
react_1.default.createElement(Text_1.default, { text: "Rating", size: "xs", opacity: 4, block: true }),
|
|
243
|
+
react_1.default.createElement(Text_1.default, { text: product.rating.toString(), size: "sm", block: true, lineHeight: '1', weight: 500 })))),
|
|
244
|
+
product.weight && (react_1.default.createElement(Flex_1.default, { gap: 0.3, funcss: "detail-item" },
|
|
245
|
+
react_1.default.createElement(Div_1.default, null,
|
|
246
|
+
react_1.default.createElement(pi_1.PiScales, { className: 'text-primary' })),
|
|
247
|
+
react_1.default.createElement(Div_1.default, null,
|
|
248
|
+
react_1.default.createElement(Text_1.default, { text: "Weight", size: "xs", opacity: 4, block: true }),
|
|
249
|
+
react_1.default.createElement(Text_1.default, { text: "".concat(product.weight, " ").concat(product.weightUnit || ''), size: "sm", block: true, lineHeight: '1', weight: 500 })))),
|
|
250
|
+
product.manufacturer && (react_1.default.createElement(Flex_1.default, { gap: 0.3, funcss: "detail-item" },
|
|
251
|
+
react_1.default.createElement(Div_1.default, null,
|
|
184
252
|
react_1.default.createElement(pi_1.PiUser, { className: 'text-primary' })),
|
|
185
|
-
react_1.default.createElement(
|
|
253
|
+
react_1.default.createElement(Div_1.default, null,
|
|
186
254
|
react_1.default.createElement(Text_1.default, { text: "Manufacturer", size: "xs", opacity: 4, block: true }),
|
|
187
|
-
react_1.default.createElement(Text_1.default, { text: product.manufacturer, size: "sm", block: true, lineHeight: '1' })))),
|
|
188
|
-
product.countryOfOrigin && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
|
|
189
|
-
react_1.default.createElement(
|
|
255
|
+
react_1.default.createElement(Text_1.default, { text: product.manufacturer, size: "sm", block: true, lineHeight: '1', weight: 500 })))),
|
|
256
|
+
product.countryOfOrigin && (react_1.default.createElement(Flex_1.default, { gap: 0.3, funcss: "detail-item" },
|
|
257
|
+
react_1.default.createElement(Div_1.default, null,
|
|
190
258
|
react_1.default.createElement(pi_1.PiGlobe, { className: 'text-primary' })),
|
|
191
|
-
react_1.default.createElement(
|
|
259
|
+
react_1.default.createElement(Div_1.default, null,
|
|
192
260
|
react_1.default.createElement(Text_1.default, { text: "Country of Origin", size: "xs", opacity: 4, block: true }),
|
|
193
|
-
react_1.default.createElement(Text_1.default, { text: product.countryOfOrigin, size: "sm", block: true, lineHeight: '1' })))),
|
|
194
|
-
product.
|
|
195
|
-
react_1.default.createElement(
|
|
196
|
-
react_1.default.createElement(pi_1.
|
|
197
|
-
react_1.default.createElement(
|
|
198
|
-
react_1.default.createElement(Text_1.default, { text: "
|
|
199
|
-
react_1.default.createElement(Text_1.default, { text:
|
|
200
|
-
product.
|
|
201
|
-
react_1.default.createElement(
|
|
202
|
-
react_1.default.createElement(tfi_1.TfiComments, { className: 'text-primary' })),
|
|
203
|
-
react_1.default.createElement("div", null,
|
|
204
|
-
react_1.default.createElement(Text_1.default, { text: "Rating", size: "xs", opacity: 4, block: true }),
|
|
205
|
-
react_1.default.createElement(Text_1.default, { text: product.rating, size: "sm", block: true, lineHeight: '1' })))),
|
|
206
|
-
product.brand && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
|
|
207
|
-
react_1.default.createElement("div", null,
|
|
208
|
-
react_1.default.createElement(si_1.SiBlackmagicdesign, { className: 'text-primary' })),
|
|
209
|
-
react_1.default.createElement("div", null,
|
|
210
|
-
react_1.default.createElement(Text_1.default, { text: "Brand", size: "xs", opacity: 4, block: true }),
|
|
211
|
-
react_1.default.createElement(Text_1.default, { text: product.brand, size: "sm", block: true, lineHeight: '1' })))),
|
|
212
|
-
product.category && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
|
|
213
|
-
react_1.default.createElement("div", null,
|
|
261
|
+
react_1.default.createElement(Text_1.default, { text: product.countryOfOrigin, size: "sm", block: true, lineHeight: '1', weight: 500 })))),
|
|
262
|
+
product.warranty && (react_1.default.createElement(Flex_1.default, { gap: 0.3, funcss: "detail-item" },
|
|
263
|
+
react_1.default.createElement(Div_1.default, null,
|
|
264
|
+
react_1.default.createElement(pi_1.PiShieldCheck, { className: 'text-primary' })),
|
|
265
|
+
react_1.default.createElement(Div_1.default, null,
|
|
266
|
+
react_1.default.createElement(Text_1.default, { text: "Warranty", size: "xs", opacity: 4, block: true }),
|
|
267
|
+
react_1.default.createElement(Text_1.default, { text: product.warranty, size: "sm", block: true, lineHeight: '1', weight: 500 })))),
|
|
268
|
+
product.category && (react_1.default.createElement(Flex_1.default, { gap: 0.3, funcss: "detail-item" },
|
|
269
|
+
react_1.default.createElement(Div_1.default, null,
|
|
214
270
|
react_1.default.createElement(io5_1.IoLayersOutline, { className: 'text-primary' })),
|
|
215
|
-
react_1.default.createElement(
|
|
271
|
+
react_1.default.createElement(Div_1.default, null,
|
|
216
272
|
react_1.default.createElement(Text_1.default, { text: "Category", size: "xs", opacity: 4, block: true }),
|
|
217
|
-
react_1.default.createElement(Text_1.default, { text: product.category, size: "sm", block: true, lineHeight: '1' })))),
|
|
218
|
-
product.
|
|
219
|
-
react_1.default.createElement(
|
|
220
|
-
react_1.default.createElement(pi_1.
|
|
221
|
-
react_1.default.createElement(
|
|
222
|
-
react_1.default.createElement(Text_1.default, { text: "
|
|
223
|
-
react_1.default.createElement(Text_1.default, { text:
|
|
224
|
-
product.
|
|
225
|
-
react_1.default.createElement(
|
|
226
|
-
react_1.default.createElement(pi_1.
|
|
227
|
-
react_1.default.createElement(
|
|
228
|
-
react_1.default.createElement(Text_1.default, { text: "
|
|
229
|
-
react_1.default.createElement(Text_1.default, { text:
|
|
230
|
-
|
|
231
|
-
react_1.default.createElement("div", null,
|
|
232
|
-
react_1.default.createElement(pi_1.PiScales, { className: 'text-primary' })),
|
|
233
|
-
react_1.default.createElement("div", null,
|
|
234
|
-
react_1.default.createElement(Text_1.default, { text: "Weight", size: "xs", opacity: 4, block: true }),
|
|
235
|
-
react_1.default.createElement(Text_1.default, { text: product.weight + " " + product.weightUnit, size: "sm", block: true, lineHeight: '1' }))))))))), footer: react_1.default.createElement(RowFlex_1.default, { gap: 1, justify: 'flex-end', funcss: 'pt' },
|
|
236
|
-
react_1.default.createElement(RowFlex_1.default, { gap: 0.5, alignItems: "center" },
|
|
237
|
-
react_1.default.createElement(Circle_1.default, { body: react_1.default.createElement(pi_1.PiMinus, null), onClick: function () { return setQuantity(Math.max(1, quantity - 1)); }, funcss: quantity <= 1 ? "disabled" : "" }),
|
|
238
|
-
react_1.default.createElement("div", { className: "w-90" },
|
|
239
|
-
react_1.default.createElement(Input_1.default, { type: "number", value: quantity, onChange: function (e) {
|
|
240
|
-
var value = parseInt(e.target.value);
|
|
241
|
-
if (!isNaN(value)) {
|
|
242
|
-
setQuantity(Math.max(1, value));
|
|
243
|
-
}
|
|
244
|
-
}, funcss: "text-center", bordered: true })),
|
|
245
|
-
react_1.default.createElement(Circle_1.default, { onClick: function () { return setQuantity(quantity + 1); }, bg: 'lighter' },
|
|
246
|
-
react_1.default.createElement(pi_1.PiPlus, null))),
|
|
247
|
-
react_1.default.createElement(Button_1.default, { text: "Add to Cart - ".concat(currency).concat(totalPrice), bg: "primary", raised: true, onClick: handleAddToCart })) }));
|
|
273
|
+
react_1.default.createElement(Text_1.default, { text: product.category, size: "sm", block: true, lineHeight: '1', weight: 500 })))),
|
|
274
|
+
product.brand && (react_1.default.createElement(Flex_1.default, { gap: 0.3, funcss: "detail-item" },
|
|
275
|
+
react_1.default.createElement(Div_1.default, null,
|
|
276
|
+
react_1.default.createElement(pi_1.PiStorefront, { className: 'text-primary' })),
|
|
277
|
+
react_1.default.createElement(Div_1.default, null,
|
|
278
|
+
react_1.default.createElement(Text_1.default, { text: "Store", size: "xs", opacity: 4, block: true }),
|
|
279
|
+
react_1.default.createElement(Text_1.default, { text: product.brand, size: "sm", block: true, lineHeight: '1', weight: 500 })))),
|
|
280
|
+
product.tags && product.tags.length > 0 && (react_1.default.createElement(Flex_1.default, { gap: 0.3, funcss: "detail-item" },
|
|
281
|
+
react_1.default.createElement(Div_1.default, null,
|
|
282
|
+
react_1.default.createElement(pi_1.PiTag, { className: 'text-primary' })),
|
|
283
|
+
react_1.default.createElement(Div_1.default, null,
|
|
284
|
+
react_1.default.createElement(Text_1.default, { text: "Tags", size: "xs", opacity: 4, block: true }),
|
|
285
|
+
react_1.default.createElement(Text_1.default, { text: product.tags.join(', '), size: "sm", block: true, lineHeight: '1', truncate: 1 }))))))))), footer: react_1.default.createElement(RowFlex_1.default, { gap: 1, justify: 'flex-end', funcss: 'pt' },
|
|
286
|
+
react_1.default.createElement(Button_1.default, { text: "Add to Cart", startIcon: react_1.default.createElement(pi_1.PiBag, null), bg: "primary", raised: true, onClick: handleAddToCart, disabled: !canAddToCart, funcss: !canAddToCart ? "opacity-6" : "" })) }));
|
|
248
287
|
};
|
|
249
288
|
exports.default = ProductDetail;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
var react_1 = __importDefault(require("react"));
|
|
8
|
+
var Div_1 = __importDefault(require("../div/Div"));
|
|
9
|
+
var View_1 = __importDefault(require("../view/View"));
|
|
10
|
+
var ProductLoader = function () {
|
|
11
|
+
return (react_1.default.createElement(Div_1.default, { funcss: "funui_store_product-card " },
|
|
12
|
+
react_1.default.createElement(Div_1.default, { funcss: "funui_store_image-container round-edge skeleton" }),
|
|
13
|
+
react_1.default.createElement(View_1.default, { funcss: 'skeleton round-edge', style: {
|
|
14
|
+
height: "1rem",
|
|
15
|
+
marginTop: "0.5rem"
|
|
16
|
+
} }),
|
|
17
|
+
react_1.default.createElement(View_1.default, { funcss: 'skeleton round-edge', style: {
|
|
18
|
+
height: "3rem",
|
|
19
|
+
marginTop: "0.5rem"
|
|
20
|
+
} })));
|
|
21
|
+
};
|
|
22
|
+
exports.default = ProductLoader;
|