Files
ebook-extension/ebook_backend&admin_panel/admin-frontend/admin_dashboard.html

1860 lines
41 KiB
HTML

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<!--
Admin Panel - Coupon Management System
-->
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Panel - Coupon Management</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<style>
/*
Basic reset and foundational styles for consistent rendering across browsers
*/
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/*
Body styling with gradient background and typography settings
Creates a professional look with Inter font family
*/
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: #333;
}
/*
=====================
DASHBOARD LAYOUT
=====================
Main container for the dashboard with flexbox layout
*/
.dashboard-container {
display: flex;
min-height: 100vh;
}
/*
Fixed header with user information and logout functionality
Positioned at the top with backdrop blur effect for modern appearance
*/
.dashboard-header {
position: fixed;
top: 0;
right: 0;
left: 280px;
height: 70px;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20px);
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
justify-content: flex-end;
padding: 0 30px;
z-index: 999;
}
/*
User information display in header
Shows avatar, name, role with proper spacing
*/
.header-user-info {
display: flex;
align-items: center;
gap: 15px;
}
/*
Circular user avatar with gradient background
Contains user icon with proper centering
*/
.user-avatar {
width: 40px;
height: 40px;
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 600;
font-size: 16px;
}
/*
User details container for name and role
Stacked vertically with appropriate typography
*/
.user-details {
display: flex;
flex-direction: column;
}
.user-name {
font-weight: 600;
font-size: 14px;
color: #374151;
}
.user-role {
font-size: 12px;
color: #6b7280;
}
/*
Logout button with gradient background and hover effects
Includes smooth transitions and visual feedback
*/
.logout-btn {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 16px;
background: linear-gradient(135deg, #ef4444, #dc2626);
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
transition: all 0.3s ease;
text-decoration: none;
}
.logout-btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
background: linear-gradient(135deg, #dc2626, #b91c1c);
}
.logout-btn:active {
transform: translateY(0);
}
/*
Fixed sidebar with navigation tabs and header
*/
.sidebar {
width: 280px;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20px);
border-right: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 0 40px rgba(0, 0, 0, 0.1);
position: fixed;
height: 100vh;
z-index: 1000;
transition: all 0.3s ease;
}
/*
Sidebar header with app branding
Gradient background matching the theme
*/
.sidebar-header {
padding: 30px 25px;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
}
.sidebar-header h2 {
font-size: 24px;
font-weight: 700;
margin-bottom: 5px;
}
.sidebar-header p {
font-size: 14px;
opacity: 0.9;
font-weight: 300;
}
/*
Navigation container for tabs
*/
.sidebar-nav {
padding: 20px 0;
}
/*
Individual navigation tabs with hover and active states
Includes shimmer effect and smooth transitions
*/
.tab {
display: flex;
align-items: center;
padding: 16px 25px;
margin: 4px 15px;
border-radius: 12px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 500;
color: #4a5568;
position: relative;
overflow: hidden;
}
/*
Shimmer effect for tab hover animation
Creates a light sweep across the tab
*/
.tab:before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent);
transition: left 0.5s;
}
.tab:hover:before {
left: 100%;
}
.tab:hover {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
transform: translateX(5px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
}
.tab.active {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
}
.tab i {
margin-right: 15px;
font-size: 18px;
width: 20px;
text-align: center;
}
/*
Content area with proper spacing and card layout
*/
.content {
margin-left: 280px;
margin-top: 90px;
padding: 40px;
flex: 1;
background: transparent;
}
/*
Content cards with glassmorphism effect
Elevated design with backdrop blur and shadows
*/
.content-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20px);
border-radius: 20px;
padding: 40px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
margin-bottom: 30px;
transition: all 0.3s ease;
}
.content-card:hover {
transform: translateY(-5px);
box-shadow: 0 30px 80px rgba(0, 0, 0, 0.15);
}
/*
Content headers with gradient text and proper spacing
*/
.content-header {
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 2px solid #f1f5f9;
}
.content-header h2 {
font-size: 32px;
font-weight: 700;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 8px;
}
.content-header p {
color: #64748b;
font-size: 16px;
}
/*
Utility class for hiding elements
*/
.hidden {
display: none !important;
}
/*
Styling for form elements including inputs, radios, and file uploads
*/
.form-group {
margin-bottom: 25px;
}
.form-label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #374151;
font-size: 14px;
}
/*
Radio button groups with custom styling
*/
.radio-group {
display: flex;
gap: 20px;
margin-bottom: 20px;
}
.radio-option {
display: flex;
align-items: center;
cursor: pointer;
padding: 12px 20px;
border: 2px solid #e5e7eb;
border-radius: 12px;
transition: all 0.3s ease;
background: #f9fafb;
}
.radio-option:hover {
border-color: #667eea;
background: #f0f4ff;
}
.radio-option input[type="radio"] {
margin-right: 10px;
transform: scale(1.2);
accent-color: #667eea;
}
.radio-option.active {
border-color: #667eea;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
}
/*
Standard input styling with focus states
*/
input[type="text"], input[type="number"], input[type="file"] {
width: 100%;
padding: 15px 20px;
border: 2px solid #e5e7eb;
border-radius: 12px;
font-size: 16px;
transition: all 0.3s ease;
background: #f9fafb;
}
input[type="text"]:focus, input[type="number"]:focus, input[type="file"]:focus {
outline: none;
border-color: #667eea;
background: white;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
/*
Drag and drop file upload area with visual feedback
*/
.file-upload-area {
border: 2px dashed #d1d5db;
border-radius: 12px;
padding: 40px;
text-align: center;
background: #f9fafb;
transition: all 0.3s ease;
cursor: pointer;
position: relative;
margin-bottom: 20px;
}
.file-upload-area:hover {
border-color: #667eea;
background: #f0f4ff;
}
.file-upload-area.dragover {
border-color: #667eea;
background: #f0f4ff;
transform: scale(1.02);
}
.file-upload-icon {
font-size: 48px;
color: #9ca3af;
margin-bottom: 16px;
}
.file-upload-text {
color: #6b7280;
font-size: 16px;
margin-bottom: 8px;
}
.file-upload-hint {
color: #9ca3af;
font-size: 14px;
}
/*
File information display after selection
*/
.file-info {
background: #f0f9ff;
border: 1px solid #bae6fd;
border-radius: 8px;
padding: 12px 16px;
margin-top: 15px;
display: flex;
align-items: center;
gap: 10px;
}
.file-info i {
color: #0284c7;
}
/*
Data preview section with statistics and table display
*/
.preview-section {
margin-top: 30px;
padding-top: 30px;
border-top: 2px solid #f1f5f9;
}
.preview-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
/*
Statistics cards for data preview
*/
.preview-stats {
display: flex;
gap: 20px;
margin-bottom: 20px;
}
.stat-card {
background: linear-gradient(135deg, #f0f4ff, #e0e7ff);
border: 1px solid #c7d2fe;
border-radius: 8px;
padding: 12px 16px;
text-align: center;
min-width: 120px;
}
.stat-number {
font-size: 24px;
font-weight: 700;
color: #3730a3;
}
.stat-label {
font-size: 12px;
color: #6b7280;
text-transform: uppercase;
letter-spacing: 0.5px;
}
/*
Comprehensive button styling with variants and states
*/
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 15px 30px;
border: none;
border-radius: 12px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
position: relative;
overflow: hidden;
}
/*
Primary button variant with gradient background
*/
.btn-primary {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 12px 35px rgba(102, 126, 234, 0.4);
}
.btn-secondary {
background: #6b7280;
color: white;
}
.btn-secondary:hover {
background: #4b5563;
transform: translateY(-2px);
}
.btn-success {
background: linear-gradient(135deg, #10b981, #059669);
color: white;
}
.btn-success:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(16, 185, 129, 0.3);
}
.btn-danger {
background: linear-gradient(135deg, #ef4444, #dc2626);
color: white;
}
.btn-danger:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(239, 68, 68, 0.3);
}
.btn-sm {
padding: 8px 16px;
font-size: 14px;
}
.btn i {
margin-right: 8px;
}
/*
Small action buttons for table rows and inline actions
*/
.action-buttons {
display: flex;
gap: 8px;
justify-content:left;
align-items: center;
}
.action-btn {
padding: 6px 12px;
border: none;
border-radius: 6px;
font-size: 12px;
cursor: pointer;
transition: all 0.3s ease;
min-width: 35px;
height: 35px;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
}
.action-btn i {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
font-size: 14px;
}
.action-btn:hover {
transform: translateY(-1px);
}
.delete-btn {
background: #ef4444;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
.delete-btn:hover {
background: #dc2626;
}
.delete-btn i {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
font-size: 14px;
}
/*
Collapsible section for adding new codes
*/
.add-code-section {
border: 2px solid #00aaff;
border-radius: 10px;
padding: 10px;
background-color: #eaf6ff;
margin-bottom: 20px;
}
.add-code-header {
font-size: 18px;
font-weight: bold;
cursor: pointer;
color: #0077cc;
display: flex;
align-items: center;
gap: 10px;
}
#add-code-form .add-btn {
background-color: #1abc9c;
color: white;
border: none;
padding: 8px 12px;
border-radius: 6px;
cursor: pointer;
}
.hidden {
display: none;
}
/*
Search bar with clear button and styling
*/
.search-container {
position: relative;
margin-bottom: 30px;
}
/*
Search input with icon spacing and focus states
*/
.search-input {
width: 100%;
padding: 15px 55px 15px 60px;
border: 2px solid #e5e7eb;
border-radius: 12px;
font-size: 16px;
transition: all 0.3s ease;
background: #f9fafb;
}
.search-input:focus {
outline: none;
border-color: #667eea;
background: white;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
/*
Clear search button positioned absolutely
*/
.search-clear {
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
color: #6b7280;
cursor: pointer;
font-size: 16px;
display: none;
transition: color 0.3s ease;
z-index: 2;
padding: 5px;
}
.search-clear:hover {
color: #374151;
}
.search-clear.show {
display: block;
}
/*
Status and result display cards with variants
*/
.result-card {
margin-top: 25px;
padding: 20px;
border-radius: 12px;
border-left: 4px solid #667eea;
background: linear-gradient(135deg, #f0f4ff, #e0e7ff);
font-weight: 600;
color: #1e40af;
}
.result-card.success {
border-left-color: #10b981;
background: linear-gradient(135deg, #ecfdf5, #d1fae5);
color: #047857;
}
.result-card.error {
border-left-color: #ef4444;
background: linear-gradient(135deg, #fef2f2, #fecaca);
color: #dc2626;
}
.result-card.warning {
border-left-color: #f59e0b;
background: linear-gradient(135deg, #fffbeb, #fef3c7);
color: #d97706;
}
/*
Data table with modern styling and hover effects
*/
.table-container {
background: white;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
border: 1px solid #e5e7eb;
}
table {
width: 100%;
border-collapse: collapse;
}
/*
Table header with gradient background
*/
thead {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
}
th {
padding: 20px;
text-align: left;
font-weight: 600;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
/*
Table body rows with hover effects
*/
tbody tr {
transition: all 0.3s ease;
border-bottom: 1px solid #f1f5f9;
}
tbody tr:hover {
background: #f8fafc;
transform: scale(1.01);
}
tbody tr:last-child {
border-bottom: none;
}
tbody tr.highlight {
background: #fef3c7 !important;
transform: scale(1.02);
box-shadow: 0 4px 12px rgba(251, 191, 36, 0.3);
}
td {
padding: 18px 20px;
font-size: 14px;
color: #374151;
}
/*
Center align actions column
*/
td:last-child {
text-align: center;
}
/*
Modal dialogs with backdrop blur and animations
*/
.modal {
display: none;
position: fixed;
z-index: 2000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(5px);
}
.modal.show {
display: flex;
align-items: center;
justify-content: center;
animation: fadeIn 0.3s ease;
}
/*
Modal content container with proper styling
*/
.modal-content {
background: white;
padding: 30px;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
max-width: 500px;
width: 90%;
max-height: 90vh;
overflow-y: auto;
position: relative;
animation: slideUp 0.3s ease;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 25px;
padding-bottom: 15px;
border-bottom: 2px solid #f1f5f9;
}
.modal-header h3 {
font-size: 24px;
font-weight: 700;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.close-btn {
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #6b7280;
transition: color 0.3s ease;
}
.close-btn:hover {
color: #374151;
}
.modal-footer {
display: flex;
gap: 15px;
justify-content: flex-end;
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #f1f5f9;
}
/*
Pagination controls with page numbers and navigation
*/
.pagination-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 30px;
padding: 20px;
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.pagination-info {
color: #6b7280;
font-size: 14px;
font-weight: 500;
}
.pagination-controls {
display: flex;
align-items: center;
gap: 15px;
}
.page-numbers {
display: flex;
gap: 8px;
}
/*
Individual page number buttons
*/
.page-number {
padding: 8px 12px;
border: 2px solid #e5e7eb;
background: white;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
color: #6b7280;
transition: all 0.3s ease;
min-width: 40px;
text-align: center;
}
.page-number:hover {
border-color: #667eea;
background: #f0f4ff;
color: #667eea;
}
.page-number.active {
background: linear-gradient(135deg, #667eea, #764ba2);
border-color: #667eea;
color: white;
}
.page-ellipsis {
padding: 8px 4px;
color: #6b7280;
font-size: 14px;
}
.pagination-controls .btn {
padding: 8px 16px;
font-size: 14px;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none !important;
}
@media (max-width: 768px) {
.pagination-container {
flex-direction: column;
gap: 15px;
}
.page-numbers {
flex-wrap: wrap;
justify-content: center;
}
}
/*
Status badges for displaying item states
*/
.status-badge {
display: inline-flex;
align-items: center;
padding: 6px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.status-active {
background: #dcfce7;
color: #166534;
}
.status-limited {
background: #fef3c7;
color: #92400e;
}
/*
Empty state styling for when no data is available
*/
.no-results {
text-align: center;
padding: 40px 20px;
color: #6b7280;
}
.no-results i {
font-size: 48px;
margin-bottom: 16px;
opacity: 0.5;
}
.no-results h3 {
font-size: 18px;
margin-bottom: 8px;
font-weight: 600;
}
.no-results p {
font-size: 14px;
}
/*
Information displays for search results and validation
*/
.search-result-info {
background: linear-gradient(135deg, #ecfdf5, #d1fae5);
border: 2px solid #10b981;
border-radius: 12px;
padding: 15px 20px;
margin-bottom: 20px;
color: #047857;
font-weight: 600;
display: none;
}
.search-result-info.show {
display: block;
animation: slideIn 0.3s ease-out;
}
.search-result-info i {
margin-right: 8px;
color: #10b981;
}
.no-results-info {
background: linear-gradient(135deg, #fef2f2, #fecaca);
border: 2px solid #ef4444;
border-radius: 12px;
padding: 15px 20px;
margin-bottom: 20px;
color: #dc2626;
font-weight: 600;
display: none;
}
.no-results-info.show {
display: block;
animation: slideIn 0.3s ease-out;
}
.no-results-info i {
margin-right: 8px;
color: #ef4444;
}
/*
Error display for form validation and file upload issues
*/
.validation-errors {
background: linear-gradient(135deg, #fef2f2, #fecaca);
border: 2px solid #ef4444;
border-radius: 12px;
padding: 15px 20px;
margin-bottom: 20px;
}
.validation-errors h4 {
color: #dc2626;
font-size: 16px;
font-weight: 600;
margin-bottom: 10px;
}
.validation-errors ul {
list-style: none;
padding: 0;
}
.validation-errors li {
color: #dc2626;
font-size: 14px;
margin-bottom: 5px;
padding-left: 20px;
position: relative;
}
.validation-errors li:before {
content: '•';
position: absolute;
left: 0;
font-weight: bold;
}
/*
Keyframe animations for smooth UI transitions
*/
/*
Slide in animation for content reveals
*/
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/*
Fade in animation for modal backdrops
*/
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/*
Slide up animation for modal content
*/
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/*
Pulse animation for loading states
*/
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.7;
}
}
/*
Animation utility classes
*/
.slide-in {
animation: slideIn 0.5s ease-out;
}
.loading {
animation: pulse 1.5s infinite;
}
/*
Mobile-first responsive design for all screen sizes
*/
/*
Tablet responsive adjustments
*/
@media (max-width: 768px) {
.sidebar {
transform: translateX(-100%);
width: 100%;
}
.content {
margin-left: 0;
padding: 20px;
}
.content-card {
padding: 25px;
}
.add-code-form {
flex-direction: column;
}
.action-buttons {
flex-direction: column;
gap: 5px;
}
}
/*
Styled scrollbar for webkit browsers
*/
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #f1f5f9;
}
::-webkit-scrollbar-thumb {
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: linear-gradient(135deg, #5a67d8, #6b46c1);
}
/*
Comprehensive responsive design for all device sizes
*/
@media (max-width: 1024px) {
.content {
margin-left: 280px;
margin-top: 90px;
padding: 30px;
}
.content-card {
padding: 30px;
}
.content-header h2 {
font-size: 28px;
}
}
/*
Tablet screens (768px and below)
*/
@media (max-width: 768px) {
.dashboard-container {
flex-direction: column;
}
.sidebar {
width: 100%;
height: auto;
position: relative;
z-index: 1001;
}
.dashboard-header {
left: 0;
padding: 0 20px;
}
.content {
margin-left: 0;
margin-top: 0;
padding: 20px;
}
.content-card {
padding: 20px;
border-radius: 16px;
}
.content-header h2 {
font-size: 24px;
}
.content-header p {
font-size: 14px;
}
/*
Mobile navigation layout
*/
.sidebar-nav {
display: flex;
flex-wrap: wrap;
gap: 10px;
padding: 15px;
}
.tab {
flex: 1;
min-width: 120px;
margin: 0;
padding: 12px 15px;
font-size: 14px;
}
.tab i {
margin-right: 8px;
font-size: 16px;
}
/*
Responsive table handling
*/
.table-container {
overflow-x: auto;
}
#codeTable {
min-width: 600px;
}
/*
Responsive form elements
*/
.radio-group {
flex-direction: column;
gap: 10px;
}
.radio-option {
padding: 10px 15px;
}
/*
Responsive search bar
*/
.search-container {
flex-direction: column;
gap: 10px;
}
.search-input {
width: 100%;
}
/*
Responsive pagination
*/
.pagination-container {
flex-direction: column;
gap: 15px;
align-items: center;
}
.pagination-controls {
flex-wrap: wrap;
justify-content: center;
}
/*
Responsive file upload
*/
.file-upload-area {
padding: 30px 20px;
}
.file-upload-text {
font-size: 16px;
}
.file-upload-hint {
font-size: 12px;
}
}
/*
Mobile phones (480px and below)
*/
@media (max-width: 480px) {
.content {
padding: 15px;
}
.content-card {
padding: 15px;
border-radius: 12px;
}
.content-header h2 {
font-size: 20px;
}
.content-header p {
font-size: 13px;
}
/*
Mobile sidebar adjustments
*/
.sidebar-header {
padding: 20px 15px;
}
.sidebar-header h2 {
font-size: 20px;
}
.sidebar-header p {
font-size: 12px;
}
.tab {
padding: 10px 12px;
font-size: 13px;
min-width: 100px;
}
.tab i {
font-size: 14px;
margin-right: 6px;
}
/*
Mobile table styling
*/
#codeTable {
min-width: 400px;
font-size: 12px;
}
#codeTable th,
#codeTable td {
padding: 8px 6px;
}
/*
Mobile form elements
*/
input[type="text"],
input[type="number"],
input[type="file"] {
padding: 12px 15px;
font-size: 16px;
}
.btn {
padding: 12px 20px;
font-size: 14px;
}
/*
Mobile modal adjustments
*/
.modal-content {
margin: 20px;
padding: 20px;
max-width: calc(100% - 40px);
}
.modal-header h3 {
font-size: 18px;
}
.modal-body p {
font-size: 14px;
}
/*
Mobile file upload area
*/
.file-upload-area {
padding: 20px 15px;
}
.file-upload-text {
font-size: 14px;
}
.file-upload-hint {
font-size: 11px;
}
}
/*
Small mobile phones (360px and below)
*/
@media (max-width: 360px) {
.content {
padding: 10px;
}
.content-card {
padding: 12px;
}
.content-header h2 {
font-size: 18px;
}
.tab {
padding: 8px 10px;
font-size: 12px;
min-width: 80px;
}
.tab i {
font-size: 12px;
margin-right: 4px;
}
#codeTable {
min-width: 300px;
font-size: 11px;
}
.btn {
padding: 10px 16px;
font-size: 13px;
}
}
/*
Landscape orientation adjustments for mobile devices
*/
@media (max-height: 600px) and (orientation: landscape) {
.sidebar {
height: auto;
position: relative;
}
.content {
margin-top: 0;
}
.sidebar-nav {
flex-wrap: wrap;
gap: 8px;
}
.tab {
padding: 8px 12px;
font-size: 12px;
}
}
</style>
</head>
<body>
<!-- MAIN DASHBOARD STRUCTURE -->
<div class="dashboard-container">
<!-- DASHBOARD HEADER -->
<div class="dashboard-header">
<div class="header-user-info">
<!-- User avatar with admin icon -->
<div class="user-avatar">
<i class="fas fa-user-shield"></i>
</div>
<!-- User details display -->
<div class="user-details">
<div class="user-name">Bruno</div>
<div class="user-role">Administrator</div>
</div>
<!-- Logout button with confirmation modal trigger -->
<button class="logout-btn" onclick="handleLogout()">
<i class="fas fa-sign-out-alt"></i>
Logout
</button>
</div>
</div>
<!--
Fixed sidebar containing app branding and navigation tabs
-->
<div class="sidebar">
<!-- Sidebar header with app branding -->
<div class="sidebar-header">
<h2><i class="fas fa-ticket-alt"></i> CouponHub</h2>
<p>Admin Dashboard</p>
</div>
<!-- Navigation tabs for different sections -->
<nav class="sidebar-nav">
<div class="tab active" onclick="showTab('generate', event)">
<i class="fas fa-plus-circle"></i>
Generate Code
</div>
<div class="tab" onclick="showTab('list', event)">
<i class="fas fa-list-ul"></i>
List Codes
</div>
<div class="tab" onclick="showTab('upload', event)">
<i class="fas fa-upload"></i>
Upload Codes
</div>
<div class="tab" onclick="showTab('translation-upload', event)">
<i class="fas fa-language"></i>
Upload Translation
</div>
</nav>
</div>
<!--
Contains all the different tab contents and functionality
-->
<div class="content">
<!--
Interface for generating single or bulk coupon codes
-->
<div id="generate" class="slide-in">
<div class="content-card">
<div class="content-header">
<h2><i class="fas fa-magic"></i> Generate Coupon Code</h2>
<p>Create new coupon codes for your campaigns</p>
</div>
<!-- Generation mode selection (single vs bulk) -->
<div class="form-group">
<label class="form-label">Generation Mode</label>
<div class="radio-group">
<label class="radio-option active">
<input type="radio" name="genMode" value="single" checked>
<span><i class="fas fa-ticket-alt"></i> Single Code</span>
</label>
<label class="radio-option">
<input type="radio" name="genMode" value="bulk">
<span><i class="fas fa-tickets-alt"></i> Bulk Generation</span>
</label>
</div>
</div>
<!-- Bulk quantity input (hidden by default) -->
<div id="bulkCountWrapper" class="form-group hidden">
<label class="form-label" for="bulkCount">Number of Codes</label>
<input type="number" id="bulkCount" placeholder="Enter quantity">
</div>
<!-- Generate button -->
<button class="btn btn-primary" onclick="generateCode()">
<i class="fas fa-sparkles"></i>
Generate Codes
</button>
<!-- Result display area -->
<div id="genResult"></div>
</div>
</div>
<!--
Interface for viewing, searching, and managing existing coupon codes
-->
<div id="list" class="hidden slide-in">
<div class="content-card">
<div class="content-header">
<h2><i class="fas fa-database"></i> Coupon Codes Management</h2>
<p>Complete list of all coupon codes with edit capabilities</p>
</div>
<!-- Search functionality -->
<div class="search-container">
<input type="text" id="searchInput" class="search-input" placeholder="Search coupon codes...">
<button class="search-clear" id="searchClear" onclick="clearSearch()">
<i class="fas fa-times"></i>
</button>
</div>
<!-- Search result information displays -->
<div id="searchResultInfo" class="search-result-info">
<i class="fas fa-check-circle"></i>
<span id="searchResultText"></span>
</div>
<div id="noResultsInfo" class="no-results-info">
<i class="fas fa-exclamation-circle"></i>
<span>No coupon codes found matching your search.</span>
</div>
<!-- Data table for displaying coupon codes -->
<div class="table-container">
<table id="codeTable">
<thead>
<tr>
<th><i class="fas fa-tag"></i> Coupon Code</th>
<th><i class="fas fa-clock"></i> Used At</th>
<th><i class="fas fa-cog"></i> Actions</th>
</tr>
</thead>
<tbody>
<!-- No results row (hidden by default) -->
<tr id="noResults" class="no-results" style="display: none;">
<td colspan="3">
<i class="fas fa-search"></i>
<h3>No codes found</h3>
<p>Try searching for a different coupon code</p>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Pagination controls -->
<div class="pagination-container">
<div class="pagination-info">
<span id="paginationInfo">Showing 0-0 of 0 codes</span>
</div>
<div class="pagination-controls">
<button class="btn btn-secondary" id="prevPage" onclick="changePage(-1)" disabled>
<i class="fas fa-chevron-left"></i> Previous
</button>
<div class="page-numbers" id="pageNumbers"></div>
<button class="btn btn-secondary" id="nextPage" onclick="changePage(1)" disabled>
Next <i class="fas fa-chevron-right"></i>
</button>
</div>
</div>
</div>
</div>
<!--
Interface for bulk uploading coupon codes from Excel files
-->
<div id="upload" class="hidden slide-in">
<div class="content-card">
<div class="content-header">
<h2><i class="fas fa-upload"></i> Upload Coupon Codes</h2>
<p>Bulk upload coupon codes from Excel files (.xlsx, .xls)</p>
</div>
<div class="form-group">
</div>
</div>
<!-- Drag and drop file upload area -->
<div class="file-upload-area" onclick="document.getElementById('excelFile').click()">
<i class="fas fa-cloud-upload-alt file-upload-icon"></i>
<div class="file-upload-text">Click to upload or drag and drop</div>
<div class="file-upload-hint">Excel files only (.xlsx, .xls) - Max 10MB</div>
<input type="file" id="excelFile" accept=".xlsx,.xls" style="display: none;" onchange="handleFileSelect(event)">
</div>
<!-- File information display -->
<div id="fileInfo" class="file-info" style="display: none;">
<i class="fas fa-file-excel"></i>
<span id="fileName"></span>
<button type="button" onclick="clearFile()" style="margin-left: auto; background: none; border: none; color: #ef4444; cursor: pointer;">
<i class="fas fa-times"></i>
</button>
</div>
<!-- Validation error display -->
<div id="validationErrors" class="validation-errors" style="display: none;">
<h4><i class="fas fa-exclamation-triangle"></i> Validation Errors</h4>
<ul id="errorList"></ul>
</div>
<!-- Data preview section -->
<div id="previewSection" class="preview-section" style="display: none;">
<div class="preview-header">
<h3><i class="fas fa-eye"></i> Preview Data</h3>
<!-- Statistics cards -->
<div class="preview-stats">
<div class="stat-card">
<div class="stat-number" id="totalCodes">0</div>
<div class="stat-label">Total Codes</div>
</div>
<div class="stat-card">
<div class="stat-number" id="validCodes">0</div>
<div class="stat-label">Valid Codes</div>
</div>
<div class="stat-card">
<div class="stat-number" id="duplicateCodes">0</div>
<div class="stat-label">Duplicates</div>
</div>
</div>
</div>
<!-- Preview data table -->
<div class="table-container">
<table id="previewTable">
<thead>
<tr>
<th>Code</th>
<th>Usage</th>
</tr>
</thead>
<tbody id="previewTableBody">
</tbody>
</table>
</div>
</div>
</div>
<!-- Upload result display -->
<div id="uploadResult"></div>
<!--
Interface for uploading language translation files
-->
<div id="translation-upload" class="hidden slide-in">
<div class="content-card">
<div class="content-header">
<h2><i class="fas fa-language"></i> Upload Language Translation File</h2>
<p>Upload the Excel file (.xlsx) for language translation used by the extension. Only one file can exist at a time.</p>
</div>
<div id="translationUploadSection"></div>
</div>
</div>
</div>
</div>
</div>
<!--
Confirmation dialogs for delete and logout actions
-->
<!-- Delete confirmation modal -->
<div id="deleteModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h3><i class="fas fa-trash"></i> Delete Coupon Code</h3>
<button class="close-btn" onclick="closeDeleteModal()">&times;</button>
</div>
<div class="modal-body">
<p style="font-size: 16px; color: #374151; margin-bottom: 20px;">
Are you sure you want to delete the coupon code <strong id="deleteCodeName"></strong>?
</p>
<p style="font-size: 14px; color: #ef4444; background: #fef2f2; padding: 15px; border-radius: 8px; border-left: 4px solid #ef4444;">
<i class="fas fa-exclamation-triangle"></i>
<strong>Warning:</strong> This action cannot be undone.
</p>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" onclick="closeDeleteModal()">Cancel</button>
<button class="btn btn-danger" onclick="confirmDeleteCode()">
<i class="fas fa-trash"></i> Delete Code
</button>
</div>
</div>
</div>
<!-- Logout confirmation modal -->
<div id="logoutModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h3><i class="fas fa-sign-out-alt"></i> Confirm Logout</h3>
<button class="close-btn" onclick="closeLogoutModal()">&times;</button>
</div>
<div class="modal-body">
<p style="font-size: 16px; color: #374151; margin-bottom: 20px;">
Are you sure you want to logout from the admin panel?
</p>
<p style="font-size: 14px; color: #6b7280; background: #f9fafb; padding: 15px; border-radius: 8px; border-left: 4px solid #667eea;">
<i class="fas fa-info-circle"></i>
You will be redirected to the login page.
</p>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" onclick="closeLogoutModal()">Cancel</button>
<button class="btn btn-danger" onclick="confirmLogout()">
<i class="fas fa-sign-out-alt"></i> Logout
</button>
</div>
</div>
</div>
<!--
Load required JavaScript libraries and application scripts
-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script src="/static/admin_dashboard.js"></script>
</body>
</html>