Dmytro1991ua / react_listify

Listify is a smart application that helps you keep track of your favorite food and drink recipes and ingredients in general. You will be able to create a grocery list, proceed to its details, and then create a more detailed list of items you find interesting to keep an eye on.

Home Page:https://listify.up.railway.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Listify

Project Summary

Have you ever had a situation when you are going shopping or you just found an interesting food or drink recipe and definitely would like take a note, but you do not have any notepad or something like that at hand? Oh boy, I believe you have encountered this kind of situation.
Well, there is good news for you. Listify is a smart application that helps you keep track of your favorite food and drink recipes and ingredients in general. You will be able to create a grocery list, proceed to its details, and then create a more detailed list of items you find interesting to keep an eye on

Motivation

The main goal of this project is to keep practicing and improving skills, to make hands dirty in some new development frameworks, libraries, and tools, and eventually create some awesome and useful application

Getting Started

Step-by-step instructions on how to locally run the application

Clone down this repository via HTTPS or SSH. You will need node and npm installed globally on your machine.
In order to run the application you will need to follow the next steps:
  • Run npm run packages-install in order to install all project dependencies within root directory package.json as well as within client folder.
    npm run packages-install
    
  • In root directory run npm run server in order to run a server
    npm run server
    
  • In root directory run npm run client in order to run the project itself
    npm run client
    
  • The application will be available on http://localhost:5500

Features

Detailed information about what features the application is rich in

The main features of Listify application are the following:
  • User Authentication flow that consists of abilities to Sign-In via email/password and Google, Sign-Up via email/password and Google, Forgot password, Reset Password
  • Ability to create a shopping list with a specific name and currency.
  • Ability to delete a specific shopping list.
  • Ability to see the total price of all items within a specific shopping list and information on how many items were purchased and how many need to be bought via tooltip.
  • Ability to create/update/delete a specific product item within a specific shopping list
  • Ability to select individual product item (selected item appears at the bottom of the list and is sorted by their name) or select all product items at once.
  • Ability to see all items that should be bought or have been already purchased based on selected product items within a widget.
  • Ability to create a copy of a particular shopping list with all product items.
  • Ability to delete a particular shopping list with all product items.
  • Ability to update user name, picture, change password and apply some specific user preferences such as default currency or ability to calculate products price by their quantity within user's Profile, etc.

API

General information about existing application's API endpoints

User (/api/users)
GET: /api/me - Creates a current, registered Firebase user in MongoDB or updates it.

Example of returned data:

me

POST: /api/users/profile - Updates User's information, such as name, picture, etc.

Example of returned data:

profile

Shopping Lists (/api/shopping-lists)
GET: /api/shopping-lists - Gets all availble shopping lists from database

Example of returned data:

[
    {
        "_id": "63347da0b7fcd218f1024cab",
        "user": "qnjPpkmaWlUsCb5FqcbllcxYW7v1",
        "name": "Alex Smith",
        "currency": "â‚Ł",
        "shoppingListItems": [
            {
                "name": "New",
                "quantity": 2.5,
                "units": "L",
                "price": 14,
                "isChecked": true,
                "_id": "63347da9b7fcd218f1024cad",
                "updatedAt": "2022-11-10T18:22:46.639Z",
                "createdAt": "2022-11-10T18:22:45.299Z"
            },
            {
                "name": "Product-1",
                "quantity": 1,
                "units": "L",
                "price": 5,
                "isChecked": true,
                "_id": "6337f44583d311f66fb8b49e",
                "updatedAt": "2022-11-10T18:22:49.603Z",
                "createdAt": "2022-11-10T18:22:45.299Z"
            },
            {
                "name": "new Product-2",
                "quantity": 2,
                "units": "L",
                "price": 10,
                "isChecked": false,
                "_id": "633c708240ef8be1a1e502de",
                "updatedAt": "2022-11-10T18:23:06.310Z",
                "createdAt": "2022-11-10T18:22:45.299Z"
            }
        ],
        "createdAt": "2022-09-28T17:00:16.790Z",
        "updatedAt": "2022-11-10T18:23:06.310Z",
        "__v": 0
    },
]
POST: /api/shopping-lists - Creates a new shopping list

Example of returned data:

new list

DELETE: /api/shopping-lists/:id - Deletes a particular shopping list by its ID

Example of returned data:

"6370d06590f20bef1d2af00c" - id of deleted shopping list
Shopping List Details (/api/shopping-lists)
PUT: /api/shopping-lists/:id/create-product-item - Creates a new product item within a specific shopping list

Example of returned data:

new product item

DELETE: /api/shopping-lists/:id/delete-product-item - Deletes a new product item within a specific shopping list

Example of returned data:

delete product item

PUT: /api/shopping-lists/:id/select-product-item - Selects a particular product item

Example of returned data:

select product item

PUT: /api/shopping-lists/:id/edit-product-item - Updates a particular product item

Example of returned data:

edit product item

PUT: /api/shopping-lists/:id/select-all-product-items - Selects all product items

Example of returned data:

[
  {
    name: 'Another test product',
    quantity: 0,
    units: '',
    price: 0,
    isChecked: true,
    _id: '6371071ac4722436c000cd23',
    updatedAt: '2022-11-13T15:07:18.123Z',
    createdAt: '2022-11-13T15:07:18.123Z'
  },
  {
    name: 'Updated product item',
    quantity: 2,
    units: 'L',
    price: 12,
    isChecked: true,
    _id: '6370d5a190f20bef1d2af03e',
    updatedAt: '2022-11-13T15:07:18.123Z',
    createdAt: '2022-11-13T15:07:18.123Z'
  }
]

Products views

Visual presentation of Listify application

Shopping lists/Shopping list details/Profile pages
Sign-In/Sign-Up/Forgot-password/Reset-password pages
Modals

Tools/libraries/frameworks used

Client

This project was bootstrapped with a help of a new beast in the neighborhood - Vite.

State Management

As for state management perspectives, the choice fell on Zustand.
There is no global store within the application. Hence, particular modules have their own store configurations (client/src/app/modules/shopping-lists/shopping-lists.store.ts, client/src/app/modules/aauth/auth.store.ts, etc).
Example of store configuration
// create a store itself
export const useAuthStore = create<AuthStoreState & AuthStoreActions>()(
// devtools allows to create a Redux like Devtools in browser
  devtools(
  // set function allows to merges state
    (set) => ({
      ...initialState,
      setUser: (payload) => {
        return set((state) => ({ ...state, user: payload }), false, 'setUser');
      },
      setUserLoadingStatus: (payload) =>
        set((state) => ({ ...state, userLoadingStatus: payload }), false, 'setUserLoadingStatus'),
      setUpdateUser: (payload) => {
        return set(
          produce((state) => ({ user: { ...state.user, ...payload } })),
          false,
          'setUpdateUser'
        );
      },
      reset: () => set({ ...initialState, userLoadingStatus: 'idle' }, false, 'resetAuthStore'),
    }),
    { name: 'AuthStore' }
  )
);
Example of binding React component with the store
const Profile = (): ReactElement => {
  const user = useAuthStore((state) => state.user);

  return <h1>Hello {user.name}</h1>
}
Example of the binding store without React dependency.
export const validateUserAction = async (): Promise<void> => {
  const setUser = useAuthStore.getState().setUser;

  // the rest of the code
};

React UI component library

For the sake of simplicity, speeding up the application development and for more practice perspectives, the Material UI library was chosen

Forms

The application uses:
  • Formik for forms management.
  • The 3rd-party binding Formik-Mui for Material UI components.
  • Yup for forms validation
Example of Formik usage
interface AuthSignInFormProps {
  initialValues: SignInFormInitialValues;
  validationSchema: SchemaOf<SignInFormInitialValues, never>;
  onSubmit: (values: SignInFormInitialValues, actions: FormikHelpers<SignInFormInitialValues>) => Promise<void>;
}

const SignInForm = ({ initialValues, validationSema, onSubmit }: AuthSignInFormProps): ReactElement => {
  return (
    <Formik initialValues={initialValues} onSubmit={onSubmit} validationSchema={dtFormikExampleValidationSchema}>
      {({ submitForm, isSubmitting }) => (
        <Form>
          <Field component={TextField} name='email' type='email' label='Email' />
          <Field component={TextField} type='password' label='Password' name='password' />
          <Button variant='contained' color='primary' disabled={isSubmitting} onClick={submitForm}>
            Submit
          </Button>
        </Form>
      )}
    </Formik>
  );
};

Notifications

The application uses:

Usage:

  • In order to start using react-toastify just import toastService from client/src/services/toast.service.ts and then call needed method
toastService.success("Success message");
toastService.info("Info message");
toastService.warn("Warn message");
toastService.error("Error message");

Authentication flow

Aplication users Firebase flow, because it provides a wide range of useful methods to deal with user authentication

Icons

Aplication uses React Iconsthroughout different parts of the application.

Loader Spinner

Aplication uses React Loader Spinner package

Tests

General information about application testing flow, coverage, tests running instructions, etc.

The application uses the following testing libraries/frameworks:
In order to run tests, you need to proceed with the following command within the client directory:
cd client
----
npm run test
In order to check application's tests coverage, you need to proceed with the following command within the client directory:
cd client
----
npm run coverage
In order to open Vitest testing interface in the browser and run tests there, you need to proceed with the following command within the client directory:
cd client
----
npm run test:ui
Example of Vitest browser interface

screencapture-localhost-1666-vitest-2022-11-13-11_19_17

Current application's test coverage

screencapture-localhost-52791-client-coverage-index-html-2022-11-13-12_17_15 (1)

About

Listify is a smart application that helps you keep track of your favorite food and drink recipes and ingredients in general. You will be able to create a grocery list, proceed to its details, and then create a more detailed list of items you find interesting to keep an eye on.

https://listify.up.railway.app


Languages

Language:TypeScript 99.9%Language:HTML 0.1%Language:Shell 0.0%