- Restructure hierarchy: Month → Event → Expense (new months table, FK) - Add MonthHandler with CRUD, monthly reports, dropdown create form - Events now scoped under months with extended ownership chain - AI extraction: 16 specific expense categories (Airfare, Meals, etc.) - UI: category dropdown, button-consistent cards, centered mobile shell on desktop - Dashboard/month views show claim totals per card - Description field now mandatory, forms simplified - Months sorted by name chronologically (latest first)
114 lines
7 KiB
HTML
114 lines
7 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>
|
|
<input type="text" id="currency" name="currency" placeholder="KES, USD, EUR…"
|
|
value="{{.Currency}}" required maxlength="3" style="text-transform: uppercase;">
|
|
</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="Airfare" {{if eq .Category "Airfare"}}selected{{end}}>Airfare</option>
|
|
<option value="Accommodation" {{if eq .Category "Accommodation"}}selected{{end}}>Accommodation</option>
|
|
<option value="Meals Self" {{if eq .Category "Meals Self"}}selected{{end}}>Meals Self</option>
|
|
<option value="Staff Meal" {{if eq .Category "Staff Meal"}}selected{{end}}>Staff Meal</option>
|
|
<option value="Client Meal" {{if eq .Category "Client Meal"}}selected{{end}}>Client Meal</option>
|
|
<option value="Travel - Taxi" {{if eq .Category "Travel - Taxi"}}selected{{end}}>Travel - Taxi</option>
|
|
<option value="Travel - Phone" {{if eq .Category "Travel - Phone"}}selected{{end}}>Travel - Phone</option>
|
|
<option value="Misc Travel" {{if eq .Category "Misc Travel"}}selected{{end}}>Misc Travel</option>
|
|
<option value="Mobile / Office Phone" {{if eq .Category "Mobile / Office Phone"}}selected{{end}}>Mobile / Office Phone</option>
|
|
<option value="Office Supplies" {{if eq .Category "Office Supplies"}}selected{{end}}>Office Supplies</option>
|
|
<option value="Postage / Couriers" {{if eq .Category "Postage / Couriers"}}selected{{end}}>Postage / Couriers</option>
|
|
<option value="Other Expenses" {{if eq .Category "Other Expenses"}}selected{{end}}>Other Expenses</option>
|
|
<option value="Hotel" {{if eq .Category "Hotel"}}selected{{end}}>Hotel</option>
|
|
<option value="Per Diem" {{if eq .Category "Per Diem"}}selected{{end}}>Per Diem</option>
|
|
<option value="Visa Fees" {{if eq .Category "Visa Fees"}}selected{{end}}>Visa Fees</option>
|
|
<option value="Connectivity (internet connections)" {{if eq .Category "Connectivity (internet connections)"}}selected{{end}}>Connectivity (internet connections)</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="Required notes..." required></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>
|