Files
sam-manage/resources/views/finance/accounts/index.blade.php
김보곤 fefd224c36 fix:보유계좌관리 레이아웃 화면 전체 너비로 변경
container mx-auto 제거하여 전체 너비 사용

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:45:10 +09:00

138 lines
6.4 KiB
PHP

@extends('layouts.app')
@section('title', '보유계좌관리')
@section('content')
<div class="px-4 py-6">
{{-- 페이지 헤더 --}}
<div class="flex flex-col lg:flex-row lg:justify-between lg:items-center gap-4 mb-6">
<div>
<h1 class="text-2xl font-bold text-gray-800">보유계좌관리</h1>
<p class="text-sm text-gray-500 mt-1">{{ now()->format('Y년 n월 j일') }} 현재</p>
</div>
<div class="flex flex-wrap items-center gap-2 sm:gap-3">
<a href="{{ route('finance.accounts.create') }}"
class="inline-flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition-colors">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
</svg>
계좌 등록
</a>
</div>
</div>
{{-- 요약 카드 (선택사항) --}}
@if(isset($summary) && $summary['total_accounts'] > 0)
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<div class="bg-white rounded-lg shadow-sm p-4">
<div class="text-sm text-gray-500"> 계좌 </div>
<div class="text-2xl font-bold text-gray-800">{{ $summary['total_accounts'] }}</div>
</div>
<div class="bg-white rounded-lg shadow-sm p-4">
<div class="text-sm text-gray-500"> 잔액</div>
<div class="text-2xl font-bold text-emerald-600" data-total-balance>{{ $summary['formatted_total_balance'] }}</div>
</div>
<div class="bg-white rounded-lg shadow-sm p-4">
<div class="text-sm text-gray-500">은행 </div>
<div class="text-2xl font-bold text-gray-800">{{ count($summary['by_bank']) }}</div>
</div>
</div>
@endif
{{-- 테이블 컨테이너 --}}
<div class="bg-white rounded-lg shadow-sm overflow-hidden">
{{-- 테이블 헤더 --}}
<div class="px-6 py-4 border-b border-gray-200 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
<h2 class="text-lg font-semibold text-gray-800">보유 계좌 목록</h2>
{{-- 필터/검색 --}}
<form id="filterForm" class="flex flex-col sm:flex-row gap-2 sm:gap-3">
<input type="text" name="search" placeholder="검색..."
value="{{ request('search') }}"
class="px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500">
<select name="is_active" class="px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500">
<option value="">전체 상태</option>
<option value="1" {{ request('is_active') === '1' ? 'selected' : '' }}>활성</option>
<option value="0" {{ request('is_active') === '0' ? 'selected' : '' }}>비활성</option>
</select>
<button type="submit"
hx-get="{{ route('api.admin.bank-accounts.index') }}"
hx-target="#accounts-table"
hx-include="#filterForm"
class="px-4 py-2 bg-gray-600 hover:bg-gray-700 text-white text-sm rounded-lg transition-colors">
검색
</button>
</form>
</div>
{{-- HTMX 테이블 영역 --}}
<div id="accounts-table"
hx-get="{{ route('api.admin.bank-accounts.index') }}"
hx-trigger="load"
hx-headers='{"X-CSRF-TOKEN": "{{ csrf_token() }}"}'
class="min-h-[200px]">
{{-- 로딩 스피너 --}}
<div class="flex justify-center items-center p-12">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-emerald-600"></div>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
<script>
// 필터 폼 제출 시 HTMX 트리거
document.getElementById('filterForm')?.addEventListener('submit', function(e) {
e.preventDefault();
htmx.trigger('#accounts-table', 'htmx:trigger');
});
// 바로빌 잔액 조회 및 업데이트
async function refreshAccountBalances() {
try {
const res = await fetch('{{ route("barobill.eaccount.latest-balances") }}');
const data = await res.json();
if (data.success && data.balances && data.balances.length > 0) {
const balanceMap = {};
data.balances.forEach(b => {
const num = (b.bankAccountNum || '').replace(/-/g, '');
balanceMap[num] = b.balance || 0;
});
let totalBalance = 0;
document.querySelectorAll('#accounts-table [data-account-number]').forEach(td => {
const accNum = td.dataset.accountNumber;
const balanceEl = td.querySelector('.account-balance');
if (balanceEl && balanceMap.hasOwnProperty(accNum)) {
const newBalance = balanceMap[accNum];
balanceEl.textContent = new Intl.NumberFormat('ko-KR').format(newBalance) + '원';
balanceEl.classList.remove('text-gray-900');
balanceEl.classList.add(newBalance >= 100000000 ? 'text-emerald-600' : 'text-gray-900');
totalBalance += newBalance;
} else if (balanceEl) {
totalBalance += parseFloat(balanceEl.dataset.original || 0);
}
});
// 요약 카드의 총 잔액 업데이트
const totalBalanceEl = document.querySelector('[data-total-balance]');
if (totalBalanceEl) {
totalBalanceEl.textContent = new Intl.NumberFormat('ko-KR').format(totalBalance) + '원';
}
}
} catch (e) {
console.error('잔액 조회 오류:', e);
}
}
// HTMX 테이블 로드 완료 후 잔액 조회
document.body.addEventListener('htmx:afterSwap', function(e) {
if (e.detail.target.id === 'accounts-table') {
refreshAccountBalances();
}
});
</script>
@endpush