Files
citrus/resources/views/front/career/admin_dashboard.blade.php
T

643 lines
27 KiB
PHP
Raw 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.
@extends('layouts.site')
@section('content')
<section class="wrapper bg-[#f0f7ff] py-12">
<div class="container px-4">
<div class="max-w-7xl mx-auto">
<!-- Welcome Section -->
@include('front.career.partials.welcome')
<!-- Statistics Section -->
@include('front.career.partials.stats')
<!-- Tab Switcher Menu -->
<div class="bg-white rounded-3xl p-4 shadow-xl border border-slate-100/50 mb-8">
<div class="flex flex-col sm:flex-row gap-3" role="tablist">
<button type="button" role="tab" aria-selected="true" data-tab-target="gantt-chart" class="admin-tab-btn active flex-1 flex items-center justify-center gap-3 py-4 px-6 rounded-2xl text-center font-bold text-sm transition-all border border-transparent cursor-pointer">
<i class="uil uil-schedule text-lg"></i>
<span>Gantt Şeması ve Takvimi</span>
</button>
<button type="button" role="tab" aria-selected="false" data-tab-target="intern-list" class="admin-tab-btn flex-1 flex items-center justify-center gap-3 py-4 px-6 rounded-2xl text-center font-bold text-sm transition-all border border-transparent text-slate-600 hover:bg-slate-50 cursor-pointer">
<i class="uil uil-list-ul text-lg"></i>
<span>Stajyer Listesi ve Detaylı Takip</span>
</button>
</div>
</div>
<!-- Tab Panels -->
<div id="gantt-chart-panel" class="admin-tab-panel space-y-6">
@include('front.career.partials.gantt')
</div>
<div id="intern-list-panel" class="admin-tab-panel hidden space-y-6">
@include('front.career.partials.list')
</div>
</div>
</div>
</section>
@include('front.career.partials.guide_modal')
<!-- Intern Journal Tracking & Approval Modal -->
<div id="intern-journal-modal" class="fixed inset-0 z-[9998] hidden items-center justify-center bg-slate-900/60 backdrop-blur-sm transition-opacity duration-300">
<div class="bg-white rounded-3xl shadow-2xl border border-slate-100 max-w-4xl w-full mx-4 overflow-hidden transform scale-95 opacity-0 transition-all duration-300 flex flex-col max-h-[90vh]">
<!-- Header -->
<div class="px-6 py-4 bg-gradient-to-r from-blue-50 to-indigo-50/30 border-b border-slate-100 flex items-center justify-between flex-shrink-0">
<div>
<h4 id="ijm-name" class="font-bold text-slate-800 text-lg">Stajyer Defteri ve İnceleme</h4>
<p id="ijm-meta" class="text-xs text-slate-500 font-semibold mt-0.5"></p>
</div>
<button type="button" onclick="closeInternJournalModal()" class="text-slate-400 hover:text-slate-600 transition-colors p-1.5 rounded-full hover:bg-slate-100/80">
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M6 18L18 6M6 6l12 12"/></svg>
</button>
</div>
<!-- Body -->
<div class="flex-grow p-6 overflow-y-auto no-scrollbar grid grid-cols-1 md:grid-cols-12 gap-6">
<!-- Left Sidebar: Progress & General Approvals (col-span-4) -->
<div class="md:col-span-4 space-y-6">
<!-- Progress Bar Card -->
<div class="bg-slate-50 rounded-2xl p-5 border border-slate-200/50">
<h5 class="font-bold text-slate-700 text-xs uppercase tracking-wider mb-4 flex items-center gap-1.5">
<i class="uil uil-chart-bar text-blue-600"></i>
<span>Staj İlerlemesi</span>
</h5>
<!-- Journal Filling Progress -->
<div class="space-y-2 mb-4">
<div class="flex justify-between text-xs font-bold">
<span class="text-slate-500">Defter Doldurma</span>
<span id="ijm-fill-text" class="text-slate-700">0 / 0 Gün</span>
</div>
<div class="w-full bg-slate-200 h-2.5 rounded-full overflow-hidden">
<div id="ijm-fill-progress" class="bg-blue-600 h-full rounded-full transition-all duration-500" style="width: 0%"></div>
</div>
</div>
<!-- Journal Approval Progress -->
<div class="space-y-2">
<div class="flex justify-between text-xs font-bold">
<span class="text-slate-500">Onaylı Günler</span>
<span id="ijm-approved-text" class="text-slate-700">0 / 0 Gün</span>
</div>
<div class="w-full bg-slate-200 h-2.5 rounded-full overflow-hidden">
<div id="ijm-approved-progress" class="bg-emerald-500 h-full rounded-full transition-all duration-500" style="width: 0%"></div>
</div>
</div>
</div>
<!-- Overall Signatures Card -->
<div class="bg-slate-50 rounded-2xl p-5 border border-slate-200/50 space-y-4">
<h5 class="font-bold text-slate-700 text-xs uppercase tracking-wider flex items-center gap-1.5">
<i class="uil uil-signature text-indigo-600"></i>
<span>Resmi Onaylar / İmzalar</span>
</h5>
<!-- Supervisor Signature -->
<div class="p-3 bg-white rounded-xl border border-slate-100 flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-xs font-bold text-slate-600">Sorumlu İmzası</span>
<button type="button" id="ijm-btn-supervisor" onclick="toggleNotebookSignature('supervisor')" class="px-2.5 py-1 text-[10px] font-extrabold uppercase rounded-lg border transition-all"></button>
</div>
<div class="text-[10px] text-slate-400 font-semibold" id="ijm-text-supervisor">İmzalanmadı</div>
</div>
<!-- Unit Signature -->
<div class="p-3 bg-white rounded-xl border border-slate-100 flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-xs font-bold text-slate-600">Birim Sorumlu İmzası</span>
<button type="button" id="ijm-btn-unit" onclick="toggleNotebookSignature('unit')" class="px-2.5 py-1 text-[10px] font-extrabold uppercase rounded-lg border transition-all"></button>
</div>
<div class="text-[10px] text-slate-400 font-semibold" id="ijm-text-unit">İmzalanmadı</div>
</div>
<!-- Notebook Approved -->
<div class="p-3 bg-white rounded-xl border border-slate-100 flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-xs font-bold text-slate-600">Genel Defter Onayı</span>
<button type="button" id="ijm-btn-approved" onclick="toggleNotebookSignature('approved')" class="px-2.5 py-1 text-[10px] font-extrabold uppercase rounded-lg border transition-all"></button>
</div>
<div class="text-[10px] text-slate-400 font-semibold" id="ijm-text-approved">Onaylanmadı</div>
</div>
</div>
</div>
<!-- Right Section: Carousel & Navigation (col-span-8) -->
<div class="md:col-span-8 flex flex-col space-y-4">
<!-- Carousel Controls -->
<div class="bg-slate-50 p-4 rounded-2xl border border-slate-200/50 flex items-center justify-between gap-3">
<button type="button" onclick="prevSlide()" class="p-2 bg-white hover:bg-slate-100 border border-slate-200 text-slate-600 hover:text-slate-900 rounded-xl transition-all flex items-center justify-center cursor-pointer">
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M15 19l-7-7 7-7"/></svg>
</button>
<div class="flex-grow flex items-center justify-center gap-3">
<span id="ijm-day-indicator" class="text-sm font-extrabold text-blue-600 bg-blue-50 px-3 py-1.5 rounded-xl">Gün: 0 / 0</span>
<!-- Quick Day Dropdown -->
<select id="ijm-day-select" onchange="goToSlide(this.value)" class="text-xs font-semibold text-slate-700 bg-white border border-slate-200 rounded-xl px-2.5 py-1.5 focus:outline-none focus:border-blue-400">
<!-- Options loaded dynamically -->
</select>
</div>
<button type="button" onclick="nextSlide()" class="p-2 bg-white hover:bg-slate-100 border border-slate-200 text-slate-600 hover:text-slate-900 rounded-xl transition-all flex items-center justify-center cursor-pointer">
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M9 5l7 7-7 7"/></svg>
</button>
</div>
<!-- Carousel Slide Container -->
<div class="bg-white rounded-2xl border border-slate-100 p-6 flex-grow flex flex-col shadow-sm min-h-[300px]">
<!-- Day Title & Date -->
<div class="flex items-center justify-between pb-3 border-b border-slate-100 mb-4 flex-shrink-0">
<div>
<span id="ijm-slide-title" class="text-sm font-extrabold text-slate-800">Seçili Gün</span>
<span id="ijm-slide-date" class="text-xs font-semibold text-slate-400 ml-2"></span>
</div>
<div id="ijm-slide-retroactive">
<!-- Retroactive badge -->
</div>
</div>
<!-- Slide Content (Rich text HTML) -->
<div class="flex-grow overflow-y-auto no-scrollbar prose max-w-none text-slate-700 leading-relaxed text-sm" style="max-height: 250px;">
<div id="ijm-slide-content">
<!-- Day content loaded here -->
</div>
</div>
<!-- Slide Actions / Daily approval status -->
<div class="pt-4 border-t border-slate-100 flex items-center justify-between mt-4 flex-shrink-0">
<div id="ijm-slide-status-badge">
<!-- Status badge -->
</div>
<button type="button" id="ijm-slide-action-btn" onclick="toggleActiveDayApproval()" class="px-4 py-2 text-white bg-blue-600 hover:bg-blue-700 rounded-xl font-bold text-xs shadow-lg shadow-blue-500/20 transition-all cursor-pointer">
Onayla
</button>
</div>
</div>
</div>
</div>
<!-- Footer -->
<div class="px-6 py-4 bg-slate-50 border-t border-slate-100 flex items-center justify-end flex-shrink-0">
<button type="button" onclick="closeInternJournalModal()" class="px-5 py-2.5 bg-slate-800 hover:bg-slate-900 text-white font-bold rounded-xl text-xs transition-colors shadow-md cursor-pointer">Kapat</button>
</div>
</div>
</div>
@push('styles')
<style>
.admin-tab-btn {
transition: all 0.2s ease-in-out;
}
.admin-tab-btn:hover:not(.active) {
background-color: #f8fafc;
}
.admin-tab-btn.active {
background-color: #eff6ff;
border-color: #dbeafe;
color: #1e40af !important;
}
</style>
@endpush
@push('scripts')
<script>
let currentInternId = null;
let journalEntries = [];
let activeSlideIndex = 0;
let isUpdatingSignature = false;
let isUpdatingDayApproval = false;
function openInternJournalModal(internId) {
currentInternId = internId;
activeSlideIndex = 0;
const modal = document.getElementById('intern-journal-modal');
if (!modal) return;
modal.classList.remove('hidden');
modal.classList.add('flex');
// Animate open
const card = modal.querySelector('.max-w-4xl');
if (card) {
setTimeout(() => {
card.classList.remove('scale-95', 'opacity-0');
card.classList.add('scale-100', 'opacity-100');
}, 50);
}
loadInternJournalDetails(internId);
}
function closeInternJournalModal() {
const modal = document.getElementById('intern-journal-modal');
if (!modal) return;
const card = modal.querySelector('.max-w-4xl');
if (card) {
card.classList.remove('scale-100', 'opacity-100');
card.classList.add('scale-95', 'opacity-0');
}
setTimeout(() => {
modal.classList.add('hidden');
modal.classList.remove('flex');
}, 200);
}
function loadInternJournalDetails(internId) {
const slideContent = document.getElementById('ijm-slide-content');
if (slideContent) {
slideContent.innerHTML = `
<div class="flex items-center justify-center p-12">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
</div>
`;
}
fetch(`/stajyer/admin/journal-details?intern_id=${internId}`)
.then(res => res.json())
.then(data => {
if (!data.success) {
alert(data.message || 'Veriler yüklenemedi.');
closeInternJournalModal();
return;
}
// Set Header details
const nameEl = document.getElementById('ijm-name');
if (nameEl) nameEl.textContent = data.intern.name;
let startF = data.intern.start_date ? formatDateStr(data.intern.start_date) : '-';
let endF = data.intern.end_date ? formatDateStr(data.intern.end_date) : '-';
const metaEl = document.getElementById('ijm-meta');
if (metaEl) metaEl.textContent = `${startF} - ${endF} (${data.intern.total_days} İş Günü)`;
// Setup Progress Bars
const fillPercent = data.intern.total_days > 0 ? (data.intern.filled_days / data.intern.total_days) * 100 : 0;
const fillTextEl = document.getElementById('ijm-fill-text');
if (fillTextEl) fillTextEl.textContent = `${data.intern.filled_days} / ${data.intern.total_days} Gün`;
const fillBarEl = document.getElementById('ijm-fill-progress');
if (fillBarEl) fillBarEl.style.width = `${fillPercent}%`;
// Approved days count
let approvedDaysCount = 0;
data.entries.forEach(e => {
if (e.filled && e.supervisor_approved) {
approvedDaysCount++;
}
});
const approvedPercent = data.intern.total_days > 0 ? (approvedDaysCount / data.intern.total_days) * 100 : 0;
const appTextEl = document.getElementById('ijm-approved-text');
if (appTextEl) appTextEl.textContent = `${approvedDaysCount} / ${data.intern.total_days} Gün`;
const appBarEl = document.getElementById('ijm-approved-progress');
if (appBarEl) appBarEl.style.width = `${approvedPercent}%`;
// Setup Signatures
updateSignatureUI('supervisor', data.intern.notebook_supervisor_signed, data.intern.notebook_supervisor_name);
updateSignatureUI('unit', data.intern.notebook_unit_signed, data.intern.notebook_unit_name);
updateSignatureUI('approved', data.intern.notebook_approved, null);
// Setup carousel slide data
journalEntries = data.entries;
// Setup dropdown
const select = document.getElementById('ijm-day-select');
if (select) {
select.innerHTML = '';
journalEntries.forEach((entry, idx) => {
const opt = document.createElement('option');
opt.value = idx;
opt.textContent = `${entry.day_number}. Gün (${entry.formatted_date})` + (entry.filled ? ' [DOLU]' : ' [BOŞ]');
select.appendChild(opt);
});
}
// Set total indicator text
const indEl = document.getElementById('ijm-day-indicator');
if (indEl) indEl.textContent = `Gün: 1 / ${journalEntries.length}`;
// Render first slide
renderSlide(0);
})
.catch(err => {
console.error(err);
alert('Staj detayları yüklenirken bir hata oluştu.');
closeInternJournalModal();
});
}
function formatDateStr(dateStr) {
if (!dateStr) return '';
const parts = dateStr.split('-');
if (parts.length === 3) {
return `${parts[2]}.${parts[1]}.${parts[0]}`;
}
return dateStr;
}
function updateSignatureUI(type, signed, name) {
const btn = document.getElementById(`ijm-btn-${type}`);
const label = document.getElementById(`ijm-text-${type}`);
if (!btn || !label) return;
if (type === 'supervisor') {
if (signed) {
btn.textContent = "İmzayı Kaldır";
btn.className = "px-2.5 py-1 text-[10px] font-extrabold uppercase rounded-lg border border-rose-200 bg-rose-50 text-rose-600 hover:bg-rose-100 transition-all cursor-pointer";
label.innerHTML = `<span class="text-green-600 font-extrabold"><i class="uil uil-check-circle mr-0.5"></i>İmzaladı: ${name || ''}</span>`;
} else {
btn.textContent = "İmzala";
btn.className = "px-2.5 py-1 text-[10px] font-extrabold uppercase rounded-lg border border-indigo-200 bg-indigo-50 text-indigo-600 hover:bg-indigo-100 transition-all cursor-pointer";
label.textContent = "İmzalanmadı";
}
} else if (type === 'unit') {
if (signed) {
btn.textContent = "İmzayı Kaldır";
btn.className = "px-2.5 py-1 text-[10px] font-extrabold uppercase rounded-lg border border-rose-200 bg-rose-50 text-rose-600 hover:bg-rose-100 transition-all cursor-pointer";
label.innerHTML = `<span class="text-green-600 font-extrabold"><i class="uil uil-check-circle mr-0.5"></i>İmzaladı: ${name || ''}</span>`;
} else {
btn.textContent = "İmzala";
btn.className = "px-2.5 py-1 text-[10px] font-extrabold uppercase rounded-lg border border-indigo-200 bg-indigo-50 text-indigo-600 hover:bg-indigo-100 transition-all cursor-pointer";
label.textContent = "İmzalanmadı";
}
} else if (type === 'approved') {
if (signed) {
btn.textContent = "Onayı Kaldır";
btn.className = "px-2.5 py-1 text-[10px] font-extrabold uppercase rounded-lg border border-rose-200 bg-rose-50 text-rose-600 hover:bg-rose-100 transition-all cursor-pointer";
label.innerHTML = `<span class="text-green-600 font-extrabold"><i class="uil uil-check-circle mr-0.5"></i>Defter Onaylandı</span>`;
} else {
btn.textContent = "Onayla";
btn.className = "px-2.5 py-1 text-[10px] font-extrabold uppercase rounded-lg border border-emerald-200 bg-emerald-50 text-emerald-600 hover:bg-emerald-100 transition-all cursor-pointer";
label.textContent = "Onaylanmadı";
}
}
}
function toggleNotebookSignature(type) {
if (isUpdatingSignature) return;
// Get current state
const btn = document.getElementById(`ijm-btn-${type}`);
if (!btn) return;
const isSignedCurrently = btn.textContent.includes('Kaldır');
const newSignState = !isSignedCurrently;
let promptName = '';
if (newSignState && (type === 'supervisor' || type === 'unit')) {
promptName = prompt("İmzalayan yetkili ismini giriniz veya onaylayınız:", @json(auth()->user()->name));
if (promptName === null) return; // cancelled
if (promptName.trim() === '') {
promptName = @json(auth()->user()->name);
}
}
isUpdatingSignature = true;
btn.style.opacity = '0.5';
fetch('/stajyer/admin/toggle-notebook-signature', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
body: JSON.stringify({
intern_id: currentInternId,
type: type,
signed: newSignState ? 1 : 0,
name: promptName
})
})
.then(res => res.json())
.then(data => {
if (data.success) {
const key = type === 'supervisor' ? 'notebook_supervisor_signed' : (type === 'unit' ? 'notebook_unit_signed' : 'notebook_approved');
const nameKey = type === 'supervisor' ? 'notebook_supervisor_name' : (type === 'unit' ? 'notebook_unit_name' : null);
updateSignatureUI(type, data.intern[key], data.intern[nameKey]);
} else {
alert(data.message || 'Hata oluştu.');
}
})
.catch(err => {
console.error(err);
alert('İşlem gerçekleştirilemedi.');
})
.finally(() => {
isUpdatingSignature = false;
btn.style.opacity = '1';
});
}
function renderSlide(index) {
if (index < 0 || index >= journalEntries.length) return;
activeSlideIndex = index;
const entry = journalEntries[index];
// Update indicator & select dropdown
const indEl = document.getElementById('ijm-day-indicator');
if (indEl) indEl.textContent = `Gün: ${index + 1} / ${journalEntries.length}`;
const selEl = document.getElementById('ijm-day-select');
if (selEl) selEl.value = index;
// Title & Date
const titleEl = document.getElementById('ijm-slide-title');
if (titleEl) titleEl.textContent = `${entry.day_number}. Gün Raporu`;
const dateEl = document.getElementById('ijm-slide-date');
if (dateEl) dateEl.textContent = entry.formatted_date;
// Retroactive badge
const retroBadge = document.getElementById('ijm-slide-retroactive');
if (retroBadge) {
retroBadge.innerHTML = '';
if (entry.filled && entry.is_retroactive) {
retroBadge.innerHTML = `
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-rose-50 text-rose-700 text-[10px] font-extrabold uppercase border border-rose-100">
<span class="w-1.5 h-1.5 rounded-full bg-rose-500 animate-pulse"></span>
Geriye Dönük
</span>
`;
}
}
// Content area
const contentArea = document.getElementById('ijm-slide-content');
const badgeDiv = document.getElementById('ijm-slide-status-badge');
const actionBtn = document.getElementById('ijm-slide-action-btn');
if (!contentArea || !badgeDiv || !actionBtn) return;
if (!entry.filled) {
contentArea.innerHTML = `
<div class="flex flex-col items-center justify-center p-8 text-center bg-slate-50 rounded-2xl border border-dashed border-slate-200">
<i class="uil uil-file-slash text-3xl text-slate-400 mb-2"></i>
<p class="text-sm font-medium text-slate-500">Bu gün için henüz staj raporu yazılmamıştır.</p>
</div>
`;
badgeDiv.innerHTML = `<span class="text-xs text-slate-400 font-semibold">Boş Rapor</span>`;
actionBtn.classList.add('hidden');
} else {
actionBtn.classList.remove('hidden');
const entryContent = entry.content || '<p class="text-slate-400 italic">Boş içerik.</p>';
contentArea.innerHTML = `<div class="rich-text-content prose max-w-none text-slate-700 leading-relaxed text-sm select-text">${entryContent}</div>`;
updateDayApprovalUI(entry.supervisor_approved, entry.supervisor_name);
}
}
function updateDayApprovalUI(approved, name) {
const badgeDiv = document.getElementById('ijm-slide-status-badge');
const actionBtn = document.getElementById('ijm-slide-action-btn');
if (!badgeDiv || !actionBtn) return;
if (approved) {
badgeDiv.innerHTML = `
<span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-emerald-50 text-emerald-700 text-xs font-bold border border-emerald-100">
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
Sorumlu Onayladı ${name ? `(${name})` : ''}
</span>
`;
actionBtn.textContent = "Onayı Kaldır";
actionBtn.className = "px-4 py-2 text-white bg-rose-600 hover:bg-rose-700 rounded-xl font-bold text-xs shadow-lg shadow-rose-500/20 transition-all cursor-pointer";
} else {
badgeDiv.innerHTML = `
<span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-slate-100 text-slate-600 text-xs font-bold border border-slate-200">
Onay Bekliyor
</span>
`;
actionBtn.textContent = "Günü Onayla";
actionBtn.className = "px-4 py-2 text-white bg-emerald-600 hover:bg-emerald-700 rounded-xl font-bold text-xs shadow-lg shadow-emerald-500/20 transition-all cursor-pointer";
}
}
function toggleActiveDayApproval() {
if (isUpdatingDayApproval) return;
const entry = journalEntries[activeSlideIndex];
if (!entry || !entry.entry_id) return;
const actionBtn = document.getElementById('ijm-slide-action-btn');
if (!actionBtn) return;
isUpdatingDayApproval = true;
actionBtn.style.opacity = '0.5';
fetch('/stajyer/admin/toggle-approval', {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-TOKEN": "{{ csrf_token() }}"
},
body: JSON.stringify({
entry_id: entry.entry_id
})
})
.then(res => res.json())
.then(data => {
if (data.success) {
// Update local object
entry.supervisor_approved = data.status;
entry.supervisor_name = data.supervisor_name;
// Update UI
updateDayApprovalUI(data.status, data.supervisor_name);
// Recalculate and update approved progress bar
let approvedDaysCount = 0;
journalEntries.forEach(e => {
if (e.filled && e.supervisor_approved) {
approvedDaysCount++;
}
});
const approvedPercent = journalEntries.length > 0 ? (approvedDaysCount / journalEntries.length) * 100 : 0;
const appTextEl = document.getElementById('ijm-approved-text');
if (appTextEl) appTextEl.textContent = `${approvedDaysCount} / ${journalEntries.length} Gün`;
const appBarEl = document.getElementById('ijm-approved-progress');
if (appBarEl) appBarEl.style.width = `${approvedPercent}%`;
} else {
alert(data.message || "Onay güncellenemedi.");
}
})
.catch(err => {
console.error(err);
alert("İşlem sırasında bir hata oluştu.");
})
.finally(() => {
isUpdatingDayApproval = false;
actionBtn.style.opacity = '1';
});
}
function prevSlide() {
if (activeSlideIndex > 0) {
renderSlide(activeSlideIndex - 1);
}
}
function nextSlide() {
if (activeSlideIndex < journalEntries.length - 1) {
renderSlide(activeSlideIndex + 1);
}
}
function goToSlide(idx) {
renderSlide(parseInt(idx));
}
// Admin Tab Switch Logic
document.addEventListener('DOMContentLoaded', function() {
const adminTabButtons = document.querySelectorAll('.admin-tab-btn');
const adminTabPanels = document.querySelectorAll('.admin-tab-panel');
adminTabButtons.forEach(button => {
button.addEventListener('click', () => {
// Deactivate all buttons
adminTabButtons.forEach(btn => {
btn.classList.remove('active', 'bg-blue-50', 'border-blue-100', 'text-blue-900');
btn.classList.add('text-slate-600', 'bg-transparent', 'border-transparent');
btn.setAttribute('aria-selected', 'false');
});
// Hide all panels
adminTabPanels.forEach(panel => {
panel.classList.add('hidden');
});
// Activate clicked button
button.classList.add('active', 'bg-blue-50', 'border-blue-100', 'text-blue-900');
button.classList.remove('text-slate-600', 'bg-transparent', 'border-transparent');
button.setAttribute('aria-selected', 'true');
// Show target panel
const targetId = button.getAttribute('data-tab-target');
const targetPanel = document.getElementById(targetId + '-panel');
if (targetPanel) {
targetPanel.classList.remove('hidden');
// Re-render DevExtreme Gantt chart if visible, to prevent rendering scale bugs
if (targetId === 'gantt-chart') {
const ganttEl = document.getElementById('gantt');
if (ganttEl) {
const ganttInstance = $(ganttEl).dxGantt('instance');
if (ganttInstance) {
ganttInstance.repaint();
}
}
}
}
});
});
});
</script>
@endpush
@endsection