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>

View File

@@ -1,5 +1,5 @@
<x-guest-layout>
<div class="mb-4 text-sm text-gray-600">
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
{{ __('This is a secure area of the application. Please confirm your password before continuing.') }}
</div>

View File

@@ -1,5 +1,5 @@
<x-guest-layout>
<div class="mb-4 text-sm text-gray-600">
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
{{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
</div>

View File

@@ -27,14 +27,14 @@
<!-- Remember Me -->
<div class="block mt-4">
<label for="remember_me" class="inline-flex items-center">
<input id="remember_me" type="checkbox" class="rounded border-gray-300 text-indigo-600 shadow-sm focus:ring-indigo-500" name="remember">
<span class="ms-2 text-sm text-gray-600">{{ __('Remember me') }}</span>
<input id="remember_me" type="checkbox" class="rounded border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:bg-gray-900" name="remember">
<span class="ms-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Remember me') }}</span>
</label>
</div>
<div class="flex items-center justify-end mt-4">
@if (Route::has('password.request'))
<a class="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" href="{{ route('password.request') }}">
<a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="{{ route('password.request') }}">
{{ __('Forgot your password?') }}
</a>
@endif

View File

@@ -40,7 +40,7 @@
</div>
<div class="flex items-center justify-end mt-4">
<a class="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" href="{{ route('login') }}">
<a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="{{ route('login') }}">
{{ __('Already registered?') }}
</a>

View File

@@ -1,10 +1,10 @@
<x-guest-layout>
<div class="mb-4 text-sm text-gray-600">
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
{{ __('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
</div>
@if (session('status') == 'verification-link-sent')
<div class="mb-4 font-medium text-sm text-green-600">
<div class="mb-4 font-medium text-sm text-green-600 dark:text-green-400">
{{ __('A new verification link has been sent to the email address you provided during registration.') }}
</div>
@endif
@@ -23,7 +23,7 @@
<form method="POST" action="{{ route('logout') }}">
@csrf
<button type="submit" class="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
<button type="submit" class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800">
{{ __('Log Out') }}
</button>
</form>

View File

@@ -1,7 +1,7 @@
@props(['status'])
@if ($status)
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600']) }}>
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600 dark:text-green-400']) }}>
{{ $status }}
</div>
@endif

View File

@@ -1 +1 @@
<a {{ $attributes->merge(['class' => 'block w-full px-4 py-2 text-start text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 transition duration-150 ease-in-out']) }}>{{ $slot }}</a>
<a {{ $attributes->merge(['class' => 'block w-full px-4 py-2 text-start text-sm leading-5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-700 transition duration-150 ease-in-out']) }}>{{ $slot }}</a>

View File

@@ -1,4 +1,4 @@
@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white'])
@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white dark:bg-gray-700'])
@php
switch ($align) {

View File

@@ -1,7 +1,7 @@
@props(['messages'])
@if ($messages)
<ul {{ $attributes->merge(['class' => 'text-sm text-red-600 space-y-1']) }}>
<ul {{ $attributes->merge(['class' => 'text-sm text-red-600 dark:text-red-400 space-y-1']) }}>
@foreach ((array) $messages as $message)
<li>{{ $message }}</li>
@endforeach

View File

@@ -1,5 +1,5 @@
@props(['value'])
<label {{ $attributes->merge(['class' => 'block font-medium text-sm text-gray-700']) }}>
<label {{ $attributes->merge(['class' => 'block font-medium text-sm text-gray-700 dark:text-gray-300']) }}>
{{ $value ?? $slot }}
</label>

View File

@@ -65,7 +65,7 @@ $maxWidth = [
<div
x-show="show"
class="mb-6 bg-white rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto"
class="mb-6 bg-white dark:bg-gray-800 rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto"
x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"

View File

@@ -2,8 +2,8 @@
@php
$classes = ($active ?? false)
? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'
: 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out';
? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 dark:border-indigo-600 text-sm font-medium leading-5 text-gray-900 dark:text-gray-100 focus:outline-none focus:border-indigo-700 dark:focus:border-indigo-300 transition duration-150 ease-in-out'
: 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600 focus:outline-none focus:text-gray-700 dark:focus:text-gray-300 focus:border-gray-300 dark:focus:border-gray-600 transition duration-150 ease-in-out';
@endphp
<a {{ $attributes->merge(['class' => $classes]) }} @if($active) aria-current="page" @endif>

View File

@@ -1,3 +1,3 @@
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 focus:bg-gray-700 active:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition ease-in-out duration-150']) }}>
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-gray-800 dark:bg-gray-200 border border-transparent rounded-md font-semibold text-xs text-white dark:text-gray-800 uppercase tracking-widest hover:bg-gray-700 dark:hover:bg-white focus:bg-gray-700 dark:focus:bg-white active:bg-gray-900 dark:active:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150']) }}>
{{ $slot }}
</button>

View File

@@ -2,8 +2,8 @@
@php
$classes = ($active ?? false)
? 'block w-full ps-3 pe-4 py-2 border-l-4 border-indigo-400 text-start text-base font-medium text-indigo-700 bg-indigo-50 focus:outline-none focus:text-indigo-800 focus:bg-indigo-100 focus:border-indigo-700 transition duration-150 ease-in-out'
: 'block w-full ps-3 pe-4 py-2 border-l-4 border-transparent text-start text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out';
? 'block w-full ps-3 pe-4 py-2 border-l-4 border-indigo-400 dark:border-indigo-600 text-start text-base font-medium text-indigo-700 dark:text-indigo-200 bg-indigo-50 dark:bg-indigo-900 focus:outline-none focus:text-indigo-800 dark:focus:text-indigo-100 focus:bg-indigo-100 dark:focus:bg-indigo-800 focus:border-indigo-700 dark:focus:border-indigo-300 transition duration-150 ease-in-out'
: 'block w-full ps-3 pe-4 py-2 border-l-4 border-transparent text-start text-base font-medium text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 hover:border-gray-300 dark:hover:border-gray-600 focus:outline-none focus:text-gray-800 dark:focus:text-gray-200 focus:bg-gray-50 dark:focus:bg-gray-700 focus:border-gray-300 dark:focus:border-gray-600 transition duration-150 ease-in-out';
@endphp
<a {{ $attributes->merge(['class' => $classes]) }} @if($active) aria-current="page" @endif>

View File

@@ -1,3 +1,3 @@
<button {{ $attributes->merge(['type' => 'button', 'class' => 'inline-flex items-center px-4 py-2 bg-white border border-gray-300 rounded-md font-semibold text-xs text-gray-700 uppercase tracking-widest shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-25 transition ease-in-out duration-150']) }}>
<button {{ $attributes->merge(['type' => 'button', 'class' => 'inline-flex items-center px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-500 rounded-md font-semibold text-xs text-gray-700 dark:text-gray-300 uppercase tracking-widest shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 disabled:opacity-25 transition ease-in-out duration-150']) }}>
{{ $slot }}
</button>

View File

@@ -1,3 +1,3 @@
@props(['disabled' => false])
<input {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm']) !!}>
<input {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm']) !!}>

View File

@@ -13,7 +13,7 @@
</a>
@can('create_finance_documents')
<a href="{{ route('admin.finance.create') }}" class="inline-flex items-center px-3 py-2 text-sm font-medium rounded-md bg-emerald-50 dark:bg-emerald-900 text-emerald-700 dark:text-emerald-200 hover:bg-emerald-100 dark:hover:bg-emerald-800 border border-emerald-200 dark:border-emerald-700">
建立財務申請
建立報銷申請
</a>
@endcan
</div>
@@ -46,7 +46,7 @@
<div class="bg-white dark:bg-gray-800 shadow-sm sm:rounded-lg border border-gray-100 dark:border-gray-700 p-5">
<div class="flex items-start justify-between">
<div>
<div class="text-sm font-semibold text-gray-700 dark:text-gray-300">財務申請/審核</div>
<div class="text-sm font-semibold text-gray-700 dark:text-gray-300">報銷申請/審核</div>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">申請、審核、付款、對帳全流程</p>
</div>
<span class="text-2xl">💼</span>
@@ -110,7 +110,7 @@
<h4 class="text-sm font-semibold text-gray-800 dark:text-gray-200">申請人 / 會員</h4><span>📝</span>
</div>
<ul class="mt-3 space-y-2 text-sm text-gray-700 dark:text-gray-300">
<li><a class="hover:text-blue-600 dark:hover:text-blue-400" href="{{ route('admin.finance.create') }}">建立財務申請</a></li>
<li><a class="hover:text-blue-600 dark:hover:text-blue-400" href="{{ route('admin.finance.create') }}">建立報銷申請</a></li>
<li><a class="hover:text-blue-600 dark:hover:text-blue-400" href="{{ route('admin.finance.index') }}">查看我的申請進度</a></li>
<li><a class="hover:text-blue-600 dark:hover:text-blue-400" href="{{ route('member.dashboard') }}">查看會籍與繳費紀錄</a></li>
</ul>

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-7xl sm:px-6 lg:px-8 space-y-6">
<!-- Categories -->
<div class="bg-white shadow sm:rounded-lg p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">文件類別</h3>
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">文件類別</h3>
<div class="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-6">
<a href="{{ route('documents.index') }}"
class="flex flex-col items-center p-4 border rounded-lg hover:bg-gray-50 transition
{{ !request('category') ? 'border-indigo-500 bg-indigo-50' : 'border-gray-200' }}">
class="flex flex-col items-center p-4 border rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition
{{ !request('category') ? 'border-indigo-500 bg-indigo-50 dark:bg-indigo-900/30' : 'border-gray-200 dark:border-gray-700' }}">
<span class="text-3xl mb-2">📚</span>
<span class="text-sm font-medium text-gray-900">全部文件</span>
<span class="text-xs text-gray-500 mt-1">{{ $documents->total() }}</span>
<span class="text-sm font-medium text-gray-900 dark:text-gray-100">全部文件</span>
<span class="text-xs text-gray-500 dark:text-gray-400 mt-1">{{ $documents->total() }}</span>
</a>
@foreach($categories as $category)
<a href="{{ route('documents.index', ['category' => $category->id]) }}"
class="flex flex-col items-center p-4 border rounded-lg hover:bg-gray-50 transition
{{ request('category') == $category->id ? 'border-indigo-500 bg-indigo-50' : 'border-gray-200' }}">
class="flex flex-col items-center p-4 border rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition
{{ request('category') == $category->id ? 'border-indigo-500 bg-indigo-50 dark:bg-indigo-900/30' : 'border-gray-200 dark:border-gray-700' }}">
<span class="text-3xl mb-2">{{ $category->getIconDisplay() }}</span>
<span class="text-sm font-medium text-gray-900 text-center">{{ $category->name }}</span>
<span class="text-xs text-gray-500 mt-1">{{ $category->active_documents_count }}</span>
<span class="text-sm font-medium text-gray-900 dark:text-gray-100 text-center">{{ $category->name }}</span>
<span class="text-xs text-gray-500 dark:text-gray-400 mt-1">{{ $category->active_documents_count }}</span>
</a>
@endforeach
</div>
</div>
<!-- Search -->
<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('documents.index') }}" class="flex gap-4">
<input type="hidden" name="category" value="{{ request('category') }}">
<div class="flex-1">
<input type="text" name="search" value="{{ request('search') }}" placeholder="搜尋文件標題或說明..."
class="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
class="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 focus:ring-indigo-500">
</div>
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-6 py-2 text-sm font-medium text-white hover:bg-indigo-700">
<button type="submit" class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-6 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-500">
搜尋
</button>
@if(request('search') || request('category'))
<a href="{{ route('documents.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">
<a href="{{ route('documents.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>
@endif
@@ -52,7 +52,7 @@
<!-- Documents List -->
<div class="space-y-4">
@forelse($documents as $document)
<div class="bg-white shadow sm:rounded-lg hover:shadow-md transition">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg hover:shadow-md transition">
<div class="px-6 py-5">
<div class="flex items-start">
<div class="flex-shrink-0 text-4xl mr-4">
@@ -61,15 +61,15 @@
<div class="flex-1 min-w-0">
<div class="flex items-start justify-between">
<div class="flex-1">
<h3 class="text-lg font-medium text-gray-900">
<a href="{{ route('documents.public.show', $document->public_uuid) }}" class="hover:text-indigo-600">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">
<a href="{{ route('documents.public.show', $document->public_uuid) }}" class="hover:text-indigo-600 dark:hover:text-indigo-400">
{{ $document->title }}
</a>
</h3>
@if($document->description)
<p class="mt-1 text-sm text-gray-500">{{ $document->description }}</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">{{ $document->description }}</p>
@endif
<div class="mt-2 flex flex-wrap items-center gap-x-4 gap-y-2 text-sm text-gray-500">
<div class="mt-2 flex flex-wrap items-center gap-x-4 gap-y-2 text-sm text-gray-500 dark:text-gray-400">
<span class="inline-flex items-center">
{{ $document->category->icon }} {{ $document->category->name }}
</span>
@@ -91,11 +91,11 @@
</div>
<div class="ml-6 flex flex-col space-y-2">
<a href="{{ route('documents.public.show', $document->public_uuid) }}"
class="inline-flex items-center justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700">
class="inline-flex items-center justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-500">
檢視
</a>
<a href="{{ route('documents.public.download', $document->public_uuid) }}"
class="inline-flex 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">
class="inline-flex 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-300 hover:bg-gray-50 dark:hover:bg-gray-600">
下載
</a>
</div>
@@ -105,16 +105,16 @@
</div>
</div>
@empty
<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-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>
<h3 class="mt-2 text-sm font-medium text-gray-900">找不到文件</h3>
<p class="mt-1 text-sm text-gray-500">目前沒有符合條件的文件</p>
<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>
@if(request('search') || request('category'))
<div class="mt-6">
<a href="{{ route('documents.index') }}" class="text-indigo-600 hover:text-indigo-900">
<a href="{{ route('documents.index') }}" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
瀏覽所有文件
</a>
</div>
@@ -126,7 +126,7 @@
<!-- Pagination -->
@if($documents->hasPages())
<div class="bg-white shadow sm:rounded-lg p-6">
<div class="bg-white dark:bg-gray-800 shadow sm:rounded-lg p-6">
{{ $documents->links() }}
</div>
@endif

View File

@@ -1,10 +1,10 @@
<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>
<a href="{{ route('documents.index') }}" class="text-sm text-gray-600 hover:text-gray-900">
<a href="{{ route('documents.index') }}" class="text-sm text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-200">
返回文件中心
</a>
</div>
@@ -13,32 +13,32 @@
<div class="py-12">
<div class="mx-auto max-w-4xl sm:px-6 lg:px-8 space-y-6">
<!-- Document Header -->
<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-8">
<div class="flex items-start">
<div class="flex-shrink-0 text-6xl mr-6">
{{ $document->currentVersion->getFileIcon() }}
</div>
<div class="flex-1">
<h1 class="text-2xl font-bold text-gray-900">{{ $document->title }}</h1>
<h1 class="text-2xl font-bold text-gray-900 dark:text-gray-100">{{ $document->title }}</h1>
@if($document->document_number)
<p class="mt-1 text-sm text-gray-500">文號:{{ $document->document_number }}</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">文號:{{ $document->document_number }}</p>
@endif
@if($document->description)
<p class="mt-3 text-gray-700">{{ $document->description }}</p>
<p class="mt-3 text-gray-700 dark:text-gray-300">{{ $document->description }}</p>
@endif
<div class="mt-4 flex flex-wrap items-center gap-4">
<span class="inline-flex items-center rounded-full px-3 py-1 text-sm font-medium
@if($document->access_level === 'public') bg-green-100 text-green-800
@elseif($document->access_level === 'members') bg-blue-100 text-blue-800
@else bg-gray-100 text-gray-800
@if($document->access_level === 'public') bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200
@elseif($document->access_level === 'members') bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200
@else bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200
@endif">
{{ $document->getAccessLevelLabel() }}
</span>
<span class="text-sm text-gray-500">
<span class="text-sm text-gray-500 dark:text-gray-400">
{{ $document->category->icon }} {{ $document->category->name }}
</span>
<span class="text-sm text-gray-500">
<span class="text-sm text-gray-500 dark:text-gray-400">
📅 {{ $document->created_at->format('Y年m月d日') }}
</span>
</div>
@@ -48,40 +48,40 @@
</div>
<!-- Current Version Info -->
<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>
<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>
</div>
<div class="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">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">v{{ $document->currentVersion->version_number }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">檔案名稱</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->currentVersion->original_filename }}</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->currentVersion->original_filename }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">檔案大小</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->currentVersion->getFileSizeHuman() }}</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->currentVersion->getFileSizeHuman() }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">上傳時間</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->currentVersion->uploaded_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->currentVersion->uploaded_at->format('Y-m-d H:i') }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">上傳者</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $document->currentVersion->uploadedBy->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->currentVersion->uploadedBy->name }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">檔案格式</dt>
<dd class="mt-1 text-sm text-gray-900">{{ strtoupper($document->currentVersion->getFileExtension()) }}</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">{{ strtoupper($document->currentVersion->getFileExtension()) }}</dd>
</div>
@if($document->currentVersion->version_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">{{ $document->currentVersion->version_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">{{ $document->currentVersion->version_notes }}</dd>
</div>
@endif
</dl>
@@ -90,30 +90,30 @@
@if($document->expires_at)
<div class="mt-4">
@if($document->isExpired())
<div class="rounded-md bg-red-50 p-3">
<div class="rounded-md bg-red-50 dark:bg-red-900/30 p-3">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-red-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<svg class="h-5 w-5 text-red-400 dark:text-red-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<p class="text-sm font-medium text-red-800">
<p class="text-sm font-medium text-red-800 dark:text-red-200">
此文件已於 {{ $document->expires_at->format('Y年m月d日') }} 過期
</p>
</div>
</div>
</div>
@elseif($document->isExpiringSoon(30))
<div class="rounded-md bg-yellow-50 p-3">
<div class="rounded-md bg-yellow-50 dark:bg-yellow-900/30 p-3">
<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-300" 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">
<p class="text-sm font-medium text-yellow-800">
<p class="text-sm font-medium text-yellow-800 dark:text-yellow-200">
此文件將於 {{ $document->expires_at->format('Y年m月d日') }} 過期
</p>
</div>
@@ -125,14 +125,14 @@
<div class="mt-6 flex flex-wrap gap-4">
<a href="{{ route('documents.public.download', $document->public_uuid) }}"
class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-6 py-3 text-base font-medium text-white hover:bg-indigo-700">
class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-6 py-3 text-base font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-500">
<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="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
下載文件
</a>
<button onclick="copyToClipboard('{{ $document->getPublicUrl() }}')"
class="inline-flex items-center rounded-md border border-gray-300 bg-white px-6 py-3 text-base 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-6 py-3 text-base font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-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="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
@@ -140,7 +140,7 @@
</button>
@if(settings()->isFeatureEnabled('qr_codes') && (!auth()->user() || auth()->user()->can('use_qr_codes')))
<a href="{{ route('documents.public.qrcode', $document->public_uuid) }}"
class="inline-flex items-center rounded-md border border-gray-300 bg-white px-6 py-3 text-base 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-6 py-3 text-base font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-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 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 12h4.01M16 20h4M4 12h4m12 0h.01M5 8h2a1 1 0 001-1V5a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1zm12 0h2a1 1 0 001-1V5a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 001 1zM5 20h2a1 1 0 001-1v-2a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1z" />
</svg>
@@ -153,40 +153,40 @@
<!-- Version History -->
@if($document->versions->count() > 1)
<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"> {{ $document->version_count }} 個版本</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"> {{ $document->version_count }} 個版本</p>
</div>
<div class="px-6 py-5">
<ul class="space-y-4">
@foreach($document->versions as $version)
<li class="flex items-start {{ $version->is_current ? 'bg-indigo-50 -mx-6 px-6 py-4' : '' }}">
<li class="flex items-start {{ $version->is_current ? 'bg-indigo-50 dark:bg-indigo-900/30 -mx-6 px-6 py-4' : '' }}">
<div class="flex-shrink-0 text-2xl mr-4">
{{ $version->getFileIcon() }}
</div>
<div class="flex-1 min-w-0">
<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 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">
當前版本
</span>
@endif
</div>
<p class="mt-1 text-sm text-gray-500">
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
{{ $version->original_filename }} · {{ $version->getFileSizeHuman() }}
</p>
<p class="mt-1 text-xs text-gray-500">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
{{ $version->uploaded_at->format('Y-m-d H:i') }} · {{ $version->uploadedBy->name }}
</p>
@if($version->version_notes)
<p class="mt-2 text-sm text-gray-600">{{ $version->version_notes }}</p>
<p class="mt-2 text-sm text-gray-600 dark:text-gray-300">{{ $version->version_notes }}</p>
@endif
</div>
<div class="ml-4">
<a href="{{ route('documents.public.download-version', [$document->public_uuid, $version->id]) }}"
class="text-sm text-indigo-600 hover:text-indigo-900">
class="text-sm text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300">
下載
</a>
</div>
@@ -198,31 +198,31 @@
@endif
<!-- File Integrity Info -->
<div class="bg-gray-50 shadow sm:rounded-lg">
<div class="bg-gray-50 dark:bg-gray-700 shadow sm:rounded-lg">
<div class="px-6 py-4">
<div class="flex items-center text-sm text-gray-600">
<div class="flex items-center text-sm text-gray-600 dark:text-gray-300">
<svg class="mr-2 h-5 w-5 text-green-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="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
<span>
此文件經過完整性驗證,確保內容未被篡改。檔案雜湊:
<code class="ml-1 px-2 py-1 bg-gray-100 rounded text-xs">{{ substr($document->currentVersion->file_hash, 0, 16) }}...</code>
<code class="ml-1 px-2 py-1 bg-gray-100 dark:bg-gray-900 rounded text-xs">{{ substr($document->currentVersion->file_hash, 0, 16) }}...</code>
</span>
</div>
</div>
</div>
<!-- Statistics -->
<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">
<div class="grid grid-cols-2 gap-4 text-center">
<div>
<div class="text-3xl font-bold text-indigo-600">{{ $document->view_count }}</div>
<div class="mt-1 text-sm text-gray-500">檢視次數</div>
<div class="text-3xl font-bold text-indigo-600 dark:text-indigo-400">{{ $document->view_count }}</div>
<div class="mt-1 text-sm text-gray-500 dark:text-gray-400">檢視次數</div>
</div>
<div>
<div class="text-3xl font-bold text-green-600">{{ $document->download_count }}</div>
<div class="mt-1 text-sm text-gray-500">下載次數</div>
<div class="text-3xl font-bold text-green-600 dark:text-green-400">{{ $document->download_count }}</div>
<div class="mt-1 text-sm text-gray-500 dark:text-gray-400">下載次數</div>
</div>
</div>
</div>

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" x-data="themeSwitcher()" x-init="init()" :class="{'dark': isDark}">
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -35,30 +35,5 @@
{{ $slot }}
</main>
</div>
<script>
function themeSwitcher() {
return {
isDark: false,
init() {
const stored = localStorage.getItem('theme');
if (stored) {
this.isDark = stored === 'dark';
} else {
this.isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
}
this.apply();
},
toggle() {
this.isDark = !this.isDark;
localStorage.setItem('theme', this.isDark ? 'dark' : 'light');
this.apply();
},
apply() {
document.documentElement.classList.toggle('dark', this.isDark);
}
}
}
</script>
</body>
</html>

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -18,14 +18,14 @@
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:z-50 focus:p-4 focus:bg-white focus:text-black focus:outline-none focus:ring-2 focus:ring-indigo-500">
{{ __('Skip to main content') }}
</a>
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100">
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-gray-900">
<div>
<a href="/">
<x-application-logo class="h-auto w-48 fill-current text-gray-500" />
<img src="{{ asset('images/usher-logo-long.png') }}" class="h-auto fill-current text-gray-500" style="max-width: 384px;" />
</a>
</div>
<div id="main-content" class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white shadow-md overflow-hidden sm:rounded-lg">
<div id="main-content" class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-gray-800 shadow-md overflow-hidden sm:rounded-lg">
{{ $slot }}
</div>
</div>

View File

@@ -13,23 +13,23 @@
<!-- Navigation Links -->
<div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
<x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
{{ __('Dashboard') }}
首頁
</x-nav-link>
<x-nav-link :href="route('member.dashboard')" :active="request()->routeIs('member.dashboard')">
{{ __('My Membership') }}
我的會籍
</x-nav-link>
<x-nav-link :href="route('documents.index')" :active="request()->routeIs('documents.*') && !request()->routeIs('admin.documents.*')">
{{ __('Documents') }}
文件
</x-nav-link>
@if(Auth::user() && (Auth::user()->hasRole(['admin', 'membership_manager', 'finance_accountant', 'staff']) || Auth::user()->canAny(['view_finance_documents', 'view_accounting_transactions', 'manage_system_settings'])))
@if(Auth::user() && (Auth::user()->hasRole(['admin', 'membership_manager', 'finance_accountant', 'finance_cashier', 'staff']) || Auth::user()->canAny(['view_finance_documents', 'view_incomes', 'view_accounting_transactions', 'manage_system_settings'])))
<div class="hidden sm:flex sm:items-center">
<x-dropdown align="right" width="48">
<x-slot name="trigger">
<button class="@if(request()->routeIs('admin.*')) inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 dark:border-indigo-600 text-sm font-medium leading-5 text-gray-900 dark:text-slate-100 focus:outline-none focus:border-indigo-700 dark:focus:border-indigo-300 transition duration-150 ease-in-out @else inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 dark:text-slate-400 hover:text-gray-700 dark:hover:text-slate-300 hover:border-gray-300 dark:hover:border-slate-600 focus:outline-none focus:text-gray-700 dark:focus:text-slate-300 focus:border-gray-300 dark:focus:border-slate-600 transition duration-150 ease-in-out @endif">
<div>{{ __('Management') }}</div>
<div>管理</div>
<div class="ms-1">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
@@ -42,53 +42,64 @@
<x-slot name="content">
@can('view_announcements')
<x-dropdown-link :href="route('admin.announcements.index')">
{{ __('Admin: Announcements') }}
公告管理
</x-dropdown-link>
@endcan
@hasrole('admin|membership_manager')
<x-dropdown-link :href="route('admin.members.index')">
{{ __('Admin: Members') }}
會員管理
</x-dropdown-link>
@endhasrole
@role('admin')
<x-dropdown-link :href="route('admin.roles.index')">
{{ __('Admin: Roles') }}
角色管理
</x-dropdown-link>
@endrole
@can('view_finance_documents')
<x-dropdown-link :href="route('admin.finance.index')">
{{ __('Admin: Finance') }}
報銷管理
</x-dropdown-link>
@endcan
@can('view_incomes')
<x-dropdown-link :href="route('admin.incomes.index')">
收入管理
</x-dropdown-link>
@endcan
@hasrole('admin|finance_accountant')
<x-dropdown-link :href="route('admin.budgets.index')">
{{ __('Admin: Budgets') }}
預算管理
</x-dropdown-link>
@endhasrole
@can('view_accounting_transactions')
<x-dropdown-link :href="route('admin.transactions.index')">
{{ __('Admin: Transactions') }}
交易記錄
</x-dropdown-link>
<x-dropdown-link :href="route('admin.general-ledger.index')">
總分類帳
</x-dropdown-link>
<x-dropdown-link :href="route('admin.trial-balance.index')">
試算表
</x-dropdown-link>
@endcan
<x-dropdown-link :href="route('admin.issues.index')">
{{ __('Admin: Tasks') }}
任務管理
</x-dropdown-link>
@role('admin')
<x-dropdown-link :href="route('admin.audit.index')">
{{ __('Admin: Audit Logs') }}
稽核日誌
</x-dropdown-link>
<x-dropdown-link :href="route('admin.document-categories.index')">
{{ __('Admin: Document Categories') }}
文件分類管理
</x-dropdown-link>
@endrole
@hasrole('admin|staff')
<x-dropdown-link :href="route('admin.documents.index')">
{{ __('Admin: Documents') }}
文件管理
</x-dropdown-link>
@endhasrole
@can('manage_system_settings')
<x-dropdown-link :href="route('admin.settings.general')">
{{ __('Admin: System Settings') }}
系統設定
</x-dropdown-link>
@endcan
</x-slot>
@@ -115,7 +126,7 @@
<x-slot name="content">
<x-dropdown-link :href="route('profile.edit')">
{{ __('Profile') }}
個人檔案
</x-dropdown-link>
<!-- Authentication -->
@@ -125,7 +136,7 @@
<x-dropdown-link :href="route('logout')"
onclick="event.preventDefault();
this.closest('form').submit();">
{{ __('Log Out') }}
登出
</x-dropdown-link>
</form>
</x-slot>
@@ -134,7 +145,7 @@
<!-- Hamburger -->
<div class="-me-2 flex items-center sm:hidden">
<button @click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out dark:text-slate-500 dark:hover:text-slate-400 dark:hover:bg-slate-800 dark:focus:bg-slate-800 dark:focus:text-slate-400" aria-label="{{ __('Main menu') }}">
<button @click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out dark:text-slate-500 dark:hover:text-slate-400 dark:hover:bg-slate-800 dark:focus:bg-slate-800 dark:focus:text-slate-400" aria-label="主選單">
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
<path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
<path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
@@ -148,72 +159,83 @@
<div :class="{'block': open, 'hidden': ! open}" class="hidden sm:hidden">
<div class="pt-2 pb-3 space-y-1">
<x-responsive-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
{{ __('Dashboard') }}
首頁
</x-responsive-nav-link>
<x-responsive-nav-link :href="route('member.dashboard')" :active="request()->routeIs('member.dashboard')">
{{ __('My Membership') }}
我的會籍
</x-responsive-nav-link>
<x-responsive-nav-link :href="route('documents.index')" :active="request()->routeIs('documents.*') && !request()->routeIs('admin.documents.*')">
{{ __('Documents') }}
文件
</x-responsive-nav-link>
@if(Auth::user() && (Auth::user()->hasRole(['admin', 'membership_manager', 'finance_accountant', 'staff']) || Auth::user()->canAny(['view_finance_documents', 'view_accounting_transactions', 'manage_system_settings'])))
@if(Auth::user() && (Auth::user()->hasRole(['admin', 'membership_manager', 'finance_accountant', 'finance_cashier', 'staff']) || Auth::user()->canAny(['view_finance_documents', 'view_incomes', 'view_accounting_transactions', 'manage_system_settings'])))
<div class="pt-2 pb-1 border-t border-gray-200 dark:border-gray-700 mt-2">
<div class="px-4 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">
{{ __('Management') }}
管理
</div>
</div>
@can('view_announcements')
<x-responsive-nav-link :href="route('admin.announcements.index')" :active="request()->routeIs('admin.announcements.*')">
{{ __('Admin: Announcements') }}
公告管理
</x-responsive-nav-link>
@endcan
@hasrole('admin|membership_manager')
<x-responsive-nav-link :href="route('admin.members.index')" :active="request()->routeIs('admin.members.*')">
{{ __('Admin: Members') }}
會員管理
</x-responsive-nav-link>
@endhasrole
@role('admin')
<x-responsive-nav-link :href="route('admin.roles.index')" :active="request()->routeIs('admin.roles.*')">
{{ __('Admin: Roles') }}
角色管理
</x-responsive-nav-link>
@endrole
@can('view_finance_documents')
<x-responsive-nav-link :href="route('admin.finance.index')" :active="request()->routeIs('admin.finance.*')">
{{ __('Admin: Finance') }}
報銷管理
</x-responsive-nav-link>
@endcan
@can('view_incomes')
<x-responsive-nav-link :href="route('admin.incomes.index')" :active="request()->routeIs('admin.incomes.*')">
收入管理
</x-responsive-nav-link>
@endcan
@hasrole('admin|finance_accountant')
<x-responsive-nav-link :href="route('admin.budgets.index')" :active="request()->routeIs('admin.budgets.*')">
{{ __('Admin: Budgets') }}
預算管理
</x-responsive-nav-link>
@endhasrole
@can('view_accounting_transactions')
<x-responsive-nav-link :href="route('admin.transactions.index')" :active="request()->routeIs('admin.transactions.*')">
{{ __('Admin: Transactions') }}
交易記錄
</x-responsive-nav-link>
<x-responsive-nav-link :href="route('admin.general-ledger.index')" :active="request()->routeIs('admin.general-ledger.*')">
總分類帳
</x-responsive-nav-link>
<x-responsive-nav-link :href="route('admin.trial-balance.index')" :active="request()->routeIs('admin.trial-balance.*')">
試算表
</x-responsive-nav-link>
@endcan
<x-responsive-nav-link :href="route('admin.issues.index')" :active="request()->routeIs('admin.issues.*')">
{{ __('Admin: Tasks') }}
任務管理
</x-responsive-nav-link>
@role('admin')
<x-responsive-nav-link :href="route('admin.audit.index')" :active="request()->routeIs('admin.audit.*')">
{{ __('Admin: Audit Logs') }}
稽核日誌
</x-responsive-nav-link>
<x-responsive-nav-link :href="route('admin.document-categories.index')" :active="request()->routeIs('admin.document-categories.*')">
{{ __('Admin: Document Categories') }}
文件分類管理
</x-responsive-nav-link>
@endrole
@hasrole('admin|staff')
<x-responsive-nav-link :href="route('admin.documents.index')" :active="request()->routeIs('admin.documents.*')">
{{ __('Admin: Documents') }}
文件管理
</x-responsive-nav-link>
@endhasrole
@can('manage_system_settings')
<x-responsive-nav-link :href="route('admin.settings.general')" :active="request()->routeIs('admin.settings.*')">
{{ __('Admin: System Settings') }}
系統設定
</x-responsive-nav-link>
@endcan
@endif
@@ -228,7 +250,7 @@
<div class="mt-3 space-y-1">
<x-responsive-nav-link :href="route('profile.edit')">
{{ __('Profile') }}
個人檔案
</x-responsive-nav-link>
<!-- Authentication -->
@@ -238,7 +260,7 @@
<x-responsive-nav-link :href="route('logout')"
onclick="event.preventDefault();
this.closest('form').submit();">
{{ __('Log Out') }}
登出
</x-responsive-nav-link>
</form>
</div>

View File

@@ -64,7 +64,18 @@
<h3 id="membership-info-heading" class="text-lg font-medium leading-6 text-gray-900 dark:text-gray-100">
{{ __('Membership Information') }}
</h3>
{!! $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-900 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-900 dark:text-gray-200',
};
@endphp
<span class="inline-flex rounded-full px-2 text-sm font-semibold leading-5 {{ $statusClasses }}">
{{ $member->membership_status_label }}
</span>
</div>
@if ($member->user?->profilePhotoUrl())
<div class="mt-4">

View File

@@ -9,6 +9,46 @@
<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">
{{-- Fee Summary --}}
<div class="mb-6 bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg p-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">會費明細</h3>
<div class="space-y-2">
<div class="flex justify-between text-sm">
<span class="text-gray-600 dark:text-gray-400">會費類型</span>
<span class="font-medium text-gray-900 dark:text-gray-100">
{{ $feeDetails['fee_type'] === 'entrance_fee' ? '入會會費' : '常年會費' }}
</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-gray-600 dark:text-gray-400">原始金額</span>
<span class="text-gray-900 dark:text-gray-100">NT$ {{ number_format($feeDetails['base_amount']) }}</span>
</div>
@if($feeDetails['disability_discount'])
<div class="flex justify-between text-sm text-green-600 dark:text-green-400">
<span>身心障礙優惠</span>
<span>-NT$ {{ number_format($feeDetails['discount_amount']) }}</span>
</div>
@endif
<div class="border-t border-gray-200 dark:border-gray-600 pt-2 mt-2">
<div class="flex justify-between text-base font-semibold">
<span class="text-gray-900 dark:text-gray-100">應繳金額</span>
<span class="text-indigo-600 dark:text-indigo-400">NT$ {{ number_format($feeDetails['final_amount']) }}</span>
</div>
</div>
</div>
@if(!$feeDetails['disability_discount'] && !$member->hasApprovedDisability())
<div class="mt-4 p-3 bg-yellow-50 dark:bg-yellow-900/30 rounded-md">
<p class="text-sm text-yellow-800 dark:text-yellow-200">
<strong>提示:</strong>若您持有身心障礙手冊,請先至
<a href="{{ route('profile.edit') }}" class="underline">個人資料頁面</a>
上傳手冊以享有 50% 優惠。
</p>
</div>
@endif
</div>
{{-- Payment Instructions --}}
<div class="mb-6 bg-blue-50 dark:bg-blue-900/30 border-l-4 border-blue-400 p-4">
<div class="flex">
@@ -18,11 +58,10 @@
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-blue-800 dark:text-blue-200">{{ __('Payment Instructions') }}</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">
<p>{{ __('Annual membership fee: TWD 1,000') }}</p>
<p class="mt-1">{{ __('Please upload your payment receipt (bank transfer, convenience store payment, etc.)') }}</p>
<p class="mt-1">{{ __('Your payment will be reviewed by our staff. You will receive an email notification once approved.') }}</p>
<p>請上傳您的繳費收據(銀行轉帳、超商繳費等)</p>
<p class="mt-1">我們的工作人員將審核您的繳費紀錄,審核通過後會以 Email 通知您。</p>
</div>
</div>
</div>
@@ -34,10 +73,11 @@
{{-- Amount --}}
<div>
<label for="amount" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
{{ __('Payment Amount (TWD)') }} <span class="text-red-500">*</span>
繳費金額 (TWD) <span class="text-red-500">*</span>
</label>
<input type="number" name="amount" id="amount" value="{{ old('amount', 1000) }}" required min="0" step="0.01"
<input type="number" name="amount" id="amount" value="{{ old('amount', $feeDetails['final_amount']) }}" required min="{{ $feeDetails['final_amount'] }}" step="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 dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100 @error('amount') border-red-300 @enderror">
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">最低繳費金額NT$ {{ number_format($feeDetails['final_amount']) }}</p>
@error('amount')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
</div>

View File

@@ -1,25 +1,33 @@
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Profile') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
<div class="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.update-profile-information-form')
</div>
</div>
<div class="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.update-password-form')
</div>
</div>
<div class="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
@if($member)
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.disability-certificate-form')
</div>
</div>
@endif
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.delete-user-form')
</div>

View File

@@ -1,10 +1,10 @@
<section class="space-y-6">
<header>
<h2 class="text-lg font-medium text-gray-900">
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Delete Account') }}
</h2>
<p class="mt-1 text-sm text-gray-600">
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.') }}
</p>
</header>
@@ -19,11 +19,11 @@
@csrf
@method('delete')
<h2 class="text-lg font-medium text-gray-900">
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Are you sure you want to delete your account?') }}
</h2>
<p class="mt-1 text-sm text-gray-600">
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.') }}
</p>

View File

@@ -0,0 +1,115 @@
<section>
<header>
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
身心障礙手冊
</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
持有身心障礙手冊的會員可享會費 50% 優惠。上傳後將在繳費審核時一併審核。
</p>
</header>
<!-- Current Status -->
<div class="mt-6 p-4 rounded-lg {{ $member->hasDisabilityCertificate() ? ($member->hasApprovedDisability() ? 'bg-green-50 dark:bg-green-900/30' : ($member->isDisabilityRejected() ? 'bg-red-50 dark:bg-red-900/30' : 'bg-yellow-50 dark:bg-yellow-900/30')) : 'bg-gray-50 dark:bg-gray-700/30' }}">
<div class="flex items-center">
@if($member->hasDisabilityCertificate())
@if($member->hasApprovedDisability())
<svg class="h-5 w-5 text-green-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="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="ml-2 text-sm font-medium text-green-800 dark:text-green-200">審核通過</span>
@elseif($member->isDisabilityRejected())
<svg class="h-5 w-5 text-red-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 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="ml-2 text-sm font-medium text-red-800 dark:text-red-200">審核未通過</span>
@else
<svg class="h-5 w-5 text-yellow-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 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="ml-2 text-sm font-medium text-yellow-800 dark:text-yellow-200">審核中</span>
@endif
@else
<svg class="h-5 w-5 text-gray-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="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>
<span class="ml-2 text-sm font-medium text-gray-600 dark:text-gray-400">尚未上傳</span>
@endif
</div>
@if($member->isDisabilityRejected() && $member->disability_rejection_reason)
<div class="mt-3 text-sm text-red-700 dark:text-red-300">
<strong>駁回原因:</strong>{{ $member->disability_rejection_reason }}
</div>
@endif
@if($member->hasApprovedDisability() && $member->disability_verified_at)
<div class="mt-2 text-sm text-green-700 dark:text-green-300">
審核時間:{{ $member->disability_verified_at->format('Y/m/d H:i') }}
@if($member->disabilityVerifiedBy)
(審核人:{{ $member->disabilityVerifiedBy->name }}
@endif
</div>
@endif
</div>
<!-- Upload Form -->
@if(!$member->hasApprovedDisability())
<form method="post" action="{{ route('profile.disability-certificate.upload') }}" class="mt-6 space-y-6" enctype="multipart/form-data">
@csrf
<div>
<x-input-label for="disability_certificate" :value="__('上傳身心障礙手冊')" />
@if($member->hasDisabilityCertificate())
<div class="mt-2 mb-4">
<p class="text-sm text-gray-600 dark:text-gray-400">目前已上傳檔案,您可以重新上傳以替換。</p>
<a href="{{ route('profile.disability-certificate.view') }}" target="_blank" class="inline-flex items-center mt-2 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>
@endif
<input type="file" id="disability_certificate" name="disability_certificate"
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"
accept=".jpg,.jpeg,.png,.pdf" required />
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
請上傳手冊封面及內頁照片(含照片、有效期)。支援 JPG、PNG、PDF 格式,最大 10MB。
</p>
<x-input-error class="mt-2" :messages="$errors->get('disability_certificate')" />
</div>
<div class="flex items-center gap-4">
<x-primary-button>{{ __('上傳') }}</x-primary-button>
@if (session('status') === 'disability-certificate-uploaded')
<p
x-data="{ show: true }"
x-show="show"
x-transition
x-init="setTimeout(() => show = false, 2000)"
class="text-sm text-gray-600 dark:text-gray-400"
>{{ __('已成功上傳') }}</p>
@endif
</div>
</form>
@else
<div class="mt-6">
<p class="text-sm text-gray-600 dark:text-gray-400">
您的身心障礙手冊已通過審核,繳費時將自動套用優惠。如需更新手冊,請聯繫管理員。
</p>
</div>
@endif
</section>

View File

@@ -1,10 +1,10 @@
<section>
<header>
<h2 class="text-lg font-medium text-gray-900">
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Update Password') }}
</h2>
<p class="mt-1 text-sm text-gray-600">
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __('Ensure your account is using a long, random password to stay secure.') }}
</p>
</header>
@@ -40,7 +40,7 @@
x-show="show"
x-transition
x-init="setTimeout(() => show = false, 2000)"
class="text-sm text-gray-600"
class="text-sm text-gray-600 dark:text-gray-400"
>{{ __('Saved.') }}</p>
@endif
</div>

View File

@@ -1,10 +1,10 @@
<section>
<header>
<h2 class="text-lg font-medium text-gray-900">
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Profile Information') }}
</h2>
<p class="mt-1 text-sm text-gray-600">
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __("Update your account's profile information and email address.") }}
</p>
</header>
@@ -17,7 +17,7 @@
@if ($user->profilePhotoUrl())
<div class="flex items-center space-x-4">
<img src="{{ $user->profilePhotoUrl() }}" alt="{{ __('Profile photo for :name', ['name' => $user->name]) }}" class="h-16 w-16 rounded-full object-cover">
<p class="text-sm text-gray-600">{{ __('This is your current profile photo.') }}</p>
<p class="text-sm text-gray-600 dark:text-gray-400">{{ __('This is your current profile photo.') }}</p>
</div>
@endif
@@ -27,7 +27,7 @@
id="profile_photo"
name="profile_photo"
type="file"
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"
accept="image/*"
/>
<x-input-error class="mt-2" :messages="$errors->get('profile_photo')" />
@@ -49,16 +49,16 @@
@if ($user instanceof \Illuminate\Contracts\Auth\MustVerifyEmail && ! $user->hasVerifiedEmail())
<div>
<p class="text-sm mt-2 text-gray-800">
<p class="text-sm mt-2 text-gray-800 dark:text-gray-200">
{{ __('Your email address is unverified.') }}
<button form="send-verification" class="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
<button form="send-verification" class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800">
{{ __('Click here to re-send the verification email.') }}
</button>
</p>
@if (session('status') === 'verification-link-sent')
<p class="mt-2 font-medium text-sm text-green-600">
<p class="mt-2 font-medium text-sm text-green-600 dark:text-green-400">
{{ __('A new verification link has been sent to your email address.') }}
</p>
@endif
@@ -162,7 +162,7 @@
x-show="show"
x-transition
x-init="setTimeout(() => show = false, 2000)"
class="text-sm text-gray-600"
class="text-sm text-gray-600 dark:text-gray-400"
>{{ __('Saved.') }}</p>
@endif
</div>

View File

@@ -117,11 +117,7 @@
<body>
<header>
<div style="display:flex;align-items:center;gap:12px;">
<x-application-logo class="h-auto w-32" alt="台灣尤塞氏症暨視聽弱協會" />
<div>
<div style="font-weight:700;font-size:16px;">台灣尤塞氏症暨視聽弱協會</div>
<div style="font-size:13px;color:var(--muted);">會員與財務管理系統</div>
</div>
<img src="{{ asset('images/usher-logo-long.png') }}" alt="台灣尤塞氏症暨視聽弱協會" class="h-auto" style="max-width: 256px;">
</div>
@if (Route::has('login'))
<nav>
@@ -139,58 +135,31 @@
<section class="hero">
<div class="hero-card">
<span class="pill">協會專用內部系統</span>
<h1>服務會員、串接財務簽核的核心平台</h1>
<p class="lead">
這裡集中管理會員資料、會費、文件與財務流程,並符合協會的分層簽核、審計與無障礙需求。
</p>
<div class="buttons">
<a class="btn primary" href="{{ Route::has('login') ? route('login') : '#' }}">會員登入</a>
@if (Route::has('register'))
<a class="btn ghost" href="{{ route('register') }}">新申請|註冊流程</a>
@endif
</div>
</div>
<div class="card" style="background:rgba(15,23,42,0.9);">
<h3>系統重點</h3>
<p style="margin-top:8px;">
會員自助:查詢會籍期限、繳費紀錄、更新個人資料、重設密碼。<br>
後台管理:會員新增/編輯/匯入、啟用信寄送、會費管理。<br>
財務工作流程:申請 審核(出納/會計/理事長/理事)→ 付款 對帳。<br>
安全與無障礙WCAG 2.1 AA、身份證加密與 hash、操作審計。
<strong>會員服務</strong>:查詢會籍、繳費紀錄、到期提醒<br>
<strong>財務與帳務</strong>:幹部財務報表簽核處,落實公益組織財務透明<br>
<strong>協作與文件</strong>:協會正式文件存放,對外公告連結處<br>
<strong>無障礙</strong>:符合 WCAG 2.1 AA 標準
</p>
</div>
<div class="card" style="background:rgba(15,23,42,0.9);">
<h3>會員資格及註冊流程</h3>
<p style="margin-top:8px;">
本系統目前提供會員登入使用。<br>
根據本會章程 (ToDo, 章程連結, ),本會會員目標為......(待補完) <br>
註冊流程為申請本站帳號,<br>
並繳費完成,<br>
提交繳交證明後,經由本會幹部審核通過後,方可成為正式會員。<br>
</p>
</div>
</section>
<section class="cards">
<div class="card">
<h3>會員入口</h3>
<p>登入後可查看會籍狀態、繳費紀錄、PDF 收據,並更新個人與聯絡資訊。</p>
</div>
<div class="card">
<h3>後台會員管理</h3>
<p>支援單筆/批次匯入、啟用信發送、到期提醒設定、角色與權限指派。</p>
</div>
<div class="card">
<h3>財務簽核與付款</h3>
<p>四階段流程:申請、分層審核、付款單製作與覆核、付款執行;含附件、審核歷程與分級金額控管。</p>
</div>
<div class="card">
<h3>帳務與對帳</h3>
<p>現金簿、交易分錄、銀行調節表;出納/會計/主管依職責分工,並保留完整審計記錄。</p>
</div>
<div class="card">
<h3>問題與文件</h3>
<p>內建問題追蹤、標籤、附件與關聯;文件庫支援分類、版本、權限控管與存取日誌。</p>
</div>
<div class="card">
<h3>無障礙設計</h3>
<p>HTML 語意化、必備標籤、aria-live、表格結構化信件以純文字友好格式寄送。</p>
</div>
</section>
<footer>
如需協助,請聯繫協會幹部。系統版本Laravel v{{ Illuminate\Foundation\Application::VERSION }}PHP v{{ PHP_VERSION }}
如需協助,請聯繫協會幹部。
</footer>
</body>
</html>