@duffel/components 3.0.7-canary → 3.1.2--prototype
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/.eslintrc.js +8 -0
- package/.github/CODEOWNERS +4 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
- package/.github/renovate.json +1 -5
- package/.github/workflows/release.yml +3 -0
- package/.storybook/__snapshots__/Storyshots.test.js.snap +20384 -533
- package/.tool-versions +1 -1
- package/README.md +16 -2
- package/config/esbuild.base.config.js +6 -2
- package/config/esbuild.cdn.config.js +2 -1
- package/config/esbuild.dev.config.js +2 -1
- package/config/esbuild.react.config.js +1 -1
- package/data/airports.csv +9084 -0
- package/data/cities.csv +256 -0
- package/package.json +11 -1
- package/react-dist/index.js +51 -21
- package/scripts/generate-fixture.ts +13 -8
- package/scripts/setup-suggestion-data.ts +100 -0
- package/scripts/upload-to-cdn.sh +1 -1
- package/src/components/{Card.tsx → DuffelAncillaries/Card.tsx} +1 -1
- package/src/components/{Counter.tsx → DuffelAncillaries/Counter.tsx} +1 -1
- package/src/components/{DuffelAncillaries.tsx → DuffelAncillaries/DuffelAncillaries.tsx} +68 -64
- package/src/components/{DuffelAncillariesCustomElement.tsx → DuffelAncillaries/DuffelAncillariesCustomElement.tsx} +2 -2
- package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionCard.tsx +10 -5
- package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionController.tsx +2 -2
- package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModal.tsx +4 -4
- package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalBody.tsx +3 -3
- package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalBodyPassenger.tsx +4 -4
- package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalFooter.tsx +23 -16
- package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalHeader.tsx +24 -18
- package/src/components/{bags → DuffelAncillaries/bags}/IncludedBaggageBanner.tsx +1 -1
- package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionCard.tsx +4 -4
- package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModal.tsx +3 -3
- package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalBody.tsx +3 -3
- package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalBodyListItem.tsx +1 -1
- package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalFooter.tsx +5 -5
- package/src/components/{seats → DuffelAncillaries/seats}/Amenity.tsx +2 -2
- package/src/components/{seats → DuffelAncillaries/seats}/DeckSelect.tsx +1 -1
- package/src/components/{seats → DuffelAncillaries/seats}/Element.tsx +2 -2
- package/src/components/{seats → DuffelAncillaries/seats}/ExitElement.tsx +1 -1
- package/src/components/{seats → DuffelAncillaries/seats}/Legend.tsx +2 -2
- package/src/components/{seats → DuffelAncillaries/seats}/Row.tsx +2 -2
- package/src/components/{seats → DuffelAncillaries/seats}/RowSection.tsx +5 -2
- package/src/components/{seats → DuffelAncillaries/seats}/SeatElement.tsx +3 -3
- package/src/components/{seats → DuffelAncillaries/seats}/SeatInfo.tsx +1 -1
- package/src/components/{seats → DuffelAncillaries/seats}/SeatMap.tsx +6 -2
- package/src/components/{seats → DuffelAncillaries/seats}/SeatMapUnavailable.tsx +1 -1
- package/src/components/{seats → DuffelAncillaries/seats}/SeatSelectionCard.tsx +5 -5
- package/src/components/{seats → DuffelAncillaries/seats}/SeatSelectionModal.tsx +5 -5
- package/src/components/{seats → DuffelAncillaries/seats}/SeatSelectionModalBody.tsx +1 -1
- package/src/components/{seats → DuffelAncillaries/seats}/SeatSelectionModalFooter.tsx +24 -17
- package/src/components/{seats → DuffelAncillaries/seats}/SeatSelectionModalHeader.tsx +30 -20
- package/src/components/{seats → DuffelAncillaries/seats}/SeatUnavailable.tsx +2 -2
- package/src/components/DuffelPayments/DuffelPayments.tsx +224 -0
- package/src/components/DuffelPayments/DuffelPaymentsCustomElement.tsx +130 -0
- package/src/components/PlacesLookup/PlacesLookup.tsx +123 -0
- package/src/components/ShowData/ShowData.tsx +38 -0
- package/src/components/ShowData/ShowDataCustomElement.tsx +85 -0
- package/src/components/{Button.tsx → shared/Button.tsx} +4 -3
- package/src/components/{ErrorBoundary.tsx → shared/ErrorBoundary.tsx} +2 -2
- package/src/components/{Icon.tsx → shared/Icon.tsx} +11 -11
- package/src/components/{IconButton.tsx → shared/IconButton.tsx} +1 -1
- package/src/components/{Modal.tsx → shared/Modal.tsx} +5 -1
- package/src/components/{NonIdealState.tsx → shared/NonIdealState.tsx} +1 -1
- package/src/custom-elements.ts +6 -1
- package/src/examples/client-side/index.html +1 -1
- package/src/examples/full-stack/index.html +1 -1
- package/src/examples/full-stack/server.mjs +1 -0
- package/src/examples/just-typescript/src/index.html +2 -2
- package/src/examples/just-typescript/src/index.ts +2 -1
- package/src/examples/payments-custom-element/README.md +17 -0
- package/src/examples/payments-custom-element/index.html +43 -0
- package/src/examples/payments-just-typescript/README.md +37 -0
- package/src/examples/payments-just-typescript/package.json +16 -0
- package/src/examples/payments-just-typescript/src/index.html +23 -0
- package/src/examples/payments-just-typescript/src/index.ts +18 -0
- package/src/examples/react-app/src/index.tsx +11 -6
- package/src/fixtures/offers/off_1.json +1 -10
- package/src/index.ts +3 -1
- package/src/lib/captureErrorInSentry.ts +2 -20
- package/src/lib/fetchFromDuffelAPI.ts +36 -6
- package/src/lib/formatDate.ts +3 -4
- package/src/lib/getBaggageServiceDescription.ts +1 -6
- package/src/lib/getPassengerName.ts +4 -0
- package/src/lib/getTotalAmountForServices.ts +1 -1
- package/src/lib/hasHighLuminance.ts +9 -0
- package/src/lib/logging.ts +52 -32
- package/src/lib/retrieveOffer.ts +13 -6
- package/src/lib/retrieveSeatMaps.ts +13 -8
- package/src/stories/BaggageSelectionModalHeader.stories.tsx +1 -1
- package/src/stories/Button.stories.tsx +33 -2
- package/src/stories/DuffelAncillaries.stories.tsx +42 -2
- package/src/stories/DuffelPayments.stories.tsx +34 -0
- package/src/stories/Icon.stories.tsx +3 -2
- package/src/stories/IconButton.stories.tsx +1 -1
- package/src/stories/PlacesLookup.stories.tsx +22 -0
- package/src/stories/ShowData.stories.tsx +16 -0
- package/src/styles/components/Button.css +11 -3
- package/src/styles/components/Card.css +3 -3
- package/src/styles/components/CfarSelectionModal.css +1 -1
- package/src/styles/components/DuffelPayments.css +42 -0
- package/src/styles/components/Legend.css +10 -6
- package/src/styles/components/LoadingState.css +8 -2
- package/src/styles/components/Modal.css +2 -1
- package/src/styles/components/PassengerSelect.css +8 -2
- package/src/styles/components/PlacesLookup.css +36 -0
- package/src/styles/components/Seat.css +9 -7
- package/src/styles/components/SeatInfo.css +1 -1
- package/src/styles/components/Tabs.css +5 -2
- package/src/styles/global.css +2 -0
- package/src/tests/components/DuffelAncillaries.test.tsx +1 -1
- package/src/tests/lib/createPriceFormatters.test.tsx +1 -1
- package/src/tests/lib/formatAvailableServices.test.tsx +1 -1
- package/src/tests/lib/formatSeatMaps.test.tsx +2 -2
- package/src/tests/lib/getCurrencyForServices.test.tsx +1 -1
- package/src/tests/lib/hasServiceOfSameMetadataTypeAlreadyBeenSelected.test.ts +1 -1
- package/src/tests/lib/logging.test.tsx +14 -14
- package/src/tests/lib/moneyStringFormatter.test.tsx +1 -1
- package/src/tests/lib/validateProps.test.tsx +1 -1
- package/src/types/DuffelAncillariesProps.ts +1 -1
- package/react-dist/components/AnimatedLoaderEllipsis.d.ts +0 -2
- package/react-dist/components/Button.d.ts +0 -23
- package/react-dist/components/Card.d.ts +0 -14
- package/react-dist/components/Counter.d.ts +0 -10
- package/react-dist/components/DuffelAncillaries.d.ts +0 -3
- package/react-dist/components/DuffelAncillariesCustomElement.d.ts +0 -13
- package/react-dist/components/ErrorBoundary.d.ts +0 -13
- package/react-dist/components/FetchOfferErrorState.d.ts +0 -5
- package/react-dist/components/Icon.d.ts +0 -44
- package/react-dist/components/IconButton.d.ts +0 -16
- package/react-dist/components/Modal.d.ts +0 -11
- package/react-dist/components/NonIdealState.d.ts +0 -4
- package/react-dist/components/Stamp.d.ts +0 -7
- package/react-dist/components/Tabs.d.ts +0 -16
- package/react-dist/components/bags/BaggageSelectionCard.d.ts +0 -11
- package/react-dist/components/bags/BaggageSelectionController.d.ts +0 -13
- package/react-dist/components/bags/BaggageSelectionModal.d.ts +0 -11
- package/react-dist/components/bags/BaggageSelectionModalBody.d.ts +0 -11
- package/react-dist/components/bags/BaggageSelectionModalBodyPassenger.d.ts +0 -13
- package/react-dist/components/bags/BaggageSelectionModalFooter.d.ts +0 -14
- package/react-dist/components/bags/BaggageSelectionModalHeader.d.ts +0 -9
- package/react-dist/components/bags/IncludedBaggageBanner.d.ts +0 -7
- package/react-dist/components/cancel_for_any_reason/CfarSelectionCard.d.ts +0 -10
- package/react-dist/components/cancel_for_any_reason/CfarSelectionModal.d.ts +0 -11
- package/react-dist/components/cancel_for_any_reason/CfarSelectionModalBody.d.ts +0 -7
- package/react-dist/components/cancel_for_any_reason/CfarSelectionModalBodyListItem.d.ts +0 -4
- package/react-dist/components/cancel_for_any_reason/CfarSelectionModalFooter.d.ts +0 -11
- package/react-dist/components/cancel_for_any_reason/CfarSelectionModalHeader.d.ts +0 -2
- package/react-dist/components/seats/Amenity.d.ts +0 -6
- package/react-dist/components/seats/DeckSelect.d.ts +0 -15
- package/react-dist/components/seats/Element.d.ts +0 -15
- package/react-dist/components/seats/EmptyElement.d.ts +0 -2
- package/react-dist/components/seats/ExitElement.d.ts +0 -6
- package/react-dist/components/seats/Legend.d.ts +0 -12
- package/react-dist/components/seats/Row.d.ts +0 -13
- package/react-dist/components/seats/RowSection.d.ts +0 -17
- package/react-dist/components/seats/SeatElement.d.ts +0 -13
- package/react-dist/components/seats/SeatInfo.d.ts +0 -7
- package/react-dist/components/seats/SeatMap.d.ts +0 -12
- package/react-dist/components/seats/SeatMapUnavailable.d.ts +0 -2
- package/react-dist/components/seats/SeatSelectionCard.d.ts +0 -13
- package/react-dist/components/seats/SeatSelectionModal.d.ts +0 -13
- package/react-dist/components/seats/SeatSelectionModalBody.d.ts +0 -4
- package/react-dist/components/seats/SeatSelectionModalFooter.d.ts +0 -16
- package/react-dist/components/seats/SeatSelectionModalHeader.d.ts +0 -10
- package/react-dist/components/seats/SeatUnavailable.d.ts +0 -5
- package/react-dist/custom-elements.d.ts +0 -5
- package/react-dist/custom-elements.js +0 -36
- package/react-dist/custom-elements.js.map +0 -7
- package/react-dist/index.d.ts +0 -6
- package/react-dist/index.js.map +0 -7
- package/react-dist/lib/captureErrorInSentry.d.ts +0 -1
- package/react-dist/lib/compileCreateOrderPayload.d.ts +0 -14
- package/react-dist/lib/createPriceFormatters.d.ts +0 -12
- package/react-dist/lib/fetchFromDuffelAPI.d.ts +0 -1
- package/react-dist/lib/fetchFromFixtures.d.ts +0 -4
- package/react-dist/lib/formatAvailableServices.d.ts +0 -12
- package/react-dist/lib/formatDate.d.ts +0 -2
- package/react-dist/lib/formatSeatMaps.d.ts +0 -4
- package/react-dist/lib/getBaggageServiceDescription.d.ts +0 -2
- package/react-dist/lib/getCabinsForSegmentAndDeck.d.ts +0 -2
- package/react-dist/lib/getCurrencyForSeatMaps.d.ts +0 -10
- package/react-dist/lib/getCurrencyForServices.d.ts +0 -11
- package/react-dist/lib/getFirstSeatElementMatchingCriteria.d.ts +0 -3
- package/react-dist/lib/getPassengerBySegmentList.d.ts +0 -6
- package/react-dist/lib/getPassengerInitials.d.ts +0 -1
- package/react-dist/lib/getPassengerMapById.d.ts +0 -3
- package/react-dist/lib/getPassengerName.d.ts +0 -3
- package/react-dist/lib/getRowNumber.d.ts +0 -2
- package/react-dist/lib/getSegmentList.d.ts +0 -2
- package/react-dist/lib/getServicePriceMapById.d.ts +0 -3
- package/react-dist/lib/getSymbols.d.ts +0 -2
- package/react-dist/lib/getTotalAmountForServices.d.ts +0 -6
- package/react-dist/lib/getTotalQuantity.d.ts +0 -2
- package/react-dist/lib/hasService.d.ts +0 -2
- package/react-dist/lib/hasServiceOfSameMetadataTypeAlreadyBeenSelected.d.ts +0 -3
- package/react-dist/lib/hasWings.d.ts +0 -2
- package/react-dist/lib/isBaggageService.d.ts +0 -2
- package/react-dist/lib/isCancelForAnyReasonService.d.ts +0 -2
- package/react-dist/lib/isFixtureOfferId.d.ts +0 -2
- package/react-dist/lib/isPayloadComplete.d.ts +0 -2
- package/react-dist/lib/isSeatElement.d.ts +0 -2
- package/react-dist/lib/logging.d.ts +0 -53
- package/react-dist/lib/moneyStringFormatter.d.ts +0 -8
- package/react-dist/lib/offerIsExpired.d.ts +0 -2
- package/react-dist/lib/retrieveOffer.d.ts +0 -2
- package/react-dist/lib/retrieveOfferFromDuffelAPI.d.ts +0 -1
- package/react-dist/lib/retrieveSeatMaps.d.ts +0 -2
- package/react-dist/lib/retrieveSeatMapsFromDuffelAPI.d.ts +0 -1
- package/react-dist/lib/setBodyScrollability.d.ts +0 -1
- package/react-dist/lib/validateProps.d.ts +0 -7
- package/react-dist/lib/withPlural.d.ts +0 -1
- package/react-dist/types/Aircraft.d.ts +0 -14
- package/react-dist/types/Airline.d.ts +0 -14
- package/react-dist/types/Airport.d.ts +0 -44
- package/react-dist/types/City.d.ts +0 -18
- package/react-dist/types/CreateOrderPayload.d.ts +0 -72
- package/react-dist/types/CurrencyConversion.d.ts +0 -10
- package/react-dist/types/DuffelAncillariesProps.d.ts +0 -70
- package/react-dist/types/Offer.d.ts +0 -711
- package/react-dist/types/Order.d.ts +0 -8
- package/react-dist/types/Place.d.ts +0 -8
- package/react-dist/types/SeatMap.d.ts +0 -190
- package/react-dist/types/index.d.ts +0 -11
- package/src/examples/just-typescript/yarn.lock +0 -154
- package/src/examples/react-app/yarn.lock +0 -219
- /package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalHeader.tsx +0 -0
- /package/src/components/{seats → DuffelAncillaries/seats}/EmptyElement.tsx +0 -0
- /package/src/components/{AnimatedLoaderEllipsis.tsx → shared/AnimatedLoaderEllipsis.tsx} +0 -0
- /package/src/components/{FetchOfferErrorState.tsx → shared/FetchOfferErrorState.tsx} +0 -0
- /package/src/components/{Stamp.tsx → shared/Stamp.tsx} +0 -0
- /package/src/components/{Tabs.tsx → shared/Tabs.tsx} +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# payments-just-typescript example
|
|
2
|
+
|
|
3
|
+
## TL;DR
|
|
4
|
+
|
|
5
|
+
Start on the root of the `duffel-components` repository:
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
# build duffel-components for react env:
|
|
9
|
+
yarn react-build
|
|
10
|
+
|
|
11
|
+
# change directory to example folder
|
|
12
|
+
cd src/examples/payments-just-typescript
|
|
13
|
+
|
|
14
|
+
# cleanup last install and build
|
|
15
|
+
rm -rf node_modules && rm -rf dist
|
|
16
|
+
|
|
17
|
+
# install new version
|
|
18
|
+
yarn
|
|
19
|
+
|
|
20
|
+
# build and watch example
|
|
21
|
+
yarn build
|
|
22
|
+
|
|
23
|
+
# open example
|
|
24
|
+
open src/index.html -a "Safari"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Build duffel-components
|
|
28
|
+
|
|
29
|
+
First, navigate to the root folder of the duffel-components repository and run `yarn react-build` to build the package. It should output a react-dist folder on the root. This folder is the one we reference on `src/examples/payments-just-typescript/package.json` dependencies under `duffel-components`
|
|
30
|
+
|
|
31
|
+
## Install dependencies
|
|
32
|
+
|
|
33
|
+
Once the package is built, you can cd into this directory and run `yarn` to install all dependencies. If there are changes to `react-dist` since your last install, you'll need to `rm -rf node_modules`, otherwise the updates build will not be installed.
|
|
34
|
+
|
|
35
|
+
## Run example
|
|
36
|
+
|
|
37
|
+
Finally, run `yarn dev` to build `src/examples/payments-just-typescript/src/index.tsx`. This will produce `src/examples/payments-just-typescript/dist` folder that is referenced by `src/examples/payments-just-typescript/src/index.html`. You can then open `src/examples/payments-just-typescript/src/index.html` on your browser to see the example up and running.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "just-typescript",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "esbuild src/index.ts --bundle --outfile=dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@types/node": "20.2.5",
|
|
10
|
+
"typescript": "5.0.4",
|
|
11
|
+
"duffel-components": "../../../../duffel-components/react-dist"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"esbuild": "^0.17.19"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<link
|
|
7
|
+
rel="icon"
|
|
8
|
+
type="image/png"
|
|
9
|
+
sizes="96x96"
|
|
10
|
+
href="https://duffel.com/images/favicon/favicon-96x96.png"
|
|
11
|
+
/>
|
|
12
|
+
|
|
13
|
+
<script src="../dist/index.js" defer></script>
|
|
14
|
+
<title>Duffel payments component just typescript example</title>
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
<h1 style="margin-bottom: 2rem">
|
|
18
|
+
Duffel payments component just typescript example
|
|
19
|
+
</h1>
|
|
20
|
+
|
|
21
|
+
<duffel-payments></duffel-payments>
|
|
22
|
+
</body>
|
|
23
|
+
</html>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
onDuffelPaymentsFailedPayment,
|
|
3
|
+
onDuffelPaymentsSuccessfulPayment,
|
|
4
|
+
renderDuffelPaymentsCustomElement,
|
|
5
|
+
} from "duffel-components/custom-elements";
|
|
6
|
+
|
|
7
|
+
window.onload = () => {
|
|
8
|
+
renderDuffelPaymentsCustomElement({
|
|
9
|
+
paymentIntentClientToken:
|
|
10
|
+
"eyJjbGllbnRfc2VjcmV0IjoicGlfM0psczlVQWcySmhFeTh2WTBSTm1MU0JkX3NlY3JldF9QUW9yZXNuU3laeWJadGRiejZwNzBCbUdPIiwicHVibGlzaGFibGVfa2V5IjoicGtfdGVzdF9EQUJLY0E2Vzh6OTc0cTdPSWY0YmJ2MVQwMEpwRmMyOUpWIn0=",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line
|
|
14
|
+
onDuffelPaymentsFailedPayment((error) => console.error(error));
|
|
15
|
+
|
|
16
|
+
// eslint-disable-next-line
|
|
17
|
+
onDuffelPaymentsSuccessfulPayment(() => console.log("Payment successful"));
|
|
18
|
+
};
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { DuffelAncillaries } from "duffel-components";
|
|
1
|
+
import { DuffelAncillaries, DuffelPayments } from "duffel-components";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { createRoot } from "react-dom/client";
|
|
4
4
|
|
|
5
5
|
const App: React.FC = () => (
|
|
6
|
-
|
|
7
|
-
<h1
|
|
8
|
-
Duffel ancillaries component react-app example
|
|
9
|
-
</h1>
|
|
6
|
+
<div style={{ display: "grid", gridTemplateColumns: "1fr", rowGap: "2rem" }}>
|
|
7
|
+
<h1>Duffel ancillaries component react-app example</h1>
|
|
10
8
|
|
|
11
9
|
<DuffelAncillaries
|
|
12
10
|
offer_id="fixture_off_1"
|
|
@@ -31,9 +29,16 @@ const App: React.FC = () => (
|
|
|
31
29
|
born_on: "1942-10-17",
|
|
32
30
|
},
|
|
33
31
|
]}
|
|
32
|
+
// eslint-disable-next-line
|
|
34
33
|
onPayloadReady={console.log}
|
|
35
34
|
/>
|
|
36
|
-
|
|
35
|
+
|
|
36
|
+
<DuffelPayments
|
|
37
|
+
paymentIntentClientToken="eyJjbGllbnRfc2VjcmV0IjoicGlfM0psczlVQWcySmhFeTh2WTBSTm1MU0JkX3NlY3JldF9QUW9yZXNuU3laeWJadGRiejZwNzBCbUdPIiwicHVibGlzaGFibGVfa2V5IjoicGtfdGVzdF9EQUJLY0E2Vzh6OTc0cTdPSWY0YmJ2MVQwMEpwRmMyOUpWIn0="
|
|
38
|
+
onSuccessfulPayment={console.log}
|
|
39
|
+
onFailedPayment={console.log}
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
37
42
|
);
|
|
38
43
|
|
|
39
44
|
const rootElement = document.getElementById("root");
|
|
@@ -33,16 +33,7 @@
|
|
|
33
33
|
"fare_basis_code": "Y20LGTN2",
|
|
34
34
|
"cabin_class_marketing_name": "Economy",
|
|
35
35
|
"cabin_class": "economy",
|
|
36
|
-
"baggages": [
|
|
37
|
-
{
|
|
38
|
-
"type": "checked",
|
|
39
|
-
"quantity": 1
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
"type": "carry_on",
|
|
43
|
-
"quantity": 1
|
|
44
|
-
}
|
|
45
|
-
]
|
|
36
|
+
"baggages": []
|
|
46
37
|
}
|
|
47
38
|
],
|
|
48
39
|
"origin_terminal": "2",
|
package/src/index.ts
CHANGED
|
@@ -2,5 +2,7 @@
|
|
|
2
2
|
* This file is the main entry point for the library -- `@duffel/components`.
|
|
3
3
|
* If you'd like to expose other react components, please add them here.
|
|
4
4
|
*/
|
|
5
|
-
export * from "./components/DuffelAncillaries";
|
|
5
|
+
export * from "./components/DuffelAncillaries/DuffelAncillaries";
|
|
6
|
+
export * from "./components/DuffelPayments/DuffelPayments";
|
|
7
|
+
export * from "./components/PlacesLookup/PlacesLookup";
|
|
6
8
|
export * from "./types";
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import * as Sentry from "@sentry/browser";
|
|
2
2
|
|
|
3
|
-
/* eslint-disable-next-line @typescript-eslint/no-var-requires */
|
|
4
|
-
const PACKAGE_DOT_JSON = require("../../package.json");
|
|
5
|
-
|
|
6
3
|
let hasSentryInitiated = false;
|
|
7
4
|
function initiateSentry() {
|
|
8
5
|
Sentry.init({
|
|
@@ -13,7 +10,7 @@ function initiateSentry() {
|
|
|
13
10
|
* this value to allow Sentry to resolve the correct source maps when
|
|
14
11
|
* processing events.
|
|
15
12
|
*/
|
|
16
|
-
release:
|
|
13
|
+
release: process.env.COMPONENT_VERSION,
|
|
17
14
|
|
|
18
15
|
/**
|
|
19
16
|
* List of integrations that should be installed after SDK was initialized.
|
|
@@ -36,25 +33,10 @@ function initiateSentry() {
|
|
|
36
33
|
hasSentryInitiated = true;
|
|
37
34
|
}
|
|
38
35
|
|
|
39
|
-
export const captureErrorInSentry = (
|
|
40
|
-
error: Error,
|
|
41
|
-
context?: Record<string, any>
|
|
42
|
-
) => {
|
|
36
|
+
export const captureErrorInSentry = (error: Error) => {
|
|
43
37
|
if (!hasSentryInitiated) {
|
|
44
38
|
initiateSentry();
|
|
45
39
|
}
|
|
46
40
|
|
|
47
|
-
Sentry.configureScope((scope) => {
|
|
48
|
-
if (error.message) {
|
|
49
|
-
scope.setFingerprint([error.message]);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (context) {
|
|
53
|
-
Object.entries(context).forEach(([key, value]) =>
|
|
54
|
-
scope.setExtra(key, value)
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
|
|
59
41
|
return Sentry.captureException(error);
|
|
60
42
|
};
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import { logGroup } from "./logging";
|
|
2
|
+
|
|
3
|
+
export interface ErrorResponse extends Response {
|
|
4
|
+
data: { meta: any; errors: any[] };
|
|
5
|
+
}
|
|
6
|
+
export const isErrorResponse = (response: any): response is ErrorResponse => {
|
|
7
|
+
return "data" in response && Array.isArray(response.data.errors);
|
|
8
|
+
};
|
|
9
|
+
|
|
1
10
|
const DUFFEL_API_URL = process.env.DUFFEL_API_URL;
|
|
2
11
|
const COMPONENT_VERSION = process.env.COMPONENT_VERSION;
|
|
3
12
|
|
|
@@ -7,9 +16,11 @@ export async function fetchFromDuffelAPI(
|
|
|
7
16
|
method = "GET",
|
|
8
17
|
body?: string
|
|
9
18
|
) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
19
|
+
logGroup("Making request to the Duffel API", { path, method });
|
|
20
|
+
const fullUrl = `${DUFFEL_API_URL}/ancillaries-component/${path}`;
|
|
21
|
+
let response: Response | null = null;
|
|
22
|
+
try {
|
|
23
|
+
response = await fetch(fullUrl, {
|
|
13
24
|
method,
|
|
14
25
|
body,
|
|
15
26
|
headers: {
|
|
@@ -17,8 +28,27 @@ export async function fetchFromDuffelAPI(
|
|
|
17
28
|
Authorization: `Bearer ${withClientKey}`,
|
|
18
29
|
"User-Agent": `Duffel/ancillaries-component@${COMPONENT_VERSION}`,
|
|
19
30
|
},
|
|
20
|
-
}
|
|
21
|
-
)
|
|
31
|
+
});
|
|
32
|
+
} catch (error) {
|
|
33
|
+
logGroup("Failed to make request to the Duffel API", { error });
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const data = await response.json();
|
|
38
|
+
if (Array.isArray(data.errors)) {
|
|
39
|
+
logGroup("Request to the Duffel API failed", {
|
|
40
|
+
operation: `${method} ${fullUrl}`,
|
|
41
|
+
method,
|
|
42
|
+
request_id: data?.meta?.request_id,
|
|
43
|
+
errors: data.errors,
|
|
44
|
+
status: response.status,
|
|
45
|
+
});
|
|
46
|
+
throw { ...response, data };
|
|
47
|
+
} else {
|
|
48
|
+
logGroup("Request to the Duffel succeeded", {
|
|
49
|
+
request_id: data?.meta?.request_id,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
22
52
|
|
|
23
|
-
return
|
|
53
|
+
return data;
|
|
24
54
|
}
|
package/src/lib/formatDate.ts
CHANGED
|
@@ -5,10 +5,9 @@ export const formatDateString = (dateString: string) => {
|
|
|
5
5
|
if (!isNaN(date.valueOf())) return formatDate(date);
|
|
6
6
|
else {
|
|
7
7
|
captureErrorInSentry(
|
|
8
|
-
new Error(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
8
|
+
new Error(
|
|
9
|
+
`formatDateString attempted to parse an invalid date string: ${dateString}`
|
|
10
|
+
)
|
|
12
11
|
);
|
|
13
12
|
}
|
|
14
13
|
};
|
|
@@ -6,8 +6,7 @@ export const getBaggageServiceDescription = (
|
|
|
6
6
|
) => {
|
|
7
7
|
if (!metadata) {
|
|
8
8
|
captureErrorInSentry(
|
|
9
|
-
new Error("getBaggageServiceDescription was not given any metadata")
|
|
10
|
-
{ metadata }
|
|
9
|
+
new Error("getBaggageServiceDescription was not given any metadata")
|
|
11
10
|
);
|
|
12
11
|
return null;
|
|
13
12
|
}
|
|
@@ -18,10 +17,6 @@ export const getBaggageServiceDescription = (
|
|
|
18
17
|
!metadata.maximum_height_cm &&
|
|
19
18
|
!metadata.maximum_depth_cm
|
|
20
19
|
) {
|
|
21
|
-
captureErrorInSentry(
|
|
22
|
-
new Error("getBaggageServiceDescription metadata doesn't have any data"),
|
|
23
|
-
{ metadata }
|
|
24
|
-
);
|
|
25
20
|
return null;
|
|
26
21
|
}
|
|
27
22
|
|
|
@@ -6,6 +6,10 @@ export const getPassengerName = (
|
|
|
6
6
|
offerPassenger: OfferPassenger | undefined,
|
|
7
7
|
fallbackIndex: number
|
|
8
8
|
): string => {
|
|
9
|
+
if (!createOrderPayloadPassenger) {
|
|
10
|
+
return `Passenger ${fallbackIndex}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
9
13
|
if (
|
|
10
14
|
createOrderPayloadPassenger.given_name &&
|
|
11
15
|
createOrderPayloadPassenger.family_name
|
|
@@ -37,7 +37,7 @@ export const getTotalAmountForServicesWithPriceMap = (
|
|
|
37
37
|
} else {
|
|
38
38
|
captureErrorInSentry(
|
|
39
39
|
new Error(
|
|
40
|
-
`The service id provided could not be found in neither the offer nor the seat maps
|
|
40
|
+
`The service id (${id}) provided could not be found in neither the offer nor the seat maps.`
|
|
41
41
|
)
|
|
42
42
|
);
|
|
43
43
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Use relative-luminance to determine whether the color is dark enough or not.
|
|
3
|
+
* See also: https://www.w3.org/WAI/GL/wiki/Relative_luminance
|
|
4
|
+
*/
|
|
5
|
+
export const hasHighLuminance = (accentColor: string) => {
|
|
6
|
+
const rgb = accentColor.split(", ").map((x) => parseInt(x));
|
|
7
|
+
const luminance = (0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2]) / 255;
|
|
8
|
+
return luminance > 0.5;
|
|
9
|
+
};
|
package/src/lib/logging.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Sentry from "@sentry/browser";
|
|
2
|
+
|
|
3
|
+
const MESSAGE_PREFIX = "[Duffel Ancillaries] ";
|
|
4
|
+
const LOCAL_STORAGE_KEY = "duffel-ancillaries-logger-state";
|
|
5
|
+
let LOG_INITIALISED = false;
|
|
6
|
+
|
|
7
|
+
const storeLoggerState = (shouldLog: boolean) => {
|
|
8
|
+
localStorage.setItem(LOCAL_STORAGE_KEY, shouldLog.toString());
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const shouldLog = () => localStorage.getItem(LOCAL_STORAGE_KEY) === "true";
|
|
2
12
|
|
|
3
13
|
/**
|
|
4
14
|
* The functions in this file are used to enable logging.
|
|
@@ -25,36 +35,37 @@ import { createContext, useContext } from "react";
|
|
|
25
35
|
* log('This is a log message')
|
|
26
36
|
* logGroup('These messages will be grouped together', ['This is a log message', 'This is another log message'])
|
|
27
37
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (debugMode) {
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
const initializeLogger = (debugMode: boolean): void => {
|
|
39
|
+
storeLoggerState(debugMode);
|
|
40
|
+
if (debugMode && !LOG_INITIALISED) {
|
|
41
|
+
// eslint-disable-next-line
|
|
42
|
+
console.info(
|
|
43
|
+
MESSAGE_PREFIX,
|
|
44
|
+
`\n\nDebug mode is enabled. Information about your setup will be printed to the console.
|
|
45
|
+
|
|
46
|
+
If you do not want to enable debug mode (for example in a production environment), pass "debug: false" when initializing this component.
|
|
47
|
+
|
|
48
|
+
Learn more about the Ancillaries component:
|
|
49
|
+
http://duffel.com/docs/guides/ancillaries-component`
|
|
33
50
|
);
|
|
34
51
|
}
|
|
35
|
-
|
|
36
|
-
// We return functions that do nothing because it allows consumers
|
|
37
|
-
// of this function to not have to check if the logger is enabled or not.
|
|
38
|
-
// If we returned undefined, consumers would have to do something like:
|
|
39
|
-
// if (log) { log('message') }
|
|
40
|
-
//
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
42
|
-
const noop = () => {};
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
log: debugMode ? log : noop,
|
|
46
|
-
logGroup: debugMode ? logGroup : noop,
|
|
47
|
-
};
|
|
52
|
+
LOG_INITIALISED = true;
|
|
48
53
|
};
|
|
49
54
|
|
|
50
|
-
const MESSAGE_PREFIX = "[Duffel Ancillaries] ";
|
|
51
|
-
|
|
52
55
|
/**
|
|
53
56
|
* Log a message to the console. Messages will be prefixed with "[Duffel Ancillaries]".
|
|
54
57
|
* @param message The message to print to the console.
|
|
55
58
|
*/
|
|
56
59
|
const log = (message: any) => {
|
|
57
|
-
|
|
60
|
+
if (shouldLog()) {
|
|
61
|
+
// eslint-disable-next-line
|
|
62
|
+
console.info(MESSAGE_PREFIX, message);
|
|
63
|
+
} else {
|
|
64
|
+
Sentry.addBreadcrumb({
|
|
65
|
+
category: "log",
|
|
66
|
+
message,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
58
69
|
};
|
|
59
70
|
|
|
60
71
|
/**
|
|
@@ -77,8 +88,6 @@ function logGroup(
|
|
|
77
88
|
groupName: string,
|
|
78
89
|
messagesOrObject: any[] | { [key: string]: any }
|
|
79
90
|
): void {
|
|
80
|
-
console.groupCollapsed(MESSAGE_PREFIX, groupName);
|
|
81
|
-
|
|
82
91
|
let transformedMessagesOrObject = [];
|
|
83
92
|
if (Array.isArray(messagesOrObject)) {
|
|
84
93
|
transformedMessagesOrObject = messagesOrObject;
|
|
@@ -87,14 +96,25 @@ function logGroup(
|
|
|
87
96
|
([key, value]) => ({ property: key, value })
|
|
88
97
|
);
|
|
89
98
|
}
|
|
90
|
-
transformedMessagesOrObject.forEach((message) => {
|
|
91
|
-
console.log(message);
|
|
92
|
-
});
|
|
93
99
|
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
if (shouldLog()) {
|
|
101
|
+
// eslint-disable-next-line
|
|
102
|
+
console.groupCollapsed(MESSAGE_PREFIX, groupName);
|
|
96
103
|
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
transformedMessagesOrObject.forEach((message) => {
|
|
105
|
+
// eslint-disable-next-line
|
|
106
|
+
console.info(message);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// eslint-disable-next-line
|
|
110
|
+
console.groupEnd();
|
|
111
|
+
} else {
|
|
112
|
+
Sentry.addBreadcrumb({
|
|
113
|
+
category: "log.group",
|
|
114
|
+
message: groupName,
|
|
115
|
+
data: messagesOrObject,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
99
119
|
|
|
100
|
-
export {
|
|
120
|
+
export { initializeLogger, logGroup, log };
|
package/src/lib/retrieveOffer.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Offer } from "../types/Offer";
|
|
2
2
|
import { captureErrorInSentry } from "./captureErrorInSentry";
|
|
3
|
+
import { isErrorResponse } from "./fetchFromDuffelAPI";
|
|
3
4
|
import { importFromOfferFixtures } from "./fetchFromFixtures";
|
|
4
5
|
import { isFixtureOfferId } from "./isFixtureOfferId";
|
|
5
6
|
import { retrieveOfferFromDuffelAPI } from "./retrieveOfferFromDuffelAPI";
|
|
@@ -24,23 +25,29 @@ export async function retrieveOffer(
|
|
|
24
25
|
|
|
25
26
|
if (!client_key) {
|
|
26
27
|
throw new Error(
|
|
27
|
-
"
|
|
28
|
+
"Attempted to retrieve seat maps but the client key is missing."
|
|
28
29
|
);
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
try {
|
|
32
33
|
const data = await retrieveOfferFromDuffelAPI(offer_id, client_key);
|
|
33
|
-
|
|
34
|
+
onOfferReady(data);
|
|
34
35
|
} catch (error) {
|
|
35
36
|
let message = "An unknown error occurred while retrieving the offer.";
|
|
36
37
|
if (error instanceof Error) {
|
|
37
38
|
message = error.message;
|
|
38
|
-
if (error.message.includes("
|
|
39
|
+
if (error.message.includes("Load failed")) {
|
|
39
40
|
message = "The Duffel API is not available. Please try again later.";
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
} else if (isErrorResponse(error)) {
|
|
43
|
+
if (error.status === 404) {
|
|
44
|
+
message =
|
|
45
|
+
"The offer you are looking for does not exist or has expired.";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (isErrorResponse(error) && error.status >= 500 && error.status < 600) {
|
|
50
|
+
captureErrorInSentry(new Error(message));
|
|
44
51
|
}
|
|
45
52
|
onError(message);
|
|
46
53
|
} finally {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SeatMap } from "../types/SeatMap";
|
|
2
2
|
import { captureErrorInSentry } from "./captureErrorInSentry";
|
|
3
|
+
import { isErrorResponse } from "./fetchFromDuffelAPI";
|
|
3
4
|
import { importFromSeatMapsFixtures } from "./fetchFromFixtures";
|
|
4
5
|
import { isFixtureOfferId } from "./isFixtureOfferId";
|
|
5
6
|
import { retrieveSeatMapsFromDuffelAPI } from "./retrieveSeatMapsFromDuffelAPI";
|
|
@@ -7,7 +8,7 @@ import { retrieveSeatMapsFromDuffelAPI } from "./retrieveSeatMapsFromDuffelAPI";
|
|
|
7
8
|
export async function retrieveSeatMaps(
|
|
8
9
|
offer_id: string,
|
|
9
10
|
client_key: string | null,
|
|
10
|
-
onError: (
|
|
11
|
+
onError: () => void,
|
|
11
12
|
setIsLoading: (isLoading: boolean) => void,
|
|
12
13
|
onSeatMapReady: (seatMaps: SeatMap[]) => void
|
|
13
14
|
) {
|
|
@@ -25,7 +26,7 @@ export async function retrieveSeatMaps(
|
|
|
25
26
|
|
|
26
27
|
if (!client_key) {
|
|
27
28
|
throw new Error(
|
|
28
|
-
"Attemptted to retrieve seat maps but the client key is missing"
|
|
29
|
+
"Attemptted to retrieve seat maps but the client key is missing."
|
|
29
30
|
);
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -33,17 +34,21 @@ export async function retrieveSeatMaps(
|
|
|
33
34
|
const data = await retrieveSeatMapsFromDuffelAPI(offer_id, client_key);
|
|
34
35
|
onSeatMapReady(data);
|
|
35
36
|
} catch (error) {
|
|
36
|
-
let message = "An unknown error occurred while retrieving the
|
|
37
|
+
let message = "An unknown error occurred while retrieving the seat maps.";
|
|
38
|
+
|
|
37
39
|
if (error instanceof Error) {
|
|
38
40
|
message = error.message;
|
|
39
|
-
if (error.message.includes("
|
|
41
|
+
if (error.message.includes("Load failed")) {
|
|
40
42
|
message = "The Duffel API is not available. Please try again later.";
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
} else if (isErrorResponse(error)) {
|
|
45
|
+
message =
|
|
46
|
+
error.data.errors[0]?.message ||
|
|
47
|
+
"Received an unknown error from the Duffel API.";
|
|
45
48
|
}
|
|
46
|
-
|
|
49
|
+
|
|
50
|
+
captureErrorInSentry(new Error(message));
|
|
51
|
+
onError();
|
|
47
52
|
} finally {
|
|
48
53
|
setIsLoading(false);
|
|
49
54
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BaggageSelectionModalHeader } from "@components/bags/BaggageSelectionModalHeader";
|
|
2
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { BaggageSelectionModalHeader } from "../components/DuffelAncillaries/bags/BaggageSelectionModalHeader";
|
|
3
3
|
import { OfferSliceSegment } from "../types/Offer";
|
|
4
4
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
5
5
|
const offer = require("../fixtures/offers/off_0000AUde3KwTztSRK1cznH.json");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Button, ButtonProps } from "@components/Button";
|
|
2
1
|
import type { Meta, StoryFn, StoryObj } from "@storybook/react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Button, ButtonProps } from "../components/shared/Button";
|
|
3
4
|
|
|
4
5
|
export default {
|
|
5
6
|
title: "Button",
|
|
@@ -47,7 +48,9 @@ export const WithSize48: ButtonStory = {
|
|
|
47
48
|
args: { ...defaultProps, size: 48, iconBefore: "autorenew" },
|
|
48
49
|
};
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
const AccentColorWrapper: React.FC<{ children: React.ReactNode }> = ({
|
|
52
|
+
children,
|
|
53
|
+
}) => (
|
|
51
54
|
<div
|
|
52
55
|
style={
|
|
53
56
|
{
|
|
@@ -55,6 +58,34 @@ export const WithAccentColorSet: StoryFn<ButtonProps> = () => (
|
|
|
55
58
|
} as any
|
|
56
59
|
}
|
|
57
60
|
>
|
|
61
|
+
{children}
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
export const WithAccentColorSet: StoryFn<ButtonProps> = () => (
|
|
66
|
+
<AccentColorWrapper>
|
|
58
67
|
<Button {...defaultProps} />
|
|
68
|
+
</AccentColorWrapper>
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const WhiteAccentColorWrapper: React.FC<{ children: React.ReactNode }> = ({
|
|
72
|
+
children,
|
|
73
|
+
}) => (
|
|
74
|
+
<div
|
|
75
|
+
style={
|
|
76
|
+
{
|
|
77
|
+
"--ACCENT": "255, 255, 255",
|
|
78
|
+
"--SECONDARY": "black",
|
|
79
|
+
"--TERTIARY": "grey",
|
|
80
|
+
} as any
|
|
81
|
+
}
|
|
82
|
+
>
|
|
83
|
+
{children}
|
|
59
84
|
</div>
|
|
60
85
|
);
|
|
86
|
+
|
|
87
|
+
export const WithWhiteAccentColorSet: StoryFn<ButtonProps> = () => (
|
|
88
|
+
<WhiteAccentColorWrapper>
|
|
89
|
+
<Button {...defaultProps} />
|
|
90
|
+
</WhiteAccentColorWrapper>
|
|
91
|
+
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import type { Meta, StoryFn, StoryObj } from "@storybook/react";
|
|
2
|
+
import { DuffelAncillaries } from "../components/DuffelAncillaries/DuffelAncillaries";
|
|
3
3
|
import mockPassengers from "../fixtures/passengers/mock_passengers";
|
|
4
4
|
import { DuffelAncillariesPropsWithOffersAndSeatMaps } from "../types/DuffelAncillariesProps";
|
|
5
5
|
import { Offer } from "../types/Offer";
|
|
@@ -62,6 +62,28 @@ export const ExpiredOffer: DuffelAncillariesStory = {
|
|
|
62
62
|
},
|
|
63
63
|
};
|
|
64
64
|
|
|
65
|
+
export const OneWayOnePassengerOffer: DuffelAncillariesStory = {
|
|
66
|
+
args: {
|
|
67
|
+
...defaultProps,
|
|
68
|
+
offer: {
|
|
69
|
+
...offer,
|
|
70
|
+
slices: [
|
|
71
|
+
{
|
|
72
|
+
...offer.slices[0],
|
|
73
|
+
segments: [
|
|
74
|
+
{
|
|
75
|
+
...offer.slices[0].segments[0],
|
|
76
|
+
passengers: [offer.slices[0].segments[0].passengers[0]],
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
passengers: [offer.passengers[0]],
|
|
82
|
+
available_services: [offer.available_services[0]],
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
65
87
|
export const WithCustomStyles: DuffelAncillariesStory = {
|
|
66
88
|
args: {
|
|
67
89
|
...defaultProps,
|
|
@@ -124,3 +146,21 @@ export const MarkupUsingPriceFormattersWithCustomCurrency: DuffelAncillariesStor
|
|
|
124
146
|
},
|
|
125
147
|
},
|
|
126
148
|
};
|
|
149
|
+
|
|
150
|
+
export const WithAccentColorSet: StoryFn<
|
|
151
|
+
DuffelAncillariesPropsWithOffersAndSeatMaps
|
|
152
|
+
> = () => (
|
|
153
|
+
<DuffelAncillaries
|
|
154
|
+
{...defaultProps}
|
|
155
|
+
styles={{ accentColor: "29, 78, 216" }}
|
|
156
|
+
/>
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
export const WithWhiteAccentColorSet: StoryFn<
|
|
160
|
+
DuffelAncillariesPropsWithOffersAndSeatMaps
|
|
161
|
+
> = () => (
|
|
162
|
+
<DuffelAncillaries
|
|
163
|
+
{...defaultProps}
|
|
164
|
+
styles={{ accentColor: "255, 255, 255" }}
|
|
165
|
+
/>
|
|
166
|
+
);
|