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'; +?> +
+

Post

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

SEO Settings

+
+ + +
+
+ + +
+ + + Cancel +
+
+ + + 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'; +?> +
+

Product

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

SEO & Open Graph

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + + Cancel +
+
+ + + \ 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

+
+
+ + +
+ +
+
+ +
+

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'; +?> +
+

Manage Blog Posts

+ Add New Post + + +
Post saved successfully.
+ + + + + + + + + + + + + + + + + + + + + +
TitleAuthorPublished OnActions
+ Edit + Delete +
+ Back to Admin Panel +
+ \ 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'; +?> +
+

Manage Products

+ Add New Product + + +
Product saved successfully.
+ + + + + + + + + + + + + + + + + + + + + + + +
NameURL SlugMaterialApplicationActions
+ Edit + Delete +
+ Back to Admin Panel +
+ \ 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.

+
+ + +
+
+ <?php echo htmlspecialchars($post['title']); ?> +
+
+

By on

+

...

+ Read More +
+
+
+ + +
+
+ + 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.

+ + + + + + + + +
+
+ + + +
+ +
+
+ + +
+
+ + + +
+ +
+
+ + +
+
+ + + +
+ +
+
+ +
+
+ +
+
+
+
+
+ + 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 @@ + + + + + + \ No newline at end of file diff --git a/includes/header.php b/includes/header.php new file mode 100644 index 0000000..76c5883 --- /dev/null +++ b/includes/header.php @@ -0,0 +1,70 @@ + + + + + + <?php echo htmlspecialchars($seo_title ?? 'Luxury Carpet B2B'); ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/index.php b/index.php index 7205f3d..5bcce2b 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,37 @@ - - - - - - New Style - - - - - - - - - - - - - - - - - - - - - -
-
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

+ +
+ +
+
+
+
+

Exquisite Carpets for Discerning Businesses

+

Discover unparalleled quality and bespoke designs for your luxury projects.

+ Request a Consultation +
+
+
-
-
- Page updated: (UTC) -
- - + + +
+
+
+

The Foundation of Luxury

+

+ At Luxury Carpets, we provide more than just flooring; we deliver a statement of elegance and craftsmanship. Our B2B services cater to architects, interior designers, and contractors who demand the very best for their clients. +

+
+
+
+
+ + \ No newline at end of file diff --git a/post.php b/post.php new file mode 100644 index 0000000..4af3f79 --- /dev/null +++ b/post.php @@ -0,0 +1,57 @@ +prepare('SELECT * FROM posts WHERE slug = ?'); + $stmt->execute([$slug]); + $post = $stmt->fetch(PDO::FETCH_ASSOC); + } catch (PDOException $e) { + error_log('Failed to fetch post: ' . $e->getMessage()); + } +} + +if (!$post) { + http_response_code(404); + require_once __DIR__ . '/includes/header.php'; + echo '

404

Article not found.

Back to Blog
'; + require_once __DIR__ . '/includes/footer.php'; + exit; +} + +// SEO & Page Variables +$pageTitle = $post['seo_title'] ?? $post['title']; +$pageDescription = $post['seo_meta_description'] ?? substr(strip_tags($post['content']), 0, 160); +$og_image = $post['image_url']; // Assuming this is a full URL +$og_type = 'article'; + +require_once __DIR__ . '/includes/header.php'; +?> + +
+
+
+
+
+

+
+ Posted on by +
+
+
+ <?php echo htmlspecialchars($post['title']); ?> +
+
+ +
+
+ ← Back to all articles +
+
+
+ + diff --git a/product.php b/product.php new file mode 100644 index 0000000..fc8f611 --- /dev/null +++ b/product.php @@ -0,0 +1,87 @@ +prepare('SELECT * FROM products WHERE url_slug = ?'); + $stmt->execute([$slug]); + $product = $stmt->fetch(PDO::FETCH_ASSOC); + } catch (PDOException $e) { + error_log('Failed to fetch product: ' . $e->getMessage()); + } +} + +// If no product is found, send a 404 response +if (!$product) { + http_response_code(404); + require_once __DIR__ . '/includes/header.php'; + echo '

404

Product not found.

Back to Catalog
'; + require_once __DIR__ . '/includes/footer.php'; + exit; +} + +// --- SEO & Page Variables --- +$seo_title = $product['seo_title']; +$seo_meta_description = $product['seo_meta_description']; +$canonical_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://{$_SERVER['HTTP_HOST']}" . $product['canonical_url']; +$og_title = $product['og_title']; +$og_description = $product['og_description']; +$og_image = $product['og_image']; // Assuming this is a full URL +$og_type = 'product'; + +$images = json_decode($product['images'], true); + +// JSON-LD Schema for Product +$schema = [ + '@context' => 'https://schema.org', + '@type' => 'Product', + 'name' => $product['name'], + 'description' => $product['description'], + 'image' => $images, // Array of image URLs + 'offers' => [ + '@type' => 'Offer', + 'priceCurrency' => 'USD', // Change as needed + 'price' => '0', // Add a price column if you have one + 'availability' => 'https://schema.org/InStock' + ] +]; + +require_once __DIR__ . '/includes/header.php'; +?> + +
+
+ +
+ + <?php echo htmlspecialchars($product['name']); ?> +
+ +
+ <?php echo htmlspecialchars($product['name']); ?> thumbnail +
+ +
+ +
+ + +
+

+

+
+

+
Application
+

+ +
+
+
+ + diff --git a/products.php b/products.php new file mode 100644 index 0000000..ea25243 --- /dev/null +++ b/products.php @@ -0,0 +1,50 @@ +query('SELECT id, name, description, images, url_slug, material, application FROM products ORDER BY created_at DESC'); + $products = $stmt->fetchAll(PDO::FETCH_ASSOC); +} catch (PDOException $e) { + error_log('Failed to fetch products: ' . $e->getMessage()); + // You could display a friendly error message to the user +} + +?> + +
+
+
+

Our Luxury Carpets

+

Discover our exclusive collection of hand-crafted carpets and rugs.

+
+
+ +
+ +
+

No products found. Please check back later.

+
+ + + +
+
+ <?php echo htmlspecialchars($product['name']); ?> +
+
+

|

+

...

+ View Details +
+
+
+ + +
+
+ +