Lumi/plugins/economy-framework/views/banking.ejs
2026-06-18 22:16:35 +02:00

296 lines
8.8 KiB
Plaintext

<%- include("../../../src/web/views/partials/layout-top", { title }) %>
<style>
.banking-grid {
display: grid;
gap: 16px;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.banking-card {
padding: 14px;
border-radius: 14px;
background: var(--surface-2);
display: flex;
flex-direction: column;
gap: 6px;
}
.banking-label {
color: var(--ink-soft);
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.08em;
}
.banking-value {
font-size: 1.4rem;
font-weight: 700;
}
.banking-currency {
display: inline-flex;
align-items: center;
gap: 10px;
}
.banking-currency img {
width: 32px;
height: 32px;
border-radius: 8px;
object-fit: cover;
}
.funds-grid {
display: grid;
gap: 12px;
}
.fund-item {
background: var(--surface-2);
border-radius: 14px;
padding: 12px;
display: grid;
gap: 8px;
}
.fund-meta {
display: flex;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
}
.fund-progress {
font-size: 0.9rem;
color: var(--ink-soft);
}
.uuid-chip {
border: 1px solid var(--border);
background: transparent;
color: inherit;
border-radius: 8px;
padding: 2px 8px;
font-size: 0.8rem;
cursor: pointer;
}
.uuid-chip:hover {
border-color: var(--ink-soft);
}
.tx-note-details {
margin: 0;
}
.tx-note-details summary {
cursor: pointer;
color: var(--ink);
text-decoration: underline;
text-underline-offset: 2px;
}
.tx-note-details ul {
margin: 6px 0 0;
padding-left: 18px;
color: var(--ink-soft);
}
.tx-note-period {
margin-top: 6px;
color: var(--ink-soft);
font-size: 0.85rem;
}
</style>
<section class="card">
<div class="section-header">
<div>
<h1><%= config.banking.label %></h1>
<p class="hint">Review balances, transfer funds, and track your transaction history.</p>
</div>
<div class="banking-currency">
<% if (config.currency.icon) { %>
<img src="<%= config.currency.icon %>" alt="Currency icon" />
<% } %>
<strong><%= config.currency.name %></strong>
</div>
</div>
</section>
<section class="card">
<h2>Account snapshot</h2>
<div class="banking-grid">
<div class="banking-card">
<span class="banking-label">Current balance</span>
<span class="banking-value"><%= userStats.balance %></span>
</div>
<div class="banking-card">
<span class="banking-label">Total earned</span>
<span class="banking-value"><%= userStats.totalEarned %></span>
</div>
<div class="banking-card">
<span class="banking-label">Total spent</span>
<span class="banking-value"><%= userStats.totalSpent %></span>
</div>
<div class="banking-card">
<span class="banking-label">Sent to others</span>
<span class="banking-value"><%= userStats.totalSent %></span>
</div>
<div class="banking-card">
<span class="banking-label">Received from others</span>
<span class="banking-value"><%= userStats.totalReceived %></span>
</div>
</div>
</section>
<section class="card">
<h2>Transfer to another user</h2>
<form method="post" action="/profile/banking/transfer" class="form-grid">
<div class="field lumi-user-lookup" data-user-lookup>
<label>Recipient username</label>
<input type="search" name="username" placeholder="Search by username or linked account" autocomplete="off" data-user-lookup-search />
<input type="hidden" name="recipient_user_id" data-user-lookup-id />
<div class="lumi-user-lookup-results" data-user-lookup-results hidden></div>
<div class="lumi-user-lookup-preview" data-user-lookup-preview hidden></div>
<span class="hint">Search internal usernames or linked platform accounts.</span>
</div>
<div class="field">
<label>Amount</label>
<input name="amount" />
</div>
<div class="field">
<label>Note (optional)</label>
<input name="note" />
</div>
<button type="submit" class="button">Send transfer</button>
</form>
</section>
<section class="card">
<div class="section-header">
<div>
<h2><%= config.communityFunds.plural %></h2>
<p class="hint">Support shared community goals with direct deposits.</p>
</div>
</div>
<% if (!funds.length) { %>
<p>No <%= config.communityFunds.plural.toLowerCase() %> are active right now.</p>
<% } else { %>
<div class="funds-grid">
<% funds.forEach((fund) => { %>
<div class="fund-item">
<div class="fund-meta">
<strong><%= fund.name %></strong>
<span class="fund-progress"><%= fund.current_amount %>/<%= fund.target_amount %></span>
</div>
<span class="hint"><%= fund.description || '' %></span>
<form method="post" action="/profile/banking/funds/<%= fund.id %>/donate" class="form-grid">
<div class="field">
<label>Amount</label>
<input name="amount" />
</div>
<div class="field">
<label>Note (optional)</label>
<input name="note" />
</div>
<button type="submit" class="button subtle">Donate</button>
</form>
</div>
<% }) %>
</div>
<% } %>
</section>
<section class="card">
<div class="section-header">
<div>
<h2>Transaction history</h2>
<p class="hint">All account activity with UUID records.</p>
</div>
<div class="table-tools">
<input
class="table-search"
type="search"
placeholder="Search transactions"
aria-label="Search transactions"
data-table-filter="banking-transactions"
/>
<div class="table-controls">
<label class="table-page-size">
Show
<select data-table-size="banking-transactions">
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="250">250</option>
</select>
</label>
</div>
</div>
</div>
<div class="table-wrap">
<table
class="table"
data-table="banking-transactions"
data-pageable="true"
data-page-size="25"
data-page-sizes="25,50,100,250"
>
<thead>
<tr>
<th data-sort="id">UUID</th>
<th data-sort="type">Type</th>
<th data-sort="amount">Amount</th>
<th data-sort="from">From</th>
<th data-sort="to">To</th>
<th>Note</th>
<th data-sort="date">Date</th>
</tr>
</thead>
<tbody>
<% transactions.forEach((tx) => { %>
<% const fromName = tx.from_name || 'System'; %>
<% const toName = tx.to_name || 'System'; %>
<tr
data-search="<%= `${tx.id} ${tx.type} ${tx.amount} ${fromName} ${toName} ${tx.note_search || tx.note || ''}` %>"
data-id="<%= tx.id %>"
data-type="<%= tx.type %>"
data-amount="<%= tx.amount %>"
data-from="<%= fromName %>"
data-to="<%= toName %>"
data-date="<%= tx.created_at %>"
>
<td>
<button type="button" class="uuid-chip" data-copy="<%= tx.id %>" title="Copy UUID">
<%= tx.id %>
</button>
</td>
<td><%= tx.type %></td>
<td><%= tx.amount %></td>
<td><%= fromName %></td>
<td><%= toName %></td>
<td>
<% if (tx.activity_reward) { %>
<details class="tx-note-details">
<summary><%= tx.note_display %></summary>
<% if (tx.activity_reward.hourStart && tx.activity_reward.hourEnd) { %>
<div class="tx-note-period">
<%= new Date(tx.activity_reward.hourStart).toLocaleString() %> -
<%= new Date(tx.activity_reward.hourEnd).toLocaleString() %>
</div>
<% } %>
<ul>
<% tx.activity_reward.rewards.forEach((reward) => { %>
<li>
<%= reward.label %>: <%= reward.amount %>
<% if (reward.hits > 0) { %> (<%= reward.hits %> events)<% } %>
<% if (reward.minutes > 0) { %> (<%= reward.minutes %> min)<% } %>
</li>
<% }) %>
</ul>
</details>
<% } else { %>
<%= tx.note_display || tx.note || '-' %>
<% } %>
</td>
<td><%= new Date(tx.created_at).toLocaleString() %></td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<div class="table-pagination" data-table-pagination="banking-transactions">
<button type="button" class="button subtle" data-page-prev>Previous</button>
<span class="table-page-label" data-page-label>Page 1 of 1</span>
<button type="button" class="button subtle" data-page-next>Next</button>
</div>
</section>
<%- include("../../../src/web/views/partials/layout-bottom") %>