añadí opacidad al botón de agregar pasajeros cuando no tengamos ningun pasajero agregado y el destino seleccionado al mostrar el resumen del ticket
.
.
src/Machines/bookingMachine.js:
import { createMachine, assign } from "xstate";
import { fetchCountries } from '../Utils/api'
const fillCountries = {
initial: 'loading',
states: {
loading: {
invoke: {
id: 'getCountries',
src: ()=> fetchCountries,
onDone: {
target: 'success',
actions: assign({
countries: (context,event)=> event.data
})
},
onError: {
target: 'failure',
actions: assign({
error: 'Fallo el request'
})
}
}
},
success: {},
failure: {
on: {
RETRY: { target: 'loading'}
}
}
}
}
const bookingMachine = createMachine({
id: "buy plane tickets",
initial: "initial",
context: {
passengers: [],
selectedCountry: '',
countries: [],
error: '',
},
states: {
initial: {
on: {
START: {
target: 'search',
},
},
},
search: {
on: {
CONTINUE: {
target: 'passengers',
actions: 'choiceSelectedCountry',
},
CANCEL: 'initial',
},
...fillCountries,
},
tickets: {
after: {
5000: {
target: 'initial',
actions: 'cleanContext'
}
}
},
passengers: {
on: {
DONE: {
target: "tickets",
cond: 'moreThanOnePassenger'
},
CANCEL: {
target: 'initial',
actions: 'cleanContext'
},
ADD: {
target: 'passengers',
actions: 'addPassenger'
}
},
},
},
},
{
actions: {
addPassenger: assign(
(context, event)=> context.passengers.push(event.newPassenger)
),
choiceSelectedCountry: assign({
selectedCountry: (context, event) => event.selectedCountry
}),
cleanContext: assign({
selectedCountry: '',
passengers: [],
})
},
guards: {
moreThanOnePassenger: (context)=> {
return context.passengers.length > 0
}
}
});
export default bookingMachine;
src/Containers/StepsLayout.js:
import React from 'react';
import { Welcome } from '../Components/Welcome';
import { Search } from '../Components/Search';
import { Passengers } from '../Components/Passengers';
import { Tickets } from '../Components/Tickets';
import './StepsLayout.css';
export const StepsLayout = ({ state, send }) => {
const renderContent = () => {
if (state.matches('initial')) return <Welcome send={send} />
if (state.matches('search')) return <Search state={state} send={send} />
if (state.matches('tickets')) return <Tickets context={state.context} send={send} />
if (state.matches('passengers')) return <Passengers state={state} send={send} />
return null
};
return (
<div className='StepsLayout'>
{renderContent()}
</div>
);
};
src/Components/Tickets.js:
import React from 'react';
import './Tickets.css';
export const Tickets = ({ send, context }) => {
const finish = () => {
send('FINISH')
};
return (
<div className='Tickets'>
<p className='Tickets-description description'>Gracias por volar con book a fly 💚</p>
<div className='Tickets-ticket'>
<div className='Tickets-country'>{context.selectedCountry}</div>
<div className='Tickets-passengers'>
<span>✈</span>
{context.passengers.map((passenger, idx) => (
<p key={idx}>{passenger}</p>
))}
</div>
</div>
<button onClick={finish} className='Tickets-finalizar button'>Finalizar</button>
</div>
);
};
src/Components/Passengers.js:
import React, { useState } from 'react';
import './Passengers.css';
export const Passengers = ({ state, send }) => {
const { passengers } = state.context
const [value, changeValue] = useState('');
const onChangeInput = (e) => {
changeValue(e.target.value);
}
const goToTicket = ()=> {
send('DONE')
}
const submit = (e) => {
e.preventDefault();
send('ADD', { newPassenger: value })
changeValue('');
}
return (
<form onSubmit={submit} className='Passengers'>
<p className='Passengers-title title'>Agrega a las personas que van a volar ✈️</p>
{passengers.map((passenger,index) => (
<p key={`${passenger}${index}`}>{passenger}</p>
))}
<input
id="name"
name="name"
type="text"
placeholder='Escribe el nombre completo'
required
value={value}
onChange={onChangeInput}
/>
<div className='Passengers-buttons'>
<button
className='Passengers-add button-secondary'
type="submit"
>
Agregar Pasajero
</button>
<button
className={`Passenger-pay button ${passengers.length === 0 ? 'Passenger-disabled' : ''}`}
type="button"
onClick={goToTicket}
>
Ver mi ticket
</button>
</div>
</form>
);
};
src/Components/Passengers.css:
.Passengers {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 0 8px;
}
.Passengers input {
font-size: 1rem;
margin: 16px 0;
border-radius: 8px;
padding: 8px;
border: none;
width: 100%;
box-sizing: border-box;
}
.Passengers-buttons {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
width: 100%;
margin-top: 8px;
}
.Passengers-title {
margin-bottom: 16px;
}
.Passenger-disabled {
opacity: 0.1;
}
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?