Sindbad~EG File Manager
<?php
session_start();
require_once '../includes/functions.php';
// Check if user is logged in and has admin privileges
if (!isLoggedIn() || (!hasRole('superuser') && !hasRole('area_admin'))) {
header('Location: ../login.php');
exit;
}
$db = new CopMadinaDB();
$conn = $db->getConnection();
$user = getCurrentUser();
$success = '';
$error = '';
// Handle form submissions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['action'])) {
switch ($_POST['action']) {
case 'create':
$name = trim($_POST['name']);
$description = trim($_POST['description']);
$form_fields = $_POST['form_fields'] ?? '[]';
try {
$stmt = $conn->prepare("INSERT INTO event_form_templates (name, description, form_fields, created_by) VALUES (?, ?, ?, ?)");
$stmt->execute([$name, $description, $form_fields, $user['id']]);
$success = "Form template created successfully!";
} catch (PDOException $e) {
$error = "Error creating form template: " . $e->getMessage();
}
break;
case 'update':
$id = (int)$_POST['template_id'];
$name = trim($_POST['name']);
$description = trim($_POST['description']);
$status = $_POST['status'];
$form_fields = $_POST['form_fields'] ?? '[]';
try {
$stmt = $conn->prepare("UPDATE event_form_templates SET name = ?, description = ?, form_fields = ?, status = ? WHERE id = ?");
$stmt->execute([$name, $description, $form_fields, $status, $id]);
$success = "Form template updated successfully!";
} catch (PDOException $e) {
$error = "Error updating form template: " . $e->getMessage();
}
break;
case 'delete':
$id = (int)$_POST['template_id'];
try {
$stmt = $conn->prepare("DELETE FROM event_form_templates WHERE id = ?");
$stmt->execute([$id]);
$success = "Form template deleted successfully!";
} catch (PDOException $e) {
$error = "Error deleting form template: " . $e->getMessage();
}
break;
}
}
}
// Get templates with pagination
$page = (int)($_GET['page'] ?? 1);
$limit = 10;
$offset = ($page - 1) * $limit;
$search = $_GET['search'] ?? '';
$status_filter = $_GET['status'] ?? '';
$where_conditions = [];
$params = [];
if (!empty($search)) {
$where_conditions[] = "(name LIKE ? OR description LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
}
if (!empty($status_filter)) {
$where_conditions[] = "status = ?";
$params[] = $status_filter;
}
$where_clause = !empty($where_conditions) ? "WHERE " . implode(" AND ", $where_conditions) : "";
// Get total count
$count_sql = "SELECT COUNT(*) FROM event_form_templates $where_clause";
$count_stmt = $conn->prepare($count_sql);
$count_stmt->execute($params);
$total_templates = $count_stmt->fetchColumn();
$total_pages = ceil($total_templates / $limit);
// Get templates
$sql = "SELECT eft.*, u.first_name, u.last_name
FROM event_form_templates eft
LEFT JOIN users u ON eft.created_by = u.id
$where_clause
ORDER BY eft.created_at DESC
LIMIT $limit OFFSET $offset";
$stmt = $conn->prepare($sql);
$stmt->execute($params);
$templates = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Get template for editing if requested
$edit_template = null;
if (isset($_GET['edit'])) {
$edit_id = (int)$_GET['edit'];
$stmt = $conn->prepare("SELECT * FROM event_form_templates WHERE id = ?");
$stmt->execute([$edit_id]);
$edit_template = $stmt->fetch(PDO::FETCH_ASSOC);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form Builder - COP Madina Admin</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body class="bg-gradient-to-br from-blue-50 via-white to-purple-50 min-h-screen">
<?php include 'includes/admin_sidebar.php'; ?>
<div class="ml-72 p-8">
<div class="max-w-7xl mx-auto">
<!-- Header -->
<div class="mb-8">
<div class="flex items-center justify-between">
<div>
<h1 class="text-3xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
Form Builder
</h1>
<p class="text-slate-600 mt-2">Create and manage event registration form templates</p>
</div>
<button onclick="showCreateModal()" class="px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white font-medium rounded-xl transition-all duration-200 shadow-lg hover:shadow-xl">
<i class="fas fa-plus mr-2"></i>
Create Form Template
</button>
</div>
</div>
<!-- Alerts -->
<?php if ($success): ?>
<div class="mb-6 p-4 bg-green-50 border border-green-200 rounded-xl text-green-800">
<i class="fas fa-check-circle mr-2"></i>
<?php echo htmlspecialchars($success); ?>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="mb-6 p-4 bg-red-50 border border-red-200 rounded-xl text-red-800">
<i class="fas fa-exclamation-circle mr-2"></i>
<?php echo htmlspecialchars($error); ?>
</div>
<?php endif; ?>
<!-- Filters -->
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-xl border border-white/20 p-6 mb-8">
<form method="GET" class="flex flex-wrap gap-4 items-end">
<div class="flex-1 min-w-64">
<label class="block text-sm font-medium text-slate-700 mb-2">Search Templates</label>
<input type="text" name="search" value="<?php echo htmlspecialchars($search); ?>"
placeholder="Search by name or description..."
class="w-full px-4 py-3 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent">
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-2">Status</label>
<select name="status" class="px-4 py-3 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent">
<option value="">All Statuses</option>
<option value="active" <?php echo $status_filter === 'active' ? 'selected' : ''; ?>>Active</option>
<option value="inactive" <?php echo $status_filter === 'inactive' ? 'selected' : ''; ?>>Inactive</option>
</select>
</div>
<button type="submit" class="px-6 py-3 bg-slate-600 hover:bg-slate-700 text-white font-medium rounded-xl transition-all duration-200">
<i class="fas fa-search mr-2"></i>
Search
</button>
<a href="form-builder.php" class="px-6 py-3 bg-slate-200 hover:bg-slate-300 text-slate-700 font-medium rounded-xl transition-all duration-200">
<i class="fas fa-times mr-2"></i>
Clear
</a>
</form>
</div>
<!-- Templates Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
<?php foreach ($templates as $template): ?>
<?php $form_fields = json_decode($template['form_fields'], true) ?? []; ?>
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-xl border border-white/20 p-6 hover:shadow-2xl transition-all duration-200">
<div class="flex items-start justify-between mb-4">
<div class="flex-1">
<h3 class="text-lg font-semibold text-slate-800 mb-1"><?php echo htmlspecialchars($template['name']); ?></h3>
<p class="text-sm text-slate-600"><?php echo htmlspecialchars($template['description']); ?></p>
</div>
<span class="px-3 py-1 text-xs font-medium rounded-full <?php echo $template['status'] === 'active' ? 'bg-green-100 text-green-800' : 'bg-slate-100 text-slate-600'; ?>">
<?php echo ucfirst($template['status']); ?>
</span>
</div>
<div class="space-y-2 mb-4">
<div class="flex items-center text-sm text-slate-600">
<i class="fas fa-list mr-2 text-blue-500"></i>
Fields: <?php echo count($form_fields); ?>
</div>
<div class="text-xs text-slate-500">
Created by <?php echo htmlspecialchars($template['first_name'] . ' ' . $template['last_name']); ?>
<br>
<?php echo date('M j, Y', strtotime($template['created_at'])); ?>
</div>
</div>
<div class="flex gap-2">
<a href="?edit=<?php echo $template['id']; ?>"
class="flex-1 px-3 py-2 bg-blue-100 hover:bg-blue-200 text-blue-700 text-sm font-medium rounded-lg transition-all duration-200 text-center">
<i class="fas fa-edit mr-1"></i>
Edit
</a>
<button onclick="deleteTemplate(<?php echo $template['id']; ?>, '<?php echo htmlspecialchars($template['name']); ?>')"
class="flex-1 px-3 py-2 bg-red-100 hover:bg-red-200 text-red-700 text-sm font-medium rounded-lg transition-all duration-200">
<i class="fas fa-trash mr-1"></i>
Delete
</button>
</div>
</div>
<?php endforeach; ?>
</div>
<!-- Pagination -->
<?php if ($total_pages > 1): ?>
<div class="flex justify-center">
<nav class="flex space-x-2">
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
<a href="?page=<?php echo $i; ?>&search=<?php echo urlencode($search); ?>&status=<?php echo urlencode($status_filter); ?>"
class="px-4 py-2 <?php echo $i === $page ? 'bg-blue-600 text-white' : 'bg-white text-slate-600 hover:bg-slate-50'; ?> rounded-lg transition-all duration-200">
<?php echo $i; ?>
</a>
<?php endfor; ?>
</nav>
</div>
<?php endif; ?>
</div>
</div>
<!-- Simple Form Builder Modal -->
<div id="formBuilderModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden items-center justify-center z-50">
<div class="bg-white rounded-2xl shadow-2xl max-w-4xl w-full mx-4 max-h-[90vh] overflow-y-auto">
<form method="POST" class="p-8">
<div class="flex items-center justify-between mb-6">
<h2 class="text-2xl font-bold text-slate-800" id="modalTitle">Create Form Template</h2>
<button type="button" onclick="hideModal()" class="text-slate-400 hover:text-slate-600">
<i class="fas fa-times text-xl"></i>
</button>
</div>
<input type="hidden" name="action" id="modalAction" value="create">
<input type="hidden" name="template_id" id="templateId">
<input type="hidden" name="form_fields" id="formFieldsData" value="[]">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<label class="block text-sm font-medium text-slate-700 mb-2">Template Name *</label>
<input type="text" name="name" id="templateName" required
class="w-full px-4 py-3 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent">
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-2">Description</label>
<input type="text" name="description" id="templateDescription"
class="w-full px-4 py-3 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent">
</div>
</div>
<div id="statusField" class="hidden mb-6">
<label class="block text-sm font-medium text-slate-700 mb-2">Status</label>
<select name="status" id="templateStatus"
class="w-full px-4 py-3 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent">
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</select>
</div>
<!-- Simple Form Builder -->
<div class="border border-slate-200 rounded-xl p-6 mb-6">
<h3 class="text-lg font-semibold text-slate-700 mb-4">Form Fields</h3>
<div id="formFields">
<!-- Fields will be added here -->
</div>
<button type="button" onclick="addFormField()" class="mt-4 px-4 py-2 bg-blue-100 hover:bg-blue-200 text-blue-700 rounded-lg transition-all duration-200">
<i class="fas fa-plus mr-2"></i>
Add Field
</button>
</div>
<div class="flex justify-end gap-4 pt-6 border-t">
<button type="button" onclick="hideModal()"
class="px-6 py-3 bg-slate-200 hover:bg-slate-300 text-slate-700 font-medium rounded-xl transition-all duration-200">
Cancel
</button>
<button type="submit"
class="px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white font-medium rounded-xl transition-all duration-200">
<span id="submitText">Create Template</span>
</button>
</div>
</form>
</div>
</div>
<script>
let fieldCounter = 1;
function showCreateModal() {
document.getElementById('modalTitle').textContent = 'Create Form Template';
document.getElementById('modalAction').value = 'create';
document.getElementById('submitText').textContent = 'Create Template';
document.getElementById('statusField').classList.add('hidden');
// Reset form
document.querySelector('#formBuilderModal form').reset();
document.getElementById('templateId').value = '';
document.getElementById('formFields').innerHTML = '';
fieldCounter = 1;
document.getElementById('formBuilderModal').classList.remove('hidden');
document.getElementById('formBuilderModal').classList.add('flex');
}
function hideModal() {
document.getElementById('formBuilderModal').classList.add('hidden');
document.getElementById('formBuilderModal').classList.remove('flex');
}
function addFormField() {
const fieldId = fieldCounter++;
const fieldHtml = `
<div class="border border-slate-200 rounded-lg p-4 mb-4" id="field_${fieldId}">
<div class="flex items-center justify-between mb-4">
<h4 class="font-medium text-slate-700">Field ${fieldId}</h4>
<button type="button" onclick="removeField(${fieldId})" class="text-red-500 hover:text-red-700">
<i class="fas fa-trash"></i>
</button>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-slate-700 mb-2">Field Type</label>
<select class="w-full px-3 py-2 border border-slate-200 rounded-lg" onchange="updateFieldOptions(${fieldId}, this.value)">
<option value="text">Text Input</option>
<option value="email">Email</option>
<option value="tel">Phone</option>
<option value="textarea">Textarea</option>
<option value="select">Dropdown</option>
<option value="radio">Radio Buttons</option>
<option value="checkbox">Checkboxes</option>
<option value="date">Date</option>
<option value="number">Number</option>
<option value="file">File Upload</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-2">Label</label>
<input type="text" class="w-full px-3 py-2 border border-slate-200 rounded-lg" placeholder="Field label">
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-2">Placeholder</label>
<input type="text" class="w-full px-3 py-2 border border-slate-200 rounded-lg" placeholder="Placeholder text">
</div>
<div class="flex items-center">
<label class="flex items-center">
<input type="checkbox" class="mr-2">
<span class="text-sm text-slate-700">Required</span>
</label>
</div>
</div>
<div id="options_${fieldId}" class="hidden mt-4">
<label class="block text-sm font-medium text-slate-700 mb-2">Options (one per line)</label>
<textarea class="w-full px-3 py-2 border border-slate-200 rounded-lg" rows="3" placeholder="Option 1 Option 2 Option 3"></textarea>
</div>
</div>
`;
document.getElementById('formFields').insertAdjacentHTML('beforeend', fieldHtml);
}
function removeField(fieldId) {
document.getElementById(`field_${fieldId}`).remove();
}
function updateFieldOptions(fieldId, fieldType) {
const optionsDiv = document.getElementById(`options_${fieldId}`);
if (['select', 'radio', 'checkbox'].includes(fieldType)) {
optionsDiv.classList.remove('hidden');
} else {
optionsDiv.classList.add('hidden');
}
}
function collectFormData() {
const fields = [];
const fieldDivs = document.querySelectorAll('#formFields > div');
fieldDivs.forEach((div, index) => {
const inputs = div.querySelectorAll('input, select, textarea');
const fieldType = inputs[0].value;
const label = inputs[1].value;
const placeholder = inputs[2].value;
const required = inputs[3].checked;
const field = {
type: fieldType,
label: label,
placeholder: placeholder,
required: required
};
// Add options for select, radio, checkbox
if (['select', 'radio', 'checkbox'].includes(fieldType)) {
const optionsText = inputs[4] ? inputs[4].value : '';
field.options = optionsText.split('\n').filter(opt => opt.trim() !== '');
}
fields.push(field);
});
return fields;
}
// Override form submission to collect field data
document.querySelector('#formBuilderModal form').addEventListener('submit', function(e) {
const formData = collectFormData();
document.getElementById('formFieldsData').value = JSON.stringify(formData);
});
function deleteTemplate(id, name) {
if (confirm(`Are you sure you want to delete the template "${name}"? This action cannot be undone.`)) {
const form = document.createElement('form');
form.method = 'POST';
form.innerHTML = `
<input type="hidden" name="action" value="delete">
<input type="hidden" name="template_id" value="${id}">
`;
document.body.appendChild(form);
form.submit();
}
}
// Auto-open edit modal if edit parameter is present
<?php if ($edit_template): ?>
showCreateModal();
document.getElementById('modalTitle').textContent = 'Edit Form Template';
document.getElementById('modalAction').value = 'update';
document.getElementById('submitText').textContent = 'Update Template';
document.getElementById('statusField').classList.remove('hidden');
document.getElementById('templateId').value = '<?php echo $edit_template['id']; ?>';
document.getElementById('templateName').value = '<?php echo htmlspecialchars($edit_template['name']); ?>';
document.getElementById('templateDescription').value = '<?php echo htmlspecialchars($edit_template['description']); ?>';
document.getElementById('templateStatus').value = '<?php echo $edit_template['status']; ?>';
// Load existing fields
const existingFields = <?php echo $edit_template['form_fields'] ?? '[]'; ?>;
existingFields.forEach(field => {
addFormField();
const lastField = document.querySelector('#formFields > div:last-child');
const inputs = lastField.querySelectorAll('input, select, textarea');
inputs[0].value = field.type;
inputs[1].value = field.label;
inputs[2].value = field.placeholder || '';
inputs[3].checked = field.required || false;
updateFieldOptions(fieldCounter - 1, field.type);
if (field.options && inputs[4]) {
inputs[4].value = field.options.join('\n');
}
});
<?php endif; ?>
</script>
</body>
</html>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists