Files
2026-07-25 18:36:45 +04:00

134 lines
7.2 KiB
Vue
Raw Permalink 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.
<script setup>
import { Head, Link, router, useForm } from '@inertiajs/vue3';
import { ref } from 'vue';
import AdminLayout from '../../Layouts/AdminLayout.vue';
const props = defineProps({
site: { type: Object, required: true },
auth: { type: Object, required: true },
urls: { type: Object, required: true },
flash: { type: Object, default: () => ({}) },
transactions: { type: Array, default: () => [] },
search: { type: String, default: '' },
adjustUrl: { type: String, required: true },
old: { type: Object, default: () => ({}) },
});
const searchValue = ref(props.search);
const form = useForm({
account: props.old.account || '',
direction: props.old.direction || 'credit',
amount: props.old.amount || '',
reason: props.old.reason || '',
});
function submit() {
form.post(props.adjustUrl, {
preserveScroll: true,
onSuccess: () => form.reset(),
});
}
function searchTransactions() {
router.get(props.urls.admin_balances, {
search: searchValue.value || undefined,
}, { preserveState: true, replace: true });
}
</script>
<template>
<Head><title>Слёзы Элуны {{ site.name }}</title></Head>
<AdminLayout :site="site" :auth="auth" :urls="urls" :flash="flash" current="balances">
<section class="admin-hero wrap">
<div>
<span class="eyebrow">Финансы</span>
<h1 class="h-display">Слёзы Элуны</h1>
<p class="lead">Ручные корректировки и полный журнал движения виртуальной валюты.</p>
</div>
<div class="admin-hero__badge"><small>Операций в выборке</small><strong>{{ transactions.length }}</strong></div>
</section>
<div class="admin-page wrap">
<section class="admin-section">
<div class="admin-split admin-split--form">
<article class="portal-card admin-panel corners">
<span class="admin-kicker">Новая операция</span>
<h2 class="h-serif">Изменить баланс</h2>
<form class="admin-form" @submit.prevent="submit">
<label class="admin-field">
<span>ID или логин аккаунта</span>
<input v-model="form.account" required />
<small v-if="form.errors.account">{{ form.errors.account }}</small>
</label>
<div class="admin-form-grid">
<label class="admin-field">
<span>Операция</span>
<select v-model="form.direction" required>
<option value="credit">Начислить</option>
<option value="debit">Снять</option>
</select>
<small v-if="form.errors.direction">{{ form.errors.direction }}</small>
</label>
<label class="admin-field">
<span>Количество</span>
<input v-model="form.amount" type="number" min="0.01" max="1000000" step="0.01" required />
<small v-if="form.errors.amount">{{ form.errors.amount }}</small>
</label>
</div>
<label class="admin-field">
<span>Причина</span>
<input v-model="form.reason" maxlength="255" placeholder="Компенсация, возврат, нарушение…" required />
<small v-if="form.errors.reason">{{ form.errors.reason }}</small>
</label>
<button class="btn btn-primary admin-submit" type="submit" :disabled="form.processing">
{{ form.processing ? 'Проводим…' : 'Провести операцию' }}
</button>
</form>
</article>
<article class="portal-card admin-panel admin-rules">
<span class="admin-kicker">Контроль</span>
<h2 class="h-serif">Правила операций</h2>
<div><span>01</span><p>Баланс аккаунта не может стать отрицательным.</p></div>
<div><span>02</span><p>В журнале сохраняются администратор, причина и итоговое значение.</p></div>
<div><span>03</span><p>Ошибочная операция исправляется отдельной обратной корректировкой.</p></div>
</article>
</div>
</section>
<section class="admin-section">
<div class="admin-section__head">
<div><span class="eyebrow">Аудит</span><h2 class="h-serif">Последние транзакции</h2></div>
<form class="admin-search" @submit.prevent="searchTransactions">
<input v-model="searchValue" type="search" placeholder="Логин или ID аккаунта" />
<button class="btn btn-primary" type="submit">Найти</button>
<Link v-if="search" class="btn btn-ghost" :href="urls.admin_balances">Сбросить</Link>
</form>
</div>
<div v-if="transactions.length" class="admin-ledger">
<article v-for="transaction in transactions" :key="transaction.id" class="portal-card admin-ledger__row">
<div>
<strong>{{ transaction.username }}</strong>
<small>ID #{{ transaction.account_id }} · {{ transaction.created_at }}</small>
</div>
<div>
<strong>{{ transaction.type_label }}</strong>
<small>{{ transaction.description }}</small>
<small v-if="transaction.admin">Администратор: {{ transaction.admin.username }} (#{{ transaction.admin.account_id }})</small>
</div>
<div class="admin-ledger__amount">
<strong :class="{ positive: transaction.is_positive }">
{{ transaction.is_positive ? '+' : '' }}{{ transaction.formatted_amount }}
</strong>
<small>Баланс: {{ transaction.formatted_balance_after }}</small>
</div>
</article>
</div>
<article v-else class="portal-card admin-empty"><p>Транзакции не найдены.</p></article>
</section>
</div>
</AdminLayout>
</template>