-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix return flight showing on one-way itinerary.
- Loading branch information
1 parent
01cfc0a
commit 809e342
Showing
12 changed files
with
755 additions
and
176 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,80 @@ | ||
import FlightContext from './machines/flightMachine'; | ||
import { BookButton, Header } from './components'; | ||
import { DateSelector, TripSelector } from './components'; | ||
import { TODAY } from './utils'; | ||
import FlightContext, { TODAY } from "./machines/flightMachine"; | ||
import { BookButton, Header } from "./components"; | ||
import { DateSelector, TripSelector } from "./components"; | ||
import { format } from "date-fns"; | ||
|
||
const dateFormat = "EEEE MMMM do, yyyy"; | ||
|
||
export default function App() { | ||
const { send } = FlightContext.useActorRef(); | ||
const state = FlightContext.useSelector((state) => state); | ||
const { departDate, returnDate } = state.context; | ||
const isRoundTrip = state.matches({ scheduling: 'roundTrip' }); | ||
const isBooking = state.matches('booking'); | ||
const isBooked = state.matches('booked'); | ||
const isRoundTrip = state.context.tripType === "roundTrip"; | ||
const isBooking = state.matches("booking"); | ||
const isBooked = state.matches("booked"); | ||
|
||
const isValidDepartDate = departDate >= TODAY; | ||
const isValidReturnDate = returnDate >= departDate; | ||
|
||
return ( | ||
<main> | ||
const successMessage = ( | ||
<> | ||
<Header>Booked!</Header> | ||
<p> | ||
You booked a <b>{isRoundTrip ? "round trip" : "one way"}</b> flight. | ||
</p> | ||
<p> | ||
<b>Departs:</b> {format(departDate, dateFormat)} | ||
</p> | ||
{isRoundTrip && ( | ||
<p> | ||
<b>Returns:</b> {format(returnDate, dateFormat)} | ||
</p> | ||
)} | ||
</> | ||
); | ||
|
||
const ui = ( | ||
<> | ||
<Header>Book Flight</Header> | ||
<TripSelector | ||
id="Trip Type" | ||
isBooking={isBooking} | ||
isBooked={isBooked} | ||
tripType={isRoundTrip ? 'roundTrip' : 'oneWay'} | ||
tripType={isRoundTrip ? "roundTrip" : "oneWay"} | ||
/> | ||
<DateSelector | ||
id="Depart Date" | ||
value={departDate} | ||
isValidDate={isValidDepartDate} | ||
disabled={isBooking || isBooked} | ||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => | ||
send({ | ||
type: 'CHANGE_DEPART_DATE', | ||
value: e.currentTarget.value | ||
}) | ||
} | ||
/> | ||
<DateSelector | ||
id="Return Date" | ||
value={returnDate} | ||
isValidDate={isValidReturnDate} | ||
disabled={!isRoundTrip} | ||
disabled={isBooking} | ||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => | ||
send({ | ||
type: 'CHANGE_RETURN_DATE', | ||
value: e.currentTarget.value | ||
type: "CHANGE_DEPART_DATE", | ||
value: e.currentTarget.value, | ||
}) | ||
} | ||
/> | ||
{isRoundTrip && ( | ||
<DateSelector | ||
id="Return Date" | ||
value={returnDate} | ||
isValidDate={isValidReturnDate} | ||
disabled={!isRoundTrip || isBooking} | ||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => | ||
send({ | ||
type: "CHANGE_RETURN_DATE", | ||
value: e.currentTarget.value, | ||
}) | ||
} | ||
/> | ||
)} | ||
<BookButton | ||
eventType={isRoundTrip ? 'BOOK_RETURN' : 'BOOK_DEPART'} | ||
eventType={isRoundTrip ? "BOOK_RETURN" : "BOOK_DEPART"} | ||
isBooking={isBooking} | ||
isBooked={isBooked} | ||
/> | ||
</main> | ||
</> | ||
); | ||
|
||
return <main>{isBooked ? successMessage : ui}</main>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
import Header from './Header'; | ||
import BookButton from './BookButton'; | ||
import DateSelector from './DateInput'; | ||
import TripSelector from './TripSelector'; | ||
import Header from "./Header"; | ||
import BookButton from "./BookButton"; | ||
import DateSelector from "./DateInput"; | ||
import TripSelector from "./TripSelector"; | ||
|
||
export { Header, BookButton, DateSelector, TripSelector }; |
125 changes: 72 additions & 53 deletions
125
examples/7guis-flight-booker-react/src/machines/flightMachine.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,107 +1,126 @@ | ||
import { setup, assign, assertEvent, fromPromise } from 'xstate'; | ||
import { createActorContext } from '@xstate/react'; | ||
import { TODAY, TOMORROW } from '../utils'; | ||
import { sleep } from '../utils'; | ||
import { setup, assign, assertEvent, fromPromise } from "xstate"; | ||
import { createActorContext } from "@xstate/react"; | ||
import { generateDate } from "../utils"; | ||
import { sleep } from "../utils"; | ||
|
||
export const TODAY = generateDate(0); | ||
const TOMORROW = generateDate(1); | ||
|
||
export const flightBookerMachine = setup({ | ||
types: { | ||
context: {} as FlightData, | ||
events: {} as | ||
| { type: 'BOOK_DEPART' } | ||
| { type: 'BOOK_RETURN' } | ||
| { type: 'CHANGE_TRIP_TYPE' } | ||
| { type: 'CHANGE_DEPART_DATE'; value: string } | ||
| { type: 'CHANGE_RETURN_DATE'; value: string } | ||
| { type: "BOOK_DEPART" } | ||
| { type: "BOOK_RETURN" } | ||
| { type: "CHANGE_TRIP_TYPE"; tripType: "oneWay" | "roundTrip" } | ||
| { type: "CHANGE_DEPART_DATE"; value: string } | ||
| { type: "CHANGE_RETURN_DATE"; value: string }, | ||
}, | ||
actions: { | ||
setDepartDate: assign(({ event }) => { | ||
assertEvent(event, 'CHANGE_DEPART_DATE'); | ||
assertEvent(event, "CHANGE_DEPART_DATE"); | ||
return { departDate: event.value }; | ||
}), | ||
setReturnDate: assign(({ event }) => { | ||
assertEvent(event, 'CHANGE_RETURN_DATE'); | ||
assertEvent(event, "CHANGE_RETURN_DATE"); | ||
return { returnDate: event.value }; | ||
}) | ||
}), | ||
setTripType: assign(({ event }) => { | ||
assertEvent(event, "CHANGE_TRIP_TYPE"); | ||
return { tripType: event.tripType }; | ||
}), | ||
}, | ||
actors: { | ||
Booker: fromPromise(() => { | ||
return sleep(2000); | ||
}) | ||
return sleep(1000); | ||
}), | ||
}, | ||
guards: { | ||
'isValidDepartDate?': ({ context: { departDate } }) => { | ||
"isValidDepartDate?": ({ context: { departDate } }) => { | ||
return departDate >= TODAY; | ||
}, | ||
'isValidReturnDate?': ({ context: { departDate, returnDate } }) => { | ||
"isValidReturnDate?": ({ context: { departDate, returnDate } }) => { | ||
return departDate >= TODAY && returnDate > departDate; | ||
} | ||
} | ||
}, | ||
}, | ||
}).createMachine({ | ||
id: 'flightBookerMachine', | ||
id: "flightBookerMachine", | ||
context: { | ||
departDate: TODAY, | ||
returnDate: TOMORROW | ||
returnDate: TOMORROW, | ||
tripType: "oneWay", | ||
}, | ||
initial: 'scheduling', | ||
initial: "scheduling", | ||
states: { | ||
scheduling: { | ||
initial: 'oneWay', | ||
initial: "oneWay", | ||
on: { | ||
CHANGE_DEPART_DATE: { | ||
actions: { | ||
type: 'setDepartDate' | ||
} | ||
} | ||
type: "setDepartDate", | ||
}, | ||
}, | ||
|
||
BOOK_DEPART: { | ||
target: "booking", | ||
guard: { | ||
type: "isValidDepartDate?", | ||
}, | ||
}, | ||
|
||
BOOK_RETURN: { | ||
target: "booking", | ||
guard: { | ||
type: "isValidReturnDate?", | ||
}, | ||
}, | ||
}, | ||
states: { | ||
oneWay: { | ||
on: { | ||
CHANGE_TRIP_TYPE: { | ||
target: 'roundTrip' | ||
target: "roundTrip", | ||
actions: { | ||
type: "setTripType", | ||
tripType: "roundTrip", | ||
}, | ||
}, | ||
BOOK_DEPART: { | ||
target: '#flightBookerMachine.booking', | ||
guard: { | ||
type: 'isValidDepartDate?' | ||
} | ||
} | ||
} | ||
}, | ||
}, | ||
roundTrip: { | ||
on: { | ||
CHANGE_TRIP_TYPE: { | ||
target: 'oneWay' | ||
target: "oneWay", | ||
actions: { | ||
type: "setTripType", | ||
tripType: "oneWay", | ||
}, | ||
}, | ||
|
||
CHANGE_RETURN_DATE: { | ||
actions: { | ||
type: 'setReturnDate' | ||
} | ||
type: "setReturnDate", | ||
}, | ||
}, | ||
BOOK_RETURN: { | ||
target: '#flightBookerMachine.booking', | ||
guard: { | ||
type: 'isValidReturnDate?' | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
}, | ||
}, | ||
}, | ||
booking: { | ||
invoke: { | ||
src: 'Booker', | ||
src: "Booker", | ||
onDone: { | ||
target: 'booked' | ||
target: "booked", | ||
}, | ||
onError: { | ||
target: 'scheduling' | ||
} | ||
} | ||
target: "scheduling", | ||
}, | ||
}, | ||
}, | ||
booked: { | ||
type: 'final' | ||
} | ||
} | ||
type: "final", | ||
}, | ||
}, | ||
}); | ||
|
||
export default createActorContext(flightBookerMachine); |
Oops, something went wrong.