Commit 0233895c authored by Mahmoud Aglan's avatar Mahmoud Aglan

feat(members): redesign member profile header with photo + add avatars to family tree

Member header now has a gradient banner with a large circular photo (or
initials fallback). Spouses, children, and temporary members show inline
36px avatar circles with gender-colored gradients when no photo is uploaded.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 636c8e54
......@@ -99,50 +99,75 @@ $canEdit = can('member.edit') && (!$isLocked || ($isSuperAdmin ?? false));
<?php endif; ?>
<!-- Member Header -->
<div class="card" style="margin-bottom:20px;padding:25px;">
<div style="display:flex;justify-content:space-between;align-items:start;">
<div>
<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;font-size:14px;margin-bottom:8px;"><?= e($member->full_name_en) ?></div><?php endif; ?>
<div style="display:flex;gap:15px;flex-wrap:wrap;font-size:13px;color:#6B7280;margin-top:10px;">
<?php if ($member->membership_number): ?><span>🪪 عضوية: <strong style="color:#0D7377;font-size:16px;"><?= e($member->membership_number) ?></strong></span><?php endif; ?>
<?php if (!empty($divorceTransfer)): ?>
<span style="background:#FEF3C7;padding:2px 8px;border-radius:10px;font-size:11px;">محوّل من عضوية: <a href="/members/<?= (int) $divorceTransfer['original_member_id'] ?>" style="color:#D97706;font-weight:700;"><?= e($divorceTransfer['original_membership_number']) ?></a> (<?= e($divorceTransfer['original_member_name'] ?? '') ?>)</span>
<?php endif; ?>
<?php if (!empty($member->transferred_from_death_id)): ?>
<span style="background:#DBEAFE;padding:2px 8px;border-radius:10px;font-size:11px;">أُنشئت من <a href="/death/<?= (int) $member->transferred_from_death_id ?>" style="color:#2563EB;font-weight:700;">حالة وفاة #<?= (int) $member->transferred_from_death_id ?></a><?php if (!empty($member->deceased_member_name)): ?> (<?= e($member->deceased_member_name) ?>)<?php endif; ?></span>
<?php if (!empty($deathTransfer['deceased_member_id'])): ?>
<a href="/members/archive/<?= (int) $deathTransfer['deceased_member_id'] ?>" style="background:#FEF3C7;padding:2px 8px;border-radius:10px;font-size:11px;color:#92400E;font-weight:600;text-decoration:none;">&#x1f4e6; عرض العضوية الأصلية (المؤرشفة)</a>
<?php endif; ?>
<?php endif; ?>
<?php if (!empty($waiverTransfer)): ?>
<span style="background:#F3E8FF;padding:2px 8px;border-radius:10px;font-size:11px;">تنازل من: <a href="/waivers/<?= (int) $waiverTransfer['id'] ?>" style="color:#7C3AED;font-weight:700;"><?= e($waiverTransfer['source_member_name'] ?? $member->waived_from_member_name ?? '—') ?></a></span>
<?php if (!empty($waiverTransfer['source_member_id_ref'])): ?>
<a href="/members/archive/<?= (int) $waiverTransfer['source_member_id_ref'] ?>" style="background:#FEF3C7;padding:2px 8px;border-radius:10px;font-size:11px;color:#92400E;font-weight:600;text-decoration:none;">&#x1f4e6; عرض العضوية المؤرشفة</a>
<?php endif; ?>
<?php endif; ?>
<?php if (!empty($member->ownership_transfer_date)): ?>
<span style="background:#ECFDF5;padding:2px 8px;border-radius:10px;font-size:11px;">تاريخ انتقال الملكية: <strong style="color:#059669;"><?= arabic_date($member->ownership_transfer_date) ?></strong></span>
<?php
$_memberHasPhoto = !empty($member->photo_path);
$_memberInitials = mb_substr($member->full_name_ar, 0, 2);
?>
<div class="card" style="margin-bottom:20px;padding:0;overflow:hidden;">
<div style="background:linear-gradient(135deg, #0D7377 0%, #14919B 50%, #0AA6B7 100%);padding:20px 25px 60px;position:relative;">
<div style="display:flex;justify-content:space-between;align-items:center;">
<div style="display:flex;align-items:center;gap:12px;">
<span style="display:inline-block;padding:6px 16px;border-radius:20px;font-weight:700;font-size:14px;color:#fff;background:<?= $statusColor ?>;box-shadow:0 2px 8px rgba(0,0,0,0.2);"><?= e($statusLabel) ?></span>
<?php if ($member->status === 'active'): ?>
<?php if (!empty($overdueSubscriptions)): ?>
<span style="display:inline-block;padding:4px 12px;border-radius:12px;font-size:12px;font-weight:600;background:rgba(220,38,38,0.15);color:#FCA5A5;border:1px solid rgba(220,38,38,0.3);">⚠️ اشتراكات متأخرة</span>
<?php elseif (!empty($subscriptionStatus) && $subscriptionStatus['status'] === 'paid'): ?>
<span style="display:inline-block;padding:4px 12px;border-radius:12px;font-size:12px;font-weight:600;background:rgba(5,150,105,0.15);color:#6EE7B7;border:1px solid rgba(5,150,105,0.3);">✓ العضوية سارية</span>
<?php else: ?>
<span style="display:inline-block;padding:4px 12px;border-radius:12px;font-size:12px;font-weight:600;background:rgba(217,119,6,0.15);color:#FCD34D;border:1px solid rgba(217,119,6,0.3);">⏳ في انتظار التجديد</span>
<?php endif; ?>
<?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 style="font-size:12px;color:rgba(255,255,255,0.7);">تاريخ: <?= e(substr($member->membership_origin_date ?? $member->activated_at ?? $member->created_at, 0, 10)) ?></div>
</div>
<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:<?= $statusColor ?>;"><?= e($statusLabel) ?></span>
<?php if ($member->status === 'active'): ?>
<?php if (!empty($overdueSubscriptions)): ?>
<div style="margin-top:8px;"><span style="display:inline-block;padding:4px 12px;border-radius:12px;font-size:12px;font-weight:600;background:#FEF2F2;color:#DC2626;border:1px solid #FECACA;">⚠️ اشتراكات متأخرة</span></div>
<?php elseif (!empty($subscriptionStatus) && $subscriptionStatus['status'] === 'paid'): ?>
<div style="margin-top:8px;"><span style="display:inline-block;padding:4px 12px;border-radius:12px;font-size:12px;font-weight:600;background:#ECFDF5;color:#059669;border:1px solid #A7F3D0;">✓ العضوية سارية</span></div>
</div>
<div style="padding:0 25px 25px;margin-top:-45px;position:relative;">
<div style="display:flex;align-items:end;gap:20px;">
<!-- Member Photo -->
<div style="width:100px;height:100px;border-radius:50%;overflow:hidden;border:4px solid #fff;box-shadow:0 4px 20px rgba(0,0,0,0.15);flex-shrink:0;background:<?= $_memberHasPhoto ? '#F3F4F6' : 'linear-gradient(135deg, #667EEA, #764BA2)' ?>;display:flex;align-items:center;justify-content:center;">
<?php if ($_memberHasPhoto): ?>
<img src="/<?= e($member->photo_path) ?>" alt="صورة العضو" style="width:100%;height:100%;object-fit:cover;">
<?php else: ?>
<div style="margin-top:8px;"><span style="display:inline-block;padding:4px 12px;border-radius:12px;font-size:12px;font-weight:600;background:#FEF9C3;color:#92400E;border:1px solid #FDE68A;">⏳ في انتظار التجديد</span></div>
<span style="font-size:32px;font-weight:700;color:#fff;letter-spacing:-1px;"><?= e($_memberInitials) ?></span>
<?php endif; ?>
</div>
<div style="flex:1;padding-bottom:5px;">
<h2 style="margin:0 0 2px;color:#1A1A2E;font-size:24px;font-weight:800;"><?= e($member->full_name_ar) ?></h2>
<?php if ($member->full_name_en): ?><div style="color:#6B7280;font-size:14px;margin-bottom:4px;"><?= e($member->full_name_en) ?></div><?php endif; ?>
<?php if (!$_memberHasPhoto): ?>
<span style="display:inline-block;background:#FEF2F2;color:#DC2626;padding:2px 10px;border-radius:4px;font-size:11px;font-weight:600;margin-bottom:4px;">⚠ لا توجد صورة — مطلوبة لإصدار الكارنيه</span>
<?php endif; ?>
</div>
</div>
<div style="display:flex;gap:12px;flex-wrap:wrap;font-size:13px;color:#6B7280;margin-top:14px;padding-top:14px;border-top:1px solid #E5E7EB;">
<?php if ($member->membership_number): ?><span style="background:#E6FFFA;padding:4px 10px;border-radius:6px;">🪪 عضوية: <strong style="color:#0D7377;font-size:15px;"><?= e($member->membership_number) ?></strong></span><?php endif; ?>
<span style="background:#FFF7ED;padding:4px 10px;border-radius:6px;">📋 استمارة: <strong style="color:#D97706;"><?= e($member->form_number ?? '—') ?></strong></span>
<span style="background:#F3F4F6;padding:4px 10px;border-radius:6px;">🏢 <?= e($branchName) ?></span>
<span style="background:#F3F4F6;padding:4px 10px;border-radius:6px;"><?= $member->gender === 'male' ? '👨' : '👩' ?> <?= $member->getGenderLabel() ?></span>
<?php if ($member->age_years): ?><span style="background:#F3F4F6;padding:4px 10px;border-radius:6px;">🎂 <?= (int) $member->age_years ?> سنة</span><?php endif; ?>
</div>
<?php if (!empty($divorceTransfer) || !empty($member->transferred_from_death_id) || !empty($waiverTransfer) || !empty($member->ownership_transfer_date)): ?>
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:10px;">
<?php if (!empty($divorceTransfer)): ?>
<span style="background:#FEF3C7;padding:3px 10px;border-radius:10px;font-size:11px;">محوّل من عضوية: <a href="/members/<?= (int) $divorceTransfer['original_member_id'] ?>" style="color:#D97706;font-weight:700;"><?= e($divorceTransfer['original_membership_number']) ?></a> (<?= e($divorceTransfer['original_member_name'] ?? '') ?>)</span>
<?php endif; ?>
<?php if (!empty($member->transferred_from_death_id)): ?>
<span style="background:#DBEAFE;padding:3px 10px;border-radius:10px;font-size:11px;">أُنشئت من <a href="/death/<?= (int) $member->transferred_from_death_id ?>" style="color:#2563EB;font-weight:700;">حالة وفاة #<?= (int) $member->transferred_from_death_id ?></a><?php if (!empty($member->deceased_member_name)): ?> (<?= e($member->deceased_member_name) ?>)<?php endif; ?></span>
<?php if (!empty($deathTransfer['deceased_member_id'])): ?>
<a href="/members/archive/<?= (int) $deathTransfer['deceased_member_id'] ?>" style="background:#FEF3C7;padding:3px 10px;border-radius:10px;font-size:11px;color:#92400E;font-weight:600;text-decoration:none;">&#x1f4e6; عرض العضوية الأصلية (المؤرشفة)</a>
<?php endif; ?>
<?php endif; ?>
<?php if (!empty($waiverTransfer)): ?>
<span style="background:#F3E8FF;padding:3px 10px;border-radius:10px;font-size:11px;">تنازل من: <a href="/waivers/<?= (int) $waiverTransfer['id'] ?>" style="color:#7C3AED;font-weight:700;"><?= e($waiverTransfer['source_member_name'] ?? $member->waived_from_member_name ?? '—') ?></a></span>
<?php if (!empty($waiverTransfer['source_member_id_ref'])): ?>
<a href="/members/archive/<?= (int) $waiverTransfer['source_member_id_ref'] ?>" style="background:#FEF3C7;padding:3px 10px;border-radius:10px;font-size:11px;color:#92400E;font-weight:600;text-decoration:none;">&#x1f4e6; عرض العضوية المؤرشفة</a>
<?php endif; ?>
<?php endif; ?>
<?php if (!empty($member->ownership_transfer_date)): ?>
<span style="background:#ECFDF5;padding:3px 10px;border-radius:10px;font-size:11px;">تاريخ انتقال الملكية: <strong style="color:#059669;"><?= arabic_date($member->ownership_transfer_date) ?></strong></span>
<?php endif; ?>
<div style="margin-top:10px;font-size:12px;color:#9CA3AF;">تاريخ: <?= e(substr($member->membership_origin_date ?? $member->activated_at ?? $member->created_at, 0, 10)) ?></div>
</div>
<?php endif; ?>
</div>
</div>
......@@ -1006,10 +1031,12 @@ $childClassLabels = ['included' => 'تابع مشمول', 'dependent_with_fee' =
$sHasBreakdown = !empty($s['fee_breakdown_json']);
$sBreakdown = $sHasBreakdown ? json_decode($s['fee_breakdown_json'], true) : null;
if (!is_array($sBreakdown)) $sBreakdown = null;
$_sHasPhoto = !empty($s['photo_path']);
$_sInitials = mb_substr($s['full_name_ar'], 0, 2);
?>
<tr <?= $sBreakdown ? 'style="cursor:pointer;" onclick="toggleBillDetail(\'spouse-' . $sIdx . '\')"' : '' ?>>
<td><?= (int) $s['spouse_order'] ?></td>
<td style="font-weight:600;"><?= e($s['full_name_ar']) ?></td>
<td style="font-weight:600;"><div style="display:flex;align-items:center;gap:8px;"><div style="width:36px;height:36px;border-radius:50%;overflow:hidden;flex-shrink:0;background:<?= $_sHasPhoto ? '#F3F4F6' : 'linear-gradient(135deg, #EC4899, #F472B6)' ?>;display:flex;align-items:center;justify-content:center;border:2px solid <?= $_sHasPhoto ? '#0D7377' : '#F9A8D4' ?>;box-shadow:0 1px 4px rgba(0,0,0,0.08);"><?php if ($_sHasPhoto): ?><img src="/<?= e($s['photo_path']) ?>" style="width:100%;height:100%;object-fit:cover;"><?php else: ?><span style="font-size:13px;font-weight:700;color:#fff;"><?= e($_sInitials) ?></span><?php endif; ?></div><span><?= e($s['full_name_ar']) ?></span></div></td>
<td><?php
$sClassification = $s['classification'] ?? 'working';
$sTypeLabel = match($sClassification) { 'dependent' => 'عضو تابع', 'working' => 'عضو عامل', default => 'عضو عامل' };
......@@ -1111,14 +1138,18 @@ $childClassLabels = ['included' => 'تابع مشمول', 'dependent_with_fee' =
$cIsDeceased = ($c['status'] ?? '') === 'deceased';
$cIsArchived = !empty($c['is_archived']) && !$cIsSeparated && !$cIsDeceased;
$cIsInactive = $cIsArchived || $cIsSeparated || $cIsDeceased;
$_cHasPhoto = !empty($c['photo_path']);
$_cInitials = mb_substr($c['full_name_ar'], 0, 2);
$_cGradient = ($c['gender'] === 'male') ? 'linear-gradient(135deg, #3B82F6, #60A5FA)' : 'linear-gradient(135deg, #EC4899, #F472B6)';
$_cBorder = ($c['gender'] === 'male') ? '#93C5FD' : '#F9A8D4';
?>
<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 style="font-weight:600;"><div style="display:flex;align-items:center;gap:8px;"><div style="width:36px;height:36px;border-radius:50%;overflow:hidden;flex-shrink:0;background:<?= $_cHasPhoto ? '#F3F4F6' : $_cGradient ?>;display:flex;align-items:center;justify-content:center;border:2px solid <?= $_cHasPhoto ? '#0D7377' : $_cBorder ?>;box-shadow:0 1px 4px rgba(0,0,0,0.08);"><?php if ($_cHasPhoto): ?><img src="/<?= e($c['photo_path']) ?>" style="width:100%;height:100%;object-fit:cover;"><?php else: ?><span style="font-size:13px;font-weight:700;color:#fff;"><?= e($_cInitials) ?></span><?php endif; ?></div><div><?= 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>
</div></div></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
......@@ -1198,9 +1229,13 @@ $childClassLabels = ['included' => 'تابع مشمول', 'dependent_with_fee' =
$tFee = $t['addition_fee'] ?? '0.00';
$tBreakdown = !empty($t['fee_breakdown_json']) ? json_decode($t['fee_breakdown_json'], true) : null;
if (!is_array($tBreakdown)) $tBreakdown = null;
$_tHasPhoto = !empty($t['photo_path']);
$_tInitials = mb_substr($t['full_name_ar'], 0, 2);
$_tGradient = ($t['gender'] === 'male') ? 'linear-gradient(135deg, #8B5CF6, #A78BFA)' : 'linear-gradient(135deg, #F59E0B, #FBBF24)';
$_tBorder = ($t['gender'] === 'male') ? '#C4B5FD' : '#FDE68A';
?>
<tr <?= $tBreakdown ? 'style="cursor:pointer;" onclick="toggleBillDetail(\'temp-' . $tIdx . '\')"' : '' ?>>
<td style="font-weight:600;"><?= e($t['full_name_ar']) ?></td>
<td style="font-weight:600;"><div style="display:flex;align-items:center;gap:8px;"><div style="width:36px;height:36px;border-radius:50%;overflow:hidden;flex-shrink:0;background:<?= $_tHasPhoto ? '#F3F4F6' : $_tGradient ?>;display:flex;align-items:center;justify-content:center;border:2px solid <?= $_tHasPhoto ? '#0D7377' : $_tBorder ?>;box-shadow:0 1px 4px rgba(0,0,0,0.08);"><?php if ($_tHasPhoto): ?><img src="/<?= e($t['photo_path']) ?>" style="width:100%;height:100%;object-fit:cover;"><?php else: ?><span style="font-size:13px;font-weight:700;color:#fff;"><?= e($_tInitials) ?></span><?php endif; ?></div><span><?= e($t['full_name_ar']) ?></span></div></td>
<td><span style="background:#E0F2FE;color:#0369A1;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;">عضو مؤقت</span></td>
<td style="font-size:12px;"><?= $categoryLabels[$t['category']] ?? e($t['category']) ?></td>
<td><?= $t['gender'] === 'male' ? 'ذكر' : 'أنثى' ?></td>
......
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