Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions frontend/components/OrderList.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import React from 'react'
import React, { useMemo, useState } from 'react'
import { useGetOrdersQuery } from '../state/ordersApi'

export default function OrderList() {
const orders = []
const { data: orders = [] } = useGetOrdersQuery()
const [size, setSize] = useState('All')

const filtered = useMemo(() => {
return size === 'All' ? orders : orders.filter(o => o.size === size)
}, [orders, size])

return (
<div id="orderList">
<h2>Pizza Orders</h2>
<ol>
{
orders.map(() => {
filtered.map((ord) => {
return (
<li key={1}>
<li key={ord.id}>
<div>
order details here
{`${ord.customer} ordered a size ${ord.size} with ${ord.toppings ? ord.toppings.length : 'no'} toppings`}
</div>
</li>
)
Expand All @@ -21,12 +28,16 @@ export default function OrderList() {
<div id="sizeFilters">
Filter by size:
{
['All', 'S', 'M', 'L'].map(size => {
const className = `button-filter${size === 'All' ? ' active' : ''}`
['All', 'S', 'M', 'L'].map(s => {
const className = `button-filter${s === size ? ' active' : ''}`
return <button
data-testid={`filterBtn${size}`}
data-testid={`filterBtn${s}`}
className={className}
key={size}>{size}</button>
key={s}
onClick={() => setSize(s)}
>
{s}
</button>
})
}
</div>
Expand Down
58 changes: 39 additions & 19 deletions frontend/components/PizzaForm.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
import React from 'react'

const initialFormState = { // suggested
fullName: '',
size: '',
'1': false,
'2': false,
'3': false,
'4': false,
'5': false,
}
import { useSelector, useDispatch } from 'react-redux'
import { useCreateOrderMutation } from '../state/ordersApi'
import { fieldChanged, bundleOrder, resetForm } from '../state/pizzaFormSlice'

export default function PizzaForm() {
const dispatch = useDispatch()
const form = useSelector(state => state.pizzaForm)
const [createOrder, { isLoading, isError, error, }] = useCreateOrderMutation()

const handleChange = e => {
const { name, type, checked, value } = e.target
dispatch(fieldChanged({ name, value: type === 'checkbox' ? checked : value }))
}


const onSubmit = e => {
e.preventDefault()
const { payload } = bundleOrder(form)
createOrder(payload)
.unwrap()
.then(() => dispatch(resetForm()))
.catch((err) => err)
}

return (
<form>
<form onSubmit={onSubmit}>
<h2>Pizza Form</h2>
{true && <div className='pending'>Order in progress...</div>}
{true && <div className='failure'>Order failed: fullName is required</div>}
{isLoading && <div className='pending'>Order in progress...</div>}
{isError && <div className='failure'>{error?.data?.message}</div>}

<div className="input-group">
<div>
Expand All @@ -26,14 +38,22 @@ export default function PizzaForm() {
name="fullName"
placeholder="Type full name"
type="text"
value={form.fullName}
onChange={handleChange}
/>
</div>
</div>

<div className="input-group">
<div>
<label htmlFor="size">Size</label><br />
<select data-testid="sizeSelect" id="size" name="size">
<select
data-testid="sizeSelect"
id="size"
name="size"
value={form.size}
onChange={handleChange}
>
<option value="">----Choose size----</option>
<option value="S">Small</option>
<option value="M">Medium</option>
Expand All @@ -44,19 +64,19 @@ export default function PizzaForm() {

<div className="input-group">
<label>
<input data-testid="checkPepperoni" name="1" type="checkbox" />
<input data-testid="checkPepperoni" name="1" type="checkbox" onChange={handleChange} checked={form['1']} />
Pepperoni<br /></label>
<label>
<input data-testid="checkGreenpeppers" name="2" type="checkbox" />
<input data-testid="checkGreenpeppers" name="2" type="checkbox" onChange={handleChange} checked={form['2']} />
Green Peppers<br /></label>
<label>
<input data-testid="checkPineapple" name="3" type="checkbox" />
<input data-testid="checkPineapple" name="3" type="checkbox" onChange={handleChange} checked={form['3']} />
Pineapple<br /></label>
<label>
<input data-testid="checkMushrooms" name="4" type="checkbox" />
<input data-testid="checkMushrooms" name="4" type="checkbox" onChange={handleChange} checked={form['4']} />
Mushrooms<br /></label>
<label>
<input data-testid="checkHam" name="5" type="checkbox" />
<input data-testid="checkHam" name="5" type="checkbox" onChange={handleChange} checked={form['5']} />
Ham<br /></label>
</div>
<input data-testid="submit" type="submit" />
Expand Down
29 changes: 29 additions & 0 deletions frontend/state/ordersApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

export const ordersApi = createApi({
reducerPath: 'ordersApi',
baseQuery: fetchBaseQuery({
baseUrl: 'http://localhost:9009/api/pizza/',
}),
tagTypes: ['Orders'],
endpoints: (build) => ({
getOrders: build.query({
query: () => 'history',
providesTags: ['Orders'],
}),
createOrder: build.mutation({
query: (payload) => ({
url: 'order',
method: 'POST',
body: payload
}),
invalidatesTags: ['Orders']
})
})

})

export const {
useGetOrdersQuery,
useCreateOrderMutation,
} = ordersApi
46 changes: 46 additions & 0 deletions frontend/state/pizzaFormSlice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { createSlice } from "@reduxjs/toolkit";

const initialState = { // suggested
fullName: '',
size: '',
'1': false,
'2': false,
'3': false,
'4': false,
'5': false,
}

const TOPPING_IDS = ['1', '2', '3', '4', '5']

const pizzaFormSlice = createSlice({
name: 'pizzaForm',
initialState,
reducers: {
bundleOrder: {
prepare: (form) => {
const payload = {
fullName:form.fullName.trim(),
size: form.size,
toppings: TOPPING_IDS.filter(id => form[id]),
}
return { payload }
},
reducer: (state, action) => {
state.lastPayload = action.payload
}
},
fieldChanged: (state, action) => {
const { name, value } = action.payload
state[name] = value
},
resetForm: () => initialState
}
})

export const {
bundleOrder,
fieldChanged,
resetForm
} = pizzaFormSlice.actions

export default pizzaFormSlice.reducer
5 changes: 5 additions & 0 deletions frontend/state/store.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { configureStore } from '@reduxjs/toolkit'
import { ordersApi } from './ordersApi'
import pizzaFormReducer from './pizzaFormSlice'

const exampleReducer = (state = { count: 0 }) => {
return state
Expand All @@ -7,11 +9,14 @@ const exampleReducer = (state = { count: 0 }) => {
export const resetStore = () => configureStore({
reducer: {
example: exampleReducer,
[ordersApi.reducerPath]: ordersApi.reducer,
pizzaForm: pizzaFormReducer
// add your reducer(s) here
},
middleware: getDefault => getDefault().concat(
// if using RTK Query for your networking: add your middleware here
// if using Redux Thunk for your networking: you can ignore this
ordersApi.middleware
),
})

Expand Down