|
<!DOCTYPE html> |
|
<html lang="tr"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Admin - Harmon Yazılım</title> |
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet"> |
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> |
|
<style> |
|
* { |
|
margin: 0; |
|
padding: 0; |
|
box-sizing: border-box; |
|
} |
|
|
|
body { |
|
margin: 0; |
|
padding: 0; |
|
min-height: 100vh; |
|
font-family: 'Inter', sans-serif; |
|
background: #0a0a0a; |
|
color: #e1e1e1; |
|
font-size: 14px; |
|
} |
|
|
|
.login-container { |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
min-height: 100vh; |
|
padding: 20px; |
|
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%); |
|
} |
|
|
|
.login-form { |
|
background: #1a1a1a; |
|
padding: 30px; |
|
border-radius: 12px; |
|
width: 100%; |
|
max-width: 400px; |
|
box-shadow: 0 8px 16px rgba(0,0,0,0.2); |
|
} |
|
|
|
.login-form h1 { |
|
font-size: 24px; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.form-group { |
|
margin-bottom: 20px; |
|
} |
|
|
|
.form-group label { |
|
display: block; |
|
margin-bottom: 8px; |
|
font-size: 14px; |
|
} |
|
|
|
.form-group input { |
|
width: 100%; |
|
padding: 10px; |
|
border: 1px solid #2d3748; |
|
border-radius: 6px; |
|
background: #0a0a0a; |
|
color: #e1e1e1; |
|
font-size: 14px; |
|
} |
|
|
|
.btn { |
|
padding: 10px 20px; |
|
font-size: 14px; |
|
border-radius: 6px; |
|
cursor: pointer; |
|
border: none; |
|
background: #3498db; |
|
color: white; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.btn:hover { |
|
background: #2980b9; |
|
} |
|
|
|
.admin-container { |
|
display: none; |
|
min-height: 100vh; |
|
margin-left: 250px; |
|
} |
|
|
|
.sidebar { |
|
width: 250px; |
|
position: fixed; |
|
left: 0; |
|
top: 0; |
|
height: 100vh; |
|
background: #1a1a1a; |
|
padding: 20px; |
|
box-sizing: border-box; |
|
} |
|
|
|
.sidebar-header { |
|
padding: 0 0 20px 0; |
|
margin-bottom: 20px; |
|
border-bottom: 1px solid #2d3748; |
|
} |
|
|
|
.sidebar-header h2 { |
|
font-size: 20px; |
|
color: #3498db; |
|
} |
|
|
|
.sidebar-menu { |
|
list-style: none; |
|
padding: 0; |
|
margin: 0; |
|
} |
|
|
|
.sidebar-menu li { |
|
margin-bottom: 10px; |
|
} |
|
|
|
.sidebar-menu a { |
|
display: flex; |
|
align-items: center; |
|
padding: 12px 15px; |
|
color: #e1e1e1; |
|
text-decoration: none; |
|
border-radius: 6px; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.sidebar-menu a.active { |
|
background: #3498db; |
|
color: white; |
|
} |
|
|
|
.sidebar-menu a:hover { |
|
background: rgba(52, 152, 219, 0.1); |
|
} |
|
|
|
.sidebar-menu a.active:hover { |
|
background: #3498db; |
|
} |
|
|
|
.sidebar-menu i { |
|
margin-right: 10px; |
|
width: 20px; |
|
} |
|
|
|
.navbar { |
|
position: fixed; |
|
top: 0; |
|
right: 0; |
|
left: 250px; |
|
height: 8vh; |
|
background: #1a1a1a; |
|
padding: 0 20px; |
|
display: flex; |
|
align-items: center; |
|
justify-content: space-between; |
|
z-index: 100; |
|
} |
|
|
|
.navbar-brand { |
|
display: flex; |
|
align-items: center; |
|
gap: 0.5rem; |
|
color: #3498db; |
|
font-size: 1.25rem; |
|
font-weight: 600; |
|
} |
|
|
|
.navbar-menu { |
|
display: flex; |
|
align-items: center; |
|
gap: 1rem; |
|
} |
|
|
|
.navbar-menu .btn { |
|
padding: 0.5rem 1rem; |
|
min-width: auto; |
|
} |
|
|
|
.content-area { |
|
padding: 10vh 20px 20px; |
|
} |
|
|
|
.page-title { |
|
margin-bottom: 2rem; |
|
color: #3498db; |
|
font-size: 1.5rem; |
|
font-weight: 600; |
|
} |
|
|
|
.user-list { |
|
display: grid; |
|
gap: 1.5rem; |
|
} |
|
|
|
.user-card { |
|
background: #1a1a1a; |
|
border-radius: 8px; |
|
padding: 15px; |
|
display: flex; |
|
flex-direction: column; |
|
gap: 10px; |
|
word-wrap: break-word; |
|
overflow-wrap: break-word; |
|
} |
|
|
|
.user-header { |
|
margin-bottom: 20px; |
|
} |
|
|
|
.user-stats { |
|
display: grid; |
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); |
|
gap: 15px; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.stat-item { |
|
background: #0a0a0a; |
|
padding: 15px; |
|
border-radius: 6px; |
|
} |
|
|
|
.user-actions { |
|
display: flex; |
|
gap: 1rem; |
|
flex-wrap: wrap; |
|
} |
|
|
|
.user-actions .btn { |
|
flex: 1; |
|
min-width: 120px; |
|
padding: 0.75rem 1rem; |
|
} |
|
|
|
.btn-secondary { |
|
background-color: transparent; |
|
border: 2px solid #3498db; |
|
color: #3498db; |
|
} |
|
|
|
.btn-secondary:hover { |
|
background-color: rgba(52,152,219,0.1); |
|
transform: translateY(-1px); |
|
} |
|
|
|
.btn-danger { |
|
background-color: #e74c3c; |
|
color: white; |
|
} |
|
|
|
.btn-danger:hover { |
|
background-color: #c0392b; |
|
} |
|
|
|
.status-badge { |
|
padding: 4px 8px; |
|
border-radius: 4px; |
|
font-size: 12px; |
|
display: inline-flex; |
|
align-items: center; |
|
gap: 4px; |
|
} |
|
|
|
.status-badge.verified { |
|
background-color: #2ecc71; |
|
color: white; |
|
} |
|
|
|
.status-badge.unverified { |
|
background-color: #e74c3c; |
|
color: white; |
|
} |
|
|
|
.stat-value { |
|
word-break: break-all; |
|
max-height: 15vh; |
|
overflow-y: auto; |
|
padding-right: 5px; |
|
} |
|
|
|
.api-details { |
|
background: #0a0a0a; |
|
padding: 1rem; |
|
border-radius: 4px; |
|
overflow-x: auto; |
|
color: #e1e1e1; |
|
font-family: monospace; |
|
font-size: 0.9rem; |
|
white-space: pre-wrap; |
|
word-wrap: break-word; |
|
max-height: 50vh; |
|
overflow-y: auto; |
|
} |
|
|
|
.modal-body { |
|
padding: 1rem; |
|
max-height: 80vh; |
|
overflow-y: auto; |
|
word-wrap: break-word; |
|
overflow-wrap: break-word; |
|
} |
|
|
|
.user-auth { |
|
word-break: break-all; |
|
max-width: 100%; |
|
display: inline-block; |
|
} |
|
|
|
|
|
.stat-value::-webkit-scrollbar, |
|
.api-details::-webkit-scrollbar, |
|
.modal-body::-webkit-scrollbar { |
|
width: 8px; |
|
height: 8px; |
|
} |
|
|
|
.stat-value::-webkit-scrollbar-track, |
|
.api-details::-webkit-scrollbar-track, |
|
.modal-body::-webkit-scrollbar-track { |
|
background: #1a1a1a; |
|
border-radius: 4px; |
|
} |
|
|
|
.stat-value::-webkit-scrollbar-thumb, |
|
.api-details::-webkit-scrollbar-thumb, |
|
.modal-body::-webkit-scrollbar-thumb { |
|
background: #2d3748; |
|
border-radius: 4px; |
|
} |
|
|
|
.stat-value::-webkit-scrollbar-thumb:hover, |
|
.api-details::-webkit-scrollbar-thumb:hover, |
|
.modal-body::-webkit-scrollbar-thumb:hover { |
|
background: #3498db; |
|
} |
|
|
|
@media (max-width: 768px) { |
|
.admin-container { |
|
margin-left: 0; |
|
} |
|
|
|
.sidebar { |
|
transform: translateX(-100%); |
|
z-index: 1001; |
|
box-shadow: 2px 0 10px rgba(0,0,0,0.5); |
|
} |
|
|
|
.sidebar.active { |
|
transform: translateX(0); |
|
} |
|
|
|
.navbar { |
|
left: 0; |
|
padding: 0 0.8rem; |
|
height: 7vh; |
|
} |
|
|
|
.navbar-brand { |
|
font-size: 1.1rem; |
|
} |
|
|
|
.content-area { |
|
padding: 8vh 0.8rem 0.8rem; |
|
} |
|
|
|
.user-stats { |
|
grid-template-columns: 1fr; |
|
gap: 0.8rem; |
|
} |
|
|
|
.user-actions { |
|
flex-direction: column; |
|
gap: 0.8rem; |
|
} |
|
|
|
.user-actions .btn { |
|
width: 100%; |
|
min-width: unset; |
|
} |
|
|
|
.user-card { |
|
padding: 0.8rem; |
|
} |
|
|
|
.modal-content { |
|
width: 95%; |
|
padding: 1rem; |
|
margin: 0.8rem; |
|
} |
|
|
|
.detail-grid { |
|
grid-template-columns: 1fr; |
|
} |
|
|
|
.input-group { |
|
flex-direction: column; |
|
gap: 0.8rem; |
|
} |
|
|
|
.input-group .btn { |
|
width: 100%; |
|
} |
|
|
|
.settings-form { |
|
padding: 0.8rem; |
|
} |
|
} |
|
|
|
@media (max-width: 480px) { |
|
.login-form { |
|
padding: 1rem; |
|
margin: 0.8rem; |
|
} |
|
|
|
.navbar { |
|
padding: 0 0.6rem; |
|
height: 6vh; |
|
} |
|
|
|
.navbar-brand { |
|
font-size: 1rem; |
|
} |
|
|
|
.navbar-menu .btn { |
|
padding: 0.35rem 0.6rem; |
|
font-size: 0.85rem; |
|
} |
|
|
|
.content-area { |
|
padding: 7vh 0.6rem 0.6rem; |
|
} |
|
|
|
.page-title { |
|
font-size: 1.2rem; |
|
margin-bottom: 1rem; |
|
} |
|
|
|
.user-card { |
|
padding: 0.6rem; |
|
} |
|
|
|
.user-header { |
|
margin-bottom: 0.8rem; |
|
} |
|
|
|
.stat-item { |
|
padding: 0.6rem; |
|
} |
|
|
|
.form-group { |
|
margin-bottom: 0.8rem; |
|
} |
|
|
|
.form-group input { |
|
padding: 0.4rem; |
|
font-size: 0.9rem; |
|
} |
|
|
|
.btn { |
|
padding: 0.35rem 0.6rem; |
|
font-size: 0.85rem; |
|
} |
|
|
|
.modal-content { |
|
padding: 0.8rem; |
|
} |
|
|
|
.modal-header { |
|
padding: 0.6rem; |
|
} |
|
|
|
.modal-body { |
|
padding: 0.6rem; |
|
} |
|
|
|
.detail-section { |
|
padding: 0.6rem; |
|
margin-bottom: 0.8rem; |
|
} |
|
|
|
.detail-section h4 { |
|
font-size: 1rem; |
|
margin-bottom: 0.8rem; |
|
} |
|
|
|
.api-details { |
|
padding: 0.6rem; |
|
font-size: 0.8rem; |
|
} |
|
|
|
.status-badge { |
|
padding: 0.25rem 0.5rem; |
|
font-size: 0.75rem; |
|
} |
|
} |
|
|
|
.mobile-menu-toggle { |
|
display: none; |
|
background: none; |
|
border: none; |
|
color: #3498db; |
|
font-size: 1.5rem; |
|
cursor: pointer; |
|
} |
|
|
|
@media (max-width: 768px) { |
|
.mobile-menu-toggle { |
|
display: block; |
|
} |
|
} |
|
|
|
.modal { |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 100%; |
|
height: 100vh; |
|
background: rgba(0, 0, 0, 0.8); |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
z-index: 1000; |
|
} |
|
|
|
.modal-content { |
|
background: #1a1a1a; |
|
padding: 20px; |
|
border-radius: 12px; |
|
width: 90%; |
|
max-width: 600px; |
|
max-height: 90vh; |
|
overflow-y: auto; |
|
} |
|
|
|
.modal-header { |
|
padding: 1rem; |
|
border-bottom: 1px solid #2c2c2c; |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
} |
|
|
|
.detail-section { |
|
background: #1f1f1f; |
|
border-radius: 8px; |
|
padding: 1.5rem; |
|
margin-bottom: 1.5rem; |
|
} |
|
|
|
.detail-section h4 { |
|
color: #3498db; |
|
margin-bottom: 1rem; |
|
display: flex; |
|
align-items: center; |
|
gap: 0.5rem; |
|
font-size: 1.1rem; |
|
} |
|
|
|
.detail-grid { |
|
display: grid; |
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); |
|
gap: 1rem; |
|
} |
|
|
|
.detail-item { |
|
background: #2c2c2c; |
|
padding: 1rem; |
|
border-radius: 6px; |
|
display: flex; |
|
flex-direction: column; |
|
gap: 0.5rem; |
|
} |
|
|
|
.detail-label { |
|
color: #888; |
|
font-size: 0.9rem; |
|
display: flex; |
|
align-items: center; |
|
gap: 0.5rem; |
|
} |
|
|
|
.detail-value { |
|
color: #e1e1e1; |
|
font-size: 1rem; |
|
display: flex; |
|
align-items: center; |
|
gap: 0.5rem; |
|
flex-wrap: wrap; |
|
} |
|
|
|
.input-group { |
|
display: flex; |
|
gap: 0.5rem; |
|
flex-wrap: wrap; |
|
} |
|
|
|
.input-group .form-control { |
|
flex: 1; |
|
min-width: 200px; |
|
padding: 0.5rem; |
|
background: #2c2c2c; |
|
border: 1px solid #3d3d3d; |
|
border-radius: 4px; |
|
color: #e1e1e1; |
|
} |
|
|
|
.input-group .btn { |
|
white-space: nowrap; |
|
} |
|
|
|
.btn-sm { |
|
padding: 0.25rem 0.5rem; |
|
font-size: 0.875rem; |
|
} |
|
|
|
.status-badge { |
|
padding: 0.25rem 0.5rem; |
|
border-radius: 4px; |
|
font-size: 0.875rem; |
|
display: inline-flex; |
|
align-items: center; |
|
gap: 0.25rem; |
|
font-weight: 500; |
|
} |
|
|
|
|
|
.container { |
|
width: 100%; |
|
max-width: 100%; |
|
padding: 10px; |
|
box-sizing: border-box; |
|
margin-left: 250px; |
|
} |
|
|
|
|
|
.stat-cards { |
|
display: grid; |
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); |
|
gap: 15px; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.stat-card { |
|
background: #1a1a1a; |
|
padding: 15px; |
|
border-radius: 8px; |
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
|
} |
|
|
|
|
|
.table-responsive { |
|
overflow-x: auto; |
|
margin: 15px 0; |
|
} |
|
|
|
table { |
|
width: 100%; |
|
border-collapse: collapse; |
|
} |
|
|
|
th, td { |
|
padding: 12px; |
|
text-align: left; |
|
border-bottom: 1px solid #2d3748; |
|
} |
|
|
|
|
|
.alert { |
|
padding: 12px; |
|
border-radius: 6px; |
|
margin-bottom: 15px; |
|
} |
|
|
|
.alert-success { |
|
background: #2ecc71; |
|
color: white; |
|
} |
|
|
|
.alert-error { |
|
background: #e74c3c; |
|
color: white; |
|
} |
|
|
|
|
|
::-webkit-scrollbar { |
|
width: 8px; |
|
} |
|
|
|
::-webkit-scrollbar-track { |
|
background: #1a1a1a; |
|
} |
|
|
|
::-webkit-scrollbar-thumb { |
|
background: #2d3748; |
|
border-radius: 4px; |
|
} |
|
|
|
|
|
.main-content { |
|
margin-top: 60px; |
|
padding: 15px; |
|
box-sizing: border-box; |
|
} |
|
|
|
@media (max-width: 768px) { |
|
.main-content { |
|
margin-top: 50px; |
|
padding: 10px; |
|
} |
|
} |
|
|
|
|
|
.user-cards { |
|
display: grid; |
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); |
|
gap: 15px; |
|
padding: 15px; |
|
} |
|
|
|
.user-card { |
|
background: #1a1a1a; |
|
border-radius: 8px; |
|
padding: 15px; |
|
display: flex; |
|
flex-direction: column; |
|
gap: 10px; |
|
} |
|
|
|
@media (max-width: 480px) { |
|
.user-cards { |
|
grid-template-columns: 1fr; |
|
padding: 10px; |
|
} |
|
|
|
.user-card { |
|
padding: 10px; |
|
} |
|
} |
|
|
|
|
|
.domain-list { |
|
display: grid; |
|
gap: 10px; |
|
padding: 10px; |
|
max-height: 60vh; |
|
} |
|
|
|
.domain-item { |
|
background: #1a1a1a; |
|
border-radius: 8px; |
|
padding: 10px; |
|
display: grid; |
|
grid-template-columns: 1fr auto; |
|
align-items: center; |
|
gap: 10px; |
|
} |
|
|
|
@media (max-width: 480px) { |
|
.domain-list { |
|
padding: 5px; |
|
} |
|
|
|
.domain-item { |
|
grid-template-columns: 1fr; |
|
padding: 8px; |
|
} |
|
} |
|
|
|
|
|
.settings-form { |
|
max-width: 600px; |
|
margin: 0 auto; |
|
padding: 15px; |
|
} |
|
|
|
.settings-form .form-group { |
|
margin-bottom: 15px; |
|
} |
|
|
|
@media (max-width: 480px) { |
|
.settings-form { |
|
padding: 10px; |
|
} |
|
} |
|
|
|
|
|
.loading-spinner { |
|
width: 20px; |
|
height: 20px; |
|
border: 2px solid #f3f3f3; |
|
border-top: 2px solid #3498db; |
|
border-radius: 50%; |
|
animation: spin 1s linear infinite; |
|
} |
|
|
|
@keyframes spin { |
|
0% { transform: rotate(0deg); } |
|
100% { transform: rotate(360deg); } |
|
} |
|
|
|
|
|
.text-truncate { |
|
white-space: nowrap; |
|
overflow: hidden; |
|
text-overflow: ellipsis; |
|
max-width: 100%; |
|
} |
|
|
|
|
|
.grid-container { |
|
display: grid; |
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); |
|
gap: 10px; |
|
padding: 10px; |
|
} |
|
|
|
|
|
.flex-container { |
|
display: flex; |
|
flex-wrap: wrap; |
|
gap: 10px; |
|
padding: 10px; |
|
} |
|
|
|
|
|
.tooltip { |
|
position: relative; |
|
display: inline-block; |
|
} |
|
|
|
.tooltip .tooltip-text { |
|
visibility: hidden; |
|
background-color: #2d3748; |
|
color: #e1e1e1; |
|
text-align: center; |
|
padding: 5px; |
|
border-radius: 4px; |
|
position: absolute; |
|
z-index: 1; |
|
bottom: 125%; |
|
left: 50%; |
|
transform: translateX(-50%); |
|
font-size: 11px; |
|
white-space: nowrap; |
|
} |
|
|
|
.tooltip:hover .tooltip-text { |
|
visibility: visible; |
|
} |
|
|
|
.modal-close { |
|
background: none; |
|
border: none; |
|
color: #e1e1e1; |
|
font-size: 1.5rem; |
|
cursor: pointer; |
|
padding: 0.5rem; |
|
transition: color 0.3s ease; |
|
} |
|
|
|
.modal-close:hover { |
|
color: #3498db; |
|
} |
|
|
|
|
|
.stats-bar { |
|
display: flex; |
|
gap: 20px; |
|
margin-bottom: 20px; |
|
flex-wrap: wrap; |
|
} |
|
|
|
.stat-box { |
|
background: #1a1a1a; |
|
padding: 15px 20px; |
|
border-radius: 8px; |
|
display: flex; |
|
align-items: center; |
|
gap: 15px; |
|
flex: 1; |
|
min-width: 200px; |
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1); |
|
} |
|
|
|
.stat-box i { |
|
font-size: 24px; |
|
color: #3498db; |
|
} |
|
|
|
.stat-info { |
|
display: flex; |
|
flex-direction: column; |
|
} |
|
|
|
.stat-label { |
|
font-size: 14px; |
|
color: #888; |
|
} |
|
|
|
.stat-value { |
|
font-size: 24px; |
|
font-weight: 600; |
|
color: #e1e1e1; |
|
} |
|
|
|
.search-bar { |
|
margin-bottom: 20px; |
|
} |
|
|
|
.search-bar input { |
|
width: 100%; |
|
padding: 12px; |
|
border: 1px solid #2d3748; |
|
border-radius: 8px; |
|
background: #1a1a1a; |
|
color: #e1e1e1; |
|
font-size: 14px; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.search-bar input:focus { |
|
border-color: #3498db; |
|
box-shadow: 0 0 0 2px rgba(52,152,219,0.2); |
|
outline: none; |
|
} |
|
|
|
.user-item.hidden, |
|
.domain-item.hidden { |
|
display: none; |
|
} |
|
|
|
|
|
.btn-icon { |
|
background: none; |
|
border: none; |
|
color: #3498db; |
|
cursor: pointer; |
|
padding: 5px; |
|
margin-left: 5px; |
|
border-radius: 4px; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.btn-icon:hover { |
|
background: rgba(52, 152, 219, 0.1); |
|
transform: scale(1.1); |
|
} |
|
|
|
.user-auth { |
|
display: flex; |
|
align-items: center; |
|
gap: 5px; |
|
} |
|
|
|
|
|
.status-badges { |
|
display: flex; |
|
gap: 8px; |
|
align-items: center; |
|
} |
|
|
|
.status-badge.verified { |
|
background: #2ecc71; |
|
color: white; |
|
} |
|
|
|
.status-badge.unverified { |
|
background: #e67e22; |
|
color: white; |
|
} |
|
|
|
.btn-success { |
|
background: #2ecc71; |
|
color: white; |
|
} |
|
|
|
.btn-success:hover { |
|
background: #27ae60; |
|
} |
|
|
|
.user-card[data-auth="1r2yvw8guhpd1rzu29uarxkm4nveqxf2"] { |
|
border: 1px solid #3498db; |
|
box-shadow: 0 4px 12px rgba(52, 152, 219, 0.2); |
|
} |
|
|
|
.reseller-list { |
|
display: grid; |
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); |
|
gap: 1rem; |
|
padding: 1rem 0; |
|
} |
|
|
|
.reseller-card { |
|
background: #1f1f1f; |
|
border-radius: 8px; |
|
padding: 1.5rem; |
|
display: flex; |
|
flex-direction: column; |
|
gap: 1rem; |
|
transition: all 0.3s ease; |
|
border: 1px solid #2c2c2c; |
|
} |
|
|
|
.reseller-card:hover { |
|
transform: translateY(-2px); |
|
box-shadow: 0 4px 12px rgba(0,0,0,0.2); |
|
border-color: #3498db; |
|
} |
|
|
|
.reseller-header { |
|
display: flex; |
|
align-items: center; |
|
gap: 1rem; |
|
} |
|
|
|
.reseller-avatar { |
|
width: 60px; |
|
height: 60px; |
|
border-radius: 50%; |
|
object-fit: cover; |
|
border: 2px solid #3498db; |
|
} |
|
|
|
.reseller-info { |
|
flex: 1; |
|
} |
|
|
|
.reseller-name { |
|
font-size: 1.1rem; |
|
font-weight: 500; |
|
color: #3498db; |
|
margin-bottom: 0.25rem; |
|
} |
|
|
|
.reseller-website { |
|
font-size: 0.9rem; |
|
color: #888; |
|
text-decoration: none; |
|
transition: color 0.3s ease; |
|
} |
|
|
|
.reseller-website:hover { |
|
color: #3498db; |
|
} |
|
|
|
.reseller-description { |
|
color: #e1e1e1; |
|
font-size: 0.9rem; |
|
line-height: 1.4; |
|
} |
|
|
|
.form-group textarea { |
|
width: 100%; |
|
min-height: 150px; |
|
resize: vertical; |
|
padding: 10px; |
|
border: 1px solid #2d3748; |
|
border-radius: 6px; |
|
background: #0a0a0a; |
|
color: #e1e1e1; |
|
font-size: 14px; |
|
font-family: 'Inter', sans-serif; |
|
line-height: 1.5; |
|
} |
|
|
|
.form-group textarea:focus { |
|
border-color: #3498db; |
|
outline: none; |
|
box-shadow: 0 0 0 2px rgba(52,152,219,0.2); |
|
} |
|
|
|
.user-avatar { |
|
width: 60px; |
|
height: 60px; |
|
border-radius: 50%; |
|
border: 2px solid #3498db; |
|
flex-shrink: 0; |
|
background: #1a1a1a; |
|
position: relative; |
|
overflow: hidden; |
|
} |
|
|
|
.user-avatar img { |
|
width: 100%; |
|
height: 100%; |
|
object-fit: cover; |
|
object-position: center; |
|
} |
|
|
|
.user-header { |
|
display: flex; |
|
align-items: center; |
|
gap: 1rem; |
|
} |
|
|
|
.user-info { |
|
flex: 1; |
|
} |
|
|
|
.user-info h3 { |
|
color: #3498db; |
|
margin-bottom: 0.25rem; |
|
} |
|
|
|
.user-info a { |
|
color: #888; |
|
text-decoration: none; |
|
font-size: 0.9rem; |
|
transition: color 0.3s ease; |
|
} |
|
|
|
.user-info a:hover { |
|
color: #3498db; |
|
} |
|
|
|
#toastContainer { |
|
position: fixed; |
|
top: 20px; |
|
right: 20px; |
|
z-index: 9999; |
|
} |
|
|
|
.toast { |
|
background: #333; |
|
color: white; |
|
padding: 12px 24px; |
|
border-radius: 4px; |
|
margin-bottom: 10px; |
|
min-width: 200px; |
|
box-shadow: 0 2px 5px rgba(0,0,0,0.2); |
|
animation: slideIn 0.3s ease-in-out; |
|
} |
|
|
|
.toast.toast-success { |
|
background: #2ecc71; |
|
} |
|
|
|
.toast.toast-error { |
|
background: #e74c3c; |
|
} |
|
|
|
.toast.toast-warning { |
|
background: #f1c40f; |
|
} |
|
|
|
.toast.fade-out { |
|
animation: slideOut 0.3s ease-in-out forwards; |
|
} |
|
|
|
@keyframes slideIn { |
|
from { |
|
transform: translateX(100%); |
|
opacity: 0; |
|
} |
|
to { |
|
transform: translateX(0); |
|
opacity: 1; |
|
} |
|
} |
|
|
|
@keyframes slideOut { |
|
from { |
|
transform: translateX(0); |
|
opacity: 1; |
|
} |
|
to { |
|
transform: translateX(100%); |
|
opacity: 0; |
|
} |
|
} |
|
|
|
.detail-item { |
|
display: flex; |
|
align-items: center; |
|
gap: 8px; |
|
} |
|
|
|
.detail-item .btn-sm { |
|
padding: 2px 8px; |
|
font-size: 12px; |
|
} |
|
|
|
.detail-value.user-auth { |
|
display: flex; |
|
align-items: center; |
|
gap: 1rem; |
|
flex-wrap: wrap; |
|
background: #1a1a1a; |
|
padding: 0.5rem; |
|
border-radius: 4px; |
|
font-family: monospace; |
|
} |
|
|
|
.detail-value.user-auth .input-group { |
|
margin-top: 0.5rem; |
|
width: 100%; |
|
} |
|
|
|
.detail-value.user-auth .btn-sm { |
|
padding: 0.25rem 0.5rem; |
|
font-size: 0.75rem; |
|
} |
|
|
|
.detail-value.user-auth .form-control { |
|
background: #2c2c2c; |
|
border: 1px solid #3d3d3d; |
|
color: #e1e1e1; |
|
padding: 0.25rem 0.5rem; |
|
border-radius: 4px; |
|
font-family: monospace; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="login-container" id="loginContainer"> |
|
<form class="login-form" id="loginForm" onsubmit="login(event)"> |
|
<h1>Admin Girişi</h1> |
|
<div class="form-group"> |
|
<label>Kullanıcı Adı</label> |
|
<input type="text" id="username" required> |
|
</div> |
|
<div class="form-group"> |
|
<label>Şifre</label> |
|
<input type="password" id="password" required> |
|
</div> |
|
<button type="submit" class="btn">Giriş Yap</button> |
|
</form> |
|
</div> |
|
|
|
<div class="admin-container" id="adminContainer"> |
|
<aside class="sidebar" id="sidebar"> |
|
<div class="sidebar-header"> |
|
<h2>Admin Panel</h2> |
|
</div> |
|
<ul class="sidebar-menu"> |
|
<li> |
|
<a href="#" data-page="users" onclick="changePage('users')" class="active"> |
|
<i class="fas fa-users"></i> |
|
Kullanıcılar |
|
</a> |
|
</li> |
|
<li> |
|
<a href="#" data-page="domains" onclick="changePage('domains')"> |
|
<i class="fas fa-globe"></i> |
|
Domainler |
|
</a> |
|
</li> |
|
<li> |
|
<a href="#" data-page="promo" onclick="changePage('promo')"> |
|
<i class="fas fa-gift"></i> |
|
Promo Kodları |
|
</a> |
|
</li> |
|
<li> |
|
<a href="#" data-page="settings" onclick="changePage('settings')"> |
|
<i class="fas fa-cog"></i> |
|
Ayarlar |
|
</a> |
|
</li> |
|
<li> |
|
<a href="#" data-page="resellers" onclick="changePage('resellers')"> |
|
<i class="fas fa-user-check"></i> |
|
Resellerlar |
|
</a> |
|
</li> |
|
</ul> |
|
</aside> |
|
|
|
<nav class="navbar"> |
|
<button class="mobile-menu-toggle" onclick="toggleSidebar()"> |
|
<i class="fas fa-bars"></i> |
|
</button> |
|
<div class="navbar-brand"> |
|
<i class="fas fa-shield-alt"></i> |
|
Admin - Harmon Yazılım |
|
</div> |
|
<div class="navbar-menu"> |
|
<button class="btn btn-secondary" onclick="logout()"> |
|
<i class="fas fa-sign-out-alt"></i> |
|
Çıkış Yap |
|
</button> |
|
</div> |
|
</nav> |
|
|
|
<main class="content-area"> |
|
<div id="usersPage" class="page active"> |
|
<h1 class="page-title">Kullanıcı Yönetimi</h1> |
|
<div class="stats-bar"> |
|
<div class="stat-box"> |
|
<i class="fas fa-users"></i> |
|
<div class="stat-info"> |
|
<span class="stat-label">Toplam Kullanıcı</span> |
|
<span class="stat-value" id="totalUserCount">0</span> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="search-bar"> |
|
<input type="text" id="userSearch" placeholder="Kullanıcı ara..." onkeyup="searchUsers()"> |
|
</div> |
|
<div class="user-list" id="userList"> |
|
|
|
</div> |
|
</div> |
|
|
|
<div id="domainsPage" class="page"> |
|
<h2 class="page-title">Domainler</h2> |
|
<div class="stats-bar"> |
|
<div class="stat-box"> |
|
<i class="fas fa-globe"></i> |
|
<div class="stat-info"> |
|
<span class="stat-label">Toplam Domain</span> |
|
<span class="stat-value" id="totalDomainCount">0</span> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="search-bar"> |
|
<input type="text" id="domainSearch" placeholder="Domain ara..." onkeyup="searchDomains()"> |
|
</div> |
|
<div class="user-actions" style="margin-bottom: 20px;"> |
|
<button class="btn" onclick="loadAllDomainsFromApi()"> |
|
<i class="fas fa-sync"></i> |
|
Tüm Domainleri Yükle |
|
</button> |
|
</div> |
|
<div id="domainList" class="user-list"> |
|
|
|
</div> |
|
</div> |
|
|
|
<div id="promoPage" class="page"> |
|
<h2 class="page-title">Promo Kodları</h2> |
|
<div class="user-actions" style="margin-bottom: 20px;"> |
|
<button class="btn" onclick="createPromoCode()"> |
|
<i class="fas fa-plus"></i> |
|
Yeni Promo Kodu Oluştur |
|
</button> |
|
</div> |
|
<div id="promoList" class="user-list"> |
|
|
|
</div> |
|
</div> |
|
|
|
<div id="resellersPage" class="page"> |
|
<h2 class="page-title">Reseller Yönetimi</h2> |
|
<div class="user-actions" style="margin-bottom: 20px;"> |
|
<button class="btn" onclick="addReseller()"> |
|
<i class="fas fa-plus"></i> |
|
Yeni Reseller Ekle |
|
</button> |
|
</div> |
|
<div id="resellerList" class="user-list"> |
|
|
|
</div> |
|
</div> |
|
|
|
<div id="settingsPage" class="page"> |
|
<h1 class="page-title">Sistem Ayarları</h1> |
|
<div class="settings-form"> |
|
<div class="form-group"> |
|
<label>API URL</label> |
|
<input type="text" id="apiUrl" value="https://harmon.web.tr" readonly> |
|
</div> |
|
<div class="form-group"> |
|
<label>Admin Kullanıcı Adı</label> |
|
<input type="text" id="adminUsername"> |
|
</div> |
|
<div class="form-group"> |
|
<label>Yeni Şifre</label> |
|
<input type="password" id="newPassword"> |
|
</div> |
|
<button class="btn" onclick="saveSettings()">Kaydet</button> |
|
</div> |
|
</div> |
|
</main> |
|
</div> |
|
|
|
<script> |
|
const BASE_URL = 'https://harmon.web.tr'; |
|
const API_URL = `${BASE_URL}/control.php`; |
|
let adminToken = localStorage.getItem('adminToken'); |
|
|
|
|
|
if (adminToken) { |
|
showAdminPanel(); |
|
loadUsers(); |
|
|
|
document.querySelector('[data-page="users"]').classList.add('active'); |
|
} |
|
|
|
async function login(event) { |
|
event.preventDefault(); |
|
const username = document.getElementById('username').value; |
|
const password = document.getElementById('password').value; |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=adminLogin`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json' |
|
}, |
|
body: JSON.stringify({ username, password }) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
adminToken = data.data.token; |
|
|
|
localStorage.setItem('adminToken', adminToken); |
|
localStorage.setItem('adminUsername', username); |
|
showAdminPanel(); |
|
loadUsers(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Login error:', error); |
|
alert('Giriş yapılırken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
function showAdminPanel() { |
|
document.getElementById('loginContainer').style.display = 'none'; |
|
document.getElementById('adminContainer').style.display = 'block'; |
|
} |
|
|
|
function logout() { |
|
localStorage.removeItem('adminToken'); |
|
location.reload(); |
|
} |
|
|
|
async function loadUsers() { |
|
try { |
|
const response = await fetch(`${API_URL}?action=getAllUsers`, { |
|
headers: { |
|
'X-Admin-Token': adminToken |
|
} |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
const userList = document.getElementById('userList'); |
|
|
|
document.getElementById('totalUserCount').textContent = data.data.length; |
|
|
|
|
|
const sortedUsers = data.data.sort((a, b) => { |
|
if (a.auth_code === '1r2YvW8GUhpD1RZu29uarXKM4NveQXf2') return -1; |
|
if (b.auth_code === '1r2YvW8GUhpD1RZu29uarXKM4NveQXf2') return 1; |
|
return 0; |
|
}); |
|
|
|
userList.innerHTML = sortedUsers.map(user => ` |
|
<div class="user-card" data-auth="${user.auth_code.toLowerCase()}"> |
|
<div class="user-header"> |
|
<span class="user-auth">${user.auth_code}${user.auth_code === '1r2YvW8GUhpD1RZu29uarXKM4NveQXf2' ? ' <i class="fas fa-thumbtack" style="color: #3498db;"></i>' : ''}</span> |
|
<span class="status-badge ${user.status !== 'active' ? 'inactive' : ''}">${ |
|
user.status.charAt(0).toUpperCase() + user.status.slice(1) |
|
}</span> |
|
</div> |
|
<div class="user-stats"> |
|
<div class="stat-item"> |
|
<div class="stat-label">Domain Sayısı</div> |
|
<div class="stat-value">${user.domain_count}</div> |
|
</div> |
|
<div class="stat-item"> |
|
<div class="stat-label">Domain Kredisi</div> |
|
<div class="stat-value">${user.domain_credit}</div> |
|
</div> |
|
<div class="stat-item"> |
|
<div class="stat-label">Son Giriş</div> |
|
<div class="stat-value">${new Date(user.last_login).toLocaleDateString('tr-TR')}</div> |
|
</div> |
|
</div> |
|
<div class="user-actions"> |
|
<button class="btn" onclick="updateCredit(${user.id}, ${user.domain_credit})"> |
|
Kredi Güncelle |
|
</button> |
|
<button class="btn btn-secondary" onclick="viewDomains(${user.id})"> |
|
Domainler |
|
</button> |
|
<button class="btn ${user.status === 'active' ? 'btn-danger' : ''}" |
|
onclick="toggleStatus(${user.id}, '${user.status}')"> |
|
${user.status === 'active' ? 'Devre Dışı Bırak' : 'Aktifleştir'} |
|
</button> |
|
<button class="btn btn-secondary" onclick="loginAsUser('${user.auth_code}')"> |
|
<i class="fas fa-sign-in-alt"></i> Kullanıcı Olarak Giriş |
|
</button> |
|
<button class="btn btn-success" onclick="verifyUserDomains(${user.id})"> |
|
<i class="fas fa-check-double"></i> Tüm Domainleri Doğrula |
|
</button> |
|
</div> |
|
</div> |
|
`).join(''); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error loading users:', error); |
|
alert('Kullanıcılar yüklenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function updateCredit(userId, currentCredit) { |
|
const credit = prompt('Yeni kredi miktarı:', currentCredit); |
|
if (credit === null) return; |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=updateUserCredit`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ userId, credit: parseInt(credit) }) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
loadUsers(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error updating credit:', error); |
|
alert('Kredi güncellenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function toggleStatus(userId, currentStatus) { |
|
const newStatus = currentStatus === 'active' ? 'inactive' : 'active'; |
|
try { |
|
const response = await fetch(`${API_URL}?action=updateUserStatus`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ userId, status: newStatus }) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
loadUsers(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error updating status:', error); |
|
alert('Durum güncellenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function viewDomains(userId) { |
|
try { |
|
const response = await fetch(`${API_URL}?action=getUserDomains&userId=${userId}`, { |
|
headers: { |
|
'X-Admin-Token': adminToken |
|
} |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
|
|
const modalContent = ` |
|
<div class="modal-content"> |
|
<div class="modal-header"> |
|
<h3>Kullanıcı Domainleri</h3> |
|
<button class="modal-close" onclick="closeModal()">×</button> |
|
</div> |
|
<div class="modal-body"> |
|
<div class="domain-list"> |
|
${data.data.length > 0 ? data.data.map(domain => ` |
|
<div class="domain-item"> |
|
<div class="domain-info"> |
|
<div class="domain-name">${domain.domain_name}</div> |
|
<div class="domain-status"> |
|
<span class="status-badge ${domain.status !== 'active' ? 'inactive' : ''}">${domain.status}</span> |
|
<span class="status-badge ${domain.verified ? 'verified' : 'unverified'}"> |
|
<i class="fas ${domain.verified ? 'fa-check-circle' : 'fa-exclamation-circle'}"></i> |
|
${domain.verified ? 'Doğrulanmış' : 'Doğrulanmamış'} |
|
</span> |
|
</div> |
|
</div> |
|
<div class="domain-date"> |
|
Kayıt: ${new Date(domain.created_at).toLocaleDateString('tr-TR')} |
|
</div> |
|
</div> |
|
`).join('') : '<p>Bu kullanıcının domaini bulunmuyor.</p>'} |
|
</div> |
|
</div> |
|
</div> |
|
`; |
|
|
|
|
|
const modal = document.createElement('div'); |
|
modal.className = 'modal'; |
|
modal.id = 'domainsModal'; |
|
modal.innerHTML = modalContent; |
|
document.body.appendChild(modal); |
|
|
|
|
|
modal.addEventListener('click', (e) => { |
|
if (e.target === modal) closeModal(); |
|
}); |
|
|
|
|
|
const style = document.createElement('style'); |
|
style.textContent = ` |
|
.domain-list { |
|
display: flex; |
|
flex-direction: column; |
|
gap: 10px; |
|
max-height: 60vh; |
|
overflow-y: auto; |
|
padding: 10px; |
|
} |
|
.domain-item { |
|
background: #1a1a1a; |
|
border-radius: 8px; |
|
padding: 15px; |
|
display: flex; |
|
flex-direction: column; |
|
gap: 10px; |
|
} |
|
.domain-info { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
flex-wrap: wrap; |
|
gap: 10px; |
|
} |
|
.domain-name { |
|
font-weight: 500; |
|
word-break: break-all; |
|
} |
|
.domain-status { |
|
display: flex; |
|
gap: 8px; |
|
flex-wrap: wrap; |
|
} |
|
.domain-date { |
|
font-size: 0.9em; |
|
color: #888; |
|
} |
|
`; |
|
document.head.appendChild(style); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error loading domains:', error); |
|
alert('Domainler yüklenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
function toggleSidebar() { |
|
const sidebar = document.getElementById('sidebar'); |
|
sidebar.classList.toggle('active'); |
|
} |
|
|
|
|
|
document.addEventListener('click', function(event) { |
|
const sidebar = document.getElementById('sidebar'); |
|
const mobileMenuToggle = document.querySelector('.mobile-menu-toggle'); |
|
|
|
if (window.innerWidth <= 768 && |
|
!sidebar.contains(event.target) && |
|
!mobileMenuToggle.contains(event.target) && |
|
sidebar.classList.contains('active')) { |
|
sidebar.classList.remove('active'); |
|
} |
|
}); |
|
|
|
function changePage(page) { |
|
|
|
document.querySelectorAll('.page').forEach(p => p.classList.remove('active')); |
|
document.querySelectorAll('.sidebar-menu a').forEach(a => a.classList.remove('active')); |
|
|
|
|
|
document.getElementById(page + 'Page').classList.add('active'); |
|
document.querySelector(`[data-page="${page}"]`).classList.add('active'); |
|
|
|
|
|
if (window.innerWidth <= 768) { |
|
document.getElementById('sidebar').classList.remove('active'); |
|
} |
|
|
|
|
|
switch(page) { |
|
case 'users': |
|
loadUsers(); |
|
break; |
|
case 'domains': |
|
loadAllDomains(); |
|
break; |
|
case 'promo': |
|
loadPromoCodes(); |
|
break; |
|
case 'settings': |
|
loadSettings(); |
|
break; |
|
case 'resellers': |
|
loadResellers(); |
|
break; |
|
} |
|
} |
|
|
|
async function loadAllDomains() { |
|
try { |
|
const response = await fetch(`${API_URL}?action=getAllDomains`, { |
|
headers: { |
|
'X-Admin-Token': adminToken |
|
} |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
const domainList = document.getElementById('domainList'); |
|
document.getElementById('totalDomainCount').textContent = data.data.length; |
|
|
|
domainList.innerHTML = data.data.map(domain => ` |
|
<div class="user-card" data-domain="${domain.domain_name}"> |
|
<div class="user-header"> |
|
<div class="user-info"> |
|
<h3>${domain.domain_name}</h3> |
|
<div class="user-meta"> |
|
<span class="user-auth"> |
|
<i class="fas fa-user"></i> |
|
${domain.user_auth_code || 'Atanmamış'} |
|
</span> |
|
<span> |
|
<i class="fas fa-calendar"></i> |
|
${new Date(domain.registration_date).toLocaleDateString('tr-TR')} |
|
</span> |
|
<span> |
|
<i class="fas fa-clock"></i> |
|
${new Date(domain.expiry_date).toLocaleDateString('tr-TR')} |
|
</span> |
|
<span class="status-badge ${domain.status === 'active' ? 'active' : 'inactive'}"> |
|
<i class="fas fa-${domain.status === 'active' ? 'check' : 'times'}-circle"></i> |
|
${domain.status === 'active' ? 'Aktif' : 'Pasif'} |
|
</span> |
|
</div> |
|
</div> |
|
<div class="user-actions"> |
|
${domain.status !== 'active' ? ` |
|
<button class="btn btn-sm btn-success" onclick="verifyDomain('${domain.domain_name}')"> |
|
<i class="fas fa-check"></i> Doğrula |
|
</button> |
|
` : ''} |
|
<button class="btn btn-sm btn-primary" onclick="viewDomainDetails('${domain.domain_name}')"> |
|
<i class="fas fa-info-circle"></i> Detaylar |
|
</button> |
|
<button class="btn btn-sm btn-danger" onclick="deleteDomain('${domain.domain_name}')"> |
|
<i class="fas fa-trash"></i> Sil |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
`).join(''); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error loading domains:', error); |
|
alert('Domainler yüklenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function viewDomainDetails(domain) { |
|
try { |
|
const response = await fetch(`${API_URL}?action=getDomainDetails&domain=${domain}`, { |
|
headers: { |
|
'X-Admin-Token': adminToken |
|
} |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
const domainData = data.data.domain; |
|
const apiDetails = data.data.api_details; |
|
|
|
|
|
const modalContent = ` |
|
<div class="modal-content"> |
|
<div class="modal-header"> |
|
<h3 class="modal-title">Domain Detayları</h3> |
|
<button class="modal-close" onclick="closeModal()">×</button> |
|
</div> |
|
<div class="modal-body"> |
|
<div class="detail-section"> |
|
<h4> |
|
<i class="fas fa-globe"></i> |
|
${domain} |
|
</h4> |
|
<div class="detail-grid"> |
|
<div class="detail-item"> |
|
<div class="detail-label"> |
|
<i class="fas fa-info-circle"></i> |
|
Durum |
|
</div> |
|
<div class="detail-value"> |
|
<span class="status-badge ${domainData.status === 'active' ? 'active' : 'inactive'}"> |
|
<i class="fas fa-${domainData.status === 'active' ? 'check' : 'times'}-circle"></i> |
|
${domainData.status === 'active' ? 'Aktif' : 'Pasif'} |
|
</span> |
|
</div> |
|
</div> |
|
|
|
<div class="detail-item"> |
|
<div class="detail-label"> |
|
<i class="fas fa-calendar"></i> |
|
Kayıt Tarihi |
|
</div> |
|
<div class="detail-value"> |
|
${new Date(domainData.created_at).toLocaleDateString('tr-TR')} |
|
</div> |
|
</div> |
|
|
|
<div class="detail-item"> |
|
<div class="detail-label"> |
|
<i class="fas fa-user"></i> |
|
Mevcut Kullanıcı |
|
</div> |
|
<div class="detail-value user-auth"> |
|
${domainData.user_auth_code || 'Atanmamış'} |
|
</div> |
|
</div> |
|
|
|
<div class="detail-item"> |
|
<div class="detail-label"> |
|
<i class="fas fa-shield-alt"></i> |
|
Doğrulama Durumu |
|
</div> |
|
<div class="detail-value"> |
|
<span class="status-badge ${domainData.verified ? 'verified' : 'unverified'}"> |
|
<i class="fas fa-${domainData.verified ? 'check' : 'exclamation'}-circle"></i> |
|
${domainData.verified ? 'Doğrulanmış' : 'Doğrulanmamış'} |
|
</span> |
|
${!domainData.verified ? ` |
|
<button class="btn btn-sm btn-success" onclick="verifyDomain('${domain}')"> |
|
<i class="fas fa-check-circle"></i> Doğrula |
|
</button> |
|
` : ''} |
|
</div> |
|
</div> |
|
|
|
${domainData.verified ? ` |
|
<div class="detail-item"> |
|
<div class="detail-label"> |
|
<i class="fas fa-clock"></i> |
|
Doğrulama Tarihi |
|
</div> |
|
<div class="detail-value"> |
|
${new Date(domainData.verified_at).toLocaleDateString('tr-TR')} |
|
</div> |
|
</div> |
|
` : ''} |
|
</div> |
|
</div> |
|
|
|
<div class="detail-section"> |
|
<h4> |
|
<i class="fas fa-user"></i> |
|
Domain Sahibi |
|
</h4> |
|
<div class="detail-grid"> |
|
<div class="detail-item"> |
|
<div class="detail-label"> |
|
<i class="fas fa-key"></i> |
|
Auth Code |
|
</div> |
|
<div class="detail-value user-auth"> |
|
${apiDetails.data.user_auth_code || 'Atanmamış'} |
|
${apiDetails.data.user_auth_code ? ` |
|
<button class="btn btn-sm btn-danger" onclick="unassignDomain('${domain}')"> |
|
<i class="fas fa-user-minus"></i> Atamayı Kaldır |
|
</button> |
|
` : ` |
|
<div class="input-group"> |
|
<input type="text" id="assignAuthCode" class="form-control" |
|
placeholder="Kullanıcı auth kodunu girin"> |
|
<button class="btn btn-primary" onclick="assignDomain('${domain}')"> |
|
<i class="fas fa-user-plus"></i> Ata |
|
</button> |
|
</div> |
|
`} |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="detail-section"> |
|
<h4> |
|
<i class="fas fa-code"></i> |
|
API Detayları |
|
</h4> |
|
<pre class="api-details">${JSON.stringify(apiDetails, null, 2)}</pre> |
|
</div> |
|
</div> |
|
</div> |
|
`; |
|
|
|
|
|
const modal = document.createElement('div'); |
|
modal.className = 'modal active'; |
|
modal.id = 'domainModal'; |
|
modal.innerHTML = modalContent; |
|
document.body.appendChild(modal); |
|
|
|
|
|
modal.addEventListener('click', (e) => { |
|
if (e.target === modal) closeModal(); |
|
}); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error loading domain details:', error); |
|
alert('Domain detayları yüklenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
function closeModal() { |
|
const domainModal = document.getElementById('domainModal'); |
|
const domainsModal = document.getElementById('domainsModal'); |
|
|
|
if (domainModal) { |
|
domainModal.remove(); |
|
} |
|
if (domainsModal) { |
|
domainsModal.remove(); |
|
} |
|
} |
|
|
|
async function assignDomain(domain) { |
|
const authCode = document.getElementById('assignAuthCode').value.trim(); |
|
if (!authCode) { |
|
alert('Lütfen bir auth kodu girin'); |
|
return; |
|
} |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=assignDomain`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ domain, authCode }) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
alert('Domain başarıyla atandı'); |
|
closeModal(); |
|
loadAllDomains(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error assigning domain:', error); |
|
alert('Domain atanırken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function unassignDomain(domain) { |
|
if (!confirm(`${domain} domaininin atamasını kaldırmak istediğinize emin misiniz?`)) { |
|
return; |
|
} |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=unassignDomain`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ domain }) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
alert('Domain ataması kaldırıldı'); |
|
closeModal(); |
|
loadAllDomains(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error unassigning domain:', error); |
|
alert('Domain ataması kaldırılırken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function deleteDomain(domain) { |
|
if (!confirm(`${domain} domainini silmek istediğinize emin misiniz?`)) { |
|
return; |
|
} |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=deleteDomain`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ domain }) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
loadAllDomains(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error deleting domain:', error); |
|
alert('Domain silinirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
function loadSettings() { |
|
|
|
document.getElementById('apiUrl').value = BASE_URL; |
|
document.getElementById('adminUsername').value = localStorage.getItem('adminUsername') || ''; |
|
} |
|
|
|
async function saveSettings() { |
|
const username = document.getElementById('adminUsername').value; |
|
const password = document.getElementById('newPassword').value; |
|
|
|
if (!username) { |
|
alert('Kullanıcı adı gerekli!'); |
|
return; |
|
} |
|
|
|
if (!password) { |
|
alert('Yeni şifre gerekli!'); |
|
return; |
|
} |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=updateAdminSettings`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ username, password }) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
localStorage.setItem('adminUsername', username); |
|
alert('Ayarlar başarıyla güncellendi!'); |
|
document.getElementById('newPassword').value = ''; |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error updating settings:', error); |
|
alert('Ayarlar güncellenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function loadAllDomainsFromApi() { |
|
if (!confirm('Tüm domainleri API\'den yüklemek istediğinize emin misiniz?')) { |
|
return; |
|
} |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=loadAllDomainsFromApi`, { |
|
headers: { |
|
'X-Admin-Token': adminToken |
|
} |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
alert(data.message); |
|
loadAllDomains(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error loading domains from API:', error); |
|
alert('Domainler API\'den yüklenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function loadPromoCodes() { |
|
try { |
|
const response = await fetch(`${API_URL}?action=listPromoCodes`, { |
|
headers: { |
|
'X-Admin-Token': adminToken |
|
} |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
const promoList = document.getElementById('promoList'); |
|
promoList.innerHTML = data.data.map(promo => ` |
|
<div class="user-card"> |
|
<div class="user-header"> |
|
<span class="user-auth"> |
|
${promo.code} |
|
<button class="btn-icon" onclick="copyPromoCode('${promo.code}')" title="Kodu Kopyala"> |
|
<i class="fas fa-copy"></i> |
|
</button> |
|
</span> |
|
<span class="status-badge ${promo.current_uses >= promo.max_uses && promo.max_uses !== 0 ? 'inactive' : 'active'}"> |
|
${promo.current_uses >= promo.max_uses && promo.max_uses !== 0 ? 'Tükenmiş' : 'Aktif'} |
|
</span> |
|
</div> |
|
<div class="user-stats"> |
|
<div class="stat-item"> |
|
<div class="stat-label">Kredi Miktarı</div> |
|
<div class="stat-value">${promo.discount_amount}</div> |
|
</div> |
|
<div class="stat-item"> |
|
<div class="stat-label">Kullanım</div> |
|
<div class="stat-value">${promo.current_uses}/${promo.max_uses || '∞'}</div> |
|
</div> |
|
<div class="stat-item"> |
|
<div class="stat-label">Oluşturma Tarihi</div> |
|
<div class="stat-value">${new Date(promo.created_at).toLocaleDateString('tr-TR')}</div> |
|
</div> |
|
</div> |
|
<div class="user-actions"> |
|
<button class="btn btn-danger" onclick="removePromoCode('${promo.code}')"> |
|
<i class="fas fa-trash"></i> Kodu Sil |
|
</button> |
|
</div> |
|
</div> |
|
`).join(''); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error loading promo codes:', error); |
|
alert('Promo kodları yüklenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function createPromoCode() { |
|
|
|
const modal = document.createElement('div'); |
|
modal.className = 'modal'; |
|
modal.innerHTML = ` |
|
<div class="modal-content"> |
|
<div class="modal-header"> |
|
<h3>Yeni Promo Kodu Oluştur</h3> |
|
<button onclick="this.closest('.modal').remove()">×</button> |
|
</div> |
|
<div class="modal-body"> |
|
<form id="promoForm" onsubmit="submitPromoCode(event)"> |
|
<div class="form-group"> |
|
<label>Kredi Miktarı</label> |
|
<input type="number" id="discountAmount" required min="1"> |
|
</div> |
|
<div class="form-group"> |
|
<label>Maksimum Kullanım (0 = sınırsız)</label> |
|
<input type="number" id="maxUses" required min="0" value="1"> |
|
</div> |
|
<button type="submit" class="btn">Oluştur</button> |
|
</form> |
|
</div> |
|
</div> |
|
`; |
|
document.body.appendChild(modal); |
|
} |
|
|
|
async function submitPromoCode(event) { |
|
event.preventDefault(); |
|
|
|
const discountAmount = document.getElementById('discountAmount').value; |
|
const maxUses = document.getElementById('maxUses').value; |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=createPromoCode`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ |
|
discount_amount: parseInt(discountAmount), |
|
max_uses: parseInt(maxUses) |
|
}) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
alert(`Promo kodu başarıyla oluşturuldu: ${data.data.promo_code}`); |
|
document.querySelector('.modal').remove(); |
|
loadPromoCodes(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error creating promo code:', error); |
|
alert('Promo kodu oluşturulurken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function removePromoCode(code) { |
|
if (!confirm(`"${code}" promo kodunu silmek istediğinize emin misiniz?`)) { |
|
return; |
|
} |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=removePromoCode`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ code }) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
alert('Promo kodu başarıyla silindi'); |
|
loadPromoCodes(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error removing promo code:', error); |
|
alert('Promo kodu silinirken bir hata oluştu'); |
|
} |
|
} |
|
|
|
function searchUsers() { |
|
const searchInput = document.getElementById('userSearch').value.toLowerCase(); |
|
const userCards = document.querySelectorAll('#userList .user-card'); |
|
|
|
userCards.forEach(card => { |
|
const authCode = card.getAttribute('data-auth'); |
|
if (authCode.includes(searchInput)) { |
|
card.style.display = 'block'; |
|
} else { |
|
card.style.display = 'none'; |
|
} |
|
}); |
|
} |
|
|
|
function searchDomains() { |
|
const searchInput = document.getElementById('domainSearch').value.toLowerCase(); |
|
const domainCards = document.querySelectorAll('#domainList .user-card'); |
|
|
|
domainCards.forEach(card => { |
|
const domainName = card.getAttribute('data-domain'); |
|
if (domainName.includes(searchInput)) { |
|
card.style.display = 'block'; |
|
} else { |
|
card.style.display = 'none'; |
|
} |
|
}); |
|
} |
|
|
|
|
|
const style = document.createElement('style'); |
|
style.textContent = ` |
|
.page { |
|
display: none; |
|
} |
|
.page.active { |
|
display: block; |
|
} |
|
.settings-form { |
|
max-width: 600px; |
|
background-color: #1a1a1a; |
|
padding: 2rem; |
|
border-radius: 12px; |
|
box-shadow: 0 2px 4px rgba(0,0,0,0.2); |
|
} |
|
`; |
|
document.head.appendChild(style); |
|
|
|
async function loginAsUser(authCode) { |
|
|
|
const currentAdminToken = adminToken; |
|
|
|
try { |
|
|
|
localStorage.setItem('authCode', authCode); |
|
|
|
|
|
window.open('/panel.html', '_blank'); |
|
} catch (error) { |
|
console.error('Error logging in as user:', error); |
|
alert('Kullanıcı olarak giriş yapılırken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
function copyPromoCode(code) { |
|
try { |
|
|
|
if (navigator.clipboard && window.isSecureContext) { |
|
navigator.clipboard.writeText(code).then(() => { |
|
showToast('Promo kod kopyalandı', 'success'); |
|
}).catch(() => { |
|
showToast('Promo kod kopyalanamadı', 'error'); |
|
}); |
|
} else { |
|
|
|
const textArea = document.createElement('textarea'); |
|
textArea.value = code; |
|
document.body.appendChild(textArea); |
|
textArea.select(); |
|
try { |
|
document.execCommand('copy'); |
|
showToast('Promo kod kopyalandı', 'success'); |
|
} catch (err) { |
|
showToast('Promo kod kopyalanamadı', 'error'); |
|
} |
|
document.body.removeChild(textArea); |
|
} |
|
} catch (error) { |
|
console.error('Copy error:', error); |
|
showToast('Promo kod kopyalanamadı', 'error'); |
|
} |
|
} |
|
|
|
async function verifyDomain(domain) { |
|
if (!confirm(`${domain} domainini doğrulamak istediğinize emin misiniz?`)) { |
|
return; |
|
} |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=verifyDomain`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ domain }) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
alert('Domain başarıyla doğrulandı'); |
|
loadAllDomains(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error verifying domain:', error); |
|
alert('Domain doğrulanırken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function verifyUserDomains(userId) { |
|
if (!confirm('Bu kullanıcının tüm domainlerini doğrulamak istediğinize emin misiniz?')) { |
|
return; |
|
} |
|
|
|
try { |
|
|
|
const response = await fetch(`${API_URL}?action=getUserDomains&userId=${userId}`, { |
|
headers: { |
|
'X-Admin-Token': adminToken |
|
} |
|
}); |
|
|
|
const data = await response.json(); |
|
if (!data.success) { |
|
alert(data.message); |
|
return; |
|
} |
|
|
|
let verifiedCount = 0; |
|
let failedCount = 0; |
|
|
|
|
|
for (const domain of data.data) { |
|
try { |
|
const verifyResponse = await fetch(`${API_URL}?action=verifyDomain`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ domain: domain.domain_name }) |
|
}); |
|
|
|
const verifyData = await verifyResponse.json(); |
|
if (verifyData.success) { |
|
verifiedCount++; |
|
} else { |
|
failedCount++; |
|
} |
|
} catch (error) { |
|
failedCount++; |
|
console.error(`Error verifying domain ${domain.domain_name}:`, error); |
|
} |
|
} |
|
|
|
alert(`Doğrulama tamamlandı!\nBaşarılı: ${verifiedCount}\nBaşarısız: ${failedCount}`); |
|
loadUsers(); |
|
} catch (error) { |
|
console.error('Error verifying user domains:', error); |
|
alert('Domainler doğrulanırken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function loadResellers() { |
|
try { |
|
const response = await fetch(`${API_URL}?action=getAllResellers`, { |
|
headers: { |
|
'X-Admin-Token': adminToken |
|
} |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
const resellerList = document.getElementById('resellerList'); |
|
resellerList.innerHTML = data.data.map(reseller => ` |
|
<div class="user-card"> |
|
<div class="user-header"> |
|
<div class="user-avatar"> |
|
<img |
|
src="${reseller.avatar_url}" |
|
alt="${reseller.username}" |
|
onerror="this.src='https://via.placeholder.com/60x60?text=${reseller.username.charAt(0)}'" |
|
> |
|
</div> |
|
<div class="user-info"> |
|
<h3>${reseller.username}</h3> |
|
<a href="${reseller.website}" target="_blank">${reseller.website}</a> |
|
<div class="reseller-auth">Auth Code: ${reseller.auth_code}</div> |
|
<div class="reseller-rights">Kalan Kayıt Hakkı: ${reseller.registration_rights}</div> |
|
</div> |
|
<div class="user-actions"> |
|
<button class="btn-icon" onclick="editReseller(${reseller.id})" title="Düzenle"> |
|
<i class="fas fa-edit"></i> |
|
</button> |
|
<button class="btn-icon" onclick="removeReseller(${reseller.id})" title="Sil"> |
|
<i class="fas fa-trash"></i> |
|
</button> |
|
</div> |
|
</div> |
|
<div class="user-description"> |
|
${reseller.description} |
|
</div> |
|
</div> |
|
`).join(''); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error loading resellers:', error); |
|
alert('Resellerlar yüklenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
function addReseller() { |
|
const modal = document.createElement('div'); |
|
modal.className = 'modal'; |
|
modal.innerHTML = ` |
|
<div class="modal-content"> |
|
<div class="modal-header"> |
|
<h3>Yeni Reseller Ekle</h3> |
|
<button class="modal-close" onclick="this.closest('.modal').remove()">×</button> |
|
</div> |
|
<div class="modal-body"> |
|
<form id="resellerForm"> |
|
<div class="form-group"> |
|
<label>Kullanıcı Adı</label> |
|
<input type="text" id="username" required> |
|
</div> |
|
<div class="form-group"> |
|
<label>Auth Code</label> |
|
<input type="text" id="authCode" required> |
|
</div> |
|
<div class="form-group"> |
|
<label>Profil Resmi URL</label> |
|
<input type="url" id="avatarUrl" required> |
|
</div> |
|
<div class="form-group"> |
|
<label>Website URL</label> |
|
<input type="url" id="website" required> |
|
</div> |
|
<div class="form-group"> |
|
<label>Açıklama</label> |
|
<textarea id="description" required |
|
placeholder="Reseller hakkında detaylı açıklama yazın..." |
|
style="width: 100%; min-height: 150px; resize: vertical;"></textarea> |
|
</div> |
|
<div class="form-actions"> |
|
<button type="button" class="btn btn-secondary" onclick="this.closest('.modal').remove()">İptal</button> |
|
<button type="submit" class="btn">Kaydet</button> |
|
</div> |
|
</form> |
|
</div> |
|
</div> |
|
`; |
|
|
|
document.body.appendChild(modal); |
|
|
|
modal.querySelector('form').addEventListener('submit', async (e) => { |
|
e.preventDefault(); |
|
await saveReseller(); |
|
}); |
|
} |
|
|
|
async function saveReseller() { |
|
const username = document.getElementById('username').value; |
|
const authCode = document.getElementById('authCode').value; |
|
const avatarUrl = document.getElementById('avatarUrl').value; |
|
const website = document.getElementById('website').value; |
|
const description = document.getElementById('description').value; |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=addReseller`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ |
|
username, |
|
authCode, |
|
avatarUrl, |
|
website, |
|
description |
|
}) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
alert('Reseller başarıyla eklendi'); |
|
document.querySelector('.modal').remove(); |
|
loadResellers(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error adding reseller:', error); |
|
alert('Reseller eklenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function editReseller(id) { |
|
try { |
|
|
|
const response = await fetch(`${API_URL}?action=getReseller&id=${id}`, { |
|
headers: { |
|
'X-Admin-Token': adminToken |
|
} |
|
}); |
|
|
|
const data = await response.json(); |
|
if (!data.success) { |
|
alert(data.message); |
|
return; |
|
} |
|
|
|
const reseller = data.data; |
|
|
|
|
|
const modal = document.createElement('div'); |
|
modal.className = 'modal'; |
|
modal.innerHTML = ` |
|
<div class="modal-content"> |
|
<div class="modal-header"> |
|
<h3>Reseller Düzenle</h3> |
|
<button class="modal-close" onclick="this.closest('.modal').remove()">×</button> |
|
</div> |
|
<div class="modal-body"> |
|
<form id="editResellerForm"> |
|
<div class="form-group"> |
|
<label>Profil Resmi URL</label> |
|
<input type="url" id="editAvatarUrl" value="${reseller.avatar_url}" required> |
|
</div> |
|
<div class="form-group"> |
|
<label>Kullanıcı Adı</label> |
|
<input type="text" id="editUsername" value="${reseller.username}" required> |
|
</div> |
|
<div class="form-group"> |
|
<label>Website URL</label> |
|
<input type="url" id="editWebsite" value="${reseller.website}" required> |
|
</div> |
|
<div class="form-group"> |
|
<label>Açıklama</label> |
|
<textarea id="editDescription" required |
|
placeholder="Reseller hakkında detaylı açıklama yazın..." |
|
style="width: 100%; min-height: 150px; resize: vertical;">${reseller.description}</textarea> |
|
</div> |
|
<input type="hidden" id="editResellerId" value="${reseller.id}"> |
|
<div class="form-actions"> |
|
<button type="button" class="btn btn-secondary" onclick="this.closest('.modal').remove()">İptal</button> |
|
<button type="submit" class="btn">Kaydet</button> |
|
</div> |
|
</form> |
|
</div> |
|
</div> |
|
`; |
|
|
|
document.body.appendChild(modal); |
|
|
|
modal.querySelector('form').addEventListener('submit', async (e) => { |
|
e.preventDefault(); |
|
await updateReseller(); |
|
}); |
|
|
|
} catch (error) { |
|
console.error('Error loading reseller details:', error); |
|
alert('Reseller bilgileri yüklenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function updateReseller() { |
|
const id = document.getElementById('editResellerId').value; |
|
const avatarUrl = document.getElementById('editAvatarUrl').value; |
|
const username = document.getElementById('editUsername').value; |
|
const website = document.getElementById('editWebsite').value; |
|
const description = document.getElementById('editDescription').value; |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=editReseller`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ |
|
id, |
|
avatarUrl, |
|
username, |
|
website, |
|
description |
|
}) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
alert('Reseller başarıyla güncellendi'); |
|
document.querySelector('.modal').remove(); |
|
loadResellers(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error updating reseller:', error); |
|
alert('Reseller güncellenirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
async function removeReseller(id) { |
|
if (!confirm('Bu reseller\'ı silmek istediğinize emin misiniz?')) { |
|
return; |
|
} |
|
|
|
try { |
|
const response = await fetch(`${API_URL}?action=removeReseller`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'X-Admin-Token': adminToken |
|
}, |
|
body: JSON.stringify({ id }) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.success) { |
|
alert('Reseller başarıyla silindi'); |
|
loadResellers(); |
|
} else { |
|
alert(data.message); |
|
} |
|
} catch (error) { |
|
console.error('Error removing reseller:', error); |
|
alert('Reseller silinirken bir hata oluştu.'); |
|
} |
|
} |
|
|
|
function showToast(message, type = 'info') { |
|
|
|
let toastContainer = document.getElementById('toastContainer'); |
|
if (!toastContainer) { |
|
toastContainer = document.createElement('div'); |
|
toastContainer.id = 'toastContainer'; |
|
document.body.appendChild(toastContainer); |
|
} |
|
|
|
|
|
const toast = document.createElement('div'); |
|
toast.className = `toast toast-${type}`; |
|
toast.textContent = message; |
|
|
|
|
|
toastContainer.appendChild(toast); |
|
|
|
|
|
setTimeout(() => { |
|
toast.classList.add('fade-out'); |
|
setTimeout(() => { |
|
toastContainer.removeChild(toast); |
|
}, 300); |
|
}, 3000); |
|
} |
|
</script> |
|
</body> |
|
</html> |