mautourco-components 0.2.162 → 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/molecules/DocketPrices/DocketPrices.js +0 -1
- package/dist/components/organisms/DialogSaveQuotation/DialogSaveQuotation.css +81 -0
- package/dist/components/organisms/DialogSaveQuotation/DialogSaveQuotation.d.ts +17 -1
- package/dist/components/organisms/DialogSaveQuotation/DialogSaveQuotation.js +74 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/styles/components/forms.css +5 -5
- package/dist/styles/components/organism/docket.css +1 -0
- package/package.json +1 -1
- package/src/components/molecules/DocketPrices/DocketPrices.tsx +0 -2
- package/src/components/organisms/DialogSaveQuotation/DialogSaveQuotation.css +81 -0
- package/src/components/organisms/DialogSaveQuotation/DialogSaveQuotation.tsx +281 -120
- package/src/styles/components/forms.css +5 -5
- package/src/styles/components/organism/docket.css +1 -0
|
@@ -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;
|
|
@@ -11,6 +11,14 @@
|
|
|
11
11
|
gap: var(--spacing-gap-gap-6, 24px);
|
|
12
12
|
}
|
|
13
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
|
+
|
|
14
22
|
/* Selected quotes section - tags + select all */
|
|
15
23
|
.dialog-save-quotation__quotes-section {
|
|
16
24
|
display: flex;
|
|
@@ -88,6 +96,28 @@
|
|
|
88
96
|
color: var(--color-text-state-error);
|
|
89
97
|
}
|
|
90
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
|
+
|
|
91
121
|
/* Footer - buttons full width, side by side */
|
|
92
122
|
.dialog-save-quotation__footer {
|
|
93
123
|
display: flex;
|
|
@@ -101,4 +131,55 @@
|
|
|
101
131
|
.dialog-save-quotation__footer > * {
|
|
102
132
|
flex: 1;
|
|
103
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;
|
|
104
185
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SaveQuotationSchema } from './save-quotation-schema';
|
|
2
1
|
import './DialogSaveQuotation.css';
|
|
2
|
+
import { SaveQuotationSchema } from './save-quotation-schema';
|
|
3
3
|
export interface SaveQuotationQuote {
|
|
4
4
|
id: string;
|
|
5
5
|
name: string;
|
|
@@ -16,8 +16,24 @@ export interface DialogSaveQuotationProps {
|
|
|
16
16
|
selectedQuotationIds: string[];
|
|
17
17
|
formData: SaveQuotationSchema;
|
|
18
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;
|
|
19
23
|
/** Optional default values for the form */
|
|
20
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;
|
|
21
37
|
}
|
|
22
38
|
/**
|
|
23
39
|
* DialogSaveQuotation - Modal to save quotations with agent and quotation details.
|
|
@@ -1,3 +1,14 @@
|
|
|
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
|
+
};
|
|
1
12
|
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
2
13
|
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
3
14
|
if (ar || !(i in from)) {
|
|
@@ -8,14 +19,17 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
8
19
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
9
20
|
};
|
|
10
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';
|
|
11
24
|
import { useEffect, useMemo, useState } from 'react';
|
|
12
25
|
import Button from '../../atoms/Button/Button';
|
|
13
26
|
import Checkbox from '../../atoms/Checkbox/Checkbox';
|
|
14
27
|
import Input from '../../atoms/Inputs/Input/Input';
|
|
15
28
|
import SelectedValue from '../../atoms/SelectedValue/SelectedValue';
|
|
29
|
+
import { Text } from '../../atoms/Typography/Typography';
|
|
16
30
|
import { DialogBookingConfirm } from '../DialogBookingConfirm';
|
|
17
|
-
import { saveQuotationSchema, } from './save-quotation-schema';
|
|
18
31
|
import './DialogSaveQuotation.css';
|
|
32
|
+
import { saveQuotationSchema } from './save-quotation-schema';
|
|
19
33
|
/**
|
|
20
34
|
* DialogSaveQuotation - Modal to save quotations with agent and quotation details.
|
|
21
35
|
* Based on Figma "Save quotation" design with tokens.
|
|
@@ -32,7 +46,7 @@ import './DialogSaveQuotation.css';
|
|
|
32
46
|
*/
|
|
33
47
|
export function DialogSaveQuotation(props) {
|
|
34
48
|
var _a, _b, _c, _d;
|
|
35
|
-
var open = props.open, setOpen = props.setOpen, quotations = props.quotations, onSubmit = props.onSubmit, defaultValues = props.defaultValues;
|
|
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;
|
|
36
50
|
var _e = useState(quotations), remainingQuotations = _e[0], setRemainingQuotations = _e[1];
|
|
37
51
|
var _f = useState([]), selectedQuotationIds = _f[0], setSelectedQuotationIds = _f[1];
|
|
38
52
|
var _g = useState(false), isSelectAll = _g[0], setIsSelectAll = _g[1];
|
|
@@ -40,9 +54,9 @@ export function DialogSaveQuotation(props) {
|
|
|
40
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];
|
|
41
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];
|
|
42
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];
|
|
43
|
-
var
|
|
44
|
-
|
|
45
|
-
}, [remainingQuotations, selectedQuotationIds]);
|
|
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]);
|
|
46
60
|
useEffect(function () {
|
|
47
61
|
setRemainingQuotations(quotations);
|
|
48
62
|
setSelectedQuotationIds(quotations.map(function (q) { return q.id; }));
|
|
@@ -67,6 +81,14 @@ export function DialogSaveQuotation(props) {
|
|
|
67
81
|
});
|
|
68
82
|
}
|
|
69
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
|
+
};
|
|
70
92
|
var handleSelectAll = function () {
|
|
71
93
|
if (isSelectAll) {
|
|
72
94
|
setSelectedQuotationIds(remainingQuotations.length > 1 ? [remainingQuotations[0].id] : []);
|
|
@@ -77,6 +99,9 @@ export function DialogSaveQuotation(props) {
|
|
|
77
99
|
setIsSelectAll(!isSelectAll);
|
|
78
100
|
};
|
|
79
101
|
var handleSubmit = function () {
|
|
102
|
+
var _a;
|
|
103
|
+
setFieldErrors({});
|
|
104
|
+
setFormErrorMessage(null);
|
|
80
105
|
var formData = {
|
|
81
106
|
agentForename: agentForename,
|
|
82
107
|
agentLastname: agentLastname,
|
|
@@ -85,13 +110,55 @@ export function DialogSaveQuotation(props) {
|
|
|
85
110
|
};
|
|
86
111
|
var result = saveQuotationSchema.safeParse(formData);
|
|
87
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.');
|
|
88
128
|
return;
|
|
89
129
|
}
|
|
90
130
|
onSubmit({
|
|
91
131
|
selectedQuotationIds: remainingQuotationsFiltered.map(function (q) { return q.id; }),
|
|
92
132
|
formData: result.data,
|
|
93
133
|
});
|
|
94
|
-
setOpen(false);
|
|
95
134
|
};
|
|
96
|
-
return (_jsx(DialogBookingConfirm, { open: open, setOpen: setOpen, title:
|
|
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")) }) }) }));
|
|
97
164
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -64,8 +64,8 @@ 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/DialogSendingMail';
|
|
68
67
|
export * from './components/organisms/DialogSaveQuotation';
|
|
68
|
+
export * from './components/organisms/DialogSendingMail';
|
|
69
69
|
export { default as Docket } from './components/organisms/Docket/Docket';
|
|
70
70
|
export { DocketAccordion, type DocketAccordionProps, } from './components/organisms/DocketAccordion';
|
|
71
71
|
export { Footer } from './components/organisms/Footer/Footer';
|
package/dist/index.js
CHANGED
|
@@ -66,8 +66,8 @@ 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/DialogSendingMail';
|
|
70
69
|
export * from './components/organisms/DialogSaveQuotation';
|
|
70
|
+
export * from './components/organisms/DialogSendingMail';
|
|
71
71
|
export { default as Docket } from './components/organisms/Docket/Docket';
|
|
72
72
|
export { DocketAccordion, } from './components/organisms/DocketAccordion';
|
|
73
73
|
export { Footer } from './components/organisms/Footer/Footer';
|
|
@@ -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 */
|
package/package.json
CHANGED
|
@@ -37,8 +37,6 @@ export const DocketPrices: React.FC<DocketPricesProps> = ({
|
|
|
37
37
|
return null;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
console.log('prices', prices);
|
|
41
|
-
|
|
42
40
|
return (
|
|
43
41
|
<div className={`docket-prices ${className}`}>
|
|
44
42
|
<Text variant="bold" size="sm" color="default" className="docket-prices__label">
|
|
@@ -7,6 +7,14 @@
|
|
|
7
7
|
gap: var(--spacing-gap-gap-6, 24px);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
/* Animated view wrapper (form vs success) */
|
|
11
|
+
.dialog-save-quotation__view {
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
gap: var(--spacing-gap-gap-6, 24px);
|
|
15
|
+
width: 100%;
|
|
16
|
+
}
|
|
17
|
+
|
|
10
18
|
/* Selected quotes section - tags + select all */
|
|
11
19
|
.dialog-save-quotation__quotes-section {
|
|
12
20
|
display: flex;
|
|
@@ -84,6 +92,28 @@
|
|
|
84
92
|
color: var(--color-text-state-error);
|
|
85
93
|
}
|
|
86
94
|
|
|
95
|
+
/* Disabled label – matches Figma / input design token */
|
|
96
|
+
.dialog-save-quotation__label--disabled {
|
|
97
|
+
color: var(--input-color-label-disabled, var(--color-text-state-disabled));
|
|
98
|
+
cursor: not-allowed;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.dialog-save-quotation__label--disabled.dialog-save-quotation__label--required::after {
|
|
102
|
+
color: var(--input-color-label-disabled, var(--color-text-state-disabled));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* Form error message – displayed below the form when validation fails */
|
|
106
|
+
.dialog-save-quotation__error {
|
|
107
|
+
font-family:
|
|
108
|
+
var(--font-font-family-body), 'Satoshi', 'Inter', 'Segoe UI', system-ui, sans-serif;
|
|
109
|
+
font-size: var(--font-size-text-sm, 14px);
|
|
110
|
+
font-weight: var(--font-weight-font-regular, 400);
|
|
111
|
+
line-height: var(--font-leading-leading-sm, 20px);
|
|
112
|
+
color: var(--color-text-state-error, #dc2626);
|
|
113
|
+
margin: 0;
|
|
114
|
+
padding: var(--spacing-gap-gap-2, 8px) 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
87
117
|
/* Footer - buttons full width, side by side */
|
|
88
118
|
.dialog-save-quotation__footer {
|
|
89
119
|
display: flex;
|
|
@@ -98,3 +128,54 @@
|
|
|
98
128
|
flex: 1;
|
|
99
129
|
min-width: 0;
|
|
100
130
|
}
|
|
131
|
+
|
|
132
|
+
/* ===== Success state content (Figma 4700-366717 – Shared-flows) ===== */
|
|
133
|
+
.dialog-save-quotation__content {
|
|
134
|
+
display: flex;
|
|
135
|
+
flex-direction: column;
|
|
136
|
+
align-items: center;
|
|
137
|
+
gap: var(--spacing-gap-gap-4, 16px);
|
|
138
|
+
text-align: center;
|
|
139
|
+
padding: var(--spacing-gap-gap-2, 8px) 0 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.dialog-save-quotation__content-image-container {
|
|
143
|
+
display: flex;
|
|
144
|
+
align-items: center;
|
|
145
|
+
justify-content: center;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.dialog-save-quotation__content-image {
|
|
149
|
+
width: 150px;
|
|
150
|
+
height: 150px;
|
|
151
|
+
object-fit: contain;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.dialog-save-quotation__content-text {
|
|
155
|
+
display: flex;
|
|
156
|
+
flex-direction: column;
|
|
157
|
+
gap: var(--spacing-gap-gap-2, 8px);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.dialog-save-quotation__content-title {
|
|
161
|
+
color: var(--color-text-default, #262626);
|
|
162
|
+
text-align: center;
|
|
163
|
+
|
|
164
|
+
/* heading-sm/medium */
|
|
165
|
+
font-family: var(--font-font-family-heading, Satoshi);
|
|
166
|
+
font-size: var(--font-size-text-2xl, 24px);
|
|
167
|
+
font-style: normal;
|
|
168
|
+
font-weight: var(--font-weight-font-medium, 500);
|
|
169
|
+
line-height: var(--font-leading-leading-xl, 32px); /* 133.333% */
|
|
170
|
+
letter-spacing: var(--font-tracking-tracking-normal, 0);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.dialog-save-quotation__content-message {
|
|
174
|
+
font-family:
|
|
175
|
+
var(--font-font-family-body), 'Satoshi', 'Inter', 'Segoe UI', system-ui, sans-serif;
|
|
176
|
+
font-size: var(--font-size-text-sm, 14px);
|
|
177
|
+
font-weight: var(--font-weight-font-regular, 400);
|
|
178
|
+
line-height: var(--font-leading-leading-md, 24px);
|
|
179
|
+
color: var(--color-text-default, #262626);
|
|
180
|
+
margin: 0;
|
|
181
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import { AnimatePresence } from 'motion/react';
|
|
2
|
+
import * as motion from 'motion/react-m';
|
|
1
3
|
import { useEffect, useMemo, useState } from 'react';
|
|
2
4
|
import Button from '../../atoms/Button/Button';
|
|
3
5
|
import Checkbox from '../../atoms/Checkbox/Checkbox';
|
|
4
6
|
import Input from '../../atoms/Inputs/Input/Input';
|
|
5
7
|
import SelectedValue from '../../atoms/SelectedValue/SelectedValue';
|
|
8
|
+
import { Text } from '../../atoms/Typography/Typography';
|
|
6
9
|
import { DialogBookingConfirm } from '../DialogBookingConfirm';
|
|
7
|
-
import {
|
|
8
|
-
saveQuotationSchema,
|
|
9
|
-
SaveQuotationSchema,
|
|
10
|
-
} from './save-quotation-schema';
|
|
11
10
|
import './DialogSaveQuotation.css';
|
|
11
|
+
import { saveQuotationSchema, SaveQuotationSchema } from './save-quotation-schema';
|
|
12
12
|
|
|
13
13
|
export interface SaveQuotationQuote {
|
|
14
14
|
id: string;
|
|
@@ -27,8 +27,24 @@ export interface DialogSaveQuotationProps {
|
|
|
27
27
|
selectedQuotationIds: string[];
|
|
28
28
|
formData: SaveQuotationSchema;
|
|
29
29
|
}) => void;
|
|
30
|
+
/** Callback when the book now button is clicked */
|
|
31
|
+
onHandleBookNow?: () => void;
|
|
32
|
+
/** Callback when the view on quotation grid button is clicked */
|
|
33
|
+
onHandleViewOnQuotationGrid?: () => void;
|
|
30
34
|
/** Optional default values for the form */
|
|
31
35
|
defaultValues?: Partial<SaveQuotationSchema>;
|
|
36
|
+
/** Which form inputs to disable. Omit or set to false to keep an input enabled. */
|
|
37
|
+
disabledInputs?: Partial<Record<keyof SaveQuotationSchema, boolean>>;
|
|
38
|
+
/** Whether the form is loading */
|
|
39
|
+
loading?: boolean;
|
|
40
|
+
/** Whether the form is successful */
|
|
41
|
+
successful?: boolean;
|
|
42
|
+
/** The error message to display */
|
|
43
|
+
errorMessage?: string;
|
|
44
|
+
/** The image to display when the form is successful */
|
|
45
|
+
imgSuccess?: string;
|
|
46
|
+
/** The image to display */
|
|
47
|
+
imgSuccessAlt?: string;
|
|
32
48
|
}
|
|
33
49
|
|
|
34
50
|
/**
|
|
@@ -52,6 +68,14 @@ export function DialogSaveQuotation(props: DialogSaveQuotationProps) {
|
|
|
52
68
|
quotations,
|
|
53
69
|
onSubmit,
|
|
54
70
|
defaultValues,
|
|
71
|
+
disabledInputs,
|
|
72
|
+
errorMessage,
|
|
73
|
+
successful,
|
|
74
|
+
loading,
|
|
75
|
+
imgSuccess,
|
|
76
|
+
imgSuccessAlt,
|
|
77
|
+
onHandleBookNow,
|
|
78
|
+
onHandleViewOnQuotationGrid,
|
|
55
79
|
} = props;
|
|
56
80
|
|
|
57
81
|
const [remainingQuotations, setRemainingQuotations] =
|
|
@@ -59,20 +83,17 @@ export function DialogSaveQuotation(props: DialogSaveQuotationProps) {
|
|
|
59
83
|
const [selectedQuotationIds, setSelectedQuotationIds] = useState<string[]>([]);
|
|
60
84
|
const [isSelectAll, setIsSelectAll] = useState(false);
|
|
61
85
|
|
|
62
|
-
const [agentForename, setAgentForename] = useState(
|
|
63
|
-
|
|
64
|
-
);
|
|
65
|
-
const [agentLastname, setAgentLastname] = useState(
|
|
66
|
-
defaultValues?.agentLastname ?? ''
|
|
67
|
-
);
|
|
86
|
+
const [agentForename, setAgentForename] = useState(defaultValues?.agentForename ?? '');
|
|
87
|
+
const [agentLastname, setAgentLastname] = useState(defaultValues?.agentLastname ?? '');
|
|
68
88
|
const [agency, setAgency] = useState(defaultValues?.agency ?? '');
|
|
69
|
-
const [quotationName, setQuotationName] = useState(
|
|
70
|
-
|
|
71
|
-
|
|
89
|
+
const [quotationName, setQuotationName] = useState(defaultValues?.quotationName ?? '');
|
|
90
|
+
const [fieldErrors, setFieldErrors] = useState<
|
|
91
|
+
Partial<Record<keyof SaveQuotationSchema, string>>
|
|
92
|
+
>({});
|
|
93
|
+
const [formErrorMessage, setFormErrorMessage] = useState<string | null>(null);
|
|
72
94
|
|
|
73
95
|
const remainingQuotationsFiltered = useMemo(
|
|
74
|
-
() =>
|
|
75
|
-
remainingQuotations.filter((q) => selectedQuotationIds.includes(q.id)),
|
|
96
|
+
() => remainingQuotations.filter((q) => selectedQuotationIds.includes(q.id)),
|
|
76
97
|
[remainingQuotations, selectedQuotationIds]
|
|
77
98
|
);
|
|
78
99
|
|
|
@@ -106,9 +127,20 @@ export function DialogSaveQuotation(props: DialogSaveQuotationProps) {
|
|
|
106
127
|
}
|
|
107
128
|
};
|
|
108
129
|
|
|
130
|
+
const clearFieldError = (field: keyof SaveQuotationSchema) => {
|
|
131
|
+
setFieldErrors((prev) => {
|
|
132
|
+
const next = { ...prev };
|
|
133
|
+
delete next[field];
|
|
134
|
+
return next;
|
|
135
|
+
});
|
|
136
|
+
setFormErrorMessage(null);
|
|
137
|
+
};
|
|
138
|
+
|
|
109
139
|
const handleSelectAll = () => {
|
|
110
140
|
if (isSelectAll) {
|
|
111
|
-
setSelectedQuotationIds(
|
|
141
|
+
setSelectedQuotationIds(
|
|
142
|
+
remainingQuotations.length > 1 ? [remainingQuotations[0].id] : []
|
|
143
|
+
);
|
|
112
144
|
} else {
|
|
113
145
|
setSelectedQuotationIds(remainingQuotations.map((q) => q.id));
|
|
114
146
|
}
|
|
@@ -116,6 +148,9 @@ export function DialogSaveQuotation(props: DialogSaveQuotationProps) {
|
|
|
116
148
|
};
|
|
117
149
|
|
|
118
150
|
const handleSubmit = () => {
|
|
151
|
+
setFieldErrors({});
|
|
152
|
+
setFormErrorMessage(null);
|
|
153
|
+
|
|
119
154
|
const formData: SaveQuotationSchema = {
|
|
120
155
|
agentForename,
|
|
121
156
|
agentLastname,
|
|
@@ -125,6 +160,23 @@ export function DialogSaveQuotation(props: DialogSaveQuotationProps) {
|
|
|
125
160
|
|
|
126
161
|
const result = saveQuotationSchema.safeParse(formData);
|
|
127
162
|
if (!result.success) {
|
|
163
|
+
const errors: Partial<Record<keyof SaveQuotationSchema, string>> = {};
|
|
164
|
+
const messages: string[] = [];
|
|
165
|
+
result.error.issues.forEach((issue) => {
|
|
166
|
+
const path = issue.path[0] as keyof SaveQuotationSchema;
|
|
167
|
+
if (
|
|
168
|
+
path &&
|
|
169
|
+
(path === 'agentForename' ||
|
|
170
|
+
path === 'agentLastname' ||
|
|
171
|
+
path === 'agency' ||
|
|
172
|
+
path === 'quotationName')
|
|
173
|
+
) {
|
|
174
|
+
errors[path] = issue.message;
|
|
175
|
+
messages.push(issue.message);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
setFieldErrors(errors);
|
|
179
|
+
setFormErrorMessage(messages[0] ?? 'Please correct the errors below.');
|
|
128
180
|
return;
|
|
129
181
|
}
|
|
130
182
|
|
|
@@ -132,118 +184,227 @@ export function DialogSaveQuotation(props: DialogSaveQuotationProps) {
|
|
|
132
184
|
selectedQuotationIds: remainingQuotationsFiltered.map((q) => q.id),
|
|
133
185
|
formData: result.data,
|
|
134
186
|
});
|
|
135
|
-
setOpen(false);
|
|
136
187
|
};
|
|
137
188
|
|
|
138
189
|
return (
|
|
139
190
|
<DialogBookingConfirm
|
|
140
191
|
open={open}
|
|
141
192
|
setOpen={setOpen}
|
|
142
|
-
title=
|
|
193
|
+
title={!successful ? 'Save quotation' : undefined}
|
|
143
194
|
className="!max-w-[800px]"
|
|
144
195
|
closeOnOverlayClick>
|
|
145
|
-
<div className="dialog-save-quotation">
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
196
|
+
<motion.div className="dialog-save-quotation">
|
|
197
|
+
<AnimatePresence mode="wait" initial={false}>
|
|
198
|
+
{!successful ? (
|
|
199
|
+
<motion.div
|
|
200
|
+
key="form"
|
|
201
|
+
className="dialog-save-quotation__view"
|
|
202
|
+
initial={{ opacity: 0 }}
|
|
203
|
+
animate={{ opacity: 1 }}
|
|
204
|
+
exit={{ opacity: 0 }}
|
|
205
|
+
transition={{ duration: 0.2, ease: 'easeInOut' }}>
|
|
206
|
+
<div className="dialog-save-quotation__quotes-section">
|
|
207
|
+
<div className="dialog-save-quotation__quotes-list">
|
|
208
|
+
{remainingQuotations.map((quote) => (
|
|
209
|
+
<SelectedValue
|
|
210
|
+
key={quote.id}
|
|
211
|
+
value={quote.name}
|
|
212
|
+
color={
|
|
213
|
+
selectedQuotationIds.includes(quote.id) ? 'accent' : 'neutral'
|
|
214
|
+
}
|
|
215
|
+
onSelect={() => handleSelectQuotation(quote.id)}
|
|
216
|
+
onRemove={() => handleRemoveQuotation(quote.id)}
|
|
217
|
+
size="lg"
|
|
218
|
+
textSize="md"
|
|
219
|
+
/>
|
|
220
|
+
))}
|
|
221
|
+
</div>
|
|
222
|
+
<div className="dialog-save-quotation__select-all">
|
|
223
|
+
<Checkbox
|
|
224
|
+
label="Select all quotations"
|
|
225
|
+
checked={isSelectAll || remainingQuotations.length === 1}
|
|
226
|
+
disabled={remainingQuotations.length === 1}
|
|
227
|
+
onChange={handleSelectAll}
|
|
228
|
+
labelPosition="leading"
|
|
229
|
+
/>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
|
|
233
|
+
{/* All quotations form */}
|
|
234
|
+
<h3 className="dialog-save-quotation__section-title">All quotations</h3>
|
|
235
|
+
|
|
236
|
+
<div className="dialog-save-quotation__form">
|
|
237
|
+
<div className="dialog-save-quotation__form-row">
|
|
238
|
+
<div className="dialog-save-quotation__field">
|
|
239
|
+
<label
|
|
240
|
+
htmlFor="agent-forename"
|
|
241
|
+
className={`dialog-save-quotation__label dialog-save-quotation__label--required${disabledInputs?.agentForename ? ' dialog-save-quotation__label--disabled' : ''}`}>
|
|
242
|
+
Agent Forename
|
|
243
|
+
</label>
|
|
244
|
+
<Input
|
|
245
|
+
id="agent-forename"
|
|
246
|
+
value={agentForename}
|
|
247
|
+
onChange={(e) => {
|
|
248
|
+
setAgentForename(e.target.value);
|
|
249
|
+
clearFieldError('agentForename');
|
|
250
|
+
}}
|
|
251
|
+
placeholder="Mautourco"
|
|
252
|
+
variant={
|
|
253
|
+
disabledInputs?.agentForename
|
|
254
|
+
? 'disabled'
|
|
255
|
+
: fieldErrors.agentForename || errorMessage
|
|
256
|
+
? 'error'
|
|
257
|
+
: 'default'
|
|
258
|
+
}
|
|
259
|
+
/>
|
|
260
|
+
</div>
|
|
261
|
+
<div className="dialog-save-quotation__field">
|
|
262
|
+
<label
|
|
263
|
+
htmlFor="agent-lastname"
|
|
264
|
+
className={`dialog-save-quotation__label dialog-save-quotation__label--required${disabledInputs?.agentLastname ? ' dialog-save-quotation__label--disabled' : ''}`}>
|
|
265
|
+
Agent Lastname
|
|
266
|
+
</label>
|
|
267
|
+
<Input
|
|
268
|
+
id="agent-lastname"
|
|
269
|
+
value={agentLastname}
|
|
270
|
+
onChange={(e) => {
|
|
271
|
+
setAgentLastname(e.target.value);
|
|
272
|
+
clearFieldError('agentLastname');
|
|
273
|
+
}}
|
|
274
|
+
placeholder="B2B"
|
|
275
|
+
variant={
|
|
276
|
+
disabledInputs?.agentLastname
|
|
277
|
+
? 'disabled'
|
|
278
|
+
: fieldErrors.agentLastname || errorMessage
|
|
279
|
+
? 'error'
|
|
280
|
+
: 'default'
|
|
281
|
+
}
|
|
282
|
+
/>
|
|
283
|
+
</div>
|
|
284
|
+
<div className="dialog-save-quotation__field">
|
|
285
|
+
<label
|
|
286
|
+
htmlFor="agency"
|
|
287
|
+
className={`dialog-save-quotation__label${disabledInputs?.agency ? ' dialog-save-quotation__label--disabled' : ''}`}>
|
|
288
|
+
Agency
|
|
289
|
+
</label>
|
|
290
|
+
<Input
|
|
291
|
+
id="agency"
|
|
292
|
+
value={agency}
|
|
293
|
+
onChange={(e) => {
|
|
294
|
+
setAgency(e.target.value);
|
|
295
|
+
clearFieldError('agency');
|
|
296
|
+
}}
|
|
297
|
+
placeholder="Mautourco Ltd"
|
|
298
|
+
variant={
|
|
299
|
+
disabledInputs?.agency
|
|
300
|
+
? 'disabled'
|
|
301
|
+
: fieldErrors.agency || errorMessage
|
|
302
|
+
? 'error'
|
|
303
|
+
: 'default'
|
|
304
|
+
}
|
|
305
|
+
/>
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
|
|
309
|
+
<div className="dialog-save-quotation__form-row dialog-save-quotation__form-row--single">
|
|
310
|
+
<div className="dialog-save-quotation__field">
|
|
311
|
+
<label
|
|
312
|
+
htmlFor="quotation-name"
|
|
313
|
+
className={`dialog-save-quotation__label dialog-save-quotation__label--required${disabledInputs?.quotationName ? ' dialog-save-quotation__label--disabled' : ''}`}>
|
|
314
|
+
Quotation name
|
|
315
|
+
</label>
|
|
316
|
+
<Input
|
|
317
|
+
id="quotation-name"
|
|
318
|
+
value={quotationName}
|
|
319
|
+
onChange={(e) => {
|
|
320
|
+
setQuotationName(e.target.value);
|
|
321
|
+
clearFieldError('quotationName');
|
|
322
|
+
}}
|
|
323
|
+
placeholder="Insert client's name"
|
|
324
|
+
variant={
|
|
325
|
+
disabledInputs?.quotationName
|
|
326
|
+
? 'disabled'
|
|
327
|
+
: fieldErrors.quotationName || errorMessage
|
|
328
|
+
? 'error'
|
|
329
|
+
: 'default'
|
|
330
|
+
}
|
|
331
|
+
/>
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
334
|
+
</div>
|
|
335
|
+
|
|
336
|
+
{(formErrorMessage || errorMessage) && (
|
|
337
|
+
<p className="dialog-save-quotation__error" role="alert">
|
|
338
|
+
{formErrorMessage ?? errorMessage}
|
|
339
|
+
</p>
|
|
340
|
+
)}
|
|
341
|
+
|
|
342
|
+
<div className="dialog-save-quotation__footer">
|
|
343
|
+
<Button
|
|
344
|
+
variant="outline-secondary"
|
|
345
|
+
size="sm"
|
|
346
|
+
onClick={() => setOpen(false)}
|
|
347
|
+
disabled={loading}>
|
|
348
|
+
Cancel
|
|
349
|
+
</Button>
|
|
350
|
+
<Button
|
|
351
|
+
variant="secondary"
|
|
352
|
+
size="sm"
|
|
353
|
+
onClick={handleSubmit}
|
|
354
|
+
disabled={loading}>
|
|
355
|
+
{loading ? 'Saving…' : 'Save quotation'}
|
|
356
|
+
</Button>
|
|
357
|
+
</div>
|
|
358
|
+
</motion.div>
|
|
359
|
+
) : (
|
|
360
|
+
<motion.div
|
|
361
|
+
key="success"
|
|
362
|
+
className="dialog-save-quotation__view"
|
|
363
|
+
initial={{ opacity: 0 }}
|
|
364
|
+
animate={{ opacity: 1 }}
|
|
365
|
+
exit={{ opacity: 0 }}
|
|
366
|
+
transition={{ duration: 0.2, ease: 'easeInOut' }}>
|
|
367
|
+
<div className="dialog-save-quotation__content">
|
|
368
|
+
<div
|
|
369
|
+
className="dialog-save-quotation__content-image-container"
|
|
370
|
+
aria-hidden>
|
|
371
|
+
<img
|
|
372
|
+
src={imgSuccess}
|
|
373
|
+
alt={imgSuccessAlt}
|
|
374
|
+
className="dialog-save-quotation__content-image"
|
|
375
|
+
/>
|
|
376
|
+
</div>
|
|
377
|
+
<div className="dialog-save-quotation__content-text">
|
|
378
|
+
<Text
|
|
379
|
+
variant="bold"
|
|
380
|
+
size="xl"
|
|
381
|
+
as="h2"
|
|
382
|
+
className="dialog-save-quotation__content-title ">
|
|
383
|
+
Quotation saved
|
|
384
|
+
</Text>
|
|
385
|
+
<Text size="lg">
|
|
386
|
+
<Text size="lg" variant="bold" as="span">
|
|
387
|
+
"{quotationName}"
|
|
388
|
+
</Text>{' '}
|
|
389
|
+
quotation
|
|
390
|
+
</Text>
|
|
391
|
+
</div>
|
|
392
|
+
</div>
|
|
393
|
+
<div className="dialog-save-quotation__footer">
|
|
394
|
+
<Button
|
|
395
|
+
variant="outline-secondary"
|
|
396
|
+
size="sm"
|
|
397
|
+
onClick={onHandleViewOnQuotationGrid}>
|
|
398
|
+
View on quotation grid
|
|
399
|
+
</Button>
|
|
400
|
+
<Button variant="secondary" size="sm" onClick={onHandleBookNow}>
|
|
401
|
+
Book now
|
|
402
|
+
</Button>
|
|
403
|
+
</div>
|
|
404
|
+
</motion.div>
|
|
405
|
+
)}
|
|
406
|
+
</AnimatePresence>
|
|
407
|
+
</motion.div>
|
|
247
408
|
</DialogBookingConfirm>
|
|
248
409
|
);
|
|
249
410
|
}
|
|
@@ -97,16 +97,16 @@
|
|
|
97
97
|
color: var(--color-red-400);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
/* État disabled */
|
|
100
|
+
/* État disabled – Mautourco Foundations tokens */
|
|
101
101
|
.input-field--disabled {
|
|
102
|
-
background-color: var(--color-
|
|
103
|
-
border-color: var(--color-
|
|
104
|
-
color: var(--color-
|
|
102
|
+
background-color: var(--color-elevation-state-disabled, #fbfbfb);
|
|
103
|
+
border-color: var(--color-border-input-disabled, #d1d5db);
|
|
104
|
+
color: var(--color-text-state-disabled, #a3a3a3);
|
|
105
105
|
cursor: not-allowed;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
.input-field--disabled::placeholder {
|
|
109
|
-
color: var(--color-
|
|
109
|
+
color: var(--color-text-state-disabled, #a3a3a3);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
/* Styles pour le showcase */
|