asxpio/views/admin/invoices/new.erb
Sergei Poljanski 97919f3f71
admin: restore form styling
The invoice form's text inputs, textareas and label layout depended on
.contact-form rules that were deleted with the contact form, so they
fell back to white browser defaults with labels running inline. Give
every admin form (.invoice-form) one style: labels above fields, gray
inputs on the surface token, a focus state, single column on phones,
and the submit button styled like the rest.

Assisted-by: Claude:opus-5
2026-10-10 08:32:28 +04:00

124 lines
6.5 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<div class="header">
<h1>New invoice</h1>
<p class="tagline"><a href="/admin/invoices">← all invoices</a></p>
</div>
<% if @form_errors && !@form_errors.empty? %>
<div class="form-error-base">
<% @form_errors.each_value do |msg| %>
<div><%= msg %></div>
<% end %>
</div>
<% end %>
<section class="section">
<form class="invoice-form" method="post" action="/admin/invoices" autocomplete="off">
<input type="hidden" name="authenticity_token" value="<%= csrf_token %>" />
<h2>Client</h2>
<div class="field">
<label for="client_name">Name</label>
<input type="text" id="client_name" name="client_name" value="<%= @form_values[:client_name] %>" required maxlength="200" />
</div>
<div class="field">
<label for="client_email">Email</label>
<input type="email" id="client_email" name="client_email" value="<%= @form_values[:client_email] %>" required maxlength="200" />
</div>
<div class="field">
<label for="client_address">Address <span class="optional">(optional, free text)</span></label>
<textarea id="client_address" name="client_address" rows="3" maxlength="500"><%= @form_values[:client_address] %></textarea>
</div>
<h2>Terms</h2>
<div class="invoice-grid">
<div class="field">
<label for="issued_on">Issued</label>
<input type="date" id="issued_on" name="issued_on" value="<%= @form_values[:issued_on] || Date.today.strftime('%Y-%m-%d') %>" required />
</div>
<div class="field">
<label for="due_on">Due</label>
<input type="date" id="due_on" name="due_on" value="<%= @form_values[:due_on] || (Date.today + 14).strftime('%Y-%m-%d') %>" required />
</div>
<div class="field">
<label for="currency">Currency</label>
<select id="currency" name="currency">
<% Invoice::CURRENCIES.each do |c| %>
<option value="<%= c %>" <%= 'selected' if (@form_values[:currency] || 'EUR') == c %>><%= c %></option>
<% end %>
</select>
</div>
<div class="field">
<label for="gel_rate">GEL rate (GEL per 1 <span id="gel-rate-ccy">unit</span>)</label>
<input type="text" id="gel_rate" name="gel_rate" value="<%= @form_values[:gel_rate] %>" placeholder="2.9500" inputmode="decimal" required />
<button type="button" id="fetch-gel-rate" class="link-button">↻ Fetch official (NBG)</button>
<span id="gel-rate-status" class="optional"></span>
</div>
</div>
<h2>Line items</h2>
<table class="items-table" id="items-table">
<thead>
<tr>
<th>Description</th>
<th class="num">Qty</th>
<th class="num">Unit price</th>
<th></th>
</tr>
</thead>
<tbody>
<% (@form_values[:items] || [{'description' => '', 'qty' => '', 'unit_price' => ''}]).each_with_index do |item, i| %>
<tr class="item-row">
<td><input type="text" name="items[<%= i %>][description]" value="<%= item['description'] %>" placeholder="DevOps engineering, May 2026" maxlength="300" /></td>
<td class="num"><input type="text" name="items[<%= i %>][qty]" value="<%= item['qty'] %>" placeholder="1" inputmode="decimal" /></td>
<td class="num"><input type="text" name="items[<%= i %>][unit_price]" value="<%= item['unit_price'] %>" placeholder="0.00" inputmode="decimal" /></td>
<td class="actions"><button type="button" class="remove-row" aria-label="Remove">×</button></td>
</tr>
<% end %>
</tbody>
</table>
<button type="button" id="add-row" class="link-button">+ add line</button>
<div class="field">
<label for="notes">Notes <span class="optional">(optional)</span></label>
<textarea id="notes" name="notes" rows="3" maxlength="1000"><%= @form_values[:notes] %></textarea>
</div>
<h2>Crypto payment <span class="optional">(optional)</span></h2>
<p class="optional" style="margin-top:-6px;">Leave the address blank to omit the crypto block and QR from the invoice.</p>
<div class="invoice-grid">
<div class="field">
<label for="crypto_coin">Coin</label>
<select id="crypto_coin" name="crypto_coin">
<% CryptoAsset::CODES.each do |c| %>
<option value="<%= c %>" <%= 'selected' if (@form_values[:crypto_coin] || 'LTC') == c %>><%= c %> · <%= CryptoAsset.name(c) %></option>
<% end %>
</select>
</div>
<div class="field">
<label for="crypto_address">Address</label>
<input type="text" id="crypto_address" name="crypto_address"
value="<%= @form_values[:crypto_address] || CryptoAsset.default_addresses[@form_values[:crypto_coin] || 'LTC'] %>"
placeholder="payout address" maxlength="128" />
</div>
</div>
<div class="invoice-grid">
<div class="field">
<label for="crypto_rate">Rate (1 <span id="crypto-rate-coin">coin</span> in <span id="crypto-rate-ccy">currency</span>)</label>
<input type="text" id="crypto_rate" name="crypto_rate" value="<%= @form_values[:crypto_rate] %>"
placeholder="e.g. 85.20" inputmode="decimal" />
<button type="button" id="fetch-crypto-rate" class="link-button">↻ Fetch live</button>
<span id="crypto-rate-status" class="optional"></span>
</div>
<div class="field">
<label for="crypto_amount">Amount due <span class="optional">(auto from rate; editable)</span></label>
<input type="text" id="crypto_amount" name="crypto_amount" value="<%= @form_values[:crypto_amount] %>"
placeholder="auto" inputmode="decimal" />
</div>
</div>
<script type="application/json" id="crypto-defaults"><%== CryptoAsset.default_addresses.to_json %></script>
<button type="submit" class="download-button">Create invoice</button>
</form>
</section>
<script src="/admin-invoice-form.js"></script>