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>
159 lines
11 KiB
PHP
159 lines
11 KiB
PHP
<x-app-layout>
|
||
<x-slot name="header">
|
||
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
|
||
{{ __('Submit Membership Payment') }}
|
||
</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">
|
||
|
||
{{-- 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">
|
||
<div class="flex-shrink-0">
|
||
<svg class="h-5 w-5 text-blue-400" viewBox="0 0 20 20" fill="currentColor">
|
||
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd" />
|
||
</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">
|
||
<p>請上傳您的繳費收據(銀行轉帳、超商繳費等)</p>
|
||
<p class="mt-1">我們的工作人員將審核您的繳費紀錄,審核通過後會以 Email 通知您。</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<form method="POST" action="{{ route('member.payments.store') }}" enctype="multipart/form-data" class="space-y-6">
|
||
@csrf
|
||
|
||
{{-- Amount --}}
|
||
<div>
|
||
<label for="amount" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||
繳費金額 (TWD) <span class="text-red-500">*</span>
|
||
</label>
|
||
<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>
|
||
|
||
{{-- Payment Date --}}
|
||
<div>
|
||
<label for="paid_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||
{{ __('Payment Date') }} <span class="text-red-500">*</span>
|
||
</label>
|
||
<input type="date" name="paid_at" id="paid_at" value="{{ old('paid_at', today()->format('Y-m-d')) }}" required max="{{ today()->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 @error('paid_at') border-red-300 @enderror">
|
||
@error('paid_at')<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 dark:text-gray-300">
|
||
{{ __('Payment Method') }} <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 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('payment_method') border-red-300 @enderror">
|
||
<option value="">{{ __('Select payment method') }}</option>
|
||
<option value="bank_transfer" {{ old('payment_method') == 'bank_transfer' ? 'selected' : '' }}>{{ __('Bank Transfer / ATM') }}</option>
|
||
<option value="convenience_store" {{ old('payment_method') == 'convenience_store' ? 'selected' : '' }}>{{ __('Convenience Store (7-11, FamilyMart, etc.)') }}</option>
|
||
<option value="cash" {{ old('payment_method') == 'cash' ? 'selected' : '' }}>{{ __('Cash (In-person)') }}</option>
|
||
<option value="credit_card" {{ old('payment_method') == 'credit_card' ? 'selected' : '' }}>{{ __('Credit Card') }}</option>
|
||
</select>
|
||
@error('payment_method')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
|
||
</div>
|
||
|
||
{{-- Reference Number --}}
|
||
<div>
|
||
<label for="reference" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||
{{ __('Transaction / Reference Number') }}
|
||
</label>
|
||
<input type="text" name="reference" id="reference" value="{{ old('reference') }}" 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('reference') border-red-300 @enderror"
|
||
placeholder="{{ __('e.g., Bank transaction number, receipt number') }}">
|
||
@error('reference')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
|
||
</div>
|
||
|
||
{{-- Receipt Upload --}}
|
||
<div>
|
||
<label for="receipt" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||
{{ __('Payment Receipt') }} <span class="text-red-500">*</span>
|
||
</label>
|
||
<input type="file" name="receipt" id="receipt" required accept="image/*,.pdf"
|
||
class="mt-1 block w-full text-sm text-gray-900 border border-gray-300 rounded-md cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 @error('receipt') border-red-300 @enderror">
|
||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">{{ __('Upload your payment receipt (JPG, PNG, or PDF, max 10MB)') }}</p>
|
||
@error('receipt')<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 dark:text-gray-300">
|
||
{{ __('Notes (Optional)') }}
|
||
</label>
|
||
<textarea name="notes" id="notes" 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 @error('notes') border-red-300 @enderror"
|
||
placeholder="{{ __('Any additional information...') }}">{{ old('notes') }}</textarea>
|
||
@error('notes')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
|
||
</div>
|
||
|
||
{{-- Submit Buttons --}}
|
||
<div class="flex items-center justify-end gap-x-4 border-t border-gray-200 pt-6 dark:border-gray-700">
|
||
<a href="{{ route('member.dashboard') }}"
|
||
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">
|
||
{{ __('Submit Payment') }}
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</x-app-layout>
|