feat: Tái cấu trúc bot sang kiến trúc cog, thêm hỗ trợ đa máy chủ, giới thiệu tính năng đăng ký bóng đá, giao diện web và quản lý cấu hình.

This commit is contained in:
2026-01-16 17:26:42 +07:00
parent 8c38357c28
commit b24365927a
39 changed files with 3864 additions and 997 deletions
+575
View File
@@ -0,0 +1,575 @@
/* Global Vars for Dark Mode */
:root {
--bg-color: #1a1a1a;
--sidebar-bg: #121212;
--sidebar-item-hover: #ffffff0d;
--card-bg: #262626;
--text-color: #e5e5e5;
--text-muted: #a3a3a3;
--border-color: #404040;
--accent-color: #3b82f6;
--accent-hover: #2563eb;
--danger-color: #ef4444;
--header-bg: #1f1f1f;
--bg-surface: #1f1f1f;
}
body {
font-family: 'Inter', 'Segoe UI', Tahoma, sans-serif;
margin: 0;
padding: 0;
background-color: var(--bg-color);
color: var(--text-color);
line-height: 1.5;
}
/* Layout */
.app-container {
display: flex;
height: 100vh;
overflow: hidden;
}
/* Sidebar */
.sidebar {
width: 280px;
background-color: var(--sidebar-bg);
display: flex;
flex-direction: column;
border-right: 1px solid var(--border-color);
flex-shrink: 0;
}
.brand-header {
height: 64px;
display: flex;
align-items: center;
padding: 0 20px;
border-bottom: 1px solid var(--border-color);
background-color: #00000022;
}
.brand-logo {
font-size: 24px;
margin-right: 12px;
}
.brand-header h1 {
margin: 0;
font-size: 1.1rem;
font-weight: 700;
line-height: 1.2;
}
.brand-header span {
font-size: 0.8rem;
color: var(--text-muted);
font-weight: 400;
}
.sidebar-section-title {
padding: 20px 20px 10px 20px;
font-size: 0.75rem;
font-weight: 700;
color: #666;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.server-list {
list-style: none;
padding: 0 10px;
margin: 0;
overflow-y: auto;
}
.server-item {
padding: 12px 16px;
margin-bottom: 4px;
border-radius: 6px;
cursor: pointer;
font-size: 0.95rem;
font-weight: 500;
color: #d4d4d4;
transition: all 0.2s;
border: 1px solid transparent;
}
.server-item:hover {
background-color: var(--sidebar-item-hover);
color: white;
}
.server-item.active {
background-color: #3b82f622;
color: var(--accent-color);
border-color: #3b82f644;
}
/* Main Content */
.main-content {
flex-grow: 1;
display: flex;
flex-direction: column;
min-width: 0;
}
.top-bar {
height: 64px;
background-color: var(--header-bg);
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 30px;
flex-shrink: 0;
}
.top-bar h2 {
margin: 0;
font-size: 1.25rem;
font-weight: 600;
}
.user-profile {
font-size: 0.9rem;
color: var(--text-muted);
display: flex;
align-items: center;
gap: 10px;
}
.user-profile::before {
content: "";
/* Avatar placeholder */
width: 32px;
height: 32px;
background-color: #333;
border-radius: 50%;
}
.content-area {
padding: 30px;
overflow-y: auto;
/* Custom scrollbar */
scrollbar-width: thin;
scrollbar-color: #404040 transparent;
}
.hidden {
display: none !important;
}
/* Tabs */
.tabs {
display: flex;
gap: 20px;
border-bottom: 1px solid var(--border-color);
margin-bottom: 30px;
}
.tab-btn {
padding: 12px 4px;
background: none;
border: none;
cursor: pointer;
font-size: 0.95rem;
font-weight: 500;
color: var(--text-muted);
border-bottom: 2px solid transparent;
transition: color 0.2s;
}
.tab-btn:hover {
color: var(--text-color);
}
.tab-btn.active {
color: var(--accent-color);
border-bottom-color: var(--accent-color);
}
.tab-pane {
display: none;
}
.tab-pane.active {
display: block;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(5px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Cards */
.card {
background: var(--card-bg);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 24px;
margin-bottom: 24px;
}
h3 {
margin-top: 0;
font-size: 1.1rem;
margin-bottom: 1rem;
}
h4 {
margin: 1.5rem 0 1rem 0;
font-size: 1rem;
}
.text-muted {
color: var(--text-muted);
font-size: 0.9rem;
margin-bottom: 15px;
}
/* Forms */
.form-row {
display: flex;
gap: 20px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-size: 0.9rem;
font-weight: 500;
color: #d4d4d4;
}
.form-group input {
width: 100%;
padding: 10px 12px;
background-color: #171717;
border: 1px solid var(--border-color);
border-radius: 6px;
color: white;
font-size: 0.95rem;
box-sizing: border-box;
transition: border-color 0.2s;
}
.form-group input:focus {
outline: none;
border-color: var(--accent-color);
background-color: #0a0a0a;
}
/* Services */
.service-card {
background: var(--card-bg);
border: 1px solid var(--border-color);
border-radius: 8px;
margin-bottom: 20px;
/* overflow: hidden; Removed to allow dropdowns to show */
}
.service-header {
background-color: #1f1f1f;
padding: 16px 20px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border-color);
}
.service-header h3 {
margin: 0;
font-size: 1rem;
}
.service-body {
padding: 20px;
}
.service-body.disabled {
opacity: 0.5;
pointer-events: none;
}
/* Buttons */
.btn {
padding: 8px 16px;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
font-size: 0.9rem;
transition: all 0.2s;
}
.btn.primary {
background-color: var(--accent-color);
color: white;
}
.btn.primary:hover {
background-color: var(--accent-hover);
}
.btn.secondary {
background-color: #404040;
color: white;
border: 1px solid #525252;
}
.btn.secondary:hover {
background-color: #525252;
}
.btn.danger {
background-color: transparent;
color: var(--danger-color);
border: 1px solid var(--danger-color);
}
.btn.danger:hover {
background-color: var(--danger-color);
color: white;
}
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* Table */
.table-container {
border: 1px solid var(--border-color);
border-radius: 6px;
overflow: hidden;
}
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
text-align: left;
padding: 12px 16px;
border-bottom: 1px solid var(--border-color);
}
th {
background-color: #1f1f1f;
color: #d4d4d4;
font-weight: 600;
font-size: 0.85rem;
text-transform: uppercase;
}
tr:last-child td {
border-bottom: none;
}
tr:hover td {
background-color: #333;
}
/* Info Grid */
.server-info-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 20px;
}
.info-item {
background: #1f1f1f;
padding: 20px;
border-radius: 8px;
text-align: center;
border: 1px solid var(--border-color);
}
.info-item label {
display: block;
color: var(--text-muted);
font-size: 0.85rem;
margin-bottom: 8px;
}
.info-item span {
font-size: 1.5rem;
font-weight: 700;
color: white;
}
/* Toggle */
.switch {
position: relative;
display: inline-block;
width: 44px;
height: 24px;
}
.switch input {
display: none;
}
.slider {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #404040;
transition: .3s;
border-radius: 34px;
}
.slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 3px;
bottom: 3px;
background-color: white;
transition: .3s;
border-radius: 50%;
}
input:checked+.slider {
background-color: var(--accent-color);
}
input:checked+.slider:before {
transform: translateX(20px);
}
/* Loading Overlay */
.loading-overlay {
position: absolute;
top: 64px;
/* Below header */
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 50;
backdrop-filter: blur(2px);
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid rgba(255, 255, 255, 0.1);
border-left-color: var(--accent-color);
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 15px;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.loading-overlay p {
color: var(--text-color);
font-weight: 500;
}
/* Inline Spinner */
/* Spinner for buttons */
.spinner-sm {
width: 14px;
height: 14px;
border: 2px solid rgba(255, 255, 255, 0.3);
border-left-color: white;
border-radius: 50%;
animation: spin 0.8s linear infinite;
display: inline-block;
vertical-align: middle;
margin-right: 5px;
}
/* Multi-Select & Tags */
.tags-container {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 5px;
padding: 5px;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 4px;
min-height: 38px;
}
.tag {
background: var(--accent-color);
color: white;
padding: 2px 8px;
border-radius: 12px;
font-size: 0.85em;
display: flex;
align-items: center;
gap: 5px;
}
.tag .remove {
cursor: pointer;
font-weight: bold;
opacity: 0.7;
}
.tag .remove:hover {
opacity: 1;
}
.dropdown-results {
position: absolute;
background: var(--bg-surface);
border: 1px solid var(--border-color);
width: 100%;
max-height: 200px;
overflow-y: auto;
z-index: 100;
margin-top: 5px;
display: none;
border-radius: 4px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
.dropdown-results.show {
display: block;
}
.dropdown-item {
padding: 8px 12px;
cursor: pointer;
border-bottom: 1px solid var(--border-color);
}
.dropdown-item:hover {
background: var(--bg-secondary);
}
.dropdown-item:last-child {
border-bottom: none;
}