Commit b143aca7 authored by Mahmoud Aglan's avatar Mahmoud Aglan

feat(members): show separated/deceased children greyed out on parent profile

Children who were separated (فصل) or deceased now remain visible on the
parent member's profile instead of disappearing. They appear greyed out
with status labels (مفصول / متوفي) and for separated children, a link
to their new membership profile with the membership number.

The family tree count distinguishes active vs inactive children.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent ccd9b70a
......@@ -201,15 +201,19 @@ class MemberController extends Controller
}
try {
$children = $db->select(
"SELECT c.*, TIMESTAMPDIFF(YEAR, c.date_of_birth, CURDATE()) as age_years, TIMESTAMPDIFF(MONTH, c.date_of_birth, CURDATE()) % 12 as age_months, pr.created_at AS due_date, p.payment_date
"SELECT c.*, TIMESTAMPDIFF(YEAR, c.date_of_birth, CURDATE()) as age_years, TIMESTAMPDIFF(MONTH, c.date_of_birth, CURDATE()) % 12 as age_months,
pr.created_at AS due_date, p.payment_date,
tr.target_member_id as separated_member_id, tm.membership_number as separated_membership_number
FROM children c
LEFT JOIN payment_requests pr ON pr.related_entity_type = 'children' AND pr.related_entity_id = c.id AND pr.payment_type = 'addition_fee' AND pr.is_voided = 0
LEFT JOIN payments p ON p.id = c.activated_by_payment_id AND p.is_voided = 0
WHERE c.member_id = ? AND c.is_archived = 0
ORDER BY c.child_order", [(int) $id]
LEFT JOIN transfer_requests tr ON tr.child_id = c.id AND tr.status = 'completed'
LEFT JOIN members tm ON tm.id = tr.target_member_id
WHERE c.member_id = ?
ORDER BY c.is_archived ASC, c.child_order", [(int) $id]
);
} catch (\Throwable $e) {
try { $children = $db->select("SELECT *, TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) as age_years, TIMESTAMPDIFF(MONTH, date_of_birth, CURDATE()) % 12 as age_months FROM children WHERE member_id = ? AND is_archived = 0 ORDER BY child_order", [(int) $id]); } catch (\Throwable $e2) {}
try { $children = $db->select("SELECT *, TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) as age_years, TIMESTAMPDIFF(MONTH, date_of_birth, CURDATE()) % 12 as age_months FROM children WHERE member_id = ? ORDER BY is_archived ASC, child_order", [(int) $id]); } catch (\Throwable $e2) {}
}
try {
$temporaries = $db->select(
......
......@@ -966,7 +966,8 @@ $hasIncomplete = !empty(array_filter($missingSteps, fn($s) => !$s['done']));
<!-- FAMILY TREE — unified display of all dependants -->
<!-- ═══════════════════════════════════════════════ -->
<?php
$totalDependants = count($spouses) + count($children) + count($temporaries ?? []);
$activeChildrenCount = count(array_filter($children, fn($c) => empty($c['is_archived']) && !in_array($c['status'] ?? '', ['separated', 'deceased'])));
$totalDependants = count($spouses) + $activeChildrenCount + count($temporaries ?? []);
$categoryLabels = [
'parent' => 'والد/ة', 'special_needs' => 'ذوي احتياجات خاصة', 'unmarried_daughter' => 'ابنة غير متزوجة',
'sister' => 'شقيقة', 'stepchild' => 'ابن/ة زوج', 'orphan' => 'يتيم', 'disabled_sibling' => 'شقيق معاق', 'nanny' => 'مربية',
......@@ -1062,11 +1063,16 @@ $childClassLabels = ['included' => 'تابع مشمول', 'dependent_with_fee' =
<?php if (!empty($children)): ?>
<!-- Children -->
<div style="padding:15px 20px;border-bottom:1px solid #E5E7EB;">
<div style="font-size:12px;color:#0D7377;font-weight:700;margin-bottom:10px;text-transform:uppercase;">&#x1f476; الأبناء (<?= count($children) ?>)</div>
<?php
$activeChildren = array_filter($children, fn($c) => empty($c['is_archived']) && !in_array($c['status'] ?? '', ['separated', 'deceased']));
$inactiveChildren = array_filter($children, fn($c) => !empty($c['is_archived']) || in_array($c['status'] ?? '', ['separated', 'deceased']));
?>
<div style="font-size:12px;color:#0D7377;font-weight:700;margin-bottom:10px;text-transform:uppercase;">&#x1f476; الأبناء (<?= count($activeChildren) ?><?= !empty($inactiveChildren) ? ' <span style="color:#6B7280;font-weight:500;">+ ' . count($inactiveChildren) . ' سابق</span>' : '' ?>)</div>
<?php
$childrenOver25Male = array_filter($children, function($c) {
return ($c['gender'] ?? '') === 'male'
&& ($c['status'] ?? '') === 'active'
&& empty($c['is_archived'])
&& (int) ($c['age_years'] ?? 0) >= 25;
});
?>
......@@ -1101,10 +1107,18 @@ $childClassLabels = ['included' => 'تابع مشمول', 'dependent_with_fee' =
$cFee = $c['addition_fee'] ?? '0.00';
$cBreakdown = !empty($c['fee_breakdown_json']) ? json_decode($c['fee_breakdown_json'], true) : null;
if (!is_array($cBreakdown)) $cBreakdown = null;
$cIsSeparated = ($c['status'] ?? '') === 'separated';
$cIsDeceased = ($c['status'] ?? '') === 'deceased';
$cIsArchived = !empty($c['is_archived']) && !$cIsSeparated && !$cIsDeceased;
$cIsInactive = $cIsArchived || $cIsSeparated || $cIsDeceased;
?>
<tr <?= $cBreakdown ? 'style="cursor:pointer;" onclick="toggleBillDetail(\'child-' . $cIdx . '\')"' : '' ?>>
<tr <?= $cBreakdown && !$cIsInactive ? 'style="cursor:pointer;" onclick="toggleBillDetail(\'child-' . $cIdx . '\')"' : '' ?> <?= $cIsInactive ? 'style="opacity:0.5;background:#F9FAFB;"' : '' ?>>
<td><?= (int) $c['child_order'] ?></td>
<td style="font-weight:600;"><?= e($c['full_name_ar']) ?></td>
<td style="font-weight:600;"><?= e($c['full_name_ar']) ?>
<?php if ($cIsSeparated && !empty($c['separated_membership_number'])): ?>
<a href="/members/<?= (int) $c['separated_member_id'] ?>" style="display:block;font-size:11px;color:#0D7377;font-weight:600;margin-top:2px;">عضوية #<?= e($c['separated_membership_number']) ?></a>
<?php endif; ?>
</td>
<td><span style="background:#E0F2FE;color:#0369A1;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;"><?= $childClassLabels[$c['classification'] ?? 'included'] ?? 'تابع' ?></span></td>
<td><?= $c['gender'] === 'male' ? 'ذكر' : 'أنثى' ?></td>
<td><?php
......@@ -1119,22 +1133,38 @@ $childClassLabels = ['included' => 'تابع مشمول', 'dependent_with_fee' =
<td style="font-size:12px;"><?= !empty($c['due_date']) ? e(substr($c['due_date'], 0, 10)) : '<span style="color:#9CA3AF;">—</span>' ?></td>
<td style="font-size:12px;"><?= !empty($c['payment_date']) ? e($c['payment_date']) : '<span style="color:#9CA3AF;">—</span>' ?></td>
<td style="font-weight:600;"><?php
if ($cIsInactive) {
echo '<span style="color:#9CA3AF;">—</span>';
} else {
$fee = $c['addition_fee'] ?? '0.00';
echo bccomp($fee, '0', 2) <= 0 ? '<span style="color:#059669;">مشمول</span>' : money($fee);
if ($cBreakdown) echo ' <small style="color:#0D7377;font-size:10px;">&#x25BC;</small>';
}
?></td>
<td><?php
<td><?php if ($cIsDeceased): ?>
<span style="color:#DC2626;font-weight:600;font-size:12px;">&#x25cf; متوفي</span>
<?php elseif ($cIsSeparated): ?>
<span style="color:#6B7280;font-weight:600;font-size:12px;">&#x25cf; مفصول</span>
<?php elseif ($cIsArchived): ?>
<span style="color:#6B7280;font-weight:600;font-size:12px;">&#x25cf; محذوف</span>
<?php else:
$cKey = 'children:' . (int) $c['id'];
$cInQueue = isset($pendingAdditions[$cKey]);
$cInCombined = (($c['status'] ?? '') === 'pending_payment' && !empty($pendingMembership));
if ($cInQueue || $cInCombined): ?>
<span style="color:#D97706;font-weight:600;font-size:12px;">&#x1f4b3; في الخزينة</span>
<?php else: ?>
<span style="color:<?= match($c['status'] ?? '') { 'active' => '#059669', 'pending_payment' => '#D97706', 'frozen' => '#6B7280', 'separated' => '#6B7280', default => '#DC2626' } ?>;font-weight:600;font-size:12px;">&#x25cf; <?= match($c['status'] ?? '') { 'active' => 'نشط', 'pending_payment' => 'لم يتم السداد', 'frozen' => 'مجمد', 'separated' => 'منفصل', 'inactive' => 'غير نشط', default => $c['status'] ?? '—' } ?></span>
<?php endif; ?>
<span style="color:<?= match($c['status'] ?? '') { 'active' => '#059669', 'pending_payment' => '#D97706', 'frozen' => '#6B7280', default => '#DC2626' } ?>;font-weight:600;font-size:12px;">&#x25cf; <?= match($c['status'] ?? '') { 'active' => 'نشط', 'pending_payment' => 'لم يتم السداد', 'frozen' => 'مجمد', 'inactive' => 'غير نشط', default => $c['status'] ?? '—' } ?></span>
<?php endif;
endif; ?>
</td>
<td style="white-space:nowrap;">
<a href="/members/<?= (int) $member->id ?>/children/<?= (int) $c['id'] ?>" class="btn btn-sm btn-outline">عرض</a></td>
<?php if ($cIsSeparated && !empty($c['separated_member_id'])): ?>
<a href="/members/<?= (int) $c['separated_member_id'] ?>" class="btn btn-sm btn-outline" style="color:#0D7377;">الملف</a>
<?php elseif (!$cIsInactive): ?>
<a href="/members/<?= (int) $member->id ?>/children/<?= (int) $c['id'] ?>" class="btn btn-sm btn-outline">عرض</a>
<?php endif; ?>
</td>
</tr>
<?php if ($cBreakdown): ?>
<tr id="bill-detail-child-<?= $cIdx ?>" style="display:none;">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment