Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
Clubphp
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Clubphp
Commits
64b8d478
Commit
64b8d478
authored
Apr 07, 2026
by
Administrator
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update 6 files via Son of Anton
parent
f7d90c56
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
1013 additions
and
661 deletions
+1013
-661
MemberController.php
app/Modules/Members/Controllers/MemberController.php
+338
-237
Routes.php
app/Modules/Members/Routes.php
+16
-10
FormNumberGenerator.php
app/Modules/Members/Services/FormNumberGenerator.php
+107
-0
create.php
app/Modules/Members/Views/create.php
+98
-280
fill-form.php
app/Modules/Members/Views/fill-form.php
+250
-0
show.php
app/Modules/Members/Views/show.php
+204
-134
No files found.
app/Modules/Members/Controllers/MemberController.php
View file @
64b8d478
...
@@ -9,38 +9,76 @@ use App\Core\Response;
...
@@ -9,38 +9,76 @@ use App\Core\Response;
use
App\Core\App
;
use
App\Core\App
;
use
App\Core\EventBus
;
use
App\Core\EventBus
;
use
App\Modules\Members\Models\Member
;
use
App\Modules\Members\Models\Member
;
use
App\Modules\Members\Models\MemberNote
;
use
App\Modules\Members\Services\MemberSearchService
;
use
App\Modules\Members\Services\NationalIdParser
;
use
App\Modules\Members\Services\NationalIdParser
;
use
App\Modules\
Pricing\Services\PricingEngine
;
use
App\Modules\
Members\Services\FormNumberGenerator
;
use
App\Modules\
Workflow\Services\WorkflowEngin
e
;
use
App\Modules\
Members\Services\MemberSearchServic
e
;
class
MemberController
extends
Controller
class
MemberController
extends
Controller
{
{
public
function
index
(
Request
$request
)
:
Response
public
function
index
(
Request
$request
)
:
Response
{
{
$db
=
App
::
getInstance
()
->
db
();
$filters
=
[
$filters
=
[
'q'
=>
trim
((
string
)
$request
->
get
(
'q'
,
''
)),
'q'
=>
trim
((
string
)
$request
->
get
(
'q'
,
''
)),
'status'
=>
$request
->
get
(
'status'
,
''
),
'status'
=>
$request
->
get
(
'status'
,
''
),
'branch_id'
=>
$request
->
get
(
'branch_id'
,
''
),
'branch_id'
=>
$request
->
get
(
'branch_id'
,
''
),
'membership_type'
=>
$request
->
get
(
'membership_type'
,
''
),
'date_from'
=>
$request
->
get
(
'date_from'
,
''
),
'date_from'
=>
$request
->
get
(
'date_from'
,
''
),
'date_to'
=>
$request
->
get
(
'date_to'
,
''
),
'date_to'
=>
$request
->
get
(
'date_to'
,
''
),
];
];
$page
=
max
(
1
,
(
int
)
$request
->
get
(
'page'
,
1
));
$page
=
max
(
1
,
(
int
)
$request
->
get
(
'page'
,
1
));
$
result
=
MemberSearchService
::
search
(
$filters
,
25
,
$page
)
;
$
perPage
=
25
;
$db
=
App
::
getInstance
()
->
db
();
$where
=
'm.is_archived = 0'
;
$params
=
[];
if
(
$filters
[
'q'
]
!==
''
)
{
$where
.=
' AND (m.full_name_ar LIKE ? OR m.national_id LIKE ? OR m.membership_number LIKE ? OR m.phone_mobile LIKE ? OR m.form_number LIKE ?)'
;
$s
=
'%'
.
$filters
[
'q'
]
.
'%'
;
$params
=
array_merge
(
$params
,
[
$s
,
$s
,
$s
,
$s
,
$s
]);
}
if
(
$filters
[
'status'
]
!==
''
)
{
$where
.=
' AND m.status = ?'
;
$params
[]
=
$filters
[
'status'
];
}
if
(
$filters
[
'branch_id'
]
!==
''
)
{
$where
.=
' AND m.branch_id = ?'
;
$params
[]
=
(
int
)
$filters
[
'branch_id'
];
}
if
(
$filters
[
'date_from'
]
!==
''
)
{
$where
.=
' AND m.created_at >= ?'
;
$params
[]
=
$filters
[
'date_from'
]
.
' 00:00:00'
;
}
if
(
$filters
[
'date_to'
]
!==
''
)
{
$where
.=
' AND m.created_at <= ?'
;
$params
[]
=
$filters
[
'date_to'
]
.
' 23:59:59'
;
}
$countRow
=
$db
->
selectOne
(
"SELECT COUNT(*) as cnt FROM members m WHERE
{
$where
}
"
,
$params
);
$total
=
(
int
)
(
$countRow
[
'cnt'
]
??
0
);
$offset
=
(
$page
-
1
)
*
$perPage
;
$members
=
$db
->
select
(
"SELECT m.*, b.name_ar as branch_name
FROM members m
LEFT JOIN branches b ON b.id = m.branch_id
WHERE
{
$where
}
ORDER BY m.id DESC
LIMIT
{
$perPage
}
OFFSET
{
$offset
}
"
,
$params
);
$pagination
=
\App\Core\Pagination
::
paginate
(
$total
,
$perPage
,
$page
);
$branches
=
$db
->
select
(
"SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar"
);
$branches
=
$db
->
select
(
"SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar"
);
$statuses
=
Member
::
getStatusOptions
();
return
$this
->
view
(
'Members.Views.index'
,
[
return
$this
->
view
(
'Members.Views.index'
,
[
'members'
=>
$result
[
'data'
],
'members'
=>
$members
,
'pagination'
=>
$result
[
'pagination'
],
'filters'
=>
$filters
,
'branches'
=>
$branches
,
'branches'
=>
$branches
,
'statuses'
=>
Member
::
getStatusOptions
(),
'statuses'
=>
$statuses
,
'types'
=>
Member
::
getMembershipTypes
(),
'filters'
=>
$filters
,
'pagination'
=>
$pagination
,
]);
]);
}
}
...
@@ -48,260 +86,312 @@ class MemberController extends Controller
...
@@ -48,260 +86,312 @@ class MemberController extends Controller
{
{
$db
=
App
::
getInstance
()
->
db
();
$db
=
App
::
getInstance
()
->
db
();
$branches
=
$db
->
select
(
"SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar"
);
$branches
=
$db
->
select
(
"SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar"
);
$qualifications
=
$db
->
select
(
"SELECT id, name_ar FROM qualifications WHERE is_active = 1 ORDER BY sort_order"
);
$governorates
=
$db
->
select
(
"SELECT code, name_ar FROM governorates WHERE is_active = 1 ORDER BY name_ar"
);
$nextFormNumber
=
FormNumberGenerator
::
next
();
$countries
=
$db
->
select
(
"SELECT nationality_ar FROM countries WHERE is_active = 1 ORDER BY name_ar"
);
$formFee
=
FormNumberGenerator
::
getFormFee
();
$needsStartNumber
=
(
$nextFormNumber
===
null
);
return
$this
->
view
(
'Members.Views.create'
,
[
return
$this
->
view
(
'Members.Views.create'
,
[
'branches'
=>
$branches
,
'branches'
=>
$branches
,
'
qualifications'
=>
$qualifications
,
'
nextFormNumber'
=>
$nextFormNumber
,
'
governorates'
=>
$governorates
,
'
formFee'
=>
$formFee
,
'
countries'
=>
$countries
,
'
needsStartNumber'
=>
$needsStartNumber
,
]);
]);
}
}
public
function
store
(
Request
$request
)
:
Response
public
function
store
(
Request
$request
)
:
Response
{
{
$data
=
$request
->
all
();
$db
=
App
::
getInstance
()
->
db
();
unset
(
$data
[
'_csrf_token'
]);
$employee
=
App
::
getInstance
()
->
currentEmployee
();
// If super admin is setting the starting form number
$startNumber
=
$request
->
post
(
'form_start_number'
);
if
(
$startNumber
!==
null
&&
$startNumber
!==
''
)
{
$startNum
=
(
int
)
$startNumber
;
if
(
$startNum
<=
0
)
{
return
$this
->
redirect
(
'/members/create'
)
->
withError
(
'رقم بداية الاستمارات يجب أن يكون أكبر من صفر'
);
}
FormNumberGenerator
::
setStartNumber
(
$startNum
);
}
// Validate basic fields
$fullNameAr
=
trim
((
string
)
$request
->
post
(
'full_name_ar'
,
''
));
$nationalId
=
trim
((
string
)
$request
->
post
(
'national_id'
,
''
));
$phoneMobile
=
trim
((
string
)
$request
->
post
(
'phone_mobile'
,
''
));
$branchId
=
(
int
)
$request
->
post
(
'branch_id'
,
0
);
// Validate required fields
$errors
=
[];
$errors
=
[];
if
(
empty
(
trim
(
$data
[
'full_name_ar'
]
??
''
)))
$errors
[]
=
'الاسم بالعربي مطلوب'
;
if
(
$fullNameAr
===
''
||
mb_strlen
(
$fullNameAr
)
<
5
)
{
if
(
empty
(
$data
[
'branch_id'
]
??
''
))
$errors
[]
=
'الفرع مطلوب'
;
$errors
[]
=
'الاسم بالعربي مطلوب (5 أحرف على الأقل)'
;
if
(
empty
(
$data
[
'date_of_birth'
]
??
''
))
$errors
[]
=
'تاريخ الميلاد مطلوب'
;
}
if
(
empty
(
$data
[
'gender'
]
??
''
))
$errors
[]
=
'النوع مطلوب'
;
if
(
$phoneMobile
===
''
||
!
preg_match
(
'/^01[0125]\d{8}$/'
,
$phoneMobile
))
{
if
(
empty
(
$data
[
'phone_mobile'
]
??
''
))
$errors
[]
=
'رقم المحمول مطلوب'
;
$errors
[]
=
'رقم المحمول غير صالح (01XXXXXXXXX)'
;
}
$idType
=
$data
[
'id_type'
]
??
'national_id'
;
if
(
$branchId
<=
0
)
{
$errors
[]
=
'الفرع مطلوب'
;
// Parse and validate NID if Egyptian
}
if
(
$idType
===
'national_id'
)
{
$nid
=
trim
(
$data
[
'national_id'
]
??
''
);
// Parse NID
if
(
empty
(
$nid
))
{
$dob
=
null
;
$errors
[]
=
'الرقم القومي مطلوب'
;
$ageYears
=
null
;
$ageMonths
=
null
;
$gender
=
null
;
$govCode
=
null
;
$idType
=
'national_id'
;
if
(
$nationalId
!==
''
)
{
if
(
strlen
(
$nationalId
)
!==
14
||
!
ctype_digit
(
$nationalId
))
{
$errors
[]
=
'الرقم القومي يجب أن يكون 14 رقم'
;
}
else
{
}
else
{
$parsed
=
NationalIdParser
::
parse
(
$n
i
d
);
$parsed
=
NationalIdParser
::
parse
(
$n
ationalI
d
);
if
(
!
$parsed
[
'is_valid'
])
{
if
(
!
$parsed
[
'is_valid'
])
{
$errors
=
array_merge
(
$errors
,
$parsed
[
'errors'
]);
$errors
=
array_merge
(
$errors
,
$parsed
[
'errors'
]
??
[
'الرقم القومي غير صالح'
]
);
}
else
{
}
else
{
// Override with parsed data
$dob
=
$parsed
[
'dob'
];
$data
[
'date_of_birth'
]
=
$parsed
[
'dob'
];
$ageYears
=
$parsed
[
'age_years'
];
$data
[
'age_years'
]
=
$parsed
[
'age_years'
];
$ageMonths
=
$parsed
[
'age_months'
];
$data
[
'age_months'
]
=
$parsed
[
'age_months'
];
$gender
=
$parsed
[
'gender'
];
$data
[
'gender'
]
=
$parsed
[
'gender'
];
$govCode
=
$parsed
[
'governorate_code'
];
$data
[
'governorate_code'
]
=
$parsed
[
'governorate_code'
];
// Check duplicate
// Check minimum working age
$dup
=
$db
->
selectOne
(
if
(
$parsed
[
'age_years'
]
<
21
)
{
"SELECT id, full_name_ar, membership_number FROM members WHERE national_id = ? AND is_archived = 0"
,
$errors
[]
=
'يجب أن يكون عمر العضو العامل 21 سنة على الأقل'
;
[
$nationalId
]
}
);
// Check for duplicate NID
$dup
=
NationalIdParser
::
checkDuplicate
(
$nid
);
if
(
$dup
)
{
if
(
$dup
)
{
if
(
!
$dup
[
'is_archived'
])
{
$errors
[]
=
'الرقم القومي مسجل بالفعل: '
.
$dup
[
'full_name_ar'
]
.
' ('
.
(
$dup
[
'membership_number'
]
??
'بدون رقم'
)
.
')'
;
$errors
[]
=
'الرقم القومي مسجل بالفعل للعضو: '
.
$dup
[
'full_name_ar'
]
.
' ('
.
(
$dup
[
'membership_number'
]
?:
'بدون رقم'
)
.
')'
;
}
// If archived, allow but we could show a warning — for now allow
}
}
}
}
}
}
}
elseif
(
$idType
===
'passport'
)
{
}
else
{
if
(
empty
(
trim
(
$data
[
'passport_number'
]
??
''
)))
{
// Without NID, we need DOB and gender manually
$errors
[]
=
'رقم جواز السفر مطلوب'
;
$dob
=
$request
->
post
(
'date_of_birth'
,
''
);
$gender
=
$request
->
post
(
'gender'
,
''
);
if
(
$dob
===
''
)
$errors
[]
=
'تاريخ الميلاد مطلوب'
;
if
(
$gender
===
''
)
$errors
[]
=
'النوع مطلوب'
;
if
(
$dob
)
{
$age
=
age_from_dob
(
$dob
);
$ageYears
=
$age
[
'years'
];
$ageMonths
=
$age
[
'months'
];
}
}
$idType
=
'passport'
;
}
}
if
(
!
empty
(
$errors
))
{
if
(
!
empty
(
$errors
))
{
$session
=
App
::
getInstance
()
->
session
();
$session
=
App
::
getInstance
()
->
session
();
$session
->
flash
(
'_alerts'
,
array_map
(
fn
(
$e
)
=>
[
'type'
=>
'error'
,
'message'
=>
$e
],
$errors
));
$session
->
flash
(
'_alerts'
,
array_map
(
fn
(
$e
)
=>
[
'type'
=>
'error'
,
'message'
=>
$e
],
$errors
));
$session
->
flash
(
'_old_input'
,
$
data
);
$session
->
flash
(
'_old_input'
,
$
request
->
all
()
);
return
$this
->
redirect
(
'/members/create'
);
return
$this
->
redirect
(
'/members/create'
);
}
}
// Calculate age if not already set
// Generate form number
if
(
!
empty
(
$data
[
'date_of_birth'
])
&&
empty
(
$data
[
'age_years'
]))
{
$formNumber
=
FormNumberGenerator
::
next
();
$age
=
age_from_dob
(
$data
[
'date_of_birth'
]);
if
(
$formNumber
===
null
)
{
$data
[
'age_years'
]
=
$age
[
'years'
];
return
$this
->
redirect
(
'/members/create'
)
->
withError
(
'يجب تحديد رقم بداية الاستمارات أولاً'
);
$data
[
'age_months'
]
=
$age
[
'months'
];
}
// Get membership price
$branchId
=
(
int
)
$data
[
'branch_id'
];
$qualCode
=
null
;
if
(
!
empty
(
$data
[
'qualification_id'
]))
{
$db
=
App
::
getInstance
()
->
db
();
$qualRow
=
$db
->
selectOne
(
"SELECT code FROM qualifications WHERE id = ?"
,
[(
int
)
$data
[
'qualification_id'
]]);
$qualCode
=
$qualRow
[
'code'
]
??
'high'
;
}
}
$priceInfo
=
$qualCode
?
PricingEngine
::
getMembershipPrice
(
$branchId
,
$qualCode
)
:
[
'price'
=>
'0.00'
];
// Create member with basic info
$membershipValue
=
$priceInfo
[
'price'
]
??
'0.00'
;
$employee
=
App
::
getInstance
()
->
currentEmployee
();
// Create the member
$member
=
Member
::
create
([
$member
=
Member
::
create
([
'full_name_ar'
=>
trim
(
$data
[
'full_name_ar'
]),
'full_name_ar'
=>
$fullNameAr
,
'full_name_en'
=>
trim
(
$data
[
'full_name_en'
]
??
''
),
'national_id'
=>
$nationalId
?:
null
,
'national_id'
=>
$data
[
'national_id'
]
??
null
,
'passport_number'
=>
$request
->
post
(
'passport_number'
)
?:
null
,
'passport_number'
=>
$data
[
'passport_number'
]
??
null
,
'id_type'
=>
$idType
,
'id_type'
=>
$idType
,
'id_issue_date'
=>
$data
[
'id_issue_date'
]
?:
null
,
'date_of_birth'
=>
$dob
,
'id_expiry_date'
=>
$data
[
'id_expiry_date'
]
?:
null
,
'age_years'
=>
$ageYears
,
'date_of_birth'
=>
$data
[
'date_of_birth'
],
'age_months'
=>
$ageMonths
,
'age_years'
=>
(
int
)
(
$data
[
'age_years'
]
??
0
),
'gender'
=>
$gender
,
'age_months'
=>
(
int
)
(
$data
[
'age_months'
]
??
0
),
'governorate_code'
=>
$govCode
,
'gender'
=>
$data
[
'gender'
],
'phone_mobile'
=>
$phoneMobile
,
'place_of_birth'
=>
$data
[
'place_of_birth'
]
??
null
,
'nationality'
=>
$data
[
'nationality'
]
??
'مصري'
,
'governorate_code'
=>
$data
[
'governorate_code'
]
??
null
,
'religion'
=>
$data
[
'religion'
]
??
null
,
'qualification_id'
=>
!
empty
(
$data
[
'qualification_id'
])
?
(
int
)
$data
[
'qualification_id'
]
:
null
,
'marital_status'
=>
$data
[
'marital_status'
]
??
null
,
'branch_id'
=>
$branchId
,
'branch_id'
=>
$branchId
,
'membership_type'
=>
$data
[
'membership_type'
]
??
'working'
,
'nationality'
=>
'مصري'
,
'member_category'
=>
'working_member'
,
'form_number'
=>
(
string
)
$formNumber
,
'form_date'
=>
date
(
'Y-m-d'
),
'status'
=>
'potential'
,
'status'
=>
'potential'
,
'phone_home'
=>
$data
[
'phone_home'
]
??
null
,
'membership_type'
=>
'working'
,
'phone_mobile'
=>
$data
[
'phone_mobile'
],
'member_category'
=>
'working_member'
,
'phone_international'
=>
$data
[
'phone_international'
]
??
null
,
'email'
=>
$data
[
'email'
]
??
null
,
'emergency_name'
=>
$data
[
'emergency_name'
]
??
null
,
'emergency_phone'
=>
$data
[
'emergency_phone'
]
??
null
,
'residence_type'
=>
$data
[
'residence_type'
]
??
null
,
'residence_address'
=>
$data
[
'residence_address'
]
??
null
,
'landmark'
=>
$data
[
'landmark'
]
??
null
,
'floor'
=>
$data
[
'floor'
]
??
null
,
'apartment'
=>
$data
[
'apartment'
]
??
null
,
'area'
=>
$data
[
'area'
]
??
null
,
'governorate'
=>
$data
[
'governorate'
]
??
null
,
'correspondence_address'
=>
$data
[
'correspondence_address'
]
??
null
,
'employment_type'
=>
$data
[
'employment_type'
]
??
null
,
'occupation'
=>
$data
[
'occupation'
]
??
null
,
'job_title'
=>
$data
[
'job_title'
]
??
null
,
'employment_date'
=>
!
empty
(
$data
[
'employment_date'
])
?
$data
[
'employment_date'
]
:
null
,
'business_address'
=>
$data
[
'business_address'
]
??
null
,
'office_phone'
=>
$data
[
'office_phone'
]
??
null
,
'office_fax'
=>
$data
[
'office_fax'
]
??
null
,
'business_activity'
=>
$data
[
'business_activity'
]
??
null
,
'membership_value'
=>
$membershipValue
,
'referral_source'
=>
$data
[
'referral_source'
]
??
null
,
]);
]);
// Create workflow instance
try
{
$wfInstance
=
WorkflowEngine
::
createInstance
(
'new_membership'
,
'members'
,
(
int
)
$member
->
id
);
$db
=
App
::
getInstance
()
->
db
();
$db
->
update
(
'members'
,
[
'workflow_instance_id'
=>
(
int
)
$wfInstance
->
id
,
],
'`id` = ?'
,
[
$member
->
id
]);
}
catch
(
\Throwable
$e
)
{
// Workflow creation failed — log but don't block member creation
\App\Core\Logger
::
warning
(
"Failed to create workflow for member #
{
$member
->
id
}
: "
.
$e
->
getMessage
());
}
EventBus
::
dispatch
(
'member.created'
,
[
EventBus
::
dispatch
(
'member.created'
,
[
'member_id'
=>
(
int
)
$member
->
id
,
'member_id'
=>
(
int
)
$member
->
id
,
'branch_id'
=>
$branchId
,
'form_number'
=>
(
string
)
$formNumber
,
'created_by'
=>
$employee
?
(
int
)
$employee
->
id
:
null
,
]);
]);
return
$this
->
redirect
(
'/members/'
.
$member
->
id
)
->
withSuccess
(
'تم إنشاء العضو بنجاح — الحالة: عضوية محتملة'
);
$formFee
=
FormNumberGenerator
::
getFormFee
();
return
$this
->
redirect
(
'/members/'
.
$member
->
id
)
->
withSuccess
(
'تم تسجيل العضو — استمارة رقم: '
.
$formNumber
.
' — رسوم الاستمارة: '
.
money
(
$formFee
));
}
}
public
function
show
(
Request
$request
,
string
$id
)
:
Response
public
function
show
(
Request
$request
,
string
$id
)
:
Response
{
{
$db
=
App
::
getInstance
()
->
db
();
$member
=
Member
::
find
((
int
)
$id
);
$member
=
Member
::
find
((
int
)
$id
);
if
(
!
$member
)
{
if
(
!
$member
||
$member
->
is_archived
)
{
return
$this
->
redirect
(
'/members'
)
->
withError
(
'العضو غير موجود'
);
return
$this
->
redirect
(
'/members'
)
->
withError
(
'العضو غير موجود'
);
}
}
$db
=
App
::
getInstance
()
->
db
();
$branch
=
$db
->
selectOne
(
"SELECT name_ar FROM branches WHERE id = ?"
,
[(
int
)
$member
->
branch_id
]);
$qualification
=
$member
->
qualification_id
?
$db
->
selectOne
(
"SELECT name_ar FROM qualifications WHERE id = ?"
,
[(
int
)
$member
->
qualification_id
])
:
null
;
// Build profile data — future phases enrich this via events
// Load family data
$profileData
=
[
$spouses
=
[];
'member'
=>
$member
,
$children
=
[];
'spouses'
=>
[],
try
{
'children'
=>
[],
$spouses
=
$db
->
select
(
'temporary'
=>
[],
"SELECT * FROM spouses WHERE member_id = ? AND is_archived = 0 ORDER BY spouse_order"
,
'payments'
=>
[],
[(
int
)
$id
]
'installments'
=>
[],
);
'subscriptions'
=>
[],
}
catch
(
\Throwable
$e
)
{}
'documents'
=>
[],
'violations'
=>
[],
'fines'
=>
[],
];
// Load data from tables that exist (future phases add data via event)
try
{
$tablesToCheck
=
[
$children
=
$db
->
select
(
'spouses'
=>
"SELECT * FROM spouses WHERE member_id = ? AND is_archived = 0 ORDER BY spouse
_order"
,
"SELECT * FROM children WHERE member_id = ? AND is_archived = 0 ORDER BY child
_order"
,
'children'
=>
"SELECT * FROM children WHERE member_id = ? AND is_archived = 0 ORDER BY child_order"
,
[(
int
)
$id
]
'temporary_members'
=>
"SELECT * FROM temporary_members WHERE member_id = ? AND is_archived = 0 ORDER BY created_at"
,
);
];
}
catch
(
\Throwable
$e
)
{}
foreach
(
$tablesToCheck
as
$key
=>
$sql
)
{
// Load payments
$payments
=
[];
$totalPaid
=
'0.00'
;
try
{
try
{
if
(
$db
->
tableExists
(
$key
))
{
$payments
=
$db
->
select
(
$mapKey
=
$key
===
'temporary_members'
?
'temporary'
:
$key
;
"SELECT p.*, r.receipt_number FROM payments p LEFT JOIN receipts r ON r.id = p.receipt_id
$profileData
[
$mapKey
]
=
$db
->
select
(
$sql
,
[(
int
)
$member
->
id
]);
WHERE p.member_id = ? AND p.is_voided = 0 ORDER BY p.payment_date DESC LIMIT 10"
,
[(
int
)
$id
]
);
$totalPaidRow
=
$db
->
selectOne
(
"SELECT COALESCE(SUM(amount), 0) as total FROM payments WHERE member_id = ? AND is_voided = 0"
,
[(
int
)
$id
]
);
$totalPaid
=
$totalPaidRow
[
'total'
]
??
'0.00'
;
}
catch
(
\Throwable
$e
)
{}
// Load notes
$notes
=
$member
->
getNotes
();
$formFee
=
FormNumberGenerator
::
getFormFee
();
// Check if form is filled (has qualification = minimum indicator of filled form)
$formFilled
=
(
$member
->
qualification_id
!==
null
&&
$member
->
qualification_id
>
0
);
return
$this
->
view
(
'Members.Views.show'
,
[
'member'
=>
$member
,
'branchName'
=>
$branch
[
'name_ar'
]
??
'—'
,
'qualificationName'
=>
$qualification
[
'name_ar'
]
??
'—'
,
'spouses'
=>
$spouses
,
'children'
=>
$children
,
'payments'
=>
$payments
,
'totalPaid'
=>
$totalPaid
,
'notes'
=>
$notes
,
'formFee'
=>
$formFee
,
'formFilled'
=>
$formFilled
,
]);
}
}
}
catch
(
\Throwable
$e
)
{
// Table doesn't exist yet — that's fine
public
function
fillForm
(
Request
$request
,
string
$id
)
:
Response
{
$db
=
App
::
getInstance
()
->
db
();
$member
=
Member
::
find
((
int
)
$id
);
if
(
!
$member
||
$member
->
is_archived
)
{
return
$this
->
redirect
(
'/members'
)
->
withError
(
'العضو غير موجود'
);
}
}
$branches
=
$db
->
select
(
"SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar"
);
$qualifications
=
$db
->
select
(
"SELECT id, name_ar FROM qualifications WHERE is_active = 1 ORDER BY sort_order"
);
$governorates
=
$db
->
select
(
"SELECT code, name_ar FROM governorates WHERE is_active = 1 ORDER BY name_ar"
);
$countries
=
$db
->
select
(
"SELECT nationality_ar FROM countries WHERE is_active = 1 ORDER BY name_ar"
);
return
$this
->
view
(
'Members.Views.fill-form'
,
[
'member'
=>
$member
,
'branches'
=>
$branches
,
'qualifications'
=>
$qualifications
,
'governorates'
=>
$governorates
,
'countries'
=>
$countries
,
]);
}
}
// Let other modules enrich profile data
public
function
saveFillForm
(
Request
$request
,
string
$id
)
:
Response
EventBus
::
dispatch
(
'member.profile_data'
,
$profileData
);
{
$db
=
App
::
getInstance
()
->
db
();
$member
=
Member
::
find
((
int
)
$id
);
if
(
!
$member
||
$member
->
is_archived
)
{
return
$this
->
redirect
(
'/members'
)
->
withError
(
'العضو غير موجود'
);
}
// Get notes
$data
=
$request
->
all
();
$notes
=
$member
->
getNotes
(
);
unset
(
$data
[
'_csrf_token'
]
);
// Get workflow info
// Build update array — only update non-empty fields
$workflowInstance
=
null
;
$updateFields
=
[
if
(
$member
->
workflow_instance_id
)
{
'full_name_en'
,
'place_of_birth'
,
'nationality'
,
'religion'
,
try
{
'qualification_id'
,
'marital_status'
,
'id_issue_date'
,
'id_expiry_date'
,
$workflowInstance
=
$db
->
selectOne
(
'phone_home'
,
'phone_international'
,
'email'
,
"SELECT wi.*, wd.name_ar as workflow_name FROM workflow_instances wi JOIN workflow_definitions wd ON wd.id = wi.workflow_definition_id WHERE wi.id = ?"
,
'emergency_name'
,
'emergency_phone'
,
[(
int
)
$member
->
workflow_instance_id
]
'residence_type'
,
'residence_address'
,
'landmark'
,
'floor'
,
'apartment'
,
);
'area'
,
'governorate'
,
'correspondence_address'
,
}
catch
(
\Throwable
$e
)
{
'employment_type'
,
'occupation'
,
'job_title'
,
'employment_date'
,
// ignore
'business_address'
,
'office_phone'
,
'office_fax'
,
'business_activity'
,
'referral_source'
,
];
$update
=
[];
foreach
(
$updateFields
as
$field
)
{
if
(
array_key_exists
(
$field
,
$data
))
{
$val
=
trim
((
string
)
(
$data
[
$field
]
??
''
));
$update
[
$field
]
=
(
$val
===
''
)
?
null
:
$val
;
}
}
}
}
// Get audit history (last 20 actions)
// Handle qualification_id as integer
$auditHistory
=
[];
if
(
isset
(
$update
[
'qualification_id'
]))
{
$update
[
'qualification_id'
]
=
$update
[
'qualification_id'
]
?
(
int
)
$update
[
'qualification_id'
]
:
null
;
}
// Calculate membership value based on branch + qualification
if
(
!
empty
(
$update
[
'qualification_id'
]))
{
try
{
try
{
$auditHistory
=
$db
->
select
(
$pricing
=
$db
->
selectOne
(
"SELECT * FROM audit_trail WHERE entity_type = 'members' AND entity_id = ? ORDER BY created_at DESC LIMIT 20"
,
"SELECT price FROM pricing_configs
[(
int
)
$member
->
id
]
WHERE branch_id = ? AND qualification_id = ? AND membership_type = 'working'
AND is_active = 1 AND effective_from <= CURDATE()
AND (effective_to IS NULL OR effective_to >= CURDATE())
ORDER BY effective_from DESC LIMIT 1"
,
[(
int
)
$member
->
branch_id
,
(
int
)
$update
[
'qualification_id'
]]
);
);
}
catch
(
\Throwable
$e
)
{
if
(
$pricing
)
{
// ignore
$update
[
'membership_value'
]
=
$pricing
[
'price'
];
}
}
catch
(
\Throwable
$e
)
{}
}
}
return
$this
->
view
(
'Members.Views.show'
,
array_merge
(
$profileData
,
[
// Update status to under_review if still potential
'notes'
=>
$notes
,
if
(
$member
->
status
===
'potential'
)
{
'workflowInstance'
=>
$workflowInstance
,
$update
[
'status'
]
=
'under_review'
;
'auditHistory'
=>
$auditHistory
,
}
]));
if
(
!
empty
(
$update
))
{
$member
->
update
(
$update
);
}
EventBus
::
dispatch
(
'member.form_filled'
,
[
'member_id'
=>
(
int
)
$id
,
'form_number'
=>
$member
->
form_number
,
]);
return
$this
->
redirect
(
'/members/'
.
$id
)
->
withSuccess
(
'تم ملء الاستمارة بنجاح — الحالة: تحت المراجعة'
);
}
}
public
function
edit
(
Request
$request
,
string
$id
)
:
Response
public
function
edit
(
Request
$request
,
string
$id
)
:
Response
{
{
$db
=
App
::
getInstance
()
->
db
();
$member
=
Member
::
find
((
int
)
$id
);
$member
=
Member
::
find
((
int
)
$id
);
if
(
!
$member
)
{
if
(
!
$member
||
$member
->
is_archived
)
{
return
$this
->
redirect
(
'/members'
)
->
withError
(
'العضو غير موجود'
);
return
$this
->
redirect
(
'/members'
)
->
withError
(
'العضو غير موجود'
);
}
}
$db
=
App
::
getInstance
()
->
db
();
$branches
=
$db
->
select
(
"SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar"
);
$branches
=
$db
->
select
(
"SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar"
);
$qualifications
=
$db
->
select
(
"SELECT id, name_ar FROM qualifications WHERE is_active = 1 ORDER BY sort_order"
);
$qualifications
=
$db
->
select
(
"SELECT id, name_ar FROM qualifications WHERE is_active = 1 ORDER BY sort_order"
);
$governorates
=
$db
->
select
(
"SELECT code, name_ar FROM governorates WHERE is_active = 1 ORDER BY name_ar"
);
$governorates
=
$db
->
select
(
"SELECT code, name_ar FROM governorates WHERE is_active = 1 ORDER BY name_ar"
);
...
@@ -319,65 +409,76 @@ class MemberController extends Controller
...
@@ -319,65 +409,76 @@ class MemberController extends Controller
public
function
update
(
Request
$request
,
string
$id
)
:
Response
public
function
update
(
Request
$request
,
string
$id
)
:
Response
{
{
$member
=
Member
::
find
((
int
)
$id
);
$member
=
Member
::
find
((
int
)
$id
);
if
(
!
$member
)
{
if
(
!
$member
||
$member
->
is_archived
)
{
return
$this
->
redirect
(
'/members'
)
->
withError
(
'العضو غير موجود'
);
return
$this
->
redirect
(
'/members'
)
->
withError
(
'العضو غير موجود'
);
}
}
$data
=
$request
->
all
();
$data
=
$request
->
all
();
unset
(
$data
[
'_csrf_token'
]);
unset
(
$data
[
'_csrf_token'
]);
// Recalculate age
$allowedFields
=
[
if
(
!
empty
(
$data
[
'date_of_birth'
]))
{
'full_name_en'
,
'phone_home'
,
'phone_mobile'
,
'phone_international'
,
$age
=
age_from_dob
(
$data
[
'date_of_birth'
]);
'email'
,
'emergency_name'
,
'emergency_phone'
,
$data
[
'age_years'
]
=
$age
[
'years'
];
$data
[
'age_months'
]
=
$age
[
'months'
];
}
$updateFields
=
[
'full_name_en'
,
'religion'
,
'marital_status'
,
'phone_home'
,
'phone_mobile'
,
'phone_international'
,
'email'
,
'emergency_name'
,
'emergency_phone'
,
'residence_type'
,
'residence_address'
,
'landmark'
,
'floor'
,
'apartment'
,
'residence_type'
,
'residence_address'
,
'landmark'
,
'floor'
,
'apartment'
,
'area'
,
'governorate'
,
'correspondence_address'
,
'area'
,
'governorate'
,
'correspondence_address'
,
'employment_type'
,
'occupation'
,
'job_title'
,
'employment_date'
,
'employment_type'
,
'occupation'
,
'job_title'
,
'employment_date'
,
'business_address'
,
'office_phone'
,
'office_fax'
,
'business_activity'
,
'business_address'
,
'office_phone'
,
'office_fax'
,
'business_activity'
,
'referral_source'
,
'referral_source'
,
'religion'
,
'marital_status'
,
];
];
$update
Data
=
[];
$update
=
[];
foreach
(
$
update
Fields
as
$field
)
{
foreach
(
$
allowed
Fields
as
$field
)
{
if
(
array_key_exists
(
$field
,
$data
))
{
if
(
array_key_exists
(
$field
,
$data
))
{
$val
=
$data
[
$field
]
;
$val
=
trim
((
string
)
(
$data
[
$field
]
??
''
))
;
$update
Data
[
$field
]
=
(
$val
===
''
||
$val
===
null
)
?
null
:
$val
;
$update
[
$field
]
=
(
$val
===
''
)
?
null
:
$val
;
}
}
}
}
if
(
!
empty
(
$update
Data
))
{
if
(
!
empty
(
$update
))
{
$member
->
update
(
$update
Data
);
$member
->
update
(
$update
);
}
}
// Handle notes
return
$this
->
redirect
(
'/members/'
.
$id
)
->
withSuccess
(
'تم تحديث بيانات العضو'
);
$noteText
=
trim
(
$data
[
'new_note'
]
??
''
);
}
if
(
$noteText
!==
''
)
{
$employee
=
App
::
getInstance
()
->
currentEmployee
();
public
function
changeStatus
(
Request
$request
,
string
$id
)
:
Response
MemberNote
::
create
([
{
'member_id'
=>
(
int
)
$member
->
id
,
$member
=
Member
::
find
((
int
)
$id
);
'note_text'
=>
$noteText
,
if
(
!
$member
)
{
]
);
return
$this
->
redirect
(
'/members'
)
->
withError
(
'العضو غير موجود'
);
}
}
return
$this
->
redirect
(
'/members/'
.
$member
->
id
)
->
withSuccess
(
'تم تحديث بيانات العضو بنجاح'
);
$newStatus
=
trim
((
string
)
$request
->
post
(
'status'
,
''
));
$validStatuses
=
array_keys
(
Member
::
getStatusOptions
());
if
(
!
in_array
(
$newStatus
,
$validStatuses
))
{
return
$this
->
redirect
(
'/members/'
.
$id
)
->
withError
(
'حالة غير صالحة'
);
}
$oldStatus
=
$member
->
status
;
$member
->
update
([
'status'
=>
$newStatus
]);
EventBus
::
dispatch
(
'member.status_changed'
,
[
'member_id'
=>
(
int
)
$id
,
'old_status'
=>
$oldStatus
,
'new_status'
=>
$newStatus
,
]);
return
$this
->
redirect
(
'/members/'
.
$id
)
->
withSuccess
(
'تم تغيير الحالة إلى: '
.
(
Member
::
getStatusOptions
()[
$newStatus
]
??
$newStatus
));
}
}
public
function
search
(
Request
$request
)
:
Response
public
function
search
(
Request
$request
)
:
Response
{
{
$db
=
App
::
getInstance
()
->
db
();
$q
=
trim
((
string
)
$request
->
get
(
'q'
,
''
));
$branches
=
$db
->
select
(
"SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar"
);
$results
=
[];
if
(
$q
!==
''
&&
mb_strlen
(
$q
)
>=
2
)
{
$results
=
MemberSearchService
::
search
(
$q
,
50
);
}
return
$this
->
view
(
'Members.Views.search'
,
[
return
$this
->
view
(
'Members.Views.search'
,
[
'branches'
=>
$branches
,
'query'
=>
$q
,
'statuses'
=>
Member
::
getStatusOptions
(),
'results'
=>
$results
,
'results'
=>
null
,
]);
]);
}
}
}
}
\ No newline at end of file
app/Modules/Members/Routes.php
View file @
64b8d478
...
@@ -2,15 +2,21 @@
...
@@ -2,15 +2,21 @@
declare
(
strict_types
=
1
);
declare
(
strict_types
=
1
);
return
[
return
[
// Member CRUD
[
'GET'
,
'/members'
,
'Members\Controllers\MemberController@index'
,
[
'auth'
],
'member.view'
],
[
'GET'
,
'/members'
,
'Members\Controllers\MemberController@index'
,
[
'auth'
],
'member.view'
],
[
'GET'
,
'/members/search'
,
'Members\Controllers\MemberController@search'
,
[
'auth'
],
'member.search'
],
[
'GET'
,
'/members/create'
,
'Members\Controllers\MemberController@create'
,
[
'auth'
],
'member.create'
],
[
'GET'
,
'/members/create'
,
'Members\Controllers\MemberController@create'
,
[
'auth'
],
'member.create'
],
[
'POST'
,
'/members'
,
'Members\Controllers\MemberController@store'
,
[
'auth'
],
'member.create'
],
[
'POST'
,
'/members'
,
'Members\Controllers\MemberController@store'
,
[
'auth'
],
'member.create'
],
[
'GET'
,
'/members/search'
,
'Members\Controllers\MemberController@search'
,
[
'auth'
],
'member.view'
],
[
'GET'
,
'/members/{id}'
,
'Members\Controllers\MemberController@show'
,
[
'auth'
],
'member.view'
],
[
'GET'
,
'/members/{id}'
,
'Members\Controllers\MemberController@show'
,
[
'auth'
],
'member.view'
],
[
'GET'
,
'/members/{id}/edit'
,
'Members\Controllers\MemberController@edit'
,
[
'auth'
],
'member.edit'
],
[
'GET'
,
'/members/{id}/edit'
,
'Members\Controllers\MemberController@edit'
,
[
'auth'
],
'member.edit'
],
[
'POST'
,
'/members/{id}'
,
'Members\Controllers\MemberController@update'
,
[
'auth'
],
'member.edit'
],
[
'POST'
,
'/members/{id}'
,
'Members\Controllers\MemberController@update'
,
[
'auth'
],
'member.edit'
],
[
'POST'
,
'/members/{id}/status'
,
'Members\Controllers\MemberController@changeStatus'
,[
'auth'
],
'member.change_status'
],
// Fill Form (استمارة)
[
'GET'
,
'/members/{id}/fill-form'
,
'Members\Controllers\MemberController@fillForm'
,
[
'auth'
],
'member.edit'
],
[
'POST'
,
'/members/{id}/fill-form'
,
'Members\Controllers\MemberController@saveFillForm'
,[
'auth'
],
'member.edit'
],
// API endpoints
// API endpoints
[
'POST'
,
'/api/members/parse-nid'
,
'Members\Controllers\MemberApiController@parseNid'
,
[
'auth'
],
'member.create'
],
[
'POST'
,
'/api/members/parse-nid'
,
'Members\Controllers\MemberApiController@parseNid'
,
[
'auth'
],
'member.create'
],
[
'POST'
,
'/api/members/quick-search'
,
'Members\Controllers\MemberApiController@quickSearch'
,
[
'auth'
],
'member.search'
],
[
'POST'
,
'/api/members/search'
,
'Members\Controllers\MemberApiController@search'
,
[
'auth'
],
'member.view'
],
[
'POST'
,
'/api/members/check-duplicate'
,
'Members\Controllers\MemberApiController@checkDuplicate'
,
[
'auth'
],
'member.create'
],
];
];
\ No newline at end of file
app/Modules/Members/Services/FormNumberGenerator.php
0 → 100644
View file @
64b8d478
<?php
declare
(
strict_types
=
1
);
namespace
App\Modules\Members\Services
;
use
App\Core\App
;
final
class
FormNumberGenerator
{
/**
* Get the next form number.
* Returns null if not configured (super admin must set starting number).
*/
public
static
function
next
()
:
?
int
{
$db
=
App
::
getInstance
()
->
db
();
// Check existing form numbers in members table
$last
=
$db
->
selectOne
(
"SELECT MAX(CAST(form_number AS UNSIGNED)) as last_num
FROM members
WHERE form_number IS NOT NULL
AND form_number REGEXP '^[0-9]+$'"
);
$lastNum
=
(
int
)
(
$last
[
'last_num'
]
??
0
);
if
(
$lastNum
>
0
)
{
return
$lastNum
+
1
;
}
// No existing forms — check system config for starting number
$config
=
$db
->
selectOne
(
"SELECT config_value FROM system_config WHERE config_key = ?"
,
[
'membership.form_start_number'
]
);
if
(
$config
&&
is_numeric
(
$config
[
'config_value'
])
&&
(
int
)
$config
[
'config_value'
]
>
0
)
{
return
(
int
)
$config
[
'config_value'
];
}
// Not configured
return
null
;
}
/**
* Set the starting form number (called once by super admin).
*/
public
static
function
setStartNumber
(
int
$number
)
:
void
{
$db
=
App
::
getInstance
()
->
db
();
$existing
=
$db
->
selectOne
(
"SELECT id FROM system_config WHERE config_key = ?"
,
[
'membership.form_start_number'
]
);
if
(
$existing
)
{
$db
->
update
(
'system_config'
,
[
'config_value'
=>
(
string
)
$number
,
'updated_at'
=>
date
(
'Y-m-d H:i:s'
),
],
'`id` = ?'
,
[(
int
)
$existing
[
'id'
]]
);
}
else
{
$db
->
insert
(
'system_config'
,
[
'config_key'
=>
'membership.form_start_number'
,
'config_value'
=>
(
string
)
$number
,
'config_type'
=>
'integer'
,
'group_name'
=>
'membership'
,
'description_ar'
=>
'رقم بداية الاستمارات'
,
'description_en'
=>
'Starting Form Number'
,
'is_editable'
=>
1
,
'created_at'
=>
date
(
'Y-m-d H:i:s'
),
'updated_at'
=>
date
(
'Y-m-d H:i:s'
),
]);
}
}
/**
* Check if the form number system is configured.
*/
public
static
function
isConfigured
()
:
bool
{
return
self
::
next
()
!==
null
;
}
/**
* Get the form fee amount from service catalog or default.
*/
public
static
function
getFormFee
()
:
string
{
try
{
$db
=
App
::
getInstance
()
->
db
();
$fee
=
$db
->
selectOne
(
"SELECT base_amount FROM service_catalog WHERE service_code = 'FORM_NEW_MEMBERSHIP' AND is_active = 1 LIMIT 1"
);
if
(
$fee
&&
$fee
[
'base_amount'
])
{
return
$fee
[
'base_amount'
];
}
}
catch
(
\Throwable
$e
)
{
}
return
'505.00'
;
}
}
\ No newline at end of file
app/Modules/Members/Views/create.php
View file @
64b8d478
<?php
$__template
->
layout
(
'Layout.main'
);
?>
<?php
$__template
->
layout
(
'Layout.main'
);
?>
<?php
$__template
->
section
(
'title'
);
?>
تسجيل عضو جديد
<?php
$__template
->
endSection
();
?>
<?php
$__template
->
section
(
'title'
);
?>
تسجيل عضو جديد
<?php
$__template
->
endSection
();
?>
<?php
$__template
->
section
(
'content'
);
?>
<?php
$__template
->
section
(
'content'
);
?>
<form
method=
"POST"
action=
"/members"
id=
"member-form"
>
<?=
csrf_field
()
?>
<!-- Personal Data -->
<?php
if
(
$needsStartNumber
)
:
?>
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<!-- First time: Super admin must set starting form number -->
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
><h3
style=
"margin:0;color:#0D7377;"
>
البيانات الشخصية
</h3></div>
<div
class=
"card"
style=
"margin-bottom:20px;padding:20px;border-right:4px solid #D97706;"
>
<div
style=
"padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:15px;"
>
<h3
style=
"color:#D97706;margin:0 0 10px;"
>
⚠ تحديد رقم بداية الاستمارات
</h3>
<div
class=
"form-group"
style=
"grid-column:1/-1;"
>
<p
style=
"color:#6B7280;font-size:14px;margin-bottom:15px;"
>
هذه المرة الأولى — يجب تحديد رقم أول استمارة في النظام
</p>
<label
class=
"form-label"
>
الاسم بالكامل (عربي)
<span
style=
"color:#DC2626;"
>
*
</span></label>
<form
method=
"POST"
action=
"/members"
id=
"member-form"
>
<input
type=
"text"
name=
"full_name_ar"
value=
"
<?=
e
(
old
(
'full_name_ar'
))
?>
"
class=
"form-input"
required
minlength=
"10"
maxlength=
"200"
>
<?=
csrf_field
()
?>
</div>
<div
style=
"display:flex;gap:15px;align-items:end;margin-bottom:20px;"
>
<div
class=
"form-group"
>
<div
class=
"form-group"
style=
"flex:0 0 200px;"
>
<label
class=
"form-label"
>
الاسم بالكامل (إنجليزي)
</label>
<label
class=
"form-label"
>
رقم أول استمارة
<span
style=
"color:#DC2626;"
>
*
</span></label>
<input
type=
"text"
name=
"full_name_en"
value=
"
<?=
e
(
old
(
'full_name_en'
))
?>
"
class=
"form-input"
>
<input
type=
"number"
name=
"form_start_number"
class=
"form-input"
required
min=
"1"
style=
"direction:ltr;text-align:left;font-size:18px;font-weight:700;"
placeholder=
"مثال: 15001"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
نوع إثبات الشخصية
<span
style=
"color:#DC2626;"
>
*
</span></label>
<select
name=
"id_type"
id=
"id_type"
class=
"form-select"
required
>
<option
value=
"national_id"
<?=
old
(
'id_type'
,
'national_id'
)
===
'national_id'
?
'selected'
:
''
?>
>
رقم قومي
</option>
<option
value=
"passport"
<?=
old
(
'id_type'
)
===
'passport'
?
'selected'
:
''
?>
>
جواز سفر
</option>
</select>
</div>
<div
class=
"form-group"
id=
"nid-group"
>
<label
class=
"form-label"
>
الرقم القومي
<span
style=
"color:#DC2626;"
>
*
</span></label>
<input
type=
"text"
name=
"national_id"
id=
"national_id"
value=
"
<?=
e
(
old
(
'national_id'
))
?>
"
class=
"form-input"
maxlength=
"14"
pattern=
"\d{14}"
style=
"direction:ltr;text-align:left;"
placeholder=
"أدخل 14 رقم"
>
<div
id=
"nid-feedback"
style=
"margin-top:5px;font-size:12px;"
></div>
</div>
<div
class=
"form-group"
id=
"passport-group"
style=
"display:none;"
>
<label
class=
"form-label"
>
رقم جواز السفر
</label>
<input
type=
"text"
name=
"passport_number"
value=
"
<?=
e
(
old
(
'passport_number'
))
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
تاريخ الميلاد
<span
style=
"color:#DC2626;"
>
*
</span></label>
<input
type=
"date"
name=
"date_of_birth"
id=
"date_of_birth"
value=
"
<?=
e
(
old
(
'date_of_birth'
))
?>
"
class=
"form-input"
required
style=
"background:#F3F4F6;"
readonly
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
السن
</label>
<input
type=
"text"
name=
"age_display"
id=
"age_display"
class=
"form-input"
style=
"background:#F3F4F6;"
readonly
>
<input
type=
"hidden"
name=
"age_years"
id=
"age_years"
value=
"
<?=
e
(
old
(
'age_years'
))
?>
"
>
<input
type=
"hidden"
name=
"age_months"
id=
"age_months"
value=
"
<?=
e
(
old
(
'age_months'
))
?>
"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
النوع
<span
style=
"color:#DC2626;"
>
*
</span></label>
<select
name=
"gender"
id=
"gender"
class=
"form-select"
required
style=
"background:#F3F4F6;"
disabled
>
<option
value=
""
>
—
</option>
<option
value=
"male"
<?=
old
(
'gender'
)
===
'male'
?
'selected'
:
''
?>
>
ذكر
</option>
<option
value=
"female"
<?=
old
(
'gender'
)
===
'female'
?
'selected'
:
''
?>
>
أنثى
</option>
</select>
<input
type=
"hidden"
name=
"gender"
id=
"gender_hidden"
value=
"
<?=
e
(
old
(
'gender'
))
?>
"
>
</div>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
محافظة الميلاد
</label>
<input
type=
"text"
id=
"gov_display"
class=
"form-input"
style=
"background:#F3F4F6;"
readonly
>
<input
type=
"hidden"
name=
"governorate_code"
id=
"governorate_code"
value=
"
<?=
e
(
old
(
'governorate_code'
))
?>
"
>
</div>
</div>
<div
class=
"form-group"
>
<?php
else
:
?>
<label
class=
"form-label"
>
الجنسية
<span
style=
"color:#DC2626;"
>
*
</span></label>
<form
method=
"POST"
action=
"/members"
id=
"member-form"
>
<select
name=
"nationality"
class=
"form-select"
>
<?=
csrf_field
()
?>
<option
value=
"مصري"
selected
>
مصري
</option>
<?php
endif
;
?>
<?php
foreach
(
$countries
as
$c
)
:
?>
<?php
if
(
$c
[
'nationality_ar'
]
!==
'مصري'
)
:
?>
<!-- Form Info Banner -->
<option
value=
"
<?=
e
(
$c
[
'nationality_ar'
])
?>
"
<?=
old
(
'nationality'
)
===
$c
[
'nationality_ar'
]
?
'selected'
:
''
?>
>
<?=
e
(
$c
[
'nationality_ar'
])
?>
</option>
<div
class=
"card"
style=
"margin-bottom:20px;padding:20px;background:#EFF6FF;border:1px solid #BFDBFE;"
>
<div
style=
"display:flex;justify-content:space-between;align-items:center;"
>
<div>
<strong
style=
"color:#0284C7;font-size:16px;"
>
📋 استمارة عضوية جديدة
</strong>
<p
style=
"color:#6B7280;font-size:13px;margin:5px 0 0;"
>
أدخل البيانات الأساسية فقط — باقي البيانات تُملأ في الاستمارة بعد دفع الرسوم
</p>
</div>
<div
style=
"text-align:left;"
>
<?php
if
(
!
$needsStartNumber
&&
$nextFormNumber
)
:
?>
<div
style=
"font-size:12px;color:#6B7280;"
>
رقم الاستمارة التالي
</div>
<div
style=
"font-size:28px;font-weight:700;color:#0D7377;direction:ltr;"
>
<?=
(
int
)
$nextFormNumber
?>
</div>
<?php
endif
;
?>
<?php
endif
;
?>
<?php
endforeach
;
?>
<div
style=
"font-size:13px;color:#D97706;font-weight:600;margin-top:5px;"
>
رسوم الاستمارة:
<?=
money
(
$formFee
)
?>
</div>
</select>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
الديانة
</label>
<select
name=
"religion"
class=
"form-select"
>
<option
value=
""
>
-- اختر --
</option>
<option
value=
"muslim"
<?=
old
(
'religion'
)
===
'muslim'
?
'selected'
:
''
?>
>
مسلم
</option>
<option
value=
"christian"
<?=
old
(
'religion'
)
===
'christian'
?
'selected'
:
''
?>
>
مسيحي
</option>
<option
value=
"other"
<?=
old
(
'religion'
)
===
'other'
?
'selected'
:
''
?>
>
أخرى
</option>
</select>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
المؤهل الدراسي
<span
style=
"color:#DC2626;"
>
*
</span></label>
<select
name=
"qualification_id"
class=
"form-select"
required
>
<option
value=
""
>
-- اختر --
</option>
<?php
foreach
(
$qualifications
as
$q
)
:
?>
<option
value=
"
<?=
(
int
)
$q
[
'id'
]
?>
"
<?=
old
(
'qualification_id'
)
==
$q
[
'id'
]
?
'selected'
:
''
?>
>
<?=
e
(
$q
[
'name_ar'
])
?>
</option>
<?php
endforeach
;
?>
</select>
<small
style=
"color:#6B7280;"
>
المؤهل يؤثر على قيمة العضوية
</small>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
الحالة الاجتماعية
</label>
<select
name=
"marital_status"
class=
"form-select"
>
<option
value=
""
>
-- اختر --
</option>
<option
value=
"single"
<?=
old
(
'marital_status'
)
===
'single'
?
'selected'
:
''
?>
>
أعزب
</option>
<option
value=
"married"
<?=
old
(
'marital_status'
)
===
'married'
?
'selected'
:
''
?>
>
متزوج
</option>
<option
value=
"divorced"
<?=
old
(
'marital_status'
)
===
'divorced'
?
'selected'
:
''
?>
>
مطلق
</option>
<option
value=
"widowed"
<?=
old
(
'marital_status'
)
===
'widowed'
?
'selected'
:
''
?>
>
أرمل
</option>
</select>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
تاريخ إصدار إثبات الشخصية
</label>
<input
type=
"date"
name=
"id_issue_date"
value=
"
<?=
e
(
old
(
'id_issue_date'
))
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
تاريخ انتهاء إثبات الشخصية
</label>
<input
type=
"date"
name=
"id_expiry_date"
value=
"
<?=
e
(
old
(
'id_expiry_date'
))
?>
"
class=
"form-input"
>
</div>
</div>
</div>
</div>
</div>
</div>
<!--
Contact
-->
<!--
Basic Info Card
-->
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
><h3
style=
"margin:0;color:#0D7377;"
>
بيانات الاتصال
</h3></div>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
>
<div
style=
"padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:15px;"
>
<h3
style=
"margin:0;color:#0D7377;"
>
البيانات الأساسية
</h3>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
رقم المحمول
<span
style=
"color:#DC2626;"
>
*
</span></label>
<input
type=
"tel"
name=
"phone_mobile"
value=
"
<?=
e
(
old
(
'phone_mobile'
))
?>
"
class=
"form-input"
required
maxlength=
"11"
style=
"direction:ltr;text-align:left;"
placeholder=
"01XXXXXXXXX"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
تليفون المنزل
</label>
<input
type=
"tel"
name=
"phone_home"
value=
"
<?=
e
(
old
(
'phone_home'
))
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
رقم تليفون خارج مصر
</label>
<input
type=
"tel"
name=
"phone_international"
value=
"
<?=
e
(
old
(
'phone_international'
))
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
البريد الإلكتروني
</label>
<input
type=
"email"
name=
"email"
value=
"
<?=
e
(
old
(
'email'
))
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
شخص للطوارئ — الاسم
</label>
<input
type=
"text"
name=
"emergency_name"
value=
"
<?=
e
(
old
(
'emergency_name'
))
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
شخص للطوارئ — المحمول
</label>
<input
type=
"tel"
name=
"emergency_phone"
value=
"
<?=
e
(
old
(
'emergency_phone'
))
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
</div>
</div>
<div
style=
"padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:20px;"
>
<!-- Full Name Arabic -->
<div
class=
"form-group"
style=
"grid-column:1/-1;"
>
<label
class=
"form-label"
>
الاسم بالكامل (عربي)
<span
style=
"color:#DC2626;"
>
*
</span></label>
<input
type=
"text"
name=
"full_name_ar"
value=
"
<?=
e
(
old
(
'full_name_ar'
))
?>
"
class=
"form-input"
required
minlength=
"5"
maxlength=
"200"
placeholder=
"الاسم رباعي بالعربي"
style=
"font-size:16px;"
>
</div>
</div>
<!-- Residence -->
<!-- National ID -->
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
><h3
style=
"margin:0;color:#0D7377;"
>
بيانات السكن
</h3></div>
<div
style=
"padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:15px;"
>
<div
class=
"form-group"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
نوع السكن
</label>
<label
class=
"form-label"
>
الرقم القومي
<span
style=
"color:#DC2626;"
>
*
</span></label>
<select
name=
"residence_type"
class=
"form-select"
>
<input
type=
"text"
name=
"national_id"
id=
"national_id"
value=
"
<?=
e
(
old
(
'national_id'
))
?>
"
class=
"form-input"
maxlength=
"14"
style=
"direction:ltr;text-align:left;font-size:18px;letter-spacing:2px;"
placeholder=
"أدخل 14 رقم"
>
<option
value=
""
>
-- اختر --
</option>
<div
id=
"nid-feedback"
style=
"margin-top:5px;font-size:12px;"
></div>
<option
value=
"rented"
<?=
old
(
'residence_type'
)
===
'rented'
?
'selected'
:
''
?>
>
إيجار
</option>
<option
value=
"owned"
<?=
old
(
'residence_type'
)
===
'owned'
?
'selected'
:
''
?>
>
ملك
</option>
<option
value=
"other"
<?=
old
(
'residence_type'
)
===
'other'
?
'selected'
:
''
?>
>
أخرى
</option>
</select>
</div>
</div>
<!-- Phone -->
<div
class=
"form-group"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
المنطقة
</label>
<label
class=
"form-label"
>
رقم المحمول
<span
style=
"color:#DC2626;"
>
*
</span></label>
<input
type=
"text"
name=
"area"
value=
"
<?=
e
(
old
(
'area'
))
?>
"
class=
"form-input"
>
<input
type=
"tel"
name=
"phone_mobile"
value=
"
<?=
e
(
old
(
'phone_mobile'
))
?>
"
class=
"form-input"
required
maxlength=
"11"
style=
"direction:ltr;text-align:left;font-size:16px;"
placeholder=
"01XXXXXXXXX"
>
</div>
<div
class=
"form-group"
style=
"grid-column:1/-1;"
>
<label
class=
"form-label"
>
عنوان السكن
</label>
<textarea
name=
"residence_address"
class=
"form-textarea"
rows=
"2"
>
<?=
e
(
old
(
'residence_address'
))
?>
</textarea>
</div>
</div>
<!-- Branch -->
<div
class=
"form-group"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
ال
محافظة
</label>
<label
class=
"form-label"
>
ال
فرع
<span
style=
"color:#DC2626;"
>
*
</span>
</label>
<select
name=
"
governorate"
class=
"form-select
"
>
<select
name=
"
branch_id"
class=
"form-select"
required
style=
"font-size:16px;
"
>
<option
value=
""
>
-- اختر --
</option>
<option
value=
""
>
-- اختر
الفرع
--
</option>
<?php
foreach
(
$
governorates
as
$g
)
:
?>
<?php
foreach
(
$
branches
as
$b
)
:
?>
<option
value=
"
<?=
e
(
$g
[
'name_ar'
])
?>
"
<?=
old
(
'governorate'
)
===
$g
[
'name_ar'
]
?
'selected'
:
''
?>
>
<?=
e
(
$g
[
'name_ar'
])
?>
</option>
<option
value=
"
<?=
(
int
)
$b
[
'id'
]
?>
"
<?=
old
(
'branch_id'
)
==
$b
[
'id'
]
?
'selected'
:
''
?>
>
<?=
e
(
$b
[
'name_ar'
])
?>
</option>
<?php
endforeach
;
?>
<?php
endforeach
;
?>
</select>
</select>
</div>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
عنوان المراسلات
</label>
<select
name=
"correspondence_address"
class=
"form-select"
>
<option
value=
""
>
-- اختر --
</option>
<option
value=
"work"
<?=
old
(
'correspondence_address'
)
===
'work'
?
'selected'
:
''
?>
>
العمل
</option>
<option
value=
"residence"
<?=
old
(
'correspondence_address'
)
===
'residence'
?
'selected'
:
''
?>
>
السكن
</option>
<option
value=
"other"
<?=
old
(
'correspondence_address'
)
===
'other'
?
'selected'
:
''
?>
>
أخرى
</option>
</select>
</div>
</div>
</div>
<!-- Work -->
<!-- Auto-parsed fields (read-only) -->
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
><h3
style=
"margin:0;color:#0D7377;"
>
بيانات العمل
</h3></div>
<div
style=
"padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:15px;"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
نوع التوظيف
</label>
<select
name=
"employment_type"
class=
"form-select"
>
<option
value=
""
>
-- اختر --
</option>
<option
value=
"employed"
<?=
old
(
'employment_type'
)
===
'employed'
?
'selected'
:
''
?>
>
موظف
</option>
<option
value=
"self_employed"
<?=
old
(
'employment_type'
)
===
'self_employed'
?
'selected'
:
''
?>
>
أعمال حرة
</option>
<option
value=
"professions"
<?=
old
(
'employment_type'
)
===
'professions'
?
'selected'
:
''
?>
>
مهن حرة
</option>
<option
value=
"other"
<?=
old
(
'employment_type'
)
===
'other'
?
'selected'
:
''
?>
>
أخرى
</option>
</select>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
المهنة
</label>
<input
type=
"text"
name=
"occupation"
value=
"
<?=
e
(
old
(
'occupation'
))
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
المركز الوظيفي
</label>
<input
type=
"text"
name=
"job_title"
value=
"
<?=
e
(
old
(
'job_title'
))
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
تاريخ الالتحاق بالعمل
</label>
<label
class=
"form-label"
>
تاريخ الميلاد
</label>
<input
type=
"date"
name=
"employment_date"
value=
"
<?=
e
(
old
(
'employment_date'
))
?>
"
class=
"form-input"
>
<input
type=
"date"
name=
"date_of_birth"
id=
"date_of_birth"
value=
"
<?=
e
(
old
(
'date_of_birth'
))
?>
"
class=
"form-input"
style=
"background:#F3F4F6;"
readonly
>
</div>
<div
class=
"form-group"
style=
"grid-column:1/-1;"
>
<label
class=
"form-label"
>
عنوان العمل
</label>
<textarea
name=
"business_address"
class=
"form-textarea"
rows=
"2"
>
<?=
e
(
old
(
'business_address'
))
?>
</textarea>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
تليفون العمل
</label>
<input
type=
"tel"
name=
"office_phone"
value=
"
<?=
e
(
old
(
'office_phone'
))
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
</div>
<div
class=
"form-group"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
نشاط العمل
</label>
<label
class=
"form-label"
>
السن
</label>
<input
type=
"text"
name=
"business_activity"
value=
"
<?=
e
(
old
(
'business_activity'
))
?>
"
class=
"form-input"
>
<input
type=
"text"
id=
"age_display"
class=
"form-input"
style=
"background:#F3F4F6;"
readonly
>
</div
>
<input
type=
"hidden"
name=
"age_years"
id=
"age_years"
>
</div
>
<input
type=
"hidden"
name=
"age_months"
id=
"age_months"
>
</div>
</div>
<!-- Membership -->
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
><h3
style=
"margin:0;color:#0D7377;"
>
بيانات العضوية
</h3></div>
<div
style=
"padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:15px;"
>
<div
class=
"form-group"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
الفرع
<span
style=
"color:#DC2626;"
>
*
</span></label>
<label
class=
"form-label"
>
النوع
</label>
<select
name=
"branch_id"
class=
"form-select"
required
>
<input
type=
"text"
id=
"gender_display"
class=
"form-input"
style=
"background:#F3F4F6;"
readonly
>
<option
value=
""
>
-- اختر --
</option>
<input
type=
"hidden"
name=
"gender"
id=
"gender_hidden"
value=
"
<?=
e
(
old
(
'gender'
))
?>
"
>
<?php
foreach
(
$branches
as
$b
)
:
?>
<option
value=
"
<?=
(
int
)
$b
[
'id'
]
?>
"
<?=
old
(
'branch_id'
)
==
$b
[
'id'
]
?
'selected'
:
''
?>
>
<?=
e
(
$b
[
'name_ar'
])
?>
</option>
<?php
endforeach
;
?>
</select>
</div>
</div>
<div
class=
"form-group"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
كيف عرفت النادي
</label>
<label
class=
"form-label"
>
محافظة الميلاد
</label>
<select
name=
"referral_source"
class=
"form-select"
>
<input
type=
"text"
id=
"gov_display"
class=
"form-input"
style=
"background:#F3F4F6;"
readonly
>
<option
value=
""
>
-- اختر --
</option>
<input
type=
"hidden"
name=
"governorate_code"
id=
"governorate_code"
>
<option
value=
"social_media"
<?=
old
(
'referral_source'
)
===
'social_media'
?
'selected'
:
''
?>
>
مواقع التواصل الاجتماعي
</option>
<option
value=
"tv"
<?=
old
(
'referral_source'
)
===
'tv'
?
'selected'
:
''
?>
>
إعلان التليفزيون
</option>
<option
value=
"friend"
<?=
old
(
'referral_source'
)
===
'friend'
?
'selected'
:
''
?>
>
من خلال صديق
</option>
<option
value=
"radio"
<?=
old
(
'referral_source'
)
===
'radio'
?
'selected'
:
''
?>
>
إعلان الراديو
</option>
<option
value=
"outdoor"
<?=
old
(
'referral_source'
)
===
'outdoor'
?
'selected'
:
''
?>
>
إعلانات الطريق
</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<div
style=
"display:flex;gap:10px;"
>
<div
style=
"display:flex;gap:10px;"
>
<button
type=
"submit"
class=
"btn btn-primary"
>
تسجيل العضو
</button>
<button
type=
"submit"
class=
"btn btn-primary"
style=
"padding:12px 30px;font-size:16px;"
>
📋 تسجيل وإنشاء الاستمارة
</button>
<a
href=
"/members"
class=
"btn btn-outline"
>
إلغاء
</a>
<a
href=
"/members"
class=
"btn btn-outline"
style=
"padding:12px 20px;"
>
إلغاء
</a>
</div>
</div>
</form>
</form>
...
@@ -259,60 +111,24 @@
...
@@ -259,60 +111,24 @@
<?php
$__template
->
section
(
'scripts'
);
?>
<?php
$__template
->
section
(
'scripts'
);
?>
<script>
<script>
document
.
addEventListener
(
'DOMContentLoaded'
,
function
()
{
document
.
addEventListener
(
'DOMContentLoaded'
,
function
()
{
var
idTypeSelect
=
document
.
getElementById
(
'id_type'
);
var
nidGroup
=
document
.
getElementById
(
'nid-group'
);
var
passportGroup
=
document
.
getElementById
(
'passport-group'
);
var
nidInput
=
document
.
getElementById
(
'national_id'
);
var
nidInput
=
document
.
getElementById
(
'national_id'
);
var
dobInput
=
document
.
getElementById
(
'date_of_birth'
);
var
dobInput
=
document
.
getElementById
(
'date_of_birth'
);
var
ageDisplay
=
document
.
getElementById
(
'age_display'
);
var
ageDisplay
=
document
.
getElementById
(
'age_display'
);
var
ageYears
=
document
.
getElementById
(
'age_years'
);
var
ageYears
=
document
.
getElementById
(
'age_years'
);
var
ageMonths
=
document
.
getElementById
(
'age_months'
);
var
ageMonths
=
document
.
getElementById
(
'age_months'
);
var
gender
Select
=
document
.
getElementById
(
'gender
'
);
var
gender
Display
=
document
.
getElementById
(
'gender_display
'
);
var
genderHidden
=
document
.
getElementById
(
'gender_hidden'
);
var
genderHidden
=
document
.
getElementById
(
'gender_hidden'
);
var
govDisplay
=
document
.
getElementById
(
'gov_display'
);
var
govDisplay
=
document
.
getElementById
(
'gov_display'
);
var
govCode
=
document
.
getElementById
(
'governorate_code'
);
var
govCode
=
document
.
getElementById
(
'governorate_code'
);
var
feedback
=
document
.
getElementById
(
'nid-feedback'
);
var
feedback
=
document
.
getElementById
(
'nid-feedback'
);
function
toggleIdType
()
{
if
(
idTypeSelect
.
value
===
'passport'
)
{
nidGroup
.
style
.
display
=
'none'
;
passportGroup
.
style
.
display
=
'block'
;
dobInput
.
removeAttribute
(
'readonly'
);
dobInput
.
style
.
background
=
''
;
genderSelect
.
removeAttribute
(
'disabled'
);
genderSelect
.
style
.
background
=
''
;
}
else
{
nidGroup
.
style
.
display
=
'block'
;
passportGroup
.
style
.
display
=
'none'
;
dobInput
.
setAttribute
(
'readonly'
,
'readonly'
);
dobInput
.
style
.
background
=
'#F3F4F6'
;
}
}
idTypeSelect
.
addEventListener
(
'change'
,
toggleIdType
);
toggleIdType
();
nidInput
.
addEventListener
(
'input'
,
function
()
{
nidInput
.
addEventListener
(
'input'
,
function
()
{
var
val
=
this
.
value
.
replace
(
/
\D
/g
,
''
);
var
val
=
this
.
value
.
replace
(
/
\D
/g
,
''
);
this
.
value
=
val
;
this
.
value
=
val
;
if
(
val
.
length
===
14
)
{
if
(
val
.
length
===
14
)
{
parseNid
(
val
);
}
else
{
feedback
.
innerHTML
=
''
;
dobInput
.
value
=
''
;
ageDisplay
.
value
=
''
;
ageYears
.
value
=
''
;
ageMonths
.
value
=
''
;
genderSelect
.
value
=
''
;
genderHidden
.
value
=
''
;
govDisplay
.
value
=
''
;
govCode
.
value
=
''
;
}
});
function
parseNid
(
nid
)
{
feedback
.
innerHTML
=
'<span style="color:#0284C7;">جاري التحقق...</span>'
;
feedback
.
innerHTML
=
'<span style="color:#0284C7;">جاري التحقق...</span>'
;
var
formData
=
new
FormData
();
var
formData
=
new
FormData
();
formData
.
append
(
'national_id'
,
nid
);
formData
.
append
(
'national_id'
,
val
);
var
csrfToken
=
document
.
querySelector
(
'input[name="_csrf_token"]'
);
var
csrfToken
=
document
.
querySelector
(
'input[name="_csrf_token"]'
);
if
(
csrfToken
)
formData
.
append
(
'_csrf_token'
,
csrfToken
.
value
);
if
(
csrfToken
)
formData
.
append
(
'_csrf_token'
,
csrfToken
.
value
);
...
@@ -325,25 +141,27 @@ document.addEventListener('DOMContentLoaded', function() {
...
@@ -325,25 +141,27 @@ document.addEventListener('DOMContentLoaded', function() {
ageDisplay
.
value
=
p
.
age_years
+
' سنة و '
+
p
.
age_months
+
' شهر'
;
ageDisplay
.
value
=
p
.
age_years
+
' سنة و '
+
p
.
age_months
+
' شهر'
;
ageYears
.
value
=
p
.
age_years
;
ageYears
.
value
=
p
.
age_years
;
ageMonths
.
value
=
p
.
age_months
;
ageMonths
.
value
=
p
.
age_months
;
genderSelect
.
value
=
p
.
gender
;
genderDisplay
.
value
=
p
.
gender
===
'male'
?
'ذكر'
:
'أنثى'
;
genderHidden
.
value
=
p
.
gender
;
genderHidden
.
value
=
p
.
gender
;
govDisplay
.
value
=
p
.
governorate_name_ar
||
''
;
govDisplay
.
value
=
p
.
governorate_name_ar
||
''
;
govCode
.
value
=
p
.
governorate_code
||
''
;
govCode
.
value
=
p
.
governorate_code
||
''
;
feedback
.
innerHTML
=
'<span style="color:#059669;">✓ الرقم القومي صالح</span>'
;
feedback
.
innerHTML
=
'<span style="color:#059669;">✓ الرقم القومي صالح</span>'
;
if
(
data
.
duplicate
)
{
if
(
data
.
duplicate
)
{
var
d
=
data
.
duplicate
;
feedback
.
innerHTML
+=
'<br><span style="color:#DC2626;">✖ مسجل بالفعل: '
+
data
.
duplicate
.
full_name_ar
+
'</span>'
;
var
msg
=
d
.
is_archived
?
'⚠ هذا الرقم مسجل في الأرشيف: '
:
'✖ هذا الرقم مسجل بالفعل: '
;
feedback
.
innerHTML
+=
'<br><span style="color:'
+
(
d
.
is_archived
?
'#D97706'
:
'#DC2626'
)
+
';">'
+
msg
+
d
.
full_name_ar
+
' ('
+
(
d
.
membership_number
||
'بدون رقم'
)
+
')</span>'
;
}
}
}
else
{
}
else
{
feedback
.
innerHTML
=
'<span style="color:#DC2626;">✖ '
+
(
p
.
errors
?
p
.
errors
.
join
(
' | '
)
:
'رقم
غير صالح'
)
+
'</span>'
;
feedback
.
innerHTML
=
'<span style="color:#DC2626;">✖ '
+
(
p
.
errors
?
p
.
errors
.
join
(
' | '
)
:
'
غير صالح'
)
+
'</span>'
;
}
}
})
})
.
catch
(
function
()
{
.
catch
(
function
()
{
feedback
.
innerHTML
=
'<span style="color:#DC2626;">خطأ</span>'
;
});
feedback
.
innerHTML
=
'<span style="color:#DC2626;">خطأ في الاتصال</span>'
;
}
else
{
});
feedback
.
innerHTML
=
''
;
dobInput
.
value
=
''
;
ageDisplay
.
value
=
''
;
genderDisplay
.
value
=
''
;
govDisplay
.
value
=
''
;
}
}
});
});
});
</script>
</script>
<?php
$__template
->
endSection
();
?>
<?php
$__template
->
endSection
();
?>
\ No newline at end of file
app/Modules/Members/Views/fill-form.php
0 → 100644
View file @
64b8d478
<?php
$__template
->
layout
(
'Layout.main'
);
?>
<?php
$__template
->
section
(
'title'
);
?>
ملء الاستمارة —
<?=
e
(
$member
->
full_name_ar
)
?><?php
$__template
->
endSection
();
?>
<?php
$__template
->
section
(
'content'
);
?>
<!-- Header -->
<div
class=
"card"
style=
"margin-bottom:20px;padding:20px;background:#FFF7ED;border:1px solid #FED7AA;"
>
<div
style=
"display:flex;justify-content:space-between;align-items:center;"
>
<div>
<h2
style=
"margin:0 0 5px;color:#D97706;"
>
📋 استمارة رقم
<?=
e
(
$member
->
form_number
??
'—'
)
?>
</h2>
<p
style=
"margin:0;color:#6B7280;font-size:14px;"
>
<strong>
<?=
e
(
$member
->
full_name_ar
)
?>
</strong>
— الرقم القومي:
<?=
e
(
$member
->
national_id
??
'—'
)
?>
— تاريخ الاستمارة:
<?=
e
(
$member
->
form_date
??
date
(
'Y-m-d'
))
?>
</p>
</div>
<a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
"
class=
"btn btn-outline"
>
← العودة للعضو
</a>
</div>
</div>
<form
method=
"POST"
action=
"/members/
<?=
(
int
)
$member
->
id
?>
/fill-form"
>
<?=
csrf_field
()
?>
<!-- Section 1: Personal Details -->
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
>
<h3
style=
"margin:0;color:#0D7377;"
>
1. البيانات الشخصية التكميلية
</h3>
</div>
<div
style=
"padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:15px;"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
الاسم بالإنجليزي
</label>
<input
type=
"text"
name=
"full_name_en"
value=
"
<?=
e
(
$member
->
full_name_en
??
''
)
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
محل الميلاد
</label>
<input
type=
"text"
name=
"place_of_birth"
value=
"
<?=
e
(
$member
->
place_of_birth
??
''
)
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
الجنسية
</label>
<select
name=
"nationality"
class=
"form-select"
>
<option
value=
"مصري"
<?=
(
$member
->
nationality
??
''
)
===
'مصري'
?
'selected'
:
''
?>
>
مصري
</option>
<?php
foreach
(
$countries
as
$c
)
:
?>
<?php
if
(
$c
[
'nationality_ar'
]
!==
'مصري'
)
:
?>
<option
value=
"
<?=
e
(
$c
[
'nationality_ar'
])
?>
"
<?=
(
$member
->
nationality
??
''
)
===
$c
[
'nationality_ar'
]
?
'selected'
:
''
?>
>
<?=
e
(
$c
[
'nationality_ar'
])
?>
</option>
<?php
endif
;
?>
<?php
endforeach
;
?>
</select>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
الديانة
</label>
<select
name=
"religion"
class=
"form-select"
>
<option
value=
""
>
-- اختر --
</option>
<option
value=
"muslim"
<?=
(
$member
->
religion
??
''
)
===
'muslim'
?
'selected'
:
''
?>
>
مسلم
</option>
<option
value=
"christian"
<?=
(
$member
->
religion
??
''
)
===
'christian'
?
'selected'
:
''
?>
>
مسيحي
</option>
<option
value=
"other"
<?=
(
$member
->
religion
??
''
)
===
'other'
?
'selected'
:
''
?>
>
أخرى
</option>
</select>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
المؤهل الدراسي
<span
style=
"color:#DC2626;"
>
*
</span></label>
<select
name=
"qualification_id"
class=
"form-select"
required
>
<option
value=
""
>
-- اختر المؤهل --
</option>
<?php
foreach
(
$qualifications
as
$q
)
:
?>
<option
value=
"
<?=
(
int
)
$q
[
'id'
]
?>
"
<?=
(
$member
->
qualification_id
??
0
)
==
$q
[
'id'
]
?
'selected'
:
''
?>
>
<?=
e
(
$q
[
'name_ar'
])
?>
</option>
<?php
endforeach
;
?>
</select>
<small
style=
"color:#D97706;"
>
المؤهل يؤثر على قيمة العضوية
</small>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
الحالة الاجتماعية
</label>
<select
name=
"marital_status"
class=
"form-select"
>
<option
value=
""
>
-- اختر --
</option>
<option
value=
"single"
<?=
(
$member
->
marital_status
??
''
)
===
'single'
?
'selected'
:
''
?>
>
أعزب
</option>
<option
value=
"married"
<?=
(
$member
->
marital_status
??
''
)
===
'married'
?
'selected'
:
''
?>
>
متزوج
</option>
<option
value=
"divorced"
<?=
(
$member
->
marital_status
??
''
)
===
'divorced'
?
'selected'
:
''
?>
>
مطلق
</option>
<option
value=
"widowed"
<?=
(
$member
->
marital_status
??
''
)
===
'widowed'
?
'selected'
:
''
?>
>
أرمل
</option>
</select>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
تاريخ إصدار إثبات الشخصية
</label>
<input
type=
"date"
name=
"id_issue_date"
value=
"
<?=
e
(
$member
->
id_issue_date
??
''
)
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
تاريخ انتهاء إثبات الشخصية
</label>
<input
type=
"date"
name=
"id_expiry_date"
value=
"
<?=
e
(
$member
->
id_expiry_date
??
''
)
?>
"
class=
"form-input"
>
</div>
</div>
</div>
<!-- Section 2: Contact -->
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
>
<h3
style=
"margin:0;color:#0D7377;"
>
2. بيانات الاتصال
</h3>
</div>
<div
style=
"padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:15px;"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
تليفون المنزل
</label>
<input
type=
"tel"
name=
"phone_home"
value=
"
<?=
e
(
$member
->
phone_home
??
''
)
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
رقم تليفون خارج مصر
</label>
<input
type=
"tel"
name=
"phone_international"
value=
"
<?=
e
(
$member
->
phone_international
??
''
)
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
البريد الإلكتروني
</label>
<input
type=
"email"
name=
"email"
value=
"
<?=
e
(
$member
->
email
??
''
)
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
<div
class=
"form-group"
></div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
شخص للطوارئ — الاسم
</label>
<input
type=
"text"
name=
"emergency_name"
value=
"
<?=
e
(
$member
->
emergency_name
??
''
)
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
شخص للطوارئ — المحمول
</label>
<input
type=
"tel"
name=
"emergency_phone"
value=
"
<?=
e
(
$member
->
emergency_phone
??
''
)
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
</div>
</div>
<!-- Section 3: Residence -->
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
>
<h3
style=
"margin:0;color:#0D7377;"
>
3. بيانات السكن
</h3>
</div>
<div
style=
"padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:15px;"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
نوع السكن
</label>
<select
name=
"residence_type"
class=
"form-select"
>
<option
value=
""
>
-- اختر --
</option>
<option
value=
"owned"
<?=
(
$member
->
residence_type
??
''
)
===
'owned'
?
'selected'
:
''
?>
>
ملك
</option>
<option
value=
"rented"
<?=
(
$member
->
residence_type
??
''
)
===
'rented'
?
'selected'
:
''
?>
>
إيجار
</option>
<option
value=
"other"
<?=
(
$member
->
residence_type
??
''
)
===
'other'
?
'selected'
:
''
?>
>
أخرى
</option>
</select>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
المنطقة
</label>
<input
type=
"text"
name=
"area"
value=
"
<?=
e
(
$member
->
area
??
''
)
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
style=
"grid-column:1/-1;"
>
<label
class=
"form-label"
>
عنوان السكن
</label>
<textarea
name=
"residence_address"
class=
"form-textarea"
rows=
"2"
>
<?=
e
(
$member
->
residence_address
??
''
)
?>
</textarea>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
علامة مميزة
</label>
<input
type=
"text"
name=
"landmark"
value=
"
<?=
e
(
$member
->
landmark
??
''
)
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
الدور
</label>
<input
type=
"text"
name=
"floor"
value=
"
<?=
e
(
$member
->
floor
??
''
)
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
الشقة
</label>
<input
type=
"text"
name=
"apartment"
value=
"
<?=
e
(
$member
->
apartment
??
''
)
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
المحافظة
</label>
<select
name=
"governorate"
class=
"form-select"
>
<option
value=
""
>
-- اختر --
</option>
<?php
foreach
(
$governorates
as
$g
)
:
?>
<option
value=
"
<?=
e
(
$g
[
'name_ar'
])
?>
"
<?=
(
$member
->
governorate
??
''
)
===
$g
[
'name_ar'
]
?
'selected'
:
''
?>
>
<?=
e
(
$g
[
'name_ar'
])
?>
</option>
<?php
endforeach
;
?>
</select>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
عنوان المراسلات
</label>
<select
name=
"correspondence_address"
class=
"form-select"
>
<option
value=
""
>
-- اختر --
</option>
<option
value=
"residence"
<?=
(
$member
->
correspondence_address
??
''
)
===
'residence'
?
'selected'
:
''
?>
>
السكن
</option>
<option
value=
"work"
<?=
(
$member
->
correspondence_address
??
''
)
===
'work'
?
'selected'
:
''
?>
>
العمل
</option>
<option
value=
"other"
<?=
(
$member
->
correspondence_address
??
''
)
===
'other'
?
'selected'
:
''
?>
>
أخرى
</option>
</select>
</div>
</div>
</div>
<!-- Section 4: Employment -->
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
>
<h3
style=
"margin:0;color:#0D7377;"
>
4. بيانات العمل
</h3>
</div>
<div
style=
"padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:15px;"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
نوع التوظيف
</label>
<select
name=
"employment_type"
class=
"form-select"
>
<option
value=
""
>
-- اختر --
</option>
<option
value=
"employed"
<?=
(
$member
->
employment_type
??
''
)
===
'employed'
?
'selected'
:
''
?>
>
موظف
</option>
<option
value=
"self_employed"
<?=
(
$member
->
employment_type
??
''
)
===
'self_employed'
?
'selected'
:
''
?>
>
أعمال حرة
</option>
<option
value=
"professions"
<?=
(
$member
->
employment_type
??
''
)
===
'professions'
?
'selected'
:
''
?>
>
مهن حرة
</option>
<option
value=
"retired"
<?=
(
$member
->
employment_type
??
''
)
===
'retired'
?
'selected'
:
''
?>
>
متقاعد
</option>
<option
value=
"other"
<?=
(
$member
->
employment_type
??
''
)
===
'other'
?
'selected'
:
''
?>
>
أخرى
</option>
</select>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
المهنة
</label>
<input
type=
"text"
name=
"occupation"
value=
"
<?=
e
(
$member
->
occupation
??
''
)
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
المركز الوظيفي
</label>
<input
type=
"text"
name=
"job_title"
value=
"
<?=
e
(
$member
->
job_title
??
''
)
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
تاريخ الالتحاق بالعمل
</label>
<input
type=
"date"
name=
"employment_date"
value=
"
<?=
e
(
$member
->
employment_date
??
''
)
?>
"
class=
"form-input"
>
</div>
<div
class=
"form-group"
style=
"grid-column:1/-1;"
>
<label
class=
"form-label"
>
عنوان العمل
</label>
<textarea
name=
"business_address"
class=
"form-textarea"
rows=
"2"
>
<?=
e
(
$member
->
business_address
??
''
)
?>
</textarea>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
تليفون العمل
</label>
<input
type=
"tel"
name=
"office_phone"
value=
"
<?=
e
(
$member
->
office_phone
??
''
)
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
فاكس العمل
</label>
<input
type=
"tel"
name=
"office_fax"
value=
"
<?=
e
(
$member
->
office_fax
??
''
)
?>
"
class=
"form-input"
style=
"direction:ltr;text-align:left;"
>
</div>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
نشاط العمل
</label>
<input
type=
"text"
name=
"business_activity"
value=
"
<?=
e
(
$member
->
business_activity
??
''
)
?>
"
class=
"form-input"
>
</div>
</div>
</div>
<!-- Section 5: How did you hear -->
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
>
<h3
style=
"margin:0;color:#0D7377;"
>
5. معلومات إضافية
</h3>
</div>
<div
style=
"padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:15px;"
>
<div
class=
"form-group"
>
<label
class=
"form-label"
>
كيف عرفت النادي
</label>
<select
name=
"referral_source"
class=
"form-select"
>
<option
value=
""
>
-- اختر --
</option>
<option
value=
"social_media"
<?=
(
$member
->
referral_source
??
''
)
===
'social_media'
?
'selected'
:
''
?>
>
مواقع التواصل الاجتماعي
</option>
<option
value=
"tv"
<?=
(
$member
->
referral_source
??
''
)
===
'tv'
?
'selected'
:
''
?>
>
إعلان تليفزيون
</option>
<option
value=
"friend"
<?=
(
$member
->
referral_source
??
''
)
===
'friend'
?
'selected'
:
''
?>
>
من خلال صديق
</option>
<option
value=
"radio"
<?=
(
$member
->
referral_source
??
''
)
===
'radio'
?
'selected'
:
''
?>
>
إعلان راديو
</option>
<option
value=
"outdoor"
<?=
(
$member
->
referral_source
??
''
)
===
'outdoor'
?
'selected'
:
''
?>
>
إعلانات الطريق
</option>
<option
value=
"member"
<?=
(
$member
->
referral_source
??
''
)
===
'member'
?
'selected'
:
''
?>
>
عضو بالنادي
</option>
<option
value=
"other"
<?=
(
$member
->
referral_source
??
''
)
===
'other'
?
'selected'
:
''
?>
>
أخرى
</option>
</select>
</div>
</div>
</div>
<div
style=
"display:flex;gap:10px;"
>
<button
type=
"submit"
class=
"btn btn-primary"
style=
"padding:12px 30px;font-size:16px;"
>
✓ حفظ الاستمارة
</button>
<a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
"
class=
"btn btn-outline"
style=
"padding:12px 20px;"
>
إلغاء
</a>
</div>
</form>
<?php
$__template
->
endSection
();
?>
\ No newline at end of file
app/Modules/Members/Views/show.php
View file @
64b8d478
<?php
$__template
->
layout
(
'Layout.main'
);
?>
<?php
$__template
->
layout
(
'Layout.main'
);
?>
<?php
$__template
->
section
(
'title'
);
?>
العضو:
<?=
e
(
$member
->
full_name_ar
)
?><?php
$__template
->
endSection
();
?>
<?php
$__template
->
section
(
'title'
);
?><?=
e
(
$member
->
full_name_ar
)
?><?php
$__template
->
endSection
();
?>
<?php
$__template
->
section
(
'page_actions'
);
?>
<?php
$__template
->
section
(
'page_actions'
);
?>
<a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
/edit"
class=
"btn btn-outline"
>
تعديل
</a>
<a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
/edit"
class=
"btn btn-outline"
>
✏️
تعديل
</a>
<a
href=
"/members"
class=
"btn btn-outline"
>
←
قائمة الأعضاء
</a>
<a
href=
"/members"
class=
"btn btn-outline"
>
←
العودة
</a>
<?php
$__template
->
endSection
();
?>
<?php
$__template
->
endSection
();
?>
<?php
$__template
->
section
(
'content'
);
?>
<?php
$__template
->
section
(
'content'
);
?>
<!-- Profile Header -->
<?php
<div
class=
"card"
style=
"margin-bottom:20px;padding:20px;display:flex;justify-content:space-between;align-items:center;"
>
$statusLabel
=
$member
->
getStatusLabel
();
$statusColor
=
$member
->
getStatusColor
();
?>
<!-- Form Not Filled Banner -->
<?php
if
(
!
$formFilled
&&
in_array
(
$member
->
status
,
[
'potential'
]))
:
?>
<div
class=
"card"
style=
"margin-bottom:20px;padding:25px;background:linear-gradient(135deg, #FFF7ED, #FEF3C7);border:2px solid #F59E0B;"
>
<div
style=
"display:flex;justify-content:space-between;align-items:center;"
>
<div>
<h3
style=
"color:#D97706;margin:0 0 8px;"
>
📋 الاستمارة لم تُملأ بعد
</h3>
<p
style=
"color:#92400E;margin:0;font-size:14px;"
>
استمارة رقم
<strong
style=
"font-size:18px;"
>
<?=
e
(
$member
->
form_number
)
?>
</strong>
— رسوم الاستمارة:
<strong>
<?=
money
(
$formFee
)
?>
</strong>
</p>
<p
style=
"color:#6B7280;margin:8px 0 0;font-size:13px;"
>
يجب دفع رسوم الاستمارة ثم ملء باقي البيانات
</p>
</div>
<a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
/fill-form"
class=
"btn btn-primary"
style=
"padding:15px 30px;font-size:16px;background:#D97706;border-color:#D97706;"
>
📝 ملء الاستمارة
</a>
</div>
</div>
<?php
endif
;
?>
<!-- Member Header Card -->
<div
class=
"card"
style=
"margin-bottom:20px;overflow:visible;"
>
<div
style=
"padding:25px;"
>
<div
style=
"display:flex;justify-content:space-between;align-items:start;"
>
<div>
<div>
<h2
style=
"margin:0;color:#1A1A2E;"
>
<?=
e
(
$member
->
full_name_ar
)
?>
</h2>
<h2
style=
"margin:0 0 5px;color:#1A1A2E;font-size:22px;"
>
<?=
e
(
$member
->
full_name_ar
)
?>
</h2>
<?php
if
(
$member
->
full_name_en
)
:
?>
<div
style=
"color:#6B7280;margin-top:4px;"
>
<?=
e
(
$member
->
full_name_en
)
?>
</div>
<?php
endif
;
?>
<?php
if
(
$member
->
full_name_en
)
:
?>
<div
style=
"margin-top:8px;display:flex;gap:15px;font-size:13px;color:#6B7280;"
>
<div
style=
"color:#6B7280;font-size:14px;margin-bottom:8px;"
>
<?=
e
(
$member
->
full_name_en
)
?>
</div>
<span>
رقم العضوية:
<strong
style=
"color:#0D7377;"
>
<?=
e
(
$member
->
membership_number
?:
'لم يُحدد بعد'
)
?>
</strong></span>
<?php
endif
;
?>
<span>
الفرع:
<strong>
<?=
e
(
$member
->
getBranchName
())
?>
</strong></span>
<div
style=
"display:flex;gap:15px;flex-wrap:wrap;font-size:13px;color:#6B7280;margin-top:10px;"
>
<span>
النوع:
<strong>
<?=
e
(
$member
->
getGenderLabel
())
?>
</strong></span>
<?php
if
(
$member
->
membership_number
)
:
?>
<span>
🪪 رقم العضوية:
<strong
style=
"color:#0D7377;font-size:16px;"
>
<?=
e
(
$member
->
membership_number
)
?>
</strong></span>
<?php
endif
;
?>
<span>
📋 استمارة:
<strong
style=
"color:#D97706;"
>
<?=
e
(
$member
->
form_number
??
'—'
)
?>
</strong></span>
<span>
🏢
<?=
e
(
$branchName
)
?>
</span>
<span>
<?=
$member
->
gender
===
'male'
?
'👨'
:
'👩'
?>
<?=
$member
->
getGenderLabel
()
?>
</span>
<?php
if
(
$member
->
age_years
)
:
?>
<span>
🎂
<?=
(
int
)
$member
->
age_years
?>
سنة
</span>
<?php
endif
;
?>
</div>
</div>
</div>
</div>
<div
style=
"text-align:left;"
>
<div
style=
"text-align:left;"
>
<span
style=
"display:inline-block;padding:6px 16px;border-radius:20px;font-weight:700;font-size:14px;color:#fff;background:
<?=
$member
->
getStatusColor
()
?>
;"
>
<span
style=
"display:inline-block;padding:6px 16px;border-radius:20px;font-weight:700;font-size:14px;color:#fff;background:
<?=
$statusColor
?>
;"
>
<?=
e
(
$member
->
getStatusLabel
()
)
?>
<?=
e
(
$statusLabel
)
?>
</span>
</span>
<div
style=
"margin-top:10px;font-size:12px;color:#9CA3AF;"
>
تاريخ التسجيل:
<?=
e
(
substr
(
$member
->
created_at
,
0
,
10
))
?>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Tabs -->
<!-- Info Grid -->
<div
style=
"display:flex;gap:0;margin-bottom:20px;border-bottom:2px solid #E5E7EB;"
>
<div
style=
"display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:20px;"
>
<?php
$tabs
=
[
'personal'
=>
'البيانات الشخصية'
,
'family'
=>
'الأسرة'
,
'financial'
=>
'المالية'
,
'documents'
=>
'المستندات'
,
'activity'
=>
'النشاط'
,
];
?>
<?php
foreach
(
$tabs
as
$key
=>
$label
)
:
?>
<button
class=
"tab-btn"
data-tab=
"
<?=
$key
?>
"
style=
"padding:10px 20px;border:none;background:transparent;cursor:pointer;font-size:14px;font-weight:600;color:#6B7280;border-bottom:3px solid transparent;
<?=
$key
===
'personal'
?
'color:#0D7377;border-bottom-color:#0D7377;'
:
''
?>
"
onclick=
"switchTab('
<?=
$key
?>
')"
>
<?=
e
(
$label
)
?>
</button>
<?php
endforeach
;
?>
</div>
<!-- Tab: Personal -->
<!-- Personal Info -->
<div
id=
"tab-personal"
class=
"tab-content"
>
<div
class=
"card"
>
<div
style=
"display:grid;grid-template-columns:1fr 1fr;gap:20px;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
>
<div
class=
"card"
style=
"padding:20px;"
>
<h3
style=
"margin:0;color:#0D7377;font-size:15px;"
>
👤 البيانات الشخصية
</h3>
<h4
style=
"color:#0D7377;margin-bottom:15px;"
>
البيانات الشخصية
</h4>
</div>
<table
style=
"width:100%;font-size:14px;"
>
<div
style=
"padding:15px 20px;"
>
<tr><td
style=
"padding:6px 0;color:#6B7280;width:40%;"
>
الرقم القومي
</td><td
style=
"padding:6px 0;direction:ltr;text-align:right;font-weight:600;"
>
<?=
e
(
$member
->
national_id
?:
'—'
)
?>
</td></tr>
<table
style=
"width:100%;font-size:13px;"
>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
جواز السفر
</td><td
style=
"padding:6px 0;"
>
<?=
e
(
$member
->
passport_number
?:
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:5px 0;color:#6B7280;width:40%;"
>
الرقم القومي
</td><td
style=
"padding:5px 0;direction:ltr;text-align:right;font-weight:600;"
>
<?=
e
(
$member
->
national_id
??
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
تاريخ الميلاد
</td><td
style=
"padding:6px 0;"
>
<?=
e
(
$member
->
date_of_birth
)
?>
</td></tr>
<tr><td
style=
"padding:5px 0;color:#6B7280;"
>
تاريخ الميلاد
</td><td
style=
"padding:5px 0;"
>
<?=
e
(
$member
->
date_of_birth
??
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
السن
</td><td
style=
"padding:6px 0;"
>
<?=
(
int
)
$member
->
age_years
?>
سنة
<?=
$member
->
age_months
?
'و '
.
(
int
)
$member
->
age_months
.
' شهر'
:
''
?>
</td></tr>
<tr><td
style=
"padding:5px 0;color:#6B7280;"
>
المحمول
</td><td
style=
"padding:5px 0;direction:ltr;text-align:right;"
>
<?=
e
(
$member
->
phone_mobile
??
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
الجنسية
</td><td
style=
"padding:6px 0;"
>
<?=
e
(
$member
->
nationality
?:
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:5px 0;color:#6B7280;"
>
الجنسية
</td><td
style=
"padding:5px 0;"
>
<?=
e
(
$member
->
nationality
??
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
الديانة
</td><td
style=
"padding:6px 0;"
>
<?=
e
(
$member
->
religion
?:
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:5px 0;color:#6B7280;"
>
المؤهل
</td><td
style=
"padding:5px 0;"
>
<?=
e
(
$qualificationName
)
?>
</td></tr>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
المؤهل
</td><td
style=
"padding:6px 0;"
>
<?=
e
(
$member
->
getQualificationName
())
?>
</td></tr>
<tr><td
style=
"padding:5px 0;color:#6B7280;"
>
الحالة الاجتماعية
</td><td
style=
"padding:5px 0;"
>
<?=
e
(
$member
->
marital_status
??
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
الحالة الاجتماعية
</td><td
style=
"padding:6px 0;"
>
<?=
e
(
$member
->
marital_status
?:
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:5px 0;color:#6B7280;"
>
الديانة
</td><td
style=
"padding:5px 0;"
>
<?=
e
(
$member
->
religion
??
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
قيمة العضوية
</td><td
style=
"padding:6px 0;font-weight:700;color:#0D7377;"
>
<?=
$member
->
membership_value
?
money
(
$member
->
membership_value
)
:
'—'
?>
</td></tr>
<?php
if
(
$member
->
email
)
:
?>
</table>
<tr><td
style=
"padding:5px 0;color:#6B7280;"
>
البريد
</td><td
style=
"padding:5px 0;direction:ltr;text-align:right;"
>
<?=
e
(
$member
->
email
)
?>
</td></tr>
</div>
<?php
endif
;
?>
<div
class=
"card"
style=
"padding:20px;"
>
<h4
style=
"color:#0D7377;margin-bottom:15px;"
>
بيانات الاتصال
</h4>
<table
style=
"width:100%;font-size:14px;"
>
<tr><td
style=
"padding:6px 0;color:#6B7280;width:40%;"
>
المحمول
</td><td
style=
"padding:6px 0;direction:ltr;text-align:right;"
>
<?=
e
(
$member
->
phone_mobile
)
?>
</td></tr>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
المنزل
</td><td
style=
"padding:6px 0;direction:ltr;text-align:right;"
>
<?=
e
(
$member
->
phone_home
?:
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
البريد
</td><td
style=
"padding:6px 0;direction:ltr;text-align:right;"
>
<?=
e
(
$member
->
email
?:
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
طوارئ
</td><td
style=
"padding:6px 0;"
>
<?=
e
(
$member
->
emergency_name
?:
'—'
)
?>
—
<?=
e
(
$member
->
emergency_phone
?:
''
)
?>
</td></tr>
</table>
<h4
style=
"color:#0D7377;margin:20px 0 15px;"
>
العمل
</h4>
<table
style=
"width:100%;font-size:14px;"
>
<tr><td
style=
"padding:6px 0;color:#6B7280;width:40%;"
>
المهنة
</td><td
style=
"padding:6px 0;"
>
<?=
e
(
$member
->
occupation
?:
'—'
)
?>
</td></tr>
<tr><td
style=
"padding:6px 0;color:#6B7280;"
>
جهة العمل
</td><td
style=
"padding:6px 0;"
>
<?=
e
(
$member
->
business_address
?:
'—'
)
?>
</td></tr>
</table>
</table>
</div>
</div>
</div>
</div>
<!-- Notes -->
<!-- Financial Summary -->
<div
class=
"card"
style=
"margin-top:20px;padding:20px;"
>
<div
class=
"card"
>
<h4
style=
"color:#0D7377;margin-bottom:15px;"
>
الملاحظات
</h4>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
>
<?php
if
(
!
empty
(
$notes
))
:
?>
<h3
style=
"margin:0;color:#0D7377;font-size:15px;"
>
💰 الملخص المالي
</h3>
<?php
foreach
(
$notes
as
$note
)
:
?>
<div
style=
"padding:10px 0;border-bottom:1px solid #F3F4F6;font-size:13px;"
>
<div
style=
"color:#1A1A2E;"
>
<?=
nl2br
(
e
(
$note
[
'note_text'
]))
?>
</div>
<div
style=
"color:#9CA3AF;font-size:11px;margin-top:4px;"
>
<?=
e
(
$note
[
'employee_name'
]
??
'النظام'
)
?>
—
<?=
e
(
$note
[
'created_at'
])
?>
</div>
</div>
</div>
<?php
endforeach
;
?>
<div
style=
"padding:15px 20px;"
>
<?php
else
:
?>
<div
style=
"display:grid;grid-template-columns:1fr 1fr;gap:15px;margin-bottom:15px;"
>
<p
style=
"color:#6B7280;"
>
لا توجد ملاحظات
</p>
<div
style=
"background:#F0FDF4;padding:15px;border-radius:8px;text-align:center;"
>
<div
style=
"font-size:22px;font-weight:700;color:#059669;"
>
<?=
money
(
$member
->
membership_value
??
'0'
)
?>
</div>
<div
style=
"color:#6B7280;font-size:12px;"
>
قيمة العضوية
</div>
</div>
<div
style=
"background:#EFF6FF;padding:15px;border-radius:8px;text-align:center;"
>
<div
style=
"font-size:22px;font-weight:700;color:#0284C7;"
>
<?=
money
(
$totalPaid
)
?>
</div>
<div
style=
"color:#6B7280;font-size:12px;"
>
إجمالي المدفوع
</div>
</div>
</div>
<a
href=
"/payments/member/
<?=
(
int
)
$member
->
id
?>
"
class=
"btn btn-outline"
style=
"width:100%;text-align:center;"
>
عرض كل المدفوعات
</a>
</div>
</div>
</div>
<!-- Quick Actions -->
<div
class=
"card"
style=
"margin-bottom:20px;padding:15px;"
>
<div
style=
"display:flex;gap:10px;flex-wrap:wrap;"
>
<?php
if
(
!
$formFilled
&&
$member
->
status
===
'potential'
)
:
?>
<a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
/fill-form"
class=
"btn btn-primary"
>
📝 ملء الاستمارة
</a>
<?php
endif
;
?>
<a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
/spouses/create"
class=
"btn btn-outline"
>
💍 إضافة زوج/ة
</a>
<a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
/children/create"
class=
"btn btn-outline"
>
👶 إضافة ابن/ة
</a>
<a
href=
"/payments/process/
<?=
(
int
)
$member
->
id
?>
"
class=
"btn btn-outline"
>
💰 تسجيل دفعة
</a>
<a
href=
"/documents/upload/
<?=
(
int
)
$member
->
id
?>
"
class=
"btn btn-outline"
>
📁 رفع مستندات
</a>
<a
href=
"/interviews/schedule/
<?=
(
int
)
$member
->
id
?>
"
class=
"btn btn-outline"
>
🗓️ تحديد مقابلة
</a>
<a
href=
"/installments/create/
<?=
(
int
)
$member
->
id
?>
"
class=
"btn btn-outline"
>
📅 خطة تقسيط
</a>
<?php
if
(
$member
->
status
===
'active'
)
:
?>
<a
href=
"/carnets/issue/
<?=
(
int
)
$member
->
id
?>
"
class=
"btn btn-outline"
>
🪪 إصدار كارنيه
</a>
<?php
endif
;
?>
<?php
endif
;
?>
</div>
</div>
</div>
</div>
<!-- Tab: Family -->
<!-- Family: Spouses -->
<div
id=
"tab-family"
class=
"tab-content"
style=
"display:none;"
>
<?php
if
(
!
empty
(
$spouses
))
:
?>
<div
class=
"card"
style=
"padding:20px;margin-bottom:20px;"
>
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<h4
style=
"color:#0D7377;margin-bottom:15px;"
>
الزوجات
</h4>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;display:flex;justify-content:space-between;align-items:center;"
>
<?php
if
(
!
empty
(
$spouses
))
:
?>
<h3
style=
"margin:0;color:#0D7377;font-size:15px;"
>
💍 الزوجات (
<?=
count
(
$spouses
)
?>
)
</h3>
<table
class=
"data-table"
><thead><tr><th>
#
</th><th>
الاسم
</th><th>
الرقم القومي
</th><th>
تاريخ الميلاد
</th><th>
السن
</th><th>
التصنيف
</th><th>
الحالة
</th></tr></thead><tbody>
<a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
/spouses/create"
class=
"btn btn-sm btn-outline"
>
+ إضافة
</a>
</div>
<div
class=
"table-responsive"
>
<table
class=
"data-table"
>
<thead><tr><th>
#
</th><th>
الاسم
</th><th>
الرقم القومي
</th><th>
تاريخ الميلاد
</th><th>
الحالة
</th><th>
الإجراءات
</th></tr></thead>
<tbody>
<?php
foreach
(
$spouses
as
$s
)
:
?>
<?php
foreach
(
$spouses
as
$s
)
:
?>
<tr><td>
<?=
(
int
)
$s
[
'spouse_order'
]
?>
</td><td>
<?=
e
(
$s
[
'full_name_ar'
])
?>
</td><td
style=
"direction:ltr;text-align:right;"
>
<?=
e
(
$s
[
'national_id'
]
??
'—'
)
?>
</td><td>
<?=
e
(
$s
[
'date_of_birth'
])
?>
</td><td>
<?=
(
int
)
(
$s
[
'age_years'
]
??
0
)
?>
</td><td>
<?=
e
(
$s
[
'classification'
]
??
'—'
)
?>
</td><td>
<?=
e
(
$s
[
'status'
])
?>
</td></tr>
<tr>
<td>
<?=
(
int
)
$s
[
'spouse_order'
]
?>
</td>
<td
style=
"font-weight:600;"
>
<?=
e
(
$s
[
'full_name_ar'
])
?>
</td>
<td
style=
"direction:ltr;text-align:right;font-size:12px;"
>
<?=
e
(
$s
[
'national_id'
]
??
'—'
)
?>
</td>
<td
style=
"font-size:13px;"
>
<?=
e
(
$s
[
'date_of_birth'
])
?>
</td>
<td><span
style=
"color:
<?=
$s
[
'status'
]
===
'active'
?
'#059669'
:
'#DC2626'
?>
;font-weight:600;"
>
●
<?=
$s
[
'status'
]
===
'active'
?
'نشط'
:
$s
[
'status'
]
?>
</span></td>
<td><a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
/spouses/
<?=
(
int
)
$s
[
'id'
]
?>
"
class=
"btn btn-sm btn-outline"
>
عرض
</a></td>
</tr>
<?php
endforeach
;
?>
<?php
endforeach
;
?>
</tbody></table
>
</tbody
>
<
?php
else
:
?>
<p
style=
"color:#6B7280;"
>
لا توجد زوجات مسجلة
</p>
<?php
endif
;
?
>
<
/table
>
</div>
</div>
<div
class=
"card"
style=
"padding:20px;margin-bottom:20px;"
>
</div>
<h4
style=
"color:#0D7377;margin-bottom:15px;"
>
الأبناء
</h4>
<?php
endif
;
?>
<?php
if
(
!
empty
(
$children
))
:
?>
<table
class=
"data-table"
><thead><tr><th>
#
</th><th>
الاسم
</th><th>
النوع
</th><th>
تاريخ الميلاد
</th><th>
السن
</th><th>
التصنيف
</th><th>
الحالة
</th></tr></thead><tbody>
<!-- Family: Children -->
<?php
if
(
!
empty
(
$children
))
:
?>
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;display:flex;justify-content:space-between;align-items:center;"
>
<h3
style=
"margin:0;color:#0D7377;font-size:15px;"
>
👨👩👧👦 الأبناء (
<?=
count
(
$children
)
?>
)
</h3>
<a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
/children/create"
class=
"btn btn-sm btn-outline"
>
+ إضافة
</a>
</div>
<div
class=
"table-responsive"
>
<table
class=
"data-table"
>
<thead><tr><th>
#
</th><th>
الاسم
</th><th>
النوع
</th><th>
تاريخ الميلاد
</th><th>
السن
</th><th>
التصنيف
</th><th>
الحالة
</th><th>
الإجراءات
</th></tr></thead>
<tbody>
<?php
foreach
(
$children
as
$c
)
:
?>
<?php
foreach
(
$children
as
$c
)
:
?>
<tr><td>
<?=
(
int
)
$c
[
'child_order'
]
?>
</td><td>
<?=
e
(
$c
[
'full_name_ar'
])
?>
</td><td>
<?=
$c
[
'gender'
]
===
'male'
?
'ذكر'
:
'أنثى'
?>
</td><td>
<?=
e
(
$c
[
'date_of_birth'
])
?>
</td><td>
<?=
(
int
)
(
$c
[
'age_years'
]
??
0
)
?>
</td><td>
<?=
e
(
$c
[
'classification'
]
??
'—'
)
?>
</td><td>
<?=
e
(
$c
[
'status'
])
?>
</td></tr>
<tr>
<?php
endforeach
;
?>
<td>
<?=
(
int
)
$c
[
'child_order'
]
?>
</td>
</tbody></table>
<td
style=
"font-weight:600;"
>
<?=
e
(
$c
[
'full_name_ar'
])
?>
</td>
<?php
else
:
?>
<p
style=
"color:#6B7280;"
>
لا يوجد أبناء مسجلون
</p>
<?php
endif
;
?>
<td>
<?=
$c
[
'gender'
]
===
'male'
?
'ذكر'
:
'أنثى'
?>
</td>
</div>
<td
style=
"font-size:13px;"
>
<?=
e
(
$c
[
'date_of_birth'
])
?>
</td>
<div
class=
"card"
style=
"padding:20px;"
>
<td>
<?=
(
int
)
(
$c
[
'age_years'
]
??
0
)
?>
</td>
<h4
style=
"color:#0D7377;margin-bottom:15px;"
>
الأعضاء المؤقتون
</h4>
<td
style=
"font-size:12px;"
>
<?=
e
(
$c
[
'classification'
]
??
'—'
)
?>
</td>
<?php
if
(
!
empty
(
$temporary
))
:
?>
<td><span
style=
"color:
<?=
$c
[
'status'
]
===
'active'
?
'#059669'
:
'#DC2626'
?>
;font-weight:600;"
>
●
<?=
$c
[
'status'
]
===
'active'
?
'نشط'
:
$c
[
'status'
]
?>
</span></td>
<table
class=
"data-table"
><thead><tr><th>
الاسم
</th><th>
الفئة
</th><th>
السن
</th><th>
الحالة
</th></tr></thead><tbody>
<td><a
href=
"/members/
<?=
(
int
)
$member
->
id
?>
/children/
<?=
(
int
)
$c
[
'id'
]
?>
"
class=
"btn btn-sm btn-outline"
>
عرض
</a></td>
<?php
foreach
(
$temporary
as
$t
)
:
?>
</tr>
<tr><td>
<?=
e
(
$t
[
'full_name_ar'
])
?>
</td><td>
<?=
e
(
$t
[
'category'
])
?>
</td><td>
<?=
(
int
)
(
$t
[
'age_years'
]
??
0
)
?>
</td><td>
<?=
e
(
$t
[
'status'
])
?>
</td></tr>
<?php
endforeach
;
?>
<?php
endforeach
;
?>
</tbody></table
>
</tbody
>
<
?php
else
:
?>
<p
style=
"color:#6B7280;"
>
لا يوجد أعضاء مؤقتون
</p>
<?php
endif
;
?
>
<
/table
>
</div>
</div>
</div>
</div>
<?php
endif
;
?>
<!-- Tab: Financial -->
<!-- Recent Payments -->
<div
id=
"tab-financial"
class=
"tab-content"
style=
"display:none;"
>
<?php
if
(
!
empty
(
$payments
))
:
?>
<div
class=
"card"
style=
"padding:40px;text-align:center;color:#6B7280;"
>
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<p>
البيانات المالية ستكون متاحة بعد تفعيل وحدة المدفوعات
</p>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
>
<h3
style=
"margin:0;color:#0D7377;font-size:15px;"
>
💳 آخر المدفوعات
</h3>
</div>
<div
class=
"table-responsive"
>
<table
class=
"data-table"
>
<thead><tr><th>
التاريخ
</th><th>
النوع
</th><th>
المبلغ
</th><th>
الإيصال
</th></tr></thead>
<tbody>
<?php
foreach
(
$payments
as
$p
)
:
?>
<tr>
<td
style=
"font-size:13px;"
>
<?=
e
(
$p
[
'payment_date'
])
?>
</td>
<td
style=
"font-size:13px;"
>
<?=
e
(
\App\Modules\Payments\Models\Payment
::
getPaymentTypeLabel
(
$p
[
'payment_type'
]))
?>
</td>
<td
style=
"font-weight:600;"
>
<?=
money
(
$p
[
'amount'
])
?>
</td>
<td
style=
"font-size:12px;direction:ltr;text-align:right;"
>
<?=
e
(
$p
[
'receipt_number'
]
??
'—'
)
?>
</td>
</tr>
<?php
endforeach
;
?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?php
endif
;
?>
<!-- Tab: Documents -->
<!-- Status Change -->
<div
id=
"tab-documents"
class=
"tab-content"
style=
"display:none;"
>
<div
class=
"card"
style=
"margin-bottom:20px;"
>
<div
class=
"card"
style=
"padding:40px;text-align:center;color:#6B7280;"
>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
>
<p>
المستندات ستكون متاحة بعد تفعيل وحدة إدارة المستندات
</p>
<h3
style=
"margin:0;color:#0D7377;font-size:15px;"
>
🔄 تغيير الحالة
</h3>
</div>
<div
style=
"padding:15px 20px;"
>
<form
method=
"POST"
action=
"/members/
<?=
(
int
)
$member
->
id
?>
/status"
style=
"display:flex;gap:10px;align-items:center;"
>
<?=
csrf_field
()
?>
<select
name=
"status"
class=
"form-select"
style=
"width:auto;"
>
<?php
foreach
(
\App\Modules\Members\Models\Member
::
getStatusOptions
()
as
$val
=>
$label
)
:
?>
<option
value=
"
<?=
e
(
$val
)
?>
"
<?=
$member
->
status
===
$val
?
'selected'
:
''
?>
>
<?=
e
(
$label
)
?>
</option>
<?php
endforeach
;
?>
</select>
<button
type=
"submit"
class=
"btn btn-outline"
onclick=
"return confirm('تغيير حالة العضو؟')"
>
تحديث الحالة
</button>
</form>
</div>
</div>
</div>
</div>
<!-- Tab: Activity -->
<!-- Notes -->
<div
id=
"tab-activity"
class=
"tab-content"
style=
"display:none;"
>
<?php
if
(
!
empty
(
$notes
))
:
?>
<div
class=
"card"
style=
"padding:20px;"
>
<div
class=
"card"
>
<h4
style=
"color:#0D7377;margin-bottom:15px;"
>
سجل النشاط
</h4>
<div
style=
"padding:15px 20px;border-bottom:1px solid #E5E7EB;"
>
<?php
if
(
!
empty
(
$auditHistory
))
:
?>
<h3
style=
"margin:0;color:#0D7377;font-size:15px;"
>
📝 الملاحظات
</h3>
<?php
foreach
(
$auditHistory
as
$i
=>
$entry
)
:
?>
<div
style=
"display:flex;gap:15px;padding:12px 0;
<?=
$i
<
count
(
$auditHistory
)
-
1
?
'border-bottom:1px solid #F3F4F6;'
:
''
?>
"
>
<div
style=
"flex-shrink:0;width:10px;height:10px;border-radius:50%;background:#0D7377;margin-top:5px;"
></div>
<div
style=
"flex:1;"
>
<div
style=
"display:flex;justify-content:space-between;"
><strong
style=
"font-size:13px;"
>
<?=
e
(
$entry
[
'action'
])
?>
</strong><span
style=
"font-size:11px;color:#9CA3AF;"
>
<?=
e
(
$entry
[
'created_at'
])
?>
</span></div>
<div
style=
"font-size:12px;color:#6B7280;"
>
<?=
e
(
$entry
[
'employee_name'
]
??
'النظام'
)
?><?php
if
(
$entry
[
'notes'
])
:
?>
—
<?=
e
(
mb_substr
(
$entry
[
'notes'
],
0
,
100
))
?><?php
endif
;
?>
</div>
</div>
</div>
<div
style=
"padding:15px 20px;"
>
<?php
foreach
(
$notes
as
$note
)
:
?>
<div
style=
"padding:10px 0;border-bottom:1px solid #F3F4F6;"
>
<div
style=
"font-size:13px;"
>
<?=
nl2br
(
e
(
$note
[
'note_text'
]))
?>
</div>
<div
style=
"font-size:11px;color:#9CA3AF;margin-top:5px;"
>
<?=
e
(
$note
[
'employee_name'
]
??
'النظام'
)
?>
—
<?=
e
(
$note
[
'created_at'
])
?>
</div>
</div>
</div>
<?php
endforeach
;
?>
<?php
endforeach
;
?>
<?php
else
:
?>
<p
style=
"color:#6B7280;"
>
لا يوجد سجل نشاط
</p>
<?php
endif
;
?>
<div
style=
"margin-top:15px;"
><a
href=
"/audit/entity/members/
<?=
(
int
)
$member
->
id
?>
"
class=
"btn btn-sm btn-outline"
>
عرض السجل الكامل
</a></div>
</div>
</div>
</div>
</div>
<?php
endif
;
?>
<?php
$__template
->
endSection
();
?>
<?php
$__template
->
endSection
();
?>
\ No newline at end of file
<?php
$__template
->
section
(
'scripts'
);
?>
<script>
function
switchTab
(
tabName
)
{
document
.
querySelectorAll
(
'.tab-content'
).
forEach
(
function
(
el
)
{
el
.
style
.
display
=
'none'
;
});
document
.
querySelectorAll
(
'.tab-btn'
).
forEach
(
function
(
el
)
{
el
.
style
.
color
=
'#6B7280'
;
el
.
style
.
borderBottomColor
=
'transparent'
;
});
var
tab
=
document
.
getElementById
(
'tab-'
+
tabName
);
var
btn
=
document
.
querySelector
(
'[data-tab="'
+
tabName
+
'"]'
);
if
(
tab
)
tab
.
style
.
display
=
'block'
;
if
(
btn
)
{
btn
.
style
.
color
=
'#0D7377'
;
btn
.
style
.
borderBottomColor
=
'#0D7377'
;
}
}
</script>
<?php
$__template
->
endSection
();
?>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment