384 lines
14 KiB
JavaScript
384 lines
14 KiB
JavaScript
|
||
// 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');
|
||
}
|
||
});
|
||
});
|
||
|
||
let quill;
|
||
|
||
// Tab Switch Logic
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
// Initialize Quill editor
|
||
quill = new Quill('#editor-content-quill', {
|
||
theme: 'snow',
|
||
modules: {
|
||
toolbar: [
|
||
['bold', 'italic', 'underline', 'strike'], // toggled buttons
|
||
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
|
||
['clean'] // remove formatting button
|
||
]
|
||
}
|
||
});
|
||
|
||
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');
|
||
}
|
||
});
|
||
});
|
||
|
||
// Handle initial state of date logic
|
||
calculateEndDateFrontend();
|
||
|
||
// Fetch Github commits in memory if repo is set
|
||
fetchAllCommitsInMemory();
|
||
|
||
// Select first day of the notebook workspace on load
|
||
selectNotebookDay(0);
|
||
});
|
||
|
||
const githubRepoUrl = "dummy";
|
||
let allGithubCommits = {};
|
||
let activeDayIdx = 0;
|
||
|
||
function fetchAllCommitsInMemory() {
|
||
if (!githubRepoUrl) return;
|
||
|
||
let repoClean = githubRepoUrl.replace(/https?:\/\/(www\.)?github\.com\//i, '');
|
||
repoClean = repoClean.replace(/\/$/, '');
|
||
const parts = repoClean.split('/');
|
||
if (parts.length < 2) 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) throw new Error('API Error');
|
||
return response.json();
|
||
})
|
||
.then(commits => {
|
||
if (!Array.isArray(commits)) return;
|
||
commits.forEach(item => {
|
||
const dateStr = item.commit.author.date;
|
||
if (dateStr) {
|
||
const dateOnly = dateStr.substring(0, 10);
|
||
if (!allGithubCommits[dateOnly]) {
|
||
allGithubCommits[dateOnly] = [];
|
||
}
|
||
allGithubCommits[dateOnly].push(item);
|
||
}
|
||
});
|
||
})
|
||
.catch(err => {
|
||
console.warn('Commits could not be pre-loaded in memory.', err);
|
||
});
|
||
}
|
||
|
||
function selectNotebookDay(idx) {
|
||
const oldBtn = document.getElementById(`btn-day-${activeDayIdx}`);
|
||
if (oldBtn) {
|
||
oldBtn.classList.remove('border-blue-200', 'bg-blue-50/50');
|
||
oldBtn.classList.add('border-slate-100', 'bg-white');
|
||
const oldTitle = oldBtn.querySelector('span.text-xs');
|
||
if (oldTitle) {
|
||
oldTitle.classList.remove('text-blue-700');
|
||
oldTitle.classList.add('text-slate-800');
|
||
}
|
||
}
|
||
|
||
activeDayIdx = idx;
|
||
const newBtn = document.getElementById(`btn-day-${idx}`);
|
||
if (newBtn) {
|
||
newBtn.classList.add('border-blue-200', 'bg-blue-50/50');
|
||
newBtn.classList.remove('border-slate-100', 'bg-white');
|
||
const newTitle = newBtn.querySelector('span.text-xs');
|
||
if (newTitle) {
|
||
newTitle.classList.add('text-blue-700');
|
||
newTitle.classList.remove('text-slate-800');
|
||
}
|
||
|
||
const dayNum = newBtn.getAttribute('data-day-num');
|
||
const dateVal = newBtn.getAttribute('data-date');
|
||
const dateFormatted = newBtn.getAttribute('data-formatted-date');
|
||
const savedContent = newBtn.getAttribute('data-saved-content');
|
||
|
||
document.getElementById('editor-day-title').textContent = `${dayNum}. Gün`;
|
||
document.getElementById('editor-day-date').textContent = dateFormatted;
|
||
|
||
quill.root.innerHTML = savedContent || '';
|
||
document.getElementById('save-status').textContent = '';
|
||
|
||
// Future validation
|
||
const dateParts = dateVal.split('-');
|
||
const selectedDate = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
|
||
const today = new Date();
|
||
today.setHours(0,0,0,0);
|
||
|
||
const isFuture = selectedDate > today;
|
||
const warningBlock = document.getElementById('future-warning');
|
||
const saveBtn = document.getElementById('save-btn');
|
||
const gitBtn = document.querySelector('button[onclick="fillFromGithub()"]');
|
||
|
||
if (isFuture) {
|
||
warningBlock.classList.remove('hidden');
|
||
quill.enable(false);
|
||
saveBtn.disabled = true;
|
||
saveBtn.classList.add('opacity-50', 'cursor-not-allowed');
|
||
if (gitBtn) {
|
||
gitBtn.disabled = true;
|
||
gitBtn.classList.add('opacity-50', 'cursor-not-allowed');
|
||
}
|
||
} else {
|
||
warningBlock.classList.add('hidden');
|
||
quill.enable(true);
|
||
saveBtn.disabled = false;
|
||
saveBtn.classList.remove('opacity-50', 'cursor-not-allowed');
|
||
if (gitBtn) {
|
||
gitBtn.disabled = false;
|
||
gitBtn.classList.remove('opacity-50', 'cursor-not-allowed');
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
function fillFromGithub() {
|
||
const btn = document.getElementById(`btn-day-${activeDayIdx}`);
|
||
if (!btn) return;
|
||
|
||
const dateVal = btn.getAttribute('data-date');
|
||
const dayCommits = allGithubCommits[dateVal] || [];
|
||
|
||
if (dayCommits.length === 0) {
|
||
alert("Bu staj gününe ait GitHub commit'i bulunamadı. Lütfen commit attığınızdan ve tarihin doğru olduğundan emin olun.");
|
||
return;
|
||
}
|
||
|
||
let commitHtml = "<ul>";
|
||
const sorted = [...dayCommits].reverse();
|
||
sorted.forEach(c => {
|
||
const msg = c.commit.message;
|
||
const sha = c.sha.substring(0, 7);
|
||
const authorDate = new Date(c.commit.author.date);
|
||
const time = authorDate.toLocaleTimeString('tr-TR', { hour: '2-digit', minute: '2-digit' });
|
||
commitHtml += `<li><strong>[${time}]</strong> (<em>${sha}</em>) ${msg}</li>`;
|
||
});
|
||
commitHtml += "</ul>";
|
||
|
||
const currentHtml = quill.root.innerHTML.trim();
|
||
if (currentHtml !== "" && currentHtml !== "<p><br></p>") {
|
||
if (confirm("Mevcut rapor içeriğinizin sonuna bu günün commitlerini eklemek ister misiniz? (Hayır derseniz mevcut içerik silinip commitler yazılır.)")) {
|
||
quill.root.innerHTML = currentHtml + "<br><br>" + commitHtml;
|
||
} else {
|
||
quill.root.innerHTML = commitHtml;
|
||
}
|
||
} else {
|
||
quill.root.innerHTML = commitHtml;
|
||
}
|
||
}
|
||
|
||
function saveActiveDay() {
|
||
const btn = document.getElementById(`btn-day-${activeDayIdx}`);
|
||
if (!btn) return;
|
||
|
||
const dayNum = btn.getAttribute('data-day-num');
|
||
const dateVal = btn.getAttribute('data-date');
|
||
let contentVal = quill.root.innerHTML;
|
||
if (contentVal === '<p><br></p>') {
|
||
contentVal = '';
|
||
}
|
||
const statusText = document.getElementById('save-status');
|
||
|
||
statusText.textContent = "Kaydediliyor...";
|
||
statusText.className = "text-xs font-semibold text-slate-400 animate-pulse";
|
||
|
||
fetch(""dummy"", {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
"X-CSRF-TOKEN": ""dummy""
|
||
},
|
||
body: JSON.stringify({
|
||
day_number: dayNum,
|
||
date: dateVal,
|
||
content: contentVal
|
||
})
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
statusText.textContent = "Başarıyla kaydedildi.";
|
||
statusText.className = "text-xs font-semibold text-green-600";
|
||
|
||
btn.setAttribute('data-saved-content', contentVal);
|
||
|
||
const badge = document.getElementById(`badge-day-${activeDayIdx}`);
|
||
if (badge) {
|
||
if (contentVal.trim() !== '') {
|
||
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";
|
||
} else {
|
||
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";
|
||
}
|
||
}
|
||
} else {
|
||
statusText.textContent = data.message || "Kaydedilemedi.";
|
||
statusText.className = "text-xs font-semibold text-red-600";
|
||
}
|
||
})
|
||
.catch(err => {
|
||
console.error(err);
|
||
statusText.textContent = "Bağlantı hatası oluştu.";
|
||
statusText.className = "text-xs font-semibold text-red-600";
|
||
});
|
||
}
|
||
|
||
function openPrintModal() {
|
||
const modal = document.getElementById('print-modal');
|
||
const card = document.getElementById('print-modal-card');
|
||
modal.classList.remove('hidden');
|
||
setTimeout(() => {
|
||
card.classList.remove('scale-95', 'opacity-0');
|
||
card.classList.add('scale-100', 'opacity-100');
|
||
}, 10);
|
||
}
|
||
|
||
function closePrintModal() {
|
||
const modal = document.getElementById('print-modal');
|
||
const card = document.getElementById('print-modal-card');
|
||
card.classList.remove('scale-100', 'opacity-100');
|
||
card.classList.add('scale-95', 'opacity-0');
|
||
setTimeout(() => {
|
||
modal.classList.add('hidden');
|
||
}, 300);
|
||
}
|
||
|
||
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);
|
||
});
|
||
}
|