Skip to content

Commit

Permalink
Add solidjs flight booker
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewiggins committed Oct 16, 2023
1 parent 0241f50 commit 977cfa2
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 5 deletions.
31 changes: 31 additions & 0 deletions frameworks/solid-js/src/7GUIs-flight-booker/DateEntry.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @typedef DateEntryProps
* @property {string} label
* @property {string} date
* @property {(newDate: string) => void} setDate
* @property {string | null} errorMsg
* @property {boolean} [disabled]
*/

/**
* @param {DateEntryProps} props
*/
export function DateEntry(props) {
const inputId = `${props.label}-date`;
return (
<div class={"form-group" + (props.errorMsg ? " has-error" : "")}>
<label class="form-label" for={inputId}>
{props.label}
</label>
<input
id={inputId}
class="form-input"
type="text"
value={props.date}
onInput={e => props.setDate(e.currentTarget.value)}
disabled={props.disabled}
/>
{props.errorMsg && <p class="form-input-hint">{props.errorMsg}</p>}
</div>
);
}
24 changes: 24 additions & 0 deletions frameworks/solid-js/src/7GUIs-flight-booker/TripType.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export const ONE_WAY_FLIGHT = "one-way";
export const RETURN_FLIGHT = "return";

/**
* @param {{ tripType: string; setTripType(value: string): void; }} props
*/
export function TripType(props) {
return (
<div class="form-group">
<label class="form-label" for="trip-type">
Trip type
</label>
<select
id="trip-type"
class="form-select"
value={props.tripType}
onInput={e => props.setTripType(e.currentTarget.value)}
>
<option value={ONE_WAY_FLIGHT}>one-way flight</option>
<option value={RETURN_FLIGHT}>return flight</option>
</select>
</div>
);
}
98 changes: 98 additions & 0 deletions frameworks/solid-js/src/7GUIs-flight-booker/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { createMemo, createSignal } from "solid-js";
import { render } from "solid-js/web";
import { today, validateDate } from "../../../../lib/date";
import { TripType, RETURN_FLIGHT, ONE_WAY_FLIGHT } from "./TripType";
import { DateEntry } from "./DateEntry";

const initialDate = today();

/**
* @typedef {import('solid-js').Accessor<T>} Accessor
* @template T
*/

/**
* @param {string} initialDate
* @returns {[Accessor<string>, Accessor<string | null>, (string) => void]}
*/
function useDate(initialDate) {
const [date, setDate] = createSignal(initialDate);
const [error, setError] = createSignal(null);

/** @type {(newDate: string) => void} */
function updateDate(newDate) {
setDate(newDate);

try {
validateDate(newDate);
setError(null);
} catch (error) {
setError(error.message);
}
}

return [date, error, updateDate];
}

function App() {
const [tripType, setTripType] = createSignal(ONE_WAY_FLIGHT);
const [departing, departingError, setDeparting] = useDate(initialDate);
const [returning, returningError, setReturning] = useDate(initialDate);

const finalReturningError = createMemo(() => {
if (
departingError() == null &&
returningError() == null &&
tripType() == RETURN_FLIGHT &&
returning() < departing()
) {
return "Returning date must be on or after departing date.";
} else {
return returningError();
}
});

function bookFlight() {
const type = tripType() === RETURN_FLIGHT ? "return" : "one-way";

let message = `You have booked a ${type} flight, departing ${departing()}`;
if (tripType() == RETURN_FLIGHT) {
message += ` and returning ${returning()}`;
}

alert(message);
}

return (
<>
<TripType
tripType={tripType()}
setTripType={value => setTripType(value)}
/>
<DateEntry
label="Departing"
date={departing()}
setDate={newDate => setDeparting(newDate)}
errorMsg={departingError()}
/>
<DateEntry
label="Returning"
date={returning()}
setDate={newDate => setReturning(newDate)}
errorMsg={finalReturningError()}
disabled={tripType() !== RETURN_FLIGHT}
/>
<div class="form-group">
<button
disabled={Boolean(departingError() || finalReturningError())}
onClick={bookFlight}
class="btn btn-primary"
>
book
</button>
</div>
</>
);
}

render(App, document.getElementById("app"));
1 change: 0 additions & 1 deletion frameworks/solid-js/src/7GUIs-timer/index.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
createSignal,
onMount,
onCleanup,
createMemo,
createRenderEffect
Expand Down
14 changes: 10 additions & 4 deletions sizes.json
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,17 @@
"gzip": 3021,
"brotli": 2736
},
"7GUIs-flight-booker": {
"raw": 24511,
"minified": 10295,
"gzip": 4085,
"brotli": 3669
},
"7GUIs-timer": {
"raw": 20167,
"minified": 8336,
"gzip": 3447,
"brotli": 3108
"raw": 19713,
"minified": 8099,
"gzip": 3348,
"brotli": 3028
}
},
"svelte": {
Expand Down

0 comments on commit 977cfa2

Please sign in to comment.