'; return;
}
swg_taskTemplates.forEach(template => {
const button = document.createElement('button');
button.type = 'button';
button.className = 'swg-button swg-quick-add-btn';
button.textContent = template.name;
button.onclick = () => swg_quickAddTaskFromTemplate(template.id);
container.appendChild(button);
});
}
function swg_quickAddTaskFromTemplate(templateId) {
const template = swg_taskTemplates.find(t => t.id == templateId);
if (template) {
swg_clearWorklogEntryForm(false); // Clear form but keep date
document.getElementById('swg_logTaskDescription').value = template.defaultDescription || template.name;
document.getElementById('swg_logCategory').value = template.defaultCategory;
// Suggest next available start time
const logDate = document.getElementById('swg_logDate').value;
const logsForDay = swg_dailyWorklogEntries.filter(log => log.date === logDate).sort((a,b) => a.endTime.localeCompare(b.endTime));
let suggestedStartTime = "09:00"; // Default start
if (logsForDay.length > 0) {
suggestedStartTime = logsForDay[logsForDay.length - 1].endTime;
}
document.getElementById('swg_logStartTime').value = suggestedStartTime;
if (template.defaultEstMinutes > 0) {
const startMinutes = swg_calculateDurationMinutes("00:00", suggestedStartTime); // Convert HH:MM to minutes from midnight
const endTotalMinutes = startMinutes + template.defaultEstMinutes;
const endHours = String(Math.floor(endTotalMinutes / 60) % 24).padStart(2, '0');
const endMinutes = String(endTotalMinutes % 60).padStart(2, '0');
document.getElementById('swg_logEndTime').value = `${endHours}:${endMinutes}`;
}
document.getElementById('swg_logTaskDescription').focus(); // Focus on description for potential minor edits
}
}
function swg_clearWorklogEntryForm(clearDate = false) {
document.getElementById('swg_worklogEntryId').value = '';
if(clearDate) document.getElementById('swg_logDate').value = SWG_CONTEXT_DATE_STR;
document.getElementById('swg_logTaskDescription').value = '';
document.getElementById('swg_logStartTime').value = '';
document.getElementById('swg_logEndTime').value = '';
document.getElementById('swg_logCategory').value = '';
document.getElementById('swg_logNotes').value = '';
document.getElementById('swg_saveWorklogEntryButton').textContent = 'Add/Update Entry';
const cancelBtn = document.getElementById('swg_cancelEntryEditBtn');
if(cancelBtn) cancelBtn.style.display = 'none';
}
function swg_saveWorklogEntry() {
const id = document.getElementById('swg_worklogEntryId').value;
const date = document.getElementById('swg_logDate').value;
const description = document.getElementById('swg_logTaskDescription').value.trim();
const startTime = document.getElementById('swg_logStartTime').value;
const endTime = document.getElementById('swg_logEndTime').value;
const category = document.getElementById('swg_logCategory').value.trim();
const notes = document.getElementById('swg_logNotes').value.trim();
const durationMinutes = swg_calculateDurationMinutes(startTime, endTime);
if (!date) { alert("Please select a date for the worklog entry."); return; }
if (!description || !startTime || !endTime || !category) { alert("Description, Start/End Times, and Category are required."); return; }
if (durationMinutes <= 0) { alert("End Time must be after Start Time for a valid duration."); return; }
const entry = {date, description, startTime, endTime, durationMinutes, category, notes};
if (id) {
const index = swg_dailyWorklogEntries.findIndex(e => e.id == id);
if(index > -1) swg_dailyWorklogEntries[index] = {...swg_dailyWorklogEntries[index], ...entry};
} else {
swg_dailyWorklogEntries.push({id: Date.now(), ...entry});
}
swg_clearWorklogEntryForm(false); // Keep date, clear rest
swg_renderDailyLogTable();
}
function swg_editWorklogEntry(entryId) {
const entry = swg_dailyWorklogEntries.find(e => e.id == entryId);
if (entry) {
document.getElementById('swg_worklogEntryId').value = entry.id;
document.getElementById('swg_logDate').value = entry.date; // Ensure date is correct
document.getElementById('swg_currentLogDateDisplay').textContent = entry.date;
document.getElementById('swg_logTaskDescription').value = entry.description;
document.getElementById('swg_logStartTime').value = entry.startTime;
document.getElementById('swg_logEndTime').value = entry.endTime;
document.getElementById('swg_logCategory').value = entry.category;
document.getElementById('swg_logNotes').value = entry.notes;
document.getElementById('swg_saveWorklogEntryButton').textContent = 'Update Entry';
const cancelBtn = document.getElementById('swg_cancelEntryEditBtn');
if(cancelBtn) cancelBtn.style.display = 'inline-block';
}
}
function swg_deleteWorklogEntry(entryId) {
if (confirm("Delete this worklog entry?")) {
swg_dailyWorklogEntries = swg_dailyWorklogEntries.filter(e => e.id != entryId);
swg_renderDailyLogTable();
}
}
function swg_renderDailyLogTable() {
const currentDate = document.getElementById('swg_logDate').value;
const tbody = document.getElementById('swg_dailyLogTable')?.getElementsByTagName('tbody')[0];
if (!tbody) return;
tbody.innerHTML = '';
const entriesForDate = swg_dailyWorklogEntries.filter(e => e.date === currentDate).sort((a,b) => a.startTime.localeCompare(b.startTime));
let totalMinutesToday = 0;
const categoryTimes = {};
if (entriesForDate.length === 0) {
tbody.innerHTML = `
| No work logged for this date. |
`;
} else {
entriesForDate.forEach(entry => {
totalMinutesToday += entry.durationMinutes;
categoryTimes[entry.category] = (categoryTimes[entry.category] || 0) + entry.durationMinutes;
const row = tbody.insertRow();
row.insertCell().textContent = entry.description;
row.insertCell().textContent = entry.category;
row.insertCell().textContent = entry.startTime;
row.insertCell().textContent = entry.endTime;
row.insertCell().textContent = swg_formatMinutesToHHMM(entry.durationMinutes);
row.insertCell().textContent = entry.notes || '-';
const actionsCell = row.insertCell();
actionsCell.innerHTML = `
`;
});
}
document.getElementById('swg_logTotalTime').textContent = swg_formatMinutesToHHMM(totalMinutesToday);
const categorySummaryDiv = document.getElementById('swg_logCategorySummary');
categorySummaryDiv.innerHTML = '
Time by Category:
';
if (Object.keys(categoryTimes).length > 0) {
const ul = document.createElement('ul');
ul.style.paddingLeft = '20px'; ul.style.fontSize = '0.9em';
Object.entries(categoryTimes).sort((a,b)=>b[1]-a[1]).forEach(([cat, min]) => { // Sort by time desc
const li = document.createElement('li');
li.textContent = `${cat}: ${swg_formatMinutesToHHMM(min)}`;
ul.appendChild(li);
});
categorySummaryDiv.appendChild(ul);
} else {
categorySummaryDiv.innerHTML += '
No categories logged.
';
}
}
// PDF Download
function swg_downloadPDF() {
const logDate = document.getElementById('swg_logDate').value;
const entriesForDate = swg_dailyWorklogEntries.filter(e => e.date === logDate).sort((a,b) => a.startTime.localeCompare(b.startTime));
if (entriesForDate.length === 0) {
alert("No worklog entries for this date to download."); return;
}
const doc = new jsPDF();
const primaryColorPDF = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim();
const textColorPDF = getComputedStyle(document.documentElement).getPropertyValue('--text-color').trim();
const whiteColorPDF = '#FFFFFF';
doc.setFontSize(18); doc.setTextColor(primaryColorPDF);
doc.text("Daily Worklog Report", 14, 20);
doc.setFontSize(10); doc.setTextColor(textColorPDF);
doc.text(`Date: ${logDate}`, 14, 28);
doc.text(`Generated On: ${SWG_GENERATED_ON_STRING}`, 14, 33);
let currentY = 45;
let totalMinutes = 0;
const categoryTimesPDF = {};
entriesForDate.forEach(entry => {
totalMinutes += entry.durationMinutes;
categoryTimesPDF[entry.category] = (categoryTimesPDF[entry.category] || 0) + entry.durationMinutes;
});
doc.setFontSize(12); doc.setFont(undefined, 'bold'); doc.setTextColor(primaryColorPDF);
doc.text("Summary:", 14, currentY); currentY += 7;
doc.setFontSize(10); doc.setFont(undefined, 'normal'); doc.setTextColor(textColorPDF);
doc.text(`Total Hours Logged: ${swg_formatMinutesToHHMM(totalMinutes)}`, 16, currentY); currentY += 7;
doc.setFont(undefined, 'bold'); doc.text("Time by Category/Project:", 16, currentY); currentY +=6;
doc.setFont(undefined, 'normal');
if (Object.keys(categoryTimesPDF).length > 0) {
Object.entries(categoryTimesPDF).sort((a,b)=>b[1]-a[1]).forEach(([cat, min]) => {
if (currentY > 270) { doc.addPage(); currentY = 20;}
doc.text(`- ${cat}: ${swg_formatMinutesToHHMM(min)}`, 18, currentY); currentY +=5;
});
} else {
doc.text("- No categories logged.", 18, currentY); currentY +=5;
}
currentY += 5;
doc.setFontSize(12); doc.setFont(undefined, 'bold'); doc.setTextColor(primaryColorPDF);
if (currentY > 250) { doc.addPage(); currentY = 20; }
doc.text("Detailed Worklog:", 14, currentY); currentY += 7;
const tableData = entriesForDate.map(e => [
e.description, e.category, e.startTime, e.endTime, swg_formatMinutesToHHMM(e.durationMinutes), e.notes || '-'
]);
doc.autoTable({
startY: currentY,
head: [['Description', 'Category/Project', 'Start', 'End', 'Duration', 'Notes']],
body: tableData,
theme: 'grid',
headStyles: { fillColor: primaryColorPDF, textColor: whiteColorPDF, fontSize: 9 },
styles: { fontSize: 8, cellPadding: 1.5, overflow: 'linebreak' },
columnStyles: { 0: { cellWidth: 60 }, 5: { cellWidth: 'auto'} }
});
doc.save(`Daily_Worklog_${logDate}.pdf`);
}