commit 6c8960d09d205afcea577bd3f1a8e828f214b77a Author: Ravi Gulhane <> Date: Mon May 18 10:13:20 2026 +0530 Recover project structure diff --git a/laravel b/laravel new file mode 160000 index 0000000..71f2f59 --- /dev/null +++ b/laravel @@ -0,0 +1 @@ +Subproject commit 71f2f59185314709834fd132e91636eca4d1d0fb diff --git a/website/achievements.php b/website/achievements.php new file mode 100644 index 0000000..6f58b77 --- /dev/null +++ b/website/achievements.php @@ -0,0 +1,44 @@ + + +
+
+
+

Achievements

+

Milestones powered by data and collaboration

+
+
+
+
1Mn+
+
Lives touched
+
+
+
+
+
5k+
+
Doctors trained
+
+
+
+
+
500+
+
Medical schools
+
+
+
+
+
300+
+
Research studies
+
+
+
+

These numbers reflect multi-year partnerships, field programs, and training cohorts across India.

+
+
+
+ + diff --git a/website/admin/admins.php b/website/admin/admins.php new file mode 100644 index 0000000..5c5b45f --- /dev/null +++ b/website/admin/admins.php @@ -0,0 +1,112 @@ +query("SELECT email, created_at FROM admins ORDER BY created_at DESC"); +$admins = is_array($admins) ? $admins : []; +$assetPathPrefix = '../'; +$pageTitle = 'Admins'; +$currentPage = ''; +$extraStyles = << + 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; } + +CSS; + +require __DIR__ . '/../includes/admin-header.php'; +?> + +
+
+
+
+

Admins

+

Manage administrator accounts

+
+
+ + + +
+ + +
+ + +
+

Add Admin

+
+ + + + + + +
+ +
+
+
+ +
+

Existing Admins

+ +

No admins found.

+ + + + + + + + + + + + + + + + +
EmailCreated
+ +
+
+
+ + diff --git a/website/admin/contacts.php b/website/admin/contacts.php new file mode 100644 index 0000000..b4481b9 --- /dev/null +++ b/website/admin/contacts.php @@ -0,0 +1,91 @@ + + 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; } + +CSS; + +require __DIR__ . '/../includes/admin-header.php'; +?> + +
+
+
+
+

Contact Entries

+

Messages from the contact form

+
+
Read-only
+
+ + +
+ Export CSV +
+ + +

No messages yet.

+ + + + + + + + + + + + + + + + + + + + + + +
NameEmailOrganizationMessageReceived
+ +
+
+ + diff --git a/website/admin/login.php b/website/admin/login.php new file mode 100644 index 0000000..19a416a --- /dev/null +++ b/website/admin/login.php @@ -0,0 +1,47 @@ + + +
+
+
+

Admin Login

+ +
+ +
+
+ + +
+
+ + +
+ +

Default admin: ravi@stratawiz.com / qwerty

+
+
+
+
+ + diff --git a/website/admin/logout.php b/website/admin/logout.php new file mode 100644 index 0000000..3f36376 --- /dev/null +++ b/website/admin/logout.php @@ -0,0 +1,5 @@ + + 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; } + +CSS; + +require __DIR__ . '/../includes/admin-header.php'; +?> + +
+
+
+
+

Newsletter

+

Subscription list

+
+
Read-only
+
+ + +
+ Export CSV +
+ + +

No subscribers yet.

+ + + + + + + + + + + + + + + + + + +
First NameEmailSubscribed
+ +
+
+ + diff --git a/website/admin/resources.php b/website/admin/resources.php new file mode 100644 index 0000000..d714e9e --- /dev/null +++ b/website/admin/resources.php @@ -0,0 +1,191 @@ +'; print_r($resources); exit; +$assetPathPrefix = '../'; +$pageTitle = 'Manage Resources'; +$currentPage = 'resources'; +$extraStyles = << + 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; } + +CSS; + +require __DIR__ . '/../includes/admin-header.php'; +?> + +
+
+
+
+

Resources

+

Resources for Learning and Research

+

Add short descriptions and labels; they will appear instantly on the public site.

+
+ +
+ + + +
Resource added successfully.
+ + +
Resource deleted.
+ + +
+ + + +

No resources yet. Add your first entry below.

+ + + + + + + + + + + + + $resource): ?> + + + + + + + + + + +
TitleSummaryLabelAsset
+ + Download + + Watch + + None + + Delete
+ + +
+
+

Add Resource

+
+ + + + + + + + + + + + + + +

Upload a file or provide a video URL (or both).

+ +
+ + View live site +
+
+
+
+
+
+ + diff --git a/website/admin/sessions.php b/website/admin/sessions.php new file mode 100644 index 0000000..3fcda81 --- /dev/null +++ b/website/admin/sessions.php @@ -0,0 +1,163 @@ + + 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; } + +CSS; + +require __DIR__ . '/../includes/admin-header.php'; +?> + +
+
+
+
+

Upcoming Sessions

+

Manage events and workshops

+

Add session details to show on the public site.

+
+ +
+ + + +
Session added successfully.
+ + +
Session deleted.
+ + +
Session updated.
+ + +
+ + + +

No sessions yet. Add your first event below.

+ + + + + + + + + + + + + + + + + + + + + + +
TitleDescriptionTagStart Date
+ Edit | + Delete +
+ + +
+
+

+
+ + + + + + + + + + + + + + + + + + +
+ + View live +
+
+
+
+
+
+ + diff --git a/website/admin/tutorials.php b/website/admin/tutorials.php new file mode 100644 index 0000000..182ea62 --- /dev/null +++ b/website/admin/tutorials.php @@ -0,0 +1,222 @@ + + 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; } + +CSS; + +require __DIR__ . '/../includes/admin-header.php'; +?> + +
+
+
+
+

Tutorials

+

Manage tutorials

+

Add training tutorials with downloads or video links.

+
+ +
+ + + +
Tutorial added successfully.
+ + +
Tutorial deleted.
+ + +
Tutorial updated successfully.
+ + +
+ + + +

No tutorials yet. Add your first entry below.

+ + + + + + + + + + + + + + + + + + + + + + + +
TitleDescriptionStatusAsset
+ + Download + + Watch + + None + + + Edit | + Delete +
+ + +
+
+

+
+ + + + + + + + + + + + + + + + + + +

Current file: Download

+ +

Upload a file or provide a video URL (or both).

+ + +
+
+
+
+
+ + diff --git a/website/assets/css/admin.css b/website/assets/css/admin.css new file mode 100644 index 0000000..5ac74bb --- /dev/null +++ b/website/assets/css/admin.css @@ -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; +} diff --git a/website/assets/css/style.css b/website/assets/css/style.css new file mode 100644 index 0000000..5fcd576 --- /dev/null +++ b/website/assets/css/style.css @@ -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; } diff --git a/website/assets/js/main.js b/website/assets/js/main.js new file mode 100644 index 0000000..5da48f9 --- /dev/null +++ b/website/assets/js/main.js @@ -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. + }); + } +}); diff --git a/website/contact.php b/website/contact.php new file mode 100644 index 0000000..a2bb8d1 --- /dev/null +++ b/website/contact.php @@ -0,0 +1,72 @@ + + +
+
+
+
+
+

Contact

+

We would love to hear from you

+

Tell us about your research needs, training goals, or partnership ideas.

+
    +
  • • Program design consultations
  • +
  • • Training calendar requests
  • +
  • • Media and speaking inquiries
  • +
+
+
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/website/data/resources.json b/website/data/resources.json new file mode 100644 index 0000000..166e9a9 --- /dev/null +++ b/website/data/resources.json @@ -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" + } +] diff --git a/website/expertise.php b/website/expertise.php new file mode 100644 index 0000000..0418a34 --- /dev/null +++ b/website/expertise.php @@ -0,0 +1,48 @@ + + +
+
+
+
+

Our Expertise

+

Our Services & Expertise

+
+
+
+
+
+
★
+
Research
+

Rigorous studies to map lung health trends and inform community programs.

+
+
+
+
+
+
+
★
+
Training
+

Workshops and mentoring that upskill clinicians and field teams.

+
+
+
+
+
+
+
★
+
Consulting
+

Advisory for programs to scale respiratory care safely and effectively.

+
+
+
+
+
+
+
+ + diff --git a/website/experts.php b/website/experts.php new file mode 100644 index 0000000..9ca8488 --- /dev/null +++ b/website/experts.php @@ -0,0 +1,28 @@ + + +
+
+
+
+

Our Experts

+

Meet the team driving respiratory innovation

+

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.

+
    +
  • 300+ specialists and faculty contributors
  • +
  • Cross-functional teams for research and training
  • +
  • Field experience across diverse geographies
  • +
+
+
+
+
Trusted by leading institutes
+
+
+
+
+ + diff --git a/website/includes/admin-footer.php b/website/includes/admin-footer.php new file mode 100644 index 0000000..162f444 --- /dev/null +++ b/website/includes/admin-footer.php @@ -0,0 +1,9 @@ +
+
+ ©2025 Stratawiz.com +
+
+ + + + diff --git a/website/includes/admin-header.php b/website/includes/admin-header.php new file mode 100644 index 0000000..aea96cf --- /dev/null +++ b/website/includes/admin-header.php @@ -0,0 +1,33 @@ + + + + + + + <?php echo htmlspecialchars($pageTitle); ?> + + + + + + diff --git a/website/includes/auth.php b/website/includes/auth.php new file mode 100644 index 0000000..8d9c605 --- /dev/null +++ b/website/includes/auth.php @@ -0,0 +1,50 @@ +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]); + } +} diff --git a/website/includes/db.php b/website/includes/db.php new file mode 100644 index 0000000..686efa1 --- /dev/null +++ b/website/includes/db.php @@ -0,0 +1,223 @@ + 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; +} diff --git a/website/includes/footer.php b/website/includes/footer.php new file mode 100644 index 0000000..d2bb41b --- /dev/null +++ b/website/includes/footer.php @@ -0,0 +1,12 @@ + + + + + diff --git a/website/includes/header.php b/website/includes/header.php new file mode 100644 index 0000000..2532b5a --- /dev/null +++ b/website/includes/header.php @@ -0,0 +1,46 @@ + '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'], +]; +?> + + + + + + <?php echo htmlspecialchars($pageTitle); ?> + + + + + + diff --git a/website/includes/mysqli-class.php b/website/includes/mysqli-class.php new file mode 100644 index 0000000..2ce488a --- /dev/null +++ b/website/includes/mysqli-class.php @@ -0,0 +1,138 @@ +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; + } +} diff --git a/website/includes/site-footer.php b/website/includes/site-footer.php new file mode 100644 index 0000000..6678ef5 --- /dev/null +++ b/website/includes/site-footer.php @@ -0,0 +1,14 @@ + + + + + diff --git a/website/includes/site-header.php b/website/includes/site-header.php new file mode 100644 index 0000000..8437d09 --- /dev/null +++ b/website/includes/site-header.php @@ -0,0 +1,50 @@ + + + + + + + + + + + + <?php echo htmlspecialchars($pageTitle); ?> + + + + + diff --git a/website/index.php b/website/index.php new file mode 100644 index 0000000..4f7635a --- /dev/null +++ b/website/index.php @@ -0,0 +1,282 @@ + + +
+
+
+
+
+

Transforming Respiratory Health Through

+

Research, Training & Innovation

+

Advancing the science of lung health to create a healthier India.

+ +
+
+
+
1Mn+
+
Lives touched
+
+
+
+
+
5k+
+
Doctors trained
+
+
+
+
+
500+
+
Medical schools
+
+
+
+
+
300+
+
Research studies
+
+
+
+
+
50+
+
New research
+
+
+
+
+
+
+
+
+ Lab ready +
+
+
+
+ +
+
+
+
+
+
+
+ 300+ + consultants & specialists +
+
+
+
+

Who we are

+

Grounded in data, inspired by care

+

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.

+
    +
  • + + Modern Research Device +
  • +
  • + + World Class laboratory +
  • +
+ Learn more +
+
+
+
+ +
+
+
+
+

Our Expertise

+

Our Services & Expertise

+
+
+
+
+
+
+
★
+
Research
+

Rigorous studies to map lung health trends and inform community programs.

+ Learn more +
+
+
+
+
+
+
★
+
Training
+

Workshops and mentoring that upskill clinicians and field teams.

+ Learn more +
+
+
+
+
+
+
★
+
Consulting
+

Advisory for programs to scale respiratory care safely and effectively.

+ Learn more +
+
+
+
+
+
+ +
+
+
+
+

Training Program

+

Our modular training brings together research-backed content, case-based discussions, and practical skill-building so teams can lead respiratory health initiatives confidently.

+
    +
  • • Research Training
  • +
  • • Spirometry & Lung Function Testing
  • +
  • • Critical Situations
  • +
  • • Audit Program
  • +
  • • Quality Assurance
  • +
+ Join the training +
+
+
+
+ 100+ batch completions +
+
+
+
+
+ +
+
+
+
+

Latest Events

+

Latest Events

+
+ View all events +
+ +

No upcoming sessions yet. Check back soon.

+ +
+ + +
+
+
+
+ Upcoming +
Session
+

Starts:

+

Venue:

+ Register +
+
+
+ +
+ +
+
+ +
+
+
+

Resources for Learning and Research

+

Resources for Learning and Research

+

Well-curated resources to explore our work and keep you up to date on our research.

+
+ +

No resources yet.

+ +
+ + +
+
+ +
+

+
+ + Download + + + Watch + + + No download yet + +
+
+
+ +
+ +
+
+ + +
+
+
+
+

Subscribe

+

Subscribe to Regular Newsletters.

+

Get curated research insights and training updates straight to your inbox.

+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+ + diff --git a/website/news-events.php b/website/news-events.php new file mode 100644 index 0000000..2de956e --- /dev/null +++ b/website/news-events.php @@ -0,0 +1,41 @@ + + +
+
+
+

News & Events

+

Latest updates, workshops, and announcements

+ +

No sessions announced yet. Check back soon.

+ +
+ + +
+
+
Upcoming
+

+

Starts:

+

Venue:

+ Register +
+ +
+ +
+
+
+ + diff --git a/website/resources.php b/website/resources.php new file mode 100644 index 0000000..01878c2 --- /dev/null +++ b/website/resources.php @@ -0,0 +1,56 @@ + + +
+
+
+

Resources

+

Resources for Learning and Research

+

Downloadable guides, publications, and toolkits created by our faculty to support your teams.

+ + +

No resources yet. Check back soon.

+ +
+ + +
+ +
+ +
+ +
+
+
+ + diff --git a/website/services.php b/website/services.php new file mode 100644 index 0000000..15ba369 --- /dev/null +++ b/website/services.php @@ -0,0 +1,35 @@ + + +
+
+
+

Our Services

+

Integrated solutions for lung health programs

+

From research design to clinical training and program evaluation, our services are built to deliver measurable outcomes.

+ +
+
+
R
+

Research Design

+

Protocol development, ethics submissions, and analytics frameworks tailored to your population.

+
+
+
T
+

Training & Upskilling

+

Workshops, certifications, and blended learning pathways for clinicians and field teams.

+
+
+
Q
+

Quality & Audits

+

End-to-end audits, standard operating procedures, and continuous improvement playbooks.

+
+
+
+
+
+ + diff --git a/website/sessions-list.php b/website/sessions-list.php new file mode 100644 index 0000000..be7e345 --- /dev/null +++ b/website/sessions-list.php @@ -0,0 +1,50 @@ + + +
+
+
+
+
+

Events

+

Current & Upcoming Sessions

+
+
+ +

No sessions announced yet. Check back soon.

+ +
+ + +
+
+
+
Upcoming
+
+
+

Starts:

+

Venue:

+ Register +
+
+
+ +
+ +
+
+
+ + diff --git a/website/training.php b/website/training.php new file mode 100644 index 0000000..5798834 --- /dev/null +++ b/website/training.php @@ -0,0 +1,33 @@ + + +
+
+
+
+
+

Training Program

+

Our modular training brings together research-backed content, case-based discussions, and practical skill-building so teams can lead respiratory health initiatives confidently.

+
    +
  • • Research Training
  • +
  • • Spirometry & Lung Function Testing
  • +
  • • Critical Situations
  • +
  • • Audit Program
  • +
  • • Quality Assurance
  • +
+ Join the training +
+
+
+ 100+ batch completions +
+
+
+
+
+ + diff --git a/website/uploads/tutorial_1764217762_7756.docx b/website/uploads/tutorial_1764217762_7756.docx new file mode 100644 index 0000000..b5b5bc2 Binary files /dev/null and b/website/uploads/tutorial_1764217762_7756.docx differ diff --git a/website/who-we-are.php b/website/who-we-are.php new file mode 100644 index 0000000..6143517 --- /dev/null +++ b/website/who-we-are.php @@ -0,0 +1,30 @@ + + +
+
+
+
+
+
+
+
+

Who we are

+

Grounded in data, inspired by care

+

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.

+
    +
  • • Modern research device set-up
  • +
  • • World-class laboratory standards
  • +
+ Explore expertise +
+
+
+
+
+ + diff --git a/website/work-with-us.php b/website/work-with-us.php new file mode 100644 index 0000000..e92928b --- /dev/null +++ b/website/work-with-us.php @@ -0,0 +1,43 @@ + + +
+
+
+

Work with us

+

Partner with us on research, training programs, or pilot initiatives to strengthen respiratory health outcomes.

+
+
+
+
+
Research collaborations
+

Co-design studies, data collection, and analysis with our research team.

+
+
+
+
+
+
+
Training partnerships
+

Upskill your teams with modular curricula and faculty-led workshops.

+
+
+
+
+
+
+
Program consulting
+

Set up or scale clinics, QA processes, and field operations with our experts.

+
+
+
+
+
+
+
+ +