Sindbad~EG File Manager
<?php
require_once '../../config/config.php';
require_once '../../classes/EmailService.php';
checkLogin();
$pageTitle = 'Member Transfer Requests - ' . APP_NAME;
$db = Database::getInstance()->getConnection();
$success = '';
$error = '';
$userId = $_SESSION['user_id'] ?? null;
// Approve or deny request
if (isset($_GET['action'], $_GET['id']) && is_numeric($_GET['id'])) {
$requestId = (int)$_GET['id'];
$action = $_GET['action']; // approve | deny
if ($action === 'approve' || $action === 'deny') {
try {
$db->beginTransaction();
// Load request
$stmt = $db->prepare('SELECT r.*, m.area_id, m.district_id, m.assembly_id, m.first_name, m.last_name, m.email
FROM member_transfer_requests r
JOIN members m ON r.member_id = m.id
WHERE r.id = :id FOR UPDATE');
$stmt->execute(['id' => $requestId]);
$req = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$req) {
throw new Exception('Request not found.');
}
if ($req['status'] !== 'pending') {
throw new Exception('This request has already been processed.');
}
if ($action === 'approve') {
// Insert into member_transfers history
$hist = $db->prepare('INSERT INTO member_transfers (
member_id,
from_area_id, from_district_id, from_assembly_id,
to_area_id, to_district_id, to_assembly_id,
performed_by_user_id, performed_at, reversed
) VALUES (
:member_id,
:from_area_id, :from_district_id, :from_assembly_id,
:to_area_id, :to_district_id, :to_assembly_id,
:performed_by_user_id, :performed_at, 0
)');
$hist->execute([
'member_id' => $req['member_id'],
'from_area_id' => $req['area_id'],
'from_district_id' => $req['district_id'],
'from_assembly_id' => $req['assembly_id'],
'to_area_id' => $req['to_area_id'],
'to_district_id' => $req['to_district_id'],
'to_assembly_id' => $req['to_assembly_id'],
'performed_by_user_id' => $userId,
'performed_at' => date('Y-m-d H:i:s')
]);
// Update member location
$upd = $db->prepare('UPDATE members
SET area_id = :area_id,
district_id = :district_id,
assembly_id = :assembly_id
WHERE id = :member_id');
$upd->execute([
'area_id' => $req['to_area_id'],
'district_id' => $req['to_district_id'],
'assembly_id' => $req['to_assembly_id'],
'member_id' => $req['member_id']
]);
// Mark request as approved
$updateReq = $db->prepare('UPDATE member_transfer_requests
SET status = "approved",
decided_at = :decided_at,
decided_by_user_id = :decided_by
WHERE id = :id');
$updateReq->execute([
'decided_at' => date('Y-m-d H:i:s'),
'decided_by' => $userId,
'id' => $requestId
]);
$success = 'Transfer request approved and member moved to the new location.';
} else {
// Deny
$updateReq = $db->prepare('UPDATE member_transfer_requests
SET status = "denied",
decided_at = :decided_at,
decided_by_user_id = :decided_by
WHERE id = :id');
$updateReq->execute([
'decided_at' => date('Y-m-d H:i:s'),
'decided_by' => $userId,
'id' => $requestId
]);
$success = 'Transfer request denied.';
}
$db->commit();
if ($action === 'approve' && !empty($req['email'])) {
try {
$emailService = new EmailService();
$memberName = trim(($req['first_name'] ?? '') . ' ' . ($req['last_name'] ?? ''));
$subject = 'Your membership transfer has been approved';
$body = '<h2>Membership Transfer Approved</h2>' .
'<p>Dear ' . htmlspecialchars($memberName) . ',</p>' .
'<p>Your request to transfer your membership has been <strong>approved</strong>.</p>' .
'<p>If this was expected, no further action is needed. If you have any questions, please contact your leaders.</p>' .
'<p>Thank you.</p>';
$emailService->queueEmail(
$req['email'],
$memberName,
$subject,
$body,
'general'
);
} catch (Exception $ex) {
error_log('Transfer approval email error: ' . $ex->getMessage());
}
}
} catch (Exception $e) {
$db->rollBack();
$error = 'Failed to process request: ' . $e->getMessage();
}
}
}
// Load requests
$sql = "SELECT r.*,
m.first_name, m.last_name, m.title,
fa.area_name AS from_area_name,
fd.district_name AS from_district_name,
fas.assembly_name AS from_assembly_name,
ta.area_name AS to_area_name,
td.district_name AS to_district_name,
tas.assembly_name AS to_assembly_name,
u.full_name AS decided_by_name
FROM member_transfer_requests r
JOIN members m ON r.member_id = m.id
LEFT JOIN areas fa ON r.from_area_id = fa.id
LEFT JOIN districts fd ON r.from_district_id = fd.id
LEFT JOIN assemblies fas ON r.from_assembly_id = fas.id
LEFT JOIN areas ta ON r.to_area_id = ta.id
LEFT JOIN districts td ON r.to_district_id = td.id
LEFT JOIN assemblies tas ON r.to_assembly_id = tas.id
LEFT JOIN users u ON r.decided_by_user_id = u.id
ORDER BY r.status = 'pending' DESC, r.created_at DESC
LIMIT 200";
$stmt = $db->prepare($sql);
$stmt->execute();
$requests = $stmt->fetchAll(PDO::FETCH_ASSOC);
include '../../includes/header.php';
include '../../includes/sidebar.php';
?>
<main class="flex-1 md:ml-64 mt-16">
<div class="container mx-auto px-4 py-8">
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-6 gap-4">
<div>
<h1 class="text-3xl font-bold text-gray-800">
<i class="fas fa-inbox mr-2 text-blue-500"></i>Member Transfer Requests
</h1>
<p class="text-gray-600 mt-2">Review transfer requests submitted from the member portal and approve or deny them.</p>
</div>
<div class="flex gap-3">
<a href="member_transfer.php" class="btn-gradient text-white px-6 py-3 rounded-full font-semibold transition shadow-lg hover:shadow-xl">
<i class="fas fa-exchange-alt mr-2"></i>Transfer Members
</a>
</div>
</div>
<?php if ($success): ?>
<div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-4 rounded-lg mb-4">
<i class="fas fa-check-circle mr-2"></i><?php echo $success; ?>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 rounded-lg mb-4">
<i class="fas fa-exclamation-circle mr-2"></i><?php echo $error; ?>
</div>
<?php endif; ?>
<div class="bg-white rounded-lg shadow-lg overflow-hidden">
<div class="px-4 py-4 border-b border-gray-200 bg-gray-50 flex justify-between items-center">
<h2 class="text-lg font-semibold text-gray-800">Recent Requests (latest 200)</h2>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 text-sm">
<thead class="bg-gradient-to-r from-blue-500 to-blue-600 text-white">
<tr>
<th class="px-4 py-2 text-left font-medium uppercase tracking-wider">Member</th>
<th class="px-4 py-2 text-left font-medium uppercase tracking-wider">From</th>
<th class="px-4 py-2 text-left font-medium uppercase tracking-wider">To</th>
<th class="px-4 py-2 text-left font-medium uppercase tracking-wider">Reason</th>
<th class="px-4 py-2 text-left font-medium uppercase tracking-wider">Status</th>
<th class="px-4 py-2 text-left font-medium uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<?php if (empty($requests)): ?>
<tr>
<td colspan="6" class="px-6 py-8 text-center text-gray-500">
<i class="fas fa-inbox text-4xl mb-2 text-gray-300"></i>
<p>No transfer requests found.</p>
</td>
</tr>
<?php else: ?>
<?php foreach ($requests as $r): ?>
<tr class="hover:bg-gray-50">
<td class="px-4 py-3">
<div class="font-semibold text-gray-800"><?php echo htmlspecialchars(trim(($r['title'] ?? '') . ' ' . $r['first_name'] . ' ' . $r['last_name'])); ?></div>
<div class="text-xs text-gray-500">Requested: <?php echo htmlspecialchars($r['created_at']); ?></div>
</td>
<td class="px-4 py-3 text-xs">
<div class="text-gray-800"><?php echo htmlspecialchars($r['from_assembly_name'] ?? ''); ?></div>
<div class="text-gray-500"><?php echo htmlspecialchars(($r['from_district_name'] ?? '') . ' / ' . ($r['from_area_name'] ?? '')); ?></div>
</td>
<td class="px-4 py-3 text-xs">
<div class="text-gray-800"><?php echo htmlspecialchars($r['to_assembly_name'] ?? ''); ?></div>
<div class="text-gray-500"><?php echo htmlspecialchars(($r['to_district_name'] ?? '') . ' / ' . ($r['to_area_name'] ?? '')); ?></div>
</td>
<td class="px-4 py-3 text-xs text-gray-700">
<?php echo nl2br(htmlspecialchars($r['reason'] ?? '')); ?>
</td>
<td class="px-4 py-3 text-xs">
<?php if ($r['status'] === 'pending'): ?>
<span class="inline-flex px-2 py-1 rounded-full bg-yellow-100 text-yellow-800 font-semibold">
<i class="fas fa-clock mr-1"></i>Pending
</span>
<?php elseif ($r['status'] === 'approved'): ?>
<span class="inline-flex px-2 py-1 rounded-full bg-green-100 text-green-800 font-semibold">
<i class="fas fa-check mr-1"></i>Approved
</span>
<div class="text-gray-500 mt-1 text-xs">By: <?php echo htmlspecialchars($r['decided_by_name'] ?? ''); ?></div>
<?php else: ?>
<span class="inline-flex px-2 py-1 rounded-full bg-red-100 text-red-800 font-semibold">
<i class="fas fa-times mr-1"></i>Denied
</span>
<div class="text-gray-500 mt-1 text-xs">By: <?php echo htmlspecialchars($r['decided_by_name'] ?? ''); ?></div>
<?php endif; ?>
</td>
<td class="px-4 py-3 text-xs">
<?php if ($r['status'] === 'pending'): ?>
<div class="flex space-x-2">
<a href="member_transfer_requests.php?action=approve&id=<?php echo $r['id']; ?>"
onclick="return confirm('Approve this transfer and move the member?');"
class="inline-flex items-center px-3 py-1 rounded bg-green-600 hover:bg-green-700 text-white font-semibold">
<i class="fas fa-check mr-1"></i>Approve
</a>
<a href="member_transfer_requests.php?action=deny&id=<?php echo $r['id']; ?>"
onclick="return confirm('Deny this transfer request?');"
class="inline-flex items-center px-3 py-1 rounded bg-red-600 hover:bg-red-700 text-white font-semibold">
<i class="fas fa-times mr-1"></i>Deny
</a>
</div>
<?php else: ?>
<span class="text-gray-400 text-xs">No actions</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</main>
<?php include '../../includes/footer.php'; ?>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists