Initial commit: Animexe Laravel platform
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
@extends('admin.layouts.app')
|
||||
@section('title', 'Bildirimler')
|
||||
@section('page-title', 'Bildirim Yönetimi')
|
||||
|
||||
@section('content')
|
||||
|
||||
{{-- Stats --}}
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-6 col-md-3">
|
||||
<div class="stat-card">
|
||||
<div class="stat-card-top">
|
||||
<div>
|
||||
<div class="stat-value">{{ number_format($stats['total']) }}</div>
|
||||
<div class="stat-label mt-1">Toplam Bildirim</div>
|
||||
</div>
|
||||
<div class="stat-icon violet"><i class="bi bi-bell-fill"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<div class="stat-card">
|
||||
<div class="stat-card-top">
|
||||
<div>
|
||||
<div class="stat-value">{{ number_format($stats['unread']) }}</div>
|
||||
<div class="stat-label mt-1">Okunmamış</div>
|
||||
</div>
|
||||
<div class="stat-icon orange"><i class="bi bi-eye-slash-fill"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<div class="stat-card">
|
||||
<div class="stat-card-top">
|
||||
<div>
|
||||
<div class="stat-value">{{ number_format($stats['users']) }}</div>
|
||||
<div class="stat-label mt-1">Kullanıcı</div>
|
||||
</div>
|
||||
<div class="stat-icon green"><i class="bi bi-people-fill"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<div class="stat-card">
|
||||
<div class="stat-card-top">
|
||||
<div>
|
||||
<div class="stat-value">{{ number_format($stats['today']) }}</div>
|
||||
<div class="stat-label mt-1">Bugün Gönderildi</div>
|
||||
</div>
|
||||
<div class="stat-icon cyan"><i class="bi bi-send-fill"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
|
||||
{{-- ── Sol: Gönder ── --}}
|
||||
<div class="col-lg-5">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<i class="bi bi-send" style="color:var(--accent-lt)"></i>
|
||||
<h6>Bildirim Gönder</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('admin.notifications.send') }}">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Başlık <span style="color:var(--danger)">*</span></label>
|
||||
<input type="text" name="title" class="form-control"
|
||||
value="{{ old('title') }}" placeholder="Yeni Bölüm Yüklendi!" maxlength="100" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Mesaj <span style="color:var(--danger)">*</span></label>
|
||||
<textarea name="body" id="notif-body" class="form-control" rows="3"
|
||||
placeholder="Yeni bölümler yayında, hemen izle!" maxlength="500" required>{{ old('body') }}</textarea>
|
||||
<div class="form-text">
|
||||
<span id="bodyCount">{{ strlen(old('body','')) }}</span>/500 karakter
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">
|
||||
Link <span style="color:var(--text2);font-size:11px">(opsiyonel)</span>
|
||||
</label>
|
||||
<input type="url" name="url" class="form-control"
|
||||
value="{{ old('url') }}" placeholder="https://...">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">İkon</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text" style="min-width:42px;justify-content:center">
|
||||
<i id="iconPreview" class="bi bi-megaphone-fill" style="color:var(--accent-lt)"></i>
|
||||
</span>
|
||||
<input type="text" name="icon" id="iconInput" class="form-control"
|
||||
value="{{ old('icon','bi-megaphone-fill') }}" placeholder="bi-megaphone-fill">
|
||||
</div>
|
||||
<div class="d-flex gap-2 flex-wrap mt-2">
|
||||
@foreach(['bi-megaphone-fill','bi-star-fill','bi-bell-fill','bi-gift-fill','bi-play-circle-fill','bi-trophy-fill','bi-info-circle-fill','bi-exclamation-triangle-fill'] as $ic)
|
||||
<button type="button" class="icon-preset"
|
||||
style="width:32px;height:32px;border-radius:8px;border:1px solid var(--border2);background:var(--surface2);color:var(--text2);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;transition:all .12s"
|
||||
data-icon="{{ $ic }}" title="{{ $ic }}">
|
||||
<i class="bi {{ $ic }}"></i>
|
||||
</button>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label">Hedef Kitle <span style="color:var(--danger)">*</span></label>
|
||||
<select name="target" class="form-select" required>
|
||||
<option value="all" {{ old('target','all')==='all' ?'selected':'' }}>
|
||||
Tüm Kullanıcılar ({{ number_format($stats['users']) }})
|
||||
</option>
|
||||
<option value="premium" {{ old('target')==='premium' ?'selected':'' }}>Sadece Premium Üyeler</option>
|
||||
<option value="free" {{ old('target')==='free' ?'selected':'' }}>Sadece Ücretsiz Üyeler</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary w-100"
|
||||
onclick="return confirm('Bildirim gönderilsin mi?')">
|
||||
<i class="bi bi-send"></i> Bildirimi Gönder
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ── Sağ: Son Bildirimler ── --}}
|
||||
<div class="col-lg-7">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<i class="bi bi-clock-history" style="color:var(--info)"></i>
|
||||
<h6>Son Bildirimler</h6>
|
||||
<span style="font-size:12px;color:var(--text2);margin-left:4px">Son 50</span>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="padding-left:20px">Kullanıcı</th>
|
||||
<th>Tür</th>
|
||||
<th>İçerik</th>
|
||||
<th style="text-align:center">Durum</th>
|
||||
<th>Tarih</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($recent as $n)
|
||||
@php $d = $n->data; @endphp
|
||||
<tr>
|
||||
<td style="padding-left:20px;font-size:13px;font-weight:600;color:var(--text)">
|
||||
{{ $n->user?->name ?? '—' }}
|
||||
@if($n->user?->username)
|
||||
<div style="font-size:11.5px;font-weight:400;color:var(--text2)">@{{ $n->user->username }}</div>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($n->type === 'admin')
|
||||
<span class="badge" style="background:var(--accent-dim);color:var(--accent-lt)">Admin</span>
|
||||
@elseif($n->type === 'episode')
|
||||
<span class="badge bg-success">Bölüm</span>
|
||||
@else
|
||||
<span class="badge bg-secondary">{{ $n->type }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td style="max-width:180px">
|
||||
@if($n->type === 'admin')
|
||||
<div style="font-size:13px;font-weight:600;color:var(--text)">{{ $d['title'] ?? '' }}</div>
|
||||
@if(!empty($d['body']))
|
||||
<div style="font-size:12px;color:var(--text2)">{{ Str::limit($d['body'],55) }}</div>
|
||||
@endif
|
||||
@elseif($n->type === 'episode')
|
||||
<div style="font-size:12.5px;color:var(--info);font-weight:600">{{ $d['anime_title'] ?? '' }}</div>
|
||||
<div style="font-size:12px;color:var(--text2)">{{ $d['episode_number'] ?? '' }}. Bölüm</div>
|
||||
@endif
|
||||
</td>
|
||||
<td style="text-align:center">
|
||||
@if($n->read_at)
|
||||
<span style="font-size:12px;color:var(--text3);display:inline-flex;align-items:center;gap:3px">
|
||||
<i class="bi bi-check2-all" style="font-size:11px"></i> Okundu
|
||||
</span>
|
||||
@else
|
||||
<span style="font-size:12px;color:var(--warning);display:inline-flex;align-items:center;gap:4px">
|
||||
<i class="bi bi-circle-fill" style="font-size:6px"></i> Yeni
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
<td style="font-size:12px;color:var(--text2)">{{ $n->created_at->format('d.m H:i') }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<div class="empty-state py-4">
|
||||
<i class="bi bi-bell"></i>
|
||||
<p>Henüz bildirim gönderilmemiş.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
// Karakter sayacı
|
||||
const bodyTa = document.getElementById('notif-body');
|
||||
const bodyCount = document.getElementById('bodyCount');
|
||||
if (bodyTa && bodyCount) {
|
||||
bodyTa.addEventListener('input', () => {
|
||||
bodyCount.textContent = bodyTa.value.length;
|
||||
bodyCount.style.color = bodyTa.value.length > 450 ? 'var(--danger)' : '';
|
||||
});
|
||||
}
|
||||
// İkon preview
|
||||
const iconInput = document.getElementById('iconInput');
|
||||
const iconPreview = document.getElementById('iconPreview');
|
||||
if (iconInput) {
|
||||
iconInput.addEventListener('input', () => {
|
||||
iconPreview.className = 'bi ' + iconInput.value.trim();
|
||||
});
|
||||
}
|
||||
document.querySelectorAll('.icon-preset').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const ic = btn.dataset.icon;
|
||||
if (iconInput) { iconInput.value = ic; }
|
||||
if (iconPreview) { iconPreview.className = 'bi ' + ic; }
|
||||
document.querySelectorAll('.icon-preset').forEach(b => b.style.borderColor = '');
|
||||
btn.style.borderColor = 'var(--accent)';
|
||||
btn.style.background = 'var(--accent-dim)';
|
||||
btn.style.color = 'var(--accent-lt)';
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
Reference in New Issue
Block a user