diff --git a/.htaccess b/.htaccess index e2bbc23..82ddba8 100644 --- a/.htaccess +++ b/.htaccess @@ -1,18 +1,4 @@ -DirectoryIndex index.php index.html -Options -Indexes -Options -MultiViews - RewriteEngine On - -# 0) Serve existing files/directories as-is -RewriteCond %{REQUEST_FILENAME} -f [OR] -RewriteCond %{REQUEST_FILENAME} -d -RewriteRule ^ - [L] - -# 1) Internal map: /page or /page/ -> /page.php (if such PHP file exists) -RewriteCond %{REQUEST_FILENAME}.php -f -RewriteRule ^(.+?)/?$ $1.php [L] - -# 2) Optional: strip trailing slash for non-directories (keeps .php links working) +RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^(.+)/$ $1 [R=301,L] +RewriteRule ^post/([a-zA-Z0-9-]+)$ post.php?slug=$1 [L] \ No newline at end of file diff --git a/admin.php b/admin.php new file mode 100644 index 0000000..d813857 --- /dev/null +++ b/admin.php @@ -0,0 +1,115 @@ +prepare("INSERT INTO posts (title, content, author, slug) VALUES (?, ?, ?, ?)"); + $stmt->execute([$title, $content, $author, $slug]); + $message = '
Post created successfully!
'; + } catch (PDOException $e) { + $message = '
Error: ' . $e->getMessage() . '
'; + } + } else { + $message = '
Please fill in all fields.
'; + } +} +?> + +

Add New Post Logout

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

Manage Posts

+
+ + + + + + + + + + + + query("SELECT id, title, author, created_at FROM posts ORDER BY created_at DESC"); + $posts = $stmt->fetchAll(); + + if ($posts) { + foreach ($posts as $post) { + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ''; + echo ""; + } + } else { + echo ''; + } + } catch (PDOException $e) { + echo ''; + } + ?> + +
#TitleAuthorCreated AtActions
" . htmlspecialchars($post['id']) . "" . htmlspecialchars($post['title']) . "" . htmlspecialchars($post['author']) . "" . date("F j, Y, g:i a", strtotime($post['created_at'])) . " + View + Edit + Delete +
No posts found.
Error: ' . $e->getMessage() . '
+
+ + + diff --git a/ai-and-tech.php b/ai-and-tech.php new file mode 100644 index 0000000..7174a2e --- /dev/null +++ b/ai-and-tech.php @@ -0,0 +1,15 @@ + + +
+
+
+

AI & Tech Innovation

+

This is the page for AI & Tech Innovation.

+
+
+
+ + diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..44c2b1d --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,131 @@ +@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Poppins:wght@400;500&display=swap'); + +body { + background-color: #fdfdfd; + color: #333; + font-family: 'Poppins', sans-serif; + line-height: 1.6; +} + +h1, h2, h3, h4, h5, h6 { + font-family: 'Playfair Display', serif; + font-weight: 700; + color: #222; +} + +a { + color: #007bff; + transition: color 0.3s ease; +} + +a:hover { + color: #0056b3; + text-decoration: none; +} + +.navbar { + background-color: #fff; + box-shadow: 0 2px 4px rgba(0,0,0,0.05); + padding: 1rem 0; +} + +.navbar-brand { + font-family: 'Playfair Display', serif; + font-weight: 700; + font-size: 1.75rem; + color: #333 !important; +} + +.nav-link { + font-family: 'Poppins', sans-serif; + font-weight: 500; + text-transform: uppercase; + font-size: 0.9rem; + color: #555 !important; + margin-left: 1.5rem; + transition: color 0.3s ease; +} + +.nav-link:hover { + color: #007bff !important; +} + +.card { + border: none; + border-radius: 15px; + background-color: #fff; + box-shadow: 0 10px 30px rgba(0,0,0,0.07); + overflow: hidden; + transition: transform 0.3s ease, box-shadow 0.3s ease; + margin-bottom: 2.5rem; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 15px 35px rgba(0,0,0,0.1); +} + +.card-body { + padding: 2.5rem; +} + +.card-title { + font-size: 2rem; + margin-bottom: 1rem; + line-height: 1.3; +} + +.card-text { + color: #666; + font-size: 1.05rem; +} + +.btn { + border-radius: 50px; + font-family: 'Poppins', sans-serif; + font-weight: 500; + padding: 0.8rem 2rem; + font-size: 0.9rem; + text-transform: uppercase; + letter-spacing: 1px; + transition: all 0.3s ease; +} + +.btn-primary { + background-color: #007bff; + border-color: #007bff; + color: #fff; + box-shadow: 0 5px 15px rgba(0, 123, 255, 0.2); +} + +.btn-primary:hover { + background-color: #0056b3; + border-color: #0056b3; + transform: translateY(-2px); + box-shadow: 0 8px 20px rgba(0, 123, 255, 0.3); +} + +.footer { + background-color: #333; + color: #fdfdfd; + padding: 3rem 0; + margin-top: 4rem; +} + +.footer a { + color: #fdfdfd; +} + +.footer a:hover { + color: #007bff; +} + +.container { + max-width: 1140px; +} + +.post-meta { + font-size: 0.9rem; + color: #888; + margin-bottom: 1.5rem; +} \ No newline at end of file diff --git a/automotives.php b/automotives.php new file mode 100644 index 0000000..545565f --- /dev/null +++ b/automotives.php @@ -0,0 +1,15 @@ + + +
+
+
+

Automotives

+

This is the page for Automotives.

+
+
+
+ + diff --git a/creative-and-tourism.php b/creative-and-tourism.php new file mode 100644 index 0000000..6999f51 --- /dev/null +++ b/creative-and-tourism.php @@ -0,0 +1,15 @@ + + +
+
+
+

Creative & Tourism Industries

+

This is the page for Creative & Tourism Industries.

+
+
+
+ + diff --git a/db/config.php b/db/config.php index b02e7fc..3f51609 100644 --- a/db/config.php +++ b/db/config.php @@ -1,17 +1,26 @@ PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - ]); - } - return $pdo; -} + static $p; + if ($p) return $p; + + // Read credentials from environment variables + $dbName = getenv('DB_NAME') ?: 'my_database'; + $dbHost = getenv('DB_HOST') ?: '127.0.0.1'; + $dbPort = getenv('DB_PORT') ?: '3306'; + $dbUser = getenv('DB_USER') ?: 'user'; + $dbPass = getenv('DB_PASS') ?: 'password'; + + $dsn = "mysql:host={$dbHost};port={$dbPort};dbname={$dbName};charset=utf8mb4"; + + try { + $p = new PDO($dsn, $dbUser, $dbPass, [ + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, + ]); + return $p; + } 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()); + } +} \ No newline at end of file diff --git a/db/migrations/001_create_posts_table.sql b/db/migrations/001_create_posts_table.sql new file mode 100644 index 0000000..c159550 --- /dev/null +++ b/db/migrations/001_create_posts_table.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS posts ( + id INT AUTO_INCREMENT PRIMARY KEY, + title VARCHAR(255) NOT NULL, + content TEXT NOT NULL, + author VARCHAR(255) NOT NULL, + slug VARCHAR(255) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); \ No newline at end of file diff --git a/db/migrations/002_create_users_table.sql b/db/migrations/002_create_users_table.sql new file mode 100644 index 0000000..9f0fcc8 --- /dev/null +++ b/db/migrations/002_create_users_table.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(50) NOT NULL UNIQUE, + password VARCHAR(255) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); diff --git a/db/migrations/003_create_youtube_videos_table.sql b/db/migrations/003_create_youtube_videos_table.sql new file mode 100644 index 0000000..d23ae0d --- /dev/null +++ b/db/migrations/003_create_youtube_videos_table.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS `youtube_videos` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `youtube_id` VARCHAR(255) NOT NULL UNIQUE, + `title` VARCHAR(255) NOT NULL, + `thumbnail_url` VARCHAR(255) NOT NULL, + `published_at` DATETIME NOT NULL, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); diff --git a/db/setup.php b/db/setup.php new file mode 100644 index 0000000..c12b132 --- /dev/null +++ b/db/setup.php @@ -0,0 +1,26 @@ +exec($sql); + } + + // Add a default admin user if one doesn't exist + $stmt = $pdo->query("SELECT * FROM users WHERE username = 'admin'"); + if ($stmt->rowCount() == 0) { + $username = 'admin'; + $password = password_hash('password', PASSWORD_DEFAULT); + $pdo->prepare("INSERT INTO users (username, password) VALUES (?, ?)")->execute([$username, $password]); + } + + echo "Database setup and seeding successful."; +} catch (PDOException $e) { + die("Database setup failed: " . $e->getMessage()); +} diff --git a/delete.php b/delete.php new file mode 100644 index 0000000..6007a3a --- /dev/null +++ b/delete.php @@ -0,0 +1,25 @@ +prepare("DELETE FROM posts WHERE id = ?"); + $stmt->execute([$post_id]); + } catch (PDOException $e) { + die("Error: " . $e->getMessage()); + } +} + +header('Location: admin.php'); +exit; +?> \ No newline at end of file diff --git a/edit.php b/edit.php new file mode 100644 index 0000000..1ed650a --- /dev/null +++ b/edit.php @@ -0,0 +1,79 @@ +prepare("SELECT * FROM posts WHERE id = ?"); + $stmt->execute([$post_id]); + $post = $stmt->fetch(); +} catch (PDOException $e) { + $message = '
Error: ' . $e->getMessage() . '
'; +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $title = $_POST['title'] ?? ''; + $content = $_POST['content'] ?? ''; + $author = $_POST['author'] ?? ''; + + if ($title && $content && $author) { + try { + $pdo = db(); + $stmt = $pdo->prepare("UPDATE posts SET title = ?, content = ?, author = ? WHERE id = ?"); + $stmt->execute([$title, $content, $author, $post_id]); + header('Location: admin.php'); + exit; + } catch (PDOException $e) { + $message = '
Error: ' . $e->getMessage() . '
'; + } + } else { + $message = '
Please fill in all fields.
'; + } +} + +if (!$post) { + echo "
Post not found.
"; + require_once __DIR__ . '/includes/footer.php'; + exit; +} +?> + +

Edit Post

+ + + +
+
+ + +
+
+ + +
+
+ + +
+ + Cancel +
+ + + + + + + + diff --git a/includes/header.php b/includes/header.php new file mode 100644 index 0000000..7a1fb09 --- /dev/null +++ b/includes/header.php @@ -0,0 +1,37 @@ + + + + + + <?php echo htmlspecialchars($pageTitle ?? 'My Blog'); ?> + + + + + + + + + + + +
diff --git a/index.php b/index.php index 7205f3d..dbfa388 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,44 @@ query("SELECT * FROM posts ORDER BY created_at DESC"); + $posts = $stmt->fetchAll(); +} catch (PDOException $e) { + die("Error: " . $e->getMessage()); +} ?> - - - - - - 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

-
-
- - - + +
+

Welcome to Our Blog

+

The latest news and updates, at your fingertips.

+
+ +
+ +
+
+

No posts yet!

+

Go to the admin page to create your first post.

+
+
+ + +
+
+
+

+ +

...

+ Read More +
+
+
+ + +
+ + diff --git a/login.php b/login.php new file mode 100644 index 0000000..7b6621d --- /dev/null +++ b/login.php @@ -0,0 +1,76 @@ +prepare("SELECT * FROM users WHERE username = ?"); + $stmt->execute([$username]); + $user = $stmt->fetch(); + + if ($user && password_verify($password, $user['password'])) { + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + header('Location: admin.php'); + exit; + } else { + $error = 'Invalid username or password.'; + } + } +} +?> + + + + + + Login + + + + +
+
+
+
+
+ Admin Login +
+
+ +
+ +
+
+ + +
+
+ + +
+ +
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..4e97304 --- /dev/null +++ b/logout.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/post.php b/post.php new file mode 100644 index 0000000..51570ec --- /dev/null +++ b/post.php @@ -0,0 +1,39 @@ +prepare("SELECT * FROM posts WHERE slug = ?"); + $stmt->execute([$slug]); + $post = $stmt->fetch(); + } catch (PDOException $e) { + die("Error: " . $e->getMessage()); + } +} + +if (!$post) { + http_response_code(404); + $pageTitle = 'Post Not Found'; + require_once __DIR__ . '/includes/header.php'; + echo "

Post Not Found

Sorry, the post you are looking for does not exist.

"; + require_once __DIR__ . '/includes/footer.php'; + exit; +} + +$pageTitle = $post['title']; +require_once __DIR__ . '/includes/header.php'; +?> + +
+

+

By on

+
+
+ +Back to Blog + + diff --git a/skills-development.php b/skills-development.php new file mode 100644 index 0000000..32da9d7 --- /dev/null +++ b/skills-development.php @@ -0,0 +1,15 @@ + + +
+
+
+

Skills Development

+

This is the page for Skills Development.

+
+
+
+ + diff --git a/trade-and-industry.php b/trade-and-industry.php new file mode 100644 index 0000000..045a184 --- /dev/null +++ b/trade-and-industry.php @@ -0,0 +1,15 @@ + + +
+
+
+

Trade & Industry

+

This is the page for Trade & Industry.

+
+
+
+ + diff --git a/videos.php b/videos.php new file mode 100644 index 0000000..a635cdb --- /dev/null +++ b/videos.php @@ -0,0 +1,30 @@ +query("SELECT * FROM youtube_videos ORDER BY published_at DESC"); +$videos = $stmt->fetchAll(); +?> + +
+

Latest Videos

+
+ +
+
+ + <?php echo htmlspecialchars($video['title']); ?> + +
+
+ +
+
+
+
+ +
+
+ + diff --git a/youtube.php b/youtube.php new file mode 100644 index 0000000..e6f1ad1 --- /dev/null +++ b/youtube.php @@ -0,0 +1,40 @@ +entry)) { + die('No video entries found in the RSS feed.'); +} + +$pdo = db(); + +$stmt = $pdo->prepare("INSERT IGNORE INTO youtube_videos (youtube_id, title, thumbnail_url, published_at) VALUES (:youtube_id, :title, :thumbnail_url, :published_at)"); + +foreach ($xml->entry as $entry) { + $media = $entry->children('media', true); + $yt = $entry->children('yt', true); + + $video_id = (string)$yt->videoId; + $title = (string)$media->group->title; + $thumbnail_url = (string)$media->group->thumbnail->attributes()->url; + $published_at = new DateTime((string)$entry->published); + + $stmt->execute([ + ':youtube_id' => $video_id, + ':title' => $title, + ':thumbnail_url' => $thumbnail_url, + ':published_at' => $published_at->format('Y-m-d H:i:s') + ]); +} + +echo "YouTube videos have been successfully imported.";