Sindbad~EG File Manager
<?php
require_once '../../config/config.php';
checkLogin();
$pageTitle = 'Member Transfer - ' . APP_NAME;
$db = Database::getInstance()->getConnection();
$success = '';
$error = '';
// Access
$accessLevel = $_SESSION['access_level'] ?? 'assembly';
$areaId = $_SESSION['area_id'] ?? null;
$districtId = $_SESSION['district_id'] ?? null;
$assemblyId = $_SESSION['assembly_id'] ?? null;
$userId = $_SESSION['user_id'] ?? null;
// Handle transfer submit
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['transfer_members'])) {
$memberIds = isset($_POST['member_ids']) && is_array($_POST['member_ids'])
? array_filter($_POST['member_ids'], 'is_numeric')
: [];
$toAreaId = (int)($_POST['to_area_id'] ?? 0);
$toDistrictId = (int)($_POST['to_district_id'] ?? 0);
$toAssemblyId = (int)($_POST['to_assembly_id'] ?? 0);
if (empty($memberIds)) {
$error = 'Please select at least one member to transfer.';
} elseif ($toAreaId <= 0 || $toDistrictId <= 0 || $toAssemblyId <= 0) {
$error = 'Please select Area, District and Assembly to transfer to.';
} else {
try {
$db->beginTransaction();
$now = date('Y-m-d H:i:s');
foreach ($memberIds as $mid) {
// Load current location
$stmt = $db->prepare('SELECT area_id, district_id, assembly_id FROM members WHERE id = :id');
$stmt->execute(['id' => $mid]);
$current = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$current) {
continue;
}
// Insert history row (requires member_transfers table in DB)
$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' => $mid,
'from_area_id' => $current['area_id'],
'from_district_id' => $current['district_id'],
'from_assembly_id' => $current['assembly_id'],
'to_area_id' => $toAreaId,
'to_district_id' => $toDistrictId,
'to_assembly_id' => $toAssemblyId,
'performed_by_user_id' => $userId,
'performed_at' => $now
]);
// Update member location
$upd = $db->prepare('UPDATE members SET area_id = :area_id, district_id = :district_id, assembly_id = :assembly_id WHERE id = :id');
$upd->execute([
'area_id' => $toAreaId,
'district_id' => $toDistrictId,
'assembly_id' => $toAssemblyId,
'id' => $mid
]);
}
$db->commit();
$success = 'Member transfer completed successfully.';
} catch (PDOException $e) {
$db->rollBack();
$error = 'Transfer failed: ' . $e->getMessage();
}
}
}
// Load locations for filters and target selects
$areas = [];
$districts = [];
$assemblies = [];
try {
$areasStmt = $db->query("SELECT id, area_name FROM areas WHERE is_active = 1 ORDER BY area_name");
$areas = $areasStmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {}
try {
$districtsStmt = $db->query("SELECT id, district_name, area_id FROM districts WHERE is_active = 1 ORDER BY district_name");
$districts = $districtsStmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {}
try {
$assembliesStmt = $db->query("SELECT id, assembly_name, district_id FROM assemblies WHERE is_active = 1 ORDER BY assembly_name");
$assemblies = $assembliesStmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {}
// Build member listing (filtered by access level and optional search)
$where = ' WHERE 1=1';
$params = [];
if ($accessLevel === 'assembly') {
$where .= ' AND m.assembly_id = :assembly_id';
$params['assembly_id'] = $assemblyId;
} elseif ($accessLevel === 'district') {
$where .= ' AND m.district_id = :district_id';
$params['district_id'] = $districtId;
} elseif ($accessLevel === 'area') {
$where .= ' AND m.area_id = :area_id';
$params['area_id'] = $areaId;
}
if (!empty($_GET['filter_district'])) {
$where .= ' AND m.district_id = :filter_district';
$params['filter_district'] = (int)$_GET['filter_district'];
}
if (!empty($_GET['filter_assembly'])) {
$where .= ' AND m.assembly_id = :filter_assembly';
$params['filter_assembly'] = (int)$_GET['filter_assembly'];
}
if (!empty($_GET['search'])) {
$search = '%' . $_GET['search'] . '%';
$where .= ' AND (m.first_name LIKE :s1 OR m.last_name LIKE :s2 OR m.email LIKE :s3)';
$params['s1'] = $search;
$params['s2'] = $search;
$params['s3'] = $search;
}
$sql = "SELECT m.id, m.first_name, m.last_name, m.title, m.email, m.phone,
a.area_name, d.district_name, asm.assembly_name
FROM members m
JOIN areas a ON m.area_id = a.id
JOIN districts d ON m.district_id = d.id
JOIN assemblies asm ON m.assembly_id = asm.id" .
$where .
' ORDER BY a.area_name, d.district_name, asm.assembly_name, m.first_name, m.last_name
LIMIT 200';
$stmt = $db->prepare($sql);
$stmt->execute($params);
$members = $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">
<!-- Page Header -->
<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-exchange-alt mr-2 text-blue-500"></i>Member Transfer
</h1>
<p class="text-gray-600 mt-2">Transfer members from one assembly to another and keep a history of movements.</p>
</div>
<div class="flex gap-3">
<a href="member_transfer_history.php" class="bg-indigo-600 text-white px-6 py-3 rounded-full font-semibold transition shadow-lg hover:bg-indigo-700">
<i class="fas fa-history mr-2"></i>Transfer History
</a>
<a href="../membership/index.php" class="btn-gradient text-white px-6 py-3 rounded-full font-semibold transition shadow-lg hover:shadow-xl">
<i class="fas fa-users mr-2"></i>Back to 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; ?>
<!-- Filters -->
<div class="bg-white rounded-lg shadow-lg p-6 mb-6">
<form method="GET" action="" class="flex flex-col md:flex-row gap-4 items-center">
<div class="flex-1 w-full">
<div class="relative">
<input type="text" name="search" placeholder="Search by name or email..." value="<?php echo htmlspecialchars($_GET['search'] ?? ''); ?>" class="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" />
<i class="fas fa-search absolute left-3 top-4 text-gray-400"></i>
</div>
</div>
<div class="flex items-center space-x-3">
<div>
<label class="block text-xs font-semibold text-gray-600 mb-1">District</label>
<select name="filter_district" id="filterDistrictSelect" class="px-3 py-2 border border-gray-300 rounded-lg text-sm">
<option value="">All</option>
<?php foreach ($districts as $dist): ?>
<option value="<?php echo $dist['id']; ?>" <?php echo (isset($_GET['filter_district']) && $_GET['filter_district'] == $dist['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($dist['district_name']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div>
<label class="block text-xs font-semibold text-gray-600 mb-1">Assembly</label>
<select name="filter_assembly" id="filterAssemblySelect" class="px-3 py-2 border border-gray-300 rounded-lg text-sm">
<option value="">All</option>
<?php foreach ($assemblies as $asm): ?>
<option value="<?php echo $asm['id']; ?>" data-district-id="<?php echo $asm['district_id']; ?>" <?php echo (isset($_GET['filter_assembly']) && $_GET['filter_assembly'] == $asm['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($asm['assembly_name']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<button type="submit" class="bg-blue-500 text-white px-6 py-3 rounded-lg hover:bg-blue-600 transition">
<i class="fas fa-filter mr-2"></i>Filter
</button>
<a href="member_transfer.php" class="bg-gray-500 text-white px-6 py-3 rounded-lg hover:bg-gray-600 transition text-center">
<i class="fas fa-redo mr-2"></i>Reset
</a>
</div>
</form>
</div>
<!-- Transfer Form & Member List -->
<form method="POST" class="bg-white rounded-lg shadow-lg overflow-hidden">
<div class="px-4 py-4 border-b border-gray-200 bg-gray-50 flex flex-col md:flex-row md:items-center md:justify-between gap-4">
<div>
<h2 class="text-lg font-semibold text-gray-800">Select Members to Transfer</h2>
<p class="text-xs text-gray-500">Use the checkboxes below to choose one or more members.</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-3 w-full md:w-auto">
<div>
<label class="block text-xs font-semibold text-gray-600 mb-1">To Area</label>
<select name="to_area_id" id="toAreaSelect" class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm" required>
<option value="">Select Area</option>
<?php foreach ($areas as $area): ?>
<option value="<?php echo $area['id']; ?>"><?php echo htmlspecialchars($area['area_name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div>
<label class="block text-xs font-semibold text-gray-600 mb-1">To District</label>
<select name="to_district_id" id="toDistrictSelect" class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm" required>
<option value="">Select District</option>
<?php foreach ($districts as $dist): ?>
<option value="<?php echo $dist['id']; ?>" data-area-id="<?php echo $dist['area_id']; ?>"><?php echo htmlspecialchars($dist['district_name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div>
<label class="block text-xs font-semibold text-gray-600 mb-1">To Assembly</label>
<select name="to_assembly_id" id="toAssemblySelect" class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm" required>
<option value="">Select Assembly</option>
<?php foreach ($assemblies as $asm): ?>
<option value="<?php echo $asm['id']; ?>" data-district-id="<?php echo $asm['district_id']; ?>"><?php echo htmlspecialchars($asm['assembly_name']); ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gradient-to-r from-blue-500 to-blue-600">
<tr>
<th class="px-4 py-3 text-left text-xs font-medium text-white uppercase tracking-wider">
<input type="checkbox" id="selectAllMembers" class="rounded" />
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white uppercase tracking-wider">Member</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white uppercase tracking-wider">Contact</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white uppercase tracking-wider">Current Location</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<?php if (empty($members)): ?>
<tr>
<td colspan="4" class="px-6 py-8 text-center text-gray-500">
<i class="fas fa-users-slash text-4xl mb-2 text-gray-300"></i>
<p>No members found for the selected filters.</p>
</td>
</tr>
<?php else: ?>
<?php foreach ($members as $m): ?>
<tr class="hover:bg-gray-50">
<td class="px-4 py-3">
<input type="checkbox" name="member_ids[]" value="<?php echo $m['id']; ?>" class="memberCheckbox rounded" />
</td>
<td class="px-6 py-3">
<div class="font-semibold text-gray-800"><?php echo htmlspecialchars(trim(($m['title'] ?? '') . ' ' . $m['first_name'] . ' ' . $m['last_name'])); ?></div>
</td>
<td class="px-6 py-3 text-sm">
<div class="text-gray-800"><?php echo htmlspecialchars($m['phone'] ?? ''); ?></div>
<div class="text-gray-500"><?php echo htmlspecialchars($m['email'] ?? ''); ?></div>
</td>
<td class="px-6 py-3 text-sm">
<div class="text-gray-800"><?php echo htmlspecialchars($m['assembly_name']); ?></div>
<div class="text-gray-500 text-xs"><?php echo htmlspecialchars($m['district_name'] . ' / ' . $m['area_name']); ?></div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
<div class="px-4 py-4 border-t border-gray-200 flex justify-end">
<button type="submit" name="transfer_members" value="1" class="btn-gradient text-white px-6 py-3 rounded-lg font-semibold hover:shadow-lg transition" <?php echo empty($members) ? 'disabled' : ''; ?>>
<i class="fas fa-exchange-alt mr-2"></i>Transfer Selected Members
</button>
</div>
</form>
</div>
<script>
// Filter Assembly options in filters based on District (for member list)
document.addEventListener('DOMContentLoaded', function() {
var filterDistrict = document.getElementById('filterDistrictSelect');
var filterAssembly = document.getElementById('filterAssemblySelect');
if (filterDistrict && filterAssembly) {
function filterAssemblyOptions() {
var d = filterDistrict.value;
filterAssembly.querySelectorAll('option').forEach(function(opt) {
if (!opt.dataset.districtId) { opt.style.display = ''; return; }
opt.style.display = (!d || opt.dataset.districtId === d) ? '' : 'none';
});
}
filterAssemblyOptions();
filterDistrict.addEventListener('change', function() {
filterAssembly.value = '';
filterAssemblyOptions();
});
}
// Target location dependent dropdowns
var toArea = document.getElementById('toAreaSelect');
var toDistrict = document.getElementById('toDistrictSelect');
var toAssembly = document.getElementById('toAssemblySelect');
function filterTargetDistricts() {
var a = toArea.value;
toDistrict.querySelectorAll('option').forEach(function(opt) {
if (!opt.dataset.areaId) { opt.style.display = ''; return; }
opt.style.display = (!a || opt.dataset.areaId === a) ? '' : 'none';
});
}
function filterTargetAssemblies() {
var d = toDistrict.value;
toAssembly.querySelectorAll('option').forEach(function(opt) {
if (!opt.dataset.districtId) { opt.style.display = ''; return; }
opt.style.display = (!d || opt.dataset.districtId === d) ? '' : 'none';
});
}
if (toArea && toDistrict && toAssembly) {
filterTargetDistricts();
filterTargetAssemblies();
toArea.addEventListener('change', function() {
toDistrict.value = '';
toAssembly.value = '';
filterTargetDistricts();
filterTargetAssemblies();
});
toDistrict.addEventListener('change', function() {
toAssembly.value = '';
filterTargetAssemblies();
});
}
// Select all checkboxes
var selectAll = document.getElementById('selectAllMembers');
var memberCheckboxes = document.querySelectorAll('.memberCheckbox');
if (selectAll) {
selectAll.addEventListener('change', function() {
memberCheckboxes.forEach(function(cb) { cb.checked = selectAll.checked; });
});
}
});
</script>
</main>
<?php include '../../includes/footer.php'; ?>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists