mautourco-components 0.2.13 → 0.2.15

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.
Files changed (35) hide show
  1. package/dist/components/atoms/Icon/icons/PlusCircleIcon.d.ts +12 -0
  2. package/dist/components/atoms/Icon/icons/PlusCircleIcon.js +36 -0
  3. package/dist/components/atoms/Icon/icons/QuotationIcon.d.ts +8 -0
  4. package/dist/components/atoms/Icon/icons/QuotationIcon.js +36 -0
  5. package/dist/components/atoms/Icon/icons/registry.d.ts +2 -0
  6. package/dist/components/atoms/Icon/icons/registry.js +4 -0
  7. package/dist/components/atoms/Inputs/DropdownInput/DropdownInput.js +15 -3
  8. package/dist/components/organisms/MultipleQuotationDocket/MultipleQuotationDocket.d.ts +64 -0
  9. package/dist/components/organisms/MultipleQuotationDocket/MultipleQuotationDocket.js +45 -0
  10. package/dist/components/organisms/MultipleQuotationDocket/index.d.ts +2 -0
  11. package/dist/components/organisms/MultipleQuotationDocket/index.js +1 -0
  12. package/dist/components/organisms/QuoteHeader/QuoteHeader.css +2142 -0
  13. package/dist/components/organisms/QuoteHeader/QuoteHeader.d.ts +12 -0
  14. package/dist/components/organisms/QuoteHeader/QuoteHeader.js +41 -0
  15. package/dist/components/organisms/QuoteHeader/constant.d.ts +3 -0
  16. package/dist/components/organisms/QuoteHeader/constant.js +8 -0
  17. package/dist/index.d.ts +4 -0
  18. package/dist/index.js +2 -0
  19. package/dist/styles/components/dropdown.css +7 -6
  20. package/dist/styles/components/forms.css +18 -9
  21. package/dist/styles/components/organism/multiple-quotation-docket.css +2304 -0
  22. package/package.json +1 -1
  23. package/src/components/atoms/Icon/icons/PlusCircleIcon.tsx +60 -0
  24. package/src/components/atoms/Icon/icons/QuotationIcon.tsx +50 -0
  25. package/src/components/atoms/Icon/icons/registry.tsx +4 -0
  26. package/src/components/atoms/Inputs/DropdownInput/DropdownInput.tsx +29 -17
  27. package/src/components/organisms/CarBookingCard/index.ts +1 -0
  28. package/src/components/organisms/MultipleQuotationDocket/MultipleQuotationDocket.tsx +349 -0
  29. package/src/components/organisms/MultipleQuotationDocket/index.ts +6 -0
  30. package/src/components/organisms/QuoteHeader/QuoteHeader.css +37 -0
  31. package/src/components/organisms/QuoteHeader/QuoteHeader.tsx +93 -0
  32. package/src/components/organisms/QuoteHeader/constant.ts +8 -0
  33. package/src/styles/components/dropdown.css +7 -6
  34. package/src/styles/components/forms.css +18 -11
  35. package/src/styles/components/organism/multiple-quotation-docket.css +222 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mautourco-components",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
4
4
  "private": false,
5
5
  "description": "Bibliothèque de composants Motorco pour le redesign",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+
3
+ interface PlusCircleIconProps {
4
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
5
+ className?: string;
6
+ color?: string;
7
+ /**
8
+ * Couleur par défaut si aucune couleur n'est spécifiée
9
+ */
10
+ defaultColor?: string;
11
+ }
12
+
13
+ const PlusCircleIcon: React.FC<PlusCircleIconProps> = ({
14
+ size = 'md',
15
+ className = '',
16
+ color,
17
+ }) => {
18
+ const getSizeClasses = () => {
19
+ switch (size) {
20
+ case 'xs':
21
+ return 'w-3 h-3';
22
+ case 'sm':
23
+ return 'w-4 h-4';
24
+ case 'md':
25
+ return 'w-5 h-5';
26
+ case 'lg':
27
+ return 'w-6 h-6';
28
+ case 'xl':
29
+ return 'w-8 h-8';
30
+ default:
31
+ return 'w-5 h-5';
32
+ }
33
+ };
34
+
35
+ const sizeClasses = getSizeClasses();
36
+ const colorClass = color ? `text-${color}` : 'text-current';
37
+ const classes = `${sizeClasses} ${colorClass} ${className}`;
38
+
39
+ return (
40
+ <svg
41
+ className={classes}
42
+ viewBox="0 0 16 16"
43
+ fill="none"
44
+ xmlns="http://www.w3.org/2000/svg">
45
+ <g clip-path="url(#clip0_7074_66340)">
46
+ <path
47
+ d="M13.915 8.00098C13.915 4.7334 11.2666 2.08416 7.99902 2.08398C4.73134 2.08398 2.08203 4.73329 2.08203 8.00098C2.08221 11.2685 4.73145 13.917 7.99902 13.917C11.2664 13.9168 13.9149 11.2684 13.915 8.00098ZM7.24902 10.667V8.75098H5.33203C4.91793 8.75098 4.58221 8.41504 4.58203 8.00098C4.58203 7.58676 4.91782 7.25098 5.33203 7.25098H7.24902V5.33398C7.24902 4.91977 7.58481 4.58398 7.99902 4.58398C8.41309 4.58416 8.74902 4.91988 8.74902 5.33398V7.25098H10.665L10.7422 7.25488C11.1203 7.29337 11.415 7.61271 11.415 8.00098C11.4149 8.38912 11.1202 8.70862 10.7422 8.74707L10.665 8.75098H8.74902V10.667C8.74902 11.0811 8.41309 11.4168 7.99902 11.417C7.58481 11.417 7.24902 11.0812 7.24902 10.667ZM15.415 8.00098C15.4149 12.0968 12.0949 15.4168 7.99902 15.417C3.90302 15.417 0.582208 12.0969 0.582031 8.00098C0.582031 3.90487 3.90291 0.583984 7.99902 0.583984C12.095 0.584161 15.415 3.90497 15.415 8.00098Z"
48
+ fill="white"
49
+ />
50
+ </g>
51
+ <defs>
52
+ <clipPath id="clip0_7074_66340">
53
+ <rect width="16" height="16" fill="white" />
54
+ </clipPath>
55
+ </defs>
56
+ </svg>
57
+ );
58
+ };
59
+
60
+ export default PlusCircleIcon;
@@ -0,0 +1,50 @@
1
+ import React from 'react';
2
+
3
+ interface QuotationIconProps {
4
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
5
+ className?: string;
6
+ color?: string;
7
+ }
8
+
9
+ const QuotationIcon: React.FC<QuotationIconProps> = ({
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 22 20"
39
+ fill="none"
40
+ xmlns="http://www.w3.org/2000/svg">
41
+ <path
42
+ d="M10 16V17C10 17.3444 9.93703 17.6814 9.82422 18H19C19.2652 18 19.5195 17.8946 19.707 17.707C19.8946 17.5195 20 17.2652 20 17V16H10ZM14 9C14.5523 9 15 9.44771 15 10C15 10.5523 14.5523 11 14 11H9C8.44771 11 8 10.5523 8 10C8 9.44771 8.44771 9 9 9H14ZM14 5C14.5523 5 15 5.44772 15 6C15 6.55228 14.5523 7 14 7H9C8.44771 7 8 6.55228 8 6C8 5.44772 8.44771 5 9 5H14ZM4 3C4 2.73478 3.89457 2.4805 3.70703 2.29297C3.54289 2.12883 3.32763 2.02757 3.09863 2.00488L3 2C2.73478 2 2.4805 2.10543 2.29297 2.29297C2.10543 2.4805 2 2.73478 2 3V5H4V3ZM6 17L6.00488 17.0986C6.02757 17.3276 6.12883 17.5429 6.29297 17.707C6.48051 17.8946 6.73478 18 7 18C7.26522 18 7.51949 17.8946 7.70703 17.707C7.89457 17.5195 8 17.2652 8 17V16C8 15.4696 8.21087 14.961 8.58594 14.5859C8.96101 14.2109 9.46957 14 10 14H17V3C17 2.73478 16.8946 2.48051 16.707 2.29297C16.5195 2.10543 16.2652 2 16 2H5.82422C5.93703 2.31859 6 2.65558 6 3V17ZM19 14H20C20.5304 14 21.039 14.2109 21.4141 14.5859C21.7891 14.961 22 15.4696 22 16V17C22 17.7957 21.6837 18.5585 21.1211 19.1211C20.5585 19.6837 19.7957 20 19 20H7C6.20435 20 5.44151 19.6837 4.87891 19.1211C4.3163 18.5585 4 17.7957 4 17V7H2C1.46957 7 0.96101 6.78913 0.585938 6.41406C0.210865 6.03899 0 5.53043 0 5V3C0 2.20435 0.316297 1.44152 0.878906 0.878906C1.3711 0.386708 2.01649 0.0829076 2.70312 0.0146484L3 0H16C16.7957 0 17.5585 0.316297 18.1211 0.878906C18.6837 1.44151 19 2.20435 19 3V14Z"
43
+ fill="currentColor"
44
+ />
45
+ </svg>
46
+ );
47
+ };
48
+
49
+ export default QuotationIcon;
50
+
@@ -35,7 +35,9 @@ import NightIcon from './NightIcon';
35
35
  import PlaneIcon from './PlaneIcon';
36
36
  import PlaneLandingOutlineIcon from './PlaneLandingOutlineIcon';
37
37
  import PlaneTakeoffOutlineIcon from './PlaneTakeoffOutlineIcon';
38
+ import PlusCircleIcon from './PlusCircleIcon';
38
39
  import PlusIcon from './PlusIcon';
40
+ import QuotationIcon from './QuotationIcon';
39
41
  import Search from './Search';
40
42
  import Settings from './Settings';
41
43
  import ShipIcon from './ShipIcon';
@@ -108,6 +110,7 @@ export const ICONS = {
108
110
  linkedin: LinkedInIcon as unknown as IconComponent,
109
111
  plus: PlusIcon as unknown as IconComponent,
110
112
  minus: MinusIcon as unknown as IconComponent,
113
+ quotation: QuotationIcon as unknown as IconComponent,
111
114
  home: HomeIcon as unknown as IconComponent,
112
115
  plane: PlaneIcon as unknown as IconComponent,
113
116
  ship: ShipIcon as unknown as IconComponent,
@@ -122,6 +125,7 @@ export const ICONS = {
122
125
  bus: BusIcon as unknown as IconComponent,
123
126
  map: MapIcon as unknown as IconComponent,
124
127
  wallet: WalletIcon as unknown as IconComponent,
128
+ 'plus-circle': PlusCircleIcon as unknown as IconComponent,
125
129
  } as const satisfies Record<string, IconComponent>;
126
130
 
127
131
  export type IconName = keyof typeof ICONS;
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React, { useEffect, useRef, useState } from 'react';
2
2
  import Icon from '../../Icon/Icon';
3
3
  import Spinner from '../../Spinner/Spinner';
4
4
 
@@ -19,12 +19,14 @@ const DropdownInput: React.FC<DropdownInputProps> = ({
19
19
  onClick,
20
20
  className = '',
21
21
  options = [],
22
- onSelect
22
+ onSelect,
23
23
  }) => {
24
24
  const [isOpen, setIsOpen] = useState(false);
25
+ const dropdownRef = useRef<HTMLDivElement>(null);
26
+
25
27
  const handleClick = () => {
26
28
  if (state === 'disabled' || state === 'loading') return;
27
-
29
+
28
30
  setIsOpen(!isOpen);
29
31
  onClick?.();
30
32
  };
@@ -54,36 +56,46 @@ const DropdownInput: React.FC<DropdownInputProps> = ({
54
56
  if (state === 'loading') {
55
57
  return <Spinner size="sm" className="dropdown-input__icon" />;
56
58
  }
57
-
59
+
58
60
  return (
59
- <Icon
60
- name={isOpen ? 'chevron-up' : 'chevron-down'}
61
- size="sm"
62
- className="dropdown-input__icon dropdown-input__icon--chevron"
61
+ <Icon
62
+ name={isOpen ? 'chevron-up' : 'chevron-down'}
63
+ size="sm"
64
+ className="dropdown-input__icon dropdown-input__icon--chevron"
63
65
  />
64
66
  );
65
67
  };
66
68
 
67
- const displayText = state === 'loading' ? 'Loading...' : (value || placeholder);
69
+ const displayText = state === 'loading' ? 'Loading...' : value || placeholder;
70
+
71
+ useEffect(() => {
72
+ const handleClickOutside = (event: MouseEvent) => {
73
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
74
+ setIsOpen(false);
75
+ }
76
+ };
77
+
78
+ document.addEventListener('mousedown', handleClickOutside);
79
+
80
+ return () => {
81
+ document.removeEventListener('mousedown', handleClickOutside);
82
+ };
83
+ }, []);
68
84
 
69
85
  return (
70
- <div className={`dropdown-container ${className}`}>
71
- <div
72
- className={`dropdown-input ${getStateClasses()}`}
73
- onClick={handleClick}
74
- >
86
+ <div ref={dropdownRef} className={`dropdown-container ${className}`}>
87
+ <div className={`dropdown-input ${getStateClasses()}`} onClick={handleClick}>
75
88
  <span className="dropdown-input__text">{displayText}</span>
76
89
  {getIcon()}
77
90
  </div>
78
-
91
+
79
92
  {isOpen && options.length > 0 && (
80
93
  <div className="dropdown-menu">
81
94
  {options.map((option, index) => (
82
95
  <div
83
96
  key={index}
84
97
  className="dropdown-option"
85
- onClick={() => handleOptionSelect(option)}
86
- >
98
+ onClick={() => handleOptionSelect(option)}>
87
99
  {option}
88
100
  </div>
89
101
  ))}
@@ -12,3 +12,4 @@ export type {
12
12
 
13
13
 
14
14
 
15
+
@@ -0,0 +1,349 @@
1
+ import React from 'react';
2
+ import Button from '../../atoms/Button/Button';
3
+ import Chip from '../../atoms/Chip/Chip';
4
+ import Icon, { IconName } from '../../atoms/Icon/Icon';
5
+ import { Heading, Text } from '../../atoms/Typography/Typography';
6
+ import TextWithIcon from '../../molecules/TextWithIcon/TextWithIcon';
7
+ import CardContainer from '../CardContainer/CardContainer';
8
+
9
+ export type DocketServiceType =
10
+ | 'Accommodation'
11
+ | 'Transfer'
12
+ | 'Handling fee'
13
+ | 'Excursion'
14
+ | 'Other Services';
15
+
16
+ export interface DocketDetailsData {
17
+ /** Service type */
18
+ type: DocketServiceType;
19
+ /** Service name/title */
20
+ serviceName?: string;
21
+ /** Price for this service */
22
+ price: string;
23
+ /** Currency for the price */
24
+ currency: string;
25
+ /** Start date */
26
+ startDate?: string;
27
+ /** End date */
28
+ endDate?: string;
29
+ /** Number of nights */
30
+ nights?: number;
31
+ /** Client type */
32
+ clientType?: string;
33
+ /** Adults count */
34
+ adults?: number;
35
+ /** Children details */
36
+ children?: Array<{ age: number }>;
37
+ /** Room type */
38
+ roomType?: string;
39
+ /** Meal plan */
40
+ mealPlan?: string;
41
+ /** Additional details to display */
42
+ details?: Array<{
43
+ icon: IconName;
44
+ label: string;
45
+ value: string;
46
+ }>;
47
+ /** Error message to display (e.g., "Please select your second room") */
48
+ errorMessage?: string;
49
+ }
50
+
51
+ export interface MultipleQuotationDocketProps {
52
+ /** Title of the quotation */
53
+ title?: string;
54
+ /** List of service details */
55
+ services: DocketDetailsData[];
56
+ /** Total prices in different currencies */
57
+ totalPrices: Array<{ currency: string; amount: string }>;
58
+ /** Callback when "More options" is clicked */
59
+ onMoreOptionsClick?: () => void;
60
+ /** Callback when "Add new quote" is clicked */
61
+ onAddNewQuoteClick?: () => void;
62
+ /** Callback when "View" is clicked */
63
+ onViewClick?: () => void;
64
+ /** Callback when "Save" is clicked */
65
+ onSaveClick?: () => void;
66
+ /** Callback when "Book now" is clicked */
67
+ onBookNowClick?: () => void;
68
+ /** Additional CSS classes */
69
+ className?: string;
70
+ }
71
+
72
+ const getServiceIcon = (type: DocketServiceType): IconName => {
73
+ switch (type) {
74
+ case 'Accommodation':
75
+ return 'accom';
76
+ case 'Transfer':
77
+ return 'bus';
78
+ case 'Excursion':
79
+ return 'map-pin';
80
+ case 'Handling fee':
81
+ return 'wallet';
82
+ case 'Other Services':
83
+ return 'more';
84
+ default:
85
+ return 'more';
86
+ }
87
+ };
88
+
89
+ const DocketDetails: React.FC<{ data: DocketDetailsData }> = ({ data }) => {
90
+ const {
91
+ type,
92
+ serviceName,
93
+ startDate,
94
+ endDate,
95
+ nights,
96
+ clientType,
97
+ adults,
98
+ children,
99
+ roomType,
100
+ mealPlan,
101
+ details,
102
+ errorMessage,
103
+ } = data;
104
+ const icon = getServiceIcon(type);
105
+
106
+ return (
107
+ <div className="multiple-quotation-docket__details">
108
+ {errorMessage && (
109
+ <div className="multiple-quotation-docket__error">
110
+ <Text variant="bold" size="sm" color="state-error">
111
+ {errorMessage}
112
+ </Text>
113
+ </div>
114
+ )}
115
+
116
+ {serviceName && (
117
+ <div className="multiple-quotation-docket__service-name">
118
+ <Text variant="bold" size="base">
119
+ {serviceName}
120
+ </Text>
121
+ </div>
122
+ )}
123
+
124
+ {(startDate || endDate || nights) && (
125
+ <div className="multiple-quotation-docket__date-info">
126
+ {startDate && endDate && (
127
+ <div className="multiple-quotation-docket__date-range">
128
+ <TextWithIcon icon="calendar-range-outline" color="accent">
129
+ {startDate}
130
+ </TextWithIcon>
131
+ <Icon name="arrow-right-outline" size="sm" />
132
+ <TextWithIcon icon="calendar-range-outline" color="accent">
133
+ {endDate}
134
+ </TextWithIcon>
135
+ </div>
136
+ )}
137
+ {nights !== undefined && (
138
+ <TextWithIcon icon="night" color="subtle">
139
+ {nights} nights
140
+ </TextWithIcon>
141
+ )}
142
+ </div>
143
+ )}
144
+
145
+ {(clientType || adults || children) && (
146
+ <div className="multiple-quotation-docket__client-info">
147
+ {clientType && (
148
+ <div className="multiple-quotation-docket__client-type">
149
+ <Text variant="bold" size="sm" color="subtle">
150
+ Client type:
151
+ </Text>
152
+ <Text variant="medium" size="sm" color="subtle">
153
+ {clientType}
154
+ </Text>
155
+ </div>
156
+ )}
157
+
158
+ <div className="multiple-quotation-docket__guests">
159
+ {adults !== undefined && (
160
+ <TextWithIcon icon="user" color="subtle">
161
+ {adults} Adults
162
+ </TextWithIcon>
163
+ )}
164
+ {children && children.length > 0 && (
165
+ <div className="multiple-quotation-docket__children">
166
+ {children.map((child, index) => (
167
+ <div key={index} className="multiple-quotation-docket__child">
168
+ <TextWithIcon icon="user" color="subtle">
169
+ <span>
170
+ <span>1 Child </span>
171
+ <span className="multiple-quotation-docket__child-age">
172
+ ({child.age} y.o)
173
+ </span>
174
+ </span>
175
+ </TextWithIcon>
176
+ {index < children.length - 1 && (
177
+ <div className="multiple-quotation-docket__divider" />
178
+ )}
179
+ </div>
180
+ ))}
181
+ </div>
182
+ )}
183
+ </div>
184
+ </div>
185
+ )}
186
+
187
+ {(roomType || mealPlan) && (
188
+ <div className="multiple-quotation-docket__room-info">
189
+ {roomType && (
190
+ <TextWithIcon icon="accom" color="subtle">
191
+ {roomType}
192
+ </TextWithIcon>
193
+ )}
194
+ {mealPlan && (
195
+ <div className="multiple-quotation-docket__meal-plan">
196
+ <TextWithIcon icon="utensils" color="subtle">
197
+ Meal-Plan
198
+ </TextWithIcon>
199
+ <div className="multiple-quotation-docket__divider" />
200
+ <Text variant="medium" size="sm" color="subtle">
201
+ {mealPlan}
202
+ </Text>
203
+ </div>
204
+ )}
205
+ </div>
206
+ )}
207
+
208
+ {details && details.length > 0 && (
209
+ <div className="multiple-quotation-docket__additional-details">
210
+ {details.map((detail, index) => (
211
+ <TextWithIcon key={index} icon={detail.icon} color="subtle">
212
+ {detail.label}: {detail.value}
213
+ </TextWithIcon>
214
+ ))}
215
+ </div>
216
+ )}
217
+ </div>
218
+ );
219
+ };
220
+
221
+ export const MultipleQuotationDocket: React.FC<MultipleQuotationDocketProps> = ({
222
+ title = 'Your quotation',
223
+ services,
224
+ totalPrices,
225
+ onMoreOptionsClick,
226
+ onAddNewQuoteClick,
227
+ onViewClick,
228
+ onSaveClick,
229
+ onBookNowClick,
230
+ className = '',
231
+ }) => {
232
+ return (
233
+ <CardContainer spacing="chill" className={`multiple-quotation-docket ${className}`}>
234
+ {/* Header */}
235
+ <div className="multiple-quotation-docket__header">
236
+ <div className="multiple-quotation-docket__title">
237
+ <Icon name="quotation" size="lg" />
238
+ <Heading
239
+ level={4}
240
+ variant="bold"
241
+ className="multiple-quotation-docket__title-text">
242
+ {title}
243
+ </Heading>
244
+ </div>
245
+ {onMoreOptionsClick && (
246
+ <Chip
247
+ type="outline"
248
+ color="neutral"
249
+ size="sm"
250
+ trailingIcon="chevron-down"
251
+ onClick={onMoreOptionsClick}
252
+ className="multiple-quotation-docket__more-options">
253
+ More options
254
+ </Chip>
255
+ )}
256
+ </div>
257
+
258
+ {/* Services List */}
259
+ <div className="multiple-quotation-docket__services">
260
+ {services.map((service, index) => (
261
+ <div key={index} className="multiple-quotation-docket__service">
262
+ <div className="multiple-quotation-docket__service-header">
263
+ <div className="multiple-quotation-docket__service-title">
264
+ <div className="multiple-quotation-docket__section-bar" />
265
+ <Icon
266
+ name={getServiceIcon(service.type)}
267
+ size="sm"
268
+ color="var(--color-icon-branded, #0f7173)"
269
+ />
270
+ <Text variant="bold" size="sm" color="accent">
271
+ {service.type}
272
+ </Text>
273
+ </div>
274
+ <Chip type="filled" color="accent" size="sm">
275
+ {service.currency} {service.price}
276
+ </Chip>
277
+ </div>
278
+ <DocketDetails data={service} />
279
+ </div>
280
+ ))}
281
+ </div>
282
+
283
+ {/* Total Section */}
284
+ {totalPrices.length > 0 && (
285
+ <div className="multiple-quotation-docket__total">
286
+ <div className="multiple-quotation-docket__total-line" />
287
+ <div className="multiple-quotation-docket__total-content">
288
+ <Text variant="bold" size="sm">
289
+ Total :
290
+ </Text>
291
+ <div className="multiple-quotation-docket__total-prices">
292
+ {totalPrices.map((total, index) => (
293
+ <Text key={index} variant="bold" size="sm">
294
+ {total.currency} {total.amount}
295
+ </Text>
296
+ ))}
297
+ </div>
298
+ </div>
299
+ <div className="multiple-quotation-docket__total-line" />
300
+ </div>
301
+ )}
302
+
303
+ {/* Actions */}
304
+ <div className="multiple-quotation-docket__actions">
305
+ {onAddNewQuoteClick && (
306
+ <Button
307
+ variant="outline-secondary"
308
+ size="sm"
309
+ leadingIcon="plus"
310
+ onClick={onAddNewQuoteClick}
311
+ className="multiple-quotation-docket__action-button">
312
+ Add new quote
313
+ </Button>
314
+ )}
315
+ <div className="multiple-quotation-docket__action-group">
316
+ {onViewClick && (
317
+ <Button
318
+ variant="outline-secondary"
319
+ size="sm"
320
+ onClick={onViewClick}
321
+ className="multiple-quotation-docket__action-button multiple-quotation-docket__action-button--flex">
322
+ View
323
+ </Button>
324
+ )}
325
+ {onSaveClick && (
326
+ <Button
327
+ variant="outline-secondary"
328
+ size="sm"
329
+ onClick={onSaveClick}
330
+ className="multiple-quotation-docket__action-button multiple-quotation-docket__action-button--flex">
331
+ Save
332
+ </Button>
333
+ )}
334
+ {onBookNowClick && (
335
+ <Button
336
+ variant="primary"
337
+ size="sm"
338
+ onClick={onBookNowClick}
339
+ className="multiple-quotation-docket__action-button multiple-quotation-docket__action-button--book">
340
+ Book now
341
+ </Button>
342
+ )}
343
+ </div>
344
+ </div>
345
+ </CardContainer>
346
+ );
347
+ };
348
+
349
+ export default MultipleQuotationDocket;
@@ -0,0 +1,6 @@
1
+ export { MultipleQuotationDocket, default } from './MultipleQuotationDocket';
2
+ export type {
3
+ DocketDetailsData,
4
+ DocketServiceType,
5
+ MultipleQuotationDocketProps,
6
+ } from './MultipleQuotationDocket';
@@ -0,0 +1,37 @@
1
+ .quote-header {
2
+ @apply w-full;
3
+ }
4
+
5
+ .quote-header__button {
6
+ width: 206px;
7
+ }
8
+
9
+ .quote-header__title {
10
+ @apply px-2 relative mb-10;
11
+ &::before {
12
+ content: '';
13
+ @apply absolute top-1/2 left-0 -translate-y-1/2;
14
+ @apply w-1 h-8;
15
+ background-color: var(--color-elevation-brand-subtle);
16
+ }
17
+ }
18
+
19
+ .quote-header__search-container {
20
+ @apply mt-12;
21
+ @apply flex justify-between;
22
+ > button {
23
+ @apply gap-x-2.5;
24
+ min-width: 129px;
25
+ }
26
+ }
27
+
28
+ .quote-header__search {
29
+ width: 364px;
30
+ }
31
+
32
+ .quote-header__filters {
33
+ @apply flex gap-3 my-8;
34
+ .dropdown-container {
35
+ width: 139px;
36
+ }
37
+ }