Giter Club home page Giter Club logo

dmytro1991ua / react_listify Goto Github PK

View Code? Open in Web Editor NEW
7.0 1.0 2.0 1.64 MB

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

HTML 0.08% TypeScript 99.88% Shell 0.04%
expressjs firebase formik formik-mui material-ui mongodb nodejs reacr-router-dom react react-icons react-loader-spinner react-tes react-toastify vite vitest yup zustand moongose react-testing-library

react_listify's Introduction

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

1) Clone down this repository via HTTPS or SSH. You will need node and npm installed globally on your machine.
2) Create a .env file separately for root and client directories and set the following environment variables:

env file for root directory

NODE_ENV=development
PORT=8080
MONGODB_URI="mongodb+srv://your_connection_with_mongoDB"
FIREBASE_PROJECT_ID="your_firebase_project_id"
FIREBASE_KEY_ID="your_firebase_key_id"
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY---your_key_id-----END PRIVATE KEY-----\n"
FIREBASE_CLIENT_EMAIL="your_firebase_client_email"
FIREBASE_CLIENT_ID="your_firebase_client_id"
FIREBASE_AUTH_URI="your_firebase_auth_uri"
FIREBASE_TOKEN_URI="your_firebase_token_uri"
FIREBASE_AUTH_PROVIDER_X509_CERT_URL="your_firebase_auth_provider_cert_url"
FIREBASE_CLIENT_X509_CERT_URL="your_firebase_client_cert_url"

env file for client directory

 VITE_FIREBASE_API_KEY=your_firebase_api_key
 VITE_AUTH_DOMAIN=yor_firebase_auth_domain
 VITE_PROJECT_ID=your_firebase_project_id
 VITE_STORAGE_BUCKET=your_firebase_storage_bucket
 VITE_MESSAGING_SENDER_ID=your_firebase_sender_id
 VITE_MESSAGING_APP_ID=1:your_firebase_messaging_app_id
 VITE_API_BASE_URL=your_base_url
 VITE_NODE_ENV=development
3) 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
    
  • 4) 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 edit a particular shopping list's name
  • 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 delete all selected product items all together 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
  • Ability to add to and remove a specific shopping list from favorites,
  • Ability to select all shopping lists for further deletion,
  • Ability to delete all selected shopping lists all together at once, 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
PUT: /api/shopping-lists/select-all-shopping-lists - Selects all shopping lists for the further deletion

Example of returned data: Untitled

{
    "_id": "658166208bcf2cdf0c607ac4",
    "user": "Xhp3G87YBhaq29QWOWi0WYExxJp1",
    "name": "Terra Store",
    "currency": "$",
    "shoppingListItems": [],
    "isFavorite": false,
    "isChecked": true,
    "createdAt": "2023-12-19T09:45:04.269Z",
    "updatedAt": "2023-12-19T10:22:19.224Z",
    "__v": 0
}
PUT: /api/shopping-lists/delete-all-shopping-lists - Delete all selected shopping lists altogether at once

Example of returned data: Untitled_2

{
    "success": true,
    "message": "All shopping lists have been deleted successfully",
    "data": []
}
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'
  }
]
PUT: /api/shopping-lists/:id/add-to-favorites - Adds to or remove a specific shopping-list from favorites

Example of returned data:

example_1

{
    "_id": "656b2103c7ed1d8b57e15168",
    "user": "Xhp3G87YBhaq29QWOWi0WYExxJp1",
    "name": "Cosmopolitan Cocktail",
    "currency": "$",
    "shoppingListItems": [],
    "isFavorite": true,
    "createdAt": "2023-12-02T12:20:19.458Z",
    "updatedAt": "2023-12-02T12:41:48.016Z",
    "__v": 0
}
PUT: /api/shopping-lists/:id/edit-shopping-list - Edits a particular shopping list's name

Example of returned data:

example_2

{
    "_id": "656b20b9c7ed1d8b57e15166",
    "user": "Xhp3G87YBhaq29QWOWi0WYExxJp1",
    "name": "Shepherd's pie",
    "currency": "$",
    "shoppingListItems": [],
    "isFavorite": true,
    "createdAt": "2023-12-02T12:19:05.416Z",
    "updatedAt": "2023-12-02T12:47:52.872Z",
    "__v": 0
}
PUT: /api/shopping-lists/:id/select-all-product-items - Selects all product items

Example of returned data:

Untitled_3

{
    "_id": "6581760b8bcf2cdf0c607af0",
    "user": "Xhp3G87YBhaq29QWOWi0WYExxJp1",
    "name": "Terra store",
    "currency": "$",
    "shoppingListItems": [
        {
            "name": "Yogurt",
            "quantity": 1,
            "units": "L",
            "price": 2,
            "isChecked": true,
            "_id": "658176548bcf2cdf0c607af2",
            "createdAt": "2023-12-19T11:32:23.800Z",
            "updatedAt": "2023-12-19T11:32:23.800Z"
        },
        {
            "name": "Milk",
            "quantity": 1,
            "units": "L",
            "price": 4,
            "isChecked": true,
            "_id": "658176608bcf2cdf0c607af8",
            "createdAt": "2023-12-19T11:32:23.800Z",
            "updatedAt": "2023-12-19T11:32:23.800Z"
        }
    ],
    "isFavorite": false,
    "isChecked": false,
    "createdAt": "2023-12-19T10:52:59.489Z",
    "updatedAt": "2023-12-19T11:32:23.800Z",
    "__v": 0
}
PUT: /api/shopping-lists/:id/delete-all-product-items - Deletes all selected product items

Example of returned data:

Untitled_4

{
    "success": true,
    "message": "All product items have been deleted successfully",
    "data": {
        "_id": "6581760b8bcf2cdf0c607af0",
        "user": "Xhp3G87YBhaq29QWOWi0WYExxJp1",
        "name": "Terra store",
        "currency": "$",
        "shoppingListItems": [],
        "isFavorite": false,
        "isChecked": false,
        "createdAt": "2023-12-19T10:52:59.489Z",
        "updatedAt": "2023-12-19T11:37:09.763Z",
        "__v": 0
    }
}

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 the 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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.