New Vesion Aslam
This commit is contained in:
parent
4f61082b27
commit
7cb17c6136
@ -90,7 +90,7 @@ class AdminController extends Controller {
|
||||
$status = $_POST['status'] ?? 'published';
|
||||
$is_vip = isset($_POST['is_vip']) ? 1 : 0;
|
||||
|
||||
$icon_path = $this->handleUpload('icon_file');
|
||||
$icon_path = $this->handleUpload('icon_file', true);
|
||||
|
||||
$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)");
|
||||
@ -121,7 +121,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') ?: $apk['icon_path'];
|
||||
$icon_path = $this->handleUpload('icon_file', true) ?: $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']]);
|
||||
@ -141,7 +141,7 @@ class AdminController extends Controller {
|
||||
echo json_encode(['success' => true]);
|
||||
}
|
||||
|
||||
private function handleUpload($field) {
|
||||
private function handleUpload($field, $compress = false) {
|
||||
if (!isset($_FILES[$field]) || $_FILES[$field]['error'] !== UPLOAD_ERR_OK) {
|
||||
return null;
|
||||
}
|
||||
@ -155,13 +155,61 @@ class AdminController extends Controller {
|
||||
$fileName = uniqid() . '.' . $ext;
|
||||
$targetPath = $uploadDir . $fileName;
|
||||
|
||||
if (move_uploaded_file($_FILES[$field]['tmp_name'], $targetPath)) {
|
||||
return $targetPath;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Settings Management
|
||||
public function settingsForm() {
|
||||
$this->checkAuth();
|
||||
$settings = [
|
||||
'site_name' => get_setting('site_name'),
|
||||
'site_icon' => get_setting('site_icon'),
|
||||
'site_favicon' => get_setting('site_favicon'),
|
||||
'meta_description' => get_setting('meta_description'),
|
||||
'meta_keywords' => get_setting('meta_keywords'),
|
||||
'head_js' => get_setting('head_js'),
|
||||
'body_js' => get_setting('body_js'),
|
||||
];
|
||||
$this->view('admin/settings', ['settings' => $settings]);
|
||||
}
|
||||
|
||||
public function saveSettings() {
|
||||
$this->checkAuth();
|
||||
$db = db_pdo();
|
||||
|
||||
$fields = ['site_name', 'meta_description', 'meta_keywords', 'head_js', 'body_js'];
|
||||
foreach ($fields as $field) {
|
||||
if (isset($_POST[$field])) {
|
||||
$stmt = $db->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = ?");
|
||||
$stmt->execute([$_POST[$field], $field]);
|
||||
}
|
||||
}
|
||||
|
||||
$site_icon = $this->handleUpload('site_icon_file');
|
||||
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');
|
||||
if ($site_favicon) {
|
||||
$stmt = $db->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = 'site_favicon'");
|
||||
$stmt->execute([$site_favicon]);
|
||||
}
|
||||
|
||||
$this->redirect('/admin/settings');
|
||||
}
|
||||
|
||||
// Category Management
|
||||
public function categories() {
|
||||
$this->checkAuth();
|
||||
@ -207,7 +255,6 @@ class AdminController extends Controller {
|
||||
public function rejectWithdrawal($params) {
|
||||
$this->checkAuth();
|
||||
$db = db_pdo();
|
||||
// Refund balance if rejected? The user didn't specify, but let's do it for fairness
|
||||
$wd = $db->query("SELECT * FROM withdrawals WHERE id = " . $params['id'])->fetch();
|
||||
if ($wd && $wd['status'] === 'pending') {
|
||||
$stmt = $db->prepare("UPDATE users SET balance = balance + ? WHERE id = ?");
|
||||
|
||||
@ -17,7 +17,8 @@ class AuthController extends Controller {
|
||||
if (isset($_SESSION['user_id'])) {
|
||||
$this->redirect('/profile');
|
||||
}
|
||||
$ref = $_GET['ref'] ?? '';
|
||||
// Check GET first, then Session
|
||||
$ref = $_GET['ref'] ?? ($_SESSION['global_ref'] ?? '');
|
||||
$this->view('auth/register', ['ref' => $ref]);
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,11 @@ class HomeController extends Controller {
|
||||
$db = db_pdo();
|
||||
$category = $_GET['category'] ?? null;
|
||||
|
||||
// Store global referral code if present
|
||||
if (isset($_GET['ref'])) {
|
||||
$_SESSION['global_ref'] = $_GET['ref'];
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM apks WHERE status = 'published'";
|
||||
$params = [];
|
||||
|
||||
@ -32,7 +37,7 @@ class HomeController extends Controller {
|
||||
|
||||
return $this->view('home', [
|
||||
'apks' => $apks,
|
||||
'title' => 'ApkNusa - Professional APK Download Portal'
|
||||
'title' => get_setting('site_name', 'ApkNusa') . ' - Professional APK Download Portal'
|
||||
]);
|
||||
}
|
||||
|
||||
@ -47,12 +52,17 @@ class HomeController extends Controller {
|
||||
$this->redirect('/');
|
||||
}
|
||||
|
||||
// Store referral code if present
|
||||
// Store referral code if present specifically for this APK
|
||||
if (isset($_GET['ref'])) {
|
||||
$_SESSION['ref_download_' . $apk['id']] = $_GET['ref'];
|
||||
}
|
||||
|
||||
$this->view('apk_detail', ['apk' => $apk]);
|
||||
$this->view('apk_detail', [
|
||||
'apk' => $apk,
|
||||
'title' => 'Download ' . $apk['title'] . ' ' . $apk['version'] . ' - ' . get_setting('site_name', 'ApkNusa'),
|
||||
'meta_description' => 'Download ' . $apk['title'] . ' ' . $apk['version'] . ' APK for free. ' . substr(strip_tags($apk['description']), 0, 150) . '...',
|
||||
'meta_keywords' => $apk['title'] . ', ' . $apk['title'] . ' apk, download ' . $apk['title']
|
||||
]);
|
||||
}
|
||||
|
||||
public function download($params) {
|
||||
@ -67,7 +77,9 @@ class HomeController extends Controller {
|
||||
}
|
||||
|
||||
// Check for referral earnings
|
||||
$ref_code = $_SESSION['ref_download_' . $apk['id']] ?? null;
|
||||
// Try specific APK referral first, then global referral
|
||||
$ref_code = $_SESSION['ref_download_' . $apk['id']] ?? ($_SESSION['global_ref'] ?? null);
|
||||
|
||||
if ($ref_code) {
|
||||
$stmt = $db->prepare("SELECT id FROM users WHERE referral_code = ?");
|
||||
$stmt->execute([$ref_code]);
|
||||
@ -91,7 +103,8 @@ class HomeController extends Controller {
|
||||
$stmt->execute([$referrer_id, $apk['id'], $ip]);
|
||||
}
|
||||
}
|
||||
// Clear session after processing
|
||||
// Clear session specific to this APK, but maybe keep global_ref?
|
||||
// The user might download other APKs too.
|
||||
unset($_SESSION['ref_download_' . $apk['id']]);
|
||||
}
|
||||
|
||||
@ -102,4 +115,4 @@ class HomeController extends Controller {
|
||||
// Redirect to actual file
|
||||
$this->redirect($apk['download_url']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
52
app/Controllers/SitemapController.php
Normal file
52
app/Controllers/SitemapController.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Core\Controller;
|
||||
use App\Services\ApkService;
|
||||
|
||||
class SitemapController extends Controller {
|
||||
|
||||
public function index() {
|
||||
$apkService = new ApkService();
|
||||
$apks = $apkService->getAllApks();
|
||||
|
||||
$db = db_pdo();
|
||||
$categories = $db->query("SELECT * FROM categories")->fetchAll();
|
||||
|
||||
header("Content-Type: application/xml; charset=utf-8");
|
||||
|
||||
$baseUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]";
|
||||
|
||||
echo '<?xml version="1.0" encoding="UTF-8"?>';
|
||||
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
|
||||
|
||||
// Home
|
||||
echo '<url>';
|
||||
echo '<loc>' . $baseUrl . '/</loc>';
|
||||
echo '<priority>1.0</priority>';
|
||||
echo '<changefreq>daily</changefreq>';
|
||||
echo '</url>';
|
||||
|
||||
// APKs
|
||||
foreach ($apks as $apk) {
|
||||
echo '<url>';
|
||||
echo '<loc>' . $baseUrl . '/apk/' . htmlspecialchars($apk['slug']) . '</loc>';
|
||||
echo '<lastmod>' . date('Y-m-d', strtotime($apk['created_at'] ?? 'now')) . '</lastmod>';
|
||||
echo '<priority>0.8</priority>';
|
||||
echo '<changefreq>weekly</changefreq>';
|
||||
echo '</url>';
|
||||
}
|
||||
|
||||
// Categories (if you have category pages, assuming /category/slug)
|
||||
foreach ($categories as $category) {
|
||||
echo '<url>';
|
||||
echo '<loc>' . $baseUrl . '/category/' . htmlspecialchars($category['slug']) . '</loc>';
|
||||
echo '<priority>0.6</priority>';
|
||||
echo '<changefreq>weekly</changefreq>';
|
||||
echo '</url>';
|
||||
}
|
||||
|
||||
echo '</urlset>';
|
||||
}
|
||||
}
|
||||
@ -2,15 +2,49 @@
|
||||
|
||||
use App\Services\LanguageService;
|
||||
|
||||
function lang($key) {
|
||||
return LanguageService::translate($key);
|
||||
}
|
||||
|
||||
function asset($path) {
|
||||
return '/' . ltrim($path, '/');
|
||||
}
|
||||
|
||||
function db_pdo() {
|
||||
require_once __DIR__ . '/../../db/config.php';
|
||||
return db();
|
||||
}
|
||||
|
||||
function view($view, $data = []) {
|
||||
extract($data);
|
||||
$viewPath = __DIR__ . '/../../views/' . $view . '.php';
|
||||
if (file_exists($viewPath)) {
|
||||
require $viewPath;
|
||||
} else {
|
||||
echo "View $view not found";
|
||||
}
|
||||
}
|
||||
|
||||
function redirect($path) {
|
||||
header("Location: $path");
|
||||
exit;
|
||||
}
|
||||
|
||||
function __($key, $default = null) {
|
||||
return LanguageService::translate($key, $default);
|
||||
}
|
||||
|
||||
function get_setting($key, $default = '') {
|
||||
$db = db();
|
||||
$stmt = $db->prepare("SELECT setting_value FROM settings WHERE setting_key = ?");
|
||||
$stmt->execute([$key]);
|
||||
$result = $stmt->fetch();
|
||||
return $result ? $result['setting_value'] : $default;
|
||||
}
|
||||
|
||||
function compress_image($source, $destination, $quality) {
|
||||
$info = getimagesize($source);
|
||||
if ($info['mime'] == 'image/jpeg') {
|
||||
$image = imagecreatefromjpeg($source);
|
||||
} elseif ($info['mime'] == 'image/gif') {
|
||||
$image = imagecreatefromgif($source);
|
||||
} elseif ($info['mime'] == 'image/png') {
|
||||
$image = imagecreatefrompng($source);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
imagejpeg($image, $destination, $quality);
|
||||
return $destination;
|
||||
}
|
||||
@ -3,8 +3,43 @@
|
||||
namespace App\Services;
|
||||
|
||||
class LanguageService {
|
||||
public static function translate($key) {
|
||||
// Mock translation
|
||||
return $key;
|
||||
private static $translations = [];
|
||||
private static $lang = 'id';
|
||||
|
||||
public static function init() {
|
||||
if (isset($_SESSION['lang'])) {
|
||||
self::$lang = $_SESSION['lang'];
|
||||
} elseif (isset($_COOKIE['lang'])) {
|
||||
self::$lang = $_COOKIE['lang'];
|
||||
}
|
||||
|
||||
$langFile = __DIR__ . '/../../lang/' . self::$lang . '.php';
|
||||
if (file_exists($langFile)) {
|
||||
self::$translations = require $langFile;
|
||||
} else {
|
||||
// Default to English if the translation file doesn't exist
|
||||
self::$lang = 'en';
|
||||
$langFile = __DIR__ . '/../../lang/' . self::$lang . '.php';
|
||||
if (file_exists($langFile)) {
|
||||
self::$translations = require $langFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function translate($key, $default = null) {
|
||||
if (empty(self::$translations)) {
|
||||
self::init();
|
||||
}
|
||||
return self::$translations[$key] ?? ($default ?? $key);
|
||||
}
|
||||
|
||||
public static function setLang($lang) {
|
||||
self::$lang = $lang;
|
||||
$_SESSION['lang'] = $lang;
|
||||
setcookie('lang', $lang, time() + (86400 * 30), "/");
|
||||
}
|
||||
|
||||
public static function getLang() {
|
||||
return self::$lang;
|
||||
}
|
||||
}
|
||||
5
db/migrations/20260224_add_seo_and_ads_settings.sql
Normal file
5
db/migrations/20260224_add_seo_and_ads_settings.sql
Normal file
@ -0,0 +1,5 @@
|
||||
INSERT IGNORE INTO settings (setting_key, setting_value) VALUES
|
||||
('meta_description', 'Download the latest APKs for free.'),
|
||||
('meta_keywords', 'apk, download, android, games, apps'),
|
||||
('head_js', ''),
|
||||
('body_js', '');
|
||||
38
index.php
38
index.php
@ -1,16 +1,46 @@
|
||||
<?php
|
||||
|
||||
require_once 'app/Core/Router.php';
|
||||
require_once 'app/Core/Controller.php';
|
||||
// Autoloader
|
||||
spl_autoload_register(function ($class) {
|
||||
$prefix = 'App\';
|
||||
$base_dir = __DIR__ . '/app/';
|
||||
|
||||
$len = strlen($prefix);
|
||||
if (strncmp($prefix, $class, $len) !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$relative_class = substr($class, $len);
|
||||
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
|
||||
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
}
|
||||
});
|
||||
|
||||
require_once 'app/Helpers/functions.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
session_start();
|
||||
|
||||
// Initialize Language Service
|
||||
\App\Services\LanguageService::init();
|
||||
|
||||
use App\Core\Router;
|
||||
|
||||
$router = new Router();
|
||||
|
||||
// Sitemap
|
||||
$router->get('/sitemap.xml', 'SitemapController@index');
|
||||
|
||||
// Language Switch
|
||||
$router->get('/lang/:code', function($params) {
|
||||
$code = $params['code'];
|
||||
\App\Services\LanguageService::setLang($code);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/'));
|
||||
exit;
|
||||
});
|
||||
|
||||
// Home & APKs
|
||||
$router->get('/', 'HomeController@index');
|
||||
$router->get('/apk/:slug', 'HomeController@apkDetail');
|
||||
@ -33,6 +63,10 @@ $router->get('/admin/logout', 'AdminController@logout');
|
||||
// Admin Dashboard
|
||||
$router->get('/admin/dashboard', 'AdminController@dashboard');
|
||||
|
||||
// Admin Settings
|
||||
$router->get('/admin/settings', 'AdminController@settingsForm');
|
||||
$router->post('/admin/settings', 'AdminController@saveSettings');
|
||||
|
||||
// Admin APKs
|
||||
$router->get('/admin/apks', 'AdminController@apks');
|
||||
$router->get('/admin/apks/add', 'AdminController@addApkForm');
|
||||
|
||||
174
install.php
Normal file
174
install.php
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
if (file_exists('db/config.php') && !isset($_GET['force'])) {
|
||||
// Check if DB is already connected
|
||||
require_once 'db/config.php';
|
||||
try {
|
||||
db();
|
||||
die("Application already installed. Delete db/config.php if you want to reinstall.");
|
||||
} catch (Exception $e) {
|
||||
// Continue to installation
|
||||
}
|
||||
}
|
||||
|
||||
$step = $_GET['step'] ?? 1;
|
||||
$error = '';
|
||||
$success = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if ($step == 2) {
|
||||
$host = $_POST['db_host'];
|
||||
$name = $_POST['db_name'];
|
||||
$user = $_POST['db_user'];
|
||||
$pass = $_POST['db_pass'];
|
||||
|
||||
try {
|
||||
$pdo = new PDO("mysql:host=$host;charset=utf8mb4", $user, $pass, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||
]);
|
||||
$pdo->exec("CREATE DATABASE IF NOT EXISTS `$name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||||
$pdo->exec("USE `$name`");
|
||||
|
||||
// Save config
|
||||
$configContent = "<?php\ndefine('DB_HOST', '$host');\ndefine('DB_NAME', '$name');\ndefine('DB_USER', '$user');\ndefine('DB_PASS', '$pass');\n\nfunction db() {\n static \$pdo;\n if (!\$pdo) {\n \$pdo = new PDO('mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=utf8mb4', DB_USER, DB_PASS, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
]);\n }\n return \$pdo;
|
||||
}\n";
|
||||
file_put_contents('db/config.php', $configContent);
|
||||
|
||||
$_SESSION['install_pdo'] = ['host' => $host, 'name' => $name, 'user' => $user, 'pass' => $pass];
|
||||
header("Location: install.php?step=3");
|
||||
exit;
|
||||
} catch (PDOException $e) {
|
||||
$error = "Database Error: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
if ($step == 3) {
|
||||
require_once 'db/config.php';
|
||||
$db = db();
|
||||
|
||||
// Import Schema
|
||||
$schemaFile = 'full_schema.sql';
|
||||
if (file_exists($schemaFile)) {
|
||||
$sql = file_get_contents($schemaFile);
|
||||
$db->exec($sql);
|
||||
} else {
|
||||
// Basic tables if full_schema.sql is missing
|
||||
$db->exec("CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) UNIQUE, password VARCHAR(255), balance DECIMAL(10,2) DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
|
||||
$db->exec("CREATE TABLE IF NOT EXISTS settings (id INT AUTO_INCREMENT PRIMARY KEY, setting_key VARCHAR(255) UNIQUE, setting_value TEXT)");
|
||||
$db->exec("INSERT IGNORE INTO settings (setting_key, setting_value) VALUES ('site_name', 'My APK Store'), ('site_icon', ''), ('site_favicon', '')");
|
||||
}
|
||||
|
||||
// Create Admin
|
||||
$admin_user = $_POST['admin_user'];
|
||||
$admin_pass = password_hash($_POST['admin_pass'], PASSWORD_DEFAULT);
|
||||
|
||||
$stmt = $db->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
|
||||
$stmt->execute([$admin_user, $admin_pass]);
|
||||
|
||||
$success = "Installation complete!";
|
||||
$step = 4;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Installer</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body { background-color: #f4f7f6; }
|
||||
.install-box { max-width: 500px; margin: 100px auto; background: #fff; padding: 40px; border-radius: 10px; box-shadow: 0 5px 15px rgba(0,0,0,0.1); }
|
||||
.step-indicator { display: flex; justify-content: space-between; margin-bottom: 30px; }
|
||||
.step { width: 30px; height: 30px; border-radius: 50%; background: #ddd; text-align: center; line-height: 30px; color: #fff; }
|
||||
.step.active { background: #0d6efd; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="install-box">
|
||||
<h3 class="text-center mb-4">Web Installer</h3>
|
||||
|
||||
<div class="step-indicator">
|
||||
<div class="step <?php echo $step >= 1 ? 'active' : ''; ">1</div>
|
||||
<div class="step <?php echo $step >= 2 ? 'active' : ''; ">2</div>
|
||||
<div class="step <?php echo $step >= 3 ? 'active' : ''; ">3</div>
|
||||
<div class="step <?php echo $step >= 4 ? 'active' : ''; ">4</div>
|
||||
</div>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger"><?php echo $error; ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($step == 1): ?>
|
||||
<h5>Welcome</h5>
|
||||
<p>This wizard will help you install the application on your server.</p>
|
||||
<div class="d-grid">
|
||||
<a href="?step=2" class="btn btn-primary">Start Installation</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($step == 2): ?>
|
||||
<h5>Database Configuration</h5>
|
||||
<form method="POST">
|
||||
<div class="mb-3">
|
||||
<label>DB Host</label>
|
||||
<input type="text" name="db_host" class="form-control" value="localhost" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label>DB Name</label>
|
||||
<input type="text" name="db_name" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label>DB User</label>
|
||||
<input type="text" name="db_user" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label>DB Password</label>
|
||||
<input type="password" name="db_pass" class="form-control">
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary">Connect & Continue</button>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($step == 3): ?>
|
||||
<h5>Admin Account</h5>
|
||||
<form method="POST">
|
||||
<div class="mb-3">
|
||||
<label>Admin Username</label>
|
||||
<input type="text" name="admin_user" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label>Admin Password</label>
|
||||
<input type="password" name="admin_pass" class="form-control" required>
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary">Finish Installation</button>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($step == 4): ?>
|
||||
<div class="text-center">
|
||||
<h1 class="text-success"><i class="fas fa-check-circle"></i></h1>
|
||||
<h5>Installation Successful!</h5>
|
||||
<p>You can now log in to your admin panel.</p>
|
||||
<div class="alert alert-warning">
|
||||
<strong>Important:</strong> Please delete <code>install.php</code> file from your server.
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<a href="/admin/login" class="btn btn-primary">Go to Admin Panel</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
35
lang/en.php
Normal file
35
lang/en.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
return [
|
||||
'home' => 'Home',
|
||||
'search' => 'Search...',
|
||||
'login' => 'Login',
|
||||
'register' => 'Register',
|
||||
'logout' => 'Logout',
|
||||
'profile' => 'Profile',
|
||||
'admin' => 'Admin',
|
||||
'download' => 'Download',
|
||||
'share' => 'Share',
|
||||
'categories' => 'Categories',
|
||||
'all_categories' => 'All Categories',
|
||||
'latest_apks' => 'Latest APKs',
|
||||
'featured_apks' => 'Featured APKs',
|
||||
'download_now' => 'Download Now',
|
||||
'share_link' => 'Share Link',
|
||||
'balance' => 'Balance',
|
||||
'referral_link' => 'Referral Link',
|
||||
'withdraw' => 'Withdraw',
|
||||
'withdrawal_history' => 'Withdrawal History',
|
||||
'settings' => 'Settings',
|
||||
'site_name' => 'Site Name',
|
||||
'site_icon' => 'Site Icon',
|
||||
'site_favicon' => 'Site Favicon',
|
||||
'save_settings' => 'Save Settings',
|
||||
'select_language' => 'Select Language',
|
||||
'language_indonesia' => 'Indonesian',
|
||||
'language_english' => 'English',
|
||||
'admin_dashboard' => 'Admin Dashboard',
|
||||
'manage_apks' => 'Manage APKs',
|
||||
'manage_categories' => 'Manage Categories',
|
||||
'manage_withdrawals' => 'Manage Withdrawals',
|
||||
'general_settings' => 'General Settings',
|
||||
];
|
||||
35
lang/id.php
Normal file
35
lang/id.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
return [
|
||||
'home' => 'Beranda',
|
||||
'search' => 'Cari...',
|
||||
'login' => 'Masuk',
|
||||
'register' => 'Daftar',
|
||||
'logout' => 'Keluar',
|
||||
'profile' => 'Profil',
|
||||
'admin' => 'Admin',
|
||||
'download' => 'Unduh',
|
||||
'share' => 'Bagikan',
|
||||
'categories' => 'Kategori',
|
||||
'all_categories' => 'Semua Kategori',
|
||||
'latest_apks' => 'APK Terbaru',
|
||||
'featured_apks' => 'APK Unggulan',
|
||||
'download_now' => 'Unduh Sekarang',
|
||||
'share_link' => 'Bagikan Link',
|
||||
'balance' => 'Saldo',
|
||||
'referral_link' => 'Link Referral',
|
||||
'withdraw' => 'Tarik Saldo',
|
||||
'withdrawal_history' => 'Riwayat Penarikan',
|
||||
'settings' => 'Pengaturan',
|
||||
'site_name' => 'Nama Website',
|
||||
'site_icon' => 'Ikon Website',
|
||||
'site_favicon' => 'Favicon Website',
|
||||
'save_settings' => 'Simpan Pengaturan',
|
||||
'select_language' => 'Pilih Bahasa',
|
||||
'language_indonesia' => 'Indonesia',
|
||||
'language_english' => 'English',
|
||||
'admin_dashboard' => 'Dashboard Admin',
|
||||
'manage_apks' => 'Kelola APK',
|
||||
'manage_categories' => 'Kelola Kategori',
|
||||
'manage_withdrawals' => 'Kelola Penarikan',
|
||||
'general_settings' => 'Pengaturan Umum',
|
||||
];
|
||||
@ -5,26 +5,26 @@
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg border-0 rounded-4">
|
||||
<div class="card-header bg-white py-3">
|
||||
<h5 class="m-0 fw-bold"><?php echo $action === 'add' ? 'Add New APK' : 'Edit APK: ' . $apk['title']; ?></h5>
|
||||
<h5 class="m-0 fw-bold"><?php echo $action === 'add' ? 'Add New APK' : 'Edit APK: ' . htmlspecialchars($apk['title']); ?></h5>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<form action="<?php echo $action === 'add' ? '/admin/apks/add' : '/admin/apks/edit/' . $apk['id']; ?>" method="POST" enctype="multipart/form-data">
|
||||
<div class="mb-3">
|
||||
<label for="title" class="form-label fw-medium">APK Title</label>
|
||||
<input type="text" class="form-control" id="title" name="title" value="<?php echo $apk['title'] ?? ''; ?>" required>
|
||||
<input type="text" class="form-control" id="title" name="title" value="<?php echo htmlspecialchars($apk['title'] ?? ''); ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="version" class="form-label fw-medium">Version</label>
|
||||
<input type="text" class="form-control" id="version" name="version" value="<?php echo $apk['version'] ?? ''; ?>" required>
|
||||
<input type="text" class="form-control" id="version" name="version" value="<?php echo htmlspecialchars($apk['version'] ?? ''); ?>" required>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="category_id" class="form-label fw-medium">Category</label>
|
||||
<label for="category_id" class="form-label fw-medium"><?php echo __('categories'); ?></label>
|
||||
<select class="form-select" id="category_id" name="category_id">
|
||||
<option value="">Uncategorized</option>
|
||||
<?php foreach ($categories as $cat): ?>
|
||||
<option value="<?php echo $cat['id']; ?>" <?php echo (isset($apk['category_id']) && $apk['category_id'] == $cat['id']) ? 'selected' : ''; ?>><?php echo $cat['name']; ?></option>
|
||||
<option value="<?php echo $cat['id']; ?>" <?php echo (isset($apk['category_id']) && $apk['category_id'] == $cat['id']) ? 'selected' : ''; ?>><?php echo htmlspecialchars($cat['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
@ -32,26 +32,29 @@
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="description" class="form-label fw-medium">Description</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="4" required><?php echo $apk['description'] ?? ''; ?></textarea>
|
||||
<textarea class="form-control" id="description" name="description" rows="4" required><?php echo htmlspecialchars($apk['description'] ?? ''); ?></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-medium">APK Icon</label>
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<?php if (isset($apk['icon_path'])): ?>
|
||||
<img src="/<?php echo $apk['icon_path']; ?>" class="rounded me-3 border" width="60" height="60">
|
||||
<?php if (!empty($apk['icon_path'])): ?>
|
||||
<img src="/<?php echo $apk['icon_path']; ?>" class="rounded me-3 border shadow-sm" width="64" height="64">
|
||||
<?php endif; ?>
|
||||
<input type="file" class="form-control" id="icon_file" name="icon_file" accept="image/*">
|
||||
<div class="flex-grow-1">
|
||||
<input type="file" class="form-control" id="icon_file" name="icon_file" accept="image/*">
|
||||
<div class="form-text text-muted"><i class="fas fa-info-circle me-1"></i> Icons are automatically compressed to optimize speed.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="image_url" class="form-label fw-medium">External Icon URL (Optional)</label>
|
||||
<input type="url" class="form-control" id="image_url" name="image_url" value="<?php echo $apk['image_url'] ?? ''; ?>" placeholder="https://example.com/icon.png">
|
||||
<input type="url" class="form-control" id="image_url" name="image_url" value="<?php echo htmlspecialchars($apk['image_url'] ?? ''); ?>" placeholder="https://example.com/icon.png">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="download_url" class="form-label fw-medium">Download URL</label>
|
||||
<input type="url" class="form-control" id="download_url" name="download_url" value="<?php echo $apk['download_url'] ?? ''; ?>" required>
|
||||
<input type="url" class="form-control" id="download_url" name="download_url" value="<?php echo htmlspecialchars($apk['download_url'] ?? ''); ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
@ -65,14 +68,14 @@
|
||||
<div class="col-md-6 d-flex align-items-center mt-4">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="is_vip" name="is_vip" <?php echo (isset($apk['is_vip']) && $apk['is_vip']) ? 'checked' : ''; ?>>
|
||||
<label class="form-check-label" for="is_vip">VIP APK</label>
|
||||
<label class="form-check-label fw-medium" for="is_vip">VIP APK</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="/admin/apks" class="btn btn-light px-4">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary px-5">Save APK</button>
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end border-top pt-4">
|
||||
<a href="/admin/apks" class="btn btn-light px-4 fw-bold">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary px-5 fw-bold"><i class="fas fa-save me-2"></i>Save APK</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -81,4 +84,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include __DIR__ . '/../footer.php'; ?>
|
||||
<?php include __DIR__ . '/../footer.php'; ?>
|
||||
|
||||
@ -2,25 +2,28 @@
|
||||
|
||||
<div class="container-fluid py-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0 text-gray-800">Dashboard Overview</h1>
|
||||
<h1 class="h3 mb-0 text-gray-800 fw-bold"><?php echo __('admin_dashboard'); ?></h1>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="/admin/apks/add" class="btn btn-primary shadow-sm rounded-pill px-4">
|
||||
<i class="bi bi-plus-lg me-1"></i> Add APK
|
||||
<a href="/admin/apks/add" class="btn btn-primary shadow-sm rounded-pill px-4 fw-bold">
|
||||
<i class="fas fa-plus me-1"></i> Add APK
|
||||
</a>
|
||||
<a href="/admin/settings" class="btn btn-outline-secondary shadow-sm rounded-pill px-4 fw-bold">
|
||||
<i class="fas fa-cog me-1"></i> <?php echo __('settings'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4 mb-4">
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="card border-0 shadow-sm rounded-4 h-100 py-2 border-start border-primary border-4">
|
||||
<div class="card border-0 shadow-sm rounded-4 h-100 py-2 border-start border-primary border-4 bg-white">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col mr-2">
|
||||
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Total APKs</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo number_format($total_apks); ?></div>
|
||||
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1 small fw-bold">Total APKs</div>
|
||||
<div class="h4 mb-0 font-weight-bold text-gray-800"><?php echo number_format($total_apks); ?></div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="bi bi-android2 fs-1 text-gray-300"></i>
|
||||
<i class="fas fa-mobile-alt fa-2x text-gray-300"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -28,15 +31,15 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="card border-0 shadow-sm rounded-4 h-100 py-2 border-start border-success border-4">
|
||||
<div class="card border-0 shadow-sm rounded-4 h-100 py-2 border-start border-success border-4 bg-white">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col mr-2">
|
||||
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">Total Downloads</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo number_format($total_downloads); ?></div>
|
||||
<div class="text-xs font-weight-bold text-success text-uppercase mb-1 small fw-bold">Total Downloads</div>
|
||||
<div class="h4 mb-0 font-weight-bold text-gray-800"><?php echo number_format($total_downloads); ?></div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="bi bi-download fs-1 text-gray-300"></i>
|
||||
<i class="fas fa-download fa-2x text-gray-300"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -44,15 +47,15 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="card border-0 shadow-sm rounded-4 h-100 py-2 border-start border-info border-4">
|
||||
<div class="card border-0 shadow-sm rounded-4 h-100 py-2 border-start border-info border-4 bg-white">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col mr-2">
|
||||
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">Total Users</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo number_format($total_users); ?></div>
|
||||
<div class="text-xs font-weight-bold text-info text-uppercase mb-1 small fw-bold">Total Users</div>
|
||||
<div class="h4 mb-0 font-weight-bold text-gray-800"><?php echo number_format($total_users); ?></div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="bi bi-people fs-1 text-gray-300"></i>
|
||||
<i class="fas fa-users fa-2x text-gray-300"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -60,15 +63,15 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="card border-0 shadow-sm rounded-4 h-100 py-2 border-start border-warning border-4">
|
||||
<div class="card border-0 shadow-sm rounded-4 h-100 py-2 border-start border-warning border-4 bg-white">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col mr-2">
|
||||
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">Pending Withdrawals</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo number_format($pending_withdrawals); ?></div>
|
||||
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1 small fw-bold">Pending Withdrawals</div>
|
||||
<div class="h4 mb-0 font-weight-bold text-gray-800"><?php echo number_format($pending_withdrawals); ?></div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="bi bi-wallet2 fs-1 text-gray-300"></i>
|
||||
<i class="fas fa-wallet fa-2x text-gray-300"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -78,32 +81,32 @@
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow border-0 rounded-4 mb-4">
|
||||
<div class="card-header bg-white py-3">
|
||||
<h6 class="m-0 font-weight-bold text-primary">Recent APKs</h6>
|
||||
<div class="card shadow-sm border-0 rounded-4 mb-4 bg-white">
|
||||
<div class="card-header bg-white py-3 border-bottom border-light">
|
||||
<h6 class="m-0 font-weight-bold text-primary fw-bold">Recent APKs</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Version</th>
|
||||
<th>Downloads</th>
|
||||
<th>Status</th>
|
||||
<th class="border-0">Title</th>
|
||||
<th class="border-0">Version</th>
|
||||
<th class="border-0">Downloads</th>
|
||||
<th class="border-0">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($recent_apks as $apk): ?>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="fw-bold text-gray-800"><?php echo $apk['title']; ?></div>
|
||||
<small class="text-muted"><?php echo $apk['slug']; ?></small>
|
||||
<div class="fw-bold text-dark"><?php echo htmlspecialchars($apk['title']); ?></div>
|
||||
<small class="text-muted"><?php echo htmlspecialchars($apk['slug']); ?></small>
|
||||
</td>
|
||||
<td>v<?php echo $apk['version']; ?></td>
|
||||
<td><?php echo number_format($apk['total_downloads']); ?></td>
|
||||
<td>v<?php echo htmlspecialchars($apk['version']); ?></td>
|
||||
<td><i class="fas fa-download me-1 text-muted"></i> <?php echo number_format($apk['total_downloads']); ?></td>
|
||||
<td>
|
||||
<span class="badge bg-<?php echo $apk['status'] === 'published' ? 'success' : 'secondary'; ?>">
|
||||
<span class="badge rounded-pill bg-<?php echo $apk['status'] === 'published' ? 'success' : 'secondary'; ?> px-3 py-2">
|
||||
<?php echo ucfirst($apk['status']); ?>
|
||||
</span>
|
||||
</td>
|
||||
@ -117,24 +120,27 @@
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4">
|
||||
<div class="card shadow border-0 rounded-4">
|
||||
<div class="card-header bg-white py-3">
|
||||
<h6 class="m-0 font-weight-bold text-primary">Quick Navigation</h6>
|
||||
<div class="card shadow-sm border-0 rounded-4 bg-white">
|
||||
<div class="card-header bg-white py-3 border-bottom border-light">
|
||||
<h6 class="m-0 font-weight-bold text-primary fw-bold">Quick Navigation</h6>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="list-group list-group-flush">
|
||||
<a href="/admin/apks" class="list-group-item list-group-item-action py-3 px-4">
|
||||
<i class="bi bi-android2 me-2 text-primary"></i> Manage APKs
|
||||
<div class="list-group list-group-flush rounded-bottom-4">
|
||||
<a href="/admin/apks" class="list-group-item list-group-item-action py-3 px-4 border-0">
|
||||
<i class="fas fa-mobile-alt me-2 text-primary"></i> Manage APKs
|
||||
</a>
|
||||
<a href="/admin/categories" class="list-group-item list-group-item-action py-3 px-4">
|
||||
<i class="bi bi-tags me-2 text-info"></i> Categories
|
||||
<a href="/admin/categories" class="list-group-item list-group-item-action py-3 px-4 border-0">
|
||||
<i class="fas fa-tags me-2 text-info"></i> <?php echo __('categories'); ?>
|
||||
</a>
|
||||
<a href="/admin/withdrawals" class="list-group-item list-group-item-action py-3 px-4">
|
||||
<i class="bi bi-cash-stack me-2 text-success"></i> Withdrawal Requests
|
||||
<a href="/admin/withdrawals" class="list-group-item list-group-item-action py-3 px-4 border-0">
|
||||
<i class="fas fa-cash-register me-2 text-success"></i> <?php echo __('manage_withdrawals'); ?>
|
||||
<?php if ($pending_withdrawals > 0): ?>
|
||||
<span class="badge bg-danger rounded-pill float-end"><?php echo $pending_withdrawals; ?></span>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<a href="/admin/settings" class="list-group-item list-group-item-action py-3 px-4 border-0">
|
||||
<i class="fas fa-cog me-2 text-secondary"></i> <?php echo __('settings'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -142,4 +148,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include __DIR__ . '/footer.php'; ?>
|
||||
<?php include __DIR__ . '/footer.php'; ?>
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="<?php echo \App\Services\LanguageService::getLang(); ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Admin Panel - APK Portal</title>
|
||||
<title><?php echo __('admin_dashboard'); ?> - <?php echo htmlspecialchars(get_setting('site_name', 'APK ADMIN')); ?></title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<link rel="icon" type="image/x-icon" href="/<?php echo get_setting('site_favicon'); ?>">
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: #4e73df;
|
||||
@ -19,32 +20,33 @@
|
||||
background-color: #fff;
|
||||
box-shadow: 0 .15rem 1.75rem 0 rgba(58,59,69,.15);
|
||||
}
|
||||
.sidebar {
|
||||
min-height: calc(100vh - 56px);
|
||||
background-color: #4e73df;
|
||||
background-image: linear-gradient(180deg,#4e73df 10%,#224abe 100%);
|
||||
background-size: cover;
|
||||
}
|
||||
.nav-link {
|
||||
color: rgba(255,255,255,.8);
|
||||
padding: 1rem 1.5rem;
|
||||
border-bottom: 1px solid rgba(255,255,255,.05);
|
||||
color: #4e73df;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 0.35rem;
|
||||
transition: all 0.2s;
|
||||
font-weight: 600;
|
||||
}
|
||||
.nav-link:hover {
|
||||
color: #fff;
|
||||
background-color: rgba(255,255,255,.1);
|
||||
background-color: rgba(78, 115, 223, 0.1);
|
||||
color: #224abe;
|
||||
}
|
||||
.nav-link.active {
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
background-color: #4e73df;
|
||||
color: #fff !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-admin sticky-top py-3">
|
||||
<div class="container-fluid px-4">
|
||||
<a class="navbar-brand fw-bold text-primary" href="/admin/dashboard">
|
||||
<i class="bi bi-shield-lock-fill me-2"></i>APK ADMIN
|
||||
<a class="navbar-brand fw-bold text-primary d-flex align-items-center" href="/admin/dashboard">
|
||||
<?php if (get_setting('site_icon')): ?>
|
||||
<img src="/<?php echo get_setting('site_icon'); ?>" alt="Logo" class="me-2" style="height: 30px;">
|
||||
<?php else: ?>
|
||||
<i class="fas fa-shield-halved me-2"></i>
|
||||
<?php endif; ?>
|
||||
<?php echo htmlspecialchars(get_setting('site_name', 'APK ADMIN')); ?>
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
@ -52,23 +54,35 @@
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark px-3" href="/admin/dashboard">Dashboard</a>
|
||||
<a class="nav-link px-3" href="/admin/dashboard"><i class="fas fa-tachometer-alt me-1"></i> Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark px-3" href="/admin/apks">APKs</a>
|
||||
<a class="nav-link px-3" href="/admin/apks"><i class="fas fa-mobile-alt me-1"></i> APKs</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark px-3" href="/admin/categories">Categories</a>
|
||||
<a class="nav-link px-3" href="/admin/categories"><i class="fas fa-list me-1"></i> <?php echo __('categories'); ?></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark px-3" href="/admin/withdrawals">Withdrawals</a>
|
||||
<a class="nav-link px-3" href="/admin/withdrawals"><i class="fas fa-wallet me-1"></i> <?php echo __('manage_withdrawals'); ?></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3" href="/admin/settings"><i class="fas fa-cog me-1"></i> <?php echo __('settings'); ?></a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="text-muted me-3">Welcome, <b><?php echo $_SESSION['username'] ?? 'Admin'; ?></b></span>
|
||||
<a href="/" class="btn btn-outline-secondary btn-sm me-2" target="_blank">View Site</a>
|
||||
<a href="/admin/logout" class="btn btn-danger btn-sm">Logout</a>
|
||||
<div class="dropdown me-3">
|
||||
<button class="btn btn-outline-primary btn-sm dropdown-toggle fw-bold" type="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-globe me-1"></i> <?php echo \App\Services\LanguageService::getLang() == 'id' ? 'ID' : 'EN'; ?>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow border-0">
|
||||
<li><a class="dropdown-item" href="/lang/id">🇮🇩 Indonesia</a></li>
|
||||
<li><a class="dropdown-item" href="/lang/en">🇺🇸 English</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<span class="text-muted me-3 d-none d-md-inline"><b><?php echo $_SESSION['username'] ?? 'Admin'; ?></b></span>
|
||||
<a href="/" class="btn btn-outline-secondary btn-sm me-2" target="_blank"><i class="fas fa-external-link-alt"></i></a>
|
||||
<a href="/admin/logout" class="btn btn-danger btn-sm"><i class="fas fa-sign-out-alt"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
96
views/admin/settings.php
Normal file
96
views/admin/settings.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php include 'header.php'; ?>
|
||||
|
||||
<div class="container-fluid py-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-header bg-white py-3">
|
||||
<h5 class="mb-0 fw-bold text-primary"><i class="fas fa-cog me-2"></i><?php echo __('general_settings'); ?></h5>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<form action="/admin/settings" method="POST" enctype="multipart/form-data">
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-semibold"><?php echo __('site_name'); ?></label>
|
||||
<input type="text" name="site_name" class="form-control form-control-lg" value="<?php echo htmlspecialchars($settings['site_name']); ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold"><?php echo __('site_icon'); ?></label>
|
||||
<input type="file" name="site_icon_file" class="form-control" accept="image/*">
|
||||
<?php if ($settings['site_icon']): ?>
|
||||
<div class="mt-2">
|
||||
<img src="/<?php echo $settings['site_icon']; ?>" alt="Icon" class="img-thumbnail" style="max-height: 50px;">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold"><?php echo __('site_favicon'); ?></label>
|
||||
<input type="file" name="site_favicon_file" class="form-control" accept="image/*">
|
||||
<?php if ($settings['site_favicon']): ?>
|
||||
<div class="mt-2">
|
||||
<img src="/<?php echo $settings['site_favicon']; ?>" alt="Favicon" class="img-thumbnail" style="max-height: 32px;">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
<h5 class="fw-bold mb-3"><i class="fas fa-search me-2"></i>SEO Settings</h5>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-semibold">Meta Description</label>
|
||||
<textarea name="meta_description" class="form-control" rows="3"><?php echo htmlspecialchars($settings['meta_description'] ?? ''); ?></textarea>
|
||||
<div class="form-text">Brief description of your site for search engines.</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-semibold">Meta Keywords</label>
|
||||
<input type="text" name="meta_keywords" class="form-control" value="<?php echo htmlspecialchars($settings['meta_keywords'] ?? ''); ?>">
|
||||
<div class="form-text">Comma separated keywords (e.g. apk, games, mod).</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
<h5 class="fw-bold mb-3"><i class="fas fa-code me-2"></i>Custom Scripts & Ads</h5>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-semibold">Head JS (Ads/Analytics)</label>
|
||||
<textarea name="head_js" class="form-control" rows="5" placeholder="<script>...</script>"><?php echo htmlspecialchars($settings['head_js'] ?? ''); ?></textarea>
|
||||
<div class="form-text">Injected before </head>.</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-semibold">Body JS (Ads/Analytics)</label>
|
||||
<textarea name="body_js" class="form-control" rows="5" placeholder="<script>...</script>"><?php echo htmlspecialchars($settings['body_js'] ?? ''); ?></textarea>
|
||||
<div class="form-text">Injected before </body>.</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid mt-4">
|
||||
<button type="submit" class="btn btn-primary btn-lg py-3 fw-bold">
|
||||
<i class="fas fa-save me-2"></i><?php echo __('save_settings'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm border-0 mt-4">
|
||||
<div class="card-header bg-white py-3">
|
||||
<h5 class="mb-0 fw-bold text-primary"><i class="fas fa-language me-2"></i><?php echo __('select_language'); ?></h5>
|
||||
</div>
|
||||
<div class="card-body p-4 text-center">
|
||||
<div class="btn-group w-100" role="group">
|
||||
<a href="/lang/id" class="btn btn-outline-primary py-3 fw-bold <?php echo \App\Services\LanguageService::getLang() == 'id' ? 'active' : ''; ?>">
|
||||
🇮🇩 <?php echo __('language_indonesia'); ?>
|
||||
</a>
|
||||
<a href="/lang/en" class="btn btn-outline-primary py-3 fw-bold <?php echo \App\Services\LanguageService::getLang() == 'en' ? 'active' : ''; ?>">
|
||||
🇺🇸 <?php echo __('language_english'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@ -6,14 +6,14 @@
|
||||
<div class="card shadow border-0 rounded-4 mb-4">
|
||||
<div class="card-body text-center p-5">
|
||||
<div class="bg-success text-white rounded-circle d-inline-flex align-items-center justify-content-center mb-4" style="width: 80px; height: 80px;">
|
||||
<i class="bi bi-person-fill fs-1"></i>
|
||||
<i class="fas fa-user fs-1"></i>
|
||||
</div>
|
||||
<h3 class="fw-bold mb-0"><?php echo $user['username']; ?></h3>
|
||||
<p class="text-muted">Member since <?php echo date('M Y', strtotime($user['created_at'])); ?></p>
|
||||
<hr>
|
||||
<div class="row g-0">
|
||||
<div class="col-6 border-end">
|
||||
<h4 class="fw-bold text-success mb-0"><?php echo $user['points']; ?></h4>
|
||||
<h4 class="fw-bold text-success mb-0"><?php echo number_format($user['points']); ?></h4>
|
||||
<small class="text-muted text-uppercase">Points</small>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
@ -26,10 +26,10 @@
|
||||
|
||||
<div class="card shadow border-0 rounded-4 mb-4">
|
||||
<div class="card-body p-4 text-center bg-light">
|
||||
<h6 class="text-uppercase text-muted fw-bold mb-2">Current Balance</h6>
|
||||
<h6 class="text-uppercase text-muted fw-bold mb-2"><?php echo __('balance'); ?></h6>
|
||||
<h2 class="fw-bold text-success mb-3">Rp <?php echo number_format($user['balance'], 0, ',', '.'); ?></h2>
|
||||
<button class="btn btn-success btn-lg px-5 rounded-pill" data-bs-toggle="modal" data-bs-target="#withdrawModal">
|
||||
<i class="bi bi-wallet2 me-2"></i> Withdraw
|
||||
<i class="fas fa-wallet me-2"></i> <?php echo __('withdraw'); ?>
|
||||
</button>
|
||||
<p class="small text-muted mt-3 mb-0">Min. withdraw: Rp 10.000</p>
|
||||
</div>
|
||||
@ -46,12 +46,12 @@
|
||||
|
||||
<div class="card shadow border-0 rounded-4 mb-4">
|
||||
<div class="card-header bg-white py-3">
|
||||
<h5 class="m-0 fw-bold">My Referral Code</h5>
|
||||
<h5 class="m-0 fw-bold"><?php echo __('referral_link'); ?></h5>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<p>Share your referral link to earn <b>Rp 500</b> for every download.</p>
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" class="form-control bg-light" id="refLink" value="<?php echo 'http://' . $_SERVER['HTTP_HOST'] . '/register?ref=' . $user['referral_code']; ?>" readonly>
|
||||
<input type="text" class="form-control bg-light" id="refLink" value="<?php echo 'http://' . $_SERVER['HTTP_HOST'] . '/?ref=' . $user['referral_code']; ?>" readonly>
|
||||
<button class="btn btn-outline-success" type="button" onclick="copyText('refLink')">Copy Link</button>
|
||||
</div>
|
||||
<div class="small text-muted">Example APK referral link:</div>
|
||||
@ -63,7 +63,7 @@
|
||||
|
||||
<div class="card shadow border-0 rounded-4">
|
||||
<div class="card-header bg-white py-3 d-flex justify-content-between align-items-center">
|
||||
<h5 class="m-0 fw-bold">Withdrawal History</h5>
|
||||
<h5 class="m-0 fw-bold"><?php echo __('withdrawal_history'); ?></h5>
|
||||
<span class="badge bg-light text-dark">Recent activities</span>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
|
||||
@ -1,13 +1,18 @@
|
||||
</main>
|
||||
</main>
|
||||
<footer class="bg-white border-top py-5">
|
||||
<div class="container">
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-4">
|
||||
<a class="navbar-brand fw-bold text-success" href="/">
|
||||
<i class="bi bi-robot"></i> ApkNusa
|
||||
<a class="navbar-brand fw-bold text-success d-flex align-items-center" href="/">
|
||||
<?php if (get_setting('site_icon')): ?>
|
||||
<img src="/<?php echo get_setting('site_icon'); ?>" alt="Logo" class="me-2" style="height: 30px;">
|
||||
<?php else: ?>
|
||||
<i class="bi bi-robot"></i>
|
||||
<?php endif; ?>
|
||||
<?php echo htmlspecialchars(get_setting('site_name', 'ApkNusa')); ?>
|
||||
</a>
|
||||
<p class="text-muted mt-3 pe-lg-5">
|
||||
ApkNusa is your premier source for professional APK downloads, offering the latest and safest Android applications and games.
|
||||
<?php echo htmlspecialchars(get_setting('site_name', 'ApkNusa')); ?> is your premier source for professional APK downloads, offering the latest and safest Android applications and games.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6 col-lg-2">
|
||||
@ -38,7 +43,7 @@
|
||||
<hr class="my-5 text-black-50 opacity-25">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-6 text-center text-md-start">
|
||||
<span class="text-muted small">© <?php echo date('Y'); ?> ApkNusa. All rights reserved.</span>
|
||||
<span class="text-muted small">© <?php echo date('Y'); ?> <?php echo htmlspecialchars(get_setting('site_name', 'ApkNusa')); ?>. All rights reserved.</span>
|
||||
</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">
|
||||
@ -53,5 +58,6 @@
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/assets/js/main.js"></script>
|
||||
<?php echo get_setting('body_js'); ?>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@ -1,22 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="<?php echo \App\Services\LanguageService::getLang(); ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php echo $title ?? 'ApkNusa'; ?></title>
|
||||
<meta name="description" content="<?php echo $_SERVER['PROJECT_DESCRIPTION'] ?? 'Download Professional APKs with ApkNusa.'; ?>">
|
||||
<title><?php echo $title ?? htmlspecialchars(get_setting('site_name', 'ApkNusa')); ?></title>
|
||||
|
||||
<meta name="description" content="<?php echo $meta_description ?? htmlspecialchars(get_setting('meta_description', 'Download Professional APKs.')); ?>">
|
||||
<meta name="keywords" content="<?php echo $meta_keywords ?? htmlspecialchars(get_setting('meta_keywords', 'apk, android, download')); ?>">
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||
<link rel="icon" type="image/x-icon" href="/<?php echo get_setting('site_favicon'); ?>">
|
||||
<link rel="stylesheet" href="/assets/css/custom.css">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<?php echo get_setting('head_js'); ?>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-white border-bottom py-3 sticky-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand fw-bold text-success" href="/">
|
||||
<i class="bi bi-robot"></i> ApkNusa
|
||||
<a class="navbar-brand fw-bold text-success d-flex align-items-center" href="/">
|
||||
<?php if (get_setting('site_icon')): ?>
|
||||
<img src="/<?php echo get_setting('site_icon'); ?>" alt="Logo" class="me-2" style="height: 30px;">
|
||||
<?php else: ?>
|
||||
<i class="fas fa-robot"></i>
|
||||
<?php endif; ?>
|
||||
<?php echo htmlspecialchars(get_setting('site_name', 'ApkNusa')); ?>
|
||||
</a>
|
||||
<button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
@ -24,27 +36,34 @@
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav ms-auto align-items-center">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3" href="/">Home</a>
|
||||
<a class="nav-link px-3" href="/"><?php echo __('home'); ?></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3" href="#">Games</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3" href="#">Apps</a>
|
||||
<a class="nav-link px-3" href="#"><?php echo __('categories'); ?></a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item dropdown px-3">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-globe me-1"></i> <?php echo \App\Services\LanguageService::getLang() == 'id' ? 'ID' : 'EN'; ?>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow border-0">
|
||||
<li><a class="dropdown-item" href="/lang/id">🇮🇩 Indonesia</a></li>
|
||||
<li><a class="dropdown-item" href="/lang/en">🇺🇸 English</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<?php if (isset($_SESSION['user_id'])): ?>
|
||||
<li class="nav-item ms-lg-3">
|
||||
<a class="btn btn-outline-success rounded-pill px-4 d-flex align-items-center" href="/profile">
|
||||
<i class="bi bi-person-circle me-2"></i> Profile
|
||||
<i class="fas fa-user-circle me-2"></i> <?php echo __('profile'); ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php else: ?>
|
||||
<li class="nav-item ms-lg-3">
|
||||
<a class="btn btn-outline-dark rounded-pill px-4" href="/login">Login</a>
|
||||
<a class="btn btn-outline-dark rounded-pill px-4" href="/login"><?php echo __('login'); ?></a>
|
||||
</li>
|
||||
<li class="nav-item ms-lg-2">
|
||||
<a class="btn btn-success rounded-pill px-4" href="/register">Join Free</a>
|
||||
<a class="btn btn-success rounded-pill px-4" href="/register"><?php echo __('register'); ?></a>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<?php include 'header.php'; ?>
|
||||
|
||||
<div class="container">
|
||||
<div class="row align-items-center mb-5">
|
||||
<div class="row align-items-center mb-5 mt-4">
|
||||
<div class="col-lg-7">
|
||||
<h1 class="display-4 fw-bold mb-3">Download the Best <span class="text-success">Android APKs</span> Professionally</h1>
|
||||
<p class="lead text-muted mb-4">Fast, safe, and secure downloads for your favorite mobile apps and games. No registration required to browse.</p>
|
||||
@ -10,23 +10,23 @@
|
||||
<a href="/register" class="btn btn-outline-dark btn-lg px-4 rounded-pill">Join Referral</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-5 d-none d-lg-block">
|
||||
<div class="col-lg-5 d-none d-lg-block text-center">
|
||||
<div class="position-relative">
|
||||
<div class="bg-success opacity-10 position-absolute rounded-circle" style="width: 400px; height: 400px; top: -50px; right: -50px; z-index: -1;"></div>
|
||||
<img src="https://img.icons8.com/color/512/android-os.png" class="img-fluid floating-animation" alt="Android APKs">
|
||||
<img src="https://img.icons8.com/color/512/android-os.png" class="img-fluid floating-animation" alt="Android APKs" style="max-height: 350px;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section id="latest" class="mb-5">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 class="fw-bold mb-0">Latest Releases</h2>
|
||||
<h2 class="fw-bold mb-0"><?php echo __('latest_apks'); ?></h2>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-light dropdown-toggle rounded-pill" type="button" data-bs-toggle="dropdown">
|
||||
Categories
|
||||
<?php echo __('categories'); ?>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="/">All</a></li>
|
||||
<li><a class="dropdown-item" href="/"><?php echo __('all_categories'); ?></a></li>
|
||||
<?php
|
||||
$db = db();
|
||||
$categories = $db->query("SELECT * FROM categories")->fetchAll();
|
||||
@ -36,28 +36,27 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-4">
|
||||
|
||||
<!-- Grid optimized for 3 columns on desktop and mobile as requested -->
|
||||
<div class="row g-2 g-md-4">
|
||||
<?php foreach ($apks as $apk): ?>
|
||||
<div class="col-12 col-md-6 col-lg-4">
|
||||
<div class="col-4 col-md-4">
|
||||
<div class="card h-100 border-0 shadow-sm rounded-4 hover-lift">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="card-body p-2 p-md-4 text-center text-md-start">
|
||||
<div class="d-md-flex align-items-center mb-2 mb-md-3">
|
||||
<?php
|
||||
$icon = !empty($apk['icon_path']) ? '/'.$apk['icon_path'] : $apk['image_url'];
|
||||
?>
|
||||
<img src="<?php echo $icon; ?>" class="rounded-3 me-3" width="60" height="60" alt="<?php echo $apk['title']; ?>" style="object-fit: cover;">
|
||||
<div>
|
||||
<h5 class="card-title fw-bold mb-0 text-truncate" style="max-width: 180px;"><?php echo $apk['title']; ?></h5>
|
||||
<span class="badge bg-light text-dark fw-normal">v<?php echo $apk['version']; ?></span>
|
||||
<?php if ($apk['is_vip']): ?>
|
||||
<span class="badge bg-warning text-dark ms-1"><i class="bi bi-star-fill"></i> VIP</span>
|
||||
<?php endif; ?>
|
||||
<img src="<?php echo $icon; ?>" class="rounded-3 mx-auto mx-md-0 mb-2 mb-md-0 d-block d-md-inline-block" width="50" height="50" alt="<?php echo $apk['title']; ?>" style="object-fit: cover; width: 50px; height: 50px;">
|
||||
<div class="ms-md-3">
|
||||
<h6 class="card-title fw-bold mb-0 text-truncate mx-auto" style="max-width: 100%;"><?php echo $apk['title']; ?></h6>
|
||||
<span class="badge bg-light text-dark fw-normal d-none d-md-inline-block">v<?php echo $apk['version']; ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="card-text text-muted small mb-4 line-clamp-2"><?php echo $apk['description']; ?></p>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted small"><i class="bi bi-download me-1"></i> <?php echo number_format($apk['total_downloads']); ?></span>
|
||||
<a href="/apk/<?php echo $apk['slug']; ?>" class="btn btn-success rounded-pill px-4 btn-sm fw-medium">Details</a>
|
||||
<p class="card-text text-muted small mb-3 line-clamp-2 d-none d-md-block"><?php echo $apk['description']; ?></p>
|
||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-center gap-2">
|
||||
<span class="text-muted small d-none d-md-inline-block"><i class="fas fa-download me-1"></i> <?php echo number_format($apk['total_downloads']); ?></span>
|
||||
<a href="/apk/<?php echo $apk['slug']; ?>" class="btn btn-success rounded-pill px-3 btn-sm fw-medium w-100 w-md-auto">Details</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -79,4 +78,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@media (max-width: 767px) {
|
||||
.card-title {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.btn-sm {
|
||||
font-size: 0.7rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
Loading…
x
Reference in New Issue
Block a user