Add phone login support and member import functionality
Features: - Support login via phone number or email (LoginRequest) - Add members:import-roster command for Excel roster import - Merge survey emails with roster data Code Quality (Phase 1-4): - Add database locking for balance calculation - Add self-approval checks for finance workflow - Create service layer (FinanceDocumentApprovalService, PaymentVerificationService) - Add HasAccountingEntries and HasApprovalWorkflow traits - Create FormRequest classes for validation - Add status-badge component - Define authorization gates in AuthServiceProvider - Add accounting config file Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,10 +5,10 @@
|
||||
<form method="POST" action="{{ route('login') }}">
|
||||
@csrf
|
||||
|
||||
<!-- Email Address -->
|
||||
<!-- Email or Phone -->
|
||||
<div>
|
||||
<x-input-label for="email" :value="__('Email')" />
|
||||
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus autocomplete="username" />
|
||||
<x-input-label for="email" :value="__('Email or Phone')" />
|
||||
<x-text-input id="email" class="block mt-1 w-full" type="text" name="email" :value="old('email')" required autofocus autocomplete="username" placeholder="email@example.com 或 0912345678" />
|
||||
<x-input-error :messages="$errors->get('email')" class="mt-2" />
|
||||
</div>
|
||||
|
||||
|
||||
81
resources/views/components/status-badge.blade.php
Normal file
81
resources/views/components/status-badge.blade.php
Normal file
@@ -0,0 +1,81 @@
|
||||
@props([
|
||||
'status',
|
||||
'label' => null,
|
||||
'type' => 'default'
|
||||
])
|
||||
|
||||
@php
|
||||
// Status to color mapping
|
||||
$colors = [
|
||||
// Approval statuses
|
||||
'pending' => 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300',
|
||||
'approved_secretary' => 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300',
|
||||
'approved_chair' => 'bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-300',
|
||||
'approved_board' => 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
|
||||
'rejected' => 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300',
|
||||
|
||||
// Legacy statuses
|
||||
'approved_cashier' => 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300',
|
||||
'approved_accountant' => 'bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-300',
|
||||
|
||||
// Disbursement statuses
|
||||
'requester_confirmed' => 'bg-cyan-100 text-cyan-800 dark:bg-cyan-900 dark:text-cyan-300',
|
||||
'cashier_confirmed' => 'bg-teal-100 text-teal-800 dark:bg-teal-900 dark:text-teal-300',
|
||||
'completed' => 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
|
||||
|
||||
// Member statuses
|
||||
'active' => 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
|
||||
'inactive' => 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300',
|
||||
'suspended' => 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300',
|
||||
'expired' => 'bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-300',
|
||||
|
||||
// Issue statuses
|
||||
'open' => 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300',
|
||||
'in_progress' => 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300',
|
||||
'review' => 'bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-300',
|
||||
'closed' => 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300',
|
||||
|
||||
// Payment statuses
|
||||
'paid' => 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
|
||||
'unpaid' => 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300',
|
||||
'overdue' => 'bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-300',
|
||||
|
||||
// General
|
||||
'success' => 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
|
||||
'warning' => 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300',
|
||||
'error' => 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300',
|
||||
'info' => 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300',
|
||||
];
|
||||
|
||||
// Status to label mapping (if no label provided)
|
||||
$labels = [
|
||||
'pending' => '待審核',
|
||||
'approved_secretary' => '秘書長已核准',
|
||||
'approved_chair' => '理事長已核准',
|
||||
'approved_board' => '董理事會已核准',
|
||||
'rejected' => '已駁回',
|
||||
'approved_cashier' => '出納已審核',
|
||||
'approved_accountant' => '會計已審核',
|
||||
'requester_confirmed' => '申請人已確認',
|
||||
'cashier_confirmed' => '出納已確認',
|
||||
'completed' => '已完成',
|
||||
'active' => '有效',
|
||||
'inactive' => '無效',
|
||||
'suspended' => '停權',
|
||||
'expired' => '已過期',
|
||||
'open' => '開啟',
|
||||
'in_progress' => '進行中',
|
||||
'review' => '審查中',
|
||||
'closed' => '已關閉',
|
||||
'paid' => '已繳費',
|
||||
'unpaid' => '未繳費',
|
||||
'overdue' => '已逾期',
|
||||
];
|
||||
|
||||
$colorClass = $colors[$status] ?? 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300';
|
||||
$displayLabel = $label ?? ($labels[$status] ?? $status);
|
||||
@endphp
|
||||
|
||||
<span {{ $attributes->merge(['class' => 'inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ' . $colorClass]) }}>
|
||||
{{ $displayLabel }}
|
||||
</span>
|
||||
Reference in New Issue
Block a user