Initial commit: Animexe Laravel platform

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 00:01:48 +03:00
co-authored by Claude Opus 4.8
commit a63515cfc6
366 changed files with 74773 additions and 0 deletions
+825
View File
@@ -0,0 +1,825 @@
@extends('frontend.layouts.app')
@section('title', $user->name . ' — Profil — Animexe')
@push('styles')
<style>
/* ═══════════════════════════ PROFILE ═══════════════════════════ */
/* ── Hero banner ──────────────────────────────────────────────── */
.pr-hero{
position:relative;overflow:hidden;
background:#05050e;
padding-bottom:0;
}
.pr-hero-bg{
position:absolute;inset:0;
background:
radial-gradient(ellipse 80% 60% at 20% 50%, rgba(0,245,255,.06), transparent),
radial-gradient(ellipse 60% 80% at 80% 30%, rgba(255,45,125,.05), transparent);
}
.pr-hero-inner{
position:relative;z-index:1;
max-width:960px;margin:0 auto;
padding:calc(var(--nav-h) + 32px) 24px 0;
}
.pr-top{display:flex;align-items:flex-start;gap:20px;flex-wrap:wrap;margin-bottom:28px}
.pr-top-main{display:flex;align-items:flex-end;gap:20px;flex:1;min-width:0}
/* ── Avatar ───────────────────────────────────────────────────── */
.pr-avatar{
width:96px;height:96px;border-radius:24px;flex-shrink:0;
background:linear-gradient(135deg,var(--accent2),var(--accent));
display:flex;align-items:center;justify-content:center;
font-size:2.4rem;font-weight:900;color:#fff;overflow:hidden;
box-shadow:0 0 0 3px rgba(0,245,255,.2),0 16px 48px rgba(0,0,0,.5);
}
.pr-info{flex:1;min-width:0;padding-bottom:4px}
.pr-name{font-size:1.7rem;font-weight:900;color:#fff;line-height:1.1;margin-bottom:4px}
.pr-handle{font-size:.84rem;color:rgba(255,255,255,.35);margin-bottom:10px}
.pr-badges{display:flex;gap:7px;flex-wrap:wrap}
.pbadge{padding:4px 12px;border-radius:20px;font-size:.7rem;font-weight:700;letter-spacing:.05em;display:inline-flex;align-items:center;gap:5px}
.pbadge-admin{background:rgba(255,45,125,.15);border:1px solid rgba(255,45,125,.35);color:var(--accent)}
.pbadge-premium{background:rgba(255,208,0,.12);border:1px solid rgba(255,208,0,.3);color:#ffd700}
.pbadge-member{background:rgba(0,245,255,.07);border:1px solid rgba(0,245,255,.2);color:var(--accent2)}
/* ── Stat pills ───────────────────────────────────────────────── */
.pr-stats{
display:flex;gap:6px;flex-wrap:wrap;
padding:20px 0 0;
border-top:1px solid rgba(255,255,255,.06);
margin-top:8px;
}
.pr-stat{
display:flex;flex-direction:column;align-items:center;
padding:10px 20px;border-radius:12px;
background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.07);
min-width:80px;flex:1;
}
.pr-stat .v{font-size:1.25rem;font-weight:800;color:#fff;line-height:1}
.pr-stat .l{font-size:.62rem;text-transform:uppercase;letter-spacing:.1em;color:rgba(255,255,255,.35);margin-top:4px;font-weight:600}
/* ── Tab nav ──────────────────────────────────────────────────── */
.pr-tabs{
display:flex;gap:2px;
border-top:1px solid rgba(255,255,255,.06);
margin-top:20px;
overflow-x:auto;scrollbar-width:none;
}
.pr-tabs::-webkit-scrollbar{display:none}
.pr-tab{
padding:12px 18px;background:none;border:none;
border-bottom:2px solid transparent;
color:rgba(255,255,255,.35);font-size:.82rem;font-weight:600;
cursor:pointer;font-family:inherit;transition:all .15s;
white-space:nowrap;flex-shrink:0;display:flex;align-items:center;gap:6px;
margin-bottom:-1px;
}
.pr-tab:hover{color:rgba(255,255,255,.65)}
.pr-tab.on{color:var(--accent2);border-bottom-color:var(--accent2)}
/* ── Body ─────────────────────────────────────────────────────── */
.pr-body{max-width:960px;margin:0 auto;padding:32px 24px 64px}
.pr-pane{display:none}
.pr-pane.on{display:block}
/* ── Section header ───────────────────────────────────────────── */
.pr-sec-h{
font-size:.68rem;text-transform:uppercase;letter-spacing:.12em;
color:rgba(255,255,255,.3);font-weight:700;
margin-bottom:16px;display:flex;align-items:center;gap:8px;
}
.pr-sec-h::before{content:'';width:3px;height:14px;background:linear-gradient(180deg,var(--accent2),var(--accent));border-radius:2px}
/* ── Continue watching cards ──────────────────────────────────── */
.cw-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:12px}
.cw-card{
border-radius:10px;overflow:hidden;
background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.07);
text-decoration:none;display:block;
transition:transform .15s,border-color .15s;
}
.cw-card:hover{transform:translateY(-3px);border-color:rgba(0,245,255,.25)}
.cw-thumb{position:relative;aspect-ratio:2/3;overflow:hidden}
.cw-thumb img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .3s}
.cw-card:hover .cw-thumb img{transform:scale(1.05)}
.cw-thumb-ph{width:100%;height:100%;background:rgba(255,255,255,.04);display:flex;align-items:center;justify-content:center;color:rgba(255,255,255,.2);font-size:2rem}
.cw-grad{position:absolute;inset:0;background:linear-gradient(to top,rgba(0,0,0,.85) 0%,transparent 55%)}
.cw-play{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:38px;height:38px;border-radius:50%;background:rgba(255,45,125,.85);display:flex;align-items:center;justify-content:center}
.cw-play i{color:#fff;font-size:.95rem}
.cw-progress{position:absolute;bottom:28px;left:10px;right:10px}
.cw-prog-bar{height:3px;background:rgba(255,255,255,.2);border-radius:2px;overflow:hidden}
.cw-prog-fill{height:100%;background:var(--accent);border-radius:2px}
.cw-ep{position:absolute;bottom:8px;left:10px;font-size:.62rem;color:rgba(255,255,255,.6);font-weight:600}
.cw-info{padding:8px 10px}
.cw-info-title{font-size:.76rem;font-weight:600;color:rgba(255,255,255,.8);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* ── Achievement grid ─────────────────────────────────────────── */
.ach-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px}
.ach-card{
display:flex;align-items:center;gap:14px;
background:rgba(255,255,255,.03);
border:1px solid rgba(255,255,255,.07);
border-radius:12px;padding:14px 16px;
transition:border-color .15s;
}
.ach-card.earned{background:rgba(255,255,255,.05)}
.ach-card:not(.earned){opacity:.35}
.ach-icon-wrap{width:44px;height:44px;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:1.4rem;flex-shrink:0}
.ach-body .ach-title{font-size:.85rem;font-weight:700;color:#fff;margin-bottom:2px}
.ach-body .ach-desc{font-size:.72rem;color:rgba(255,255,255,.35);line-height:1.4}
.ach-body .ach-date{font-size:.66rem;margin-top:4px;font-weight:600}
/* ── Watchlist tabs ───────────────────────────────────────────── */
.wl-filter{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:20px}
.wl-filter-btn{
padding:6px 14px;border-radius:20px;border:1px solid rgba(255,255,255,.1);
background:none;color:rgba(255,255,255,.45);font-size:.78rem;font-weight:600;
cursor:pointer;font-family:inherit;transition:all .15s;
}
.wl-filter-btn:hover{border-color:rgba(255,255,255,.25);color:rgba(255,255,255,.7)}
.wl-filter-btn.on{background:rgba(0,245,255,.1);border-color:rgba(0,245,255,.3);color:var(--accent2)}
.wl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(110px,1fr));gap:10px}
.wl-card{
border-radius:9px;overflow:hidden;text-decoration:none;display:block;
background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.07);
transition:transform .15s,border-color .15s;
}
.wl-card:hover{transform:translateY(-2px);border-color:rgba(255,255,255,.18)}
.wl-card img{width:100%;aspect-ratio:2/3;object-fit:cover;display:block}
.wl-card-ph{aspect-ratio:2/3;background:rgba(255,255,255,.04);display:flex;align-items:center;justify-content:center;color:rgba(255,255,255,.2)}
.wl-card-title{padding:7px 8px;font-size:.72rem;font-weight:600;color:rgba(255,255,255,.7);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* ── Heatmap ──────────────────────────────────────────────────── */
.heatmap-wrap{
background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);
border-radius:14px;padding:20px 24px;
}
.heatmap-scroll{overflow-x:auto;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.1) transparent;padding-bottom:6px}
.heatmap-grid{display:flex;gap:3px;min-width:max-content}
.hm-col{display:flex;flex-direction:column;gap:3px}
.hm-cell{width:13px;height:13px;border-radius:3px}
.heatmap-legend{display:flex;align-items:center;gap:10px;margin-top:14px;font-size:.7rem;color:rgba(255,255,255,.3)}
.heatmap-legend-cells{display:flex;gap:3px;align-items:center}
.heatmap-stats{display:flex;gap:20px;margin-top:12px;font-size:.78rem;color:rgba(255,255,255,.4)}
/* ── Notes ────────────────────────────────────────────────────── */
.note-card{
background:rgba(255,255,255,.03);border:1px solid rgba(255,215,0,.12);
border-radius:12px;padding:16px 18px;margin-bottom:10px;
}
.note-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.note-anime{font-size:.8rem;font-weight:700;color:var(--accent2);text-decoration:none}
.note-anime:hover{text-decoration:underline}
.note-ep{font-size:.72rem;color:rgba(255,255,255,.3)}
.note-ts{font-size:.72rem;color:#ffd700;display:inline-flex;align-items:center;gap:4px}
.note-date{font-size:.68rem;color:rgba(255,255,255,.25);margin-left:auto}
.note-text{font-size:.87rem;color:rgba(255,255,255,.65);line-height:1.6}
/* ── Comments ─────────────────────────────────────────────────── */
.cm-card{
background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);
border-radius:12px;padding:14px 16px;margin-bottom:10px;
}
.cm-top{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.cm-ava{width:30px;height:30px;border-radius:10px;background:linear-gradient(135deg,var(--accent2),var(--accent));display:flex;align-items:center;justify-content:center;font-size:.75rem;font-weight:800;color:#fff;flex-shrink:0}
.cm-name{font-size:.84rem;font-weight:700;color:rgba(255,255,255,.8)}
.cm-time{font-size:.72rem;color:rgba(255,255,255,.25);margin-left:auto}
.cm-text{font-size:.88rem;color:rgba(255,255,255,.6);line-height:1.6}
.cm-gif{max-width:200px;border-radius:8px;margin-top:8px}
.pr-empty{text-align:center;padding:56px 20px;color:rgba(255,255,255,.2);font-size:.9rem}
.pr-empty i{font-size:2.5rem;display:block;margin-bottom:12px;opacity:.25}
/* ── Responsive ───────────────────────────────────────────────── */
@media(max-width:600px){
.pr-hero-inner{padding:calc(var(--nav-h) + 16px) 16px 0}
.pr-body{padding:24px 16px 48px}
.pr-avatar{width:72px;height:72px;border-radius:18px;font-size:1.8rem}
.pr-name{font-size:1.3rem}
.pr-stat{padding:8px 12px;min-width:60px}
.pr-stat .v{font-size:1rem}
.ach-grid{grid-template-columns:1fr}
.cw-grid{grid-template-columns:repeat(auto-fill,minmax(110px,1fr))}
.pr-top{flex-direction:column;gap:14px}
.pr-top-main{align-items:flex-start}
.pr-edit-btn{align-self:stretch;justify-content:center}
}
/* ═══════════════════════════════════════════════════
PROFILE PAGE PREMIUM ENHANCEMENTS
═══════════════════════════════════════════════════ */
/* Avatar animated rainbow border */
@keyframes avatar-border-spin{
0%{background-position:0% 50%}
100%{background-position:200% 50%}
}
.pr-avatar{
position:relative;
}
.pr-avatar::before{
content:'';position:absolute;inset:-2px;border-radius:26px;z-index:-1;
background:linear-gradient(135deg,var(--accent2),var(--accent),var(--accent3),var(--accent2));
background-size:300% 300%;
animation:avatar-border-spin 3s linear infinite;
}
/* Username gradient */
.pr-name{
background:linear-gradient(135deg,#fff 0%,rgba(255,255,255,.85) 60%,rgba(240,244,255,.6) 100%);
-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;
}
/* Stats strip enhanced */
.pr-stats{
background:rgba(255,255,255,.02);
border-radius:14px;
padding:14px;
border:1px solid rgba(255,255,255,.05);
gap:8px;
}
.pr-stat{
border-radius:10px;
background:rgba(255,255,255,.04);
border:1px solid rgba(255,255,255,.07);
transition:all .2s;
}
.pr-stat:hover{
background:rgba(0,245,255,.06);
border-color:rgba(0,245,255,.2);
transform:translateY(-2px);
}
.pr-stat .v{
background:linear-gradient(135deg,var(--accent2),var(--accent));
-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;
font-size:1.35rem;
}
/* Tab enhanced */
.pr-tab.on{
color:var(--accent2);
text-shadow:0 0 12px rgba(0,245,255,.3);
}
/* Entrance animations */
@keyframes pr-fade-up{
from{opacity:0;transform:translateY(18px)}
to{opacity:1;transform:none}
}
.pr-avatar{animation:pr-fade-up .5s cubic-bezier(.22,1,.36,1) .1s both}
.pr-info{animation:pr-fade-up .5s cubic-bezier(.22,1,.36,1) .2s both}
.pr-stats{animation:pr-fade-up .5s cubic-bezier(.22,1,.36,1) .3s both}
.pr-tabs{animation:pr-fade-up .4s cubic-bezier(.22,1,.36,1) .4s both}
/* Achievement cards enhanced */
.ach-card.earned{
border:1px solid rgba(255,255,255,.1);
background:linear-gradient(135deg,rgba(255,255,255,.05),rgba(0,245,255,.02));
transition:all .2s;
}
.ach-card.earned:hover{
border-color:rgba(0,245,255,.2);
transform:translateY(-2px);
box-shadow:0 8px 24px rgba(0,0,0,.4),0 0 20px rgba(0,245,255,.05);
}
/* Watchlist cards enhanced */
.wl-card:hover{
transform:translateY(-3px);
border-color:rgba(0,245,255,.2);
box-shadow:0 8px 24px rgba(0,0,0,.4);
}
/* Heatmap wrap */
.heatmap-wrap{
background:linear-gradient(135deg,rgba(255,255,255,.03),rgba(0,245,255,.01));
border:1px solid rgba(0,245,255,.07);
}
/* Profile edit button */
.pr-edit-btn{
transition:all .18s;
}
.pr-edit-btn:hover{
background:rgba(0,245,255,.12);
border-color:rgba(0,245,255,.4);
color:var(--accent2);
box-shadow:0 0 20px rgba(0,245,255,.15);
}
/* Body panes reveal */
.pr-body{animation:pr-fade-up .5s cubic-bezier(.22,1,.36,1) .2s both}
/* Profile color accent on section headers */
.pr-sec-h::before{
box-shadow:0 0 10px rgba(0,245,255,.5);
}
/* ── Swipe history ───────────────────────────────────── */
.swipe-filter {
padding: 5px 13px; border-radius: 999px; font-size: .68rem;
background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.08);
color: var(--text3); cursor: pointer; font-family: var(--font);
transition: all .15s; display: inline-flex; align-items: center; gap: 5px;
}
.swipe-filter:hover { border-color: rgba(0,245,255,.25); color: var(--text2); }
.swipe-filter.on { background: rgba(0,245,255,.1); border-color: var(--accent2); color: var(--accent2); }
.swipe-f-count {
font-size: .6rem; background: rgba(255,255,255,.08); border-radius: 999px;
padding: 1px 6px; color: var(--text3);
}
.swipe-filter.on .swipe-f-count { background: rgba(0,245,255,.15); color: var(--accent2); }
.swipe-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
gap: 10px;
}
.swipe-item {
text-decoration: none; border-radius: 12px; overflow: hidden;
background: var(--surface2); display: flex; flex-direction: column;
transition: transform .18s, box-shadow .18s;
}
.swipe-item:hover { transform: translateY(-3px); box-shadow: 0 8px 24px rgba(0,0,0,.4); }
.swipe-poster {
position: relative; aspect-ratio: 2/3; overflow: hidden;
}
.swipe-poster img { width: 100%; height: 100%; object-fit: cover; display: block; }
.swipe-poster-ph {
width: 100%; height: 100%;
display: flex; align-items: center; justify-content: center;
color: var(--text3); font-size: 1.5rem;
}
.swipe-dir-badge {
position: absolute; top: 6px; right: 6px;
width: 22px; height: 22px; border-radius: 50%;
display: flex; align-items: center; justify-content: center;
font-size: .6rem; font-weight: 700;
}
.badge-like { background: rgba(0,245,255,.18); color: var(--accent2); border: 1px solid rgba(0,245,255,.3); }
.badge-skip { background: rgba(255,45,125,.15); color: #ff2d7d; border: 1px solid rgba(255,45,125,.3); }
.swipe-info { padding: 7px 8px 9px; }
.swipe-title {
font-size: .68rem; font-weight: 600; color: var(--text);
line-height: 1.3; margin-bottom: 4px;
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.swipe-meta { display: flex; gap: 6px; font-size: .6rem; color: var(--text3); flex-wrap: wrap; }
.swipe-item.skip .swipe-poster { opacity: .65; }
.swipe-item.skip .swipe-poster img { filter: grayscale(25%); }
</style>
@endpush
@section('content')
@php $pColor = $user->profile_color ?? '#00f5ff'; @endphp
{{-- Hero --}}
<div class="pr-hero" style="--pr-color:{{ $pColor }}">
{{-- Banner --}}
@if($user->banner_image)
<div style="position:absolute;inset:0;overflow:hidden">
<img src="{{ \App\Support\MediaUrl::fromStoragePath($user->banner_image) }}" alt=""
style="width:100%;height:100%;object-fit:cover;opacity:.35;filter:blur(1px)">
<div style="position:absolute;inset:0;background:linear-gradient(to bottom,rgba(5,5,14,.3) 0%,rgba(5,5,14,.85) 100%)"></div>
</div>
@else
<div class="pr-hero-bg" style="background:radial-gradient(ellipse 80% 60% at 20% 50%,{{ $pColor }}18,transparent),radial-gradient(ellipse 60% 80% at 80% 30%,{{ $pColor }}10,transparent)"></div>
@endif
<div class="pr-hero-inner">
{{-- Top row: avatar + info + edit button --}}
<div class="pr-top">
<div class="pr-top-main">
{{-- Avatar --}}
<div class="pr-avatar" style="background:linear-gradient(135deg,{{ $pColor }},{{ $pColor }}88);box-shadow:0 0 0 3px {{ $pColor }}33,0 16px 48px rgba(0,0,0,.5)">
@if($user->avatar)
<img src="{{ \App\Support\MediaUrl::fromStoragePath($user->avatar) }}" alt="{{ $user->name }}"
style="width:100%;height:100%;object-fit:cover;border-radius:22px">
@else
{{ mb_strtoupper(mb_substr($user->name,0,1)) }}
@endif
</div>
<div class="pr-info">
<div class="pr-name">{{ $user->name }}</div>
@if($user->username)
<div class="pr-handle">@php echo '@' . e($user->username); @endphp</div>
@endif
@if($user->bio)
<div style="font-size:.83rem;color:rgba(255,255,255,.55);margin-bottom:10px;max-width:500px;line-height:1.5">{{ $user->bio }}</div>
@endif
{{-- Sosyal linkler --}}
@if($user->twitter || $user->instagram || $user->discord || $user->website)
<div style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:10px;align-items:center">
@if($user->twitter)
<a href="https://x.com/{{ $user->twitter }}" target="_blank" rel="noopener"
style="color:rgba(255,255,255,.5);font-size:.82rem;text-decoration:none;display:flex;align-items:center;gap:4px;transition:color .2s"
onmouseover="this.style.color='{{ $pColor }}'" onmouseout="this.style.color='rgba(255,255,255,.5)'">
<i class="bi bi-twitter-x"></i> {{ $user->twitter }}
</a>
@endif
@if($user->instagram)
<a href="https://instagram.com/{{ $user->instagram }}" target="_blank" rel="noopener"
style="color:rgba(255,255,255,.5);font-size:.82rem;text-decoration:none;display:flex;align-items:center;gap:4px;transition:color .2s"
onmouseover="this.style.color='{{ $pColor }}'" onmouseout="this.style.color='rgba(255,255,255,.5)'">
<i class="bi bi-instagram"></i> {{ $user->instagram }}
</a>
@endif
@if($user->discord)
<span style="color:rgba(255,255,255,.5);font-size:.82rem;display:flex;align-items:center;gap:4px">
<i class="bi bi-discord"></i> {{ $user->discord }}
</span>
@endif
@if($user->website)
<a href="{{ $user->website }}" target="_blank" rel="noopener"
style="color:rgba(255,255,255,.5);font-size:.82rem;text-decoration:none;display:flex;align-items:center;gap:4px;transition:color .2s"
onmouseover="this.style.color='{{ $pColor }}'" onmouseout="this.style.color='rgba(255,255,255,.5)'">
<i class="bi bi-globe2"></i> {{ parse_url($user->website, PHP_URL_HOST) }}
</a>
@endif
</div>
@endif
<div class="pr-badges">
@if($user->role==='admin')
<span class="pbadge pbadge-admin"><i class="bi bi-shield-fill"></i> Admin</span>
@elseif($user->role==='moderator')
<span class="pbadge pbadge-admin"><i class="bi bi-shield-half"></i> Moderatör</span>
@endif
@if($user->isPremium())
<span class="pbadge pbadge-premium"><i class="bi bi-star-fill"></i> Premium</span>
@else
<span class="pbadge pbadge-member"><i class="bi bi-person-check"></i> Üye</span>
@endif
<span class="pbadge" style="background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);color:rgba(255,255,255,.35)"><i class="bi bi-calendar3"></i> {{ $user->created_at->format('Y') }}'den beri</span>
</div>
</div>
</div>
{{-- Ayarlar butonu ayrı satırda, üstte sabit --}}
<a href="{{ route('profile.settings') }}" class="pr-edit-btn"
style="flex-shrink:0;padding:8px 16px;border-radius:10px;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.12);color:rgba(255,255,255,.6);font-size:.82rem;text-decoration:none;display:flex;align-items:center;gap:7px;transition:all .2s;white-space:nowrap;align-self:flex-start;margin-top:4px"
onmouseover="this.style.background='rgba(255,255,255,.12)';this.style.color='#fff'"
onmouseout="this.style.background='rgba(255,255,255,.07)';this.style.color='rgba(255,255,255,.6)'">
<i class="bi bi-pencil-square"></i> Profili Düzenle
</a>
</div>
{{-- Stats --}}
<div class="pr-stats">
<div class="pr-stat">
<span class="v">{{ $watchStats['episodes'] }}</span>
<span class="l">Bölüm</span>
</div>
<div class="pr-stat">
<span class="v">{{ $watchStats['hours'] }}</span>
<span class="l">Saat</span>
</div>
<div class="pr-stat">
<span class="v">{{ $watchStats['watchlist'] }}</span>
<span class="l">Listede</span>
</div>
<div class="pr-stat">
<span class="v">{{ $commentCount }}</span>
<span class="l">Yorum</span>
</div>
@if($allAchievements->count())
<div class="pr-stat">
<span class="v">{{ $achievements->count() }}</span>
<span class="l">Başarım</span>
</div>
@endif
</div>
{{-- Tab nav --}}
<div class="pr-tabs" id="pr-tabs">
@if($continueItems->count())
<button class="pr-tab on" data-pane="continue"><i class="bi bi-play-circle"></i> Devam Et</button>
@endif
<button class="pr-tab {{ !$continueItems->count() ? 'on' : '' }}" data-pane="watchlist"><i class="bi bi-bookmark"></i> Listem</button>
<button class="pr-tab" data-pane="activity"><i class="bi bi-graph-up"></i> Aktivite</button>
@if($allAchievements->count())
<button class="pr-tab" data-pane="achievements"><i class="bi bi-trophy"></i> Başarımlar</button>
@endif
<button class="pr-tab" data-pane="notes"><i class="bi bi-journal-text"></i> Notlar @if($episodeNotes->count())<span style="font-size:.68rem;background:rgba(0,245,255,.15);color:var(--accent2);border-radius:10px;padding:1px 6px;margin-left:2px">{{ $episodeNotes->count() }}</span>@endif</button>
<button class="pr-tab" data-pane="comments"><i class="bi bi-chat-dots"></i> Yorumlar</button>
<button class="pr-tab" data-pane="swipes"><i class="bi bi-hand-index-thumb"></i> Keşfet @if($swipeHistory->count())<span style="font-size:.65rem;background:rgba(0,245,255,.12);color:var(--accent2);border-radius:10px;padding:1px 6px;margin-left:2px">{{ $swipeHistory->count() }}</span>@endif</button>
</div>
</div>
</div>
{{-- Body --}}
<div class="pr-body">
{{-- DEVAM ET --}}
@if($continueItems->count())
<div class="pr-pane on" id="pane-continue">
<div class="pr-sec-h"><span>Kaldığın Yerden Devam Et</span></div>
<div class="cw-grid">
@foreach($continueItems as $cw)
@php $anime = $cw->anime; @endphp
@if(!$anime) @continue @endif
<a href="{{ route('watch',[$anime->slug,$cw->season_number,$cw->episode_number]) }}" class="cw-card">
<div class="cw-thumb">
@if($anime->cover_image)
<img src="{{ \App\Support\MediaUrl::fromStoragePath($anime->cover_image) }}" alt="">
@else
<div class="cw-thumb-ph"><i class="bi bi-image"></i></div>
@endif
<div class="cw-grad"></div>
<div class="cw-play"><i class="bi bi-play-fill"></i></div>
<div class="cw-progress">
<div class="cw-prog-bar"><div class="cw-prog-fill" style="width:{{ $cw->percent_complete }}%"></div></div>
</div>
<div class="cw-ep">S{{ str_pad($cw->season_number,2,'0',STR_PAD_LEFT) }}E{{ str_pad($cw->episode_number,2,'0',STR_PAD_LEFT) }} · {{ $cw->percent_complete }}%</div>
</div>
<div class="cw-info"><div class="cw-info-title">{{ $anime->title }}</div></div>
</a>
@endforeach
</div>
</div>
@endif
{{-- İZLEME LİSTESİ --}}
<div class="pr-pane {{ !$continueItems->count() ? 'on' : '' }}" id="pane-watchlist">
<div class="pr-sec-h" style="display:flex;align-items:center;justify-content:space-between">
<span>İzleme Listesi</span>
@if(auth()->user()->hasPerk('watchlist_export'))
<div style="display:flex;gap:6px">
<a href="{{ route('watchlist.export', ['format'=>'csv']) }}" style="font-size:.72rem;color:rgba(0,245,255,.7);text-decoration:none;display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border:1px solid rgba(0,245,255,.2);border-radius:6px">
<i class="bi bi-download"></i> CSV
</a>
<a href="{{ route('watchlist.export', ['format'=>'json']) }}" style="font-size:.72rem;color:rgba(0,245,255,.7);text-decoration:none;display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border:1px solid rgba(0,245,255,.2);border-radius:6px">
<i class="bi bi-download"></i> JSON
</a>
</div>
@endif
</div>
@if($watchlistItems->count())
{{-- Filter buttons --}}
<div class="wl-filter">
<button class="wl-filter-btn on" data-wl="all">Tümü</button>
@foreach(\App\Models\Watchlist::STATUSES as $status => $label)
@if(isset($watchlistItems[$status]) && $watchlistItems[$status]->count())
<button class="wl-filter-btn" data-wl="{{ $status }}">{{ $label }} <span style="opacity:.5">({{ $watchlistItems[$status]->count() }})</span></button>
@endif
@endforeach
</div>
@foreach(\App\Models\Watchlist::STATUSES as $status => $label)
@if(isset($watchlistItems[$status]) && $watchlistItems[$status]->count())
<div class="wl-section wl-grid" data-wl="{{ $status }}" style="margin-bottom:24px">
@foreach($watchlistItems[$status] as $wl)
@if(!$wl->anime) @continue @endif
<a href="{{ $wl->anime->detailUrl }}" class="wl-card">
@if($wl->anime->cover_image)
<img src="{{ \App\Support\MediaUrl::fromStoragePath($wl->anime->cover_image) }}" alt="" loading="lazy">
@else
<div class="wl-card-ph"><i class="bi bi-image"></i></div>
@endif
<div class="wl-card-title">{{ $wl->anime->title }}</div>
</a>
@endforeach
</div>
@endif
@endforeach
@else
<div class="pr-empty"><i class="bi bi-bookmark"></i>Liste henüz boş.</div>
@endif
</div>
{{-- AKTİVİTE / HEATMAP --}}
<div class="pr-pane" id="pane-activity">
<div class="pr-sec-h"><span>İzleme Aktivitesi Son 1 Yıl</span></div>
@php
$today = now()->startOfDay();
$start = $today->copy()->subDays(364);
$gridStart= $start->copy()->startOfWeek(\Carbon\Carbon::MONDAY);
$weeks = [];
$cur = $gridStart->copy();
while ($cur->lte($today)) {
$week = [];
for ($d = 0; $d < 7; $d++) {
$key = $cur->format('Y-m-d');
$week[] = ['date'=>$key,'count'=>$heatmapRaw[$key]??0,'past'=>$cur->lte($today)&&$cur->gte($start)];
$cur->addDay();
}
$weeks[] = $week;
}
$maxCount = !empty($heatmapRaw) ? max($heatmapRaw) : 1;
$totalDays = collect($heatmapRaw)->filter()->count();
$totalEpYear= array_sum($heatmapRaw);
@endphp
<div class="heatmap-wrap">
<div class="heatmap-scroll">
<div class="heatmap-grid">
@foreach($weeks as $week)
<div class="hm-col">
@foreach($week as $cell)
@php
$alpha = 0;
$bg = 'rgba(255,255,255,.05)';
if ($cell['past'] && $cell['count'] > 0) {
$intensity = min(1, $cell['count'] / max($maxCount,1));
$alpha = 0.18 + $intensity * 0.82;
$bg = "rgba(0,245,255,{$alpha})";
} elseif (!$cell['past']) {
$bg = 'transparent';
}
@endphp
<div class="hm-cell" title="{{ $cell['past'] ? $cell['date'].': '.($cell['count']?$cell['count'].' bölüm':'boş') : '' }}"
style="background:{{ $bg }}"></div>
@endforeach
</div>
@endforeach
</div>
</div>
<div class="heatmap-legend">
<span>Az</span>
<div class="heatmap-legend-cells">
<div style="width:13px;height:13px;border-radius:3px;background:rgba(255,255,255,.05)"></div>
<div style="width:13px;height:13px;border-radius:3px;background:rgba(0,245,255,.2)"></div>
<div style="width:13px;height:13px;border-radius:3px;background:rgba(0,245,255,.45)"></div>
<div style="width:13px;height:13px;border-radius:3px;background:rgba(0,245,255,.7)"></div>
<div style="width:13px;height:13px;border-radius:3px;background:rgba(0,245,255,1)"></div>
</div>
<span>Çok</span>
</div>
<div class="heatmap-stats">
<span><i class="bi bi-calendar3 me-1"></i>{{ $totalDays }} aktif gün</span>
<span><i class="bi bi-play-circle me-1"></i>{{ $totalEpYear }} bölüm izlendi</span>
</div>
</div>
</div>
{{-- BAŞARIMLAR --}}
@if($allAchievements->count())
<div class="pr-pane" id="pane-achievements">
@php $earnedIds = $achievements->pluck('achievement_id')->toArray(); @endphp
<div class="pr-sec-h"><span>Başarımlar <span style="opacity:.4;font-weight:400">{{ $achievements->count() }}/{{ $allAchievements->count() }}</span></span></div>
<div class="ach-grid">
@foreach($allAchievements->sortByDesc(fn($a)=>in_array($a->id,$earnedIds)) as $ach)
@php $earned = in_array($ach->id, $earnedIds); @endphp
<div class="ach-card {{ $earned ? 'earned' : '' }}" style="{{ $earned ? 'border-color:'.substr($ach->color,0,7).'33' : '' }}">
<div class="ach-icon-wrap" style="background:{{ $earned ? substr($ach->color,0,7).'1a' : 'rgba(255,255,255,.04)' }}">
<i class="bi {{ $ach->icon }}" style="color:{{ $earned ? $ach->color : 'rgba(255,255,255,.2)' }}"></i>
</div>
<div class="ach-body">
<div class="ach-title">{{ $ach->title }}</div>
<div class="ach-desc">{{ $ach->description }}</div>
@if($earned)
@php $ea = $achievements->firstWhere('achievement_id',$ach->id); @endphp
<div class="ach-date" style="color:{{ $ach->color }}">{{ $ea?->earned_at?->format('d.m.Y') }}</div>
@endif
</div>
</div>
@endforeach
</div>
</div>
@endif
{{-- NOTLAR --}}
<div class="pr-pane" id="pane-notes">
<div class="pr-sec-h"><span>Bölüm Notlarım</span></div>
@forelse($episodeNotes as $note)
<div class="note-card">
<div class="note-meta">
@if($note->anime)<a href="{{ $note->anime->detailUrl }}" class="note-anime">{{ $note->anime->title }}</a>@endif
@if($note->episode)<span class="note-ep">{{ $note->episode->episode_number }}. Bölüm</span>@endif
@if($note->timestamp_at)<span class="note-ts"><i class="bi bi-clock"></i> {{ $note->timestamp_label }}</span>@endif
<span class="note-date">{{ $note->created_at->format('d.m.Y') }}</span>
</div>
<div class="note-text">{{ $note->content }}</div>
</div>
@empty
<div class="pr-empty"><i class="bi bi-journal-text"></i>Henüz not almadın.<br><small style="font-size:.78rem;opacity:.6">İzlerken bölüm içindeki not ikonuna tıklayarak not alabilirsin.</small></div>
@endforelse
</div>
{{-- YORUMLAR --}}
{{-- ── Keşfet Geçmişi ──────────────────────────────────────── --}}
<div class="pr-pane" id="pane-swipes">
<div class="pr-sec-h" style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px">
<span>Keşfet Geçmişi</span>
@if($swipeHistory->count())
<div style="display:flex;gap:14px;font-size:.68rem;color:var(--text3)">
<span style="color:var(--accent2)">
<i class="bi bi-heart-fill" style="margin-right:3px"></i>
{{ $swipeHistory->where('direction','like')->count() }} beğeni
</span>
<span>
<i class="bi bi-x-lg" style="margin-right:3px;color:#ff2d7d"></i>
{{ $swipeHistory->where('direction','skip')->count() }} geç
</span>
<a href="{{ route('discover') }}" style="color:var(--accent2);text-decoration:none">
<i class="bi bi-arrow-right" style="margin-right:3px"></i>Devam et
</a>
</div>
@endif
</div>
@if($swipeHistory->isEmpty())
<div class="pr-empty">
<i class="bi bi-hand-index-thumb"></i>
Henüz hiç anime keşfetmedin. <a href="{{ route('discover') }}" style="color:var(--accent2);text-decoration:none">Hemen başla </a>
</div>
@else
{{-- Filter buttons --}}
<div style="display:flex;gap:6px;margin-bottom:16px;flex-wrap:wrap">
<button class="swipe-filter on" data-f="all">Tümü <span class="swipe-f-count">{{ $swipeHistory->count() }}</span></button>
<button class="swipe-filter" data-f="like"><i class="bi bi-heart-fill" style="color:var(--accent2);font-size:.75rem"></i> Beğendiklerim <span class="swipe-f-count">{{ $swipeHistory->where('direction','like')->count() }}</span></button>
<button class="swipe-filter" data-f="skip"><i class="bi bi-x-lg" style="color:#ff2d7d;font-size:.75rem"></i> Geçtiklerim <span class="swipe-f-count">{{ $swipeHistory->where('direction','skip')->count() }}</span></button>
</div>
<div class="swipe-grid" id="swipeGrid">
@foreach($swipeHistory as $sw)
@php $a = $sw->anime; @endphp
<a href="{{ $a->detailUrl }}" class="swipe-item {{ $sw->direction }}" data-dir="{{ $sw->direction }}" title="{{ $a->title }}">
<div class="swipe-poster">
@if($a->coverUrl)
<img src="{{ $a->coverUrl }}" alt="{{ $a->title }}" loading="lazy">
@else
<div class="swipe-poster-ph"><i class="bi bi-film"></i></div>
@endif
<div class="swipe-dir-badge {{ $sw->direction === 'like' ? 'badge-like' : 'badge-skip' }}">
@if($sw->direction === 'like')
<i class="bi bi-heart-fill"></i>
@else
<i class="bi bi-x-lg"></i>
@endif
</div>
</div>
<div class="swipe-info">
<div class="swipe-title">{{ $a->title }}</div>
<div class="swipe-meta">
@if($a->release_year)<span>{{ $a->release_year }}</span>@endif
@if($a->rating)<span style="color:#fbbf24"><i class="bi bi-star-fill" style="font-size:.55rem"></i> {{ number_format($a->rating,1) }}</span>@endif
</div>
</div>
</a>
@endforeach
</div>
@endif
</div>
<div class="pr-pane" id="pane-comments">
<div class="pr-sec-h"><span>Son Yorumlar</span></div>
@if($recentComments->isEmpty())
<div class="pr-empty"><i class="bi bi-chat-dots"></i>Henüz yorum yok.</div>
@else
@foreach($recentComments as $c)
<div class="cm-card">
<div class="cm-top">
<div class="cm-ava">{{ mb_strtoupper(mb_substr($user->name,0,1)) }}</div>
<span class="cm-name">{{ $user->name }}</span>
<span class="cm-time">{{ $c->created_at->diffForHumans() }}</span>
</div>
@if($c->content)<div class="cm-text">{{ $c->content }}</div>@endif
@if($c->gif_url)<img src="{{ $c->gif_url }}" alt="" class="cm-gif">@endif
</div>
@endforeach
@endif
</div>
</div>
@endsection
@push('scripts')
<script>
// Tab switching
document.querySelectorAll('.pr-tab').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.pr-tab').forEach(t => t.classList.remove('on'));
document.querySelectorAll('.pr-pane').forEach(p => p.classList.remove('on'));
btn.classList.add('on');
document.getElementById('pane-' + btn.dataset.pane)?.classList.add('on');
});
});
// Watchlist filter
document.querySelectorAll('.wl-filter-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.wl-filter-btn').forEach(b => b.classList.remove('on'));
btn.classList.add('on');
const target = btn.dataset.wl;
document.querySelectorAll('.wl-section').forEach(sec => {
sec.style.display = (target === 'all' || sec.dataset.wl === target) ? 'grid' : 'none';
});
});
});
// Swipe history filter
document.querySelectorAll('.swipe-filter').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.swipe-filter').forEach(b => b.classList.remove('on'));
btn.classList.add('on');
const f = btn.dataset.f;
document.querySelectorAll('#swipeGrid .swipe-item').forEach(item => {
item.style.display = (f === 'all' || item.dataset.dir === f) ? '' : 'none';
});
});
});
</script>
@endpush