Add membership fee system with disability discount and fix document permissions

Features:
- Implement two fee types: entrance fee and annual fee (both NT$1,000)
- Add 50% discount for disability certificate holders
- Add disability certificate upload in member profile
- Integrate disability verification into cashier approval workflow
- Add membership fee settings in system admin

Document permissions:
- Fix hard-coded role logic in Document model
- Use permission-based authorization instead of role checks

Additional features:
- Add announcements, general ledger, and trial balance modules
- Add income management and accounting entries
- Add comprehensive test suite with factories
- Update UI translations to Traditional Chinese

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-01 09:56:01 +08:00
parent 83ce1f7fc8
commit 642b879dd4
207 changed files with 19487 additions and 3048 deletions

View File

@@ -0,0 +1,129 @@
<x-app-layout>
<x-slot name="header">
<div class="flex items-center justify-between">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
建立公告
</h2>
<a href="{{ route('admin.announcements.index') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
返回列表
</a>
</div>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-4xl sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<form method="POST" action="{{ route('admin.announcements.store') }}" class="space-y-6 p-6">
@csrf
<!-- Title -->
<div>
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-300">標題 <span class="text-red-500">*</span></label>
<input type="text" name="title" id="title" value="{{ old('title') }}" required
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="輸入公告標題">
@error('title')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Content -->
<div>
<label for="content" class="block text-sm font-medium text-gray-700 dark:text-gray-300">內容 <span class="text-red-500">*</span></label>
<textarea name="content" id="content" rows="10" required
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="輸入公告內容">{{ old('content') }}</textarea>
@error('content')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Access Level -->
<div>
<label for="access_level" class="block text-sm font-medium text-gray-700 dark:text-gray-300">存取權限 <span class="text-red-500">*</span></label>
<select name="access_level" id="access_level" required
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="members" {{ old('access_level') === 'members' ? 'selected' : '' }}>會員(需付費會籍)</option>
<option value="public" {{ old('access_level') === 'public' ? 'selected' : '' }}>公開(所有人可見)</option>
<option value="board" {{ old('access_level') === 'board' ? 'selected' : '' }}>理事會(僅理事可見)</option>
<option value="admin" {{ old('access_level') === 'admin' ? 'selected' : '' }}>管理員(僅管理員可見)</option>
</select>
@error('access_level')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Published At -->
<div>
<label for="published_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">發布時間(選填,留空則立即發布)</label>
<input type="datetime-local" name="published_at" id="published_at" value="{{ old('published_at') }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">設定未來時間可排程發布</p>
@error('published_at')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Expires At -->
<div>
<label for="expires_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">過期時間(選填)</label>
<input type="datetime-local" name="expires_at" id="expires_at" value="{{ old('expires_at') }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">過期後將自動隱藏</p>
@error('expires_at')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Is Pinned -->
<div class="flex items-center">
<input type="checkbox" name="is_pinned" id="is_pinned" value="1" {{ old('is_pinned') ? 'checked' : '' }}
class="h-4 w-4 rounded border-gray-300 dark:border-gray-700 text-indigo-600 focus:ring-indigo-500 dark:bg-gray-900">
<label for="is_pinned" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">置頂此公告</label>
</div>
<!-- Display Order (only shown when pinned) -->
<div id="display_order_container" style="display: none;">
<label for="display_order" class="block text-sm font-medium text-gray-700 dark:text-gray-300">顯示順序</label>
<input type="number" name="display_order" id="display_order" value="{{ old('display_order', 0) }}" min="0"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">數字越小越優先顯示</p>
</div>
<!-- Action Buttons -->
<div class="flex items-center justify-end space-x-3 border-t border-gray-200 dark:border-gray-700 pt-6">
<a href="{{ route('admin.announcements.index') }}" class="rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
取消
</a>
<button type="submit" name="save_action" value="draft" class="rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
儲存為草稿
</button>
<button type="submit" name="save_action" value="publish" class="rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
發布公告
</button>
</div>
</form>
</div>
</div>
</div>
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', function() {
const isPinnedCheckbox = document.getElementById('is_pinned');
const displayOrderContainer = document.getElementById('display_order_container');
function toggleDisplayOrder() {
if (isPinnedCheckbox.checked) {
displayOrderContainer.style.display = 'block';
} else {
displayOrderContainer.style.display = 'none';
}
}
isPinnedCheckbox.addEventListener('change', toggleDisplayOrder);
toggleDisplayOrder();
});
</script>
@endpush
</x-app-layout>

View File

@@ -0,0 +1,126 @@
<x-app-layout>
<x-slot name="header">
<div class="flex items-center justify-between">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
編輯公告
</h2>
<a href="{{ route('admin.announcements.show', $announcement) }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
返回查看
</a>
</div>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-4xl sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<form method="POST" action="{{ route('admin.announcements.update', $announcement) }}" class="space-y-6 p-6">
@csrf
@method('PATCH')
<!-- Title -->
<div>
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-300">標題 <span class="text-red-500">*</span></label>
<input type="text" name="title" id="title" value="{{ old('title', $announcement->title) }}" required
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
@error('title')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Content -->
<div>
<label for="content" class="block text-sm font-medium text-gray-700 dark:text-gray-300">內容 <span class="text-red-500">*</span></label>
<textarea name="content" id="content" rows="10" required
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">{{ old('content', $announcement->content) }}</textarea>
@error('content')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Access Level -->
<div>
<label for="access_level" class="block text-sm font-medium text-gray-700 dark:text-gray-300">存取權限 <span class="text-red-500">*</span></label>
<select name="access_level" id="access_level" required
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="members" {{ old('access_level', $announcement->access_level) === 'members' ? 'selected' : '' }}>會員</option>
<option value="public" {{ old('access_level', $announcement->access_level) === 'public' ? 'selected' : '' }}>公開</option>
<option value="board" {{ old('access_level', $announcement->access_level) === 'board' ? 'selected' : '' }}>理事會</option>
<option value="admin" {{ old('access_level', $announcement->access_level) === 'admin' ? 'selected' : '' }}>管理員</option>
</select>
@error('access_level')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Published At -->
<div>
<label for="published_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">發布時間</label>
<input type="datetime-local" name="published_at" id="published_at"
value="{{ old('published_at', $announcement->published_at?->format('Y-m-d\TH:i')) }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
@error('published_at')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Expires At -->
<div>
<label for="expires_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">過期時間</label>
<input type="datetime-local" name="expires_at" id="expires_at"
value="{{ old('expires_at', $announcement->expires_at?->format('Y-m-d\TH:i')) }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
@error('expires_at')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Is Pinned -->
<div class="flex items-center">
<input type="checkbox" name="is_pinned" id="is_pinned" value="1"
{{ old('is_pinned', $announcement->is_pinned) ? 'checked' : '' }}
class="h-4 w-4 rounded border-gray-300 dark:border-gray-700 text-indigo-600 focus:ring-indigo-500 dark:bg-gray-900">
<label for="is_pinned" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">置頂此公告</label>
</div>
<!-- Display Order -->
<div id="display_order_container">
<label for="display_order" class="block text-sm font-medium text-gray-700 dark:text-gray-300">顯示順序</label>
<input type="number" name="display_order" id="display_order"
value="{{ old('display_order', $announcement->display_order) }}" min="0"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
</div>
<!-- Action Buttons -->
<div class="flex items-center justify-end space-x-3 border-t border-gray-200 dark:border-gray-700 pt-6">
<a href="{{ route('admin.announcements.show', $announcement) }}" class="rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
取消
</a>
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
儲存變更
</button>
</div>
</form>
</div>
</div>
</div>
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', function() {
const isPinnedCheckbox = document.getElementById('is_pinned');
const displayOrderContainer = document.getElementById('display_order_container');
function toggleDisplayOrder() {
if (isPinnedCheckbox.checked) {
displayOrderContainer.style.display = 'block';
} else {
displayOrderContainer.style.display = 'none';
}
}
isPinnedCheckbox.addEventListener('change', toggleDisplayOrder);
toggleDisplayOrder();
});
</script>
@endpush
</x-app-layout>

View File

@@ -0,0 +1,186 @@
<x-app-layout>
<x-slot name="header">
<div class="flex items-center justify-between">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
公告管理
</h2>
<a href="{{ route('admin.announcements.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
+ 建立公告
</a>
</div>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-6">
@if (session('status'))
<div class="rounded-md bg-green-50 dark:bg-green-900/50 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 dark:bg-red-900/50 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<!-- Statistics -->
<div class="grid grid-cols-1 gap-4 md:grid-cols-5">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
<div class="text-sm font-medium text-gray-500 dark:text-gray-400">總計</div>
<div class="mt-2 text-3xl font-bold text-gray-900 dark:text-gray-100">{{ $stats['total'] }}</div>
</div>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
<div class="text-sm font-medium text-gray-500 dark:text-gray-400">草稿</div>
<div class="mt-2 text-3xl font-bold text-gray-600 dark:text-gray-400">{{ $stats['draft'] }}</div>
</div>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
<div class="text-sm font-medium text-gray-500 dark:text-gray-400">已發布</div>
<div class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ $stats['published'] }}</div>
</div>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
<div class="text-sm font-medium text-gray-500 dark:text-gray-400">已歸檔</div>
<div class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ $stats['archived'] }}</div>
</div>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
<div class="text-sm font-medium text-gray-500 dark:text-gray-400">置頂中</div>
<div class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ $stats['pinned'] }}</div>
</div>
</div>
<!-- Search and Filter -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
<form method="GET" action="{{ route('admin.announcements.index') }}" class="space-y-4">
<div class="grid grid-cols-1 gap-4 md:grid-cols-4">
<div>
<label for="search" class="block text-sm font-medium text-gray-700 dark:text-gray-300">搜尋</label>
<input type="text" name="search" id="search" value="{{ request('search') }}" placeholder="標題、內容..."
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
</div>
<div>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">狀態</label>
<select name="status" id="status" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部</option>
<option value="draft" {{ request('status') === 'draft' ? 'selected' : '' }}>草稿</option>
<option value="published" {{ request('status') === 'published' ? 'selected' : '' }}>已發布</option>
<option value="archived" {{ request('status') === 'archived' ? 'selected' : '' }}>已歸檔</option>
</select>
</div>
<div>
<label for="access_level" class="block text-sm font-medium text-gray-700 dark:text-gray-300">存取權限</label>
<select name="access_level" id="access_level" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部</option>
<option value="public" {{ request('access_level') === 'public' ? 'selected' : '' }}>公開</option>
<option value="members" {{ request('access_level') === 'members' ? 'selected' : '' }}>會員</option>
<option value="board" {{ request('access_level') === 'board' ? 'selected' : '' }}>理事會</option>
<option value="admin" {{ request('access_level') === 'admin' ? 'selected' : '' }}>管理員</option>
</select>
</div>
<div>
<label for="pinned" class="block text-sm font-medium text-gray-700 dark:text-gray-300">置頂</label>
<select name="pinned" id="pinned" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部</option>
<option value="yes" {{ request('pinned') === 'yes' ? 'selected' : '' }}>已置頂</option>
<option value="no" {{ request('pinned') === 'no' ? 'selected' : '' }}>未置頂</option>
</select>
</div>
</div>
<div class="flex justify-end space-x-2">
<a href="{{ route('admin.announcements.index') }}" class="rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
清除
</a>
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
搜尋
</button>
</div>
</form>
</div>
<div class="flex justify-between items-center">
<div>
<p class="text-sm text-gray-600 dark:text-gray-400"> {{ $announcements->total() }} 則公告</p>
</div>
</div>
<!-- Announcements Table -->
<div class="bg-white dark:bg-gray-800 shadow overflow-hidden sm:rounded-lg">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">公告</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">狀態</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">存取權限</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">建立者</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">瀏覽次數</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">建立時間</th>
<th scope="col" class="px-6 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">操作</th>
</tr>
</thead>
<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
@forelse($announcements as $announcement)
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
@if($announcement->is_pinned)
<span class="mr-2 text-blue-500" title="置頂公告">📌</span>
@endif
<div>
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">
<a href="{{ route('admin.announcements.show', $announcement) }}" class="hover:text-indigo-600 dark:hover:text-indigo-400">
{{ $announcement->title }}
</a>
</div>
<div class="text-sm text-gray-500 dark:text-gray-400">
{{ \Illuminate\Support\Str::limit($announcement->content, 60) }}
</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="inline-flex rounded-full px-2 text-xs font-semibold leading-5
@if($announcement->status === 'draft') bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-300
@elseif($announcement->status === 'published') bg-green-100 dark:bg-green-900/50 text-green-800 dark:text-green-300
@else bg-yellow-100 dark:bg-yellow-900/50 text-yellow-800 dark:text-yellow-300
@endif">
{{ $announcement->getStatusLabel() }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
{{ $announcement->getAccessLevelLabel() }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
{{ $announcement->creator->name ?? 'N/A' }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
{{ $announcement->view_count }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
{{ $announcement->created_at->format('Y-m-d H:i') }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium space-x-2">
<a href="{{ route('admin.announcements.show', $announcement) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">查看</a>
@if($announcement->canBeEditedBy(auth()->user()))
<a href="{{ route('admin.announcements.edit', $announcement) }}" class="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-300">編輯</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-6 py-12 text-center text-sm text-gray-500 dark:text-gray-400">
沒有找到公告。<a href="{{ route('admin.announcements.create') }}" class="text-indigo-600 dark:text-indigo-400 hover:underline">建立第一則公告</a>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<!-- Pagination -->
@if($announcements->hasPages())
<div class="bg-white dark:bg-gray-800 px-4 py-3 border-t border-gray-200 dark:border-gray-700 sm:px-6">
{{ $announcements->links() }}
</div>
@endif
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,170 @@
<x-app-layout>
<x-slot name="header">
<div class="flex items-center justify-between">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
公告詳情
</h2>
<div class="flex items-center space-x-2">
<a href="{{ route('admin.announcements.index') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
返回列表
</a>
@if($announcement->canBeEditedBy(auth()->user()))
<a href="{{ route('admin.announcements.edit', $announcement) }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
編輯公告
</a>
@endif
</div>
</div>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-4xl sm:px-6 lg:px-8 space-y-6">
@if (session('status'))
<div class="rounded-md bg-green-50 dark:bg-green-900/50 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 dark:bg-red-900/50 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<!-- Announcement Content -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
<div class="mb-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-2xl font-bold text-gray-900 dark:text-gray-100">
@if($announcement->is_pinned)
<span class="text-blue-500" title="置頂公告">📌</span>
@endif
{{ $announcement->title }}
</h3>
<span class="inline-flex rounded-full px-3 py-1 text-sm font-semibold
@if($announcement->status === 'draft') bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-300
@elseif($announcement->status === 'published') bg-green-100 dark:bg-green-900/50 text-green-800 dark:text-green-300
@else bg-yellow-100 dark:bg-yellow-900/50 text-yellow-800 dark:text-yellow-300
@endif">
{{ $announcement->getStatusLabel() }}
</span>
</div>
<div class="prose dark:prose-invert max-w-none">
<div class="whitespace-pre-wrap text-gray-700 dark:text-gray-300">{{ $announcement->content }}</div>
</div>
</div>
</div>
<!-- Metadata -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
<h4 class="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-4">公告資訊</h4>
<dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">存取權限</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $announcement->getAccessLevelLabel() }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">瀏覽次數</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $announcement->view_count }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">建立者</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $announcement->creator->name ?? 'N/A' }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">建立時間</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $announcement->created_at->format('Y-m-d H:i:s') }}</dd>
</div>
@if($announcement->published_at)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">發布時間</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $announcement->published_at->format('Y-m-d H:i:s') }}
@if($announcement->isScheduled())
<span class="ml-2 inline-flex rounded-full bg-blue-100 dark:bg-blue-900/50 px-2 py-1 text-xs font-semibold text-blue-800 dark:text-blue-300">排程中</span>
@endif
</dd>
</div>
@endif
@if($announcement->expires_at)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">過期時間</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $announcement->expires_at->format('Y-m-d H:i:s') }}
@if($announcement->isExpired())
<span class="ml-2 inline-flex rounded-full bg-red-100 dark:bg-red-900/50 px-2 py-1 text-xs font-semibold text-red-800 dark:text-red-300">已過期</span>
@endif
</dd>
</div>
@endif
@if($announcement->lastUpdatedBy)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">最後更新者</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $announcement->lastUpdatedBy->name }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">最後更新時間</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $announcement->updated_at->format('Y-m-d H:i:s') }}</dd>
</div>
@endif
</dl>
</div>
<!-- Actions -->
@if($announcement->canBeEditedBy(auth()->user()))
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
<h4 class="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-4">操作</h4>
<div class="flex flex-wrap gap-3">
@if($announcement->isDraft() && auth()->user()->can('publish_announcements'))
<form method="POST" action="{{ route('admin.announcements.publish', $announcement) }}">
@csrf
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-green-600 dark:bg-green-500 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 dark:hover:bg-green-600">
發布公告
</button>
</form>
@endif
@if($announcement->isPublished() && auth()->user()->can('publish_announcements'))
<form method="POST" action="{{ route('admin.announcements.archive', $announcement) }}">
@csrf
<button type="submit" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
歸檔公告
</button>
</form>
@endif
@if(!$announcement->is_pinned && auth()->user()->can('edit_announcements'))
<form method="POST" action="{{ route('admin.announcements.pin', $announcement) }}">
@csrf
<button type="submit" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
📌 置頂公告
</button>
</form>
@endif
@if($announcement->is_pinned && auth()->user()->can('edit_announcements'))
<form method="POST" action="{{ route('admin.announcements.unpin', $announcement) }}">
@csrf
<button type="submit" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
取消置頂
</button>
</form>
@endif
@if(auth()->user()->can('delete_announcements'))
<form method="POST" action="{{ route('admin.announcements.destroy', $announcement) }}"
onsubmit="return confirm('確定要刪除此公告嗎?');">
@csrf
@method('DELETE')
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-red-600 dark:bg-red-500 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 dark:hover:bg-red-600">
刪除公告
</button>
</form>
@endif
</div>
</div>
@endif
</div>
</div>
</x-app-layout>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Audit Logs') }}
稽核日誌
</h2>
</x-slot>
@@ -9,18 +9,18 @@
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="GET" action="{{ route('admin.audit.index') }}" class="space-y-4" role="search" aria-label="{{ __('Filter audit logs') }}">
<form method="GET" action="{{ route('admin.audit.index') }}" class="space-y-4" role="search" aria-label="篩選稽核日誌">
<div class="grid grid-cols-1 gap-4 md:grid-cols-4">
<div>
<label for="user_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('User') }}
使用者
</label>
<select
name="user_id"
id="user_id"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100"
>
<option value="">{{ __('All Users') }}</option>
<option value="">所有使用者</option>
@foreach ($users as $user)
<option value="{{ $user->id }}" @selected(request('user_id') == $user->id)>
{{ $user->name }}
@@ -31,14 +31,14 @@
<div>
<label for="event" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Event') }}
事件
</label>
<select
name="event"
id="event"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100"
>
<option value="">{{ __('All Events') }}</option>
<option value="">所有事件</option>
@foreach ($actions as $action)
<option value="{{ $action }}" @selected(request('action') == $action)>
{{ ucfirst($action) }}
@@ -49,14 +49,14 @@
<div>
<label for="auditable_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Model Type') }}
模型類型
</label>
<select
name="auditable_type"
id="auditable_type"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100"
>
<option value="">{{ __('All Types') }}</option>
<option value="">所有類型</option>
@foreach ($auditableTypes as $type)
<option value="{{ $type }}" @selected(request('auditable_type') == $type)>
{{ class_basename($type) }}
@@ -67,7 +67,7 @@
<div class="flex items-end">
<button type="submit" class="inline-flex w-full justify-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
{{ __('Filter') }}
篩選
</button>
</div>
</div>
@@ -78,22 +78,22 @@
<thead class="bg-gray-50 dark:bg-gray-900">
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100 sm:pl-6">
{{ __('User') }}
使用者
</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">
{{ __('Event') }}
事件
</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">
{{ __('Model') }}
模型
</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">
{{ __('Details') }}
詳情
</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">
{{ __('IP Address') }}
IP位址
</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">
{{ __('Date') }}
日期
</th>
</tr>
</thead>
@@ -120,7 +120,7 @@
<div>{{ $log->description ?: '—' }}</div>
@if(!empty($log->metadata))
<details class="cursor-pointer group mt-1">
<summary class="text-xs text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">{{ __('Metadata') }}</summary>
<summary class="text-xs text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">元數據</summary>
<div class="mt-2 p-2 bg-gray-50 dark:bg-gray-900 rounded text-xs font-mono overflow-x-auto">
<pre class="whitespace-pre-wrap text-gray-800 dark:text-gray-200">{{ json_encode($log->metadata, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) }}</pre>
</div>
@@ -137,7 +137,7 @@
@empty
<tr>
<td colspan="6" class="px-3 py-4 text-sm text-gray-500 dark:text-gray-400 text-center">
{{ __('No audit logs found.') }}
找不到稽核日誌。
</td>
</tr>
@endforelse

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
製作銀行調節表
</h2>
</x-slot>
@@ -8,22 +8,22 @@
<div class="py-12">
<div class="mx-auto max-w-5xl sm:px-6 lg:px-8 space-y-4">
@if (session('error'))
<div class="rounded-md bg-red-50 p-4">
<p class="text-sm font-medium text-red-800">{{ session('error') }}</p>
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<!-- Help Info -->
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
<div class="bg-blue-50 dark:bg-blue-900/30 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="h-5 w-5 text-blue-400 dark:text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-blue-800">銀行調節表說明</h3>
<div class="mt-2 text-sm text-blue-700">
<h3 class="text-sm font-medium text-blue-800 dark:text-blue-200">銀行調節表說明</h3>
<div class="mt-2 text-sm text-blue-700 dark:text-blue-300">
<p>銀行調節表用於核對銀行對帳單餘額與內部現金簿餘額的差異。請準備好:</p>
<ul class="list-disc pl-5 mt-2 space-y-1">
<li>銀行對帳單 (PDF/圖片檔)</li>
@@ -40,89 +40,89 @@
@csrf
<!-- Basic Information -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">基本資訊</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">基本資訊</h3>
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<!-- Reconciliation Month -->
<div>
<label for="reconciliation_month" class="block text-sm font-medium text-gray-700">
調節月份 <span class="text-red-500">*</span>
<label for="reconciliation_month" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
調節月份 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<input type="month" name="reconciliation_month" id="reconciliation_month" required
value="{{ old('reconciliation_month', $month) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('reconciliation_month') border-red-300 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100 @error('reconciliation_month') border-red-300 dark:border-red-700 @enderror">
@error('reconciliation_month')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Bank Statement Date -->
<div>
<label for="bank_statement_date" class="block text-sm font-medium text-gray-700">
對帳單日期 <span class="text-red-500">*</span>
<label for="bank_statement_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
對帳單日期 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<input type="date" name="bank_statement_date" id="bank_statement_date" required
value="{{ old('bank_statement_date') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('bank_statement_date') border-red-300 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100 @error('bank_statement_date') border-red-300 dark:border-red-700 @enderror">
@error('bank_statement_date')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Bank Statement Balance -->
<div>
<label for="bank_statement_balance" class="block text-sm font-medium text-gray-700">
銀行對帳單餘額 <span class="text-red-500">*</span>
<label for="bank_statement_balance" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
銀行對帳單餘額 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<div class="relative mt-1 rounded-md shadow-sm">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<span class="text-gray-500 sm:text-sm">NT$</span>
<span class="text-gray-500 dark:text-gray-400 sm:text-sm">NT$</span>
</div>
<input type="number" name="bank_statement_balance" id="bank_statement_balance" step="0.01" required
value="{{ old('bank_statement_balance') }}"
class="block w-full rounded-md border-gray-300 pl-12 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('bank_statement_balance') border-red-300 @enderror">
class="block w-full rounded-md border-gray-300 dark:border-gray-700 pl-12 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100 @error('bank_statement_balance') border-red-300 dark:border-red-700 @enderror">
</div>
@error('bank_statement_balance')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- System Book Balance -->
<div>
<label for="system_book_balance" class="block text-sm font-medium text-gray-700">
系統帳面餘額 <span class="text-red-500">*</span>
<label for="system_book_balance" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
系統帳面餘額 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<div class="relative mt-1 rounded-md shadow-sm">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<span class="text-gray-500 sm:text-sm">NT$</span>
<span class="text-gray-500 dark:text-gray-400 sm:text-sm">NT$</span>
</div>
<input type="number" name="system_book_balance" id="system_book_balance" step="0.01" required
value="{{ old('system_book_balance', $systemBalance) }}"
class="block w-full rounded-md border-gray-300 pl-12 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('system_book_balance') border-red-300 @enderror">
class="block w-full rounded-md border-gray-300 dark:border-gray-700 pl-12 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100 @error('system_book_balance') border-red-300 dark:border-red-700 @enderror">
</div>
<p class="mt-1 text-xs text-gray-500">從現金簿自動帶入: NT$ {{ number_format($systemBalance, 2) }}</p>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">從現金簿自動帶入: NT$ {{ number_format($systemBalance, 2) }}</p>
@error('system_book_balance')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Bank Statement File -->
<div class="sm:col-span-2">
<label for="bank_statement_file" class="block text-sm font-medium text-gray-700">
<label for="bank_statement_file" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
銀行對帳單檔案
</label>
<input type="file" name="bank_statement_file" id="bank_statement_file" accept=".pdf,.jpg,.jpeg,.png"
class="mt-1 block w-full text-sm text-gray-500
class="mt-1 block w-full text-sm text-gray-500 dark:text-gray-400
file:mr-4 file:py-2 file:px-4
file:rounded-md file:border-0
file:text-sm file:font-semibold
file:bg-indigo-50 file:text-indigo-700
hover:file:bg-indigo-100">
<p class="mt-1 text-xs text-gray-500">支援格式: PDF, JPG, PNG (最大 10MB)</p>
file:bg-indigo-50 dark:file:bg-indigo-900/50 file:text-indigo-700 dark:file:text-indigo-300
hover:file:bg-indigo-100 dark:hover:file:bg-indigo-800">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">支援格式: PDF, JPG, PNG (最大 10MB)</p>
@error('bank_statement_file')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
@@ -130,13 +130,13 @@
</div>
<!-- Outstanding Checks -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">未兌現支票</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">未兌現支票</h3>
<div id="outstanding-checks-container" class="space-y-3">
<!-- Template will be added by JavaScript -->
</div>
<button type="button" onclick="addOutstandingCheck()" class="mt-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<button type="button" onclick="addOutstandingCheck()" class="mt-3 inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
<svg class="-ml-1 mr-2 h-4 w-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>
@@ -146,13 +146,13 @@
</div>
<!-- Deposits in Transit -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">在途存款</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">在途存款</h3>
<div id="deposits-container" class="space-y-3">
<!-- Template will be added by JavaScript -->
</div>
<button type="button" onclick="addDeposit()" class="mt-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<button type="button" onclick="addDeposit()" class="mt-3 inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
<svg class="-ml-1 mr-2 h-4 w-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>
@@ -162,13 +162,13 @@
</div>
<!-- Bank Charges -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">銀行手續費</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">銀行手續費</h3>
<div id="charges-container" class="space-y-3">
<!-- Template will be added by JavaScript -->
</div>
<button type="button" onclick="addCharge()" class="mt-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<button type="button" onclick="addCharge()" class="mt-3 inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
<svg class="-ml-1 mr-2 h-4 w-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>
@@ -178,20 +178,20 @@
</div>
<!-- Notes -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<label for="notes" class="block text-sm font-medium text-gray-700">備註</label>
<label for="notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">備註</label>
<textarea name="notes" id="notes" rows="3"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">{{ old('notes') }}</textarea>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">{{ old('notes') }}</textarea>
</div>
</div>
<!-- Form Actions -->
<div class="flex justify-end space-x-3">
<a href="{{ route('admin.bank-reconciliations.index') }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<a href="{{ route('admin.bank-reconciliations.index') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
取消
</a>
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
製作調節表
</button>
</div>
@@ -208,22 +208,22 @@
function addOutstandingCheck() {
const container = document.getElementById('outstanding-checks-container');
const div = document.createElement('div');
div.className = 'grid grid-cols-1 gap-4 sm:grid-cols-3 p-4 border border-gray-200 rounded-md';
div.className = 'grid grid-cols-1 gap-4 sm:grid-cols-3 p-4 border border-gray-200 dark:border-gray-700 rounded-md';
div.innerHTML = `
<div>
<label class="block text-sm font-medium text-gray-700">支票號碼</label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">支票號碼</label>
<input type="text" name="outstanding_checks[${checkIndex}][check_number]"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
<div>
<label class="block text-sm font-medium text-gray-700">金額 <span class="text-red-500">*</span></label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">金額 <span class="text-red-500 dark:text-red-400">*</span></label>
<input type="number" name="outstanding_checks[${checkIndex}][amount]" step="0.01" min="0" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
<div>
<label class="block text-sm font-medium text-gray-700">說明</label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">說明</label>
<input type="text" name="outstanding_checks[${checkIndex}][description]"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
`;
container.appendChild(div);
@@ -233,22 +233,22 @@
function addDeposit() {
const container = document.getElementById('deposits-container');
const div = document.createElement('div');
div.className = 'grid grid-cols-1 gap-4 sm:grid-cols-3 p-4 border border-gray-200 rounded-md';
div.className = 'grid grid-cols-1 gap-4 sm:grid-cols-3 p-4 border border-gray-200 dark:border-gray-700 rounded-md';
div.innerHTML = `
<div>
<label class="block text-sm font-medium text-gray-700">存款日期</label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">存款日期</label>
<input type="date" name="deposits_in_transit[${depositIndex}][date]"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
<div>
<label class="block text-sm font-medium text-gray-700">金額 <span class="text-red-500">*</span></label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">金額 <span class="text-red-500 dark:text-red-400">*</span></label>
<input type="number" name="deposits_in_transit[${depositIndex}][amount]" step="0.01" min="0" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
<div>
<label class="block text-sm font-medium text-gray-700">說明</label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">說明</label>
<input type="text" name="deposits_in_transit[${depositIndex}][description]"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
`;
container.appendChild(div);
@@ -258,18 +258,18 @@
function addCharge() {
const container = document.getElementById('charges-container');
const div = document.createElement('div');
div.className = 'grid grid-cols-1 gap-4 sm:grid-cols-2 p-4 border border-gray-200 rounded-md';
div.className = 'grid grid-cols-1 gap-4 sm:grid-cols-2 p-4 border border-gray-200 dark:border-gray-700 rounded-md';
div.innerHTML = `
<div>
<label class="block text-sm font-medium text-gray-700">金額 <span class="text-red-500">*</span></label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">金額 <span class="text-red-500 dark:text-red-400">*</span></label>
<input type="number" name="bank_charges[${chargeIndex}][amount]" step="0.01" min="0" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
<div>
<label class="block text-sm font-medium text-gray-700">說明</label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">說明</label>
<input type="text" name="bank_charges[${chargeIndex}][description]"
placeholder="例如: 轉帳手續費"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
`;
container.appendChild(div);

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
銀行調節表
</h2>
</x-slot>
@@ -8,21 +8,21 @@
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-4">
@if (session('status'))
<div class="rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 p-4">
<p class="text-sm font-medium text-red-800">{{ session('error') }}</p>
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<!-- Action Button -->
@can('prepare_bank_reconciliation')
<div class="flex justify-end">
<a href="{{ route('admin.bank-reconciliations.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<a href="{{ route('admin.bank-reconciliations.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
<svg class="-ml-1 mr-2 h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
@@ -32,12 +32,12 @@
@endcan
<!-- Filters -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="GET" action="{{ route('admin.bank-reconciliations.index') }}" class="grid grid-cols-1 gap-4 sm:grid-cols-3">
<div>
<label for="reconciliation_status" class="block text-sm font-medium text-gray-700">狀態</label>
<select name="reconciliation_status" id="reconciliation_status" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
<label for="reconciliation_status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">狀態</label>
<select name="reconciliation_status" id="reconciliation_status" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部</option>
<option value="pending" {{ request('reconciliation_status') == 'pending' ? 'selected' : '' }}>待覆核</option>
<option value="completed" {{ request('reconciliation_status') == 'completed' ? 'selected' : '' }}>已完成</option>
@@ -46,16 +46,16 @@
</div>
<div>
<label for="month" class="block text-sm font-medium text-gray-700">調節月份</label>
<label for="month" class="block text-sm font-medium text-gray-700 dark:text-gray-300">調節月份</label>
<input type="month" name="month" id="month" value="{{ request('month') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
</div>
<div class="flex items-end">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
篩選
</button>
<a href="{{ route('admin.bank-reconciliations.index') }}" class="ml-2 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<a href="{{ route('admin.bank-reconciliations.index') }}" class="ml-2 inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
清除
</a>
</div>
@@ -64,71 +64,71 @@
</div>
<!-- Reconciliations Table -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
調節月份
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
銀行餘額
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
帳面餘額
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
差異金額
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
狀態
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
製表人
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
<span class="sr-only">操作</span>
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse ($reconciliations as $reconciliation)
<tr>
<td class="whitespace-nowrap px-4 py-4 text-sm font-medium text-gray-900">
<td class="whitespace-nowrap px-4 py-4 text-sm font-medium text-gray-900 dark:text-gray-100">
{{ $reconciliation->reconciliation_month->format('Y年m月') }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-right text-gray-500">
<td class="whitespace-nowrap px-4 py-4 text-sm text-right text-gray-500 dark:text-gray-400">
NT$ {{ number_format($reconciliation->bank_statement_balance, 2) }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-right text-gray-500">
<td class="whitespace-nowrap px-4 py-4 text-sm text-right text-gray-500 dark:text-gray-400">
NT$ {{ number_format($reconciliation->system_book_balance, 2) }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-right {{ $reconciliation->discrepancy_amount > 0 ? 'text-red-600 font-semibold' : 'text-gray-500' }}">
<td class="whitespace-nowrap px-4 py-4 text-sm text-right {{ $reconciliation->discrepancy_amount > 0 ? 'text-red-600 dark:text-red-400 font-semibold' : 'text-gray-500 dark:text-gray-400' }}">
NT$ {{ number_format($reconciliation->discrepancy_amount, 2) }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm">
<span class="inline-flex rounded-full px-2 text-xs font-semibold leading-5
@if($reconciliation->reconciliation_status === 'completed') bg-green-100 text-green-800
@elseif($reconciliation->reconciliation_status === 'discrepancy') bg-red-100 text-red-800
@else bg-yellow-100 text-yellow-800
@if($reconciliation->reconciliation_status === 'completed') bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200
@elseif($reconciliation->reconciliation_status === 'discrepancy') bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200
@else bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200
@endif">
{{ $reconciliation->getStatusText() }}
</span>
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500">
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
{{ $reconciliation->preparedByCashier->name ?? 'N/A' }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-right text-sm font-medium">
<a href="{{ route('admin.bank-reconciliations.show', $reconciliation) }}" class="text-indigo-600 hover:text-indigo-900">
<a href="{{ route('admin.bank-reconciliations.show', $reconciliation) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
查看
</a>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-8 text-center text-sm text-gray-500">
<td colspan="7" class="px-4 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
沒有銀行調節表記錄
</td>
</tr>
@@ -144,16 +144,16 @@
</div>
<!-- Help Info -->
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
<div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="h-5 w-5 text-blue-400 dark:text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-blue-800">關於銀行調節表</h3>
<div class="mt-2 text-sm text-blue-700">
<h3 class="text-sm font-medium text-blue-800 dark:text-blue-200">關於銀行調節表</h3>
<div class="mt-2 text-sm text-blue-700 dark:text-blue-300">
<p>銀行調節表用於核對銀行對帳單與內部現金簿的差異。建議每月定期製作,以確保帳務正確。</p>
<p class="mt-1">調節流程:出納製作 會計覆核 主管核准</p>
</div>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Create Budget') }} (úË)
新增預算 ()
</h2>
</x-slot>
@@ -9,13 +9,13 @@
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800">
<div class="px-4 py-5 sm:p-6">
<form method="POST" action="{{ route('admin.budgets.store') }}" class="space-y-6" aria-label="{{ __('Create budget form') }}">
<form method="POST" action="{{ route('admin.budgets.store') }}" class="space-y-6" aria-label="新增預算表單">
@csrf
<!-- Fiscal Year -->
<div>
<label for="fiscal_year" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Fiscal Year') }} <span class="text-red-500" aria-label="{{ __('required') }}">*</span>
會計年度 <span class="text-red-500" aria-label="必填">*</span>
</label>
<input type="number"
name="fiscal_year"
@@ -27,7 +27,7 @@
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 dark:focus:ring-offset-gray-800 @error('fiscal_year') border-red-300 dark:border-red-500 @enderror"
aria-describedby="fiscal_year_help @error('fiscal_year') fiscal_year_error @enderror">
<p id="fiscal_year_help" class="mt-1 text-sm text-gray-500 dark:text-gray-400">
{{ __('The fiscal year this budget applies to') }}
此預算適用的會計年度
</p>
@error('fiscal_year')
<p id="fiscal_year_error" class="mt-1 text-sm text-red-600 dark:text-red-400" role="alert">{{ $message }}</p>
@@ -37,7 +37,7 @@
<!-- Name -->
<div>
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Budget Name') }} <span class="text-red-500" aria-label="{{ __('required') }}">*</span>
預算名稱 <span class="text-red-500" aria-label="必填">*</span>
</label>
<input type="text"
name="name"
@@ -46,10 +46,10 @@
required
maxlength="255"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 dark:focus:ring-offset-gray-800 @error('name') border-red-300 dark:border-red-500 @enderror"
placeholder="{{ __('e.g., Annual Budget 2025') }}"
placeholder="例如2025年度預算"
aria-describedby="name_help @error('name') name_error @enderror">
<p id="name_help" class="mt-1 text-sm text-gray-500 dark:text-gray-400">
{{ __('Descriptive name for this budget') }}
此預算的描述性名稱
</p>
@error('name')
<p id="name_error" class="mt-1 text-sm text-red-600 dark:text-red-400" role="alert">{{ $message }}</p>
@@ -59,19 +59,19 @@
<!-- Period Type -->
<div>
<label for="period_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Period Type') }} <span class="text-red-500" aria-label="{{ __('required') }}">*</span>
期間類型 <span class="text-red-500" aria-label="必填">*</span>
</label>
<select name="period_type"
id="period_type"
required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 dark:focus:ring-offset-gray-800 @error('period_type') border-red-300 dark:border-red-500 @enderror"
aria-describedby="period_type_help @error('period_type') period_type_error @enderror">
<option value="annual" @selected(old('period_type', 'annual') === 'annual')>{{ __('Annual') }} ()</option>
<option value="quarterly" @selected(old('period_type') === 'quarterly')>{{ __('Quarterly') }} ()</option>
<option value="monthly" @selected(old('period_type') === 'monthly')>{{ __('Monthly') }} (¦)</option>
<option value="annual" @selected(old('period_type', 'annual') === 'annual')>年度 </option>
<option value="quarterly" @selected(old('period_type') === 'quarterly')>季度 </option>
<option value="monthly" @selected(old('period_type') === 'monthly')>月度 ()</option>
</select>
<p id="period_type_help" class="mt-1 text-sm text-gray-500 dark:text-gray-400">
{{ __('Budget period duration') }}
預算期間長度
</p>
@error('period_type')
<p id="period_type_error" class="mt-1 text-sm text-red-600 dark:text-red-400" role="alert">{{ $message }}</p>
@@ -82,7 +82,7 @@
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label for="period_start" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Period Start Date') }} <span class="text-red-500" aria-label="{{ __('required') }}">*</span>
期間開始日期 <span class="text-red-500" aria-label="必填">*</span>
</label>
<input type="date"
name="period_start"
@@ -98,7 +98,7 @@
<div>
<label for="period_end" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Period End Date') }} <span class="text-red-500" aria-label="{{ __('required') }}">*</span>
期間結束日期 <span class="text-red-500" aria-label="必填">*</span>
</label>
<input type="date"
name="period_end"
@@ -116,16 +116,16 @@
<!-- Notes -->
<div>
<label for="notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Notes') }} (;)
備註
</label>
<textarea name="notes"
id="notes"
rows="3"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 dark:focus:ring-offset-gray-800 @error('notes') border-red-300 dark:border-red-500 @enderror"
placeholder="{{ __('Optional notes about this budget...') }}"
placeholder="關於此預算的選填備註..."
aria-describedby="notes_help @error('notes') notes_error @enderror">{{ old('notes') }}</textarea>
<p id="notes_help" class="mt-1 text-sm text-gray-500 dark:text-gray-400">
{{ __('Additional information about this budget (optional)') }}
關於此預算的額外資訊(選填)
</p>
@error('notes')
<p id="notes_error" class="mt-1 text-sm text-red-600 dark:text-red-400" role="alert">{{ $message }}</p>
@@ -136,11 +136,11 @@
<div class="flex items-center justify-end gap-x-4 border-t border-gray-200 pt-6 dark:border-gray-700">
<a href="{{ route('admin.budgets.index') }}"
class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600 dark:hover:bg-gray-600 dark:focus:ring-offset-gray-800">
{{ __('Cancel') }}
取消
</a>
<button type="submit"
class="inline-flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-400 dark:focus:ring-offset-gray-800">
{{ __('Create Budget') }}
新增預算
</button>
</div>
</form>
@@ -157,14 +157,14 @@
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-blue-800 dark:text-blue-200">
{{ __('Next Steps') }}
下一步
</h3>
<div class="mt-2 text-sm text-blue-700 dark:text-blue-300">
<p>{{ __('After creating the budget, you will be able to:') }}</p>
<p>建立預算後,您將能夠:</p>
<ul class="list-disc pl-5 mt-2 space-y-1">
<li>{{ __('Add budget items for income and expense accounts') }}</li>
<li>{{ __('Submit the budget for chair approval') }}</li>
<li>{{ __('Activate the budget to start tracking actual amounts') }}</li>
<li>為收入和支出帳戶新增預算項目</li>
<li>提交預算以供主席核准</li>
<li>啟用預算以開始追蹤實際金額</li>
</ul>
</div>
</div>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Edit Budget') }} - {{ $budget->fiscal_year }}
編輯預算 - {{ $budget->fiscal_year }}
</h2>
</x-slot>
@@ -13,30 +13,30 @@
<!-- Basic Info -->
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Basic Information') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">基本資訊</h3>
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Budget Name') }} *</label>
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">預算名稱 *</label>
<input type="text" name="name" id="name" value="{{ old('name', $budget->name) }}" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
@error('name')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<div>
<label for="period_start" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Period Start') }} *</label>
<label for="period_start" class="block text-sm font-medium text-gray-700 dark:text-gray-300">期間開始 *</label>
<input type="date" name="period_start" id="period_start" value="{{ old('period_start', $budget->period_start->format('Y-m-d')) }}" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
</div>
<div>
<label for="period_end" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Period End') }} *</label>
<label for="period_end" class="block text-sm font-medium text-gray-700 dark:text-gray-300">期間結束 *</label>
<input type="date" name="period_end" id="period_end" value="{{ old('period_end', $budget->period_end->format('Y-m-d')) }}" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
</div>
<div class="sm:col-span-2">
<label for="notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Notes') }}</label>
<label for="notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">備註</label>
<textarea name="notes" id="notes" rows="3" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">{{ old('notes', $budget->notes) }}</textarea>
</div>
</div>
@@ -45,25 +45,25 @@
<!-- Income Items -->
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">{{ __('Income') }} (6e)</h3>
<button type="button" @click="addItem('income')" class="btn-secondary text-sm">+ {{ __('Add Income Item') }}</button>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">收入 </h3>
<button type="button" @click="addItem('income')" class="btn-secondary text-sm">+ 新增收入項目</button>
</div>
<div class="space-y-4">
<template x-for="(item, index) in incomeItems" :key="index">
<div class="flex gap-4 items-start bg-gray-50 dark:bg-gray-900 p-4 rounded-md">
<div class="flex-1">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Account') }}</label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">帳戶</label>
<select :name="'budget_items[income_' + index + '][chart_of_account_id]'" x-model="item.account_id" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('Select account...') }}</option>
<option value="">選擇帳戶...</option>
@foreach($incomeAccounts as $account)
<option value="{{ $account->id }}">{{ $account->account_code }} - {{ $account->account_name_zh }}</option>
@endforeach
</select>
</div>
<div class="w-48">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Amount') }}</label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">金額</label>
<input type="number" :name="'budget_items[income_' + index + '][budgeted_amount]'" x-model="item.amount" step="0.01" min="0" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
</div>
@@ -75,7 +75,7 @@
</div>
</template>
<div x-show="incomeItems.length === 0" class="text-center py-8 text-gray-500 dark:text-gray-400">
{{ __('No income items. Click "Add Income Item" to get started.') }}
無收入項目。點擊「新增收入項目」開始。
</div>
</div>
</div>
@@ -83,25 +83,25 @@
<!-- Expense Items -->
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">{{ __('Expenses') }} (/ú)</h3>
<button type="button" @click="addItem('expense')" class="btn-secondary text-sm">+ {{ __('Add Expense Item') }}</button>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">支出 (/<EFBFBD>)</h3>
<button type="button" @click="addItem('expense')" class="btn-secondary text-sm">+ 新增支出項目</button>
</div>
<div class="space-y-4">
<template x-for="(item, index) in expenseItems" :key="index">
<div class="flex gap-4 items-start bg-gray-50 dark:bg-gray-900 p-4 rounded-md">
<div class="flex-1">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Account') }}</label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">帳戶</label>
<select :name="'budget_items[expense_' + index + '][chart_of_account_id]'" x-model="item.account_id" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('Select account...') }}</option>
<option value="">選擇帳戶...</option>
@foreach($expenseAccounts as $account)
<option value="{{ $account->id }}">{{ $account->account_code }} - {{ $account->account_name_zh }}</option>
@endforeach
</select>
</div>
<div class="w-48">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Amount') }}</label>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">金額</label>
<input type="number" :name="'budget_items[expense_' + index + '][budgeted_amount]'" x-model="item.amount" step="0.01" min="0" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
</div>
@@ -113,15 +113,15 @@
</div>
</template>
<div x-show="expenseItems.length === 0" class="text-center py-8 text-gray-500 dark:text-gray-400">
{{ __('No expense items. Click "Add Expense Item" to get started.') }}
無支出項目。點擊「新增支出項目」開始。
</div>
</div>
</div>
<!-- Actions -->
<div class="flex items-center justify-end gap-x-4">
<a href="{{ route('admin.budgets.show', $budget) }}" class="btn-secondary">{{ __('Cancel') }}</a>
<button type="submit" class="btn-primary">{{ __('Save Budget') }}</button>
<a href="{{ route('admin.budgets.show', $budget) }}" class="btn-secondary">取消</a>
<button type="submit" class="btn-primary">儲存預算</button>
</div>
</form>
</div>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Budgets') }} (—¡)
預算管理
</h2>
</x-slot>
@@ -31,34 +31,34 @@
<div class="sm:flex sm:items-center sm:justify-between mb-6">
<div>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">
{{ __('Budget List') }}
預算列表
</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __('Manage annual budgets and track financial performance') }}
管理年度預算並追蹤財務績效
</p>
</div>
<div class="mt-4 sm:mt-0">
<a href="{{ route('admin.budgets.create') }}"
class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-400 dark:focus:ring-offset-gray-800"
aria-label="{{ __('Create new budget') }}">
aria-label="新增預算">
<svg class="-ml-0.5 mr-1.5 h-5 w-5" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
<path d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z" />
</svg>
{{ __('Create Budget') }}
新增預算
</a>
</div>
</div>
<!-- Filters -->
<form method="GET" action="{{ route('admin.budgets.index') }}" class="mb-6 space-y-4" role="search" aria-label="{{ __('Filter budgets') }}">
<form method="GET" action="{{ route('admin.budgets.index') }}" class="mb-6 space-y-4" role="search" aria-label="篩選預算">
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
<div>
<label for="fiscal_year" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Fiscal Year') }} ()
會計年度
</label>
<select id="fiscal_year" name="fiscal_year"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('All Years') }}</option>
<option value="">所有年度</option>
@foreach($fiscalYears as $year)
<option value="{{ $year }}" @selected(request('fiscal_year') == $year)>
{{ $year }}
@@ -69,23 +69,23 @@
<div>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Status') }} (ÀK)
狀態
</label>
<select id="status" name="status"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('All Statuses') }}</option>
<option value="draft" @selected(request('status') === 'draft')>{{ __('Draft') }}</option>
<option value="submitted" @selected(request('status') === 'submitted')>{{ __('Submitted') }}</option>
<option value="approved" @selected(request('status') === 'approved')>{{ __('Approved') }}</option>
<option value="active" @selected(request('status') === 'active')>{{ __('Active') }}</option>
<option value="closed" @selected(request('status') === 'closed')>{{ __('Closed') }}</option>
<option value="">所有狀態</option>
<option value="draft" @selected(request('status') === 'draft')>草稿</option>
<option value="submitted" @selected(request('status') === 'submitted')>已提交</option>
<option value="approved" @selected(request('status') === 'approved')>已核准</option>
<option value="active" @selected(request('status') === 'active')>使用中</option>
<option value="closed" @selected(request('status') === 'closed')>已結案</option>
</select>
</div>
<div class="flex items-end">
<button type="submit"
class="inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600 dark:hover:bg-gray-600 dark:focus:ring-offset-gray-800">
{{ __('Filter') }}
篩選
</button>
</div>
</div>
@@ -95,27 +95,27 @@
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg dark:ring-gray-700">
<table class="min-w-full divide-y divide-gray-300 dark:divide-gray-600">
<caption class="sr-only">
{{ __('List of budgets showing fiscal year, name, period, and status') }}
預算列表,顯示會計年度、名稱、期間和狀態
</caption>
<thead class="bg-gray-50 dark:bg-gray-900">
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100 sm:pl-6">
{{ __('Fiscal Year') }}
會計年度
</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">
{{ __('Name') }}
名稱
</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">
{{ __('Period') }}
期間
</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">
{{ __('Status') }}
狀態
</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">
{{ __('Created By') }}
建立者
</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6">
<span class="sr-only">{{ __('Actions') }}</span>
<span class="sr-only">操作</span>
</th>
</tr>
</thead>
@@ -133,24 +133,24 @@
</td>
<td class="whitespace-nowrap px-3 py-4 text-sm">
@if($budget->status === 'draft')
<span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-800 dark:bg-gray-700 dark:text-gray-200" role="status" aria-label="{{ __('Status: Draft') }}">
{{ __('Draft') }}
<span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-800 dark:bg-gray-700 dark:text-gray-200" role="status" aria-label="狀態:草稿">
草稿
</span>
@elseif($budget->status === 'submitted')
<span class="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-medium text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200" role="status" aria-label="{{ __('Status: Submitted') }}">
{{ __('Submitted') }}
<span class="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-medium text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200" role="status" aria-label="狀態:已提交">
已提交
</span>
@elseif($budget->status === 'approved')
<span class="inline-flex items-center rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800 dark:bg-blue-900 dark:text-blue-200" role="status" aria-label="{{ __('Status: Approved') }}">
{{ __('Approved') }}
<span class="inline-flex items-center rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800 dark:bg-blue-900 dark:text-blue-200" role="status" aria-label="狀態:已核准">
已核准
</span>
@elseif($budget->status === 'active')
<span class="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800 dark:bg-green-900 dark:text-green-200" role="status" aria-label="{{ __('Status: Active') }}">
 {{ __('Active') }}
<span class="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800 dark:bg-green-900 dark:text-green-200" role="status" aria-label="狀態:使用中">
使用中
</span>
@elseif($budget->status === 'closed')
<span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-800 dark:bg-gray-700 dark:text-gray-200" role="status" aria-label="{{ __('Status: Closed') }}">
{{ __('Closed') }}
<span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-800 dark:bg-gray-700 dark:text-gray-200" role="status" aria-label="狀態:已結案">
已結案
</span>
@endif
</td>
@@ -160,15 +160,15 @@
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6">
<a href="{{ route('admin.budgets.show', $budget) }}"
class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800"
aria-label="{{ __('View budget for fiscal year :year', ['year' => $budget->fiscal_year]) }}">
{{ __('View') }}
aria-label="檢視 {{ $budget->fiscal_year }} 年度預算">
檢視
</a>
@if($budget->canBeEdited())
<span class="text-gray-300 dark:text-gray-600" aria-hidden="true"> | </span>
<a href="{{ route('admin.budgets.edit', $budget) }}"
class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800"
aria-label="{{ __('Edit budget for fiscal year :year', ['year' => $budget->fiscal_year]) }}">
{{ __('Edit') }}
aria-label="編輯 {{ $budget->fiscal_year }} 年度預算">
編輯
</a>
@endif
</td>
@@ -179,15 +179,15 @@
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<p class="mt-2 text-sm font-semibold">{{ __('No budgets found') }}</p>
<p class="mt-1 text-sm">{{ __('Get started by creating a new budget.') }}</p>
<p class="mt-2 text-sm font-semibold">找不到預算</p>
<p class="mt-1 text-sm">開始建立新的預算。</p>
<div class="mt-6">
<a href="{{ route('admin.budgets.create') }}"
class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-400 dark:focus:ring-offset-gray-800">
<svg class="-ml-0.5 mr-1.5 h-5 w-5" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
<path d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z" />
</svg>
{{ __('Create Budget') }}
新增預算
</a>
</div>
</td>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Budget Details') }} - {{ $budget->fiscal_year }}
預算詳情 - {{ $budget->fiscal_year }}
</h2>
</x-slot>
@@ -24,23 +24,23 @@
</div>
<div>
@if($budget->status === 'active')
<span class="inline-flex rounded-full bg-green-100 px-3 py-1 text-sm font-medium text-green-800 dark:bg-green-900 dark:text-green-200"> {{ __('Active') }}</span>
<span class="inline-flex rounded-full bg-green-100 px-3 py-1 text-sm font-medium text-green-800 dark:bg-green-900 dark:text-green-200"> 使用中</span>
@elseif($budget->status === 'approved')
<span class="inline-flex rounded-full bg-blue-100 px-3 py-1 text-sm font-medium text-blue-800 dark:bg-blue-900 dark:text-blue-200">{{ __('Approved') }}</span>
<span class="inline-flex rounded-full bg-blue-100 px-3 py-1 text-sm font-medium text-blue-800 dark:bg-blue-900 dark:text-blue-200">已核准</span>
@else
<span class="inline-flex rounded-full bg-gray-100 px-3 py-1 text-sm font-medium text-gray-800 dark:bg-gray-700 dark:text-gray-200">{{ __(ucfirst($budget->status)) }}</span>
<span class="inline-flex rounded-full bg-gray-100 px-3 py-1 text-sm font-medium text-gray-800 dark:bg-gray-700 dark:text-gray-200">{{ ucfirst($budget->status) }}</span>
@endif
</div>
</div>
<div class="mt-6 flex gap-3">
@if($budget->canBeEdited())
<a href="{{ route('admin.budgets.edit', $budget) }}" class="btn-secondary">{{ __('Edit') }}</a>
<a href="{{ route('admin.budgets.edit', $budget) }}" class="btn-secondary">編輯</a>
@endif
@if($budget->isDraft())
<form method="POST" action="{{ route('admin.budgets.submit', $budget) }}">
@csrf
<button type="submit" class="btn-primary">{{ __('Submit') }}</button>
<button type="submit" class="btn-primary">提交</button>
</form>
@endif
</div>
@@ -49,19 +49,19 @@
<!-- Summary Cards -->
<div class="grid grid-cols-1 gap-6 sm:grid-cols-4">
<div class="bg-white shadow rounded-lg dark:bg-gray-800 p-5">
<dt class="text-sm text-gray-500 dark:text-gray-400">{{ __('Budgeted Income') }}</dt>
<dt class="text-sm text-gray-500 dark:text-gray-400">預算收入</dt>
<dd class="text-2xl font-bold text-gray-900 dark:text-gray-100">NT$ {{ number_format($budget->total_budgeted_income) }}</dd>
</div>
<div class="bg-white shadow rounded-lg dark:bg-gray-800 p-5">
<dt class="text-sm text-gray-500 dark:text-gray-400">{{ __('Budgeted Expense') }}</dt>
<dt class="text-sm text-gray-500 dark:text-gray-400">預算支出</dt>
<dd class="text-2xl font-bold text-gray-900 dark:text-gray-100">NT$ {{ number_format($budget->total_budgeted_expense) }}</dd>
</div>
<div class="bg-white shadow rounded-lg dark:bg-gray-800 p-5">
<dt class="text-sm text-gray-500 dark:text-gray-400">{{ __('Actual Income') }}</dt>
<dt class="text-sm text-gray-500 dark:text-gray-400">實際收入</dt>
<dd class="text-2xl font-bold text-gray-900 dark:text-gray-100">NT$ {{ number_format($budget->total_actual_income) }}</dd>
</div>
<div class="bg-white shadow rounded-lg dark:bg-gray-800 p-5">
<dt class="text-sm text-gray-500 dark:text-gray-400">{{ __('Actual Expense') }}</dt>
<dt class="text-sm text-gray-500 dark:text-gray-400">實際支出</dt>
<dd class="text-2xl font-bold text-gray-900 dark:text-gray-100">NT$ {{ number_format($budget->total_actual_expense) }}</dd>
</div>
</div>
@@ -69,14 +69,14 @@
<!-- Income Items -->
@if($incomeItems->count() > 0)
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-base font-semibold text-gray-900 dark:text-gray-100 mb-4">{{ __('Income') }} (6e)</h3>
<h3 class="text-base font-semibold text-gray-900 dark:text-gray-100 mb-4">收入 </h3>
<table class="min-w-full divide-y divide-gray-300 dark:divide-gray-600">
<thead class="bg-gray-50 dark:bg-gray-900">
<tr>
<th scope="col" class="py-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Account') }}</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Budgeted') }}</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Actual') }}</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Variance') }}</th>
<th scope="col" class="py-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">帳戶</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">預算</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">實際</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">差異</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
@@ -96,14 +96,14 @@
<!-- Expense Items -->
@if($expenseItems->count() > 0)
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-base font-semibold text-gray-900 dark:text-gray-100 mb-4">{{ __('Expenses') }} (/ú)</h3>
<h3 class="text-base font-semibold text-gray-900 dark:text-gray-100 mb-4">支出 (/<EFBFBD>)</h3>
<table class="min-w-full divide-y divide-gray-300 dark:divide-gray-600">
<thead class="bg-gray-50 dark:bg-gray-900">
<tr>
<th scope="col" class="py-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Account') }}</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Budgeted') }}</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Actual') }}</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Utilization') }}</th>
<th scope="col" class="py-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">帳戶</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">預算</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">實際</th>
<th scope="col" class="px-3 py-3 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">使用率</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">

View File

@@ -1,14 +1,14 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
現金簿餘額報表
</h2>
</x-slot>
<div class="py-6">
<div class="mx-auto max-w-5xl sm:px-6 lg:px-8 space-y-6">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
<h3 class="font-semibold mb-4">帳戶餘額</h3>
<ul class="list-disc list-inside space-y-1">
@foreach($accounts as $account)
@@ -18,8 +18,8 @@
</div>
</div>
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
<h3 class="font-semibold mb-4">本月摘要</h3>
<p>收入:{{ $monthlySummary['receipts'] ?? 0 }}</p>
<p>支出:{{ $monthlySummary['payments'] ?? 0 }}</p>

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
記錄現金簿分錄
</h2>
</x-slot>
@@ -8,32 +8,32 @@
<div class="py-12">
<div class="mx-auto max-w-4xl sm:px-6 lg:px-8 space-y-4">
@if (session('error'))
<div class="rounded-md bg-red-50 p-4">
<p class="text-sm font-medium text-red-800">{{ session('error') }}</p>
<div class="rounded-md bg-red-50 dark:bg-red-900/50 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<!-- Related Finance Document Info (if applicable) -->
@if($financeDocument)
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
<h3 class="text-sm font-medium text-blue-900 mb-2">關聯財務申請單</h3>
<div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
<h3 class="text-sm font-medium text-blue-900 dark:text-blue-100 mb-2">關聯報銷申請單</h3>
<dl class="grid grid-cols-1 gap-x-4 gap-y-2 sm:grid-cols-2 text-sm">
<div>
<dt class="font-medium text-blue-700">標題</dt>
<dd class="text-blue-900">{{ $financeDocument->title }}</dd>
<dt class="font-medium text-blue-700 dark:text-blue-300">標題</dt>
<dd class="text-blue-900 dark:text-blue-100">{{ $financeDocument->title }}</dd>
</div>
<div>
<dt class="font-medium text-blue-700">金額</dt>
<dd class="text-blue-900">NT$ {{ number_format($financeDocument->amount, 2) }}</dd>
<dt class="font-medium text-blue-700 dark:text-blue-300">金額</dt>
<dd class="text-blue-900 dark:text-blue-100">NT$ {{ number_format($financeDocument->amount, 2) }}</dd>
</div>
@if($financeDocument->paymentOrder)
<div>
<dt class="font-medium text-blue-700">付款單號</dt>
<dd class="text-blue-900 font-mono">{{ $financeDocument->paymentOrder->payment_order_number }}</dd>
<dt class="font-medium text-blue-700 dark:text-blue-300">付款單號</dt>
<dd class="text-blue-900 dark:text-blue-100 font-mono">{{ $financeDocument->paymentOrder->payment_order_number }}</dd>
</div>
<div>
<dt class="font-medium text-blue-700">付款方式</dt>
<dd class="text-blue-900">{{ $financeDocument->paymentOrder->getPaymentMethodText() }}</dd>
<dt class="font-medium text-blue-700 dark:text-blue-300">付款方式</dt>
<dd class="text-blue-900 dark:text-blue-100">{{ $financeDocument->paymentOrder->getPaymentMethodText() }}</dd>
</div>
@endif
</dl>
@@ -48,127 +48,127 @@
<input type="hidden" name="finance_document_id" value="{{ $financeDocument->id }}">
@endif
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">分錄資訊</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">分錄資訊</h3>
<div class="grid grid-cols-1 gap-6">
<!-- Entry Date -->
<div>
<label for="entry_date" class="block text-sm font-medium text-gray-700">
記帳日期 <span class="text-red-500">*</span>
<label for="entry_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
記帳日期 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<input type="date" name="entry_date" id="entry_date" required
value="{{ old('entry_date', now()->format('Y-m-d')) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('entry_date') border-red-300 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300 @error('entry_date') border-red-300 dark:border-red-700 @enderror">
@error('entry_date')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Entry Type -->
<div>
<label for="entry_type" class="block text-sm font-medium text-gray-700">
類型 <span class="text-red-500">*</span>
<label for="entry_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
類型 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<select name="entry_type" id="entry_type" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('entry_type') border-red-300 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300 @error('entry_type') border-red-300 dark:border-red-700 @enderror">
<option value="">請選擇類型</option>
<option value="receipt" {{ old('entry_type') == 'receipt' ? 'selected' : '' }}>收入</option>
<option value="payment" {{ old('entry_type', $financeDocument ? 'payment' : '') == 'payment' ? 'selected' : '' }}>支出</option>
</select>
@error('entry_type')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Payment Method -->
<div>
<label for="payment_method" class="block text-sm font-medium text-gray-700">
付款方式 <span class="text-red-500">*</span>
<label for="payment_method" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
付款方式 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<select name="payment_method" id="payment_method" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('payment_method') border-red-300 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300 @error('payment_method') border-red-300 dark:border-red-700 @enderror">
<option value="">請選擇付款方式</option>
<option value="bank_transfer" {{ old('payment_method', $financeDocument && $financeDocument->paymentOrder ? $financeDocument->paymentOrder->payment_method : '') == 'bank_transfer' ? 'selected' : '' }}>銀行轉帳</option>
<option value="check" {{ old('payment_method', $financeDocument && $financeDocument->paymentOrder ? $financeDocument->paymentOrder->payment_method : '') == 'check' ? 'selected' : '' }}>支票</option>
<option value="cash" {{ old('payment_method', $financeDocument && $financeDocument->paymentOrder ? $financeDocument->paymentOrder->payment_method : '') == 'cash' ? 'selected' : '' }}>現金</option>
</select>
@error('payment_method')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Bank Account -->
<div>
<label for="bank_account" class="block text-sm font-medium text-gray-700">
<label for="bank_account" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
銀行帳戶
</label>
<input type="text" name="bank_account" id="bank_account"
value="{{ old('bank_account', 'Main Account') }}"
placeholder="例如: Main Account, Petty Cash"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('bank_account') border-red-300 @enderror">
<p class="mt-1 text-xs text-gray-500">用於區分不同的現金/銀行帳戶</p>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300 @error('bank_account') border-red-300 dark:border-red-700 @enderror">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">用於區分不同的現金/銀行帳戶</p>
@error('bank_account')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Amount -->
<div>
<label for="amount" class="block text-sm font-medium text-gray-700">
金額 <span class="text-red-500">*</span>
<label for="amount" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
金額 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<div class="relative mt-1 rounded-md shadow-sm">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<span class="text-gray-500 sm:text-sm">NT$</span>
<span class="text-gray-500 dark:text-gray-400 sm:text-sm">NT$</span>
</div>
<input type="number" name="amount" id="amount" step="0.01" min="0.01" required
value="{{ old('amount', $financeDocument && $financeDocument->paymentOrder ? $financeDocument->paymentOrder->payment_amount : '') }}"
class="block w-full rounded-md border-gray-300 pl-12 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('amount') border-red-300 @enderror">
class="block w-full rounded-md border-gray-300 dark:border-gray-700 pl-12 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300 @error('amount') border-red-300 dark:border-red-700 @enderror">
</div>
@error('amount')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Receipt Number -->
<div>
<label for="receipt_number" class="block text-sm font-medium text-gray-700">
<label for="receipt_number" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
收據/憑證編號
</label>
<input type="text" name="receipt_number" id="receipt_number"
value="{{ old('receipt_number') }}"
placeholder="例如: RCP-2025-001"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('receipt_number') border-red-300 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300 @error('receipt_number') border-red-300 dark:border-red-700 @enderror">
@error('receipt_number')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Transaction Reference -->
<div>
<label for="transaction_reference" class="block text-sm font-medium text-gray-700">
<label for="transaction_reference" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
交易參考號
</label>
<input type="text" name="transaction_reference" id="transaction_reference"
value="{{ old('transaction_reference', $financeDocument && $financeDocument->paymentOrder ? $financeDocument->paymentOrder->transaction_reference : '') }}"
placeholder="銀行交易編號或支票號碼"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('transaction_reference') border-red-300 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300 @error('transaction_reference') border-red-300 dark:border-red-700 @enderror">
@error('transaction_reference')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Notes -->
<div>
<label for="notes" class="block text-sm font-medium text-gray-700">
<label for="notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
備註
</label>
<textarea name="notes" id="notes" rows="3"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">{{ old('notes') }}</textarea>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">{{ old('notes') }}</textarea>
@error('notes')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
@@ -176,16 +176,16 @@
</div>
<!-- Help Text -->
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
<div class="bg-yellow-50 dark:bg-yellow-900/30 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-yellow-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="h-5 w-5 text-yellow-400 dark:text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-yellow-800">注意事項</h3>
<div class="mt-2 text-sm text-yellow-700">
<h3 class="text-sm font-medium text-yellow-800 dark:text-yellow-300">注意事項</h3>
<div class="mt-2 text-sm text-yellow-700 dark:text-yellow-400">
<ul class="list-disc pl-5 space-y-1">
<li>提交後將自動計算交易前後餘額</li>
<li>請確認金額和類型(收入/支出)正確</li>
@@ -199,10 +199,10 @@
<!-- Form Actions -->
<div class="flex justify-end space-x-3">
<a href="{{ route('admin.cashier-ledger.index') }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<a href="{{ route('admin.cashier-ledger.index') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
取消
</a>
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
記錄分錄
</button>
</div>

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
出納現金簿
</h2>
</x-slot>
@@ -8,34 +8,34 @@
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-4">
@if (session('status'))
<div class="rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="rounded-md bg-green-50 dark:bg-green-900/50 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 p-4">
<p class="text-sm font-medium text-red-800">{{ session('error') }}</p>
<div class="rounded-md bg-red-50 dark:bg-red-900/50 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<!-- Action Buttons -->
<div class="flex justify-between">
<a href="{{ route('admin.cashier-ledger.balance-report') }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<svg class="-ml-1 mr-2 h-5 w-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<a href="{{ route('admin.cashier-ledger.balance-report') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
<svg class="-ml-1 mr-2 h-5 w-5 text-gray-500 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
餘額報表
</a>
<div class="flex space-x-3">
<a href="{{ route('admin.cashier-ledger.export', request()->all()) }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<svg class="-ml-1 mr-2 h-5 w-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<a href="{{ route('admin.cashier-ledger.export', request()->all()) }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
<svg class="-ml-1 mr-2 h-5 w-5 text-gray-500 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
匯出 CSV
</a>
@can('record_cashier_ledger')
<a href="{{ route('admin.cashier-ledger.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<a href="{{ route('admin.cashier-ledger.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
<svg class="-ml-1 mr-2 h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
@@ -47,14 +47,14 @@
<!-- Current Balances Summary -->
@if(isset($balances) && $balances->isNotEmpty())
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">當前餘額</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">當前餘額</h3>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
@foreach($balances as $account => $balance)
<div class="rounded-lg border border-gray-200 p-4">
<dt class="text-sm font-medium text-gray-500">{{ $account }}</dt>
<dd class="mt-1 text-2xl font-semibold {{ $balance >= 0 ? 'text-green-600' : 'text-red-600' }}">
<div class="rounded-lg border border-gray-200 dark:border-gray-700 p-4">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ $account }}</dt>
<dd class="mt-1 text-2xl font-semibold {{ $balance >= 0 ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400' }}">
NT$ {{ number_format($balance, 2) }}
</dd>
</div>
@@ -65,12 +65,12 @@
@endif
<!-- Filters -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="GET" action="{{ route('admin.cashier-ledger.index') }}" class="grid grid-cols-1 gap-4 sm:grid-cols-5">
<div>
<label for="entry_type" class="block text-sm font-medium text-gray-700">類型</label>
<select name="entry_type" id="entry_type" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
<label for="entry_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">類型</label>
<select name="entry_type" id="entry_type" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部</option>
<option value="receipt" {{ request('entry_type') == 'receipt' ? 'selected' : '' }}>收入</option>
<option value="payment" {{ request('entry_type') == 'payment' ? 'selected' : '' }}>支出</option>
@@ -78,8 +78,8 @@
</div>
<div>
<label for="payment_method" class="block text-sm font-medium text-gray-700">付款方式</label>
<select name="payment_method" id="payment_method" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
<label for="payment_method" class="block text-sm font-medium text-gray-700 dark:text-gray-300">付款方式</label>
<select name="payment_method" id="payment_method" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部</option>
<option value="bank_transfer" {{ request('payment_method') == 'bank_transfer' ? 'selected' : '' }}>銀行轉帳</option>
<option value="check" {{ request('payment_method') == 'check' ? 'selected' : '' }}>支票</option>
@@ -88,22 +88,22 @@
</div>
<div>
<label for="date_from" class="block text-sm font-medium text-gray-700">開始日期</label>
<label for="date_from" class="block text-sm font-medium text-gray-700 dark:text-gray-300">開始日期</label>
<input type="date" name="date_from" id="date_from" value="{{ request('date_from') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
</div>
<div>
<label for="date_to" class="block text-sm font-medium text-gray-700">結束日期</label>
<label for="date_to" class="block text-sm font-medium text-gray-700 dark:text-gray-300">結束日期</label>
<input type="date" name="date_to" id="date_to" value="{{ request('date_to') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
</div>
<div class="flex items-end">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
篩選
</button>
<a href="{{ route('admin.cashier-ledger.index') }}" class="ml-2 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<a href="{{ route('admin.cashier-ledger.index') }}" class="ml-2 inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
清除
</a>
</div>
@@ -112,80 +112,80 @@
</div>
<!-- Ledger Entries Table -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
日期
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
類型
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
付款方式
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
銀行帳戶
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
金額
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
交易前餘額
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
交易後餘額
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
記錄人
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
<span class="sr-only">操作</span>
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse ($entries as $entry)
<tr class="{{ $entry->isReceipt() ? 'bg-green-50' : 'bg-red-50' }} bg-opacity-20">
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-900">
<tr class="{{ $entry->isReceipt() ? 'bg-green-50 dark:bg-green-900/20' : 'bg-red-50 dark:bg-red-900/20' }}">
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-900 dark:text-gray-100">
{{ $entry->entry_date->format('Y-m-d') }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm">
<span class="inline-flex rounded-full px-2 text-xs font-semibold leading-5
{{ $entry->isReceipt() ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800' }}">
{{ $entry->isReceipt() ? 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200' : 'bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200' }}">
{{ $entry->getEntryTypeText() }}
</span>
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500">
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
{{ $entry->getPaymentMethodText() }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500">
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
{{ $entry->bank_account ?? 'N/A' }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-right font-medium {{ $entry->isReceipt() ? 'text-green-600' : 'text-red-600' }}">
<td class="whitespace-nowrap px-4 py-4 text-sm text-right font-medium {{ $entry->isReceipt() ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400' }}">
{{ $entry->isReceipt() ? '+' : '-' }} NT$ {{ number_format($entry->amount, 2) }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-right text-gray-500">
<td class="whitespace-nowrap px-4 py-4 text-sm text-right text-gray-500 dark:text-gray-400">
NT$ {{ number_format($entry->balance_before, 2) }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-right font-semibold text-gray-900">
<td class="whitespace-nowrap px-4 py-4 text-sm text-right font-semibold text-gray-900 dark:text-gray-100">
NT$ {{ number_format($entry->balance_after, 2) }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500">
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
{{ $entry->recordedByCashier->name ?? 'N/A' }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-right text-sm font-medium">
<a href="{{ route('admin.cashier-ledger.show', $entry) }}" class="text-indigo-600 hover:text-indigo-900">
<a href="{{ route('admin.cashier-ledger.show', $entry) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
查看
</a>
</td>
</tr>
@empty
<tr>
<td colspan="9" class="px-4 py-8 text-center text-sm text-gray-500">
<td colspan="9" class="px-4 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
沒有現金簿記錄
</td>
</tr>

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
現金簿分錄詳情
</h2>
</x-slot>
@@ -8,63 +8,63 @@
<div class="py-12">
<div class="mx-auto max-w-4xl sm:px-6 lg:px-8 space-y-4">
<!-- Entry Info -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-medium leading-6 text-gray-900">分錄資訊</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">分錄資訊</h3>
<span class="inline-flex rounded-full px-3 py-1 text-sm font-semibold
{{ $entry->isReceipt() ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800' }}">
{{ $entry->isReceipt() ? 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200' : 'bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200' }}">
{{ $entry->getEntryTypeText() }}
</span>
</div>
<dl class="grid grid-cols-1 gap-x-4 gap-y-4 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500">記帳日期</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $entry->entry_date->format('Y-m-d') }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">記帳日期</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $entry->entry_date->format('Y-m-d') }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">付款方式</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $entry->getPaymentMethodText() }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款方式</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $entry->getPaymentMethodText() }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">銀行帳戶</dt>
<dd class="mt-1 text-sm text-gray-900 font-mono">{{ $entry->bank_account ?? 'N/A' }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">銀行帳戶</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 font-mono">{{ $entry->bank_account ?? 'N/A' }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">金額</dt>
<dd class="mt-1 text-lg font-semibold {{ $entry->isReceipt() ? 'text-green-600' : 'text-red-600' }}">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">金額</dt>
<dd class="mt-1 text-lg font-semibold {{ $entry->isReceipt() ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400' }}">
{{ $entry->isReceipt() ? '+' : '-' }} NT$ {{ number_format($entry->amount, 2) }}
</dd>
</div>
@if($entry->receipt_number)
<div>
<dt class="text-sm font-medium text-gray-500">收據/憑證編號</dt>
<dd class="mt-1 text-sm text-gray-900 font-mono">{{ $entry->receipt_number }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">收據/憑證編號</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 font-mono">{{ $entry->receipt_number }}</dd>
</div>
@endif
@if($entry->transaction_reference)
<div>
<dt class="text-sm font-medium text-gray-500">交易參考號</dt>
<dd class="mt-1 text-sm text-gray-900 font-mono">{{ $entry->transaction_reference }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">交易參考號</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 font-mono">{{ $entry->transaction_reference }}</dd>
</div>
@endif
<div>
<dt class="text-sm font-medium text-gray-500">記錄人</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $entry->recordedByCashier->name }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">記錄人</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $entry->recordedByCashier->name }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">記錄時間</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $entry->recorded_at->format('Y-m-d H:i') }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">記錄時間</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $entry->recorded_at->format('Y-m-d H:i') }}</dd>
</div>
@if($entry->notes)
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500">備註</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $entry->notes }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">備註</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $entry->notes }}</dd>
</div>
@endif
</dl>
@@ -72,36 +72,36 @@
</div>
<!-- Balance Information -->
<div class="bg-gradient-to-r from-blue-50 to-indigo-50 shadow sm:rounded-lg border border-blue-200">
<div class="bg-gradient-to-r from-blue-50 to-indigo-50 dark:from-blue-900/30 dark:to-indigo-900/30 shadow sm:rounded-lg border border-blue-200 dark:border-blue-800">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">餘額變動</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">餘額變動</h3>
<div class="grid grid-cols-3 gap-4">
<div class="text-center p-4 bg-white rounded-lg shadow-sm">
<dt class="text-xs font-medium text-gray-500 uppercase">交易前餘額</dt>
<dd class="mt-2 text-2xl font-semibold text-gray-700">
<div class="text-center p-4 bg-white dark:bg-gray-700 rounded-lg shadow-sm">
<dt class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase">交易前餘額</dt>
<dd class="mt-2 text-2xl font-semibold text-gray-700 dark:text-gray-300">
{{ number_format($entry->balance_before, 2) }}
</dd>
</div>
<div class="text-center p-4 bg-white rounded-lg shadow-sm flex items-center justify-center">
<div class="text-center p-4 bg-white dark:bg-gray-700 rounded-lg shadow-sm flex items-center justify-center">
<div>
<svg class="h-8 w-8 mx-auto {{ $entry->isReceipt() ? 'text-green-500' : 'text-red-500' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="h-8 w-8 mx-auto {{ $entry->isReceipt() ? 'text-green-500 dark:text-green-400' : 'text-red-500 dark:text-red-400' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@if($entry->isReceipt())
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v3m0 0v3m0-3h3m-3 0H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" />
@else
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" />
@endif
</svg>
<div class="mt-1 text-lg font-semibold {{ $entry->isReceipt() ? 'text-green-600' : 'text-red-600' }}">
<div class="mt-1 text-lg font-semibold {{ $entry->isReceipt() ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400' }}">
{{ $entry->isReceipt() ? '+' : '-' }} {{ number_format($entry->amount, 2) }}
</div>
</div>
</div>
<div class="text-center p-4 bg-white rounded-lg shadow-sm">
<dt class="text-xs font-medium text-gray-500 uppercase">交易後餘額</dt>
<dd class="mt-2 text-2xl font-semibold {{ $entry->balance_after >= 0 ? 'text-green-600' : 'text-red-600' }}">
<div class="text-center p-4 bg-white dark:bg-gray-700 rounded-lg shadow-sm">
<dt class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase">交易後餘額</dt>
<dd class="mt-2 text-2xl font-semibold {{ $entry->balance_after >= 0 ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400' }}">
{{ number_format($entry->balance_after, 2) }}
</dd>
</div>
@@ -111,34 +111,34 @@
<!-- Related Finance Document -->
@if($entry->financeDocument)
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">關聯財務申請單</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">關聯報銷申請單</h3>
<dl class="grid grid-cols-1 gap-x-4 gap-y-4 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500">申請標題</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $entry->financeDocument->title }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">申請標題</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $entry->financeDocument->title }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">申請類型</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $entry->financeDocument->getRequestTypeText() }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">申請類型</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $entry->financeDocument->getRequestTypeText() }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">申請金額</dt>
<dd class="mt-1 text-sm text-gray-900">NT$ {{ number_format($entry->financeDocument->amount, 2) }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">申請金額</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">NT$ {{ number_format($entry->financeDocument->amount, 2) }}</dd>
</div>
@if($entry->financeDocument->member)
<div>
<dt class="text-sm font-medium text-gray-500">關聯會員</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $entry->financeDocument->member->full_name }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">關聯會員</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $entry->financeDocument->member->full_name }}</dd>
</div>
@endif
@if($entry->financeDocument->paymentOrder)
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500">付款單號</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款單號</dt>
<dd class="mt-1">
<a href="{{ route('admin.payment-orders.show', $entry->financeDocument->paymentOrder) }}" class="text-indigo-600 hover:text-indigo-900 font-mono">
<a href="{{ route('admin.payment-orders.show', $entry->financeDocument->paymentOrder) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300 font-mono">
{{ $entry->financeDocument->paymentOrder->payment_order_number }}
</a>
</dd>
@@ -146,7 +146,7 @@
@endif
</dl>
<div class="mt-4">
<a href="{{ route('admin.finance.show', $entry->financeDocument) }}" class="text-indigo-600 hover:text-indigo-900">
<a href="{{ route('admin.finance.show', $entry->financeDocument) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
查看完整申請單
</a>
</div>
@@ -156,13 +156,13 @@
<!-- Actions -->
<div class="flex justify-between">
<a href="{{ route('admin.cashier-ledger.index') }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<a href="{{ route('admin.cashier-ledger.index') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
返回列表
</a>
@if($entry->financeDocument)
<a href="{{ route('admin.finance.show', $entry->financeDocument) }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
查看財務申請單
<a href="{{ route('admin.finance.show', $entry->financeDocument) }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
查看報銷申請單
</a>
@endif
</div>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Admin Dashboard') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
管理後台
</h2>
</x-slot>
@@ -10,18 +10,18 @@
<div class="space-y-6">
{{-- My Pending Approvals Alert --}}
@if ($myPendingApprovals > 0)
<div class="rounded-md bg-yellow-50 p-4" role="alert" aria-live="polite">
<div class="rounded-md bg-yellow-50 dark:bg-yellow-900/50 p-4" role="alert" aria-live="polite">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-yellow-400" viewBox="0 0 20 20" fill="currentColor">
<svg class="h-5 w-5 text-yellow-400 dark:text-yellow-300" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<p class="text-sm font-medium text-yellow-800">
{{ __('You have :count finance document(s) waiting for your approval.', ['count' => $myPendingApprovals]) }}
<a href="{{ route('admin.finance.index') }}" class="font-semibold underline hover:text-yellow-700">
{{ __('View pending approvals') }}
<p class="text-sm font-medium text-yellow-800 dark:text-yellow-200">
您有 {{ $myPendingApprovals }} 個報銷單等待您的核准。
<a href="{{ route('admin.finance.index') }}" class="font-semibold underline hover:text-yellow-700 dark:hover:text-yellow-100">
查看待核准項目
</a>
</p>
</div>
@@ -32,103 +32,103 @@
{{-- Stats Grid --}}
<div class="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-4">
{{-- Total Members --}}
<div class="overflow-hidden rounded-lg bg-white shadow">
<div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow">
<div class="p-5">
<div class="flex items-center">
<div class="flex-shrink-0">
<svg class="h-6 w-6 text-gray-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<svg class="h-6 w-6 text-gray-400 dark:text-gray-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" />
</svg>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="truncate text-sm font-medium text-gray-500">{{ __('Total Members') }}</dt>
<dd class="text-2xl font-semibold text-gray-900">{{ number_format($totalMembers) }}</dd>
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">會員總數</dt>
<dd class="text-2xl font-semibold text-gray-900 dark:text-gray-100">{{ number_format($totalMembers) }}</dd>
</dl>
</div>
</div>
</div>
<div class="bg-gray-50 px-5 py-3">
<div class="bg-gray-50 dark:bg-gray-700 px-5 py-3">
<div class="text-sm">
<a href="{{ route('admin.members.index') }}" class="font-medium text-indigo-600 hover:text-indigo-900">
{{ __('View all') }}
<a href="{{ route('admin.members.index') }}" class="font-medium text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
查看全部
</a>
</div>
</div>
</div>
{{-- Active Members --}}
<div class="overflow-hidden rounded-lg bg-white shadow">
<div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow">
<div class="p-5">
<div class="flex items-center">
<div class="flex-shrink-0">
<svg class="h-6 w-6 text-green-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<svg class="h-6 w-6 text-green-400 dark:text-green-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="truncate text-sm font-medium text-gray-500">{{ __('Active Members') }}</dt>
<dd class="text-2xl font-semibold text-green-600">{{ number_format($activeMembers) }}</dd>
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">使用中會員</dt>
<dd class="text-2xl font-semibold text-green-600 dark:text-green-400">{{ number_format($activeMembers) }}</dd>
</dl>
</div>
</div>
</div>
<div class="bg-gray-50 px-5 py-3">
<div class="bg-gray-50 dark:bg-gray-700 px-5 py-3">
<div class="text-sm">
<a href="{{ route('admin.members.index', ['status' => 'active']) }}" class="font-medium text-indigo-600 hover:text-indigo-900">
{{ __('View active') }}
<a href="{{ route('admin.members.index', ['status' => 'active']) }}" class="font-medium text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
查看使用中
</a>
</div>
</div>
</div>
{{-- Expired Members --}}
<div class="overflow-hidden rounded-lg bg-white shadow">
<div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow">
<div class="p-5">
<div class="flex items-center">
<div class="flex-shrink-0">
<svg class="h-6 w-6 text-red-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<svg class="h-6 w-6 text-red-400 dark:text-red-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
</svg>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="truncate text-sm font-medium text-gray-500">{{ __('Expired Members') }}</dt>
<dd class="text-2xl font-semibold text-red-600">{{ number_format($expiredMembers) }}</dd>
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">已過期會員</dt>
<dd class="text-2xl font-semibold text-red-600 dark:text-red-400">{{ number_format($expiredMembers) }}</dd>
</dl>
</div>
</div>
</div>
<div class="bg-gray-50 px-5 py-3">
<div class="bg-gray-50 dark:bg-gray-700 px-5 py-3">
<div class="text-sm">
<a href="{{ route('admin.members.index', ['status' => 'expired']) }}" class="font-medium text-indigo-600 hover:text-indigo-900">
{{ __('View expired') }}
<a href="{{ route('admin.members.index', ['status' => 'expired']) }}" class="font-medium text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
查看已過期
</a>
</div>
</div>
</div>
{{-- Expiring Soon --}}
<div class="overflow-hidden rounded-lg bg-white shadow">
<div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow">
<div class="p-5">
<div class="flex items-center">
<div class="flex-shrink-0">
<svg class="h-6 w-6 text-yellow-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<svg class="h-6 w-6 text-yellow-400 dark:text-yellow-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="truncate text-sm font-medium text-gray-500">{{ __('Expiring in 30 Days') }}</dt>
<dd class="text-2xl font-semibold text-yellow-600">{{ number_format($expiringSoon) }}</dd>
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">30天內到期</dt>
<dd class="text-2xl font-semibold text-yellow-600 dark:text-yellow-400">{{ number_format($expiringSoon) }}</dd>
</dl>
</div>
</div>
</div>
<div class="bg-gray-50 px-5 py-3">
<div class="bg-gray-50 dark:bg-gray-700 px-5 py-3">
<div class="text-sm">
<span class="text-gray-500">{{ __('Renewal reminders needed') }}</span>
<span class="text-gray-500 dark:text-gray-400">需要更新提醒</span>
</div>
</div>
</div>
@@ -137,74 +137,74 @@
{{-- Revenue Stats --}}
<div class="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3">
{{-- Total Revenue --}}
<div class="overflow-hidden rounded-lg bg-white shadow">
<div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow">
<div class="p-5">
<div class="flex items-center">
<div class="flex-shrink-0">
<svg class="h-6 w-6 text-gray-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<svg class="h-6 w-6 text-gray-400 dark:text-gray-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v12m-3-2.818l.879.659c1.171.879 3.07.879 4.242 0 1.172-.879 1.172-2.303 0-3.182C13.536 12.219 12.768 12 12 12c-.725 0-1.45-.22-2.003-.659-1.106-.879-1.106-2.303 0-3.182s2.9-.879 4.006 0l.415.33M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="truncate text-sm font-medium text-gray-500">{{ __('Total Revenue') }}</dt>
<dd class="text-2xl font-semibold text-gray-900">${{ number_format($totalRevenue, 2) }}</dd>
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">總收入</dt>
<dd class="text-2xl font-semibold text-gray-900 dark:text-gray-100">${{ number_format($totalRevenue, 2) }}</dd>
</dl>
</div>
</div>
</div>
<div class="bg-gray-50 px-5 py-3">
<div class="text-sm text-gray-500">
{{ number_format($totalPayments) }} {{ __('total payments') }}
<div class="bg-gray-50 dark:bg-gray-700 px-5 py-3">
<div class="text-sm text-gray-500 dark:text-gray-400">
{{ number_format($totalPayments) }} 總付款
</div>
</div>
</div>
{{-- This Month Revenue --}}
<div class="overflow-hidden rounded-lg bg-white shadow">
<div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow">
<div class="p-5">
<div class="flex items-center">
<div class="flex-shrink-0">
<svg class="h-6 w-6 text-green-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<svg class="h-6 w-6 text-green-400 dark:text-green-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 18.75a60.07 60.07 0 0115.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 013 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 00-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 01-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 003 15h-.75M15 10.5a3 3 0 11-6 0 3 3 0 016 0zm3 0h.008v.008H18V10.5zm-12 0h.008v.008H6V10.5z" />
</svg>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="truncate text-sm font-medium text-gray-500">{{ __('This Month') }}</dt>
<dd class="text-2xl font-semibold text-green-600">${{ number_format($revenueThisMonth, 2) }}</dd>
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">本月</dt>
<dd class="text-2xl font-semibold text-green-600 dark:text-green-400">${{ number_format($revenueThisMonth, 2) }}</dd>
</dl>
</div>
</div>
</div>
<div class="bg-gray-50 px-5 py-3">
<div class="text-sm text-gray-500">
{{ number_format($paymentsThisMonth) }} {{ __('payments this month') }}
<div class="bg-gray-50 dark:bg-gray-700 px-5 py-3">
<div class="text-sm text-gray-500 dark:text-gray-400">
{{ number_format($paymentsThisMonth) }} 本月付款
</div>
</div>
</div>
{{-- Pending Approvals --}}
<div class="overflow-hidden rounded-lg bg-white shadow">
<div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow">
<div class="p-5">
<div class="flex items-center">
<div class="flex-shrink-0">
<svg class="h-6 w-6 text-blue-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<svg class="h-6 w-6 text-blue-400 dark:text-blue-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75 2.25 2.25 0 00-.1-.664m-5.8 0A2.251 2.251 0 0113.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m0 0H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V9.375c0-.621-.504-1.125-1.125-1.125H8.25zM6.75 12h.008v.008H6.75V12zm0 3h.008v.008H6.75V15zm0 3h.008v.008H6.75V18z" />
</svg>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="truncate text-sm font-medium text-gray-500">{{ __('Finance Documents') }}</dt>
<dd class="text-2xl font-semibold text-blue-600">{{ number_format($pendingApprovals) }}</dd>
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">報銷單</dt>
<dd class="text-2xl font-semibold text-blue-600 dark:text-blue-400">{{ number_format($pendingApprovals) }}</dd>
</dl>
</div>
</div>
</div>
<div class="bg-gray-50 px-5 py-3">
<div class="bg-gray-50 dark:bg-gray-700 px-5 py-3">
<div class="text-sm">
<a href="{{ route('admin.finance.index') }}" class="font-medium text-indigo-600 hover:text-indigo-900">
{{ __('View pending') }}
<a href="{{ route('admin.finance.index') }}" class="font-medium text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
查看待處理
</a>
</div>
</div>
@@ -214,25 +214,25 @@
{{-- Recent Payments & Finance Stats --}}
<div class="grid grid-cols-1 gap-5 lg:grid-cols-2">
{{-- Recent Payments --}}
<div class="overflow-hidden rounded-lg bg-white shadow">
<div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900">{{ __('Recent Payments') }}</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">最近付款</h3>
<div class="mt-4 flow-root">
@if ($recentPayments->count() > 0)
<ul role="list" class="-my-5 divide-y divide-gray-200">
<ul role="list" class="-my-5 divide-y divide-gray-200 dark:divide-gray-700">
@foreach ($recentPayments as $payment)
<li class="py-4">
<div class="flex items-center space-x-4">
<div class="min-w-0 flex-1">
<p class="truncate text-sm font-medium text-gray-900">
<p class="truncate text-sm font-medium text-gray-900 dark:text-gray-100">
{{ $payment->member?->full_name ?? __('N/A') }}
</p>
<p class="truncate text-sm text-gray-500">
<p class="truncate text-sm text-gray-500 dark:text-gray-400">
{{ $payment->paid_at?->format('Y-m-d') ?? __('N/A') }}
</p>
</div>
<div>
<span class="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
<span class="inline-flex items-center rounded-full bg-green-100 dark:bg-green-900 px-2.5 py-0.5 text-xs font-medium text-green-800 dark:text-green-200">
${{ number_format($payment->amount, 2) }}
</span>
</div>
@@ -241,43 +241,96 @@
@endforeach
</ul>
@else
<p class="text-sm text-gray-500">{{ __('No recent payments.') }}</p>
<p class="text-sm text-gray-500 dark:text-gray-400">沒有最近的付款記錄。</p>
@endif
</div>
</div>
</div>
{{-- Finance Document Stats --}}
<div class="overflow-hidden rounded-lg bg-white shadow">
<div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900">{{ __('Finance Document Status') }}</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">報銷單狀態</h3>
<div class="mt-6 space-y-4">
<div class="flex items-center justify-between">
<div class="flex items-center">
<span class="flex h-3 w-3 rounded-full bg-yellow-400"></span>
<span class="ml-3 text-sm font-medium text-gray-900">{{ __('Pending Approval') }}</span>
<span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-100">待核准</span>
</div>
<span class="text-sm font-semibold text-gray-900">{{ number_format($pendingApprovals) }}</span>
<span class="text-sm font-semibold text-gray-900 dark:text-gray-100">{{ number_format($pendingApprovals) }}</span>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center">
<span class="flex h-3 w-3 rounded-full bg-green-400"></span>
<span class="ml-3 text-sm font-medium text-gray-900">{{ __('Fully Approved') }}</span>
<span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-100">完全核准</span>
</div>
<span class="text-sm font-semibold text-gray-900">{{ number_format($fullyApprovedDocs) }}</span>
<span class="text-sm font-semibold text-gray-900 dark:text-gray-100">{{ number_format($fullyApprovedDocs) }}</span>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center">
<span class="flex h-3 w-3 rounded-full bg-red-400"></span>
<span class="ml-3 text-sm font-medium text-gray-900">{{ __('Rejected') }}</span>
<span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-100">已拒絕</span>
</div>
<span class="text-sm font-semibold text-gray-900">{{ number_format($rejectedDocs) }}</span>
<span class="text-sm font-semibold text-gray-900 dark:text-gray-100">{{ number_format($rejectedDocs) }}</span>
</div>
</div>
</div>
</div>
</div>
{{-- Recent Announcements --}}
@if($recentAnnouncements->isNotEmpty())
<div class="mt-8">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="border-b border-gray-200 dark:border-gray-700 px-4 py-5 sm:px-6">
<div class="flex items-center justify-between">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">📢 最新公告</h3>
@can('view_announcements')
<a href="{{ route('admin.announcements.index') }}" class="text-sm font-medium text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
查看全部
</a>
@endcan
</div>
</div>
<ul role="list" class="divide-y divide-gray-200 dark:divide-gray-700">
@foreach($recentAnnouncements as $announcement)
<li class="px-4 py-4 sm:px-6 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors">
<div class="flex items-start justify-between">
<div class="flex-1 min-w-0">
<div class="flex items-center mb-1">
@if($announcement->is_pinned)
<span class="mr-2 text-blue-500" title="置頂公告">📌</span>
@endif
<h4 class="text-sm font-semibold text-gray-900 dark:text-gray-100 truncate">
{{ $announcement->title }}
</h4>
</div>
<p class="text-sm text-gray-600 dark:text-gray-400 line-clamp-2">
{{ $announcement->getExcerpt(120) }}
</p>
<div class="mt-2 flex items-center space-x-4 text-xs text-gray-500 dark:text-gray-400">
<span>{{ $announcement->published_at?->diffForHumans() ?? $announcement->created_at->diffForHumans() }}</span>
<span></span>
<span>{{ $announcement->getAccessLevelLabel() }}</span>
@if($announcement->view_count > 0)
<span></span>
<span>👁 {{ $announcement->view_count }} 次瀏覽</span>
@endif
</div>
</div>
@can('view_announcements')
<a href="{{ route('admin.announcements.show', $announcement) }}" class="ml-4 flex-shrink-0 text-sm font-medium text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
查看
</a>
@endcan
</div>
</li>
@endforeach
</ul>
</div>
</div>
@endif
</div>
</div>
</div>
</x-app-layout>
</x-app-layout>

View File

@@ -1,95 +1,95 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
新增文件類別
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<form action="{{ route('admin.document-categories.store') }}" method="POST" class="p-6 space-y-6">
@csrf
<div>
<label for="name" class="block text-sm font-medium text-gray-700">
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
類別名稱 <span class="text-red-500">*</span>
</label>
<input type="text" name="name" id="name" value="{{ old('name') }}" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 @error('name') border-red-500 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 @error('name') border-red-500 @enderror dark:bg-gray-700 dark:text-gray-100">
@error('name')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="slug" class="block text-sm font-medium text-gray-700">
<label for="slug" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
代碼 (URL slug)
</label>
<input type="text" name="slug" id="slug" value="{{ old('slug') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 @error('slug') border-red-500 @enderror">
<p class="mt-1 text-sm text-gray-500">留空則自動產生</p>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 @error('slug') border-red-500 @enderror dark:bg-gray-700 dark:text-gray-100">
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">留空則自動產生</p>
@error('slug')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="description" class="block text-sm font-medium text-gray-700">
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
說明
</label>
<textarea name="description" id="description" rows="3"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">{{ old('description') }}</textarea>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-700 dark:text-gray-100">{{ old('description') }}</textarea>
@error('description')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="icon" class="block text-sm font-medium text-gray-700">
<label for="icon" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
圖示 (emoji)
</label>
<input type="text" name="icon" id="icon" value="{{ old('icon') }}" placeholder="📄"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
<p class="mt-1 text-sm text-gray-500">輸入 emoji例如📄 📝 📊 📋</p>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-700 dark:text-gray-100">
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">輸入 emoji例如📄 📝 📊 📋</p>
@error('icon')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="default_access_level" class="block text-sm font-medium text-gray-700">
<label for="default_access_level" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
預設存取權限 <span class="text-red-500">*</span>
</label>
<select name="default_access_level" id="default_access_level" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-700 dark:text-gray-100">
<option value="public" {{ old('default_access_level') === 'public' ? 'selected' : '' }}>公開 (任何人可查看)</option>
<option value="members" {{ old('default_access_level') === 'members' ? 'selected' : '' }}>會員 (需登入且為會員)</option>
<option value="admin" {{ old('default_access_level') === 'admin' ? 'selected' : '' }}>管理員 (僅管理員可查看)</option>
<option value="board" {{ old('default_access_level') === 'board' ? 'selected' : '' }}>理事會 (僅理事會成員)</option>
</select>
@error('default_access_level')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="sort_order" class="block text-sm font-medium text-gray-700">
<label for="sort_order" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
排序順序
</label>
<input type="number" name="sort_order" id="sort_order" value="{{ old('sort_order', 0) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
<p class="mt-1 text-sm text-gray-500">數字越小越前面</p>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-700 dark:text-gray-100">
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">數字越小越前面</p>
@error('sort_order')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="flex items-center justify-end space-x-4 pt-4">
<a href="{{ route('admin.document-categories.index') }}" class="rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<a href="{{ route('admin.document-categories.index') }}" class="rounded-md border border-gray-300 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
取消
</a>
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700">
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
建立類別
</button>
</div>

View File

@@ -1,96 +1,54 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
編輯文件類別
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
編輯分類
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<form action="{{ route('admin.document-categories.update', $documentCategory) }}" method="POST" class="p-6 space-y-6">
@csrf
@method('PATCH')
<div>
<label for="name" class="block text-sm font-medium text-gray-700">
名稱 <span class="text-red-500">*</span>
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
類名稱 <span class="text-red-500">*</span>
</label>
<input type="text" name="name" id="name" value="{{ old('name', $documentCategory->name) }}" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 @error('name') border-red-500 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
@error('name')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="slug" class="block text-sm font-medium text-gray-700">
代碼 (URL slug)
<label for="icon" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
圖示(表情符號)
</label>
<input type="text" name="slug" id="slug" value="{{ old('slug', $documentCategory->slug) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 @error('slug') border-red-500 @enderror">
@error('slug')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<input type="text" name="icon" id="icon" value="{{ old('icon', $documentCategory->icon) }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">例如:📁, 📃, 📊</p>
@error('icon')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="description" class="block text-sm font-medium text-gray-700">
說明
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
描述
</label>
<textarea name="description" id="description" rows="3"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">{{ old('description', $documentCategory->description) }}</textarea>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:text-gray-100">{{ old('description', $documentCategory->description) }}</textarea>
@error('description')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="icon" class="block text-sm font-medium text-gray-700">
圖示 (emoji)
</label>
<input type="text" name="icon" id="icon" value="{{ old('icon', $documentCategory->icon) }}" placeholder="📄"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
<p class="mt-1 text-sm text-gray-500">輸入 emoji例如📄 📝 📊 📋</p>
@error('icon')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<div>
<label for="default_access_level" class="block text-sm font-medium text-gray-700">
預設存取權限 <span class="text-red-500">*</span>
</label>
<select name="default_access_level" id="default_access_level" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
<option value="public" {{ old('default_access_level', $documentCategory->default_access_level) === 'public' ? 'selected' : '' }}>公開 (任何人可查看)</option>
<option value="members" {{ old('default_access_level', $documentCategory->default_access_level) === 'members' ? 'selected' : '' }}>會員 (需登入且為會員)</option>
<option value="admin" {{ old('default_access_level', $documentCategory->default_access_level) === 'admin' ? 'selected' : '' }}>管理員 (僅管理員可查看)</option>
<option value="board" {{ old('default_access_level', $documentCategory->default_access_level) === 'board' ? 'selected' : '' }}>理事會 (僅理事會成員)</option>
</select>
@error('default_access_level')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<div>
<label for="sort_order" class="block text-sm font-medium text-gray-700">
排序順序
</label>
<input type="number" name="sort_order" id="sort_order" value="{{ old('sort_order', $documentCategory->sort_order) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
<p class="mt-1 text-sm text-gray-500">數字越小越前面</p>
@error('sort_order')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<div class="flex items-center justify-end space-x-4 pt-4">
<a href="{{ route('admin.document-categories.index') }}" class="rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
取消
</a>
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700">
更新類別
<div class="flex items-center justify-end">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
更新分類
</button>
</div>
</form>

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
文件類別管理
</h2>
</x-slot>
@@ -8,23 +8,23 @@
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-6">
@if (session('status'))
<div class="rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 p-4">
<p class="text-sm font-medium text-red-800">{{ session('error') }}</p>
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<div class="flex justify-between items-center">
<div>
<h3 class="text-lg font-medium text-gray-900">文件類別</h3>
<p class="mt-1 text-sm text-gray-600">管理文件分類,設定預設存取權限</p>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">文件類別</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">管理文件分類,設定預設存取權限</p>
</div>
<a href="{{ route('admin.document-categories.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700">
<a href="{{ route('admin.document-categories.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
<svg class="-ml-1 mr-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
@@ -32,60 +32,60 @@
</a>
</div>
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">圖示</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">名稱</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">代碼</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">預設存取</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">文件數量</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">排序</th>
<th scope="col" class="px-6 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">操作</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">圖示</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">名稱</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">代碼</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">預設存取</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">文件數量</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">排序</th>
<th scope="col" class="px-6 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse ($categories as $category)
<tr>
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
<td class="px-6 py-4 whitespace-nowrap text-2xl">
{{ $category->getIconDisplay() }}
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-gray-900">{{ $category->name }}</div>
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">{{ $category->name }}</div>
@if($category->description)
<div class="text-sm text-gray-500">{{ $category->description }}</div>
<div class="text-sm text-gray-500 dark:text-gray-400">{{ $category->description }}</div>
@endif
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<code class="px-2 py-1 bg-gray-100 rounded">{{ $category->slug }}</code>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
<code class="px-2 py-1 bg-gray-100 rounded dark:bg-gray-700 dark:text-gray-200">{{ $category->slug }}</code>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="inline-flex rounded-full px-2 py-1 text-xs font-semibold
@if($category->default_access_level === 'public') bg-green-100 text-green-800
@elseif($category->default_access_level === 'members') bg-blue-100 text-blue-800
@elseif($category->default_access_level === 'admin') bg-purple-100 text-purple-800
@else bg-gray-100 text-gray-800
@if($category->default_access_level === 'public') bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200
@elseif($category->default_access_level === 'members') bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-200
@elseif($category->default_access_level === 'admin') bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-200
@else bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200
@endif">
{{ $category->getAccessLevelLabel() }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
{{ $category->active_documents_count }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
{{ $category->sort_order }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium space-x-2">
<a href="{{ route('admin.document-categories.edit', $category) }}" class="text-indigo-600 hover:text-indigo-900">
<a href="{{ route('admin.document-categories.edit', $category) }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
編輯
</a>
<form action="{{ route('admin.document-categories.destroy', $category) }}" method="POST" class="inline" onsubmit="return confirm('確定要刪除此類別嗎?');">
@csrf
@method('DELETE')
<button type="submit" class="text-red-600 hover:text-red-900">
<button type="submit" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">
刪除
</button>
</form>
@@ -93,7 +93,7 @@
</tr>
@empty
<tr>
<td colspan="7" class="px-6 py-4 text-center text-sm text-gray-500">
<td colspan="7" class="px-6 py-4 text-center text-sm text-gray-500 dark:text-gray-400">
尚無類別資料
</td>
</tr>

View File

@@ -1,22 +1,22 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
上傳文件
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<form action="{{ route('admin.documents.store') }}" method="POST" enctype="multipart/form-data" class="p-6 space-y-6">
@csrf
<div>
<label for="document_category_id" class="block text-sm font-medium text-gray-700">
文件類別 <span class="text-red-500">*</span>
<label for="document_category_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
文件類別 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<select name="document_category_id" id="document_category_id" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 @error('document_category_id') border-red-500 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300 @error('document_category_id') border-red-500 @enderror">
<option value="">請選擇類別</option>
@foreach($categories as $category)
<option value="{{ $category->id }}" {{ old('document_category_id') == $category->id ? 'selected' : '' }}>
@@ -25,97 +25,97 @@
@endforeach
</select>
@error('document_category_id')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="title" class="block text-sm font-medium text-gray-700">
文件標題 <span class="text-red-500">*</span>
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
文件標題 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<input type="text" name="title" id="title" value="{{ old('title') }}" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 @error('title') border-red-500 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300 @error('title') border-red-500 @enderror">
@error('title')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="document_number" class="block text-sm font-medium text-gray-700">
<label for="document_number" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
文件編號
</label>
<input type="text" name="document_number" id="document_number" value="{{ old('document_number') }}"
placeholder="例如BYL-2024-001"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 @error('document_number') border-red-500 @enderror">
<p class="mt-1 text-sm text-gray-500">選填,用於正式文件編號</p>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300 @error('document_number') border-red-500 @enderror">
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">選填,用於正式文件編號</p>
@error('document_number')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="description" class="block text-sm font-medium text-gray-700">
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
文件說明
</label>
<textarea name="description" id="description" rows="3"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 @error('description') border-red-500 @enderror">{{ old('description') }}</textarea>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300 @error('description') border-red-500 @enderror">{{ old('description') }}</textarea>
@error('description')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="access_level" class="block text-sm font-medium text-gray-700">
存取權限 <span class="text-red-500">*</span>
<label for="access_level" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
存取權限 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<select name="access_level" id="access_level" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 @error('access_level') border-red-500 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300 @error('access_level') border-red-500 @enderror">
<option value="public" {{ old('access_level') === 'public' ? 'selected' : '' }}>公開 (任何人可查看)</option>
<option value="members" {{ old('access_level') === 'members' ? 'selected' : '' }}>會員 (需登入且為會員)</option>
<option value="admin" {{ old('access_level') === 'admin' ? 'selected' : '' }}>管理員 (僅管理員可查看)</option>
<option value="board" {{ old('access_level') === 'board' ? 'selected' : '' }}>理事會 (僅理事會成員)</option>
</select>
@error('access_level')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="file" class="block text-sm font-medium text-gray-700">
上傳檔案 <span class="text-red-500">*</span>
<label for="file" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
上傳檔案 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<input type="file" name="file" id="file" required accept=".pdf,.doc,.docx,.xls,.xlsx,.txt"
class="mt-1 block w-full text-sm text-gray-500
class="mt-1 block w-full text-sm text-gray-500 dark:text-gray-400
file:mr-4 file:py-2 file:px-4
file:rounded-md file:border-0
file:text-sm file:font-semibold
file:bg-indigo-50 file:text-indigo-700
hover:file:bg-indigo-100
file:bg-indigo-50 dark:file:bg-indigo-900/50 file:text-indigo-700 dark:file:text-indigo-300
hover:file:bg-indigo-100 dark:hover:file:bg-indigo-800
@error('file') border-red-500 @enderror">
<p class="mt-1 text-sm text-gray-500">支援格式PDF, Word, Excel, 文字檔,最大 10MB</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">支援格式PDF, Word, Excel, 文字檔,最大 10MB</p>
@error('file')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="version_notes" class="block text-sm font-medium text-gray-700">
<label for="version_notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
版本說明
</label>
<textarea name="version_notes" id="version_notes" rows="2" placeholder="例如:初始版本"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">{{ old('version_notes') }}</textarea>
<p class="mt-1 text-sm text-gray-500">說明此版本的內容或變更</p>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300">{{ old('version_notes') }}</textarea>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">說明此版本的內容或變更</p>
@error('version_notes')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="border-t border-gray-200 pt-4">
<div class="border-t border-gray-200 dark:border-gray-700 pt-4">
<div class="flex items-center justify-end space-x-4">
<a href="{{ route('admin.documents.index') }}" class="rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<a href="{{ route('admin.documents.index') }}" class="rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
取消
</a>
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700">
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
上傳文件
</button>
</div>

View File

@@ -1,23 +1,23 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
編輯文件資訊
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<form action="{{ route('admin.documents.update', $document) }}" method="POST" class="p-6 space-y-6">
@csrf
@method('PATCH')
<div>
<label for="document_category_id" class="block text-sm font-medium text-gray-700">
文件類別 <span class="text-red-500">*</span>
<label for="document_category_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
文件類別 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<select name="document_category_id" id="document_category_id" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300">
@foreach($categories as $category)
<option value="{{ $category->id }}" {{ old('document_category_id', $document->document_category_id) == $category->id ? 'selected' : '' }}>
{{ $category->icon }} {{ $category->name }}
@@ -25,69 +25,69 @@
@endforeach
</select>
@error('document_category_id')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="title" class="block text-sm font-medium text-gray-700">
文件標題 <span class="text-red-500">*</span>
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
文件標題 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<input type="text" name="title" id="title" value="{{ old('title', $document->title) }}" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300">
@error('title')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="document_number" class="block text-sm font-medium text-gray-700">
<label for="document_number" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
文件編號
</label>
<input type="text" name="document_number" id="document_number" value="{{ old('document_number', $document->document_number) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300">
@error('document_number')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="description" class="block text-sm font-medium text-gray-700">
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
文件說明
</label>
<textarea name="description" id="description" rows="3"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">{{ old('description', $document->description) }}</textarea>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300">{{ old('description', $document->description) }}</textarea>
@error('description')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="access_level" class="block text-sm font-medium text-gray-700">
存取權限 <span class="text-red-500">*</span>
<label for="access_level" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
存取權限 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<select name="access_level" id="access_level" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300">
<option value="public" {{ old('access_level', $document->access_level) === 'public' ? 'selected' : '' }}>公開 (任何人可查看)</option>
<option value="members" {{ old('access_level', $document->access_level) === 'members' ? 'selected' : '' }}>會員 (需登入且為會員)</option>
<option value="admin" {{ old('access_level', $document->access_level) === 'admin' ? 'selected' : '' }}>管理員 (僅管理員可查看)</option>
<option value="board" {{ old('access_level', $document->access_level) === 'board' ? 'selected' : '' }}>理事會 (僅理事會成員)</option>
</select>
@error('access_level')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="bg-yellow-50 border border-yellow-200 rounded-md p-4">
<div class="bg-yellow-50 dark:bg-yellow-900/30 border border-yellow-200 dark:border-yellow-800 rounded-md p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-yellow-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<svg class="h-5 w-5 text-yellow-400 dark:text-yellow-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-yellow-800">注意</h3>
<div class="mt-2 text-sm text-yellow-700">
<h3 class="text-sm font-medium text-yellow-800 dark:text-yellow-300">注意</h3>
<div class="mt-2 text-sm text-yellow-700 dark:text-yellow-400">
<p>此處僅更新文件資訊,不會變更檔案內容。如需更新檔案,請使用「上傳新版本」功能。</p>
</div>
</div>
@@ -95,10 +95,10 @@
</div>
<div class="flex items-center justify-end space-x-4 pt-4">
<a href="{{ route('admin.documents.show', $document) }}" class="rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<a href="{{ route('admin.documents.show', $document) }}" class="rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
取消
</a>
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700">
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
更新資訊
</button>
</div>

View File

@@ -1,14 +1,14 @@
<x-app-layout>
<x-slot name="header">
<div class="flex items-center justify-between">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
文件管理
</h2>
<div class="flex items-center space-x-2">
<a href="{{ route('admin.documents.statistics') }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<a href="{{ route('admin.documents.statistics') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
📊 統計分析
</a>
<a href="{{ route('admin.documents.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-700">
<a href="{{ route('admin.documents.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
+ 上傳文件
</a>
</div>
@@ -18,29 +18,29 @@
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-6">
@if (session('status'))
<div class="rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="rounded-md bg-green-50 dark:bg-green-900/50 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 p-4">
<p class="text-sm font-medium text-red-800">{{ session('error') }}</p>
<div class="rounded-md bg-red-50 dark:bg-red-900/50 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<!-- Search and Filter -->
<div class="bg-white shadow sm:rounded-lg p-6">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
<form method="GET" action="{{ route('admin.documents.index') }}" class="space-y-4">
<div class="grid grid-cols-1 gap-4 md:grid-cols-4">
<div>
<label for="search" class="block text-sm font-medium text-gray-700">搜尋</label>
<label for="search" class="block text-sm font-medium text-gray-700 dark:text-gray-300">搜尋</label>
<input type="text" name="search" id="search" value="{{ request('search') }}" placeholder="標題、文號..."
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
</div>
<div>
<label for="category" class="block text-sm font-medium text-gray-700">類別</label>
<select name="category" id="category" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
<label for="category" class="block text-sm font-medium text-gray-700 dark:text-gray-300">類別</label>
<select name="category" id="category" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部類別</option>
@foreach($categories as $cat)
<option value="{{ $cat->id }}" {{ request('category') == $cat->id ? 'selected' : '' }}>
@@ -50,8 +50,8 @@
</select>
</div>
<div>
<label for="access_level" class="block text-sm font-medium text-gray-700">存取權限</label>
<select name="access_level" id="access_level" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
<label for="access_level" class="block text-sm font-medium text-gray-700 dark:text-gray-300">存取權限</label>
<select name="access_level" id="access_level" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部</option>
<option value="public" {{ request('access_level') === 'public' ? 'selected' : '' }}>公開</option>
<option value="members" {{ request('access_level') === 'members' ? 'selected' : '' }}>會員</option>
@@ -60,8 +60,8 @@
</select>
</div>
<div>
<label for="status" class="block text-sm font-medium text-gray-700">狀態</label>
<select name="status" id="status" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">狀態</label>
<select name="status" id="status" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部</option>
<option value="active" {{ request('status') === 'active' ? 'selected' : '' }}>啟用</option>
<option value="archived" {{ request('status') === 'archived' ? 'selected' : '' }}>封存</option>
@@ -69,10 +69,10 @@
</div>
</div>
<div class="flex justify-end space-x-2">
<a href="{{ route('admin.documents.index') }}" class="rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<a href="{{ route('admin.documents.index') }}" class="rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
清除
</a>
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700">
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
搜尋
</button>
</div>
@@ -81,9 +81,9 @@
<div class="flex justify-between items-center">
<div>
<p class="text-sm text-gray-600"> {{ $documents->total() }} 個文件</p>
<p class="text-sm text-gray-600 dark:text-gray-400"> {{ $documents->total() }} 個文件</p>
</div>
<a href="{{ route('admin.documents.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700">
<a href="{{ route('admin.documents.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
<svg class="-ml-1 mr-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
@@ -92,56 +92,56 @@
</div>
<!-- Documents Table -->
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<div class="bg-white dark:bg-gray-800 shadow overflow-hidden sm:rounded-lg">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">文件</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">類別</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">存取</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">版本</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">統計</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">狀態</th>
<th scope="col" class="px-6 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">操作</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">文件</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">類別</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">存取</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">版本</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">統計</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">狀態</th>
<th scope="col" class="px-6 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse ($documents as $document)
<tr class="hover:bg-gray-50">
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
<td class="px-6 py-4">
<div class="flex items-center">
<div class="text-2xl mr-3">
{{ $document->currentVersion?->getFileIcon() ?? '📄' }}
</div>
<div>
<div class="text-sm font-medium text-gray-900">{{ $document->title }}</div>
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">{{ $document->title }}</div>
@if($document->document_number)
<div class="text-xs text-gray-500">{{ $document->document_number }}</div>
<div class="text-xs text-gray-500 dark:text-gray-400">{{ $document->document_number }}</div>
@endif
@if($document->description)
<div class="text-xs text-gray-500 mt-1">{{ Str::limit($document->description, 60) }}</div>
<div class="text-xs text-gray-500 dark:text-gray-400 mt-1">{{ Str::limit($document->description, 60) }}</div>
@endif
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
{{ $document->category->icon }} {{ $document->category->name }}
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="inline-flex rounded-full px-2 py-1 text-xs font-semibold
@if($document->access_level === 'public') bg-green-100 text-green-800
@elseif($document->access_level === 'members') bg-blue-100 text-blue-800
@elseif($document->access_level === 'admin') bg-purple-100 text-purple-800
@else bg-gray-100 text-gray-800
@if($document->access_level === 'public') bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200
@elseif($document->access_level === 'members') bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200
@elseif($document->access_level === 'admin') bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200
@else bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-300
@endif">
{{ $document->getAccessLevelLabel() }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
<div>v{{ $document->currentVersion?->version_number ?? '—' }}</div>
<div class="text-xs text-gray-400"> {{ $document->version_count }} </div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
<div class="flex items-center space-x-3">
<span title="檢視次數">👁️ {{ $document->view_count }}</span>
<span title="下載次數">⬇️ {{ $document->download_count }}</span>
@@ -149,12 +149,12 @@
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="inline-flex rounded-full px-2 py-1 text-xs font-semibold
{{ $document->status === 'active' ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800' }}">
{{ $document->status === 'active' ? 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200' : 'bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-300' }}">
{{ $document->getStatusLabel() }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<a href="{{ route('admin.documents.show', $document) }}" class="text-indigo-600 hover:text-indigo-900">
<a href="{{ route('admin.documents.show', $document) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
查看
</a>
</td>
@@ -162,12 +162,12 @@
@empty
<tr>
<td colspan="7" class="px-6 py-12 text-center">
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<svg class="mx-auto h-12 w-12 text-gray-400 dark:text-gray-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<p class="mt-2 text-sm text-gray-500">尚無文件</p>
<p class="mt-1 text-sm text-gray-500">
<a href="{{ route('admin.documents.create') }}" class="text-indigo-600 hover:text-indigo-900">上傳第一個文件</a>
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">尚無文件</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
<a href="{{ route('admin.documents.create') }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">上傳第一個文件</a>
</p>
</td>
</tr>
@@ -176,7 +176,7 @@
</table>
@if($documents->hasPages())
<div class="px-6 py-4 border-t border-gray-200">
<div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700">
{{ $documents->links() }}
</div>
@endif

View File

@@ -1,24 +1,24 @@
<x-app-layout>
<x-slot name="header">
<div class="flex items-center justify-between">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ $document->title }}
</h2>
<div class="flex items-center space-x-2">
<a href="{{ route('admin.documents.edit', $document) }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<a href="{{ route('admin.documents.edit', $document) }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
編輯資訊
</a>
@if($document->status === 'active')
<form action="{{ route('admin.documents.archive', $document) }}" method="POST" class="inline">
@csrf
<button type="submit" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<button type="submit" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
封存
</button>
</form>
@else
<form action="{{ route('admin.documents.restore', $document) }}" method="POST" class="inline">
@csrf
<button type="submit" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<button type="submit" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
恢復
</button>
</form>
@@ -30,88 +30,94 @@
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-6">
@if (session('status'))
<div class="rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="rounded-md bg-green-50 dark:bg-green-900/50 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 p-4">
<p class="text-sm font-medium text-red-800">{{ session('error') }}</p>
<div class="rounded-md bg-red-50 dark:bg-red-900/50 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<!-- Document Info -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-6 py-5">
<h3 class="text-lg font-medium leading-6 text-gray-900">文件資訊</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">文件資訊</h3>
</div>
<div class="border-t border-gray-200 px-6 py-5">
<div class="border-t border-gray-200 dark:border-gray-700 px-6 py-5">
<dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500">類別</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->category->icon }} {{ $document->category->name }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">類別</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $document->category->icon }} {{ $document->category->name }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">文件編號</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->document_number ?? '—' }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">文件編號</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $document->document_number ?? '—' }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">存取權限</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">存取權限</dt>
<dd class="mt-1">
<span class="inline-flex rounded-full px-2 py-1 text-xs font-semibold
@if($document->access_level === 'public') bg-green-100 text-green-800
@elseif($document->access_level === 'members') bg-blue-100 text-blue-800
@elseif($document->access_level === 'admin') bg-purple-100 text-purple-800
@else bg-gray-100 text-gray-800
@if($document->access_level === 'public') bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200
@elseif($document->access_level === 'members') bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200
@elseif($document->access_level === 'admin') bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200
@else bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-300
@endif">
{{ $document->getAccessLevelLabel() }}
</span>
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">狀態</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">狀態</dt>
<dd class="mt-1">
<span class="inline-flex rounded-full px-2 py-1 text-xs font-semibold
{{ $document->status === 'active' ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800' }}">
{{ $document->status === 'active' ? 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200' : 'bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-300' }}">
{{ $document->getStatusLabel() }}
</span>
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">當前版本</dt>
<dd class="mt-1 text-sm text-gray-900">v{{ $document->currentVersion->version_number }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">當前版本</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
@if($document->currentVersion)
v{{ $document->currentVersion->version_number }}
@else
<span class="text-gray-400">尚無版本</span>
@endif
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">總版本數</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->version_count }} 個版本</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">總版本數</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $document->version_count }} 個版本</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">檢視 / 下載次數</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->view_count }} / {{ $document->download_count }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">檢視 / 下載次數</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $document->view_count }} / {{ $document->download_count }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">公開連結</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">公開連結</dt>
<dd class="mt-1 text-sm">
<a href="{{ $document->getPublicUrl() }}" target="_blank" class="text-indigo-600 hover:text-indigo-900">
<a href="{{ $document->getPublicUrl() }}" target="_blank" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
{{ $document->getPublicUrl() }}
</a>
</dd>
</div>
@if($document->description)
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500">說明</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->description }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">說明</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $document->description }}</dd>
</div>
@endif
<div>
<dt class="text-sm font-medium text-gray-500">建立者</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->createdBy->name }} · {{ $document->created_at->format('Y-m-d H:i') }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">建立者</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $document->createdBy->name }} · {{ $document->created_at->format('Y-m-d H:i') }}</dd>
</div>
@if($document->lastUpdatedBy)
<div>
<dt class="text-sm font-medium text-gray-500">最後更新</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->lastUpdatedBy->name }} · {{ $document->updated_at->format('Y-m-d H:i') }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">最後更新</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $document->lastUpdatedBy->name }} · {{ $document->updated_at->format('Y-m-d H:i') }}</dd>
</div>
@endif
</dl>
@@ -119,31 +125,31 @@
</div>
<!-- Upload New Version -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-6 py-5">
<h3 class="text-lg font-medium leading-6 text-gray-900">上傳新版本</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">上傳新版本</h3>
</div>
<div class="border-t border-gray-200 px-6 py-5">
<div class="border-t border-gray-200 dark:border-gray-700 px-6 py-5">
<form action="{{ route('admin.documents.upload-version', $document) }}" method="POST" enctype="multipart/form-data" class="space-y-4">
@csrf
<div>
<label for="file" class="block text-sm font-medium text-gray-700">選擇檔案 <span class="text-red-500">*</span></label>
<label for="file" class="block text-sm font-medium text-gray-700 dark:text-gray-300">選擇檔案 <span class="text-red-500 dark:text-red-400">*</span></label>
<input type="file" name="file" id="file" required
class="mt-1 block w-full text-sm text-gray-500
class="mt-1 block w-full text-sm text-gray-500 dark:text-gray-400
file:mr-4 file:py-2 file:px-4
file:rounded-md file:border-0
file:text-sm file:font-semibold
file:bg-indigo-50 file:text-indigo-700
hover:file:bg-indigo-100">
<p class="mt-1 text-sm text-gray-500">最大 10MB</p>
file:bg-indigo-50 dark:file:bg-indigo-900/50 file:text-indigo-700 dark:file:text-indigo-300
hover:file:bg-indigo-100 dark:hover:file:bg-indigo-800">
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">最大 10MB</p>
</div>
<div>
<label for="version_notes" class="block text-sm font-medium text-gray-700">版本說明 <span class="text-red-500">*</span></label>
<label for="version_notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">版本說明 <span class="text-red-500 dark:text-red-400">*</span></label>
<textarea name="version_notes" id="version_notes" rows="2" required placeholder="說明此版本的變更內容"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"></textarea>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900 dark:text-gray-300"></textarea>
</div>
<div class="flex justify-end">
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700">
<button type="submit" class="rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
上傳新版本
</button>
</div>
@@ -152,13 +158,13 @@
</div>
<!-- Version History -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-6 py-5">
<h3 class="text-lg font-medium leading-6 text-gray-900">版本歷史</h3>
<p class="mt-1 text-sm text-gray-600">所有版本永久保留,無法刪除</p>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">版本歷史</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">所有版本永久保留,無法刪除</p>
</div>
<div class="border-t border-gray-200">
<ul class="divide-y divide-gray-200">
<div class="border-t border-gray-200 dark:border-gray-700">
<ul class="divide-y divide-gray-200 dark:divide-gray-700">
@foreach($versionHistory as $history)
@php $version = $history['version']; @endphp
<li class="px-6 py-5">
@@ -168,15 +174,15 @@
<span class="text-2xl">{{ $version->getFileIcon() }}</span>
<div>
<div class="flex items-center space-x-2">
<span class="text-sm font-medium text-gray-900">版本 {{ $version->version_number }}</span>
<span class="text-sm font-medium text-gray-900 dark:text-gray-100">版本 {{ $version->version_number }}</span>
@if($version->is_current)
<span class="inline-flex rounded-full bg-green-100 px-2 py-1 text-xs font-semibold text-green-800">
<span class="inline-flex rounded-full bg-green-100 dark:bg-green-900 px-2 py-1 text-xs font-semibold text-green-800 dark:text-green-200">
當前版本
</span>
@endif
</div>
<div class="mt-1 text-sm text-gray-900">{{ $version->original_filename }}</div>
<div class="mt-1 flex items-center space-x-4 text-xs text-gray-500">
<div class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $version->original_filename }}</div>
<div class="mt-1 flex items-center space-x-4 text-xs text-gray-500 dark:text-gray-400">
<span>{{ $version->getFileSizeHuman() }}</span>
<span>{{ $version->uploadedBy->name }}</span>
<span>{{ $version->uploaded_at->format('Y-m-d H:i') }}</span>
@@ -185,17 +191,17 @@
@endif
</div>
@if($version->version_notes)
<div class="mt-2 text-sm text-gray-600">
<div class="mt-2 text-sm text-gray-600 dark:text-gray-400">
<span class="font-medium">變更說明:</span>{{ $version->version_notes }}
</div>
@endif
<div class="mt-2 flex items-center space-x-2 text-xs text-gray-500">
<div class="mt-2 flex items-center space-x-2 text-xs text-gray-500 dark:text-gray-400">
<span>檔案雜湊:</span>
<code class="px-2 py-1 bg-gray-100 rounded">{{ substr($version->file_hash, 0, 16) }}...</code>
<code class="px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded">{{ substr($version->file_hash, 0, 16) }}...</code>
@if($version->verifyIntegrity())
<span class="text-green-600"> 完整</span>
<span class="text-green-600 dark:text-green-400"> 完整</span>
@else
<span class="text-red-600"> 損壞</span>
<span class="text-red-600 dark:text-red-400"> 損壞</span>
@endif
</div>
</div>
@@ -203,13 +209,13 @@
</div>
<div class="ml-6 flex flex-col space-y-2">
<a href="{{ route('admin.documents.download-version', [$document, $version]) }}"
class="inline-flex items-center rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
下載
</a>
@if(!$version->is_current)
<form action="{{ route('admin.documents.promote-version', [$document, $version]) }}" method="POST">
@csrf
<button type="submit" class="w-full inline-flex items-center justify-center rounded-md border border-indigo-300 bg-indigo-50 px-3 py-2 text-sm font-medium text-indigo-700 hover:bg-indigo-100"
<button type="submit" class="w-full inline-flex items-center justify-center rounded-md border border-indigo-300 dark:border-indigo-700 bg-indigo-50 dark:bg-indigo-900/50 px-3 py-2 text-sm font-medium text-indigo-700 dark:text-indigo-300 hover:bg-indigo-100 dark:hover:bg-indigo-800"
onclick="return confirm('確定要將此版本設為當前版本嗎?');">
設為當前
</button>
@@ -224,48 +230,48 @@
</div>
<!-- Access Logs -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-6 py-5">
<h3 class="text-lg font-medium leading-6 text-gray-900">存取記錄</h3>
<p class="mt-1 text-sm text-gray-600">最近 20 </p>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">存取記錄</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">最近 20 </p>
</div>
<div class="border-t border-gray-200">
<div class="border-t border-gray-200 dark:border-gray-700">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">時間</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">使用者</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">動作</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">IP</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">瀏覽器</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">時間</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">使用者</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">動作</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">IP</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">瀏覽器</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse($document->accessLogs->take(20) as $log)
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
{{ $log->accessed_at->format('Y-m-d H:i:s') }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-gray-100">
{{ $log->getUserDisplay() }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">
<span class="inline-flex rounded-full px-2 py-1 text-xs font-semibold
{{ $log->action === 'view' ? 'bg-blue-100 text-blue-800' : 'bg-green-100 text-green-800' }}">
{{ $log->action === 'view' ? 'bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200' : 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200' }}">
{{ $log->getActionLabel() }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
{{ $log->ip_address }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
{{ $log->getBrowser() }}
</td>
</tr>
@empty
<tr>
<td colspan="5" class="px-6 py-4 text-center text-sm text-gray-500">
<td colspan="5" class="px-6 py-4 text-center text-sm text-gray-500 dark:text-gray-400">
尚無存取記錄
</td>
</tr>

View File

@@ -1,27 +1,26 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('New Finance Document') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
新增報銷單
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="POST" action="{{ route('admin.finance.store') }}" enctype="multipart/form-data" class="space-y-6" aria-label="{{ __('Finance document submission form') }}">
<form method="POST" action="{{ route('admin.finance.store') }}" enctype="multipart/form-data" class="space-y-6" aria-label="報銷單提交表單">
@csrf
<div>
<label for="member_id" class="block text-sm font-medium text-gray-700">
{{ __('Member (optional)') }}
<label for="member_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
會員(選填)
</label>
<select
name="member_id"
id="member_id"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
<option value="">{{ __('Not linked to a member') }}</option>
<option value="">未連結會員</option>
@foreach ($members as $member)
<option value="{{ $member->id }}" @selected(old('member_id') == $member->id)>
{{ $member->full_name }}
@@ -29,83 +28,89 @@
@endforeach
</select>
@error('member_id')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="title" class="block text-sm font-medium text-gray-700">
{{ __('Title') }}
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
標題
</label>
<input
type="text"
name="title"
id="title"
value="{{ old('title') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
@error('title')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="amount" class="block text-sm font-medium text-gray-700">
{{ __('Amount') }}
<label for="amount" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
金額 <span class="text-red-500">*</span>
</label>
<input
type="number"
step="0.01"
name="amount"
id="amount"
value="{{ old('amount') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
>
<div class="relative mt-1">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<span class="text-gray-500 dark:text-gray-400 sm:text-sm">NT$</span>
</div>
<input
type="number"
step="0.01"
name="amount"
id="amount"
value="{{ old('amount') }}"
class="block w-full rounded-md border-gray-300 dark:border-gray-700 pl-12 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
</div>
@error('amount')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="description" class="block text-sm font-medium text-gray-700">
{{ __('Description') }}
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
描述
</label>
<textarea
name="description"
id="description"
rows="4"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>{{ old('description') }}</textarea>
@error('description')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="attachment" class="block text-sm font-medium text-gray-700">
{{ __('Attachment (optional)') }}
<label for="attachment" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
附件(選填)
</label>
<input
type="file"
name="attachment"
id="attachment"
class="mt-1 block w-full text-sm text-gray-900 border border-gray-300 rounded-md cursor-pointer focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"
class="mt-1 block w-full text-sm text-gray-900 dark:text-gray-300 border border-gray-300 dark:border-gray-700 rounded-md cursor-pointer focus:outline-none focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:border-indigo-500 dark:bg-gray-900"
>
@error('attachment')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
<p class="mt-1 text-sm text-gray-500">
{{ __('Max file size: 10MB') }}
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
最大檔案大小10MB
</p>
</div>
<div class="flex justify-end gap-3">
<a href="{{ route('admin.finance.index') }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Cancel') }}
<a href="{{ route('admin.finance.index') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-900 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
取消
</a>
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Submit Document') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white dark:text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
提交文件
</button>
</div>
</form>

View File

@@ -1,82 +1,179 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Finance Documents') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
報銷申請單
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-4">
@if (session('status'))
<div class="rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
<div class="flex justify-end">
<a href="{{ route('admin.finance.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('New Document') }}
<div class="flex justify-between items-center">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">報銷單列表</h3>
<a href="{{ route('admin.finance.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<svg class="mr-2 h-4 w-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 class="bg-white shadow sm:rounded-lg">
{{-- Filters --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="GET" action="{{ route('admin.finance.index') }}" class="grid grid-cols-1 gap-4 sm:grid-cols-4">
{{-- 審核狀態篩選 --}}
<div>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">審核狀態</label>
<select name="status" id="status" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部狀態</option>
<option value="pending" @selected(request('status') == 'pending')>待審核</option>
<option value="approved_secretary" @selected(request('status') == 'approved_secretary')>秘書長已核准</option>
<option value="approved_chair" @selected(request('status') == 'approved_chair')>理事長已核准</option>
<option value="approved_board" @selected(request('status') == 'approved_board')>董理事會已核准</option>
<option value="rejected" @selected(request('status') == 'rejected')>已駁回</option>
</select>
</div>
{{-- 工作流程階段篩選 --}}
<div>
<label for="workflow_stage" class="block text-sm font-medium text-gray-700 dark:text-gray-300">工作流程階段</label>
<select name="workflow_stage" id="workflow_stage" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部階段</option>
<option value="approval" @selected(request('workflow_stage') == 'approval')>審核階段</option>
<option value="payment" @selected(request('workflow_stage') == 'payment')>出帳階段</option>
<option value="recording" @selected(request('workflow_stage') == 'recording')>入帳階段</option>
<option value="completed" @selected(request('workflow_stage') == 'completed')>已完成</option>
</select>
</div>
{{-- 金額級別篩選 --}}
<div>
<label for="amount_tier" class="block text-sm font-medium text-gray-700 dark:text-gray-300">金額級別</label>
<select name="amount_tier" id="amount_tier" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部級別</option>
<option value="small" @selected(request('amount_tier') == 'small')>小額 (< 5,000)</option>
<option value="medium" @selected(request('amount_tier') == 'medium')>中額 (5,000-50,000)</option>
<option value="large" @selected(request('amount_tier') == 'large')>大額 (> 50,000)</option>
</select>
</div>
{{-- 篩選按鈕 --}}
<div class="flex items-end space-x-2">
<button type="submit" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
篩選
</button>
<a href="{{ route('admin.finance.index') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
重設
</a>
</div>
</form>
</div>
</div>
{{-- Table --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200" role="table">
<thead class="bg-gray-50">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700" role="table">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
{{ __('Title') }}
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
標題
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
{{ __('Member') }}
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
申請人
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
{{ __('Amount') }}
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
金額
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
{{ __('Status') }}
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
審核狀態
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
{{ __('Submitted At') }}
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
工作流程
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">
<span class="sr-only">{{ __('View') }}</span>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
提交時間
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
<span class="sr-only">操作</span>
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse ($documents as $document)
<tr>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900">
{{ $document->title }}
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
<div class="font-medium">{{ $document->title }}</div>
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900">
{{ $document->member?->full_name ?? __('N/A') }}
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ $document->submittedBy?->name ?? '不適用' }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900">
@if (! is_null($document->amount))
{{ number_format($document->amount, 2) }}
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
<div>NT$ {{ number_format($document->amount, 2) }}</div>
<div class="text-xs text-gray-500 dark:text-gray-400">{{ $document->getAmountTierText() }}</div>
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm">
@if ($document->isRejected())
<span class="inline-flex rounded-full bg-red-100 dark:bg-red-900 px-2 text-xs font-semibold leading-5 text-red-800 dark:text-red-200">
{{ $document->status_label }}
</span>
@elseif ($document->isApprovalComplete())
<span class="inline-flex rounded-full bg-green-100 dark:bg-green-900 px-2 text-xs font-semibold leading-5 text-green-800 dark:text-green-200">
{{ $document->status_label }}
</span>
@else
{{ __('N/A') }}
<span class="inline-flex rounded-full bg-yellow-100 dark:bg-yellow-900 px-2 text-xs font-semibold leading-5 text-yellow-800 dark:text-yellow-200">
{{ $document->status_label }}
</span>
@endif
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900">
{{ ucfirst($document->status) }}
<td class="whitespace-nowrap px-4 py-3 text-sm">
@if ($document->isRejected())
<span class="inline-flex rounded-full bg-red-100 dark:bg-red-900 px-2 text-xs font-semibold leading-5 text-red-800 dark:text-red-200">
已駁回
</span>
@elseif ($document->isRecordingComplete())
<span class="inline-flex rounded-full bg-green-100 dark:bg-green-900 px-2 text-xs font-semibold leading-5 text-green-800 dark:text-green-200">
已完成
</span>
@elseif ($document->isDisbursementComplete())
<span class="inline-flex rounded-full bg-blue-100 dark:bg-blue-900 px-2 text-xs font-semibold leading-5 text-blue-800 dark:text-blue-200">
入帳階段
</span>
@elseif ($document->isApprovalComplete())
<span class="inline-flex rounded-full bg-purple-100 dark:bg-purple-900 px-2 text-xs font-semibold leading-5 text-purple-800 dark:text-purple-200">
出帳階段
</span>
@else
<span class="inline-flex rounded-full bg-gray-100 dark:bg-gray-700 px-2 text-xs font-semibold leading-5 text-gray-800 dark:text-gray-200">
審核階段
</span>
@endif
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900">
{{ optional($document->submitted_at)->toDateString() }}
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ optional($document->submitted_at)->format('Y-m-d') }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-right text-sm">
<a href="{{ route('admin.finance.show', $document) }}" class="text-indigo-600 hover:text-indigo-900">
{{ __('View') }}
<a href="{{ route('admin.finance.show', $document) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
檢視
</a>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="px-4 py-4 text-sm text-gray-500">
{{ __('No finance documents found.') }}
<td colspan="7" class="px-4 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<p class="mt-2 text-sm font-semibold">找不到報銷申請單</p>
<p class="mt-1 text-sm">點選「新增報銷單」開始建立。</p>
</td>
</tr>
@endforelse
@@ -92,4 +189,3 @@
</div>
</div>
</x-app-layout>

View File

@@ -1,11 +1,11 @@
<x-app-layout>
<x-slot name="header">
<div class="flex items-center justify-between">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Finance Document Details') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
報銷申請單詳情
</h2>
<a href="{{ route('admin.finance.index') }}" class="text-sm text-indigo-600 hover:text-indigo-900">
&larr; {{ __('Back to list') }}
<a href="{{ route('admin.finance.index') }}" class="text-sm text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
&larr; 返回列表
</a>
</div>
</x-slot>
@@ -14,39 +14,82 @@
<div class="mx-auto max-w-4xl sm:px-6 lg:px-8 space-y-6">
{{-- Status Message --}}
@if (session('status'))
<div class="rounded-md bg-green-50 p-4" role="status" aria-live="polite">
<p class="text-sm font-medium text-green-800">
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4" role="status" aria-live="polite">
<p class="text-sm font-medium text-green-800 dark:text-green-200">
{{ session('status') }}
</p>
</div>
@endif
{{-- Document Details --}}
<div class="bg-white shadow sm:rounded-lg">
{{-- Workflow Stage Overview --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">
{{ __('Document Information') }}
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">
工作流程階段
</h3>
<span class="inline-flex rounded-full px-3 py-1 text-sm font-semibold
@if ($document->isRejected())
bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200
@elseif ($document->isRecordingComplete())
bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200
@else
bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200
@endif
">
{{ $document->workflow_stage_label }}
</span>
</div>
{{-- Stage Progress Bar --}}
<div class="flex items-center space-x-2">
{{-- 審核階段 --}}
<div class="flex-1 text-center">
<div class="h-2 rounded-full {{ $document->isApprovalComplete() || $document->isRejected() ? 'bg-green-500' : 'bg-gray-200 dark:bg-gray-700' }}"></div>
<span class="text-xs text-gray-500 dark:text-gray-400 mt-1">審核</span>
</div>
<div class="w-4 text-gray-400"></div>
{{-- 出帳階段 --}}
<div class="flex-1 text-center">
<div class="h-2 rounded-full {{ $document->isDisbursementComplete() ? 'bg-green-500' : ($document->isApprovalComplete() && !$document->isRejected() ? 'bg-yellow-500' : 'bg-gray-200 dark:bg-gray-700') }}"></div>
<span class="text-xs text-gray-500 dark:text-gray-400 mt-1">出帳</span>
</div>
<div class="w-4 text-gray-400"></div>
{{-- 入帳階段 --}}
<div class="flex-1 text-center">
<div class="h-2 rounded-full {{ $document->isRecordingComplete() ? 'bg-green-500' : ($document->isDisbursementComplete() ? 'bg-yellow-500' : 'bg-gray-200 dark:bg-gray-700') }}"></div>
<span class="text-xs text-gray-500 dark:text-gray-400 mt-1">入帳</span>
</div>
</div>
</div>
</div>
{{-- Document Details --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">
報銷單資訊
</h3>
<dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500">{{ __('Title') }}</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->title }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">標題</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $document->title }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">{{ __('Status') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">審核狀態</dt>
<dd class="mt-1">
@if ($document->isRejected())
<span class="inline-flex rounded-full bg-red-100 px-2 text-xs font-semibold leading-5 text-red-800">
<span class="inline-flex rounded-full bg-red-100 dark:bg-red-900 px-2 text-xs font-semibold leading-5 text-red-800 dark:text-red-200">
{{ $document->status_label }}
</span>
@elseif ($document->isFullyApproved())
<span class="inline-flex rounded-full bg-green-100 px-2 text-xs font-semibold leading-5 text-green-800">
@elseif ($document->isApprovalComplete())
<span class="inline-flex rounded-full bg-green-100 dark:bg-green-900 px-2 text-xs font-semibold leading-5 text-green-800 dark:text-green-200">
{{ $document->status_label }}
</span>
@else
<span class="inline-flex rounded-full bg-yellow-100 px-2 text-xs font-semibold leading-5 text-yellow-800">
<span class="inline-flex rounded-full bg-yellow-100 dark:bg-yellow-900 px-2 text-xs font-semibold leading-5 text-yellow-800 dark:text-yellow-200">
{{ $document->status_label }}
</span>
@endif
@@ -54,52 +97,47 @@
</div>
<div>
<dt class="text-sm font-medium text-gray-500">{{ __('Member') }}</dt>
<dd class="mt-1 text-sm text-gray-900">
@if ($document->member)
<a href="{{ route('admin.members.show', $document->member) }}" class="text-indigo-600 hover:text-indigo-900">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">金額</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
NT$ {{ number_format($document->amount, 2) }}
<span class="text-xs text-gray-500 dark:text-gray-400 ml-1">({{ $document->getAmountTierText() }})</span>
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">申請人</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $document->submittedBy?->name ?? '不適用' }}
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">提交時間</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $document->submitted_at?->format('Y-m-d H:i:s') ?? '不適用' }}
</dd>
</div>
@if ($document->member)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">關聯會員</dt>
<dd class="mt-1 text-sm">
<a href="{{ route('admin.members.show', $document->member) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
{{ $document->member->full_name }}
</a>
@else
<span class="text-gray-500">{{ __('Not linked to a member') }}</span>
@endif
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">{{ __('Amount') }}</dt>
<dd class="mt-1 text-sm text-gray-900">
@if (!is_null($document->amount))
${{ number_format($document->amount, 2) }}
@else
<span class="text-gray-500">{{ __('N/A') }}</span>
@endif
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">{{ __('Submitted by') }}</dt>
<dd class="mt-1 text-sm text-gray-900">
{{ $document->submittedBy?->name ?? __('N/A') }}
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">{{ __('Submitted at') }}</dt>
<dd class="mt-1 text-sm text-gray-900">
{{ $document->submitted_at?->format('Y-m-d H:i:s') ?? __('N/A') }}
</dd>
</div>
</dd>
</div>
@endif
@if ($document->attachment_path)
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500">{{ __('Attachment') }}</dt>
<dd class="mt-1 text-sm text-gray-900">
<a href="{{ route('admin.finance.download', $document) }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">附件</dt>
<dd class="mt-1 text-sm">
<a href="{{ route('admin.finance.download', $document) }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
{{ __('Download Attachment') }}
下載附件
</a>
</dd>
</div>
@@ -107,57 +145,59 @@
@if ($document->description)
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500">{{ __('Description') }}</dt>
<dd class="mt-1 whitespace-pre-line text-sm text-gray-900">
{{ $document->description }}
</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">描述</dt>
<dd class="mt-1 whitespace-pre-line text-sm text-gray-900 dark:text-gray-100">{{ $document->description }}</dd>
</div>
@endif
</dl>
</div>
</div>
{{-- Approval Timeline --}}
<div class="bg-white shadow sm:rounded-lg">
{{-- Approval Timeline (新工作流程) --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">
{{ __('Approval Timeline') }}
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">
審核時程
</h3>
<div class="flow-root">
<ul role="list" class="-mb-8">
{{-- Cashier Approval --}}
{{-- 秘書長審核 (第一階段) --}}
<li>
<div class="relative pb-8">
<span class="absolute left-4 top-4 -ml-px h-full w-0.5 bg-gray-200" aria-hidden="true"></span>
<span class="absolute left-4 top-4 -ml-px h-full w-0.5 bg-gray-200 dark:bg-gray-700" aria-hidden="true"></span>
<div class="relative flex space-x-3">
<div>
@if ($document->cashier_approved_at)
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-green-500 ring-8 ring-white">
@if ($document->secretary_approved_at)
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-green-500 ring-8 ring-white dark:ring-gray-800">
<svg class="h-5 w-5 text-white" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
</span>
@elseif ($document->status === 'pending')
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-yellow-500 ring-8 ring-white dark:ring-gray-800">
<span class="h-2.5 w-2.5 rounded-full bg-white"></span>
</span>
@else
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-gray-400 ring-8 ring-white">
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-gray-400 dark:bg-gray-600 ring-8 ring-white dark:ring-gray-800">
<span class="h-2.5 w-2.5 rounded-full bg-white"></span>
</span>
@endif
</div>
<div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
<div>
<p class="text-sm text-gray-900">
{{ __('Cashier Approval') }}
@if ($document->cashier_approved_at)
<span class="font-medium text-gray-900">{{ $document->approvedByCashier?->name }}</span>
<p class="text-sm text-gray-900 dark:text-gray-100">
秘書長核准
@if ($document->secretary_approved_at)
<span class="font-medium">{{ $document->approvedBySecretary?->name }}</span>
@endif
</p>
</div>
<div class="whitespace-nowrap text-right text-sm text-gray-500">
@if ($document->cashier_approved_at)
{{ $document->cashier_approved_at->format('Y-m-d H:i') }}
<div class="whitespace-nowrap text-right text-sm text-gray-500 dark:text-gray-400">
@if ($document->secretary_approved_at)
{{ $document->secretary_approved_at->format('Y-m-d H:i') }}
@else
{{ __('Pending') }}
待處理
@endif
</div>
</div>
@@ -165,90 +205,102 @@
</div>
</li>
{{-- Accountant Approval --}}
<li>
<div class="relative pb-8">
<span class="absolute left-4 top-4 -ml-px h-full w-0.5 bg-gray-200" aria-hidden="true"></span>
<div class="relative flex space-x-3">
<div>
@if ($document->accountant_approved_at)
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-green-500 ring-8 ring-white">
<svg class="h-5 w-5 text-white" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
</span>
@else
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-gray-400 ring-8 ring-white">
<span class="h-2.5 w-2.5 rounded-full bg-white"></span>
</span>
@endif
</div>
<div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
{{-- 理事長審核 (第二階段:中額以上) --}}
@if (in_array($document->amount_tier, ['medium', 'large']))
<li>
<div class="relative pb-8">
<span class="absolute left-4 top-4 -ml-px h-full w-0.5 bg-gray-200 dark:bg-gray-700" aria-hidden="true"></span>
<div class="relative flex space-x-3">
<div>
<p class="text-sm text-gray-900">
{{ __('Accountant Approval') }}
@if ($document->accountant_approved_at)
<span class="font-medium text-gray-900">{{ $document->approvedByAccountant?->name }}</span>
@endif
</p>
</div>
<div class="whitespace-nowrap text-right text-sm text-gray-500">
@if ($document->accountant_approved_at)
{{ $document->accountant_approved_at->format('Y-m-d H:i') }}
@else
{{ __('Pending') }}
@endif
</div>
</div>
</div>
</div>
</li>
{{-- Chair Approval --}}
<li>
<div class="relative pb-8">
<div class="relative flex space-x-3">
<div>
@if ($document->chair_approved_at)
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-green-500 ring-8 ring-white">
<svg class="h-5 w-5 text-white" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
</span>
@else
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-gray-400 ring-8 ring-white">
<span class="h-2.5 w-2.5 rounded-full bg-white"></span>
</span>
@endif
</div>
<div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
<div>
<p class="text-sm text-gray-900">
{{ __('Chair Approval') }}
@if ($document->chair_approved_at)
<span class="font-medium text-gray-900">{{ $document->approvedByChair?->name }}</span>
@endif
</p>
</div>
<div class="whitespace-nowrap text-right text-sm text-gray-500">
@if ($document->chair_approved_at)
{{ $document->chair_approved_at->format('Y-m-d H:i') }}
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-green-500 ring-8 ring-white dark:ring-gray-800">
<svg class="h-5 w-5 text-white" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
</span>
@elseif ($document->status === 'approved_secretary')
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-yellow-500 ring-8 ring-white dark:ring-gray-800">
<span class="h-2.5 w-2.5 rounded-full bg-white"></span>
</span>
@else
{{ __('Pending') }}
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-gray-400 dark:bg-gray-600 ring-8 ring-white dark:ring-gray-800">
<span class="h-2.5 w-2.5 rounded-full bg-white"></span>
</span>
@endif
</div>
<div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
<div>
<p class="text-sm text-gray-900 dark:text-gray-100">
理事長核准
@if ($document->chair_approved_at)
<span class="font-medium">{{ $document->approvedByChair?->name }}</span>
@endif
</p>
</div>
<div class="whitespace-nowrap text-right text-sm text-gray-500 dark:text-gray-400">
@if ($document->chair_approved_at)
{{ $document->chair_approved_at->format('Y-m-d H:i') }}
@else
待處理
@endif
</div>
</div>
</div>
</div>
</div>
</li>
</li>
@endif
{{-- Rejection Info --}}
{{-- 董理事會審核 (第三階段:大額) --}}
@if ($document->amount_tier === 'large')
<li>
<div class="relative pb-8">
<div class="relative flex space-x-3">
<div>
@if ($document->board_meeting_approved_at)
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-green-500 ring-8 ring-white dark:ring-gray-800">
<svg class="h-5 w-5 text-white" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
</span>
@elseif ($document->status === 'approved_chair')
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-yellow-500 ring-8 ring-white dark:ring-gray-800">
<span class="h-2.5 w-2.5 rounded-full bg-white"></span>
</span>
@else
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-gray-400 dark:bg-gray-600 ring-8 ring-white dark:ring-gray-800">
<span class="h-2.5 w-2.5 rounded-full bg-white"></span>
</span>
@endif
</div>
<div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
<div>
<p class="text-sm text-gray-900 dark:text-gray-100">
董理事會核准
@if ($document->board_meeting_approved_at)
<span class="font-medium">{{ $document->approvedByBoardMeeting?->title ?? '理事會決議' }}</span>
@endif
</p>
</div>
<div class="whitespace-nowrap text-right text-sm text-gray-500 dark:text-gray-400">
@if ($document->board_meeting_approved_at)
{{ $document->board_meeting_approved_at->format('Y-m-d H:i') }}
@else
待處理
@endif
</div>
</div>
</div>
</div>
</li>
@endif
{{-- 駁回資訊 --}}
@if ($document->isRejected())
<li>
<div class="relative">
<div class="relative flex space-x-3">
<div>
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-red-500 ring-8 ring-white">
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-red-500 ring-8 ring-white dark:ring-gray-800">
<svg class="h-5 w-5 text-white" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
@@ -256,17 +308,17 @@
</div>
<div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
<div class="flex-1">
<p class="text-sm text-gray-900">
{{ __('Rejected by') }}
<span class="font-medium text-gray-900">{{ $document->rejectedBy?->name }}</span>
<p class="text-sm text-gray-900 dark:text-gray-100">
駁回者
<span class="font-medium">{{ $document->rejectedBy?->name }}</span>
</p>
@if ($document->rejection_reason)
<p class="mt-2 text-sm text-red-600">
<strong>{{ __('Reason:') }}</strong> {{ $document->rejection_reason }}
<p class="mt-2 text-sm text-red-600 dark:text-red-400">
<strong>原因:</strong> {{ $document->rejection_reason }}
</p>
@endif
</div>
<div class="whitespace-nowrap text-right text-sm text-gray-500">
<div class="whitespace-nowrap text-right text-sm text-gray-500 dark:text-gray-400">
{{ $document->rejected_at?->format('Y-m-d H:i') }}
</div>
</div>
@@ -279,23 +331,150 @@
</div>
</div>
{{-- Approval Actions --}}
@if (!$document->isRejected() && !$document->isFullyApproved())
<div class="bg-white shadow sm:rounded-lg">
{{-- 出帳確認區塊 --}}
@if ($document->isApprovalComplete() && !$document->isRejected())
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">
{{ __('Actions') }}
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">
出帳確認
<span class="ml-2 text-sm font-normal text-gray-500 dark:text-gray-400">(需申請人與出納雙重確認)</span>
</h3>
<div class="space-y-4">
{{-- 申請人確認狀態 --}}
<div class="flex items-center justify-between p-4 rounded-lg {{ $document->requester_confirmed_at ? 'bg-green-50 dark:bg-green-900/30' : 'bg-gray-50 dark:bg-gray-700' }}">
<div class="flex items-center">
@if ($document->requester_confirmed_at)
<svg class="h-5 w-5 text-green-500 mr-3" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
@else
<span class="h-5 w-5 rounded-full border-2 border-gray-300 dark:border-gray-500 mr-3"></span>
@endif
<div>
<p class="text-sm font-medium text-gray-900 dark:text-gray-100">申請人確認領款</p>
@if ($document->requester_confirmed_at)
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ $document->requesterConfirmedBy?->name }} - {{ $document->requester_confirmed_at->format('Y-m-d H:i') }}
</p>
@endif
</div>
</div>
@if (!$document->requester_confirmed_at && $document->canRequesterConfirmDisbursement(auth()->user()))
<form method="POST" action="{{ route('admin.finance.confirm-disbursement', $document) }}">
@csrf
<button type="submit" class="inline-flex items-center rounded-md bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700">
確認已領款
</button>
</form>
@endif
</div>
{{-- 出納確認狀態 --}}
<div class="flex items-center justify-between p-4 rounded-lg {{ $document->cashier_confirmed_at ? 'bg-green-50 dark:bg-green-900/30' : 'bg-gray-50 dark:bg-gray-700' }}">
<div class="flex items-center">
@if ($document->cashier_confirmed_at)
<svg class="h-5 w-5 text-green-500 mr-3" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
@else
<span class="h-5 w-5 rounded-full border-2 border-gray-300 dark:border-gray-500 mr-3"></span>
@endif
<div>
<p class="text-sm font-medium text-gray-900 dark:text-gray-100">出納確認出帳</p>
@if ($document->cashier_confirmed_at)
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ $document->cashierConfirmedBy?->name }} - {{ $document->cashier_confirmed_at->format('Y-m-d H:i') }}
</p>
@endif
</div>
</div>
@if (!$document->cashier_confirmed_at && $document->canCashierConfirmDisbursement() && (auth()->user()->hasRole('finance_cashier') || auth()->user()->hasRole('admin')))
<form method="POST" action="{{ route('admin.finance.confirm-disbursement', $document) }}">
@csrf
<button type="submit" class="inline-flex items-center rounded-md bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700">
確認已出帳
</button>
</form>
@endif
</div>
{{-- 出帳狀態摘要 --}}
<div class="text-center text-sm {{ $document->isDisbursementComplete() ? 'text-green-600 dark:text-green-400' : 'text-gray-500 dark:text-gray-400' }}">
@if ($document->isDisbursementComplete())
出帳確認完成
@else
{{ $document->disbursement_status_label }}
@endif
</div>
</div>
</div>
</div>
@endif
{{-- 入帳確認區塊 --}}
@if ($document->isDisbursementComplete())
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">
入帳確認
</h3>
<div class="flex items-center justify-between p-4 rounded-lg {{ $document->accountant_recorded_at ? 'bg-green-50 dark:bg-green-900/30' : 'bg-gray-50 dark:bg-gray-700' }}">
<div class="flex items-center">
@if ($document->accountant_recorded_at)
<svg class="h-5 w-5 text-green-500 mr-3" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
@else
<span class="h-5 w-5 rounded-full border-2 border-gray-300 dark:border-gray-500 mr-3"></span>
@endif
<div>
<p class="text-sm font-medium text-gray-900 dark:text-gray-100">會計確認入帳</p>
@if ($document->accountant_recorded_at)
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ $document->accountantRecordedBy?->name }} - {{ $document->accountant_recorded_at->format('Y-m-d H:i') }}
</p>
@endif
</div>
</div>
@if ($document->canAccountantConfirmRecording() && (auth()->user()->hasRole('finance_accountant') || auth()->user()->hasRole('admin')))
<form method="POST" action="{{ route('admin.finance.confirm-recording', $document) }}">
@csrf
<button type="submit" class="inline-flex items-center rounded-md bg-green-600 px-3 py-2 text-sm font-medium text-white hover:bg-green-700">
確認入帳
</button>
</form>
@endif
</div>
</div>
</div>
@endif
{{-- Approval Actions (審核中才顯示) --}}
@if (!$document->isRejected() && !$document->isApprovalComplete())
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">
審核操作
</h3>
<div class="flex gap-3">
{{-- Approve Button --}}
@php
$canApprove = false;
if (auth()->user()->hasRole('cashier') && $document->canBeApprovedByCashier()) {
$isAdmin = auth()->user()->hasRole('admin');
$isSecretary = auth()->user()->hasRole('secretary_general');
$isChair = auth()->user()->hasRole('finance_chair');
$isBoardMember = auth()->user()->hasRole('finance_board_member');
if ($isAdmin && !$document->isApprovalComplete() && !$document->isRejected()) {
$canApprove = true;
} elseif (auth()->user()->hasRole('accountant') && $document->canBeApprovedByAccountant()) {
} elseif ($isSecretary && $document->canBeApprovedBySecretary(auth()->user())) {
$canApprove = true;
} elseif (auth()->user()->hasRole('chair') && $document->canBeApprovedByChair()) {
} elseif ($isChair && $document->canBeApprovedByChair(auth()->user())) {
$canApprove = true;
} elseif ($isBoardMember && $document->canBeApprovedByBoard(auth()->user())) {
$canApprove = true;
}
@endphp
@@ -307,18 +486,21 @@
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
{{ __('Approve') }}
核准
@if ($isAdmin)
<span class="ml-1 text-xs opacity-75">(管理員)</span>
@endif
</button>
</form>
@endif
{{-- Reject Button (show for cashier, accountant, chair) --}}
@if (auth()->user()->hasRole('cashier') || auth()->user()->hasRole('accountant') || auth()->user()->hasRole('chair'))
{{-- Reject Button --}}
@if (auth()->user()->hasRole('admin') || auth()->user()->hasRole('secretary_general') || auth()->user()->hasRole('finance_chair'))
<button type="button" onclick="document.getElementById('rejectModal').classList.remove('hidden')" class="inline-flex items-center rounded-md border border-transparent bg-red-600 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
{{ __('Reject') }}
駁回
</button>
@endif
</div>
@@ -331,43 +513,43 @@
{{-- Rejection Modal --}}
<div id="rejectModal" class="fixed inset-0 z-10 hidden overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
<div class="flex min-h-screen items-end justify-center px-4 pb-20 pt-4 text-center sm:block sm:p-0">
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" onclick="document.getElementById('rejectModal').classList.add('hidden')"></div>
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 dark:bg-gray-900 dark:bg-opacity-75 transition-opacity" onclick="document.getElementById('rejectModal').classList.add('hidden')"></div>
<div class="inline-block transform overflow-hidden rounded-lg bg-white text-left align-bottom shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:align-middle">
<div class="inline-block transform overflow-hidden rounded-lg bg-white dark:bg-gray-800 text-left align-bottom shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:align-middle">
<form method="POST" action="{{ route('admin.finance.reject', $document) }}">
@csrf
<div class="bg-white px-4 pb-4 pt-5 sm:p-6 sm:pb-4">
<div class="bg-white dark:bg-gray-800 px-4 pb-4 pt-5 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
<svg class="h-6 w-6 text-red-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<div class="mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-red-100 dark:bg-red-900 sm:mx-0 sm:h-10 sm:w-10">
<svg class="h-6 w-6 text-red-600 dark:text-red-200" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
</svg>
</div>
<div class="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left flex-1">
<h3 class="text-base font-semibold leading-6 text-gray-900" id="modal-title">
{{ __('Reject Document') }}
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-gray-100" id="modal-title">
駁回報銷單
</h3>
<div class="mt-4">
<label for="rejection_reason" class="block text-sm font-medium text-gray-700">
{{ __('Rejection Reason') }}
<label for="rejection_reason" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
駁回原因
</label>
<textarea
name="rejection_reason"
id="rejection_reason"
rows="4"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-red-500 focus:ring-red-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-red-500 focus:ring-red-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
></textarea>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6 gap-3">
<div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6 gap-3">
<button type="submit" class="inline-flex w-full justify-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 sm:w-auto">
{{ __('Reject') }}
駁回
</button>
<button type="button" onclick="document.getElementById('rejectModal').classList.add('hidden')" class="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto">
{{ __('Cancel') }}
<button type="button" onclick="document.getElementById('rejectModal').classList.add('hidden')" class="mt-3 inline-flex w-full justify-center rounded-md bg-white dark:bg-gray-700 px-3 py-2 text-sm font-semibold text-gray-900 dark:text-gray-100 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 sm:mt-0 sm:w-auto">
取消
</button>
</div>
</form>

View File

@@ -0,0 +1,270 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
總分類帳
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-6">
<!-- Filter Form -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="GET" action="{{ route('admin.general-ledger.index') }}" class="space-y-4">
<div class="grid grid-cols-1 gap-4 sm:grid-cols-4">
<!-- Account Selection -->
<div class="sm:col-span-2">
<label for="account_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
科目
</label>
<select name="account_id" id="account_id"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
<option value="">請選擇科目</option>
@foreach($accounts as $account)
<option value="{{ $account->id }}" @selected(request('account_id') == $account->id)>
{{ $account->account_code }} - {{ $account->account_name_zh }}
</option>
@endforeach
</select>
</div>
<!-- Start Date -->
<div>
<label for="start_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
開始日期
</label>
<input type="date" name="start_date" id="start_date" value="{{ $startDate }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
<!-- End Date -->
<div>
<label for="end_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
結束日期
</label>
<input type="date" name="end_date" id="end_date" value="{{ $endDate }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
</div>
<div class="flex gap-4">
<button type="submit" class="inline-flex justify-center rounded-md bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
查詢
</button>
<a href="{{ route('admin.general-ledger.index') }}" class="inline-flex justify-center rounded-md bg-white dark:bg-gray-700 px-4 py-2 text-sm font-semibold text-gray-900 dark:text-gray-100 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600">
清除
</a>
</div>
</form>
</div>
</div>
@if($selectedAccount)
<!-- Account Info -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ $selectedAccount->account_code }} - {{ $selectedAccount->account_name_zh }}
<span class="text-sm text-gray-500 dark:text-gray-400">
({{ $selectedAccount->account_name_en }})
</span>
</h3>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
類型:
@switch($selectedAccount->account_type)
@case('asset') 資產 @break
@case('liability') 負債 @break
@case('net_asset') 淨資產/基金 @break
@case('income') 收入 @break
@case('expense') 支出 @break
@default {{ $selectedAccount->account_type }}
@endswitch
</p>
</div>
</div>
<!-- Summary Cards -->
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
<!-- Opening Balance -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg border-l-4 border-gray-400">
<div class="px-4 py-5 sm:p-6">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">
期初餘額
</dt>
<dd class="mt-1 text-2xl font-semibold {{ $openingBalance >= 0 ? 'text-gray-900 dark:text-gray-100' : 'text-red-600 dark:text-red-400' }}">
NT$ {{ number_format($openingBalance, 2) }}
</dd>
</div>
</div>
<!-- Debit Total -->
<div class="bg-blue-50 dark:bg-blue-900/30 shadow sm:rounded-lg border-l-4 border-blue-400">
<div class="px-4 py-5 sm:p-6">
<dt class="text-sm font-medium text-blue-800 dark:text-blue-200">
借方總計
</dt>
<dd class="mt-1 text-2xl font-semibold text-blue-900 dark:text-blue-100">
NT$ {{ number_format($debitTotal, 2) }}
</dd>
</div>
</div>
<!-- Credit Total -->
<div class="bg-purple-50 dark:bg-purple-900/30 shadow sm:rounded-lg border-l-4 border-purple-400">
<div class="px-4 py-5 sm:p-6">
<dt class="text-sm font-medium text-purple-800 dark:text-purple-200">
貸方總計
</dt>
<dd class="mt-1 text-2xl font-semibold text-purple-900 dark:text-purple-100">
NT$ {{ number_format($creditTotal, 2) }}
</dd>
</div>
</div>
<!-- Closing Balance -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg border-l-4 {{ $closingBalance >= 0 ? 'border-green-400' : 'border-red-400' }}">
<div class="px-4 py-5 sm:p-6">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">
期末餘額
</dt>
<dd class="mt-1 text-2xl font-semibold {{ $closingBalance >= 0 ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400' }}">
NT$ {{ number_format($closingBalance, 2) }}
</dd>
</div>
</div>
</div>
<!-- Entries Table -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h4 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">
分錄明細
</h4>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
日期
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
憑證
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
說明
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-blue-600 dark:text-blue-400">
借方
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-purple-600 dark:text-purple-400">
貸方
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
餘額
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
<!-- Opening Balance Row -->
<tr class="bg-gray-50 dark:bg-gray-700">
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ \Carbon\Carbon::parse($startDate)->format('Y/m/d') }}
</td>
<td class="px-4 py-3 text-sm text-gray-500 dark:text-gray-400" colspan="2">
<em>期初餘額</em>
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-gray-500 dark:text-gray-400">
-
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-gray-500 dark:text-gray-400">
-
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right font-medium {{ $openingBalance >= 0 ? 'text-gray-900 dark:text-gray-100' : 'text-red-600 dark:text-red-400' }}">
{{ number_format($openingBalance, 2) }}
</td>
</tr>
@php $runningBalance = $openingBalance; @endphp
@forelse($entries as $entry)
@php
if (in_array($selectedAccount->account_type, ['asset', 'expense'])) {
$runningBalance += ($entry->entry_type === 'debit' ? $entry->amount : -$entry->amount);
} else {
$runningBalance += ($entry->entry_type === 'credit' ? $entry->amount : -$entry->amount);
}
@endphp
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ $entry->entry_date->format('Y/m/d') }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm">
@if($entry->financeDocument)
<a href="{{ route('admin.finance.show', $entry->financeDocument) }}" class="text-indigo-600 dark:text-indigo-400 hover:underline">
#{{ $entry->finance_document_id }}
</a>
@else
<span class="text-gray-400">-</span>
@endif
</td>
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100 max-w-xs truncate">
{{ $entry->description ?? '-' }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-blue-600 dark:text-blue-400">
{{ $entry->entry_type === 'debit' ? number_format($entry->amount, 2) : '' }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-purple-600 dark:text-purple-400">
{{ $entry->entry_type === 'credit' ? number_format($entry->amount, 2) : '' }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right font-medium {{ $runningBalance >= 0 ? 'text-gray-900 dark:text-gray-100' : 'text-red-600 dark:text-red-400' }}">
{{ number_format($runningBalance, 2) }}
</td>
</tr>
@empty
<tr>
<td colspan="6" class="px-4 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
此期間無分錄
</td>
</tr>
@endforelse
<!-- Totals Row -->
@if($entries && $entries->count() > 0)
<tr class="bg-gray-100 dark:bg-gray-700 font-semibold">
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100" colspan="3">
本期合計
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-blue-700 dark:text-blue-300">
{{ number_format($debitTotal, 2) }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-purple-700 dark:text-purple-300">
{{ number_format($creditTotal, 2) }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right {{ $closingBalance >= 0 ? 'text-green-700 dark:text-green-300' : 'text-red-700 dark:text-red-300' }}">
{{ number_format($closingBalance, 2) }}
</td>
</tr>
@endif
</tbody>
</table>
</div>
</div>
</div>
@else
<!-- No Account Selected -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-12 text-center">
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<h3 class="mt-2 text-sm font-medium text-gray-900 dark:text-gray-100">
請選擇科目
</h3>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
從上方下拉選單選擇科目以查看分錄明細
</p>
</div>
</div>
@endif
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,272 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
新增收入記錄
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="POST" action="{{ route('admin.incomes.store') }}" enctype="multipart/form-data">
@csrf
<div class="space-y-6">
{{-- 基本資訊 --}}
<div>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">基本資訊</h3>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">輸入收入的基本資料。</p>
</div>
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
{{-- 標題 --}}
<div class="sm:col-span-2">
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
標題 <span class="text-red-500">*</span>
</label>
<input type="text" name="title" id="title" value="{{ old('title') }}" required
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="例如2024年度會費收入">
@error('title')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
{{-- 收入日期 --}}
<div>
<label for="income_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
收入日期 <span class="text-red-500">*</span>
</label>
<input type="date" name="income_date" id="income_date" value="{{ old('income_date', date('Y-m-d')) }}" required
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
@error('income_date')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
{{-- 金額 --}}
<div>
<label for="amount" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
金額 (NT$) <span class="text-red-500">*</span>
</label>
<input type="number" name="amount" id="amount" value="{{ old('amount') }}" required
step="0.01" min="0.01"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="0.00">
@error('amount')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
{{-- 收入類型 --}}
<div>
<label for="income_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
收入類型 <span class="text-red-500">*</span>
</label>
<select name="income_type" id="income_type" required
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">請選擇收入類型</option>
<option value="membership_fee" @selected(old('income_type') == 'membership_fee')>會費</option>
<option value="entrance_fee" @selected(old('income_type') == 'entrance_fee')>入會費</option>
<option value="donation" @selected(old('income_type') == 'donation')>捐款</option>
<option value="activity" @selected(old('income_type') == 'activity')>活動收入</option>
<option value="grant" @selected(old('income_type') == 'grant')>補助款</option>
<option value="interest" @selected(old('income_type') == 'interest')>利息收入</option>
<option value="other" @selected(old('income_type') == 'other')>其他</option>
</select>
@error('income_type')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
{{-- 會計科目 --}}
<div>
<label for="chart_of_account_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
會計科目 <span class="text-red-500">*</span>
</label>
<select name="chart_of_account_id" id="chart_of_account_id" required
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">請選擇會計科目</option>
@foreach ($chartOfAccounts as $account)
<option value="{{ $account->id }}" @selected(old('chart_of_account_id') == $account->id)>
{{ $account->account_code }} - {{ $account->account_name_zh }}
</option>
@endforeach
</select>
@error('chart_of_account_id')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
<hr class="border-gray-200 dark:border-gray-700">
{{-- 付款資訊 --}}
<div>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">付款資訊</h3>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">記錄付款方式與相關資訊。</p>
</div>
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
{{-- 付款方式 --}}
<div>
<label for="payment_method" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
付款方式 <span class="text-red-500">*</span>
</label>
<select name="payment_method" id="payment_method" required
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">請選擇付款方式</option>
<option value="cash" @selected(old('payment_method') == 'cash')>現金</option>
<option value="bank_transfer" @selected(old('payment_method') == 'bank_transfer')>銀行轉帳</option>
<option value="check" @selected(old('payment_method') == 'check')>支票</option>
</select>
@error('payment_method')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
{{-- 銀行帳號 --}}
<div>
<label for="bank_account" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
銀行帳號
</label>
<input type="text" name="bank_account" id="bank_account" value="{{ old('bank_account') }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="例如012-12345678">
@error('bank_account')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
{{-- 付款人姓名 --}}
<div>
<label for="payer_name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
付款人姓名
</label>
<input type="text" name="payer_name" id="payer_name" value="{{ old('payer_name') }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="付款人姓名">
@error('payer_name')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
{{-- 關聯會員 --}}
<div>
<label for="member_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
關聯會員
</label>
<select name="member_id" id="member_id"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">不關聯會員</option>
@foreach ($members as $member)
<option value="{{ $member->id }}" @selected(old('member_id', $selectedMember?->id) == $member->id)>
{{ $member->full_name }}
</option>
@endforeach
</select>
@error('member_id')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
{{-- 收據編號 --}}
<div>
<label for="receipt_number" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
收據編號
</label>
<input type="text" name="receipt_number" id="receipt_number" value="{{ old('receipt_number') }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="收據編號">
@error('receipt_number')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
{{-- 交易參考號 --}}
<div>
<label for="transaction_reference" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
交易參考號
</label>
<input type="text" name="transaction_reference" id="transaction_reference" value="{{ old('transaction_reference') }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="銀行交易參考號">
@error('transaction_reference')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
<hr class="border-gray-200 dark:border-gray-700">
{{-- 說明與備註 --}}
<div>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">說明與備註</h3>
</div>
<div class="grid grid-cols-1 gap-6">
{{-- 說明 --}}
<div>
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
說明
</label>
<textarea name="description" id="description" rows="3"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="收入來源說明">{{ old('description') }}</textarea>
@error('description')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
{{-- 備註 --}}
<div>
<label for="notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
內部備註
</label>
<textarea name="notes" id="notes" rows="2"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="內部備註(僅管理員可見)">{{ old('notes') }}</textarea>
@error('notes')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
{{-- 附件 --}}
<div>
<label for="attachment" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
附件
</label>
<input type="file" name="attachment" id="attachment"
class="mt-1 block w-full text-sm text-gray-500 dark:text-gray-400
file:mr-4 file:py-2 file:px-4
file:rounded-md file:border-0
file:text-sm file:font-semibold
file:bg-indigo-50 file:text-indigo-700
dark:file:bg-indigo-900 dark:file:text-indigo-300
hover:file:bg-indigo-100 dark:hover:file:bg-indigo-800">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">支援 PDF、圖片等格式最大 10MB</p>
@error('attachment')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
{{-- 提交按鈕 --}}
<div class="flex justify-end space-x-3 pt-6">
<a href="{{ route('admin.incomes.index') }}"
class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
取消
</a>
<button type="submit"
class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
建立收入記錄
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,234 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
收入管理
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-4">
@if (session('status'))
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
{{-- Statistics Cards --}}
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">待確認收入</dt>
<dd class="mt-1 text-2xl font-semibold text-yellow-600 dark:text-yellow-400">
{{ $statistics['pending_count'] }}
</dd>
<dd class="text-sm text-gray-500 dark:text-gray-400">
NT$ {{ number_format($statistics['pending_amount'], 2) }}
</dd>
</div>
</div>
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">已確認收入</dt>
<dd class="mt-1 text-2xl font-semibold text-green-600 dark:text-green-400">
{{ $statistics['confirmed_count'] }}
</dd>
<dd class="text-sm text-gray-500 dark:text-gray-400">
NT$ {{ number_format($statistics['confirmed_amount'], 2) }}
</dd>
</div>
</div>
</div>
<div class="flex justify-between items-center">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">收入記錄列表</h3>
<div class="flex space-x-2">
<a href="{{ route('admin.incomes.statistics') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
統計報表
</a>
@can('record_income')
<a href="{{ route('admin.incomes.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<svg class="mr-2 h-4 w-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>
@endcan
</div>
</div>
{{-- Filters --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="GET" action="{{ route('admin.incomes.index') }}" class="grid grid-cols-1 gap-4 sm:grid-cols-5">
{{-- 狀態篩選 --}}
<div>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">狀態</label>
<select name="status" id="status" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部狀態</option>
<option value="pending" @selected(request('status') == 'pending')>待確認</option>
<option value="confirmed" @selected(request('status') == 'confirmed')>已確認</option>
<option value="cancelled" @selected(request('status') == 'cancelled')>已取消</option>
</select>
</div>
{{-- 收入類型篩選 --}}
<div>
<label for="income_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">收入類型</label>
<select name="income_type" id="income_type" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部類型</option>
<option value="membership_fee" @selected(request('income_type') == 'membership_fee')>會費</option>
<option value="entrance_fee" @selected(request('income_type') == 'entrance_fee')>入會費</option>
<option value="donation" @selected(request('income_type') == 'donation')>捐款</option>
<option value="activity" @selected(request('income_type') == 'activity')>活動收入</option>
<option value="grant" @selected(request('income_type') == 'grant')>補助款</option>
<option value="interest" @selected(request('income_type') == 'interest')>利息收入</option>
<option value="other" @selected(request('income_type') == 'other')>其他</option>
</select>
</div>
{{-- 付款方式篩選 --}}
<div>
<label for="payment_method" class="block text-sm font-medium text-gray-700 dark:text-gray-300">付款方式</label>
<select name="payment_method" id="payment_method" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部方式</option>
<option value="cash" @selected(request('payment_method') == 'cash')>現金</option>
<option value="bank_transfer" @selected(request('payment_method') == 'bank_transfer')>銀行轉帳</option>
<option value="check" @selected(request('payment_method') == 'check')>支票</option>
</select>
</div>
{{-- 日期範圍 --}}
<div>
<label for="date_from" class="block text-sm font-medium text-gray-700 dark:text-gray-300">起始日期</label>
<input type="date" name="date_from" id="date_from" value="{{ request('date_from') }}" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
</div>
{{-- 篩選按鈕 --}}
<div class="flex items-end space-x-2">
<button type="submit" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
篩選
</button>
<a href="{{ route('admin.incomes.index') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
重設
</a>
</div>
</form>
</div>
</div>
{{-- Table --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700" role="table">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
收入編號
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
標題
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
收入類型
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
金額
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
付款方式
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
狀態
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
日期
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
<span class="sr-only">操作</span>
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse ($incomes as $income)
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
<div class="font-mono text-xs">{{ $income->income_number }}</div>
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
<div class="font-medium">{{ $income->title }}</div>
@if ($income->member)
<div class="text-xs text-gray-500 dark:text-gray-400">
會員:{{ $income->member->full_name }}
</div>
@elseif ($income->payer_name)
<div class="text-xs text-gray-500 dark:text-gray-400">
付款人:{{ $income->payer_name }}
</div>
@endif
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ $income->getIncomeTypeText() }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
<span class="font-semibold">NT$ {{ number_format($income->amount, 2) }}</span>
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ $income->getPaymentMethodText() }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm">
@if ($income->isCancelled())
<span class="inline-flex rounded-full bg-red-100 dark:bg-red-900 px-2 text-xs font-semibold leading-5 text-red-800 dark:text-red-200">
{{ $income->getStatusText() }}
</span>
@elseif ($income->isConfirmed())
<span class="inline-flex rounded-full bg-green-100 dark:bg-green-900 px-2 text-xs font-semibold leading-5 text-green-800 dark:text-green-200">
{{ $income->getStatusText() }}
</span>
@else
<span class="inline-flex rounded-full bg-yellow-100 dark:bg-yellow-900 px-2 text-xs font-semibold leading-5 text-yellow-800 dark:text-yellow-200">
{{ $income->getStatusText() }}
</span>
@endif
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ $income->income_date->format('Y-m-d') }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-right text-sm">
<a href="{{ route('admin.incomes.show', $income) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
檢視
</a>
</td>
</tr>
@empty
<tr>
<td colspan="8" class="px-4 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<p class="mt-2 text-sm font-semibold">尚無收入記錄</p>
<p class="mt-1 text-sm">點選「新增收入」開始建立。</p>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<div class="mt-4">
{{ $incomes->links() }}
</div>
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,329 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
收入詳情 - {{ $income->income_number }}
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-4xl sm:px-6 lg:px-8 space-y-6">
@if (session('status'))
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
{{-- 狀態卡片 --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center justify-between">
<div>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">
{{ $income->title }}
</h3>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
收入編號:{{ $income->income_number }}
</p>
</div>
<div>
@if ($income->isCancelled())
<span class="inline-flex items-center rounded-full bg-red-100 dark:bg-red-900 px-3 py-1 text-sm font-medium text-red-800 dark:text-red-200">
{{ $income->getStatusText() }}
</span>
@elseif ($income->isConfirmed())
<span class="inline-flex items-center rounded-full bg-green-100 dark:bg-green-900 px-3 py-1 text-sm font-medium text-green-800 dark:text-green-200">
{{ $income->getStatusText() }}
</span>
@else
<span class="inline-flex items-center rounded-full bg-yellow-100 dark:bg-yellow-900 px-3 py-1 text-sm font-medium text-yellow-800 dark:text-yellow-200">
{{ $income->getStatusText() }}
</span>
@endif
</div>
</div>
{{-- 操作按鈕 --}}
<div class="mt-6 flex space-x-3">
@if ($income->canBeConfirmed())
@can('confirm_income')
<form method="POST" action="{{ route('admin.incomes.confirm', $income) }}" class="inline">
@csrf
<button type="submit" onclick="return confirm('確定要確認此收入嗎?將會自動產生出納日記帳和會計分錄。')"
class="inline-flex items-center rounded-md border border-transparent bg-green-600 dark:bg-green-500 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 dark:hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2">
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
確認收入
</button>
</form>
@endcan
@endif
@if ($income->canBeCancelled())
@can('cancel_income')
<form method="POST" action="{{ route('admin.incomes.cancel', $income) }}" class="inline">
@csrf
<button type="submit" onclick="return confirm('確定要取消此收入嗎?')"
class="inline-flex items-center rounded-md border border-red-300 dark:border-red-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-red-700 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/30 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
取消收入
</button>
</form>
@endcan
@endif
@if ($income->attachment_path)
<a href="{{ route('admin.incomes.download', $income) }}"
class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
下載附件
</a>
@endif
</div>
</div>
</div>
{{-- 金額與日期資訊 --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">金額與日期</h4>
<dl class="grid grid-cols-1 gap-4 sm:grid-cols-3">
<div class="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-4">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">金額</dt>
<dd class="mt-1 text-2xl font-semibold text-gray-900 dark:text-gray-100">
NT$ {{ number_format($income->amount, 2) }}
</dd>
</div>
<div class="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-4">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">收入日期</dt>
<dd class="mt-1 text-lg font-medium text-gray-900 dark:text-gray-100">
{{ $income->income_date->format('Y-m-d') }}
</dd>
</div>
<div class="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-4">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">收入類型</dt>
<dd class="mt-1 text-lg font-medium text-gray-900 dark:text-gray-100">
{{ $income->getIncomeTypeText() }}
</dd>
</div>
</dl>
</div>
</div>
{{-- 會計資訊 --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">會計資訊</h4>
<dl class="grid grid-cols-1 gap-4 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">會計科目</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
@if ($income->chartOfAccount)
{{ $income->chartOfAccount->account_code }} - {{ $income->chartOfAccount->account_name_zh }}
@else
<span class="text-gray-400">未指定</span>
@endif
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款方式</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $income->getPaymentMethodText() }}
</dd>
</div>
@if ($income->bank_account)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">銀行帳號</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $income->bank_account }}
</dd>
</div>
@endif
@if ($income->receipt_number)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">收據編號</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $income->receipt_number }}
</dd>
</div>
@endif
@if ($income->transaction_reference)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">交易參考號</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $income->transaction_reference }}
</dd>
</div>
@endif
</dl>
</div>
</div>
{{-- 付款人資訊 --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">付款人資訊</h4>
<dl class="grid grid-cols-1 gap-4 sm:grid-cols-2">
@if ($income->member)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">關聯會員</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
<a href="{{ route('admin.members.show', $income->member) }}" class="text-indigo-600 dark:text-indigo-400 hover:underline">
{{ $income->member->full_name }}
</a>
</dd>
</div>
@endif
@if ($income->payer_name)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款人姓名</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $income->payer_name }}
</dd>
</div>
@endif
@if (!$income->member && !$income->payer_name)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款人</dt>
<dd class="mt-1 text-sm text-gray-400">未記錄</dd>
</div>
@endif
</dl>
</div>
</div>
{{-- 說明與備註 --}}
@if ($income->description || $income->notes)
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">說明與備註</h4>
<dl class="space-y-4">
@if ($income->description)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">說明</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 whitespace-pre-wrap">{{ $income->description }}</dd>
</div>
@endif
@if ($income->notes)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">內部備註</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 whitespace-pre-wrap">{{ $income->notes }}</dd>
</div>
@endif
</dl>
</div>
</div>
@endif
{{-- 處理記錄 --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">處理記錄</h4>
<dl class="grid grid-cols-1 gap-4 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">出納記錄人</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $income->recordedByCashier?->name ?? '不適用' }}
</dd>
@if ($income->recorded_at)
<dd class="text-xs text-gray-500 dark:text-gray-400">
{{ $income->recorded_at->format('Y-m-d H:i') }}
</dd>
@endif
</div>
@if ($income->isConfirmed())
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">會計確認人</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $income->confirmedByAccountant?->name ?? '不適用' }}
</dd>
@if ($income->confirmed_at)
<dd class="text-xs text-gray-500 dark:text-gray-400">
{{ $income->confirmed_at->format('Y-m-d H:i') }}
</dd>
@endif
</div>
@endif
</dl>
</div>
</div>
{{-- 關聯記錄 --}}
@if ($income->isConfirmed() && ($income->cashierLedgerEntry || $income->accountingEntries->count() > 0))
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">關聯記錄</h4>
@if ($income->cashierLedgerEntry)
<div class="mb-4">
<h5 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">出納日記帳</h5>
<div class="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-3">
<a href="{{ route('admin.cashier-ledger.show', $income->cashierLedgerEntry) }}" class="text-indigo-600 dark:text-indigo-400 hover:underline">
查看出納日記帳記錄
</a>
</div>
</div>
@endif
@if ($income->accountingEntries->count() > 0)
<div>
<h5 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">會計分錄</h5>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300">會計科目</th>
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">借方</th>
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">貸方</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
@foreach ($income->accountingEntries as $entry)
<tr>
<td class="px-4 py-2 text-sm text-gray-900 dark:text-gray-100">
{{ $entry->chartOfAccount->account_code }} - {{ $entry->chartOfAccount->account_name_zh }}
</td>
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
@if ($entry->entry_type === 'debit')
NT$ {{ number_format($entry->amount, 2) }}
@endif
</td>
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
@if ($entry->entry_type === 'credit')
NT$ {{ number_format($entry->amount, 2) }}
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
</div>
</div>
@endif
{{-- 返回按鈕 --}}
<div class="flex justify-start">
<a href="{{ route('admin.incomes.index') }}"
class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
返回列表
</a>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,216 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
收入統計報表
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-6">
{{-- 篩選器 --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="GET" action="{{ route('admin.incomes.statistics') }}" class="flex items-end space-x-4">
<div>
<label for="year" class="block text-sm font-medium text-gray-700 dark:text-gray-300">年度</label>
<select name="year" id="year" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
@for ($y = date('Y'); $y >= date('Y') - 5; $y--)
<option value="{{ $y }}" @selected($year == $y)>{{ $y }}</option>
@endfor
</select>
</div>
<div>
<label for="month" class="block text-sm font-medium text-gray-700 dark:text-gray-300">月份</label>
<select name="month" id="month" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全年</option>
@for ($m = 1; $m <= 12; $m++)
<option value="{{ $m }}" @selected($month == $m)>{{ $m }}</option>
@endfor
</select>
</div>
<div class="flex space-x-2">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
查詢
</button>
<a href="{{ route('admin.incomes.export', ['date_from' => $year . '-01-01', 'date_to' => $year . '-12-31']) }}"
class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
匯出 CSV
</a>
</div>
</form>
</div>
</div>
{{-- 總計 --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">
{{ $year }}{{ $month ? $month . '月' : '' }}收入總計
</h3>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
<div class="bg-indigo-50 dark:bg-indigo-900/30 rounded-lg p-4">
<dt class="text-sm font-medium text-indigo-600 dark:text-indigo-400">總收入金額</dt>
<dd class="mt-1 text-3xl font-semibold text-indigo-900 dark:text-indigo-100">
NT$ {{ number_format($total['amount'], 2) }}
</dd>
</div>
<div class="bg-green-50 dark:bg-green-900/30 rounded-lg p-4">
<dt class="text-sm font-medium text-green-600 dark:text-green-400">收入筆數</dt>
<dd class="mt-1 text-3xl font-semibold text-green-900 dark:text-green-100">
{{ number_format($total['count']) }}
</dd>
</div>
</div>
</div>
</div>
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
{{-- 依收入類型統計 --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">依收入類型統計</h3>
@if ($byType->count() > 0)
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300">類型</th>
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">筆數</th>
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">金額</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
@foreach ($byType as $item)
<tr>
<td class="px-4 py-2 text-sm text-gray-900 dark:text-gray-100">
{{ \App\Models\Income::getIncomeTypeLabel($item->income_type) }}
</td>
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
{{ number_format($item->count) }}
</td>
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
NT$ {{ number_format($item->total_amount, 2) }}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@else
<p class="text-sm text-gray-500 dark:text-gray-400">此期間無收入資料</p>
@endif
</div>
</div>
{{-- 依會計科目統計 --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">依會計科目統計</h3>
@if ($byAccount->count() > 0)
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300">科目</th>
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">筆數</th>
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">金額</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
@foreach ($byAccount as $item)
<tr>
<td class="px-4 py-2 text-sm text-gray-900 dark:text-gray-100">
@if ($item->chartOfAccount)
{{ $item->chartOfAccount->account_code }} - {{ $item->chartOfAccount->account_name_zh }}
@else
未分類
@endif
</td>
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
{{ number_format($item->count) }}
</td>
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
NT$ {{ number_format($item->total_amount, 2) }}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@else
<p class="text-sm text-gray-500 dark:text-gray-400">此期間無收入資料</p>
@endif
</div>
</div>
</div>
{{-- 依月份統計 --}}
@if (!$month)
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ $year }}年月度收入趨勢</h3>
@if ($byMonth->count() > 0)
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300">月份</th>
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">筆數</th>
<th class="px-4 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300">金額</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300">圖示</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
@php
$maxAmount = $byMonth->max('total_amount') ?: 1;
@endphp
@for ($m = 1; $m <= 12; $m++)
@php
$monthData = $byMonth->firstWhere('month', $m);
$amount = $monthData->total_amount ?? 0;
$count = $monthData->count ?? 0;
$percentage = ($amount / $maxAmount) * 100;
@endphp
<tr>
<td class="px-4 py-2 text-sm text-gray-900 dark:text-gray-100">
{{ $m }}
</td>
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
{{ number_format($count) }}
</td>
<td class="px-4 py-2 text-sm text-right text-gray-900 dark:text-gray-100">
NT$ {{ number_format($amount, 2) }}
</td>
<td class="px-4 py-2">
<div class="w-full bg-gray-200 dark:bg-gray-600 rounded-full h-2">
<div class="bg-indigo-600 dark:bg-indigo-500 h-2 rounded-full" style="width: {{ $percentage }}%"></div>
</div>
</td>
</tr>
@endfor
</tbody>
</table>
</div>
@else
<p class="text-sm text-gray-500 dark:text-gray-400">此年度無收入資料</p>
@endif
</div>
</div>
@endif
{{-- 返回按鈕 --}}
<div class="flex justify-start">
<a href="{{ route('admin.incomes.index') }}"
class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600">
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
返回收入列表
</a>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -1,59 +1,57 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Create Label') }}
新增標籤
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-2xl sm:px-6 lg:px-8">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<form method="POST" action="{{ route('admin.issue-labels.store') }}" class="space-y-6">
@csrf
<div>
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Name') }} <span class="text-red-500">*</span>
名稱 <span class="text-red-500">*</span>
</label>
<input type="text" name="name" id="name" value="{{ old('name') }}" required maxlength="255"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('name') border-red-300 @enderror"
placeholder="{{ __('e.g., urgent, bug, enhancement') }}">
placeholder="例如:錯誤、功能、增強">
@error('name')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<div>
<label for="color" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Color') }} <span class="text-red-500">*</span>
顏色 <span class="text-red-500">*</span>
</label>
<div class="mt-1 flex gap-2">
<input type="color" name="color" id="color" value="{{ old('color', '#6B7280') }}" required
class="h-10 w-20 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:border-gray-600">
<input type="text" id="color-text" value="{{ old('color', '#6B7280') }}" maxlength="7"
class="flex-1 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"
placeholder="#000000">
<div class="mt-1 flex items-center gap-2">
<input type="color" name="color" id="color" value="{{ old('color', '#3b82f6') }}" required
class="h-10 w-20 rounded-md border-gray-300 dark:border-gray-600 p-1">
<input type="text" name="color_text" id="color_text" value="{{ old('color', '#3b82f6') }}" required maxlength="7"
class="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"
placeholder="#RRGGBB">
</div>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">{{ __('Choose a color for this label') }}</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">標籤的十六進位色碼</p>
@error('color')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<div>
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Description') }}
<label for="text_color" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
文字顏色
</label>
<textarea name="description" id="description" rows="3" maxlength="500"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"
placeholder="{{ __('Optional description...') }}">{{ old('description') }}</textarea>
@error('description')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
<select name="text_color" id="text_color"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="#ffffff" @selected(old('text_color') == '#ffffff')>White</option>
<option value="#000000" @selected(old('text_color') == '#000000')>Black</option>
</select>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">對比的文字顏色</p>
@error('text_color')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<div class="flex items-center justify-end gap-x-4 border-t border-gray-200 pt-6 dark:border-gray-700">
<a href="{{ route('admin.issue-labels.index') }}"
class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600">
{{ __('Cancel') }}
</a>
<button type="submit"
class="inline-flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400">
{{ __('Create Label') }}
<div class="flex items-center justify-end pt-6">
<button type="submit" class="inline-flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-400 dark:focus:ring-offset-gray-800">
新增標籤
</button>
</div>
</form>
@@ -62,19 +60,17 @@
</div>
<script>
// Sync color picker and text input
const colorPicker = document.getElementById('color');
const colorText = document.getElementById('color-text');
const colorInput = document.getElementById('color');
const colorTextInput = document.getElementById('color_text');
colorPicker.addEventListener('input', (e) => {
colorText.value = e.target.value.toUpperCase();
colorInput.addEventListener('input', (e) => {
colorTextInput.value = e.target.value;
});
colorText.addEventListener('input', (e) => {
const value = e.target.value;
if (/^#[0-9A-Fa-f]{6}$/.test(value)) {
colorPicker.value = value;
colorTextInput.addEventListener('input', (e) => {
if (e.target.value.match(/^#[0-9A-Fa-f]{6}$/)) {
colorInput.value = e.target.value;
}
});
</script>
</x-app-layout>
</x-app-layout>

View File

@@ -1,12 +1,12 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Edit Label') }} - {{ $issueLabel->name }}
編輯標籤
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-2xl sm:px-6 lg:px-8">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<form method="POST" action="{{ route('admin.issue-labels.update', $issueLabel) }}" class="space-y-6">
@csrf
@@ -14,43 +14,45 @@
<div>
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Name') }} <span class="text-red-500">*</span>
名稱 <span class="text-red-500">*</span>
</label>
<input type="text" name="name" id="name" value="{{ old('name', $issueLabel->name) }}" required maxlength="255"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('name') border-red-300 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('name') border-red-300 @enderror"
placeholder="例如:錯誤、功能、增強">
@error('name')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<div>
<label for="color" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Color') }} <span class="text-red-500">*</span>
顏色 <span class="text-red-500">*</span>
</label>
<div class="mt-1 flex gap-2">
<div class="mt-1 flex items-center gap-2">
<input type="color" name="color" id="color" value="{{ old('color', $issueLabel->color) }}" required
class="h-10 w-20 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:border-gray-600">
<input type="text" id="color-text" value="{{ old('color', $issueLabel->color) }}" maxlength="7"
class="flex-1 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
class="h-10 w-20 rounded-md border-gray-300 dark:border-gray-600 p-1">
<input type="text" name="color_text" id="color_text" value="{{ old('color', $issueLabel->color) }}" required maxlength="7"
class="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"
placeholder="#RRGGBB">
</div>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">標籤的十六進位色碼</p>
@error('color')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<div>
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Description') }}
<label for="text_color" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
文字顏色
</label>
<textarea name="description" id="description" rows="3" maxlength="500"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">{{ old('description', $issueLabel->description) }}</textarea>
@error('description')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
<select name="text_color" id="text_color"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="#ffffff" @selected(old('text_color', $issueLabel->text_color) == '#ffffff')>White</option>
<option value="#000000" @selected(old('text_color', $issueLabel->text_color) == '#000000')>Black</option>
</select>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">對比的文字顏色</p>
@error('text_color')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<div class="flex items-center justify-end gap-x-4 border-t border-gray-200 pt-6 dark:border-gray-700">
<a href="{{ route('admin.issue-labels.index') }}"
class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600">
{{ __('Cancel') }}
</a>
<button type="submit"
class="inline-flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400">
{{ __('Update Label') }}
<div class="flex items-center justify-end pt-6">
<button type="submit" class="inline-flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-400 dark:focus:ring-offset-gray-800">
更新標籤
</button>
</div>
</form>
@@ -59,19 +61,17 @@
</div>
<script>
// Sync color picker and text input
const colorPicker = document.getElementById('color');
const colorText = document.getElementById('color-text');
const colorInput = document.getElementById('color');
const colorTextInput = document.getElementById('color_text');
colorPicker.addEventListener('input', (e) => {
colorText.value = e.target.value.toUpperCase();
colorInput.addEventListener('input', (e) => {
colorTextInput.value = e.target.value;
});
colorText.addEventListener('input', (e) => {
const value = e.target.value;
if (/^#[0-9A-Fa-f]{6}$/.test(value)) {
colorPicker.value = value;
colorTextInput.addEventListener('input', (e) => {
if (e.target.value.match(/^#[0-9A-Fa-f]{6}$/)) {
colorInput.value = e.target.value;
}
});
</script>
</x-app-layout>
</x-app-layout>

View File

@@ -1,14 +1,14 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Issue Labels') }} (標籤管理)
任務標籤
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
@if (session('status'))
<div class="mb-4 rounded-md bg-green-50 p-4 dark:bg-green-900/30 border-l-4 border-green-400" role="status">
<div class="mb-4 rounded-md bg-green-50 p-4 dark:bg-green-900/30 border-l-4 border-green-400 dark:border-green-500" role="status">
<p class="text-sm text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@@ -16,13 +16,13 @@
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-center sm:justify-between mb-6">
<div>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">{{ __('Manage Labels') }}</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">{{ __('Create and manage labels for categorizing issues') }}</p>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">標籤</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">管理用於分類任務的標籤</p>
</div>
<div class="mt-4 sm:mt-0">
<a href="{{ route('admin.issue-labels.create') }}" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400">
<a href="{{ route('admin.issue-labels.create') }}" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
<svg class="-ml-0.5 mr-1.5 h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"/></svg>
{{ __('Create Label') }}
新增標籤
</a>
</div>
</div>
@@ -31,42 +31,42 @@
<table class="min-w-full divide-y divide-gray-300 dark:divide-gray-600">
<thead class="bg-gray-50 dark:bg-gray-900">
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Label') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Description') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Issues') }}</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4"><span class="sr-only">{{ __('Actions') }}</span></th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">名稱</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">顏色</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">使用情況</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4"><span class="sr-only">操作</span></th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white dark:divide-gray-700 dark:bg-gray-800">
@forelse($labels as $label)
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm">
<span class="inline-flex items-center rounded-full px-3 py-1 text-sm font-medium"
style="background-color: {{ $label->color }}; color: {{ $label->text_color }}">
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium">
<span class="inline-flex items-center rounded-full px-2 py-1 text-xs font-medium" style="background-color: {{ $label->color }}20; color: {{ $label->color }}">
{{ $label->name }}
</span>
</td>
<td class="px-3 py-4 text-sm text-gray-900 dark:text-gray-100">
{{ $label->description ?? '—' }}
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500 dark:text-gray-400">
<div class="flex items-center gap-2">
<div class="w-4 h-4 rounded-full border border-gray-200 dark:border-gray-600" style="background-color: {{ $label->color }}"></div>
{{ $label->color }}
</div>
</td>
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-900 dark:text-gray-100">
{{ $label->issues_count }}
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500 dark:text-gray-400">
{{ $label->issues_count }} 任務
</td>
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium">
<a href="{{ route('admin.issue-labels.edit', $label) }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-4">{{ __('Edit') }}</a>
@if($label->issues_count === 0)
<form method="POST" action="{{ route('admin.issue-labels.destroy', $label) }}" class="inline" onsubmit="return confirm('{{ __('Delete this label?') }}')">
@csrf
@method('DELETE')
<button type="submit" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">{{ __('Delete') }}</button>
</form>
@endif
<a href="{{ route('admin.issue-labels.edit', $label) }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">編輯</a>
<form method="POST" action="{{ route('admin.issue-labels.destroy', $label) }}" class="inline" onsubmit="return confirm('刪除此標籤?')">
@csrf
@method('DELETE')
<button type="submit" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300 ml-2">刪除</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="4" class="px-3 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
<p>{{ __('No labels found') }}</p>
找不到標籤
</td>
</tr>
@endforelse
@@ -76,4 +76,4 @@
</div>
</div>
</div>
</x-app-layout>
</x-app-layout>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Task Reports & Analytics') }}
任務報告與分析
</h2>
</x-slot>
@@ -13,20 +13,20 @@
<form method="GET" action="{{ route('admin.issue-reports.index') }}" class="flex flex-wrap gap-4 items-end">
<div class="flex-1 min-w-[200px]">
<label for="start_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Start Date') }}
開始日期
</label>
<input type="date" name="start_date" id="start_date" value="{{ $startDate->format('Y-m-d') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
</div>
<div class="flex-1 min-w-[200px]">
<label for="end_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('End Date') }}
結束日期
</label>
<input type="date" name="end_date" id="end_date" value="{{ $endDate->format('Y-m-d') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
</div>
<button type="submit" class="inline-flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400">
{{ __('Apply Filter') }}
套用篩選
</button>
</form>
</div>
@@ -34,19 +34,19 @@
{{-- Summary Statistics --}}
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 border-l-4 border-blue-400">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Total Tasks') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">總任務數</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-gray-100">{{ number_format($stats['total_issues']) }}</dd>
</div>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 border-l-4 border-green-400">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Open Tasks') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">開啟的任務</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-gray-100">{{ number_format($stats['open_issues']) }}</dd>
</div>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 border-l-4 border-gray-400">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Closed Tasks') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">已結案任務</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-gray-100">{{ number_format($stats['closed_issues']) }}</dd>
</div>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 border-l-4 border-red-400">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Overdue Tasks') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">逾期任務</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-gray-100">{{ number_format($stats['overdue_issues']) }}</dd>
</div>
</div>
@@ -55,7 +55,7 @@
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
{{-- Tasks by Status --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Tasks by Status') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">依狀態的任務</h3>
<div class="space-y-2">
@foreach(['new', 'assigned', 'in_progress', 'review', 'closed'] as $status)
<div class="flex items-center justify-between">
@@ -74,7 +74,7 @@
{{-- Tasks by Priority --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Tasks by Priority') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">依優先級的任務</h3>
<div class="space-y-2">
@foreach(['low', 'medium', 'high', 'urgent'] as $priority)
@php
@@ -96,7 +96,7 @@
{{-- Tasks by Type --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Tasks by Type') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">依類型的任務</h3>
<div class="space-y-2">
@foreach(['work_item', 'project_task', 'maintenance', 'member_request'] as $type)
<div class="flex items-center justify-between">
@@ -117,22 +117,22 @@
{{-- Time Tracking Metrics --}}
@if($timeTrackingMetrics && $timeTrackingMetrics->total_estimated > 0)
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Time Tracking Metrics') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">時間追蹤指標</h3>
<div class="grid grid-cols-1 sm:grid-cols-4 gap-4">
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Total Estimated Hours') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">總預估時數</dt>
<dd class="mt-1 text-2xl font-semibold text-gray-900 dark:text-gray-100">{{ number_format($timeTrackingMetrics->total_estimated, 1) }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Total Actual Hours') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">總實際時數</dt>
<dd class="mt-1 text-2xl font-semibold text-gray-900 dark:text-gray-100">{{ number_format($timeTrackingMetrics->total_actual, 1) }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Avg Estimated Hours') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">平均預估時數</dt>
<dd class="mt-1 text-2xl font-semibold text-gray-900 dark:text-gray-100">{{ number_format($timeTrackingMetrics->avg_estimated, 1) }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Avg Actual Hours') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">平均實際時數</dt>
<dd class="mt-1 text-2xl font-semibold text-gray-900 dark:text-gray-100">{{ number_format($timeTrackingMetrics->avg_actual, 1) }}</dd>
</div>
</div>
@@ -142,7 +142,7 @@
@endphp
<div class="mt-4">
<p class="text-sm text-gray-600 dark:text-gray-400">
{{ __('Variance') }}:
差異:
<span class="font-semibold {{ $variance > 0 ? 'text-red-600 dark:text-red-400' : 'text-green-600 dark:text-green-400' }}">
{{ $variance > 0 ? '+' : '' }}{{ number_format($variance, 1) }} hours ({{ number_format($variancePercentage, 1) }}%)
</span>
@@ -154,24 +154,24 @@
{{-- Average Resolution Time --}}
@if($avgResolutionTime)
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-2">{{ __('Average Resolution Time') }}</h3>
<p class="text-3xl font-semibold text-gray-900 dark:text-gray-100">{{ number_format($avgResolutionTime, 1) }} {{ __('days') }}</p>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-2">平均解決時間</h3>
<p class="text-3xl font-semibold text-gray-900 dark:text-gray-100">{{ number_format($avgResolutionTime, 1) }} </p>
</div>
@endif
{{-- Assignee Performance --}}
@if($assigneePerformance->isNotEmpty())
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Assignee Performance (Top 10)') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">指派對象表現前10名</h3>
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg">
<table class="min-w-full divide-y divide-gray-300 dark:divide-gray-600">
<thead class="bg-gray-50 dark:bg-gray-900">
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Assignee') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Total Assigned') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Completed') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Overdue') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Completion Rate') }}</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">指派對象</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">總指派數</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">已完成</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">逾期</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">完成率</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@@ -210,7 +210,7 @@
{{-- Top Labels Used --}}
@if($topLabels->isNotEmpty())
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Top Labels Used') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">最常用標籤</h3>
<div class="space-y-3">
@foreach($topLabels as $label)
<div class="flex items-center justify-between">
@@ -220,7 +220,7 @@
{{ $label->name }}
</span>
</div>
<span class="text-sm font-semibold text-gray-900 dark:text-gray-100">{{ $label->usage_count }} {{ __('uses') }}</span>
<span class="text-sm font-semibold text-gray-900 dark:text-gray-100">{{ $label->usage_count }} 使用</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2 dark:bg-gray-700">
@php
@@ -236,16 +236,16 @@
{{-- Recent Tasks --}}
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Recent Tasks') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">最近的任務</h3>
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg dark:ring-gray-700">
<table class="min-w-full divide-y divide-gray-300 dark:divide-gray-600">
<thead class="bg-gray-50 dark:bg-gray-900">
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Task') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Status') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Priority') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Assignee') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Created') }}</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">任務</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">狀態</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">優先級</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">指派對象</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">已建立</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white dark:divide-gray-700 dark:bg-gray-800">

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Create Task') }} (建立任務)
新增任務 (建立任務)
</h2>
</x-slot>
@@ -14,22 +14,22 @@
<!-- Title -->
<div>
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Title') }} <span class="text-red-500">*</span>
標題 <span class="text-red-500">*</span>
</label>
<input type="text" name="title" id="title" value="{{ old('title') }}" required maxlength="255"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('title') border-red-300 @enderror"
placeholder="{{ __('Brief summary of the task') }}">
placeholder="任務簡述">
@error('title')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<!-- Description -->
<div>
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Description') }}
描述
</label>
<textarea name="description" id="description" rows="5"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"
placeholder="{{ __('Detailed description of the task...') }}">{{ old('description') }}</textarea>
placeholder="詳細描述此任務...">{{ old('description') }}</textarea>
@error('description')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
@@ -37,30 +37,30 @@
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label for="issue_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Task Type') }} <span class="text-red-500">*</span>
任務類型 <span class="text-red-500">*</span>
</label>
<select name="issue_type" id="issue_type" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('issue_type') border-red-300 @enderror">
<option value="">{{ __('Select type...') }}</option>
<option value="work_item" @selected(old('issue_type') === 'work_item')>{{ __('Work Item') }}</option>
<option value="project_task" @selected(old('issue_type') === 'project_task')>{{ __('Project Task') }}</option>
<option value="maintenance" @selected(old('issue_type') === 'maintenance')>{{ __('Maintenance') }}</option>
<option value="member_request" @selected(old('issue_type') === 'member_request')>{{ __('Member Request') }}</option>
<option value="">選擇類型...</option>
<option value="work_item" @selected(old('issue_type') === 'work_item')>工作項目</option>
<option value="project_task" @selected(old('issue_type') === 'project_task')>專案任務</option>
<option value="maintenance" @selected(old('issue_type') === 'maintenance')>維護</option>
<option value="member_request" @selected(old('issue_type') === 'member_request')>會員請求</option>
</select>
@error('issue_type')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<div>
<label for="priority" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Priority') }} <span class="text-red-500">*</span>
優先級 <span class="text-red-500">*</span>
</label>
<select name="priority" id="priority" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('priority') border-red-300 @enderror">
<option value="">{{ __('Select priority...') }}</option>
<option value="low" @selected(old('priority') === 'low')>{{ __('Low') }} </option>
<option value="medium" @selected(old('priority', 'medium') === 'medium')>{{ __('Medium') }} </option>
<option value="high" @selected(old('priority') === 'high')>{{ __('High') }} </option>
<option value="urgent" @selected(old('priority') === 'urgent')>{{ __('Urgent') }} </option>
<option value="">選擇優先級...</option>
<option value="low" @selected(old('priority') === 'low')> </option>
<option value="medium" @selected(old('priority', 'medium') === 'medium')> </option>
<option value="high" @selected(old('priority') === 'high')> </option>
<option value="urgent" @selected(old('priority') === 'urgent')>緊急 </option>
</select>
@error('priority')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
@@ -70,21 +70,21 @@
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label for="assigned_to_user_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Assign To') }}
指派給
</label>
<select name="assigned_to_user_id" id="assigned_to_user_id"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('Unassigned') }}</option>
<option value="">未指派</option>
@foreach($users as $user)
<option value="{{ $user->id }}" @selected(old('assigned_to_user_id') == $user->id)>{{ $user->name }}</option>
@endforeach
</select>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">{{ __('Optional: Assign to a team member') }}</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">選填:指派給團隊成員</p>
</div>
<div>
<label for="due_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Due Date') }}
截止日期
</label>
<input type="date" name="due_date" id="due_date" value="{{ old('due_date') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
@@ -95,50 +95,50 @@
<!-- Estimated Hours -->
<div>
<label for="estimated_hours" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Estimated Hours') }}
預估時數
</label>
<input type="number" name="estimated_hours" id="estimated_hours" value="{{ old('estimated_hours') }}" step="0.5" min="0"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"
placeholder="0.0">
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">{{ __('Estimated time to complete this task') }}</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">完成此任務的預估時間</p>
</div>
<!-- Member (for member requests) -->
<div>
<label for="member_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Related Member') }}
相關會員
</label>
<select name="member_id" id="member_id"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('None') }}</option>
<option value=""></option>
@foreach($members as $member)
<option value="{{ $member->id }}" @selected(old('member_id') == $member->id)>{{ $member->full_name }}</option>
@endforeach
</select>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">{{ __('Link to a member for member requests') }}</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">連結至會員(用於會員請求)</p>
</div>
<!-- Parent Task (for sub-tasks) -->
<div>
<label for="parent_issue_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Parent Task') }}
父任務
</label>
<select name="parent_issue_id" id="parent_issue_id"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('None (top-level task)') }}</option>
<option value="">無(頂層任務)</option>
@foreach($openIssues as $parentIssue)
<option value="{{ $parentIssue->id }}" @selected(old('parent_issue_id') == $parentIssue->id)>
{{ $parentIssue->issue_number }} - {{ $parentIssue->title }}
</option>
@endforeach
</select>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">{{ __('Make this a sub-task of another task') }}</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">將此設為另一個任務的子任務</p>
</div>
<!-- Labels -->
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
{{ __('Labels') }}
標籤
</label>
<div class="grid grid-cols-2 sm:grid-cols-3 gap-2">
@foreach($labels as $label)
@@ -153,18 +153,18 @@
</label>
@endforeach
</div>
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">{{ __('Select one or more labels to categorize this task') }}</p>
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">選擇一個或多個標籤來分類此任務</p>
</div>
<!-- Actions -->
<div class="flex items-center justify-end gap-x-4 border-t border-gray-200 pt-6 dark:border-gray-700">
<a href="{{ route('admin.issues.index') }}"
class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600 dark:hover:bg-gray-600">
{{ __('Cancel') }}
取消
</a>
<button type="submit"
class="inline-flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-400 dark:focus:ring-offset-gray-800">
{{ __('Create Task') }}
新增任務
</button>
</div>
</form>
@@ -179,14 +179,14 @@
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-blue-800 dark:text-blue-200">{{ __('Creating Tasks') }}</h3>
<h3 class="text-sm font-medium text-blue-800 dark:text-blue-200">建立任務</h3>
<div class="mt-2 text-sm text-blue-700 dark:text-blue-300">
<ul class="list-disc pl-5 space-y-1">
<li>{{ __('Use work items for general tasks and todos') }}</li>
<li>{{ __('Project tasks are for specific project milestones') }}</li>
<li>{{ __('Member requests track inquiries or requests from members') }}</li>
<li>{{ __('Assign tasks to team members to track responsibility') }}</li>
<li>{{ __('Use labels to categorize and filter tasks easily') }}</li>
<li>使用工作項目處理一般任務和待辦事項</li>
<li>專案任務用於特定的專案里程碑</li>
<li>會員請求追蹤來自會員的查詢或請求</li>
<li>將任務指派給團隊成員以追蹤責任歸屬</li>
<li>使用標籤輕鬆分類和篩選任務</li>
</ul>
</div>
</div>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Edit Issue') }} - {{ $issue->issue_number }}
編輯任務 - {{ $issue->issue_number }}
</h2>
</x-slot>
@@ -15,22 +15,22 @@
<!-- Title -->
<div>
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Title') }} <span class="text-red-500">*</span>
標題 <span class="text-red-500">*</span>
</label>
<input type="text" name="title" id="title" value="{{ old('title', $issue->title) }}" required maxlength="255"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('title') border-red-300 @enderror"
placeholder="{{ __('Brief summary of the issue') }}">
placeholder="任務簡述">
@error('title')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<!-- Description -->
<div>
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Description') }}
描述
</label>
<textarea name="description" id="description" rows="5"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"
placeholder="{{ __('Detailed description of the issue...') }}">{{ old('description', $issue->description) }}</textarea>
placeholder="詳細描述此任務...">{{ old('description', $issue->description) }}</textarea>
@error('description')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
@@ -38,30 +38,30 @@
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label for="issue_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Issue Type') }} <span class="text-red-500">*</span>
任務類型 <span class="text-red-500">*</span>
</label>
<select name="issue_type" id="issue_type" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('issue_type') border-red-300 @enderror">
<option value="">{{ __('Select type...') }}</option>
<option value="work_item" @selected(old('issue_type', $issue->issue_type) === 'work_item')>{{ __('Work Item') }}</option>
<option value="project_task" @selected(old('issue_type', $issue->issue_type) === 'project_task')>{{ __('Project Task') }}</option>
<option value="maintenance" @selected(old('issue_type', $issue->issue_type) === 'maintenance')>{{ __('Maintenance') }}</option>
<option value="member_request" @selected(old('issue_type', $issue->issue_type) === 'member_request')>{{ __('Member Request') }}</option>
<option value="">選擇類型...</option>
<option value="work_item" @selected(old('issue_type', $issue->issue_type) === 'work_item')>工作項目</option>
<option value="project_task" @selected(old('issue_type', $issue->issue_type) === 'project_task')>專案任務</option>
<option value="maintenance" @selected(old('issue_type', $issue->issue_type) === 'maintenance')>維護</option>
<option value="member_request" @selected(old('issue_type', $issue->issue_type) === 'member_request')>會員請求</option>
</select>
@error('issue_type')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<div>
<label for="priority" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Priority') }} <span class="text-red-500">*</span>
優先級 <span class="text-red-500">*</span>
</label>
<select name="priority" id="priority" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('priority') border-red-300 @enderror">
<option value="">{{ __('Select priority...') }}</option>
<option value="low" @selected(old('priority', $issue->priority) === 'low')>{{ __('Low') }} </option>
<option value="medium" @selected(old('priority', $issue->priority) === 'medium')>{{ __('Medium') }} </option>
<option value="high" @selected(old('priority', $issue->priority) === 'high')>{{ __('High') }} </option>
<option value="urgent" @selected(old('priority', $issue->priority) === 'urgent')>{{ __('Urgent') }} </option>
<option value="">選擇優先級...</option>
<option value="low" @selected(old('priority', $issue->priority) === 'low')> </option>
<option value="medium" @selected(old('priority', $issue->priority) === 'medium')> </option>
<option value="high" @selected(old('priority', $issue->priority) === 'high')> </option>
<option value="urgent" @selected(old('priority', $issue->priority) === 'urgent')>緊急 </option>
</select>
@error('priority')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
@@ -71,11 +71,11 @@
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label for="assigned_to_user_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Assign To') }}
指派給
</label>
<select name="assigned_to_user_id" id="assigned_to_user_id"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('Unassigned') }}</option>
<option value="">未指派</option>
@foreach($users as $user)
<option value="{{ $user->id }}" @selected(old('assigned_to_user_id', $issue->assigned_to_user_id) == $user->id)>{{ $user->name }}</option>
@endforeach
@@ -84,11 +84,11 @@
<div>
<label for="reviewer_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Reviewer') }}
審查者
</label>
<select name="reviewer_id" id="reviewer_id"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('None') }}</option>
<option value=""></option>
@foreach($users as $user)
<option value="{{ $user->id }}" @selected(old('reviewer_id', $issue->reviewer_id) == $user->id)>{{ $user->name }}</option>
@endforeach
@@ -100,7 +100,7 @@
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label for="due_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Due Date') }}
截止日期
</label>
<input type="date" name="due_date" id="due_date" value="{{ old('due_date', $issue->due_date?->format('Y-m-d')) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
@@ -109,7 +109,7 @@
<div>
<label for="estimated_hours" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Estimated Hours') }}
預估時數
</label>
<input type="number" name="estimated_hours" id="estimated_hours" value="{{ old('estimated_hours', $issue->estimated_hours) }}" step="0.5" min="0"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
@@ -119,11 +119,11 @@
<!-- Member (for member requests) -->
<div>
<label for="member_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Related Member') }}
相關會員
</label>
<select name="member_id" id="member_id"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('None') }}</option>
<option value=""></option>
@foreach($members as $member)
<option value="{{ $member->id }}" @selected(old('member_id', $issue->member_id) == $member->id)>{{ $member->full_name }}</option>
@endforeach
@@ -133,11 +133,11 @@
<!-- Parent Issue (for sub-tasks) -->
<div>
<label for="parent_issue_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Parent Issue') }}
父任務
</label>
<select name="parent_issue_id" id="parent_issue_id"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('None (top-level issue)') }}</option>
<option value="">無(頂層任務)</option>
@foreach($openIssues as $parentIssue)
<option value="{{ $parentIssue->id }}" @selected(old('parent_issue_id', $issue->parent_issue_id) == $parentIssue->id)>
{{ $parentIssue->issue_number }} - {{ $parentIssue->title }}
@@ -149,7 +149,7 @@
<!-- Labels -->
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
{{ __('Labels') }}
標籤
</label>
<div class="grid grid-cols-2 sm:grid-cols-3 gap-2">
@foreach($labels as $label)
@@ -170,11 +170,11 @@
<div class="flex items-center justify-end gap-x-4 border-t border-gray-200 pt-6 dark:border-gray-700">
<a href="{{ route('admin.issues.show', $issue) }}"
class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600 dark:hover:bg-gray-600">
{{ __('Cancel') }}
取消
</a>
<button type="submit"
class="inline-flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-400 dark:focus:ring-offset-gray-800">
{{ __('Update Issue') }}
更新任務
</button>
</div>
</form>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Tasks') }} (任務追蹤)
任務管理 (任務追蹤)
</h2>
</x-slot>
@@ -23,13 +23,13 @@
<!-- Header -->
<div class="sm:flex sm:items-center sm:justify-between mb-6">
<div>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">{{ __('Task Tracker') }}</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">{{ __('Manage work items, tasks, and member requests') }}</p>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">任務追蹤器</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">管理工作項目、任務和會員請求</p>
</div>
<div class="mt-4 sm:mt-0">
<a href="{{ route('admin.issues.create') }}" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-400 dark:focus:ring-offset-gray-800">
<svg class="-ml-0.5 mr-1.5 h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"/></svg>
{{ __('Create Task') }}
新增任務
</a>
</div>
</div>
@@ -37,19 +37,19 @@
<!-- Summary Stats -->
<div class="grid grid-cols-1 gap-4 sm:grid-cols-4 mb-6">
<div class="bg-blue-50 dark:bg-blue-900/30 rounded-lg p-4 border-l-4 border-blue-400">
<dt class="text-sm font-medium text-blue-800 dark:text-blue-200">{{ __('Total Open') }}</dt>
<dt class="text-sm font-medium text-blue-800 dark:text-blue-200">總開啟數</dt>
<dd class="mt-1 text-2xl font-semibold text-blue-900 dark:text-blue-100">{{ $stats['total_open'] }}</dd>
</div>
<div class="bg-purple-50 dark:bg-purple-900/30 rounded-lg p-4 border-l-4 border-purple-400">
<dt class="text-sm font-medium text-purple-800 dark:text-purple-200">{{ __('Assigned to Me') }}</dt>
<dt class="text-sm font-medium text-purple-800 dark:text-purple-200">指派給我</dt>
<dd class="mt-1 text-2xl font-semibold text-purple-900 dark:text-purple-100">{{ $stats['assigned_to_me'] }}</dd>
</div>
<div class="bg-red-50 dark:bg-red-900/30 rounded-lg p-4 border-l-4 border-red-400">
<dt class="text-sm font-medium text-red-800 dark:text-red-200">{{ __('Overdue') }}</dt>
<dt class="text-sm font-medium text-red-800 dark:text-red-200">逾期</dt>
<dd class="mt-1 text-2xl font-semibold text-red-900 dark:text-red-100">{{ $stats['overdue'] }}</dd>
</div>
<div class="bg-orange-50 dark:bg-orange-900/30 rounded-lg p-4 border-l-4 border-orange-400">
<dt class="text-sm font-medium text-orange-800 dark:text-orange-200">{{ __('High Priority') }}</dt>
<dt class="text-sm font-medium text-orange-800 dark:text-orange-200">高優先級</dt>
<dd class="mt-1 text-2xl font-semibold text-orange-900 dark:text-orange-100">{{ $stats['high_priority'] }}</dd>
</div>
</div>
@@ -58,40 +58,40 @@
<form method="GET" class="mb-6 space-y-4" role="search">
<div class="grid grid-cols-1 gap-4 sm:grid-cols-4">
<div>
<label for="issue_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Type') }}</label>
<label for="issue_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">類型</label>
<select name="issue_type" id="issue_type" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('All Types') }}</option>
<option value="work_item" @selected(request('issue_type') === 'work_item')>{{ __('Work Item') }}</option>
<option value="project_task" @selected(request('issue_type') === 'project_task')>{{ __('Project Task') }}</option>
<option value="maintenance" @selected(request('issue_type') === 'maintenance')>{{ __('Maintenance') }}</option>
<option value="member_request" @selected(request('issue_type') === 'member_request')>{{ __('Member Request') }}</option>
<option value="">所有類型</option>
<option value="work_item" @selected(request('issue_type') === 'work_item')>工作項目</option>
<option value="project_task" @selected(request('issue_type') === 'project_task')>專案任務</option>
<option value="maintenance" @selected(request('issue_type') === 'maintenance')>維護</option>
<option value="member_request" @selected(request('issue_type') === 'member_request')>會員請求</option>
</select>
</div>
<div>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Status') }}</label>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">狀態</label>
<select name="status" id="status" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('All Statuses') }}</option>
<option value="new" @selected(request('status') === 'new')>{{ __('New') }}</option>
<option value="assigned" @selected(request('status') === 'assigned')>{{ __('Assigned') }}</option>
<option value="in_progress" @selected(request('status') === 'in_progress')>{{ __('In Progress') }}</option>
<option value="review" @selected(request('status') === 'review')>{{ __('Review') }}</option>
<option value="closed" @selected(request('status') === 'closed')>{{ __('Closed') }}</option>
<option value="">所有狀態</option>
<option value="new" @selected(request('status') === 'new')></option>
<option value="assigned" @selected(request('status') === 'assigned')>已指派</option>
<option value="in_progress" @selected(request('status') === 'in_progress')>進行中</option>
<option value="review" @selected(request('status') === 'review')>審查</option>
<option value="closed" @selected(request('status') === 'closed')>已結案</option>
</select>
</div>
<div>
<label for="priority" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Priority') }}</label>
<label for="priority" class="block text-sm font-medium text-gray-700 dark:text-gray-300">優先級</label>
<select name="priority" id="priority" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('All Priorities') }}</option>
<option value="low" @selected(request('priority') === 'low')>{{ __('Low') }}</option>
<option value="medium" @selected(request('priority') === 'medium')>{{ __('Medium') }}</option>
<option value="high" @selected(request('priority') === 'high')>{{ __('High') }}</option>
<option value="urgent" @selected(request('priority') === 'urgent')>{{ __('Urgent') }}</option>
<option value="">所有優先級</option>
<option value="low" @selected(request('priority') === 'low')></option>
<option value="medium" @selected(request('priority') === 'medium')></option>
<option value="high" @selected(request('priority') === 'high')></option>
<option value="urgent" @selected(request('priority') === 'urgent')>緊急</option>
</select>
</div>
<div>
<label for="assigned_to" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Assignee') }}</label>
<label for="assigned_to" class="block text-sm font-medium text-gray-700 dark:text-gray-300">指派對象</label>
<select name="assigned_to" id="assigned_to" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('All Assignees') }}</option>
<option value="">所有指派對象</option>
@foreach($users as $user)
<option value="{{ $user->id }}" @selected(request('assigned_to') == $user->id)>{{ $user->name }}</option>
@endforeach
@@ -100,14 +100,14 @@
</div>
<div class="flex gap-4">
<div class="flex-1">
<label for="search" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Search') }}</label>
<input type="text" name="search" id="search" value="{{ request('search') }}" placeholder="{{ __('Task number, title, or description...') }}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<label for="search" class="block text-sm font-medium text-gray-700 dark:text-gray-300">搜尋</label>
<input type="text" name="search" id="search" value="{{ request('search') }}" placeholder="任務編號、標題或描述..." class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
</div>
<div class="flex items-end gap-2">
<button type="submit" class="inline-flex justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600 dark:hover:bg-gray-600">{{ __('Filter') }}</button>
<button type="submit" class="inline-flex justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600 dark:hover:bg-gray-600">篩選</button>
<label class="inline-flex items-center">
<input type="checkbox" name="show_closed" value="1" @checked(request('show_closed') === '1') class="rounded border-gray-300 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:bg-gray-700 dark:border-gray-600">
<span class="ml-2 text-sm text-gray-700 dark:text-gray-300">{{ __('Show closed') }}</span>
<span class="ml-2 text-sm text-gray-700 dark:text-gray-300">顯示已結案</span>
</label>
</div>
</div>
@@ -116,16 +116,16 @@
<!-- Issues Table -->
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg dark:ring-gray-700">
<table class="min-w-full divide-y divide-gray-300 dark:divide-gray-600">
<caption class="sr-only">{{ __('List of tasks with their current status and assignment') }}</caption>
<caption class="sr-only">任務列表及其目前狀態與指派</caption>
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Task') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Type') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Status') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Priority') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Assignee') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Due Date') }}</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4"><span class="sr-only">{{ __('Actions') }}</span></th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">任務</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">類型</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">狀態</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">優先級</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">指派對象</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">截止日期</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4"><span class="sr-only">操作</span></th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white dark:divide-gray-700 dark:bg-gray-800">
@@ -163,7 +163,7 @@
<span class="{{ $issue->is_overdue ? 'text-red-600 dark:text-red-400 font-semibold' : '' }}">
{{ $issue->due_date->format('Y-m-d') }}
@if($issue->is_overdue)
<span class="text-xs">({{ __('Overdue') }})</span>
<span class="text-xs">(逾期)</span>
@endif
</span>
@else
@@ -171,16 +171,16 @@
@endif
</td>
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium">
<a href="{{ route('admin.issues.show', $issue) }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">{{ __('View') }}</a>
<a href="{{ route('admin.issues.show', $issue) }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">檢視</a>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-3 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
<p>{{ __('No tasks found') }}</p>
<p>找不到任務</p>
<div class="mt-4">
<a href="{{ route('admin.issues.create') }}" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400">
+ {{ __('Create First Task') }}
+ 新增第一個任務
</a>
</div>
</td>

View File

@@ -31,23 +31,23 @@
<div class="flex items-center gap-4 text-sm text-gray-500 dark:text-gray-400">
<span>{{ $issue->issue_type_label }}</span>
<span>"</span>
<span>{{ __('Created by') }} {{ $issue->creator->name }}</span>
<span>建立者 {{ $issue->creator->name }}</span>
<span>"</span>
<span>{{ $issue->created_at->diffForHumans() }}</span>
</div>
</div>
<div class="mt-4 sm:mt-0 flex gap-2">
@if(!$issue->isClosed() || Auth::user()->is_admin)
@if(!$issue->isClosed() || Auth::user()->hasRole('admin'))
<a href="{{ route('admin.issues.edit', $issue) }}" class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600">
{{ __('Edit') }}
編輯
</a>
@endif
@if(Auth::user()->is_admin)
<form method="POST" action="{{ route('admin.issues.destroy', $issue) }}" onsubmit="return confirm('{{ __('Are you sure?') }}')">
@if(Auth::user()->hasRole('admin'))
<form method="POST" action="{{ route('admin.issues.destroy', $issue) }}" onsubmit="return confirm('您確定嗎?')">
@csrf
@method('DELETE')
<button type="submit" class="inline-flex items-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 dark:bg-red-500 dark:hover:bg-red-400">
{{ __('Delete') }}
刪除
</button>
</form>
@endif
@@ -68,55 +68,55 @@
<!-- Description -->
<div class="prose dark:prose-invert max-w-none mb-6">
<h4 class="text-sm font-medium text-gray-900 dark:text-gray-100 mb-2">{{ __('Description') }}</h4>
<h4 class="text-sm font-medium text-gray-900 dark:text-gray-100 mb-2">描述</h4>
<div class="text-gray-700 dark:text-gray-300 whitespace-pre-wrap">{{ $issue->description ?: __('No description provided') }}</div>
</div>
<!-- Details Grid -->
<dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2 border-t border-gray-200 dark:border-gray-700 pt-6">
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Assigned To') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">指派對象</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $issue->assignee?->name ?? __('Unassigned') }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Reviewer') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">審查者</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $issue->reviewer?->name ?? __('None') }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Due Date') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">截止日期</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
@if($issue->due_date)
<span class="{{ $issue->is_overdue ? 'text-red-600 dark:text-red-400 font-semibold' : '' }}">
{{ $issue->due_date->format('Y-m-d') }}
@if($issue->is_overdue)
({{ __('Overdue by :days days', ['days' => abs($issue->days_until_due)]) }})
(逾期 {{ abs($issue->days_until_due) }} )
@elseif($issue->days_until_due !== null && $issue->days_until_due >= 0)
({{ __(':days days left', ['days' => $issue->days_until_due]) }})
({{ $issue->days_until_due }} 天剩餘)
@endif
</span>
@else
<span class="text-gray-400">{{ __('No due date') }}</span>
<span class="text-gray-400">無截止日期</span>
@endif
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Time Tracking') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">時間追蹤</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ number_format($issue->actual_hours, 1) }}h
@if($issue->estimated_hours)
/ {{ number_format($issue->estimated_hours, 1) }}h {{ __('estimated') }}
/ {{ number_format($issue->estimated_hours, 1) }}h 預估
@endif
</dd>
</div>
@if($issue->member)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Related Member') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">相關會員</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $issue->member->full_name }}</dd>
</div>
@endif
@if($issue->parentIssue)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Parent Issue') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">父任務</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
<a href="{{ route('admin.issues.show', $issue->parentIssue) }}" class="text-indigo-600 hover:underline dark:text-indigo-400">
{{ $issue->parentIssue->issue_number }} - {{ $issue->parentIssue->title }}
@@ -129,7 +129,7 @@
<!-- Sub-tasks -->
@if($issue->subTasks->count() > 0)
<div class="mt-6 border-t border-gray-200 dark:border-gray-700 pt-6">
<h4 class="text-sm font-medium text-gray-900 dark:text-gray-100 mb-3">{{ __('Sub-tasks') }} ({{ $issue->subTasks->count() }})</h4>
<h4 class="text-sm font-medium text-gray-900 dark:text-gray-100 mb-3">子任務 ({{ $issue->subTasks->count() }})</h4>
<ul class="space-y-2">
@foreach($issue->subTasks as $subTask)
<li class="flex items-center gap-2">
@@ -150,21 +150,21 @@
<!-- Workflow Actions -->
@if(!$issue->isClosed())
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Actions') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">操作</h3>
<div class="flex flex-wrap gap-2">
<!-- Update Status -->
<form method="POST" action="{{ route('admin.issues.update-status', $issue) }}" class="inline-flex gap-2">
@csrf
@method('PATCH')
<select name="status" class="rounded-md border-gray-300 text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="new" @selected($issue->status === 'new')>{{ __('New') }}</option>
<option value="assigned" @selected($issue->status === 'assigned')>{{ __('Assigned') }}</option>
<option value="in_progress" @selected($issue->status === 'in_progress')>{{ __('In Progress') }}</option>
<option value="review" @selected($issue->status === 'review')>{{ __('Review') }}</option>
<option value="closed" @selected($issue->status === 'closed')>{{ __('Closed') }}</option>
<option value="new" @selected($issue->status === 'new')></option>
<option value="assigned" @selected($issue->status === 'assigned')>已指派</option>
<option value="in_progress" @selected($issue->status === 'in_progress')>進行中</option>
<option value="review" @selected($issue->status === 'review')>審查</option>
<option value="closed" @selected($issue->status === 'closed')>已結案</option>
</select>
<button type="submit" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400">
{{ __('Update Status') }}
更新狀態
</button>
</form>
@@ -172,13 +172,13 @@
<form method="POST" action="{{ route('admin.issues.assign', $issue) }}" class="inline-flex gap-2">
@csrf
<select name="assigned_to_user_id" class="rounded-md border-gray-300 text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('Unassigned') }}</option>
<option value="">未指派</option>
@foreach($users as $user)
<option value="{{ $user->id }}" @selected($issue->assigned_to_user_id == $user->id)>{{ $user->name }}</option>
@endforeach
</select>
<button type="submit" class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600">
{{ __('Assign') }}
指派
</button>
</form>
</div>
@@ -188,7 +188,7 @@
<!-- Comments -->
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">
{{ __('Comments') }} ({{ $issue->comments->count() }})
留言 ({{ $issue->comments->count() }})
</h3>
<!-- Comments List -->
@@ -199,13 +199,13 @@
<span class="font-medium text-sm text-gray-900 dark:text-gray-100">{{ $comment->user->name }}</span>
<span class="text-xs text-gray-500 dark:text-gray-400">{{ $comment->created_at->diffForHumans() }}</span>
@if($comment->is_internal)
<span class="text-xs bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200 px-2 py-0.5 rounded">{{ __('Internal') }}</span>
<span class="text-xs bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200 px-2 py-0.5 rounded">內部</span>
@endif
</div>
<p class="text-sm text-gray-700 dark:text-gray-300 whitespace-pre-wrap">{{ $comment->comment_text }}</p>
</div>
@empty
<p class="text-sm text-gray-500 dark:text-gray-400 text-center py-4">{{ __('No comments yet') }}</p>
<p class="text-sm text-gray-500 dark:text-gray-400 text-center py-4">尚無留言</p>
@endforelse
</div>
@@ -214,14 +214,14 @@
@csrf
<textarea name="comment_text" rows="3" required
class="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 mb-2"
placeholder="{{ __('Add a comment...') }}"></textarea>
placeholder="新增留言..."></textarea>
<div class="flex items-center justify-between">
<label class="inline-flex items-center">
<input type="checkbox" name="is_internal" value="1" class="rounded border-gray-300 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:bg-gray-700 dark:border-gray-600">
<span class="ml-2 text-sm text-gray-700 dark:text-gray-300">{{ __('Internal comment') }}</span>
<span class="ml-2 text-sm text-gray-700 dark:text-gray-300">內部留言</span>
</label>
<button type="submit" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-500 dark:bg-indigo-500">
{{ __('Add Comment') }}
新增留言
</button>
</div>
</form>
@@ -230,7 +230,7 @@
<!-- Attachments -->
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">
{{ __('Attachments') }} ({{ $issue->attachments->count() }})
附件 ({{ $issue->attachments->count() }})
</h3>
<div class="space-y-2 mb-6">
@@ -246,18 +246,18 @@
</div>
</div>
<div class="flex gap-2">
<a href="{{ route('admin.issues.attachments.download', $attachment) }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 text-sm">{{ __('Download') }}</a>
@if(Auth::user()->is_admin)
<form method="POST" action="{{ route('admin.issues.attachments.destroy', $attachment) }}" onsubmit="return confirm('{{ __('Delete this attachment?') }}')">
<a href="{{ route('admin.issues.attachments.download', $attachment) }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 text-sm">下載</a>
@if(Auth::user()->hasRole('admin'))
<form method="POST" action="{{ route('admin.issues.attachments.destroy', $attachment) }}" onsubmit="return confirm('刪除此附件?')">
@csrf
@method('DELETE')
<button type="submit" class="text-red-600 hover:text-red-900 dark:text-red-400 text-sm">{{ __('Delete') }}</button>
<button type="submit" class="text-red-600 hover:text-red-900 dark:text-red-400 text-sm">刪除</button>
</form>
@endif
</div>
</div>
@empty
<p class="text-sm text-gray-500 dark:text-gray-400 text-center py-4">{{ __('No attachments') }}</p>
<p class="text-sm text-gray-500 dark:text-gray-400 text-center py-4">無附件</p>
@endforelse
</div>
@@ -267,17 +267,17 @@
<div class="flex items-center gap-2">
<input type="file" name="file" required class="block w-full text-sm text-gray-900 dark:text-gray-100 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100 dark:file:bg-indigo-900 dark:file:text-indigo-200">
<button type="submit" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-500 dark:bg-indigo-500">
{{ __('Upload') }}
上傳
</button>
</div>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">{{ __('Max size: 10MB') }}</p>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">最大大小10MB</p>
</form>
</div>
<!-- Time Logs -->
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">
{{ __('Time Tracking') }} ({{ number_format($issue->total_time_logged, 1) }}h total)
時間追蹤 ({{ number_format($issue->total_time_logged, 1) }}h total)
</h3>
<div class="space-y-2 mb-6">
@@ -289,21 +289,21 @@
</div>
</div>
@empty
<p class="text-sm text-gray-500 dark:text-gray-400 text-center py-4">{{ __('No time logged yet') }}</p>
<p class="text-sm text-gray-500 dark:text-gray-400 text-center py-4">尚未記錄時間</p>
@endforelse
</div>
<!-- Log Time Form -->
<form method="POST" action="{{ route('admin.issues.time-logs.store', $issue) }}" class="border-t border-gray-200 dark:border-gray-700 pt-4 grid grid-cols-2 gap-2">
@csrf
<input type="number" name="hours" step="0.25" min="0.25" placeholder="{{ __('Hours') }}" required
<input type="number" name="hours" step="0.25" min="0.25" placeholder="時數" required
class="rounded-md border-gray-300 text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<input type="date" name="logged_at" value="{{ now()->format('Y-m-d') }}" required
class="rounded-md border-gray-300 text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<input type="text" name="description" placeholder="{{ __('What did you do?') }}"
<input type="text" name="description" placeholder="您做了什麼?"
class="col-span-2 rounded-md border-gray-300 text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<button type="submit" class="col-span-2 inline-flex justify-center items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-500 dark:bg-indigo-500">
{{ __('Log Time') }}
記錄時間
</button>
</form>
</div>
@@ -313,11 +313,11 @@
<div class="space-y-6">
<!-- Timeline -->
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Progress') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">進度</h3>
<x-issue.timeline :issue="$issue" />
<div class="mt-4">
<div class="flex justify-between text-sm mb-1">
<span class="text-gray-700 dark:text-gray-300">{{ __('Completion') }}</span>
<span class="text-gray-700 dark:text-gray-300">完成度</span>
<span class="font-medium text-gray-900 dark:text-gray-100">{{ $issue->progress_percentage }}%</span>
</div>
<div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
@@ -329,7 +329,7 @@
<!-- Watchers -->
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">
{{ __('Watchers') }} ({{ $issue->watchers->count() }})
觀察者 ({{ $issue->watchers->count() }})
</h3>
<ul class="space-y-2 mb-4">
@@ -341,7 +341,7 @@
@csrf
@method('DELETE')
<input type="hidden" name="user_id" value="{{ $watcher->id }}">
<button type="submit" class="text-xs text-red-600 hover:text-red-900 dark:text-red-400">{{ __('Remove') }}</button>
<button type="submit" class="text-xs text-red-600 hover:text-red-900 dark:text-red-400">移除</button>
</form>
@endif
</li>
@@ -353,13 +353,13 @@
@csrf
<div class="flex gap-2">
<select name="user_id" required class="flex-1 rounded-md border-gray-300 text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('Add watcher...') }}</option>
<option value="">新增觀察者...</option>
@foreach($users->whereNotIn('id', $issue->watchers->pluck('id')) as $user)
<option value="{{ $user->id }}">{{ $user->name }}</option>
@endforeach
</select>
<button type="submit" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-500 dark:bg-indigo-500">
{{ __('Add') }}
新增
</button>
</div>
</form>

View File

@@ -1,13 +1,13 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Activate Membership') }} - {{ $member->full_name }}
啟用會員資格 - {{ $member->full_name }}
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-2xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg px-4 py-5 sm:p-6">
@if($approvedPayment)
{{-- Approved Payment Info --}}
@@ -19,12 +19,12 @@
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-green-800 dark:text-green-200">{{ __('Payment Approved') }}</h3>
<h3 class="text-sm font-medium text-green-800 dark:text-green-200">付款已核准</h3>
<div class="mt-2 text-sm text-green-700 dark:text-green-300">
<p>{{ __('Amount') }}: TWD {{ number_format($approvedPayment->amount, 0) }}</p>
<p>{{ __('Payment Date') }}: {{ $approvedPayment->paid_at->format('Y-m-d') }}</p>
<p>{{ __('Payment Method') }}: {{ $approvedPayment->payment_method_label }}</p>
<p>{{ __('Approved on') }}: {{ $approvedPayment->chair_verified_at->format('Y-m-d H:i') }}</p>
<p>金額: TWD {{ number_format($approvedPayment->amount, 0) }}</p>
<p>付款日期: {{ $approvedPayment->paid_at->format('Y-m-d') }}</p>
<p>付款方式: {{ $approvedPayment->payment_method_label }}</p>
<p>核准日期: {{ $approvedPayment->chair_verified_at->format('Y-m-d H:i') }}</p>
</div>
</div>
</div>
@@ -33,18 +33,18 @@
{{-- Member Info --}}
<div class="mb-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-3">{{ __('Member Information') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-3">會員資訊</h3>
<dl class="grid grid-cols-1 gap-x-4 gap-y-4 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Full Name') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">全名</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $member->full_name }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Email') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">電子郵件</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $member->email }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Current Status') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">目前狀態</dt>
<dd class="mt-1">
<span class="inline-flex items-center rounded-full px-2 py-1 text-xs font-medium {{ $member->membership_status_badge }}">
{{ $member->membership_status_label }}
@@ -59,19 +59,19 @@
@csrf
<div class="border-t border-gray-200 dark:border-gray-700 pt-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Membership Activation Details') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">會員啟用詳情</h3>
{{-- Membership Type --}}
<div>
<label for="membership_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Membership Type') }} <span class="text-red-500">*</span>
會員類型 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<select name="membership_type" id="membership_type" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('membership_type') border-red-300 @enderror">
<option value="regular" {{ old('membership_type', 'regular') == 'regular' ? 'selected' : '' }}>{{ __('Regular Member (一般會員)') }}</option>
<option value="student" {{ old('membership_type') == 'student' ? 'selected' : '' }}>{{ __('Student Member (學生會員)') }}</option>
<option value="honorary" {{ old('membership_type') == 'honorary' ? 'selected' : '' }}>{{ __('Honorary Member (榮譽會員)') }}</option>
<option value="lifetime" {{ old('membership_type') == 'lifetime' ? 'selected' : '' }}>{{ __('Lifetime Member (終身會員)') }}</option>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm @error('membership_type') border-red-300 @enderror">
<option value="regular" {{ old('membership_type', 'regular') == 'regular' ? 'selected' : '' }}>一般會員</option>
<option value="student" {{ old('membership_type') == 'student' ? 'selected' : '' }}>學生會員</option>
<option value="honorary" {{ old('membership_type') == 'honorary' ? 'selected' : '' }}>榮譽會員</option>
<option value="lifetime" {{ old('membership_type') == 'lifetime' ? 'selected' : '' }}>終身會員</option>
</select>
@error('membership_type')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
@@ -79,23 +79,23 @@
{{-- Start Date --}}
<div class="mt-4">
<label for="membership_started_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Membership Start Date') }} <span class="text-red-500">*</span>
會員資格開始日 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<input type="date" name="membership_started_at" id="membership_started_at"
value="{{ old('membership_started_at', today()->format('Y-m-d')) }}" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('membership_started_at') border-red-300 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm @error('membership_started_at') border-red-300 @enderror">
@error('membership_started_at')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
{{-- End Date --}}
<div class="mt-4">
<label for="membership_expires_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Membership Expiry Date') }} <span class="text-red-500">*</span>
會員資格到期日 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<input type="date" name="membership_expires_at" id="membership_expires_at"
value="{{ old('membership_expires_at', today()->addYear()->format('Y-m-d')) }}" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('membership_expires_at') border-red-300 @enderror">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">{{ __('Default: One year from start date') }}</p>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm @error('membership_expires_at') border-red-300 @enderror">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">預設:開始日期後一年</p>
@error('membership_expires_at')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
</div>
@@ -110,21 +110,21 @@
</div>
<div class="ml-3">
<p class="text-sm text-blue-700 dark:text-blue-300">
{{ __('After activation, the member will receive a confirmation email and gain access to member-only resources.') }}
啟用後,會員將收到確認電子郵件並獲得會員專屬資源的存取權限。
</p>
</div>
</div>
</div>
{{-- Submit Buttons --}}
<div class="flex items-center justify-end gap-x-4 border-t border-gray-200 pt-6 dark:border-gray-700">
<div class="flex items-center justify-end gap-x-4 border-t border-gray-200 dark:border-gray-700 pt-6">
<a href="{{ route('admin.members.show', $member) }}"
class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600">
{{ __('Cancel') }}
class="rounded-md bg-white dark:bg-gray-700 px-3 py-2 text-sm font-semibold text-gray-900 dark:text-gray-100 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600">
取消
</a>
<button type="submit"
class="inline-flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400">
{{ __('Activate Membership') }}
class="inline-flex justify-center rounded-md bg-indigo-600 dark:bg-indigo-500 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 dark:hover:bg-indigo-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
啟用會員資格
</button>
</div>
</form>
@@ -168,4 +168,4 @@
}
});
</script>
</x-app-layout>
</x-app-layout>

View File

@@ -1,236 +1,236 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Create new member') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
新增會員
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
@if (session('status'))
<div class="mb-4 rounded-md bg-green-50 p-4" role="status" aria-live="polite">
<p class="text-sm font-medium text-green-800">
<div class="mb-4 rounded-md bg-green-50 dark:bg-green-900/50 p-4" role="status" aria-live="polite">
<p class="text-sm font-medium text-green-800 dark:text-green-200">
{{ session('status') }}
</p>
</div>
@endif
<form method="POST" action="{{ route('admin.members.store') }}" class="space-y-6" aria-label="{{ __('Create member form') }}">
<form method="POST" action="{{ route('admin.members.store') }}" class="space-y-6" aria-label="新增會員表單">
@csrf
<div>
<label for="full_name" class="block text-sm font-medium text-gray-700">
{{ __('Full name') }}
<label for="full_name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
全名
</label>
<input
type="text"
name="full_name"
id="full_name"
value="{{ old('full_name') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
@error('full_name')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="email" class="block text-sm font-medium text-gray-700">
{{ __('Email') }}
<label for="email" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
電子郵件
</label>
<input
type="email"
name="email"
id="email"
value="{{ old('email') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
@error('email')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
<p class="mt-1 text-sm text-gray-500">
{{ __('An activation email will be sent to this address.') }}
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
啟用電子郵件將發送至此地址。
</p>
</div>
<div>
<label for="national_id" class="block text-sm font-medium text-gray-700">
{{ __('National ID') }}
<label for="national_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
身分證號
</label>
<input
type="text"
name="national_id"
id="national_id"
value="{{ old('national_id') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
autocomplete="off"
>
@error('national_id')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
<p class="mt-1 text-sm text-gray-500">
{{ __('Will be stored encrypted for security.') }}
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
將加密儲存以確保安全。
</p>
</div>
<div>
<label for="phone" class="block text-sm font-medium text-gray-700">
{{ __('Phone') }}
<label for="phone" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
電話
</label>
<input
type="text"
name="phone"
id="phone"
value="{{ old('phone') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('phone')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="grid gap-6 sm:grid-cols-2">
<div>
<label for="membership_started_at" class="block text-sm font-medium text-gray-700">
{{ __('Membership start date') }}
<label for="membership_started_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
會員資格開始日
</label>
<input
type="date"
name="membership_started_at"
id="membership_started_at"
value="{{ old('membership_started_at') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('membership_started_at')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="membership_expires_at" class="block text-sm font-medium text-gray-700">
{{ __('Membership expiry date') }}
<label for="membership_expires_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
會員資格到期日
</label>
<input
type="date"
name="membership_expires_at"
id="membership_expires_at"
value="{{ old('membership_expires_at') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('membership_expires_at')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
<div>
<label for="address_line_1" class="block text-sm font-medium text-gray-700">
{{ __('Address Line 1') }}
<label for="address_line_1" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
地址第1行
</label>
<input
type="text"
name="address_line_1"
id="address_line_1"
value="{{ old('address_line_1') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('address_line_1')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="address_line_2" class="block text-sm font-medium text-gray-700">
{{ __('Address Line 2') }}
<label for="address_line_2" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
地址第2行
</label>
<input
type="text"
name="address_line_2"
id="address_line_2"
value="{{ old('address_line_2') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('address_line_2')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="grid gap-6 sm:grid-cols-2">
<div>
<label for="city" class="block text-sm font-medium text-gray-700">
{{ __('City') }}
<label for="city" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
城市
</label>
<input
type="text"
name="city"
id="city"
value="{{ old('city') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('city')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="postal_code" class="block text-sm font-medium text-gray-700">
{{ __('Postal Code') }}
<label for="postal_code" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
郵遞區號
</label>
<input
type="text"
name="postal_code"
id="postal_code"
value="{{ old('postal_code') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('postal_code')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
<div>
<label for="emergency_contact_name" class="block text-sm font-medium text-gray-700">
{{ __('Emergency Contact Name') }}
<label for="emergency_contact_name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
緊急聯絡人姓名
</label>
<input
type="text"
name="emergency_contact_name"
id="emergency_contact_name"
value="{{ old('emergency_contact_name') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('emergency_contact_name')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="emergency_contact_phone" class="block text-sm font-medium text-gray-700">
{{ __('Emergency Contact Phone') }}
<label for="emergency_contact_phone" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
緊急聯絡人電話
</label>
<input
type="text"
name="emergency_contact_phone"
id="emergency_contact_phone"
value="{{ old('emergency_contact_phone') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('emergency_contact_phone')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="flex justify-end gap-3">
<a href="{{ route('admin.members.index') }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Cancel') }}
<a href="{{ route('admin.members.index') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
取消
</a>
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Create member') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
新增會員
</button>
</div>
</form>

View File

@@ -1,17 +1,17 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Edit member') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
編輯會員
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
@if (session('status'))
<div class="mb-4 rounded-md bg-green-50 p-4" role="status" aria-live="polite">
<p class="text-sm font-medium text-green-800">
<div class="mb-4 rounded-md bg-green-50 dark:bg-green-900/50 p-4" role="status" aria-live="polite">
<p class="text-sm font-medium text-green-800 dark:text-green-200">
{{ session('status') }}
</p>
</div>
@@ -22,210 +22,210 @@
@method('PATCH')
<div>
<label for="full_name" class="block text-sm font-medium text-gray-700">
{{ __('Full name') }}
<label for="full_name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
全名
</label>
<input
type="text"
name="full_name"
id="full_name"
value="{{ old('full_name', $member->full_name) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
@error('full_name')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="email" class="block text-sm font-medium text-gray-700">
{{ __('Email') }}
<label for="email" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
電子郵件
</label>
<input
type="email"
name="email"
id="email"
value="{{ old('email', $member->email) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
@error('email')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="national_id" class="block text-sm font-medium text-gray-700">
{{ __('National ID') }}
<label for="national_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
身分證號
</label>
<input
type="text"
name="national_id"
id="national_id"
value="{{ old('national_id', $member->national_id) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
autocomplete="off"
>
@error('national_id')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
<p class="mt-1 text-sm text-gray-500">
{{ __('Will be stored encrypted for security.') }}
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
將加密儲存以確保安全。
</p>
</div>
<div>
<label for="phone" class="block text-sm font-medium text-gray-700">
{{ __('Phone') }}
<label for="phone" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
電話
</label>
<input
type="text"
name="phone"
id="phone"
value="{{ old('phone', $member->phone) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('phone')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="grid gap-6 sm:grid-cols-2">
<div>
<label for="membership_started_at" class="block text-sm font-medium text-gray-700">
{{ __('Membership start date') }}
<label for="membership_started_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
會員資格開始日
</label>
<input
type="date"
name="membership_started_at"
id="membership_started_at"
value="{{ old('membership_started_at', optional($member->membership_started_at)->toDateString()) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('membership_started_at')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="membership_expires_at" class="block text-sm font-medium text-gray-700">
{{ __('Membership expiry date') }}
<label for="membership_expires_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
會員資格到期日
</label>
<input
type="date"
name="membership_expires_at"
id="membership_expires_at"
value="{{ old('membership_expires_at', optional($member->membership_expires_at)->toDateString()) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('membership_expires_at')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
<div>
<label for="address_line_1" class="block text-sm font-medium text-gray-700">
{{ __('Address Line 1') }}
<label for="address_line_1" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
地址第1行
</label>
<input
type="text"
name="address_line_1"
id="address_line_1"
value="{{ old('address_line_1', $member->address_line_1) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('address_line_1')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="address_line_2" class="block text-sm font-medium text-gray-700">
{{ __('Address Line 2') }}
<label for="address_line_2" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
地址第2行
</label>
<input
type="text"
name="address_line_2"
id="address_line_2"
value="{{ old('address_line_2', $member->address_line_2) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('address_line_2')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="grid gap-6 sm:grid-cols-2">
<div>
<label for="city" class="block text-sm font-medium text-gray-700">
{{ __('City') }}
<label for="city" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
城市
</label>
<input
type="text"
name="city"
id="city"
value="{{ old('city', $member->city) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('city')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="postal_code" class="block text-sm font-medium text-gray-700">
{{ __('Postal Code') }}
<label for="postal_code" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
郵遞區號
</label>
<input
type="text"
name="postal_code"
id="postal_code"
value="{{ old('postal_code', $member->postal_code) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('postal_code')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
<div>
<label for="emergency_contact_name" class="block text-sm font-medium text-gray-700">
{{ __('Emergency Contact Name') }}
<label for="emergency_contact_name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
緊急聯絡人姓名
</label>
<input
type="text"
name="emergency_contact_name"
id="emergency_contact_name"
value="{{ old('emergency_contact_name', $member->emergency_contact_name) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('emergency_contact_name')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="emergency_contact_phone" class="block text-sm font-medium text-gray-700">
{{ __('Emergency Contact Phone') }}
<label for="emergency_contact_phone" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
緊急聯絡人電話
</label>
<input
type="text"
name="emergency_contact_phone"
id="emergency_contact_phone"
value="{{ old('emergency_contact_phone', $member->emergency_contact_phone) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('emergency_contact_phone')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="flex justify-end">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Save changes') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
儲存變更
</button>
</div>
</form>

View File

@@ -1,54 +1,54 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Import members from CSV') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
從CSV匯入會員
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<p class="text-sm text-gray-700 mb-4">
{{ __('Upload a CSV file with the following header columns (existing members matched by email are updated):') }}
<p class="text-sm text-gray-700 dark:text-gray-300 mb-4">
上傳具有以下標題列的CSV檔案現有會員將依電子郵件比對並更新
</p>
<ul class="list-disc list-inside text-sm text-gray-700 mb-4 space-y-1">
<li><code>full_name</code></li>
<li><code>email</code></li>
<li><code>phone</code></li>
<li><code>address_line_1</code> (optional)</li>
<li><code>address_line_2</code> (optional)</li>
<li><code>city</code> (optional)</li>
<li><code>postal_code</code> (optional)</li>
<li><code>emergency_contact_name</code> (optional)</li>
<li><code>emergency_contact_phone</code> (optional)</li>
<li><code>membership_started_at</code> (YYYY-MM-DD)</li>
<li><code>membership_expires_at</code> (YYYY-MM-DD)</li>
<ul class="list-disc list-inside text-sm text-gray-700 dark:text-gray-300 mb-4 space-y-1">
<li><code class="text-gray-800 dark:text-gray-200">full_name</code></li>
<li><code class="text-gray-800 dark:text-gray-200">email</code></li>
<li><code class="text-gray-800 dark:text-gray-200">phone</code></li>
<li><code class="text-gray-800 dark:text-gray-200">address_line_1</code> (optional)</li>
<li><code class="text-gray-800 dark:text-gray-200">address_line_2</code> (optional)</li>
<li><code class="text-gray-800 dark:text-gray-200">city</code> (optional)</li>
<li><code class="text-gray-800 dark:text-gray-200">postal_code</code> (optional)</li>
<li><code class="text-gray-800 dark:text-gray-200">emergency_contact_name</code> (optional)</li>
<li><code class="text-gray-800 dark:text-gray-200">emergency_contact_phone</code> (optional)</li>
<li><code class="text-gray-800 dark:text-gray-200">membership_started_at</code> (YYYY-MM-DD)</li>
<li><code class="text-gray-800 dark:text-gray-200">membership_expires_at</code> (YYYY-MM-DD)</li>
</ul>
<form method="POST" action="{{ route('admin.members.import') }}" enctype="multipart/form-data" class="space-y-6">
@csrf
<div>
<label for="file" class="block text-sm font-medium text-gray-700">
{{ __('CSV file') }}
<label for="file" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
CSV檔案
</label>
<input
type="file"
name="file"
id="file"
accept=".csv,text/csv"
class="mt-1 block w-full text-sm text-gray-900 file:mr-4 file:rounded-md file:border-0 file:bg-indigo-50 file:px-4 file:py-2 file:text-sm file:font-semibold file:text-indigo-700 hover:file:bg-indigo-100"
class="mt-1 block w-full text-sm text-gray-900 dark:text-gray-100 file:mr-4 file:rounded-md file:border-0 file:bg-indigo-50 dark:file:bg-indigo-900/50 file:px-4 file:py-2 file:text-sm file:font-semibold file:text-indigo-700 dark:file:text-indigo-300 hover:file:bg-indigo-100 dark:hover:file:bg-indigo-900"
required
>
@error('file')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="flex justify-end">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Start import') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
開始匯入
</button>
</div>
</form>

View File

@@ -1,170 +1,236 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Members') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
會員管理
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="GET" action="{{ route('admin.members.index') }}" class="mb-4 space-y-4" role="search" aria-label="{{ __('Search and filter members') }}">
<form method="GET" action="{{ route('admin.members.index') }}" class="mb-4 space-y-4" role="search" aria-label="搜尋和篩選會員">
<div>
<label for="search" class="block text-sm font-medium text-gray-700">
{{ __('Search by name, email, phone, or national ID') }}
<label for="search" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
依姓名、電子郵件、電話或身分證號搜尋
</label>
<input
type="text"
name="search"
id="search"
value="{{ $filters['search'] ?? '' }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
placeholder="{{ __('Enter search term...') }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="輸入搜尋關鍵字..."
>
<p class="mt-1 text-xs text-gray-500">
{{ __('Searches in name, email, phone number, and national ID') }}
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
在姓名、電子郵件、電話號碼和身分證號中搜尋
</p>
</div>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
<div>
<label for="status" class="block text-sm font-medium text-gray-700">
{{ __('Membership status') }}
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
會員資格狀態
</label>
<select
id="status"
name="status"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
<option value="">{{ __('All') }}</option>
<option value="active" @selected(($filters['status'] ?? '') === 'active')>{{ __('Active') }}</option>
<option value="expired" @selected(($filters['status'] ?? '') === 'expired')>{{ __('Expired') }}</option>
<option value="expiring_soon" @selected(($filters['status'] ?? '') === 'expiring_soon')>{{ __('Expiring Soon (30 days)') }}</option>
<option value="">所有</option>
<option value="active" @selected(($filters['status'] ?? '') === 'active')>使用中</option>
<option value="expired" @selected(($filters['status'] ?? '') === 'expired')>已過期</option>
<option value="expiring_soon" @selected(($filters['status'] ?? '') === 'expiring_soon')>即將到期30天內</option>
</select>
</div>
<div>
<label for="payment_status" class="block text-sm font-medium text-gray-700">
{{ __('Payment status') }}
<label for="payment_status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
付款狀態
</label>
<select
id="payment_status"
name="payment_status"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
<option value="">{{ __('All') }}</option>
<option value="has_payments" @selected(($filters['payment_status'] ?? '') === 'has_payments')>{{ __('Has Payments') }}</option>
<option value="no_payments" @selected(($filters['payment_status'] ?? '') === 'no_payments')>{{ __('No Payments') }}</option>
<option value="">所有</option>
<option value="has_payments" @selected(($filters['payment_status'] ?? '') === 'has_payments')>有付款記錄</option>
<option value="no_payments" @selected(($filters['payment_status'] ?? '') === 'no_payments')>無付款記錄</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">
{{ __('Date range') }}
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">
日期範圍
</label>
<button
type="button"
onclick="document.getElementById('dateFilters').classList.toggle('hidden')"
class="mt-1 inline-flex w-full items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
class="mt-1 inline-flex w-full items-center justify-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800"
>
{{ __('Toggle Date Filters') }}
切換日期篩選
</button>
</div>
</div>
<div id="dateFilters" class="{{ (($filters['started_from'] ?? '') || ($filters['started_to'] ?? '')) ? '' : 'hidden' }} grid grid-cols-1 gap-4 sm:grid-cols-2">
<div>
<label for="started_from" class="block text-sm font-medium text-gray-700">
{{ __('Joined from') }}
<label for="started_from" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
加入起始
</label>
<input
type="date"
name="started_from"
id="started_from"
value="{{ $filters['started_from'] ?? '' }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
</div>
<div>
<label for="started_to" class="block text-sm font-medium text-gray-700">
{{ __('Joined to') }}
<label for="started_to" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
加入結束
</label>
<input
type="date"
name="started_to"
id="started_to"
value="{{ $filters['started_to'] ?? '' }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
</div>
</div>
<div class="flex flex-wrap items-center gap-2 justify-between">
<div class="flex gap-2">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Apply filters') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
套用篩選
</button>
<a href="{{ route('admin.members.export', request()->only('search','status')) }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Export CSV') }}
<a href="{{ route('admin.members.export', request()->only('search','status')) }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
匯出CSV
</a>
</div>
<div class="flex gap-2">
<a href="{{ route('admin.members.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-green-600 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2">
{{ __('Create Member') }}
<a href="{{ route('admin.members.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-green-600 dark:bg-green-500 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 dark:hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500 dark:focus:ring-green-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
新增會員
</a>
<a href="{{ route('admin.members.import-form') }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Import CSV') }}
<a href="{{ route('admin.members.import-form') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
匯入CSV
</a>
</div>
</div>
</form>
<!-- Batch Actions Toolbar (Hidden by default) -->
<div id="batchActions" class="hidden mb-4 p-4 bg-gray-50 dark:bg-gray-700 rounded-md border border-gray-200 dark:border-gray-600 flex items-center justify-between">
<div class="flex items-center space-x-4">
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">
<span id="selectedCount">0</span> 已選擇
</span>
<!-- Batch Delete -->
<form id="batchDeleteForm" action="{{ route('admin.members.batch-destroy') }}" method="POST" onsubmit="return confirm('您確定要刪除選取的會員嗎?');">
@csrf
<div id="batchDeleteInputs"></div>
<button type="submit" class="text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300 text-sm font-medium">
刪除所選
</button>
</form>
<span class="text-gray-300 dark:text-gray-500">|</span>
<!-- Batch Update Status -->
<form id="batchStatusForm" action="{{ route('admin.members.batch-update-status') }}" method="POST" class="flex items-center space-x-2">
@csrf
<div id="batchStatusInputs"></div>
<select name="status" required class="text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100 rounded-md shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600">
<option value="">設定狀態...</option>
<option value="active">活躍</option>
<option value="pending">待審核</option>
<option value="expired">已過期</option>
<option value="suspended">已停權</option>
</select>
<button type="submit" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-800 dark:hover:text-indigo-300 text-sm font-medium">
更新
</button>
</form>
</div>
</div>
<div class="mt-4 overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200" role="table">
<thead class="bg-gray-50">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700" role="table">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
{{ __('Name') }}
<th scope="col" class="px-4 py-3 text-left">
<input type="checkbox" id="selectAll" class="rounded border-gray-300 dark:border-gray-600 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-800">
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
{{ __('Email') }}
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
名稱
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
{{ __('Membership Expires') }}
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
電子郵件
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">
<span class="sr-only">{{ __('Actions') }}</span>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
角色
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
會員資格到期
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
狀態
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
<span class="sr-only">操作</span>
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse ($members as $member)
<tr>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900">
<td class="px-4 py-3">
<input type="checkbox" name="selected_ids[]" value="{{ $member->id }}" class="member-checkbox rounded border-gray-300 dark:border-gray-600 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-700">
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ $member->full_name }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900">
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ $member->email }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900">
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
@if($member->user && $member->user->roles->isNotEmpty())
<div class="flex flex-wrap gap-1">
@foreach($member->user->roles as $role)
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-indigo-100 dark:bg-indigo-900 text-indigo-800 dark:text-indigo-200">
{{ $role->name }}
</span>
@endforeach
</div>
@else
<span class="text-gray-500 dark:text-gray-400">-</span>
@endif
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
@if ($member->membership_expires_at)
{{ $member->membership_expires_at->toDateString() }}
@else
<span class="text-gray-500">{{ __('Not set') }}</span>
<span class="text-gray-500 dark:text-gray-400">未設定</span>
@endif
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm">
<span class="inline-flex rounded-full px-2 text-xs font-semibold leading-5 {{ $member->membership_status_badge }}">
{{ $member->membership_status_label }}
</span>
</td>
<td class="whitespace-nowrap px-4 py-3 text-right text-sm font-medium">
<a href="{{ route('admin.members.show', $member) }}" class="text-indigo-600 hover:text-indigo-900">
{{ __('View') }}
<a href="{{ route('admin.members.show', $member) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
檢視
</a>
</td>
</tr>
@empty
<tr>
<td colspan="4" class="px-4 py-4 text-sm text-gray-500">
{{ __('No members found.') }}
<td colspan="7" class="px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
找不到會員。
</td>
</tr>
@endforelse
@@ -179,4 +245,56 @@
</div>
</div>
</div>
</x-app-layout>
<script>
document.addEventListener('DOMContentLoaded', function() {
const selectAll = document.getElementById('selectAll');
const checkboxes = document.querySelectorAll('.member-checkbox');
const batchActions = document.getElementById('batchActions');
const selectedCount = document.getElementById('selectedCount');
const batchDeleteInputs = document.getElementById('batchDeleteInputs');
const batchStatusInputs = document.getElementById('batchStatusInputs');
function updateBatchUI() {
const selected = Array.from(checkboxes).filter(cb => cb.checked);
selectedCount.textContent = selected.length;
if (selected.length > 0) {
batchActions.classList.remove('hidden');
} else {
batchActions.classList.add('hidden');
}
// Update hidden inputs for forms
batchDeleteInputs.innerHTML = '';
batchStatusInputs.innerHTML = '';
selected.forEach(cb => {
const input1 = document.createElement('input');
input1.type = 'hidden';
input1.name = 'ids[]';
input1.value = cb.value;
batchDeleteInputs.appendChild(input1);
const input2 = document.createElement('input');
input2.type = 'hidden';
input2.name = 'ids[]';
input2.value = cb.value;
batchStatusInputs.appendChild(input2);
});
}
selectAll.addEventListener('change', function() {
checkboxes.forEach(cb => cb.checked = selectAll.checked);
updateBatchUI();
});
checkboxes.forEach(cb => {
cb.addEventListener('change', function() {
updateBatchUI();
selectAll.checked = Array.from(checkboxes).every(c => c.checked);
});
});
});
</script>
</x-app-layout>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Member details') }}
會員詳情
</h2>
</x-slot>
@@ -15,7 +15,7 @@
->first();
@endphp
@if($approvedPayment && $member->isPending() && (Auth::user()->can('activate_memberships') || Auth::user()->is_admin))
@if($approvedPayment && $member->isPending() && (Auth::user()->can('activate_memberships') || Auth::user()->hasRole('admin')))
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
<div class="flex">
<div class="flex-shrink-0">
@@ -25,14 +25,14 @@
</div>
<div class="ml-3 flex-1">
<h3 class="text-sm font-medium text-green-800 dark:text-green-200">
{{ __('Ready for Activation') }}
準備啟用
</h3>
<div class="mt-2 text-sm text-green-700 dark:text-green-300">
<p>{{ __('This member has a fully approved payment and is ready for membership activation.') }}</p>
<p>此會員的付款已完全核准,準備啟用會員資格。</p>
</div>
<div class="mt-4">
<a href="{{ route('admin.members.activate', $member) }}" class="inline-flex items-center rounded-md bg-green-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600">
{{ __('Activate Membership') }}
<a href="{{ route('admin.members.activate', $member) }}" class="inline-flex items-center rounded-md bg-green-600 dark:bg-green-500 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 dark:hover:bg-green-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600">
啟用會員資格
</a>
</div>
</div>
@@ -45,29 +45,40 @@
<div class="flex items-center justify-between mb-4">
<div class="flex items-center gap-3">
@if ($member->user?->profilePhotoUrl())
<img src="{{ $member->user->profilePhotoUrl() }}" alt="{{ __('Profile photo') }}" class="h-16 w-16 rounded-full object-cover ring-2 ring-indigo-500">
<img src="{{ $member->user->profilePhotoUrl() }}" alt="個人照片" class="h-16 w-16 rounded-full object-cover ring-2 ring-indigo-500">
@endif
<div>
<h3 id="member-info-heading" class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">
{{ $member->full_name }}
</h3>
<div class="mt-1 flex items-center gap-2">
{!! $member->membership_status_badge !!}
@php
$statusClasses = match($member->membership_status) {
'pending' => 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200',
'active' => 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
'expired' => 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200',
'suspended' => 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200',
default => 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200',
};
@endphp
<span class="inline-flex rounded-full px-2 text-xs font-semibold leading-5 {{ $statusClasses }}">
{{ $member->membership_status_label }}
</span>
<span class="inline-flex items-center rounded-md bg-gray-100 dark:bg-gray-700 px-2.5 py-0.5 text-xs font-medium text-gray-800 dark:text-gray-200">
{{ $member->membership_type_label }}
</span>
</div>
</div>
</div>
<a href="{{ route('admin.members.edit', $member) }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Edit') }}
<a href="{{ route('admin.members.edit', $member) }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
編輯
</a>
</div>
<dl class="mt-5 grid grid-cols-1 gap-5 sm:grid-cols-2">
<div class="overflow-hidden rounded-lg bg-gray-50 dark:bg-gray-700 px-4 py-5 sm:p-6">
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">
{{ __('Email') }}
電子郵件
</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $member->email }}
@@ -76,7 +87,7 @@
<div class="overflow-hidden rounded-lg bg-gray-50 dark:bg-gray-700 px-4 py-5 sm:p-6">
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">
{{ __('Phone') }}
電話
</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $member->phone ?? __('Not set') }}
@@ -85,7 +96,7 @@
<div class="overflow-hidden rounded-lg bg-gray-50 dark:bg-gray-700 px-4 py-5 sm:p-6">
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">
{{ __('Membership Status') }}
會員資格狀態
</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $member->membership_status_label }}
@@ -94,7 +105,7 @@
<div class="overflow-hidden rounded-lg bg-gray-50 dark:bg-gray-700 px-4 py-5 sm:p-6">
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">
{{ __('Membership Type') }}
會員類型
</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $member->membership_type_label }}
@@ -103,35 +114,35 @@
<div class="overflow-hidden rounded-lg bg-gray-50 dark:bg-gray-700 px-4 py-5 sm:p-6">
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">
{{ __('Membership start') }}
會員資格開始
</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
@if ($member->membership_started_at)
{{ $member->membership_started_at->toDateString() }}
@else
{{ __('Not set') }}
未設定
@endif
</dd>
</div>
<div class="overflow-hidden rounded-lg bg-gray-50 dark:bg-gray-700 px-4 py-5 sm:p-6">
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">
{{ __('Membership expires') }}
會員資格到期
</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
@if ($member->membership_expires_at)
{{ $member->membership_expires_at->toDateString() }}
@else
{{ __('Not set') }}
未設定
@endif
</dd>
</div>
<div class="overflow-hidden rounded-lg bg-gray-50 px-4 py-5 sm:p-6 sm:col-span-2">
<dt class="truncate text-sm font-medium text-gray-500">
{{ __('Address') }}
<div class="overflow-hidden rounded-lg bg-gray-50 dark:bg-gray-700 px-4 py-5 sm:p-6 sm:col-span-2">
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">
地址
</dt>
<dd class="mt-1 text-sm text-gray-900 space-y-1">
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 space-y-1">
<div>{{ $member->address_line_1 ?? __('Not set') }}</div>
@if ($member->address_line_2)
<div>{{ $member->address_line_2 }}</div>
@@ -145,43 +156,75 @@
</dd>
</div>
<div class="overflow-hidden rounded-lg bg-gray-50 px-4 py-5 sm:p-6 sm:col-span-2">
<dt class="truncate text-sm font-medium text-gray-500">
{{ __('Emergency Contact') }}
<div class="overflow-hidden rounded-lg bg-gray-50 dark:bg-gray-700 px-4 py-5 sm:p-6 sm:col-span-2">
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">
緊急聯絡人
</dt>
<dd class="mt-1 text-sm text-gray-900 space-y-1">
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 space-y-1">
<div>{{ $member->emergency_contact_name ?? __('Not set') }}</div>
<div>{{ $member->emergency_contact_phone ?? '' }}</div>
</dd>
</div>
{{-- Disability Certificate Status --}}
<div class="overflow-hidden rounded-lg bg-gray-50 dark:bg-gray-700 px-4 py-5 sm:p-6 sm:col-span-2">
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-400">
身心障礙手冊
</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
<div class="flex items-center gap-3">
<span class="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium {{ $member->disability_status_badge }}">
{{ $member->disability_status_label }}
</span>
@if($member->hasDisabilityCertificate())
<a href="{{ route('admin.members.disability-certificate', $member) }}" target="_blank" class="text-indigo-600 dark:text-indigo-400 hover:underline text-sm">
檢視手冊
</a>
@endif
</div>
@if($member->hasApprovedDisability() && $member->disability_verified_at)
<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">
審核時間:{{ $member->disability_verified_at->format('Y/m/d H:i') }}
@if($member->disabilityVerifiedBy)
(審核人:{{ $member->disabilityVerifiedBy->name }}
@endif
</p>
@endif
@if($member->isDisabilityRejected() && $member->disability_rejection_reason)
<p class="mt-2 text-xs text-red-500 dark:text-red-400">
駁回原因:{{ $member->disability_rejection_reason }}
</p>
@endif
</dd>
</div>
</dl>
</div>
</section>
@if ($member->user)
<section aria-labelledby="roles-heading" class="bg-white shadow sm:rounded-lg">
<section aria-labelledby="roles-heading" class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6 space-y-4">
<div class="flex items-center justify-between">
<h3 id="roles-heading" class="text-lg font-medium leading-6 text-gray-900">
{{ __('Roles') }}
<h3 id="roles-heading" class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">
角色管理
</h3>
</div>
<div class="flex flex-wrap gap-2">
@forelse ($member->user->roles as $role)
<span class="inline-flex items-center rounded-full bg-indigo-100 px-3 py-1 text-sm font-medium text-indigo-800">
<span class="inline-flex items-center rounded-full bg-indigo-100 dark:bg-indigo-900 px-3 py-1 text-sm font-medium text-indigo-800 dark:text-indigo-200">
{{ $role->name }}
</span>
@empty
<p class="text-sm text-gray-500">{{ __('No roles assigned.') }}</p>
<p class="text-sm text-gray-500 dark:text-gray-400">未指派角色。</p>
@endforelse
</div>
<form method="POST" action="{{ route('admin.members.roles.update', $member) }}" class="space-y-3">
@csrf
@method('PATCH')
<p class="text-sm text-gray-600">
{{ __('Select roles for this member\'s user account.') }}
<p class="text-sm text-gray-600 dark:text-gray-400">
選擇此會員使用者帳戶的角色。
</p>
<div class="grid gap-3 sm:grid-cols-2">
@foreach ($roles as $role)
@@ -191,18 +234,18 @@
name="roles[]"
value="{{ $role->name }}"
@checked($member->user->hasRole($role->name))
class="rounded border-gray-300 text-indigo-600 shadow-sm focus:ring-indigo-500"
class="rounded border-gray-300 dark:border-gray-600 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:bg-gray-700"
>
<span class="text-sm text-gray-800">
<span class="text-sm text-gray-800 dark:text-gray-200">
{{ $role->name }}
<span class="block text-xs text-gray-500">{{ $role->description }}</span>
<span class="block text-xs text-gray-500 dark:text-gray-400">{{ $role->description }}</span>
</span>
</label>
@endforeach
</div>
<div class="flex justify-end">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Update Roles') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
更新角色
</button>
</div>
</form>
@@ -214,10 +257,10 @@
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center justify-between">
<h3 id="admin-payment-history-heading" class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">
{{ __('Payment history') }}
付款歷史
</h3>
<a href="{{ route('admin.members.payments.create', $member) }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Record payment') }}
<a href="{{ route('admin.members.payments.create', $member) }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
記錄付款
</a>
</div>
@@ -226,22 +269,22 @@
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
{{ __('Paid at') }}
付款時間
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
{{ __('Amount') }}
金額
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
{{ __('Method') }}
方式
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
{{ __('Status') }}
狀態
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
{{ __('Submitted By') }}
提交者
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
{{ __('Actions') }}
操作
</th>
</tr>
</thead>
@@ -269,29 +312,29 @@
<span class="text-xs">{{ $payment->submittedBy->name }}</span>
</div>
@else
<span class="text-xs text-gray-500 dark:text-gray-400">{{ __('Admin') }}</span>
<span class="text-xs text-gray-500 dark:text-gray-400">管理員</span>
@endif
</td>
<td class="whitespace-nowrap px-4 py-3 text-right text-sm space-x-3">
@if($payment->status)
{{-- New payment verification system --}}
@if(Auth::user()->can('view_payment_verifications') || Auth::user()->is_admin)
@if(Auth::user()->can('view_payment_verifications') || Auth::user()->hasRole('admin'))
<a href="{{ route('admin.payment-verifications.show', $payment) }}" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300">
{{ __('Verify') }}
驗證
</a>
@endif
@if($payment->receipt_path)
<a href="{{ route('admin.payment-verifications.download-receipt', $payment) }}" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300" title="{{ __('Download Receipt') }}">
{{ __('Receipt') }}
<a href="{{ route('admin.payment-verifications.download-receipt', $payment) }}" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300" title="下載收據">
收據
</a>
@endif
@else
{{-- Legacy admin-created payments --}}
<a href="{{ route('admin.members.payments.receipt', [$member, $payment]) }}" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300" title="{{ __('Download Receipt') }}">
{{ __('Receipt') }}
<a href="{{ route('admin.members.payments.receipt', [$member, $payment]) }}" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300" title="下載收據">
收據
</a>
<a href="{{ route('admin.members.payments.edit', [$member, $payment]) }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
{{ __('Edit') }}
編輯
</a>
@endif
</td>
@@ -302,7 +345,7 @@
<svg class="mx-auto h-12 w-12 text-gray-400 dark:text-gray-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
</svg>
<p class="mt-2">{{ __('No payment records found.') }}</p>
<p class="mt-2">找不到付款記錄。</p>
</td>
</tr>
@endforelse
@@ -313,4 +356,4 @@
</section>
</div>
</div>
</x-app-layout>
</x-app-layout>

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
製作付款單
</h2>
</x-slot>
@@ -8,41 +8,41 @@
<div class="py-12">
<div class="mx-auto max-w-4xl sm:px-6 lg:px-8 space-y-4">
@if (session('error'))
<div class="rounded-md bg-red-50 p-4">
<p class="text-sm font-medium text-red-800">{{ session('error') }}</p>
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<!-- Finance Document Info -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">財務申請單資訊</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">報銷申請單資訊</h3>
<dl class="grid grid-cols-1 gap-x-4 gap-y-4 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500">申請標題</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $financeDocument->title }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">申請標題</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $financeDocument->title }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">申請金額</dt>
<dd class="mt-1 text-sm text-gray-900">NT$ {{ number_format($financeDocument->amount, 2) }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">申請金額</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">NT$ {{ number_format($financeDocument->amount, 2) }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">申請類型</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $financeDocument->getRequestTypeText() }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">申請類型</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $financeDocument->getRequestTypeText() }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">金額級別</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $financeDocument->getAmountTierText() }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">金額級別</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $financeDocument->getAmountTierText() }}</dd>
</div>
@if($financeDocument->member)
<div>
<dt class="text-sm font-medium text-gray-500">關聯會員</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $financeDocument->member->full_name }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">關聯會員</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $financeDocument->member->full_name }}</dd>
</div>
@endif
<div>
<dt class="text-sm font-medium text-gray-500">申請人</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $financeDocument->submittedBy->name }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">申請人</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $financeDocument->submittedBy->name }}</dd>
</div>
</dl>
</div>
@@ -52,98 +52,98 @@
<form method="POST" action="{{ route('admin.payment-orders.store', $financeDocument) }}" class="space-y-4">
@csrf
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">付款單資訊</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">付款單資訊</h3>
<div class="grid grid-cols-1 gap-6">
<!-- Payee Name -->
<div>
<label for="payee_name" class="block text-sm font-medium text-gray-700">
收款人姓名 <span class="text-red-500">*</span>
<label for="payee_name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
收款人姓名 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<input type="text" name="payee_name" id="payee_name" required
value="{{ old('payee_name', $financeDocument->member->full_name ?? '') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('payee_name') border-red-300 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300 @error('payee_name') border-red-300 dark:border-red-700 @enderror">
@error('payee_name')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Payment Method -->
<div>
<label for="payment_method" class="block text-sm font-medium text-gray-700">
付款方式 <span class="text-red-500">*</span>
<label for="payment_method" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
付款方式 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<select name="payment_method" id="payment_method" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('payment_method') border-red-300 @enderror">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300 @error('payment_method') border-red-300 dark:border-red-700 @enderror">
<option value="">請選擇付款方式</option>
<option value="bank_transfer" {{ old('payment_method') == 'bank_transfer' ? 'selected' : '' }}>銀行轉帳</option>
<option value="check" {{ old('payment_method') == 'check' ? 'selected' : '' }}>支票</option>
<option value="cash" {{ old('payment_method') == 'cash' ? 'selected' : '' }}>現金</option>
</select>
@error('payment_method')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Bank Information (shown when bank_transfer is selected) -->
<div id="bank_info" class="space-y-4" style="display: none;">
<div>
<label for="payee_bank_name" class="block text-sm font-medium text-gray-700">
<label for="payee_bank_name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
銀行名稱
</label>
<input type="text" name="payee_bank_name" id="payee_bank_name"
value="{{ old('payee_bank_name') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
</div>
<div>
<label for="payee_bank_code" class="block text-sm font-medium text-gray-700">
<label for="payee_bank_code" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
銀行代碼
</label>
<input type="text" name="payee_bank_code" id="payee_bank_code" maxlength="10"
value="{{ old('payee_bank_code') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
</div>
<div>
<label for="payee_account_number" class="block text-sm font-medium text-gray-700">
<label for="payee_account_number" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
銀行帳號
</label>
<input type="text" name="payee_account_number" id="payee_account_number" maxlength="30"
value="{{ old('payee_account_number') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
</div>
</div>
<!-- Payment Amount -->
<div>
<label for="payment_amount" class="block text-sm font-medium text-gray-700">
付款金額 <span class="text-red-500">*</span>
<label for="payment_amount" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
付款金額 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<div class="relative mt-1 rounded-md shadow-sm">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<span class="text-gray-500 sm:text-sm">NT$</span>
<span class="text-gray-500 dark:text-gray-400 sm:text-sm">NT$</span>
</div>
<input type="number" name="payment_amount" id="payment_amount" step="0.01" min="0" required
value="{{ old('payment_amount', $financeDocument->amount) }}"
class="block w-full rounded-md border-gray-300 pl-12 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm @error('payment_amount') border-red-300 @enderror">
class="block w-full rounded-md border-gray-300 dark:border-gray-700 pl-12 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300 @error('payment_amount') border-red-300 dark:border-red-700 @enderror">
</div>
@error('payment_amount')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Notes -->
<div>
<label for="notes" class="block text-sm font-medium text-gray-700">
<label for="notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
備註
</label>
<textarea name="notes" id="notes" rows="3"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">{{ old('notes') }}</textarea>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">{{ old('notes') }}</textarea>
@error('notes')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
@@ -152,10 +152,10 @@
<!-- Form Actions -->
<div class="flex justify-end space-x-3">
<a href="{{ route('admin.finance.show', $financeDocument) }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<a href="{{ route('admin.finance.show', $financeDocument) }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
取消
</a>
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
製作付款單
</button>
</div>

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
付款單管理
</h2>
</x-slot>
@@ -8,24 +8,24 @@
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-4">
@if (session('status'))
<div class="rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 p-4">
<p class="text-sm font-medium text-red-800">{{ session('error') }}</p>
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<!-- Filters -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="GET" action="{{ route('admin.payment-orders.index') }}" class="grid grid-cols-1 gap-4 sm:grid-cols-4">
<div>
<label for="status" class="block text-sm font-medium text-gray-700">狀態</label>
<select name="status" id="status" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">狀態</label>
<select name="status" id="status" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部</option>
<option value="draft" {{ request('status') == 'draft' ? 'selected' : '' }}>草稿</option>
<option value="pending_verification" {{ request('status') == 'pending_verification' ? 'selected' : '' }}>待出納覆核</option>
@@ -36,8 +36,8 @@
</div>
<div>
<label for="verification_status" class="block text-sm font-medium text-gray-700">覆核狀態</label>
<select name="verification_status" id="verification_status" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
<label for="verification_status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">覆核狀態</label>
<select name="verification_status" id="verification_status" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部</option>
<option value="pending" {{ request('verification_status') == 'pending' ? 'selected' : '' }}>待覆核</option>
<option value="approved" {{ request('verification_status') == 'approved' ? 'selected' : '' }}>已通過</option>
@@ -46,8 +46,8 @@
</div>
<div>
<label for="execution_status" class="block text-sm font-medium text-gray-700">執行狀態</label>
<select name="execution_status" id="execution_status" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
<label for="execution_status" class="block text-sm font-medium text-gray-700 dark:text-gray-300">執行狀態</label>
<select name="execution_status" id="execution_status" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300">
<option value="">全部</option>
<option value="pending" {{ request('execution_status') == 'pending' ? 'selected' : '' }}>待執行</option>
<option value="completed" {{ request('execution_status') == 'completed' ? 'selected' : '' }}>已完成</option>
@@ -56,10 +56,10 @@
</div>
<div class="flex items-end">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
篩選
</button>
<a href="{{ route('admin.payment-orders.index') }}" class="ml-2 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<a href="{{ route('admin.payment-orders.index') }}" class="ml-2 inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
清除
</a>
</div>
@@ -68,73 +68,73 @@
</div>
<!-- Payment Orders Table -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
付款單號
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
收款人
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
金額
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
付款方式
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
狀態
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
製單人
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500">
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
<span class="sr-only">操作</span>
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse ($paymentOrders as $order)
<tr>
<td class="whitespace-nowrap px-4 py-4 text-sm font-medium text-gray-900">
<td class="whitespace-nowrap px-4 py-4 text-sm font-medium text-gray-900 dark:text-gray-100">
{{ $order->payment_order_number }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500">
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
{{ $order->payee_name }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500">
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
NT$ {{ number_format($order->payment_amount, 2) }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500">
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
{{ $order->getPaymentMethodText() }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm">
<span class="inline-flex rounded-full px-2 text-xs font-semibold leading-5
@if($order->status === 'executed') bg-green-100 text-green-800
@elseif($order->status === 'verified') bg-blue-100 text-blue-800
@elseif($order->status === 'pending_verification') bg-yellow-100 text-yellow-800
@elseif($order->status === 'cancelled') bg-red-100 text-red-800
@else bg-gray-100 text-gray-800
@if($order->status === 'executed') bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200
@elseif($order->status === 'verified') bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200
@elseif($order->status === 'pending_verification') bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200
@elseif($order->status === 'cancelled') bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200
@else bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-300
@endif">
{{ $order->getStatusText() }}
</span>
</td>
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500">
<td class="whitespace-nowrap px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
{{ $order->createdByAccountant->name ?? 'N/A' }}
</td>
<td class="whitespace-nowrap px-4 py-4 text-right text-sm font-medium">
<a href="{{ route('admin.payment-orders.show', $order) }}" class="text-indigo-600 hover:text-indigo-900">
<a href="{{ route('admin.payment-orders.show', $order) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
查看
</a>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-8 text-center text-sm text-gray-500">
<td colspan="7" class="px-4 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
沒有付款單記錄
</td>
</tr>

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
付款單詳情: {{ $paymentOrder->payment_order_number }}
</h2>
</x-slot>
@@ -8,28 +8,28 @@
<div class="py-12">
<div class="mx-auto max-w-5xl sm:px-6 lg:px-8 space-y-4">
@if (session('status'))
<div class="rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 p-4">
<p class="text-sm font-medium text-red-800">{{ session('error') }}</p>
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
<p class="text-sm font-medium text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
<!-- Payment Order Info -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-medium leading-6 text-gray-900">付款單資訊</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">付款單資訊</h3>
<span class="inline-flex rounded-full px-3 py-1 text-sm font-semibold
@if($paymentOrder->status === 'executed') bg-green-100 text-green-800
@elseif($paymentOrder->status === 'verified') bg-blue-100 text-blue-800
@elseif($paymentOrder->status === 'pending_verification') bg-yellow-100 text-yellow-800
@elseif($paymentOrder->status === 'cancelled') bg-red-100 text-red-800
@else bg-gray-100 text-gray-800
@if($paymentOrder->status === 'executed') bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200
@elseif($paymentOrder->status === 'verified') bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200
@elseif($paymentOrder->status === 'pending_verification') bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200
@elseif($paymentOrder->status === 'cancelled') bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200
@else bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-300
@endif">
{{ $paymentOrder->getStatusText() }}
</span>
@@ -37,48 +37,48 @@
<dl class="grid grid-cols-1 gap-x-4 gap-y-4 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500">付款單號</dt>
<dd class="mt-1 text-sm text-gray-900 font-mono">{{ $paymentOrder->payment_order_number }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款單號</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 font-mono">{{ $paymentOrder->payment_order_number }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">收款人</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->payee_name }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">收款人</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->payee_name }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">付款金額</dt>
<dd class="mt-1 text-sm text-gray-900 font-semibold">NT$ {{ number_format($paymentOrder->payment_amount, 2) }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款金額</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 font-semibold">NT$ {{ number_format($paymentOrder->payment_amount, 2) }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">付款方式</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->getPaymentMethodText() }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款方式</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->getPaymentMethodText() }}</dd>
</div>
@if($paymentOrder->payment_method === 'bank_transfer')
<div>
<dt class="text-sm font-medium text-gray-500">銀行名稱</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->payee_bank_name ?? 'N/A' }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">銀行名稱</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->payee_bank_name ?? 'N/A' }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">銀行代碼</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->payee_bank_code ?? 'N/A' }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">銀行代碼</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->payee_bank_code ?? 'N/A' }}</dd>
</div>
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500">銀行帳號</dt>
<dd class="mt-1 text-sm text-gray-900 font-mono">{{ $paymentOrder->payee_account_number ?? 'N/A' }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">銀行帳號</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 font-mono">{{ $paymentOrder->payee_account_number ?? 'N/A' }}</dd>
</div>
@endif
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500">製單人(會計)</dt>
<dd class="mt-1 text-sm text-gray-900">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">製單人(會計)</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $paymentOrder->createdByAccountant->name }} - {{ $paymentOrder->created_at->format('Y-m-d H:i') }}
</dd>
</div>
@if($paymentOrder->notes)
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500">備註</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->notes }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">備註</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->notes }}</dd>
</div>
@endif
</dl>
@@ -86,27 +86,27 @@
</div>
<!-- Verification Section -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">出納覆核</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">出納覆核</h3>
@if($paymentOrder->verified_at)
<dl class="grid grid-cols-1 gap-x-4 gap-y-4 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500">覆核人</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->verifiedByCashier->name }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">覆核人</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->verifiedByCashier->name }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">覆核時間</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->verified_at->format('Y-m-d H:i') }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">覆核時間</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->verified_at->format('Y-m-d H:i') }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">覆核狀態</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">覆核狀態</dt>
<dd class="mt-1 text-sm">
<span class="inline-flex rounded-full px-2 text-xs font-semibold
@if($paymentOrder->verification_status === 'approved') bg-green-100 text-green-800
@elseif($paymentOrder->verification_status === 'rejected') bg-red-100 text-red-800
@else bg-yellow-100 text-yellow-800
@if($paymentOrder->verification_status === 'approved') bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200
@elseif($paymentOrder->verification_status === 'rejected') bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200
@else bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200
@endif">
@if($paymentOrder->verification_status === 'approved') 通過
@elseif($paymentOrder->verification_status === 'rejected') 駁回
@@ -117,30 +117,30 @@
</div>
@if($paymentOrder->verification_notes)
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500">覆核備註</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->verification_notes }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">覆核備註</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->verification_notes }}</dd>
</div>
@endif
</dl>
@else
<p class="text-sm text-gray-500 mb-4">此付款單待出納覆核</p>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">此付款單待出納覆核</p>
@can('verify_payment_order')
@if($paymentOrder->canBeVerifiedByCashier())
<form method="POST" action="{{ route('admin.payment-orders.verify', $paymentOrder) }}" class="space-y-4">
@csrf
<div>
<label for="verification_notes" class="block text-sm font-medium text-gray-700">覆核備註</label>
<label for="verification_notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">覆核備註</label>
<textarea name="verification_notes" id="verification_notes" rows="3"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"></textarea>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"></textarea>
</div>
<div class="flex space-x-3">
<button type="submit" name="action" value="approve"
class="inline-flex items-center rounded-md border border-transparent bg-green-600 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2">
class="inline-flex items-center rounded-md border border-transparent bg-green-600 dark:bg-green-500 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 dark:hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500 dark:focus:ring-green-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
通過覆核
</button>
<button type="submit" name="action" value="reject"
class="inline-flex items-center rounded-md border border-transparent bg-red-600 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">
class="inline-flex items-center rounded-md border border-transparent bg-red-600 dark:bg-red-500 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 dark:hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 dark:focus:ring-red-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
駁回
</button>
</div>
@@ -152,27 +152,27 @@
</div>
<!-- Execution Section -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">付款執行</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">付款執行</h3>
@if($paymentOrder->executed_at)
<dl class="grid grid-cols-1 gap-x-4 gap-y-4 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500">執行人</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->executedByCashier->name }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">執行人</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->executedByCashier->name }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">執行時間</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->executed_at->format('Y-m-d H:i') }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">執行時間</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->executed_at->format('Y-m-d H:i') }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">執行狀態</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">執行狀態</dt>
<dd class="mt-1 text-sm">
<span class="inline-flex rounded-full px-2 text-xs font-semibold
@if($paymentOrder->execution_status === 'completed') bg-green-100 text-green-800
@elseif($paymentOrder->execution_status === 'failed') bg-red-100 text-red-800
@else bg-yellow-100 text-yellow-800
@if($paymentOrder->execution_status === 'completed') bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200
@elseif($paymentOrder->execution_status === 'failed') bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200
@else bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200
@endif">
@if($paymentOrder->execution_status === 'completed') 已完成
@elseif($paymentOrder->execution_status === 'failed') 失敗
@@ -183,15 +183,15 @@
</div>
@if($paymentOrder->transaction_reference)
<div>
<dt class="text-sm font-medium text-gray-500">交易參考號</dt>
<dd class="mt-1 text-sm text-gray-900 font-mono">{{ $paymentOrder->transaction_reference }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">交易參考號</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 font-mono">{{ $paymentOrder->transaction_reference }}</dd>
</div>
@endif
@if($paymentOrder->payment_receipt_path)
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500">付款憑證</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款憑證</dt>
<dd class="mt-1">
<a href="{{ route('admin.payment-orders.download-receipt', $paymentOrder) }}" class="text-indigo-600 hover:text-indigo-900">
<a href="{{ route('admin.payment-orders.download-receipt', $paymentOrder) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
下載憑證
</a>
</dd>
@@ -199,41 +199,41 @@
@endif
</dl>
@else
<p class="text-sm text-gray-500 mb-4">此付款單待執行付款</p>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">此付款單待執行付款</p>
@can('execute_payment')
@if($paymentOrder->canBeExecuted())
<form method="POST" action="{{ route('admin.payment-orders.execute', $paymentOrder) }}" enctype="multipart/form-data" class="space-y-4">
@csrf
<div>
<label for="transaction_reference" class="block text-sm font-medium text-gray-700">
交易參考號 <span class="text-red-500">*</span>
<label for="transaction_reference" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
交易參考號 <span class="text-red-500 dark:text-red-400">*</span>
</label>
<input type="text" name="transaction_reference" id="transaction_reference" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
<p class="mt-1 text-xs text-gray-500">銀行交易編號或支票號碼</p>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">銀行交易編號或支票號碼</p>
</div>
<div>
<label for="payment_receipt" class="block text-sm font-medium text-gray-700">
<label for="payment_receipt" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
付款憑證
</label>
<input type="file" name="payment_receipt" id="payment_receipt"
class="mt-1 block w-full text-sm text-gray-500
class="mt-1 block w-full text-sm text-gray-500 dark:text-gray-400
file:mr-4 file:py-2 file:px-4
file:rounded-md file:border-0
file:text-sm file:font-semibold
file:bg-indigo-50 file:text-indigo-700
hover:file:bg-indigo-100">
<p class="mt-1 text-xs text-gray-500">上傳轉帳收據或付款證明(最大 10MB</p>
file:bg-indigo-50 dark:file:bg-indigo-900/50 file:text-indigo-700 dark:file:text-indigo-300
hover:file:bg-indigo-100 dark:hover:file:bg-indigo-800">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">上傳轉帳收據或付款證明(最大 10MB</p>
</div>
<div>
<label for="execution_notes" class="block text-sm font-medium text-gray-700">執行備註</label>
<label for="execution_notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">執行備註</label>
<textarea name="execution_notes" id="execution_notes" rows="3"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"></textarea>
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"></textarea>
</div>
<div>
<button type="submit"
class="inline-flex items-center rounded-md border border-transparent bg-green-600 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2">
class="inline-flex items-center rounded-md border border-transparent bg-green-600 dark:bg-green-500 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 dark:hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500 dark:focus:ring-green-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
確認執行付款
</button>
</div>
@@ -245,31 +245,31 @@
</div>
<!-- Related Finance Document -->
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-4">關聯財務申請單</h3>
<h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100 mb-4">關聯報銷申請單</h3>
<dl class="grid grid-cols-1 gap-x-4 gap-y-4 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500">申請標題</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->financeDocument->title }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">申請標題</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->financeDocument->title }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">申請類型</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->financeDocument->getRequestTypeText() }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">申請類型</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->financeDocument->getRequestTypeText() }}</dd>
</div>
@if($paymentOrder->financeDocument->member)
<div>
<dt class="text-sm font-medium text-gray-500">關聯會員</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->financeDocument->member->full_name }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">關聯會員</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->financeDocument->member->full_name }}</dd>
</div>
@endif
<div>
<dt class="text-sm font-medium text-gray-500">申請人</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $paymentOrder->financeDocument->submittedBy->name }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">申請人</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $paymentOrder->financeDocument->submittedBy->name }}</dd>
</div>
</dl>
<div class="mt-4">
<a href="{{ route('admin.finance.show', $paymentOrder->financeDocument) }}" class="text-indigo-600 hover:text-indigo-900">
<a href="{{ route('admin.finance.show', $paymentOrder->financeDocument) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
查看完整申請單
</a>
</div>
@@ -278,7 +278,7 @@
<!-- Actions -->
<div class="flex justify-between">
<a href="{{ route('admin.payment-orders.index') }}" class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<a href="{{ route('admin.payment-orders.index') }}" class="inline-flex items-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
返回列表
</a>
@@ -286,7 +286,7 @@
@if(!$paymentOrder->isExecuted() && $paymentOrder->status !== 'cancelled')
<form method="POST" action="{{ route('admin.payment-orders.cancel', $paymentOrder) }}" onsubmit="return confirm('確定要取消此付款單嗎?');">
@csrf
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-red-600 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-red-600 dark:bg-red-500 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 dark:hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 dark:focus:ring-red-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
取消付款單
</button>
</form>

View File

@@ -1,20 +1,20 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Payment Verification Dashboard') }}
付款驗證控制台
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
@if (session('status'))
<div class="mb-4 rounded-md bg-green-50 p-4 dark:bg-green-900/30 border-l-4 border-green-400">
<div class="mb-4 rounded-md bg-green-50 p-4 dark:bg-green-900/30 border-l-4 border-green-400 dark:border-green-500">
<p class="text-sm text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="mb-4 rounded-md bg-red-50 p-4 dark:bg-red-900/30 border-l-4 border-red-400">
<div class="mb-4 rounded-md bg-red-50 p-4 dark:bg-red-900/30 border-l-4 border-red-400 dark:border-red-500">
<p class="text-sm text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
@@ -23,14 +23,14 @@
<div class="mb-4 border-b border-gray-200 dark:border-gray-700">
<nav class="-mb-px flex space-x-8">
<a href="{{ route('admin.payment-verifications.index', ['tab' => 'all']) }}"
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'all' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300' }}">
{{ __('All Payments') }}
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'all' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 dark:hover:border-gray-600' }}">
所有付款
</a>
@can('verify_payments_cashier')
<a href="{{ route('admin.payment-verifications.index', ['tab' => 'cashier']) }}"
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'cashier' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300' }}">
{{ __('Cashier Queue') }}
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'cashier' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 dark:hover:border-gray-600' }}">
出納待處理
@if($counts['pending'] > 0)
<span class="ml-2 rounded-full bg-red-100 px-2 py-0.5 text-xs font-medium text-red-800 dark:bg-red-900 dark:text-red-200">
{{ $counts['pending'] }}
@@ -41,8 +41,8 @@
@can('verify_payments_accountant')
<a href="{{ route('admin.payment-verifications.index', ['tab' => 'accountant']) }}"
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'accountant' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300' }}">
{{ __('Accountant Queue') }}
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'accountant' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 dark:hover:border-gray-600' }}">
會計待處理
@if($counts['cashier_approved'] > 0)
<span class="ml-2 rounded-full bg-red-100 px-2 py-0.5 text-xs font-medium text-red-800 dark:bg-red-900 dark:text-red-200">
{{ $counts['cashier_approved'] }}
@@ -53,8 +53,8 @@
@can('verify_payments_chair')
<a href="{{ route('admin.payment-verifications.index', ['tab' => 'chair']) }}"
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'chair' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300' }}">
{{ __('Chair Queue') }}
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'chair' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 dark:hover:border-gray-600' }}">
主席待處理
@if($counts['accountant_approved'] > 0)
<span class="ml-2 rounded-full bg-red-100 px-2 py-0.5 text-xs font-medium text-red-800 dark:bg-red-900 dark:text-red-200">
{{ $counts['accountant_approved'] }}
@@ -64,13 +64,13 @@
@endcan
<a href="{{ route('admin.payment-verifications.index', ['tab' => 'approved']) }}"
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'approved' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300' }}">
{{ __('Approved') }} ({{ $counts['approved'] }})
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'approved' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 dark:hover:border-gray-600' }}">
已核准 ({{ $counts['approved'] }})
</a>
<a href="{{ route('admin.payment-verifications.index', ['tab' => 'rejected']) }}"
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'rejected' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300' }}">
{{ __('Rejected') }} ({{ $counts['rejected'] }})
class="border-b-2 py-4 px-1 text-sm font-medium {{ $tab === 'rejected' ? 'border-indigo-500 text-indigo-600 dark:text-indigo-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 dark:hover:border-gray-600' }}">
已拒絕 ({{ $counts['rejected'] }})
</a>
</nav>
</div>
@@ -79,10 +79,10 @@
<div class="mb-4">
<form method="GET" action="{{ route('admin.payment-verifications.index') }}" class="flex gap-2">
<input type="hidden" name="tab" value="{{ $tab }}">
<input type="text" name="search" value="{{ request('search') }}" placeholder="{{ __('Search by member name, email, or reference...') }}"
<input type="text" name="search" value="{{ request('search') }}" placeholder="依會員姓名、電子郵件或參考編號搜尋..."
class="flex-1 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<button type="submit" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
{{ __('Search') }}
<button type="submit" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400">
搜尋
</button>
</form>
</div>
@@ -93,13 +93,13 @@
<table class="min-w-full divide-y divide-gray-300 dark:divide-gray-600">
<thead class="bg-gray-50 dark:bg-gray-900">
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Member') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Amount') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Payment Date') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Method') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Status') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Submitted') }}</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4"><span class="sr-only">{{ __('Actions') }}</span></th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">會員</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">金額</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">付款日期</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">方式</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">狀態</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">已提交</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4"><span class="sr-only">操作</span></th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white dark:divide-gray-700 dark:bg-gray-800">
@@ -133,14 +133,14 @@
</td>
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium">
<a href="{{ route('admin.payment-verifications.show', $payment) }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
{{ __('View & Verify') }}
查看與驗證
</a>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-3 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
{{ __('No payments found') }}
找不到付款記錄
</td>
</tr>
@endforelse
@@ -154,4 +154,4 @@
</div>
</div>
</div>
</x-app-layout>
</x-app-layout>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Payment Verification') }} - {{ $payment->member->full_name }}
付款驗證 - {{ $payment->member->full_name }}
</h2>
</x-slot>
@@ -9,32 +9,32 @@
<div class="mx-auto max-w-4xl sm:px-6 lg:px-8 space-y-6">
@if (session('status'))
<div class="rounded-md bg-green-50 p-4 dark:bg-green-900/30 border-l-4 border-green-400">
<div class="rounded-md bg-green-50 p-4 dark:bg-green-900/30 border-l-4 border-green-400 dark:border-green-500">
<p class="text-sm text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
@if (session('error'))
<div class="rounded-md bg-red-50 p-4 dark:bg-red-900/30 border-l-4 border-red-400">
<div class="rounded-md bg-red-50 p-4 dark:bg-red-900/30 border-l-4 border-red-400 dark:border-red-500">
<p class="text-sm text-red-800 dark:text-red-200">{{ session('error') }}</p>
</div>
@endif
{{-- Payment Details --}}
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Payment Details') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">付款詳情</h3>
<dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2">
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Member') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">會員</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $payment->member->full_name }}<br>
<span class="text-gray-500">{{ $payment->member->email }}</span>
<span class="text-gray-500 dark:text-gray-400">{{ $payment->member->email }}</span>
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Status') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">狀態</dt>
<dd class="mt-1">
<span class="inline-flex items-center rounded-full px-2 py-1 text-xs font-medium
@if($payment->status === 'pending') bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200
@@ -48,27 +48,53 @@
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Amount') }}</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">TWD {{ number_format($payment->amount, 0) }}</dd>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">會費類型</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $payment->fee_type_label }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Payment Date') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">繳納金額</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">TWD {{ number_format($payment->amount, 0) }}</dd>
</div>
@if($payment->base_amount)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">原始金額</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">TWD {{ number_format($payment->base_amount, 0) }}</dd>
</div>
@endif
@if($payment->disability_discount)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">身心障礙優惠</dt>
<dd class="mt-1 text-sm text-green-600 dark:text-green-400">-TWD {{ number_format($payment->discount_amount, 0) }}</dd>
</div>
@endif
@if($payment->final_amount)
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">應繳金額</dt>
<dd class="mt-1 text-sm font-semibold text-indigo-600 dark:text-indigo-400">TWD {{ number_format($payment->final_amount, 0) }}</dd>
</div>
@endif
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款日期</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $payment->paid_at->format('Y-m-d') }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Payment Method') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款方式</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $payment->payment_method_label }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Reference Number') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">參考編號</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ $payment->reference ?? '—' }}</dd>
</div>
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Submitted By') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">提交者</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100">
{{ $payment->submittedBy->name }} on {{ $payment->created_at->format('Y-m-d H:i') }}
</dd>
@@ -76,21 +102,21 @@
@if($payment->notes)
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Notes') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">備註</dt>
<dd class="mt-1 text-sm text-gray-900 dark:text-gray-100 whitespace-pre-line">{{ $payment->notes }}</dd>
</div>
@endif
@if($payment->receipt_path)
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ __('Payment Receipt') }}</dt>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">付款收據</dt>
<dd class="mt-1">
<a href="{{ route('admin.payment-verifications.download-receipt', $payment) }}" target="_blank"
class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600">
<svg class="-ml-0.5 mr-1.5 h-5 w-5 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600 dark:hover:bg-gray-600">
<svg class="-ml-0.5 mr-1.5 h-5 w-5 text-gray-400 dark:text-gray-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
{{ __('Download Receipt') }}
下載收據
</a>
</dd>
</div>
@@ -100,7 +126,7 @@
{{-- Verification History --}}
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Verification History') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">驗證歷史</h3>
<div class="flow-root">
<ul role="list" class="-mb-8">
@@ -112,7 +138,7 @@
<svg class="h-5 w-5 text-white" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" /></svg>
</span></div>
<div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
<div><p class="text-sm text-gray-500 dark:text-gray-400">{{ __('Verified by Cashier') }}: <span class="font-medium text-gray-900 dark:text-gray-100">{{ $payment->verifiedByCashier->name }}</span></p></div>
<div><p class="text-sm text-gray-500 dark:text-gray-400">出納已驗證: <span class="font-medium text-gray-900 dark:text-gray-100">{{ $payment->verifiedByCashier->name }}</span></p></div>
<div class="whitespace-nowrap text-right text-sm text-gray-500 dark:text-gray-400">{{ $payment->cashier_verified_at->format('Y-m-d H:i') }}</div>
</div>
</div>
@@ -128,7 +154,7 @@
<svg class="h-5 w-5 text-white" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" /></svg>
</span></div>
<div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
<div><p class="text-sm text-gray-500 dark:text-gray-400">{{ __('Verified by Accountant') }}: <span class="font-medium text-gray-900 dark:text-gray-100">{{ $payment->verifiedByAccountant->name }}</span></p></div>
<div><p class="text-sm text-gray-500 dark:text-gray-400">會計已驗證: <span class="font-medium text-gray-900 dark:text-gray-100">{{ $payment->verifiedByAccountant->name }}</span></p></div>
<div class="whitespace-nowrap text-right text-sm text-gray-500 dark:text-gray-400">{{ $payment->accountant_verified_at->format('Y-m-d H:i') }}</div>
</div>
</div>
@@ -144,7 +170,7 @@
<svg class="h-5 w-5 text-white" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" /></svg>
</span></div>
<div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
<div><p class="text-sm text-gray-500 dark:text-gray-400">{{ __('Final Approval by Chair') }}: <span class="font-medium text-gray-900 dark:text-gray-100">{{ $payment->verifiedByChair->name }}</span></p></div>
<div><p class="text-sm text-gray-500 dark:text-gray-400">主席最終核准: <span class="font-medium text-gray-900 dark:text-gray-100">{{ $payment->verifiedByChair->name }}</span></p></div>
<div class="whitespace-nowrap text-right text-sm text-gray-500 dark:text-gray-400">{{ $payment->chair_verified_at->format('Y-m-d H:i') }}</div>
</div>
</div>
@@ -161,7 +187,7 @@
</span></div>
<div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
<div>
<p class="text-sm text-gray-500 dark:text-gray-400">{{ __('Rejected by') }}: <span class="font-medium text-gray-900 dark:text-gray-100">{{ $payment->rejectedBy->name }}</span></p>
<p class="text-sm text-gray-500 dark:text-gray-400">拒絕者: <span class="font-medium text-gray-900 dark:text-gray-100">{{ $payment->rejectedBy->name }}</span></p>
@if($payment->rejection_reason)
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $payment->rejection_reason }}</p>
@endif
@@ -179,18 +205,56 @@
{{-- Verification Actions --}}
@if(!$payment->isRejected() && !$payment->isFullyApproved())
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Verification Actions') }}</h3>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">驗證操作</h3>
<div class="space-y-4">
@if($payment->canBeApprovedByCashier() && Auth::user()->can('verify_payments_cashier'))
<form method="POST" action="{{ route('admin.payment-verifications.approve-cashier', $payment) }}" class="border-l-4 border-green-400 pl-4">
@csrf
{{-- Disability Certificate Verification (if applicable) --}}
@if($payment->member->hasDisabilityCertificate() && $payment->member->isDisabilityPending())
<div class="mb-6 p-4 bg-yellow-50 dark:bg-yellow-900/30 rounded-lg">
<h4 class="text-sm font-semibold text-yellow-800 dark:text-yellow-200 mb-3">身心障礙手冊審核</h4>
<p class="text-sm text-yellow-700 dark:text-yellow-300 mb-3">此會員已上傳身心障礙手冊,請一併審核:</p>
<a href="{{ route('admin.members.disability-certificate', $payment->member) }}" target="_blank"
class="inline-flex items-center mb-4 text-sm text-indigo-600 dark:text-indigo-400 hover:underline">
<svg class="w-4 h-4 mr-1" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
</svg>
檢視身心障礙手冊
</a>
<div class="space-y-2">
<label class="flex items-center">
<input type="radio" name="disability_action" value="approve" class="h-4 w-4 text-green-600 focus:ring-green-500 border-gray-300 dark:border-gray-600">
<span class="ml-2 text-sm text-gray-700 dark:text-gray-300">通過 - 確認為有效身心障礙手冊</span>
</label>
<label class="flex items-center">
<input type="radio" name="disability_action" value="reject" class="h-4 w-4 text-red-600 focus:ring-red-500 border-gray-300 dark:border-gray-600">
<span class="ml-2 text-sm text-gray-700 dark:text-gray-300">駁回</span>
</label>
</div>
<div id="disability_rejection_reason_container" class="mt-3 hidden">
<label for="disability_rejection_reason" class="block text-sm font-medium text-gray-700 dark:text-gray-300">駁回原因</label>
<input type="text" name="disability_rejection_reason" id="disability_rejection_reason"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"
placeholder="請說明駁回原因">
</div>
<p class="mt-3 text-xs text-yellow-600 dark:text-yellow-400">* 通過後,會員未來繳費將自動享有 50% 優惠</p>
</div>
@endif
<div class="mb-3">
<label for="cashier_notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Notes (Optional)') }}</label>
<label for="cashier_notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">備註(選填)</label>
<textarea name="notes" id="cashier_notes" rows="2" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"></textarea>
</div>
<button type="submit" class="inline-flex justify-center rounded-md bg-green-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500">
{{ __('Approve as Cashier') }}
<button type="submit" class="inline-flex justify-center rounded-md bg-green-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 dark:hover:bg-green-400">
出納核准
</button>
</form>
@endif
@@ -199,11 +263,11 @@
<form method="POST" action="{{ route('admin.payment-verifications.approve-accountant', $payment) }}" class="border-l-4 border-green-400 pl-4">
@csrf
<div class="mb-3">
<label for="accountant_notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Notes (Optional)') }}</label>
<label for="accountant_notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">備註(選填)</label>
<textarea name="notes" id="accountant_notes" rows="2" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"></textarea>
</div>
<button type="submit" class="inline-flex justify-center rounded-md bg-green-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500">
{{ __('Approve as Accountant') }}
<button type="submit" class="inline-flex justify-center rounded-md bg-green-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 dark:hover:bg-green-400">
會計核准
</button>
</form>
@endif
@@ -212,24 +276,24 @@
<form method="POST" action="{{ route('admin.payment-verifications.approve-chair', $payment) }}" class="border-l-4 border-green-400 pl-4">
@csrf
<div class="mb-3">
<label for="chair_notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Notes (Optional)') }}</label>
<label for="chair_notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">備註(選填)</label>
<textarea name="notes" id="chair_notes" rows="2" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"></textarea>
</div>
<button type="submit" class="inline-flex justify-center rounded-md bg-green-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500">
{{ __('Final Approval as Chair') }}
<button type="submit" class="inline-flex justify-center rounded-md bg-green-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 dark:hover:bg-green-400">
主席最終核准
</button>
</form>
@endif
{{-- Reject Form --}}
<form method="POST" action="{{ route('admin.payment-verifications.reject', $payment) }}" class="border-l-4 border-red-400 pl-4" onsubmit="return confirm('{{ __('Are you sure you want to reject this payment?') }}')">
<form method="POST" action="{{ route('admin.payment-verifications.reject', $payment) }}" class="border-l-4 border-red-400 pl-4" onsubmit="return confirm('您確定要拒絕此付款嗎?')">
@csrf
<div class="mb-3">
<label for="rejection_reason" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Rejection Reason') }} <span class="text-red-500">*</span></label>
<label for="rejection_reason" class="block text-sm font-medium text-gray-700 dark:text-gray-300">拒絕原因 <span class="text-red-500">*</span></label>
<textarea name="rejection_reason" id="rejection_reason" rows="3" required class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"></textarea>
</div>
<button type="submit" class="inline-flex justify-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500">
{{ __('Reject Payment') }}
<button type="submit" class="inline-flex justify-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 dark:hover:bg-red-400">
拒絕付款
</button>
</form>
</div>
@@ -238,10 +302,28 @@
{{-- Back Button --}}
<div>
<a href="{{ route('admin.payment-verifications.index') }}" class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600">
{{ __('Back to List') }}
<a href="{{ route('admin.payment-verifications.index') }}" class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600 dark:hover:bg-gray-600">
返回列表
</a>
</div>
</div>
</div>
</x-app-layout>
@push('scripts')
<script>
// Toggle disability rejection reason field
document.querySelectorAll('input[name="disability_action"]').forEach(function(radio) {
radio.addEventListener('change', function() {
const container = document.getElementById('disability_rejection_reason_container');
if (this.value === 'reject') {
container.classList.remove('hidden');
document.getElementById('disability_rejection_reason').required = true;
} else {
container.classList.add('hidden');
document.getElementById('disability_rejection_reason').required = false;
}
});
});
</script>
@endpush
</x-app-layout>

View File

@@ -1,37 +1,37 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Record payment for :name', ['name' => $member->full_name]) }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
記錄付款 - {{ $member->full_name }}
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="POST" action="{{ route('admin.members.payments.store', $member) }}" class="space-y-6">
@csrf
<div>
<label for="paid_at" class="block text-sm font-medium text-gray-700">
{{ __('Paid at') }}
<label for="paid_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
付款時間
</label>
<input
type="date"
name="paid_at"
id="paid_at"
value="{{ old('paid_at', now()->toDateString()) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
@error('paid_at')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="amount" class="block text-sm font-medium text-gray-700">
{{ __('Amount') }}
<label for="amount" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
金額
</label>
<input
type="number"
@@ -39,49 +39,49 @@
name="amount"
id="amount"
value="{{ old('amount') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
@error('amount')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="method" class="block text-sm font-medium text-gray-700">
{{ __('Method') }}
<label for="method" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
方式
</label>
<input
type="text"
name="method"
id="method"
value="{{ old('method') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('method')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="reference" class="block text-sm font-medium text-gray-700">
{{ __('Reference') }}
<label for="reference" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
參考
</label>
<input
type="text"
name="reference"
id="reference"
value="{{ old('reference') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('reference')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="flex justify-end">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Save payment') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
儲存付款
</button>
</div>
</form>

View File

@@ -1,38 +1,38 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Edit payment for :name', ['name' => $member->full_name]) }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
編輯付款 - {{ $member->full_name }}
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="POST" action="{{ route('admin.members.payments.update', [$member, $payment]) }}" class="space-y-6">
@csrf
@method('PATCH')
<div>
<label for="paid_at" class="block text-sm font-medium text-gray-700">
{{ __('Paid at') }}
<label for="paid_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
付款時間
</label>
<input
type="date"
name="paid_at"
id="paid_at"
value="{{ old('paid_at', optional($payment->paid_at)->toDateString()) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
@error('paid_at')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="amount" class="block text-sm font-medium text-gray-700">
{{ __('Amount') }}
<label for="amount" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
金額
</label>
<input
type="number"
@@ -40,43 +40,43 @@
name="amount"
id="amount"
value="{{ old('amount', $payment->amount) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
@error('amount')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="method" class="block text-sm font-medium text-gray-700">
{{ __('Method') }}
<label for="method" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
方式
</label>
<input
type="text"
name="method"
id="method"
value="{{ old('method', $payment->method) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('method')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="reference" class="block text-sm font-medium text-gray-700">
{{ __('Reference') }}
<label for="reference" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
參考
</label>
<input
type="text"
name="reference"
id="reference"
value="{{ old('reference', $payment->reference) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('reference')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
@@ -84,13 +84,13 @@
<form method="POST" action="{{ route('admin.members.payments.destroy', [$member, $payment]) }}">
@csrf
@method('DELETE')
<button type="submit" class="inline-flex items-center rounded-md border border-red-300 bg-white px-4 py-2 text-sm font-medium text-red-700 hover:bg-red-50 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">
{{ __('Delete') }}
<button type="submit" class="inline-flex items-center rounded-md border border-red-300 dark:border-red-700 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-medium text-red-700 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
刪除
</button>
</form>
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Save changes') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
儲存變更
</button>
</div>
</form>

View File

@@ -1,53 +1,53 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Create Role') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
新增角色
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="POST" action="{{ route('admin.roles.store') }}" class="space-y-6">
@csrf
<div>
<label for="name" class="block text-sm font-medium text-gray-700">
{{ __('Name') }}
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
名稱
</label>
<input
type="text"
name="name"
id="name"
value="{{ old('name') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
@error('name')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="description" class="block text-sm font-medium text-gray-700">
{{ __('Description') }}
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
描述
</label>
<input
type="text"
name="description"
id="description"
value="{{ old('description') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('description')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="flex justify-end">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Create Role') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
新增角色
</button>
</div>
</form>

View File

@@ -1,54 +1,54 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Edit Role') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
編輯角色
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8">
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="POST" action="{{ route('admin.roles.update', $role) }}" class="space-y-6">
@csrf
@method('PATCH')
<div>
<label for="name" class="block text-sm font-medium text-gray-700">
{{ __('Name') }}
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
名稱
</label>
<input
type="text"
name="name"
id="name"
value="{{ old('name', $role->name) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required
>
@error('name')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="description" class="block text-sm font-medium text-gray-700">
{{ __('Description') }}
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
描述
</label>
<input
type="text"
name="description"
id="description"
value="{{ old('description', $role->description) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
>
@error('description')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
<p class="mt-2 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div class="flex justify-end">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Save changes') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
儲存變更
</button>
</div>
</form>

View File

@@ -1,58 +1,58 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Roles') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
角色管理
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-6xl sm:px-6 lg:px-8 space-y-6">
@if (session('status'))
<div class="rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
<div class="flex justify-end">
<a href="{{ route('admin.roles.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Create Role') }}
<a href="{{ route('admin.roles.create') }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
新增角色
</a>
</div>
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200" role="table">
<thead class="bg-gray-50">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700" role="table">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">{{ __('Name') }}</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">{{ __('Description') }}</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">{{ __('Users') }}</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500"><span class="sr-only">{{ __('Actions') }}</span></th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">名稱</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">描述</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">使用者</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300"><span class="sr-only">操作</span></th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse ($roles as $role)
<tr>
<td class="px-4 py-3 text-sm font-medium text-gray-900">
<td class="px-4 py-3 text-sm font-medium text-gray-900 dark:text-gray-100">
{{ $role->name }}
</td>
<td class="px-4 py-3 text-sm text-gray-900">
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ $role->description ?? __('—') }}
</td>
<td class="px-4 py-3 text-sm text-gray-900">
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ $role->users_count }}
</td>
<td class="px-4 py-3 text-right text-sm">
<a href="{{ route('admin.roles.show', $role) }}" class="text-indigo-600 hover:text-indigo-900">
{{ __('View') }}
<a href="{{ route('admin.roles.show', $role) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
檢視
</a>
</td>
</tr>
@empty
<tr>
<td colspan="4" class="px-4 py-4 text-sm text-gray-500">
{{ __('No roles found.') }}
<td colspan="4" class="px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
找不到角色。
</td>
</tr>
@endforelse

View File

@@ -1,105 +1,105 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Role Details') }}
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
角色詳情
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-6xl sm:px-6 lg:px-8 space-y-6">
@if (session('status'))
<div class="rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6 flex items-center justify-between">
<div>
<h3 class="text-lg font-medium text-gray-900">{{ $role->name }}</h3>
<p class="mt-1 text-sm text-gray-600">{{ $role->description ?: __('No description') }}</p>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">{{ $role->name }}</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">{{ $role->description ?: __('No description') }}</p>
</div>
<a href="{{ route('admin.roles.edit', $role) }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Edit Role') }}
<a href="{{ route('admin.roles.edit', $role) }}" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
編輯角色
</a>
</div>
</div>
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6 space-y-4">
<h3 class="text-lg font-medium text-gray-900">
{{ __('Assign Users') }}
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">
指派使用者
</h3>
<form method="POST" action="{{ route('admin.roles.assign-users', $role) }}" class="space-y-3">
@csrf
<label for="user_ids" class="block text-sm font-medium text-gray-700">
{{ __('Select users to assign') }}
<label for="user_ids" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
選擇要指派的使用者
</label>
<select name="user_ids[]" id="user_ids" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" multiple size="5">
<select name="user_ids[]" id="user_ids" class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100" multiple size="5">
@foreach ($availableUsers as $user)
<option value="{{ $user->id }}">{{ $user->name }} ({{ $user->email }})</option>
@endforeach
</select>
@error('user_ids')
<p class="text-sm text-red-600">{{ $message }}</p>
<p class="text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
<div class="flex justify-end">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
{{ __('Assign Selected') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
指派所選項目
</button>
</div>
</form>
</div>
</div>
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6 space-y-4">
<div class="flex items-center justify-between">
<h3 class="text-lg font-medium text-gray-900">
{{ __('Users with this role') }}
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">
擁有此角色的使用者
</h3>
<form method="GET" action="{{ route('admin.roles.show', $role) }}" class="flex gap-2" role="search">
<input
type="text"
name="search"
value="{{ $search }}"
placeholder="{{ __('Search users') }}"
class="block rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
placeholder="搜尋使用者"
class="block rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"
>
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-gray-200 px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-300">
{{ __('Search') }}
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-gray-200 dark:bg-gray-700 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-300 dark:hover:bg-gray-600">
搜尋
</button>
</form>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200" role="table">
<thead class="bg-gray-50">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700" role="table">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">{{ __('Name') }}</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">{{ __('Email') }}</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500"><span class="sr-only">{{ __('Remove') }}</span></th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">名稱</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">電子郵件</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300"><span class="sr-only">移除</span></th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse ($users as $user)
<tr>
<td class="px-4 py-3 text-sm text-gray-900">{{ $user->name }}</td>
<td class="px-4 py-3 text-sm text-gray-900">{{ $user->email }}</td>
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">{{ $user->name }}</td>
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">{{ $user->email }}</td>
<td class="px-4 py-3 text-right text-sm">
<form method="POST" action="{{ route('admin.roles.remove-user', [$role, $user]) }}" onsubmit="return confirm('{{ __('Remove this role from the user?') }}');">
<form method="POST" action="{{ route('admin.roles.remove-user', [$role, $user]) }}" onsubmit="return confirm('從使用者移除此角色?');">
@csrf
@method('DELETE')
<button type="submit" class="text-red-600 hover:text-red-800">
{{ __('Remove') }}
<button type="submit" class="text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300">
移除
</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="3" class="px-4 py-4 text-sm text-gray-500">
{{ __('No users assigned to this role.') }}
<td colspan="3" class="px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
此角色未指派任何使用者。
</td>
</tr>
@endforelse

View File

@@ -1,41 +1,49 @@
<div class="bg-white shadow sm:rounded-lg">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<nav class="space-y-1 p-4">
<a href="{{ route('admin.settings.general') }}"
class="flex items-center px-3 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.settings.general') ? 'bg-indigo-50 text-indigo-700' : 'text-gray-700 hover:bg-gray-50' }}">
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.settings.general') ? 'text-indigo-500' : 'text-gray-400' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
class="flex items-center px-3 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.settings.general') ? 'bg-indigo-50 dark:bg-indigo-900/50 text-indigo-700 dark:text-indigo-300' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700' }}">
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.settings.general') ? 'text-indigo-500 dark:text-indigo-400' : 'text-gray-400 dark:text-gray-500' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
一般設定
</a>
<a href="{{ route('admin.settings.membership') }}"
class="flex items-center px-3 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.settings.membership') ? 'bg-indigo-50 dark:bg-indigo-900/50 text-indigo-700 dark:text-indigo-300' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700' }}">
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.settings.membership') ? 'text-indigo-500 dark:text-indigo-400' : 'text-gray-400 dark:text-gray-500' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
會費設定
</a>
<a href="{{ route('admin.settings.features') }}"
class="flex items-center px-3 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.settings.features') ? 'bg-indigo-50 text-indigo-700' : 'text-gray-700 hover:bg-gray-50' }}">
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.settings.features') ? 'text-indigo-500' : 'text-gray-400' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
class="flex items-center px-3 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.settings.features') ? 'bg-indigo-50 dark:bg-indigo-900/50 text-indigo-700 dark:text-indigo-300' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700' }}">
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.settings.features') ? 'text-indigo-500 dark:text-indigo-400' : 'text-gray-400 dark:text-gray-500' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
文件功能
</a>
<a href="{{ route('admin.settings.security') }}"
class="flex items-center px-3 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.settings.security') ? 'bg-indigo-50 text-indigo-700' : 'text-gray-700 hover:bg-gray-50' }}">
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.settings.security') ? 'text-indigo-500' : 'text-gray-400' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
class="flex items-center px-3 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.settings.security') ? 'bg-indigo-50 dark:bg-indigo-900/50 text-indigo-700 dark:text-indigo-300' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700' }}">
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.settings.security') ? 'text-indigo-500 dark:text-indigo-400' : 'text-gray-400 dark:text-gray-500' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg>
安全性與限制
</a>
<a href="{{ route('admin.settings.notifications') }}"
class="flex items-center px-3 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.settings.notifications') ? 'bg-indigo-50 text-indigo-700' : 'text-gray-700 hover:bg-gray-50' }}">
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.settings.notifications') ? 'text-indigo-500' : 'text-gray-400' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
class="flex items-center px-3 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.settings.notifications') ? 'bg-indigo-50 dark:bg-indigo-900/50 text-indigo-700 dark:text-indigo-300' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700' }}">
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.settings.notifications') ? 'text-indigo-500 dark:text-indigo-400' : 'text-gray-400 dark:text-gray-500' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
通知設定
</a>
<a href="{{ route('admin.settings.advanced') }}"
class="flex items-center px-3 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.settings.advanced') ? 'bg-indigo-50 text-indigo-700' : 'text-gray-700 hover:bg-gray-50' }}">
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.settings.advanced') ? 'text-indigo-500' : 'text-gray-400' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
class="flex items-center px-3 py-2 text-sm font-medium rounded-md {{ request()->routeIs('admin.settings.advanced') ? 'bg-indigo-50 dark:bg-indigo-900/50 text-indigo-700 dark:text-indigo-300' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700' }}">
<svg class="mr-3 h-5 w-5 {{ request()->routeIs('admin.settings.advanced') ? 'text-indigo-500 dark:text-indigo-400' : 'text-gray-400 dark:text-gray-500' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" />
</svg>
進階設定

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
系統設定 - 進階設定
</h2>
</x-slot>
@@ -16,157 +16,157 @@
<!-- Main Content -->
<div class="lg:col-span-3">
@if (session('status'))
<div class="mb-6 rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="mb-6 rounded-md bg-green-50 dark:bg-green-900/50 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
<div class="bg-white shadow sm:rounded-lg">
<div class="px-6 py-5 border-b border-gray-200">
<h3 class="text-lg font-medium text-gray-900">進階設定</h3>
<p class="mt-1 text-sm text-gray-600">配置 QR Code、統計、版本控制和其他進階功能</p>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-6 py-5 border-b border-gray-200 dark:border-gray-700">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">進階設定</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">配置 QR Code、統計、版本控制和其他進階功能</p>
</div>
<form action="{{ route('admin.settings.advanced.update') }}" method="POST" class="px-6 py-6 space-y-8">
@csrf
<!-- QR Code Settings Section -->
<div class="border-b border-gray-200 pb-6">
<h4 class="text-base font-medium text-gray-900 mb-4">QR Code 設定</h4>
<div class="border-b border-gray-200 dark:border-gray-700 pb-6">
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">QR Code 設定</h4>
<div class="grid grid-cols-1 gap-6 md:grid-cols-2">
<div>
<label for="qr_code_size" class="block text-sm font-medium text-gray-700">
<label for="qr_code_size" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
QR Code 尺寸(像素)
</label>
<input type="number" name="qr_code_size" id="qr_code_size"
value="{{ old('qr_code_size', $settings['qr_code_size']) }}"
min="100" max="1000"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
@error('qr_code_size')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="qr_code_format" class="block text-sm font-medium text-gray-700">
<label for="qr_code_format" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
QR Code 格式
</label>
<select name="qr_code_format" id="qr_code_format"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<option value="png" {{ $settings['qr_code_format'] === 'png' ? 'selected' : '' }}>PNG</option>
<option value="svg" {{ $settings['qr_code_format'] === 'svg' ? 'selected' : '' }}>SVG</option>
</select>
@error('qr_code_format')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
</div>
<!-- Statistics Settings Section -->
<div class="border-b border-gray-200 pb-6">
<h4 class="text-base font-medium text-gray-900 mb-4">統計報表設定</h4>
<div class="border-b border-gray-200 dark:border-gray-700 pb-6">
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">統計報表設定</h4>
<div class="grid grid-cols-1 gap-6 md:grid-cols-2">
<div>
<label for="statistics_time_range" class="block text-sm font-medium text-gray-700">
<label for="statistics_time_range" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
統計時間範圍(天)
</label>
<input type="number" name="statistics_time_range" id="statistics_time_range"
value="{{ old('statistics_time_range', $settings['statistics_time_range']) }}"
min="7" max="365"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<p class="mt-1 text-sm text-gray-500">預設顯示的統計天數</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">預設顯示的統計天數</p>
@error('statistics_time_range')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="statistics_top_n" class="block text-sm font-medium text-gray-700">
<label for="statistics_top_n" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
熱門項目顯示數量
</label>
<input type="number" name="statistics_top_n" id="statistics_top_n"
value="{{ old('statistics_top_n', $settings['statistics_top_n']) }}"
min="5" max="100"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<p class="mt-1 text-sm text-gray-500">顯示前 N 個熱門文件</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">顯示前 N 個熱門文件</p>
@error('statistics_top_n')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
</div>
<!-- Document Settings Section -->
<div class="border-b border-gray-200 pb-6">
<h4 class="text-base font-medium text-gray-900 mb-4">文件設定</h4>
<div class="border-b border-gray-200 dark:border-gray-700 pb-6">
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">文件設定</h4>
<div class="grid grid-cols-1 gap-6 md:grid-cols-2">
<div>
<label for="default_expiration_days" class="block text-sm font-medium text-gray-700">
<label for="default_expiration_days" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
預設到期天數
</label>
<input type="number" name="default_expiration_days" id="default_expiration_days"
value="{{ old('default_expiration_days', $settings['default_expiration_days']) }}"
min="0" max="3650"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<p class="mt-1 text-sm text-gray-500">新文件的預設到期天數0 表示永不過期)</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">新文件的預設到期天數0 表示永不過期)</p>
@error('default_expiration_days')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="expiration_warning_days" class="block text-sm font-medium text-gray-700">
<label for="expiration_warning_days" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
到期前提醒天數
</label>
<input type="number" name="expiration_warning_days" id="expiration_warning_days"
value="{{ old('expiration_warning_days', $settings['expiration_warning_days']) }}"
min="1" max="365"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<p class="mt-1 text-sm text-gray-500">到期前幾天發送提醒通知</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">到期前幾天發送提醒通知</p>
@error('expiration_warning_days')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="max_tags_per_document" class="block text-sm font-medium text-gray-700">
<label for="max_tags_per_document" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
每個文件的標籤上限
</label>
<input type="number" name="max_tags_per_document" id="max_tags_per_document"
value="{{ old('max_tags_per_document', $settings['max_tags_per_document']) }}"
min="1" max="50"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
@error('max_tags_per_document')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="default_access_level" class="block text-sm font-medium text-gray-700">
<label for="default_access_level" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
預設存取權限
</label>
<select name="default_access_level" id="default_access_level"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<option value="public" {{ $settings['default_access_level'] === 'public' ? 'selected' : '' }}>公開</option>
<option value="members" {{ $settings['default_access_level'] === 'members' ? 'selected' : '' }}>會員</option>
<option value="admin" {{ $settings['default_access_level'] === 'admin' ? 'selected' : '' }}>管理員</option>
<option value="board" {{ $settings['default_access_level'] === 'board' ? 'selected' : '' }}>理事會</option>
</select>
<p class="mt-1 text-sm text-gray-500">新文件的預設存取權限</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">新文件的預設存取權限</p>
@error('default_access_level')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
@@ -176,11 +176,11 @@
<div class="flex items-center h-5">
<input type="checkbox" name="auto_archive_enabled" id="auto_archive_enabled"
{{ $settings['auto_archive_enabled'] ? 'checked' : '' }}
class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
class="w-4 h-4 text-indigo-600 dark:text-indigo-500 border-gray-300 dark:border-gray-700 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900">
</div>
<div class="ml-3 text-sm">
<label for="auto_archive_enabled" class="font-medium text-gray-700">自動封存過期文件</label>
<p class="text-gray-500">當文件到期時自動將其封存</p>
<label for="auto_archive_enabled" class="font-medium text-gray-700 dark:text-gray-300">自動封存過期文件</label>
<p class="text-gray-500 dark:text-gray-400">當文件到期時自動將其封存</p>
</div>
</div>
</div>
@@ -188,45 +188,45 @@
<!-- System Settings Section -->
<div>
<h4 class="text-base font-medium text-gray-900 mb-4">系統設定</h4>
<h4 class="text-base font-medium text-gray-900 dark:text-gray-100 mb-4">系統設定</h4>
<div class="grid grid-cols-1 gap-6 md:grid-cols-2">
<div>
<label for="audit_log_retention_days" class="block text-sm font-medium text-gray-700">
<label for="audit_log_retention_days" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
稽核記錄保留天數
</label>
<input type="number" name="audit_log_retention_days" id="audit_log_retention_days"
value="{{ old('audit_log_retention_days', $settings['audit_log_retention_days']) }}"
min="30" max="3650"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<p class="mt-1 text-sm text-gray-500">稽核記錄保留的天數</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">稽核記錄保留的天數</p>
@error('audit_log_retention_days')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<div>
<label for="max_versions_retain" class="block text-sm font-medium text-gray-700">
<label for="max_versions_retain" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
版本保留數量
</label>
<input type="number" name="max_versions_retain" id="max_versions_retain"
value="{{ old('max_versions_retain', $settings['max_versions_retain']) }}"
min="0" max="100"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<p class="mt-1 text-sm text-gray-500">每個文件保留的最大版本數0 表示無限制)</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">每個文件保留的最大版本數0 表示無限制)</p>
@error('max_versions_retain')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
</div>
</div>
<!-- Submit Button -->
<div class="flex items-center justify-end pt-4 border-t">
<div class="flex items-center justify-end pt-4 border-t border-gray-200 dark:border-gray-700">
<button type="submit"
class="inline-flex justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
class="inline-flex justify-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
儲存變更
</button>
</div>

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
系統設定 - 文件功能
</h2>
</x-slot>
@@ -16,15 +16,15 @@
<!-- Main Content -->
<div class="lg:col-span-3">
@if (session('status'))
<div class="mb-6 rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="mb-6 rounded-md bg-green-50 dark:bg-green-900/50 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
<div class="bg-white shadow sm:rounded-lg">
<div class="px-6 py-5 border-b border-gray-200">
<h3 class="text-lg font-medium text-gray-900">文件功能開關</h3>
<p class="mt-1 text-sm text-gray-600">控制文件管理系統的進階功能</p>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-6 py-5 border-b border-gray-200 dark:border-gray-700">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">文件功能開關</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">控制文件管理系統的進階功能</p>
</div>
<form action="{{ route('admin.settings.features.update') }}" method="POST" class="px-6 py-6 space-y-6">
@@ -35,11 +35,11 @@
<div class="flex items-center h-5">
<input type="checkbox" name="qr_codes_enabled" id="qr_codes_enabled"
{{ $settings['qr_codes_enabled'] ? 'checked' : '' }}
class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
class="w-4 h-4 text-indigo-600 dark:text-indigo-500 border-gray-300 dark:border-gray-700 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900">
</div>
<div class="ml-3 text-sm">
<label for="qr_codes_enabled" class="font-medium text-gray-700">啟用 QR Code 功能</label>
<p class="text-gray-500">允許為文件產生 QR Code 以便快速存取</p>
<label for="qr_codes_enabled" class="font-medium text-gray-700 dark:text-gray-300">啟用 QR Code 功能</label>
<p class="text-gray-500 dark:text-gray-400">允許為文件產生 QR Code 以便快速存取</p>
</div>
</div>
@@ -48,11 +48,11 @@
<div class="flex items-center h-5">
<input type="checkbox" name="tagging_enabled" id="tagging_enabled"
{{ $settings['tagging_enabled'] ? 'checked' : '' }}
class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
class="w-4 h-4 text-indigo-600 dark:text-indigo-500 border-gray-300 dark:border-gray-700 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900">
</div>
<div class="ml-3 text-sm">
<label for="tagging_enabled" class="font-medium text-gray-700">啟用標籤功能</label>
<p class="text-gray-500">允許為文件添加標籤以便分類和搜尋</p>
<label for="tagging_enabled" class="font-medium text-gray-700 dark:text-gray-300">啟用標籤功能</label>
<p class="text-gray-500 dark:text-gray-400">允許為文件添加標籤以便分類和搜尋</p>
</div>
</div>
@@ -61,11 +61,11 @@
<div class="flex items-center h-5">
<input type="checkbox" name="expiration_enabled" id="expiration_enabled"
{{ $settings['expiration_enabled'] ? 'checked' : '' }}
class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
class="w-4 h-4 text-indigo-600 dark:text-indigo-500 border-gray-300 dark:border-gray-700 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900">
</div>
<div class="ml-3 text-sm">
<label for="expiration_enabled" class="font-medium text-gray-700">啟用到期日功能</label>
<p class="text-gray-500">允許設定文件到期日並接收提醒通知</p>
<label for="expiration_enabled" class="font-medium text-gray-700 dark:text-gray-300">啟用到期日功能</label>
<p class="text-gray-500 dark:text-gray-400">允許設定文件到期日並接收提醒通知</p>
</div>
</div>
@@ -74,11 +74,11 @@
<div class="flex items-center h-5">
<input type="checkbox" name="bulk_import_enabled" id="bulk_import_enabled"
{{ $settings['bulk_import_enabled'] ? 'checked' : '' }}
class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
class="w-4 h-4 text-indigo-600 dark:text-indigo-500 border-gray-300 dark:border-gray-700 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900">
</div>
<div class="ml-3 text-sm">
<label for="bulk_import_enabled" class="font-medium text-gray-700">啟用批次匯入功能</label>
<p class="text-gray-500">允許管理員批次匯入多個文件</p>
<label for="bulk_import_enabled" class="font-medium text-gray-700 dark:text-gray-300">啟用批次匯入功能</label>
<p class="text-gray-500 dark:text-gray-400">允許管理員批次匯入多個文件</p>
</div>
</div>
@@ -87,11 +87,11 @@
<div class="flex items-center h-5">
<input type="checkbox" name="statistics_enabled" id="statistics_enabled"
{{ $settings['statistics_enabled'] ? 'checked' : '' }}
class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
class="w-4 h-4 text-indigo-600 dark:text-indigo-500 border-gray-300 dark:border-gray-700 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900">
</div>
<div class="ml-3 text-sm">
<label for="statistics_enabled" class="font-medium text-gray-700">啟用統計報表功能</label>
<p class="text-gray-500">顯示文件下載統計和使用分析</p>
<label for="statistics_enabled" class="font-medium text-gray-700 dark:text-gray-300">啟用統計報表功能</label>
<p class="text-gray-500 dark:text-gray-400">顯示文件下載統計和使用分析</p>
</div>
</div>
@@ -100,18 +100,18 @@
<div class="flex items-center h-5">
<input type="checkbox" name="version_history_enabled" id="version_history_enabled"
{{ $settings['version_history_enabled'] ? 'checked' : '' }}
class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
class="w-4 h-4 text-indigo-600 dark:text-indigo-500 border-gray-300 dark:border-gray-700 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900">
</div>
<div class="ml-3 text-sm">
<label for="version_history_enabled" class="font-medium text-gray-700">啟用版本控制功能</label>
<p class="text-gray-500">保留文件歷史版本並允許回溯</p>
<label for="version_history_enabled" class="font-medium text-gray-700 dark:text-gray-300">啟用版本控制功能</label>
<p class="text-gray-500 dark:text-gray-400">保留文件歷史版本並允許回溯</p>
</div>
</div>
<!-- Submit Button -->
<div class="flex items-center justify-end pt-4 border-t">
<div class="flex items-center justify-end pt-4 border-t border-gray-200 dark:border-gray-700">
<button type="submit"
class="inline-flex justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
class="inline-flex justify-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
儲存變更
</button>
</div>

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
系統設定 - 一般設定
</h2>
</x-slot>
@@ -16,15 +16,15 @@
<!-- Main Content -->
<div class="lg:col-span-3">
@if (session('status'))
<div class="mb-6 rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="mb-6 rounded-md bg-green-50 dark:bg-green-900/50 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
<div class="bg-white shadow sm:rounded-lg">
<div class="px-6 py-5 border-b border-gray-200">
<h3 class="text-lg font-medium text-gray-900">一般設定</h3>
<p class="mt-1 text-sm text-gray-600">配置系統的基本資訊</p>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-6 py-5 border-b border-gray-200 dark:border-gray-700">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">一般設定</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">配置系統的基本資訊</p>
</div>
<form action="{{ route('admin.settings.general.update') }}" method="POST" class="px-6 py-6 space-y-6">
@@ -32,42 +32,42 @@
<!-- System Name -->
<div>
<label for="system_name" class="block text-sm font-medium text-gray-700">
<label for="system_name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
系統名稱
</label>
<input type="text" name="system_name" id="system_name"
value="{{ old('system_name', $settings['system_name']) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<p class="mt-1 text-sm text-gray-500">顯示在系統各處的名稱</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">顯示在系統各處的名稱</p>
@error('system_name')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Timezone -->
<div>
<label for="timezone" class="block text-sm font-medium text-gray-700">
<label for="timezone" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
時區
</label>
<select name="timezone" id="timezone"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<option value="Asia/Taipei" {{ $settings['timezone'] === 'Asia/Taipei' ? 'selected' : '' }}>台北 (Asia/Taipei)</option>
<option value="Asia/Hong_Kong" {{ $settings['timezone'] === 'Asia/Hong_Kong' ? 'selected' : '' }}>香港 (Asia/Hong_Kong)</option>
<option value="Asia/Shanghai" {{ $settings['timezone'] === 'Asia/Shanghai' ? 'selected' : '' }}>上海 (Asia/Shanghai)</option>
<option value="UTC" {{ $settings['timezone'] === 'UTC' ? 'selected' : '' }}>UTC</option>
</select>
<p class="mt-1 text-sm text-gray-500">系統使用的時區設定</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">系統使用的時區設定</p>
@error('timezone')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Submit Button -->
<div class="flex items-center justify-end pt-4 border-t">
<div class="flex items-center justify-end pt-4 border-t border-gray-200 dark:border-gray-700">
<button type="submit"
class="inline-flex justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
class="inline-flex justify-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
儲存變更
</button>
</div>

View File

@@ -0,0 +1,174 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
系統設定 - 會費設定
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="grid grid-cols-1 gap-6 lg:grid-cols-4">
<!-- Sidebar -->
<div class="lg:col-span-1">
@include('admin.settings._sidebar')
</div>
<!-- Main Content -->
<div class="lg:col-span-3">
@if (session('status'))
<div class="mb-6 rounded-md bg-green-50 dark:bg-green-900/50 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-6 py-5 border-b border-gray-200 dark:border-gray-700">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">會費設定</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">配置會員繳費金額與折扣</p>
</div>
<form action="{{ route('admin.settings.membership.update') }}" method="POST" class="px-6 py-6 space-y-6">
@csrf
<!-- Entrance Fee -->
<div>
<label for="entrance_fee" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
入會會費
</label>
<div class="mt-1 relative rounded-md shadow-sm">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<span class="text-gray-500 dark:text-gray-400 sm:text-sm">NT$</span>
</div>
<input type="number" name="entrance_fee" id="entrance_fee"
value="{{ old('entrance_fee', $settings['entrance_fee']) }}"
class="pl-12 mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
min="0" step="1" required>
</div>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">新會員首次加入時繳納的一次性費用</p>
@error('entrance_fee')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Annual Fee -->
<div>
<label for="annual_fee" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
常年會費
</label>
<div class="mt-1 relative rounded-md shadow-sm">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<span class="text-gray-500 dark:text-gray-400 sm:text-sm">NT$</span>
</div>
<input type="number" name="annual_fee" id="annual_fee"
value="{{ old('annual_fee', $settings['annual_fee']) }}"
class="pl-12 mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
min="0" step="1" required>
</div>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">會員每年續繳的年費</p>
@error('annual_fee')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Disability Discount Rate -->
<div>
<label for="disability_discount_rate" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
身心障礙優惠
</label>
<div class="mt-1 relative rounded-md shadow-sm">
<input type="number" name="disability_discount_rate" id="disability_discount_rate"
value="{{ old('disability_discount_rate', $settings['disability_discount_rate']) }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300 pr-12"
min="0" max="100" step="1" required>
<div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
<span class="text-gray-500 dark:text-gray-400 sm:text-sm">%</span>
</div>
</div>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">持有身心障礙手冊且審核通過的會員可享的折扣比例</p>
@error('disability_discount_rate')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Preview Section -->
<div class="mt-8 p-4 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
<h4 class="text-sm font-medium text-gray-900 dark:text-gray-100 mb-3">會費試算預覽</h4>
<div class="grid grid-cols-2 gap-4 text-sm">
<div>
<p class="text-gray-600 dark:text-gray-400">一般會員入會費用:</p>
<p class="font-medium text-gray-900 dark:text-gray-100" id="preview-entrance">NT$ {{ number_format($settings['entrance_fee']) }}</p>
</div>
<div>
<p class="text-gray-600 dark:text-gray-400">身心障礙會員入會費用:</p>
<p class="font-medium text-green-600 dark:text-green-400" id="preview-entrance-discount">NT$ {{ number_format($settings['entrance_fee'] * (1 - $settings['disability_discount_rate'] / 100)) }}</p>
</div>
<div>
<p class="text-gray-600 dark:text-gray-400">一般會員年費:</p>
<p class="font-medium text-gray-900 dark:text-gray-100" id="preview-annual">NT$ {{ number_format($settings['annual_fee']) }}</p>
</div>
<div>
<p class="text-gray-600 dark:text-gray-400">身心障礙會員年費:</p>
<p class="font-medium text-green-600 dark:text-green-400" id="preview-annual-discount">NT$ {{ number_format($settings['annual_fee'] * (1 - $settings['disability_discount_rate'] / 100)) }}</p>
</div>
</div>
</div>
<!-- Submit Button -->
<div class="flex items-center justify-end pt-4 border-t border-gray-200 dark:border-gray-700">
<button type="submit"
class="inline-flex justify-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
儲存變更
</button>
</div>
</form>
</div>
<!-- Info Card -->
<div class="mt-6 bg-blue-50 dark:bg-blue-900/30 shadow sm:rounded-lg">
<div class="px-6 py-5">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-blue-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-blue-800 dark:text-blue-200">會費說明</h3>
<div class="mt-2 text-sm text-blue-700 dark:text-blue-300">
<ul class="list-disc pl-5 space-y-1">
<li><strong>入會會費</strong>:新會員首次加入時繳納,僅繳一次</li>
<li><strong>常年會費</strong>:會員每年需繳納的年費,以會籍週年日計算</li>
<li><strong>身心障礙優惠</strong>:會員上傳身心障礙手冊並經審核通過後,可享有折扣優惠</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@push('scripts')
<script>
// Update preview when values change
function updatePreview() {
const entranceFee = parseFloat(document.getElementById('entrance_fee').value) || 0;
const annualFee = parseFloat(document.getElementById('annual_fee').value) || 0;
const discountRate = parseFloat(document.getElementById('disability_discount_rate').value) || 0;
const formatter = new Intl.NumberFormat('zh-TW');
document.getElementById('preview-entrance').textContent = 'NT$ ' + formatter.format(entranceFee);
document.getElementById('preview-annual').textContent = 'NT$ ' + formatter.format(annualFee);
document.getElementById('preview-entrance-discount').textContent = 'NT$ ' + formatter.format(Math.round(entranceFee * (1 - discountRate / 100)));
document.getElementById('preview-annual-discount').textContent = 'NT$ ' + formatter.format(Math.round(annualFee * (1 - discountRate / 100)));
}
document.getElementById('entrance_fee').addEventListener('input', updatePreview);
document.getElementById('annual_fee').addEventListener('input', updatePreview);
document.getElementById('disability_discount_rate').addEventListener('input', updatePreview);
</script>
@endpush
</x-app-layout>

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
系統設定 - 通知設定
</h2>
</x-slot>
@@ -16,15 +16,15 @@
<!-- Main Content -->
<div class="lg:col-span-3">
@if (session('status'))
<div class="mb-6 rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="mb-6 rounded-md bg-green-50 dark:bg-green-900/50 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
<div class="bg-white shadow sm:rounded-lg">
<div class="px-6 py-5 border-b border-gray-200">
<h3 class="text-lg font-medium text-gray-900">通知設定</h3>
<p class="mt-1 text-sm text-gray-600">配置系統通知和電子郵件提醒</p>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-6 py-5 border-b border-gray-200 dark:border-gray-700">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">通知設定</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">配置系統通知和電子郵件提醒</p>
</div>
<form action="{{ route('admin.settings.notifications.update') }}" method="POST" class="px-6 py-6 space-y-6">
@@ -35,11 +35,11 @@
<div class="flex items-center h-5">
<input type="checkbox" name="enabled" id="enabled"
{{ $settings['enabled'] ? 'checked' : '' }}
class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
class="w-4 h-4 text-indigo-600 dark:text-indigo-500 border-gray-300 dark:border-gray-700 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900">
</div>
<div class="ml-3 text-sm">
<label for="enabled" class="font-medium text-gray-700">啟用系統通知</label>
<p class="text-gray-500">啟用所有系統通知功能</p>
<label for="enabled" class="font-medium text-gray-700 dark:text-gray-300">啟用系統通知</label>
<p class="text-gray-500 dark:text-gray-400">啟用所有系統通知功能</p>
</div>
</div>
@@ -48,26 +48,26 @@
<div class="flex items-center h-5">
<input type="checkbox" name="expiration_alerts_enabled" id="expiration_alerts_enabled"
{{ $settings['expiration_alerts_enabled'] ? 'checked' : '' }}
class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
class="w-4 h-4 text-indigo-600 dark:text-indigo-500 border-gray-300 dark:border-gray-700 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900">
</div>
<div class="ml-3 text-sm">
<label for="expiration_alerts_enabled" class="font-medium text-gray-700">文件到期提醒</label>
<p class="text-gray-500">當文件即將到期時發送電子郵件提醒</p>
<label for="expiration_alerts_enabled" class="font-medium text-gray-700 dark:text-gray-300">文件到期提醒</label>
<p class="text-gray-500 dark:text-gray-400">當文件即將到期時發送電子郵件提醒</p>
</div>
</div>
<!-- Expiration Recipients -->
<div>
<label for="expiration_recipients" class="block text-sm font-medium text-gray-700">
<label for="expiration_recipients" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
到期通知收件人
</label>
<input type="text" name="expiration_recipients" id="expiration_recipients"
value="{{ old('expiration_recipients', implode(', ', $settings['expiration_recipients'])) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="admin@example.com, manager@example.com">
<p class="mt-1 text-sm text-gray-500">接收到期通知的電子郵件地址,以逗號分隔</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">接收到期通知的電子郵件地址,以逗號分隔</p>
@error('expiration_recipients')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
@@ -76,11 +76,11 @@
<div class="flex items-center h-5">
<input type="checkbox" name="archive_notifications_enabled" id="archive_notifications_enabled"
{{ $settings['archive_notifications_enabled'] ? 'checked' : '' }}
class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
class="w-4 h-4 text-indigo-600 dark:text-indigo-500 border-gray-300 dark:border-gray-700 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900">
</div>
<div class="ml-3 text-sm">
<label for="archive_notifications_enabled" class="font-medium text-gray-700">文件封存通知</label>
<p class="text-gray-500">當文件被封存時發送通知</p>
<label for="archive_notifications_enabled" class="font-medium text-gray-700 dark:text-gray-300">文件封存通知</label>
<p class="text-gray-500 dark:text-gray-400">當文件被封存時發送通知</p>
</div>
</div>
@@ -89,18 +89,18 @@
<div class="flex items-center h-5">
<input type="checkbox" name="new_document_alerts_enabled" id="new_document_alerts_enabled"
{{ $settings['new_document_alerts_enabled'] ? 'checked' : '' }}
class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
class="w-4 h-4 text-indigo-600 dark:text-indigo-500 border-gray-300 dark:border-gray-700 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900">
</div>
<div class="ml-3 text-sm">
<label for="new_document_alerts_enabled" class="font-medium text-gray-700">新文件通知</label>
<p class="text-gray-500">當有新文件上傳時發送通知給相關人員</p>
<label for="new_document_alerts_enabled" class="font-medium text-gray-700 dark:text-gray-300">新文件通知</label>
<p class="text-gray-500 dark:text-gray-400">當有新文件上傳時發送通知給相關人員</p>
</div>
</div>
<!-- Submit Button -->
<div class="flex items-center justify-end pt-4 border-t">
<div class="flex items-center justify-end pt-4 border-t border-gray-200 dark:border-gray-700">
<button type="submit"
class="inline-flex justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
class="inline-flex justify-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
儲存變更
</button>
</div>

View File

@@ -1,6 +1,6 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
系統設定 - 安全性與限制
</h2>
</x-slot>
@@ -16,15 +16,15 @@
<!-- Main Content -->
<div class="lg:col-span-3">
@if (session('status'))
<div class="mb-6 rounded-md bg-green-50 p-4">
<p class="text-sm font-medium text-green-800">{{ session('status') }}</p>
<div class="mb-6 rounded-md bg-green-50 dark:bg-green-900/50 p-4">
<p class="text-sm font-medium text-green-800 dark:text-green-200">{{ session('status') }}</p>
</div>
@endif
<div class="bg-white shadow sm:rounded-lg">
<div class="px-6 py-5 border-b border-gray-200">
<h3 class="text-lg font-medium text-gray-900">安全性與限制設定</h3>
<p class="mt-1 text-sm text-gray-600">配置下載速率限制和文件上傳限制</p>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-6 py-5 border-b border-gray-200 dark:border-gray-700">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">安全性與限制設定</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">配置下載速率限制和文件上傳限制</p>
</div>
<form action="{{ route('admin.settings.security.update') }}" method="POST" class="px-6 py-6 space-y-6">
@@ -32,71 +32,71 @@
<!-- Rate Limit - Authenticated Users -->
<div>
<label for="rate_limit_authenticated" class="block text-sm font-medium text-gray-700">
<label for="rate_limit_authenticated" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
已登入用戶下載限制(每小時)
</label>
<input type="number" name="rate_limit_authenticated" id="rate_limit_authenticated"
value="{{ old('rate_limit_authenticated', $settings['rate_limit_authenticated']) }}"
min="1" max="1000"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<p class="mt-1 text-sm text-gray-500">已登入用戶每小時可下載的文件次數</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">已登入用戶每小時可下載的文件次數</p>
@error('rate_limit_authenticated')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Rate Limit - Guest Users -->
<div>
<label for="rate_limit_guest" class="block text-sm font-medium text-gray-700">
<label for="rate_limit_guest" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
訪客下載限制(每小時)
</label>
<input type="number" name="rate_limit_guest" id="rate_limit_guest"
value="{{ old('rate_limit_guest', $settings['rate_limit_guest']) }}"
min="1" max="1000"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<p class="mt-1 text-sm text-gray-500">未登入訪客每小時可下載的文件次數</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">未登入訪客每小時可下載的文件次數</p>
@error('rate_limit_guest')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Max File Size -->
<div>
<label for="max_file_size_mb" class="block text-sm font-medium text-gray-700">
<label for="max_file_size_mb" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
檔案大小上限MB
</label>
<input type="number" name="max_file_size_mb" id="max_file_size_mb"
value="{{ old('max_file_size_mb', $settings['max_file_size_mb']) }}"
min="1" max="100"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
required>
<p class="mt-1 text-sm text-gray-500">單一文件上傳的最大檔案大小</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">單一文件上傳的最大檔案大小</p>
@error('max_file_size_mb')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Allowed File Types -->
<div>
<label for="allowed_file_types" class="block text-sm font-medium text-gray-700">
<label for="allowed_file_types" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
允許的檔案類型
</label>
<input type="text" name="allowed_file_types" id="allowed_file_types"
value="{{ old('allowed_file_types', implode(', ', $settings['allowed_file_types'])) }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 sm:text-sm dark:bg-gray-900 dark:text-gray-300"
placeholder="pdf, doc, docx, xls, xlsx">
<p class="mt-1 text-sm text-gray-500">允許上傳的檔案副檔名,以逗號分隔</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">允許上傳的檔案副檔名,以逗號分隔</p>
@error('allowed_file_types')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@enderror
</div>
<!-- Submit Button -->
<div class="flex items-center justify-end pt-4 border-t">
<div class="flex items-center justify-end pt-4 border-t border-gray-200 dark:border-gray-700">
<button type="submit"
class="inline-flex justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
class="inline-flex justify-center rounded-md border border-transparent bg-indigo-600 dark:bg-indigo-500 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-600 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
儲存變更
</button>
</div>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Record Transaction') }} (¤)
記錄交易
</h2>
</x-slot>
@@ -14,13 +14,13 @@
<!-- Transaction Type -->
<div>
<label for="transaction_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Transaction Type') }} <span class="text-red-500">*</span>
交易類型 <span class="text-red-500">*</span>
</label>
<select name="transaction_type" id="transaction_type" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('transaction_type') border-red-300 @enderror">
<option value="">{{ __('Select type...') }}</option>
<option value="income" @selected(old('transaction_type') === 'income')>{{ __('Income') }} (6e)</option>
<option value="expense" @selected(old('transaction_type') === 'expense')>{{ __('Expense') }} (/ú)</option>
<option value="">選擇類型...</option>
<option value="income" @selected(old('transaction_type') === 'income')>收入</option>
<option value="expense" @selected(old('transaction_type') === 'expense')>支出</option>
</select>
@error('transaction_type')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
@@ -28,19 +28,19 @@
<!-- Account -->
<div>
<label for="chart_of_account_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Account') }} <span class="text-red-500">*</span>
帳戶 <span class="text-red-500">*</span>
</label>
<select name="chart_of_account_id" id="chart_of_account_id" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('chart_of_account_id') border-red-300 @enderror">
<option value="">{{ __('Select account...') }}</option>
<optgroup label="{{ __('Income Accounts') }}">
<option value="">選擇帳戶...</option>
<optgroup label="收入帳戶">
@foreach($incomeAccounts as $account)
<option value="{{ $account->id }}" @selected(old('chart_of_account_id') == $account->id)>
{{ $account->account_code }} - {{ $account->account_name_zh }}
</option>
@endforeach
</optgroup>
<optgroup label="{{ __('Expense Accounts') }}">
<optgroup label="支出帳戶">
@foreach($expenseAccounts as $account)
<option value="{{ $account->id }}" @selected(old('chart_of_account_id') == $account->id)>
{{ $account->account_code }} - {{ $account->account_name_zh }}
@@ -54,7 +54,7 @@
<!-- Transaction Date -->
<div>
<label for="transaction_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Transaction Date') }} <span class="text-red-500">*</span>
交易日期 <span class="text-red-500">*</span>
</label>
<input type="date" name="transaction_date" id="transaction_date" value="{{ old('transaction_date', now()->format('Y-m-d')) }}" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('transaction_date') border-red-300 @enderror">
@@ -64,7 +64,7 @@
<!-- Amount -->
<div>
<label for="amount" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Amount') }} (NT$) <span class="text-red-500">*</span>
金額 (NT$) <span class="text-red-500">*</span>
</label>
<input type="number" name="amount" id="amount" value="{{ old('amount') }}" step="0.01" min="0.01" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('amount') border-red-300 @enderror"
@@ -75,33 +75,33 @@
<!-- Description -->
<div>
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Description') }} <span class="text-red-500">*</span>
描述 <span class="text-red-500">*</span>
</label>
<input type="text" name="description" id="description" value="{{ old('description') }}" required maxlength="255"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('description') border-red-300 @enderror"
placeholder="{{ __('Brief description of the transaction') }}">
placeholder="交易的簡要描述">
@error('description')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>
<!-- Reference Number -->
<div>
<label for="reference_number" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Reference Number') }}
參考編號
</label>
<input type="text" name="reference_number" id="reference_number" value="{{ old('reference_number') }}" maxlength="255"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"
placeholder="{{ __('Receipt or invoice number (optional)') }}">
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">{{ __('Optional reference or receipt number') }}</p>
placeholder="收據或發票號碼(選填)">
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">選填參考編號或收據號碼</p>
</div>
<!-- Budget Item (Optional) -->
<div>
<label for="budget_item_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Link to Budget') }}
連結至預算
</label>
<select name="budget_item_id" id="budget_item_id"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('No budget link (standalone transaction)') }}</option>
<option value="">不連結預算(獨立交易)</option>
@foreach($budgets as $budget)
<optgroup label="{{ $budget->name }} ({{ $budget->fiscal_year }})">
@foreach($budget->budgetItems as $item)
@@ -112,28 +112,28 @@
</optgroup>
@endforeach
</select>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">{{ __('Link this transaction to a budget item to track actual vs budgeted amounts') }}</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">將此交易連結至預算項目以追蹤實際與預算金額</p>
</div>
<!-- Notes -->
<div>
<label for="notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Notes') }}
備註
</label>
<textarea name="notes" id="notes" rows="3"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100"
placeholder="{{ __('Additional notes (optional)') }}">{{ old('notes') }}</textarea>
placeholder="額外備註(選填)">{{ old('notes') }}</textarea>
</div>
<!-- Actions -->
<div class="flex items-center justify-end gap-x-4 border-t border-gray-200 pt-6 dark:border-gray-700">
<a href="{{ route('admin.transactions.index') }}"
class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600 dark:hover:bg-gray-600">
{{ __('Cancel') }}
取消
</a>
<button type="submit"
class="inline-flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-400 dark:focus:ring-offset-gray-800">
{{ __('Record Transaction') }}
記錄交易
</button>
</div>
</form>
@@ -148,13 +148,13 @@
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-blue-800 dark:text-blue-200">{{ __('Recording Transactions') }}</h3>
<h3 class="text-sm font-medium text-blue-800 dark:text-blue-200">記錄交易</h3>
<div class="mt-2 text-sm text-blue-700 dark:text-blue-300">
<ul class="list-disc pl-5 space-y-1">
<li>{{ __('Choose income or expense type based on money flow') }}</li>
<li>{{ __('Select the appropriate chart of account for categorization') }}</li>
<li>{{ __('Link to a budget item to automatically update budget vs actual tracking') }}</li>
<li>{{ __('Add reference numbers for audit trails and reconciliation') }}</li>
<li>根據資金流向選擇收入或支出類型</li>
<li>選擇適當的會計科目進行分類</li>
<li>連結至預算項目以自動更新預算與實際追蹤</li>
<li>新增參考編號以供稽核追蹤和對帳</li>
</ul>
</div>
</div>
@@ -162,4 +162,4 @@
</div>
</div>
</div>
</x-app-layout>
</x-app-layout>

View File

@@ -1,7 +1,7 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Transactions') }} (¤)
收支記錄 (收支記錄)
</h2>
</x-slot>
@@ -17,13 +17,13 @@
<!-- Header -->
<div class="sm:flex sm:items-center sm:justify-between mb-6">
<div>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">{{ __('Transaction List') }}</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">{{ __('Track all income and expense transactions') }}</p>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">交易列表</h3>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">追蹤所有收入和支出交易</p>
</div>
<div class="mt-4 sm:mt-0">
<a href="{{ route('admin.transactions.create') }}" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-400 dark:focus:ring-offset-gray-800">
<svg class="-ml-0.5 mr-1.5 h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"/></svg>
{{ __('Record Transaction') }}
記錄交易
</a>
</div>
</div>
@@ -31,11 +31,11 @@
<!-- Summary Cards -->
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 mb-6">
<div class="bg-green-50 dark:bg-green-900/30 rounded-lg p-4 border-l-4 border-green-400">
<dt class="text-sm font-medium text-green-800 dark:text-green-200">{{ __('Total Income') }}</dt>
<dt class="text-sm font-medium text-green-800 dark:text-green-200">總收入</dt>
<dd class="mt-1 text-2xl font-semibold text-green-900 dark:text-green-100">NT$ {{ number_format($totalIncome, 2) }}</dd>
</div>
<div class="bg-red-50 dark:bg-red-900/30 rounded-lg p-4 border-l-4 border-red-400">
<dt class="text-sm font-medium text-red-800 dark:text-red-200">{{ __('Total Expense') }}</dt>
<dt class="text-sm font-medium text-red-800 dark:text-red-200">總支出</dt>
<dd class="mt-1 text-2xl font-semibold text-red-900 dark:text-red-100">NT$ {{ number_format($totalExpense, 2) }}</dd>
</div>
</div>
@@ -44,38 +44,38 @@
<form method="GET" class="mb-6 space-y-4" role="search">
<div class="grid grid-cols-1 gap-4 sm:grid-cols-4">
<div>
<label for="transaction_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Type') }}</label>
<label for="transaction_type" class="block text-sm font-medium text-gray-700 dark:text-gray-300">類型</label>
<select name="transaction_type" id="transaction_type" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('All') }}</option>
<option value="income" @selected(request('transaction_type') === 'income')>{{ __('Income') }}</option>
<option value="expense" @selected(request('transaction_type') === 'expense')>{{ __('Expense') }}</option>
<option value="">所有</option>
<option value="income" @selected(request('transaction_type') === 'income')>收入</option>
<option value="expense" @selected(request('transaction_type') === 'expense')>支出</option>
</select>
</div>
<div>
<label for="chart_of_account_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Account') }}</label>
<label for="chart_of_account_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300">帳戶</label>
<select name="chart_of_account_id" id="chart_of_account_id" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<option value="">{{ __('All Accounts') }}</option>
<option value="">所有帳戶</option>
@foreach($accounts as $account)
<option value="{{ $account->id }}" @selected(request('chart_of_account_id') == $account->id)>{{ $account->account_code }} - {{ $account->account_name_zh }}</option>
@endforeach
</select>
</div>
<div>
<label for="start_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Start Date') }}</label>
<label for="start_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">開始日期</label>
<input type="date" name="start_date" id="start_date" value="{{ request('start_date') }}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
</div>
<div>
<label for="end_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('End Date') }}</label>
<label for="end_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">結束日期</label>
<input type="date" name="end_date" id="end_date" value="{{ request('end_date') }}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
</div>
</div>
<div class="flex gap-4">
<div class="flex-1">
<label for="search" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Search') }}</label>
<input type="text" name="search" id="search" value="{{ request('search') }}" placeholder="{{ __('Description or reference number...') }}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
<label for="search" class="block text-sm font-medium text-gray-700 dark:text-gray-300">搜尋</label>
<input type="text" name="search" id="search" value="{{ request('search') }}" placeholder="描述或參考編號..." class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
</div>
<div class="flex items-end">
<button type="submit" class="inline-flex justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600 dark:hover:bg-gray-600">{{ __('Filter') }}</button>
<button type="submit" class="inline-flex justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-100 dark:ring-gray-600 dark:hover:bg-gray-600">篩選</button>
</div>
</div>
</form>
@@ -83,15 +83,15 @@
<!-- Transactions Table -->
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg dark:ring-gray-700">
<table class="min-w-full divide-y divide-gray-300 dark:divide-gray-600">
<caption class="sr-only">{{ __('List of transactions') }}</caption>
<caption class="sr-only">交易列表</caption>
<thead class="bg-gray-50 dark:bg-gray-900">
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Date') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Type') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Account') }}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Description') }}</th>
<th scope="col" class="px-3 py-3.5 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">{{ __('Amount') }}</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4"><span class="sr-only">{{ __('Actions') }}</span></th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">日期</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">類型</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">帳戶</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-100">描述</th>
<th scope="col" class="px-3 py-3.5 text-right text-sm font-semibold text-gray-900 dark:text-gray-100">金額</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4"><span class="sr-only">操作</span></th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white dark:divide-gray-700 dark:bg-gray-800">
@@ -102,9 +102,9 @@
</td>
<td class="whitespace-nowrap px-3 py-4 text-sm">
@if($transaction->transaction_type === 'income')
<span class="inline-flex items-center rounded-full bg-green-100 px-2 py-1 text-xs font-medium text-green-800 dark:bg-green-900 dark:text-green-200">{{ __('Income') }}</span>
<span class="inline-flex items-center rounded-full bg-green-100 px-2 py-1 text-xs font-medium text-green-800 dark:bg-green-900 dark:text-green-200">收入</span>
@else
<span class="inline-flex items-center rounded-full bg-red-100 px-2 py-1 text-xs font-medium text-red-800 dark:bg-red-900 dark:text-red-200">{{ __('Expense') }}</span>
<span class="inline-flex items-center rounded-full bg-red-100 px-2 py-1 text-xs font-medium text-red-800 dark:bg-red-900 dark:text-red-200">支出</span>
@endif
</td>
<td class="px-3 py-4 text-sm text-gray-900 dark:text-gray-100">
@@ -116,16 +116,16 @@
{{ $transaction->transaction_type === 'income' ? '+' : '-' }}NT$ {{ number_format($transaction->amount, 2) }}
</td>
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium">
<a href="{{ route('admin.transactions.show', $transaction) }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">{{ __('View') }}</a>
<a href="{{ route('admin.transactions.show', $transaction) }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">檢視</a>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="px-3 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
<p>{{ __('No transactions found') }}</p>
<p>找不到交易記錄</p>
<div class="mt-4">
<a href="{{ route('admin.transactions.create') }}" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400">
+ {{ __('Record First Transaction') }}
+ 記錄第一筆交易
</a>
</div>
</td>
@@ -142,4 +142,4 @@
</div>
</div>
</div>
</x-app-layout>
</x-app-layout>

View File

@@ -0,0 +1,310 @@
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
試算表
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 space-y-6">
<!-- Filter Form -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<form method="GET" action="{{ route('admin.trial-balance.index') }}" class="space-y-4">
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
<!-- Start Date -->
<div>
<label for="start_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
開始日期
</label>
<input type="date" name="start_date" id="start_date" value="{{ $startDate }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
<!-- End Date -->
<div>
<label for="end_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
結束日期
</label>
<input type="date" name="end_date" id="end_date" value="{{ $endDate }}"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-gray-100">
</div>
<!-- Buttons -->
<div class="flex items-end gap-4">
<button type="submit" class="inline-flex justify-center rounded-md bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-700 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800">
產生
</button>
<a href="{{ route('admin.trial-balance.index') }}" class="inline-flex justify-center rounded-md bg-white dark:bg-gray-700 px-4 py-2 text-sm font-semibold text-gray-900 dark:text-gray-100 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600">
重設
</a>
</div>
</div>
</form>
</div>
</div>
<!-- Balance Status Alert -->
@if($isBalanced)
<div class="rounded-md bg-green-50 dark:bg-green-900/30 p-4 border border-green-200 dark:border-green-800">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-green-400" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-green-800 dark:text-green-200">
借貸平衡
</h3>
<p class="mt-1 text-sm text-green-700 dark:text-green-300">
借方總計等於貸方總計,試算表正確
</p>
</div>
</div>
</div>
@else
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4 border border-red-200 dark:border-red-800">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-red-800 dark:text-red-200">
借貸不平衡
</h3>
<p class="mt-1 text-sm text-red-700 dark:text-red-300">
差額: NT$ {{ number_format(abs($difference), 2) }}
({{ $difference > 0 ? '借方多' : '貸方多' }})
</p>
</div>
</div>
</div>
@endif
<!-- Summary Cards -->
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
<!-- Debit Total -->
<div class="bg-blue-50 dark:bg-blue-900/30 shadow sm:rounded-lg border-l-4 border-blue-400">
<div class="px-4 py-5 sm:p-6">
<dt class="text-sm font-medium text-blue-800 dark:text-blue-200">
借方總計
</dt>
<dd class="mt-1 text-3xl font-semibold text-blue-900 dark:text-blue-100">
NT$ {{ number_format($grandDebitTotal, 2) }}
</dd>
</div>
</div>
<!-- Credit Total -->
<div class="bg-purple-50 dark:bg-purple-900/30 shadow sm:rounded-lg border-l-4 border-purple-400">
<div class="px-4 py-5 sm:p-6">
<dt class="text-sm font-medium text-purple-800 dark:text-purple-200">
貸方總計
</dt>
<dd class="mt-1 text-3xl font-semibold text-purple-900 dark:text-purple-100">
NT$ {{ number_format($grandCreditTotal, 2) }}
</dd>
</div>
</div>
<!-- Difference -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg border-l-4 {{ $isBalanced ? 'border-green-400' : 'border-red-400' }}">
<div class="px-4 py-5 sm:p-6">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">
差額
</dt>
<dd class="mt-1 text-3xl font-semibold {{ $isBalanced ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400' }}">
NT$ {{ number_format(abs($difference), 2) }}
</dd>
</div>
</div>
</div>
@php
$typeLabels = [
'asset' => '資產 (Assets)',
'liability' => '負債 (Liabilities)',
'net_asset' => '淨資產/基金 (Net Assets)',
'income' => '收入 (Income)',
'expense' => '支出 (Expenses)',
];
$typeOrder = ['asset', 'liability', 'net_asset', 'income', 'expense'];
@endphp
<!-- Accounts by Type -->
@if($accounts->count() > 0)
@foreach($typeOrder as $type)
@if(isset($accountsByType[$type]) && $accountsByType[$type]->count() > 0)
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4 flex items-center">
@switch($type)
@case('asset')
<span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-green-100 dark:bg-green-900/50 text-green-600 dark:text-green-400 mr-2">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</span>
@break
@case('liability')
<span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-red-100 dark:bg-red-900/50 text-red-600 dark:text-red-400 mr-2">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 14l6-6m-5.5.5h.01m4.99 5h.01M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16l3.5-2 3.5 2 3.5-2 3.5 2z" />
</svg>
</span>
@break
@case('net_asset')
<span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-indigo-100 dark:bg-indigo-900/50 text-indigo-600 dark:text-indigo-400 mr-2">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
</span>
@break
@case('income')
<span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-emerald-100 dark:bg-emerald-900/50 text-emerald-600 dark:text-emerald-400 mr-2">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
</svg>
</span>
@break
@case('expense')
<span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-orange-100 dark:bg-orange-900/50 text-orange-600 dark:text-orange-400 mr-2">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 17h8m0 0V9m0 8l-8-8-4 4-6-6" />
</svg>
</span>
@break
@endswitch
{{ $typeLabels[$type] ?? ucfirst($type) }}
</h3>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
科目代碼
</th>
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-300">
科目名稱
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-blue-600 dark:text-blue-400">
借方
</th>
<th scope="col" class="px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-purple-600 dark:text-purple-400">
貸方
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@php $typeDebitTotal = 0; $typeCreditTotal = 0; @endphp
@foreach($accountsByType[$type] as $item)
@php
$typeDebitTotal += $item['debit_total'];
$typeCreditTotal += $item['credit_total'];
@endphp
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
<td class="whitespace-nowrap px-4 py-3 text-sm font-mono text-gray-900 dark:text-gray-100">
<a href="{{ route('admin.general-ledger.index', ['account_id' => $item['account']->id, 'start_date' => $startDate, 'end_date' => $endDate]) }}"
class="text-indigo-600 dark:text-indigo-400 hover:underline">
{{ $item['account']->account_code }}
</a>
</td>
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
{{ $item['account']->account_name_zh }}
<span class="text-xs text-gray-500 dark:text-gray-400">
{{ $item['account']->account_name_en }}
</span>
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-blue-600 dark:text-blue-400">
{{ $item['debit_total'] > 0 ? number_format($item['debit_total'], 2) : '' }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-purple-600 dark:text-purple-400">
{{ $item['credit_total'] > 0 ? number_format($item['credit_total'], 2) : '' }}
</td>
</tr>
@endforeach
<!-- Type Subtotal -->
<tr class="bg-gray-50 dark:bg-gray-700 font-semibold">
<td class="whitespace-nowrap px-4 py-3 text-sm text-gray-900 dark:text-gray-100" colspan="2">
小計
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-blue-700 dark:text-blue-300">
{{ $typeDebitTotal > 0 ? number_format($typeDebitTotal, 2) : '' }}
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm text-right text-purple-700 dark:text-purple-300">
{{ $typeCreditTotal > 0 ? number_format($typeCreditTotal, 2) : '' }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
@endif
@endforeach
<!-- Grand Total -->
<div class="bg-gray-900 dark:bg-gray-950 shadow sm:rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="overflow-x-auto">
<table class="min-w-full">
<tbody>
<tr class="text-white">
<td class="px-4 py-4 text-lg font-bold">
總計
</td>
<td class="whitespace-nowrap px-4 py-4 text-right">
<span class="text-sm text-gray-400">借方</span>
<div class="text-2xl font-bold text-blue-400">
NT$ {{ number_format($grandDebitTotal, 2) }}
</div>
</td>
<td class="whitespace-nowrap px-4 py-4 text-right">
<span class="text-sm text-gray-400">貸方</span>
<div class="text-2xl font-bold text-purple-400">
NT$ {{ number_format($grandCreditTotal, 2) }}
</div>
</td>
<td class="whitespace-nowrap px-4 py-4 text-right">
<span class="text-sm text-gray-400">差額</span>
<div class="text-2xl font-bold {{ $isBalanced ? 'text-green-400' : 'text-red-400' }}">
NT$ {{ number_format(abs($difference), 2) }}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
@else
<!-- No Data -->
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="px-4 py-12 text-center">
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<h3 class="mt-2 text-sm font-medium text-gray-900 dark:text-gray-100">
無會計分錄
</h3>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
所選期間內沒有會計分錄
</p>
<div class="mt-6">
<a href="{{ route('admin.finance.create') }}" class="inline-flex items-center rounded-md bg-indigo-600 dark:bg-indigo-500 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600">
<svg class="-ml-1 mr-2 h-5 w-5" 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>
</div>
@endif
</div>
</div>
</x-app-layout>