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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user