Sindbad~EG File Manager
<?php
require_once '../config/config.php';
require_once '../includes/email_functions_improved.php';
// Check if program ID is provided
if (!isset($_GET['program']) || empty($_GET['program'])) {
redirect('../index.php');
}
$program_id = (int)$_GET['program'];
// Get program details
$db = new Database();
$conn = $db->getConnection();
$query = "SELECT * FROM programs WHERE id = ? AND is_active = 1";
$stmt = $conn->prepare($query);
$stmt->execute([$program_id]);
$program = $stmt->fetch();
if (!$program) {
redirect('../index.php');
}
// Check registration status
$registration_status = checkRegistrationStatus($program_id);
// Get districts and assemblies
$districts_query = "SELECT id, name FROM locations WHERE type = 'district' AND is_active = 1 ORDER BY name";
$districts_stmt = $conn->prepare($districts_query);
$districts_stmt->execute();
$districts = $districts_stmt->fetchAll();
$assemblies_query = "SELECT id, name, parent_id FROM locations WHERE type = 'assembly' AND is_active = 1 ORDER BY name";
$assemblies_stmt = $conn->prepare($assemblies_query);
$assemblies_stmt->execute();
$assemblies = $assemblies_stmt->fetchAll();
// Get form template
$query = "SELECT * FROM form_templates WHERE is_active = 1 ORDER BY created_at DESC LIMIT 1";
$stmt = $conn->prepare($query);
$stmt->execute();
$form_template = $stmt->fetch();
$form_fields = $form_template ? json_decode($form_template['fields'], true) : [];
// Handle form submission
$success_message = '';
$error_message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!validateCSRFToken($_POST['csrf_token'] ?? '')) {
$error_message = 'Invalid security token. Please try again.';
} elseif (!$registration_status['is_open']) {
$error_message = $registration_status['message'];
} else {
$district_id = (int)($_POST['district_id'] ?? 0);
$assembly_id = (int)($_POST['assembly_id'] ?? 0);
$officer_type = sanitizeInput($_POST['officer_type'] ?? '');
$full_name = sanitizeInput($_POST['full_name'] ?? '');
$email = sanitizeInput($_POST['email'] ?? '');
$telephone = sanitizeInput($_POST['telephone'] ?? '');
// GPS Location data
$latitude = !empty($_POST['latitude']) ? (float)$_POST['latitude'] : null;
$longitude = !empty($_POST['longitude']) ? (float)$_POST['longitude'] : null;
$location_accuracy = !empty($_POST['location_accuracy']) ? (float)$_POST['location_accuracy'] : null;
$location_address = sanitizeInput($_POST['location_address'] ?? '');
// Get district and assembly names for backward compatibility
$district_name = '';
$assembly_name = '';
if ($district_id) {
$district_query = "SELECT name FROM locations WHERE id = ? AND type = 'district'";
$district_stmt = $conn->prepare($district_query);
$district_stmt->execute([$district_id]);
$district_result = $district_stmt->fetch();
$district_name = $district_result ? $district_result['name'] : '';
}
if ($assembly_id) {
$assembly_query = "SELECT name FROM locations WHERE id = ? AND type = 'assembly'";
$assembly_stmt = $conn->prepare($assembly_query);
$assembly_stmt->execute([$assembly_id]);
$assembly_result = $assembly_stmt->fetch();
$assembly_name = $assembly_result ? $assembly_result['name'] : '';
}
// Validate required fields
if (empty($full_name) || !$district_id || !$assembly_id || empty($officer_type)) {
$error_message = 'Full name, district, assembly, and officer type are required.';
} else {
// Collect additional form data
$additional_data = [];
foreach ($form_fields as $field) {
if (isset($_POST[$field['name']])) {
$additional_data[$field['name']] = sanitizeInput($_POST[$field['name']]);
}
}
try {
// Check for duplicate registration today
$today = date('Y-m-d');
$duplicate_query = "SELECT id, tracking_code FROM attendance_records
WHERE program_id = ? AND district_id = ? AND assembly_id = ?
AND officer_type = ? AND full_name = ?
AND DATE(submitted_at) = ?
LIMIT 1";
$duplicate_stmt = $conn->prepare($duplicate_query);
$duplicate_stmt->execute([
$program_id,
$district_id,
$assembly_id,
$officer_type,
$full_name,
$today
]);
$existing_record = $duplicate_stmt->fetch();
if ($existing_record) {
$error_message = "You are already registered for today's program. Your tracking code is: " . $existing_record['tracking_code'];
} else {
// Generate unique tracking code
$tracking_code = generateUniqueTrackingCode($conn);
$query = "INSERT INTO attendance_records (tracking_code, program_id, district_id, assembly_id, officer_type, district_name, assembly_name, full_name, email, telephone, additional_data, ip_address, user_agent, latitude, longitude, location_accuracy, location_timestamp, location_address)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($query);
$stmt->execute([
$tracking_code,
$program_id,
$district_id,
$assembly_id,
$officer_type ?: null,
$district_name,
$assembly_name,
$full_name,
$email,
$telephone,
json_encode($additional_data),
$_SERVER['REMOTE_ADDR'],
$_SERVER['HTTP_USER_AGENT'],
$latitude,
$longitude,
$location_accuracy,
($latitude && $longitude) ? date('Y-m-d H:i:s') : null,
$location_address ?: null
]);
// Get the inserted record ID
$record_id = $conn->lastInsertId();
// Prepare attendance record for email
$attendance_record = [
'id' => $record_id,
'tracking_code' => $tracking_code,
'program_id' => $program_id,
'full_name' => $full_name,
'email' => $email,
'district_name' => $district_name,
'assembly_name' => $assembly_name,
'submitted_at' => date('Y-m-d H:i:s')
];
// Send email notification if email is provided and notifications are enabled
if (!empty($email) && isEmailNotificationEnabled($conn)) {
sendAttendanceConfirmationEmail($conn, $attendance_record);
}
// Redirect to thank you page with tracking code
redirect('thank_you.php?code=' . $tracking_code);
}
} catch (Exception $e) {
$error_message = 'An error occurred while saving your information. Please try again.';
}
}
}
}
// Get site settings
$query = "SELECT setting_key, setting_value FROM settings WHERE setting_key IN ('site_title', 'site_logo')";
$stmt = $conn->prepare($query);
$stmt->execute();
$settings = [];
while ($row = $stmt->fetch()) {
$settings[$row['setting_key']] = $row['setting_value'];
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Attendance Form - <?php echo htmlspecialchars($program['name']); ?></title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3B82F6',
secondary: '#F59E0B',
accent: '#6B7280'
}
}
}
}
</script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
.gradient-bg {
background: linear-gradient(135deg, #3B82F6 0%, #F59E0B 50%, #6B7280 100%);
}
</style>
</head>
<body class="min-h-screen bg-gray-50">
<!-- Navigation -->
<nav class="gradient-bg shadow-lg">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center">
<img src="../<?php echo $settings['site_logo'] ?? SITE_LOGO; ?>" alt="Logo" class="h-8 w-8 mr-3">
<span class="text-white text-xl font-bold"><?php echo $settings['site_title'] ?? SITE_TITLE; ?></span>
</div>
<div class="flex items-center">
<a href="../index.php" class="text-white hover:text-yellow-200 transition duration-300">
<i class="fas fa-arrow-left mr-2"></i>Back to Programs
</a>
</div>
</div>
</div>
</nav>
<div class="py-12">
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
<!-- Program Info -->
<div class="bg-white rounded-lg shadow-lg p-6 mb-8">
<div class="text-center">
<h1 class="text-3xl font-bold text-gray-900 mb-2">
<?php echo htmlspecialchars($program['name']); ?>
</h1>
<p class="text-gray-600 mb-4">
<i class="fas fa-map-marker-alt mr-2"></i>
<?php echo htmlspecialchars($program['location_name'] ?? 'All Locations'); ?>
</p>
<?php if ($program['description']): ?>
<p class="text-gray-700">
<?php echo htmlspecialchars($program['description']); ?>
</p>
<?php endif; ?>
</div>
</div>
<!-- Success/Error Messages -->
<?php if ($success_message): ?>
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-6">
<div class="flex items-center">
<i class="fas fa-check-circle mr-2"></i>
<span><?php echo $success_message; ?></span>
</div>
</div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-6">
<div class="flex items-center justify-between">
<div class="flex items-center">
<i class="fas fa-exclamation-circle mr-2"></i>
<span><?php echo $error_message; ?></span>
</div>
<?php if (strpos($error_message, 'already registered') !== false): ?>
<div class="flex space-x-2">
<button onclick="checkStatus()" class="bg-blue-600 text-white px-3 py-1 rounded text-sm hover:bg-blue-700">
<i class="fas fa-search mr-1"></i>Check Status
</button>
<button onclick="exitForm()" class="bg-gray-600 text-white px-3 py-1 rounded text-sm hover:bg-gray-700">
<i class="fas fa-times mr-1"></i>Exit Form
</button>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<!-- Registration Status Message -->
<?php if (!$registration_status['is_open']): ?>
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-6 mb-6">
<div class="flex items-start">
<div class="flex-shrink-0">
<i class="fas fa-exclamation-triangle text-yellow-600 text-xl"></i>
</div>
<div class="ml-3">
<h3 class="text-lg font-semibold text-yellow-800 mb-2">Registration Closed</h3>
<p class="text-yellow-700"><?php echo htmlspecialchars($registration_status['message']); ?></p>
<?php if (isset($registration_status['open_date'])): ?>
<p class="text-sm text-yellow-600 mt-2">
<i class="fas fa-clock mr-1"></i>
Registration will open on <?php echo date('F j, Y \a\t g:i A', strtotime($registration_status['open_date'])); ?>
</p>
<?php endif; ?>
</div>
</div>
</div>
<?php elseif ($registration_status['status'] === 'scheduled_open'): ?>
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
<div class="flex items-center">
<i class="fas fa-info-circle text-blue-600 mr-2"></i>
<p class="text-blue-800"><?php echo htmlspecialchars($registration_status['message']); ?></p>
</div>
</div>
<?php endif; ?>
<!-- Attendance Form -->
<div class="bg-white rounded-lg shadow-lg p-6 <?php echo !$registration_status['is_open'] ? 'opacity-60' : ''; ?>">
<h2 class="text-2xl font-bold text-gray-900 mb-6">
<i class="fas fa-edit mr-2 text-primary"></i>
Attendance Registration
<?php if (!$registration_status['is_open']): ?>
<span class="text-sm font-normal text-red-600 ml-2">(Currently Closed)</span>
<?php endif; ?>
</h2>
<form method="POST" class="space-y-6" id="attendanceForm">
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<!-- District -->
<div>
<label for="district_id" class="block text-sm font-medium text-gray-700 mb-2">
District <span class="text-red-500">*</span>
</label>
<select id="district_id" name="district_id" required onchange="loadAssemblies()"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-colors duration-200">
<option value="">Select a District</option>
<?php foreach ($districts as $district): ?>
<option value="<?php echo $district['id']; ?>"
<?php echo (isset($_POST['district_id']) && $_POST['district_id'] == $district['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($district['name']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<!-- Assembly -->
<div>
<label for="assembly_id" class="block text-sm font-medium text-gray-700 mb-2">
Assembly <span class="text-red-500">*</span>
</label>
<select id="assembly_id" name="assembly_id" required disabled
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed">
<option value="">First select a district</option>
<?php foreach ($assemblies as $assembly): ?>
<option value="<?php echo $assembly['id']; ?>"
data-district="<?php echo $assembly['parent_id']; ?>"
<?php echo (isset($_POST['assembly_id']) && $_POST['assembly_id'] == $assembly['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($assembly['name']); ?>
</option>
<?php endforeach; ?>
</select>
<p id="assemblyHelp" class="text-xs text-gray-500 mt-1">
<i class="fas fa-info-circle mr-1"></i>
Assemblies will be filtered based on your district selection
</p>
</div>
<!-- Officer Type -->
<div>
<label for="officer_type" class="block text-sm font-medium text-gray-700 mb-2">
Officer Type <span class="text-red-500">*</span>
</label>
<select id="officer_type" name="officer_type" required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
<option value="">Select Officer Type</option>
<option value="Deacon" <?php echo (isset($_POST['officer_type']) && $_POST['officer_type'] == 'Deacon') ? 'selected' : ''; ?>>Deacon</option>
<option value="Deaconess" <?php echo (isset($_POST['officer_type']) && $_POST['officer_type'] == 'Deaconess') ? 'selected' : ''; ?>>Deaconess</option>
<option value="Elder" <?php echo (isset($_POST['officer_type']) && $_POST['officer_type'] == 'Elder') ? 'selected' : ''; ?>>Elder</option>
<option value="Pastor" <?php echo (isset($_POST['officer_type']) && $_POST['officer_type'] == 'Pastor') ? 'selected' : ''; ?>>Pastor</option>
<option value="Apostle" <?php echo (isset($_POST['officer_type']) && $_POST['officer_type'] == 'Apostle') ? 'selected' : ''; ?>>Apostle</option>
<option value="Prophet" <?php echo (isset($_POST['officer_type']) && $_POST['officer_type'] == 'Prophet') ? 'selected' : ''; ?>>Prophet</option>
<option value="Evangelist" <?php echo (isset($_POST['officer_type']) && $_POST['officer_type'] == 'Evangelist') ? 'selected' : ''; ?>>Evangelist</option>
<option value="Other" <?php echo (isset($_POST['officer_type']) && $_POST['officer_type'] == 'Other') ? 'selected' : ''; ?>>Other</option>
</select>
<p class="text-xs text-gray-500 mt-1">
<i class="fas fa-info-circle mr-1"></i>
Please select your officer type (required field)
</p>
</div>
<!-- Full Name -->
<div>
<label for="full_name" class="block text-sm font-medium text-gray-700 mb-2">
Full Name <span class="text-red-500">*</span>
</label>
<input type="text" id="full_name" name="full_name" required
value="<?php echo htmlspecialchars($_POST['full_name'] ?? ''); ?>"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
</div>
<!-- Email -->
<div>
<label for="email" class="block text-sm font-medium text-gray-700 mb-2">
Email Address
</label>
<input type="email" id="email" name="email"
value="<?php echo htmlspecialchars($_POST['email'] ?? ''); ?>"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
</div>
<!-- Telephone -->
<div>
<label for="telephone" class="block text-sm font-medium text-gray-700 mb-2">
Phone Number
</label>
<input type="tel" id="telephone" name="telephone"
value="<?php echo htmlspecialchars($_POST['telephone'] ?? ''); ?>"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
</div>
<!-- Dynamic Form Fields -->
<?php foreach ($form_fields as $field): ?>
<?php if (!in_array($field['name'], ['district_name', 'assembly_name', 'full_name', 'email', 'telephone'])): ?>
<div>
<label for="<?php echo $field['name']; ?>" class="block text-sm font-medium text-gray-700 mb-2">
<?php echo htmlspecialchars($field['label']); ?>
<?php if ($field['required'] ?? false): ?>
<span class="text-red-500">*</span>
<?php endif; ?>
</label>
<?php if ($field['type'] === 'select'): ?>
<select id="<?php echo $field['name']; ?>" name="<?php echo $field['name']; ?>"
<?php echo ($field['required'] ?? false) ? 'required' : ''; ?>
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
<option value="">Select an option</option>
<?php foreach ($field['options'] as $option): ?>
<option value="<?php echo htmlspecialchars($option); ?>"
<?php echo (($_POST[$field['name']] ?? '') === $option) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($option); ?>
</option>
<?php endforeach; ?>
</select>
<?php elseif ($field['type'] === 'radio'): ?>
<div class="space-y-2">
<?php foreach ($field['options'] as $option): ?>
<label class="flex items-center">
<input type="radio" name="<?php echo $field['name']; ?>"
value="<?php echo htmlspecialchars($option); ?>"
<?php echo (($_POST[$field['name']] ?? '') === $option) ? 'checked' : ''; ?>
<?php echo ($field['required'] ?? false) ? 'required' : ''; ?>
class="mr-2 text-primary focus:ring-primary">
<span><?php echo htmlspecialchars($option); ?></span>
</label>
<?php endforeach; ?>
</div>
<?php else: ?>
<input type="<?php echo $field['type']; ?>"
id="<?php echo $field['name']; ?>"
name="<?php echo $field['name']; ?>"
value="<?php echo htmlspecialchars($_POST[$field['name']] ?? ''); ?>"
<?php echo ($field['required'] ?? false) ? 'required' : ''; ?>
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
<?php endif; ?>
</div>
<?php endif; ?>
<?php endforeach; ?>
<!-- GPS Location Section -->
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
<div class="flex items-center justify-between mb-3">
<h3 class="text-lg font-semibold text-blue-900">
<i class="fas fa-map-marker-alt mr-2"></i>Location Verification
</h3>
<span id="locationStatus" class="text-sm text-gray-600">Auto-detecting...</span>
</div>
<p class="text-sm text-blue-800 mb-4">
<i class="fas fa-info-circle mr-1"></i>
Your location is being automatically detected to verify attendance. This is optional and helps ensure accurate record-keeping.
</p>
<div class="space-y-3">
<button type="button" id="getLocationBtn"
class="w-full bg-blue-600 text-white py-2 px-4 rounded-lg hover:bg-blue-700 transition duration-300">
<i class="fas fa-crosshairs mr-2"></i>
<span id="locationBtnText">Retry Location Detection</span>
</button>
<div id="locationInfo" class="hidden bg-white rounded-lg p-3 border">
<div class="flex items-start space-x-3">
<i class="fas fa-check-circle text-green-600 mt-1"></i>
<div class="flex-1">
<p class="text-sm font-medium text-gray-900">Location Captured</p>
<p id="locationAddress" class="text-sm text-gray-600"></p>
<p id="locationCoords" class="text-xs text-gray-500 mt-1"></p>
</div>
</div>
</div>
<div id="locationError" class="hidden bg-red-50 border border-red-200 rounded-lg p-3">
<div class="flex items-start space-x-3">
<i class="fas fa-exclamation-triangle text-red-600 mt-1"></i>
<div class="flex-1">
<p class="text-sm font-medium text-red-900">Location Access Denied</p>
<p class="text-sm text-red-700">You can still submit without location data.</p>
</div>
</div>
</div>
</div>
<!-- Hidden fields for GPS data -->
<input type="hidden" id="latitude" name="latitude">
<input type="hidden" id="longitude" name="longitude">
<input type="hidden" id="location_accuracy" name="location_accuracy">
<input type="hidden" id="location_address" name="location_address">
</div>
<!-- Submit Button -->
<div class="pt-6">
<button type="submit"
<?php echo !$registration_status['is_open'] ? 'disabled' : ''; ?>
class="w-full <?php echo $registration_status['is_open'] ? 'gradient-bg hover:opacity-90' : 'bg-gray-400 cursor-not-allowed'; ?> text-white font-bold py-3 px-4 rounded-lg transition duration-300">
<?php if ($registration_status['is_open']): ?>
<i class="fas fa-paper-plane mr-2"></i>
Submit Attendance
<?php else: ?>
<i class="fas fa-lock mr-2"></i>
Registration Closed
<?php endif; ?>
</button>
</div>
</form>
</div>
<!-- Back to Programs -->
<div class="text-center mt-8">
<a href="../index.php" class="text-primary hover:text-blue-700 font-medium">
<i class="fas fa-arrow-left mr-2"></i>
Back to Program Selection
</a>
</div>
</div>
</div>
<script>
// Handle district/assembly relationship
function loadAssemblies() {
const districtId = document.getElementById('district_id').value;
const assemblySelect = document.getElementById('assembly_id');
const allOptions = assemblySelect.querySelectorAll('option[data-district]');
// Reset assembly selection
assemblySelect.value = '';
// Show/hide assembly options based on selected district
allOptions.forEach(option => {
if (districtId === '' || option.dataset.district === districtId) {
option.style.display = 'block';
} else {
option.style.display = 'none';
}
});
// If only one assembly available for the district, auto-select it
const visibleOptions = Array.from(allOptions).filter(option =>
option.style.display !== 'none' && option.value !== ''
);
if (visibleOptions.length === 1) {
assemblySelect.value = visibleOptions[0].value;
}
// Update assembly dropdown placeholder and state
const placeholder = assemblySelect.querySelector('option[value=""]');
if (districtId === '') {
placeholder.textContent = 'First select a district';
assemblySelect.disabled = true;
assemblySelect.classList.add('bg-gray-100', 'cursor-not-allowed');
} else if (visibleOptions.length === 0) {
placeholder.textContent = 'No assemblies available for this district';
assemblySelect.disabled = true;
assemblySelect.classList.add('bg-gray-100', 'cursor-not-allowed');
} else {
placeholder.textContent = 'Select an Assembly';
assemblySelect.disabled = false;
assemblySelect.classList.remove('bg-gray-100', 'cursor-not-allowed');
}
}
// Form validation
document.querySelector('form').addEventListener('submit', function(e) {
const fullName = document.getElementById('full_name').value.trim();
const districtId = document.getElementById('district_id').value;
const assemblyId = document.getElementById('assembly_id').value;
if (!fullName) {
e.preventDefault();
alert('Please enter your full name.');
document.getElementById('full_name').focus();
return false;
}
if (!districtId) {
e.preventDefault();
alert('Please select a district.');
document.getElementById('district_id').focus();
return false;
}
if (!assemblyId) {
e.preventDefault();
alert('Please select an assembly.');
document.getElementById('assembly_id').focus();
return false;
}
// Show loading state
const submitBtn = this.querySelector('button[type="submit"]');
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Submitting...';
submitBtn.disabled = true;
});
// Auto-format phone number
const phoneInput = document.getElementById('telephone');
if (phoneInput) {
phoneInput.addEventListener('input', function(e) {
let value = e.target.value.replace(/\D/g, '');
if (value.length >= 10) {
value = value.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
}
e.target.value = value;
});
}
// GPS Location functionality
let locationCaptured = false;
// Automatically try to get location on page load
function autoGetLocation() {
if (navigator.geolocation) {
const locationStatus = document.getElementById('locationStatus');
locationStatus.textContent = 'Detecting...';
locationStatus.className = 'text-sm text-blue-600';
navigator.geolocation.getCurrentPosition(
function(position) {
handleLocationSuccess(position, true);
},
function(error) {
console.log('Auto location failed:', error);
// Don't show error for automatic detection, just leave it as optional
const locationStatus = document.getElementById('locationStatus');
locationStatus.textContent = 'Optional';
locationStatus.className = 'text-sm text-gray-600';
},
{
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 300000
}
);
}
}
function handleLocationSuccess(position, isAutomatic = false) {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
const accuracy = position.coords.accuracy;
// Store coordinates in hidden fields
document.getElementById('latitude').value = lat;
document.getElementById('longitude').value = lng;
document.getElementById('location_accuracy').value = accuracy;
// Update UI
locationCaptured = true;
const locationStatus = document.getElementById('locationStatus');
const locationInfo = document.getElementById('locationInfo');
const btn = document.getElementById('getLocationBtn');
const btnText = document.getElementById('locationBtnText');
locationStatus.textContent = isAutomatic ? 'Auto-detected' : 'Captured';
locationStatus.className = 'text-sm text-green-600 font-medium';
// Show coordinates
document.getElementById('locationCoords').textContent =
`Coordinates: ${lat.toFixed(6)}, ${lng.toFixed(6)} (±${Math.round(accuracy)}m)`;
// Try to get address using reverse geocoding
reverseGeocode(lat, lng);
// Show success message
locationInfo.classList.remove('hidden');
// Update button
btn.disabled = false;
btnText.textContent = isAutomatic ? 'Location Auto-detected' : 'Location Captured';
btn.classList.remove('opacity-50');
btn.classList.remove('bg-blue-600', 'hover:bg-blue-700');
btn.classList.add('bg-green-600', 'hover:bg-green-700');
}
document.getElementById('getLocationBtn').addEventListener('click', function() {
const btn = this;
const btnText = document.getElementById('locationBtnText');
const locationInfo = document.getElementById('locationInfo');
const locationError = document.getElementById('locationError');
const locationStatus = document.getElementById('locationStatus');
// Check if geolocation is supported
if (!navigator.geolocation) {
showLocationError('Geolocation is not supported by this browser.');
return;
}
// Update button state
btn.disabled = true;
btnText.textContent = 'Getting Location...';
btn.classList.add('opacity-50');
// Hide previous messages
locationInfo.classList.add('hidden');
locationError.classList.add('hidden');
// Get current position
navigator.geolocation.getCurrentPosition(
function(position) {
handleLocationSuccess(position, false);
},
function(error) {
let errorMessage = 'Unable to retrieve your location.';
switch(error.code) {
case error.PERMISSION_DENIED:
errorMessage = 'Location access denied by user.';
break;
case error.POSITION_UNAVAILABLE:
errorMessage = 'Location information is unavailable.';
break;
case error.TIMEOUT:
errorMessage = 'Location request timed out.';
break;
}
showLocationError(errorMessage);
},
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 300000 // 5 minutes
}
);
});
function showLocationError(message) {
const btn = document.getElementById('getLocationBtn');
const btnText = document.getElementById('locationBtnText');
const locationError = document.getElementById('locationError');
locationError.querySelector('.text-red-700').textContent = message;
locationError.classList.remove('hidden');
// Reset button
btn.disabled = false;
btnText.textContent = 'Try Again';
btn.classList.remove('opacity-50');
}
function reverseGeocode(lat, lng) {
// Using a free geocoding service (OpenStreetMap Nominatim)
fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&zoom=18&addressdetails=1`)
.then(response => response.json())
.then(data => {
if (data && data.display_name) {
const address = data.display_name;
document.getElementById('location_address').value = address;
document.getElementById('locationAddress').textContent = address;
} else {
document.getElementById('locationAddress').textContent = 'Address not available';
}
})
.catch(error => {
console.log('Reverse geocoding failed:', error);
document.getElementById('locationAddress').textContent = 'Address lookup failed';
});
}
// Initialize everything when page loads
document.addEventListener('DOMContentLoaded', function() {
// Load assemblies based on district selection
loadAssemblies();
// Disable form inputs if registration is closed
<?php if (!$registration_status['is_open']): ?>
const formInputs = document.querySelectorAll('#attendanceForm input, #attendanceForm select, #attendanceForm textarea, #attendanceForm button');
formInputs.forEach(function(input) {
if (input.type !== 'hidden') {
input.disabled = true;
input.classList.add('opacity-50', 'cursor-not-allowed');
}
});
<?php endif; ?>
// Automatically try to get GPS location
<?php if ($registration_status['is_open']): ?>
setTimeout(function() {
autoGetLocation();
}, 1000); // Wait 1 second after page load
<?php endif; ?>
// Check if location was previously captured (for form resubmission)
const lat = document.getElementById('latitude').value;
const lng = document.getElementById('longitude').value;
if (lat && lng) {
locationCaptured = true;
const locationStatus = document.getElementById('locationStatus');
const locationInfo = document.getElementById('locationInfo');
const btn = document.getElementById('getLocationBtn');
const btnText = document.getElementById('locationBtnText');
locationStatus.textContent = 'Captured';
locationStatus.className = 'text-sm text-green-600 font-medium';
document.getElementById('locationCoords').textContent =
`Coordinates: ${parseFloat(lat).toFixed(6)}, ${parseFloat(lng).toFixed(6)}`;
locationInfo.classList.remove('hidden');
btnText.textContent = 'Location Captured';
btn.classList.remove('bg-blue-600', 'hover:bg-blue-700');
btn.classList.add('bg-green-600', 'hover:bg-green-700');
}
});
// Function to exit the form
function exitForm() {
if (confirm('Are you sure you want to exit the attendance form?')) {
window.location.href = '../index.php';
}
}
// Function to check attendance status
function checkStatus() {
// Extract tracking code from error message
const errorText = document.querySelector('.bg-red-100 span').textContent;
const trackingCodeMatch = errorText.match(/tracking code is: ([A-Z0-9]+)/);
if (trackingCodeMatch && trackingCodeMatch[1]) {
const trackingCode = trackingCodeMatch[1];
window.open('../check_status.php?code=' + trackingCode, '_blank');
} else {
alert('Unable to extract tracking code. Please check your status manually.');
}
}
</script>
</body>
</html>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists