Autosave: 20260225-203753
This commit is contained in:
parent
24820a45de
commit
e342e6bc0e
@ -108,7 +108,7 @@ class AdminController extends Controller {
|
||||
$status = $_POST['status'] ?? 'published';
|
||||
$is_vip = isset($_POST['is_vip']) ? 1 : 0;
|
||||
|
||||
$icon_path = $this->handleUpload('icon_file', true);
|
||||
$icon_path = $this->handleUpload('icon_file', 'icons');
|
||||
|
||||
$db = db_pdo();
|
||||
$stmt = $db->prepare("INSERT INTO apks (title, slug, description, version, image_url, icon_path, download_url, category_id, status, is_vip, display_order) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)");
|
||||
@ -142,7 +142,7 @@ class AdminController extends Controller {
|
||||
$download_url = $download_urls[$index] ?? '';
|
||||
$description = $title; // Default description to title for mass upload
|
||||
|
||||
$icon_path = $this->handleMassUploadFile('icon_files', $index, true);
|
||||
$icon_path = $this->handleMassUploadFile('icon_files', $index, 'icons');
|
||||
|
||||
$stmt->execute([$title, $slug, $description, $version, $icon_path, $download_url, $category_id, $status]);
|
||||
}
|
||||
@ -150,12 +150,12 @@ class AdminController extends Controller {
|
||||
$this->redirect('/admin/apks');
|
||||
}
|
||||
|
||||
private function handleMassUploadFile($field, $index, $compress = false) {
|
||||
private function handleMassUploadFile($field, $index, $dir = 'icons') {
|
||||
if (!isset($_FILES[$field]['name'][$index]) || $_FILES[$field]['error'][$index] !== UPLOAD_ERR_OK) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$uploadDir = 'assets/uploads/icons/';
|
||||
$uploadDir = 'assets/uploads/' . $dir . '/';
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0775, true);
|
||||
}
|
||||
@ -164,14 +164,8 @@ class AdminController extends Controller {
|
||||
$fileName = uniqid() . '.' . $ext;
|
||||
$targetPath = $uploadDir . $fileName;
|
||||
|
||||
if ($compress) {
|
||||
if (compress_image($_FILES[$field]['tmp_name'][$index], $targetPath, 75)) {
|
||||
return $targetPath;
|
||||
}
|
||||
} else {
|
||||
if (move_uploaded_file($_FILES[$field]['tmp_name'][$index], $targetPath)) {
|
||||
return $targetPath;
|
||||
}
|
||||
if (compress_image($_FILES[$field]['tmp_name'][$index], $targetPath, 75)) {
|
||||
return $targetPath;
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -199,7 +193,7 @@ class AdminController extends Controller {
|
||||
|
||||
$db = db_pdo();
|
||||
$apk = $db->query("SELECT * FROM apks WHERE id = " . $params['id'])->fetch();
|
||||
$icon_path = $this->handleUpload('icon_file', true) ?: $apk['icon_path'];
|
||||
$icon_path = $this->handleUpload('icon_file', 'icons') ?: $apk['icon_path'];
|
||||
|
||||
$stmt = $db->prepare("UPDATE apks SET title = ?, description = ?, version = ?, image_url = ?, icon_path = ?, download_url = ?, category_id = ?, status = ?, is_vip = ? WHERE id = ?");
|
||||
$stmt->execute([$title, $description, $version, $image_url, $icon_path, $download_url, $category_id, $status, $is_vip, $params['id']]);
|
||||
@ -219,12 +213,12 @@ class AdminController extends Controller {
|
||||
echo json_encode(['success' => true]);
|
||||
}
|
||||
|
||||
private function handleUpload($field, $compress = false) {
|
||||
private function handleUpload($field, $dir = 'icons') {
|
||||
if (!isset($_FILES[$field]) || $_FILES[$field]['error'] !== UPLOAD_ERR_OK) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$uploadDir = 'assets/uploads/icons/';
|
||||
$uploadDir = 'assets/uploads/' . $dir . '/';
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0775, true);
|
||||
}
|
||||
@ -233,14 +227,8 @@ class AdminController extends Controller {
|
||||
$fileName = uniqid() . '.' . $ext;
|
||||
$targetPath = $uploadDir . $fileName;
|
||||
|
||||
if ($compress) {
|
||||
if (compress_image($_FILES[$field]['tmp_name'], $targetPath, 75)) {
|
||||
return $targetPath;
|
||||
}
|
||||
} else {
|
||||
if (move_uploaded_file($_FILES[$field]['tmp_name'], $targetPath)) {
|
||||
return $targetPath;
|
||||
}
|
||||
if (compress_image($_FILES[$field]['tmp_name'], $targetPath, 75)) {
|
||||
return $targetPath;
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -257,6 +245,10 @@ class AdminController extends Controller {
|
||||
'meta_keywords' => get_setting('meta_keywords'),
|
||||
'head_js' => get_setting('head_js'),
|
||||
'body_js' => get_setting('body_js'),
|
||||
'facebook_url' => get_setting('facebook_url'),
|
||||
'twitter_url' => get_setting('twitter_url'),
|
||||
'instagram_url' => get_setting('instagram_url'),
|
||||
'github_url' => get_setting('github_url'),
|
||||
];
|
||||
$this->view('admin/settings', ['settings' => $settings]);
|
||||
}
|
||||
@ -265,7 +257,10 @@ class AdminController extends Controller {
|
||||
$this->checkAuth();
|
||||
$db = db_pdo();
|
||||
|
||||
$fields = ['site_name', 'meta_description', 'meta_keywords', 'head_js', 'body_js'];
|
||||
$fields = [
|
||||
'site_name', 'meta_description', 'meta_keywords', 'head_js', 'body_js',
|
||||
'facebook_url', 'twitter_url', 'instagram_url', 'github_url'
|
||||
];
|
||||
foreach ($fields as $field) {
|
||||
if (isset($_POST[$field])) {
|
||||
$stmt = $db->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = ?");
|
||||
@ -273,13 +268,13 @@ class AdminController extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$site_icon = $this->handleUpload('site_icon_file');
|
||||
$site_icon = $this->handleUpload('site_icon_file', 'settings');
|
||||
if ($site_icon) {
|
||||
$stmt = $db->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = 'site_icon'");
|
||||
$stmt->execute([$site_icon]);
|
||||
}
|
||||
|
||||
$site_favicon = $this->handleUpload('site_favicon_file');
|
||||
$site_favicon = $this->handleUpload('site_favicon_file', 'settings');
|
||||
if ($site_favicon) {
|
||||
$stmt = $db->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = 'site_favicon'");
|
||||
$stmt->execute([$site_favicon]);
|
||||
@ -288,6 +283,66 @@ class AdminController extends Controller {
|
||||
$this->redirect('/admin/settings');
|
||||
}
|
||||
|
||||
// Blog Management
|
||||
public function posts() {
|
||||
$this->checkAuth();
|
||||
$db = db_pdo();
|
||||
$posts = $db->query("SELECT * FROM posts ORDER BY created_at DESC")->fetchAll();
|
||||
$this->view('admin/posts/index', ['posts' => $posts]);
|
||||
}
|
||||
|
||||
public function addPostForm() {
|
||||
$this->checkAuth();
|
||||
$this->view('admin/posts/form', ['action' => 'add']);
|
||||
}
|
||||
|
||||
public function addPost() {
|
||||
$this->checkAuth();
|
||||
$title = $_POST['title'];
|
||||
$slug = $this->slugify($title);
|
||||
$content = $_POST['content'];
|
||||
$status = $_POST['status'] ?? 'published';
|
||||
|
||||
$image_path = $this->handleUpload('image_file', 'blog');
|
||||
|
||||
$db = db_pdo();
|
||||
$stmt = $db->prepare("INSERT INTO posts (title, slug, content, image_path, status) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$title, $slug, $content, $image_path, $status]);
|
||||
|
||||
$this->redirect('/admin/posts');
|
||||
}
|
||||
|
||||
public function editPostForm($params) {
|
||||
$this->checkAuth();
|
||||
$db = db_pdo();
|
||||
$post = $db->query("SELECT * FROM posts WHERE id = " . $params['id'])->fetch();
|
||||
$this->view('admin/posts/form', ['action' => 'edit', 'post' => $post]);
|
||||
}
|
||||
|
||||
public function editPost($params) {
|
||||
$this->checkAuth();
|
||||
$title = $_POST['title'];
|
||||
$content = $_POST['content'];
|
||||
$status = $_POST['status'];
|
||||
|
||||
$db = db_pdo();
|
||||
$post = $db->query("SELECT * FROM posts WHERE id = " . $params['id'])->fetch();
|
||||
$image_path = $this->handleUpload('image_file', 'blog') ?: $post['image_path'];
|
||||
|
||||
$stmt = $db->prepare("UPDATE posts SET title = ?, content = ?, image_path = ?, status = ? WHERE id = ?");
|
||||
$stmt->execute([$title, $content, $image_path, $status, $params['id']]);
|
||||
|
||||
$this->redirect('/admin/posts');
|
||||
}
|
||||
|
||||
public function deletePost($params) {
|
||||
$this->checkAuth();
|
||||
$db = db_pdo();
|
||||
$stmt = $db->prepare("DELETE FROM posts WHERE id = ?");
|
||||
$stmt->execute([$params['id']]);
|
||||
$this->redirect('/admin/posts');
|
||||
}
|
||||
|
||||
// Category Management
|
||||
public function categories() {
|
||||
$this->checkAuth();
|
||||
@ -361,4 +416,4 @@ class AdminController extends Controller {
|
||||
$text = strtolower($text);
|
||||
return empty($text) ? 'n-a' : $text;
|
||||
}
|
||||
}
|
||||
}
|
||||
29
app/Controllers/BlogController.php
Normal file
29
app/Controllers/BlogController.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Core\Controller;
|
||||
|
||||
class BlogController extends Controller {
|
||||
|
||||
public function index() {
|
||||
$db = db_pdo();
|
||||
$posts = $db->query("SELECT * FROM posts WHERE status = 'published' ORDER BY created_at DESC")->fetchAll();
|
||||
$this->view('blog/index', ['posts' => $posts]);
|
||||
}
|
||||
|
||||
public function detail($params) {
|
||||
$slug = $params['slug'];
|
||||
$db = db_pdo();
|
||||
$stmt = $db->prepare("SELECT * FROM posts WHERE slug = ? AND status = 'published'");
|
||||
$stmt->execute([$slug]);
|
||||
$post = $stmt->fetch();
|
||||
|
||||
if (!$post) {
|
||||
$this->view('404');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->view('blog/detail', ['post' => $post]);
|
||||
}
|
||||
}
|
||||
18
db/migrations/20260225_add_blog_and_social_settings.sql
Normal file
18
db/migrations/20260225_add_blog_and_social_settings.sql
Normal file
@ -0,0 +1,18 @@
|
||||
-- Create posts table for Blog
|
||||
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,
|
||||
`image_path` VARCHAR(255) DEFAULT NULL,
|
||||
`status` ENUM('published', 'draft') DEFAULT 'published',
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Add Social Media Settings
|
||||
INSERT IGNORE INTO `settings` (`setting_key`, `setting_value`) VALUES
|
||||
('facebook_url', ''),
|
||||
('twitter_url', ''),
|
||||
('instagram_url', ''),
|
||||
('github_url', '');
|
||||
14
index.php
14
index.php
@ -46,6 +46,10 @@ $router->get('/', 'HomeController@index');
|
||||
$router->get('/apk/:slug', 'HomeController@apkDetail');
|
||||
$router->get('/download/:slug', 'HomeController@download');
|
||||
|
||||
// Blog
|
||||
$router->get('/blog', 'BlogController@index');
|
||||
$router->get('/blog/:slug', 'BlogController@detail');
|
||||
|
||||
// Static Pages
|
||||
$router->get('/help-center', 'HomeController@helpCenter');
|
||||
$router->get('/privacy-policy', 'HomeController@privacyPolicy');
|
||||
@ -87,6 +91,14 @@ $router->post('/admin/apks/edit/:id', 'AdminController@editApk');
|
||||
$router->get('/admin/apks/delete/:id', 'AdminController@deleteApk');
|
||||
$router->post('/admin/apks/reorder', 'AdminController@updateOrder');
|
||||
|
||||
// Admin Posts (Blog)
|
||||
$router->get('/admin/posts', 'AdminController@posts');
|
||||
$router->get('/admin/posts/add', 'AdminController@addPostForm');
|
||||
$router->post('/admin/posts/add', 'AdminController@addPost');
|
||||
$router->get('/admin/posts/edit/:id', 'AdminController@editPostForm');
|
||||
$router->post('/admin/posts/edit/:id', 'AdminController@editPost');
|
||||
$router->get('/admin/posts/delete/:id', 'AdminController@deletePost');
|
||||
|
||||
// Admin Categories
|
||||
$router->get('/admin/categories', 'AdminController@categories');
|
||||
$router->post('/admin/categories/add', 'AdminController@addCategory');
|
||||
@ -97,4 +109,4 @@ $router->get('/admin/withdrawals', 'AdminController@withdrawals');
|
||||
$router->get('/admin/withdrawals/approve/:id', 'AdminController@approveWithdrawal');
|
||||
$router->get('/admin/withdrawals/reject/:id', 'AdminController@rejectWithdrawal');
|
||||
|
||||
$router->dispatch();
|
||||
$router->dispatch();
|
||||
@ -191,6 +191,9 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3 mb-1" href="/admin/apks/mass-upload"><i class="fas fa-cloud-upload-alt me-1"></i> Mass Upload</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3 mb-1" href="/admin/posts"><i class="fas fa-newspaper me-1"></i> Blog</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3 mb-1" href="/admin/categories"><i class="fas fa-list me-1"></i> <?php echo __('categories'); ?></a>
|
||||
</li>
|
||||
@ -250,4 +253,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
<main class="min-vh-100">
|
||||
|
||||
52
views/admin/posts/form.php
Normal file
52
views/admin/posts/form.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php include dirname(__DIR__) . '/header.php'; ?>
|
||||
|
||||
<div class="container-fluid py-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 class="h3 mb-0 text-gray-800"><?php echo $action === 'add' ? 'Add New Post' : 'Edit Post'; ?></h2>
|
||||
<a href="/admin/posts" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left me-1"></i> Back to List
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-body">
|
||||
<form action="/admin/posts/<?php echo $action === 'add' ? 'add' : 'edit/' . $post['id']; ?>" method="POST" enctype="multipart/form-data">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Title</label>
|
||||
<input type="text" name="title" class="form-control" value="<?php echo htmlspecialchars($post['title'] ?? ''); ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Featured Image</label>
|
||||
<input type="file" name="image_file" class="form-control" accept="image/*">
|
||||
<?php if (isset($post['image_path']) && $post['image_path']): ?>
|
||||
<div class="mt-2">
|
||||
<img src="/<?php echo $post['image_path']; ?>" alt="" class="img-thumbnail" style="max-height: 150px;">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Content</label>
|
||||
<textarea name="content" class="form-control" rows="15" required><?php echo htmlspecialchars($post['content'] ?? ''); ?></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Status</label>
|
||||
<select name="status" class="form-control">
|
||||
<option value="published" <?php echo (isset($post['status']) && $post['status'] === 'published') ? 'selected' : ''; ?>>Published</option>
|
||||
<option value="draft" <?php echo (isset($post['status']) && $post['status'] === 'draft') ? 'selected' : ''; ?>>Draft</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
<button type="submit" class="btn btn-primary btn-lg">
|
||||
<i class="fas fa-save me-1"></i> <?php echo $action === 'add' ? 'Create Post' : 'Update Post'; ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include dirname(__DIR__) . '/footer.php'; ?>
|
||||
68
views/admin/posts/index.php
Normal file
68
views/admin/posts/index.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php include dirname(__DIR__) . '/header.php'; ?>
|
||||
|
||||
<div class="container-fluid py-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 class="h3 mb-0 text-gray-800">Blog Posts</h2>
|
||||
<a href="/admin/posts/add" class="btn btn-primary">
|
||||
<i class="fas fa-plus me-1"></i> Add New Post
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered" width="100%" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Image</th>
|
||||
<th>Title</th>
|
||||
<th>Status</th>
|
||||
<th>Date</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($posts as $post): ?>
|
||||
<tr>
|
||||
<td style="width: 80px;">
|
||||
<?php if ($post['image_path']): ?>
|
||||
<img src="/<?php echo $post['image_path']; ?>" alt="" class="img-thumbnail" style="height: 50px; width: 50px; object-fit: cover;">
|
||||
<?php else: ?>
|
||||
<div class="bg-light d-flex align-items-center justify-content-center img-thumbnail" style="height: 50px; width: 50px;">
|
||||
<i class="fas fa-image text-muted"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<div class="fw-bold"><?php echo htmlspecialchars($post['title']); ?></div>
|
||||
<small class="text-muted"><?php echo $post['slug']; ?></small>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-<?php echo $post['status'] === 'published' ? 'success' : 'warning'; ?>">
|
||||
<?php echo ucfirst($post['status']); ?>
|
||||
</span>
|
||||
</td>
|
||||
<td><?php echo date('M d, Y', strtotime($post['created_at'])); ?></td>
|
||||
<td>
|
||||
<a href="/admin/posts/edit/<?php echo $post['id']; ?>" class="btn btn-sm btn-info">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<a href="/admin/posts/delete/<?php echo $post['id']; ?>" class="btn btn-sm btn-danger" onclick="return confirm('Are you sure?')">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($posts)): ?>
|
||||
<tr>
|
||||
<td colspan="5" class="text-center py-4 text-muted">No posts found.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include dirname(__DIR__) . '/footer.php'; ?>
|
||||
@ -35,6 +35,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
<h5 class="fw-bold mb-3"><i class="fas fa-share-alt me-2"></i>Social Media Settings</h5>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">Facebook URL</label>
|
||||
<input type="url" name="facebook_url" class="form-control" value="<?php echo htmlspecialchars($settings['facebook_url'] ?? ''); ?>" placeholder="https://facebook.com/yourpage">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">Twitter (X) URL</label>
|
||||
<input type="url" name="twitter_url" class="form-control" value="<?php echo htmlspecialchars($settings['twitter_url'] ?? ''); ?>" placeholder="https://twitter.com/yourprofile">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">Instagram URL</label>
|
||||
<input type="url" name="instagram_url" class="form-control" value="<?php echo htmlspecialchars($settings['instagram_url'] ?? ''); ?>" placeholder="https://instagram.com/yourprofile">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">GitHub URL</label>
|
||||
<input type="url" name="github_url" class="form-control" value="<?php echo htmlspecialchars($settings['github_url'] ?? ''); ?>" placeholder="https://github.com/yourprofile">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
<h5 class="fw-bold mb-3"><i class="fas fa-search me-2"></i>SEO Settings</h5>
|
||||
|
||||
@ -93,4 +118,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
<?php include 'footer.php'; ?>
|
||||
|
||||
67
views/blog/detail.php
Normal file
67
views/blog/detail.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php include dirname(__DIR__) . '/header.php'; ?>
|
||||
|
||||
<article class="py-5">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<nav aria-label="breadcrumb" class="mb-4">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="/">Home</a></li>
|
||||
<li class="breadcrumb-item"><a href="/blog">Blog</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page"><?php echo htmlspecialchars($post['title']); ?></li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<header class="mb-5 text-center">
|
||||
<h1 class="display-4 fw-bold mb-3"><?php echo htmlspecialchars($post['title']); ?></h1>
|
||||
<div class="text-muted d-flex align-items-center justify-content-center">
|
||||
<span class="me-3"><i class="far fa-calendar-alt me-1"></i> <?php echo date('F d, Y', strtotime($post['created_at'])); ?></span>
|
||||
<span><i class="far fa-user me-1"></i> Admin</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<?php if ($post['image_path']): ?>
|
||||
<div class="mb-5 shadow-sm rounded-4 overflow-hidden">
|
||||
<img src="/<?php echo $post['image_path']; ?>" class="img-fluid w-100" alt="<?php echo htmlspecialchars($post['title']); ?>">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="blog-content fs-5 lh-lg text-secondary">
|
||||
<?php echo nl2br($post['content']); ?>
|
||||
</div>
|
||||
|
||||
<hr class="my-5">
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center bg-light p-4 rounded-4">
|
||||
<div class="fw-bold">Share this article:</div>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="https://facebook.com/sharer/sharer.php?u=<?php echo urlencode("https://" . $_SERVER['HTTP_HOST'] . "/blog/" . $post['slug']); ?>" target="_blank" class="btn btn-outline-primary btn-sm rounded-circle">
|
||||
<i class="fab fa-facebook-f"></i>
|
||||
</a>
|
||||
<a href="https://twitter.com/intent/tweet?url=<?php echo urlencode("https://" . $_SERVER['HTTP_HOST'] . "/blog/" . $post['slug']); ?>&text=<?php echo urlencode($post['title']); ?>" target="_blank" class="btn btn-outline-info btn-sm rounded-circle">
|
||||
<i class="fab fa-twitter"></i>
|
||||
</a>
|
||||
<a href="https://api.whatsapp.com/send?text=<?php echo urlencode($post['title'] . " - https://" . $_SERVER['HTTP_HOST'] . "/blog/" . $post['slug']); ?>" target="_blank" class="btn btn-outline-success btn-sm rounded-circle">
|
||||
<i class="fab fa-whatsapp"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<style>
|
||||
.blog-content {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
.blog-content h2, .blog-content h3 {
|
||||
color: #333;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
||||
<?php include dirname(__DIR__) . '/footer.php'; ?>
|
||||
56
views/blog/index.php
Normal file
56
views/blog/index.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php include dirname(__DIR__) . '/header.php'; ?>
|
||||
|
||||
<section class="py-5 bg-light">
|
||||
<div class="container">
|
||||
<div class="row mb-5">
|
||||
<div class="col-lg-6 mx-auto text-center">
|
||||
<h1 class="display-4 fw-bold mb-3">Blog & Articles</h1>
|
||||
<p class="lead text-muted">Dapatkan informasi terbaru seputar aplikasi, game, dan tips teknologi di sini.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
<?php foreach ($posts as $post): ?>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<article class="card h-100 border-0 shadow-sm overflow-hidden hover-lift transition-all">
|
||||
<?php if ($post['image_path']): ?>
|
||||
<img src="/<?php echo $post['image_path']; ?>" class="card-img-top" alt="<?php echo htmlspecialchars($post['title']); ?>" style="height: 200px; object-fit: cover;">
|
||||
<?php else: ?>
|
||||
<div class="bg-primary bg-opacity-10 d-flex align-items-center justify-content-center" style="height: 200px;">
|
||||
<i class="fas fa-newspaper fa-3x text-primary opacity-25"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="card-body p-4">
|
||||
<div class="text-muted small mb-2">
|
||||
<i class="far fa-calendar-alt me-1"></i> <?php echo date('M d, Y', strtotime($post['created_at'])); ?>
|
||||
</div>
|
||||
<h2 class="h5 card-title fw-bold mb-3">
|
||||
<a href="/blog/<?php echo $post['slug']; ?>" class="text-dark text-decoration-none stretched-link">
|
||||
<?php echo htmlspecialchars($post['title']); ?>
|
||||
</a>
|
||||
</h2>
|
||||
<p class="card-text text-muted mb-0">
|
||||
<?php
|
||||
$excerpt = strip_tags($post['content']);
|
||||
echo mb_strimwidth($excerpt, 0, 120, '...');
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (empty($posts)): ?>
|
||||
<div class="col-12 text-center py-5">
|
||||
<div class="mb-3">
|
||||
<i class="fas fa-folder-open fa-3x text-muted opacity-25"></i>
|
||||
</div>
|
||||
<h3 class="text-muted">Belum ada artikel yang diterbitkan.</h3>
|
||||
<a href="/" class="btn btn-primary mt-3">Kembali ke Beranda</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include dirname(__DIR__) . '/footer.php'; ?>
|
||||
@ -26,6 +26,7 @@
|
||||
<div class="col-6 col-lg-2">
|
||||
<h6 class="fw-bold mb-3"><?php echo __('resources'); ?></h6>
|
||||
<ul class="list-unstyled">
|
||||
<li><a href="/blog" class="text-muted text-decoration-none py-1 d-block small">Blog</a></li>
|
||||
<li><a href="/help-center" class="text-muted text-decoration-none py-1 d-block small"><?php echo __('support_center'); ?></a></li>
|
||||
<li><a href="/terms-of-service" class="text-muted text-decoration-none py-1 d-block small"><?php echo __('terms_of_service'); ?></a></li>
|
||||
<li><a href="/privacy-policy" class="text-muted text-decoration-none py-1 d-block small"><?php echo __('privacy_policy'); ?></a></li>
|
||||
@ -47,10 +48,18 @@
|
||||
</div>
|
||||
<div class="col-md-6 text-center text-md-end mt-3 mt-md-0">
|
||||
<div class="d-flex justify-content-center justify-content-md-end gap-3">
|
||||
<a href="#" class="text-muted"><i class="bi bi-facebook"></i></a>
|
||||
<a href="#" class="text-muted"><i class="bi bi-twitter-x"></i></a>
|
||||
<a href="#" class="text-muted"><i class="bi bi-instagram"></i></a>
|
||||
<a href="#" class="text-muted"><i class="bi bi-github"></i></a>
|
||||
<?php if ($fb = get_setting('facebook_url')): ?>
|
||||
<a href="<?php echo $fb; ?>" target="_blank" class="text-muted"><i class="bi bi-facebook"></i></a>
|
||||
<?php endif; ?>
|
||||
<?php if ($tw = get_setting('twitter_url')): ?>
|
||||
<a href="<?php echo $tw; ?>" target="_blank" class="text-muted"><i class="bi bi-twitter-x"></i></a>
|
||||
<?php endif; ?>
|
||||
<?php if ($ig = get_setting('instagram_url')): ?>
|
||||
<a href="<?php echo $ig; ?>" target="_blank" class="text-muted"><i class="bi bi-instagram"></i></a>
|
||||
<?php endif; ?>
|
||||
<?php if ($gh = get_setting('github_url')): ?>
|
||||
<a href="<?php echo $gh; ?>" target="_blank" class="text-muted"><i class="bi bi-github"></i></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -60,4 +69,4 @@
|
||||
<script src="/assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||
<?php echo get_setting('body_js'); ?>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@ -98,6 +98,10 @@ $currentLang = \App\Services\LanguageService::getLang();
|
||||
<a class="nav-link px-3" href="/"><?php echo __('home'); ?></a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3" href="/blog">Blog</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item dropdown px-3">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<?php echo __('categories'); ?>
|
||||
@ -171,4 +175,4 @@ $currentLang = \App\Services\LanguageService::getLang();
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="min-vh-100">
|
||||
<main class="min-vh-100">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user