Skip to content

Commit

Permalink
Convert date input on Flight Booker to text field
Browse files Browse the repository at this point in the history
* Use custom date validator
* Update date validation to require leading 0s to support sorting
  • Loading branch information
andrewiggins committed Jul 16, 2019
1 parent a89fdbd commit 8ca627c
Show file tree
Hide file tree
Showing 20 changed files with 273 additions and 196 deletions.
9 changes: 3 additions & 6 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,13 @@

* Add tests verifying each implementation of an app returns the expected markup
* For Vue, implement getFrameworkFragment(frameworkName) that returns either toHTMLString.Fragment or div depending on if frameworkName supports Fragments
* Consider changing flight booker to do input validation to demonstrate how that flow works...
* Would also make it easier to test since using date input in puppeteer is hard
* Perhaps require dates to match yyyy-mm-dd format (ISO format?) using regex /([0-9]{4})-([0-9]{2})-([0-9]{2})/ + simplified validation logic (month <= 12, day <= 31). Perhaps incorrect values are marked as invalid for date values that don't match parsed date after passing into Date constructor

* Consider having one page per app with a framework selector? with standalone page option?
* Add Compare page
* plus button to add multiple frameworks of one app to view source and Compare
* Consider showing source files inline under app
* Perhaps add toggle for source and js output? Particularly useful for compiler frameworks (Vue, Svelte)
* Add link to framework repl if exists
* Consider having one page per app with a framework selector? with standalone page option?
* Add Compare page
* plus button to add multiple frameworks of one app to view source and Compare
* Add brotli/gzip radio option to summary page (power radios using /scripts/bundles/summary.js)
* Add rollup-plugin-visualizer html to output

Expand Down
4 changes: 2 additions & 2 deletions dist/frameworks/preact-hooks/7GUIs-flight-booker.html
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ <h1 class="page-title">7GUIs Flight Booker - Preact Hooks</h1>
<div class="panel-header"></div>
<div class="panel-body"><div id="app"></div></div>
<div class="panel-footer">
<div>Gzip: 4.06 kB</div>
<div>Brotli: 3.67 kB</div>
<div>Gzip: 4.36 kB</div>
<div>Brotli: 3.95 kB</div>
</div>
</div>
<script
Expand Down
2 changes: 1 addition & 1 deletion dist/frameworks/preact-hooks/7GUIs-flight-booker.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/frameworks/preact/7GUIs-flight-booker.html
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ <h1 class="page-title">7GUIs Flight Booker - Preact</h1>
<div class="panel-header"></div>
<div class="panel-body"><div id="app"></div></div>
<div class="panel-footer">
<div>Gzip: 3.85 kB</div>
<div>Brotli: 3.49 kB</div>
<div>Gzip: 4.17 kB</div>
<div>Brotli: 3.77 kB</div>
</div>
</div>
<script
Expand Down
2 changes: 1 addition & 1 deletion dist/frameworks/preact/7GUIs-flight-booker.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/frameworks/react-hooks/7GUIs-flight-booker.html
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ <h1 class="page-title">7GUIs Flight Booker - React Hooks</h1>
<div class="panel-header"></div>
<div class="panel-body"><div id="app"></div></div>
<div class="panel-footer">
<div>Gzip: 37.8 kB</div>
<div>Brotli: 33.2 kB</div>
<div>Gzip: 38.1 kB</div>
<div>Brotli: 33.5 kB</div>
</div>
</div>
<script
Expand Down
2 changes: 1 addition & 1 deletion dist/frameworks/react-hooks/7GUIs-flight-booker.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/frameworks/react/7GUIs-flight-booker.html
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ <h1 class="page-title">7GUIs Flight Booker - React</h1>
<div class="panel-header"></div>
<div class="panel-body"><div id="app"></div></div>
<div class="panel-footer">
<div>Gzip: 37.9 kB</div>
<div>Brotli: 33.4 kB</div>
<div>Gzip: 38.2 kB</div>
<div>Brotli: 33.5 kB</div>
</div>
</div>
<script
Expand Down
2 changes: 1 addition & 1 deletion dist/frameworks/react/7GUIs-flight-booker.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/frameworks/svelte/7GUIs-flight-booker.html
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ <h1 class="page-title">7GUIs Flight Booker - Svelte</h1>
<div class="panel-header"></div>
<div class="panel-body"><div id="app"></div></div>
<div class="panel-footer">
<div>Gzip: 2.22 kB</div>
<div>Brotli: 1.99 kB</div>
<div>Gzip: 2.74 kB</div>
<div>Brotli: 2.46 kB</div>
</div>
</div>
<script
Expand Down
2 changes: 1 addition & 1 deletion dist/frameworks/svelte/7GUIs-flight-booker.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 10 additions & 10 deletions dist/summary.html
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,11 @@ <h2>brotli</h2>
</tr>
<tr>
<td>7GUIs Flight Booker</td>
<td>3.49 kB</td>
<td>3.67 kB</td>
<td>33.4 kB</td>
<td>33.2 kB</td>
<td>1.99 kB</td>
<td>3.77 kB</td>
<td>3.95 kB</td>
<td>33.5 kB</td>
<td>33.5 kB</td>
<td>2.46 kB</td>
<td></td>
</tr>
<tr>
Expand Down Expand Up @@ -325,11 +325,11 @@ <h2>gzip</h2>
</tr>
<tr>
<td>7GUIs Flight Booker</td>
<td>3.85 kB</td>
<td>4.06 kB</td>
<td>37.9 kB</td>
<td>37.8 kB</td>
<td>2.22 kB</td>
<td>4.17 kB</td>
<td>4.36 kB</td>
<td>38.2 kB</td>
<td>38.1 kB</td>
<td>2.74 kB</td>
<td></td>
</tr>
<tr>
Expand Down
63 changes: 37 additions & 26 deletions frameworks/preact-hooks/src/7GUIs-flight-booker/index.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,45 @@
import { h, render, Fragment } from "preact";
import { useState } from "preact/hooks";
import { today, validateDate } from "../../../../lib/date";

const initial = new Date();
const initialDate = today();
const oneWayFlight = "one-way";
const returnFlight = "return";

function convertToDate(str) {
const split = str.split("-");
return new Date(+split[0], +split[1] - 1, +split[2]);
}
function useDate(initialDate) {
const [date, setDate] = useState(initialDate);
const [error, setError] = useState(null);

function updateDate(newDate) {
setDate(newDate);

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

function convertToDateString(fullDate) {
let month = fullDate.getMonth() + 1;
let date = fullDate.getDate();
return [
fullDate.getFullYear(),
month < 10 ? "0" + month : month,
date < 10 ? "0" + date : date
].join("-");
return [date, error, updateDate];
}

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

const isBookDisabled =
departingError ||
returningError ||
(tripType == returnFlight && returning < departing);

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

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

alert(message);
Expand All @@ -52,34 +61,36 @@ function App() {
<option value={returnFlight}>return flight</option>
</select>
</div>
<div class="form-group">
<div class={"form-group" + (departingError ? " has-error" : "")}>
<label class="form-label" for="departing-date">
Departing
</label>
<input
id="departing-date"
class="form-input"
type="date"
value={convertToDateString(departing)}
onInput={e => setDeparting(convertToDate(e.target.value))}
type="text"
value={departing}
onInput={e => setDeparting(e.target.value)}
/>
{departingError && <p class="form-input-hint">{departingError}</p>}
</div>
<div class="form-group">
<div class={"form-group" + (returningError ? " has-error" : "")}>
<label class="form-label" for="returning-date">
Returning
</label>
<input
id="returning-date"
class="form-input"
type="date"
value={convertToDateString(returning)}
onInput={e => setReturning(convertToDate(e.target.value))}
type="text"
value={returning}
onInput={e => setReturning(e.target.value)}
disabled={tripType !== returnFlight}
/>
{returningError && <p class="form-input-hint">{returningError}</p>}
</div>
<div class="form-group">
<button
disabled={tripType == returnFlight && returning < departing}
disabled={isBookDisabled}
onClick={bookFlight}
class="btn btn-primary"
>
Expand Down
Loading

0 comments on commit 8ca627c

Please sign in to comment.