NextReceipt/templates/dashboard.html
cclohmar f0c576c543 feat: transform NextExpense into NextReceipt — receipt saver for warranty & returns
- Replace events+expenses with flat purchases table
- Add warranty_months, return_days, product_name fields
- Remove currency conversion, CSV/PDF reporting, event filing
- Simplify auth (no onboarding/department/profile)
- Update AI extraction prompts for product/warranty info
- Update all branding: templates, install.sh, Makefile, service file
2026-06-21 18:57:29 +00:00

119 lines
7.2 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="theme-color" content="#10b981">
<title>NextReceipt</title>
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
<link rel="alternate icon" href="/static/icons/icon-192.png">
<link rel="manifest" href="/manifest.json">
<link rel="stylesheet" href="/static/css/style.css?v=4">
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
</head>
<body>
<div class="app-shell">
<header class="app-header">
<h1 class="app-title"><img src="/static/favicon.svg" width="24" height="24" alt="" style="vertical-align: middle; margin-right: 0.5rem;">NextReceipt</h1>
<button class="btn btn-secondary btn-sm" style="font-size: 0.75rem;"
hx-post="/logout" hx-target="body" hx-push-url="true">Logout</button>
</header>
<main class="main-content">
<div class="dashboard-header">
<h2>My Purchases</h2>
</div>
<!-- Purchase List -->
<div id="purchase-list">
{{if .Purchases}}
<h3 style="margin-bottom: 1rem; font-size: 1rem; font-weight: 600;">Purchases ({{len .Purchases}})</h3>
<div style="display: flex; flex-direction: column; gap: 0.5rem;">
{{range .Purchases}}
<div style="display: flex; align-items: center; background: var(--color-card); border: 1px solid var(--color-border); border-radius: 0.5rem; padding: 0.75rem;">
<div style="flex: 1; min-width: 0;">
<div style="font-weight: 500; color: var(--color-text);">{{.ProductName}}</div>
<div style="font-size: 0.75rem; color: var(--color-text-muted);">{{.Store}} &middot; {{.Category}} &middot; {{.PurchaseDate}}</div>
{{if .Notes}}<div style="font-size: 0.75rem; color: var(--color-text-muted);">{{.Notes}}</div>{{end}}
{{if .WarrantyMonths}}
<div style="font-size: 0.7rem; color: #6ee7b7;">Warranty: {{.WarrantyMonths}} months</div>
{{end}}
{{if .ReturnDays}}
<div style="font-size: 0.7rem; color: #fcd34d;">Return: {{.ReturnDays}} days</div>
{{end}}
</div>
<div style="text-align: right; margin-right: 0.75rem;">
<div style="font-weight: 600; color: var(--color-text);">{{printf "%.2f" .Amount}} {{.Currency}}</div>
</div>
<div style="display: flex; gap: 0.25rem;">
{{if .ImagePath}}
<button class="btn btn-sm" style="background: none; border: 1px solid var(--color-border); border-radius: 0.375rem; padding: 0.25rem 0.5rem; font-size: 0.75rem; cursor: pointer; flex-shrink: 0; color: var(--color-text);"
onclick="document.getElementById('img-{{.ID}}').classList.toggle('hidden')"
title="View receipt image">🖼️</button>
{{end}}
<button class="btn btn-sm" style="background: none; border: 1px solid var(--color-border); border-radius: 0.375rem; padding: 0.25rem 0.5rem; font-size: 0.75rem; cursor: pointer; flex-shrink: 0; color: var(--color-text);"
hx-get="/purchases/{{.ID}}/edit"
hx-target="#receipt-form"
hx-swap="innerHTML"
title="Edit purchase">✏️</button>
<button class="btn btn-sm" style="background: none; border: 1px solid #7f1d1d; border-radius: 0.375rem; padding: 0.25rem 0.5rem; font-size: 0.75rem; cursor: pointer; flex-shrink: 0; color: #fca5a5;"
onclick="if(confirm('Delete this purchase?')) htmx.trigger('#del-{{.ID}}','click')"
title="Delete purchase">🗑️</button>
<div hx-delete="/purchases/{{.ID}}" hx-target="#purchase-list" hx-swap="outerHTML" id="del-{{.ID}}" style="display:none"></div>
</div>
</div>
{{if .ImagePath}}
<div id="img-{{.ID}}" class="hidden" style="position: fixed; inset: 0; background: rgba(0,0,0,0.85); z-index: 999; align-items: center; justify-content: center; cursor: pointer; padding: 1rem;"
onclick="this.classList.add('hidden')">
<span style="position: absolute; top: 1rem; right: 1rem; font-size: 2rem; color: #fff; line-height: 1; cursor: pointer; z-index: 1000;">&times;</span>
<img src="/storage/{{.ImagePath}}" alt="Receipt" style="max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 0.5rem;" onclick="event.stopPropagation()">
</div>
{{end}}
{{end}}
</div>
{{else}}
<div style="text-align: center; padding: 3rem; color: var(--color-text-muted); font-size: 0.875rem;">
<p>No purchases yet. Upload a receipt to get started.</p>
</div>
{{end}}
</div>
<!-- Receipt Form (edit/add) -->
<div id="receipt-form" style="margin-top: 1.5rem;"></div>
<!-- Add Receipt Buttons -->
<div style="margin-top: 1.5rem; display: flex; gap: 0.75rem;">
<label for="receipt-camera" class="btn btn-primary" style="flex: 1; text-align: center; cursor: pointer;">
📷 Camera
</label>
<label for="receipt-upload" class="btn btn-secondary" style="flex: 1; text-align: center; cursor: pointer;">
📁 Upload
</label>
</div>
<!-- Hidden file input: camera (mobile) -->
<input type="file" id="receipt-camera" name="receipt" accept="image/*" capture="environment" style="display: none;"
hx-post="/purchases/upload"
hx-encoding="multipart/form-data"
hx-target="#receipt-form"
hx-swap="innerHTML"
hx-indicator="#upload-indicator"
hx-trigger="change">
<!-- Hidden file input: gallery / PDF upload -->
<input type="file" id="receipt-upload" name="receipt" accept="image/*,.pdf" style="display: none;"
hx-post="/purchases/upload"
hx-encoding="multipart/form-data"
hx-target="#receipt-form"
hx-swap="innerHTML"
hx-indicator="#upload-indicator"
hx-trigger="change">
<div id="upload-indicator" class="htmx-indicator" style="text-align: center; padding: 1rem;">
<div class="spinner"></div>
<p>Analyzing receipt...</p>
</div>
</main>
</div>
</body>
</html>