mautourco-components 0.2.5 → 0.2.8
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/README.md +190 -190
- package/dist/components/atoms/Avatar/Avatar.d.ts +14 -14
- package/dist/components/atoms/Avatar/Avatar.js +31 -31
- package/dist/components/atoms/Button/Button.css +320 -320
- package/dist/components/atoms/Button/Button.d.ts +27 -27
- package/dist/components/atoms/Button/Button.js +35 -35
- package/dist/components/atoms/Checkbox/Checkbox.d.ts +13 -13
- package/dist/components/atoms/Checkbox/Checkbox.js +39 -39
- package/dist/components/atoms/Icon/Icon.d.ts +10 -10
- package/dist/components/atoms/Icon/Icon.js +123 -123
- package/dist/components/atoms/Icon/icons/ArrivalIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/ArrivalIcon.js +31 -31
- package/dist/components/atoms/Icon/icons/BuildingIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/BuildingIcon.js +36 -36
- package/dist/components/atoms/Icon/icons/CalendarIcon.d.ts +12 -12
- package/dist/components/atoms/Icon/icons/CalendarIcon.js +41 -41
- package/dist/components/atoms/Icon/icons/CalendarOutlineIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/CalendarOutlineIcon.js +36 -36
- package/dist/components/atoms/Icon/icons/CarIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/CarIcon.js +30 -30
- package/dist/components/atoms/Icon/icons/Check.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/Check.js +30 -30
- package/dist/components/atoms/Icon/icons/CheckCircleIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/CheckCircleIcon.js +30 -30
- package/dist/components/atoms/Icon/icons/Chevron.d.ts +9 -9
- package/dist/components/atoms/Icon/icons/Chevron.js +54 -54
- package/dist/components/atoms/Icon/icons/ChevronDownIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/ChevronDownIcon.js +30 -30
- package/dist/components/atoms/Icon/icons/Close.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/Close.js +30 -30
- package/dist/components/atoms/Icon/icons/DeleteIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/DeleteIcon.js +30 -30
- package/dist/components/atoms/Icon/icons/DepartureIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/DepartureIcon.js +30 -30
- package/dist/components/atoms/Icon/icons/EyeIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/EyeIcon.js +30 -30
- package/dist/components/atoms/Icon/icons/FacebookIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/FacebookIcon.js +36 -36
- package/dist/components/atoms/Icon/icons/HomeIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/HomeIcon.js +25 -25
- package/dist/components/atoms/Icon/icons/InfoIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/InfoIcon.js +30 -30
- package/dist/components/atoms/Icon/icons/LinkedInIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/LinkedInIcon.js +36 -36
- package/dist/components/atoms/Icon/icons/MapPinIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/MapPinIcon.js +30 -30
- package/dist/components/atoms/Icon/icons/MautoucoLogo.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/MautoucoLogo.js +37 -37
- package/dist/components/atoms/Icon/icons/MenuIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/MenuIcon.js +37 -37
- package/dist/components/atoms/Icon/icons/MinusIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/MinusIcon.js +25 -25
- package/dist/components/atoms/Icon/icons/MoreIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/MoreIcon.js +30 -30
- package/dist/components/atoms/Icon/icons/PlaneIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/PlaneIcon.js +36 -36
- package/dist/components/atoms/Icon/icons/PlusIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/PlusIcon.js +25 -25
- package/dist/components/atoms/Icon/icons/Search.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/Search.js +30 -30
- package/dist/components/atoms/Icon/icons/Settings.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/Settings.js +30 -30
- package/dist/components/atoms/Icon/icons/ShipIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/ShipIcon.js +36 -36
- package/dist/components/atoms/Icon/icons/StrollerIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/StrollerIcon.js +30 -30
- package/dist/components/atoms/Icon/icons/TwitterIcon.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/TwitterIcon.js +36 -36
- package/dist/components/atoms/Icon/icons/User.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/User.js +30 -30
- package/dist/components/atoms/Icon/icons/UserIcon.d.ts +12 -12
- package/dist/components/atoms/Icon/icons/UserIcon.js +41 -41
- package/dist/components/atoms/Icon/icons/Youtube.d.ts +8 -8
- package/dist/components/atoms/Icon/icons/Youtube.js +36 -36
- package/dist/components/atoms/Illustration/Illustration.d.ts +14 -14
- package/dist/components/atoms/Illustration/Illustration.js +33 -33
- package/dist/components/atoms/Illustration/illustrations.d.ts +51 -51
- package/dist/components/atoms/Illustration/illustrations.js +97 -97
- package/dist/components/atoms/Inputs/DropdownInput/DropdownInput.d.ts +12 -12
- package/dist/components/atoms/Inputs/DropdownInput/DropdownInput.js +53 -53
- package/dist/components/atoms/Inputs/Input/Input.d.ts +15 -15
- package/dist/components/atoms/Inputs/Input/Input.js +27 -27
- package/dist/components/atoms/Inputs/Textarea/Textarea.d.ts +14 -14
- package/dist/components/atoms/Inputs/Textarea/Textarea.js +15 -15
- package/dist/components/atoms/Link/Link.d.ts +44 -44
- package/dist/components/atoms/Link/Link.js +76 -76
- package/dist/components/atoms/RatingStar/RatingStar.d.ts +40 -40
- package/dist/components/atoms/RatingStar/RatingStar.js +54 -54
- package/dist/components/atoms/SegmentedButton/SegmentedButton.d.ts +27 -27
- package/dist/components/atoms/SegmentedButton/SegmentedButton.js +49 -49
- package/dist/components/atoms/SelectedValue/SelectedValue.d.ts +11 -11
- package/dist/components/atoms/SelectedValue/SelectedValue.js +29 -29
- package/dist/components/atoms/Slider/Slider.d.ts +52 -52
- package/dist/components/atoms/Slider/Slider.js +30 -30
- package/dist/components/atoms/Spinner/Spinner.d.ts +9 -9
- package/dist/components/atoms/Spinner/Spinner.js +38 -38
- package/dist/components/atoms/Spinner/variants/ButtonSpinner.d.ts +8 -8
- package/dist/components/atoms/Spinner/variants/ButtonSpinner.js +19 -19
- package/dist/components/atoms/Spinner/variants/LoadingSpinner.d.ts +7 -7
- package/dist/components/atoms/Spinner/variants/LoadingSpinner.js +7 -7
- package/dist/components/atoms/Tab/Tab.css +266 -266
- package/dist/components/atoms/Tab/Tab.d.ts +22 -22
- package/dist/components/atoms/Tab/Tab.js +54 -54
- package/dist/components/atoms/Typography/Typography.d.ts +26 -24
- package/dist/components/atoms/Typography/Typography.js +109 -100
- package/dist/components/molecules/Calendar/CalendarInput.d.ts +34 -34
- package/dist/components/molecules/Calendar/CalendarInput.js +49 -49
- package/dist/components/molecules/Calendar/DateTime.d.ts +25 -25
- package/dist/components/molecules/Calendar/DateTime.js +106 -106
- package/dist/components/molecules/Calendar/TimePicker.d.ts +16 -16
- package/dist/components/molecules/Calendar/TimePicker.js +91 -91
- package/dist/components/molecules/LocationDropdown/LocationDropdown.d.ts +34 -34
- package/dist/components/molecules/LocationDropdown/LocationDropdown.js +120 -120
- package/dist/components/molecules/LocationDropdown/index.d.ts +2 -2
- package/dist/components/molecules/LocationDropdown/index.js +1 -1
- package/dist/components/molecules/MultiSelectDropdown/MultiSelectDropdown.d.ts +29 -29
- package/dist/components/molecules/MultiSelectDropdown/MultiSelectDropdown.js +106 -106
- package/dist/components/molecules/RatingTab/RatingTab.d.ts +39 -39
- package/dist/components/molecules/RatingTab/RatingTab.js +41 -41
- package/dist/components/molecules/TabGroup/TabGroup.d.ts +17 -17
- package/dist/components/molecules/TabGroup/TabGroup.js +30 -30
- package/dist/components/molecules/UserCard/UserCard.d.ts +20 -20
- package/dist/components/molecules/UserCard/UserCard.js +57 -57
- package/dist/components/organisms/CardContainer/CardContainer.d.ts +37 -37
- package/dist/components/organisms/CardContainer/CardContainer.js +27 -27
- package/dist/components/organisms/DateTimePicker/DateTimePicker.d.ts +15 -15
- package/dist/components/organisms/DateTimePicker/DateTimePicker.js +66 -66
- package/dist/components/organisms/Dialog/Dialog.d.ts +103 -103
- package/dist/components/organisms/Dialog/Dialog.js +162 -162
- package/dist/components/organisms/Footer/Footer.d.ts +38 -38
- package/dist/components/organisms/Footer/Footer.js +74 -74
- package/dist/components/organisms/PaxSelector/PaxSelector.d.ts +63 -63
- package/dist/components/organisms/PaxSelector/PaxSelector.js +402 -402
- package/dist/components/organisms/RoundTrip/RoundTrip.d.ts +54 -54
- package/dist/components/organisms/RoundTrip/RoundTrip.js +179 -179
- package/dist/components/organisms/RoundTrip/index.d.ts +2 -2
- package/dist/components/organisms/RoundTrip/index.js +1 -1
- package/dist/components/organisms/SearchBarTransfer/SearchBarTransfer.d.ts +35 -35
- package/dist/components/organisms/SearchBarTransfer/SearchBarTransfer.js +192 -192
- package/dist/components/organisms/SearchBarTransfer/index.d.ts +2 -2
- package/dist/components/organisms/SearchBarTransfer/index.js +1 -1
- package/dist/components/organisms/TopNavigation/DesktopNav.d.ts +33 -33
- package/dist/components/organisms/TopNavigation/DesktopNav.js +32 -32
- package/dist/components/organisms/TopNavigation/MobileNav.d.ts +32 -32
- package/dist/components/organisms/TopNavigation/MobileNav.js +45 -45
- package/dist/components/organisms/TopNavigation/TopNavigation.d.ts +33 -33
- package/dist/components/organisms/TopNavigation/TopNavigation.js +20 -20
- package/dist/components/organisms/TransferLine/TransferLine.d.ts +53 -53
- package/dist/components/organisms/TransferLine/TransferLine.js +179 -179
- package/dist/components/ui/button.d.ts +10 -10
- package/dist/components/ui/button.js +56 -56
- package/dist/components/ui/calendar.d.ts +8 -8
- package/dist/components/ui/calendar.js +87 -87
- package/dist/components/ui/popover.d.ts +7 -7
- package/dist/components/ui/popover.js +42 -42
- package/dist/hooks/useMobile.d.ts +5 -5
- package/dist/hooks/useMobile.js +26 -26
- package/dist/index.d.ts +49 -49
- package/dist/index.js +46 -46
- package/dist/lib/utils.d.ts +7 -7
- package/dist/lib/utils.js +13 -13
- package/dist/styles/components/avatar.css +122 -122
- package/dist/styles/components/calendar.css +140 -140
- package/dist/styles/components/checkbox.css +206 -206
- package/dist/styles/components/dropdown.css +269 -269
- package/dist/styles/components/forms.css +209 -209
- package/dist/styles/components/illustration.css +123 -123
- package/dist/styles/components/molecule/calendarInput.css +133 -133
- package/dist/styles/components/molecule/dateTime.css +126 -126
- package/dist/styles/components/molecule/location-dropdown.css +132 -132
- package/dist/styles/components/molecule/timePicker.css +122 -122
- package/dist/styles/components/multiselect-dropdown.css +286 -286
- package/dist/styles/components/organism/card-container.css +148 -148
- package/dist/styles/components/organism/dialog.css +168 -168
- package/dist/styles/components/organism/footer.css +119 -119
- package/dist/styles/components/organism/pax-selector.css +605 -617
- package/dist/styles/components/organism/round-trip.css +139 -139
- package/dist/styles/components/organism/search-bar-transfer.css +158 -167
- package/dist/styles/components/organism/topnavigation.css +142 -142
- package/dist/styles/components/organism/transfer-line.css +138 -138
- package/dist/styles/components/rating-star.css +145 -145
- package/dist/styles/components/rating-tab.css +178 -180
- package/dist/styles/components/scrollbar.css +155 -155
- package/dist/styles/components/segmented-button.css +214 -214
- package/dist/styles/components/selected-value.css +175 -175
- package/dist/styles/components/slider.css +182 -182
- package/dist/styles/components/typography.css +245 -245
- package/dist/styles/tokens/tokens.css +119 -119
- package/dist/styles/tokens/tokens.d.ts +3108 -3108
- package/dist/styles/tokens/tokens.js +2652 -2652
- package/package.json +103 -103
- package/src/components/atoms/Avatar/Avatar.tsx +60 -60
- package/src/components/atoms/Button/Button.css +200 -200
- package/src/components/atoms/Button/Button.tsx +82 -82
- package/src/components/atoms/Checkbox/Checkbox.tsx +83 -83
- package/src/components/atoms/Icon/Icon.tsx +163 -163
- package/src/components/atoms/Icon/icons/ArrivalIcon.tsx +52 -52
- package/src/components/atoms/Icon/icons/BuildingIcon.tsx +50 -50
- package/src/components/atoms/Icon/icons/CalendarIcon.tsx +63 -63
- package/src/components/atoms/Icon/icons/CalendarOutlineIcon.tsx +50 -50
- package/src/components/atoms/Icon/icons/CarIcon.tsx +44 -44
- package/src/components/atoms/Icon/icons/Check.tsx +36 -36
- package/src/components/atoms/Icon/icons/CheckCircleIcon.tsx +48 -48
- package/src/components/atoms/Icon/icons/Chevron.tsx +73 -73
- package/src/components/atoms/Icon/icons/ChevronDownIcon.tsx +46 -46
- package/src/components/atoms/Icon/icons/Close.tsx +39 -39
- package/src/components/atoms/Icon/icons/DeleteIcon.tsx +44 -44
- package/src/components/atoms/Icon/icons/DepartureIcon.tsx +50 -50
- package/src/components/atoms/Icon/icons/EyeIcon.tsx +44 -44
- package/src/components/atoms/Icon/icons/FacebookIcon.tsx +50 -50
- package/src/components/atoms/Icon/icons/HomeIcon.tsx +52 -52
- package/src/components/atoms/Icon/icons/InfoIcon.tsx +44 -44
- package/src/components/atoms/Icon/icons/LinkedInIcon.tsx +50 -50
- package/src/components/atoms/Icon/icons/MapPinIcon.tsx +44 -44
- package/src/components/atoms/Icon/icons/MautoucoLogo.tsx +93 -93
- package/src/components/atoms/Icon/icons/MenuIcon.tsx +49 -49
- package/src/components/atoms/Icon/icons/MinusIcon.tsx +45 -45
- package/src/components/atoms/Icon/icons/MoreIcon.tsx +44 -44
- package/src/components/atoms/Icon/icons/PlaneIcon.tsx +50 -50
- package/src/components/atoms/Icon/icons/PlusIcon.tsx +45 -45
- package/src/components/atoms/Icon/icons/Search.tsx +37 -37
- package/src/components/atoms/Icon/icons/Settings.tsx +38 -38
- package/src/components/atoms/Icon/icons/ShipIcon.tsx +50 -50
- package/src/components/atoms/Icon/icons/StrollerIcon.tsx +44 -44
- package/src/components/atoms/Icon/icons/TwitterIcon.tsx +50 -50
- package/src/components/atoms/Icon/icons/User.tsx +37 -37
- package/src/components/atoms/Icon/icons/UserIcon.tsx +63 -63
- package/src/components/atoms/Icon/icons/Youtube.tsx +50 -50
- package/src/components/atoms/Illustration/Illustration.tsx +28 -28
- package/src/components/atoms/Illustration/illustrations.ts +116 -116
- package/src/components/atoms/Inputs/DropdownInput/DropdownInput.tsx +96 -96
- package/src/components/atoms/Inputs/Textarea/Textarea.tsx +51 -51
- package/src/components/atoms/Link/Link.tsx +168 -168
- package/src/components/atoms/RatingStar/RatingStar.tsx +114 -114
- package/src/components/atoms/SegmentedButton/SegmentedButton.tsx +94 -94
- package/src/components/atoms/SelectedValue/SelectedValue.tsx +59 -59
- package/src/components/atoms/Slider/Slider.tsx +95 -95
- package/src/components/atoms/Spinner/Spinner.tsx +56 -56
- package/src/components/atoms/Spinner/variants/ButtonSpinner.tsx +37 -37
- package/src/components/atoms/Spinner/variants/LoadingSpinner.tsx +22 -22
- package/src/components/atoms/Tab/Tab.css +147 -147
- package/src/components/atoms/Tab/Tab.tsx +96 -96
- package/src/components/atoms/Typography/Typography.tsx +180 -153
- package/src/components/molecules/Calendar/CalendarInput.tsx +135 -135
- package/src/components/molecules/Calendar/DateTime.tsx +172 -172
- package/src/components/molecules/Calendar/TimePicker.tsx +174 -174
- package/src/components/molecules/LocationDropdown/LocationDropdown.tsx +234 -234
- package/src/components/molecules/LocationDropdown/index.ts +2 -2
- package/src/components/molecules/RatingTab/RatingTab.tsx +96 -96
- package/src/components/molecules/TabGroup/TabGroup.tsx +60 -60
- package/src/components/molecules/UserCard/UserCard.stories.tsx +36 -36
- package/src/components/molecules/UserCard/UserCard.tsx +173 -173
- package/src/components/organisms/CardContainer/CardContainer.tsx +66 -66
- package/src/components/organisms/DateTimePicker/DateTimePicker.tsx +110 -110
- package/src/components/organisms/Dialog/Dialog.tsx +352 -352
- package/src/components/organisms/Footer/Footer.tsx +290 -290
- package/src/components/organisms/PaxSelector/PaxSelector.tsx +979 -979
- package/src/components/organisms/RoundTrip/RoundTrip.tsx +335 -335
- package/src/components/organisms/RoundTrip/index.ts +2 -2
- package/src/components/organisms/SearchBarTransfer/SearchBarTransfer.tsx +388 -388
- package/src/components/organisms/SearchBarTransfer/index.ts +2 -2
- package/src/components/organisms/TopNavigation/DesktopNav.tsx +133 -133
- package/src/components/organisms/TopNavigation/MobileNav.tsx +212 -212
- package/src/components/organisms/TopNavigation/TopNavigation.tsx +45 -45
- package/src/components/organisms/TransferLine/TransferLine.tsx +369 -369
- package/src/components/ui/button.tsx +60 -60
- package/src/components/ui/calendar.tsx +246 -246
- package/src/components/ui/popover.tsx +46 -46
- package/src/styles/components/avatar.css +58 -58
- package/src/styles/components/calendar.css +85 -85
- package/src/styles/components/checkbox.css +130 -130
- package/src/styles/components/dropdown.css +214 -214
- package/src/styles/components/forms.css +147 -147
- package/src/styles/components/illustration.css +7 -7
- package/src/styles/components/molecule/calendarInput.css +156 -156
- package/src/styles/components/molecule/dateTime.css +14 -14
- package/src/styles/components/molecule/location-dropdown.css +204 -204
- package/src/styles/components/molecule/timePicker.css +78 -78
- package/src/styles/components/multiselect-dropdown.css +230 -230
- package/src/styles/components/organism/card-container.css +49 -49
- package/src/styles/components/organism/dialog.css +241 -241
- package/src/styles/components/organism/footer.css +113 -113
- package/src/styles/components/organism/pax-selector.css +690 -702
- package/src/styles/components/organism/round-trip.css +55 -55
- package/src/styles/components/organism/search-bar-transfer.css +122 -127
- package/src/styles/components/organism/topnavigation.css +161 -161
- package/src/styles/components/organism/transfer-line.css +86 -86
- package/src/styles/components/rating-star.css +39 -39
- package/src/styles/components/rating-tab.css +81 -83
- package/src/styles/components/scrollbar.css +63 -63
- package/src/styles/components/segmented-button.css +134 -134
- package/src/styles/components/selected-value.css +80 -80
- package/src/styles/components/slider.css +86 -86
- package/src/styles/components/typography.css +251 -251
- package/src/styles/fonts.css +50 -0
- package/src/styles/tokens/tokens.css +119 -119
- package/src/styles/tokens/tokens.js +12 -6
|
@@ -1,388 +1,388 @@
|
|
|
1
|
-
import React, { useState, useEffect } from "react";
|
|
2
|
-
import RoundTrip, { RoundTripData } from "../RoundTrip/RoundTrip";
|
|
3
|
-
import TransferLine, {
|
|
4
|
-
TransferLineData,
|
|
5
|
-
TransferType,
|
|
6
|
-
} from "../TransferLine/TransferLine";
|
|
7
|
-
import Button from "../../atoms/Button/Button";
|
|
8
|
-
import Checkbox from "../../atoms/Checkbox/Checkbox";
|
|
9
|
-
import { Text, Heading } from "../../atoms/Typography/Typography";
|
|
10
|
-
import { LocationOption, LocationGroup } from "../../molecules/LocationDropdown/LocationDropdown";
|
|
11
|
-
import Icon, { IconName } from "../../atoms/Icon/Icon";
|
|
12
|
-
import SegmentedButton, { SegmentedButtonOption } from "../../atoms/SegmentedButton/SegmentedButton";
|
|
13
|
-
import "../../../styles/components/organism/search-bar-transfer.css";
|
|
14
|
-
|
|
15
|
-
export type TransferMode = "roundtrip" | "custom";
|
|
16
|
-
|
|
17
|
-
export interface SearchBarTransferData {
|
|
18
|
-
mode: TransferMode;
|
|
19
|
-
sameVehicle: boolean;
|
|
20
|
-
roundTripData?: RoundTripData;
|
|
21
|
-
transferLines?: TransferLineData[];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface SearchBarTransferProps {
|
|
25
|
-
/** Initial mode */
|
|
26
|
-
mode?: TransferMode;
|
|
27
|
-
/** Location options for dropdowns */
|
|
28
|
-
locations?: {
|
|
29
|
-
options?: LocationOption[];
|
|
30
|
-
groups?: LocationGroup[];
|
|
31
|
-
};
|
|
32
|
-
/** Default round trip data (for roundtrip mode) */
|
|
33
|
-
defaultRoundTripData?: RoundTripData;
|
|
34
|
-
/** Default transfer lines (for custom mode) */
|
|
35
|
-
defaultTransferLines?: TransferLineData[];
|
|
36
|
-
/** Default "same vehicle" checkbox state */
|
|
37
|
-
defaultSameVehicle?: boolean;
|
|
38
|
-
/** Callback when search button is clicked */
|
|
39
|
-
onSearch?: (data: SearchBarTransferData) => void;
|
|
40
|
-
/** Callback when data changes */
|
|
41
|
-
onChange?: (data: SearchBarTransferData) => void;
|
|
42
|
-
/** Additional CSS classes */
|
|
43
|
-
className?: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
let transferIdCounter = 0;
|
|
47
|
-
|
|
48
|
-
const SearchBarTransfer: React.FC<SearchBarTransferProps> = ({
|
|
49
|
-
mode: initialMode = "roundtrip",
|
|
50
|
-
locations = { options: [], groups: [] },
|
|
51
|
-
defaultRoundTripData,
|
|
52
|
-
defaultTransferLines,
|
|
53
|
-
defaultSameVehicle = false,
|
|
54
|
-
onSearch,
|
|
55
|
-
onChange,
|
|
56
|
-
className = "",
|
|
57
|
-
}) => {
|
|
58
|
-
// Generate unique ID for transfer lines
|
|
59
|
-
const generateTransferId = () => {
|
|
60
|
-
transferIdCounter += 1;
|
|
61
|
-
return `transfer-${transferIdCounter}-${Date.now()}`;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// Ensure default transfer lines have IDs
|
|
65
|
-
const initializeTransferLines = (lines?: TransferLineData[]): TransferLineData[] => {
|
|
66
|
-
if (!lines) return [];
|
|
67
|
-
return lines.map((line) => ({
|
|
68
|
-
...line,
|
|
69
|
-
id: line.id || generateTransferId(),
|
|
70
|
-
}));
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const [mode, setMode] = useState<TransferMode>(initialMode);
|
|
74
|
-
const [sameVehicle, setSameVehicle] = useState(defaultSameVehicle);
|
|
75
|
-
const [roundTripData, setRoundTripData] = useState<RoundTripData | undefined>(defaultRoundTripData);
|
|
76
|
-
const [transferLines, setTransferLines] = useState<TransferLineData[]>(
|
|
77
|
-
initializeTransferLines(defaultTransferLines)
|
|
78
|
-
);
|
|
79
|
-
const [error, setError] = useState<string | null>(null);
|
|
80
|
-
|
|
81
|
-
// Notify parent of changes
|
|
82
|
-
useEffect(() => {
|
|
83
|
-
const data: SearchBarTransferData = {
|
|
84
|
-
mode,
|
|
85
|
-
sameVehicle,
|
|
86
|
-
roundTripData: mode === "roundtrip" ? roundTripData : undefined,
|
|
87
|
-
transferLines: mode === "custom" ? transferLines : undefined,
|
|
88
|
-
};
|
|
89
|
-
onChange?.(data);
|
|
90
|
-
}, [mode, sameVehicle, roundTripData, transferLines, onChange]);
|
|
91
|
-
|
|
92
|
-
// Mode options for SegmentedButton
|
|
93
|
-
const modeOptions: SegmentedButtonOption[] = [
|
|
94
|
-
{ value: "roundtrip", label: "Round trip" },
|
|
95
|
-
{ value: "custom", label: "Custom transfer" },
|
|
96
|
-
];
|
|
97
|
-
|
|
98
|
-
// Handle mode change
|
|
99
|
-
const handleModeChange = (newMode: string) => {
|
|
100
|
-
const transferMode = newMode as TransferMode;
|
|
101
|
-
if (transferMode === mode) return;
|
|
102
|
-
|
|
103
|
-
if (transferMode === "custom" && mode === "roundtrip" && roundTripData) {
|
|
104
|
-
// Parse roundtrip to two transfer lines
|
|
105
|
-
const arrivalTransfer: TransferLineData = {
|
|
106
|
-
id: generateTransferId(),
|
|
107
|
-
type: "arrival",
|
|
108
|
-
paxData: roundTripData.paxData,
|
|
109
|
-
transferDate: roundTripData.arrivalDate,
|
|
110
|
-
pickupPoint: roundTripData.pickupDropoffPoint,
|
|
111
|
-
dropoffPoint: roundTripData.accommodation,
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const departureTransfer: TransferLineData = {
|
|
115
|
-
id: generateTransferId(),
|
|
116
|
-
type: "departure",
|
|
117
|
-
paxData: roundTripData.paxData,
|
|
118
|
-
transferDate: roundTripData.departureDate,
|
|
119
|
-
pickupPoint: roundTripData.accommodation,
|
|
120
|
-
dropoffPoint: roundTripData.pickupDropoffPoint,
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
setTransferLines([arrivalTransfer, departureTransfer]);
|
|
124
|
-
setRoundTripData(undefined);
|
|
125
|
-
} else if (transferMode === "roundtrip" && mode === "custom") {
|
|
126
|
-
// Reset everything when switching to roundtrip
|
|
127
|
-
setTransferLines([]);
|
|
128
|
-
setRoundTripData(undefined);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
setMode(transferMode);
|
|
132
|
-
setError(null);
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
// Handle adding transfer lines
|
|
136
|
-
const handleAddTransfer = (type: TransferType) => {
|
|
137
|
-
const newTransfer: TransferLineData = {
|
|
138
|
-
id: generateTransferId(),
|
|
139
|
-
type,
|
|
140
|
-
};
|
|
141
|
-
setTransferLines([...transferLines, newTransfer]);
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
// Handle transfer line data change
|
|
145
|
-
const handleTransferLineChange = (id: string, data: TransferLineData) => {
|
|
146
|
-
setTransferLines((prevLines) =>
|
|
147
|
-
prevLines.map((line) => (line.id === id ? data : line))
|
|
148
|
-
);
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
// Handle transfer line deletion
|
|
152
|
-
const handleDeleteTransferLine = (id: string) => {
|
|
153
|
-
setTransferLines((prevLines) => prevLines.filter((line) => line.id !== id));
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// Validate data
|
|
157
|
-
const validateData = (): boolean => {
|
|
158
|
-
if (mode === "roundtrip") {
|
|
159
|
-
if (!roundTripData) {
|
|
160
|
-
setError("Please fill in all the transfer details.");
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
// Check if required fields are filled
|
|
164
|
-
if (
|
|
165
|
-
!roundTripData.paxData ||
|
|
166
|
-
!roundTripData.arrivalDate ||
|
|
167
|
-
!roundTripData.departureDate ||
|
|
168
|
-
!roundTripData.pickupDropoffPoint ||
|
|
169
|
-
!roundTripData.accommodation
|
|
170
|
-
) {
|
|
171
|
-
setError("Please fill in all the transfer details.");
|
|
172
|
-
return false;
|
|
173
|
-
}
|
|
174
|
-
} else {
|
|
175
|
-
if (transferLines.length === 0) {
|
|
176
|
-
setError("Please add at least one transfer.");
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
// Check if all transfer lines have required data
|
|
180
|
-
for (const line of transferLines) {
|
|
181
|
-
if (
|
|
182
|
-
!line.paxData ||
|
|
183
|
-
!line.transferDate ||
|
|
184
|
-
!line.pickupPoint ||
|
|
185
|
-
!line.dropoffPoint
|
|
186
|
-
) {
|
|
187
|
-
setError("Please fill in all the transfer details.");
|
|
188
|
-
return false;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
setError(null);
|
|
193
|
-
return true;
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
// Handle search
|
|
197
|
-
const handleSearch = () => {
|
|
198
|
-
if (validateData()) {
|
|
199
|
-
const data: SearchBarTransferData = {
|
|
200
|
-
mode,
|
|
201
|
-
sameVehicle,
|
|
202
|
-
roundTripData: mode === "roundtrip" ? roundTripData : undefined,
|
|
203
|
-
transferLines: mode === "custom" ? transferLines : undefined,
|
|
204
|
-
};
|
|
205
|
-
onSearch?.(data);
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
return (
|
|
210
|
-
<div className={`search-bar-transfer ${className}`}>
|
|
211
|
-
{/* Header with title and mode selector */}
|
|
212
|
-
<div className="search-bar-transfer__header">
|
|
213
|
-
<Heading level={
|
|
214
|
-
Select your transfer details
|
|
215
|
-
</Heading>
|
|
216
|
-
|
|
217
|
-
{/* Segmented Button for mode selection */}
|
|
218
|
-
<div className="search-bar-transfer__mode-selector">
|
|
219
|
-
<SegmentedButton
|
|
220
|
-
options={modeOptions}
|
|
221
|
-
value={mode}
|
|
222
|
-
onChange={handleModeChange}
|
|
223
|
-
name="transfer-mode"
|
|
224
|
-
/>
|
|
225
|
-
</div>
|
|
226
|
-
</div>
|
|
227
|
-
|
|
228
|
-
{/* Content based on mode */}
|
|
229
|
-
{mode === "roundtrip" ? (
|
|
230
|
-
<RoundTrip
|
|
231
|
-
id="roundtrip-main"
|
|
232
|
-
locations={locations}
|
|
233
|
-
paxData={roundTripData?.paxData}
|
|
234
|
-
arrivalDate={roundTripData?.arrivalDate}
|
|
235
|
-
departureDate={roundTripData?.departureDate}
|
|
236
|
-
pickupDropoffPoint={roundTripData?.pickupDropoffPoint?.id as string}
|
|
237
|
-
accommodation={roundTripData?.accommodation?.id as string}
|
|
238
|
-
onChange={setRoundTripData}
|
|
239
|
-
/>
|
|
240
|
-
) : (
|
|
241
|
-
<>
|
|
242
|
-
{/* Transfer type selector */}
|
|
243
|
-
<div className="search-bar-transfer__transfer-type">
|
|
244
|
-
<Text size="lg" variant="bold" as="div" className="search-bar-transfer__transfer-type-label">
|
|
245
|
-
Select a transfer type you want to add
|
|
246
|
-
</Text>
|
|
247
|
-
<div className="search-bar-transfer__add-buttons">
|
|
248
|
-
<Button
|
|
249
|
-
variant="outline-secondary"
|
|
250
|
-
size="sm"
|
|
251
|
-
leadingIcon="plus"
|
|
252
|
-
onClick={() => handleAddTransfer("arrival")}
|
|
253
|
-
>
|
|
254
|
-
Add Arrival
|
|
255
|
-
</Button>
|
|
256
|
-
<Button
|
|
257
|
-
variant="outline-secondary"
|
|
258
|
-
size="sm"
|
|
259
|
-
leadingIcon="plus"
|
|
260
|
-
onClick={() => handleAddTransfer("departure")}
|
|
261
|
-
>
|
|
262
|
-
Add Departure
|
|
263
|
-
</Button>
|
|
264
|
-
<Button
|
|
265
|
-
variant="outline-secondary"
|
|
266
|
-
size="sm"
|
|
267
|
-
leadingIcon="plus"
|
|
268
|
-
onClick={() => handleAddTransfer("inter-hotel")}
|
|
269
|
-
>
|
|
270
|
-
Add Inter-Hotel
|
|
271
|
-
</Button>
|
|
272
|
-
</div>
|
|
273
|
-
</div>
|
|
274
|
-
|
|
275
|
-
{/* Transfer lines list */}
|
|
276
|
-
{transferLines.length > 0 && (
|
|
277
|
-
<div className="search-bar-transfer__transfer-lines">
|
|
278
|
-
{(() => {
|
|
279
|
-
// Group transfers by type
|
|
280
|
-
const groupedTransfers: { [key in TransferType]: TransferLineData[] } = {
|
|
281
|
-
arrival: [],
|
|
282
|
-
departure: [],
|
|
283
|
-
"inter-hotel": [],
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
transferLines.forEach((line) => {
|
|
287
|
-
groupedTransfers[line.type].push(line);
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
// Get the order of non-empty groups
|
|
291
|
-
const typeOrder: TransferType[] = ["arrival", "inter-hotel", "departure"];
|
|
292
|
-
const nonEmptyGroups = typeOrder.filter((type) => groupedTransfers[type].length > 0);
|
|
293
|
-
|
|
294
|
-
// Category labels and icons
|
|
295
|
-
const categoryInfo: { [key in TransferType]: { label: string; icon: IconName } } = {
|
|
296
|
-
arrival: { label: "Arrival", icon: "arrival" },
|
|
297
|
-
departure: { label: "Departure", icon: "departure" },
|
|
298
|
-
"inter-hotel": { label: "Inter-Hotel", icon: "building" },
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
return nonEmptyGroups.map((type, groupIndex) => (
|
|
302
|
-
<React.Fragment key={type}>
|
|
303
|
-
{/* Category header */}
|
|
304
|
-
<div className="search-bar-transfer__category-header">
|
|
305
|
-
<Icon name={categoryInfo[type].icon} size="md" />
|
|
306
|
-
<Text size="md" variant="bold" as="span">
|
|
307
|
-
{categoryInfo[type].label}
|
|
308
|
-
</Text>
|
|
309
|
-
</div>
|
|
310
|
-
|
|
311
|
-
{/* Transfer lines in this category */}
|
|
312
|
-
{groupedTransfers[type].map((line) => (
|
|
313
|
-
<TransferLine
|
|
314
|
-
key={line.id}
|
|
315
|
-
id={line.id}
|
|
316
|
-
type={line.type}
|
|
317
|
-
paxData={line.paxData}
|
|
318
|
-
transferDate={line.transferDate}
|
|
319
|
-
pickupPoint={line.pickupPoint?.id}
|
|
320
|
-
dropoffPoint={line.dropoffPoint?.id}
|
|
321
|
-
locations={locations}
|
|
322
|
-
onDataChange={(data) => handleTransferLineChange(line.id, data)}
|
|
323
|
-
onDelete={() => handleDeleteTransferLine(line.id)}
|
|
324
|
-
showDelete={transferLines.length > 1}
|
|
325
|
-
/>
|
|
326
|
-
))}
|
|
327
|
-
|
|
328
|
-
{/* Show separator between categories, but not after the last one */}
|
|
329
|
-
{groupIndex < nonEmptyGroups.length - 1 && (
|
|
330
|
-
<svg
|
|
331
|
-
className="search-bar-transfer__divider"
|
|
332
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
333
|
-
width="100%"
|
|
334
|
-
height="1"
|
|
335
|
-
viewBox="0 0 1076 1"
|
|
336
|
-
fill="none"
|
|
337
|
-
preserveAspectRatio="none"
|
|
338
|
-
>
|
|
339
|
-
<path
|
|
340
|
-
d="M0 0.5L1076 0.499906"
|
|
341
|
-
stroke="var(--color-border-medium, #A3A3A3)"
|
|
342
|
-
strokeWidth="1"
|
|
343
|
-
strokeDasharray="10 10"
|
|
344
|
-
/>
|
|
345
|
-
</svg>
|
|
346
|
-
)}
|
|
347
|
-
</React.Fragment>
|
|
348
|
-
));
|
|
349
|
-
})()}
|
|
350
|
-
</div>
|
|
351
|
-
)}
|
|
352
|
-
</>
|
|
353
|
-
)}
|
|
354
|
-
|
|
355
|
-
{/* Bottom actions */}
|
|
356
|
-
<div className="search-bar-transfer__actions">
|
|
357
|
-
<Checkbox
|
|
358
|
-
checked={sameVehicle}
|
|
359
|
-
onChange={setSameVehicle}
|
|
360
|
-
label="Use the same vehicle for all your transfers"
|
|
361
|
-
/>
|
|
362
|
-
|
|
363
|
-
<div className="search-bar-transfer__cta">
|
|
364
|
-
{error && (
|
|
365
|
-
<div className="search-bar-transfer__error">
|
|
366
|
-
<div className="search-bar-transfer__error-bar" />
|
|
367
|
-
<div className="search-bar-transfer__error-content">
|
|
368
|
-
<Icon name="info" size="md" className="search-bar-transfer__error-icon" />
|
|
369
|
-
<Text size="sm" variant="bold" className="search-bar-transfer__error-text">
|
|
370
|
-
{error}
|
|
371
|
-
</Text>
|
|
372
|
-
</div>
|
|
373
|
-
</div>
|
|
374
|
-
)}
|
|
375
|
-
<Button
|
|
376
|
-
variant="primary"
|
|
377
|
-
size="lg"
|
|
378
|
-
onClick={handleSearch}
|
|
379
|
-
>
|
|
380
|
-
Search
|
|
381
|
-
</Button>
|
|
382
|
-
</div>
|
|
383
|
-
</div>
|
|
384
|
-
</div>
|
|
385
|
-
);
|
|
386
|
-
};
|
|
387
|
-
|
|
388
|
-
export default SearchBarTransfer;
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
|
2
|
+
import RoundTrip, { RoundTripData } from "../RoundTrip/RoundTrip";
|
|
3
|
+
import TransferLine, {
|
|
4
|
+
TransferLineData,
|
|
5
|
+
TransferType,
|
|
6
|
+
} from "../TransferLine/TransferLine";
|
|
7
|
+
import Button from "../../atoms/Button/Button";
|
|
8
|
+
import Checkbox from "../../atoms/Checkbox/Checkbox";
|
|
9
|
+
import { Text, Heading } from "../../atoms/Typography/Typography";
|
|
10
|
+
import { LocationOption, LocationGroup } from "../../molecules/LocationDropdown/LocationDropdown";
|
|
11
|
+
import Icon, { IconName } from "../../atoms/Icon/Icon";
|
|
12
|
+
import SegmentedButton, { SegmentedButtonOption } from "../../atoms/SegmentedButton/SegmentedButton";
|
|
13
|
+
import "../../../styles/components/organism/search-bar-transfer.css";
|
|
14
|
+
|
|
15
|
+
export type TransferMode = "roundtrip" | "custom";
|
|
16
|
+
|
|
17
|
+
export interface SearchBarTransferData {
|
|
18
|
+
mode: TransferMode;
|
|
19
|
+
sameVehicle: boolean;
|
|
20
|
+
roundTripData?: RoundTripData;
|
|
21
|
+
transferLines?: TransferLineData[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface SearchBarTransferProps {
|
|
25
|
+
/** Initial mode */
|
|
26
|
+
mode?: TransferMode;
|
|
27
|
+
/** Location options for dropdowns */
|
|
28
|
+
locations?: {
|
|
29
|
+
options?: LocationOption[];
|
|
30
|
+
groups?: LocationGroup[];
|
|
31
|
+
};
|
|
32
|
+
/** Default round trip data (for roundtrip mode) */
|
|
33
|
+
defaultRoundTripData?: RoundTripData;
|
|
34
|
+
/** Default transfer lines (for custom mode) */
|
|
35
|
+
defaultTransferLines?: TransferLineData[];
|
|
36
|
+
/** Default "same vehicle" checkbox state */
|
|
37
|
+
defaultSameVehicle?: boolean;
|
|
38
|
+
/** Callback when search button is clicked */
|
|
39
|
+
onSearch?: (data: SearchBarTransferData) => void;
|
|
40
|
+
/** Callback when data changes */
|
|
41
|
+
onChange?: (data: SearchBarTransferData) => void;
|
|
42
|
+
/** Additional CSS classes */
|
|
43
|
+
className?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let transferIdCounter = 0;
|
|
47
|
+
|
|
48
|
+
const SearchBarTransfer: React.FC<SearchBarTransferProps> = ({
|
|
49
|
+
mode: initialMode = "roundtrip",
|
|
50
|
+
locations = { options: [], groups: [] },
|
|
51
|
+
defaultRoundTripData,
|
|
52
|
+
defaultTransferLines,
|
|
53
|
+
defaultSameVehicle = false,
|
|
54
|
+
onSearch,
|
|
55
|
+
onChange,
|
|
56
|
+
className = "",
|
|
57
|
+
}) => {
|
|
58
|
+
// Generate unique ID for transfer lines
|
|
59
|
+
const generateTransferId = () => {
|
|
60
|
+
transferIdCounter += 1;
|
|
61
|
+
return `transfer-${transferIdCounter}-${Date.now()}`;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Ensure default transfer lines have IDs
|
|
65
|
+
const initializeTransferLines = (lines?: TransferLineData[]): TransferLineData[] => {
|
|
66
|
+
if (!lines) return [];
|
|
67
|
+
return lines.map((line) => ({
|
|
68
|
+
...line,
|
|
69
|
+
id: line.id || generateTransferId(),
|
|
70
|
+
}));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const [mode, setMode] = useState<TransferMode>(initialMode);
|
|
74
|
+
const [sameVehicle, setSameVehicle] = useState(defaultSameVehicle);
|
|
75
|
+
const [roundTripData, setRoundTripData] = useState<RoundTripData | undefined>(defaultRoundTripData);
|
|
76
|
+
const [transferLines, setTransferLines] = useState<TransferLineData[]>(
|
|
77
|
+
initializeTransferLines(defaultTransferLines)
|
|
78
|
+
);
|
|
79
|
+
const [error, setError] = useState<string | null>(null);
|
|
80
|
+
|
|
81
|
+
// Notify parent of changes
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
const data: SearchBarTransferData = {
|
|
84
|
+
mode,
|
|
85
|
+
sameVehicle,
|
|
86
|
+
roundTripData: mode === "roundtrip" ? roundTripData : undefined,
|
|
87
|
+
transferLines: mode === "custom" ? transferLines : undefined,
|
|
88
|
+
};
|
|
89
|
+
onChange?.(data);
|
|
90
|
+
}, [mode, sameVehicle, roundTripData, transferLines, onChange]);
|
|
91
|
+
|
|
92
|
+
// Mode options for SegmentedButton
|
|
93
|
+
const modeOptions: SegmentedButtonOption[] = [
|
|
94
|
+
{ value: "roundtrip", label: "Round trip" },
|
|
95
|
+
{ value: "custom", label: "Custom transfer" },
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
// Handle mode change
|
|
99
|
+
const handleModeChange = (newMode: string) => {
|
|
100
|
+
const transferMode = newMode as TransferMode;
|
|
101
|
+
if (transferMode === mode) return;
|
|
102
|
+
|
|
103
|
+
if (transferMode === "custom" && mode === "roundtrip" && roundTripData) {
|
|
104
|
+
// Parse roundtrip to two transfer lines
|
|
105
|
+
const arrivalTransfer: TransferLineData = {
|
|
106
|
+
id: generateTransferId(),
|
|
107
|
+
type: "arrival",
|
|
108
|
+
paxData: roundTripData.paxData,
|
|
109
|
+
transferDate: roundTripData.arrivalDate,
|
|
110
|
+
pickupPoint: roundTripData.pickupDropoffPoint,
|
|
111
|
+
dropoffPoint: roundTripData.accommodation,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const departureTransfer: TransferLineData = {
|
|
115
|
+
id: generateTransferId(),
|
|
116
|
+
type: "departure",
|
|
117
|
+
paxData: roundTripData.paxData,
|
|
118
|
+
transferDate: roundTripData.departureDate,
|
|
119
|
+
pickupPoint: roundTripData.accommodation,
|
|
120
|
+
dropoffPoint: roundTripData.pickupDropoffPoint,
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
setTransferLines([arrivalTransfer, departureTransfer]);
|
|
124
|
+
setRoundTripData(undefined);
|
|
125
|
+
} else if (transferMode === "roundtrip" && mode === "custom") {
|
|
126
|
+
// Reset everything when switching to roundtrip
|
|
127
|
+
setTransferLines([]);
|
|
128
|
+
setRoundTripData(undefined);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
setMode(transferMode);
|
|
132
|
+
setError(null);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Handle adding transfer lines
|
|
136
|
+
const handleAddTransfer = (type: TransferType) => {
|
|
137
|
+
const newTransfer: TransferLineData = {
|
|
138
|
+
id: generateTransferId(),
|
|
139
|
+
type,
|
|
140
|
+
};
|
|
141
|
+
setTransferLines([...transferLines, newTransfer]);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// Handle transfer line data change
|
|
145
|
+
const handleTransferLineChange = (id: string, data: TransferLineData) => {
|
|
146
|
+
setTransferLines((prevLines) =>
|
|
147
|
+
prevLines.map((line) => (line.id === id ? data : line))
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Handle transfer line deletion
|
|
152
|
+
const handleDeleteTransferLine = (id: string) => {
|
|
153
|
+
setTransferLines((prevLines) => prevLines.filter((line) => line.id !== id));
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// Validate data
|
|
157
|
+
const validateData = (): boolean => {
|
|
158
|
+
if (mode === "roundtrip") {
|
|
159
|
+
if (!roundTripData) {
|
|
160
|
+
setError("Please fill in all the transfer details.");
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
// Check if required fields are filled
|
|
164
|
+
if (
|
|
165
|
+
!roundTripData.paxData ||
|
|
166
|
+
!roundTripData.arrivalDate ||
|
|
167
|
+
!roundTripData.departureDate ||
|
|
168
|
+
!roundTripData.pickupDropoffPoint ||
|
|
169
|
+
!roundTripData.accommodation
|
|
170
|
+
) {
|
|
171
|
+
setError("Please fill in all the transfer details.");
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
} else {
|
|
175
|
+
if (transferLines.length === 0) {
|
|
176
|
+
setError("Please add at least one transfer.");
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
// Check if all transfer lines have required data
|
|
180
|
+
for (const line of transferLines) {
|
|
181
|
+
if (
|
|
182
|
+
!line.paxData ||
|
|
183
|
+
!line.transferDate ||
|
|
184
|
+
!line.pickupPoint ||
|
|
185
|
+
!line.dropoffPoint
|
|
186
|
+
) {
|
|
187
|
+
setError("Please fill in all the transfer details.");
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
setError(null);
|
|
193
|
+
return true;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// Handle search
|
|
197
|
+
const handleSearch = () => {
|
|
198
|
+
if (validateData()) {
|
|
199
|
+
const data: SearchBarTransferData = {
|
|
200
|
+
mode,
|
|
201
|
+
sameVehicle,
|
|
202
|
+
roundTripData: mode === "roundtrip" ? roundTripData : undefined,
|
|
203
|
+
transferLines: mode === "custom" ? transferLines : undefined,
|
|
204
|
+
};
|
|
205
|
+
onSearch?.(data);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
return (
|
|
210
|
+
<div className={`search-bar-transfer ${className}`}>
|
|
211
|
+
{/* Header with title and mode selector */}
|
|
212
|
+
<div className="search-bar-transfer__header">
|
|
213
|
+
<Heading level={5} variant="bold" color="accent">
|
|
214
|
+
Select your transfer details
|
|
215
|
+
</Heading>
|
|
216
|
+
|
|
217
|
+
{/* Segmented Button for mode selection */}
|
|
218
|
+
<div className="search-bar-transfer__mode-selector">
|
|
219
|
+
<SegmentedButton
|
|
220
|
+
options={modeOptions}
|
|
221
|
+
value={mode}
|
|
222
|
+
onChange={handleModeChange}
|
|
223
|
+
name="transfer-mode"
|
|
224
|
+
/>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
|
|
228
|
+
{/* Content based on mode */}
|
|
229
|
+
{mode === "roundtrip" ? (
|
|
230
|
+
<RoundTrip
|
|
231
|
+
id="roundtrip-main"
|
|
232
|
+
locations={locations}
|
|
233
|
+
paxData={roundTripData?.paxData}
|
|
234
|
+
arrivalDate={roundTripData?.arrivalDate}
|
|
235
|
+
departureDate={roundTripData?.departureDate}
|
|
236
|
+
pickupDropoffPoint={roundTripData?.pickupDropoffPoint?.id as string}
|
|
237
|
+
accommodation={roundTripData?.accommodation?.id as string}
|
|
238
|
+
onChange={setRoundTripData}
|
|
239
|
+
/>
|
|
240
|
+
) : (
|
|
241
|
+
<>
|
|
242
|
+
{/* Transfer type selector */}
|
|
243
|
+
<div className="search-bar-transfer__transfer-type">
|
|
244
|
+
<Text size="lg" variant="bold" color="subtle" as="div" className="search-bar-transfer__transfer-type-label">
|
|
245
|
+
Select a transfer type you want to add
|
|
246
|
+
</Text>
|
|
247
|
+
<div className="search-bar-transfer__add-buttons">
|
|
248
|
+
<Button
|
|
249
|
+
variant="outline-secondary"
|
|
250
|
+
size="sm"
|
|
251
|
+
leadingIcon="plus"
|
|
252
|
+
onClick={() => handleAddTransfer("arrival")}
|
|
253
|
+
>
|
|
254
|
+
Add Arrival
|
|
255
|
+
</Button>
|
|
256
|
+
<Button
|
|
257
|
+
variant="outline-secondary"
|
|
258
|
+
size="sm"
|
|
259
|
+
leadingIcon="plus"
|
|
260
|
+
onClick={() => handleAddTransfer("departure")}
|
|
261
|
+
>
|
|
262
|
+
Add Departure
|
|
263
|
+
</Button>
|
|
264
|
+
<Button
|
|
265
|
+
variant="outline-secondary"
|
|
266
|
+
size="sm"
|
|
267
|
+
leadingIcon="plus"
|
|
268
|
+
onClick={() => handleAddTransfer("inter-hotel")}
|
|
269
|
+
>
|
|
270
|
+
Add Inter-Hotel
|
|
271
|
+
</Button>
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
|
|
275
|
+
{/* Transfer lines list */}
|
|
276
|
+
{transferLines.length > 0 && (
|
|
277
|
+
<div className="search-bar-transfer__transfer-lines">
|
|
278
|
+
{(() => {
|
|
279
|
+
// Group transfers by type
|
|
280
|
+
const groupedTransfers: { [key in TransferType]: TransferLineData[] } = {
|
|
281
|
+
arrival: [],
|
|
282
|
+
departure: [],
|
|
283
|
+
"inter-hotel": [],
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
transferLines.forEach((line) => {
|
|
287
|
+
groupedTransfers[line.type].push(line);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Get the order of non-empty groups
|
|
291
|
+
const typeOrder: TransferType[] = ["arrival", "inter-hotel", "departure"];
|
|
292
|
+
const nonEmptyGroups = typeOrder.filter((type) => groupedTransfers[type].length > 0);
|
|
293
|
+
|
|
294
|
+
// Category labels and icons
|
|
295
|
+
const categoryInfo: { [key in TransferType]: { label: string; icon: IconName } } = {
|
|
296
|
+
arrival: { label: "Arrival", icon: "arrival" },
|
|
297
|
+
departure: { label: "Departure", icon: "departure" },
|
|
298
|
+
"inter-hotel": { label: "Inter-Hotel", icon: "building" },
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
return nonEmptyGroups.map((type, groupIndex) => (
|
|
302
|
+
<React.Fragment key={type}>
|
|
303
|
+
{/* Category header */}
|
|
304
|
+
<div className="search-bar-transfer__category-header">
|
|
305
|
+
<Icon name={categoryInfo[type].icon} size="md" />
|
|
306
|
+
<Text size="md" variant="bold" color="default" as="span">
|
|
307
|
+
{categoryInfo[type].label}
|
|
308
|
+
</Text>
|
|
309
|
+
</div>
|
|
310
|
+
|
|
311
|
+
{/* Transfer lines in this category */}
|
|
312
|
+
{groupedTransfers[type].map((line) => (
|
|
313
|
+
<TransferLine
|
|
314
|
+
key={line.id}
|
|
315
|
+
id={line.id}
|
|
316
|
+
type={line.type}
|
|
317
|
+
paxData={line.paxData}
|
|
318
|
+
transferDate={line.transferDate}
|
|
319
|
+
pickupPoint={line.pickupPoint?.id}
|
|
320
|
+
dropoffPoint={line.dropoffPoint?.id}
|
|
321
|
+
locations={locations}
|
|
322
|
+
onDataChange={(data) => handleTransferLineChange(line.id, data)}
|
|
323
|
+
onDelete={() => handleDeleteTransferLine(line.id)}
|
|
324
|
+
showDelete={transferLines.length > 1}
|
|
325
|
+
/>
|
|
326
|
+
))}
|
|
327
|
+
|
|
328
|
+
{/* Show separator between categories, but not after the last one */}
|
|
329
|
+
{groupIndex < nonEmptyGroups.length - 1 && (
|
|
330
|
+
<svg
|
|
331
|
+
className="search-bar-transfer__divider"
|
|
332
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
333
|
+
width="100%"
|
|
334
|
+
height="1"
|
|
335
|
+
viewBox="0 0 1076 1"
|
|
336
|
+
fill="none"
|
|
337
|
+
preserveAspectRatio="none"
|
|
338
|
+
>
|
|
339
|
+
<path
|
|
340
|
+
d="M0 0.5L1076 0.499906"
|
|
341
|
+
stroke="var(--color-border-medium, #A3A3A3)"
|
|
342
|
+
strokeWidth="1"
|
|
343
|
+
strokeDasharray="10 10"
|
|
344
|
+
/>
|
|
345
|
+
</svg>
|
|
346
|
+
)}
|
|
347
|
+
</React.Fragment>
|
|
348
|
+
));
|
|
349
|
+
})()}
|
|
350
|
+
</div>
|
|
351
|
+
)}
|
|
352
|
+
</>
|
|
353
|
+
)}
|
|
354
|
+
|
|
355
|
+
{/* Bottom actions */}
|
|
356
|
+
<div className="search-bar-transfer__actions">
|
|
357
|
+
<Checkbox
|
|
358
|
+
checked={sameVehicle}
|
|
359
|
+
onChange={setSameVehicle}
|
|
360
|
+
label="Use the same vehicle for all your transfers"
|
|
361
|
+
/>
|
|
362
|
+
|
|
363
|
+
<div className="search-bar-transfer__cta">
|
|
364
|
+
{error && (
|
|
365
|
+
<div className="search-bar-transfer__error">
|
|
366
|
+
<div className="search-bar-transfer__error-bar" />
|
|
367
|
+
<div className="search-bar-transfer__error-content">
|
|
368
|
+
<Icon name="info" size="md" className="search-bar-transfer__error-icon" />
|
|
369
|
+
<Text size="sm" variant="bold" className="search-bar-transfer__error-text">
|
|
370
|
+
{error}
|
|
371
|
+
</Text>
|
|
372
|
+
</div>
|
|
373
|
+
</div>
|
|
374
|
+
)}
|
|
375
|
+
<Button
|
|
376
|
+
variant="primary"
|
|
377
|
+
size="lg"
|
|
378
|
+
onClick={handleSearch}
|
|
379
|
+
>
|
|
380
|
+
Search
|
|
381
|
+
</Button>
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
</div>
|
|
385
|
+
);
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
export default SearchBarTransfer;
|