feat: implement intern admin portal with login and dashboard management functionality
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
@extends('layouts.site')
|
||||
|
||||
@section('content')
|
||||
<section class="wrapper bg-[#f0f7ff] py-12">
|
||||
<div class="container px-4">
|
||||
<div class="max-w-7xl 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">Yönetici Paneli</span>
|
||||
<h1 class="text-3xl font-extrabold text-slate-900 tracking-tight mt-3">Hoş Geldiniz, Yöneticimiz</h1>
|
||||
<p class="text-sm text-slate-500 mt-1">Stajyer başvurularını, takvimlerini ve proje depolarını buradan takip edebilirsiniz.</p>
|
||||
</div>
|
||||
<div class="flex gap-3">
|
||||
<a href="{{ route('homepage') }}" class="px-5 py-3 rounded-xl bg-slate-100 hover:bg-slate-200 text-slate-600 font-bold text-sm transition-all flex items-center gap-2 border border-slate-200/50">
|
||||
<i class="uil uil-home text-lg"></i>
|
||||
<span>Ana Sayfa</span>
|
||||
</a>
|
||||
<form action="{{ route('intern.admin.logout') }}" method="POST">
|
||||
@csrf
|
||||
<button type="submit" class="px-5 py-3 rounded-xl bg-red-50 hover:bg-red-100 text-[#e31e24] font-bold text-sm transition-all flex items-center gap-2 border border-red-100">
|
||||
<i class="uil uil-sign-out-alt text-lg"></i>
|
||||
<span>Çıkış Yap</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stats Grid -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
<div class="bg-white p-6 rounded-3xl border border-slate-100 shadow-lg flex items-center gap-4">
|
||||
<div class="w-12 h-12 rounded-2xl bg-blue-50 text-blue-600 flex items-center justify-center text-2xl">
|
||||
<i class="uil uil-users-alt"></i>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-xs font-bold text-slate-400 block uppercase">Toplam Stajyer</span>
|
||||
<span class="text-2xl font-extrabold text-slate-800">{{ $allInterns->count() }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-6 rounded-3xl border border-slate-100 shadow-lg flex items-center gap-4">
|
||||
<div class="w-12 h-12 rounded-2xl bg-emerald-50 text-emerald-600 flex items-center justify-center text-2xl">
|
||||
<i class="uil uil-check-circle"></i>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-xs font-bold text-slate-400 block uppercase">Kabul Edilen</span>
|
||||
<span class="text-2xl font-extrabold text-slate-800">{{ $allInterns->where('status', 'accepted')->count() }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-6 rounded-3xl border border-slate-100 shadow-lg flex items-center gap-4">
|
||||
<div class="w-12 h-12 rounded-2xl bg-amber-50 text-amber-600 flex items-center justify-center text-2xl">
|
||||
<i class="uil uil-hourglass-half"></i>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-xs font-bold text-slate-400 block uppercase">Evrak Bekleyen</span>
|
||||
<span class="text-2xl font-extrabold text-slate-800">{{ $allInterns->where('status', 'waiting_document')->count() }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-6 rounded-3xl border border-slate-100 shadow-lg flex items-center gap-4">
|
||||
<div class="w-12 h-12 rounded-2xl bg-indigo-50 text-indigo-600 flex items-center justify-center text-2xl">
|
||||
<i class="uil uil-github-alt"></i>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-xs font-bold text-slate-400 block uppercase">Git Tanımlayan</span>
|
||||
<span class="text-2xl font-extrabold text-slate-800">{{ $allInterns->whereNotNull('github_repo')->count() }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gantt Chart Card -->
|
||||
<div class="bg-white rounded-3xl p-6 md:p-8 shadow-xl border border-slate-100/50 mb-8">
|
||||
<div class="flex items-center justify-between mb-6 pb-4 border-b border-slate-100">
|
||||
<h3 class="font-bold text-slate-800 text-lg flex items-center gap-2">
|
||||
<i class="uil uil-schedule text-blue-600 text-xl"></i>
|
||||
<span>Stajyer Gantt Şeması ve Takvimi</span>
|
||||
</h3>
|
||||
<span class="text-xs px-2.5 py-1 bg-blue-50 text-blue-600 rounded-full font-semibold">DevExtreme Görünümü</span>
|
||||
</div>
|
||||
|
||||
@if($ganttInterns->isEmpty())
|
||||
<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-calendar-slash text-4xl text-slate-300 mb-2"></i>
|
||||
<p class="text-sm font-medium text-slate-500">Tarihleri belirlenmiş onaylı stajyer bulunamadı.</p>
|
||||
</div>
|
||||
@else
|
||||
<!-- Gantt Container -->
|
||||
<div class="dx-viewport demo-container" style="height: 480px; overflow: hidden; border-radius: 16px; border: 1px solid rgba(0,0,0,0.05);">
|
||||
<div id="gantt" style="height: 100%; width: 100%;"></div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Interns Table & Management List -->
|
||||
<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-4 border-b border-slate-100 flex items-center gap-2">
|
||||
<i class="uil uil-list-ul text-[#e31e24] text-xl"></i>
|
||||
<span>Stajyer Listesi ve Detaylı Takip</span>
|
||||
</h3>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left border-collapse">
|
||||
<thead>
|
||||
<tr class="border-b border-slate-100 text-xs font-extrabold uppercase tracking-wider text-slate-400">
|
||||
<th class="pb-4">Stajyer</th>
|
||||
<th class="pb-4">Staj Tarihleri</th>
|
||||
<th class="pb-4">Durum</th>
|
||||
<th class="pb-4">Belgeler</th>
|
||||
<th class="pb-4">GitHub & Repo</th>
|
||||
<th class="pb-4">Kayıt Tarihi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-slate-100">
|
||||
@foreach($allInterns as $intern)
|
||||
<tr class="hover:bg-slate-50/50 transition-colors">
|
||||
<!-- Name & Info -->
|
||||
<td class="py-4">
|
||||
<div class="font-bold text-slate-800 text-sm">{{ $intern->name }}</div>
|
||||
<div class="text-xs text-slate-400 mt-0.5 flex flex-col gap-0.5">
|
||||
<span><i class="uil uil-envelope mr-1"></i>{{ $intern->email }}</span>
|
||||
@if($intern->phone)
|
||||
<span><i class="uil uil-phone mr-1"></i>{{ $intern->phone }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<!-- Internship Dates -->
|
||||
<td class="py-4 text-xs font-semibold text-slate-600">
|
||||
@if($intern->internship_start_date && $intern->internship_end_date)
|
||||
<div class="flex flex-col">
|
||||
<span>{{ \Carbon\Carbon::parse($intern->internship_start_date)->format('d.m.Y') }} - {{ \Carbon\Carbon::parse($intern->internship_end_date)->format('d.m.Y') }}</span>
|
||||
<span class="text-blue-500 font-extrabold mt-0.5">{{ $intern->internship_total_days }} İş Günü</span>
|
||||
</div>
|
||||
@else
|
||||
<span class="text-slate-300 italic">Belirlenmemiş</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
<!-- Status -->
|
||||
<td class="py-4">
|
||||
<span class="inline-flex px-2.5 py-1 rounded-full text-[10px] font-extrabold 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') Evrak Bekleniyor
|
||||
@else Beklemede @endif
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<!-- Documents -->
|
||||
<td class="py-4 space-y-1">
|
||||
<div class="flex flex-wrap gap-1">
|
||||
@if($intern->cv_path)
|
||||
<a href="{{ Storage::disk('public')->url($intern->cv_path) }}" target="_blank" class="px-2 py-1 bg-slate-100 hover:bg-slate-200 text-slate-600 font-bold text-[10px] rounded-lg transition-all flex items-center gap-1">
|
||||
<i class="uil uil-file-alt"></i> CV
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@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-2 py-1 bg-blue-50 hover:bg-blue-100 text-blue-600 font-bold text-[10px] rounded-lg transition-all flex items-center gap-1">
|
||||
<i class="uil uil-file-upload"></i> İmzalanacak Form
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@if($intern->signed_internship_form_path)
|
||||
<a href="{{ Storage::disk('public')->url($intern->signed_internship_form_path) }}" target="_blank" class="px-2 py-1 bg-green-50 hover:bg-green-100 text-green-600 font-bold text-[10px] rounded-lg transition-all flex items-center gap-1">
|
||||
<i class="uil uil-file-check-alt"></i> İmzalı Form
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<!-- GitHub Repository -->
|
||||
<td class="py-4">
|
||||
@if($intern->github_repo)
|
||||
<div class="flex flex-col gap-1">
|
||||
<a href="{{ $intern->github_repo }}" target="_blank" class="text-blue-600 hover:text-blue-800 font-extrabold text-xs inline-flex items-center gap-1">
|
||||
<i class="uil uil-github"></i> Depoyu Aç
|
||||
</a>
|
||||
<!-- If they have repo, we can fetch their journal commits or trigger the controller download markdown -->
|
||||
<a href="{{ route('intern.download-journal') }}?intern_id={{ $intern->id }}" class="px-2 py-1 bg-emerald-50 hover:bg-emerald-100 text-emerald-600 font-bold text-[10px] rounded-lg transition-all flex items-center justify-center gap-1 w-max">
|
||||
<i class="uil uil-arrow-down-tray"></i> Günlüğü İndir (.md)
|
||||
</a>
|
||||
</div>
|
||||
@else
|
||||
<span class="text-slate-300 italic">Tanımlanmamış</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
<!-- Register Date -->
|
||||
<td class="py-4 text-xs font-semibold text-slate-400">
|
||||
{{ \Carbon\Carbon::parse($intern->created_at)->format('d.m.Y H:i') }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@push('styles')
|
||||
<!-- DevExtreme Gantt CSS Dependencies -->
|
||||
<link rel="stylesheet" href="https://cdn3.devexpress.com/jslib/23.2.5/css/dx.light.css">
|
||||
<link rel="stylesheet" href="https://cdn3.devexpress.com/jslib/23.2.5/css/dx-gantt.css">
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
|
||||
<!-- Gantt Chart Javascript Dependencies & Initialization -->
|
||||
@if(!$ganttInterns->isEmpty())
|
||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
||||
<script src="https://cdn3.devexpress.com/jslib/23.2.5/js/dx.all.js"></script>
|
||||
<script src="https://cdn3.devexpress.com/jslib/23.2.5/js/dx-gantt.min.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
const ganttData = @json($ganttInterns);
|
||||
|
||||
const formattedData = ganttData.map(intern => ({
|
||||
id: intern.id,
|
||||
parentId: 0,
|
||||
title: intern.title,
|
||||
start: new Date(intern.start),
|
||||
end: new Date(intern.end),
|
||||
progress: 100
|
||||
}));
|
||||
|
||||
$('#gantt').dxGantt({
|
||||
tasks: {
|
||||
dataSource: formattedData,
|
||||
},
|
||||
editing: {
|
||||
enabled: false,
|
||||
},
|
||||
validation: {
|
||||
autoUpdateParentTasks: true,
|
||||
},
|
||||
toolbar: {
|
||||
items: [
|
||||
'collapseAll',
|
||||
'expandAll',
|
||||
'separator',
|
||||
'zoomIn',
|
||||
'zoomOut',
|
||||
],
|
||||
},
|
||||
columns: [{
|
||||
dataField: 'title',
|
||||
caption: 'Stajyer Adı',
|
||||
width: 200,
|
||||
}, {
|
||||
dataField: 'start',
|
||||
caption: 'Başlangıç Tarihi',
|
||||
dataType: 'date',
|
||||
format: 'dd.MM.yyyy',
|
||||
width: 110,
|
||||
}, {
|
||||
dataField: 'end',
|
||||
caption: 'Bitiş Tarihi',
|
||||
dataType: 'date',
|
||||
format: 'dd.MM.yyyy',
|
||||
width: 110,
|
||||
}],
|
||||
scaleType: 'days',
|
||||
taskListWidth: 420,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endif
|
||||
@endpush
|
||||
@@ -0,0 +1,87 @@
|
||||
@extends('layouts.site')
|
||||
|
||||
@section('content')
|
||||
<section class="wrapper bg-[#f0f7ff] min-h-[70vh] flex items-center py-12">
|
||||
<div class="container px-4">
|
||||
<div class="max-w-md mx-auto bg-white/80 backdrop-blur-md rounded-3xl shadow-2xl border border-slate-100/50 overflow-hidden">
|
||||
<div class="p-8 md:p-10">
|
||||
<div class="text-center mb-8">
|
||||
<div class="inline-flex w-16 h-16 rounded-full bg-red-50 text-[#e31e24] items-center justify-center mb-4">
|
||||
<i class="uil uil-shield text-3xl"></i>
|
||||
</div>
|
||||
<h1 class="text-3xl font-extrabold text-slate-900 tracking-tight">Yönetici Girişi</h1>
|
||||
<p class="text-sm text-slate-500 mt-2">Staj takip sistemini yönetmek için e-posta ve şifrenizle giriş yapın.</p>
|
||||
</div>
|
||||
|
||||
@if($errors->any())
|
||||
<div class="bg-red-50 border-l-4 border-[#e31e24] p-4 rounded-xl mb-6">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<i class="uil uil-exclamation-triangle text-[#e31e24] text-xl"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="text-sm text-red-700 font-medium">
|
||||
{{ $errors->first() }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(session('success'))
|
||||
<div class="bg-green-50 border-l-4 border-green-500 p-4 rounded-xl mb-6">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<i class="uil uil-check-circle text-green-500 text-xl"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="text-sm text-green-700 font-medium">
|
||||
{{ session('success') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form action="{{ route('intern.admin.login.submit') }}" method="POST" class="space-y-6">
|
||||
@csrf
|
||||
|
||||
<div class="space-y-2">
|
||||
<label for="email" class="text-sm font-bold text-slate-700 block">E-posta</label>
|
||||
<div class="relative">
|
||||
<span class="absolute inset-y-0 left-0 flex items-center pl-4 text-slate-400">
|
||||
<i class="uil uil-envelope"></i>
|
||||
</span>
|
||||
<input type="email" name="email" id="email" class="w-full pl-11 pr-5 py-3.5 rounded-xl border border-slate-200 focus:ring-4 focus:ring-red-500/10 focus:border-[#e31e24] outline-none transition-all placeholder-slate-300" placeholder="E-posta adresinizi girin" value="{{ old('email') }}" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<label for="password" class="text-sm font-bold text-slate-700 block">Şifre</label>
|
||||
<div class="relative">
|
||||
<span class="absolute inset-y-0 left-0 flex items-center pl-4 text-slate-400">
|
||||
<i class="uil uil-key-skeleton-alt"></i>
|
||||
</span>
|
||||
<input type="password" name="password" id="password" class="w-full pl-11 pr-5 py-3.5 rounded-xl border border-slate-200 focus:ring-4 focus:ring-red-500/10 focus:border-[#e31e24] outline-none transition-all placeholder-slate-300" placeholder="Şifrenizi girin" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="w-full py-4 bg-[#e31e24] hover:bg-[#c4191f] text-white font-bold rounded-xl transition-all shadow-lg shadow-red-500/20 flex items-center justify-center gap-2 mt-4 hover:-translate-y-0.5">
|
||||
<span>Giriş Yap</span>
|
||||
<i class="uil uil-arrow-right text-xl"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@push('styles')
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<style>
|
||||
.shadow-2xl {
|
||||
box-shadow: 0 1.5rem 4rem rgba(30, 41, 59, 0.08) !important;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
@endsection
|
||||
Reference in New Issue
Block a user