mautourco-components 0.2.73 → 0.2.75
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/dist/components/atoms/Icon/icons/ViewQuotationIcon.d.ts +8 -0
- package/dist/components/atoms/Icon/icons/ViewQuotationIcon.js +25 -0
- package/dist/components/atoms/Icon/icons/registry.d.ts +1 -0
- package/dist/components/atoms/Icon/icons/registry.js +2 -0
- package/dist/components/organisms/CarBookingCard/CarBookingCard.js +38 -2
- package/dist/components/organisms/Docket/Docket.js +1 -1
- package/dist/styles/components/organism/docket.css +46 -0
- package/package.json +1 -1
- package/src/components/atoms/Icon/icons/ViewQuotationIcon.tsx +105 -0
- package/src/components/atoms/Icon/icons/registry.tsx +2 -0
- package/src/components/organisms/CarBookingCard/CarBookingCard.tsx +54 -10
- package/src/components/organisms/Docket/Docket.tsx +11 -9
- package/src/styles/components/organism/docket.css +46 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
var ViewQuotationIcon = function (_a) {
|
|
3
|
+
var _b = _a.size, size = _b === void 0 ? 'md' : _b, _c = _a.className, className = _c === void 0 ? '' : _c, color = _a.color;
|
|
4
|
+
var getSizeClasses = function () {
|
|
5
|
+
switch (size) {
|
|
6
|
+
case 'xs':
|
|
7
|
+
return 'w-3 h-3';
|
|
8
|
+
case 'sm':
|
|
9
|
+
return 'w-4 h-4';
|
|
10
|
+
case 'md':
|
|
11
|
+
return 'w-5 h-5';
|
|
12
|
+
case 'lg':
|
|
13
|
+
return 'w-6 h-6';
|
|
14
|
+
case 'xl':
|
|
15
|
+
return 'w-8 h-8';
|
|
16
|
+
default:
|
|
17
|
+
return 'w-5 h-5';
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
var sizeClasses = getSizeClasses();
|
|
21
|
+
var colorClass = color ? "text-".concat(color) : 'text-current';
|
|
22
|
+
var classes = "".concat(sizeClasses, " ").concat(colorClass, " ").concat(className);
|
|
23
|
+
return (_jsxs("svg", { className: classes, viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("rect", { x: "4", y: "4", width: "12", height: "12", stroke: "currentColor", strokeWidth: "1.5", fill: "none", strokeLinecap: "round" }), _jsx("path", { d: "M4 4L4 1M4 4L1 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M16 4L16 1M16 4L19 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M4 16L4 19M4 16L1 16", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M16 16L16 19M16 16L19 16", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("ellipse", { cx: "10", cy: "10", rx: "3.5", ry: "2.5", stroke: "currentColor", strokeWidth: "1.5", fill: "none" }), _jsx("circle", { cx: "10", cy: "10", r: "1.5", fill: "currentColor" })] }));
|
|
24
|
+
};
|
|
25
|
+
export default ViewQuotationIcon;
|
|
@@ -70,6 +70,7 @@ import TwitterIcon from './TwitterIcon';
|
|
|
70
70
|
import User from './User';
|
|
71
71
|
import UserIcon from './UserIcon';
|
|
72
72
|
import UtensilsIcon from './Utensils';
|
|
73
|
+
import ViewQuotationIcon from './ViewQuotationIcon';
|
|
73
74
|
import WalletIcon from './WalletIcon';
|
|
74
75
|
import YouTubeIcon from './Youtube';
|
|
75
76
|
var ChevronDown = function (props) { return _jsx(Chevron, __assign({ direction: "down" }, props)); };
|
|
@@ -148,4 +149,5 @@ export var ICONS = {
|
|
|
148
149
|
'close-circle': CloseCircleIcon,
|
|
149
150
|
clock: ClockIcon,
|
|
150
151
|
'info-2': Info2Icon,
|
|
152
|
+
'view-quotation': ViewQuotationIcon,
|
|
151
153
|
};
|
|
@@ -10,6 +10,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
10
10
|
return __assign.apply(this, arguments);
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
import { useState } from 'react';
|
|
13
14
|
import Button from '../../atoms/Button/Button';
|
|
14
15
|
import Divider from '../../atoms/Divider/Divider';
|
|
15
16
|
import DropdownInput from '../../atoms/Inputs/DropdownInput/DropdownInput';
|
|
@@ -19,13 +20,48 @@ import './CarBookingCard.css';
|
|
|
19
20
|
var CarBookingCard = function (_a) {
|
|
20
21
|
var _b;
|
|
21
22
|
var imageSrc = _a.imageSrc, title = _a.title, _c = _a.size, size = _c === void 0 ? 'large' : _c, _d = _a.state, state = _d === void 0 ? 'default' : _d, _e = _a.type, type = _e === void 0 ? 'default' : _e, features = _a.features, infoText = _a.infoText, _f = _a.priceTitle, priceTitle = _f === void 0 ? 'Price breakdown' : _f, _g = _a.priceRows, priceRows = _g === void 0 ? [] : _g, showSupplement = _a.showSupplement, supplementMessage = _a.supplementMessage, _h = _a.supplementLabel, supplementLabel = _h === void 0 ? 'Supplement' : _h, _j = _a.supplementPlaceholder, supplementPlaceholder = _j === void 0 ? 'Select a supplement' : _j, supplementValue = _a.supplementValue, _k = _a.supplementState, supplementState = _k === void 0 ? 'default' : _k, _l = _a.supplementOptions, supplementOptions = _l === void 0 ? [] : _l, onSupplementSelect = _a.onSupplementSelect, totalPrice = _a.totalPrice, _m = _a.totalPriceLabel, totalPriceLabel = _m === void 0 ? 'Total price' : _m, ctaLabel = _a.ctaLabel, ctaButtonProps = _a.ctaButtonProps, onCtaClick = _a.onCtaClick, _o = _a.readonly, readonly = _o === void 0 ? false : _o, _p = _a.className, className = _p === void 0 ? '' : _p;
|
|
23
|
+
var _q = useState(state === 'selected'), isSelected = _q[0], setIsSelected = _q[1];
|
|
24
|
+
var _r = useState(false), isHovered = _r[0], setIsHovered = _r[1];
|
|
22
25
|
var resolvedShowSupplement = showSupplement !== null && showSupplement !== void 0 ? showSupplement : Boolean(supplementLabel || supplementPlaceholder || supplementOptions.length > 0);
|
|
23
26
|
var resolvedSupplementState = supplementMessage ? 'disabled' : supplementState;
|
|
27
|
+
// Handle CTA click: toggle between "Add to quote" and "Selected"
|
|
28
|
+
var handleCtaClick = function (e) {
|
|
29
|
+
setIsSelected(!isSelected);
|
|
30
|
+
onCtaClick === null || onCtaClick === void 0 ? void 0 : onCtaClick(e);
|
|
31
|
+
};
|
|
32
|
+
// Determine button state based on selection and hover
|
|
33
|
+
var shouldShowRemove = isSelected && isHovered;
|
|
34
|
+
var shouldShowSelected = isSelected && !isHovered;
|
|
35
|
+
var resolvedCtaLabel = shouldShowRemove
|
|
36
|
+
? 'Remove'
|
|
37
|
+
: shouldShowSelected
|
|
38
|
+
? 'Selected'
|
|
39
|
+
: ctaLabel;
|
|
40
|
+
var resolvedCtaButtonProps = shouldShowRemove
|
|
41
|
+
? {
|
|
42
|
+
variant: 'destructive',
|
|
43
|
+
size: 'sm',
|
|
44
|
+
leadingIcon: 'close',
|
|
45
|
+
iconSize: 'sm',
|
|
46
|
+
}
|
|
47
|
+
: shouldShowSelected
|
|
48
|
+
? {
|
|
49
|
+
variant: 'secondary',
|
|
50
|
+
size: 'sm',
|
|
51
|
+
leadingIcon: 'check-circle',
|
|
52
|
+
iconSize: 'sm',
|
|
53
|
+
}
|
|
54
|
+
: {
|
|
55
|
+
variant: 'primary',
|
|
56
|
+
size: 'sm',
|
|
57
|
+
};
|
|
58
|
+
// Update card state class based on selection
|
|
59
|
+
var resolvedState = isSelected ? 'selected' : state;
|
|
24
60
|
var baseClass = 'car-booking-card';
|
|
25
61
|
var classes = [
|
|
26
62
|
baseClass,
|
|
27
63
|
"".concat(baseClass, "--").concat(size),
|
|
28
|
-
"".concat(baseClass, "--").concat(
|
|
64
|
+
"".concat(baseClass, "--").concat(resolvedState),
|
|
29
65
|
"".concat(baseClass, "--").concat(type),
|
|
30
66
|
readonly ? "".concat(baseClass, "--readonly") : '',
|
|
31
67
|
className,
|
|
@@ -35,6 +71,6 @@ var CarBookingCard = function (_a) {
|
|
|
35
71
|
return (_jsxs("article", { className: classes, children: [_jsx("div", { className: "car-booking-card__image-wrap", children: _jsx("img", { className: "car-booking-card__image", src: imageSrc, alt: "" }) }), _jsx("div", { className: "car-booking-card__active-divider" }), _jsxs("div", { className: "car-booking-card__body", children: [_jsxs("section", { className: "car-booking-card__section car-booking-card__section--content", children: [_jsxs("div", { className: "car-booking-card__title", children: [_jsx("span", { className: "car-booking-card__title-marker", "aria-hidden": "true" }), _jsx(Heading, { level: 4, variant: "bold", color: "accent", className: "car-booking-card__title-text", children: title })] }), _jsx("div", { className: "car-booking-card__features", children: features.map(function (feature, idx) {
|
|
36
72
|
var _a;
|
|
37
73
|
return (_jsx(FeatureRow, __assign({}, feature, { className: "car-booking-card__feature-row ".concat((_a = feature.className) !== null && _a !== void 0 ? _a : '').trim() }), "".concat(feature.label, "-").concat(idx)));
|
|
38
|
-
}) }), infoText && !readonly && (_jsxs("div", { className: "car-booking-card__info", children: [_jsx("span", { className: "car-booking-card__info-icon", "aria-hidden": "true", children: "i" }), _jsx(Text, { size: "sm", leading: "5", variant: "regular", color: "default", className: "car-booking-card__info-text", children: infoText })] }))] }), resolvedShowSupplement && !readonly && (_jsxs("section", { className: "car-booking-card__section car-booking-card__section--supplement", children: [_jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" }), _jsxs("div", { className: "car-booking-card__supplement-header", children: [_jsx(Text, { as: "h3", size: "md", variant: "bold", leading: "none", color: "default", className: "car-booking-card__section-title", children: supplementLabel }), supplementMessage && (_jsx(Text, { as: "p", size: "sm", leading: "5", variant: "regular", className: "car-booking-card__supplement-message", children: supplementMessage }))] }), readonly ? (_jsx(Text, { size: "sm", leading: "5", variant: "regular", color: supplementValue ? "default" : "subtle", className: "car-booking-card__supplement-value", children: supplementValue || supplementPlaceholder })) : (_jsx(DropdownInput, { placeholder: supplementPlaceholder, value: supplementValue, state: resolvedSupplementState, options: supplementOptions, onSelect: onSupplementSelect }))] })), priceRows.length > 0 && !readonly && (_jsxs("section", { className: "car-booking-card__section car-booking-card__section--price", children: [_jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" }), _jsxs("div", { className: "car-booking-card__price-content", children: [_jsx(Text, { as: "h3", size: "md", variant: "bold", leading: "none", color: "default", className: "car-booking-card__section-title", children: priceTitle }), _jsx("div", { className: "car-booking-card__price-rows", children: priceRows.map(function (row, idx) { return (_jsxs("div", { className: "car-booking-card__price-row", children: [_jsx(Text, { size: "sm", leading: "5", variant: "regular", color: "subtle", className: "car-booking-card__price-label", children: row.label }), _jsx(Text, { size: "sm", leading: "5", variant: "bold", color: "subtle", className: "car-booking-card__price-value", children: row.value })] }, "".concat(row.label, "-").concat(idx))); }) })] }), _jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" })] })), !readonly && _jsxs("footer", { className: "car-booking-card__footer", children: [_jsxs("div", { className: "car-booking-card__total", children: [_jsx(Text, { size: "base", variant: "bold", color: "accent", className: "car-booking-card__total-price", children: totalPrice }), _jsx(Text, { size: "sm", variant: "regular", color: "subtle", className: "car-booking-card__total-label", children: totalPriceLabel })] }), !readonly && (_jsx(
|
|
74
|
+
}) }), infoText && !readonly && (_jsxs("div", { className: "car-booking-card__info", children: [_jsx("span", { className: "car-booking-card__info-icon", "aria-hidden": "true", children: "i" }), _jsx(Text, { size: "sm", leading: "5", variant: "regular", color: "default", className: "car-booking-card__info-text", children: infoText })] }))] }), resolvedShowSupplement && !readonly && (_jsxs("section", { className: "car-booking-card__section car-booking-card__section--supplement", children: [_jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" }), _jsxs("div", { className: "car-booking-card__supplement-header", children: [_jsx(Text, { as: "h3", size: "md", variant: "bold", leading: "none", color: "default", className: "car-booking-card__section-title", children: supplementLabel }), supplementMessage && (_jsx(Text, { as: "p", size: "sm", leading: "5", variant: "regular", className: "car-booking-card__supplement-message", children: supplementMessage }))] }), readonly ? (_jsx(Text, { size: "sm", leading: "5", variant: "regular", color: supplementValue ? "default" : "subtle", className: "car-booking-card__supplement-value", children: supplementValue || supplementPlaceholder })) : (_jsx(DropdownInput, { placeholder: supplementPlaceholder, value: supplementValue, state: resolvedSupplementState, options: supplementOptions, onSelect: onSupplementSelect }))] })), priceRows.length > 0 && !readonly && (_jsxs("section", { className: "car-booking-card__section car-booking-card__section--price", children: [_jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" }), _jsxs("div", { className: "car-booking-card__price-content", children: [_jsx(Text, { as: "h3", size: "md", variant: "bold", leading: "none", color: "default", className: "car-booking-card__section-title", children: priceTitle }), _jsx("div", { className: "car-booking-card__price-rows", children: priceRows.map(function (row, idx) { return (_jsxs("div", { className: "car-booking-card__price-row", children: [_jsx(Text, { size: "sm", leading: "5", variant: "regular", color: "subtle", className: "car-booking-card__price-label", children: row.label }), _jsx(Text, { size: "sm", leading: "5", variant: "bold", color: "subtle", className: "car-booking-card__price-value", children: row.value })] }, "".concat(row.label, "-").concat(idx))); }) })] }), _jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" })] })), !readonly && _jsxs("footer", { className: "car-booking-card__footer", children: [_jsxs("div", { className: "car-booking-card__total", children: [_jsx(Text, { size: "base", variant: "bold", color: "accent", className: "car-booking-card__total-price", children: totalPrice }), _jsx(Text, { size: "sm", variant: "regular", color: "subtle", className: "car-booking-card__total-label", children: totalPriceLabel })] }), !readonly && (_jsx("div", { onMouseEnter: function () { return setIsHovered(true); }, onMouseLeave: function () { return setIsHovered(false); }, className: "car-booking-card__cta-wrapper", children: _jsx(Button, __assign({}, resolvedCtaButtonProps, { onClick: handleCtaClick, className: "car-booking-card__cta ".concat((_b = resolvedCtaButtonProps === null || resolvedCtaButtonProps === void 0 ? void 0 : resolvedCtaButtonProps.className) !== null && _b !== void 0 ? _b : '').trim(), children: resolvedCtaLabel })) }))] })] })] }));
|
|
39
75
|
};
|
|
40
76
|
export default CarBookingCard;
|
|
@@ -43,7 +43,7 @@ export var DocketHeader = function (_a) {
|
|
|
43
43
|
export var DocketFooter = function (_a) {
|
|
44
44
|
var _b = _a.mode, mode = _b === void 0 ? 'multiple' : _b, onAddNewQuoteClick = _a.onAddNewQuoteClick, onViewClick = _a.onViewClick, onSaveClick = _a.onSaveClick, onBookNowClick = _a.onBookNowClick, _c = _a.className, className = _c === void 0 ? '' : _c;
|
|
45
45
|
var isSingleMode = mode === 'single';
|
|
46
|
-
return (_jsxs("div", { className: "docket__footer ".concat(className), children: [!isSingleMode && onAddNewQuoteClick && (_jsx(Button, { variant: "outline-secondary", size: "sm", leadingIcon: "plus", onClick: onAddNewQuoteClick, className: "docket__footer-button docket__footer-button--full", children: "Add new quote" })),
|
|
46
|
+
return (_jsxs("div", { className: "docket__footer ".concat(className), children: [!isSingleMode && onAddNewQuoteClick && (_jsx(Button, { variant: "outline-secondary", size: "sm", leadingIcon: "plus", onClick: onAddNewQuoteClick, className: "docket__footer-button docket__footer-button--full", children: "Add new quote" })), !isSingleMode && onViewClick && (_jsx("div", { className: "docket__footer-view", children: _jsxs("button", { type: "button", onClick: onViewClick, className: "docket__footer-view-link", children: [_jsx(Icon, { name: "view-quotation", size: "sm", className: "docket__footer-view-icon" }), _jsx("span", { className: "docket__footer-view-text", children: "View quotation" })] }) })), _jsxs("div", { className: "docket__footer-actions", children: [onSaveClick && (_jsx(Button, { variant: "outline-secondary", size: "sm", onClick: onSaveClick, className: "docket__footer-button", children: "Save quotation" })), onBookNowClick && (_jsx(Button, { variant: "secondary", size: "sm", onClick: onBookNowClick, className: "docket__footer-button docket__footer-button--primary", children: "Book now" }))] })] }));
|
|
47
47
|
};
|
|
48
48
|
/**
|
|
49
49
|
* Docket is a container component for displaying quotation/docket information.
|
|
@@ -221,6 +221,52 @@
|
|
|
221
221
|
min-width: 162px;
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
+
.docket__footer-view {
|
|
225
|
+
display: flex;
|
|
226
|
+
justify-content: flex-end;
|
|
227
|
+
width: 100%;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.docket__footer-view-link {
|
|
231
|
+
display: inline-flex;
|
|
232
|
+
align-items: center;
|
|
233
|
+
gap: var(--component-button-spacing-ghost-sm-gap, 6px);
|
|
234
|
+
background: none;
|
|
235
|
+
border: none;
|
|
236
|
+
padding: var(--component-button-spacing-ghost-sm-padding-y, 0px) var(--component-button-spacing-ghost-sm-padding-x, 0px);
|
|
237
|
+
cursor: pointer;
|
|
238
|
+
font-family: var(--font-font-family-body, 'Satoshi', sans-serif);
|
|
239
|
+
font-size: var(--font-size-text-sm, 14px);
|
|
240
|
+
font-weight: var(--font-weight-font-medium, 500);
|
|
241
|
+
line-height: var(--font-leading-leading-sm, 20px);
|
|
242
|
+
color: var(--color-button-ghost-foreground-default, #78716c);
|
|
243
|
+
text-decoration: none;
|
|
244
|
+
transition: color 0.2s ease;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.docket__footer-view-link:hover {
|
|
248
|
+
color: var(--color-button-ghost-foreground-hover, #44403c);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.docket__footer-view-link:active {
|
|
252
|
+
color: var(--color-button-ghost-foreground-pressed, #1c1917);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.docket__footer-view-link:focus {
|
|
256
|
+
outline: none;
|
|
257
|
+
color: var(--color-button-ghost-foreground-focused, #1c1917);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.docket__footer-view-text {
|
|
261
|
+
display: inline-block;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.docket__footer-view-icon {
|
|
265
|
+
display: inline-flex;
|
|
266
|
+
align-items: center;
|
|
267
|
+
color: inherit;
|
|
268
|
+
}
|
|
269
|
+
|
|
224
270
|
.docket__footer-actions {
|
|
225
271
|
display: flex;
|
|
226
272
|
gap: var(--spacing-gap-md, 8px);
|
package/package.json
CHANGED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ViewQuotationIconProps {
|
|
4
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
5
|
+
className?: string;
|
|
6
|
+
color?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const ViewQuotationIcon: React.FC<ViewQuotationIconProps> = ({
|
|
10
|
+
size = 'md',
|
|
11
|
+
className = '',
|
|
12
|
+
color,
|
|
13
|
+
}) => {
|
|
14
|
+
const getSizeClasses = () => {
|
|
15
|
+
switch (size) {
|
|
16
|
+
case 'xs':
|
|
17
|
+
return 'w-3 h-3';
|
|
18
|
+
case 'sm':
|
|
19
|
+
return 'w-4 h-4';
|
|
20
|
+
case 'md':
|
|
21
|
+
return 'w-5 h-5';
|
|
22
|
+
case 'lg':
|
|
23
|
+
return 'w-6 h-6';
|
|
24
|
+
case 'xl':
|
|
25
|
+
return 'w-8 h-8';
|
|
26
|
+
default:
|
|
27
|
+
return 'w-5 h-5';
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const sizeClasses = getSizeClasses();
|
|
32
|
+
const colorClass = color ? `text-${color}` : 'text-current';
|
|
33
|
+
const classes = `${sizeClasses} ${colorClass} ${className}`;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<svg
|
|
37
|
+
className={classes}
|
|
38
|
+
viewBox="0 0 20 20"
|
|
39
|
+
fill="none"
|
|
40
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
41
|
+
{/* Square frame */}
|
|
42
|
+
<rect
|
|
43
|
+
x="4"
|
|
44
|
+
y="4"
|
|
45
|
+
width="12"
|
|
46
|
+
height="12"
|
|
47
|
+
stroke="currentColor"
|
|
48
|
+
strokeWidth="1.5"
|
|
49
|
+
fill="none"
|
|
50
|
+
strokeLinecap="round"
|
|
51
|
+
/>
|
|
52
|
+
{/* Corner brackets extending outward - top-left */}
|
|
53
|
+
<path
|
|
54
|
+
d="M4 4L4 1M4 4L1 4"
|
|
55
|
+
stroke="currentColor"
|
|
56
|
+
strokeWidth="1.5"
|
|
57
|
+
strokeLinecap="round"
|
|
58
|
+
strokeLinejoin="round"
|
|
59
|
+
/>
|
|
60
|
+
{/* Corner brackets - top-right */}
|
|
61
|
+
<path
|
|
62
|
+
d="M16 4L16 1M16 4L19 4"
|
|
63
|
+
stroke="currentColor"
|
|
64
|
+
strokeWidth="1.5"
|
|
65
|
+
strokeLinecap="round"
|
|
66
|
+
strokeLinejoin="round"
|
|
67
|
+
/>
|
|
68
|
+
{/* Corner brackets - bottom-left */}
|
|
69
|
+
<path
|
|
70
|
+
d="M4 16L4 19M4 16L1 16"
|
|
71
|
+
stroke="currentColor"
|
|
72
|
+
strokeWidth="1.5"
|
|
73
|
+
strokeLinecap="round"
|
|
74
|
+
strokeLinejoin="round"
|
|
75
|
+
/>
|
|
76
|
+
{/* Corner brackets - bottom-right */}
|
|
77
|
+
<path
|
|
78
|
+
d="M16 16L16 19M16 16L19 16"
|
|
79
|
+
stroke="currentColor"
|
|
80
|
+
strokeWidth="1.5"
|
|
81
|
+
strokeLinecap="round"
|
|
82
|
+
strokeLinejoin="round"
|
|
83
|
+
/>
|
|
84
|
+
{/* Eye shape */}
|
|
85
|
+
<ellipse
|
|
86
|
+
cx="10"
|
|
87
|
+
cy="10"
|
|
88
|
+
rx="3.5"
|
|
89
|
+
ry="2.5"
|
|
90
|
+
stroke="currentColor"
|
|
91
|
+
strokeWidth="1.5"
|
|
92
|
+
fill="none"
|
|
93
|
+
/>
|
|
94
|
+
{/* Eye pupil */}
|
|
95
|
+
<circle
|
|
96
|
+
cx="10"
|
|
97
|
+
cy="10"
|
|
98
|
+
r="1.5"
|
|
99
|
+
fill="currentColor"
|
|
100
|
+
/>
|
|
101
|
+
</svg>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export default ViewQuotationIcon;
|
|
@@ -60,6 +60,7 @@ import TwitterIcon from './TwitterIcon';
|
|
|
60
60
|
import User from './User';
|
|
61
61
|
import UserIcon from './UserIcon';
|
|
62
62
|
import UtensilsIcon from './Utensils';
|
|
63
|
+
import ViewQuotationIcon from './ViewQuotationIcon';
|
|
63
64
|
import WalletIcon from './WalletIcon';
|
|
64
65
|
import YouTubeIcon from './Youtube';
|
|
65
66
|
|
|
@@ -152,6 +153,7 @@ export const ICONS = {
|
|
|
152
153
|
'close-circle': CloseCircleIcon as unknown as IconComponent,
|
|
153
154
|
clock: ClockIcon as unknown as IconComponent,
|
|
154
155
|
'info-2': Info2Icon as unknown as IconComponent,
|
|
156
|
+
'view-quotation': ViewQuotationIcon as unknown as IconComponent,
|
|
155
157
|
} as const satisfies Record<string, IconComponent>;
|
|
156
158
|
|
|
157
159
|
export type IconName = keyof typeof ICONS;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import Button, { ButtonProps } from '../../atoms/Button/Button';
|
|
3
3
|
import Divider from '../../atoms/Divider/Divider';
|
|
4
4
|
import DropdownInput from '../../atoms/Inputs/DropdownInput/DropdownInput';
|
|
@@ -90,16 +90,56 @@ const CarBookingCard: React.FC<CarBookingCardProps> = ({
|
|
|
90
90
|
readonly = false,
|
|
91
91
|
className = '',
|
|
92
92
|
}) => {
|
|
93
|
+
const [isSelected, setIsSelected] = useState(state === 'selected');
|
|
94
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
95
|
+
|
|
93
96
|
const resolvedShowSupplement =
|
|
94
97
|
showSupplement ?? Boolean(supplementLabel || supplementPlaceholder || supplementOptions.length > 0);
|
|
95
98
|
const resolvedSupplementState =
|
|
96
99
|
supplementMessage ? 'disabled' : supplementState;
|
|
97
100
|
|
|
101
|
+
// Handle CTA click: toggle between "Add to quote" and "Selected"
|
|
102
|
+
const handleCtaClick = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
103
|
+
setIsSelected(!isSelected);
|
|
104
|
+
onCtaClick?.(e);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Determine button state based on selection and hover
|
|
108
|
+
const shouldShowRemove = isSelected && isHovered;
|
|
109
|
+
const shouldShowSelected = isSelected && !isHovered;
|
|
110
|
+
|
|
111
|
+
const resolvedCtaLabel = shouldShowRemove
|
|
112
|
+
? 'Remove'
|
|
113
|
+
: shouldShowSelected
|
|
114
|
+
? 'Selected'
|
|
115
|
+
: ctaLabel;
|
|
116
|
+
|
|
117
|
+
const resolvedCtaButtonProps: Omit<ButtonProps, 'children'> = shouldShowRemove
|
|
118
|
+
? {
|
|
119
|
+
variant: 'destructive',
|
|
120
|
+
size: 'sm',
|
|
121
|
+
leadingIcon: 'close',
|
|
122
|
+
iconSize: 'sm',
|
|
123
|
+
}
|
|
124
|
+
: shouldShowSelected
|
|
125
|
+
? {
|
|
126
|
+
variant: 'secondary',
|
|
127
|
+
size: 'sm',
|
|
128
|
+
leadingIcon: 'check-circle',
|
|
129
|
+
iconSize: 'sm',
|
|
130
|
+
}
|
|
131
|
+
: {
|
|
132
|
+
variant: 'primary',
|
|
133
|
+
size: 'sm',
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// Update card state class based on selection
|
|
137
|
+
const resolvedState = isSelected ? 'selected' : state;
|
|
98
138
|
const baseClass = 'car-booking-card';
|
|
99
139
|
const classes = [
|
|
100
140
|
baseClass,
|
|
101
141
|
`${baseClass}--${size}`,
|
|
102
|
-
`${baseClass}--${
|
|
142
|
+
`${baseClass}--${resolvedState}`,
|
|
103
143
|
`${baseClass}--${type}`,
|
|
104
144
|
readonly ? `${baseClass}--readonly` : '',
|
|
105
145
|
className,
|
|
@@ -236,15 +276,19 @@ const CarBookingCard: React.FC<CarBookingCardProps> = ({
|
|
|
236
276
|
</div>
|
|
237
277
|
|
|
238
278
|
{!readonly && (
|
|
239
|
-
<
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
onClick={onCtaClick}
|
|
244
|
-
className={`car-booking-card__cta ${ctaButtonProps?.className ?? ''}`.trim()}
|
|
279
|
+
<div
|
|
280
|
+
onMouseEnter={() => setIsHovered(true)}
|
|
281
|
+
onMouseLeave={() => setIsHovered(false)}
|
|
282
|
+
className="car-booking-card__cta-wrapper"
|
|
245
283
|
>
|
|
246
|
-
|
|
247
|
-
|
|
284
|
+
<Button
|
|
285
|
+
{...resolvedCtaButtonProps}
|
|
286
|
+
onClick={handleCtaClick}
|
|
287
|
+
className={`car-booking-card__cta ${resolvedCtaButtonProps?.className ?? ''}`.trim()}
|
|
288
|
+
>
|
|
289
|
+
{resolvedCtaLabel}
|
|
290
|
+
</Button>
|
|
291
|
+
</div>
|
|
248
292
|
)}
|
|
249
293
|
</footer>}
|
|
250
294
|
</div>
|
|
@@ -275,16 +275,18 @@ export const DocketFooter: React.FC<DocketFooterProps> = ({
|
|
|
275
275
|
Add new quote
|
|
276
276
|
</Button>
|
|
277
277
|
)}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
<
|
|
281
|
-
|
|
282
|
-
size="sm"
|
|
278
|
+
{!isSingleMode && onViewClick && (
|
|
279
|
+
<div className="docket__footer-view">
|
|
280
|
+
<button
|
|
281
|
+
type="button"
|
|
283
282
|
onClick={onViewClick}
|
|
284
|
-
className="docket__footer-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
283
|
+
className="docket__footer-view-link">
|
|
284
|
+
<Icon name="view-quotation" size="sm" className="docket__footer-view-icon" />
|
|
285
|
+
<span className="docket__footer-view-text">View quotation</span>
|
|
286
|
+
</button>
|
|
287
|
+
</div>
|
|
288
|
+
)}
|
|
289
|
+
<div className="docket__footer-actions">
|
|
288
290
|
{onSaveClick && (
|
|
289
291
|
<Button
|
|
290
292
|
variant="outline-secondary"
|
|
@@ -207,6 +207,52 @@
|
|
|
207
207
|
min-width: 162px;
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
+
.docket__footer-view {
|
|
211
|
+
display: flex;
|
|
212
|
+
justify-content: flex-end;
|
|
213
|
+
width: 100%;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.docket__footer-view-link {
|
|
217
|
+
display: inline-flex;
|
|
218
|
+
align-items: center;
|
|
219
|
+
gap: var(--component-button-spacing-ghost-sm-gap, 6px);
|
|
220
|
+
background: none;
|
|
221
|
+
border: none;
|
|
222
|
+
padding: var(--component-button-spacing-ghost-sm-padding-y, 0px) var(--component-button-spacing-ghost-sm-padding-x, 0px);
|
|
223
|
+
cursor: pointer;
|
|
224
|
+
font-family: var(--font-font-family-body, 'Satoshi', sans-serif);
|
|
225
|
+
font-size: var(--font-size-text-sm, 14px);
|
|
226
|
+
font-weight: var(--font-weight-font-medium, 500);
|
|
227
|
+
line-height: var(--font-leading-leading-sm, 20px);
|
|
228
|
+
color: var(--color-button-ghost-foreground-default, #78716c);
|
|
229
|
+
text-decoration: none;
|
|
230
|
+
transition: color 0.2s ease;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.docket__footer-view-link:hover {
|
|
234
|
+
color: var(--color-button-ghost-foreground-hover, #44403c);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.docket__footer-view-link:active {
|
|
238
|
+
color: var(--color-button-ghost-foreground-pressed, #1c1917);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.docket__footer-view-link:focus {
|
|
242
|
+
outline: none;
|
|
243
|
+
color: var(--color-button-ghost-foreground-focused, #1c1917);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.docket__footer-view-text {
|
|
247
|
+
display: inline-block;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.docket__footer-view-icon {
|
|
251
|
+
display: inline-flex;
|
|
252
|
+
align-items: center;
|
|
253
|
+
color: inherit;
|
|
254
|
+
}
|
|
255
|
+
|
|
210
256
|
.docket__footer-actions {
|
|
211
257
|
display: flex;
|
|
212
258
|
gap: var(--spacing-gap-md, 8px);
|