Skip to content

Commit

Permalink
Merge pull request #66 from jpedroh/refactor-react-query
Browse files Browse the repository at this point in the history
feature: alter front end to use react query and bump to react 18.
  • Loading branch information
jpedroh authored Sep 6, 2022
2 parents 52a162b + 9473e4f commit 32db617
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 299 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 12
node-version: 16
- run: yarn install --frozen-lockfile
- run: npx semantic-release
env:
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
"@types/node": "^15.0.1",
"conventional-changelog-conventionalcommits": "^4.6.0",
"jest": "^26.2.2",
"nx": "14.6.4",
"semantic-release": "^17.4.3",
"ts-jest": "^26.1.4",
"typescript": "^4.2.4",
"nx": "14.6.4"
"typescript": "^4.8.2"
},
"scripts": {
"test": "yarn jest",
Expand Down
7 changes: 4 additions & 3 deletions packages/front/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"dependencies": {
"@craco/craco": "^6.1.2",
"@mach/common": "*",
"@tanstack/react-query": "^4.2.3",
"@testing-library/jest-dom": "^5.12.0",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^12.8.3",
Expand All @@ -14,10 +15,10 @@
"@types/react": "^17.0.5",
"@types/react-dom": "^17.0.3",
"@types/react-router-dom": "^5.1.7",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-infinite-scroll-component": "^6.1.0",
"react-router-dom": "^5.2.0",
"react-router-dom": "6",
"typescript": "^4.2.4",
"web-vitals": "^1.1.2"
},
Expand Down
18 changes: 10 additions & 8 deletions packages/front/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { FC } from 'react'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import { FlightsProvider } from './contexts/FlightsContext'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import Home from './views/Home'
import Search from './views/Search'

const queryClient = new QueryClient()

const App: FC = () => {
return (
<FlightsProvider>
<QueryClientProvider client={queryClient}>
<BrowserRouter basename={import.meta.env.BASE_URL}>
<Switch>
<Route exact path={'/'} component={Home} />
<Route exact path={'/search'} component={Search} />
</Switch>
<Routes>
<Route path={'/'} element={<Home />} />
<Route path={'/search'} element={<Search />} />
</Routes>
</BrowserRouter>
</FlightsProvider>
</QueryClientProvider>
)
}

Expand Down
15 changes: 5 additions & 10 deletions packages/front/src/components/SearchFlightsForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
import { ChangeEventHandler, FC, FormEventHandler, useState } from 'react'
import Alert from '../Alert'
import Button from '../Button'
import FormInput from '../FormInput'
import styles from './index.module.css'

type SearchFlightsFormFields = { departureIcao: string; arrivalIcao: string }
export type SearchFlightsFormFields = { departureIcao: string; arrivalIcao: string }

type Props = {
onSubmit: (params: Partial<SearchFlightsFormFields>) => void
loading: boolean
error: string
}

const SearchFlightsForm: FC<Props> = ({ onSubmit, loading, error }) => {
const SearchFlightsForm: FC<Props> = ({ onSubmit }) => {
const [form, setForm] = useState<SearchFlightsFormFields>({
arrivalIcao: '',
departureIcao: ''
})

const isSubmitDisabled = form.arrivalIcao.trim().length === 0 && form.departureIcao.trim().length === 0

const onChange: ChangeEventHandler<HTMLInputElement> = evt => {
setForm(form => ({
...form,
Expand All @@ -35,8 +34,6 @@ const SearchFlightsForm: FC<Props> = ({ onSubmit, loading, error }) => {

return (
<form className={styles.container} onSubmit={handleSubmit}>
{error ? <Alert>{error}</Alert> : ''}

<div>
<label>Departure ICAO</label>
<FormInput
Expand All @@ -57,9 +54,7 @@ const SearchFlightsForm: FC<Props> = ({ onSubmit, loading, error }) => {
/>
</div>

<Button type="submit" disabled={loading}>
{loading ? 'Loading' : 'Search flights'}
</Button>
<Button type="submit" disabled={isSubmitDisabled}>Search flights</Button>
</form>
)
}
Expand Down
45 changes: 0 additions & 45 deletions packages/front/src/contexts/FlightsContext/index.tsx

This file was deleted.

42 changes: 0 additions & 42 deletions packages/front/src/contexts/FlightsContext/reducer.ts

This file was deleted.

33 changes: 0 additions & 33 deletions packages/front/src/contexts/FlightsContext/types.tsx

This file was deleted.

16 changes: 16 additions & 0 deletions packages/front/src/hooks/use-extract-flight-parameters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useLocation } from "react-router-dom"

export function useExtractFlightParameters() {
const params = new URLSearchParams(useLocation().search)

let query: Record<string, string> = {}

if (params.get('departureIcao')) {
query.departureIcao = params.get('departureIcao')!
}
if (params.get('arrivalIcao')) {
query.arrivalIcao = params.get('arrivalIcao')!
}

return query
}
31 changes: 31 additions & 0 deletions packages/front/src/hooks/use-flights-query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Flight from '@mach/common';
import { useInfiniteQuery } from '@tanstack/react-query';
import http from "../utils/http";

export type FlightsQuery = Partial<{
departureIcao: string;
arrivalIcao: string;
}>

type FlightsResponse = {
items: Flight[];
count: number;
}

function fetchFlights(query: FlightsQuery & { offset: number }) {
return http<FlightsResponse>({ url: '//mach-api.herokuapp.com/flights', query: { ...query, limit: 30 } })
}

export function useFlightsQuery(params: FlightsQuery) {
const query = useInfiniteQuery({
queryKey: ['flights', params.departureIcao, params.arrivalIcao],
queryFn: ({ pageParam: offset = 0 }) => fetchFlights({ ...params, offset }),
getNextPageParam: (_, allPages) => allPages.reduce((prev, cur) => prev + cur.items.length, 0)
})

return {
...query,
data: query.data?.pages.flatMap(v => v.items) ?? [],
totalItems: query.data?.pages[0].count ?? 0
}
}
10 changes: 6 additions & 4 deletions packages/front/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App'
import reportWebVitals from './reportWebVitals'

ReactDOM.render(
const container = document.getElementById('root')
const root = createRoot(container)

root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
</React.StrictMode>
)

// If you want to start measuring performance in your app, pass a function
Expand Down
30 changes: 14 additions & 16 deletions packages/front/src/views/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
import { FC, useContext, useEffect } from 'react'
import { useHistory } from 'react-router-dom'
import { FC } from 'react'
import { useNavigate } from 'react-router-dom'
import Lead from '../components/Lead'
import SearchFlightsForm from '../components/SearchFlightsForm'
import { FlightsContext } from '../contexts/FlightsContext'
import SearchFlightsForm, { SearchFlightsFormFields } from '../components/SearchFlightsForm'
import GeneralLayout from '../layouts/GeneralLayout'

const Home: FC = () => {
const { state, loadFlights } = useContext(FlightsContext)
const history = useHistory()
const navigate = useNavigate()

useEffect(() => {
if (state.data.count > 0) {
history.push('/search')
const handleSubmit = (params: Partial<SearchFlightsFormFields>) => {
const urlParams = new URLSearchParams()
if (params.departureIcao) {
urlParams.set('departureIcao', params.departureIcao)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [state.data.count])
if (params.arrivalIcao) {
urlParams.set('arrivalIcao', params.arrivalIcao)
}
navigate(`/search?${urlParams.toString()}`);
}

return (
<GeneralLayout>
<Lead>To begin, fill at least one of the following fields.</Lead>
<SearchFlightsForm
onSubmit={params => loadFlights({ offset: 0, limit: 30, ...params })}
loading={state.loading}
error={state.error ? state.error.message : ''}
/>
<SearchFlightsForm onSubmit={handleSubmit} />
</GeneralLayout>
)
}
Expand Down
Loading

0 comments on commit 32db617

Please sign in to comment.