diff --git a/app/Controllers/AdminController.php b/app/Controllers/AdminController.php new file mode 100644 index 0000000..a9aecd0 --- /dev/null +++ b/app/Controllers/AdminController.php @@ -0,0 +1,239 @@ +redirect('/admin/login'); + } + } + + public function loginForm() { + if (isset($_SESSION['user_id'])) { + $this->redirect('/admin/dashboard'); + } + $this->view('admin/login'); + } + + public function login() { + $username = $_POST['username'] ?? ''; + $password = $_POST['password'] ?? ''; + + $db = db_pdo(); + $stmt = $db->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']; + $this->redirect('/admin/dashboard'); + } else { + $error = "Invalid username or password"; + $this->view('admin/login', ['error' => $error]); + } + } + + public function logout() { + session_destroy(); + $this->redirect('/admin/login'); + } + + public function dashboard() { + $this->checkAuth(); + $apkService = new ApkService(); + $db = db_pdo(); + $stats = [ + 'total_apks' => count($apkService->getAllApks()), + 'total_downloads' => $this->getTotalDownloads(), + 'total_users' => $db->query("SELECT COUNT(*) FROM users")->fetchColumn(), + 'pending_withdrawals' => $db->query("SELECT COUNT(*) FROM withdrawals WHERE status = 'pending'")->fetchColumn(), + 'recent_apks' => array_slice($apkService->getAllApks(), 0, 5) + ]; + $this->view('admin/dashboard', $stats); + } + + private function getTotalDownloads() { + $db = db_pdo(); + return $db->query("SELECT SUM(total_downloads) FROM apks")->fetchColumn() ?: 0; + } + + // APK Management + public function apks() { + $this->checkAuth(); + $apkService = new ApkService(); + $apks = $apkService->getAllApks(); + $this->view('admin/apks/index', ['apks' => $apks]); + } + + public function addApkForm() { + $this->checkAuth(); + $db = db_pdo(); + $categories = $db->query("SELECT * FROM categories")->fetchAll(); + $this->view('admin/apks/form', ['action' => 'add', 'categories' => $categories]); + } + + public function addApk() { + $this->checkAuth(); + $title = $_POST['title']; + $slug = $this->slugify($title); + $description = $_POST['description']; + $version = $_POST['version']; + $image_url = $_POST['image_url']; + $download_url = $_POST['download_url']; + $category_id = $_POST['category_id'] ?? null; + $status = $_POST['status'] ?? 'published'; + $is_vip = isset($_POST['is_vip']) ? 1 : 0; + + $icon_path = $this->handleUpload('icon_file'); + + $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)"); + $stmt->execute([$title, $slug, $description, $version, $image_url, $icon_path, $download_url, $category_id, $status, $is_vip]); + + $this->redirect('/admin/apks'); + } + + public function editApkForm($params) { + $this->checkAuth(); + $apkService = new ApkService(); + $apk = $apkService->getApkById($params['id']); + $db = db_pdo(); + $categories = $db->query("SELECT * FROM categories")->fetchAll(); + $this->view('admin/apks/form', ['action' => 'edit', 'apk' => $apk, 'categories' => $categories]); + } + + public function editApk($params) { + $this->checkAuth(); + $title = $_POST['title']; + $description = $_POST['description']; + $version = $_POST['version']; + $image_url = $_POST['image_url']; + $download_url = $_POST['download_url']; + $category_id = $_POST['category_id'] ?? null; + $status = $_POST['status']; + $is_vip = isset($_POST['is_vip']) ? 1 : 0; + + $db = db_pdo(); + $apk = $db->query("SELECT * FROM apks WHERE id = " . $params['id'])->fetch(); + $icon_path = $this->handleUpload('icon_file') ?: $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']]); + + $this->redirect('/admin/apks'); + } + + public function updateOrder() { + $this->checkAuth(); + $order = $_POST['order'] ?? []; + $db = db_pdo(); + foreach ($order as $index => $id) { + $stmt = $db->prepare("UPDATE apks SET display_order = ? WHERE id = ?"); + $stmt->execute([$index, $id]); + } + header('Content-Type: application/json'); + echo json_encode(['success' => true]); + } + + private function handleUpload($field) { + if (!isset($_FILES[$field]) || $_FILES[$field]['error'] !== UPLOAD_ERR_OK) { + return null; + } + + $uploadDir = 'assets/uploads/icons/'; + if (!is_dir($uploadDir)) { + mkdir($uploadDir, 0775, true); + } + + $ext = pathinfo($_FILES[$field]['name'], PATHINFO_EXTENSION); + $fileName = uniqid() . '.' . $ext; + $targetPath = $uploadDir . $fileName; + + if (move_uploaded_file($_FILES[$field]['tmp_name'], $targetPath)) { + return $targetPath; + } + + return null; + } + + // Category Management + public function categories() { + $this->checkAuth(); + $db = db_pdo(); + $categories = $db->query("SELECT * FROM categories")->fetchAll(); + $this->view('admin/categories/index', ['categories' => $categories]); + } + + public function addCategory() { + $this->checkAuth(); + $name = $_POST['name']; + $slug = $this->slugify($name); + $db = db_pdo(); + $stmt = $db->prepare("INSERT INTO categories (name, slug) VALUES (?, ?)"); + $stmt->execute([$name, $slug]); + $this->redirect('/admin/categories'); + } + + public function deleteCategory($params) { + $this->checkAuth(); + $db = db_pdo(); + $stmt = $db->prepare("DELETE FROM categories WHERE id = ?"); + $stmt->execute([$params['id']]); + $this->redirect('/admin/categories'); + } + + // Withdrawal Management + public function withdrawals() { + $this->checkAuth(); + $db = db_pdo(); + $withdrawals = $db->query("SELECT w.*, u.username FROM withdrawals w JOIN users u ON w.user_id = u.id ORDER BY w.created_at DESC")->fetchAll(); + $this->view('admin/withdrawals/index', ['withdrawals' => $withdrawals]); + } + + public function approveWithdrawal($params) { + $this->checkAuth(); + $db = db_pdo(); + $stmt = $db->prepare("UPDATE withdrawals SET status = 'approved' WHERE id = ?"); + $stmt->execute([$params['id']]); + $this->redirect('/admin/withdrawals'); + } + + 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 = ?"); + $stmt->execute([$wd['amount'], $wd['user_id']]); + + $stmt = $db->prepare("UPDATE withdrawals SET status = 'rejected' WHERE id = ?"); + $stmt->execute([$params['id']]); + } + $this->redirect('/admin/withdrawals'); + } + + public function deleteApk($params) { + $this->checkAuth(); + $db = db_pdo(); + $stmt = $db->prepare("DELETE FROM apks WHERE id = ?"); + $stmt->execute([$params['id']]); + $this->redirect('/admin/apks'); + } + + private function slugify($text) { + $text = preg_replace('~[^\pL\d]+~u', '-', $text); + $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text); + $text = preg_replace('~[^-\w]+~', '', $text); + $text = trim($text, '-'); + $text = preg_replace('~-+~', '-', $text); + $text = strtolower($text); + return empty($text) ? 'n-a' : $text; + } +} \ No newline at end of file diff --git a/app/Controllers/ApkController.php b/app/Controllers/ApkController.php index ad1aca3..2cca845 100644 --- a/app/Controllers/ApkController.php +++ b/app/Controllers/ApkController.php @@ -28,11 +28,26 @@ class ApkController extends Controller { public function download($params) { $apk = $this->apkService->getBySlug($params['slug']); - if ($apk) { - $this->apkService->incrementDownload($apk['id']); - // In a real app, this would be a link to a file or a CDN. - // For now, let's redirect to a mock download URL or back. - $this->redirect($apk['download_url'] === '#' ? '/apk/' . $apk['slug'] . '?downloaded=1' : $apk['download_url']); + + if (!$apk) { + header("HTTP/1.0 404 Not Found"); + echo "APK Not Found"; + return; } + + // Increment download counter + $this->apkService->incrementDownload($apk['id']); + + // Get the download URL + $downloadUrl = $apk['download_url']; + + // If URL is empty or #, redirect back to detail with a message + if (empty($downloadUrl) || $downloadUrl === '#') { + $this->redirect('/apk/' . $apk['slug'] . '?error=no_url'); + return; + } + + // Redirect to the actual download link (External URL) + $this->redirect($downloadUrl); } -} +} \ No newline at end of file diff --git a/app/Controllers/AuthController.php b/app/Controllers/AuthController.php new file mode 100644 index 0000000..c20a9b1 --- /dev/null +++ b/app/Controllers/AuthController.php @@ -0,0 +1,157 @@ +redirect('/profile'); + } + $this->view('auth/login'); + } + + public function registerForm() { + if (isset($_SESSION['user_id'])) { + $this->redirect('/profile'); + } + $ref = $_GET['ref'] ?? ''; + $this->view('auth/register', ['ref' => $ref]); + } + + public function login() { + $username = $_POST['username'] ?? ''; + $password = $_POST['password'] ?? ''; + + $db = db_pdo(); + $stmt = $db->prepare("SELECT * FROM users WHERE username = ? AND role = 'user'"); + $stmt->execute([$username]); + $user = $stmt->fetch(); + + if ($user && password_verify($password, $user['password'])) { + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['role'] = $user['role']; + $this->redirect('/profile'); + } else { + $this->view('auth/login', ['error' => 'Invalid username or password']); + } + } + + public function register() { + $username = $_POST['username'] ?? ''; + $password = $_POST['password'] ?? ''; + $confirm_password = $_POST['confirm_password'] ?? ''; + $ref_code = $_POST['ref_code'] ?? ''; + + if ($password !== $confirm_password) { + $this->view('auth/register', ['error' => 'Passwords do not match', 'ref' => $ref_code]); + return; + } + + $db = db_pdo(); + + // Check if username exists + $stmt = $db->prepare("SELECT id FROM users WHERE username = ?"); + $stmt->execute([$username]); + if ($stmt->fetch()) { + $this->view('auth/register', ['error' => 'Username already exists', 'ref' => $ref_code]); + return; + } + + $hashed_password = password_hash($password, PASSWORD_DEFAULT); + $referral_code = substr(md5(uniqid($username, true)), 0, 8); + + $referred_by = null; + if (!empty($ref_code)) { + $stmt = $db->prepare("SELECT id FROM users WHERE referral_code = ?"); + $stmt->execute([$ref_code]); + $referrer = $stmt->fetch(); + if ($referrer) { + $referred_by = $referrer['id']; + } + } + + $stmt = $db->prepare("INSERT INTO users (username, password, referral_code, referred_by, role, balance) VALUES (?, ?, ?, ?, 'user', 0)"); + $stmt->execute([$username, $hashed_password, $referral_code, $referred_by]); + $userId = $db->lastInsertId(); + + if ($referred_by) { + // Reward referrer with points (not balance yet, as per previous logic) + $stmt = $db->prepare("UPDATE users SET points = points + 10, total_referrals = total_referrals + 1 WHERE id = ?"); + $stmt->execute([$referred_by]); + } + + $_SESSION['user_id'] = $userId; + $_SESSION['username'] = $username; + $_SESSION['role'] = 'user'; + + $this->redirect('/profile'); + } + + public function logout() { + session_destroy(); + $this->redirect('/'); + } + + public function profile() { + if (!isset($_SESSION['user_id'])) { + $this->redirect('/login'); + } + + $db = db_pdo(); + $stmt = $db->prepare("SELECT * FROM users WHERE id = ?"); + $stmt->execute([$_SESSION['user_id']]); + $user = $stmt->fetch(); + + $stmt = $db->prepare("SELECT * FROM withdrawals WHERE user_id = ? ORDER BY created_at DESC"); + $stmt->execute([$user['id']]); + $withdrawals = $stmt->fetchAll(); + + $this->view('auth/profile', [ + 'user' => $user, + 'withdrawals' => $withdrawals, + 'success' => $_SESSION['success'] ?? null, + 'error' => $_SESSION['error'] ?? null + ]); + unset($_SESSION['success'], $_SESSION['error']); + } + + public function requestWithdrawal() { + if (!isset($_SESSION['user_id'])) { + $this->redirect('/login'); + } + + $amount = (float)$_POST['amount']; + $method = $_POST['method']; + $details = $_POST['details']; + + if ($amount < 10000) { // Minimum WD + $_SESSION['error'] = "Minimum withdrawal is Rp 10.000"; + $this->redirect('/profile'); + } + + $db = db_pdo(); + $stmt = $db->prepare("SELECT balance FROM users WHERE id = ?"); + $stmt->execute([$_SESSION['user_id']]); + $balance = $stmt->fetchColumn(); + + if ($balance < $amount) { + $_SESSION['error'] = "Insufficient balance"; + $this->redirect('/profile'); + } + + // Deduct balance + $stmt = $db->prepare("UPDATE users SET balance = balance - ? WHERE id = ?"); + $stmt->execute([$amount, $_SESSION['user_id']]); + + // Create WD request + $stmt = $db->prepare("INSERT INTO withdrawals (user_id, amount, method, account_details, status) VALUES (?, ?, ?, ?, 'pending')"); + $stmt->execute([$_SESSION['user_id'], $amount, $method, $details]); + + $_SESSION['success'] = "Withdrawal request submitted successfully"; + $this->redirect('/profile'); + } +} \ No newline at end of file diff --git a/app/Controllers/HomeController.php b/app/Controllers/HomeController.php index aa23f18..78eb02b 100644 --- a/app/Controllers/HomeController.php +++ b/app/Controllers/HomeController.php @@ -13,10 +13,93 @@ class HomeController extends Controller { } public function index() { - $apks = $this->apkService->getLatest(12); + $db = db_pdo(); + $category = $_GET['category'] ?? null; + + $sql = "SELECT * FROM apks WHERE status = 'published'"; + $params = []; + + if ($category) { + $sql .= " AND category_id = (SELECT id FROM categories WHERE slug = ?)"; + $params[] = $category; + } + + $sql .= " ORDER BY display_order ASC, created_at DESC LIMIT 12"; + + $stmt = $db->prepare($sql); + $stmt->execute($params); + $apks = $stmt->fetchAll(); + return $this->view('home', [ 'apks' => $apks, 'title' => 'ApkNusa - Professional APK Download Portal' ]); } -} + + public function apkDetail($params) { + $slug = $params['slug']; + $db = db_pdo(); + $stmt = $db->prepare("SELECT * FROM apks WHERE slug = ?"); + $stmt->execute([$slug]); + $apk = $stmt->fetch(); + + if (!$apk) { + $this->redirect('/'); + } + + // Store referral code if present + if (isset($_GET['ref'])) { + $_SESSION['ref_download_' . $apk['id']] = $_GET['ref']; + } + + $this->view('apk_detail', ['apk' => $apk]); + } + + public function download($params) { + $slug = $params['slug']; + $db = db_pdo(); + $stmt = $db->prepare("SELECT * FROM apks WHERE slug = ?"); + $stmt->execute([$slug]); + $apk = $stmt->fetch(); + + if (!$apk) { + $this->redirect('/'); + } + + // Check for referral earnings + $ref_code = $_SESSION['ref_download_' . $apk['id']] ?? null; + if ($ref_code) { + $stmt = $db->prepare("SELECT id FROM users WHERE referral_code = ?"); + $stmt->execute([$ref_code]); + $referrer = $stmt->fetch(); + + if ($referrer) { + $referrer_id = $referrer['id']; + $ip = $_SERVER['REMOTE_ADDR']; + + // Check if this IP already earned for this APK today (prevent abuse) + $stmt = $db->prepare("SELECT id FROM referral_downloads WHERE referrer_id = ? AND apk_id = ? AND ip_address = ? AND created_at > DATE_SUB(NOW(), INTERVAL 1 DAY)"); + $stmt->execute([$referrer_id, $apk['id'], $ip]); + + if (!$stmt->fetch()) { + // Credit 500 IDR + $stmt = $db->prepare("UPDATE users SET balance = balance + 500 WHERE id = ?"); + $stmt->execute([$referrer_id]); + + // Log download + $stmt = $db->prepare("INSERT INTO referral_downloads (referrer_id, apk_id, ip_address, amount) VALUES (?, ?, ?, 500)"); + $stmt->execute([$referrer_id, $apk['id'], $ip]); + } + } + // Clear session after processing + unset($_SESSION['ref_download_' . $apk['id']]); + } + + // Increment total downloads + $stmt = $db->prepare("UPDATE apks SET total_downloads = total_downloads + 1 WHERE id = ?"); + $stmt->execute([$apk['id']]); + + // Redirect to actual file + $this->redirect($apk['download_url']); + } +} \ No newline at end of file diff --git a/app/Core/Router.php b/app/Core/Router.php index cf1ee12..80a0c88 100644 --- a/app/Core/Router.php +++ b/app/Core/Router.php @@ -3,36 +3,49 @@ namespace App\Core; class Router { - protected $routes = []; + private $routes = []; - public function add($method, $path, $handler) { - $path = preg_replace('/\{([a-z]+)\}/', '(?P<\1>[^/]+)', $path); + public function get($path, $handler) { + $this->add('GET', $path, $handler); + } + + public function post($path, $handler) { + $this->add('POST', $path, $handler); + } + + private function add($method, $path, $handler) { + $path = preg_replace('/:([^\/]+)/', '(?P<$1>[^/]+)', $path); + $path = '#^' . $path . '$#'; $this->routes[] = [ - 'method' => strtoupper($method), - 'path' => '#^' . $path . '$#', + 'method' => $method, + 'path' => $path, 'handler' => $handler ]; } - public function dispatch($method, $uri) { - $uri = parse_url($uri, PHP_URL_PATH); - + public function dispatch() { + $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); + $method = $_SERVER['REQUEST_METHOD']; + foreach ($this->routes as $route) { - if ($route['method'] === strtoupper($method) && preg_match($route['path'], $uri, $matches)) { + if ($route['method'] === $method && preg_match($route['path'], $uri, $matches)) { $handler = $route['handler']; $params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY); - - if (is_array($handler)) { - [$controllerClass, $methodName] = $handler; + + if (is_string($handler) && strpos($handler, '@') !== false) { + [$controllerName, $methodName] = explode('@', $handler); + $controllerClass = "App\\Controllers\\".$controllerName; $controller = new $controllerClass(); return $controller->$methodName($params); } - - return $handler($params); + + if (is_callable($handler)) { + return call_user_func_array($handler, [$params]); + } } } header("HTTP/1.0 404 Not Found"); echo "404 Not Found"; } -} +} \ No newline at end of file diff --git a/app/Helpers/functions.php b/app/Helpers/functions.php new file mode 100644 index 0000000..446ffe1 --- /dev/null +++ b/app/Helpers/functions.php @@ -0,0 +1,16 @@ +fetch(); } + public function getAllApks() { + $stmt = $this->db->prepare("SELECT * FROM apks ORDER BY created_at DESC"); + $stmt->execute(); + return $stmt->fetchAll(); + } + + public function getApkById($id) { + $stmt = $this->db->prepare("SELECT * FROM apks WHERE id = ?"); + $stmt->execute([$id]); + return $stmt->fetch(); + } + public function incrementDownload($apkId) { $stmt = $this->db->prepare("UPDATE apks SET total_downloads = total_downloads + 1 WHERE id = :id"); $stmt->execute(['id' => $apkId]); @@ -34,4 +46,4 @@ class ApkService { 'ip' => $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0' ]); } -} +} \ No newline at end of file diff --git a/app/Services/LanguageService.php b/app/Services/LanguageService.php new file mode 100644 index 0000000..67d0c07 --- /dev/null +++ b/app/Services/LanguageService.php @@ -0,0 +1,10 @@ +add('GET', '/', ['App\Controllers\HomeController', 'index']); -$router->add('GET', '/apk/{slug}', ['App\Controllers\ApkController', 'detail']); -$router->add('GET', '/apk/{slug}/download', ['App\Controllers\ApkController', 'download']); +// Home & APKs +$router->get('/', 'HomeController@index'); +$router->get('/apk/:slug', 'HomeController@apkDetail'); +$router->get('/download/:slug', 'HomeController@download'); -$method = $_SERVER['REQUEST_METHOD']; -$uri = $_SERVER['REQUEST_URI']; +// Auth +$router->get('/login', 'AuthController@loginForm'); +$router->post('/login', 'AuthController@login'); +$router->get('/register', 'AuthController@registerForm'); +$router->post('/register', 'AuthController@register'); +$router->get('/logout', 'AuthController@logout'); +$router->get('/profile', 'AuthController@profile'); +$router->post('/withdraw', 'AuthController@requestWithdrawal'); -$router->dispatch($method, $uri); \ No newline at end of file +// Admin Auth +$router->get('/admin/login', 'AdminController@loginForm'); +$router->post('/admin/login', 'AdminController@login'); +$router->get('/admin/logout', 'AdminController@logout'); + +// Admin Dashboard +$router->get('/admin/dashboard', 'AdminController@dashboard'); + +// Admin APKs +$router->get('/admin/apks', 'AdminController@apks'); +$router->get('/admin/apks/add', 'AdminController@addApkForm'); +$router->post('/admin/apks/add', 'AdminController@addApk'); +$router->get('/admin/apks/edit/:id', 'AdminController@editApkForm'); +$router->post('/admin/apks/edit/:id', 'AdminController@editApk'); +$router->get('/admin/apks/delete/:id', 'AdminController@deleteApk'); +$router->post('/admin/apks/reorder', 'AdminController@updateOrder'); + +// Admin Categories +$router->get('/admin/categories', 'AdminController@categories'); +$router->post('/admin/categories/add', 'AdminController@addCategory'); +$router->get('/admin/categories/delete/:id', 'AdminController@deleteCategory'); + +// Admin Withdrawals +$router->get('/admin/withdrawals', 'AdminController@withdrawals'); +$router->get('/admin/withdrawals/approve/:id', 'AdminController@approveWithdrawal'); +$router->get('/admin/withdrawals/reject/:id', 'AdminController@rejectWithdrawal'); + +$router->dispatch(); \ No newline at end of file diff --git a/views/admin/apks/form.php b/views/admin/apks/form.php new file mode 100644 index 0000000..d2adf5a --- /dev/null +++ b/views/admin/apks/form.php @@ -0,0 +1,84 @@ + + +
+
+
+
+
+
+
+
+
+
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+ +
+ + + + +
+
+ + +
+
+ +
+ + +
+ +
+
+ + +
+
+
+ > + +
+
+
+ +
+ Cancel + +
+
+
+
+
+
+
+ + \ No newline at end of file diff --git a/views/admin/apks/index.php b/views/admin/apks/index.php new file mode 100644 index 0000000..8f5fe68 --- /dev/null +++ b/views/admin/apks/index.php @@ -0,0 +1,116 @@ + + +
+
+

Manage APKs

+ + Add New APK + +
+ +
+
+
APK List (Drag to Reorder)
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IconTitleVersionCategoryDownloadsStatusVIPActions
+ + + + + + query("SELECT name FROM categories WHERE id = " . ($apk['category_id'] ?: 0))->fetchColumn(); + echo $cat ?: 'Uncategorized'; + ?> + + + + + + + VIP + + - + + + +
+
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/views/admin/categories/index.php b/views/admin/categories/index.php new file mode 100644 index 0000000..4aac68d --- /dev/null +++ b/views/admin/categories/index.php @@ -0,0 +1,60 @@ + + +
+
+
+
+
+
Add New Category
+
+
+
+
+ + +
+
+ +
+
+
+
+
+ +
+
+
+
All Categories
+
+
+
+ + + + + + + + + + + + + + + + + +
NameSlugActions
+ + Delete + +
+
+
+
+
+
+
+ + diff --git a/views/admin/dashboard.php b/views/admin/dashboard.php new file mode 100644 index 0000000..2d55ead --- /dev/null +++ b/views/admin/dashboard.php @@ -0,0 +1,145 @@ + + +
+
+

Dashboard Overview

+ +
+ +
+
+
+
+
+
+
Total APKs
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
Total Downloads
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
Total Users
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
Pending Withdrawals
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
Recent APKs
+
+
+
+ + + + + + + + + + + + + + + + + + + +
TitleVersionDownloadsStatus
+
+ +
v + + + +
+
+
+
+
+ + +
+
+ + \ No newline at end of file diff --git a/views/admin/footer.php b/views/admin/footer.php new file mode 100644 index 0000000..793508f --- /dev/null +++ b/views/admin/footer.php @@ -0,0 +1,12 @@ + + + + + + diff --git a/views/admin/header.php b/views/admin/header.php new file mode 100644 index 0000000..b7f44ce --- /dev/null +++ b/views/admin/header.php @@ -0,0 +1,74 @@ + + + + + + Admin Panel - APK Portal + + + + + + diff --git a/views/admin/login.php b/views/admin/login.php new file mode 100644 index 0000000..4aaf0f8 --- /dev/null +++ b/views/admin/login.php @@ -0,0 +1,53 @@ + + + + + + Admin Login - ApkNusa + + + + +
+

ApkNusa Admin

+ +
+ +
+
+ + +
+
+ + +
+ +
+
+ + diff --git a/views/admin/withdrawals/index.php b/views/admin/withdrawals/index.php new file mode 100644 index 0000000..a34fb54 --- /dev/null +++ b/views/admin/withdrawals/index.php @@ -0,0 +1,72 @@ + + +
+
+

Withdrawal Requests

+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UserAmount (IDR)MethodDetailsDateStatusActions
No withdrawal requests found.
+
+
+ Rp + + + + + + + + + +
+
+
+
+
+ + diff --git a/views/apk_detail.php b/views/apk_detail.php index 3d204b6..a1a2ba6 100644 --- a/views/apk_detail.php +++ b/views/apk_detail.php @@ -4,7 +4,11 @@ @@ -13,7 +17,10 @@
- <?php echo $apk['title']; ?> + + <?php echo $apk['title']; ?>

v

Official and original version. Verified safe for Android device.

@@ -25,10 +32,11 @@ VIP
- - Download APK Now + + + Download Now -

File size: ~45MB (approx.) | Android 6.0 or higher

+

By clicking Download, you agree to our terms of service.

@@ -64,67 +72,48 @@
Is this safe to download?
-

Yes, every APK on ApkNusa is scanned for malware and verified to ensure it is the original, unmodified file from the developer.

+

Yes, every app on ApkNusa is scanned and verified to ensure it is original and safe from the official developers.

-
-
Popular Similar Apps
-
-
- Facebook -
-
Facebook
- Social Media -
- View -
-
- TikTok -
-
TikTok
- Entertainment -
- View -
-
- YouTube -
-
YouTube
- Video Player -
- View -
+
+
Share & Earn
+

Share this link and earn Rp 500 for every download!

+
+ query("SELECT referral_code FROM users WHERE id = ".$_SESSION['user_id'])->fetchColumn() : ''; + $shareLink = 'http://'.$_SERVER['HTTP_HOST'].'/apk/'.$apk['slug'].($ref ? '?ref='.$ref : ''); + ?> + +
-
- See all Apps + + Login to earn money +
-
- -
Join our community
-

Register today to enjoy premium features, earn rewards, and track your download history.

- Join Now +
+ +
Referral Program
+

Join our community, share APKs, and get paid directly to your e-wallet or bank account.

+ Get Started
- -
- -
- + diff --git a/views/auth/login.php b/views/auth/login.php new file mode 100644 index 0000000..091f1f5 --- /dev/null +++ b/views/auth/login.php @@ -0,0 +1,33 @@ + + +
+
+
+
+

Login to ApkNusa

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

Don't have an account? Register here

+
+
+
+
+
+ + diff --git a/views/auth/profile.php b/views/auth/profile.php new file mode 100644 index 0000000..de2ebf9 --- /dev/null +++ b/views/auth/profile.php @@ -0,0 +1,165 @@ + + +
+
+
+
+
+
+ +
+

+

Member since

+
+
+
+

+ Points +
+
+

+ Referrals +
+
+
+
+ +
+
+
Current Balance
+

Rp

+ +

Min. withdraw: Rp 10.000

+
+
+
+ +
+ +
+ + +
+ + +
+
+
My Referral Code
+
+
+

Share your referral link to earn Rp 500 for every download.

+
+ + +
+
Example APK referral link:
+
+ +
+
+
+ +
+
+
Withdrawal History
+ Recent activities +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
DateAmountMethodStatus
No withdrawal history yet.
Rp + + + + +
+
+
+
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/views/auth/register.php b/views/auth/register.php new file mode 100644 index 0000000..155a62d --- /dev/null +++ b/views/auth/register.php @@ -0,0 +1,43 @@ + + +
+
+
+
+

Register for ApkNusa

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

Already have an account? Login here

+
+
+
+
+
+ + diff --git a/views/header.php b/views/header.php index ece91a6..a2df323 100644 --- a/views/header.php +++ b/views/header.php @@ -13,12 +13,12 @@ -
@@ -18,20 +18,36 @@
-
+

Latest Releases

- View All +
-
+
- <?php echo $apk['title']; ?> + + <?php echo $apk['title']; ?>
-
+
v VIP @@ -41,7 +57,7 @@

@@ -54,7 +70,7 @@

Start your referral journey today

-

Join our community, share your favorite APKs, and earn reward points for every successful referral download.

+

Earn Rp 500 for every download via your link. Join our community and share your favorite APKs.

Get Started @@ -63,4 +79,4 @@
- + \ No newline at end of file