/liven-to-buy

Virtual shop application developed for https://liven.tech training week.

Primary LanguageTypeScript

Project Logo

React JavaScript Redux Figma

🚀 Liven's online store 💥

Project Design 1 Project Design 2

Project Design 3

Summary

🔖 About

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.

🖼️ Layout

The layout of this application is available on Figma.

💻 Demo

This application was hosted by Netlify and can be found here: Liven to Buy.

🚀 Technologies

This application uses the following technologies:

📖 Learnings

  • Handling forms

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,
})
  • Sharing logics

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,
  }
}
  • Sharing simple states

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
}
  • Memorized values

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,
  ])

  // ...
}

💢 Difficulties

  • 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