NextExpense/templates/receipt_form.html
cclohmar dcb43b08a0 feat: send receipt images as ZIP attachment with report
- Email now includes both report (CSV/PDF) + ZIP of all receipt images
- ZIP images named {event-name}-{index}.{ext} matching list order
- Uses Go's archive/zip (stdlib, no external deps)
- Sender.SendReport now accepts []*Attachment for multiple files
- Gracefully skips missing image files with warnings
2026-05-30 13:38:23 +00:00

127 lines
8 KiB
HTML

<div id="receipt-form">
{{if .AIError}}
<div class="error-message" style="background: #fef2f2; border: 1px solid #fecaca; color: #dc2626; padding: 0.75rem; border-radius: 0.5rem; margin-bottom: 1rem;">
{{.AIError}}
</div>
{{end}}
<div class="card" style="padding: 1rem;">
<div style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: 1rem;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14 2 14 8 20 8"/>
</svg>
<span style="font-weight: 600;">Receipt Details</span>
<span class="badge badge-open" style="margin-left: auto;">AI Extracted</span>
</div>
{{if .EditID}}
<form hx-put="/expenses/{{.EditID}}" hx-target="#receipt-form" hx-swap="outerHTML"
hx-indicator="#save-indicator">
{{else}}
<form hx-post="/expenses" hx-target="#receipt-form" hx-swap="outerHTML"
hx-indicator="#save-indicator">
{{end}}
<input type="hidden" name="image_path" value="{{.ImagePath}}">
{{if .EditID}}<input type="hidden" name="edit_id" value="{{.EditID}}">{{end}}
<div class="form-row">
<div class="form-group">
<label for="amount">Amount *</label>
<input type="number" id="amount" name="amount" step="0.01" min="0" placeholder="0.00"
value="{{.Amount}}" required inputmode="decimal">
</div>
<div class="form-group">
<label for="currency">Currency *</label>
<select id="currency" name="currency" required>
<option value="">Select</option>
<option value="KES" {{if eq .Currency "KES"}}selected{{end}}>KES - Kenyan Shilling</option>
<option value="USD" {{if eq .Currency "USD"}}selected{{end}}>USD - US Dollar</option>
<option value="EUR" {{if eq .Currency "EUR"}}selected{{end}}>EUR - Euro</option>
<option value="GBP" {{if eq .Currency "GBP"}}selected{{end}}>GBP - British Pound</option>
<option value="JPY" {{if eq .Currency "JPY"}}selected{{end}}>JPY - Japanese Yen</option>
<option value="CHF" {{if eq .Currency "CHF"}}selected{{end}}>CHF - Swiss Franc</option>
<option value="SEK" {{if eq .Currency "SEK"}}selected{{end}}>SEK - Swedish Krona</option>
<option value="NOK" {{if eq .Currency "NOK"}}selected{{end}}>NOK - Norwegian Krone</option>
<option value="DKK" {{if eq .Currency "DKK"}}selected{{end}}>DKK - Danish Krone</option>
<option value="PLN" {{if eq .Currency "PLN"}}selected{{end}}>PLN - Polish Zloty</option>
<option value="CZK" {{if eq .Currency "CZK"}}selected{{end}}>CZK - Czech Koruna</option>
<option value="HUF" {{if eq .Currency "HUF"}}selected{{end}}>HUF - Hungarian Forint</option>
<option value="RON" {{if eq .Currency "RON"}}selected{{end}}>RON - Romanian Leu</option>
<option value="ZAR" {{if eq .Currency "ZAR"}}selected{{end}}>ZAR - South African Rand</option>
<option value="NGN" {{if eq .Currency "NGN"}}selected{{end}}>NGN - Nigerian Naira</option>
<option value="EGP" {{if eq .Currency "EGP"}}selected{{end}}>EGP - Egyptian Pound</option>
<option value="TZS" {{if eq .Currency "TZS"}}selected{{end}}>TZS - Tanzanian Shilling</option>
<option value="UGX" {{if eq .Currency "UGX"}}selected{{end}}>UGX - Ugandan Shilling</option>
<option value="RWF" {{if eq .Currency "RWF"}}selected{{end}}>RWF - Rwandan Franc</option>
<option value="AED" {{if eq .Currency "AED"}}selected{{end}}>AED - UAE Dirham</option>
<option value="CNY" {{if eq .Currency "CNY"}}selected{{end}}>CNY - Chinese Yuan</option>
<option value="INR" {{if eq .Currency "INR"}}selected{{end}}>INR - Indian Rupee</option>
<option value="BRL" {{if eq .Currency "BRL"}}selected{{end}}>BRL - Brazilian Real</option>
</select>
</div>
</div>
<div class="form-group">
<label for="merchant">Merchant *</label>
<input type="text" id="merchant" name="merchant" placeholder="Store or business name"
value="{{.Merchant}}" required>
</div>
<div class="form-row">
<div class="form-group">
<label for="category">Category *</label>
<select id="category" name="category" required>
<option value="">Select</option>
<option value="Food" {{if eq .Category "Food"}}selected{{end}}>Food</option>
<option value="Travel" {{if eq .Category "Travel"}}selected{{end}}>Travel</option>
<option value="Lodging" {{if eq .Category "Lodging"}}selected{{end}}>Lodging</option>
<option value="Software" {{if eq .Category "Software"}}selected{{end}}>Software</option>
<option value="Other" {{if eq .Category "Other"}}selected{{end}}>Other</option>
</select>
</div>
<div class="form-group">
<label for="date">Date *</label>
<input type="date" id="date" name="date" value="{{.Date}}" required>
</div>
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea id="description" name="description" placeholder="Optional notes...">{{.Description}}</textarea>
</div>
{{if .BaseCurrency}}
<div class="card" style="padding: 0.75rem; background: #064e3b; border: 1px solid #065f46; border-radius: 0.5rem; margin-bottom: 1rem;">
<div style="font-size: 0.875rem; font-weight: 600; color: #6ee7b7; margin-bottom: 0.5rem;">
Claim Conversion
</div>
<div class="form-row">
<div class="form-group">
<label for="converted_amount">Converted Amount ({{.BaseCurrency}})</label>
<input type="number" id="converted_amount" name="converted_amount" step="0.01" min="0" placeholder="0.00"
value="{{.ConvertedAmount}}" inputmode="decimal">
</div>
<div class="form-group">
<label>Rate</label>
<input type="text" class="form-control" value="1 {{.Currency}} = {{printf "%.6f" .ExchangeRate}} {{.BaseCurrency}}" readonly style="background: var(--color-card); padding: 0.5rem; border: 1px solid var(--color-border); border-radius: 0.375rem; width: 100%; box-sizing: border-box; color: var(--color-text-muted);">
</div>
</div>
<input type="hidden" name="base_currency" value="{{.BaseCurrency}}">
<input type="hidden" name="exchange_rate" value="{{.ExchangeRate}}">
</div>
{{end}}
<div style="display: flex; gap: 0.5rem;">
<button type="submit" class="btn btn-primary" id="save-indicator">
<span class="spinner htmx-indicator"></span>
{{if .EditID}}Update Expense{{else}}Save Expense{{end}}
</button>
<button type="button" class="btn btn-secondary"
onclick="document.getElementById('receipt-form').innerHTML = ''">
Cancel
</button>
</div>
</form>
</div>
</div>