Files
2026-07-14 00:01:48 +03:00

1331 lines
49 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title', 'Panel') Animexe Admin</title>
@php $__fav = \App\Models\Setting::get('site_favicon','') @endphp
@if($__fav)<link rel="icon" href="{{ $__fav }}">@else<link rel="icon" href="/favicon.png">@endif
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
<style>
/* ═══════════════════════════════════════════════════════════════
ANIMEXE ADMIN — Design System v2
═══════════════════════════════════════════════════════════════ */
:root {
--bg: #07071c;
--bg2: #0c0c26;
--sidebar-bg: #090920;
--topbar-bg: #0a0a21;
--surface: #10103a;
--surface2: rgba(255,255,255,0.03);
--border: rgba(255,255,255,0.07);
--border2: rgba(255,255,255,0.12);
--accent: #7c3aed;
--accent-lt: #a855f7;
--accent-glow: rgba(124,58,237,0.3);
--accent-dim: rgba(124,58,237,0.12);
--text: #e2e0f0;
--text2: #8b87a8;
--text3: #55527a;
--success: #10b981;
--success-dim: rgba(16,185,129,0.12);
--danger: #ef4444;
--danger-dim: rgba(239,68,68,0.12);
--warning: #f59e0b;
--warning-dim: rgba(245,158,11,0.12);
--info: #06b6d4;
--info-dim: rgba(6,182,212,0.12);
--sidebar-w: 260px;
--topbar-h: 60px;
--radius: 12px;
--radius-sm: 8px;
--radius-lg: 16px;
--shadow: 0 4px 24px rgba(0,0,0,0.35);
--shadow-lg: 0 8px 48px rgba(0,0,0,0.5);
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
background: var(--bg);
color: var(--text);
font-family: 'Inter', 'Segoe UI', system-ui, sans-serif;
font-size: 14px;
line-height: 1.6;
overflow-x: hidden;
-webkit-font-smoothing: antialiased;
}
/* ── Scrollbar ── */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.18); }
/* ════════════════════════════════════════════════════════════════
SIDEBAR
════════════════════════════════════════════════════════════════ */
#sidebar {
position: fixed;
top: 0; left: 0;
width: var(--sidebar-w);
height: 100vh;
background: var(--sidebar-bg);
border-right: 1px solid var(--border);
display: flex;
flex-direction: column;
z-index: 1050;
transition: transform 0.3s cubic-bezier(0.4,0,0.2,1);
overflow: hidden;
}
/* Brand */
.sb-brand {
display: flex;
align-items: center;
gap: 10px;
padding: 0 20px;
height: var(--topbar-h);
border-bottom: 1px solid var(--border);
flex-shrink: 0;
text-decoration: none;
}
.sb-brand-icon {
width: 34px; height: 34px;
background: linear-gradient(135deg, var(--accent), var(--accent-lt));
border-radius: 10px;
display: flex; align-items: center; justify-content: center;
font-size: 16px; color: #fff;
box-shadow: 0 0 20px var(--accent-glow);
flex-shrink: 0;
}
.sb-brand-text {
font-size: 15px;
font-weight: 800;
color: var(--text);
letter-spacing: 0.5px;
}
.sb-brand-text span { color: var(--accent-lt); }
.sb-close {
display: none;
margin-left: auto;
background: none;
border: none;
color: var(--text2);
font-size: 18px;
cursor: pointer;
padding: 4px;
line-height: 1;
border-radius: 6px;
transition: all 0.15s;
}
.sb-close:hover { background: var(--surface2); color: var(--text); }
/* Nav */
.sb-nav {
flex: 1;
overflow-y: auto;
padding: 12px 0;
scrollbar-width: thin;
scrollbar-color: rgba(255,255,255,0.06) transparent;
}
.sb-section {
padding: 14px 20px 6px;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1.2px;
color: var(--text3);
}
.sb-section:first-child { padding-top: 6px; }
.sb-link {
display: flex;
align-items: center;
gap: 10px;
margin: 1px 10px;
padding: 9px 12px;
border-radius: var(--radius-sm);
color: var(--text2);
text-decoration: none;
font-size: 13.5px;
font-weight: 500;
transition: all 0.15s;
position: relative;
}
.sb-link:hover {
background: rgba(255,255,255,0.04);
color: var(--text);
}
.sb-link.active {
background: var(--accent-dim);
color: var(--accent-lt);
}
.sb-link.active::before {
content: '';
position: absolute;
left: 0; top: 50%;
transform: translateY(-50%);
width: 3px; height: 60%;
background: var(--accent-lt);
border-radius: 0 3px 3px 0;
}
.sb-link i {
font-size: 15px;
width: 20px;
text-align: center;
flex-shrink: 0;
opacity: 0.75;
}
.sb-link.active i { opacity: 1; }
.sb-link .sb-badge {
margin-left: auto;
padding: 2px 7px;
border-radius: 99px;
font-size: 10px;
font-weight: 700;
line-height: 1.4;
background: var(--danger);
color: #fff;
}
.sb-link .sb-badge-warn { background: var(--warning); color: #000; }
.sb-link .sb-badge-muted { background: rgba(255,255,255,0.08); color: var(--text2); }
/* Sidebar footer */
.sb-footer {
flex-shrink: 0;
padding: 14px 20px;
border-top: 1px solid var(--border);
}
.sb-footer-user {
display: flex;
align-items: center;
gap: 10px;
}
.sb-avatar {
width: 34px; height: 34px;
border-radius: 10px;
background: linear-gradient(135deg, var(--accent), var(--accent-lt));
display: flex; align-items: center; justify-content: center;
font-weight: 700;
font-size: 13px;
color: #fff;
flex-shrink: 0;
}
.sb-user-info { min-width: 0; flex: 1; }
.sb-user-name {
font-size: 13px;
font-weight: 600;
color: var(--text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.sb-user-role {
font-size: 11px;
color: var(--text3);
font-weight: 500;
}
.sb-logout {
background: none;
border: none;
color: var(--text3);
font-size: 16px;
cursor: pointer;
padding: 5px;
border-radius: 6px;
flex-shrink: 0;
transition: all 0.15s;
line-height: 1;
}
.sb-logout:hover { background: var(--danger-dim); color: var(--danger); }
/* ════════════════════════════════════════════════════════════════
OVERLAY
════════════════════════════════════════════════════════════════ */
#sb-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.65);
backdrop-filter: blur(3px);
z-index: 1040;
}
#sb-overlay.on { display: block; }
/* ════════════════════════════════════════════════════════════════
TOPBAR
════════════════════════════════════════════════════════════════ */
#topbar {
position: fixed;
top: 0;
left: var(--sidebar-w);
right: 0;
height: var(--topbar-h);
background: var(--topbar-bg);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
padding: 0 24px;
gap: 12px;
z-index: 900;
backdrop-filter: blur(12px);
}
#topbar-hamburger {
display: none;
background: none;
border: none;
color: var(--text2);
font-size: 20px;
cursor: pointer;
padding: 5px;
border-radius: 8px;
line-height: 1;
flex-shrink: 0;
transition: all 0.15s;
}
#topbar-hamburger:hover { background: var(--surface2); color: var(--text); }
.topbar-title {
font-size: 15px;
font-weight: 700;
color: var(--text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.topbar-right {
display: flex;
align-items: center;
gap: 8px;
margin-left: auto;
flex-shrink: 0;
}
.topbar-btn {
display: flex;
align-items: center;
justify-content: center;
width: 36px; height: 36px;
border-radius: var(--radius-sm);
border: 1px solid var(--border);
background: var(--surface2);
color: var(--text2);
text-decoration: none;
font-size: 15px;
transition: all 0.15s;
cursor: pointer;
}
.topbar-btn:hover { background: rgba(255,255,255,0.07); color: var(--text); border-color: var(--border2); }
.topbar-divider { width: 1px; height: 24px; background: var(--border); flex-shrink: 0; }
.topbar-user {
display: flex;
align-items: center;
gap: 9px;
padding: 5px 10px 5px 6px;
border-radius: var(--radius-sm);
border: 1px solid var(--border);
background: var(--surface2);
cursor: default;
}
.topbar-avatar {
width: 28px; height: 28px;
border-radius: 8px;
background: linear-gradient(135deg, var(--accent), var(--accent-lt));
display: flex; align-items: center; justify-content: center;
font-weight: 700;
font-size: 11px;
color: #fff;
flex-shrink: 0;
}
.topbar-username {
font-size: 13px;
font-weight: 600;
color: var(--text);
}
/* ════════════════════════════════════════════════════════════════
MAIN CONTENT
════════════════════════════════════════════════════════════════ */
#main {
margin-left: var(--sidebar-w);
padding-top: var(--topbar-h);
min-height: 100vh;
}
.content-wrap { padding: 28px 30px; }
/* ════════════════════════════════════════════════════════════════
PAGE HEADER
════════════════════════════════════════════════════════════════ */
.page-header {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12px;
margin-bottom: 24px;
}
.page-header-left h1,
.page-header-left h2,
.page-header-left h3,
.page-header-left h4,
.page-header-left h5,
.page-header h5,
.page-header h4 {
font-size: 18px;
font-weight: 700;
color: var(--text);
margin: 0;
}
.page-header .text-muted,
.page-sub {
font-size: 13px;
color: var(--text2);
margin-top: 2px;
}
.page-header-actions {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
/* ════════════════════════════════════════════════════════════════
CARDS
════════════════════════════════════════════════════════════════ */
.card {
background: var(--bg2);
border: 1px solid var(--border);
border-radius: var(--radius);
box-shadow: none;
}
.card-header {
background: transparent;
border-bottom: 1px solid var(--border);
padding: 16px 20px;
display: flex;
align-items: center;
gap: 10px;
}
.card-header h5,
.card-header h6 {
font-size: 14px;
font-weight: 700;
color: var(--text);
margin: 0;
}
.card-body { padding: 20px; }
.card-footer {
background: transparent;
border-top: 1px solid var(--border);
padding: 14px 20px;
}
/* Stat Cards */
.stat-card {
background: var(--bg2);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 22px;
display: flex;
flex-direction: column;
gap: 10px;
transition: border-color 0.2s, box-shadow 0.2s;
}
.stat-card:hover {
border-color: var(--border2);
box-shadow: 0 0 0 1px var(--border2), var(--shadow);
}
.stat-card-top {
display: flex;
align-items: center;
justify-content: space-between;
}
.stat-icon {
width: 44px; height: 44px;
border-radius: 12px;
display: flex; align-items: center; justify-content: center;
font-size: 20px;
flex-shrink: 0;
}
.stat-icon.violet { background: var(--accent-dim); color: var(--accent-lt); }
.stat-icon.cyan { background: var(--info-dim); color: var(--info); }
.stat-icon.green { background: var(--success-dim); color: var(--success); }
.stat-icon.orange { background: var(--warning-dim); color: var(--warning); }
.stat-icon.red { background: var(--danger-dim); color: var(--danger); }
.stat-value {
font-size: 28px;
font-weight: 800;
color: var(--text);
letter-spacing: -0.5px;
line-height: 1;
}
.stat-label {
font-size: 12.5px;
color: var(--text2);
font-weight: 500;
}
.stat-trend {
font-size: 12px;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 3px;
}
.stat-trend.up { color: var(--success); }
.stat-trend.down { color: var(--danger); }
/* ════════════════════════════════════════════════════════════════
TABLES
════════════════════════════════════════════════════════════════ */
.table-wrap {
background: var(--bg2);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
}
.table-wrap .table-responsive { border-radius: 0; }
.table {
--bs-table-bg: transparent;
--bs-table-border-color: var(--border);
--bs-table-color: var(--text);
--bs-table-hover-bg: rgba(255,255,255,0.025);
color: var(--text);
margin: 0;
}
.table thead th {
background: rgba(255,255,255,0.02);
border-bottom: 1px solid var(--border);
color: var(--text2);
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.7px;
padding: 12px 16px;
white-space: nowrap;
}
.table tbody td {
padding: 13px 16px;
vertical-align: middle;
font-size: 13.5px;
border-color: var(--border);
color: var(--text);
}
.table tbody tr:hover td { background: rgba(255,255,255,0.025) !important; }
.table tbody tr:last-child td { border-bottom: none; }
.table-dark { --bs-table-bg: var(--bg2); }
/* ════════════════════════════════════════════════════════════════
FORMS
════════════════════════════════════════════════════════════════ */
.form-control,
.form-select {
background: var(--bg);
border: 1px solid var(--border2);
color: var(--text);
border-radius: var(--radius-sm);
font-size: 13.5px;
padding: 9px 14px;
transition: border-color 0.15s, box-shadow 0.15s;
}
.form-control:focus,
.form-select:focus {
background: var(--bg);
border-color: var(--accent);
color: var(--text);
box-shadow: 0 0 0 3px var(--accent-glow);
outline: none;
}
.form-control::placeholder { color: var(--text3); }
.form-control:disabled,
.form-select:disabled {
background: rgba(255,255,255,0.03);
border-color: var(--border);
color: var(--text3);
opacity: 1;
}
.form-label {
font-size: 13px;
font-weight: 600;
color: var(--text2);
margin-bottom: 6px;
}
.form-text { color: var(--text3); font-size: 12px; }
.form-check-input {
background-color: var(--bg);
border-color: var(--border2);
}
.form-check-input:checked {
background-color: var(--accent);
border-color: var(--accent);
}
.form-check-input:focus { box-shadow: 0 0 0 3px var(--accent-glow); }
.input-group-text {
background: rgba(255,255,255,0.04);
border-color: var(--border2);
color: var(--text2);
font-size: 13.5px;
}
textarea.form-control { resize: vertical; min-height: 100px; }
/* ════════════════════════════════════════════════════════════════
BUTTONS
════════════════════════════════════════════════════════════════ */
.btn {
font-size: 13px;
font-weight: 600;
padding: 8px 16px;
border-radius: var(--radius-sm);
transition: all 0.15s;
display: inline-flex;
align-items: center;
gap: 6px;
line-height: 1.4;
}
.btn i { font-size: 14px; }
.btn-sm { padding: 5px 11px; font-size: 12px; }
.btn-sm i { font-size: 12px; }
.btn-lg { padding: 11px 22px; font-size: 14px; }
.btn-primary {
background: var(--accent);
border-color: var(--accent);
color: #fff;
}
.btn-primary:hover, .btn-primary:focus {
background: #6d28d9;
border-color: #6d28d9;
color: #fff;
box-shadow: 0 0 0 3px var(--accent-glow);
}
.btn-outline-primary {
border-color: var(--accent);
color: var(--accent-lt);
background: transparent;
}
.btn-outline-primary:hover {
background: var(--accent-dim);
border-color: var(--accent);
color: var(--accent-lt);
}
.btn-secondary {
background: rgba(255,255,255,0.07);
border-color: var(--border2);
color: var(--text);
}
.btn-secondary:hover {
background: rgba(255,255,255,0.12);
border-color: var(--border2);
color: var(--text);
}
.btn-outline-secondary {
border-color: var(--border2);
color: var(--text2);
background: transparent;
}
.btn-outline-secondary:hover {
background: rgba(255,255,255,0.06);
border-color: var(--border2);
color: var(--text);
}
.btn-success { background: var(--success); border-color: var(--success); color: #fff; }
.btn-success:hover { background: #059669; border-color: #059669; color: #fff; }
.btn-outline-success { border-color: var(--success); color: var(--success); background: transparent; }
.btn-outline-success:hover { background: var(--success-dim); border-color: var(--success); color: var(--success); }
.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn-danger:hover { background: #dc2626; border-color: #dc2626; color: #fff; }
.btn-outline-danger { border-color: var(--danger); color: var(--danger); background: transparent; }
.btn-outline-danger:hover { background: var(--danger-dim); border-color: var(--danger); color: var(--danger); }
.btn-warning { background: var(--warning); border-color: var(--warning); color: #000; font-weight: 700; }
.btn-outline-warning { border-color: var(--warning); color: var(--warning); background: transparent; }
.btn-outline-warning:hover { background: var(--warning-dim); border-color: var(--warning); color: var(--warning); }
.btn-info { background: var(--info); border-color: var(--info); color: #000; font-weight: 700; }
.btn-outline-info { border-color: var(--info); color: var(--info); background: transparent; }
.btn-light {
background: rgba(255,255,255,0.06);
border-color: var(--border);
color: var(--text2);
}
.btn-light:hover {
background: rgba(255,255,255,0.1);
color: var(--text);
}
.btn-dark {
background: rgba(0,0,0,0.3);
border-color: var(--border);
color: var(--text2);
}
.btn-link { color: var(--accent-lt); text-decoration: none; padding: 0; }
.btn-link:hover { color: var(--accent); text-decoration: underline; }
/* ════════════════════════════════════════════════════════════════
BADGES
════════════════════════════════════════════════════════════════ */
.badge {
font-size: 11px;
font-weight: 700;
padding: 3px 9px;
border-radius: 99px;
letter-spacing: 0.2px;
}
.bg-primary { background: var(--accent) !important; color: #fff; }
.bg-secondary { background: rgba(255,255,255,0.08) !important; color: var(--text2) !important; }
.bg-success { background: var(--success) !important; }
.bg-danger { background: var(--danger) !important; }
.bg-warning { background: var(--warning) !important; color: #000 !important; }
.bg-info { background: var(--info) !important; color: #000 !important; }
.bg-dark { background: rgba(255,255,255,0.06) !important; color: var(--text2) !important; }
.text-primary { color: var(--accent-lt) !important; }
.text-success { color: var(--success) !important; }
.text-danger { color: var(--danger) !important; }
.text-warning { color: var(--warning) !important; }
.text-info { color: var(--info) !important; }
.text-muted { color: var(--text2) !important; }
.text-secondary{ color: var(--text2) !important; }
.badge-premium { background: linear-gradient(135deg, #f59e0b, #d97706); color: #000; }
.badge-free { background: rgba(255,255,255,0.08); color: var(--text2); }
/* ════════════════════════════════════════════════════════════════
ALERTS
════════════════════════════════════════════════════════════════ */
.alert {
border-radius: var(--radius-sm);
border: 1px solid;
font-size: 13.5px;
padding: 12px 16px;
}
.alert-success { background: var(--success-dim); border-color: rgba(16,185,129,0.3); color: #6ee7b7; }
.alert-danger { background: var(--danger-dim); border-color: rgba(239,68,68,0.3); color: #fca5a5; }
.alert-warning { background: var(--warning-dim); border-color: rgba(245,158,11,0.3); color: #fcd34d; }
.alert-info { background: var(--info-dim); border-color: rgba(6,182,212,0.3); color: #67e8f9; }
.alert-primary { background: var(--accent-dim); border-color: rgba(124,58,237,0.3); color: var(--accent-lt); }
.btn-close { filter: invert(0.7) brightness(1.5); }
/* ════════════════════════════════════════════════════════════════
MODALS
════════════════════════════════════════════════════════════════ */
.modal-content {
background: var(--bg2);
border: 1px solid var(--border2);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-lg);
color: var(--text);
}
.modal-header {
border-bottom: 1px solid var(--border);
padding: 18px 22px;
}
.modal-header .modal-title { font-size: 15px; font-weight: 700; }
.modal-body { padding: 22px; }
.modal-footer {
border-top: 1px solid var(--border);
padding: 14px 22px;
gap: 8px;
}
.modal-backdrop { backdrop-filter: blur(4px); }
/* ════════════════════════════════════════════════════════════════
DROPDOWNS
════════════════════════════════════════════════════════════════ */
.dropdown-menu {
background: var(--bg2);
border: 1px solid var(--border2);
border-radius: var(--radius-sm);
padding: 6px;
box-shadow: var(--shadow-lg);
min-width: 160px;
}
.dropdown-item {
color: var(--text2);
border-radius: 6px;
font-size: 13px;
padding: 7px 12px;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.12s;
}
.dropdown-item:hover { background: rgba(255,255,255,0.06); color: var(--text); }
.dropdown-item.text-danger:hover { background: var(--danger-dim); color: var(--danger); }
.dropdown-divider { border-color: var(--border); margin: 4px 0; }
.dropdown-header { color: var(--text3); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.8px; }
/* ════════════════════════════════════════════════════════════════
PAGINATION
════════════════════════════════════════════════════════════════ */
.pagination {
gap: 3px;
align-items: center;
}
.pagination .page-link {
background: var(--bg2);
border: 1px solid var(--border);
color: var(--text2);
border-radius: var(--radius-sm) !important;
font-size: 13px;
padding: 6px 12px;
transition: all 0.15s;
}
.pagination .page-link:hover {
background: rgba(255,255,255,0.06);
border-color: var(--border2);
color: var(--text);
}
.pagination .page-item.active .page-link {
background: var(--accent);
border-color: var(--accent);
color: #fff;
box-shadow: 0 0 12px var(--accent-glow);
}
.pagination .page-item.disabled .page-link {
background: transparent;
border-color: var(--border);
color: var(--text3);
opacity: 0.5;
}
/* ════════════════════════════════════════════════════════════════
TOASTS (Flash Messages)
════════════════════════════════════════════════════════════════ */
#toast-container {
position: fixed;
bottom: 24px;
right: 24px;
z-index: 9999;
display: flex;
flex-direction: column;
gap: 8px;
pointer-events: none;
}
.ax-toast {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 18px;
border-radius: var(--radius-sm);
border: 1px solid;
font-size: 13.5px;
font-weight: 500;
max-width: 380px;
pointer-events: auto;
box-shadow: var(--shadow-lg);
backdrop-filter: blur(12px);
animation: toastIn 0.28s cubic-bezier(0.22,1,0.36,1) forwards;
}
.ax-toast.out { animation: toastOut 0.22s ease forwards; }
.ax-toast-success { background: rgba(16,185,129,0.12); border-color: rgba(16,185,129,0.35); color: #6ee7b7; }
.ax-toast-error { background: rgba(239,68,68,0.12); border-color: rgba(239,68,68,0.35); color: #fca5a5; }
.ax-toast-warning { background: rgba(245,158,11,0.12); border-color: rgba(245,158,11,0.35); color: #fcd34d; }
.ax-toast-info { background: rgba(6,182,212,0.12); border-color: rgba(6,182,212,0.35); color: #67e8f9; }
.ax-toast i { font-size: 16px; flex-shrink: 0; }
.ax-toast-msg { flex: 1; line-height: 1.4; }
.ax-toast-close {
background: none; border: none; cursor: pointer;
color: inherit; opacity: 0.5; font-size: 14px;
padding: 0; line-height: 1; flex-shrink: 0;
transition: opacity 0.12s;
}
.ax-toast-close:hover { opacity: 1; }
@keyframes toastIn {
from { opacity: 0; transform: translateX(20px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes toastOut {
from { opacity: 1; transform: translateX(0); }
to { opacity: 0; transform: translateX(20px); }
}
/* ════════════════════════════════════════════════════════════════
MISC COMPONENTS
════════════════════════════════════════════════════════════════ */
/* Dividers */
hr { border-color: var(--border); opacity: 1; }
/* Nav Tabs */
.nav-tabs {
border-bottom: 1px solid var(--border);
gap: 2px;
}
.nav-tabs .nav-link {
color: var(--text2);
border: none;
border-bottom: 2px solid transparent;
padding: 9px 16px;
font-size: 13px;
font-weight: 600;
border-radius: 0;
transition: all 0.15s;
background: none;
}
.nav-tabs .nav-link:hover { color: var(--text); }
.nav-tabs .nav-link.active { color: var(--accent-lt); border-bottom-color: var(--accent-lt); background: none; }
.tab-content { padding-top: 20px; }
/* Nav Pills */
.nav-pills .nav-link {
color: var(--text2);
font-size: 13px;
font-weight: 600;
padding: 7px 14px;
border-radius: var(--radius-sm);
transition: all 0.15s;
}
.nav-pills .nav-link:hover { background: rgba(255,255,255,0.05); color: var(--text); }
.nav-pills .nav-link.active { background: var(--accent-dim); color: var(--accent-lt); }
/* List Group */
.list-group-item {
background: transparent;
border-color: var(--border);
color: var(--text);
padding: 12px 16px;
font-size: 13.5px;
}
.list-group-item:first-child { border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
.list-group-item:last-child { border-radius: 0 0 var(--radius-sm) var(--radius-sm); }
.list-group-item.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent-lt); }
/* Code */
code {
background: rgba(255,255,255,0.06);
border: 1px solid var(--border);
border-radius: 4px;
padding: 1px 6px;
font-size: 12.5px;
color: var(--accent-lt);
}
pre {
background: rgba(0,0,0,0.3);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 16px;
font-size: 12.5px;
color: var(--text);
}
/* Progress */
.progress {
background: rgba(255,255,255,0.06);
border-radius: 99px;
height: 6px;
}
.progress-bar { background: var(--accent); border-radius: 99px; }
/* Spinner */
.spinner-border { color: var(--accent); }
/* Switch */
.form-switch .form-check-input {
width: 36px; height: 20px;
cursor: pointer;
}
.form-switch .form-check-input:checked { background-color: var(--accent); border-color: var(--accent); }
/* Eski stat-card → card dönüşümü için fallback padding */
.card:not(:has(.card-body)):not(:has(.card-header)) { padding: 18px 20px; }
/* Alert dark */
.alert-dark {
background: rgba(255,255,255,0.04);
border-color: var(--border2);
color: var(--text);
}
.alert-secondary {
background: rgba(255,255,255,0.04);
border-color: var(--border);
color: var(--text2);
}
/* Bootstrap dark-mode utility overrides (no data-bs-theme needed) */
.border-secondary { border-color: var(--border) !important; }
.border-secondary-subtle { border-color: var(--border) !important; }
.border-dark { border-color: var(--border2) !important; }
.bg-body-secondary { background: rgba(255,255,255,0.04) !important; }
.bg-body-tertiary { background: rgba(255,255,255,0.02) !important; }
.text-body-secondary { color: var(--text2) !important; }
.fw-500 { font-weight: 500; }
.small { font-size: 12.5px; }
/* Breadcrumb */
.breadcrumb { font-size: 12.5px; margin: 0; }
.breadcrumb-item { color: var(--text2); }
.breadcrumb-item + .breadcrumb-item::before { color: var(--text3); }
.breadcrumb-item.active { color: var(--text); }
.breadcrumb-item a { color: var(--text2); text-decoration: none; }
.breadcrumb-item a:hover { color: var(--accent-lt); }
/* Filter rows */
.filter-card {
background: var(--bg2);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 16px 20px;
margin-bottom: 16px;
}
/* Action buttons in tables */
.action-btns { display: flex; gap: 5px; align-items: center; }
.action-btns .btn { padding: 5px 10px; }
/* Empty state */
.empty-state {
text-align: center;
padding: 60px 20px;
color: var(--text2);
}
.empty-state i { font-size: 40px; opacity: 0.3; margin-bottom: 12px; display: block; }
.empty-state h6 { font-size: 15px; color: var(--text); margin-bottom: 6px; }
.empty-state p { font-size: 13px; color: var(--text2); }
/* Avatar */
.user-avatar {
width: 36px; height: 36px;
border-radius: 10px;
background: linear-gradient(135deg, var(--accent), var(--accent-lt));
display: flex; align-items: center; justify-content: center;
font-weight: 700;
font-size: 14px;
color: #fff;
flex-shrink: 0;
}
.user-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
.user-avatar.sm { width: 28px; height: 28px; font-size: 11px; border-radius: 8px; }
.user-avatar.lg { width: 48px; height: 48px; font-size: 18px; border-radius: 14px; }
/* Inline search */
.search-input-wrap { position: relative; }
.search-input-wrap .bi-search {
position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
color: var(--text3); font-size: 13px; pointer-events: none;
}
.search-input-wrap input { padding-left: 34px; }
/* Perm grid */
.perm-row {
display: flex; align-items: center; justify-content: space-between;
padding: 12px 16px;
border-bottom: 1px solid var(--border);
gap: 12px;
}
.perm-row:last-child { border-bottom: none; }
.perm-name { font-size: 13px; font-weight: 600; color: var(--text); }
.perm-desc { font-size: 12px; color: var(--text2); margin-top: 1px; }
.perm-toggle { display: flex; gap: 6px; flex-shrink: 0; }
.perm-toggle label {
cursor: pointer; padding: 4px 12px; border-radius: 99px;
font-size: 12px; font-weight: 700;
border: 1px solid var(--border2);
color: var(--text2);
transition: all 0.15s;
}
.perm-toggle input:checked + label.free { background: var(--success); border-color: var(--success); color: #fff; }
.perm-toggle input:checked + label.premium { background: var(--warning); border-color: var(--warning); color: #000; }
.perm-toggle input { display: none; }
/* ════════════════════════════════════════════════════════════════
RESPONSIVE — TABLET (≤ 1024px)
════════════════════════════════════════════════════════════════ */
@media (max-width: 1024px) {
.content-wrap { padding: 22px 20px; }
}
/* ════════════════════════════════════════════════════════════════
RESPONSIVE — MOBILE (≤ 768px)
════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
/* Sidebar becomes off-canvas drawer */
#sidebar {
transform: translateX(-100%);
box-shadow: 8px 0 40px rgba(0,0,0,0.6);
}
#sidebar.open { transform: translateX(0); }
.sb-close { display: flex; }
/* Topbar full width */
#topbar { left: 0; padding: 0 14px; gap: 8px; }
#topbar-hamburger { display: flex; }
.topbar-username { display: none; }
.topbar-divider { display: none; }
/* Main full width */
#main { margin-left: 0; }
.content-wrap { padding: 16px 14px; }
/* Page header stack */
.page-header { flex-direction: column; align-items: flex-start; gap: 10px; }
.page-header-actions { width: 100%; }
/* Stat cards */
.stat-value { font-size: 22px; }
/* Tables scroll */
.table-responsive { -webkit-overflow-scrolling: touch; }
/* Filter card compact */
.filter-card { padding: 12px 14px; }
/* Perm rows stack */
.perm-row { flex-direction: column; align-items: flex-start; }
/* Toast container */
#toast-container { bottom: 16px; right: 12px; left: 12px; }
.ax-toast { max-width: 100%; }
/* Pagination small */
.pagination .page-link { padding: 5px 10px; font-size: 12px; }
/* Action buttons compact */
.action-btns .btn .btn-text { display: none; }
}
/* ════════════════════════════════════════════════════════════════
RESPONSIVE — SMALL MOBILE (≤ 480px)
════════════════════════════════════════════════════════════════ */
@media (max-width: 480px) {
.content-wrap { padding: 12px 10px; }
.topbar-title { font-size: 13.5px; }
.card-body { padding: 14px; }
.stat-card { padding: 16px; }
}
</style>
@stack('styles')
</head>
<body>
{{-- Toast container --}}
<div id="toast-container"></div>
{{-- Sidebar overlay --}}
<div id="sb-overlay" onclick="sbClose()"></div>
{{-- ══ Sidebar ══ --}}
<nav id="sidebar">
<a href="{{ route('admin.dashboard') }}" class="sb-brand" onclick="sbCloseMobile()">
<div class="sb-brand-icon"><i class="bi bi-play-fill"></i></div>
<div class="sb-brand-text">ANIME<span>XE</span></div>
<button class="sb-close" onclick="sbClose();event.preventDefault();" title="Kapat"><i class="bi bi-x-lg"></i></button>
</a>
<div class="sb-nav">
<div class="sb-section">Ana</div>
<a href="{{ route('admin.dashboard') }}" class="sb-link {{ request()->routeIs('admin.dashboard') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-grid-1x2"></i> Dashboard
</a>
<div class="sb-section">İçerik</div>
<a href="{{ route('admin.animes.index') }}" class="sb-link {{ request()->routeIs('admin.animes*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-play-circle"></i> Animeler
</a>
<a href="{{ route('admin.episodes.index') }}" class="sb-link {{ request()->routeIs('admin.episodes*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-collection-play"></i> Bölümler
</a>
<a href="{{ route('admin.genres.index') }}" class="sb-link {{ request()->routeIs('admin.genres*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-tags"></i> Türler
</a>
<a href="{{ route('admin.banners.index') }}" class="sb-link {{ request()->routeIs('admin.banners*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-image"></i> Bannerlar
</a>
<a href="{{ route('admin.trending.index') }}" class="sb-link {{ request()->routeIs('admin.trending*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-fire"></i> Trend Yönetimi
</a>
<a href="{{ route('admin.import.index') }}" class="sb-link {{ request()->routeIs('admin.import*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-cloud-download"></i> İçe Aktar
</a>
<a href="{{ route('admin.ai.descriptions') }}" class="sb-link {{ request()->routeIs('admin.ai*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-stars"></i> AI Açıklamalar
</a>
<a href="{{ route('admin.blog.index') }}" class="sb-link {{ request()->routeIs('admin.blog*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-journal-richtext"></i> Blog
@php try { $draftCount = \App\Models\BlogPost::where('status','draft')->count(); } catch(\Exception $e) { $draftCount = 0; } @endphp
@if($draftCount > 0)<span class="sb-badge sb-badge-muted">{{ $draftCount }}</span>@endif
</a>
<a href="{{ route('admin.anime-requests.index') }}" class="sb-link {{ request()->routeIs('admin.anime-requests*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-plus-square"></i> Anime İstekleri
@php try { $pendingReqs = \App\Models\AnimeRequest::where('status','pending')->count(); } catch(\Exception $e) { $pendingReqs = 0; } @endphp
@if($pendingReqs > 0)<span class="sb-badge sb-badge-warn">{{ $pendingReqs }}</span>@endif
</a>
<div class="sb-section">Kullanıcılar</div>
<a href="{{ route('admin.users.index') }}" class="sb-link {{ request()->routeIs('admin.users.index') || request()->routeIs('admin.users.show') || request()->routeIs('admin.users.edit') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-people"></i> Kullanıcılar
</a>
@if(auth()->user()->isAdmin())
<a href="{{ route('admin.moderators.index') }}" class="sb-link {{ request()->routeIs('admin.moderators*') ? 'active' : '' }}" style="color:#f59e0b" onclick="sbCloseMobile()">
<i class="bi bi-shield-check"></i> Moderatörler
</a>
@endif
<a href="{{ route('admin.analytics.users') }}" class="sb-link {{ request()->routeIs('admin.analytics.users*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-graph-up"></i> Kullanıcı Analitik
</a>
<a href="{{ route('admin.comments.index') }}" class="sb-link {{ request()->routeIs('admin.comments*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-chat-dots"></i> Yorumlar
@php try { $pendingComments = \App\Models\Comment::where('status','pending')->count(); } catch(\Exception $e) { $pendingComments = 0; } @endphp
@if($pendingComments > 0)<span class="sb-badge">{{ $pendingComments }}</span>@endif
</a>
<div class="sb-section">Premium</div>
<a href="{{ route('admin.plans.index') }}" class="sb-link {{ request()->routeIs('admin.plans*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-star"></i> Üyelik Planları
</a>
<a href="{{ route('admin.subscriptions.index') }}" class="sb-link {{ request()->routeIs('admin.subscriptions*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-credit-card"></i> Abonelikler
</a>
<a href="{{ route('admin.activation-codes.index') }}" class="sb-link {{ request()->routeIs('admin.activation-codes*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-key-fill"></i> Aktivasyon Kodları
</a>
<div class="sb-section">İstatistik</div>
<a href="{{ route('admin.analytics.index') }}" class="sb-link {{ request()->routeIs('admin.analytics.index') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-bar-chart-line"></i> Analitik
</a>
<a href="{{ route('admin.stats.index') }}" class="sb-link {{ request()->routeIs('admin.stats*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-calendar-week"></i> İçerik İstatistik
</a>
<a href="{{ route('admin.notifications.index') }}" class="sb-link {{ request()->routeIs('admin.notifications*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-megaphone"></i> Bildirimler
</a>
<a href="{{ route('admin.mobile.index') }}" class="sb-link {{ request()->routeIs('admin.mobile*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-phone"></i> Mobil Uygulama
</a>
<a href="{{ route('admin.health.index') }}" class="sb-link {{ request()->routeIs('admin.health*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-activity"></i> Sağlık Kontrolü
</a>
<a href="{{ route('admin.ads.index') }}" class="sb-link {{ request()->routeIs('admin.ads*') ? 'active' : '' }}" style="color:#ffd60a" onclick="sbCloseMobile()">
<i class="bi bi-badge-ad-fill"></i> Reklamlar
</a>
<div class="sb-section">Sistem</div>
<a href="{{ route('admin.seo.index') }}" class="sb-link {{ request()->routeIs('admin.seo*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-search-heart"></i> SEO Paneli
</a>
<a href="{{ route('admin.permissions.index') }}" class="sb-link {{ request()->routeIs('admin.permissions*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-shield-lock"></i> İzin Ayarları
</a>
<a href="{{ route('admin.settings.index') }}" class="sb-link {{ request()->routeIs('admin.settings*') ? 'active' : '' }}" onclick="sbCloseMobile()">
<i class="bi bi-gear"></i> Ayarlar
</a>
</div>
<div class="sb-footer">
<div class="sb-footer-user">
<div class="sb-avatar">{{ strtoupper(substr(auth()->user()->name ?? 'A', 0, 1)) }}</div>
<div class="sb-user-info">
<div class="sb-user-name">{{ auth()->user()->name }}</div>
<div class="sb-user-role">{{ auth()->user()->isAdmin() ? 'Yönetici' : 'Moderatör' }}</div>
</div>
<form method="POST" action="{{ route('admin.logout') }}" class="d-inline">
@csrf
<button type="submit" class="sb-logout" title="Çıkış Yap"><i class="bi bi-box-arrow-right"></i></button>
</form>
</div>
</div>
</nav>
{{-- ══ Topbar ══ --}}
<header id="topbar">
<button id="topbar-hamburger" onclick="sbOpen()" title="Menü"><i class="bi bi-list"></i></button>
<div class="topbar-title">@yield('page-title', 'Dashboard')</div>
<div class="topbar-right">
<a href="{{ route('admin.health.index') }}" class="topbar-btn" title="Sistem Sağlığı">
<i class="bi bi-activity"></i>
</a>
<a href="{{ route('admin.settings.index') }}" class="topbar-btn" title="Ayarlar">
<i class="bi bi-gear"></i>
</a>
<div class="topbar-divider"></div>
<div class="topbar-user">
<div class="topbar-avatar">{{ strtoupper(substr(auth()->user()->name ?? 'A', 0, 1)) }}</div>
<span class="topbar-username">{{ auth()->user()->name }}</span>
</div>
</div>
</header>
{{-- ══ Main ══ --}}
<main id="main">
<div class="content-wrap">
@yield('content')
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
/* ── Sidebar ── */
function sbOpen() {
document.getElementById('sidebar').classList.add('open');
document.getElementById('sb-overlay').classList.add('on');
document.body.style.overflow = 'hidden';
}
function sbClose() {
document.getElementById('sidebar').classList.remove('open');
document.getElementById('sb-overlay').classList.remove('on');
document.body.style.overflow = '';
}
function sbCloseMobile() { if (window.innerWidth <= 768) sbClose(); }
document.addEventListener('keydown', e => { if (e.key === 'Escape') sbClose(); });
/* ── Toast system ── */
function axToast(msg, type = 'info', duration = 4000) {
const icons = { success:'check-circle-fill', error:'x-circle-fill', warning:'exclamation-triangle-fill', info:'info-circle-fill' };
const t = document.createElement('div');
t.className = `ax-toast ax-toast-${type}`;
t.innerHTML = `<i class="bi bi-${icons[type]||icons.info}"></i><div class="ax-toast-msg">${msg}</div><button class="ax-toast-close" onclick="this.parentElement.remove()"><i class="bi bi-x-lg"></i></button>`;
document.getElementById('toast-container').appendChild(t);
const dismiss = () => {
t.classList.add('out');
setTimeout(() => t.remove(), 220);
};
setTimeout(dismiss, duration);
}
/* ── Flash messages → toasts ── */
@if(session('success'))
axToast(@json(session('success')), 'success');
@endif
@if(session('error'))
axToast(@json(session('error')), 'error', 6000);
@endif
@if(session('warning'))
axToast(@json(session('warning')), 'warning', 5000);
@endif
@if(session('info'))
axToast(@json(session('info')), 'info');
@endif
@if($errors->any())
@foreach($errors->all() as $error)
axToast(@json($error), 'error', 6000);
@endforeach
@endif
/* ── CSRF for fetch/xhr ── */
const _csrf = document.querySelector('meta[name="csrf-token"]')?.content;
function axFetch(url, opts = {}) {
return fetch(url, {
headers: { 'X-CSRF-TOKEN': _csrf, 'Accept': 'application/json', 'Content-Type': 'application/json', ...(opts.headers||{}) },
...opts
});
}
/* ── Confirm delete helper ── */
function axConfirm(msg, formOrCallback) {
if (!confirm(msg || 'Bu işlemi onaylıyor musun?')) return false;
if (typeof formOrCallback === 'function') formOrCallback();
else if (formOrCallback instanceof HTMLFormElement) formOrCallback.submit();
return true;
}
</script>
@stack('scripts')
</body>
</html>