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

807 lines
43 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-4xl mx-auto">
<!-- Top header / Welcome card -->
<div class="bg-white rounded-3xl p-6 md:p-8 shadow-xl border border-slate-100/50 flex flex-col md:flex-row justify-between items-start md:items-center gap-6 mb-8">
<div>
<span class="text-xs uppercase font-extrabold tracking-widest text-[#e31e24] bg-red-50 px-3 py-1.5 rounded-full">Stajyer Paneli</span>
<h1 class="text-3xl font-extrabold text-slate-900 tracking-tight mt-3">Hoş Geldiniz, {{ $intern->name }}</h1>
<p class="text-sm text-slate-500 mt-1">Staj belgelerinizi ve başvuru detaylarınızı buradan yönetebilirsiniz.</p>
</div>
<form action="{{ route('intern.logout') }}" method="POST">
@csrf
<button type="submit" class="px-5 py-3 rounded-xl bg-slate-100 hover:bg-red-50 text-slate-600 hover:text-[#e31e24] font-bold text-sm transition-all flex items-center gap-2 border border-slate-200/50 hover:border-red-100">
<i class="uil uil-sign-out-alt text-lg"></i>
<span>Çıkış Yap</span>
</button>
</form>
</div>
<!-- Session & Validation Alerts -->
@if(session('success'))
<div class="bg-green-50 border border-green-200 text-green-700 px-6 py-4 rounded-3xl mb-8 flex items-center gap-3 shadow-sm">
<i class="uil uil-check-circle text-2xl flex-shrink-0"></i>
<span class="font-bold text-sm">{{ session('success') }}</span>
</div>
@endif
@if(session('error'))
<div class="bg-red-50 border border-red-200 text-[#e31e24] px-6 py-4 rounded-3xl mb-8 flex items-center gap-3 shadow-sm">
<i class="uil uil-exclamation-octagon text-2xl flex-shrink-0"></i>
<span class="font-bold text-sm">{{ session('error') }}</span>
</div>
@endif
@if($errors->any())
<div class="bg-red-50 border border-red-200 text-[#e31e24] px-6 py-4 rounded-3xl mb-8 shadow-sm">
<div class="flex items-center gap-3 mb-2">
<i class="uil uil-exclamation-octagon text-2xl flex-shrink-0"></i>
<span class="font-bold text-sm">Lütfen aşağıdaki hataları düzeltin:</span>
</div>
<ul class="list-disc list-inside text-xs font-semibold space-y-1 ml-1">
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Application Info & Document Download Grid -->
<div class="grid grid-cols-1 md:grid-cols-12 gap-8">
<!-- Sidebar stats / statuses / tabs -->
<div class="md:col-span-4 space-y-6">
<div class="bg-white rounded-3xl p-4 shadow-xl border border-slate-100/50">
<h3 class="font-bold text-slate-800 text-base mb-4 px-3 pb-2 border-b border-slate-100">Menü</h3>
<div class="space-y-1" role="tablist">
<!-- Menu Item 1: Kişisel Bilgileriniz -->
<button type="button" role="tab" aria-selected="true" data-tab-target="personal-info" class="tab-btn active w-full flex items-center gap-4 p-3 rounded-2xl text-left transition-all border border-transparent">
<div class="w-10 h-10 rounded-xl bg-blue-50 text-blue-600 flex items-center justify-center text-xl flex-shrink-0 tab-icon">
<i class="uil uil-user"></i>
</div>
<div class="flex-grow">
<span class="block text-sm font-extrabold text-slate-800">Kişisel Bilgiler</span>
<span class="block text-xs text-slate-400 font-semibold mt-0.5">Başvuru detaylarınız</span>
</div>
</button>
<!-- Menu Item 2: Belgeleriniz -->
<button type="button" role="tab" aria-selected="false" data-tab-target="documents" class="tab-btn w-full flex items-center gap-4 p-3 rounded-2xl text-left transition-all border border-transparent">
<div class="w-10 h-10 rounded-xl bg-slate-50 text-slate-500 flex items-center justify-center text-xl flex-shrink-0 tab-icon">
<i class="uil uil-file-alt"></i>
</div>
<div class="flex-grow">
<span class="block text-sm font-extrabold text-slate-800">Belgeleriniz</span>
<span class="block text-xs text-slate-400 font-semibold mt-0.5">CV ve staj formları</span>
</div>
</button>
<!-- Menu Item 3: Staj Günlüğü -->
<button type="button" role="tab" aria-selected="false" data-tab-target="journal" class="tab-btn w-full flex items-center gap-4 p-3 rounded-2xl text-left transition-all border border-transparent">
<div class="w-10 h-10 rounded-xl bg-slate-50 text-slate-500 flex items-center justify-center text-xl flex-shrink-0 tab-icon">
<i class="uil uil-github"></i>
</div>
<div class="flex-grow">
<span class="block text-sm font-extrabold text-slate-800">Staj Günlüğü</span>
<span class="block text-xs text-slate-400 font-semibold mt-0.5">GitHub commit geçmişi</span>
</div>
</button>
</div>
</div>
</div>
<!-- Content Panels -->
<div class="md:col-span-8">
<!-- Panel 1: Kişisel Bilgileriniz -->
<div id="personal-info-panel" class="tab-panel space-y-6">
<div class="bg-white rounded-3xl p-6 md:p-8 shadow-xl border border-slate-100/50">
<h3 class="font-bold text-slate-800 text-lg mb-6 pb-2 border-b border-slate-100">Kişisel Bilgileriniz</h3>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
<div>
<span class="text-xs text-slate-400 font-extrabold uppercase tracking-wider block">E-posta</span>
<span class="text-sm font-bold text-slate-700 block mt-1.5">{{ $intern->email }}</span>
</div>
@if($intern->phone)
<div>
<span class="text-xs text-slate-400 font-extrabold uppercase tracking-wider block">Telefon</span>
<span class="text-sm font-bold text-slate-700 block mt-1.5">{{ $intern->phone }}</span>
</div>
@endif
<div>
<span class="text-xs text-slate-400 font-extrabold uppercase tracking-wider block">Staj Durumu</span>
<div class="mt-2">
<span class="inline-flex px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider
@if($intern->status === 'accepted') bg-green-50 text-green-700 border border-green-200
@elseif($intern->status === 'rejected') bg-red-50 text-red-700 border border-red-200
@elseif($intern->status === 'reviewed') bg-blue-50 text-blue-700 border border-blue-200
@elseif($intern->status === 'waiting_document') bg-amber-50 text-amber-700 border border-amber-200
@else bg-slate-50 text-slate-500 border border-slate-200 @endif">
@if($intern->status === 'accepted') Kabul Edildi
@elseif($intern->status === 'rejected') Reddedildi
@elseif($intern->status === 'reviewed') İncelendi
@elseif($intern->status === 'waiting_document') Belge Bekleniyor
@else Beklemede @endif
</span>
</div>
</div>
@if($intern->internship_total_days)
<div>
<span class="text-xs text-slate-400 font-extrabold uppercase tracking-wider block">Toplam Süre</span>
<span class="text-sm font-bold text-blue-600 block mt-1.5">{{ $intern->internship_total_days }} İş Günü <span class="text-xs text-slate-400 font-normal">(Haftada 5 Gün)</span></span>
</div>
@endif
@if($intern->internship_start_date)
<div>
<span class="text-xs text-slate-400 font-extrabold uppercase tracking-wider block">Staj Başlangıç Tarihi</span>
<span class="text-sm font-bold text-slate-700 block mt-1.5">{{ \Carbon\Carbon::parse($intern->internship_start_date)->format('d.m.Y') }}</span>
</div>
@endif
@if($intern->internship_end_date)
<div>
<span class="text-xs text-slate-400 font-extrabold uppercase tracking-wider block">Staj Bitiş Tarihi</span>
<span class="text-sm font-bold text-slate-700 block mt-1.5">{{ \Carbon\Carbon::parse($intern->internship_end_date)->format('d.m.Y') }}</span>
</div>
@endif
</div>
</div>
</div>
<!-- Panel 2: Belgeleriniz -->
<div id="documents-panel" class="tab-panel hidden space-y-6">
<div class="bg-white rounded-3xl p-6 md:p-8 shadow-xl border border-slate-100/50">
<h3 class="font-bold text-slate-800 text-lg mb-6 pb-2 border-b border-slate-100">Belgeleriniz</h3>
<div class="space-y-6">
<!-- CV Card -->
<div class="p-5 rounded-2xl border border-slate-100 bg-slate-50/50 flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 hover:border-slate-200 transition-all">
<div class="flex items-center gap-4">
<div class="w-12 h-12 rounded-xl bg-red-50 text-[#e31e24] flex items-center justify-center text-2xl flex-shrink-0">
<i class="uil uil-file-alt"></i>
</div>
<div>
<h4 class="font-bold text-slate-800 text-base">Özgeçmiş (CV)</h4>
<p class="text-xs text-slate-400 mt-0.5">Başvuru sırasında yüklemiş olduğunuz özgeçmiş belgeniz.</p>
</div>
</div>
@if($intern->cv_path)
<a href="{{ Storage::disk('public')->url($intern->cv_path) }}" target="_blank" class="w-full sm:w-auto px-5 py-2.5 bg-slate-800 hover:bg-slate-900 text-white font-bold rounded-xl text-sm transition-all flex items-center justify-center gap-2 shadow-md">
<i class="uil uil-arrow-down-tray"></i>
<span>İndir</span>
</a>
@else
<span class="text-xs text-slate-400 italic">Yüklenmemiş</span>
@endif
</div>
<!-- Intern Upload: To Be Signed Form Card -->
<div class="p-5 rounded-2xl border border-slate-100 bg-slate-50/50 hover:border-slate-200 transition-all">
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-4">
<div class="flex items-center gap-4">
<div class="w-12 h-12 rounded-xl bg-blue-50 text-blue-600 flex items-center justify-center text-2xl flex-shrink-0">
<i class="uil uil-file-upload-alt"></i>
</div>
<div>
<h4 class="font-bold text-slate-800 text-base">İmzalanacak Staj Formu</h4>
@if($intern->to_be_signed_internship_form_path)
<p class="text-xs text-green-600 font-semibold mt-0.5">Staj formunuz başarıyla yüklendi. İmza işlemleri için hazır.</p>
@else
<p class="text-xs text-slate-400 mt-0.5">İmzalanmasını istediğiniz staj formunu buradan yükleyebilirsiniz.</p>
@endif
</div>
</div>
<div class="flex items-center gap-2 w-full sm:w-auto">
@if($intern->to_be_signed_internship_form_path)
<a href="{{ Storage::disk('public')->url($intern->to_be_signed_internship_form_path) }}" target="_blank" class="px-4 py-2.5 bg-slate-850 hover:bg-slate-900 text-white font-bold rounded-xl text-xs transition-all flex items-center justify-center gap-1.5 shadow-sm">
<i class="uil uil-arrow-down-tray"></i>
<span>Görüntüle</span>
</a>
<button type="button" onclick="document.getElementById('upload-form-wrapper').classList.toggle('hidden')" class="px-4 py-2.5 bg-blue-50 hover:bg-blue-100 text-blue-600 font-bold rounded-xl text-xs transition-all flex items-center justify-center gap-1.5">
<i class="uil uil-edit"></i>
<span>Değiştir</span>
</button>
@else
<button type="button" onclick="document.getElementById('upload-form-wrapper').classList.toggle('hidden')" class="w-full sm:w-auto px-5 py-2.5 bg-blue-600 hover:bg-blue-700 text-white font-bold rounded-xl text-sm transition-all flex items-center justify-center gap-2 shadow-md shadow-blue-500/10">
<i class="uil uil-plus"></i>
<span>Yükle</span>
</button>
@endif
</div>
</div>
<!-- Form Upload Dropzone Area -->
<div id="upload-form-wrapper" class="{{ $intern->to_be_signed_internship_form_path ? 'hidden' : '' }} mt-4 border-t border-slate-100 pt-4">
<form action="{{ route('intern.upload-form') }}" method="POST" enctype="multipart/form-data" class="space-y-4">
@csrf
<!-- Company Legal Info Copy Box -->
<div class="bg-slate-50 border border-slate-200/60 rounded-2xl p-5 text-sm text-slate-600">
<div class="flex items-center gap-2 mb-3">
<i class="uil uil-info-circle text-blue-600 text-lg flex-shrink-0"></i>
<h5 class="font-extrabold text-slate-800 text-sm tracking-tight">Şirket Legal Bilgilerimiz</h5>
</div>
<p class="text-xs text-slate-400 mb-4 leading-normal">
Lütfen staj formunuzu doldururken şirketimize ait aşağıdaki resmi bilgileri kullanın. Sağdaki kopyalama butonlarını kullanarak bilgileri kolayca kopyalayabilirsiniz.
</p>
<div class="space-y-2.5">
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2 bg-white px-3 py-2 rounded-xl border border-slate-100/80">
<span class="text-xs text-slate-400 font-bold sm:w-1/4">Şirket Unvanı</span>
<div class="flex items-center justify-between sm:w-3/4 w-full gap-2">
<span id="legal-title" class="text-xs font-bold text-slate-700 select-all break-all">TRUNÇGİL TEKNOLOJİ SANAYİ VE TİCARET LİMİTED ŞİRKETİ</span>
<button type="button" onclick="copyToClipboard('legal-title', this)" class="text-slate-400 hover:text-blue-600 transition-colors p-1 flex-shrink-0" title="Kopyala">
<i class="uil uil-copy text-sm"></i>
</button>
</div>
</div>
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2 bg-white px-3 py-2 rounded-xl border border-slate-100/80">
<span class="text-xs text-slate-400 font-bold sm:w-1/4">Adres</span>
<div class="flex items-center justify-between sm:w-3/4 w-full gap-2">
<span id="legal-address" class="text-xs font-bold text-slate-700 select-all break-all">Çamtepe Mah. Mahmut Tevfik Atay Bul. Gaziantep Teknopark No: 4A İç Kapı No: 1 Şahinbey / Gaziantep</span>
<button type="button" onclick="copyToClipboard('legal-address', this)" class="text-slate-400 hover:text-blue-600 transition-colors p-1 flex-shrink-0" title="Kopyala">
<i class="uil uil-copy text-sm"></i>
</button>
</div>
</div>
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2 bg-white px-3 py-2 rounded-xl border border-slate-100/80">
<span class="text-xs text-slate-400 font-bold sm:w-1/4">Vergi Dairesi & No</span>
<div class="flex items-center justify-between sm:w-3/4 w-full gap-2">
<span id="legal-tax" class="text-xs font-bold text-slate-700 select-all break-all">Şahinbey V.D. / 8591492435</span>
<button type="button" onclick="copyToClipboard('legal-tax', this)" class="text-slate-400 hover:text-blue-600 transition-colors p-1 flex-shrink-0" title="Kopyala">
<i class="uil uil-copy text-sm"></i>
</button>
</div>
</div>
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2 bg-white px-3 py-2 rounded-xl border border-slate-100/80">
<span class="text-xs text-slate-400 font-bold sm:w-1/4">MERSİS No</span>
<div class="flex items-center justify-between sm:w-3/4 w-full gap-2">
<span id="legal-mersis" class="text-xs font-bold text-slate-700 select-all break-all">0859149243500001</span>
<button type="button" onclick="copyToClipboard('legal-mersis', this)" class="text-slate-400 hover:text-blue-600 transition-colors p-1 flex-shrink-0" title="Kopyala">
<i class="uil uil-copy text-sm"></i>
</button>
</div>
</div>
</div>
</div>
<div class="space-y-4">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label for="internship_start_date" class="block text-xs font-extrabold text-slate-500 uppercase tracking-wider mb-1.5">Staj Başlangıç Tarihi</label>
<input type="date" name="internship_start_date" id="internship_start_date" onchange="calculateEndDateFrontend()" oninput="calculateEndDateFrontend()" required value="{{ $intern->internship_start_date }}" class="w-full px-4 py-3 rounded-xl border border-slate-200 focus:border-blue-400 focus:ring-1 focus:ring-blue-400 focus:outline-none text-sm font-semibold text-slate-700 bg-white transition-all" />
</div>
<div>
<label for="internship_total_days" class="block text-xs font-extrabold text-slate-500 uppercase tracking-wider mb-1.5">Staj Süresi (İş Günü)</label>
<input type="number" name="internship_total_days" id="internship_total_days" onchange="calculateEndDateFrontend()" oninput="calculateEndDateFrontend()" min="1" required value="{{ $intern->internship_total_days }}" placeholder="Örn: 20" class="w-full px-4 py-3 rounded-xl border border-slate-200 focus:border-blue-400 focus:ring-1 focus:ring-blue-400 focus:outline-none text-sm font-semibold text-slate-700 bg-white transition-all" />
</div>
</div>
<div>
<label for="internship_end_date" class="block text-xs font-extrabold text-slate-500 uppercase tracking-wider mb-1.5">Staj Bitiş Tarihi (Otomatik)</label>
<input type="date" name="internship_end_date" id="internship_end_date" readonly class="w-full px-4 py-3 rounded-xl border border-slate-200 bg-slate-50 text-slate-500 cursor-not-allowed focus:outline-none text-sm font-semibold transition-all" value="{{ $intern->internship_end_date }}" />
</div>
</div>
<div class="relative border-2 border-dashed border-slate-200 hover:border-blue-400 rounded-2xl p-6 transition-all bg-white flex flex-col items-center justify-center text-center cursor-pointer group">
<input type="file" name="internship_form" id="internship_form" accept=".pdf,.docx,.jpg,.png,.jpeg" onchange="handleFileSelected(this)" class="absolute inset-0 w-full h-full opacity-0 cursor-pointer z-10" />
<i class="uil uil-cloud-upload text-4xl text-slate-400 group-hover:text-blue-500 transition-colors mb-2"></i>
<p class="text-sm font-bold text-slate-700">Dosya Seçin veya Sürükleyin</p>
<p class="text-xs text-slate-400 mt-1">PDF, DOCX, JPG veya PNG (Maks. 50MB)</p>
<p id="selected-file-name" class="text-xs font-bold text-blue-600 mt-3"></p>
</div>
<div class="flex justify-end">
<button type="submit" id="submit-upload-btn" disabled class="px-6 py-2.5 bg-blue-600 hover:bg-blue-700 text-white font-bold rounded-xl text-sm transition-all flex items-center gap-2 opacity-50 cursor-not-allowed">
<i class="uil uil-check"></i>
<span>Dosyayı Kaydet</span>
</button>
</div>
</form>
</div>
</div>
<!-- Signed Internship Form Card -->
<div class="p-5 rounded-2xl border border-slate-100 bg-slate-50/50 flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 hover:border-slate-200 transition-all">
<div class="flex items-center gap-4">
<div class="w-12 h-12 rounded-xl @if($intern->signed_internship_form_path) bg-green-50 text-green-600 @else bg-amber-50 text-amber-600 @endif flex items-center justify-center text-2xl flex-shrink-0">
<i class="uil uil-file-check-alt"></i>
</div>
<div class="flex-grow">
<h4 class="font-bold text-slate-800 text-base">İmzalı Staj Formu</h4>
@if($intern->signed_internship_form_path)
<p class="text-xs text-slate-400 mt-0.5">Şirketimiz tarafından imzalanmış ve onaylanmış staj belgeniz.</p>
@else
<p class="text-xs text-amber-600/90 font-medium mt-0.5">Belgeniz imza aşamasındadır. Yöneticilerimiz tarafından onaylandığında buradan indirebilirsiniz.</p>
@endif
</div>
</div>
@if($intern->signed_internship_form_path)
<a href="{{ Storage::disk('public')->url($intern->signed_internship_form_path) }}" target="_blank" class="w-full sm:w-auto px-5 py-2.5 bg-[#e31e24] hover:bg-[#c4191f] text-white font-bold rounded-xl text-sm transition-all flex items-center justify-center gap-2 shadow-md shadow-red-500/10">
<i class="uil uil-arrow-down-tray"></i>
<span>İndir</span>
</a>
@else
<button disabled class="w-full sm:w-auto px-5 py-2.5 bg-slate-100 text-slate-400 font-bold rounded-xl text-sm cursor-not-allowed flex items-center justify-center gap-2 border border-slate-200/50">
<i class="uil uil-hourglass"></i>
<span>Bekleniyor</span>
</button>
@endif
</div>
</div>
</div>
</div>
<!-- Panel 3: Staj Günlüğü -->
<div id="journal-panel" class="tab-panel hidden space-y-6">
<div class="bg-white rounded-3xl p-6 md:p-8 shadow-xl border border-slate-100/50">
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-6 pb-4 border-b border-slate-100">
<div>
<h3 class="font-bold text-slate-800 text-lg">Staj Günlüğü</h3>
<p class="text-xs text-slate-400 mt-0.5">Public GitHub deponuzdaki commit geçmişi günlük olarak listelenir.</p>
</div>
@if($intern->github_repo)
<a href="{{ route('intern.download-journal') }}" class="w-full sm:w-auto px-4 py-2.5 bg-green-600 hover:bg-green-700 text-white font-bold rounded-xl text-xs transition-all flex items-center justify-center gap-2 shadow-md shadow-green-500/10">
<i class="uil uil-arrow-down-tray text-sm"></i>
<span>Günlüğü İndir (.md)</span>
</a>
@endif
</div>
<!-- GitHub Repository URL Configuration -->
<div class="p-5 rounded-2xl border border-slate-100 bg-slate-50/50 mb-6">
<form action="{{ route('intern.save-github') }}" method="POST" class="space-y-4">
@csrf
<div>
<label for="github_repo" class="block text-xs font-extrabold text-slate-500 uppercase tracking-wider mb-2">GitHub Public Depo URL'si</label>
<div class="flex flex-col sm:flex-row gap-3">
<input type="url" name="github_repo" id="github_repo" placeholder="https://github.com/kullaniciadi/depo-adi" value="{{ $intern->github_repo }}" required class="w-full px-4 py-3 rounded-xl border border-slate-200 focus:border-blue-400 focus:ring-1 focus:ring-blue-400 focus:outline-none text-sm font-semibold text-slate-700 bg-white transition-all" />
<button type="submit" class="px-5 py-3 bg-blue-600 hover:bg-blue-700 text-white font-bold rounded-xl text-sm transition-all shadow-md shadow-blue-500/10 flex-shrink-0">
{{ $intern->github_repo ? 'Güncelle' : 'Kaydet' }}
</button>
</div>
<span class="block text-xs text-slate-400 mt-2"><i class="uil uil-info-circle text-blue-600"></i> Deponuzun <strong>public (herkese açık)</strong> olması ve en az bir commit içermesi gerekmektedir.</span>
</div>
</form>
</div>
<!-- Commits timeline / history load wrapper -->
<div id="commits-loader" class="hidden py-8 flex flex-col items-center justify-center">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mb-2"></div>
<span class="text-xs text-slate-400 font-semibold">GitHub'dan commitler yükleniyor...</span>
</div>
<div id="commits-error" class="hidden p-4 rounded-xl bg-red-50 border border-red-200 text-[#e31e24] text-xs font-semibold">
</div>
<div id="commits-empty" class="hidden p-6 rounded-2xl border border-slate-100 text-center text-slate-400 italic text-sm">
Henüz hiç commit bulunamadı veya deponuz tanımlanmadı. Lütfen deponuzu tanımlayın ve commitlerinizi gönderin.
</div>
<!-- Day Paginator / Navbar -->
<div id="journal-carousel-nav" class="hidden flex items-center justify-between gap-4 p-3 bg-slate-50/80 border border-slate-100 rounded-2xl mb-6 select-none">
<button type="button" id="prev-day-btn" onclick="navigateDay(-1)" class="w-10 h-10 rounded-xl bg-white hover:bg-blue-50 text-slate-600 hover:text-blue-600 border border-slate-200/60 hover:border-blue-100 flex items-center justify-center transition-all shadow-sm">
<i class="uil uil-angle-left text-xl"></i>
</button>
<div class="flex-grow overflow-x-auto no-scrollbar py-1">
<div id="day-tabs-container" class="flex gap-2 justify-start sm:justify-center min-w-max px-2">
<!-- Day tabs rendered dynamically -->
</div>
</div>
<button type="button" id="next-day-btn" onclick="navigateDay(1)" class="w-10 h-10 rounded-xl bg-white hover:bg-blue-50 text-slate-600 hover:text-blue-600 border border-slate-200/60 hover:border-blue-100 flex items-center justify-center transition-all shadow-sm">
<i class="uil uil-angle-right text-xl"></i>
</button>
</div>
<!-- Day Content Timeline Container (Carousel View) -->
<div id="commits-timeline-container" class="hidden">
<div id="active-day-card" class="bg-white border border-slate-100/80 rounded-2xl p-6 shadow-sm transition-all duration-300 transform">
<!-- Active Day Details (Date / Day Title) -->
<div class="flex items-center justify-between mb-8 pb-4 border-b border-slate-100">
<div class="flex items-center gap-3">
<span id="active-day-title" class="text-base font-extrabold text-blue-600 bg-blue-50 px-4 py-1.5 rounded-full">1. Gün</span>
<span id="active-day-date" class="text-sm font-semibold text-slate-400"><i class="uil uil-calendar-alt mr-1"></i> 29.05.2026</span>
</div>
<span id="active-day-commit-count" class="text-xs font-bold text-slate-400 bg-slate-50 border border-slate-100 px-2.5 py-1 rounded-lg">3 Commit</span>
</div>
<!-- Timeline items list -->
<div class="relative pl-6 sm:pl-8 before:content-[''] before:absolute before:left-[11px] sm:before:left-[15px] before:top-2 before:bottom-2 before:w-[2px] before:bg-slate-100">
<div id="timeline-events" class="space-y-6">
<!-- Event items rendered dynamically -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
@push('styles')
<script src="https://cdn.tailwindcss.com"></script>
<script>
// Tab Switch Logic
document.addEventListener('DOMContentLoaded', function() {
const tabButtons = document.querySelectorAll('.tab-btn');
const tabPanels = document.querySelectorAll('.tab-panel');
tabButtons.forEach(button => {
button.addEventListener('click', () => {
// Deactivate active tab
tabButtons.forEach(btn => {
btn.classList.remove('active', 'bg-blue-50', 'border-blue-100', 'text-blue-900');
btn.classList.add('bg-transparent', 'border-transparent', 'text-slate-600');
btn.querySelector('.tab-icon').classList.remove('bg-blue-600', 'text-white');
btn.querySelector('.tab-icon').classList.add('bg-slate-50', 'text-slate-500');
btn.setAttribute('aria-selected', 'false');
});
// Hide active panels
tabPanels.forEach(panel => {
panel.classList.add('hidden');
});
// Activate clicked tab
button.classList.add('active', 'bg-blue-50', 'border-blue-100', 'text-blue-900');
button.classList.remove('bg-transparent', 'border-transparent', 'text-slate-600');
button.querySelector('.tab-icon').classList.add('bg-blue-600', 'text-white');
button.querySelector('.tab-icon').classList.remove('bg-slate-50', 'text-slate-500');
button.setAttribute('aria-selected', 'true');
// Show targets panel
const targetId = button.getAttribute('data-tab-target');
const targetPanel = document.getElementById(targetId + '-panel');
if (targetPanel) {
targetPanel.classList.remove('hidden');
}
// If journal is selected, trigger GitHub commits loading
if (targetId === 'journal') {
loadGithubCommits();
}
});
});
// Handle initial state of date logic
calculateEndDateFrontend();
});
const githubRepoUrl = @json($intern->github_repo);
let commitDays = [];
let activeDayIndex = 0;
function loadGithubCommits() {
const loader = document.getElementById('commits-loader');
const errorEl = document.getElementById('commits-error');
const emptyEl = document.getElementById('commits-empty');
const navEl = document.getElementById('journal-carousel-nav');
const containerEl = document.getElementById('commits-timeline-container');
if (!githubRepoUrl) {
emptyEl.classList.remove('hidden');
return;
}
loader.classList.remove('hidden');
errorEl.classList.add('hidden');
emptyEl.classList.add('hidden');
navEl.classList.add('hidden');
containerEl.classList.add('hidden');
commitDays = [];
// Parse owner and repo
let repoClean = githubRepoUrl.replace(/https?:\/\/(www\.)?github\.com\//i, '');
repoClean = repoClean.replace(/\/$/, '');
const parts = repoClean.split('/');
if (parts.length < 2) {
loader.classList.add('hidden');
errorEl.textContent = 'Github depo URL\'si çözümlenemedi. Geçerli format: https://github.com/kullanici/depo';
errorEl.classList.remove('hidden');
return;
}
const owner = parts[0];
const repo = parts[1].replace(/\.git$/i, '');
fetch(`https://api.github.com/repos/${owner}/${repo}/commits?per_page=100`)
.then(response => {
if (!response.ok) {
if (response.status === 404) {
throw new Error('Depo bulunamadı veya private (gizli). Deponuzun public (herkese açık) olduğundan emin olun.');
} else if (response.status === 403) {
throw new Error('GitHub API istek limiti aşıldı. Lütfen daha sonra tekrar deneyin veya yukarıdaki indirme butonunu kullanın.');
} else {
throw new Error('GitHub API hatası: ' + response.statusText);
}
}
return response.json();
})
.then(commits => {
loader.classList.add('hidden');
if (!Array.isArray(commits) || commits.length === 0) {
emptyEl.classList.remove('hidden');
return;
}
// Reverse to show in chronological order (Day 1, Day 2...)
commits.reverse();
// Group commits by date (YYYY-MM-DD)
const grouped = {};
commits.forEach(item => {
const dateStr = item.commit.author.date;
if (dateStr) {
const dateOnly = dateStr.substring(0, 10); // "YYYY-MM-DD"
if (!grouped[dateOnly]) {
grouped[dateOnly] = [];
}
grouped[dateOnly].push(item);
}
});
const sortedDates = Object.keys(grouped).sort();
commitDays = sortedDates.map((date, index) => {
const dateParts = date.split('-');
return {
date: date,
dayNum: index + 1,
formattedDate: `${dateParts[2]}.${dateParts[1]}.${dateParts[0]}`,
commits: grouped[date]
};
});
if (commitDays.length === 0) {
emptyEl.classList.remove('hidden');
return;
}
activeDayIndex = 0;
navEl.classList.remove('hidden');
containerEl.classList.remove('hidden');
renderDayTabs();
renderActiveDay();
})
.catch(err => {
loader.classList.add('hidden');
errorEl.textContent = err.message || 'Bir hata oluştu.';
errorEl.classList.remove('hidden');
});
}
function renderDayTabs() {
const container = document.getElementById('day-tabs-container');
container.innerHTML = '';
commitDays.forEach((day, index) => {
const isActive = index === activeDayIndex;
const activeClass = isActive
? 'text-blue-700 bg-blue-50 border border-blue-200 font-extrabold shadow-sm'
: 'bg-white hover:bg-slate-50 text-slate-600 border border-slate-200/60 font-semibold hover:text-blue-600';
const tab = document.createElement('button');
tab.type = 'button';
tab.className = `px-5 py-2 rounded-xl transition-all flex flex-col items-center justify-center ${activeClass}`;
tab.innerHTML = `
<span class="text-xs">${day.dayNum}. Gün</span>
<span class="text-[9px] mt-0.5 opacity-70 font-medium">${day.formattedDate}</span>
`;
tab.onclick = () => {
activeDayIndex = index;
renderDayTabs();
renderActiveDay();
};
container.appendChild(tab);
});
// Handle scroll to active element
const activeTab = container.children[activeDayIndex];
if (activeTab) {
activeTab.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
}
// Disable/enable arrows
const prevBtn = document.getElementById('prev-day-btn');
const nextBtn = document.getElementById('next-day-btn');
prevBtn.disabled = activeDayIndex === 0;
prevBtn.classList.toggle('opacity-40', activeDayIndex === 0);
prevBtn.classList.toggle('cursor-not-allowed', activeDayIndex === 0);
nextBtn.disabled = activeDayIndex === commitDays.length - 1;
nextBtn.classList.toggle('opacity-40', activeDayIndex === commitDays.length - 1);
nextBtn.classList.toggle('cursor-not-allowed', activeDayIndex === commitDays.length - 1);
}
function renderActiveDay() {
const card = document.getElementById('active-day-card');
// Smooth transition
card.style.opacity = '0.3';
card.style.transform = 'translateY(5px)';
setTimeout(() => {
const day = commitDays[activeDayIndex];
document.getElementById('active-day-title').textContent = `${day.dayNum}. Gün`;
document.getElementById('active-day-date').innerHTML = `<i class="uil uil-calendar-alt mr-1"></i> ${day.formattedDate}`;
document.getElementById('active-day-commit-count').textContent = `${day.commits.length} Commit`;
const eventsContainer = document.getElementById('timeline-events');
eventsContainer.innerHTML = '';
day.commits.forEach(c => {
const message = c.commit.message;
const authorDate = new Date(c.commit.author.date);
const timeStr = authorDate.toLocaleTimeString('tr-TR', { hour: '2-digit', minute: '2-digit' });
const shaShort = c.sha.substring(0, 7);
const commitUrl = c.html_url;
const eventHtml = `
<div class="relative group">
<!-- Timeline Dot -->
<div class="absolute -left-[31px] sm:-left-[39px] top-1.5 w-6 h-6 rounded-full bg-white border-2 border-blue-500 flex items-center justify-center transition-all group-hover:bg-blue-500">
<div class="w-2 h-2 rounded-full bg-blue-500 group-hover:bg-white transition-all"></div>
</div>
<!-- Event Card -->
<div class="p-4 bg-slate-50/50 hover:bg-blue-50/10 border border-slate-100 hover:border-blue-100/60 rounded-2xl transition-all shadow-sm">
<div class="flex items-center justify-between gap-4 mb-2">
<span class="text-xs font-bold text-slate-400"><i class="uil uil-clock mr-1"></i> ${timeStr}</span>
<a href="${commitUrl}" target="_blank" class="text-xs font-mono font-bold text-blue-600 hover:text-blue-700 bg-blue-50/60 hover:bg-blue-50 px-2.5 py-0.5 rounded-lg border border-blue-100/40 transition-colors">
${shaShort}
</a>
</div>
<p class="text-sm font-bold text-slate-700 leading-relaxed whitespace-pre-line">${escapeHtml(message)}</p>
</div>
</div>
`;
eventsContainer.insertAdjacentHTML('beforeend', eventHtml);
});
card.style.opacity = '1';
card.style.transform = 'translateY(0)';
}, 150);
}
function navigateDay(dir) {
const newIndex = activeDayIndex + dir;
if (newIndex >= 0 && newIndex < commitDays.length) {
activeDayIndex = newIndex;
renderDayTabs();
renderActiveDay();
}
}
function escapeHtml(text) {
if (!text) return '';
return text
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
function handleFileSelected(input) {
const fileNameElement = document.getElementById('selected-file-name');
const submitBtn = document.getElementById('submit-upload-btn');
if (input.files && input.files.length > 0) {
const file = input.files[0];
const fileSizeMB = file.size / (1024 * 1024);
if (fileSizeMB > 50) {
alert('Dosya boyutu 50MB\'ı aşamaz.');
input.value = '';
fileNameElement.textContent = '';
submitBtn.disabled = true;
submitBtn.classList.add('opacity-50', 'cursor-not-allowed');
return;
}
fileNameElement.textContent = 'Seçilen dosya: ' + file.name + ' (' + fileSizeMB.toFixed(2) + ' MB)';
submitBtn.disabled = false;
submitBtn.classList.remove('opacity-50', 'cursor-not-allowed');
} else {
fileNameElement.textContent = '';
submitBtn.disabled = true;
submitBtn.classList.add('opacity-50', 'cursor-not-allowed');
}
}
function calculateEndDateFrontend() {
const startDateVal = document.getElementById('internship_start_date').value;
const totalDaysVal = document.getElementById('internship_total_days').value;
const endDateInput = document.getElementById('internship_end_date');
if (!startDateVal || !totalDaysVal || totalDaysVal <= 0) {
return;
}
let date = new Date(startDateVal);
let daysToAdd = parseInt(totalDaysVal);
let count = 0;
let endDate = new Date(startDateVal);
while (count < daysToAdd) {
const dayOfWeek = date.getDay();
if (dayOfWeek === 6 || dayOfWeek === 0) { // 6 = Saturday, 0 = Sunday
date.setDate(date.getDate() + 1);
continue;
}
endDate = new Date(date);
date.setDate(date.getDate() + 1);
count++;
}
// Format to YYYY-MM-DD
const yyyy = endDate.getFullYear();
const mm = String(endDate.getMonth() + 1).padStart(2, '0');
const dd = String(endDate.getDate()).padStart(2, '0');
endDateInput.value = `${yyyy}-${mm}-${dd}`;
}
function copyToClipboard(elementId, btn) {
const text = document.getElementById(elementId).textContent;
navigator.clipboard.writeText(text).then(() => {
const icon = btn.querySelector('i');
const originalClass = icon.className;
icon.className = 'uil uil-check text-green-500';
setTimeout(() => {
icon.className = originalClass;
}, 2000);
});
}
</script>
<style>
.shadow-xl {
box-shadow: 0 1rem 3rem rgba(30, 41, 59, 0.04) !important;
}
.tab-btn {
transition: all 0.2s ease-in-out;
}
.tab-btn:hover:not(.active) {
background-color: #f8fafc;
}
.tab-btn.active {
background-color: #eff6ff;
border-color: #dbeafe;
color: #1e40af !important;
}
.tab-btn.active span.text-slate-800 {
color: #1e40af !important;
}
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
</style>
@endpush
@endsection