0.2
This commit is contained in:
parent
50088c45be
commit
6e132e0b38
34
README.md
Normal file
34
README.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# SecureLife Insurance Application
|
||||||
|
|
||||||
|
This is a comprehensive insurance application system built with PHP. It features a public-facing landing page, a multi-step insurance application form, and a secure, feature-rich admin dashboard.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* **Modern Homepage:** A visually appealing and responsive homepage.
|
||||||
|
* **Multi-Step Subscription Form:** A user-friendly, multi-step form for insurance applications.
|
||||||
|
* **Dynamic Form Fields:** The form dynamically shows fields based on the selected insurance type.
|
||||||
|
* **Admin Dashboard:** A secure admin dashboard to manage and view applications.
|
||||||
|
* **Application Management:** Admins can view, search, filter, and update the status of applications.
|
||||||
|
* **Email Notifications:** Automatic email notifications to users and admins upon application submission and status changes.
|
||||||
|
* **Analytics Chart:** A chart on the admin dashboard to visualize application trends.
|
||||||
|
* **Details View:** A detailed view for each application.
|
||||||
|
|
||||||
|
## Setup and Installation
|
||||||
|
|
||||||
|
1. **Database:**
|
||||||
|
* The database configuration is in `db/config.php`. Update the credentials if needed.
|
||||||
|
* To create the necessary tables, run the migration script: `php db/migrate.php`.
|
||||||
|
|
||||||
|
2. **Email:**
|
||||||
|
* The email configuration is in `mail/config.php`. You can configure your SMTP settings there.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
* **Database:** `db/config.php`
|
||||||
|
* **Email:** `mail/config.php`
|
||||||
|
* **Admin Credentials:** The admin username and password are currently hardcoded in `admin.php`. It is recommended to move these to a more secure configuration file.
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
|
||||||
|
* **Car Data:** The list of car manufacturers and models can be found and modified in `subscribe-step2.php`.
|
||||||
|
* **Styling:** The application's styling can be customized in `assets/css/custom.css`.
|
||||||
140
admin-details.php
Normal file
140
admin-details.php
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// --- Authentication Check ---
|
||||||
|
$is_logged_in = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
||||||
|
if (!$is_logged_in) {
|
||||||
|
header('Location: admin.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
// --- Data Fetching ---
|
||||||
|
$subscription = null;
|
||||||
|
$error_message = null;
|
||||||
|
|
||||||
|
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
|
||||||
|
$error_message = "Invalid application ID.";
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM subscriptions WHERE id = :id");
|
||||||
|
$stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
$subscription = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (!$subscription) {
|
||||||
|
$error_message = "Application not found.";
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$error_message = "Database error: " . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_specific_coverage_details_html($sub) {
|
||||||
|
$type = $sub['insuranceType'] ?? 'N/A';
|
||||||
|
$output = '';
|
||||||
|
switch ($type) {
|
||||||
|
case 'Car':
|
||||||
|
$output .= "<p><strong>Car Make:</strong> " . htmlspecialchars($sub['carMake']) . "</p>";
|
||||||
|
$output .= "<p><strong>Car Model:</strong> " . htmlspecialchars($sub['carModel']) . "</p>";
|
||||||
|
$output .= "<p><strong>Year of Manufacture:</strong> " . htmlspecialchars($sub['carYear']) . "</p>";
|
||||||
|
break;
|
||||||
|
case 'Health':
|
||||||
|
$output .= "<p><strong>Number of Dependents:</strong> " . htmlspecialchars($sub['healthDependents']) . "</p>";
|
||||||
|
break;
|
||||||
|
case 'Life':
|
||||||
|
$output .= "<p><strong>Coverage Amount:</strong> $" . number_format($sub['lifeCoverage'], 2) . "</p>";
|
||||||
|
break;
|
||||||
|
case 'Home':
|
||||||
|
$output .= "<p><strong>Property Type:</strong> " . htmlspecialchars($sub['homeType']) . "</p>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Page Setup ---
|
||||||
|
$page_title = "Application Details";
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!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($page_title); ?> - SecureLife</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand" href="index.php">SecureLife</a>
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="admin.php?action=logout">Logout</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="container my-5">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<h1 class="h3 fw-bold">Application #<?php echo htmlspecialchars($subscription['id'] ?? ''); ?></h1>
|
||||||
|
<a href="admin.php" class="btn btn-outline-secondary"> ← Back to Dashboard</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ($error_message): ?>
|
||||||
|
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
|
||||||
|
<?php elseif ($subscription): ?>
|
||||||
|
<div class="card shadow-sm border-0" style="border-radius: 0.75rem;">
|
||||||
|
<div class="card-header bg-white p-4 border-0">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<h2 class="h5 fw-bold mb-0">Details</h2>
|
||||||
|
<?php
|
||||||
|
$status = $subscription['status'];
|
||||||
|
$badge_class = 'bg-secondary'; // Default
|
||||||
|
if ($status === 'Pending') {
|
||||||
|
$badge_class = 'bg-warning text-dark';
|
||||||
|
} elseif ($status === 'Approved') {
|
||||||
|
$badge_class = 'bg-success';
|
||||||
|
} elseif ($status === 'Rejected') {
|
||||||
|
$badge_class = 'bg-danger';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<p class="mb-0"><strong>Status:</strong> <span class="badge <?php echo $badge_class; ?>"><?php echo htmlspecialchars($status); ?></span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h5 class="fw-bold">Personal Information</h5>
|
||||||
|
<p><strong>Full Name:</strong> <?php echo htmlspecialchars($subscription['fullName']); ?></p>
|
||||||
|
<p><strong>Email:</strong> <?php echo htmlspecialchars($subscription['email']); ?></p>
|
||||||
|
<p><strong>Phone:</strong> <?php echo htmlspecialchars($subscription['phone']); ?></p>
|
||||||
|
<p><strong>Submitted At:</strong> <?php echo date("F j, Y, g:i a", strtotime($subscription['created_at'])); ?></p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h5 class="fw-bold">Insurance Details</h5>
|
||||||
|
<p><strong>Insurance Type:</strong> <?php echo htmlspecialchars($subscription['insuranceType']); ?></p>
|
||||||
|
<?php echo get_specific_coverage_details_html($subscription); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="text-center py-4 mt-auto bg-dark text-white">
|
||||||
|
<p class="mb-0">© <?php echo date("Y"); ?> SecureLife. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
84
admin.php
Normal file
84
admin.php
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// --- Configuration ---
|
||||||
|
// IMPORTANT: These are hardcoded for demonstration purposes.
|
||||||
|
// In a real-world application, use a secure way to store and manage credentials.
|
||||||
|
$admin_credentials = require __DIR__ . '/config/admin_credentials.php';
|
||||||
|
define('ADMIN_USERNAME', $admin_credentials['username']);
|
||||||
|
define('ADMIN_PASSWORD', $admin_credentials['password']);
|
||||||
|
|
||||||
|
$error_message = null;
|
||||||
|
$is_logged_in = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
||||||
|
|
||||||
|
// --- Logout Logic ---
|
||||||
|
if (isset($_GET['action']) && $_GET['action'] === 'logout') {
|
||||||
|
session_unset();
|
||||||
|
session_destroy();
|
||||||
|
header('Location: admin.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Login Logic ---
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['username']) && isset($_POST['password'])) {
|
||||||
|
if ($_POST['username'] === ADMIN_USERNAME && $_POST['password'] === ADMIN_PASSWORD) {
|
||||||
|
$_SESSION['isAdmin'] = true;
|
||||||
|
header('Location: admin.php');
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$error_message = "Invalid username or password.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Page Setup ---
|
||||||
|
$page_title = $is_logged_in ? "Admin Dashboard" : "Admin Login";
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!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($page_title); ?> - SecureLife</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand" href="index.php">SecureLife</a>
|
||||||
|
<?php if ($is_logged_in): ?>
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="admin.php?action=logout">Logout</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="container my-5">
|
||||||
|
<?php
|
||||||
|
if ($is_logged_in) {
|
||||||
|
include 'partials/admin_dashboard.php';
|
||||||
|
} else {
|
||||||
|
// Pass the error message to the login form
|
||||||
|
include 'partials/admin_login.php';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="text-center py-4 mt-auto bg-dark text-white">
|
||||||
|
<p class="mb-0">© <?php echo date("Y"); ?> SecureLife. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
68
api/chart-data.php
Normal file
68
api/chart-data.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
require_once __DIR__ . '/../db/config.php';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// 1. Data for the line chart (applications over time)
|
||||||
|
$line_chart_stmt = $pdo->prepare(
|
||||||
|
"SELECT DATE(created_at) as date, COUNT(*) as count
|
||||||
|
FROM subscriptions
|
||||||
|
WHERE created_at >= CURDATE() - INTERVAL 30 DAY
|
||||||
|
GROUP BY DATE(created_at)
|
||||||
|
ORDER BY date ASC"
|
||||||
|
);
|
||||||
|
$line_chart_stmt->execute();
|
||||||
|
$line_chart_results = $line_chart_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$line_chart_labels = [];
|
||||||
|
$line_chart_data = [];
|
||||||
|
foreach ($line_chart_results as $row) {
|
||||||
|
$line_chart_labels[] = $row['date'];
|
||||||
|
$line_chart_data[] = (int)$row['count'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Data for status counts (key metrics)
|
||||||
|
$status_stmt = $pdo->prepare("SELECT status, COUNT(*) as count FROM subscriptions GROUP BY status");
|
||||||
|
$status_stmt->execute();
|
||||||
|
$status_results = $status_stmt->fetchAll(PDO::FETCH_KEY_PAIR);
|
||||||
|
|
||||||
|
$total_applications = array_sum($status_results);
|
||||||
|
$status_counts = [
|
||||||
|
'Total' => $total_applications,
|
||||||
|
'Approved' => $status_results['Approved'] ?? 0,
|
||||||
|
'Pending' => $status_results['Pending'] ?? 0,
|
||||||
|
'Rejected' => $status_results['Rejected'] ?? 0,
|
||||||
|
];
|
||||||
|
|
||||||
|
// 3. Data for insurance type distribution (pie chart)
|
||||||
|
$type_stmt = $pdo->prepare("SELECT insuranceType, COUNT(*) as count FROM subscriptions GROUP BY insuranceType");
|
||||||
|
$type_stmt->execute();
|
||||||
|
$type_results = $type_stmt->fetchAll(PDO::FETCH_KEY_PAIR);
|
||||||
|
|
||||||
|
$pie_chart_labels = array_keys($type_results);
|
||||||
|
$pie_chart_data = array_values($type_results);
|
||||||
|
|
||||||
|
// --- Combine all data into a single response ---
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'line_chart' => [
|
||||||
|
'labels' => $line_chart_labels,
|
||||||
|
'data' => $line_chart_data,
|
||||||
|
],
|
||||||
|
'key_metrics' => $status_counts,
|
||||||
|
'pie_chart' => [
|
||||||
|
'labels' => $pie_chart_labels,
|
||||||
|
'data' => $pie_chart_data,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Failed to fetch chart data.',
|
||||||
|
'error' => $e->getMessage() // For debugging
|
||||||
|
]);
|
||||||
|
}
|
||||||
60
api/update-status.php
Normal file
60
api/update-status.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
require_once __DIR__ . '/../db/config.php';
|
||||||
|
require_once __DIR__ . '/../mail/MailService.php';
|
||||||
|
|
||||||
|
$response = ['success' => false, 'message' => 'Invalid request'];
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$data = json_decode(file_get_contents('php://input'), true);
|
||||||
|
$id = $data['id'] ?? null;
|
||||||
|
$status = $data['status'] ?? null;
|
||||||
|
|
||||||
|
$allowed_statuses = ['Pending', 'Approved', 'Rejected'];
|
||||||
|
|
||||||
|
if ($id && $status && in_array($status, $allowed_statuses)) {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("UPDATE subscriptions SET status = :status WHERE id = :id");
|
||||||
|
$stmt->execute([':status' => $status, ':id' => $id]);
|
||||||
|
|
||||||
|
if ($stmt->rowCount() > 0) {
|
||||||
|
$response = ['success' => true, 'message' => 'Status updated successfully.'];
|
||||||
|
|
||||||
|
// Fetch user details for email notification
|
||||||
|
$stmt = $pdo->prepare("SELECT fullName, email, insuranceType FROM subscriptions WHERE id = :id");
|
||||||
|
$stmt->execute([':id' => $id]);
|
||||||
|
$subscription = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if ($subscription) {
|
||||||
|
$user_email = $subscription['email'];
|
||||||
|
$user_name = $subscription['fullName'];
|
||||||
|
$insurance_type = $subscription['insuranceType'];
|
||||||
|
$subject = '';
|
||||||
|
$body = '';
|
||||||
|
|
||||||
|
if ($status === 'Approved') {
|
||||||
|
$subject = "Congratulations! Your SecureLife Application is Approved";
|
||||||
|
$body = "<h1>Application Approved!</h1><p>Dear {$user_name},</p><p>We are pleased to inform you that your application for <strong>{$insurance_type}</strong> insurance has been approved. Welcome to SecureLife!</p><p>We will follow up with your policy documents shortly.</p>";
|
||||||
|
} elseif ($status === 'Rejected') {
|
||||||
|
$subject = "Update on Your SecureLife Application";
|
||||||
|
$body = "<h1>Application Update</h1><p>Dear {$user_name},</p><p>We have carefully reviewed your application for <strong>{$insurance_type}</strong> insurance. We regret to inform you that we are unable to approve your application at this time.</p><p>Thank you for your interest in SecureLife.</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($subject) && !empty($body)) {
|
||||||
|
MailService::sendMail($user_email, $subject, $body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$response['message'] = 'Could not find a subscription with that ID or status is unchanged.';
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$response['message'] = 'An error occurred: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$response['message'] = 'Invalid ID or status provided.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode($response);
|
||||||
@ -1,109 +1,155 @@
|
|||||||
/* SecureLife Custom Styles */
|
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap');
|
/* assets/css/custom.css */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--primary-color: #0052CC;
|
--primary-color: #0A2540;
|
||||||
--secondary-color: #00A3BF;
|
--accent-color: #00c4ff;
|
||||||
--bg-light: #F8F9FA;
|
--light-bg: #f8f9fa;
|
||||||
--surface-white: #FFFFFF;
|
--white: #ffffff;
|
||||||
--text-dark: #212529;
|
--font-family: 'Inter', sans-serif;
|
||||||
--text-light: #6c757d;
|
|
||||||
--border-radius: 0.5rem;
|
|
||||||
--shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
|
||||||
--shadow-md: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Poppins', sans-serif;
|
font-family: var(--font-family);
|
||||||
background-color: var(--bg-light);
|
background-color: var(--white);
|
||||||
color: var(--text-dark);
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
.navbar-brand {
|
.navbar-brand {
|
||||||
|
font-family: var(--font-family);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero {
|
.btn-primary-modern {
|
||||||
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
|
|
||||||
color: var(--surface-white);
|
|
||||||
padding: 6rem 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero h1 {
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 3.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero p {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
font-weight: 300;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: var(--primary-color);
|
background-color: var(--primary-color);
|
||||||
border-color: var(--primary-color);
|
border-color: var(--primary-color);
|
||||||
font-weight: 600;
|
color: var(--white);
|
||||||
padding: 0.75rem 2rem;
|
font-weight: 500;
|
||||||
border-radius: var(--border-radius);
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary:hover {
|
.btn-primary-modern:hover {
|
||||||
transform: translateY(-2px);
|
background-color: #001f36;
|
||||||
box-shadow: var(--shadow-md);
|
border-color: #001f36;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-title {
|
.btn-accent-modern {
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
border-color: var(--accent-color);
|
||||||
|
color: var(--primary-color);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
margin-bottom: 3rem;
|
padding: 0.75rem 1.5rem;
|
||||||
text-align: center;
|
border-radius: 0.5rem;
|
||||||
}
|
|
||||||
|
|
||||||
.accordion-item {
|
|
||||||
border: 1px solid #dee2e6;
|
|
||||||
border-radius: var(--border-radius) !important;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
box-shadow: var(--shadow-sm);
|
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-item:hover {
|
.btn-accent-modern:hover {
|
||||||
transform: translateY(-3px);
|
background-color: #00a2d1;
|
||||||
box-shadow: var(--shadow-md);
|
border-color: #00a2d1;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-header {
|
|
||||||
border-radius: var(--border-radius);
|
/* Hero Section */
|
||||||
|
.hero-section {
|
||||||
|
background: url('https://picsum.photos/1600/900?random=1') no-repeat center center;
|
||||||
|
background-size: cover;
|
||||||
|
position: relative;
|
||||||
|
padding: 8rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-button {
|
.hero-section::before {
|
||||||
font-weight: 600;
|
content: '';
|
||||||
color: var(--text-dark);
|
position: absolute;
|
||||||
border-radius: var(--border-radius) !important;
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: rgba(10, 37, 64, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-button:not(.collapsed) {
|
.hero-section .container {
|
||||||
background-color: var(--primary-color);
|
position: relative;
|
||||||
color: var(--surface-white);
|
z-index: 2;
|
||||||
box-shadow: inset 0 -1px 0 rgba(0,0,0,.125);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-button:focus {
|
/* Services Section */
|
||||||
box-shadow: 0 0 0 0.25rem rgba(0, 82, 204, 0.25);
|
.service-card {
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
background-color: var(--white);
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
text-align: center;
|
||||||
|
padding: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-body img {
|
.service-card:hover {
|
||||||
max-width: 150px;
|
transform: translateY(-10px);
|
||||||
border-radius: var(--border-radius);
|
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.1);
|
||||||
box-shadow: var(--shadow-sm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
.service-card .icon-box {
|
||||||
background-color: var(--surface-white);
|
width: 80px;
|
||||||
padding: 2rem 0;
|
height: 80px;
|
||||||
margin-top: 4rem;
|
margin: 0 auto 1.5rem;
|
||||||
border-top: 1px solid #e9ecef;
|
border-radius: 50%;
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
color: var(--primary-color);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 2rem;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card:hover .icon-box {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Why Choose Us Section */
|
||||||
|
.bg-light-blue {
|
||||||
|
background-color: #f0f8ff;
|
||||||
|
border-radius: 1rem;
|
||||||
|
padding: 4rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-box {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-box:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-primary-modern {
|
||||||
|
color: var(--primary-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
footer.bg-dark {
|
||||||
|
background-color: var(--primary-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animation */
|
||||||
|
.service-card, .feature-box {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
animation: fadeInUp 0.5s forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row.g-4 > * {
|
||||||
|
animation-delay: calc(var(--animation-order) * 100ms);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1,66 @@
|
|||||||
// SecureLife Main JS
|
function updateStatus(id, status) {
|
||||||
|
if (!confirm(`Are you sure you want to change the status to "${status}"?`)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch('api/update-status.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ id: id, status: status }),
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
alert('Error updating status: ' + data.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('An unexpected error occurred.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const chartCanvas = document.getElementById('applicationsChart');
|
||||||
|
if (chartCanvas) {
|
||||||
|
fetch('/api/chart-data.php')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
const ctx = chartCanvas.getContext('2d');
|
||||||
|
new Chart(ctx, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: data.labels,
|
||||||
|
datasets: [{
|
||||||
|
label: 'New Applications',
|
||||||
|
data: data.data,
|
||||||
|
fill: false,
|
||||||
|
borderColor: '#0052CC',
|
||||||
|
tension: 0.1
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
beginAtZero: true,
|
||||||
|
ticks: {
|
||||||
|
stepSize: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error('Failed to load chart data:', data.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error fetching chart data:', error));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
7
config/admin_credentials.php
Normal file
7
config/admin_credentials.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// It is recommended to use environment variables for credentials.
|
||||||
|
return [
|
||||||
|
'username' => 'admin',
|
||||||
|
'password' => 'password',
|
||||||
|
];
|
||||||
14
config/car_data.php
Normal file
14
config/car_data.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'Toyota' => ['Camry', 'Corolla', 'RAV4', 'Highlander'],
|
||||||
|
'Honda' => ['Civic', 'Accord', 'CR-V', 'Pilot'],
|
||||||
|
'Ford' => ['F-150', 'Mustang', 'Explorer', 'Escape'],
|
||||||
|
'Chevrolet' => ['Silverado', 'Equinox', 'Malibu', 'Tahoe'],
|
||||||
|
'Nissan' => ['Rogue', 'Altima', 'Sentra'],
|
||||||
|
'Jeep' => ['Wrangler', 'Grand Cherokee'],
|
||||||
|
'Hyundai' => ['Elantra', 'Sonata', 'Tucson'],
|
||||||
|
'BMW' => ['3 Series', '5 Series', 'X3', 'X5'],
|
||||||
|
'Mercedes-Benz' => ['C-Class', 'E-Class', 'GLC'],
|
||||||
|
'Audi' => ['A4', 'A6', 'Q5'],
|
||||||
|
];
|
||||||
35
db/migrate.php
Normal file
35
db/migrate.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../db/config.php';
|
||||||
|
|
||||||
|
try {
|
||||||
|
// First, connect without a database name to create it
|
||||||
|
$pdo_admin = new PDO('mysql:host=' . DB_HOST, DB_USER, DB_PASS, [
|
||||||
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||||
|
]);
|
||||||
|
$pdo_admin->exec("CREATE DATABASE IF NOT EXISTS `" . DB_NAME . "` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;");
|
||||||
|
echo "Database '" . DB_NAME . "' created or already exists.\n";
|
||||||
|
|
||||||
|
// Now, connect to the specific database to run migrations
|
||||||
|
$pdo = db();
|
||||||
|
$migrationsDir = __DIR__ . '/migrations';
|
||||||
|
$files = glob($migrationsDir . '/*.sql');
|
||||||
|
|
||||||
|
if (empty($files)) {
|
||||||
|
echo "No migration files found.\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort($files);
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
echo "Running migration: " . basename($file) . "...\n";
|
||||||
|
$sql = file_get_contents($file);
|
||||||
|
$pdo->exec($sql);
|
||||||
|
echo "Migration successful.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "All migrations completed.\n";
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
die("Database migration failed: " . $e->getMessage() . "\n");
|
||||||
|
}
|
||||||
14
db/migrations/001_create_subscriptions_table.sql
Normal file
14
db/migrations/001_create_subscriptions_table.sql
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS subscriptions (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
fullName VARCHAR(255) NOT NULL,
|
||||||
|
email VARCHAR(255) NOT NULL,
|
||||||
|
phone VARCHAR(50) NOT NULL,
|
||||||
|
insuranceType VARCHAR(50) NOT NULL,
|
||||||
|
carMake VARCHAR(100),
|
||||||
|
carModel VARCHAR(100),
|
||||||
|
carYear INT,
|
||||||
|
healthDependents INT,
|
||||||
|
lifeCoverage DECIMAL(15, 2),
|
||||||
|
homeType VARCHAR(50),
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
2
db/migrations/002_add_status_to_subscriptions.sql
Normal file
2
db/migrations/002_add_status_to_subscriptions.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE subscriptions
|
||||||
|
ADD COLUMN status VARCHAR(50) NOT NULL DEFAULT 'submitted' AFTER homeType;
|
||||||
222
index.php
222
index.php
@ -3,156 +3,116 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>SecureLife - Your Future, Secured.</title>
|
||||||
<!-- Meta Tags -->
|
<meta name="description" content="SecureLife offers comprehensive and affordable insurance plans for car, health, life, and home. Get your free quote today.">
|
||||||
<title>SecureLife - Your Future, Secured</title>
|
|
||||||
<meta name="description" content="SecureLife offers comprehensive and affordable insurance plans for car, health, life, and home. Get your free quote today. Built with Flatlogic Generator.">
|
|
||||||
<meta name="keywords" content="insurance, car insurance, health insurance, life insurance, home insurance, insurance platform, get quote, secure life, Flatlogic Generator">
|
|
||||||
<meta property="og:title" content="SecureLife - Your Future, Secured">
|
|
||||||
<meta property="og:description" content="SecureLife offers comprehensive and affordable insurance plans for car, health, life, and home. Get your free quote today.">
|
|
||||||
<meta property="og:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? '', ENT_QUOTES, 'UTF-8'); ?>">
|
|
||||||
<meta name="twitter:card" content="summary_large_image">
|
|
||||||
<meta name="twitter:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? '', ENT_QUOTES, 'UTF-8'); ?>">
|
|
||||||
|
|
||||||
<!-- Bootstrap 5 CSS -->
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<!-- Custom CSS -->
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link rel="stylesheet" href="assets/css/custom.css">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<!-- Header -->
|
<header class="navbar navbar-expand-lg navbar-light bg-white shadow-sm sticky-top">
|
||||||
<header class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="navbar-brand" href="#">SecureLife</a>
|
<a class="navbar-brand" href="index.php" style="font-family: 'Inter', sans-serif; font-weight: 700; color: #0A2540;">SecureLife</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
<a href="subscribe.php" class="btn btn-primary-modern d-none d-lg-inline-block">Get a Quote</a>
|
||||||
<span class="navbar-toggler-icon"></span>
|
|
||||||
</button>
|
|
||||||
<div class="collapse navbar-collapse" id="navbarNav">
|
|
||||||
<ul class="navbar-nav ms-auto">
|
|
||||||
<li class="nav-item"><a class="nav-link active" href="#">Home</a></li>
|
|
||||||
<li class="nav-item"><a class="nav-link" href="#">About</a></li>
|
|
||||||
<li class="nav-item"><a class="nav-link" href="#">Contact</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- Hero Section -->
|
<!-- Hero Section -->
|
||||||
<section class="hero">
|
<section class="hero-section text-white text-center">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>Your Future, Secured.</h1>
|
<h1 class="display-3 fw-bold">Your Future, Secured.</h1>
|
||||||
<p class="lead">Affordable, reliable insurance plans tailored for you.</p>
|
<p class="lead my-4">Comprehensive and affordable insurance plans tailored for you.</p>
|
||||||
<a href="subscribe.php" class="btn btn-primary btn-lg">Get Your Free Quote</a>
|
<a href="subscribe.php" class="btn btn-accent-modern btn-lg">Get Your Free Quote</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Main Content -->
|
<main class="container my-5">
|
||||||
<main class="container mt-5 pt-4">
|
<!-- Services Section -->
|
||||||
<h2 class="section-title">Comprehensive Coverage for Every Need</h2>
|
<section id="services" class="py-5 text-center">
|
||||||
|
<h2 class="fw-bold">Comprehensive Coverage for Every Need</h2>
|
||||||
|
<p class="lead text-muted mb-5">Explore our insurance options designed to protect what matters most.</p>
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-md-6 col-lg-3 d-flex align-items-stretch">
|
||||||
|
<div class="card service-card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="icon-box"><i class="bi bi-car-front-fill"></i></div>
|
||||||
|
<h5 class="card-title">Car Insurance</h5>
|
||||||
|
<p class="card-text">Hit the road with confidence. Comprehensive coverage against accidents, theft, and damages.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 col-lg-3 d-flex align-items-stretch">
|
||||||
|
<div class="card service-card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="icon-box"><i class="bi bi-heart-pulse-fill"></i></div>
|
||||||
|
<h5 class="card-title">Health Insurance</h5>
|
||||||
|
<p class="card-text">Your health is your wealth. Access a wide network of hospitals and specialists.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 col-lg-3 d-flex align-items-stretch">
|
||||||
|
<div class="card service-card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="icon-box"><i class="bi bi-person-heart"></i></div>
|
||||||
|
<h5 class="card-title">Life Insurance</h5>
|
||||||
|
<p class="card-text">Secure your family's future. A financial safety net for your loved ones.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 col-lg-3 d-flex align-items-stretch">
|
||||||
|
<div class="card service-card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="icon-box"><i class="bi bi-house-heart-fill"></i></div>
|
||||||
|
<h5 class="card-title">Home Insurance</h5>
|
||||||
|
<p class="card-text">Protect your biggest investment. Coverage from natural disasters to theft.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- Accordion for Insurance Types -->
|
<!-- Why Choose Us Section -->
|
||||||
<div class="accordion" id="insuranceAccordion">
|
<section id="why-choose-us" class="py-5 mt-5 bg-light-blue">
|
||||||
|
<div class="container text-center">
|
||||||
|
<h2 class="fw-bold">Why Choose SecureLife?</h2>
|
||||||
|
<p class="lead text-muted mb-5">We provide more than just insurance. We provide peace of mind.</p>
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="feature-box">
|
||||||
|
<i class="bi bi-shield-check fs-1 text-primary-modern"></i>
|
||||||
|
<h4 class="mt-3">Trusted & Reliable</h4>
|
||||||
|
<p>With years of experience, we are a name you can trust.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="feature-box">
|
||||||
|
<i class="bi bi-headset fs-1 text-primary-modern"></i>
|
||||||
|
<h4 class="mt-3">24/7 Support</h4>
|
||||||
|
<p>Our team is always here to help, any time of the day.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="feature-box">
|
||||||
|
<i class="bi bi-file-earmark-text fs-1 text-primary-modern"></i>
|
||||||
|
<h4 class="mt-3">Easy Claims</h4>
|
||||||
|
<p>A hassle-free claims process to get you back on your feet.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- Car Insurance -->
|
|
||||||
<div class="accordion-item">
|
|
||||||
<h2 class="accordion-header" id="headingOne">
|
|
||||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne">
|
|
||||||
<i class="bi bi-car-front-fill me-3"></i> Car Insurance
|
|
||||||
</button>
|
|
||||||
</h2>
|
|
||||||
<div id="collapseOne" class="accordion-collapse collapse show" data-bs-parent="#insuranceAccordion">
|
|
||||||
<div class="accordion-body">
|
|
||||||
<div class="row align-items-center">
|
|
||||||
<div class="col-md-3 text-center">
|
|
||||||
<img src="https://images.pexels.com/photos/116675/pexels-photo-116675.jpeg?auto=compress&cs=tinysrgb&w=600" alt="Car on a scenic road" class="img-fluid">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-9">
|
|
||||||
<strong>Hit the road with confidence.</strong> Our car insurance provides comprehensive coverage against accidents, theft, and damages. We offer flexible plans with options for roadside assistance and rental car reimbursement, ensuring you're never left stranded.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Health Insurance -->
|
|
||||||
<div class="accordion-item">
|
|
||||||
<h2 class="accordion-header" id="headingTwo">
|
|
||||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo">
|
|
||||||
<i class="bi bi-heart-pulse-fill me-3"></i> Health Insurance
|
|
||||||
</button>
|
|
||||||
</h2>
|
|
||||||
<div id="collapseTwo" class="accordion-collapse collapse" data-bs-parent="#insuranceAccordion">
|
|
||||||
<div class="accordion-body">
|
|
||||||
<div class="row align-items-center">
|
|
||||||
<div class="col-md-3 text-center">
|
|
||||||
<img src="https://images.pexels.com/photos/4021775/pexels-photo-4021775.jpeg?auto=compress&cs=tinysrgb&w=600" alt="Doctor with a stethoscope" class="img-fluid">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-9">
|
|
||||||
<strong>Your health is your wealth.</strong> Protect it with our wide range of health insurance plans. Gain access to a vast network of hospitals and specialists, with coverage for everything from routine check-ups to major surgeries.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Life Insurance -->
|
|
||||||
<div class="accordion-item">
|
|
||||||
<h2 class="accordion-header" id="headingThree">
|
|
||||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseThree">
|
|
||||||
<i class="bi bi-person-hearts me-3"></i> Life Insurance
|
|
||||||
</button>
|
|
||||||
</h2>
|
|
||||||
<div id="collapseThree" class="accordion-collapse collapse" data-bs-parent="#insuranceAccordion">
|
|
||||||
<div class="accordion-body">
|
|
||||||
<div class="row align-items-center">
|
|
||||||
<div class="col-md-3 text-center">
|
|
||||||
<img src="https://images.pexels.com/photos/3184423/pexels-photo-3184423.jpeg?auto=compress&cs=tinysrgb&w=600" alt="Happy family" class="img-fluid">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-9">
|
|
||||||
<strong>Secure your family's future.</strong> Our life insurance policies provide a financial safety net for your loved ones in your absence. Choose from term life, whole life, and investment-linked plans to find the perfect fit for your long-term goals.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Home Insurance -->
|
|
||||||
<div class="accordion-item">
|
|
||||||
<h2 class="accordion-header" id="headingFour">
|
|
||||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseFour">
|
|
||||||
<i class="bi bi-house-heart-fill me-3"></i> Home Insurance
|
|
||||||
</button>
|
|
||||||
</h2>
|
|
||||||
<div id="collapseFour" class="accordion-collapse collapse" data-bs-parent="#insuranceAccordion">
|
|
||||||
<div class="accordion-body">
|
|
||||||
<div class="row align-items-center">
|
|
||||||
<div class="col-md-3 text-center">
|
|
||||||
<img src="https://images.pexels.com/photos/106399/pexels-photo-106399.jpeg?auto=compress&cs=tinysrgb&w=600" alt="Modern beautiful house" class="img-fluid">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-9">
|
|
||||||
<strong>Protect your biggest investment.</strong> Our home insurance covers your property and belongings against fire, theft, natural disasters, and more. Enjoy peace of mind knowing that your sanctuary is safe and sound.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Footer -->
|
<footer class="text-center py-4 mt-auto bg-dark text-white">
|
||||||
<footer class="text-center text-muted">
|
<p class="mb-0">© <?php echo date("Y"); ?> SecureLife. All Rights Reserved.</p>
|
||||||
<div class="container">
|
|
||||||
<p>© <?php echo date("Y"); ?> SecureLife. All Rights Reserved.</p>
|
|
||||||
</div>
|
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<!-- Bootstrap 5 JS -->
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<!-- Custom JS -->
|
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||||
<script src="assets/js/main.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@ -105,7 +105,7 @@ class MailService
|
|||||||
if (!file_exists($configPath)) {
|
if (!file_exists($configPath)) {
|
||||||
throw new \RuntimeException('Mail config not found. Copy mail/config.sample.php to mail/config.php and fill in credentials.');
|
throw new \RuntimeException('Mail config not found. Copy mail/config.sample.php to mail/config.php and fill in credentials.');
|
||||||
}
|
}
|
||||||
$cfg = require $configPath;
|
$cfg = require_once $configPath;
|
||||||
if (!is_array($cfg)) {
|
if (!is_array($cfg)) {
|
||||||
throw new \RuntimeException('Invalid mail config format: expected array');
|
throw new \RuntimeException('Invalid mail config format: expected array');
|
||||||
}
|
}
|
||||||
|
|||||||
168
partials/admin_dashboard.php
Normal file
168
partials/admin_dashboard.php
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../db/config.php';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// --- Pagination Settings ---
|
||||||
|
$limit = 10; // Subscriptions per page
|
||||||
|
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
|
||||||
|
$offset = ($page - 1) * $limit;
|
||||||
|
|
||||||
|
// --- Filtering and Searching ---
|
||||||
|
$base_sql = "FROM subscriptions";
|
||||||
|
$params = [];
|
||||||
|
$where_clauses = [];
|
||||||
|
|
||||||
|
if (!empty($_GET['status'])) {
|
||||||
|
$where_clauses[] = "status = :status";
|
||||||
|
$params[':status'] = $_GET['status'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($_GET['search'])) {
|
||||||
|
$where_clauses[] = "(fullName LIKE :search OR email LIKE :search)";
|
||||||
|
$params[':search'] = '%' . $_GET['search'] . '%';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($where_clauses)) {
|
||||||
|
$base_sql .= " WHERE " . implode(' AND ', $where_clauses);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Get Total Count for Pagination ---
|
||||||
|
$count_stmt = $pdo->prepare("SELECT COUNT(id) " . $base_sql);
|
||||||
|
$count_stmt->execute($params);
|
||||||
|
$total_subscriptions = $count_stmt->fetchColumn();
|
||||||
|
$total_pages = ceil($total_subscriptions / $limit);
|
||||||
|
|
||||||
|
// --- Get Subscriptions for Current Page ---
|
||||||
|
$subscriptions_sql = "SELECT id, fullName, email, insuranceType, status, created_at " . $base_sql . " ORDER BY created_at DESC LIMIT :limit OFFSET :offset";
|
||||||
|
$stmt = $pdo->prepare($subscriptions_sql);
|
||||||
|
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
|
||||||
|
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
|
||||||
|
foreach ($params as $key => &$val) {
|
||||||
|
$stmt->bindParam($key, $val);
|
||||||
|
}
|
||||||
|
$stmt->execute();
|
||||||
|
$subscriptions = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
die("Database error: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="row mb-4">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card shadow-sm border-0" style="border-radius: 0.75rem;">
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<h2 class="card-title h5 fw-bold">Application Trends</h2>
|
||||||
|
<p class="text-muted small">New applications over the last 30 days.</p>
|
||||||
|
<canvas id="applicationsChart"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card shadow-sm border-0" style="border-radius: 0.75rem;">
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<h2 class="card-title h5 fw-bold">All Applications</h2>
|
||||||
|
<p class="text-muted small">Manage all insurance applications.</p>
|
||||||
|
|
||||||
|
<!-- Filter and Search Form -->
|
||||||
|
<form action="admin.php" method="GET" class="row g-3 align-items-center mb-4">
|
||||||
|
<div class="col-md-5">
|
||||||
|
<input type="text" name="search" class="form-control" placeholder="Search by name or email..." value="<?php echo htmlspecialchars($_GET['search'] ?? ''); ?>">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<select name="status" class="form-select">
|
||||||
|
<option value="">All Statuses</option>
|
||||||
|
<option value="Pending" <?php echo (($_GET['status'] ?? '') === 'Pending') ? 'selected' : ''; ?>>Pending</option>
|
||||||
|
<option value="Approved" <?php echo (($_GET['status'] ?? '') === 'Approved') ? 'selected' : ''; ?>>Approved</option>
|
||||||
|
<option value="Rejected" <?php echo (($_GET['status'] ?? '') === 'Rejected') ? 'selected' : ''; ?>>Rejected</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<button type="submit" class="btn btn-primary-modern w-100">Filter</button>
|
||||||
|
<a href="admin.php" class="btn btn-secondary w-100 mt-2">Clear</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover align-middle">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th scope="col">ID</th>
|
||||||
|
<th scope="col">Full Name</th>
|
||||||
|
<th scope="col">Email</th>
|
||||||
|
<th scope="col">Insurance Type</th>
|
||||||
|
<th scope="col">Status</th>
|
||||||
|
<th scope="col">Date</th>
|
||||||
|
<th scope="col">Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if (empty($subscriptions)): ?>
|
||||||
|
<tr>
|
||||||
|
<td colspan="7" class="text-center text-muted py-4">No applications found.</td>
|
||||||
|
</tr>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($subscriptions as $sub): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars($sub['id']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($sub['fullName']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($sub['email']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($sub['insuranceType']); ?></td>
|
||||||
|
<td>
|
||||||
|
<?php
|
||||||
|
$status = $sub['status'];
|
||||||
|
$badge_class = 'bg-secondary'; // Default
|
||||||
|
if ($status === 'Pending') {
|
||||||
|
$badge_class = 'bg-warning text-dark';
|
||||||
|
} elseif ($status === 'Approved') {
|
||||||
|
$badge_class = 'bg-success';
|
||||||
|
} elseif ($status === 'Rejected') {
|
||||||
|
$badge_class = 'bg-danger';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<span class="badge <?php echo $badge_class; ?>"><?php echo htmlspecialchars($status); ?></span>
|
||||||
|
</td>
|
||||||
|
<td><?php echo date("Y-m-d", strtotime($sub['created_at'])); ?></td>
|
||||||
|
<td>
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" id="dropdownMenuButton-<?php echo $sub['id']; ?>" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-gear"></i>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton-<?php echo $sub['id']; ?>">
|
||||||
|
<li><a class="dropdown-item" href="admin-details.php?id=<?php echo $sub['id']; ?>">Details</a></li>
|
||||||
|
<li><hr class="dropdown-divider"></li>
|
||||||
|
<li><a class="dropdown-item" href="#" onclick="updateStatus(<?php echo $sub['id']; ?>, 'Pending')">Set Pending</a></li>
|
||||||
|
<li><a class="dropdown-item" href="#" onclick="updateStatus(<?php echo $sub['id']; ?>, 'Approved')">Set Approved</a></li>
|
||||||
|
<li><a class="dropdown-item" href="#" onclick="updateStatus(<?php echo $sub['id']; ?>, 'Rejected')">Set Rejected</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Pagination -->
|
||||||
|
<nav aria-label="Page navigation">
|
||||||
|
<ul class="pagination justify-content-center">
|
||||||
|
<?php if ($page > 1): ?>
|
||||||
|
<li class="page-item"><a class="page-link" href="?page=<?php echo $page - 1; ?>&search=<?php echo htmlspecialchars($_GET['search'] ?? ''); ?>&status=<?php echo htmlspecialchars($_GET['status'] ?? ''); ?>">Previous</a></li>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
|
||||||
|
<li class="page-item <?php echo ($i == $page) ? 'active' : ''; ?>"><a class="page-link" href="?page=<?php echo $i; ?>&search=<?php echo htmlspecialchars($_GET['search'] ?? ''); ?>&status=<?php echo htmlspecialchars($_GET['status'] ?? ''); ?>"><?php echo $i; ?></a></li>
|
||||||
|
<?php endfor; ?>
|
||||||
|
|
||||||
|
<?php if ($page < $total_pages): ?>
|
||||||
|
<li class="page-item"><a class="page-link" href="?page=<?php echo $page + 1; ?>&search=<?php echo htmlspecialchars($_GET['search'] ?? ''); ?>&status=<?php echo htmlspecialchars($_GET['status'] ?? ''); ?>">Next</a></li>
|
||||||
|
<?php endif; ?>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
25
partials/admin_login.php
Normal file
25
partials/admin_login.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-5">
|
||||||
|
<div class="card shadow-sm border-0" style="border-radius: 0.75rem;">
|
||||||
|
<div class="card-body p-5">
|
||||||
|
<h1 class="card-title text-center mb-4 fw-bold">Admin Login</h1>
|
||||||
|
<?php if (isset($error_message)): ?>
|
||||||
|
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<form action="admin.php" method="post">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="username" class="form-label">Username</label>
|
||||||
|
<input type="text" class="form-control form-control-lg" id="username" name="username" required value="admin">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="password" class="form-label">Password</label>
|
||||||
|
<input type="password" class="form-control form-control-lg" id="password" name="password" required value="password">
|
||||||
|
</div>
|
||||||
|
<div class="d-grid mt-4">
|
||||||
|
<button type="submit" class="btn btn-primary-modern btn-lg">Login</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
168
subscribe-step2.php
Normal file
168
subscribe-step2.php
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
if (!isset($_SESSION['personal_details'])) {
|
||||||
|
header('Location: subscribe.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$_SESSION['insurance_details'] = [
|
||||||
|
'insuranceType' => filter_input(INPUT_POST, 'insuranceType', FILTER_SANITIZE_STRING),
|
||||||
|
'carMake' => filter_input(INPUT_POST, 'carMake', FILTER_SANITIZE_STRING),
|
||||||
|
'carModel' => filter_input(INPUT_POST, 'carModel', FILTER_SANITIZE_STRING),
|
||||||
|
'carYear' => filter_input(INPUT_POST, 'carYear', FILTER_SANITIZE_STRING),
|
||||||
|
'healthDependents' => filter_input(INPUT_POST, 'healthDependents', FILTER_SANITIZE_NUMBER_INT),
|
||||||
|
'lifeCoverage' => filter_input(INPUT_POST, 'lifeCoverage', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION),
|
||||||
|
'homeType' => filter_input(INPUT_POST, 'homeType', FILTER_SANITIZE_STRING),
|
||||||
|
];
|
||||||
|
header('Location: subscribe-step3.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$car_data = require __DIR__ . '/config/car_data.php';
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Subscribe - SecureLife</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand" href="index.php">SecureLife</a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="container my-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<div class="card shadow-sm border-0" style="border-radius: 0.75rem;">
|
||||||
|
<div class="card-body p-5">
|
||||||
|
<h1 class="card-title text-center mb-2 fw-bold">Choose Your Coverage</h1>
|
||||||
|
<p class="text-center text-muted mb-5">Step 2: Select your insurance plan and details</p>
|
||||||
|
|
||||||
|
<form action="subscribe-step2.php" method="POST">
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="insuranceType" class="form-label fs-5">Insurance Type</label>
|
||||||
|
<select class="form-select form-select-lg" id="insuranceType" name="insuranceType" required>
|
||||||
|
<option value="" selected disabled>-- Select an insurance type --</option>
|
||||||
|
<option value="Car">Car Insurance</option>
|
||||||
|
<option value="Health">Health Insurance</option>
|
||||||
|
<option value="Life">Life Insurance</option>
|
||||||
|
<option value="Home">Home Insurance</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="carFields" class="dynamic-fields d-none border-top pt-4 mt-4">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="carMake" class="form-label">Car Make</label>
|
||||||
|
<select class="form-select" id="carMake" name="carMake">
|
||||||
|
<option value="" selected disabled>-- Select Make --</option>
|
||||||
|
<?php foreach (array_keys($car_data) as $make): ?>
|
||||||
|
<option value="<?php echo $make; ?>"><?php echo $make; ?></option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="carModel" class="form-label">Car Model</label>
|
||||||
|
<select class="form-select" id="carModel" name="carModel" disabled>
|
||||||
|
<option value="" selected disabled>-- Select Model --</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="carYear" class="form-label">Year of Manufacture</label>
|
||||||
|
<input type="date" class="form-control" id="carYear" name="carYear">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="healthFields" class="dynamic-fields d-none border-top pt-4 mt-4">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="healthDependents" class="form-label">Number of Dependents</label>
|
||||||
|
<input type="number" class="form-control" id="healthDependents" name="healthDependents" placeholder="e.g., 2">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="lifeFields" class="dynamic-fields d-none border-top pt-4 mt-4">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="lifeCoverage" class="form-label">Desired Coverage Amount ($)</label>
|
||||||
|
<input type="number" class="form-control" id="lifeCoverage" name="lifeCoverage" step="1000" placeholder="e.g., 500000">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="homeFields" class="dynamic-fields d-none border-top pt-4 mt-4">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="homeType" class="form-label">Property Type</label>
|
||||||
|
<select class="form-select" id="homeType" name="homeType">
|
||||||
|
<option value="House">House</option>
|
||||||
|
<option value="Apartment">Apartment</option>
|
||||||
|
<option value="Condo">Condo</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between mt-5">
|
||||||
|
<a href="subscribe.php" class="btn btn-secondary btn-lg">← Go Back</a>
|
||||||
|
<button type="submit" class="btn btn-primary-modern btn-lg">Next Step →</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="text-center py-4 mt-auto bg-dark text-white">
|
||||||
|
<p class="mb-0">© <?php echo date("Y"); ?> SecureLife. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script>
|
||||||
|
const carData = <?php echo json_encode($car_data); ?>;
|
||||||
|
|
||||||
|
document.getElementById('insuranceType').addEventListener('change', function () {
|
||||||
|
document.querySelectorAll('.dynamic-fields').forEach(function (el) {
|
||||||
|
el.classList.add('d-none');
|
||||||
|
});
|
||||||
|
var selectedType = this.value;
|
||||||
|
if (selectedType) {
|
||||||
|
var fieldsetId = selectedType.toLowerCase() + 'Fields';
|
||||||
|
var fieldset = document.getElementById(fieldsetId);
|
||||||
|
if (fieldset) {
|
||||||
|
fieldset.classList.remove('d-none');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('carMake').addEventListener('change', function() {
|
||||||
|
const carModelSelect = document.getElementById('carModel');
|
||||||
|
const selectedMake = this.value;
|
||||||
|
|
||||||
|
// Clear existing options
|
||||||
|
carModelSelect.innerHTML = '<option value="" selected disabled>-- Select Model --</option>';
|
||||||
|
|
||||||
|
if (selectedMake && carData[selectedMake]) {
|
||||||
|
carModelSelect.disabled = false;
|
||||||
|
carData[selectedMake].forEach(function(model) {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = model;
|
||||||
|
option.textContent = model;
|
||||||
|
carModelSelect.appendChild(option);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
carModelSelect.disabled = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
173
subscribe-step3.php
Normal file
173
subscribe-step3.php
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
require_once __DIR__ . '/mail/MailService.php';
|
||||||
|
|
||||||
|
// Redirect to step 1 if session is not fully populated
|
||||||
|
if (!isset($_SESSION['personal_details']) || !isset($_SESSION['insurance_details'])) {
|
||||||
|
header('Location: subscribe.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$personal_details = $_SESSION['personal_details'];
|
||||||
|
$insurance_details = $_SESSION['insurance_details'];
|
||||||
|
|
||||||
|
function get_coverage_details_html($details) {
|
||||||
|
$type = $details['insuranceType'] ?? 'N/A';
|
||||||
|
$output = '';
|
||||||
|
switch ($type) {
|
||||||
|
case 'Car':
|
||||||
|
$output .= "<li><strong>Car Make:</strong> " . htmlspecialchars($details['carMake']) . "</li>";
|
||||||
|
$output .= "<li><strong>Car Model:</strong> " . htmlspecialchars($details['carModel']) . "</li>";
|
||||||
|
$output .= "<li><strong>Year of Manufacture:</strong> " . htmlspecialchars($details['carYear']) . "</li>";
|
||||||
|
break;
|
||||||
|
case 'Health':
|
||||||
|
$output .= "<li><strong>Number of Dependents:</strong> " . htmlspecialchars($details['healthDependents']) . "</li>";
|
||||||
|
break;
|
||||||
|
case 'Life':
|
||||||
|
$output .= "<li><strong>Coverage Amount:</strong> $" . number_format($details['lifeCoverage'], 2) . "</li>";
|
||||||
|
break;
|
||||||
|
case 'Home':
|
||||||
|
$output .= "<li><strong>Property Type:</strong> " . htmlspecialchars($details['homeType']) . "</li>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
$show_success_message = false;
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare(
|
||||||
|
"INSERT INTO subscriptions (fullName, email, phone, insuranceType, carMake, carModel, carYear, healthDependents, lifeCoverage, homeType) " .
|
||||||
|
"VALUES (:fullName, :email, :phone, :insuranceType, :carMake, :carModel, :carYear, :healthDependents, :lifeCoverage, :homeType)"
|
||||||
|
);
|
||||||
|
|
||||||
|
$stmt->execute([
|
||||||
|
':fullName' => $personal_details['fullName'],
|
||||||
|
':email' => $personal_details['email'],
|
||||||
|
':phone' => $personal_details['phone'],
|
||||||
|
':insuranceType' => $insurance_details['insuranceType'],
|
||||||
|
':carMake' => $insurance_details['carMake'] ?? null,
|
||||||
|
':carModel' => $insurance_details['carModel'] ?? null,
|
||||||
|
':carYear' => $insurance_details['carYear'] ?: null,
|
||||||
|
':healthDependents' => $insurance_details['healthDependents'] ?: null,
|
||||||
|
':lifeCoverage' => $insurance_details['lifeCoverage'] ?: null,
|
||||||
|
':homeType' => $insurance_details['homeType'] ?? null,
|
||||||
|
]);
|
||||||
|
$submission_id = $pdo->lastInsertId();
|
||||||
|
|
||||||
|
// --- Send Confirmation Email to User ---
|
||||||
|
$user_subject = "Your Subscription to SecureLife is Confirmed!";
|
||||||
|
$user_body_html = "<h1>Welcome to SecureLife, " . htmlspecialchars($personal_details['fullName']) . "!</h1>";
|
||||||
|
$user_body_html .= "<p>We have received your application for " . htmlspecialchars($insurance_details['insuranceType']) . " insurance. Here is a summary of your submission:</p>";
|
||||||
|
$user_body_html .= "<ul>" . get_coverage_details_html($insurance_details) . "</ul>";
|
||||||
|
$user_body_html .= "<p>We will review your application and get back to you shortly. Your submission ID is: <strong>{$submission_id}</strong></p>";
|
||||||
|
MailService::sendMail($personal_details['email'], $user_subject, $user_body_html);
|
||||||
|
|
||||||
|
// --- Send Notification Email to Admin ---
|
||||||
|
$admin_subject = "New Insurance Application Received (#{$submission_id})";
|
||||||
|
$admin_body_html = "<h1>New Submission</h1>";
|
||||||
|
$admin_body_html .= "<p>A new insurance application has been submitted by <strong>" . htmlspecialchars($personal_details['fullName']) . "</strong>.</p>";
|
||||||
|
$admin_body_html .= "<h5>Personal Details</h5><ul>";
|
||||||
|
$admin_body_html .= "<li>Name: " . htmlspecialchars($personal_details['fullName']) . "</li>";
|
||||||
|
$admin_body_html .= "<li>Email: " . htmlspecialchars($personal_details['email']) . "</li>";
|
||||||
|
$admin_body_html .= "<li>Phone: " . htmlspecialchars($personal_details['phone']) . "</li></ul>";
|
||||||
|
$admin_body_html .= "<h5>Insurance Details</h5><ul>";
|
||||||
|
$admin_body_html .= "<li>Type: " . htmlspecialchars($insurance_details['insuranceType']) . "</li>";
|
||||||
|
$admin_body_html .= get_coverage_details_html($insurance_details) . "</ul>";
|
||||||
|
$admin_body_html .= "<p>You can view this submission in the <a href=\"http://{\$\_SERVER['HTTP_HOST']}/admin.php\">Admin Dashboard</a>.</p>";
|
||||||
|
MailService::sendMail(null, $admin_subject, $admin_body_html); // $to = null uses MAIL_TO from env
|
||||||
|
|
||||||
|
// Clear the session and show a success message
|
||||||
|
session_unset();
|
||||||
|
session_destroy();
|
||||||
|
$show_success_message = true;
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
error_log("Database error: " . $e->getMessage());
|
||||||
|
die("An error occurred. Please try again later.");
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log("Mail sending error: " . $e->getMessage());
|
||||||
|
die("An error occurred. Please try again later.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Confirm Subscription - SecureLife</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand" href="index.php">SecureLife</a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="container my-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<div class="card shadow-sm border-0" style="border-radius: 0.75rem;">
|
||||||
|
<div class="card-body p-5">
|
||||||
|
<?php if ($show_success_message): ?>
|
||||||
|
<div class="text-center">
|
||||||
|
<i class="bi bi-check-circle-fill text-success" style="font-size: 4rem;"></i>
|
||||||
|
<h1 class="card-title mt-4 fw-bold">Subscription Complete!</h1>
|
||||||
|
<p class="text-muted fs-5">Thank you for choosing SecureLife. A confirmation email has been sent to you. We will be in touch shortly.</p>
|
||||||
|
<a href="index.php" class="btn btn-primary-modern btn-lg mt-4">Back to Home</a>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<h1 class="card-title text-center mb-2 fw-bold">Confirm Your Details</h1>
|
||||||
|
<p class="text-center text-muted mb-5">Step 3: Please review your information before confirming.</p>
|
||||||
|
|
||||||
|
<div class="bg-light-blue p-4 rounded-3">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h5 class="fw-bold">Personal Details</h5>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<li><strong>Full Name:</strong> <?php echo htmlspecialchars($personal_details['fullName']); ?></li>
|
||||||
|
<li><strong>Email:</strong> <?php echo htmlspecialchars($personal_details['email']); ?></li>
|
||||||
|
<li><strong>Phone:</strong> <?php echo htmlspecialchars($personal_details['phone']); ?></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h5 class="fw-bold">Insurance Details</h5>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<li><strong>Insurance Type:</strong> <?php echo htmlspecialchars($insurance_details['insuranceType']); ?></li>
|
||||||
|
<?php echo get_coverage_details_html($insurance_details); ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form action="subscribe-step3.php" method="POST">
|
||||||
|
<div class="d-flex justify-content-between mt-5">
|
||||||
|
<a href="subscribe-step2.php" class="btn btn-secondary btn-lg">← Go Back</a>
|
||||||
|
<button type="submit" class="btn btn-success btn-lg">Confirm Subscription ✓</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="text-center py-4 mt-auto bg-dark text-white">
|
||||||
|
<p class="mb-0">© <?php echo date("Y"); ?> SecureLife. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
72
subscribe.php
Normal file
72
subscribe.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$_SESSION['personal_details'] = [
|
||||||
|
'fullName' => filter_input(INPUT_POST, 'fullName', FILTER_SANITIZE_STRING),
|
||||||
|
'email' => filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL),
|
||||||
|
'phone' => filter_input(INPUT_POST, 'phone', FILTER_SANITIZE_STRING),
|
||||||
|
];
|
||||||
|
header('Location: subscribe-step2.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Subscribe - SecureLife</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand" href="index.php">SecureLife</a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="container my-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<div class="card shadow-sm border-0" style="border-radius: 0.75rem;">
|
||||||
|
<div class="card-body p-5">
|
||||||
|
<h1 class="card-title text-center mb-2 fw-bold">Get Your Free Quote</h1>
|
||||||
|
<p class="text-center text-muted mb-5">Step 1: Tell us about yourself</p>
|
||||||
|
|
||||||
|
<form action="subscribe.php" method="POST">
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="fullName" class="form-label fs-5">Full Name</label>
|
||||||
|
<input type="text" class="form-control form-control-lg" id="fullName" name="fullName" placeholder="e.g., John Doe" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="email" class="form-label fs-5">Email Address</label>
|
||||||
|
<input type="email" class="form-control form-control-lg" id="email" name="email" placeholder="e.g., john.doe@example.com" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="phone" class="form-label fs-5">Phone Number</label>
|
||||||
|
<input type="tel" class="form-control form-control-lg" id="phone" name="phone" placeholder="e.g., (555) 123-4567" required>
|
||||||
|
</div>
|
||||||
|
<div class="d-grid mt-5">
|
||||||
|
<button type="submit" class="btn btn-primary-modern btn-lg">Next Step →</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="text-center py-4 mt-auto bg-dark text-white">
|
||||||
|
<p class="mb-0">© <?php echo date("Y"); ?> SecureLife. All Rights Reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user