Skip to content

sohamnotes/voucher-tracker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

88 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎟️ Voucher Tracker

A simple local-first web app to track vouchers / gift cards with expiry dates, categories, usage status, and private mode.

🚫 No cloud
🚫 No login
🚫 No database
🐳 Runs fully on your computer using Docker


✨ Features

  • βž• Create, ✏️ update, ❌ delete vouchers
  • ⏳ Track voucher expiry dates
  • πŸ“† Automatically calculate days left
  • πŸ“§ Email notifications for expiring vouchers
  • ⏰ Notification runs:
    • πŸš€ Immediately when server starts
    • πŸ•˜ Every day at 9:00 AM IST
  • 🏷️ Mark vouchers as Used / Active / Expired
  • πŸ”ƒ Auto sort by expiry (expiring first)
  • πŸ’° Show total voucher value based on filters
  • πŸ” Search & filter vouchers
  • πŸ“¦ Fully offline (data stored locally)
  • 🐳 Dockerized (no Node.js, no Javascript required)

⏰ Email Notification Logic

  • 🧠 Implemented using node-cron
  • 🟒 Runs only while Docker containers are running
  • πŸ“§ Sends HTML email containing:
    • 🏒 Company name
    • 🎟️ Voucher code
    • πŸ” Voucher PIN
    • πŸ“… Expiry date
    • ⏳ Days left
  • 🚫 Skips already used vouchers
  • πŸ” Looks ahead 10 days for upcoming expiries

πŸ› οΈ Prerequisites

🐳 Docker Desktop (Mandatory)

This project runs entirely using Docker.

Download Docker Desktop: https://www.docker.com/products/docker-desktop/

Supported platforms:

  • πŸͺŸ Windows
  • 🍎 macOS
  • 🐧 Linux

🧰 Git (Mandatory)

Git is required to clone the repository and manage source code.

Download Git: https://git-scm.com/downloads

Supported platforms:

  • πŸͺŸ Windows
  • 🍎 macOS
  • 🐧 Linux

🐳 Start Docker (IMPORTANT)

Before running any command below, Docker Desktop must be running.

βœ… Step 1: Open Docker Desktop

  • πŸͺŸ Windows: Start Menu β†’ Docker Desktop
  • 🍎 macOS: Applications β†’ Docker Desktop

βœ… Step 2: Wait for Green Indicator

Docker is ready ONLY when:

  • 🐳 Docker whale icon is visible
  • 🟒 Status shows β€œRunning”
  • 🟒 Green dot / "Engine running” is visible on the bottom left corner

⚠️ If Docker is not running, setup commands will fail.


πŸ” Email Setup (Gmail SMTP – App Password)

Email notifications require a Gmail App Password.

βœ… Requirements

  • πŸ‘€ Google account
  • πŸ”‘ 2-Step Verification enabled

πŸ”‘ Generate Gmail App Password

  1. Google Account β†’ Security
  2. Enable 2-Step Verification
  3. Open App passwords
  4. Select:
    • App: Mail
    • Device: Other (Custom)
  5. Name: Voucher Tracker SMTP
  6. Generate password
  7. Copy the 16-character password

⚠️ Notes:

  • ❌ Do NOT use your normal Gmail password
  • βœ… Use ONLY the App Password in environment file
  • Paste the password without any space

πŸš€ One-Command Setup & Start

No Javascript. No Node.js. Everything runs via Docker.

⚠️ Important – Read Before You Start

  • βœ… Ensure Email to Send, App Password, and Receiver email(s) are ready and configured before proceeding with this step
  • πŸ“§ For multiple recipients, separate email addresses using a semicolon (;)

Example:

john@example.com;jane@example.com;team@example.com

πŸͺŸ Windows (PowerShell)

Open PowerShell and run (Copy, Paste and Press Enter if script not started automatically) and provide details needed to send voucher expiring emails

{
    $folder = "voucher-tracker"
    $repo = "https://github.com/sohampshetty/voucher-tracker.git"
    $branch = "main"
    $currentDir = (Get-Location).Path

    Write-Host "`nπŸ”„ Voucher Tracker – Auto Setup Started" -ForegroundColor Cyan

    # ------------------------------------------------------------
    # 1️⃣ Clone or update repo
    # ------------------------------------------------------------
    if (Test-Path $folder) {
        Write-Host "πŸ“₯ Updating existing repository..." -ForegroundColor Yellow
        Set-Location $folder
        git fetch origin
        git reset --hard
        git clean -fd
        git checkout $branch
        git pull origin $branch
        Set-Location $currentDir
    } else {
        Write-Host "πŸ“¦ Cloning repository..." -ForegroundColor Green
        git clone -b $branch $repo
    }

    Set-Location "$currentDir\$folder"

    # ------------------------------------------------------------
    # 2️⃣ Ask for ports
    # ------------------------------------------------------------
    Write-Host "`nβš™οΈ Port Configuration" -ForegroundColor Cyan
    Write-Host "πŸ‘‰ Press Enter to use default ports" -ForegroundColor DarkGray

    $frontendPort = Read-Host "Frontend (UI) port [9000]"
    if ([string]::IsNullOrWhiteSpace($frontendPort)) { $frontendPort = "9000" }

    $backendPort = Read-Host "Backend (API) port [9100]"
    if ([string]::IsNullOrWhiteSpace($backendPort)) { $backendPort = "9100" }

    Write-Host "`n🧠 Using ports β†’ UI: $frontendPort | API: $backendPort" -ForegroundColor Green

    $env:FRONTEND_PORT = $frontendPort
    $env:PORT = $backendPort

    # ------------------------------------------------------------
    # 3️⃣ Email config (ask ONLY if missing)
    # ------------------------------------------------------------
    Write-Host "`nπŸ“§ Email Configuration" -ForegroundColor Cyan
    Write-Host "ℹ️ Email is used only for sending voucher expiry notifications. Enter information requested (will be asked only when missing) and press Enter" -ForegroundColor DarkGray

    $envFile = "server\.env"
    $requiredVars = @("EMAIL_USER", "EMAIL_PASS", "NOTIFY_EMAIL")
    $envMap = @{}
    $allPresent = $true

    if (Test-Path $envFile) {
        Get-Content $envFile | ForEach-Object {
            if ($_ -match '^\s*([^#=]+)\s*=\s*(.*)\s*$') {
                $envMap[$matches[1]] = $matches[2]
            }
        }
    }

    foreach ($key in $requiredVars) {
        if (-not ($envMap.ContainsKey($key) -and -not [string]::IsNullOrWhiteSpace($envMap[$key]))) {

            switch ($key) {
                "EMAIL_USER" {
                    $envMap[$key] = Read-Host "➑️ Enter sender email address (used for SMTP sending)"
                }
                "EMAIL_PASS" {
                    $envMap[$key] = Read-Host "➑️ Enter email app password (SMTP app password, NOT your email login password)"
                }
                "NOTIFY_EMAIL" {
                    $envMap[$key] = Read-Host "➑️ Enter receiver email address(es) (use ; to separate multiple emails)"
                }
            }

            $allPresent = $false
        }
    }

    if ($allPresent) {
        Write-Host "πŸ“¨ Email configuration validated successfully!" -ForegroundColor Green
    } else {
        ($requiredVars | ForEach-Object { "$_=$($envMap[$_])" }) |
            Set-Content $envFile -Encoding UTF8
    }

    # ------------------------------------------------------------
    # 4️⃣ Rebuild everything clean
    # ------------------------------------------------------------
    Write-Host "`n🐳 Building Docker containers... (this may take a while)" -ForegroundColor Cyan

    $env:BUILD_TIME = (Get-Date).ToString("yyyyMMddHHmmss")

    docker-compose down --volumes --remove-orphans
    docker-compose build --no-cache
    docker-compose up -d

    # ------------------------------------------------------------
    # 5️⃣ Open UI
    # ------------------------------------------------------------
    $url = "http://localhost:$frontendPort"
    Write-Host "`n🌐 Opening Voucher Tracker β†’ $url" -ForegroundColor Green
    Start-Process $url

    Write-Host "`nβœ… Setup complete!" -ForegroundColor Green
    Start-Sleep -Seconds 1
    Stop-Process -Id $PID
} | & { process { $_.Invoke() } }


🍎 macOS (Terminal / iMac / MacBook)

Open Terminal and run (Copy, Paste and Press Enter if script not started automatically) and provide details needed to send voucher expiring emails

FOLDER="voucher-tracker"
REPO="https://github.com/sohampshetty/voucher-tracker.git"
BRANCH="main"
CURRENT_DIR="$(pwd)"

echo
echo "Voucher Tracker - Auto Setup Started"
echo

# ------------------------------------------------------------
# 1. Clone or update repo
# ------------------------------------------------------------
if [ -d "$FOLDER" ]; then
  echo "Updating existing repository..."
  cd "$FOLDER" || exit 1
  git fetch origin
  git reset --hard
  git clean -fd
  git checkout "$BRANCH"
  git pull origin "$BRANCH"
  cd "$CURRENT_DIR" || exit 1
else
  echo "Cloning repository..."
  git clone -b "$BRANCH" "$REPO"
fi

cd "$CURRENT_DIR/$FOLDER" || exit 1

# ------------------------------------------------------------
# 2. Port configuration
# ------------------------------------------------------------
echo
echo "Port Configuration"
echo "Press Enter to use default ports"

printf "\nFrontend (UI) port [9000]: "
read FRONTEND_PORT
FRONTEND_PORT=${FRONTEND_PORT:-9000}

printf "\nBackend (API) port [9100]: "
read BACKEND_PORT
BACKEND_PORT=${BACKEND_PORT:-9100}

echo
echo "Using ports -> UI: $FRONTEND_PORT | API: $BACKEND_PORT"

export FRONTEND_PORT
export PORT="$BACKEND_PORT"

# ------------------------------------------------------------
# 3. Email configuration
# ------------------------------------------------------------
echo
echo "Email Configuration"
echo "Email is used only for sending voucher expiry notifications. Enter information requested (will be asked only when missing) and press Enter."

ENV_FILE="server/.env"

EMAIL_USER=""
EMAIL_PASS=""
NOTIFY_EMAIL=""

if [ -f "$ENV_FILE" ]; then
  while IFS='=' read -r key value; do
    case "$key" in
      EMAIL_USER) EMAIL_USER="$value" ;;
      EMAIL_PASS) EMAIL_PASS="$value" ;;
      NOTIFY_EMAIL) NOTIFY_EMAIL="$value" ;;
    esac
  done < "$ENV_FILE"
fi

if [ -z "$EMAIL_USER" ]; then
  printf "\nEnter sender email address (used for SMTP sending): "
  read EMAIL_USER
fi

if [ -z "$EMAIL_PASS" ]; then
  printf "Enter email app password (SMTP app password, NOT your email login password): "
  read EMAIL_PASS
fi

if [ -z "$NOTIFY_EMAIL" ]; then
  printf "Enter receiver email address(es) (use ; to separate multiple emails):"
  read NOTIFY_EMAIL
fi

echo "EMAIL_USER=$EMAIL_USER" > "$ENV_FILE"
echo "EMAIL_PASS=$EMAIL_PASS" >> "$ENV_FILE"
echo "NOTIFY_EMAIL=$NOTIFY_EMAIL" >> "$ENV_FILE"

echo
echo "Email configuration ready"

# ------------------------------------------------------------
# 4. Docker build
# ------------------------------------------------------------
echo
echo "Building Docker containers (this may take a while)"

export BUILD_TIME="$(date +%Y%m%d%H%M%S)"

docker-compose down --volumes --remove-orphans > /dev/null 2>&1
docker-compose build --no-cache --quiet
docker-compose up -d > /dev/null 2>&1

# ------------------------------------------------------------
# 5. Open UI
# ------------------------------------------------------------
URL="http://localhost:$FRONTEND_PORT"
echo
echo "Opening Voucher Tracker -> $URL"
open "$URL"

echo
echo "Setup complete"



🌐 Access the Application (Only Chrome Supported)

The application will open automatically in default browser, if not use below url (replace port if not used default) in Chrome.

http://localhost:9000


🧭 Managing Docker Containers

You can manage the app containers from Docker Desktop UI.

  1. Open Docker Desktop
  2. Go to the Containers tab
  3. You will see containers like:
    • voucher-tracker (Manages both the below)
    • voucher-backend
    • voucher-frontend

From here you can:

  • ▢️ Start containers
  • ⏸️ Stop containers
  • πŸ”„ Restart containers
  • πŸ“œ View logs
  • πŸ“ Browse container files (Files tab)
  • πŸ—‘οΈ Remove containers safely

This is the easiest way if you are not comfortable with terminal commands.

⚠️ Important Notes

  • 🟒 Containers must be running for email notifications to work

πŸ“‚ Data Persistence

All voucher data is stored locally at:

server/data/vouchers.json

πŸ”‘ Always back up this file β€” all your vouchers live here.


πŸ”’ Security Notes

  • 🚫 Never commit .env files
  • 🚫 Never commit server/data/vouchers.json
  • πŸ”‘ Always use Gmail App Password
  • ⚠️ Avoid running multiple Docker instances (prevents duplicate emails)

πŸ”Œ After System Shutdown / Restart

If your system is restarted or shut down, Docker containers do NOT start automatically unless Docker Desktop is running.

Follow these steps to bring the app back online.

🐳 Step 1: Start Docker Desktop

  • πŸͺŸ Windows: Open Docker Desktop from Start Menu
  • 🍎 macOS: Open Docker Desktop from Applications

Wait until:

  • 🐳 Docker whale icon is visible
  • 🟒 Status shows Running

▢️ Step 2: Start Containers (Only if Needed)

Using Docker Desktop (Easy)

  1. Open Docker Desktop
  2. Go to Containers
  3. Locate the project
  4. Click Start ▢️

βœ… Step 3: Verify App

  • Open browser: http://localhost:9000
  • If backend is running, email notifications will resume automatically

⚠️ Important Notes

  • ⏰ Scheduled emails run only while containers are running
  • πŸ›‘ If Docker Desktop is closed, emails will NOT be sent
  • πŸ”„ No rebuild is required after restart
  • πŸ” .env and voucher data remain safe

πŸ’‘ Optional Tip (Auto-Start)

You can enable β€œStart Docker Desktop on login” in Docker settings so the app comes back automatically after reboot.


πŸ“¬ Need Help?

🐦 X (Twitter): https://x.com/aree_dinosaur
πŸ“§ Email: aree.dinosaur@gmail.com


πŸ™ Thank you for using Voucher Tracker.

Built with care ❀️
Hope it saves you money before vouchers expire πŸ˜„
Happy hacking πŸš€

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •