Initial commit: Animexe Laravel platform
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,253 @@
|
||||
@extends('frontend.layouts.app')
|
||||
@section('title', 'Mahkeme: ' . Str::limit($tribunal->question, 60) . ' | Animexe')
|
||||
@php
|
||||
// Sabit renk paleti — a,b,c,d,e,f
|
||||
$palette = [
|
||||
'a' => ['bg'=>'rgba(0,200,100,.08)', 'bg2'=>'rgba(0,200,100,.22)', 'border'=>'rgba(0,200,100,.25)', 'border2'=>'#00c864', 'text'=>'#00c864', 'bar'=>'#00c864'],
|
||||
'b' => ['bg'=>'rgba(255,60,60,.08)', 'bg2'=>'rgba(255,60,60,.22)', 'border'=>'rgba(255,60,60,.25)', 'border2'=>'#ff3c3c', 'text'=>'#ff3c3c', 'bar'=>'#ff3c3c'],
|
||||
'c' => ['bg'=>'rgba(59,130,246,.08)', 'bg2'=>'rgba(59,130,246,.22)', 'border'=>'rgba(59,130,246,.25)', 'border2'=>'#3b82f6', 'text'=>'#3b82f6', 'bar'=>'#3b82f6'],
|
||||
'd' => ['bg'=>'rgba(245,158,11,.08)', 'bg2'=>'rgba(245,158,11,.22)', 'border'=>'rgba(245,158,11,.25)', 'border2'=>'#f59e0b', 'text'=>'#f59e0b', 'bar'=>'#f59e0b'],
|
||||
'e' => ['bg'=>'rgba(167,139,250,.08)','bg2'=>'rgba(167,139,250,.22)','border'=>'rgba(167,139,250,.25)','border2'=>'#a78bfa','text'=>'#a78bfa','bar'=>'#a78bfa'],
|
||||
'f' => ['bg'=>'rgba(236,72,153,.08)', 'bg2'=>'rgba(236,72,153,.22)', 'border'=>'rgba(236,72,153,.25)', 'border2'=>'#ec4899','text'=>'#ec4899','bar'=>'#ec4899'],
|
||||
];
|
||||
$cols = count($allSides) <= 2 ? '1fr 1fr' : (count($allSides) <= 3 ? '1fr 1fr 1fr' : 'repeat(auto-fit,minmax(140px,1fr))');
|
||||
@endphp
|
||||
@push('styles')
|
||||
<style>
|
||||
.tb-wrap{max-width:900px;margin:0 auto;padding:calc(var(--nav-h) + 32px) 20px 60px}
|
||||
.tb-anime-link{font-size:.75rem;color:rgba(255,45,125,.8);font-weight:700;text-transform:uppercase;letter-spacing:.08em;text-decoration:none;display:inline-block;margin-bottom:12px}
|
||||
.tb-question{font-size:1.5rem;font-weight:900;line-height:1.35;margin-bottom:14px}
|
||||
.tb-status{display:inline-block;padding:3px 12px;border-radius:20px;font-size:.72rem;font-weight:700;margin-bottom:20px}
|
||||
.tb-status.open{background:rgba(0,200,100,.15);color:#00c864;border:1px solid rgba(0,200,100,.25)}
|
||||
.tb-status.closed{background:rgba(255,255,255,.06);color:rgba(255,255,255,.4);border:1px solid rgba(255,255,255,.1)}
|
||||
|
||||
/* Vote Card */
|
||||
.tb-votebar{background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);border-radius:16px;padding:24px;margin-bottom:24px}
|
||||
.tb-sides{display:grid;gap:10px;margin-bottom:20px;grid-template-columns:{{ $cols }}}
|
||||
.tb-vote-btn{padding:13px 10px;border-radius:12px;border:2px solid transparent;cursor:pointer;font-weight:800;font-size:.88rem;font-family:inherit;transition:all .2s;text-align:center;line-height:1.3}
|
||||
|
||||
/* Multi-bar */
|
||||
.tb-multibar{display:flex;flex-direction:column;gap:8px}
|
||||
.tb-bar-row{display:flex;align-items:center;gap:10px}
|
||||
.tb-bar-label{font-size:.72rem;font-weight:700;white-space:nowrap;min-width:80px;max-width:120px;overflow:hidden;text-overflow:ellipsis}
|
||||
.tb-bar-track{flex:1;height:8px;border-radius:99px;background:rgba(255,255,255,.07);overflow:hidden}
|
||||
.tb-bar-fill{height:100%;border-radius:99px;transition:width .5s cubic-bezier(.22,1,.36,1)}
|
||||
.tb-bar-pct{font-size:.72rem;color:rgba(255,255,255,.4);min-width:40px;text-align:right}
|
||||
|
||||
/* Arguments */
|
||||
.tb-args{margin-top:28px}
|
||||
.tb-args-title{font-size:.8rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:rgba(255,255,255,.3);margin-bottom:16px}
|
||||
.tb-arg-card{background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);border-radius:12px;padding:16px;margin-bottom:10px}
|
||||
.tb-arg-side-badge{display:inline-block;padding:2px 10px;border-radius:20px;font-size:.68rem;font-weight:800;margin-bottom:8px}
|
||||
.tb-arg-body{font-size:.9rem;line-height:1.5;margin-bottom:10px}
|
||||
.tb-arg-meta{display:flex;align-items:center;gap:12px;font-size:.72rem;color:rgba(255,255,255,.3)}
|
||||
.tb-arg-vote-btn{background:none;border:1px solid rgba(255,255,255,.1);border-radius:20px;padding:3px 12px;color:rgba(255,255,255,.4);cursor:pointer;font-size:.72rem;font-family:inherit;display:inline-flex;align-items:center;gap:5px;transition:all .15s}
|
||||
.tb-arg-vote-btn:hover,.tb-arg-vote-btn.on{background:rgba(255,215,0,.12);border-color:rgba(255,215,0,.3);color:#ffd700}
|
||||
|
||||
/* Argue form */
|
||||
.tb-argue-form{background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);border-radius:14px;padding:20px;margin-top:24px}
|
||||
.tb-argue-title{font-size:.88rem;font-weight:700;margin-bottom:12px}
|
||||
.tb-argue-sides{display:grid;gap:8px;margin-bottom:12px;grid-template-columns:{{ $cols }}}
|
||||
.tb-argue-side-btn{padding:9px 8px;border-radius:10px;cursor:pointer;font-weight:700;font-size:.8rem;font-family:inherit;border:2px solid transparent;transition:all .15s;text-align:center}
|
||||
textarea.tb-inp{width:100%;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-radius:10px;padding:10px 14px;color:#fff;font-size:.88rem;font-family:inherit;resize:none;outline:none;margin-bottom:10px;box-sizing:border-box}
|
||||
.tb-submit-btn{padding:10px 24px;border-radius:10px;border:none;background:rgba(255,45,125,.2);color:#ff2d7d;font-weight:700;font-size:.88rem;cursor:pointer;font-family:inherit;transition:background .15s}
|
||||
.tb-submit-btn:hover{background:rgba(255,45,125,.35)}
|
||||
</style>
|
||||
@endpush
|
||||
@section('content')
|
||||
<div class="tb-wrap">
|
||||
|
||||
<a class="tb-anime-link" href="{{ $tribunal->anime?->detailUrl ?? '#' }}">
|
||||
<i class="bi bi-arrow-left"></i> {{ $tribunal->anime->title }}
|
||||
</a>
|
||||
|
||||
<div class="tb-status {{ $tribunal->status }}">
|
||||
{{ $tribunal->status === 'open' ? '🟢 Dava Açık' : '🔴 Dava Kapalı' }}
|
||||
@if($tribunal->closes_at && $tribunal->status === 'open')
|
||||
· {{ $tribunal->closes_at->diffForHumans() }} kapanıyor
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="tb-question">{{ $tribunal->question }}</div>
|
||||
|
||||
{{-- Oy sistemi --}}
|
||||
<div class="tb-votebar">
|
||||
<div class="tb-sides">
|
||||
@foreach($allSides as $key => $label)
|
||||
@php $c = $palette[$key] ?? $palette['a']; @endphp
|
||||
<button id="vote-{{ $key }}" class="tb-vote-btn"
|
||||
style="background:{{ $c['bg'] }};color:{{ $c['text'] }};border-color:{{ $c['border'] }}"
|
||||
data-bg="{{ $c['bg'] }}" data-bg2="{{ $c['bg2'] }}" data-border="{{ $c['border'] }}" data-border2="{{ $c['border2'] }}"
|
||||
onclick="castVote('{{ $key }}')">
|
||||
{{ $label }}
|
||||
<div style="font-size:.7rem;font-weight:400;opacity:.7;margin-top:3px">
|
||||
<span id="vcnt-{{ $key }}">{{ $voteCounts[$key] ?? 0 }}</span> oy
|
||||
· <span id="vpct-{{ $key }}">{{ $total > 0 ? round(($voteCounts[$key]??0)/$total*100) : 0 }}%</span>
|
||||
</div>
|
||||
</button>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
{{-- Çok taraflı bar --}}
|
||||
<div class="tb-multibar">
|
||||
@foreach($allSides as $key => $label)
|
||||
@php $c = $palette[$key] ?? $palette['a']; $pct = $total > 0 ? round(($voteCounts[$key]??0)/$total*100) : 0; @endphp
|
||||
<div class="tb-bar-row">
|
||||
<div class="tb-bar-label" style="color:{{ $c['text'] }}">{{ $label }}</div>
|
||||
<div class="tb-bar-track">
|
||||
<div class="tb-bar-fill" id="bar-{{ $key }}" style="width:{{ $pct }}%;background:{{ $c['bar'] }}"></div>
|
||||
</div>
|
||||
<div class="tb-bar-pct" id="bpct-{{ $key }}">{{ $pct }}%</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div style="margin-top:10px;font-size:.72rem;color:rgba(255,255,255,.25)">
|
||||
Toplam <span id="total-votes">{{ $total }}</span> oy
|
||||
@auth @if($myVote) · <span style="color:rgba(255,255,255,.5)">Oyunuz: <strong>{{ $allSides[$myVote] ?? $myVote }}</strong></span> @endif @endauth
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Argümanlar --}}
|
||||
<div class="tb-args">
|
||||
<div class="tb-args-title"><i class="bi bi-chat-quote"></i> Argümanlar</div>
|
||||
<div id="arg-list">
|
||||
@forelse($arguments as $arg)
|
||||
@php $c2 = $palette[$arg['side']] ?? $palette['a']; @endphp
|
||||
<div class="tb-arg-card" id="arg-{{ $arg['id'] }}">
|
||||
<span class="tb-arg-side-badge"
|
||||
style="background:{{ $c2['bg'] }};color:{{ $c2['text'] }}">{{ $allSides[$arg['side']] ?? $arg['side'] }}</span>
|
||||
<div class="tb-arg-body">{{ $arg['body'] }}</div>
|
||||
<div class="tb-arg-meta">
|
||||
<span>{{ $arg['name'] ?? $arg['username'] }}</span>
|
||||
<span>{{ $arg['created_at'] }}</span>
|
||||
<button class="tb-arg-vote-btn {{ $arg['voted'] ? 'on' : '' }}" id="avgbtn-{{ $arg['id'] }}"
|
||||
onclick="argVote({{ $arg['id'] }})">
|
||||
<i class="bi bi-hand-thumbs-up"></i>
|
||||
<span id="avgcnt-{{ $arg['id'] }}">{{ $arg['vote_count'] }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<div id="no-args" style="text-align:center;padding:30px;color:rgba(255,255,255,.25);font-size:.85rem">
|
||||
Henüz argüman girilmemiş. İlk sen gir!
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Argüman formu --}}
|
||||
@auth
|
||||
@if(!$myArgument && $tribunal->status === 'open')
|
||||
<div class="tb-argue-form">
|
||||
<div class="tb-argue-title">⚔️ Senin Argümanın — Hangi taraftasın?</div>
|
||||
<div class="tb-argue-sides">
|
||||
@foreach($allSides as $key => $label)
|
||||
@php $c3 = $palette[$key] ?? $palette['a']; @endphp
|
||||
<button id="arg-side-{{ $key }}" class="tb-argue-side-btn"
|
||||
style="background:{{ $c3['bg'] }};color:{{ $c3['text'] }};border-color:{{ $c3['border'] }}"
|
||||
data-bg="{{ $c3['bg'] }}" data-bg2="{{ $c3['bg2'] }}" data-border="{{ $c3['border'] }}" data-border2="{{ $c3['border2'] }}"
|
||||
onclick="selectArgSide('{{ $key }}')">{{ $label }}</button>
|
||||
@endforeach
|
||||
</div>
|
||||
<textarea class="tb-inp" id="arg-body" rows="3" maxlength="500" placeholder="Argümanını yaz (min 10, max 500 karakter)..."></textarea>
|
||||
<div id="arg-err" style="color:#ff4444;font-size:.78rem;margin-bottom:8px;display:none"></div>
|
||||
<button class="tb-submit-btn" onclick="submitArg()">Argümanı Gönder</button>
|
||||
</div>
|
||||
@elseif($myArgument)
|
||||
<div style="padding:14px;background:rgba(0,200,100,.06);border:1px solid rgba(0,200,100,.2);border-radius:12px;font-size:.85rem;color:rgba(255,255,255,.5);margin-top:24px">
|
||||
✅ Argümanınızı gönderdiniz.
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div style="margin-top:20px;text-align:center;font-size:.85rem;color:rgba(255,255,255,.3)">
|
||||
<a href="{{ route('frontend.login') }}" style="color:#ff2d7d">Giriş yap</a> — argüman girmek için
|
||||
</div>
|
||||
@endauth
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
@push('scripts')
|
||||
<script>
|
||||
const CSRF = document.querySelector('meta[name="csrf-token"]')?.content ?? '';
|
||||
const IS_AUTH = {{ auth()->check() ? 'true' : 'false' }};
|
||||
const MY_VOTE = {{ $myVote ? json_encode($myVote) : 'null' }};
|
||||
let selectedArgSide = null;
|
||||
|
||||
// İlk yüklemede aktif oyu vurgula
|
||||
if (MY_VOTE) activateVoteBtn(MY_VOTE);
|
||||
|
||||
function activateVoteBtn(side) {
|
||||
document.querySelectorAll('.tb-vote-btn').forEach(b => {
|
||||
const isMe = b.id === 'vote-' + side;
|
||||
b.style.background = isMe ? b.dataset.bg2 : b.dataset.bg;
|
||||
b.style.borderColor = isMe ? b.dataset.border2 : b.dataset.border;
|
||||
});
|
||||
}
|
||||
|
||||
function selectArgSide(s) {
|
||||
selectedArgSide = s;
|
||||
document.querySelectorAll('.tb-argue-side-btn').forEach(b => {
|
||||
const isMe = b.id === 'arg-side-' + s;
|
||||
b.style.background = isMe ? b.dataset.bg2 : b.dataset.bg;
|
||||
b.style.borderColor = isMe ? b.dataset.border2 : b.dataset.border;
|
||||
});
|
||||
}
|
||||
|
||||
async function castVote(side) {
|
||||
if (!IS_AUTH) { window.location.href = '{{ route('frontend.login') }}'; return; }
|
||||
const r = await fetch('{{ route('tribunal.vote', $tribunal) }}', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': CSRF, 'Accept': 'application/json' },
|
||||
body: JSON.stringify({ side }),
|
||||
});
|
||||
const d = await r.json();
|
||||
updateVoteBar(d.voted, d.counts, d.total);
|
||||
}
|
||||
|
||||
function updateVoteBar(voted, counts, total) {
|
||||
activateVoteBtn(voted);
|
||||
document.getElementById('total-votes').textContent = total;
|
||||
for (const [key, cnt] of Object.entries(counts)) {
|
||||
const pct = total > 0 ? Math.round(cnt / total * 100) : 0;
|
||||
const fill = document.getElementById('bar-' + key);
|
||||
const pctEl = document.getElementById('bpct-' + key);
|
||||
const vcnt = document.getElementById('vcnt-' + key);
|
||||
const vpct = document.getElementById('vpct-' + key);
|
||||
if (fill) fill.style.width = pct + '%';
|
||||
if (pctEl) pctEl.textContent = pct + '%';
|
||||
if (vcnt) vcnt.textContent = cnt;
|
||||
if (vpct) vpct.textContent = pct + '%';
|
||||
}
|
||||
}
|
||||
|
||||
async function argVote(id) {
|
||||
if (!IS_AUTH) { window.location.href = '{{ route('frontend.login') }}'; return; }
|
||||
const r = await fetch(`/arguman/${id}/oy`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': CSRF, 'Accept': 'application/json' },
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
const d = await r.json();
|
||||
document.getElementById('avgcnt-' + id).textContent = d.vote_count;
|
||||
document.getElementById('avgbtn-' + id).classList.toggle('on', d.voted);
|
||||
}
|
||||
|
||||
async function submitArg() {
|
||||
const err = document.getElementById('arg-err');
|
||||
const body = document.getElementById('arg-body').value.trim();
|
||||
err.style.display = 'none';
|
||||
if (!selectedArgSide) { err.textContent = 'Taraf seçin.'; err.style.display = 'block'; return; }
|
||||
if (body.length < 10) { err.textContent = 'Argüman en az 10 karakter olmalı.'; err.style.display = 'block'; return; }
|
||||
|
||||
const r = await fetch('{{ route('tribunal.argue', $tribunal) }}', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': CSRF, 'Accept': 'application/json' },
|
||||
body: JSON.stringify({ side: selectedArgSide, body }),
|
||||
});
|
||||
const d = await r.json();
|
||||
if (d.ok) window.location.reload();
|
||||
else { err.textContent = d.error || 'Hata.'; err.style.display = 'block'; }
|
||||
}
|
||||
</script>
|
||||
@endpush
|
||||
Reference in New Issue
Block a user