V baru
This commit is contained in:
parent
01072acc88
commit
3d02f25bbd
38
app/Controllers/AIController.php
Normal file
38
app/Controllers/AIController.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Core\Controller;
|
||||
|
||||
class AIController extends Controller {
|
||||
|
||||
public function chat() {
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$userMessage = $input['message'] ?? '';
|
||||
|
||||
if (empty($userMessage)) {
|
||||
echo json_encode(['error' => 'Message is empty']);
|
||||
return;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../../ai/LocalAIApi.php';
|
||||
|
||||
$systemPrompt = "You are a helpful assistant for " . get_setting('site_name', 'ApkNusa') . ", an APK downloader and tech blog site. Provide concise and accurate information about Android apps, games, and technology. Be youthful and professional.";
|
||||
|
||||
$resp = \LocalAIApi::createResponse([
|
||||
'input' => [
|
||||
['role' => 'system', 'content' => $systemPrompt],
|
||||
['role' => 'user', 'content' => $userMessage],
|
||||
],
|
||||
]);
|
||||
|
||||
if (!empty($resp['success'])) {
|
||||
$text = \LocalAIApi::extractText($resp);
|
||||
echo json_encode(['reply' => $text]);
|
||||
} else {
|
||||
echo json_encode(['error' => 'AI Assistant is currently unavailable.']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -54,11 +54,18 @@ class AdminController extends Controller {
|
||||
'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)
|
||||
'recent_apks' => array_slice($apkService->getAllApks(), 0, 5),
|
||||
'referral_stats' => $this->getReferralStats()
|
||||
];
|
||||
$this->view('admin/dashboard', $stats);
|
||||
}
|
||||
|
||||
private function getReferralStats() {
|
||||
$db = db_pdo();
|
||||
$stmt = $db->query("SELECT DATE(created_at) as date, COUNT(*) as count FROM referral_downloads WHERE created_at > DATE_SUB(NOW(), INTERVAL 7 DAY) GROUP BY DATE(created_at) ORDER BY date ASC");
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
|
||||
private function getTotalDownloads() {
|
||||
$db = db_pdo();
|
||||
return $db->query("SELECT SUM(total_downloads) FROM apks")->fetchColumn() ?: 0;
|
||||
@ -239,6 +246,7 @@ class AdminController extends Controller {
|
||||
$this->checkAuth();
|
||||
$settings = [
|
||||
'site_name' => get_setting('site_name'),
|
||||
'contact_email' => get_setting('contact_email'),
|
||||
'site_icon' => get_setting('site_icon'),
|
||||
'site_favicon' => get_setting('site_favicon'),
|
||||
'meta_description' => get_setting('meta_description'),
|
||||
@ -251,6 +259,7 @@ class AdminController extends Controller {
|
||||
'github_url' => get_setting('github_url'),
|
||||
'telegram_url' => get_setting('telegram_url'),
|
||||
'whatsapp_url' => get_setting('whatsapp_url'),
|
||||
'maintenance_mode' => get_setting('maintenance_mode'),
|
||||
];
|
||||
$this->view('admin/settings', ['settings' => $settings]);
|
||||
}
|
||||
@ -260,7 +269,7 @@ class AdminController extends Controller {
|
||||
$db = db_pdo();
|
||||
|
||||
$fields = [
|
||||
'site_name', 'meta_description', 'meta_keywords', 'head_js', 'body_js',
|
||||
'site_name', 'contact_email', 'meta_description', 'meta_keywords', 'head_js', 'body_js',
|
||||
'facebook_url', 'twitter_url', 'instagram_url', 'github_url', 'telegram_url', 'whatsapp_url'
|
||||
];
|
||||
foreach ($fields as $field) {
|
||||
|
||||
45
app/Controllers/ContactController.php
Normal file
45
app/Controllers/ContactController.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Core\Controller;
|
||||
use MailService;
|
||||
|
||||
class ContactController extends Controller {
|
||||
|
||||
public function index() {
|
||||
$this->view('contact', [
|
||||
'title' => __('contact_us') . ' - ' . get_setting('site_name', 'ApkNusa')
|
||||
]);
|
||||
}
|
||||
|
||||
public function submit() {
|
||||
$name = $_POST['name'] ?? '';
|
||||
$email = $_POST['email'] ?? '';
|
||||
$subject = $_POST['subject'] ?? 'New Contact Message';
|
||||
$message = $_POST['message'] ?? '';
|
||||
|
||||
if (empty($name) || empty($email) || empty($message)) {
|
||||
$_SESSION['error'] = 'All fields are required.';
|
||||
$this->redirect('/contact');
|
||||
}
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$_SESSION['error'] = 'Invalid email address.';
|
||||
$this->redirect('/contact');
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../../mail/MailService.php';
|
||||
|
||||
$res = \MailService::sendContactMessage($name, $email, $message, null, $subject);
|
||||
|
||||
if (!empty($res['success'])) {
|
||||
$_SESSION['success'] = 'Your message has been sent successfully!';
|
||||
} else {
|
||||
$_SESSION['error'] = 'Failed to send message. Please try again later.';
|
||||
// Log error if needed: error_log($res['error']);
|
||||
}
|
||||
|
||||
$this->redirect('/contact');
|
||||
}
|
||||
}
|
||||
33
app/Controllers/NewsletterController.php
Normal file
33
app/Controllers/NewsletterController.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Core\Controller;
|
||||
|
||||
class NewsletterController extends Controller {
|
||||
|
||||
public function subscribe() {
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$email = $input['email'] ?? '';
|
||||
|
||||
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
echo json_encode(['error' => 'Please provide a valid email address.']);
|
||||
return;
|
||||
}
|
||||
|
||||
$db = db_pdo();
|
||||
try {
|
||||
$stmt = $db->prepare("INSERT INTO newsletter_subscribers (email) VALUES (?)");
|
||||
$stmt->execute([$email]);
|
||||
echo json_encode(['success' => 'Thank you for subscribing!']);
|
||||
} catch (\PDOException $e) {
|
||||
if ($e->getCode() == 23000) { // Duplicate entry
|
||||
echo json_encode(['success' => 'You are already subscribed!']);
|
||||
} else {
|
||||
echo json_encode(['error' => 'An error occurred. Please try again.']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -38,10 +38,21 @@ class SitemapController extends Controller {
|
||||
echo '</url>';
|
||||
}
|
||||
|
||||
// Blog Posts
|
||||
$posts = $db->query("SELECT * FROM posts WHERE status = 'published'")->fetchAll();
|
||||
foreach ($posts as $post) {
|
||||
echo '<url>';
|
||||
echo '<loc>' . $baseUrl . '/blog/' . htmlspecialchars($post['slug']) . '</loc>';
|
||||
echo '<lastmod>' . date('Y-m-d', strtotime($post['created_at'] ?? 'now')) . '</lastmod>';
|
||||
echo '<priority>0.7</priority>';
|
||||
echo '<changefreq>monthly</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 '<loc>' . $baseUrl . '/?category=' . htmlspecialchars($category['slug']) . '</loc>';
|
||||
echo '<priority>0.6</priority>';
|
||||
echo '<changefreq>weekly</changefreq>';
|
||||
echo '</url>';
|
||||
|
||||
@ -91,13 +91,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
dropdownBtn.innerHTML = `${categoryName} <i class="bi bi-chevron-down ms-1 small"></i>`;
|
||||
}
|
||||
|
||||
// Update title if not searching
|
||||
if (latestTitle && !url.includes('search=')) {
|
||||
// We could use translations here but for simplicity we'll just use the category name
|
||||
// if it's All Categories, we'll reset to original (usually "Latest APKs")
|
||||
// However, we'll just keep it simple for now.
|
||||
}
|
||||
|
||||
// Update URL without refreshing
|
||||
window.history.pushState({ category: category }, '', url);
|
||||
})
|
||||
@ -115,6 +108,90 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
};
|
||||
|
||||
// AI Chat Assistant Logic
|
||||
const initAIChat = () => {
|
||||
const toggleBtn = document.getElementById('toggle-ai-chat');
|
||||
const closeBtn = document.getElementById('close-ai-chat');
|
||||
const chatWindow = document.getElementById('ai-chat-window');
|
||||
const chatInput = document.getElementById('ai-chat-input');
|
||||
const sendBtn = document.getElementById('send-ai-chat');
|
||||
const messagesContainer = document.getElementById('ai-chat-messages');
|
||||
|
||||
if (!toggleBtn || !chatWindow) return;
|
||||
|
||||
toggleBtn.addEventListener('click', () => {
|
||||
chatWindow.classList.toggle('d-none');
|
||||
if (!chatWindow.classList.contains('d-none')) {
|
||||
chatInput.focus();
|
||||
}
|
||||
});
|
||||
|
||||
closeBtn.addEventListener('click', () => {
|
||||
chatWindow.classList.add('d-none');
|
||||
});
|
||||
|
||||
const appendMessage = (message, isUser = false) => {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'mb-3 d-flex ' + (isUser ? 'justify-content-end' : '');
|
||||
|
||||
const content = document.createElement('div');
|
||||
content.className = (isUser ? 'bg-success text-white' : 'bg-white') + ' p-3 rounded-4 shadow-sm small';
|
||||
content.style.maxWidth = '85%';
|
||||
if (isUser) {
|
||||
content.style.borderBottomRightRadius = '0';
|
||||
} else {
|
||||
content.style.borderBottomLeftRadius = '0';
|
||||
}
|
||||
content.textContent = message;
|
||||
|
||||
div.appendChild(content);
|
||||
messagesContainer.appendChild(div);
|
||||
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
||||
};
|
||||
|
||||
const sendMessage = () => {
|
||||
const message = chatInput.value.trim();
|
||||
if (!message) return;
|
||||
|
||||
appendMessage(message, true);
|
||||
chatInput.value = '';
|
||||
|
||||
// Loading state
|
||||
const loadingDiv = document.createElement('div');
|
||||
loadingDiv.className = 'mb-3 d-flex';
|
||||
loadingDiv.innerHTML = '<div class="bg-white p-3 rounded-4 shadow-sm small" style="border-bottom-left-radius: 0 !important;"><div class="spinner-border spinner-border-sm text-success" role="status"></div> Thinking...</div>';
|
||||
messagesContainer.appendChild(loadingDiv);
|
||||
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
||||
|
||||
fetch('/api/ai/chat', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ message: message })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
messagesContainer.removeChild(loadingDiv);
|
||||
if (data.reply) {
|
||||
appendMessage(data.reply);
|
||||
} else {
|
||||
appendMessage(data.error || 'Sorry, something went wrong.');
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
messagesContainer.removeChild(loadingDiv);
|
||||
appendMessage('Error connecting to AI assistant.');
|
||||
console.error(err);
|
||||
});
|
||||
};
|
||||
|
||||
sendBtn.addEventListener('click', sendMessage);
|
||||
chatInput.addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter') sendMessage();
|
||||
});
|
||||
};
|
||||
|
||||
// Initial Sync
|
||||
const currentTheme = html.getAttribute('data-theme') || 'light';
|
||||
updateIcons(currentTheme);
|
||||
@ -132,6 +209,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
initThemeToggle('theme-toggle');
|
||||
initThemeToggle('theme-toggle-mobile');
|
||||
initCategoryAjax();
|
||||
initAIChat();
|
||||
|
||||
console.log('ApkNusa ready.');
|
||||
});
|
||||
});
|
||||
14
index.php
14
index.php
@ -28,7 +28,19 @@ session_start();
|
||||
|
||||
use App\Core\Router;
|
||||
|
||||
// Maintenance Mode Check
|
||||
if (get_setting('maintenance_mode') === '1') {
|
||||
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||
$isAdmin = strpos($uri, '/admin') === 0 || strpos($uri, '/login') === 0 || strpos($uri, '/logout') === 0;
|
||||
if (!$isAdmin && !isset($_SESSION['admin_id'])) {
|
||||
require_once 'views/maintenance.php';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$router = new Router();
|
||||
$router->post('/api/newsletter/subscribe', 'NewsletterController@subscribe');
|
||||
$router->post('/api/ai/chat', 'AIController@chat');
|
||||
|
||||
// Sitemap
|
||||
$router->get('/sitemap.xml', 'SitemapController@index');
|
||||
@ -51,6 +63,8 @@ $router->get('/blog', 'BlogController@index');
|
||||
$router->get('/blog/:slug', 'BlogController@detail');
|
||||
|
||||
// Static Pages
|
||||
$router->get('/contact', 'ContactController@index');
|
||||
$router->post('/contact', 'ContactController@submit');
|
||||
$router->get('/help-center', 'HomeController@helpCenter');
|
||||
$router->get('/privacy-policy', 'HomeController@privacyPolicy');
|
||||
$router->get('/terms-of-service', 'HomeController@termsOfService');
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
<?php include __DIR__ . '/../header.php'; ?>
|
||||
|
||||
<div class="container-fluid py-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div class="d-flex align-items-center mb-4">
|
||||
<h1 class="h3 mb-0 text-gray-800">Manage APKs</h1>
|
||||
<form action="/admin/apks" method="GET" class="d-flex gap-2 ms-auto me-3">
|
||||
<input type="text" name="search" class="form-control form-control-sm" placeholder="Search APKs..." value="<?php echo htmlspecialchars($_GET['search'] ?? ''); ?>">
|
||||
<button type="submit" class="btn btn-sm btn-outline-secondary"><i class="bi bi-search"></i></button>
|
||||
</form>
|
||||
<a href="/admin/apks/add" class="btn btn-primary shadow-sm">
|
||||
<i class="bi bi-plus-lg me-1"></i> Add New APK
|
||||
</a>
|
||||
|
||||
@ -79,6 +79,68 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm border-0 rounded-4 bg-white">
|
||||
<div class="card-header bg-white py-3 border-bottom border-light d-flex justify-content-between align-items-center">
|
||||
<h6 class="m-0 font-weight-bold text-primary fw-bold">Referral Downloads (Last 7 Days)</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<canvas id="referralChart" style="height: 300px; width: 100%;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const ctx = document.getElementById('referralChart').getContext('2d');
|
||||
const stats = <?php echo json_encode($referral_stats); ?>;
|
||||
|
||||
const labels = stats.map(s => s.date);
|
||||
const counts = stats.map(s => s.count);
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: labels.length ? labels : ['No Data'],
|
||||
datasets: [{
|
||||
label: 'Referral Downloads',
|
||||
data: counts.length ? counts : [0],
|
||||
borderColor: '#10B981',
|
||||
backgroundColor: 'rgba(16, 185, 129, 0.1)',
|
||||
fill: true,
|
||||
tension: 0.4,
|
||||
pointRadius: 5,
|
||||
pointBackgroundColor: '#10B981'
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
grid: {
|
||||
color: 'rgba(0, 0, 0, 0.05)'
|
||||
}
|
||||
},
|
||||
x: {
|
||||
grid: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm border-0 rounded-4 mb-4 bg-white">
|
||||
|
||||
@ -10,6 +10,10 @@
|
||||
<div class="card-body p-4">
|
||||
<form action="/admin/settings" method="POST" enctype="multipart/form-data">
|
||||
<div class="mb-4">
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-semibold">Contact Email</label>
|
||||
<input type="email" name="contact_email" class="form-control" value="<?php echo htmlspecialchars($settings['contact_email'] ?? ''); ?>" placeholder="support@yourdomain.com">
|
||||
</div>
|
||||
<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>
|
||||
@ -35,6 +39,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4 p-3 bg-light rounded border">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" name="maintenance_mode" value="1" id="maintenanceMode" <?php echo ($settings['maintenance_mode'] ?? '0') === '1' ? 'checked' : ''; ?>>
|
||||
<label class="form-check-label fw-bold" for="maintenanceMode">
|
||||
<i class="fas fa-tools me-2 text-warning"></i>Maintenance Mode
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-text mt-1">When enabled, regular visitors will see a maintenance page. Admins can still access the site.</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>
|
||||
|
||||
@ -129,4 +143,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
<?php include 'footer.php'; ?>
|
||||
|
||||
78
views/contact.php
Normal file
78
views/contact.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php include 'header.php'; ?>
|
||||
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow border-0 rounded-4 overflow-hidden">
|
||||
<div class="row g-0">
|
||||
<div class="col-lg-5 bg-success p-5 text-white d-flex flex-column justify-content-center">
|
||||
<h2 class="fw-bold mb-4">Get in Touch</h2>
|
||||
<p class="mb-4 opacity-75">Have questions or feedback about our APKs? We'd love to hear from you. Send us a message and we'll respond as soon as possible.</p>
|
||||
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<i class="bi bi-geo-alt-fill me-3 fs-4"></i>
|
||||
<span>Jakarta, Indonesia</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<i class="bi bi-envelope-fill me-3 fs-4"></i>
|
||||
<span><?php echo get_setting('contact_email', 'support@apknusa.com'); ?></span>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 pt-4 border-top border-white border-opacity-25">
|
||||
<h6 class="fw-bold mb-3">Follow Us</h6>
|
||||
<div class="d-flex gap-3">
|
||||
<?php if($fb = get_setting('facebook_url')): ?><a href="<?php echo $fb; ?>" class="text-white fs-5"><i class="bi bi-facebook"></i></a><?php endif; ?>
|
||||
<?php if($tw = get_setting('twitter_url')): ?><a href="<?php echo $tw; ?>" class="text-white fs-5"><i class="bi bi-twitter-x"></i></a><?php endif; ?>
|
||||
<?php if($ig = get_setting('instagram_url')): ?><a href="<?php echo $ig; ?>" class="text-white fs-5"><i class="bi bi-instagram"></i></a><?php endif; ?>
|
||||
<?php if($tg = get_setting('telegram_url')): ?><a href="<?php echo $tg; ?>" class="text-white fs-5"><i class="bi bi-telegram"></i></a><?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-7 p-5 bg-white">
|
||||
<?php if (isset($_SESSION['success'])): ?>
|
||||
<div class="alert alert-success alert-dismissible fade show rounded-3 mb-4" role="alert">
|
||||
<i class="bi bi-check-circle-fill me-2"></i>
|
||||
<?php echo $_SESSION['success']; unset($_SESSION['success']); ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($_SESSION['error'])): ?>
|
||||
<div class="alert alert-danger alert-dismissible fade show rounded-3 mb-4" role="alert">
|
||||
<i class="bi bi-exclamation-triangle-fill me-2"></i>
|
||||
<?php echo $_SESSION['error']; unset($_SESSION['error']); ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form action="/contact" method="POST">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold small text-uppercase">Full Name</label>
|
||||
<input type="text" name="name" class="form-control form-control-lg bg-light border-0 px-4" placeholder="Your Name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold small text-uppercase">Email Address</label>
|
||||
<input type="email" name="email" class="form-control form-control-lg bg-light border-0 px-4" placeholder="name@example.com" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold small text-uppercase">Subject</label>
|
||||
<input type="text" name="subject" class="form-control form-control-lg bg-light border-0 px-4" placeholder="How can we help?">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold small text-uppercase">Message</label>
|
||||
<textarea name="message" class="form-control bg-light border-0 px-4 py-3" rows="4" placeholder="Your message here..." required></textarea>
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-success btn-lg rounded-pill py-3 fw-bold">
|
||||
Send Message <i class="bi bi-send-fill ms-2"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@ -30,15 +30,17 @@
|
||||
<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>
|
||||
<li><a href="/contact" class="text-muted text-decoration-none py-1 d-block small">Contact Us</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<h6 class="fw-bold mb-3"><?php echo __('subscribe'); ?></h6>
|
||||
<p class="text-muted small"><?php echo __('subscribe_text'); ?></p>
|
||||
<div class="input-group">
|
||||
<input type="email" class="form-control border-light-subtle" placeholder="<?php echo __('email_placeholder'); ?>">
|
||||
<button class="btn btn-success px-3" type="button"><?php echo __('subscribe'); ?></button>
|
||||
<input type="email" id="newsletter-email" class="form-control border-light-subtle" placeholder="<?php echo __('email_placeholder'); ?>">
|
||||
<button class="btn btn-success px-3" id="newsletter-btn" type="button"><?php echo __('subscribe'); ?></button>
|
||||
</div>
|
||||
<div id="newsletter-msg" class="mt-2 small"></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-5 text-black-50 opacity-25">
|
||||
@ -71,8 +73,85 @@
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- AI Chat Assistant -->
|
||||
<div id="ai-chat-wrapper" class="fixed-bottom p-3 d-flex flex-column align-items-end" style="z-index: 1050; pointer-events: none;">
|
||||
<div id="ai-chat-window" class="card shadow-lg border-0 mb-3 d-none" style="width: 350px; max-width: 90vw; height: 450px; pointer-events: auto; border-radius: 20px;">
|
||||
<div class="card-header bg-success text-white py-3 d-flex justify-content-between align-items-center" style="border-radius: 20px 20px 0 0;">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-white rounded-circle p-1 me-2">
|
||||
<i class="bi bi-robot text-success"></i>
|
||||
</div>
|
||||
<span class="fw-bold">ApkNusa AI</span>
|
||||
</div>
|
||||
<button type="button" class="btn-close btn-close-white" id="close-ai-chat"></button>
|
||||
</div>
|
||||
<div class="card-body overflow-auto p-3" id="ai-chat-messages" style="background: var(--subtle-bg);">
|
||||
<div class="mb-3">
|
||||
<div class="bg-white p-3 rounded-4 shadow-sm small" style="max-width: 85%; border-bottom-left-radius: 0 !important;">
|
||||
Hello! How can I help you today?
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-white border-0 p-3" style="border-radius: 0 0 20px 20px;">
|
||||
<div class="input-group">
|
||||
<input type="text" id="ai-chat-input" class="form-control border-light-subtle rounded-pill-start px-3" placeholder="Type a message...">
|
||||
<button class="btn btn-success rounded-pill-end px-3" id="send-ai-chat">
|
||||
<i class="bi bi-send-fill"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-success shadow-lg d-flex align-items-center justify-content-center p-0 rounded-circle" id="toggle-ai-chat" style="width: 60px; height: 60px; pointer-events: auto;">
|
||||
<i class="bi bi-chat-dots-fill fs-3"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#ai-chat-messages::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
#ai-chat-messages::-webkit-scrollbar-thumb {
|
||||
background: #10B981;
|
||||
border-radius: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||
<script>
|
||||
document.getElementById('newsletter-btn').addEventListener('click', function() {
|
||||
const email = document.getElementById('newsletter-email').value;
|
||||
const msg = document.getElementById('newsletter-msg');
|
||||
|
||||
if (!email) return;
|
||||
|
||||
this.disabled = true;
|
||||
this.innerHTML = '<span class="spinner-border spinner-border-sm"></span>';
|
||||
|
||||
fetch('/api/newsletter/subscribe', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email: email })
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
this.disabled = false;
|
||||
this.innerHTML = '<?php echo __("subscribe"); ?>';
|
||||
if (data.success) {
|
||||
msg.innerHTML = '<span class="text-success">' + data.success + '</span>';
|
||||
document.getElementById('newsletter-email').value = '';
|
||||
} else {
|
||||
msg.innerHTML = '<span class="text-danger">' + data.error + '</span>';
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
this.disabled = false;
|
||||
this.innerHTML = '<?php echo __("subscribe"); ?>';
|
||||
msg.innerHTML = '<span class="text-danger">An error occurred.</span>';
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php echo get_setting('body_js'); ?>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
50
views/maintenance.php
Normal file
50
views/maintenance.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
$currentTheme = \App\Services\ThemeService::getCurrent();
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="<?php echo $currentTheme; ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Under Maintenance - <?php echo htmlspecialchars(get_setting('site_name', 'ApkNusa')); ?></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.11.1/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="/assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
text-align: center;
|
||||
background: var(--bg-color);
|
||||
color: var(--text-color);
|
||||
}
|
||||
.maintenance-container {
|
||||
max-width: 500px;
|
||||
padding: 2rem;
|
||||
background: var(--card-bg);
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
.icon-wrapper {
|
||||
font-size: 5rem;
|
||||
color: #10B981;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="maintenance-container">
|
||||
<div class="icon-wrapper">
|
||||
<i class="bi bi-tools"></i>
|
||||
</div>
|
||||
<h1 class="fw-bold mb-3">Under Maintenance</h1>
|
||||
<p class="text-muted mb-4">We're currently performing some scheduled maintenance. We'll be back shortly. Thank you for your patience!</p>
|
||||
<div class="d-flex justify-content-center gap-3">
|
||||
<a href="mailto:<?php echo get_setting('contact_email'); ?>" class="btn btn-outline-success rounded-pill px-4">Contact Support</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user