diff --git a/admin/.htaccess b/admin/.htaccess
new file mode 100644
index 0000000..cc2c075
--- /dev/null
+++ b/admin/.htaccess
@@ -0,0 +1,4 @@
+RewriteEngine On
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteRule ^(.*)$ index.php?path=$1 [L,QSA]
\ No newline at end of file
diff --git a/admin/delete_post.php b/admin/delete_post.php
new file mode 100644
index 0000000..3a1b67e
--- /dev/null
+++ b/admin/delete_post.php
@@ -0,0 +1,21 @@
+prepare('DELETE FROM posts WHERE id = ?');
+$stmt->execute([$_GET['id']]);
+
+header('Location: posts.php?status=deleted');
+exit;
+?>
\ No newline at end of file
diff --git a/admin/delete_product.php b/admin/delete_product.php
new file mode 100644
index 0000000..ee9e97d
--- /dev/null
+++ b/admin/delete_product.php
@@ -0,0 +1,21 @@
+prepare('DELETE FROM products WHERE id = ?');
+$stmt->execute([$_GET['id']]);
+
+header('Location: products.php?status=deleted');
+exit;
+?>
\ No newline at end of file
diff --git a/admin/edit_post.php b/admin/edit_post.php
new file mode 100644
index 0000000..7298e3d
--- /dev/null
+++ b/admin/edit_post.php
@@ -0,0 +1,109 @@
+ '',
+ 'title' => '',
+ 'slug' => '',
+ 'content' => '',
+ 'author' => '',
+ 'image_url' => '',
+ 'seo_title' => '',
+ 'seo_meta_description' => ''
+];
+
+// Check if it's an edit request
+if (isset($_GET['id'])) {
+ $stmt = $pdo->prepare('SELECT * FROM posts WHERE id = ?');
+ $stmt->execute([$_GET['id']]);
+ $post = $stmt->fetch(PDO::FETCH_ASSOC);
+ if (!$post) {
+ die('Post not found.');
+ }
+}
+
+// Handle form submission
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ $id = $_POST['id'] ?? null;
+ $title = $_POST['title'];
+ $slug = $_POST['slug'];
+ $content = $_POST['content'];
+ $author = $_POST['author'];
+ $image_url = $_POST['image_url'];
+ $seo_title = $_POST['seo_title'];
+ $seo_meta_description = $_POST['seo_meta_description'];
+
+ if ($id) { // Update
+ $sql = "UPDATE posts SET title = ?, slug = ?, content = ?, author = ?, image_url = ?, seo_title = ?, seo_meta_description = ? WHERE id = ?";
+ $stmt = $pdo->prepare($sql);
+ $stmt->execute([$title, $slug, $content, $author, $image_url, $seo_title, $seo_meta_description, $id]);
+ } else { // Insert
+ $sql = "INSERT INTO posts (title, slug, content, author, image_url, seo_title, seo_meta_description) VALUES (?, ?, ?, ?, ?, ?, ?)";
+ $stmt = $pdo->prepare($sql);
+ $stmt->execute([$title, $slug, $content, $author, $image_url, $seo_title, $seo_meta_description]);
+ }
+
+ header('Location: posts.php?status=success');
+ exit;
+}
+
+include __DIR__ . '/../includes/header.php';
+?>
+
+
+
+
diff --git a/admin/edit_product.php b/admin/edit_product.php
new file mode 100644
index 0000000..69b0af5
--- /dev/null
+++ b/admin/edit_product.php
@@ -0,0 +1,150 @@
+ '',
+ 'name' => '',
+ 'description' => '',
+ 'images' => '',
+ 'material' => '',
+ 'application' => '',
+ 'url_slug' => '',
+ 'seo_title' => '',
+ 'seo_meta_description' => '',
+ 'canonical_url' => '',
+ 'og_title' => '',
+ 'og_description' => '',
+ 'og_image' => '',
+ 'schema_type' => 'Product'
+];
+
+if (isset($_GET['id'])) {
+ $stmt = $pdo->prepare('SELECT * FROM products WHERE id = ?');
+ $stmt->execute([$_GET['id']]);
+ $product = $stmt->fetch(PDO::FETCH_ASSOC);
+ if (!$product) {
+ die('Product not found.');
+ }
+}
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ $id = $_POST['id'] ?? null;
+ $name = $_POST['name'];
+ $description = $_POST['description'];
+ $images = $_POST['images'];
+ $material = $_POST['material'];
+ $application = $_POST['application'];
+ $url_slug = $_POST['url_slug'];
+ $seo_title = $_POST['seo_title'];
+ $seo_meta_description = $_POST['seo_meta_description'];
+ $canonical_url = $_POST['canonical_url'];
+ $og_title = $_POST['og_title'];
+ $og_description = $_POST['og_description'];
+ $og_image = $_POST['og_image'];
+ $schema_type = $_POST['schema_type'];
+
+ if ($id) { // Update
+ $sql = "UPDATE products SET name=?, description=?, images=?, material=?, application=?, url_slug=?, seo_title=?, seo_meta_description=?, canonical_url=?, og_title=?, og_description=?, og_image=?, schema_type=? WHERE id=?";
+ $params = [$name, $description, $images, $material, $application, $url_slug, $seo_title, $seo_meta_description, $canonical_url, $og_title, $og_description, $og_image, $schema_type, $id];
+ } else { // Insert
+ $sql = "INSERT INTO products (name, description, images, material, application, url_slug, seo_title, seo_meta_description, canonical_url, og_title, og_description, og_image, schema_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ $params = [$name, $description, $images, $material, $application, $url_slug, $seo_title, $seo_meta_description, $canonical_url, $og_title, $og_description, $og_image, $schema_type];
+ }
+ $stmt = $pdo->prepare($sql);
+ $stmt->execute($params);
+
+ header('Location: products.php?status=success');
+ exit;
+}
+
+include __DIR__ . '/../includes/header.php';
+?>
+
+
+
+
\ No newline at end of file
diff --git a/admin/index.php b/admin/index.php
new file mode 100644
index 0000000..a60d353
--- /dev/null
+++ b/admin/index.php
@@ -0,0 +1,57 @@
+
+
+
Admin Login
+
+
+ Password
+
+
+ Login
+
+
+
+
+
Admin Panel
+
Welcome to the admin panel. Here you can manage your products and blog posts.
+
Logout
+
+
Manage Content
+
+
+query('SELECT * FROM posts ORDER BY published_at DESC');
+$posts = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+include __DIR__ . '/../includes/header.php';
+?>
+
+
\ No newline at end of file
diff --git a/admin/products.php b/admin/products.php
new file mode 100644
index 0000000..a08b196
--- /dev/null
+++ b/admin/products.php
@@ -0,0 +1,54 @@
+query('SELECT id, name, url_slug, material, application FROM products ORDER BY created_at DESC');
+$products = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+include __DIR__ . '/../includes/header.php';
+?>
+
+
\ No newline at end of file
diff --git a/assets/css/custom.css b/assets/css/custom.css
new file mode 100644
index 0000000..48a26cd
--- /dev/null
+++ b/assets/css/custom.css
@@ -0,0 +1,33 @@
+body {
+ background-color: #F8F6F4 !important;
+ font-family: 'Helvetica Neue', Arial, sans-serif;
+ color: #38404B;
+}
+
+.navbar-brand {
+ color: #A68A64 !important;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-family: 'Georgia', serif;
+ color: #38404B;
+}
+
+.btn-primary {
+ background-color: #A68A64;
+ border-color: #A68A64;
+}
+
+.btn-primary:hover {
+ background-color: #8b7355;
+ border-color: #8b7355;
+}
+
+.form-control:focus {
+ border-color: #E0CDB8;
+ box-shadow: 0 0 0 0.25rem rgba(166, 138, 100, 0.25);
+}
+
+.bg-gradient-light {
+ background: linear-gradient(180deg, #F8F6F4 0%, #FFFFFF 100%);
+}
\ No newline at end of file
diff --git a/assets/images/blog1.jpg b/assets/images/blog1.jpg
new file mode 100644
index 0000000..e69de29
diff --git a/assets/images/blog2.jpg b/assets/images/blog2.jpg
new file mode 100644
index 0000000..e69de29
diff --git a/blog.php b/blog.php
new file mode 100644
index 0000000..15d2c7a
--- /dev/null
+++ b/blog.php
@@ -0,0 +1,50 @@
+query("SELECT id, title, slug, content, author, image_url, published_at FROM posts ORDER BY published_at DESC");
+ $posts = $stmt->fetchAll(PDO::FETCH_ASSOC);
+} catch (PDOException $e) {
+ error_log('Failed to fetch posts: ' . $e->getMessage());
+}
+
+?>
+
+
+
+
+
From the Journal
+
Design insights, company news, and the art of craftsmanship.
+
+
+
+
+
+
+
No articles have been published yet. Please check back soon.
+
+
+
+
+
+
+
+
+
+
diff --git a/contact.php b/contact.php
new file mode 100644
index 0000000..327c9fa
--- /dev/null
+++ b/contact.php
@@ -0,0 +1,125 @@
+prepare(
+ "INSERT INTO inquiries (name, company, email, phone, message, source_page) VALUES (?, ?, ?, ?, ?, ?)"
+ );
+ $stmt->execute([$name, $company, $email, $phone, $message, $source_page]);
+
+ // Send email notification
+ $admin_email = getenv('MAIL_TO') ?: 'admin@example.com'; // Fallback
+ $subject = "New Inquiry from " . htmlspecialchars($name);
+ $body_html = "New Inquiry
+ Name: " . htmlspecialchars($name) . "
+ Company: " . htmlspecialchars($company) . "
+ Email: " . htmlspecialchars($email) . "
+ Phone: " . htmlspecialchars($phone) . "
+ Message:
+ " . nl2br(htmlspecialchars($message)) . "
+ Source: " . htmlspecialchars($source_page) . "
";
+ $body_text = "New Inquiry\n\nName: " . $name . "\nCompany: " . $company . "\nEmail: " . $email . "\nPhone: " . $phone . "\nMessage: " . $message . "\nSource: " . $source_page;
+
+ // Using MailService
+ MailService::sendMail($admin_email, $subject, $body_html, $body_text, ['reply_to' => $email]);
+
+ $success = true;
+ } catch (PDOException $e) {
+ $errors['db'] = 'There was a problem saving your inquiry. Please try again later.';
+ error_log('Inquiry Error: ' . $e->getMessage());
+ } catch (Exception $e) {
+ $errors['mail'] = 'There was a problem sending the notification. Your inquiry was saved.';
+ error_log('Mail Error: ' . $e->getMessage());
+ }
+ }
+}
+
+include __DIR__ . '/includes/header.php';
+?>
+
+
+
+
+
+
+
Contact Us
+
We would love to hear from you. Please fill out this form and we will get in touch with you shortly.
+
+
+
+ Thank you! Your inquiry has been sent successfully.
+
+
+
+
+
+
+
+
+
+
+
+ Company Name
+
+
+
+
Email Address
+
+
+
+
+
+
+ Phone Number (Optional)
+
+
+
+
+ Send Inquiry
+
+
+
+
+
+
+
+
+
+
diff --git a/db/.migration_done b/db/.migration_done
new file mode 100644
index 0000000..348ebd9
--- /dev/null
+++ b/db/.migration_done
@@ -0,0 +1 @@
+done
\ No newline at end of file
diff --git a/db/seed.php b/db/seed.php
new file mode 100644
index 0000000..6d4a51e
--- /dev/null
+++ b/db/seed.php
@@ -0,0 +1,65 @@
+setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+ $products = [
+ [
+ 'name' => 'Royal Kashan Carpet',
+ 'description' => 'A masterpiece of Persian art, this Royal Kashan carpet features a dense, floral pattern with a central medallion. Hand-knotted from pure silk, it offers a luxurious feel and timeless elegance.',
+ 'images' => json_encode(['https://picsum.photos/seed/kashan/800/600', 'https://picsum.photos/seed/kashan2/800/600']),
+ 'material' => 'Silk',
+ 'application' => 'Living Room, Bedroom',
+ 'url_slug' => 'royal-kashan-carpet',
+ 'seo_title' => 'Royal Kashan Silk Carpet | Luxury Persian Rugs',
+ 'seo_meta_description' => 'Discover the exquisite beauty of our hand-knotted Royal Kashan silk carpet. A timeless piece of art for your luxury interior.',
+ 'canonical_url' => '/product/royal-kashan-carpet',
+ 'og_title' => 'Royal Kashan Silk Carpet',
+ 'og_description' => 'A masterpiece of Persian art, this Royal Kashan carpet features a dense, floral pattern with a central medallion.',
+ 'og_image' => 'https://picsum.photos/seed/kashan/1200/630',
+ ],
+ [
+ 'name' => 'Modern Gabbeh Rug',
+ 'description' => 'This modern Gabbeh rug is characterized by its minimalist design and thick, plush pile. Made from hand-spun wool and natural dyes, it brings warmth and contemporary style to any space.',
+ 'images' => json_encode(['https://picsum.photos/seed/gabbeh/800/600', 'https://picsum.photos/seed/gabbeh2/800/600']),
+ 'material' => 'Wool',
+ 'application' => 'Office, Study',
+ 'url_slug' => 'modern-gabbeh-rug',
+ 'seo_title' => 'Modern Gabbeh Wool Rug | Contemporary Rugs',
+ 'seo_meta_description' => 'Add a touch of contemporary elegance with our hand-woven Modern Gabbeh wool rug. Perfect for modern and minimalist interiors.',
+ 'canonical_url' => '/product/modern-gabbeh-rug',
+ 'og_title' => 'Modern Gabbeh Wool Rug',
+ 'og_description' => 'Characterized by its minimalist design and thick, plush pile, this rug brings warmth and contemporary style.',
+ 'og_image' => 'https://picsum.photos/seed/gabbeh/1200/630',
+ ],
+ [
+ 'name' => 'Vintage Turkish Kilim',
+ 'description' => 'A beautiful vintage Turkish Kilim, featuring geometric patterns and a rich color palette. This flat-woven rug is a versatile piece that adds a bohemian and historic touch to your home.',
+ 'images' => json_encode(['https://picsum.photos/seed/kilim/800/600', 'https://picsum.photos/seed/kilim2/800/600']),
+ 'material' => 'Wool and Cotton',
+ 'application' => 'Hallway, Kitchen',
+ 'url_slug' => 'vintage-turkish-kilim',
+ 'seo_title' => 'Vintage Turkish Kilim Rug | Bohemian Flat-Weave Rugs',
+ 'seo_meta_description' => 'Explore our collection of vintage Turkish Kilim rugs. Each piece is unique and tells a story of its own, perfect for a bohemian decor.',
+ 'canonical_url' => '/product/vintage-turkish-kilim',
+ 'og_title' => 'Vintage Turkish Kilim Rug',
+ 'og_description' => 'Featuring geometric patterns and a rich color palette, this flat-woven rug is a versatile piece.',
+ 'og_image' => 'https://picsum.photos/seed/kilim/1200/630',
+ ]
+ ];
+
+ $stmt = $pdo->prepare(
+ 'INSERT INTO products (name, description, images, material, application, url_slug, seo_title, seo_meta_description, canonical_url, og_title, og_description, og_image) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE name=name'
+ );
+
+ foreach ($products as $product) {
+ $stmt->execute(array_values($product));
+ }
+
+ echo "Database seeded successfully!\n";
+
+} catch (PDOException $e) {
+ die("Database seeding failed: " . $e->getMessage() . "\n");
+}
diff --git a/db/seed_posts.php b/db/seed_posts.php
new file mode 100644
index 0000000..80619c2
--- /dev/null
+++ b/db/seed_posts.php
@@ -0,0 +1,43 @@
+setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+ $posts = [
+ [
+ 'title' => 'The Timeless Elegance of Hand-Knotted Carpets',
+ 'slug' => 'timeless-elegance-hand-knotted-carpets',
+ 'content' => 'Hand-knotted carpets are more than just floor coverings; they are works of art, imbued with history and craftsmanship. In this post, we explore the intricate process of creating these masterpieces and why they remain a symbol of luxury and timeless elegance in any interior.',
+ 'author' => 'Jane Doe',
+ 'image_url' => '/assets/images/blog1.jpg',
+ 'seo_title' => 'The Timeless Elegance of Hand-Knotted Carpets',
+ 'seo_meta_description' => 'Discover the art and history behind hand-knotted luxury carpets and why they are a timeless addition to any home.'
+ ],
+ [
+ 'title' => 'How to Choose the Perfect Carpet for Your Space',
+ 'slug' => 'how-to-choose-perfect-carpet',
+ 'content' => 'Choosing the right carpet can transform a room. This guide provides expert tips on selecting the perfect carpet based on material, color, and foot traffic to match your lifestyle and decor. From plush wool to durable synthetics, find the ideal fit for your home.',
+ 'author' => 'John Smith',
+ 'image_url' => '/assets/images/blog2.jpg',
+ 'seo_title' => 'A Guide to Choosing the Perfect Luxury Carpet',
+ 'seo_meta_description' => 'Our expert guide helps you select the perfect luxury carpet for your home, considering material, color, and use.'
+ ]
+ ];
+
+ $stmt = $pdo->prepare(
+ "INSERT INTO posts (title, slug, content, author, image_url, seo_title, seo_meta_description, published_at)
+ VALUES (:title, :slug, :content, :author, :image_url, :seo_title, :seo_meta_description, NOW())
+ ON DUPLICATE KEY UPDATE title=VALUES(title), content=VALUES(content)"
+ );
+
+ foreach ($posts as $post) {
+ $stmt->execute($post);
+ }
+
+ echo "Successfully seeded the posts table with " . count($posts) . " articles.\n";
+
+} catch (PDOException $e) {
+ die("Seeding failed: " . $e->getMessage() . "\n");
+}
diff --git a/db/setup.php b/db/setup.php
new file mode 100644
index 0000000..6d166d4
--- /dev/null
+++ b/db/setup.php
@@ -0,0 +1,72 @@
+setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+ $sql = "
+ CREATE TABLE IF NOT EXISTS `inquiries` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `name` VARCHAR(255) NOT NULL,
+ `company` VARCHAR(255) NULL,
+ `email` VARCHAR(255) NOT NULL,
+ `phone` VARCHAR(50) NULL,
+ `message` TEXT NOT NULL,
+ `source_page` VARCHAR(255) NULL,
+ `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+ );";
+ $pdo->exec($sql);
+
+ $sql_products = "
+ CREATE TABLE IF NOT EXISTS `products` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `name` VARCHAR(255) NOT NULL,
+ `description` TEXT NOT NULL,
+ `images` TEXT,
+ `material` VARCHAR(255),
+ `application` VARCHAR(255),
+ `url_slug` VARCHAR(255) NOT NULL UNIQUE,
+ `seo_title` VARCHAR(255),
+ `seo_meta_description` TEXT,
+ `canonical_url` VARCHAR(255),
+ `og_title` VARCHAR(255),
+ `og_description` TEXT,
+ `og_image` VARCHAR(255),
+ `schema_type` VARCHAR(255) DEFAULT 'Product',
+ `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+ );";
+ $pdo->exec($sql_products);
+
+ $sql_posts = "
+ CREATE TABLE IF NOT EXISTS `posts` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `title` VARCHAR(255) NOT NULL,
+ `slug` VARCHAR(255) NOT NULL UNIQUE,
+ `content` TEXT NOT NULL,
+ `author` VARCHAR(255),
+ `image_url` VARCHAR(255),
+ `published_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
+ `seo_title` VARCHAR(255),
+ `seo_meta_description` TEXT,
+ `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+ );";
+ $pdo->exec($sql_posts);
+
+ } catch (PDOException $e) {
+ error_log("DB setup failed: " . $e->getMessage());
+ // Do not die, just log the error. The page should still render.
+ }
+}
+
+// Check if a flag file exists to prevent running this on every page load
+$migration_flag = __DIR__ . '/.migration_done';
+if (!file_exists($migration_flag)) {
+ run_migrations();
+ // Create the flag file
+ file_put_contents($migration_flag, 'done');
+}
diff --git a/includes/footer.php b/includes/footer.php
new file mode 100644
index 0000000..7242f8e
--- /dev/null
+++ b/includes/footer.php
@@ -0,0 +1,10 @@
+
+
+
© Luxury Carpets. All Rights Reserved.
+
+
+
+
+
+