Liven to buy is an application that simulates a virtual store, where it is possible to add fake products to a cart and make a fake purchase.
This application was developed during @liven training week.
The layout of this application is available on Figma.
This application was hosted by Netlify and can be found here: Liven to Buy.
This application uses the following technologies:
- TypeScript
- React
- React Router (Routing)
- Redux (Global state management)
- Redux Thunk (Thunk middleware)
- Formik (Form management)
- Yup (Schema builder)
- Date FNS (Date formatting)
- React Icons (Popular icons)
- React Text Mask (Input masking)
Thanks to Formik and Yup, the management and validation of forms became easy to carry out the manipulation of the input data.
const { values, errors, handleChange, submitForm } = useFormik({
initialValues: {
email: '',
password: '',
},
validationSchema: Yup.object({
email: Yup.string().email('Invalid email.').required('Required field.'),
password: Yup.string().required('Required field.'),
}),
onSubmit: ({ email, password }) => handleSubmitForm(email, password),
validateOnChange: false,
})
With the hook useProducts it was possible to reuse the logic of ordering the products at the beginning of the application.
const useProducts = (): {
productsById: { [key: string]: Product }
productsList: Product[]
} => {
const dispatch = useDispatch()
const productsById = useSelector((state: AppState) => state.products.byId)
const productsList = useMemo(
() => Object.keys(productsById).map(key => productsById[key]),
[productsById],
)
useEffect(() => {
if (Object.keys(productsById).length > 0) return
dispatch(getProducts())
}, [dispatch, productsById])
return {
productsById,
productsList,
}
}
With the contexts, it was possible to use a simpler way of sharing states between the components.
export const NotificationContext = React.createContext<NotificationData>(
{} as NotificationData,
)
export const NotificationProvider: React.FC = ({ children }) => {
const [notification, setNotification] = useState<Notification>({
open: false,
title: '',
description: '',
})
const showNotification = useCallback((title: string, description: string) => {
setNotification({
open: true,
title,
description,
})
}, [])
const hideNotification = useCallback(() => {
setNotification(oldNotification => ({
...oldNotification,
open: false,
}))
}, [])
return (
<NotificationContext.Provider
value={{ notification, showNotification, hideNotification }}
>
{children}
<Notification />
</NotificationContext.Provider>
)
}
const useNotification = (): NotificationData => {
const context = useContext(NotificationContext)
if (!context) {
throw new Error(
'useNotification must be used within a NotificationProvider',
)
}
return context
}
With the hook useMemo, it was possible to create a memorized value for a variable and this value will only change if one of its dependencies changes.
const useCart = (): {
// ...
} => {
// ...
const {
products: selectedProducts,
// ...
} = useSelector((state: AppState) => state.cart)
const { productsById } = useProducts()
const cartProducts: Product[] = useMemo(() => {
return selectedProducts.map(selectedProduct => ({
...productsById[selectedProduct.id],
quantity: selectedProduct.quantity,
}))
}, [selectedProducts, productsById])
const haveCartProducts = useMemo(() => cartProducts.length > 0, [
cartProducts,
])
// ...
}
- Name HTML tags and CSS classes
- Understand the flow of Redux Thunk
- Handling input date
- Handle cart loading on session
- View purchase summary page
Made with 💚 by Igor Almeida