mautourco-components 0.2.161 → 0.2.163
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/SelectedValue/SelectedValue.d.ts +3 -0
- package/dist/components/atoms/SelectedValue/SelectedValue.js +3 -5
- package/dist/components/molecules/DocketPrices/DocketPrices.js +0 -1
- package/dist/components/organisms/DialogSaveQuotation/DialogSaveQuotation.css +185 -0
- package/dist/components/organisms/DialogSaveQuotation/DialogSaveQuotation.d.ts +52 -0
- package/dist/components/organisms/DialogSaveQuotation/DialogSaveQuotation.js +164 -0
- package/dist/components/organisms/DialogSaveQuotation/index.d.ts +2 -0
- package/dist/components/organisms/DialogSaveQuotation/index.js +1 -0
- package/dist/components/organisms/DialogSaveQuotation/save-quotation-schema.d.ts +8 -0
- package/dist/components/organisms/DialogSaveQuotation/save-quotation-schema.js +7 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/styles/components/forms.css +5 -5
- package/dist/styles/components/organism/docket.css +1 -0
- package/dist/styles/components/selected-value.css +24 -18
- package/package.json +1 -1
- package/src/components/atoms/SelectedValue/SelectedValue.tsx +7 -5
- package/src/components/molecules/DocketPrices/DocketPrices.tsx +0 -2
- package/src/components/organisms/DialogSaveQuotation/DialogSaveQuotation.css +181 -0
- package/src/components/organisms/DialogSaveQuotation/DialogSaveQuotation.tsx +410 -0
- package/src/components/organisms/DialogSaveQuotation/index.ts +6 -0
- package/src/components/organisms/DialogSaveQuotation/save-quotation-schema.ts +10 -0
- package/src/styles/components/forms.css +5 -5
- package/src/styles/components/organism/docket.css +1 -0
- package/src/styles/components/selected-value.css +21 -18
|
@@ -3,7 +3,10 @@ interface SelectedValueProps {
|
|
|
3
3
|
value: string;
|
|
4
4
|
className?: string;
|
|
5
5
|
iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
6
|
+
/** Chip size - controls padding and gap (Figma: chip/spacing/lg = 16px, 4px, 4px) */
|
|
6
7
|
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
8
|
+
/** Text size - defaults to same as size. Use 'md' for Figma body-md (16px, leading-24) */
|
|
9
|
+
textSize?: 'xs' | 'sm' | 'md' | 'lg';
|
|
7
10
|
variant?: 'filled' | 'text';
|
|
8
11
|
color?: 'accent' | 'neutral';
|
|
9
12
|
onRemove?: () => void;
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import Icon from '../Icon/Icon';
|
|
3
3
|
import { Text } from '../Typography/Typography';
|
|
4
4
|
var SelectedValue = function (_a) {
|
|
5
|
-
var value = _a.value, _b = _a.className, className = _b === void 0 ? '' : _b, _c = _a.iconSize, iconSize = _c === void 0 ? 'xs' : _c, _d = _a.size, size = _d === void 0 ? 'md' : _d, _e = _a.variant, variant = _e === void 0 ? 'filled' : _e, _f = _a.color, color = _f === void 0 ? 'accent' : _f, onRemove = _a.onRemove, onSelect = _a.onSelect;
|
|
5
|
+
var value = _a.value, _b = _a.className, className = _b === void 0 ? '' : _b, _c = _a.iconSize, iconSize = _c === void 0 ? 'xs' : _c, _d = _a.size, size = _d === void 0 ? 'md' : _d, textSize = _a.textSize, _e = _a.variant, variant = _e === void 0 ? 'filled' : _e, _f = _a.color, color = _f === void 0 ? 'accent' : _f, onRemove = _a.onRemove, onSelect = _a.onSelect;
|
|
6
6
|
var handleRemove = function (event) {
|
|
7
7
|
event.stopPropagation();
|
|
8
8
|
if (onRemove) {
|
|
@@ -10,9 +10,7 @@ var SelectedValue = function (_a) {
|
|
|
10
10
|
}
|
|
11
11
|
};
|
|
12
12
|
var classes = "selected-value selected-value--".concat(size, " selected-value--").concat(color, " selected-value--").concat(variant, " ").concat(className, " ").concat(onSelect ? 'cursor-pointer' : '').trim();
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
};
|
|
16
|
-
return (_jsxs("div", { className: classes, onClick: onSelect, children: [_jsx(Text, { size: getTextSize(), variant: "medium", leading: "4", className: "selected-value__text", children: value }), variant !== 'text' && onRemove && (_jsx("button", { type: "button", className: "selected-value__remove", onClick: handleRemove, "aria-label": "Remove ".concat(value), children: _jsx(Icon, { name: "close", size: iconSize, className: "selected-value__remove-icon" }) }))] }));
|
|
13
|
+
var effectiveTextSize = textSize !== null && textSize !== void 0 ? textSize : size;
|
|
14
|
+
return (_jsxs("div", { className: classes, onClick: onSelect, children: [_jsx(Text, { size: effectiveTextSize, variant: "medium", leading: "6", className: "selected-value__text", children: value }), variant !== 'text' && onRemove && (_jsx("button", { type: "button", className: "selected-value__remove", onClick: handleRemove, "aria-label": "Remove ".concat(value), children: _jsx(Icon, { name: "close", size: iconSize, className: "selected-value__remove-icon" }) }))] }));
|
|
17
15
|
};
|
|
18
16
|
export default SelectedValue;
|
|
@@ -15,7 +15,6 @@ export var DocketPrices = function (_a) {
|
|
|
15
15
|
if (!prices || prices.length === 0) {
|
|
16
16
|
return null;
|
|
17
17
|
}
|
|
18
|
-
console.log('prices', prices);
|
|
19
18
|
return (_jsxs("div", { className: "docket-prices ".concat(className), children: [_jsx(Text, { variant: "bold", size: "sm", color: "default", className: "docket-prices__label", children: label }), _jsx("div", { className: "docket-prices__price-list", children: prices.map(function (price, index) { return (_jsxs(Text, { variant: "bold", size: "sm", color: "default", children: [price.Currency, " ", formatAmount(price.Amount)] }, index)); }) })] }));
|
|
20
19
|
};
|
|
21
20
|
export default DocketPrices;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Do not edit directly, this file was auto-generated.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/* ===== DialogSaveQuotation - Tokens from Figma ===== */
|
|
6
|
+
/* Uses CSS variables from tokens.css */
|
|
7
|
+
|
|
8
|
+
.dialog-save-quotation {
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
gap: var(--spacing-gap-gap-6, 24px);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* Animated view wrapper (form vs success) */
|
|
15
|
+
.dialog-save-quotation__view {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
gap: var(--spacing-gap-gap-6, 24px);
|
|
19
|
+
width: 100%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* Selected quotes section - tags + select all */
|
|
23
|
+
.dialog-save-quotation__quotes-section {
|
|
24
|
+
display: flex;
|
|
25
|
+
padding: var(--spacing-gap-gap-4, 16px) 0 var(--spacing-gap-gap-2, 8px) 0;
|
|
26
|
+
justify-content: space-between;
|
|
27
|
+
align-items: flex-start;
|
|
28
|
+
gap: var(--spacing-gap-gap-4, 16px);
|
|
29
|
+
flex-wrap: wrap;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.dialog-save-quotation__quotes-list {
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-wrap: wrap;
|
|
35
|
+
gap: var(--spacing-gap-gap-2, 8px);
|
|
36
|
+
flex: 1;
|
|
37
|
+
min-width: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.dialog-save-quotation__select-all {
|
|
41
|
+
flex-shrink: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* All quotations section header */
|
|
45
|
+
.dialog-save-quotation__section-title {
|
|
46
|
+
font-family:
|
|
47
|
+
var(--font-font-family-body), 'Satoshi', 'Inter', 'Segoe UI', system-ui, sans-serif;
|
|
48
|
+
font-size: var(--font-size-text-base, 16px);
|
|
49
|
+
font-weight: var(--font-weight-font-bold, 700);
|
|
50
|
+
line-height: var(--font-leading-leading-md, 24px);
|
|
51
|
+
color: var(--color-text-default);
|
|
52
|
+
margin: 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* Form fields grid */
|
|
56
|
+
.dialog-save-quotation__form {
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-direction: column;
|
|
59
|
+
gap: var(--spacing-gap-gap-6, 24px);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.dialog-save-quotation__form-row {
|
|
63
|
+
display: grid;
|
|
64
|
+
grid-template-columns: repeat(3, 1fr);
|
|
65
|
+
gap: var(--spacing-gap-gap-4, 16px);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.dialog-save-quotation__form-row--single {
|
|
69
|
+
grid-template-columns: 1fr;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@media (max-width: 768px) {
|
|
73
|
+
.dialog-save-quotation__form-row {
|
|
74
|
+
grid-template-columns: 1fr;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* Form field */
|
|
79
|
+
.dialog-save-quotation__field {
|
|
80
|
+
display: flex;
|
|
81
|
+
flex-direction: column;
|
|
82
|
+
gap: var(--spacing-gap-gap-2, 8px);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.dialog-save-quotation__label {
|
|
86
|
+
font-family:
|
|
87
|
+
var(--font-font-family-body), 'Satoshi', 'Inter', 'Segoe UI', system-ui, sans-serif;
|
|
88
|
+
font-size: var(--font-size-text-sm, 14px);
|
|
89
|
+
font-weight: var(--font-weight-font-medium, 500);
|
|
90
|
+
line-height: var(--font-leading-leading-sm, 20px);
|
|
91
|
+
color: var(--color-text-default);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.dialog-save-quotation__label--required::after {
|
|
95
|
+
content: ' *';
|
|
96
|
+
color: var(--color-text-state-error);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Disabled label – matches Figma / input design token */
|
|
100
|
+
.dialog-save-quotation__label--disabled {
|
|
101
|
+
color: var(--input-color-label-disabled, var(--color-text-state-disabled));
|
|
102
|
+
cursor: not-allowed;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.dialog-save-quotation__label--disabled.dialog-save-quotation__label--required::after {
|
|
106
|
+
color: var(--input-color-label-disabled, var(--color-text-state-disabled));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Form error message – displayed below the form when validation fails */
|
|
110
|
+
.dialog-save-quotation__error {
|
|
111
|
+
font-family:
|
|
112
|
+
var(--font-font-family-body), 'Satoshi', 'Inter', 'Segoe UI', system-ui, sans-serif;
|
|
113
|
+
font-size: var(--font-size-text-sm, 14px);
|
|
114
|
+
font-weight: var(--font-weight-font-regular, 400);
|
|
115
|
+
line-height: var(--font-leading-leading-sm, 20px);
|
|
116
|
+
color: var(--color-text-state-error, #dc2626);
|
|
117
|
+
margin: 0;
|
|
118
|
+
padding: var(--spacing-gap-gap-2, 8px) 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Footer - buttons full width, side by side */
|
|
122
|
+
.dialog-save-quotation__footer {
|
|
123
|
+
display: flex;
|
|
124
|
+
flex-direction: row;
|
|
125
|
+
align-items: stretch;
|
|
126
|
+
gap: var(--spacing-gap-gap-4, 16px);
|
|
127
|
+
padding: var(--spacing-gap-gap-2, 8px) 0 var(--spacing-gap-gap-4, 16px) 0;
|
|
128
|
+
width: 100%;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.dialog-save-quotation__footer > * {
|
|
132
|
+
flex: 1;
|
|
133
|
+
min-width: 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* ===== Success state content (Figma 4700-366717 – Shared-flows) ===== */
|
|
137
|
+
.dialog-save-quotation__content {
|
|
138
|
+
display: flex;
|
|
139
|
+
flex-direction: column;
|
|
140
|
+
align-items: center;
|
|
141
|
+
gap: var(--spacing-gap-gap-4, 16px);
|
|
142
|
+
text-align: center;
|
|
143
|
+
padding: var(--spacing-gap-gap-2, 8px) 0 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.dialog-save-quotation__content-image-container {
|
|
147
|
+
display: flex;
|
|
148
|
+
align-items: center;
|
|
149
|
+
justify-content: center;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.dialog-save-quotation__content-image {
|
|
153
|
+
width: 150px;
|
|
154
|
+
height: 150px;
|
|
155
|
+
object-fit: contain;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.dialog-save-quotation__content-text {
|
|
159
|
+
display: flex;
|
|
160
|
+
flex-direction: column;
|
|
161
|
+
gap: var(--spacing-gap-gap-2, 8px);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.dialog-save-quotation__content-title {
|
|
165
|
+
color: var(--color-text-default, #262626);
|
|
166
|
+
text-align: center;
|
|
167
|
+
|
|
168
|
+
/* heading-sm/medium */
|
|
169
|
+
font-family: var(--font-font-family-heading, Satoshi);
|
|
170
|
+
font-size: var(--font-size-text-2xl, 24px);
|
|
171
|
+
font-style: normal;
|
|
172
|
+
font-weight: var(--font-weight-font-medium, 500);
|
|
173
|
+
line-height: var(--font-leading-leading-xl, 32px); /* 133.333% */
|
|
174
|
+
letter-spacing: var(--font-tracking-tracking-normal, 0);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.dialog-save-quotation__content-message {
|
|
178
|
+
font-family:
|
|
179
|
+
var(--font-font-family-body), 'Satoshi', 'Inter', 'Segoe UI', system-ui, sans-serif;
|
|
180
|
+
font-size: var(--font-size-text-sm, 14px);
|
|
181
|
+
font-weight: var(--font-weight-font-regular, 400);
|
|
182
|
+
line-height: var(--font-leading-leading-md, 24px);
|
|
183
|
+
color: var(--color-text-default, #262626);
|
|
184
|
+
margin: 0;
|
|
185
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import './DialogSaveQuotation.css';
|
|
2
|
+
import { SaveQuotationSchema } from './save-quotation-schema';
|
|
3
|
+
export interface SaveQuotationQuote {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
export interface DialogSaveQuotationProps {
|
|
8
|
+
/** Whether the dialog is open */
|
|
9
|
+
open: boolean;
|
|
10
|
+
/** Callback to control dialog open state */
|
|
11
|
+
setOpen: (open: boolean) => void;
|
|
12
|
+
/** List of quotations to save (displayed as removable chips) */
|
|
13
|
+
quotations: SaveQuotationQuote[];
|
|
14
|
+
/** Callback when form is submitted */
|
|
15
|
+
onSubmit: (data: {
|
|
16
|
+
selectedQuotationIds: string[];
|
|
17
|
+
formData: SaveQuotationSchema;
|
|
18
|
+
}) => void;
|
|
19
|
+
/** Callback when the book now button is clicked */
|
|
20
|
+
onHandleBookNow?: () => void;
|
|
21
|
+
/** Callback when the view on quotation grid button is clicked */
|
|
22
|
+
onHandleViewOnQuotationGrid?: () => void;
|
|
23
|
+
/** Optional default values for the form */
|
|
24
|
+
defaultValues?: Partial<SaveQuotationSchema>;
|
|
25
|
+
/** Which form inputs to disable. Omit or set to false to keep an input enabled. */
|
|
26
|
+
disabledInputs?: Partial<Record<keyof SaveQuotationSchema, boolean>>;
|
|
27
|
+
/** Whether the form is loading */
|
|
28
|
+
loading?: boolean;
|
|
29
|
+
/** Whether the form is successful */
|
|
30
|
+
successful?: boolean;
|
|
31
|
+
/** The error message to display */
|
|
32
|
+
errorMessage?: string;
|
|
33
|
+
/** The image to display when the form is successful */
|
|
34
|
+
imgSuccess?: string;
|
|
35
|
+
/** The image to display */
|
|
36
|
+
imgSuccessAlt?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* DialogSaveQuotation - Modal to save quotations with agent and quotation details.
|
|
40
|
+
* Based on Figma "Save quotation" design with tokens.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* <DialogSaveQuotation
|
|
45
|
+
* open={open}
|
|
46
|
+
* setOpen={setOpen}
|
|
47
|
+
* quotations={[{ id: '1', name: 'Quote 1' }]}
|
|
48
|
+
* onSubmit={(data) => console.log(data)}
|
|
49
|
+
* />
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function DialogSaveQuotation(props: DialogSaveQuotationProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
13
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
14
|
+
if (ar || !(i in from)) {
|
|
15
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
16
|
+
ar[i] = from[i];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
20
|
+
};
|
|
21
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
22
|
+
import { AnimatePresence } from 'motion/react';
|
|
23
|
+
import * as motion from 'motion/react-m';
|
|
24
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
25
|
+
import Button from '../../atoms/Button/Button';
|
|
26
|
+
import Checkbox from '../../atoms/Checkbox/Checkbox';
|
|
27
|
+
import Input from '../../atoms/Inputs/Input/Input';
|
|
28
|
+
import SelectedValue from '../../atoms/SelectedValue/SelectedValue';
|
|
29
|
+
import { Text } from '../../atoms/Typography/Typography';
|
|
30
|
+
import { DialogBookingConfirm } from '../DialogBookingConfirm';
|
|
31
|
+
import './DialogSaveQuotation.css';
|
|
32
|
+
import { saveQuotationSchema } from './save-quotation-schema';
|
|
33
|
+
/**
|
|
34
|
+
* DialogSaveQuotation - Modal to save quotations with agent and quotation details.
|
|
35
|
+
* Based on Figma "Save quotation" design with tokens.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* <DialogSaveQuotation
|
|
40
|
+
* open={open}
|
|
41
|
+
* setOpen={setOpen}
|
|
42
|
+
* quotations={[{ id: '1', name: 'Quote 1' }]}
|
|
43
|
+
* onSubmit={(data) => console.log(data)}
|
|
44
|
+
* />
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export function DialogSaveQuotation(props) {
|
|
48
|
+
var _a, _b, _c, _d;
|
|
49
|
+
var open = props.open, setOpen = props.setOpen, quotations = props.quotations, onSubmit = props.onSubmit, defaultValues = props.defaultValues, disabledInputs = props.disabledInputs, errorMessage = props.errorMessage, successful = props.successful, loading = props.loading, imgSuccess = props.imgSuccess, imgSuccessAlt = props.imgSuccessAlt, onHandleBookNow = props.onHandleBookNow, onHandleViewOnQuotationGrid = props.onHandleViewOnQuotationGrid;
|
|
50
|
+
var _e = useState(quotations), remainingQuotations = _e[0], setRemainingQuotations = _e[1];
|
|
51
|
+
var _f = useState([]), selectedQuotationIds = _f[0], setSelectedQuotationIds = _f[1];
|
|
52
|
+
var _g = useState(false), isSelectAll = _g[0], setIsSelectAll = _g[1];
|
|
53
|
+
var _h = useState((_a = defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues.agentForename) !== null && _a !== void 0 ? _a : ''), agentForename = _h[0], setAgentForename = _h[1];
|
|
54
|
+
var _j = useState((_b = defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues.agentLastname) !== null && _b !== void 0 ? _b : ''), agentLastname = _j[0], setAgentLastname = _j[1];
|
|
55
|
+
var _k = useState((_c = defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues.agency) !== null && _c !== void 0 ? _c : ''), agency = _k[0], setAgency = _k[1];
|
|
56
|
+
var _l = useState((_d = defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues.quotationName) !== null && _d !== void 0 ? _d : ''), quotationName = _l[0], setQuotationName = _l[1];
|
|
57
|
+
var _m = useState({}), fieldErrors = _m[0], setFieldErrors = _m[1];
|
|
58
|
+
var _o = useState(null), formErrorMessage = _o[0], setFormErrorMessage = _o[1];
|
|
59
|
+
var remainingQuotationsFiltered = useMemo(function () { return remainingQuotations.filter(function (q) { return selectedQuotationIds.includes(q.id); }); }, [remainingQuotations, selectedQuotationIds]);
|
|
60
|
+
useEffect(function () {
|
|
61
|
+
setRemainingQuotations(quotations);
|
|
62
|
+
setSelectedQuotationIds(quotations.map(function (q) { return q.id; }));
|
|
63
|
+
}, [quotations]);
|
|
64
|
+
useEffect(function () {
|
|
65
|
+
setIsSelectAll(remainingQuotations.length > 0 &&
|
|
66
|
+
selectedQuotationIds.length === remainingQuotations.length);
|
|
67
|
+
}, [selectedQuotationIds, remainingQuotations]);
|
|
68
|
+
var handleRemoveQuotation = function (id) {
|
|
69
|
+
if (remainingQuotations.length > 1) {
|
|
70
|
+
setRemainingQuotations(function (prev) { return prev.filter(function (q) { return q.id !== id; }); });
|
|
71
|
+
setSelectedQuotationIds(function (prev) { return prev.filter(function (quoteId) { return quoteId !== id; }); });
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
var handleSelectQuotation = function (id) {
|
|
75
|
+
if (remainingQuotations.length > 1) {
|
|
76
|
+
setSelectedQuotationIds(function (prev) {
|
|
77
|
+
if (prev.includes(id)) {
|
|
78
|
+
return prev.length > 1 ? prev.filter(function (q) { return q !== id; }) : prev;
|
|
79
|
+
}
|
|
80
|
+
return __spreadArray(__spreadArray([], prev, true), [id], false);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var clearFieldError = function (field) {
|
|
85
|
+
setFieldErrors(function (prev) {
|
|
86
|
+
var next = __assign({}, prev);
|
|
87
|
+
delete next[field];
|
|
88
|
+
return next;
|
|
89
|
+
});
|
|
90
|
+
setFormErrorMessage(null);
|
|
91
|
+
};
|
|
92
|
+
var handleSelectAll = function () {
|
|
93
|
+
if (isSelectAll) {
|
|
94
|
+
setSelectedQuotationIds(remainingQuotations.length > 1 ? [remainingQuotations[0].id] : []);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
setSelectedQuotationIds(remainingQuotations.map(function (q) { return q.id; }));
|
|
98
|
+
}
|
|
99
|
+
setIsSelectAll(!isSelectAll);
|
|
100
|
+
};
|
|
101
|
+
var handleSubmit = function () {
|
|
102
|
+
var _a;
|
|
103
|
+
setFieldErrors({});
|
|
104
|
+
setFormErrorMessage(null);
|
|
105
|
+
var formData = {
|
|
106
|
+
agentForename: agentForename,
|
|
107
|
+
agentLastname: agentLastname,
|
|
108
|
+
agency: agency,
|
|
109
|
+
quotationName: quotationName,
|
|
110
|
+
};
|
|
111
|
+
var result = saveQuotationSchema.safeParse(formData);
|
|
112
|
+
if (!result.success) {
|
|
113
|
+
var errors_1 = {};
|
|
114
|
+
var messages_1 = [];
|
|
115
|
+
result.error.issues.forEach(function (issue) {
|
|
116
|
+
var path = issue.path[0];
|
|
117
|
+
if (path &&
|
|
118
|
+
(path === 'agentForename' ||
|
|
119
|
+
path === 'agentLastname' ||
|
|
120
|
+
path === 'agency' ||
|
|
121
|
+
path === 'quotationName')) {
|
|
122
|
+
errors_1[path] = issue.message;
|
|
123
|
+
messages_1.push(issue.message);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
setFieldErrors(errors_1);
|
|
127
|
+
setFormErrorMessage((_a = messages_1[0]) !== null && _a !== void 0 ? _a : 'Please correct the errors below.');
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
onSubmit({
|
|
131
|
+
selectedQuotationIds: remainingQuotationsFiltered.map(function (q) { return q.id; }),
|
|
132
|
+
formData: result.data,
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
return (_jsx(DialogBookingConfirm, { open: open, setOpen: setOpen, title: !successful ? 'Save quotation' : undefined, className: "!max-w-[800px]", closeOnOverlayClick: true, children: _jsx(motion.div, { className: "dialog-save-quotation", children: _jsx(AnimatePresence, { mode: "wait", initial: false, children: !successful ? (_jsxs(motion.div, { className: "dialog-save-quotation__view", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2, ease: 'easeInOut' }, children: [_jsxs("div", { className: "dialog-save-quotation__quotes-section", children: [_jsx("div", { className: "dialog-save-quotation__quotes-list", children: remainingQuotations.map(function (quote) { return (_jsx(SelectedValue, { value: quote.name, color: selectedQuotationIds.includes(quote.id) ? 'accent' : 'neutral', onSelect: function () { return handleSelectQuotation(quote.id); }, onRemove: function () { return handleRemoveQuotation(quote.id); }, size: "lg", textSize: "md" }, quote.id)); }) }), _jsx("div", { className: "dialog-save-quotation__select-all", children: _jsx(Checkbox, { label: "Select all quotations", checked: isSelectAll || remainingQuotations.length === 1, disabled: remainingQuotations.length === 1, onChange: handleSelectAll, labelPosition: "leading" }) })] }), _jsx("h3", { className: "dialog-save-quotation__section-title", children: "All quotations" }), _jsxs("div", { className: "dialog-save-quotation__form", children: [_jsxs("div", { className: "dialog-save-quotation__form-row", children: [_jsxs("div", { className: "dialog-save-quotation__field", children: [_jsx("label", { htmlFor: "agent-forename", className: "dialog-save-quotation__label dialog-save-quotation__label--required".concat((disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agentForename) ? ' dialog-save-quotation__label--disabled' : ''), children: "Agent Forename" }), _jsx(Input, { id: "agent-forename", value: agentForename, onChange: function (e) {
|
|
136
|
+
setAgentForename(e.target.value);
|
|
137
|
+
clearFieldError('agentForename');
|
|
138
|
+
}, placeholder: "Mautourco", variant: (disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agentForename)
|
|
139
|
+
? 'disabled'
|
|
140
|
+
: fieldErrors.agentForename || errorMessage
|
|
141
|
+
? 'error'
|
|
142
|
+
: 'default' })] }), _jsxs("div", { className: "dialog-save-quotation__field", children: [_jsx("label", { htmlFor: "agent-lastname", className: "dialog-save-quotation__label dialog-save-quotation__label--required".concat((disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agentLastname) ? ' dialog-save-quotation__label--disabled' : ''), children: "Agent Lastname" }), _jsx(Input, { id: "agent-lastname", value: agentLastname, onChange: function (e) {
|
|
143
|
+
setAgentLastname(e.target.value);
|
|
144
|
+
clearFieldError('agentLastname');
|
|
145
|
+
}, placeholder: "B2B", variant: (disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agentLastname)
|
|
146
|
+
? 'disabled'
|
|
147
|
+
: fieldErrors.agentLastname || errorMessage
|
|
148
|
+
? 'error'
|
|
149
|
+
: 'default' })] }), _jsxs("div", { className: "dialog-save-quotation__field", children: [_jsx("label", { htmlFor: "agency", className: "dialog-save-quotation__label".concat((disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agency) ? ' dialog-save-quotation__label--disabled' : ''), children: "Agency" }), _jsx(Input, { id: "agency", value: agency, onChange: function (e) {
|
|
150
|
+
setAgency(e.target.value);
|
|
151
|
+
clearFieldError('agency');
|
|
152
|
+
}, placeholder: "Mautourco Ltd", variant: (disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agency)
|
|
153
|
+
? 'disabled'
|
|
154
|
+
: fieldErrors.agency || errorMessage
|
|
155
|
+
? 'error'
|
|
156
|
+
: 'default' })] })] }), _jsx("div", { className: "dialog-save-quotation__form-row dialog-save-quotation__form-row--single", children: _jsxs("div", { className: "dialog-save-quotation__field", children: [_jsx("label", { htmlFor: "quotation-name", className: "dialog-save-quotation__label dialog-save-quotation__label--required".concat((disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.quotationName) ? ' dialog-save-quotation__label--disabled' : ''), children: "Quotation name" }), _jsx(Input, { id: "quotation-name", value: quotationName, onChange: function (e) {
|
|
157
|
+
setQuotationName(e.target.value);
|
|
158
|
+
clearFieldError('quotationName');
|
|
159
|
+
}, placeholder: "Insert client's name", variant: (disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.quotationName)
|
|
160
|
+
? 'disabled'
|
|
161
|
+
: fieldErrors.quotationName || errorMessage
|
|
162
|
+
? 'error'
|
|
163
|
+
: 'default' })] }) })] }), (formErrorMessage || errorMessage) && (_jsx("p", { className: "dialog-save-quotation__error", role: "alert", children: formErrorMessage !== null && formErrorMessage !== void 0 ? formErrorMessage : errorMessage })), _jsxs("div", { className: "dialog-save-quotation__footer", children: [_jsx(Button, { variant: "outline-secondary", size: "sm", onClick: function () { return setOpen(false); }, disabled: loading, children: "Cancel" }), _jsx(Button, { variant: "secondary", size: "sm", onClick: handleSubmit, disabled: loading, children: loading ? 'Saving…' : 'Save quotation' })] })] }, "form")) : (_jsxs(motion.div, { className: "dialog-save-quotation__view", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2, ease: 'easeInOut' }, children: [_jsxs("div", { className: "dialog-save-quotation__content", children: [_jsx("div", { className: "dialog-save-quotation__content-image-container", "aria-hidden": true, children: _jsx("img", { src: imgSuccess, alt: imgSuccessAlt, className: "dialog-save-quotation__content-image" }) }), _jsxs("div", { className: "dialog-save-quotation__content-text", children: [_jsx(Text, { variant: "bold", size: "xl", as: "h2", className: "dialog-save-quotation__content-title ", children: "Quotation saved" }), _jsxs(Text, { size: "lg", children: [_jsxs(Text, { size: "lg", variant: "bold", as: "span", children: ["\"", quotationName, "\""] }), ' ', "quotation"] })] })] }), _jsxs("div", { className: "dialog-save-quotation__footer", children: [_jsx(Button, { variant: "outline-secondary", size: "sm", onClick: onHandleViewOnQuotationGrid, children: "View on quotation grid" }), _jsx(Button, { variant: "secondary", size: "sm", onClick: onHandleBookNow, children: "Book now" })] })] }, "success")) }) }) }));
|
|
164
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DialogSaveQuotation, } from './DialogSaveQuotation';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
export declare const saveQuotationSchema: z.ZodObject<{
|
|
3
|
+
agentForename: z.ZodString;
|
|
4
|
+
agentLastname: z.ZodString;
|
|
5
|
+
agency: z.ZodOptional<z.ZodString>;
|
|
6
|
+
quotationName: z.ZodString;
|
|
7
|
+
}, z.core.$strip>;
|
|
8
|
+
export type SaveQuotationSchema = z.infer<typeof saveQuotationSchema>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
export var saveQuotationSchema = z.object({
|
|
3
|
+
agentForename: z.string().min(1, 'Agent forename is required'),
|
|
4
|
+
agentLastname: z.string().min(1, 'Agent lastname is required'),
|
|
5
|
+
agency: z.string().optional(),
|
|
6
|
+
quotationName: z.string().min(1, 'Quotation name is required'),
|
|
7
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -64,6 +64,7 @@ export { DialogComparison } from './components/organisms/DialogComparison/Dialog
|
|
|
64
64
|
export * from './components/organisms/DialogDeleteConfirm';
|
|
65
65
|
export { DialogDeleteConfirm } from './components/organisms/DialogDeleteConfirm/DialogDeleteConfirm';
|
|
66
66
|
export { DialogQuoteRename } from './components/organisms/DialogQuoteRename/DialogQuoteRename';
|
|
67
|
+
export * from './components/organisms/DialogSaveQuotation';
|
|
67
68
|
export * from './components/organisms/DialogSendingMail';
|
|
68
69
|
export { default as Docket } from './components/organisms/Docket/Docket';
|
|
69
70
|
export { DocketAccordion, type DocketAccordionProps, } from './components/organisms/DocketAccordion';
|
package/dist/index.js
CHANGED
|
@@ -66,6 +66,7 @@ export { DialogComparison } from './components/organisms/DialogComparison/Dialog
|
|
|
66
66
|
export * from './components/organisms/DialogDeleteConfirm';
|
|
67
67
|
export { DialogDeleteConfirm } from './components/organisms/DialogDeleteConfirm/DialogDeleteConfirm';
|
|
68
68
|
export { DialogQuoteRename } from './components/organisms/DialogQuoteRename/DialogQuoteRename';
|
|
69
|
+
export * from './components/organisms/DialogSaveQuotation';
|
|
69
70
|
export * from './components/organisms/DialogSendingMail';
|
|
70
71
|
export { default as Docket } from './components/organisms/Docket/Docket';
|
|
71
72
|
export { DocketAccordion, } from './components/organisms/DocketAccordion';
|
|
@@ -107,17 +107,17 @@
|
|
|
107
107
|
color: var(--color-red-400);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
/* État disabled */
|
|
110
|
+
/* État disabled – Mautourco Foundations tokens */
|
|
111
111
|
|
|
112
112
|
.input-field--disabled {
|
|
113
|
-
background-color: var(--color-
|
|
114
|
-
border-color: var(--color-
|
|
115
|
-
color: var(--color-
|
|
113
|
+
background-color: var(--color-elevation-state-disabled, #fbfbfb);
|
|
114
|
+
border-color: var(--color-border-input-disabled, #d1d5db);
|
|
115
|
+
color: var(--color-text-state-disabled, #a3a3a3);
|
|
116
116
|
cursor: not-allowed;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
.input-field--disabled::placeholder {
|
|
120
|
-
color: var(--color-
|
|
120
|
+
color: var(--color-text-state-disabled, #a3a3a3);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
/* Styles pour le showcase */
|
|
@@ -4,19 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
/* SelectedValue Component Styles */
|
|
6
6
|
|
|
7
|
+
/* Base uses sm as default; tokens: chip-spacing-*-* from Figma */
|
|
8
|
+
|
|
7
9
|
.selected-value {
|
|
8
10
|
display: inline-flex;
|
|
9
11
|
align-items: center;
|
|
10
|
-
gap: var(--chip-spacing-gap,
|
|
11
|
-
padding: var(--chip-spacing-sm-padding-y,
|
|
12
|
-
border-radius: var(--chip-border-radius-pill,
|
|
12
|
+
gap: var(--chip-spacing-sm-gap, 4px);
|
|
13
|
+
padding: var(--chip-spacing-sm-padding-y, 4px) var(--chip-spacing-sm-padding-x, 8px);
|
|
14
|
+
border-radius: var(--chip-border-radius-pill, 9999px);
|
|
13
15
|
/* Typography is now handled by the Text component */
|
|
14
16
|
cursor: default;
|
|
15
17
|
-webkit-user-select: none;
|
|
16
18
|
user-select: none;
|
|
17
19
|
max-width: 200px;
|
|
18
20
|
width: auto;
|
|
19
|
-
opacity: var(--opacity-opacity-100);
|
|
21
|
+
opacity: var(--opacity-opacity-100, 1);
|
|
20
22
|
/* Variant: text-only (no background, no padding) */
|
|
21
23
|
.selected-value--text {
|
|
22
24
|
background: transparent;
|
|
@@ -63,32 +65,36 @@
|
|
|
63
65
|
/* Size variants */
|
|
64
66
|
|
|
65
67
|
.selected-value--xs {
|
|
66
|
-
padding: var(--chip-spacing-xs-padding-y,
|
|
67
|
-
var(--chip-spacing-xs-padding-x,
|
|
68
|
-
gap: var(--chip-spacing-xs-gap,
|
|
68
|
+
padding: var(--chip-spacing-xs-padding-y, 2px)
|
|
69
|
+
var(--chip-spacing-xs-padding-x, 6px);
|
|
70
|
+
gap: var(--chip-spacing-xs-gap, 2px);
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
.selected-value--sm {
|
|
72
|
-
padding: var(--chip-spacing-sm-padding-y,
|
|
73
|
-
var(--chip-spacing-sm-padding-x,
|
|
74
|
-
gap: var(--chip-spacing-sm-gap,
|
|
74
|
+
padding: var(--chip-spacing-sm-padding-y, 4px)
|
|
75
|
+
var(--chip-spacing-sm-padding-x, 8px);
|
|
76
|
+
gap: var(--chip-spacing-sm-gap, 4px);
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
.selected-value--md {
|
|
78
|
-
padding: var(--chip-spacing-md-padding-y,
|
|
79
|
-
var(--chip-spacing-md-padding-x,
|
|
80
|
-
gap: var(--chip-spacing-md-gap,
|
|
80
|
+
padding: var(--chip-spacing-md-padding-y, 4px)
|
|
81
|
+
var(--chip-spacing-md-padding-x, 12px);
|
|
82
|
+
gap: var(--chip-spacing-md-gap, 4px);
|
|
81
83
|
}
|
|
82
84
|
|
|
85
|
+
/* Figma chip/lg: padding-x 16px, padding-y 4px, gap 4px */
|
|
86
|
+
|
|
83
87
|
.selected-value--lg {
|
|
84
|
-
padding: var(--chip-spacing-lg-padding-y,
|
|
85
|
-
var(--chip-spacing-lg-padding-x,
|
|
86
|
-
gap: var(--chip-spacing-lg-gap,
|
|
88
|
+
padding: var(--chip-spacing-lg-padding-y, 4px)
|
|
89
|
+
var(--chip-spacing-lg-padding-x, 16px);
|
|
90
|
+
gap: var(--chip-spacing-lg-gap, 4px);
|
|
87
91
|
}
|
|
88
92
|
|
|
93
|
+
/* Figma chip/color/accent/filled: bg #0f7173, fg #ffffff */
|
|
94
|
+
|
|
89
95
|
.selected-value--accent {
|
|
90
|
-
background: var(--color-atoll-green-800);
|
|
91
|
-
color: var(--color-white);
|
|
96
|
+
background: var(--chip-color-accent-filled-background, var(--color-atoll-green-800));
|
|
97
|
+
color: var(--chip-color-accent-filled-foreground, var(--color-white));
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
.selected-value--neutral {
|
package/package.json
CHANGED
|
@@ -6,7 +6,10 @@ interface SelectedValueProps {
|
|
|
6
6
|
value: string;
|
|
7
7
|
className?: string;
|
|
8
8
|
iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
9
|
+
/** Chip size - controls padding and gap (Figma: chip/spacing/lg = 16px, 4px, 4px) */
|
|
9
10
|
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
11
|
+
/** Text size - defaults to same as size. Use 'md' for Figma body-md (16px, leading-24) */
|
|
12
|
+
textSize?: 'xs' | 'sm' | 'md' | 'lg';
|
|
10
13
|
variant?: 'filled' | 'text';
|
|
11
14
|
color?: 'accent' | 'neutral';
|
|
12
15
|
onRemove?: () => void;
|
|
@@ -18,6 +21,7 @@ const SelectedValue: React.FC<SelectedValueProps> = ({
|
|
|
18
21
|
className = '',
|
|
19
22
|
iconSize = 'xs',
|
|
20
23
|
size = 'md',
|
|
24
|
+
textSize,
|
|
21
25
|
variant = 'filled',
|
|
22
26
|
color = 'accent',
|
|
23
27
|
onRemove,
|
|
@@ -33,16 +37,14 @@ const SelectedValue: React.FC<SelectedValueProps> = ({
|
|
|
33
37
|
const classes =
|
|
34
38
|
`selected-value selected-value--${size} selected-value--${color} selected-value--${variant} ${className} ${onSelect ? 'cursor-pointer' : ''}`.trim();
|
|
35
39
|
|
|
36
|
-
const
|
|
37
|
-
return size; // Utilise directement la taille passée en prop
|
|
38
|
-
};
|
|
40
|
+
const effectiveTextSize = textSize ?? size;
|
|
39
41
|
|
|
40
42
|
return (
|
|
41
43
|
<div className={classes} onClick={onSelect}>
|
|
42
44
|
<Text
|
|
43
|
-
size={
|
|
45
|
+
size={effectiveTextSize}
|
|
44
46
|
variant="medium"
|
|
45
|
-
leading="
|
|
47
|
+
leading="6"
|
|
46
48
|
className="selected-value__text">
|
|
47
49
|
{value}
|
|
48
50
|
</Text>
|