asxpio/views/admin/invoices/new.erb
Sergei Poljanski 0fbb6ee809
All checks were successful
Build and Deploy to Production / test (push) Successful in 18s
Build and Deploy to Production / build (push) Successful in 49s
Build and Deploy to Production / deploy (push) Successful in 31s
invoices: multi-crypto payment support
One asset per invoice from a registry (lib/crypto_asset.rb): BTC, LTC,
ETH, XMR, SOL, ALGO, USDT/USDC on ERC-20/TRC-20/BEP-20/Solana/Algorand.
Migration 003 generalizes the ltc_* columns to crypto_* + crypto_coin
(existing LTC invoices backfilled). QR payload adapts per asset: BIP21
amount URIs where supported, bare address for tokens with a network
hint on the PDF. Default addresses come from the CRYPTO_ADDRESSES
secret (JSON code=>address); LTC_ADDRESS still works as legacy.
2026-07-03 02:01:57 +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="contact-form 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">Create invoice</button>
</form>
</section>
<script src="/admin-invoice-form.js"></script>