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

@@ -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>