feat: implement internship journal approval status tracking and add single-day printing functionality
This commit is contained in:
@@ -494,6 +494,8 @@ class CareerController extends Controller
|
|||||||
], [
|
], [
|
||||||
'content' => $request->content,
|
'content' => $request->content,
|
||||||
'is_retroactive' => $isRetroactive,
|
'is_retroactive' => $isRetroactive,
|
||||||
|
'supervisor_approved' => false,
|
||||||
|
'supervisor_name' => null,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
@@ -521,6 +523,15 @@ class CareerController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$days = self::getInternshipDates($intern->internship_start_date, $intern->internship_total_days);
|
$days = self::getInternshipDates($intern->internship_start_date, $intern->internship_total_days);
|
||||||
|
|
||||||
|
$dayFilter = $request->query('day');
|
||||||
|
if ($dayFilter) {
|
||||||
|
$days = array_filter($days, function($d) use ($dayFilter) {
|
||||||
|
return $d['day_number'] == $dayFilter;
|
||||||
|
});
|
||||||
|
$days = array_values($days);
|
||||||
|
}
|
||||||
|
|
||||||
$savedEntries = $intern->journalEntries()->get()->keyBy('day_number');
|
$savedEntries = $intern->journalEntries()->get()->keyBy('day_number');
|
||||||
|
|
||||||
return view('front.career.print', [
|
return view('front.career.print', [
|
||||||
|
|||||||
@@ -684,6 +684,7 @@
|
|||||||
$dayDate = $d['date'];
|
$dayDate = $d['date'];
|
||||||
$dayDateFormatted = $d['formatted_date'];
|
$dayDateFormatted = $d['formatted_date'];
|
||||||
$hasSaved = isset($savedEntries[$dayNum]) && trim($savedEntries[$dayNum]->content) !== '';
|
$hasSaved = isset($savedEntries[$dayNum]) && trim($savedEntries[$dayNum]->content) !== '';
|
||||||
|
$isApproved = isset($savedEntries[$dayNum]) && $savedEntries[$dayNum]->supervisor_approved;
|
||||||
@endphp
|
@endphp
|
||||||
<button type="button"
|
<button type="button"
|
||||||
onclick="selectNotebookDay({{ $idx }})"
|
onclick="selectNotebookDay({{ $idx }})"
|
||||||
@@ -692,13 +693,19 @@
|
|||||||
data-date="{{ $dayDate }}"
|
data-date="{{ $dayDate }}"
|
||||||
data-formatted-date="{{ $dayDateFormatted }}"
|
data-formatted-date="{{ $dayDateFormatted }}"
|
||||||
data-saved-content="{{ $savedEntries[$dayNum]->content ?? '' }}"
|
data-saved-content="{{ $savedEntries[$dayNum]->content ?? '' }}"
|
||||||
|
data-approved="{{ $isApproved ? '1' : '0' }}"
|
||||||
class="notebook-day-btn w-full flex items-center justify-between p-3 rounded-2xl border text-left transition-all @if($idx === 0) border-blue-200 bg-blue-50/50 @else border-slate-100 bg-white hover:bg-slate-50 @endif">
|
class="notebook-day-btn w-full flex items-center justify-between p-3 rounded-2xl border text-left transition-all @if($idx === 0) border-blue-200 bg-blue-50/50 @else border-slate-100 bg-white hover:bg-slate-50 @endif">
|
||||||
<div>
|
<div>
|
||||||
<span class="block text-xs font-extrabold @if($idx === 0) text-blue-700 @else text-slate-800 @endif">{{ $dayNum }}. Gün</span>
|
<span class="block text-xs font-extrabold @if($idx === 0) text-blue-700 @else text-slate-800 @endif">{{ $dayNum }}. Gün</span>
|
||||||
<span class="block text-[10px] text-slate-400 mt-0.5">{{ $dayDateFormatted }}</span>
|
<span class="block text-[10px] text-slate-400 mt-0.5">{{ $dayDateFormatted }}</span>
|
||||||
</div>
|
</div>
|
||||||
<span id="badge-day-{{ $idx }}" class="inline-flex px-2 py-0.5 rounded-lg text-[9px] font-extrabold uppercase @if($hasSaved) bg-green-50 text-green-700 border border-green-200 @else bg-slate-50 text-slate-400 border border-slate-200 @endif">
|
<span id="badge-day-{{ $idx }}" class="inline-flex px-2 py-0.5 rounded-lg text-[9px] font-extrabold uppercase
|
||||||
{{ $hasSaved ? 'DOLU' : 'BOŞ' }}
|
@if($isApproved) bg-green-500 text-white border border-green-600
|
||||||
|
@elseif($hasSaved) bg-amber-50 text-amber-700 border border-amber-200
|
||||||
|
@else bg-slate-50 text-slate-400 border border-slate-200 @endif">
|
||||||
|
@if($isApproved) ONAYLANDI
|
||||||
|
@elseif($hasSaved) DOLU
|
||||||
|
@else BOŞ @endif
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
@endforeach
|
@endforeach
|
||||||
@@ -708,17 +715,25 @@
|
|||||||
<div class="lg:col-span-8 space-y-4">
|
<div class="lg:col-span-8 space-y-4">
|
||||||
<div class="bg-white border border-slate-100 rounded-2xl p-5 shadow-sm">
|
<div class="bg-white border border-slate-100 rounded-2xl p-5 shadow-sm">
|
||||||
<div class="flex items-center justify-between pb-3 border-b border-slate-100 mb-4">
|
<div class="flex items-center justify-between pb-3 border-b border-slate-100 mb-4">
|
||||||
<div>
|
<div class="flex items-center">
|
||||||
<span id="editor-day-title" class="text-sm font-extrabold text-blue-600 bg-blue-50 px-3 py-1 rounded-full">1. Gün</span>
|
<span id="editor-day-title" class="text-sm font-extrabold text-blue-600 bg-blue-50 px-3 py-1 rounded-full">1. Gün</span>
|
||||||
<span id="editor-day-date" class="text-xs font-semibold text-slate-400 ml-2"></span>
|
<span id="editor-day-date" class="text-xs font-semibold text-slate-400 ml-2"></span>
|
||||||
|
<span id="editor-day-status" class="ml-2"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
@if($intern->github_repo)
|
@if($intern->github_repo)
|
||||||
<button type="button" onclick="fillFromGithub()" class="px-3 py-1.5 bg-slate-800 hover:bg-slate-900 text-white font-extrabold rounded-lg text-[10px] transition-all flex items-center gap-1.5 shadow-sm">
|
<button type="button" onclick="fillFromGithub()" class="px-3 py-1.5 bg-slate-800 hover:bg-slate-900 text-white font-extrabold rounded-lg text-[10px] transition-all flex items-center gap-1.5 shadow-sm">
|
||||||
<i class="uil uil-github text-xs"></i>
|
<i class="uil uil-github text-xs"></i>
|
||||||
<span>Git Commitlerini Çek</span>
|
<span>Git Commitlerini Çek</span>
|
||||||
</button>
|
</button>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
<button type="button" onclick="printActiveDay()" class="px-3 py-1.5 bg-green-600 hover:bg-green-700 text-white font-extrabold rounded-lg text-[10px] transition-all flex items-center gap-1.5 shadow-sm">
|
||||||
|
<i class="uil uil-print text-xs"></i>
|
||||||
|
<span>Yazdır</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
@@ -900,6 +915,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateEditorStatusBadge(isApproved, hasSaved) {
|
||||||
|
const statusSpan = document.getElementById('editor-day-status');
|
||||||
|
if (!statusSpan) return;
|
||||||
|
|
||||||
|
if (isApproved) {
|
||||||
|
statusSpan.textContent = 'ONAYLANDI';
|
||||||
|
statusSpan.className = 'inline-flex px-2 py-0.5 rounded-full text-[10px] font-extrabold uppercase bg-green-500 text-white border border-green-600 ml-2';
|
||||||
|
} else if (hasSaved) {
|
||||||
|
statusSpan.textContent = 'ONAY BEKLİYOR';
|
||||||
|
statusSpan.className = 'inline-flex px-2 py-0.5 rounded-full text-[10px] font-extrabold uppercase bg-amber-50 text-amber-700 border border-amber-200 ml-2';
|
||||||
|
} else {
|
||||||
|
statusSpan.textContent = '';
|
||||||
|
statusSpan.className = 'hidden';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function printActiveDay() {
|
||||||
|
const btn = document.getElementById(`btn-day-${activeDayIdx}`);
|
||||||
|
if (!btn) return;
|
||||||
|
const dayNum = btn.getAttribute('data-day-num');
|
||||||
|
window.open(`{{ route('intern.print-journal') }}?size=a4&day=${dayNum}`, '_blank');
|
||||||
|
}
|
||||||
|
|
||||||
function appendCommitToQuill(sha, time, msg) {
|
function appendCommitToQuill(sha, time, msg) {
|
||||||
const escapedMsg = msg.replace(/</g, "<").replace(/>/g, ">");
|
const escapedMsg = msg.replace(/</g, "<").replace(/>/g, ">");
|
||||||
const commitHtml = `<li><strong>[${time}]</strong> (<em>${sha}</em>) ${escapedMsg}</li>`;
|
const commitHtml = `<li><strong>[${time}]</strong> (<em>${sha}</em>) ${escapedMsg}</li>`;
|
||||||
@@ -946,6 +984,7 @@
|
|||||||
const dateVal = newBtn.getAttribute('data-date');
|
const dateVal = newBtn.getAttribute('data-date');
|
||||||
const dateFormatted = newBtn.getAttribute('data-formatted-date');
|
const dateFormatted = newBtn.getAttribute('data-formatted-date');
|
||||||
const savedContent = newBtn.getAttribute('data-saved-content');
|
const savedContent = newBtn.getAttribute('data-saved-content');
|
||||||
|
const isApproved = newBtn.getAttribute('data-approved') === '1';
|
||||||
|
|
||||||
document.getElementById('editor-day-title').textContent = `${dayNum}. Gün`;
|
document.getElementById('editor-day-title').textContent = `${dayNum}. Gün`;
|
||||||
document.getElementById('editor-day-date').textContent = dateFormatted;
|
document.getElementById('editor-day-date').textContent = dateFormatted;
|
||||||
@@ -957,6 +996,9 @@
|
|||||||
document.getElementById('save-status').textContent = '';
|
document.getElementById('save-status').textContent = '';
|
||||||
hideFallbackCommits();
|
hideFallbackCommits();
|
||||||
|
|
||||||
|
const hasSaved = savedContent && savedContent.trim() !== '' && savedContent !== '<p><br></p>';
|
||||||
|
updateEditorStatusBadge(isApproved, hasSaved);
|
||||||
|
|
||||||
// Future validation
|
// Future validation
|
||||||
const dateParts = dateVal.split('-');
|
const dateParts = dateVal.split('-');
|
||||||
const selectedDate = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
|
const selectedDate = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
|
||||||
@@ -1185,17 +1227,21 @@
|
|||||||
statusText.className = "text-xs font-semibold text-green-600";
|
statusText.className = "text-xs font-semibold text-green-600";
|
||||||
|
|
||||||
btn.setAttribute('data-saved-content', contentVal);
|
btn.setAttribute('data-saved-content', contentVal);
|
||||||
|
btn.setAttribute('data-approved', '0');
|
||||||
|
|
||||||
const badge = document.getElementById(`badge-day-${activeDayIdx}`);
|
const badge = document.getElementById(`badge-day-${activeDayIdx}`);
|
||||||
|
const hasContent = contentVal.trim() !== '' && contentVal !== '<p><br></p>';
|
||||||
if (badge) {
|
if (badge) {
|
||||||
if (contentVal.trim() !== '') {
|
if (hasContent) {
|
||||||
badge.textContent = 'DOLU';
|
badge.textContent = 'DOLU';
|
||||||
badge.className = "inline-flex px-2 py-0.5 rounded-lg text-[9px] font-extrabold uppercase bg-green-50 text-green-700 border border-green-200";
|
badge.className = "inline-flex px-2 py-0.5 rounded-lg text-[9px] font-extrabold uppercase bg-amber-50 text-amber-700 border border-amber-200";
|
||||||
} else {
|
} else {
|
||||||
badge.textContent = 'BOŞ';
|
badge.textContent = 'BOŞ';
|
||||||
badge.className = "inline-flex px-2 py-0.5 rounded-lg text-[9px] font-extrabold uppercase bg-slate-50 text-slate-400 border border-slate-200";
|
badge.className = "inline-flex px-2 py-0.5 rounded-lg text-[9px] font-extrabold uppercase bg-slate-50 text-slate-400 border border-slate-200";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateEditorStatusBadge(false, hasContent);
|
||||||
} else {
|
} else {
|
||||||
statusText.textContent = data.message || "Kaydedilemedi.";
|
statusText.textContent = data.message || "Kaydedilemedi.";
|
||||||
statusText.className = "text-xs font-semibold text-red-600";
|
statusText.className = "text-xs font-semibold text-red-600";
|
||||||
|
|||||||
@@ -331,8 +331,8 @@
|
|||||||
<span>Panele Dön</span>
|
<span>Panele Dön</span>
|
||||||
</a>
|
</a>
|
||||||
<div style="border-left: 1px solid #e2e8f0; margin: 0 5px; height: 35px;"></div>
|
<div style="border-left: 1px solid #e2e8f0; margin: 0 5px; height: 35px;"></div>
|
||||||
<a href="?size=a4{{ request()->has('intern_id') ? '&intern_id='.request('intern_id') : '' }}" class="btn {{ $size === 'a4' ? 'btn-primary' : 'btn-secondary' }}">A4 Boyutu</a>
|
<a href="?size=a4{{ request()->has('intern_id') ? '&intern_id='.request('intern_id') : '' }}{{ request()->has('day') ? '&day='.request('day') : '' }}" class="btn {{ $size === 'a4' ? 'btn-primary' : 'btn-secondary' }}">A4 Boyutu</a>
|
||||||
<a href="?size=a5{{ request()->has('intern_id') ? '&intern_id='.request('intern_id') : '' }}" class="btn {{ $size === 'a5' ? 'btn-primary' : 'btn-secondary' }}">A5 Boyutu</a>
|
<a href="?size=a5{{ request()->has('intern_id') ? '&intern_id='.request('intern_id') : '' }}{{ request()->has('day') ? '&day='.request('day') : '' }}" class="btn {{ $size === 'a5' ? 'btn-primary' : 'btn-secondary' }}">A5 Boyutu</a>
|
||||||
<button onclick="window.print()" class="btn btn-primary">
|
<button onclick="window.print()" class="btn btn-primary">
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 6 2 18 2 18 9"/><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><rect x="6" y="14" width="12" height="8"/></svg>
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 6 2 18 2 18 9"/><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><rect x="6" y="14" width="12" height="8"/></svg>
|
||||||
<span>Yazdır / PDF Kaydet</span>
|
<span>Yazdır / PDF Kaydet</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user