807 lines
43 KiB
PHP
807 lines
43 KiB
PHP
@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, "&")
|
||
.replace(/</g, "<")
|
||
.replace(/>/g, ">")
|
||
.replace(/"/g, """)
|
||
.replace(/'/g, "'");
|
||
}
|
||
|
||
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
|