fix(intern): quill editor baslatma hatasi ve staj formu yukleme izinleri duzeltildi

This commit is contained in:
Ümit Tunç
2026-09-01 14:58:32 +03:00
parent f1a579c8ee
commit ff3e084222
@@ -660,11 +660,11 @@
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <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> <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 }}" @if($intern->status !== 'pending') disabled @endif 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 disabled:bg-slate-50 disabled:text-slate-500 disabled:cursor-not-allowed" /> <input type="date" name="internship_start_date" id="internship_start_date" onchange="calculateEndDateFrontend()" oninput="calculateEndDateFrontend()" required value="{{ $intern->internship_start_date }}" @if(!in_array($intern->status, ['pending', 'waiting_document', 'reviewed'])) disabled @endif 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 disabled:bg-slate-50 disabled:text-slate-500 disabled:cursor-not-allowed" />
</div> </div>
<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> <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" @if($intern->status !== 'pending') disabled @endif 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 disabled:bg-slate-50 disabled:text-slate-500 disabled:cursor-not-allowed" /> <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" @if(!in_array($intern->status, ['pending', 'waiting_document', 'reviewed'])) disabled @endif 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 disabled:bg-slate-50 disabled:text-slate-500 disabled:cursor-not-allowed" />
</div> </div>
</div> </div>
<div> <div>
@@ -673,7 +673,7 @@
</div> </div>
</div> </div>
@if($intern->status === 'pending') @if(in_array($intern->status, ['pending', 'waiting_document', 'reviewed']))
<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"> <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" /> <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> <i class="uil uil-cloud-upload text-4xl text-slate-400 group-hover:text-blue-500 transition-colors mb-2"></i>
@@ -690,7 +690,7 @@
</div> </div>
@else @else
<div class="p-4 bg-slate-50 border border-slate-100 rounded-2xl text-center text-xs text-slate-500 font-semibold"> <div class="p-4 bg-slate-50 border border-slate-100 rounded-2xl text-center text-xs text-slate-500 font-semibold">
<i class="uil uil-lock-alt text-base mr-1"></i> Başvurunuz bekleme aşamasında (beklemede) olmadığı için staj bilgilerinizi ve dosyanızı güncelleyemezsiniz. <i class="uil uil-lock-alt text-base mr-1"></i> Başvurunuz kabul veya ret durumunda olduğu için staj formunuzu ve tarihlerinizi güncelleyemezsiniz.
</div> </div>
@endif @endif
</form> </form>
@@ -970,7 +970,7 @@
<!-- Progress Bar --> <!-- Progress Bar -->
@php @php
$userBlogs = $blogs ?? collect(); $userBlogs = ($blogs ?? collect())->sortByDesc('created_at');
$publishedBlogs = $userBlogs->where('status', 'published'); $publishedBlogs = $userBlogs->where('status', 'published');
$publishedCount = $publishedBlogs->count(); $publishedCount = $publishedBlogs->count();
$progressPercent = min(100, round(($publishedCount / 3) * 100)); $progressPercent = min(100, round(($publishedCount / 3) * 100));
@@ -1325,21 +1325,24 @@
<script> <script>
let quill; let quill = null;
// Tab Switch Logic // Tab Switch Logic
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// Initialize Quill editor // Initialize Quill editor if container exists
quill = new Quill('#editor-content-quill', { const editorElement = document.getElementById('editor-content-quill');
theme: 'snow', if (editorElement) {
modules: { quill = new Quill('#editor-content-quill', {
toolbar: [ theme: 'snow',
['bold', 'italic', 'underline', 'strike'], // toggled buttons modules: {
[{ 'list': 'ordered'}, { 'list': 'bullet' }], toolbar: [
['clean'] // remove formatting button ['bold', 'italic', 'underline', 'strike'], // toggled buttons
] [{ 'list': 'ordered'}, { 'list': 'bullet' }],
} ['clean'] // remove formatting button
}); ]
}
});
}
const tabButtons = document.querySelectorAll('.tab-btn'); const tabButtons = document.querySelectorAll('.tab-btn');
const tabPanels = document.querySelectorAll('.tab-panel'); const tabPanels = document.querySelectorAll('.tab-panel');
@@ -1379,8 +1382,10 @@
// Handle initial state of date logic // Handle initial state of date logic
calculateEndDateFrontend(); calculateEndDateFrontend();
// Select first day of the notebook workspace on load // Select first day of the notebook workspace on load if exists
selectNotebookDay(0); if (document.getElementById('btn-day-0')) {
selectNotebookDay(0);
}
}); });
const githubRepoUrl = @json($intern->github_repo); const githubRepoUrl = @json($intern->github_repo);
@@ -1496,6 +1501,7 @@
} }
function renderCommitsToEditor(commitsList) { function renderCommitsToEditor(commitsList) {
if (!quill) return;
if (commitsList.length === 0) { if (commitsList.length === 0) {
alert("Bu yazar için seçilen güne ait commit bulunamadı."); alert("Bu yazar için seçilen güne ait commit bulunamadı.");
return; return;
@@ -1575,6 +1581,7 @@
} }
function appendCommitToQuill(sha, time, msg) { function appendCommitToQuill(sha, time, msg) {
if (!quill) return;
const escapedMsg = msg.replace(/</g, "&lt;").replace(/>/g, "&gt;"); const escapedMsg = msg.replace(/</g, "&lt;").replace(/>/g, "&gt;");
const commitHtml = `<li><strong>[${time}]</strong> (<em>${sha}</em>) ${escapedMsg}</li>`; const commitHtml = `<li><strong>[${time}]</strong> (<em>${sha}</em>) ${escapedMsg}</li>`;
@@ -1622,48 +1629,59 @@
const savedContent = newBtn.getAttribute('data-saved-content'); const savedContent = newBtn.getAttribute('data-saved-content');
const isApproved = newBtn.getAttribute('data-approved') === '1'; const isApproved = newBtn.getAttribute('data-approved') === '1';
document.getElementById('editor-day-title').textContent = `${dayNum}. Gün`; const editorDayTitle = document.getElementById('editor-day-title');
document.getElementById('editor-day-date').textContent = dateFormatted; if (editorDayTitle) editorDayTitle.textContent = `${dayNum}. Gün`;
const editorDayDate = document.getElementById('editor-day-date');
if (editorDayDate) editorDayDate.textContent = dateFormatted;
quill.setContents([]); if (quill) {
if (savedContent) { quill.setContents([]);
quill.clipboard.dangerouslyPasteHTML(savedContent); if (savedContent) {
quill.clipboard.dangerouslyPasteHTML(savedContent);
}
} }
document.getElementById('save-status').textContent = ''; const saveStatus = document.getElementById('save-status');
if (saveStatus) saveStatus.textContent = '';
hideFallbackCommits(); hideFallbackCommits();
const hasSaved = savedContent && savedContent.trim() !== '' && savedContent !== '<p><br></p>'; const hasSaved = savedContent && savedContent.trim() !== '' && savedContent !== '<p><br></p>';
updateEditorStatusBadge(isApproved, hasSaved); updateEditorStatusBadge(isApproved, hasSaved);
// Future validation // Future validation
const dateParts = dateVal.split('-'); if (dateVal) {
const selectedDate = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]); const dateParts = dateVal.split('-');
const today = new Date(); const selectedDate = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
today.setHours(0,0,0,0); const today = new Date();
today.setHours(0,0,0,0);
const isFuture = selectedDate > today;
const warningBlock = document.getElementById('future-warning'); const isFuture = selectedDate > today;
const saveBtn = document.getElementById('save-btn'); const warningBlock = document.getElementById('future-warning');
const gitBtn = document.querySelector('button[onclick="fillFromGithub()"]'); const saveBtn = document.getElementById('save-btn');
const gitBtn = document.querySelector('button[onclick="fillFromGithub()"]');
if (isFuture) { if (isFuture) {
warningBlock.classList.remove('hidden'); if (warningBlock) warningBlock.classList.remove('hidden');
quill.enable(false); if (quill) quill.enable(false);
saveBtn.disabled = true; if (saveBtn) {
saveBtn.classList.add('opacity-50', 'cursor-not-allowed'); saveBtn.disabled = true;
if (gitBtn) { saveBtn.classList.add('opacity-50', 'cursor-not-allowed');
gitBtn.disabled = true; }
gitBtn.classList.add('opacity-50', 'cursor-not-allowed'); if (gitBtn) {
} gitBtn.disabled = true;
} else { gitBtn.classList.add('opacity-50', 'cursor-not-allowed');
warningBlock.classList.add('hidden'); }
quill.enable(true); } else {
saveBtn.disabled = false; if (warningBlock) warningBlock.classList.add('hidden');
saveBtn.classList.remove('opacity-50', 'cursor-not-allowed'); if (quill) quill.enable(true);
if (gitBtn) { if (saveBtn) {
gitBtn.disabled = false; saveBtn.disabled = false;
gitBtn.classList.remove('opacity-50', 'cursor-not-allowed'); saveBtn.classList.remove('opacity-50', 'cursor-not-allowed');
} }
if (gitBtn) {
gitBtn.disabled = false;
gitBtn.classList.remove('opacity-50', 'cursor-not-allowed');
}
}
} }
} }
} }
@@ -1837,7 +1855,7 @@
function saveActiveDay() { function saveActiveDay() {
const btn = document.getElementById(`btn-day-${activeDayIdx}`); const btn = document.getElementById(`btn-day-${activeDayIdx}`);
if (!btn) return; if (!btn || !quill) return;
const dayNum = btn.getAttribute('data-day-num'); const dayNum = btn.getAttribute('data-day-num');
const dateVal = btn.getAttribute('data-date'); const dateVal = btn.getAttribute('data-date');
@@ -1846,9 +1864,10 @@
contentVal = ''; contentVal = '';
} }
const statusText = document.getElementById('save-status'); const statusText = document.getElementById('save-status');
if (statusText) {
statusText.textContent = "Kaydediliyor..."; statusText.textContent = "Kaydediliyor...";
statusText.className = "text-xs font-semibold text-slate-400 animate-pulse"; statusText.className = "text-xs font-semibold text-slate-400 animate-pulse";
}
fetch("{{ route('intern.save-journal') }}", { fetch("{{ route('intern.save-journal') }}", {
method: "POST", method: "POST",
@@ -1865,8 +1884,10 @@
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
if (data.success) { if (data.success) {
statusText.textContent = "Başarıyla kaydedildi."; if (statusText) {
statusText.className = "text-xs font-semibold text-green-600"; statusText.textContent = "Başarıyla kaydedildi.";
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'); btn.setAttribute('data-approved', '0');
@@ -1885,20 +1906,25 @@
updateEditorStatusBadge(false, hasContent); updateEditorStatusBadge(false, hasContent);
} else { } else {
statusText.textContent = data.message || "Kaydedilemedi."; if (statusText) {
statusText.className = "text-xs font-semibold text-red-600"; statusText.textContent = data.message || "Kaydedilemedi.";
statusText.className = "text-xs font-semibold text-red-600";
}
} }
}) })
.catch(err => { .catch(err => {
console.error(err); console.error(err);
statusText.textContent = "Bağlantı hatası oluştu."; if (statusText) {
statusText.className = "text-xs font-semibold text-red-600"; statusText.textContent = "Bağlantı hatası oluştu.";
statusText.className = "text-xs font-semibold text-red-600";
}
}); });
} }
function openPrintModal() { function openPrintModal() {
const modal = document.getElementById('print-modal'); const modal = document.getElementById('print-modal');
const card = document.getElementById('print-modal-card'); const card = document.getElementById('print-modal-card');
if (!modal || !card) return;
modal.classList.remove('hidden'); modal.classList.remove('hidden');
setTimeout(() => { setTimeout(() => {
card.classList.remove('scale-95', 'opacity-0'); card.classList.remove('scale-95', 'opacity-0');
@@ -1909,6 +1935,7 @@
function closePrintModal() { function closePrintModal() {
const modal = document.getElementById('print-modal'); const modal = document.getElementById('print-modal');
const card = document.getElementById('print-modal-card'); const card = document.getElementById('print-modal-card');
if (!modal || !card) return;
card.classList.remove('scale-100', 'opacity-100'); card.classList.remove('scale-100', 'opacity-100');
card.classList.add('scale-95', 'opacity-0'); card.classList.add('scale-95', 'opacity-0');
setTimeout(() => { setTimeout(() => {
@@ -1925,18 +1952,24 @@
if (fileSizeMB > 50) { if (fileSizeMB > 50) {
alert('Dosya boyutu 50MB\'ı aşamaz.'); alert('Dosya boyutu 50MB\'ı aşamaz.');
input.value = ''; input.value = '';
fileNameElement.textContent = ''; if (fileNameElement) fileNameElement.textContent = '';
submitBtn.disabled = true; if (submitBtn) {
submitBtn.classList.add('opacity-50', 'cursor-not-allowed'); submitBtn.disabled = true;
submitBtn.classList.add('opacity-50', 'cursor-not-allowed');
}
return; return;
} }
fileNameElement.textContent = 'Seçilen dosya: ' + file.name + ' (' + fileSizeMB.toFixed(2) + ' MB)'; if (fileNameElement) fileNameElement.textContent = 'Seçilen dosya: ' + file.name + ' (' + fileSizeMB.toFixed(2) + ' MB)';
submitBtn.disabled = false; if (submitBtn) {
submitBtn.classList.remove('opacity-50', 'cursor-not-allowed'); submitBtn.disabled = false;
submitBtn.classList.remove('opacity-50', 'cursor-not-allowed');
}
} else { } else {
fileNameElement.textContent = ''; if (fileNameElement) fileNameElement.textContent = '';
submitBtn.disabled = true; if (submitBtn) {
submitBtn.classList.add('opacity-50', 'cursor-not-allowed'); submitBtn.disabled = true;
submitBtn.classList.add('opacity-50', 'cursor-not-allowed');
}
} }
} }
@@ -1976,10 +2009,15 @@
} }
function calculateEndDateFrontend() { function calculateEndDateFrontend() {
const startDateVal = document.getElementById('internship_start_date').value; const startDateEl = document.getElementById('internship_start_date');
const totalDaysVal = document.getElementById('internship_total_days').value; const totalDaysEl = document.getElementById('internship_total_days');
const endDateInput = document.getElementById('internship_end_date'); const endDateInput = document.getElementById('internship_end_date');
if (!startDateEl || !totalDaysEl || !endDateInput) return;
const startDateVal = startDateEl.value;
const totalDaysVal = totalDaysEl.value;
if (!startDateVal || !totalDaysVal || totalDaysVal <= 0) { if (!startDateVal || !totalDaysVal || totalDaysVal <= 0) {
return; return;
} }