diff --git a/assets/css/custom.css b/assets/css/custom.css
new file mode 100644
index 0000000..694f580
--- /dev/null
+++ b/assets/css/custom.css
@@ -0,0 +1,32 @@
+
+/* Orange and Dark Gray Theme */
+:root {
+ --bs-primary: #fd7e14; /* Vivid Orange */
+ --bs-secondary: #6c757d;
+ --bs-dark: #343a40;
+ --bs-primary-rgb: 253, 126, 20;
+}
+
+body {
+ font-family: 'Inter', sans-serif;
+ background-color: #f8f9fa;
+}
+
+.btn-primary {
+ background-color: var(--bs-primary);
+ border-color: var(--bs-primary);
+}
+
+.btn-primary:hover {
+ background-color: #e46a0a;
+ border-color: #d16209;
+}
+
+.navbar-dark {
+ background-color: var(--bs-dark) !important;
+}
+
+.footer {
+ background-color: #343a40;
+ color: white;
+}
diff --git a/assets/js/main.js b/assets/js/main.js
new file mode 100644
index 0000000..89fe2b2
--- /dev/null
+++ b/assets/js/main.js
@@ -0,0 +1,19 @@
+
+// Main JavaScript file
+(function() {
+ 'use strict';
+ window.addEventListener('load', function() {
+ // Fetch all the forms we want to apply custom Bootstrap validation styles to
+ var forms = document.getElementsByClassName('needs-validation');
+ // Loop over them and prevent submission
+ var validation = Array.prototype.filter.call(forms, function(form) {
+ form.addEventListener('submit', function(event) {
+ if (form.checkValidity() === false) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ form.classList.add('was-validated');
+ }, false);
+ });
+ }, false);
+})();
diff --git a/db/config.php b/db/config.php
index cc9229f..f6e3568 100644
--- a/db/config.php
+++ b/db/config.php
@@ -1,17 +1,57 @@
PDO::ERRMODE_EXCEPTION,
- PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
- ]);
- }
- return $pdo;
+ static $pdo;
+ if ($pdo) {
+ return $pdo;
+ }
+ try {
+ // Connect without specifying a database to create it if it doesn't exist
+ $dsn_init = 'mysql:host=' . DB_HOST . ';port=' . DB_PORT . ';charset=utf8mb4';
+ $pdo_init = new PDO($dsn_init, DB_USER, DB_PASS, [
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
+ PDO::ATTR_EMULATE_PREPARES => false,
+ ]);
+ $pdo_init->exec('CREATE DATABASE IF NOT EXISTS `' . DB_NAME . '`');
+
+ // Now connect to the specific database
+ $dsn = 'mysql:host=' . DB_HOST . ';port=' . DB_PORT . ';dbname=' . DB_NAME . ';charset=utf8mb4';
+ $pdo = new PDO($dsn, DB_USER, DB_PASS, [
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
+ PDO::ATTR_EMULATE_PREPARES => false,
+ ]);
+
+ run_migrations($pdo);
+
+ return $pdo;
+ } catch (PDOException $e) {
+ // In a real app, you'd log this error and show a generic message
+ throw new PDOException($e->getMessage(), (int)$e->getCode());
+ }
+}
+
+function run_migrations($pdo) {
+ $pdo->exec('CREATE TABLE IF NOT EXISTS `migrations` (`migration` VARCHAR(255) NOT NULL, PRIMARY KEY (`migration`))');
+ $applied_migrations = $pdo->query('SELECT `migration` FROM `migrations`')->fetchAll(PDO::FETCH_COLUMN);
+
+ $migration_files = glob(__DIR__ . '/migrations/*.sql');
+ sort($migration_files);
+
+ foreach ($migration_files as $file) {
+ $migration_name = basename($file);
+ if (!in_array($migration_name, $applied_migrations)) {
+ $sql = file_get_contents($file);
+ $pdo->exec($sql);
+ $stmt = $pdo->prepare('INSERT INTO `migrations` (`migration`) VALUES (?)');
+ $stmt->execute([$migration_name]);
+ }
+ }
}
diff --git a/db/migrations/001_create_service_requests.sql b/db/migrations/001_create_service_requests.sql
new file mode 100644
index 0000000..ae78fc3
--- /dev/null
+++ b/db/migrations/001_create_service_requests.sql
@@ -0,0 +1,10 @@
+
+CREATE TABLE IF NOT EXISTS `service_requests` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ `email` varchar(255) NOT NULL,
+ `message` text NOT NULL,
+ `status` varchar(50) NOT NULL DEFAULT 'pending',
+ `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
diff --git a/footer.php b/footer.php
new file mode 100644
index 0000000..5e712bc
--- /dev/null
+++ b/footer.php
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+