dptxa-proxy / src /pages /admin /cai-dat.astro
TXAVLOG
Deploy DPTXA to Hugging Face Spaces
4bea261
Raw
History Blame Contribute Delete
38.7 kB
---
import AdminLayout from '../../layouts/AdminLayout.astro';
import { txasupabase } from '../../lib/txasupabase.js';
const settings = await txasupabase.getSettings();
---
<AdminLayout title="Cấu hình hệ thống">
<div class="mb-12">
<h1 class="text-4xl font-black tracking-tighter text-white">Cấu hình Hệ thống</h1>
<p class="mt-2 text-gray-500">Thiết lập toàn bộ tham số hoạt động của website, máy chủ SMTP email và cơ chế xác thực người dùng.</p>
</div>
<div class="glass rounded-[40px] p-8 md:p-10 border border-white/5 space-y-8">
<!-- Tab Header -->
<div class="flex flex-wrap gap-3 border-b border-white/5 pb-6">
<button id="btn-tab-general" class="tab-btn active-tab flex items-center gap-2 rounded-2xl px-6 py-3.5 text-xs font-black uppercase tracking-widest transition-all cursor-pointer">
<i class="fas fa-desktop"></i> Cấu hình chung
</button>
<button id="btn-tab-smtp" class="tab-btn flex items-center gap-2 rounded-2xl px-6 py-3.5 text-xs font-black uppercase tracking-widest transition-all cursor-pointer">
<i class="fas fa-envelope"></i> SMTP Email
</button>
<button id="btn-tab-user" class="tab-btn flex items-center gap-2 rounded-2xl px-6 py-3.5 text-xs font-black uppercase tracking-widest transition-all cursor-pointer">
<i class="fas fa-user-shield"></i> Người dùng
</button>
<button id="btn-tab-social" class="tab-btn flex items-center gap-2 rounded-2xl px-6 py-3.5 text-xs font-black uppercase tracking-widest transition-all cursor-pointer">
<i class="fas fa-share-alt"></i> Mạng xã hội
</button>
</div>
<!-- Tab Contents Form -->
<form id="settings-form" class="space-y-8">
<!-- 1. Tab General -->
<div id="tab-general" class="tab-content space-y-6">
<div class="grid gap-6 md:grid-cols-2">
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Tên Website</label>
<input type="text" id="site_name" name="site_name" placeholder="Ví dụ: TPHIMX" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
<p class="text-[11px] text-gray-500 font-medium">Hiển thị ở hậu tố tiêu đề các trang (Ví dụ: Trang chủ | TPHIMX).</p>
</div>
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">URL Website</label>
<input type="url" id="site_url" name="site_url" placeholder="Ví dụ: https://tphimx.com" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
<p class="text-[11px] text-gray-500 font-medium">Đường dẫn đầy đủ dùng để sinh link xác minh tài khoản, khôi phục mật khẩu.</p>
</div>
</div>
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Mô tả Website (SEO Description)</label>
<textarea id="site_description" name="site_description" rows="3" placeholder="Mô tả website..." class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all resize-none"></textarea>
</div>
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Từ khóa Website (SEO Keywords)</label>
<input type="text" id="site_keywords" name="site_keywords" placeholder="Ví dụ: xem phim online, phim vietsub, phim hd, phim moi, phim bo" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
<p class="text-[11px] text-gray-500 font-medium">Các từ khóa cách nhau bởi dấu phẩy, giúp các công cụ tìm kiếm dễ dàng tìm thấy website.</p>
</div>
</div>
<!-- 2. Tab SMTP -->
<div id="tab-smtp" class="tab-content hidden space-y-6">
<div class="grid gap-6 md:grid-cols-3">
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">SMTP Host</label>
<input type="text" id="smtp_host" name="smtp_host" placeholder="smtp.gmail.com" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">SMTP Port</label>
<input type="number" id="smtp_port" name="smtp_port" placeholder="465" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Bảo mật SMTP</label>
<select id="smtp_secure" name="smtp_secure" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all cursor-pointer">
<option value="SSL">SSL (Khuyên dùng - Port 465)</option>
<option value="TLS">TLS (Port 587)</option>
<option value="NONE">Không bảo mật</option>
</select>
</div>
</div>
<div class="grid gap-6 md:grid-cols-2">
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Tài khoản SMTP</label>
<input type="text" id="smtp_user" name="smtp_user" placeholder="gmail_cua_ban@gmail.com" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Mật khẩu ứng dụng SMTP</label>
<input type="password" id="smtp_pass" name="smtp_pass" placeholder="••••••••••••••••" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
</div>
<div class="grid gap-6 md:grid-cols-2">
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Email người gửi</label>
<input type="email" id="smtp_from_email" name="smtp_from_email" placeholder="no-reply@tphimx.com" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Tên người gửi</label>
<input type="text" id="smtp_from_name" name="smtp_from_name" placeholder="TPHIMX" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
</div>
<div class="pt-4 border-t border-white/5 flex justify-end">
<button type="button" id="btn-test-smtp" class="flex items-center gap-2 rounded-2xl bg-emerald-500/10 hover:bg-emerald-500 text-emerald-400 hover:text-white border border-emerald-500/20 px-6 py-3.5 text-xs font-black uppercase tracking-widest transition-all active:scale-95 cursor-pointer">
<i class="fas fa-paper-plane"></i> Gửi email test
</button>
</div>
</div>
<!-- 3. Tab User -->
<div id="tab-user" class="tab-content hidden space-y-6">
<div class="grid gap-6 md:grid-cols-2">
<!-- Cho phép đăng ký -->
<div class="glass-sub rounded-3xl p-6 border border-white/5 flex items-center justify-between">
<div>
<h3 class="text-sm font-bold text-white">Cho phép Đăng ký tài khoản</h3>
<p class="text-xs text-gray-500 mt-1">Cho phép khách truy cập đăng ký tài khoản mới trên trang web.</p>
</div>
<label class="relative inline-flex items-center cursor-pointer select-none">
<input type="checkbox" id="allow_registration" name="allow_registration" class="sr-only peer" />
<div class="w-11 h-6 bg-white/10 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-gray-300 after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
</label>
</div>
<!-- Xác minh email đăng ký -->
<div id="verify-email-box" class="glass-sub rounded-3xl p-6 border border-white/5 flex items-center justify-between transition-all duration-300">
<div>
<h3 class="text-sm font-bold text-white">Bắt buộc Xác minh Email</h3>
<p class="text-xs text-gray-500 mt-1">Yêu cầu xác nhận qua email trước khi tài khoản được phép sử dụng.</p>
</div>
<label class="relative inline-flex items-center cursor-pointer select-none">
<input type="checkbox" id="require_email_verification" name="require_email_verification" class="sr-only peer" />
<div class="w-11 h-6 bg-white/10 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-gray-300 after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
</label>
</div>
</div>
<div class="grid gap-6 md:grid-cols-2">
<!-- Thời gian hết hạn của token xác minh mail (giây) -->
<div id="expiry-verification-box" class="space-y-2 transition-all duration-300">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Hết hạn Token Xác minh Email (Giây)</label>
<input type="number" id="verification_token_expiry" name="verification_token_expiry" placeholder="3600" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
<p class="text-[11px] text-gray-500 font-medium">Thời gian mã xác minh có hiệu lực. Mặc định 3600 giây (1 giờ).</p>
</div>
<!-- Thời gian hết hạn của token quên mật khẩu (giây) -->
<div class="space-y-2">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Hết hạn Token Quên mật khẩu (Giây)</label>
<input type="number" id="reset_password_token_expiry" name="reset_password_token_expiry" placeholder="1800" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
<p class="text-[11px] text-gray-500 font-medium">Thời gian link reset mật khẩu có hiệu lực. Mặc định 1800 giây (30 phút).</p>
</div>
</div>
</div>
<!-- 4. Tab Social -->
<div id="tab-social" class="tab-content hidden space-y-6">
<div class="grid gap-6 md:grid-cols-2">
<!-- Facebook Page -->
<div class="glass-sub rounded-3xl p-6 border border-white/5 space-y-4">
<div class="flex items-center justify-between">
<div>
<h3 class="text-sm font-bold text-white flex items-center gap-2">
<i class="fab fa-facebook text-[#1877F2]"></i> Trang Facebook (Page)
</h3>
<p class="text-xs text-gray-500 mt-1">Bật để hiển thị biểu tượng link Facebook Page dưới footer.</p>
</div>
<label class="relative inline-flex items-center cursor-pointer select-none">
<input type="checkbox" id="social_fb_enable" name="social_fb_enable" class="sr-only peer" />
<div class="w-11 h-6 bg-white/10 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-gray-300 after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
</label>
</div>
<div id="box-social_fb_url" class="space-y-2 transition-all duration-300">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Đường dẫn Facebook Page</label>
<input type="url" id="social_fb_url" name="social_fb_url" placeholder="https://www.facebook.com/tphimx" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
</div>
<!-- Facebook Group -->
<div class="glass-sub rounded-3xl p-6 border border-white/5 space-y-4">
<div class="flex items-center justify-between">
<div>
<h3 class="text-sm font-bold text-white flex items-center gap-2">
<i class="fas fa-users text-[#1877F2]"></i> Nhóm Facebook (Group)
</h3>
<p class="text-xs text-gray-500 mt-1">Bật để hiển thị biểu tượng link Facebook Group dưới footer.</p>
</div>
<label class="relative inline-flex items-center cursor-pointer select-none">
<input type="checkbox" id="social_fb_group_enable" name="social_fb_group_enable" class="sr-only peer" />
<div class="w-11 h-6 bg-white/10 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-gray-300 after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
</label>
</div>
<div id="box-social_fb_group_url" class="space-y-2 transition-all duration-300">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Đường dẫn Facebook Group</label>
<input type="url" id="social_fb_group_url" name="social_fb_group_url" placeholder="https://www.facebook.com/groups/1819522938713878" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
</div>
<!-- Zalo Group -->
<div class="glass-sub rounded-3xl p-6 border border-white/5 space-y-4">
<div class="flex items-center justify-between">
<div>
<h3 class="text-sm font-bold text-white flex items-center gap-2">
<i class="fas fa-comments text-[#0068FF]"></i> Nhóm Zalo (Group)
</h3>
<p class="text-xs text-gray-500 mt-1">Bật để hiển thị biểu tượng link Zalo Group dưới footer.</p>
</div>
<label class="relative inline-flex items-center cursor-pointer select-none">
<input type="checkbox" id="social_zalo_group_enable" name="social_zalo_group_enable" class="sr-only peer" />
<div class="w-11 h-6 bg-white/10 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-gray-300 after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
</label>
</div>
<div id="box-social_zalo_group_url" class="space-y-2 transition-all duration-300">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Đường dẫn Zalo Group</label>
<input type="url" id="social_zalo_group_url" name="social_zalo_group_url" placeholder="https://zalo.me/g/nc4aaozaxnr5fszvnxdb" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
</div>
<!-- Telegram -->
<div class="glass-sub rounded-3xl p-6 border border-white/5 space-y-4">
<div class="flex items-center justify-between">
<div>
<h3 class="text-sm font-bold text-white flex items-center gap-2">
<i class="fab fa-telegram text-[#24A1DE]"></i> Telegram Channel / Contact
</h3>
<p class="text-xs text-gray-500 mt-1">Bật để hiển thị biểu tượng link Telegram dưới footer.</p>
</div>
<label class="relative inline-flex items-center cursor-pointer select-none">
<input type="checkbox" id="social_telegram_enable" name="social_telegram_enable" class="sr-only peer" />
<div class="w-11 h-6 bg-white/10 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-gray-300 after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
</label>
</div>
<div id="box-social_telegram_url" class="space-y-2 transition-all duration-300">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Đường dẫn Telegram</label>
<input type="url" id="social_telegram_url" name="social_telegram_url" placeholder="https://t.me/yourchannel" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
</div>
<!-- Tiktok -->
<div class="glass-sub rounded-3xl p-6 border border-white/5 space-y-4">
<div class="flex items-center justify-between">
<div>
<h3 class="text-sm font-bold text-white flex items-center gap-2">
<i class="fab fa-tiktok text-white"></i> Kênh TikTok
</h3>
<p class="text-xs text-gray-500 mt-1">Bật để hiển thị biểu tượng link TikTok dưới footer.</p>
</div>
<label class="relative inline-flex items-center cursor-pointer select-none">
<input type="checkbox" id="social_tiktok_enable" name="social_tiktok_enable" class="sr-only peer" />
<div class="w-11 h-6 bg-white/10 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-gray-300 after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
</label>
</div>
<div id="box-social_tiktok_url" class="space-y-2 transition-all duration-300">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Đường dẫn TikTok</label>
<input type="url" id="social_tiktok_url" name="social_tiktok_url" placeholder="https://www.tiktok.com/@yourchannel" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
</div>
<!-- Instagram -->
<div class="glass-sub rounded-3xl p-6 border border-white/5 space-y-4">
<div class="flex items-center justify-between">
<div>
<h3 class="text-sm font-bold text-white flex items-center gap-2">
<i class="fab fa-instagram text-[#E1306C]"></i> Kênh Instagram
</h3>
<p class="text-xs text-gray-500 mt-1">Bật để hiển thị biểu tượng link Instagram dưới footer.</p>
</div>
<label class="relative inline-flex items-center cursor-pointer select-none">
<input type="checkbox" id="social_instagram_enable" name="social_instagram_enable" class="sr-only peer" />
<div class="w-11 h-6 bg-white/10 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-gray-300 after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
</label>
</div>
<div id="box-social_instagram_url" class="space-y-2 transition-all duration-300">
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500">Đường dẫn Instagram</label>
<input type="url" id="social_instagram_url" name="social_instagram_url" placeholder="https://www.instagram.com/yourusername" class="w-full bg-[#12141d] border border-white/5 rounded-2xl px-5 py-4 text-sm text-white focus:outline-none focus:border-primary/50 transition-all" />
</div>
</div>
</div>
</div>
<!-- Submit Button -->
<div class="pt-8 border-t border-white/5 flex justify-end">
<button type="submit" class="flex items-center gap-2 rounded-2xl bg-primary px-8 py-4 text-xs font-black uppercase tracking-widest text-dark hover:scale-105 transition-all shadow-[0_0_20px_var(--primary)] cursor-pointer">
<i class="fas fa-save"></i> Lưu cài đặt
</button>
</div>
</form>
</div>
</AdminLayout>
<script is:inline define:vars={{ initialSettings: settings }}>
let currentTab = 'general';
function checkSmtpTestButtonStatus() {
const testSmtpBtn = document.getElementById('btn-test-smtp');
if (!testSmtpBtn) return;
const userVal = document.getElementById('smtp_user')?.value?.trim() || '';
const passVal = document.getElementById('smtp_pass')?.value?.trim() || '';
const isModified = userVal !== (initialSettings.smtp_user || '') || passVal !== (initialSettings.smtp_pass || '');
if (!initialSettings.smtp_user || !initialSettings.smtp_pass) {
testSmtpBtn.setAttribute('disabled', 'true');
testSmtpBtn.style.opacity = '0.4';
testSmtpBtn.style.cursor = 'not-allowed';
testSmtpBtn.setAttribute('data-txatooltip', 'Vui lòng nhập tài khoản và mật khẩu SMTP rồi bấm Lưu cài đặt trước khi gửi thử!');
} else if (isModified) {
testSmtpBtn.setAttribute('disabled', 'true');
testSmtpBtn.style.opacity = '0.4';
testSmtpBtn.style.cursor = 'not-allowed';
testSmtpBtn.setAttribute('data-txatooltip', 'Có cấu hình SMTP thay đổi chưa lưu! Vui lòng bấm Lưu cài đặt trước khi gửi thử.');
} else {
testSmtpBtn.removeAttribute('disabled');
testSmtpBtn.style.opacity = '';
testSmtpBtn.style.cursor = 'pointer';
testSmtpBtn.removeAttribute('data-txatooltip');
}
if (window.initTxaTooltips) {
window.initTxaTooltips();
}
}
function initTabs() {
const tabs = ['general', 'smtp', 'user', 'social'];
tabs.forEach(tab => {
const btn = document.getElementById(`btn-tab-${tab}`);
const content = document.getElementById(`tab-${tab}`);
if (btn && content) {
btn.onclick = (e) => {
e.preventDefault();
// Hide all contents & remove active class from all buttons
tabs.forEach(t => {
const b = document.getElementById(`btn-tab-${t}`);
const c = document.getElementById(`tab-${t}`);
b?.classList.remove('active-tab');
c?.classList.add('hidden');
});
// Show clicked tab
btn.classList.add('active-tab');
content.classList.remove('hidden');
currentTab = tab;
};
}
});
}
function fillForm() {
const form = document.getElementById('settings-form');
if (!form) return;
// Text inputs
const keys = [
'site_name', 'site_url', 'site_description', 'site_keywords',
'smtp_host', 'smtp_port', 'smtp_secure', 'smtp_user', 'smtp_pass', 'smtp_from_email', 'smtp_from_name',
'verification_token_expiry', 'reset_password_token_expiry',
'social_fb_url', 'social_fb_group_url', 'social_zalo_group_url', 'social_telegram_url', 'social_tiktok_url', 'social_instagram_url'
];
keys.forEach(key => {
const input = document.getElementById(key);
if (input && initialSettings[key] !== undefined) {
input.value = initialSettings[key];
}
});
// Checkbox inputs (Boolean)
const boolKeys = [
'allow_registration', 'require_email_verification',
'social_fb_enable', 'social_fb_group_enable', 'social_zalo_group_enable', 'social_telegram_enable', 'social_tiktok_enable', 'social_instagram_enable'
];
boolKeys.forEach(key => {
const input = document.getElementById(key);
if (input && initialSettings[key] !== undefined) {
input.checked = initialSettings[key];
}
});
updateVisibility();
checkSmtpTestButtonStatus();
}
function updateVisibility() {
const allowReg = document.getElementById('allow_registration');
const verifyBox = document.getElementById('verify-email-box');
const requireVerify = document.getElementById('require_email_verification');
const expiryBox = document.getElementById('expiry-verification-box');
// 1. Cho phép đăng ký
if (allowReg && verifyBox) {
if (allowReg.checked) {
verifyBox.classList.remove('opacity-40', 'pointer-events-none');
const chk = verifyBox.querySelector('input');
if (chk) chk.disabled = false;
} else {
verifyBox.classList.add('opacity-40', 'pointer-events-none');
const chk = verifyBox.querySelector('input');
if (chk) {
chk.checked = false;
chk.disabled = true;
}
}
}
// 2. Bắt buộc xác minh email
if (requireVerify && expiryBox) {
if (requireVerify.checked && (!allowReg || allowReg.checked)) {
expiryBox.classList.remove('opacity-40', 'pointer-events-none');
const inp = expiryBox.querySelector('input');
if (inp) inp.disabled = false;
} else {
expiryBox.classList.add('opacity-40', 'pointer-events-none');
const inp = expiryBox.querySelector('input');
if (inp) inp.disabled = true;
}
}
// 3. Mạng xã hội (Ẩn ô nhập link khi chưa bật)
const socials = ['social_fb', 'social_fb_group', 'social_zalo_group', 'social_telegram', 'social_tiktok', 'social_instagram'];
socials.forEach(s => {
const chk = document.getElementById(`${s}_enable`);
const box = document.getElementById(`box-${s}_url`);
if (chk && box) {
if (chk.checked) {
box.classList.remove('hidden');
const inp = box.querySelector('input');
if (inp) inp.disabled = false;
} else {
box.classList.add('hidden');
const inp = box.querySelector('input');
if (inp) inp.disabled = true;
}
}
});
}
function setupEventListeners() {
const form = document.getElementById('settings-form');
// Toggle change events
const allowReg = document.getElementById('allow_registration');
const requireVerify = document.getElementById('require_email_verification');
allowReg?.addEventListener('change', updateVisibility);
requireVerify?.addEventListener('change', updateVisibility);
// Watch for Social Switches change events
const socials = ['social_fb', 'social_fb_group', 'social_zalo_group', 'social_telegram', 'social_tiktok', 'social_instagram'];
socials.forEach(s => {
document.getElementById(`${s}_enable`)?.addEventListener('change', updateVisibility);
});
// Watch for input changes to dynamically disable SMTP test button if unsaved changes exist
document.getElementById('smtp_user')?.addEventListener('input', checkSmtpTestButtonStatus);
document.getElementById('smtp_pass')?.addEventListener('input', checkSmtpTestButtonStatus);
// Save Settings
form?.addEventListener('submit', async (e) => {
e.preventDefault();
const btn = form.querySelector('button[type="submit"]');
if (btn) btn.disabled = true;
const formData = {};
// Text and Select elements
const inputs = form.querySelectorAll('input[type="text"], input[type="url"], input[type="number"], input[type="password"], textarea, select');
inputs.forEach(inp => {
const name = inp.getAttribute('name');
if (name) {
let val = inp.value;
if (inp.getAttribute('type') === 'number') {
val = Number(val);
}
formData[name] = val;
}
});
// Toggles
const checkboxes = form.querySelectorAll('input[type="checkbox"]');
checkboxes.forEach(chk => {
const name = chk.getAttribute('name');
if (name) {
formData[name] = chk.checked;
}
});
try {
const res = await fetch('/api/admin/settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
});
const data = await res.json();
if (res.ok) {
window.txatoast.success(data.message);
// Cập nhật lại initialSettings và trạng thái nút test SMTP
initialSettings.smtp_user = formData.smtp_user;
initialSettings.smtp_pass = formData.smtp_pass;
checkSmtpTestButtonStatus();
} else {
window.txatoast.error(data.error);
}
} catch(e) {
window.txatoast.error('Lỗi lưu cấu hình máy chủ!');
} finally {
if (btn) btn.disabled = false;
}
});
// Test SMTP Email connection
const testSmtpBtn = document.getElementById('btn-test-smtp');
testSmtpBtn?.addEventListener('click', () => {
// Gather current smtp settings to test connection before save
const smtpOptions = {
smtp_host: document.getElementById('smtp_host').value.trim(),
smtp_port: Number(document.getElementById('smtp_port').value.trim()),
smtp_secure: document.getElementById('smtp_secure').value,
smtp_user: document.getElementById('smtp_user').value.trim(),
smtp_pass: document.getElementById('smtp_pass').value.trim(),
smtp_from_email: document.getElementById('smtp_from_email').value.trim(),
smtp_from_name: document.getElementById('smtp_from_name').value.trim(),
site_url: document.getElementById('site_url').value.trim(),
site_name: document.getElementById('site_name').value.trim()
};
if (!smtpOptions.smtp_host || !smtpOptions.smtp_port || !smtpOptions.smtp_user || !smtpOptions.smtp_pass) {
window.txatoast.warning('Vui lòng điền đầy đủ cấu hình SMTP (Host, Port, Tài khoản, Mật khẩu) trước khi gửi thử!');
return;
}
window.txamodal.show({
title: 'Gửi thử Email Test',
message: `
<div class="space-y-4 text-left">
<p class="text-xs text-gray-500">Mã kiểm thử sẽ gửi một Email thử nghiệm mẫu bằng cấu hình bạn đang điền phía trên.</p>
<div>
<label class="block text-[10px] font-black uppercase tracking-widest text-gray-500 mb-1">Địa chỉ Email nhận</label>
<input type="email" id="test-recipient-email" placeholder="vi_du@gmail.com" class="w-full bg-[#12141d] border border-white/5 rounded-xl px-4 py-2.5 text-sm text-white focus:outline-none focus:border-primary/50" />
</div>
</div>`,
type: 'success',
confirmText: 'Gửi ngay',
onConfirm: async () => {
const testEmailInput = document.getElementById('test-recipient-email');
const testEmail = testEmailInput ? testEmailInput.value.trim() : '';
if (!testEmail) {
window.txatoast.error('Email nhận không được để trống!');
return false;
}
// Nút đổi trạng thái (Loading state)
const confirmBtn = document.getElementById('txamodal-confirm');
const cancelBtn = document.getElementById('txamodal-cancel');
const originalConfirmHtml = confirmBtn ? confirmBtn.innerHTML : 'Gửi ngay';
if (confirmBtn) {
confirmBtn.innerHTML = '<i class="fas fa-circle-notch fa-spin mr-2"></i> Đang gửi...';
confirmBtn.disabled = true;
confirmBtn.style.opacity = '0.6';
confirmBtn.style.cursor = 'not-allowed';
}
if (cancelBtn) {
cancelBtn.disabled = true;
cancelBtn.style.opacity = '0.5';
cancelBtn.style.cursor = 'not-allowed';
}
window.txatoast.info('Đang bắt đầu gửi thư thử nghiệm...');
try {
const res = await fetch('/api/admin/test-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
toEmail: testEmail,
smtpOptions
})
});
const data = await res.json();
if (res.ok) {
window.txatoast.success(data.message);
// Reset state lại nút và đóng modal
if (confirmBtn) {
confirmBtn.innerHTML = originalConfirmHtml;
confirmBtn.disabled = false;
confirmBtn.style.opacity = '';
confirmBtn.style.cursor = 'pointer';
}
if (cancelBtn) {
cancelBtn.disabled = false;
cancelBtn.style.opacity = '';
cancelBtn.style.cursor = 'pointer';
}
window.txamodal.hide();
return true;
} else {
window.txatoast.error(data.error);
// Reset state lại nút (không đóng modal để họ sửa lại email hoặc kiểm tra lại cấu hình)
if (confirmBtn) {
confirmBtn.innerHTML = originalConfirmHtml;
confirmBtn.disabled = false;
confirmBtn.style.opacity = '';
confirmBtn.style.cursor = 'pointer';
}
if (cancelBtn) {
cancelBtn.disabled = false;
cancelBtn.style.opacity = '';
cancelBtn.style.cursor = 'pointer';
}
return false;
}
} catch(e) {
window.txatoast.error('Lỗi kết nối máy chủ gửi thử!');
// Reset state lại nút
if (confirmBtn) {
confirmBtn.innerHTML = originalConfirmHtml;
confirmBtn.disabled = false;
confirmBtn.style.opacity = '';
confirmBtn.style.cursor = 'pointer';
}
if (cancelBtn) {
cancelBtn.disabled = false;
cancelBtn.style.opacity = '';
cancelBtn.style.cursor = 'pointer';
}
return false;
}
}
});
});
}
function init() {
initTabs();
fillForm();
setupEventListeners();
}
document.addEventListener('astro:page-load', init);
</script>
<style>
.glass {
background: rgba(18, 20, 29, 0.4);
backdrop-filter: blur(40px) saturate(200%);
}
.glass-sub {
background: rgba(255, 255, 255, 0.02);
}
.tab-btn {
color: #6b7280;
border: 1px solid rgba(255, 255, 255, 0.05);
background: rgba(255, 255, 255, 0.02);
}
.tab-btn:hover {
color: #ffffff;
background: rgba(255, 255, 255, 0.05);
}
.active-tab {
background: #7c3aed !important;
color: #ffffff !important;
border-color: #7c3aed !important;
box-shadow: 0 0 15px rgba(124, 58, 237, 0.4);
}
</style>