2025-05-26 12:36:39 +02:00
2025-05-26 11:10:58 +02:00
2025-05-26 12:36:39 +02:00
2025-05-23 20:44:03 +02:00
2025-05-26 11:10:42 +02:00
2025-05-23 20:44:23 +02:00
2025-05-23 20:44:23 +02:00
2025-05-26 11:10:42 +02:00

Grocery Tracker

A web application for tracking grocery prices and shopping events. Built with FastAPI (Python) backend and React (TypeScript) frontend.

Features

  • Grocery Management: Add, edit, and track grocery items with prices, categories, and organic status
  • Shop Management: Manage different shops with locations
  • Shopping Events: Record purchases with multiple groceries and amounts
  • Price Tracking: Monitor price changes over time
  • Modern UI: Clean, responsive interface built with React and Tailwind CSS

Architecture

Technology Stack

Backend (Python):

  • FastAPI - Modern, fast web framework
  • SQLAlchemy - SQL toolkit and ORM
  • PostgreSQL - Relational database
  • Pydantic - Data validation and settings management
  • Alembic - Database migrations

Frontend (React):

  • React 18 with TypeScript
  • React Router - Client-side routing
  • Tailwind CSS - Utility-first CSS framework
  • Axios - HTTP client for API calls
  • React Hook Form - Form handling

Component Communication

┌─────────────────┐    HTTP/REST API    ┌─────────────────┐    SQL Queries    ┌─────────────────┐
│   React         │ ←─────────────────→ │   FastAPI       │ ←───────────────→ │   PostgreSQL    │
│   Frontend      │     JSON requests   │   Backend       │   SQLAlchemy ORM  │   Database      │
│   (Port 3000)   │     JSON responses  │   (Port 8000)   │                   │   (Port 5432)   │
└─────────────────┘                     └─────────────────┘                   └─────────────────┘

Data Model

Core Entities

Groceries (groceries table)

  • id: Integer, Primary key, Auto-increment
  • name: String, Grocery name (indexed, required)
  • category: String, Food category (required)
  • organic: Boolean, Organic flag (default: false)
  • weight: Float, Weight/volume (optional)
  • weight_unit: String, Unit of measurement (default: "piece")
    • Supported units: "g", "kg", "ml", "l", "piece"
  • created_at: DateTime, Creation timestamp (auto-generated)
  • updated_at: DateTime, Last update timestamp (auto-updated)

Shops (shops table)

  • id: Integer, Primary key, Auto-increment
  • name: String, Shop name (indexed, required)
  • city: String, Location city (required)
  • address: String, Full address (optional)
  • created_at: DateTime, Creation timestamp (auto-generated)
  • updated_at: DateTime, Last update timestamp (auto-updated)

Shopping Events (shopping_events table)

  • id: Integer, Primary key, Auto-increment
  • shop_id: Integer, Foreign key to shops (required)
  • date: DateTime, Purchase date (required, default: current time)
  • total_amount: Float, Total cost of shopping event (optional, auto-calculated)
  • notes: String, Optional notes about the purchase
  • created_at: DateTime, Creation timestamp (auto-generated)
  • updated_at: DateTime, Last update timestamp (auto-updated)

Association Table

Shopping Event Groceries (shopping_event_groceries table)

Many-to-many relationship between shopping events and groceries with additional data:

  • id: Integer, Primary key, Auto-increment
  • shopping_event_id: Integer, Foreign key to shopping_events (required)
  • grocery_id: Integer, Foreign key to groceries (required)
  • amount: Float, Quantity purchased in this event (required, > 0)
  • price: Float, Price at time of purchase (required, ≥ 0)

Relationships

┌─────────────────┐         ┌─────────────────────────────┐         ┌─────────────────┐
│     Shops       │         │  Shopping Event Groceries   │         │   Groceries     │
│                 │         │     (Association Table)     │         │                 │
│ • id            │ ←──────→│ • shopping_event_id         │ ←──────→│ • id            │
│ • name          │  1:N    │ • grocery_id                │  N:M    │ • name          │
│ • city          │         │ • amount                    │         │ • category      │
│ • address       │         │ • price                     │         │ • organic       │
│ • created_at    │         │                             │         │ • weight        │
└─────────────────┘         └─────────────────────────────┘         │ • weight_unit   │
         │                                  │                       │ • created_at    │
         │                                  │                       │ • updated_at    │
         │ 1:N                              │                       └─────────────────┘
         ▼                                  │
┌─────────────────┐                         │
│ Shopping Events │ ←───────────────────────┘
│                 │          1:N
│ • id            │
│ • shop_id       │
│ • date          │
│ • total_amount  │
│ • notes         │
│ • created_at    │
└─────────────────┘

Key Features

  • Price History: Each grocery purchase stores the price at that time, enabling price tracking
  • Flexible Quantities: Support for decimal amounts (e.g., 1.5 kg of apples)
  • Auto-calculation: Total amount can be automatically calculated from individual items
  • Free Items: Supports items with price 0 (samples, promotions, etc.)
  • Audit Trail: All entities have creation timestamps for tracking
  • Data Integrity: Foreign key constraints ensure referential integrity

Setup Instructions

Prerequisites

  1. Python 3.8+ - For the backend
  2. Node.js 16+ - For the frontend
  3. PostgreSQL - Database

Backend Setup

  1. Navigate to backend directory:

    cd backend
    
  2. Create virtual environment:

    python3 -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
    
  3. Install dependencies:

    pip install -r requirements.txt
    
  4. Setup database:

    # Create PostgreSQL database
    createdb grocery_tracker
    
    # Copy environment variables
    cp env.example .env
    
    # Edit .env with your database credentials
    nano .env
    
  5. Run database migrations:

    alembic upgrade head  # After setting up alembic
    
  6. Start the backend server:

    uvicorn main:app --reload
    

    The API will be available at http://localhost:8000 API docs at http://localhost:8000/docs

Frontend Setup

  1. Navigate to frontend directory:

    cd frontend
    
  2. Install dependencies:

    npm install
    
  3. Start the development server:

    npm start
    

    The app will be available at http://localhost:3000

API Endpoints

Groceries

  • GET /groceries/ - List all groceries
  • POST /groceries/ - Create new grocery
  • GET /groceries/{id} - Get specific grocery
  • PUT /groceries/{id} - Update grocery
  • DELETE /groceries/{id} - Delete grocery

Shops

  • GET /shops/ - List all shops
  • POST /shops/ - Create new shop
  • GET /shops/{id} - Get specific shop

Shopping Events

  • GET /shopping-events/ - List all shopping events
  • POST /shopping-events/ - Create new shopping event
  • GET /shopping-events/{id} - Get specific shopping event

Statistics

  • GET /stats/categories - Category spending statistics
  • GET /stats/shops - Shop visit statistics

Usage

  1. Add Shops: Start by adding shops where you buy groceries
  2. Add Groceries: Create grocery items with prices and categories
  3. Record Purchases: Use the "Add Purchase" form to record shopping events
  4. Track Prices: Monitor how prices change over time
  5. View Statistics: Analyze spending patterns by category and shop

Development

Running Tests

Backend:

cd backend
pytest

Frontend:

cd frontend
npm test

Database Migrations

cd backend
alembic revision --autogenerate -m "Description"
alembic upgrade head

Docker Deployment

Create docker-compose.yml for easy deployment:

version: '3.8'
services:
  db:
    image: postgres:15
    environment:
      POSTGRES_DB: grocery_tracker
      POSTGRES_USER: grocery_user
      POSTGRES_PASSWORD: your_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  backend:
    build: ./backend
    ports:
      - "8000:8000"
    depends_on:
      - db
    environment:
      DATABASE_URL: postgresql://grocery_user:your_password@db:5432/grocery_tracker

  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    depends_on:
      - backend

volumes:
  postgres_data:

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make changes
  4. Add tests
  5. Submit a pull request

License

MIT License

Description
No description provided
Readme 1.1 MiB
Languages
TypeScript 75.9%
Python 22.8%
Shell 0.4%
Dockerfile 0.4%
HTML 0.3%
Other 0.1%