Constructing a Meals Stock Administration App – DZone – Uplaza

Today, eating places, meals banks, house kitchens, and another enterprise that offers with merchandise and meals that go dangerous rapidly have to have good meals stock administration. Kitchens keep organized and waste is saved to a minimal by conserving monitor of inventory, checking expiration dates, and managing utilization effectively.

I’ll present you the right way to make a Meals Stock Administration App on this information. With this app, customers can:

  1. Add meals objects or elements to the stock.
  2. Monitor the amount of every merchandise.
  3. Take away objects once they’re used or expired.
  4. Optionally, generate recipes or counsel makes use of for the objects.

The Meals Stock Administration App won’t solely monitor meals objects but in addition generate recipes primarily based on the obtainable elements utilizing a Hugging Face mannequin. I’ll use Subsequent.js for the entrance finish, Materials-UI for the person interface, Firebase Firestore for real-time database performance, and a Hugging Face mannequin for recipe era.

Setting Up the Setting for Growth

We have to arrange our working atmosphere earlier than we begin writing code for our Meals Stock Administration App.

1. Set up Node.js and npm

Step one is to put in Node.js and npm. Go to the Node.js web site and get the Lengthy Time period Assist model to your laptop’s working system. Comply with the steps given for set up.

2. Making a Venture With Subsequent.js

Begin up your terminal and go to the situation the place you need to make your venture. After that, run these instructions:

  • npx create-next-app@newest food-inventory-management-app (With the @newest flag, npm will get the latest model of the Subsequent.js beginning setup.)
  • cd food-inventory-management-app

It would make a brand new Subsequent.js venture and take you to its path. You may be given quite a few configuration selections through the setup course of, set them as given under:

  • Would you want to make use of TypeScript? No
  • Would you want to make use of ESLint? Sure
  • Would you want to make use of Tailwind CSS? No
  • Would you want to make use of the src/ listing? No
  • Would you want to make use of App Router? Sure
  • Would you prefer to customise the default import alias? No

3. Putting in Firebase and Materials-UI

Within the listing of your venture, execute the next command:

  • npm set up @mui/materials @emotion/react @emotion/styled firebase

Setting Up Firebase

  • Launch a brand new venture on the Firebase Console.
  • Click on “Add app” after your venture has been constructed, then select the net platform (>).
  • Give your app a reputation if you register it, similar to “Food Inventory Management App.”
  • Make a duplicate of the Firebase setup file. Afterwards, this will likely be helpful.

4. Create a Firebase Configuration File

Make a brand new file referred to as firebase.js within the root listing of your venture and add the next code, changing the placeholders with the actual Firebase settings to your venture:

import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT_ID.appspot.com",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
appId: "YOUR_APP_ID"
 };

const app = initializeApp(firebaseConfig);

const db = getFirestore(app);

export { db };

Constructing a Flask API for Recipe Technology Utilizing Hugging Face

I am going to present you the right way to make a Flask-based API that makes use of a Hugging Face mannequin to make recipes. With a POST request, customers will be capable to ship elements to the API. It would then use a pre-trained mannequin from Hugging Face to return a recipe primarily based on these elements. We’ll use atmosphere variables to soundly deal with Hugging Face tokens.

1. Setting Up the Python Setting

  • Set up Python if not already current (brew set up python).
  • Confirm set up (python3 --version).
  • Set up dependencies (pip set up Flask flask-cors transformers huggingface_hub).

2. Setting Up the Hugging Face Token

  • Go to the Hugging Face web site.
  • If you have already got an account, click on on Signal In. If not, click on Signal Up to create a brand new account.
  • Navigate to the dropdown menu, and choose Settings.
  • Within the Settings menu, search for the Entry Tokens tab on the left facet of the web page and click on on it.
  • Below the Entry Tokens part, you will notice a button to create a brand new token. Click on on New Token.
  • Give your token a descriptive identify (e.g., “Food Inventory App Token”).
  • Select Learn because the token scope for fundamental entry to fashions and datasets. In the event you want write entry for importing fashions or knowledge, select Write.
  • Click on Generate Token. The token will likely be displayed on the display.
  • After producing the token, copy it. Make sure that to put it aside in a safe place, as you’ll need it for authentication when making API calls.

3. Conserving Hugging Face API Token Protected

Your Hugging Face API token must be saved safely in an atmosphere variable as a substitute of being written in your script as code. To do that:

  • Create an .env file within the root of your venture: (contact .env).
  • Inside this file, add your Hugging Face token (HF_TOKEN=your_hugging_face_token_here).
  • Load this atmosphere variable securely in your Flask app utilizing Python’s os module.
import os
huggingface_token = os.getenv('HF_TOKEN')

4. Constructing the Flask API

Flask app with Hugging Face’s recipe era mannequin (notice: this pattern mannequin is free). Title the file as backend.py.

import os
from flask import Flask, request, jsonify
from flask_cors import CORS
from huggingface_hub import login
from transformers import pipeline

app = Flask(__name__)
CORS(app)

# Securely get the Hugging Face token from the atmosphere
huggingface_token = os.getenv('HF_TOKEN')
if huggingface_token:
    login(token=huggingface_token)

# Load Hugging Face meals recipe mannequin pipeline
strive:
    model_name = "flax-community/t5-recipe-generation"
    recipe_generator = pipeline("text2text-generation", mannequin=model_name)
besides Exception as e:
    print(f"Error loading model: {e}")
    recipe_generator = None

@app.route('/generate_recipe', strategies=['POST'])
def generate_recipe():
    knowledge = request.json
    print("Hello")
    elements = knowledge.get('elements')
    if not elements:
        return jsonify({"error": "Ingredients not provided."}), 500
    if recipe_generator:
        strive:
            response = recipe_generator(f"Generate a recipe using the following ingredients: {ingredients}")
            return jsonify({"recipe": response[0]['generated_text']})
        besides Exception as e:
            print(f"Error generating recipe: {e}")
            return jsonify({"error": "Error generating recipe"}), 500
    else:
        return jsonify({"error": "Recipe generator model is not available."}), 500

if __name__ == '__main__':
    app.run(debug=True, port=5001)
  • Notice: The flax-community/t5-recipe-generation mannequin is loaded utilizing the Hugging Face pipeline. This mannequin will be utilized to generate recipes utilizing the given/saved elements.

Constructing the Core Elements for the Meals Stock Administration

1. Import All Needed Libraries

'use shopper';

import React, { useEffect, useState } from 'react';
import { Field, Stack, Typography, Button, TextField, IconButton, Tabs, Tab } from '@mui/materials';
import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { assortment, addDoc, deleteDoc, doc, onSnapshot, updateDoc, question, the place, getDocs } from 'firebase/firestore';
import { db } from './firebase'; // Firebase configuration
import DeleteIcon from '@mui/icons-material/Delete';
import dayjs from 'dayjs';
import axios from 'axios';

On this step, we arrange our part with the essential format and imports it wants. It is a client-side part, as proven by the 'use shopper' command on the high.

2. Utility Features

# We outline a utility operate that capitalizes the primary letter of a string.
const capitalizeFirstLetter = (string) => string.charAt(0).toUpperCase() + string.slice(1);

3. State Administration and useEffect for Firestore Snapshot

We have to arrange states to maintain monitor of pantry objects, new merchandise enter, expiration dates, search queries, lively tabs, and recipe strategies.

  • objects: Shops pantry objects
  • newItem: Shops the identify of the merchandise to be added
  • expirationDate: Shops the expiration date of the brand new merchandise
  • searchQuery: Shops the search enter for filtering objects
  • tabIndex: Shops the present tab (Accessible, Quickly to Expire, Expired)
  • recipe: Shops the generated recipe

The useEffect hook screens adjustments in Firestore knowledge utilizing the onSnapshot technique, making certain that the pantry objects are at all times updated.

export default operate Pantry() {
  const [items, setItems] = useState([]); 
  const [newItem, setNewItem] = useState(''); 
  const [expirationDate, setExpirationDate] = useState(null); 
  const [searchQuery, setSearchQuery] = useState(''); 
  const [tabIndex, setTabIndex] = useState(0); 
  const [recipe, setRecipe] = useState(''); 

  // Fetch objects from Firestore and replace state in real-time
  useEffect(() => {
    const unsubscribe = onSnapshot(assortment(db, 'pantryItems'), (snapshot) => {
      const itemsList = snapshot.docs.map((doc) => ({
        id: doc.id,
        identify: doc.knowledge().identify,
        amount: doc.knowledge().amount,
        expirationDate: doc.knowledge().expirationDate,
      }));
      setItems(itemsList);
    });
    return () => unsubscribe();
  }, []);

4. Add a New Merchandise to Firestore

This operate is used so as to add a brand new merchandise to the Firestore database. If the merchandise is already current, its amount is elevated. Alternatively, the brand new merchandise will be added with a chosen expiration date.

  // Add a brand new merchandise to Firestore
  const addItemToFirestore = async () => {
    if (newItem.trim() !== '' && expirationDate) {
      const q = question(assortment(db, 'pantryItems'), the place('identify', '==', newItem));
      const querySnapshot = await getDocs(q);

      if (querySnapshot.empty) {
        await addDoc(assortment(db, 'pantryItems'), { identify: newItem, amount: 1, expirationDate: expirationDate.toISOString() });
      } else {
        querySnapshot.forEach(async (doc) => {
          const itemRef = doc(db, 'pantryItems', doc.id);
          await updateDoc(itemRef, { amount: doc.knowledge().amount + 1 });
        });
      }

      setNewItem('');
      setExpirationDate(null);
    }
  };

5. Take away an Merchandise from Firestore or Lower Its Amount

This operate both decreases the amount of an current merchandise or removes the merchandise totally if the amount reaches zero.

  // Take away an merchandise or lower its amount
  const removeItemFromFirestore = async (id) => {
    const itemRef = doc(db, 'pantryItems', id);
    const itemDoc = await getDoc(itemRef);

    if (itemDoc.exists()) {
      const currentQuantity = itemDoc.knowledge().amount;

      if (currentQuantity > 1) {
        await updateDoc(itemRef, { amount: currentQuantity - 1 });
      } else {
        await deleteDoc(itemRef);
      }
    }
  };

6. Fetch Recipe Solutions From Flask Backend

This operate sends a listing of obtainable objects and objects which might be near their expiration date to the Flask backend for recipe era. The backend generates a recipe and shops it within the recipe state.

  // Fetch recipe strategies utilizing elements
  const fetchRecipeSuggestions = async (availableItems, soonToExpireItems) => {
    const elements = [...availableItems, ...soonToExpireItems].map(merchandise => merchandise.identify).be part of(', ');

    strive {
      const response = await axios.put up('http://127.0.0.1:5001/generate_recipe', { elements });
      setRecipe(response.knowledge.recipe);
    } catch (error) {
      console.error('Error fetching recipe strategies:', error.message);
      setRecipe('Error fetching recipe strategies. Please strive once more later.');
    }
  };

7. Filter and Categorize Objects Based mostly on Expiration

The pantry objects are sorted in line with their expiration dates. Three classes will be established: Accessible Objects, Quickly to Expire, and Expired Objects.

  // Filter and categorize objects primarily based on expiration
  const filteredItems = objects.filter((merchandise) => merchandise.identify.toLowerCase().consists of(searchQuery.toLowerCase()));
  const soonToExpireItems = filteredItems.filter((merchandise) => dayjs(merchandise.expirationDate).diff(dayjs(), 'day')  dayjs(merchandise.expirationDate).diff(dayjs(), 'day')  !soonToExpireItems.consists of(merchandise) && !expiredItems.consists of(merchandise));

Constructing the UI Elements for the Meals Stock Administration

  return (
    
      
        {/* Add new pantry merchandise */}
        
          Add Pantry Merchandise
           setNewItem(e.goal.worth)} />
           setExpirationDate(newValue)} />
          
        

        {/* Search and Tabs */}
         setSearchQuery(e.goal.worth)} />
         setTabIndex(newValue)}>
          
          
          
        

        {/* Show Objects */}
        {tabIndex === 0 && availableItems.map((merchandise) => (
          
            {capitalizeFirstLetter(merchandise.identify)} - {merchandise.amount}
             removeItemFromFirestore(merchandise.id)}>
          
        ))}
        {tabIndex === 1 && soonToExpireItems.map((merchandise) => (
          
            {capitalizeFirstLetter(merchandise.identify)} - {merchandise.amount} (Expires: {dayjs(merchandise.expirationDate).format('YYYY-MM-DD')})
             removeItemFromFirestore(merchandise.id)}>
          
        ))}
        {tabIndex === 2 && expiredItems.map((merchandise) => (
          
            {capitalizeFirstLetter(merchandise.identify)} - {merchandise.amount} (Expired: {dayjs(merchandise.expirationDate).format('YYYY-MM-DD')})
             removeItemFromFirestore(merchandise.id)}>
          
        ))}

        {/* Fetch Recipe Solutions */}
        
        {recipe && {recipe}}
      
    
  );
}

Clarification of UI Elements

1. (Container)

  • Goal: Acts as a versatile container for managing format, padding, and alignment
  • Used for: Wrapping sections like the shape, search bar, and merchandise lists

2. (Vertical/Horizontal Structure)

  • Goal: Organizes youngster elements in a vertical or horizontal format
  • Used for: Structuring kind components and merchandise listings with correct spacing

3. (Textual content Show)

  • Goal: Renders and types textual content content material
  • Used for: Displaying headings, merchandise names, expiration dates, and recipe strategies

4. (Enter Subject)

  • Goal: Supplies a textual content enter subject.
  • Used for: Inputting new pantry merchandise names and search queries

5. (Date Choice)

  • Goal: Permits customers to choose a date from a calendar
  • Used for: Deciding on expiration dates for pantry objects, built-in with the Day.js adapter

6. (Clickable Button)

  • Goal: A clickable button for actions
  • Used for: Including objects to Firestore, fetching recipes, and interacting with the database

7. and (Tab Navigation)

  • Goal: Creates a tabbed interface for navigation
  • Used for: Switching between obtainable, soon-to-expire, and expired objects

8. (Icon-Based mostly Button)

  • Goal: Button with an icon for fast actions.
  • Used for: Deleting or decreasing the amount of things, utilizing a delete icon

9. (Date Localization)

  • Goal: Manages date localization and formatting
  • Used for: Guaranteeing right show and dealing with of dates within the date picker

10. (Icon)

  • Goal: Shows a delete icon for motion
  • Used for: Indicating delete motion on buttons for merchandise removing

11. Recipe Suggestion Part

  • Goal: Shows recipe strategies primarily based on obtainable elements
  • Used for: Displaying the recipe generated by the Flask API when the “Get Recipe Suggestions” button is clicked

12. (Responsive Structure)

  • Goal: Creates responsive layouts with versatile columns.
  • Used for aligning content material: Organizing components like kinds and buttons inside a structured grid.
  • Dividing UI into columns: Structuring content material into columns and rows for a clear, responsive format on numerous display sizes.

Working the Meals Stock Administration Utility

1. Begin the Growth Server

Navigate to http://localhost:3000 as prompted by opening your browser.

2. Begin the Flask Growth Server

Begin the Flask Growth Server together with the under.

This may provoke the Flask API at http://127.0.0.1:5001.

Please keep in mind the interplay between React and Flask is completed utilizing Axios to ship HTTP requests and show the ends in actual time.

The Hugging Face mannequin I used is free to make use of. If you wish to use a special mannequin, like Llama, you are able to do that too.

Pattern Picture of the Meals Stock Administration Utility After Growth

Conclusion

Congratulations! You’ve got efficiently developed a useful Meals Stock Administration Utility.

Glad coding!

Share This Article
Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *

Exit mobile version