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-incrementname: 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-incrementname: String, Shop name (indexed, required)city: String, Location city (required)address: String, Full address (optional)created_at: DateTime, Creation timestamp (auto-generated)
Shopping Events (shopping_events table)
id: Integer, Primary key, Auto-incrementshop_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 purchasecreated_at: DateTime, Creation timestamp (auto-generated)
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-incrementshopping_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
- Python 3.8+ - For the backend
- Node.js 16+ - For the frontend
- PostgreSQL - Database
Backend Setup
-
Navigate to backend directory:
cd backend -
Create virtual environment:
python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate -
Install dependencies:
pip install -r requirements.txt -
Setup database:
# Create PostgreSQL database createdb grocery_tracker # Copy environment variables cp env.example .env # Edit .env with your database credentials nano .env -
Run database migrations:
alembic upgrade head # After setting up alembic -
Start the backend server:
uvicorn main:app --reloadThe API will be available at
http://localhost:8000API docs athttp://localhost:8000/docs
Frontend Setup
-
Navigate to frontend directory:
cd frontend -
Install dependencies:
npm install -
Start the development server:
npm startThe app will be available at
http://localhost:3000
API Endpoints
Groceries
GET /groceries/- List all groceriesPOST /groceries/- Create new groceryGET /groceries/{id}- Get specific groceryPUT /groceries/{id}- Update groceryDELETE /groceries/{id}- Delete grocery
Shops
GET /shops/- List all shopsPOST /shops/- Create new shopGET /shops/{id}- Get specific shop
Shopping Events
GET /shopping-events/- List all shopping eventsPOST /shopping-events/- Create new shopping eventGET /shopping-events/{id}- Get specific shopping event
Statistics
GET /stats/categories- Category spending statisticsGET /stats/shops- Shop visit statistics
Usage
- Add Shops: Start by adding shops where you buy groceries
- Add Groceries: Create grocery items with prices and categories
- Record Purchases: Use the "Add Purchase" form to record shopping events
- Track Prices: Monitor how prices change over time
- 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
- Fork the repository
- Create a feature branch
- Make changes
- Add tests
- Submit a pull request
License
MIT License
Description
Languages
TypeScript
75.9%
Python
22.8%
Shell
0.4%
Dockerfile
0.4%
HTML
0.3%
Other
0.1%