Recover project structure
This commit is contained in:
commit
6c8960d09d
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 71f2f59185314709834fd132e91636eca4d1d0fb
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/data.php';
|
||||||
|
$pageTitle = 'Achievements | CREST';
|
||||||
|
$metaDescription = 'See CREST milestones: lives impacted, doctors trained, studies completed, and partnerships across India.';
|
||||||
|
include __DIR__ . '/includes/site-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Achievements</p>
|
||||||
|
<h2 class="fw-bold mb-4">Milestones powered by data and collaboration</h2>
|
||||||
|
<div class="row row-cols-2 row-cols-md-4 g-3">
|
||||||
|
<div class="col">
|
||||||
|
<div class="stat-tile text-center p-3 rounded-4">
|
||||||
|
<div class="fw-bold">1Mn+</div>
|
||||||
|
<div class="text-muted small">Lives touched</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="stat-tile text-center p-3 rounded-4">
|
||||||
|
<div class="fw-bold">5k+</div>
|
||||||
|
<div class="text-muted small">Doctors trained</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="stat-tile text-center p-3 rounded-4">
|
||||||
|
<div class="fw-bold">500+</div>
|
||||||
|
<div class="text-muted small">Medical schools</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="stat-tile text-center p-3 rounded-4">
|
||||||
|
<div class="fw-bold">300+</div>
|
||||||
|
<div class="text-muted small">Research studies</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="text-muted mt-3">These numbers reflect multi-year partnerships, field programs, and training cohorts across India.</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/includes/site-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../includes/auth.php';
|
||||||
|
require_login();
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
$success = '';
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$email = trim($_POST['email'] ?? '');
|
||||||
|
$password = trim($_POST['password'] ?? '');
|
||||||
|
|
||||||
|
if ($email === '' || $password === '') {
|
||||||
|
$error = 'Email and password are required.';
|
||||||
|
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$error = 'Please enter a valid email.';
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
create_admin($email, $password);
|
||||||
|
$success = 'Admin added successfully.';
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$error = 'Could not add admin (maybe email already exists).';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
$admins = $pdo->query("SELECT email, created_at FROM admins ORDER BY created_at DESC");
|
||||||
|
$admins = is_array($admins) ? $admins : [];
|
||||||
|
$assetPathPrefix = '../';
|
||||||
|
$pageTitle = 'Admins';
|
||||||
|
$currentPage = '';
|
||||||
|
$extraStyles = <<<CSS
|
||||||
|
<style>
|
||||||
|
body { background: #f6faf7; }
|
||||||
|
.admin-shell { padding: 40px 0; }
|
||||||
|
.table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
||||||
|
.table th, .table td { text-align: left; padding: 12px 10px; border-bottom: 1px solid #e1ede7; }
|
||||||
|
.table th { color: #0f4333; }
|
||||||
|
form input { width: 100%; padding: 12px 14px; border-radius: 10px; border: 1px solid #d8e7e0; font-size: 15px; margin-top: 8px; }
|
||||||
|
form label { font-weight: 700; color: #0f4333; display: block; margin-top: 12px; }
|
||||||
|
</style>
|
||||||
|
CSS;
|
||||||
|
|
||||||
|
require __DIR__ . '/../includes/admin-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main class="admin-shell">
|
||||||
|
<div class="container">
|
||||||
|
<div class="topbar" style="display:flex; justify-content:space-between; align-items:center; margin-bottom:16px;">
|
||||||
|
<div>
|
||||||
|
<p class="eyebrow">Admins</p>
|
||||||
|
<h2>Manage administrator accounts</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="admin-nav">
|
||||||
|
<a href="/admin/tutorials.php">Tutorials</a>
|
||||||
|
<a href="/admin/sessions.php">Upcoming Sessions</a>
|
||||||
|
<a href="/admin/contacts.php">Contact Entries</a>
|
||||||
|
<a href="/admin/newsletter.php">Newsletter</a>
|
||||||
|
<a href="/admin/admins.php">Admins</a>
|
||||||
|
<a href="/admin/logout.php">Logout (<?php echo htmlspecialchars(current_admin_email() ?? ''); ?>)</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ($success): ?>
|
||||||
|
<div class="alert good"><?php echo htmlspecialchars($success); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="alert bad"><?php echo htmlspecialchars($error); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<h3>Add Admin</h3>
|
||||||
|
<form method="post">
|
||||||
|
<label for="email">Email</label>
|
||||||
|
<input type="email" id="email" name="email" required placeholder="admin@example.com">
|
||||||
|
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input type="password" id="password" name="password" required placeholder="Choose a secure password">
|
||||||
|
|
||||||
|
<div style="margin-top:16px;">
|
||||||
|
<button type="submit" class="btn primary">Add admin</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card" style="margin-top:20px;">
|
||||||
|
<h3>Existing Admins</h3>
|
||||||
|
<?php if (empty($admins)): ?>
|
||||||
|
<p class="body muted">No admins found.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Created</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($admins as $admin): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars($admin['email']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($admin['created_at']); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php require __DIR__ . '/../includes/admin-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../includes/auth.php';
|
||||||
|
require_login();
|
||||||
|
|
||||||
|
$contacts = get_contacts();
|
||||||
|
$isExport = isset($_GET['export']);
|
||||||
|
if ($isExport) {
|
||||||
|
header('Content-Type: text/csv');
|
||||||
|
header('Content-Disposition: attachment; filename="contacts.csv"');
|
||||||
|
$out = fopen('php://output', 'w');
|
||||||
|
fputcsv($out, ['Name', 'Email', 'Organization', 'Message', 'Received']);
|
||||||
|
foreach ($contacts as $c) {
|
||||||
|
fputcsv($out, [
|
||||||
|
$c['name'] ?? '',
|
||||||
|
$c['email'] ?? '',
|
||||||
|
$c['organization'] ?? '',
|
||||||
|
$c['message'] ?? '',
|
||||||
|
$c['created_at'] ?? '',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
fclose($out);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$assetPathPrefix = '../';
|
||||||
|
$pageTitle = 'Contact Entries';
|
||||||
|
$currentPage = 'contact';
|
||||||
|
$extraStyles = <<<CSS
|
||||||
|
<style>
|
||||||
|
body { background: #f6faf7; }
|
||||||
|
.admin-shell { padding: 40px 0; }
|
||||||
|
.table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
||||||
|
.table th, .table td { text-align: left; padding: 12px 10px; border-bottom: 1px solid #e1ede7; vertical-align: top; }
|
||||||
|
.table th { color: #0f4333; }
|
||||||
|
</style>
|
||||||
|
CSS;
|
||||||
|
|
||||||
|
require __DIR__ . '/../includes/admin-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main class="admin-shell">
|
||||||
|
<div class="container">
|
||||||
|
<div class="topbar" style="display:flex; justify-content:space-between; align-items:center; margin-bottom:16px;">
|
||||||
|
<div>
|
||||||
|
<p class="eyebrow">Contact Entries</p>
|
||||||
|
<h2>Messages from the contact form</h2>
|
||||||
|
</div>
|
||||||
|
<div class="btn ghost" style="pointer-events:none;">Read-only</div>
|
||||||
|
</div>
|
||||||
|
<div class="admin-nav">
|
||||||
|
<a href="/admin/tutorials.php">Tutorials</a>
|
||||||
|
<a href="/admin/sessions.php">Upcoming Sessions</a>
|
||||||
|
<a href="/admin/contacts.php">Contact Entries</a>
|
||||||
|
<a href="/admin/newsletter.php">Newsletter</a>
|
||||||
|
<a href="/admin/admins.php">Admins</a>
|
||||||
|
<a href="/admin/logout.php">Logout (<?php echo htmlspecialchars(current_admin_email() ?? ''); ?>)</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin:10px 0;">
|
||||||
|
<a class="btn outline small" href="?export=1">Export CSV</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if (empty($contacts)): ?>
|
||||||
|
<p class="body muted">No messages yet.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Organization</th>
|
||||||
|
<th>Message</th>
|
||||||
|
<th>Received</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($contacts as $contact): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars($contact['name']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($contact['email']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($contact['organization'] ?? ''); ?></td>
|
||||||
|
<td><?php echo nl2br(htmlspecialchars($contact['message'])); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($contact['created_at']); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php require __DIR__ . '/../includes/admin-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../includes/auth.php';
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$email = trim($_POST['email'] ?? '');
|
||||||
|
$password = trim($_POST['password'] ?? '');
|
||||||
|
if ($email === '' || $password === '') {
|
||||||
|
$error = 'Email and password are required.';
|
||||||
|
} elseif (attempt_login($email, $password)) {
|
||||||
|
header('Location: /admin/resources.php');
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$error = 'Invalid credentials.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$pageTitle = 'Admin Login';
|
||||||
|
$currentPage = '';
|
||||||
|
$assetPathPrefix = '../';
|
||||||
|
require __DIR__ . '/../includes/admin-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main class="section">
|
||||||
|
<div class="container" style="max-width:480px;">
|
||||||
|
<div class="card">
|
||||||
|
<h2>Admin Login</h2>
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="alert bad" style="margin-top:12px;"><?php echo htmlspecialchars($error); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<form method="post" style="display:grid; gap:12px; margin-top:12px;">
|
||||||
|
<div>
|
||||||
|
<label for="email">Email</label>
|
||||||
|
<input type="email" id="email" name="email" required placeholder="admin@example.com">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input type="password" id="password" name="password" required placeholder="••••••••">
|
||||||
|
</div>
|
||||||
|
<button class="btn primary" type="submit">Login</button>
|
||||||
|
<p class="body muted" style="font-size:13px;">Default admin: ravi@stratawiz.com / qwerty</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php require __DIR__ . '/../includes/admin-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../includes/auth.php';
|
||||||
|
logout();
|
||||||
|
header('Location: /admin/login.php');
|
||||||
|
exit;
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../includes/auth.php';
|
||||||
|
require_login();
|
||||||
|
|
||||||
|
$subs = get_subscriptions();
|
||||||
|
$isExport = isset($_GET['export']);
|
||||||
|
if ($isExport) {
|
||||||
|
header('Content-Type: text/csv');
|
||||||
|
header('Content-Disposition: attachment; filename="newsletter.csv"');
|
||||||
|
$out = fopen('php://output', 'w');
|
||||||
|
fputcsv($out, ['First Name', 'Email', 'Subscribed']);
|
||||||
|
foreach ($subs as $s) {
|
||||||
|
fputcsv($out, [
|
||||||
|
$s['first_name'] ?? '',
|
||||||
|
$s['email'] ?? '',
|
||||||
|
$s['created_at'] ?? '',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
fclose($out);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$assetPathPrefix = '../';
|
||||||
|
$pageTitle = 'Newsletter Subscribers';
|
||||||
|
$currentPage = 'news';
|
||||||
|
$extraStyles = <<<CSS
|
||||||
|
<style>
|
||||||
|
body { background: #f6faf7; }
|
||||||
|
.admin-shell { padding: 40px 0; }
|
||||||
|
.table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
||||||
|
.table th, .table td { text-align: left; padding: 12px 10px; border-bottom: 1px solid #e1ede7; }
|
||||||
|
.table th { color: #0f4333; }
|
||||||
|
</style>
|
||||||
|
CSS;
|
||||||
|
|
||||||
|
require __DIR__ . '/../includes/admin-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main class="admin-shell">
|
||||||
|
<div class="container">
|
||||||
|
<div class="topbar" style="display:flex; justify-content:space-between; align-items:center; margin-bottom:16px;">
|
||||||
|
<div>
|
||||||
|
<p class="eyebrow">Newsletter</p>
|
||||||
|
<h2>Subscription list</h2>
|
||||||
|
</div>
|
||||||
|
<div class="btn ghost" style="pointer-events:none;">Read-only</div>
|
||||||
|
</div>
|
||||||
|
<div class="admin-nav">
|
||||||
|
<a href="/admin/tutorials.php">Tutorials</a>
|
||||||
|
<a href="/admin/sessions.php">Upcoming Sessions</a>
|
||||||
|
<a href="/admin/contacts.php">Contact Entries</a>
|
||||||
|
<a href="/admin/newsletter.php">Newsletter</a>
|
||||||
|
<a href="/admin/admins.php">Admins</a>
|
||||||
|
<a href="/admin/logout.php">Logout (<?php echo htmlspecialchars(current_admin_email() ?? ''); ?>)</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin:10px 0;">
|
||||||
|
<a class="btn outline small" href="?export=1">Export CSV</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if (empty($subs)): ?>
|
||||||
|
<p class="body muted">No subscribers yet.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>First Name</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Subscribed</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($subs as $sub): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars($sub['first_name'] ?? ''); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($sub['email']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($sub['created_at']); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php require __DIR__ . '/../includes/admin-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,191 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../includes/auth.php';
|
||||||
|
require_login();
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
$uploadDir = __DIR__ . '/../uploads/';
|
||||||
|
if (!is_dir($uploadDir)) {
|
||||||
|
mkdir($uploadDir, 0775, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$title = trim($_POST['title'] ?? '');
|
||||||
|
$summary = trim($_POST['summary'] ?? '');
|
||||||
|
$label = trim($_POST['label'] ?? '');
|
||||||
|
$video_url = trim($_POST['video_url'] ?? '');
|
||||||
|
$file_path = null;
|
||||||
|
|
||||||
|
if (isset($_FILES['resource_file']) && $_FILES['resource_file']['error'] !== UPLOAD_ERR_NO_FILE) {
|
||||||
|
$file = $_FILES['resource_file'];
|
||||||
|
if ($file['error'] === UPLOAD_ERR_OK) {
|
||||||
|
$allowed = [
|
||||||
|
'application/pdf',
|
||||||
|
'application/msword',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
||||||
|
];
|
||||||
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||||
|
$mime = finfo_file($finfo, $file['tmp_name']);
|
||||||
|
finfo_close($finfo);
|
||||||
|
if (!in_array($mime, $allowed, true)) {
|
||||||
|
$error = 'Only PDF or Word documents are allowed.';
|
||||||
|
} else {
|
||||||
|
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||||||
|
$newName = 'resource_' . time() . '_' . mt_rand(1000, 9999) . '.' . $ext;
|
||||||
|
$dest = $uploadDir . $newName;
|
||||||
|
if (move_uploaded_file($file['tmp_name'], $dest)) {
|
||||||
|
$file_path = 'uploads/' . $newName;
|
||||||
|
} else {
|
||||||
|
$error = 'File upload failed.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$error = 'File upload failed.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($title === '' || $summary === '' || $label === '') {
|
||||||
|
$error = 'All fields are required.';
|
||||||
|
} elseif (!$error) {
|
||||||
|
add_resource(compact('title', 'summary', 'label', 'file_path', 'video_url'));
|
||||||
|
header('Location: resources.php?success=1');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_GET['delete'])) {
|
||||||
|
$id = (int) $_GET['delete'];
|
||||||
|
delete_resource($id);
|
||||||
|
header('Location: resources.php?deleted=1');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$resources = get_resources();
|
||||||
|
echo '<pre>'; print_r($resources); exit;
|
||||||
|
$assetPathPrefix = '../';
|
||||||
|
$pageTitle = 'Manage Resources';
|
||||||
|
$currentPage = 'resources';
|
||||||
|
$extraStyles = <<<CSS
|
||||||
|
<style>
|
||||||
|
body { background: #f6faf7; }
|
||||||
|
.admin-shell { padding: 40px 0; }
|
||||||
|
.table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
||||||
|
.table th, .table td { text-align: left; padding: 12px 10px; border-bottom: 1px solid #e1ede7; }
|
||||||
|
.table th { color: #0f4333; }
|
||||||
|
.badge { display: inline-block; padding: 6px 10px; border-radius: 10px; background: #e8f5ef; color: #0f4333; font-weight: 700; font-size: 13px; }
|
||||||
|
.inline-btn { color: #b9342f; font-weight: 700; }
|
||||||
|
form textarea { min-height: 120px; resize: vertical; }
|
||||||
|
form input, form textarea { width: 100%; padding: 12px 14px; border-radius: 10px; border: 1px solid #d8e7e0; font-size: 15px; margin-top: 8px; }
|
||||||
|
form input[type=file] { padding: 8px; }
|
||||||
|
form label { font-weight: 700; color: #0f4333; display: block; margin-top: 12px; }
|
||||||
|
.topbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
|
||||||
|
</style>
|
||||||
|
CSS;
|
||||||
|
|
||||||
|
require __DIR__ . '/../includes/admin-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main class="admin-shell">
|
||||||
|
<div class="container">
|
||||||
|
<div class="topbar">
|
||||||
|
<div>
|
||||||
|
<p class="eyebrow">Resources</p>
|
||||||
|
<h2>Resources for Learning and Research</h2>
|
||||||
|
<p class="body">Add short descriptions and labels; they will appear instantly on the public site.</p>
|
||||||
|
</div>
|
||||||
|
<button class="btn primary" onclick="document.getElementById('resource-form').scrollIntoView({behavior: 'smooth'})">Add new</button>
|
||||||
|
</div>
|
||||||
|
<div class="admin-nav">
|
||||||
|
<a href="/admin/tutorials.php">Tutorials</a>
|
||||||
|
<a href="/admin/sessions.php">Upcoming Sessions</a>
|
||||||
|
<a href="/admin/contacts.php">Contact Entries</a>
|
||||||
|
<a href="/admin/newsletter.php">Newsletter</a>
|
||||||
|
<a href="/admin/admins.php">Admins</a>
|
||||||
|
<a href="/admin/logout.php">Logout (<?php echo htmlspecialchars(current_admin_email() ?? ''); ?>)</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if (isset($_GET['success'])): ?>
|
||||||
|
<div class="alert good">Resource added successfully.</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_GET['deleted'])): ?>
|
||||||
|
<div class="alert good">Resource deleted.</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="alert bad"><?php echo htmlspecialchars($error); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (empty($resources)): ?>
|
||||||
|
<p class="body muted">No resources yet. Add your first entry below.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Summary</th>
|
||||||
|
<th>Label</th>
|
||||||
|
<th>Asset</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($resources as $index => $resource): ?>
|
||||||
|
<?php
|
||||||
|
if (!is_array($resource)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$title = htmlspecialchars((string)($resource['title'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$summary = htmlspecialchars((string)($resource['summary'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$label = htmlspecialchars((string)($resource['label'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$filePath = (string)($resource['file_path'] ?? '');
|
||||||
|
$videoUrl = (string)($resource['video_url'] ?? '');
|
||||||
|
?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo $title; ?></td>
|
||||||
|
<td><?php echo $summary; ?></td>
|
||||||
|
<td><span class="badge"><?php echo $label; ?></span></td>
|
||||||
|
<td>
|
||||||
|
<?php if ($filePath): ?>
|
||||||
|
<a class="text-link" href="/<?php echo htmlspecialchars(ltrim($filePath, '/'), ENT_QUOTES, 'UTF-8'); ?>" target="_blank">Download</a>
|
||||||
|
<?php elseif ($videoUrl): ?>
|
||||||
|
<a class="text-link" href="<?php echo htmlspecialchars($videoUrl, ENT_QUOTES, 'UTF-8'); ?>" target="_blank">Watch</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="body muted">None</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td><a class="inline-btn" href="?delete=<?php echo (int)$resource['id']; ?>" onclick="return confirm('Delete this resource?')">Delete</a></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<section id="resource-form" style="margin-top:32px;">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Add Resource</h3>
|
||||||
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
<label for="title">Title</label>
|
||||||
|
<input type="text" id="title" name="title" required placeholder="Resource title">
|
||||||
|
|
||||||
|
<label for="summary">Summary</label>
|
||||||
|
<textarea id="summary" name="summary" required placeholder="Brief description"></textarea>
|
||||||
|
|
||||||
|
<label for="label">Label / Type</label>
|
||||||
|
<input type="text" id="label" name="label" required placeholder="e.g., Publication, Toolkit">
|
||||||
|
|
||||||
|
<label for="video_url">YouTube / Video URL (optional)</label>
|
||||||
|
<input type="url" id="video_url" name="video_url" placeholder="https://youtube.com/...">
|
||||||
|
|
||||||
|
<label for="resource_file">Upload PDF / Word (optional)</label>
|
||||||
|
<input type="file" id="resource_file" name="resource_file" accept=".pdf,.doc,.docx">
|
||||||
|
<p class="body muted" style="margin:6px 0 0;">Upload a file or provide a video URL (or both).</p>
|
||||||
|
|
||||||
|
<div style="margin-top:16px;">
|
||||||
|
<button type="submit" class="btn primary">Save resource</button>
|
||||||
|
<a class="text-link" href="../index.php" style="margin-left:10px;">View live site</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php require __DIR__ . '/../includes/admin-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../includes/auth.php';
|
||||||
|
require_login();
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$title = trim($_POST['title'] ?? '');
|
||||||
|
$description = trim($_POST['description'] ?? '');
|
||||||
|
$tag = trim($_POST['tag'] ?? '');
|
||||||
|
$cta_label = trim($_POST['cta_label'] ?? 'Register');
|
||||||
|
$start_date = $_POST['start_date'] ?? null;
|
||||||
|
$editId = isset($_POST['id']) ? (int) $_POST['id'] : null;
|
||||||
|
|
||||||
|
if ($title === '' || $description === '') {
|
||||||
|
$error = 'Title and description are required.';
|
||||||
|
} else {
|
||||||
|
if ($editId) {
|
||||||
|
update_session($editId, compact('title', 'description', 'tag', 'cta_label', 'start_date'));
|
||||||
|
header('Location: sessions.php?updated=1');
|
||||||
|
} else {
|
||||||
|
add_session(compact('title', 'description', 'tag', 'cta_label', 'start_date'));
|
||||||
|
header('Location: sessions.php?success=1');
|
||||||
|
}
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_GET['delete'])) {
|
||||||
|
$id = (int) $_GET['delete'];
|
||||||
|
delete_session($id);
|
||||||
|
header('Location: sessions.php?deleted=1');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sessions = get_sessions();
|
||||||
|
$editing = null;
|
||||||
|
if (isset($_GET['edit'])) {
|
||||||
|
$editId = (int) $_GET['edit'];
|
||||||
|
foreach ($sessions as $row) {
|
||||||
|
if ((int) $row['id'] === $editId) {
|
||||||
|
$editing = $row;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$assetPathPrefix = '../';
|
||||||
|
$pageTitle = 'Manage Sessions';
|
||||||
|
$currentPage = 'news';
|
||||||
|
$extraStyles = <<<CSS
|
||||||
|
<style>
|
||||||
|
body { background: #f6faf7; }
|
||||||
|
.admin-shell { padding: 40px 0; }
|
||||||
|
.table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
||||||
|
.table th, .table td { text-align: left; padding: 12px 10px; border-bottom: 1px solid #e1ede7; }
|
||||||
|
.table th { color: #0f4333; }
|
||||||
|
.badge { display: inline-block; padding: 6px 10px; border-radius: 10px; background: #e8f5ef; color: #0f4333; font-weight: 700; font-size: 13px; }
|
||||||
|
.inline-btn { color: #b9342f; font-weight: 700; }
|
||||||
|
form textarea { min-height: 120px; resize: vertical; }
|
||||||
|
form input, form textarea { width: 100%; padding: 12px 14px; border-radius: 10px; border: 1px solid #d8e7e0; font-size: 15px; margin-top: 8px; }
|
||||||
|
form label { font-weight: 700; color: #0f4333; display: block; margin-top: 12px; }
|
||||||
|
.topbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
|
||||||
|
</style>
|
||||||
|
CSS;
|
||||||
|
|
||||||
|
require __DIR__ . '/../includes/admin-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main class="admin-shell">
|
||||||
|
<div class="container">
|
||||||
|
<div class="topbar">
|
||||||
|
<div>
|
||||||
|
<p class="eyebrow">Upcoming Sessions</p>
|
||||||
|
<h2>Manage events and workshops</h2>
|
||||||
|
<p class="body">Add session details to show on the public site.</p>
|
||||||
|
</div>
|
||||||
|
<button class="btn primary" onclick="document.getElementById('session-form').scrollIntoView({behavior:'smooth'})">Add new</button>
|
||||||
|
</div>
|
||||||
|
<div class="admin-nav">
|
||||||
|
<a href="/admin/tutorials.php">Tutorials</a>
|
||||||
|
<a href="/admin/sessions.php">Upcoming Sessions</a>
|
||||||
|
<a href="/admin/contacts.php">Contact Entries</a>
|
||||||
|
<a href="/admin/newsletter.php">Newsletter</a>
|
||||||
|
<a href="/admin/admins.php">Admins</a>
|
||||||
|
<a href="/admin/logout.php">Logout (<?php echo htmlspecialchars(current_admin_email() ?? ''); ?>)</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if (isset($_GET['success'])): ?>
|
||||||
|
<div class="alert good">Session added successfully.</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_GET['deleted'])): ?>
|
||||||
|
<div class="alert good">Session deleted.</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_GET['updated'])): ?>
|
||||||
|
<div class="alert good">Session updated.</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="alert bad"><?php echo htmlspecialchars($error); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (empty($sessions)): ?>
|
||||||
|
<p class="body muted">No sessions yet. Add your first event below.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Tag</th>
|
||||||
|
<th>Start Date</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($sessions as $session): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars($session['title']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($session['description']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($session['tag']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($session['start_date'] ?? ''); ?></td>
|
||||||
|
<td>
|
||||||
|
<a class="inline-btn" href="?edit=<?php echo (int)$session['id']; ?>">Edit</a> |
|
||||||
|
<a class="inline-btn" href="?delete=<?php echo (int)$session['id']; ?>" onclick="return confirm('Delete this session?')">Delete</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<section id="session-form" style="margin-top:32px;">
|
||||||
|
<div class="card">
|
||||||
|
<h3><?php echo $editing ? 'Edit Session' : 'Add Session'; ?></h3>
|
||||||
|
<form method="post">
|
||||||
|
<?php if ($editing): ?>
|
||||||
|
<input type="hidden" name="id" value="<?php echo (int)$editing['id']; ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
<label for="title">Title</label>
|
||||||
|
<input type="text" id="title" name="title" required placeholder="Session title" value="<?php echo htmlspecialchars($editing['title'] ?? '', ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
|
||||||
|
<label for="description">Description</label>
|
||||||
|
<textarea id="description" name="description" required placeholder="Brief description"><?php echo htmlspecialchars($editing['description'] ?? '', ENT_QUOTES, 'UTF-8'); ?></textarea>
|
||||||
|
|
||||||
|
<label for="tag">Tag</label>
|
||||||
|
<input type="text" id="tag" name="tag" placeholder="e.g., New, Upcoming" value="<?php echo htmlspecialchars($editing['tag'] ?? '', ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
|
||||||
|
<label for="cta_label">CTA Label</label>
|
||||||
|
<input type="text" id="cta_label" name="cta_label" placeholder="Register" value="<?php echo htmlspecialchars($editing['cta_label'] ?? 'Register', ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
|
||||||
|
<label for="start_date">Start Date</label>
|
||||||
|
<input type="date" id="start_date" name="start_date" value="<?php echo htmlspecialchars($editing['start_date'] ?? '', ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
|
||||||
|
<div style="margin-top:16px;">
|
||||||
|
<button type="submit" class="btn primary"><?php echo $editing ? 'Update session' : 'Save session'; ?></button>
|
||||||
|
<a class="text-link" href="/news-events.php" style="margin-left:10px;">View live</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php require __DIR__ . '/../includes/admin-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,222 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../includes/auth.php';
|
||||||
|
require_login();
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
$uploadDir = __DIR__ . '/../uploads/';
|
||||||
|
if (!is_dir($uploadDir)) {
|
||||||
|
mkdir($uploadDir, 0775, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$title = trim($_POST['title'] ?? '');
|
||||||
|
$description = trim($_POST['description'] ?? '');
|
||||||
|
$status = trim($_POST['status'] ?? 'active');
|
||||||
|
$video_url = trim($_POST['video_url'] ?? '');
|
||||||
|
$file_path = null;
|
||||||
|
$editId = isset($_POST['id']) ? (int) $_POST['id'] : null;
|
||||||
|
|
||||||
|
if (isset($_FILES['tutorial_file']) && $_FILES['tutorial_file']['error'] !== UPLOAD_ERR_NO_FILE) {
|
||||||
|
$file = $_FILES['tutorial_file'];
|
||||||
|
if ($file['error'] === UPLOAD_ERR_OK) {
|
||||||
|
$allowed = [
|
||||||
|
'application/pdf',
|
||||||
|
'application/msword',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
||||||
|
];
|
||||||
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||||
|
$mime = finfo_file($finfo, $file['tmp_name']);
|
||||||
|
finfo_close($finfo);
|
||||||
|
if (!in_array($mime, $allowed, true)) {
|
||||||
|
$error = 'Only PDF or Word documents are allowed.';
|
||||||
|
} else {
|
||||||
|
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||||||
|
$newName = 'tutorial_' . time() . '_' . mt_rand(1000, 9999) . '.' . $ext;
|
||||||
|
$dest = $uploadDir . $newName;
|
||||||
|
if (move_uploaded_file($file['tmp_name'], $dest)) {
|
||||||
|
$file_path = 'uploads/' . $newName;
|
||||||
|
} else {
|
||||||
|
$error = 'File upload failed.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$error = 'File upload failed.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($title === '' || $description === '') {
|
||||||
|
$error = 'Title and description are required.';
|
||||||
|
} elseif (!$error) {
|
||||||
|
$payload = compact('title', 'description', 'status', 'file_path', 'video_url');
|
||||||
|
if ($editId) {
|
||||||
|
update_tutorial($editId, $payload);
|
||||||
|
header('Location: tutorials.php?updated=1');
|
||||||
|
} else {
|
||||||
|
add_tutorial($payload);
|
||||||
|
header('Location: tutorials.php?success=1');
|
||||||
|
}
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_GET['delete'])) {
|
||||||
|
$id = (int) $_GET['delete'];
|
||||||
|
delete_tutorial($id);
|
||||||
|
header('Location: tutorials.php?deleted=1');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tutorials = get_tutorials(false);
|
||||||
|
$editing = null;
|
||||||
|
if (isset($_GET['edit'])) {
|
||||||
|
$editId = (int) $_GET['edit'];
|
||||||
|
foreach ($tutorials as $row) {
|
||||||
|
if ((int) $row['id'] === $editId) {
|
||||||
|
$editing = $row;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$assetPathPrefix = '../';
|
||||||
|
$pageTitle = 'Manage Tutorials';
|
||||||
|
$currentPage = 'tutorials';
|
||||||
|
$extraStyles = <<<CSS
|
||||||
|
<style>
|
||||||
|
body { background: #f6faf7; }
|
||||||
|
.admin-shell { padding: 40px 0; }
|
||||||
|
.table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
||||||
|
.table th, .table td { text-align: left; padding: 12px 10px; border-bottom: 1px solid #e1ede7; }
|
||||||
|
.table th { color: #0f4333; }
|
||||||
|
.badge { display: inline-block; padding: 6px 10px; border-radius: 10px; background: #e8f5ef; color: #0f4333; font-weight: 700; font-size: 13px; }
|
||||||
|
.inline-btn { color: #b9342f; font-weight: 700; }
|
||||||
|
form textarea { min-height: 120px; resize: vertical; }
|
||||||
|
form input, form textarea, form select { width: 100%; padding: 12px 14px; border-radius: 10px; border: 1px solid #d8e7e0; font-size: 15px; margin-top: 8px; }
|
||||||
|
form input[type=file] { padding: 8px; }
|
||||||
|
form label { font-weight: 700; color: #0f4333; display: block; margin-top: 12px; }
|
||||||
|
.topbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
|
||||||
|
</style>
|
||||||
|
CSS;
|
||||||
|
|
||||||
|
require __DIR__ . '/../includes/admin-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main class="admin-shell">
|
||||||
|
<div class="container">
|
||||||
|
<div class="topbar">
|
||||||
|
<div>
|
||||||
|
<p class="eyebrow">Tutorials</p>
|
||||||
|
<h2>Manage tutorials</h2>
|
||||||
|
<p class="body">Add training tutorials with downloads or video links.</p>
|
||||||
|
</div>
|
||||||
|
<button class="btn primary" onclick="document.getElementById('tutorial-form').scrollIntoView({behavior: 'smooth'})">Add new</button>
|
||||||
|
</div>
|
||||||
|
<div class="admin-nav">
|
||||||
|
<a href="/admin/tutorials.php">Tutorials</a>
|
||||||
|
<a href="/admin/sessions.php">Upcoming Sessions</a>
|
||||||
|
<a href="/admin/contacts.php">Contact Entries</a>
|
||||||
|
<a href="/admin/newsletter.php">Newsletter</a>
|
||||||
|
<a href="/admin/admins.php">Admins</a>
|
||||||
|
<a href="/admin/logout.php">Logout (<?php echo htmlspecialchars(current_admin_email() ?? ''); ?>)</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if (isset($_GET['success'])): ?>
|
||||||
|
<div class="alert good">Tutorial added successfully.</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_GET['deleted'])): ?>
|
||||||
|
<div class="alert good">Tutorial deleted.</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_GET['updated'])): ?>
|
||||||
|
<div class="alert good">Tutorial updated successfully.</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="alert bad"><?php echo htmlspecialchars($error); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (empty($tutorials)): ?>
|
||||||
|
<p class="body muted">No tutorials yet. Add your first entry below.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Asset</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($tutorials as $tutorial): ?>
|
||||||
|
<?php
|
||||||
|
if (!is_array($tutorial)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$title = htmlspecialchars((string)($tutorial['title'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$description = htmlspecialchars((string)($tutorial['description'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$status = htmlspecialchars((string)($tutorial['status'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$filePath = (string)($tutorial['file_path'] ?? '');
|
||||||
|
$videoUrl = (string)($tutorial['video_url'] ?? '');
|
||||||
|
?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo $title; ?></td>
|
||||||
|
<td><?php echo $description; ?></td>
|
||||||
|
<td><span class="badge"><?php echo $status; ?></span></td>
|
||||||
|
<td>
|
||||||
|
<?php if ($filePath): ?>
|
||||||
|
<a class="text-link" href="/<?php echo htmlspecialchars(ltrim($filePath, '/'), ENT_QUOTES, 'UTF-8'); ?>" target="_blank">Download</a>
|
||||||
|
<?php elseif ($videoUrl): ?>
|
||||||
|
<a class="text-link" href="<?php echo htmlspecialchars($videoUrl, ENT_QUOTES, 'UTF-8'); ?>" target="_blank">Watch</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="body muted">None</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a class="inline-btn" href="?edit=<?php echo (int)$tutorial['id']; ?>">Edit</a> |
|
||||||
|
<a class="inline-btn" href="?delete=<?php echo (int)$tutorial['id']; ?>" onclick="return confirm('Delete this tutorial?')">Delete</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<section id="tutorial-form" style="margin-top:32px;">
|
||||||
|
<div class="card">
|
||||||
|
<h3><?php echo $editing ? 'Edit Tutorial' : 'Add Tutorial'; ?></h3>
|
||||||
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
<?php if ($editing): ?>
|
||||||
|
<input type="hidden" name="id" value="<?php echo (int)$editing['id']; ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
<label for="title">Title</label>
|
||||||
|
<input type="text" id="title" name="title" required placeholder="Tutorial title" value="<?php echo htmlspecialchars($editing['title'] ?? '', ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
|
||||||
|
<label for="description">Description</label>
|
||||||
|
<textarea id="description" name="description" required placeholder="Brief description"><?php echo htmlspecialchars($editing['description'] ?? '', ENT_QUOTES, 'UTF-8'); ?></textarea>
|
||||||
|
|
||||||
|
<label for="status">Status</label>
|
||||||
|
<select id="status" name="status">
|
||||||
|
<option value="active" <?php echo (($editing['status'] ?? '') === 'active') ? 'selected' : ''; ?>>Active</option>
|
||||||
|
<option value="draft" <?php echo (($editing['status'] ?? '') === 'draft') ? 'selected' : ''; ?>>Draft</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label for="video_url">YouTube / Video URL (optional)</label>
|
||||||
|
<input type="url" id="video_url" name="video_url" placeholder="https://youtube.com/..." value="<?php echo htmlspecialchars($editing['video_url'] ?? '', ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
|
||||||
|
<label for="tutorial_file">Upload PDF / Word (optional)</label>
|
||||||
|
<input type="file" id="tutorial_file" name="tutorial_file" accept=".pdf,.doc,.docx">
|
||||||
|
<?php if (!empty($editing['file_path'])): ?>
|
||||||
|
<p class="body muted">Current file: <a href="/<?php echo htmlspecialchars($editing['file_path'], ENT_QUOTES, 'UTF-8'); ?>" target="_blank">Download</a></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
<p class="body muted" style="margin:6px 0 0;">Upload a file or provide a video URL (or both).</p>
|
||||||
|
|
||||||
|
<div style="margin-top:16px;">
|
||||||
|
<button type="submit" class="btn primary"><?php echo $editing ? 'Update tutorial' : 'Save tutorial'; ?></button>
|
||||||
|
<a class="text-link" href="/index.php" style="margin-left:10px;">View live site</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php require __DIR__ . '/../includes/admin-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
body.admin-body {
|
||||||
|
background: #f6faf7;
|
||||||
|
font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
|
||||||
|
color: #0e1e18;
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-header {
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-mark {
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: linear-gradient(135deg, #2bc08a, #11704f);
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-name {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-tagline {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-shell {
|
||||||
|
padding: 40px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-nav {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin: 10px 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-nav a {
|
||||||
|
background: #e6f3ed;
|
||||||
|
color: #0f4333;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid #e5efe9;
|
||||||
|
box-shadow: 0 10px 24px rgba(20, 72, 55, 0.08);
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary,
|
||||||
|
.btn.btn-primary {
|
||||||
|
background: #1d9c6d;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.outline,
|
||||||
|
.btn.btn-outline {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #d3e8e0;
|
||||||
|
color: #0f4333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.small {
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form input,
|
||||||
|
form textarea,
|
||||||
|
form select {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 14px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid #d8e7e0;
|
||||||
|
font-size: 15px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form textarea {
|
||||||
|
min-height: 120px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
form label {
|
||||||
|
font-weight: 700;
|
||||||
|
color: #0f4333;
|
||||||
|
display: block;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert.good {
|
||||||
|
background: #def3eb;
|
||||||
|
color: #0f4333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert.bad {
|
||||||
|
background: #ffebe8;
|
||||||
|
color: #9a2f23;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table th,
|
||||||
|
.table td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-footer {
|
||||||
|
background: #f0f5f3;
|
||||||
|
border-top: 1px solid #e0ebe5;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
.brand-mark {
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
background: linear-gradient(135deg, #2bc08a, #11704f);
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-section {
|
||||||
|
background: radial-gradient(140% 120% at 25% 20%, #e9f7f0 0%, #ffffff 60%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-tile {
|
||||||
|
background: #eef8f5;
|
||||||
|
border: 1px solid #def3eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-orb {
|
||||||
|
width: 220px;
|
||||||
|
height: 220px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: radial-gradient(circle at 30% 30%, #ffb7a6, #e06a6a 60%);
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
box-shadow: 0 18px 40px rgba(223, 121, 121, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-orb-inner {
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
background: linear-gradient(180deg, #ffede7, #ffb9a6);
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-pill {
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: #e8f5ef;
|
||||||
|
color: #0f6f52;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder-img {
|
||||||
|
min-height: 200px;
|
||||||
|
background: linear-gradient(135deg, #c2e7d9, #9cd3c3);
|
||||||
|
}
|
||||||
|
.placeholder-img.tall { min-height: 260px; }
|
||||||
|
.placeholder-img.small { min-height: 140px; }
|
||||||
|
.placeholder-img.mailer {
|
||||||
|
min-height: 220px;
|
||||||
|
background: linear-gradient(135deg, #f6f6f6, #ffffff);
|
||||||
|
box-shadow: 0 12px 30px rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge.bg-success-subtle {
|
||||||
|
background: #e8f5ef !important;
|
||||||
|
color: #0f6f52 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer a { color: #fff; }
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const form = document.querySelector('.newsletter-form');
|
||||||
|
if (form) {
|
||||||
|
form.addEventListener('submit', () => {
|
||||||
|
// Let the form submit normally; no client-side prevention so server can record subscriptions.
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/data.php';
|
||||||
|
$pageTitle = 'Contact | CREST';
|
||||||
|
$metaDescription = 'Contact CREST for research collaborations, training, media, or partnership inquiries in respiratory health.';
|
||||||
|
$contactMessage = '';
|
||||||
|
$contactError = '';
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$name = trim($_POST['name'] ?? '');
|
||||||
|
$email = trim($_POST['email'] ?? '');
|
||||||
|
$organization = trim($_POST['organization'] ?? '');
|
||||||
|
$message = trim($_POST['message'] ?? '');
|
||||||
|
|
||||||
|
if ($name === '' || $email === '' || $message === '') {
|
||||||
|
$contactError = 'Name, email, and message are required.';
|
||||||
|
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$contactError = 'Please enter a valid email.';
|
||||||
|
} else {
|
||||||
|
save_contact(compact('name', 'email', 'organization', 'message'));
|
||||||
|
$contactMessage = 'Thanks for reaching out. We will get back to you within 2 business days.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
include __DIR__ . '/includes/site-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Contact</p>
|
||||||
|
<h2 class="fw-bold">We would love to hear from you</h2>
|
||||||
|
<p class="text-muted">Tell us about your research needs, training goals, or partnership ideas.</p>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<li class="mb-2">• Program design consultations</li>
|
||||||
|
<li class="mb-2">• Training calendar requests</li>
|
||||||
|
<li class="mb-2">• Media and speaking inquiries</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card shadow-sm border-0 rounded-4 p-3">
|
||||||
|
<?php if ($contactMessage): ?>
|
||||||
|
<div class="alert alert-success"><?php echo htmlspecialchars($contactMessage); ?></div>
|
||||||
|
<?php elseif ($contactError): ?>
|
||||||
|
<div class="alert alert-danger"><?php echo htmlspecialchars($contactError); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<form class="row g-3" method="post">
|
||||||
|
<div class="col-12">
|
||||||
|
<input type="text" name="name" class="form-control rounded-3" placeholder="Full Name" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<input type="email" name="email" class="form-control rounded-3" placeholder="Email" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<input type="text" name="organization" class="form-control rounded-3" placeholder="Organization">
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<textarea name="message" class="form-control rounded-3" rows="4" placeholder="How can we help?" required></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 d-grid">
|
||||||
|
<button class="btn btn-success text-white rounded-3" type="submit">Send message</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/includes/site-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "Understanding Lung Function in Adult Populations",
|
||||||
|
"summary": "A concise explainer on spirometry metrics and how to interpret lung function assessments in community settings.",
|
||||||
|
"label": "Publication"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lung Function in India: Overview",
|
||||||
|
"summary": "Key findings from multi-city research that maps prevalence of respiratory conditions across demographic groups.",
|
||||||
|
"label": "Research Brief"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Childhood Lung Function in India",
|
||||||
|
"summary": "Practical guidance for pediatric screening teams and frontline clinicians working with young patients.",
|
||||||
|
"label": "Toolkit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Understanding Lung Function in Rural Populations",
|
||||||
|
"summary": "Field notes and methodologies for conducting door-to-door lung health studies with limited resources.",
|
||||||
|
"label": "Field Guide"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/data.php';
|
||||||
|
$pageTitle = 'Our Expertise | CREST';
|
||||||
|
$metaDescription = 'Discover CREST services in research, training, and consulting for respiratory health programs.';
|
||||||
|
include __DIR__ . '/includes/site-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="py-5 bg-light">
|
||||||
|
<div class="container">
|
||||||
|
<div class="mb-4">
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Our Expertise</p>
|
||||||
|
<h2 class="fw-bold">Our Services & Expertise</h2>
|
||||||
|
</div>
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card h-100 shadow-sm border-0 rounded-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="icon-pill mb-3">★</div>
|
||||||
|
<h5 class="fw-bold">Research</h5>
|
||||||
|
<p class="text-muted small">Rigorous studies to map lung health trends and inform community programs.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card h-100 shadow-sm border-0 rounded-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="icon-pill mb-3">★</div>
|
||||||
|
<h5 class="fw-bold">Training</h5>
|
||||||
|
<p class="text-muted small">Workshops and mentoring that upskill clinicians and field teams.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card h-100 shadow-sm border-0 rounded-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="icon-pill mb-3">★</div>
|
||||||
|
<h5 class="fw-bold">Consulting</h5>
|
||||||
|
<p class="text-muted small">Advisory for programs to scale respiratory care safely and effectively.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/includes/site-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
$pageTitle = 'Our Experts | Crest Lung Health';
|
||||||
|
$currentPage = 'experts';
|
||||||
|
require __DIR__ . '/includes/header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container two-col">
|
||||||
|
<div>
|
||||||
|
<p class="eyebrow">Our Experts</p>
|
||||||
|
<h1>Meet the team driving respiratory innovation</h1>
|
||||||
|
<p class="body">Clinical specialists, researchers, and educators collaborate to design programs that translate science into care. Each team member brings domain expertise across pulmonology, epidemiology, community health, and implementation.</p>
|
||||||
|
<ul class="checklist">
|
||||||
|
<li><span class="dot green"></span> 300+ specialists and faculty contributors</li>
|
||||||
|
<li><span class="dot green"></span> Cross-functional teams for research and training</li>
|
||||||
|
<li><span class="dot green"></span> Field experience across diverse geographies</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="photo-card">
|
||||||
|
<div class="photo tall"></div>
|
||||||
|
<div class="photo caption">Trusted by leading institutes</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php require __DIR__ . '/includes/footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<footer class="admin-footer">
|
||||||
|
<div class="container text-center small text-muted py-3">
|
||||||
|
©2025 Stratawiz.com
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="<?php echo $assetPathPrefix; ?>assets/js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
$assetPathPrefix = $assetPathPrefix ?? '';
|
||||||
|
$pageTitle = $pageTitle ?? 'Admin';
|
||||||
|
$loggedEmail = $_SESSION['admin_email'] ?? null;
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php echo htmlspecialchars($pageTitle); ?></title>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="<?php echo $assetPathPrefix; ?>assets/css/admin.css">
|
||||||
|
<?php if (!empty($extraStyles)) { echo $extraStyles; } ?>
|
||||||
|
</head>
|
||||||
|
<body class="admin-body">
|
||||||
|
<header class="site-header shadow-sm">
|
||||||
|
<div class="container d-flex justify-content-between align-items-center py-3">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<div class="brand-mark text-white fw-bold d-flex align-items-center justify-content-center">C</div>
|
||||||
|
<div>
|
||||||
|
<div class="brand-name text-success fw-bold">CREST</div>
|
||||||
|
<div class="brand-tagline text-muted">Admin Panel</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="fw-semibold text-muted">
|
||||||
|
<?php echo $loggedEmail ? htmlspecialchars($loggedEmail) : ''; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/data.php';
|
||||||
|
|
||||||
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function require_login(): void
|
||||||
|
{
|
||||||
|
if (!is_logged_in()) {
|
||||||
|
$loginPath = 'login.php';
|
||||||
|
if (strpos($_SERVER['REQUEST_URI'] ?? '', '/admin/') === false) {
|
||||||
|
$loginPath = '/admin/login.php';
|
||||||
|
}
|
||||||
|
header('Location: ' . $loginPath);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_logged_in(): bool
|
||||||
|
{
|
||||||
|
return isset($_SESSION['admin_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
function current_admin_email(): ?string
|
||||||
|
{
|
||||||
|
return $_SESSION['admin_email'] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function attempt_login(string $email, string $password): bool
|
||||||
|
{
|
||||||
|
$admin = get_admin_by_email($email);
|
||||||
|
if (!$admin) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password_verify($password, $admin['password_hash'])) {
|
||||||
|
$_SESSION['admin_id'] = $admin['id'];
|
||||||
|
$_SESSION['admin_email'] = $admin['email'];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function logout(): void
|
||||||
|
{
|
||||||
|
$_SESSION = [];
|
||||||
|
session_destroy();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,229 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/db.php';
|
||||||
|
|
||||||
|
if (!function_exists('get_resources')) {
|
||||||
|
function get_resources(): array
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$table = resource_table_name($pdo);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$rows = $pdo->query("SELECT * FROM resources_table ORDER BY id DESC");
|
||||||
|
return is_array($rows) ? $rows : [];
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
error_log('get_resources attempt failed: ' . $e->getMessage());
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('add_resource')) {
|
||||||
|
function add_resource(array $payload): void
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$table = resource_table_name($pdo);
|
||||||
|
$pdo->insert($table, [
|
||||||
|
'title' => trim($payload['title'] ?? ''),
|
||||||
|
'summary' => trim($payload['summary'] ?? ''),
|
||||||
|
'label' => trim($payload['label'] ?? ''),
|
||||||
|
'file_path' => $payload['file_path'] ?? null,
|
||||||
|
'video_url' => trim($payload['video_url'] ?? ''),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('delete_resource')) {
|
||||||
|
function delete_resource(int $id): void
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$table = resource_table_name($pdo);
|
||||||
|
$filePath = null;
|
||||||
|
$row = $pdo->getOne("SELECT file_path FROM `$table` WHERE id = ?", [$id]);
|
||||||
|
if ($row && isset($row['file_path'])) {
|
||||||
|
$filePath = $row['file_path'];
|
||||||
|
}
|
||||||
|
$pdo->deleteById($table, $id);
|
||||||
|
if ($filePath && is_string($filePath)) {
|
||||||
|
$full = __DIR__ . '/../' . ltrim($filePath, '/');
|
||||||
|
if (is_file($full)) {
|
||||||
|
@unlink($full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('get_sessions')) {
|
||||||
|
function get_sessions(): array
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$rows = $pdo->query("
|
||||||
|
SELECT id, number, start_date, status, join_link, code, venue
|
||||||
|
FROM sessions
|
||||||
|
WHERE (status IN ('current','upcoming') OR start_date >= NOW())
|
||||||
|
AND (deleted_at IS NULL OR deleted_at = '0000-00-00 00:00:00')
|
||||||
|
ORDER BY start_date ASC
|
||||||
|
");
|
||||||
|
return is_array($rows) ? $rows : [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('add_session')) {
|
||||||
|
function add_session(array $payload): void
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$pdo->insert('sessions', [
|
||||||
|
'title' => trim($payload['title'] ?? ''),
|
||||||
|
'description' => trim($payload['description'] ?? ''),
|
||||||
|
'tag' => trim($payload['tag'] ?? ''),
|
||||||
|
'cta_label' => trim($payload['cta_label'] ?? 'Register'),
|
||||||
|
'start_date' => $payload['start_date'] ?? null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('update_session')) {
|
||||||
|
function update_session(int $id, array $payload): void
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$pdo->update('sessions', [
|
||||||
|
'title' => trim($payload['title'] ?? ''),
|
||||||
|
'description' => trim($payload['description'] ?? ''),
|
||||||
|
'tag' => trim($payload['tag'] ?? ''),
|
||||||
|
'cta_label' => trim($payload['cta_label'] ?? 'Register'),
|
||||||
|
'start_date' => $payload['start_date'] ?? null,
|
||||||
|
], "id = ?", [$id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('delete_session')) {
|
||||||
|
function delete_session(int $id): void
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$pdo->deleteById('sessions', $id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('save_contact')) {
|
||||||
|
function save_contact(array $payload): void
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$pdo->insert('contacts', [
|
||||||
|
'name' => trim($payload['name'] ?? ''),
|
||||||
|
'email' => trim($payload['email'] ?? ''),
|
||||||
|
'organization' => trim($payload['organization'] ?? ''),
|
||||||
|
'message' => trim($payload['message'] ?? ''),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('get_contacts')) {
|
||||||
|
function get_contacts(): array
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
return $pdo->query("SELECT id, name, email, organization, message, created_at FROM contacts ORDER BY id DESC");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('get_tutorials')) {
|
||||||
|
function get_tutorials(bool $onlyActive = true): array
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$sql = "SELECT id, title, description, status, file_path, video_url, created_at FROM tutorials";
|
||||||
|
$params = [];
|
||||||
|
if ($onlyActive) {
|
||||||
|
$sql .= " WHERE status = ?";
|
||||||
|
$params[] = 'active';
|
||||||
|
}
|
||||||
|
$sql .= " ORDER BY id DESC";
|
||||||
|
$rows = $pdo->query($sql, $params);
|
||||||
|
return is_array($rows) ? $rows : [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('add_tutorial')) {
|
||||||
|
function add_tutorial(array $payload): void
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$pdo->insert('tutorials', [
|
||||||
|
'title' => trim($payload['title'] ?? ''),
|
||||||
|
'description' => trim($payload['description'] ?? ''),
|
||||||
|
'status' => trim($payload['status'] ?? 'active'),
|
||||||
|
'file_path' => $payload['file_path'] ?? null,
|
||||||
|
'video_url' => trim($payload['video_url'] ?? ''),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('update_tutorial')) {
|
||||||
|
function update_tutorial(int $id, array $payload): void
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$data = [
|
||||||
|
'title' => trim($payload['title'] ?? ''),
|
||||||
|
'description' => trim($payload['description'] ?? ''),
|
||||||
|
'status' => trim($payload['status'] ?? 'active'),
|
||||||
|
'video_url' => trim($payload['video_url'] ?? ''),
|
||||||
|
];
|
||||||
|
if (!empty($payload['file_path'])) {
|
||||||
|
$data['file_path'] = $payload['file_path'];
|
||||||
|
}
|
||||||
|
$pdo->update('tutorials', $data, "id = ?", [$id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('delete_tutorial')) {
|
||||||
|
function delete_tutorial(int $id): void
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$row = $pdo->getOne("SELECT file_path FROM tutorials WHERE id = ?", [$id]);
|
||||||
|
$filePath = $row['file_path'] ?? null;
|
||||||
|
$pdo->deleteById('tutorials', $id);
|
||||||
|
if ($filePath && is_string($filePath)) {
|
||||||
|
$full = __DIR__ . '/../' . ltrim($filePath, '/');
|
||||||
|
if (is_file($full)) {
|
||||||
|
@unlink($full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('save_subscription')) {
|
||||||
|
function save_subscription(array $payload): void
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$pdo->rawQuery(
|
||||||
|
"INSERT INTO newsletter_subscriptions (first_name, email) VALUES (?, ?) ON DUPLICATE KEY UPDATE first_name = VALUES(first_name)",
|
||||||
|
[
|
||||||
|
trim($payload['first_name'] ?? ''),
|
||||||
|
trim($payload['email'] ?? ''),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('get_subscriptions')) {
|
||||||
|
function get_subscriptions(): array
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
return $pdo->query("SELECT id, first_name, email, created_at FROM newsletter_subscriptions ORDER BY id DESC");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('get_admin_by_email')) {
|
||||||
|
function get_admin_by_email(string $email): ?array
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$row = $pdo->getOne("SELECT * FROM admins WHERE email = ?", [$email]);
|
||||||
|
return $row ?: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('create_admin')) {
|
||||||
|
function create_admin(string $email, string $password): void
|
||||||
|
{
|
||||||
|
$pdo = db();
|
||||||
|
$hash = password_hash($password, PASSWORD_DEFAULT);
|
||||||
|
$pdo->insert('admins', ['email' => $email, 'password_hash' => $hash]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,223 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/mysqli-class.php';
|
||||||
|
|
||||||
|
function db(): MysqliDb
|
||||||
|
{
|
||||||
|
static $db = null;
|
||||||
|
if ($db instanceof MysqliDb) {
|
||||||
|
return $db;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = 'virtualuser';
|
||||||
|
$pass = 'ltnwGXZqvQJqXjPPQgmO';
|
||||||
|
$dbName = 'shabby_road';
|
||||||
|
$host = 'virtualengage.c1qdknkurtfn.ap-south-1.rds.amazonaws.com';
|
||||||
|
$port = 3306;
|
||||||
|
|
||||||
|
$attempts = [
|
||||||
|
['socket' => null, 'host' => $host, 'port' => $port],
|
||||||
|
];
|
||||||
|
|
||||||
|
$lastError = '';
|
||||||
|
foreach ($attempts as $attempt) {
|
||||||
|
try {
|
||||||
|
$db = new MysqliDb([
|
||||||
|
'host' => $attempt['host'],
|
||||||
|
'username' => $user,
|
||||||
|
'password' => $pass,
|
||||||
|
'db' => $dbName,
|
||||||
|
'port' => $attempt['port'],
|
||||||
|
'socket' => $attempt['socket'],
|
||||||
|
'charset' => 'utf8mb4',
|
||||||
|
]);
|
||||||
|
bootstrap_schema($db);
|
||||||
|
return $db;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$lastError = $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception('Database connection failed: ' . $lastError);
|
||||||
|
}
|
||||||
|
|
||||||
|
function bootstrap_schema(MysqliDb $db): void
|
||||||
|
{
|
||||||
|
$db->rawQuery("CREATE TABLE IF NOT EXISTS admins (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
email VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
password_hash VARCHAR(255) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)");
|
||||||
|
|
||||||
|
$resourceTable = ensure_resources_table($db);
|
||||||
|
|
||||||
|
$db->rawQuery("CREATE TABLE IF NOT EXISTS sessions (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT NOT NULL,
|
||||||
|
tag VARCHAR(50) DEFAULT NULL,
|
||||||
|
cta_label VARCHAR(100) DEFAULT 'Register',
|
||||||
|
start_date DATE DEFAULT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)");
|
||||||
|
|
||||||
|
$db->rawQuery("CREATE TABLE IF NOT EXISTS contacts (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
email VARCHAR(255) NOT NULL,
|
||||||
|
organization VARCHAR(255) DEFAULT NULL,
|
||||||
|
message TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)");
|
||||||
|
|
||||||
|
$db->rawQuery("CREATE TABLE IF NOT EXISTS newsletter_subscriptions (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
first_name VARCHAR(255) DEFAULT NULL,
|
||||||
|
email VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)");
|
||||||
|
|
||||||
|
$db->rawQuery("CREATE TABLE IF NOT EXISTS tutorials (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT NOT NULL,
|
||||||
|
status VARCHAR(50) NOT NULL DEFAULT 'active',
|
||||||
|
file_path VARCHAR(255) DEFAULT NULL,
|
||||||
|
video_url VARCHAR(255) DEFAULT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)");
|
||||||
|
|
||||||
|
seed_default_admin($db);
|
||||||
|
seed_sample_resources($db, $resourceTable);
|
||||||
|
seed_sample_sessions($db);
|
||||||
|
seed_sample_tutorials($db);
|
||||||
|
}
|
||||||
|
|
||||||
|
function seed_default_admin(MysqliDb $db): void
|
||||||
|
{
|
||||||
|
$row = $db->getOne("SELECT 1 FROM admins WHERE email = ?", ['ravi@stratawiz.com']);
|
||||||
|
if ($row) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$hash = password_hash('qwerty', PASSWORD_DEFAULT);
|
||||||
|
$db->insert('admins', ['email' => 'ravi@stratawiz.com', 'password_hash' => $hash]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function seed_sample_resources(MysqliDb $db, string $table): void
|
||||||
|
{
|
||||||
|
$count = (int) $db->getValue("SELECT COUNT(*) as c FROM `$table`");
|
||||||
|
if ($count > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$samples = [
|
||||||
|
['title' => 'Understanding Lung Function in Adult Populations', 'summary' => 'A concise explainer on spirometry metrics and how to interpret lung function assessments in community settings.', 'label' => 'Publication'],
|
||||||
|
['title' => 'Lung Function in India: Overview', 'summary' => 'Key findings from multi-city research that maps prevalence of respiratory conditions across demographic groups.', 'label' => 'Research Brief'],
|
||||||
|
['title' => 'Childhood Lung Function in India', 'summary' => 'Practical guidance for pediatric screening teams and frontline clinicians working with young patients.', 'label' => 'Toolkit'],
|
||||||
|
['title' => 'Understanding Lung Function in Rural Populations', 'summary' => 'Field notes and methodologies for conducting door-to-door lung health studies with limited resources.', 'label' => 'Field Guide'],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($samples as $sample) {
|
||||||
|
$db->insert($table, $sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function seed_sample_sessions(MysqliDb $db): void
|
||||||
|
{
|
||||||
|
$count = (int) $db->getValue("SELECT COUNT(*) as c FROM sessions");
|
||||||
|
if ($count > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$samples = [
|
||||||
|
['title' => 'Nutrition guidance for advanced lung conditions', 'description' => 'Upcoming webinar on dietary support for patients with complex respiratory conditions.', 'tag' => 'New'],
|
||||||
|
['title' => 'Workshop: Field data quality for respiratory studies', 'description' => 'Hands-on clinic for research leads to strengthen field protocols and audits.', 'tag' => 'Update'],
|
||||||
|
['title' => 'Training cohort launch: Spirometry essentials', 'description' => 'New batch begins soon with live mentoring and case reviews.', 'tag' => 'Upcoming'],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($samples as $sample) {
|
||||||
|
$db->insert('sessions', $sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function seed_sample_tutorials(MysqliDb $db): void
|
||||||
|
{
|
||||||
|
$count = (int) $db->getValue("SELECT COUNT(*) as c FROM tutorials");
|
||||||
|
if ($count > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$samples = [
|
||||||
|
['title' => 'Spirometry Basics', 'description' => 'Step-by-step guide for accurate spirometry setup and testing.', 'status' => 'active'],
|
||||||
|
['title' => 'Inhaler Technique', 'description' => 'Visual walkthrough on patient education for inhaler use.', 'status' => 'active'],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($samples as $sample) {
|
||||||
|
$db->insert('tutorials', $sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensure_resources_table(MysqliDb $db): string
|
||||||
|
{
|
||||||
|
$candidates = ['resources_table', 'resources'];
|
||||||
|
|
||||||
|
// Prefer any existing table that already has rows.
|
||||||
|
foreach ($candidates as $name) {
|
||||||
|
$exists = $db->getValue("SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?", [$name]);
|
||||||
|
if ($exists) {
|
||||||
|
$count = (int) $db->getValue("SELECT COUNT(*) FROM `$name`");
|
||||||
|
if ($count > 0) {
|
||||||
|
add_resource_columns_if_missing($db, $name);
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to first existing, even if empty.
|
||||||
|
foreach ($candidates as $name) {
|
||||||
|
$exists = $db->getValue("SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?", [$name]);
|
||||||
|
if ($exists) {
|
||||||
|
add_resource_columns_if_missing($db, $name);
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = 'resources';
|
||||||
|
$db->rawQuery("CREATE TABLE IF NOT EXISTS `$name` (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
summary TEXT NOT NULL,
|
||||||
|
label VARCHAR(100) NOT NULL,
|
||||||
|
file_path VARCHAR(255) DEFAULT NULL,
|
||||||
|
video_url VARCHAR(255) DEFAULT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)");
|
||||||
|
add_resource_columns_if_missing($db, $name);
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_resource_columns_if_missing(MysqliDb $db, string $table): void
|
||||||
|
{
|
||||||
|
$columns = [
|
||||||
|
'file_path' => 'ALTER TABLE `%s` ADD COLUMN file_path VARCHAR(255) DEFAULT NULL',
|
||||||
|
'video_url' => 'ALTER TABLE `%s` ADD COLUMN video_url VARCHAR(255) DEFAULT NULL',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($columns as $column => $alter) {
|
||||||
|
$exists = $db->getValue("SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ? AND column_name = ?", [$table, $column]);
|
||||||
|
if (!$exists) {
|
||||||
|
$db->rawQuery(sprintf($alter, $table));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resource_table_name(MysqliDb $db): string
|
||||||
|
{
|
||||||
|
static $resolved;
|
||||||
|
if ($resolved) {
|
||||||
|
return $resolved;
|
||||||
|
}
|
||||||
|
$resolved = ensure_resources_table($db);
|
||||||
|
return $resolved;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
<footer class="site-footer">
|
||||||
|
<div class="copyright">
|
||||||
|
@ CREST - Chest Research and Training Pyt Lad ·
|
||||||
|
<a href="#">Privacy Policy</a> |
|
||||||
|
<a href="#">Terms of use</a> |
|
||||||
|
<a href="#">Linkin</a>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="<?php echo $assetPathPrefix; ?>assets/js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
$assetPathPrefix = $assetPathPrefix ?? '';
|
||||||
|
$pageTitle = $pageTitle ?? 'Crest Lung Health';
|
||||||
|
$currentPage = $currentPage ?? '';
|
||||||
|
|
||||||
|
$navItems = [
|
||||||
|
['key' => 'home', 'label' => 'Home', 'href' => $assetPathPrefix . 'index.php'],
|
||||||
|
['key' => 'experts', 'label' => 'Our Experts', 'href' => $assetPathPrefix . 'experts.php'],
|
||||||
|
['key' => 'services', 'label' => 'Our Services', 'href' => $assetPathPrefix . 'services.php'],
|
||||||
|
['key' => 'training', 'label' => 'Training', 'href' => $assetPathPrefix . 'training.php'],
|
||||||
|
['key' => 'achievements', 'label' => 'Achievements', 'href' => $assetPathPrefix . 'achievements.php'],
|
||||||
|
['key' => 'resources', 'label' => 'Resources', 'href' => $assetPathPrefix . 'resources.php'],
|
||||||
|
['key' => 'news', 'label' => 'News & Events', 'href' => $assetPathPrefix . 'news-events.php'],
|
||||||
|
['key' => 'contact', 'label' => 'Contact', 'href' => $assetPathPrefix . 'contact.php'],
|
||||||
|
];
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php echo htmlspecialchars($pageTitle); ?></title>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="<?php echo $assetPathPrefix; ?>assets/css/style.css">
|
||||||
|
<?php if (!empty($extraStyles)) { echo $extraStyles; } ?>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class="site-header">
|
||||||
|
<div class="container nav-bar">
|
||||||
|
<div class="brand">
|
||||||
|
<div class="brand-mark">C</div>
|
||||||
|
<div>
|
||||||
|
<div class="brand-name">CREST</div>
|
||||||
|
<div class="brand-tagline">Cancer Research Training & Consultancy</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<nav class="nav">
|
||||||
|
<?php foreach ($navItems as $item): ?>
|
||||||
|
<a href="<?php echo htmlspecialchars($item['href']); ?>"
|
||||||
|
class="<?php echo $currentPage === $item['key'] ? 'active' : ''; ?>">
|
||||||
|
<?php echo htmlspecialchars($item['label']); ?>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class MysqliDb
|
||||||
|
{
|
||||||
|
/** @var mysqli */
|
||||||
|
private $conn;
|
||||||
|
|
||||||
|
public function __construct(array $config)
|
||||||
|
{
|
||||||
|
$host = $config['host'] ?? '127.0.0.1';
|
||||||
|
$user = $config['username'] ?? 'root';
|
||||||
|
$pass = $config['password'] ?? '';
|
||||||
|
$db = $config['db'] ?? '';
|
||||||
|
$port = $config['port'] ?? null;
|
||||||
|
$socket = $config['socket'] ?? null;
|
||||||
|
$charset = $config['charset'] ?? 'utf8mb4';
|
||||||
|
|
||||||
|
$this->conn = @new mysqli($host, $user, $pass, $db, $port ?? ini_get("mysqli.default_port"), $socket);
|
||||||
|
if ($this->conn->connect_errno) {
|
||||||
|
throw new Exception('MySQL connection error: ' . $this->conn->connect_error);
|
||||||
|
}
|
||||||
|
$this->conn->set_charset($charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array|bool
|
||||||
|
*/
|
||||||
|
public function rawQuery(string $sql, array $params = [])
|
||||||
|
{
|
||||||
|
if (empty($params)) {
|
||||||
|
$result = $this->conn->query($sql);
|
||||||
|
if ($result === false) {
|
||||||
|
throw new Exception('Query error: ' . $this->conn->error);
|
||||||
|
}
|
||||||
|
if ($result === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$data = $result->fetch_all(MYSQLI_ASSOC);
|
||||||
|
$result->free();
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $this->prepareAndBind($sql, $params);
|
||||||
|
if (!$stmt->execute()) {
|
||||||
|
throw new Exception('Query error: ' . $stmt->error);
|
||||||
|
}
|
||||||
|
$res = $stmt->get_result();
|
||||||
|
$rows = $res ? $res->fetch_all(MYSQLI_ASSOC) : [];
|
||||||
|
$stmt->close();
|
||||||
|
return $rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array|bool
|
||||||
|
*/
|
||||||
|
public function query(string $sql, array $params = [])
|
||||||
|
{
|
||||||
|
return $this->rawQuery($sql, $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public function getOne(string $sql, array $params = [])
|
||||||
|
{
|
||||||
|
$rows = $this->rawQuery($sql, $params);
|
||||||
|
return $rows[0] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue(string $sql, array $params = [])
|
||||||
|
{
|
||||||
|
$row = $this->getOne($sql, $params);
|
||||||
|
if (!$row) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return array_shift($row);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function insert(string $table, array $data): int
|
||||||
|
{
|
||||||
|
$cols = array_keys($data);
|
||||||
|
$placeholders = implode(',', array_fill(0, count($cols), '?'));
|
||||||
|
$colList = '`' . implode('`,`', $cols) . '`';
|
||||||
|
$sql = "INSERT INTO `$table` ($colList) VALUES ($placeholders)";
|
||||||
|
$stmt = $this->prepareAndBind($sql, array_values($data));
|
||||||
|
if (!$stmt->execute()) {
|
||||||
|
throw new Exception('Insert error: ' . $stmt->error);
|
||||||
|
}
|
||||||
|
$id = $stmt->insert_id ?: $this->conn->insert_id;
|
||||||
|
$stmt->close();
|
||||||
|
return (int) $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteById(string $table, int $id): bool
|
||||||
|
{
|
||||||
|
$stmt = $this->prepareAndBind("DELETE FROM `$table` WHERE id = ?", [$id]);
|
||||||
|
$ok = $stmt->execute();
|
||||||
|
$stmt->close();
|
||||||
|
return $ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(string $table, array $data, string $where, array $params = []): bool
|
||||||
|
{
|
||||||
|
$sets = [];
|
||||||
|
$values = [];
|
||||||
|
foreach ($data as $col => $val) {
|
||||||
|
$sets[] = "`$col` = ?";
|
||||||
|
$values[] = $val;
|
||||||
|
}
|
||||||
|
$sql = "UPDATE `$table` SET " . implode(',', $sets) . " WHERE $where";
|
||||||
|
$bind = array_merge($values, $params);
|
||||||
|
$stmt = $this->prepareAndBind($sql, $bind);
|
||||||
|
$ok = $stmt->execute();
|
||||||
|
$stmt->close();
|
||||||
|
return $ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function prepareAndBind(string $sql, array $params): mysqli_stmt
|
||||||
|
{
|
||||||
|
$stmt = $this->conn->prepare($sql);
|
||||||
|
if (!$stmt) {
|
||||||
|
throw new Exception('Prepare failed: ' . $this->conn->error);
|
||||||
|
}
|
||||||
|
if (!empty($params)) {
|
||||||
|
$types = '';
|
||||||
|
$refs = [];
|
||||||
|
foreach ($params as $param) {
|
||||||
|
$types .= is_int($param) ? 'i' : (is_float($param) ? 'd' : 's');
|
||||||
|
}
|
||||||
|
$refs[] = &$types;
|
||||||
|
foreach ($params as $k => $v) {
|
||||||
|
$refs[] = &$params[$k];
|
||||||
|
}
|
||||||
|
$stmt->bind_param(...$refs);
|
||||||
|
}
|
||||||
|
return $stmt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<footer class="bg-success text-white py-3 mt-5">
|
||||||
|
<div class="container d-flex flex-wrap justify-content-between">
|
||||||
|
<small>@ CREST - Chest Research and Training Pyt Lad</small>
|
||||||
|
<div class="d-flex gap-3 small">
|
||||||
|
<a href="#" class="text-white text-decoration-none">Privacy Policy</a>
|
||||||
|
<a href="#" class="text-white text-decoration-none">Terms of use</a>
|
||||||
|
<a href="#" class="text-white text-decoration-none">Linkin</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="assets/js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
$pageTitle = $pageTitle ?? 'CREST';
|
||||||
|
$metaDescription = $metaDescription ?? 'CREST advances respiratory health through research, training, and collaboration.';
|
||||||
|
$canonical = '';
|
||||||
|
if (!empty($_SERVER['HTTP_HOST']) && !empty($_SERVER['REQUEST_URI'])) {
|
||||||
|
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
|
||||||
|
$canonical = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="<?php echo htmlspecialchars($metaDescription, ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
<meta name="robots" content="index,follow">
|
||||||
|
<meta property="og:title" content="<?php echo htmlspecialchars($pageTitle, ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
<meta property="og:description" content="<?php echo htmlspecialchars($metaDescription, ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
<?php if ($canonical): ?><link rel="canonical" href="<?php echo htmlspecialchars($canonical, ENT_QUOTES, 'UTF-8'); ?>"><?php endif; ?>
|
||||||
|
<title><?php echo htmlspecialchars($pageTitle); ?></title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-expand-lg bg-body-tertiary shadow-sm sticky-top">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand d-flex align-items-center gap-2" href="index.php">
|
||||||
|
<div class="brand-mark text-white fw-bold d-flex align-items-center justify-content-center">C</div>
|
||||||
|
<div>
|
||||||
|
<div class="fw-bold text-success m-0 lh-1">CREST</div>
|
||||||
|
<small class="text-muted d-block" style="font-size:12px;">Chest Research and Training</small>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" data-bs-target="#mainNav" aria-controls="mainNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="mainNav">
|
||||||
|
<ul class="navbar-nav ms-auto mb-2 mb-lg-0 small fw-semibold">
|
||||||
|
<li class="nav-item"><a class="nav-link text-muted" href="index.php">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link text-muted" href="who-we-are.php">Who we are</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link text-muted" href="expertise.php">Our Expertise</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link text-muted" href="training.php">Training</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link text-muted" href="achievements.php">Achievements</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link text-muted" href="resources.php">Resources</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link text-muted" href="work-with-us.php">Work with us</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link text-muted" href="contact.php">Contact</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
@ -0,0 +1,282 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/data.php';
|
||||||
|
$resources = get_tutorials(); // reuse tutorials data for resources section
|
||||||
|
$sessions = get_sessions();
|
||||||
|
$pageTitle = 'CREST | Chest Research and Training';
|
||||||
|
$metaDescription = 'Explore CREST respiratory research, training programs, events, and downloadable resources to strengthen lung health initiatives.';
|
||||||
|
include __DIR__ . '/includes/site-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="hero-section py-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row g-4 align-items-center">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Transforming Respiratory Health Through</p>
|
||||||
|
<h1 class="fw-bold lh-1">Research, Training & Innovation</h1>
|
||||||
|
<p class="text-muted mb-4">Advancing the science of lung health to create a healthier India.</p>
|
||||||
|
<div class="d-flex flex-wrap gap-2 mb-4">
|
||||||
|
<a class="btn btn-outline-secondary rounded-3" href="#resources">Browse services</a>
|
||||||
|
<a class="btn btn-success text-white rounded-3" href="#contact">Get in touch</a>
|
||||||
|
</div>
|
||||||
|
<div class="row row-cols-2 row-cols-md-3 row-cols-lg-5 g-2">
|
||||||
|
<div class="col">
|
||||||
|
<div class="stat-tile text-center p-3 h-100 rounded-4 bg-light-subtle">
|
||||||
|
<div class="fw-bold">1Mn+</div>
|
||||||
|
<div class="text-muted small">Lives touched</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="stat-tile text-center p-3 h-100 rounded-4 bg-light-subtle">
|
||||||
|
<div class="fw-bold">5k+</div>
|
||||||
|
<div class="text-muted small">Doctors trained</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="stat-tile text-center p-3 h-100 rounded-4 bg-light-subtle">
|
||||||
|
<div class="fw-bold">500+</div>
|
||||||
|
<div class="text-muted small">Medical schools</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="stat-tile text-center p-3 h-100 rounded-4 bg-light-subtle">
|
||||||
|
<div class="fw-bold">300+</div>
|
||||||
|
<div class="text-muted small">Research studies</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="stat-tile text-center p-3 h-100 rounded-4 bg-light-subtle">
|
||||||
|
<div class="fw-bold">50+</div>
|
||||||
|
<div class="text-muted small">New research</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 text-center">
|
||||||
|
<div class="hero-orb mx-auto mb-3">
|
||||||
|
<div class="hero-orb-inner"></div>
|
||||||
|
</div>
|
||||||
|
<span class="badge text-bg-dark px-3 py-2 rounded-pill">Lab ready</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="py-5" id="who">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row g-4 align-items-center">
|
||||||
|
<div class="col-md-5">
|
||||||
|
<div class="rounded-4 bg-light-subtle p-4 h-100 d-flex flex-column justify-content-between">
|
||||||
|
<div class="placeholder-img flex-grow-1 rounded-4 mb-3"></div>
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<span class="badge bg-success-subtle text-success fw-semibold">300+</span>
|
||||||
|
<span class="small text-muted">consultants & specialists</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-7">
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Who we are</p>
|
||||||
|
<h2 class="fw-bold">Grounded in data, inspired by care</h2>
|
||||||
|
<p class="text-muted">We are a multidisciplinary team working at the intersection of research, training, and respiratory medicine. From field studies to clinical education, we help organizations make lung health programs measurable, effective, and equitable.</p>
|
||||||
|
<ul class="list-unstyled mb-3">
|
||||||
|
<li class="d-flex align-items-center gap-2 mb-2">
|
||||||
|
<span class="dot bg-success"></span>
|
||||||
|
<span class="fw-semibold">Modern Research Device</span>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex align-items-center gap-2 mb-2">
|
||||||
|
<span class="dot bg-warning"></span>
|
||||||
|
<span class="fw-semibold">World Class laboratory</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<a class="btn btn-success text-white rounded-3" href="#expertise">Learn more</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="py-5 bg-light" id="expertise">
|
||||||
|
<div class="container">
|
||||||
|
<div class="d-flex flex-wrap justify-content-between align-items-center mb-4">
|
||||||
|
<div>
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Our Expertise</p>
|
||||||
|
<h3 class="fw-bold">Our Services & Expertise</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card h-100 shadow-sm border-0 rounded-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="icon-pill mb-3">★</div>
|
||||||
|
<h5 class="fw-bold">Research</h5>
|
||||||
|
<p class="text-muted small mb-3">Rigorous studies to map lung health trends and inform community programs.</p>
|
||||||
|
<a class="text-success fw-semibold small" href="#">Learn more</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card h-100 shadow-sm border-0 rounded-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="icon-pill mb-3">★</div>
|
||||||
|
<h5 class="fw-bold">Training</h5>
|
||||||
|
<p class="text-muted small mb-3">Workshops and mentoring that upskill clinicians and field teams.</p>
|
||||||
|
<a class="text-success fw-semibold small" href="#">Learn more</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card h-100 shadow-sm border-0 rounded-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="icon-pill mb-3">★</div>
|
||||||
|
<h5 class="fw-bold">Consulting</h5>
|
||||||
|
<p class="text-muted small mb-3">Advisory for programs to scale respiratory care safely and effectively.</p>
|
||||||
|
<a class="text-success fw-semibold small" href="#">Learn more</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="py-5" id="training">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row g-4 align-items-center">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<h3 class="fw-bold">Training Program</h3>
|
||||||
|
<p class="text-muted">Our modular training brings together research-backed content, case-based discussions, and practical skill-building so teams can lead respiratory health initiatives confidently.</p>
|
||||||
|
<ul class="list-unstyled text-muted small mb-3">
|
||||||
|
<li class="mb-1">• Research Training</li>
|
||||||
|
<li class="mb-1">• Spirometry & Lung Function Testing</li>
|
||||||
|
<li class="mb-1">• Critical Situations</li>
|
||||||
|
<li class="mb-1">• Audit Program</li>
|
||||||
|
<li class="mb-1">• Quality Assurance</li>
|
||||||
|
</ul>
|
||||||
|
<a class="btn btn-success text-white rounded-3">Join the training</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="rounded-4 bg-light-subtle p-3">
|
||||||
|
<div class="placeholder-img tall rounded-4 mb-3"></div>
|
||||||
|
<span class="badge bg-success-subtle text-success fw-semibold">100+ batch completions</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="py-5 bg-body" id="events">
|
||||||
|
<div class="container">
|
||||||
|
<div class="d-flex flex-wrap justify-content-between align-items-center mb-4">
|
||||||
|
<div>
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Latest Events</p>
|
||||||
|
<h3 class="fw-bold">Latest Events</h3>
|
||||||
|
</div>
|
||||||
|
<a class="btn btn-outline-success" href="sessions-list.php">View all events</a>
|
||||||
|
</div>
|
||||||
|
<?php if (empty($sessions)): ?>
|
||||||
|
<p class="text-muted">No upcoming sessions yet. Check back soon.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="row g-3">
|
||||||
|
<?php foreach ($sessions as $session): ?>
|
||||||
|
<?php
|
||||||
|
if (!is_array($session)) { continue; }
|
||||||
|
$number = htmlspecialchars((string)($session['number'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$startDate = !empty($session['start_date']) ? date('M d, Y', strtotime($session['start_date'])) : '';
|
||||||
|
$venue = htmlspecialchars((string)($session['venue'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$code = htmlspecialchars((string)($session['code'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$regLink = $code ? "https://road.xltr.in/register/{$code}" : '#';
|
||||||
|
?>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card h-100 shadow-sm border-0 rounded-4">
|
||||||
|
<div class="placeholder-img small rounded-top-4"></div>
|
||||||
|
<div class="card-body position-relative">
|
||||||
|
<span class="badge bg-white border text-success position-absolute top-0 end-0 m-3">Upcoming</span>
|
||||||
|
<h6 class="fw-bold mt-3">Session <?php echo $number ?: 'N/A'; ?></h6>
|
||||||
|
<?php if ($startDate): ?><p class="text-muted small mb-1">Starts: <?php echo $startDate; ?></p><?php endif; ?>
|
||||||
|
<?php if ($venue): ?><p class="text-muted small mb-2">Venue: <?php echo $venue; ?></p><?php endif; ?>
|
||||||
|
<a class="btn btn-outline-success btn-sm mt-2" href="<?php echo $regLink; ?>" target="_blank">Register</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="py-5" id="resources">
|
||||||
|
<div class="container">
|
||||||
|
<div class="mb-4">
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Resources for Learning and Research</p>
|
||||||
|
<h3 class="fw-bold">Resources for Learning and Research</h3>
|
||||||
|
<p class="text-muted small">Well-curated resources to explore our work and keep you up to date on our research.</p>
|
||||||
|
</div>
|
||||||
|
<?php if (empty($resources)): ?>
|
||||||
|
<p class="text-muted">No resources yet.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="row g-3">
|
||||||
|
<?php foreach ($resources as $resource): ?>
|
||||||
|
<?php
|
||||||
|
if (!is_array($resource)) { continue; }
|
||||||
|
$label = htmlspecialchars((string)($resource['label'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$title = htmlspecialchars((string)($resource['title'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$summary = htmlspecialchars((string)($resource['description'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$filePath = isset($resource['file_path']) ? (string)$resource['file_path'] : '';
|
||||||
|
$videoUrl = isset($resource['video_url']) ? (string)$resource['video_url'] : '';
|
||||||
|
?>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card h-100 shadow-sm border-0 rounded-4 p-3">
|
||||||
|
<span class="badge bg-success-subtle text-success fw-semibold mb-2"><?php echo $label; ?></span>
|
||||||
|
<h6 class="fw-bold"><?php echo $title; ?></h6>
|
||||||
|
<p class="text-muted small mb-3"><?php echo $summary; ?></p>
|
||||||
|
<div class="d-flex gap-2 flex-wrap">
|
||||||
|
<?php if ($filePath): ?>
|
||||||
|
<a class="btn btn-outline-success btn-sm" href="<?php echo htmlspecialchars(ltrim($filePath, '/'), ENT_QUOTES, 'UTF-8'); ?>" target="_blank">Download</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($videoUrl): ?>
|
||||||
|
<a class="btn btn-success btn-sm text-white" href="<?php echo htmlspecialchars($videoUrl, ENT_QUOTES, 'UTF-8'); ?>" target="_blank">Watch</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (!$filePath && !$videoUrl): ?>
|
||||||
|
<span class="text-muted small">No download yet</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
<section class="py-5 bg-success-subtle" id="contact">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row g-4 align-items-center">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Subscribe</p>
|
||||||
|
<h3 class="fw-bold">Subscribe to Regular Newsletters.</h3>
|
||||||
|
<p class="text-muted">Get curated research insights and training updates straight to your inbox.</p>
|
||||||
|
<?php if (!empty($newsletterMessage)): ?>
|
||||||
|
<div class="alert alert-success p-2"><?php echo htmlspecialchars($newsletterMessage); ?></div>
|
||||||
|
<?php elseif (!empty($newsletterError)): ?>
|
||||||
|
<div class="alert alert-danger p-2"><?php echo htmlspecialchars($newsletterError); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<form class="row g-2" method="post">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<input type="text" class="form-control rounded-3" name="newsletter_name" placeholder="First Name">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<input type="email" class="form-control rounded-3" name="newsletter_email" placeholder="Email" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 d-grid">
|
||||||
|
<button class="btn btn-success text-white rounded-3" type="submit">Subscribe</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 text-center">
|
||||||
|
<div class="placeholder-img mailer rounded-4"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/includes/site-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/data.php';
|
||||||
|
$pageTitle = 'News & Events | CREST';
|
||||||
|
$metaDescription = 'Stay updated on CREST respiratory health events and upcoming training sessions.';
|
||||||
|
$sessions = get_sessions();
|
||||||
|
include __DIR__ . '/includes/site-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="py-5 bg-light">
|
||||||
|
<div class="container">
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">News & Events</p>
|
||||||
|
<h1 class="fw-bold">Latest updates, workshops, and announcements</h1>
|
||||||
|
<?php if (empty($sessions)): ?>
|
||||||
|
<p class="text-muted" style="margin-top:16px;">No sessions announced yet. Check back soon.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="row g-3" style="margin-top:16px;">
|
||||||
|
<?php foreach ($sessions as $session): ?>
|
||||||
|
<?php
|
||||||
|
$number = htmlspecialchars((string)($session['number'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$startDate = !empty($session['start_date']) ? date('M d, Y', strtotime($session['start_date'])) : '';
|
||||||
|
$venue = htmlspecialchars((string)($session['venue'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$code = htmlspecialchars((string)($session['code'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$regLink = $code ? "https://road.xltr.in/register/{$code}" : '#';
|
||||||
|
?>
|
||||||
|
<article class="card event-card col-md-4">
|
||||||
|
<div class="placeholder-img small"></div>
|
||||||
|
<div class="chip">Upcoming</div>
|
||||||
|
<h3><?php echo $number ? 'Session ' . $number : 'Session'; ?></h3>
|
||||||
|
<?php if ($startDate): ?><p class="text-muted small mb-1">Starts: <?php echo $startDate; ?></p><?php endif; ?>
|
||||||
|
<?php if ($venue): ?><p class="text-muted small mb-2">Venue: <?php echo $venue; ?></p><?php endif; ?>
|
||||||
|
<a class="btn btn-outline-success btn-sm" href="<?php echo $regLink; ?>" target="_blank">Register</a>
|
||||||
|
</article>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/includes/site-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/data.php';
|
||||||
|
$pageTitle = 'Resources | CREST';
|
||||||
|
$metaDescription = 'Download CREST respiratory learning resources including tutorials, guides, and video sessions.';
|
||||||
|
$resources = get_tutorials(false); // reuse tutorials data for resources page
|
||||||
|
include __DIR__ . '/includes/site-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Resources</p>
|
||||||
|
<h1 class="fw-bold">Resources for Learning and Research</h1>
|
||||||
|
<p class="text-muted">Downloadable guides, publications, and toolkits created by our faculty to support your teams.</p>
|
||||||
|
|
||||||
|
<?php if (empty($resources)): ?>
|
||||||
|
<p class="text-muted" style="margin-top:16px;">No resources yet. Check back soon.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="row g-3" style="margin-top:20px;">
|
||||||
|
<?php foreach ($resources as $resource): ?>
|
||||||
|
<?php
|
||||||
|
if (!is_array($resource)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$label = htmlspecialchars((string)($resource['label'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$title = htmlspecialchars((string)($resource['title'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$summary = htmlspecialchars((string)($resource['description'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$filePath = isset($resource['file_path']) ? (string)$resource['file_path'] : '';
|
||||||
|
$videoUrl = isset($resource['video_url']) ? (string)$resource['video_url'] : '';
|
||||||
|
?>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<article class="card h-100 shadow-sm border-0 rounded-4 p-3">
|
||||||
|
<span class="badge bg-success-subtle text-success fw-semibold mb-2"><?php echo $label ?: 'Resource'; ?></span>
|
||||||
|
<h3 class="h5 fw-bold"><?php echo $title; ?></h3>
|
||||||
|
<p class="text-muted small mb-3"><?php echo $summary; ?></p>
|
||||||
|
<div class="d-flex gap-2 flex-wrap">
|
||||||
|
<?php if ($filePath): ?>
|
||||||
|
<a class="btn btn-outline-success btn-sm" href="<?php echo htmlspecialchars(ltrim($filePath, '/'), ENT_QUOTES, 'UTF-8'); ?>" target="_blank">Download</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($videoUrl): ?>
|
||||||
|
<a class="btn btn-success btn-sm text-white" href="<?php echo htmlspecialchars($videoUrl, ENT_QUOTES, 'UTF-8'); ?>" target="_blank">Watch</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (!$filePath && !$videoUrl): ?>
|
||||||
|
<span class="text-muted small">No download yet</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/includes/site-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
$pageTitle = 'Our Services | Crest Lung Health';
|
||||||
|
$currentPage = 'services';
|
||||||
|
require __DIR__ . '/includes/header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="section light">
|
||||||
|
<div class="container">
|
||||||
|
<p class="eyebrow">Our Services</p>
|
||||||
|
<h1>Integrated solutions for lung health programs</h1>
|
||||||
|
<p class="body">From research design to clinical training and program evaluation, our services are built to deliver measurable outcomes.</p>
|
||||||
|
|
||||||
|
<div class="card-grid" style="margin-top:20px;">
|
||||||
|
<article class="card">
|
||||||
|
<div class="icon-pill">R</div>
|
||||||
|
<h3>Research Design</h3>
|
||||||
|
<p>Protocol development, ethics submissions, and analytics frameworks tailored to your population.</p>
|
||||||
|
</article>
|
||||||
|
<article class="card">
|
||||||
|
<div class="icon-pill">T</div>
|
||||||
|
<h3>Training & Upskilling</h3>
|
||||||
|
<p>Workshops, certifications, and blended learning pathways for clinicians and field teams.</p>
|
||||||
|
</article>
|
||||||
|
<article class="card">
|
||||||
|
<div class="icon-pill">Q</div>
|
||||||
|
<h3>Quality & Audits</h3>
|
||||||
|
<p>End-to-end audits, standard operating procedures, and continuous improvement playbooks.</p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php require __DIR__ . '/includes/footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/data.php';
|
||||||
|
$pageTitle = 'Events | CREST';
|
||||||
|
$metaDescription = 'Browse all current and upcoming CREST sessions with dates, venues, and registration links.';
|
||||||
|
$sessions = get_sessions();
|
||||||
|
include __DIR__ . '/includes/site-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="py-5 bg-light">
|
||||||
|
<div class="container">
|
||||||
|
<div class="d-flex flex-wrap justify-content-between align-items-center mb-4">
|
||||||
|
<div>
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Events</p>
|
||||||
|
<h1 class="fw-bold">Current & Upcoming Sessions</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php if (empty($sessions)): ?>
|
||||||
|
<p class="text-muted" style="margin-top:16px;">No sessions announced yet. Check back soon.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="row g-3" style="margin-top:16px;">
|
||||||
|
<?php foreach ($sessions as $session): ?>
|
||||||
|
<?php
|
||||||
|
if (!is_array($session)) { continue; }
|
||||||
|
$number = htmlspecialchars((string)($session['number'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$startDate = !empty($session['start_date']) ? date('M d, Y', strtotime($session['start_date'])) : '';
|
||||||
|
$venue = htmlspecialchars((string)($session['venue'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$code = htmlspecialchars((string)($session['code'] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
$regLink = $code ? "https://road.xltr.in/register/{$code}" : '#';
|
||||||
|
?>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<article class="card event-card h-100">
|
||||||
|
<div class="placeholder-img small"></div>
|
||||||
|
<div class="chip">Upcoming</div>
|
||||||
|
<div class="p-3">
|
||||||
|
<h5 class="fw-bold"><?php echo $number ? 'Session ' . $number : 'Session'; ?></h5>
|
||||||
|
<?php if ($startDate): ?><p class="text-muted small mb-1">Starts: <?php echo $startDate; ?></p><?php endif; ?>
|
||||||
|
<?php if ($venue): ?><p class="text-muted small mb-2">Venue: <?php echo $venue; ?></p><?php endif; ?>
|
||||||
|
<a class="btn btn-outline-success btn-sm" href="<?php echo $regLink; ?>" target="_blank">Register</a>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/includes/site-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/data.php';
|
||||||
|
$pageTitle = 'Training | CREST';
|
||||||
|
$metaDescription = 'Join CREST respiratory training programs covering spirometry, critical care, quality assurance, and field research.';
|
||||||
|
include __DIR__ . '/includes/site-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row g-4 align-items-center">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<h3 class="fw-bold">Training Program</h3>
|
||||||
|
<p class="text-muted">Our modular training brings together research-backed content, case-based discussions, and practical skill-building so teams can lead respiratory health initiatives confidently.</p>
|
||||||
|
<ul class="list-unstyled text-muted small mb-3">
|
||||||
|
<li class="mb-1">• Research Training</li>
|
||||||
|
<li class="mb-1">• Spirometry & Lung Function Testing</li>
|
||||||
|
<li class="mb-1">• Critical Situations</li>
|
||||||
|
<li class="mb-1">• Audit Program</li>
|
||||||
|
<li class="mb-1">• Quality Assurance</li>
|
||||||
|
</ul>
|
||||||
|
<a class="btn btn-success text-white rounded-3">Join the training</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="placeholder-img tall rounded-4 mb-3"></div>
|
||||||
|
<span class="badge bg-success-subtle text-success fw-semibold">100+ batch completions</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/includes/site-footer.php'; ?>
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/data.php';
|
||||||
|
$pageTitle = 'Who we are | CREST';
|
||||||
|
$metaDescription = 'Learn about CREST and our multidisciplinary team focused on advancing respiratory health through research and training.';
|
||||||
|
include __DIR__ . '/includes/site-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row g-4 align-items-center">
|
||||||
|
<div class="col-md-5">
|
||||||
|
<div class="placeholder-img tall rounded-4 mb-3"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-7">
|
||||||
|
<p class="text-uppercase text-success fw-bold small mb-1">Who we are</p>
|
||||||
|
<h2 class="fw-bold">Grounded in data, inspired by care</h2>
|
||||||
|
<p class="text-muted">We are a multidisciplinary team working at the intersection of research, training, and respiratory medicine. From field studies to clinical education, we help organizations make lung health programs measurable, effective, and equitable.</p>
|
||||||
|
<ul class="list-unstyled mb-3">
|
||||||
|
<li class="mb-2">• Modern research device set-up</li>
|
||||||
|
<li class="mb-2">• World-class laboratory standards</li>
|
||||||
|
</ul>
|
||||||
|
<a class="btn btn-success text-white rounded-3" href="expertise.php">Explore expertise</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/includes/site-footer.php'; ?>
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/data.php';
|
||||||
|
$pageTitle = 'Work with us | CREST';
|
||||||
|
$metaDescription = 'Partner with CREST for research collaborations, training partnerships, and respiratory program consulting.';
|
||||||
|
include __DIR__ . '/includes/site-header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="fw-bold mb-3">Work with us</h2>
|
||||||
|
<p class="text-muted mb-4">Partner with us on research, training programs, or pilot initiatives to strengthen respiratory health outcomes.</p>
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card shadow-sm border-0 rounded-4 h-100">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="fw-bold">Research collaborations</h5>
|
||||||
|
<p class="text-muted small mb-0">Co-design studies, data collection, and analysis with our research team.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card shadow-sm border-0 rounded-4 h-100">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="fw-bold">Training partnerships</h5>
|
||||||
|
<p class="text-muted small mb-0">Upskill your teams with modular curricula and faculty-led workshops.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card shadow-sm border-0 rounded-4 h-100">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="fw-bold">Program consulting</h5>
|
||||||
|
<p class="text-muted small mb-0">Set up or scale clinics, QA processes, and field operations with our experts.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/includes/site-footer.php'; ?>
|
||||||
Loading…
Reference in New Issue