This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
<script lang="ts">
|
||||
import { bankPageSize } from '$lib/bank.js';
|
||||
import Button from '../primitives/Button.svelte';
|
||||
let {
|
||||
total,
|
||||
offset,
|
||||
disabled = false,
|
||||
onchange,
|
||||
label = 'results'
|
||||
}: {
|
||||
total: number;
|
||||
offset: number;
|
||||
disabled?: boolean;
|
||||
onchange: (offset: number) => void;
|
||||
label?: string;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<nav class="pagination" aria-label={`${label} pagination`}>
|
||||
<span role="status"
|
||||
>{total ? offset + 1 : 0}–{Math.min(offset + bankPageSize, total)} of {total.toLocaleString()}
|
||||
{label}</span
|
||||
>
|
||||
{#if total > bankPageSize}
|
||||
<div>
|
||||
<Button
|
||||
size="sm"
|
||||
disabled={disabled || offset === 0}
|
||||
onclick={() => onchange(offset - bankPageSize)}>Previous</Button
|
||||
>
|
||||
<Button
|
||||
size="sm"
|
||||
disabled={disabled || offset + bankPageSize >= total}
|
||||
onclick={() => onchange(offset + bankPageSize)}>Next</Button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
.pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-3);
|
||||
padding-block: var(--space-3);
|
||||
color: var(--text-secondary);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
.pagination div {
|
||||
display: flex;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,53 @@
|
||||
<script lang="ts">
|
||||
import type { BankPending } from '$lib/bank.js';
|
||||
import { contextHref } from '$lib/navigation-context.js';
|
||||
import CopyValue from '../CopyValue.svelte';
|
||||
import RelativeTime from '../RelativeTime.svelte';
|
||||
import ServerIdentity from '../ServerIdentity.svelte';
|
||||
let { transfer, source }: { transfer: BankPending; source: URL } = $props();
|
||||
</script>
|
||||
|
||||
<div class="pending-details">
|
||||
<p>
|
||||
Waiting for the game server to confirm or cancel this {transfer.operation === 'deposit'
|
||||
? 'deposit'
|
||||
: 'withdrawal'}.
|
||||
</p>
|
||||
<p>
|
||||
{transfer.operation === 'deposit'
|
||||
? 'These points have not been added to the bank balance. Deposit capacity is reserved until the transfer settles.'
|
||||
: 'These points are reserved and cannot be withdrawn again until the transfer settles.'}
|
||||
</p>
|
||||
<p>
|
||||
Restore the server’s connection and allow it to retry. Pending transfers do not expire
|
||||
automatically.
|
||||
</p>
|
||||
<div>
|
||||
<ServerIdentity name={transfer.server} /> · <RelativeTime value={transfer.createdAt} />
|
||||
</div>
|
||||
{#if transfer.matchAvailable}<a href={contextHref(`/matches/${transfer.matchId}`, source)}
|
||||
>View match #{transfer.matchId}</a
|
||||
>{:else if transfer.matchId}<span>Match #{transfer.matchId} · History expired</span>{/if}
|
||||
<details>
|
||||
<summary>Transfer details</summary><CopyValue
|
||||
value={transfer.requestId}
|
||||
label="Request ID"
|
||||
/><CopyValue value={transfer.server} label="Server ID" />
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.pending-details {
|
||||
display: grid;
|
||||
gap: var(--space-3);
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
summary {
|
||||
padding-block: var(--space-2);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,70 @@
|
||||
<script lang="ts">
|
||||
import type { BankTransfer } from '$lib/bank.js';
|
||||
import { contextHref } from '$lib/navigation-context.js';
|
||||
import RelativeTime from '../RelativeTime.svelte';
|
||||
import ServerIdentity from '../ServerIdentity.svelte';
|
||||
import EmptyState from '../primitives/EmptyState.svelte';
|
||||
|
||||
let {
|
||||
entries,
|
||||
source,
|
||||
onPlayer,
|
||||
compact = false
|
||||
}: {
|
||||
entries: BankTransfer[];
|
||||
source: URL;
|
||||
onPlayer?: (guid: string) => void;
|
||||
compact?: boolean;
|
||||
} = $props();
|
||||
const number = new Intl.NumberFormat('en-US');
|
||||
</script>
|
||||
|
||||
{#if entries.length}
|
||||
<!-- svelte-ignore a11y_no_noninteractive_tabindex (Keyboard users need to scroll wide tables.) -->
|
||||
<div class="bank-table-scroll" role="region" aria-label="Bank transactions" tabindex="0">
|
||||
<table class="bank-table" class:compact>
|
||||
<caption class="sr-only">Completed bank transfers</caption>
|
||||
<thead
|
||||
><tr
|
||||
><th scope="col">Time</th>{#if onPlayer}<th scope="col">Player</th>{/if}<th
|
||||
scope="col">Transfer</th
|
||||
><th scope="col">Balance after</th><th scope="col">Server / match</th></tr
|
||||
></thead
|
||||
>
|
||||
<tbody>
|
||||
{#each entries as entry (entry.id)}
|
||||
<tr>
|
||||
<td><RelativeTime value={entry.createdAt} /></td>
|
||||
{#if onPlayer}<td
|
||||
><button class="bank-player" onclick={() => onPlayer?.(entry.guid)}
|
||||
>{entry.name ?? entry.guid}</button
|
||||
><small class="bank-id">{entry.guid}</small></td
|
||||
>{/if}
|
||||
<td class="bank-number"
|
||||
><strong
|
||||
>{entry.amount > 0 ? '+' : '−'}{number.format(
|
||||
Math.abs(entry.amount)
|
||||
)}</strong
|
||||
><small>{entry.amount > 0 ? 'Deposit' : 'Withdrawal'}</small></td
|
||||
>
|
||||
<td class="bank-number">{number.format(entry.balance)}</td>
|
||||
<td
|
||||
><ServerIdentity name={entry.server} /><small
|
||||
>{#if entry.matchAvailable}<a
|
||||
href={contextHref(`/matches/${entry.matchId}`, source)}
|
||||
>Match #{entry.matchId}</a
|
||||
>{:else if entry.matchId}Match #{entry.matchId} · History expired{:else}Match
|
||||
unavailable{/if}</small
|
||||
></td
|
||||
>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{:else}
|
||||
<EmptyState
|
||||
title="No transactions found"
|
||||
description="Completed deposits and withdrawals appear here. Try changing your filters if you expected to see more."
|
||||
/>
|
||||
{/if}
|
||||
Reference in New Issue
Block a user