Employee Task Reporting Tool

Setup

Log New Task

Task Report

Total Time: 0h 0m

Error: Tool UI elements failed to load correctly. Check HTML IDs.

'; return; // Stop script execution } // --- State & localStorage --- const NAME_STORAGE_KEY = 'taskReporter_employeeName'; const TASKS_STORAGE_KEY = 'taskReporter_tasks'; let employeeName = ''; let tasks = []; // --- Utility Functions --- // (Same as before - loadData, saveData, generateId, sanitizeHTML, isValidDateString, formatDate..., dateDiff..., addDays..., parseTimeInput, formatTimeMinutes, getStartOfWeek) const loadData = () => { try { employeeName = localStorage.getItem(NAME_STORAGE_KEY) || ''; const st=JSON.parse(localStorage.getItem(TASKS_STORAGE_KEY)); if(Array.isArray(st))tasks=st; console.log("Data loaded:",{name:employeeName, tasks:tasks.length}); } catch(e){ console.error("Err load data:",e); employeeName=''; tasks=[];}}; const saveData = () => { try { localStorage.setItem(NAME_STORAGE_KEY, employeeName); localStorage.setItem(TASKS_STORAGE_KEY, JSON.stringify(tasks)); console.log("Data saved."); } catch(e){ console.error("Err save data:",e); alert("Error saving data.");}}; const generateId = () =>'_'+Math.random().toString(36).substr(2,9); const sanitizeHTML = (str)=>(temp=>{temp.textContent=str; return temp.innerHTML;})(document.createElement('div')); const isValidDateString = (ds)=>{if(!ds||!/^\d{4}-\d{2}-\d{2}$/.test(ds))return false;const d=new Date(ds+'T00:00:00Z');if(isNaN(d.getTime()))return false;const p=ds.split('-');return d.getUTCFullYear()===parseInt(p[0],10)&&d.getUTCMonth()===parseInt(p[1],10)-1&&d.getUTCDate()===parseInt(p[2],10);}; const formatDateForDisplay = (ds)=>{if(!isValidDateString(ds))return'N/A';try{const d=new Date(ds+'T00:00:00Z');return d.toLocaleDateString(undefined,{year:'numeric',month:'short',day:'numeric',weekday:'short', timeZone:'UTC'});}catch(e){return'Invalid';}}; const formatDateShort = (ds) => {if(!isValidDateString(ds))return'N/A';try{const d=new Date(ds+'T00:00:00Z');return d.toLocaleDateString(undefined,{month:'short',day:'numeric', timeZone:'UTC'});}catch(e){return'Invalid';}}; const formatDateWeekday = (ds) => {if(!isValidDateString(ds))return'N/A';try{const d=new Date(ds+'T00:00:00Z');return d.toLocaleDateString(undefined,{weekday:'long', timeZone:'UTC'});}catch(e){return'Invalid';}}; const getTodayDateString = ()=>new Date().toISOString().split('T')[0]; const parseTimeInput = (durStr)=>{durStr=(durStr||'').toLowerCase().replace(/ /g,'');let mins=0;if(durStr.includes(':')){const p=durStr.split(':');const h=parseInt(p[0],10),m=parseInt(p[1],10);if(!isNaN(h)&&!isNaN(m))mins=h*60+m;}else if(durStr.endsWith('h')){const h=parseFloat(durStr.replace('h',''));if(!isNaN(h))mins=Math.round(h*60);}else if(durStr.endsWith('m')){const m=parseInt(durStr.replace('m',''),10);if(!isNaN(m))mins=m;}else{const h=parseFloat(durStr);if(!isNaN(h))mins=Math.round(h*60);} return mins>0?mins:null;}; const formatTimeMinutes = (tm)=>{if(tm===null||tm===undefined||tm<0)return'0m';if(tm===0)return'0m';const h=Math.floor(tm/60),m=tm%60;let r='';if(h>0)r+=`${h}h `;if(m>0)r+=`${m}m`;return r.trim();}; function getStartOfWeek(ds, startDay){if(!isValidDateString(ds))return null;const d=new Date(ds+'T00:00:00Z');const day=d.getUTCDay();const diff=d.getUTCDate()-day+(day===0&&startDay===1?-6:startDay);const mon=new Date(Date.UTC(d.getUTCFullYear(),d.getUTCMonth(),diff));return mon.toISOString().split('T')[0];} function addDaysToDate(ds, days){if (!isValidDateString(ds)) return null; try { const d=new Date(ds+'T00:00:00Z'); if(isNaN(d.getTime()))return null; d.setUTCDate(d.getUTCDate()+days); if(isNaN(d.getTime()))return null; return d.toISOString().split('T')[0];} catch(e){return null;}} // --- Setup --- // (Same as before - populate name, add listeners) employeeNameInput.value = employeeName; employeeNameInput.addEventListener('change', ()=>{employeeName=employeeNameInput.value.trim(); localStorage.setItem(NAME_STORAGE_KEY,employeeName); renderReportDisplay();}); reportTypeSelect.addEventListener('change', ()=>{ updateDateLabel(); renderReportDisplay(); }); weekStartDaySelect.addEventListener('change', ()=>{ if(reportTypeSelect.value==='Weekly'){ renderReportDisplay(); }}); dateSelectInput.addEventListener('change', ()=>{ renderReportDisplay(); }); function updateDateLabel(){ dateSelectLabel.textContent = reportTypeSelect.value === 'Weekly' ? 'Week Starting:' : 'Date:'; } // --- Task Logging --- // (Same as before - clearTaskForm, populateTaskForm) const clearTaskForm = ()=>{ editTaskIdInput.value=''; taskDescriptionInput.value=''; taskProjectInput.value=''; taskTimeInput.value=''; addUpdateLogBtn.textContent='Add Task Log'; cancelEditLogBtn.style.display='none'; }; const populateTaskForm = (tid)=>{ const task=tasks.find(t=>t.id===tid); if(task){ editTaskIdInput.value=task.id; taskDescriptionInput.value=task.description; taskProjectInput.value=task.project||''; taskTimeInput.value=formatTimeMinutes(task.timeMinutes); addUpdateLogBtn.textContent='Update Task Log'; cancelEditLogBtn.style.display='inline-block'; taskDescriptionInput.focus();} }; // --- DEBUG: Attach listener to form submit --- console.log("Attempting to attach submit listener to task form..."); taskEntryForm.addEventListener('submit', (e) => { console.log("DEBUG: Task entry form submitted!"); // Check if this appears e.preventDefault(); const id = editTaskIdInput.value; const description = taskDescriptionInput.value.trim(); const project = taskProjectInput.value.trim(); const timeStr = taskTimeInput.value.trim(); const timeMinutes = parseTimeInput(timeStr); const selectedDate = dateSelectInput.value; // --- DEBUG: Log values before checks --- console.log("DEBUG: Task Form values -", { id, description, project, timeStr, timeMinutes, selectedDate }); if (!description || timeMinutes === null) { console.warn("DEBUG: Submit prevented - Description or Time invalid."); alert("Please enter valid task description and time spent (e.g., 1.5h, 45m, 2:30)."); return; } if (!isValidDateString(selectedDate)) { console.warn("DEBUG: Submit prevented - Invalid date selected."); alert("Please select a valid date for the report."); return; } const taskDate = selectedDate; // Task is always logged against the selected date in the picker if (id) { // Update console.log("Updating task:", id); tasks = tasks.map(t => t.id === id ? { ...t, date: taskDate, description, project, timeMinutes } : t); } else { // Add console.log("Adding new task for date:", taskDate); tasks.push({ id: generateId(), date: taskDate, description, project, timeMinutes }); } saveData(); clearTaskForm(); renderReportDisplay(); // Re-render the current view console.log("Task log added/updated successfully."); }); console.log("Task form submit listener attached."); cancelEditLogBtn.addEventListener('click', clearTaskForm); // Event delegation for edit/delete task logs // (Same as before) taskLogListDiv.addEventListener('click', (e)=>{ if(e.target.matches('.edit-log-btn, .edit-log-btn *')){const btn=e.target.closest('.edit-log-btn'); const tid=btn?.dataset.id; console.log("Edit task:", tid); if(tid){populateTaskForm(tid);}} else if(e.target.matches('.delete-log-btn, .delete-log-btn *')){const btn=e.target.closest('.delete-log-btn'); const tid=btn?.dataset.id; console.log("Delete task:", tid); if(tid&&confirm('Delete task log?')){tasks=tasks.filter(t=>t.id!==tid); saveData(); if(editTaskIdInput.value===tid){clearTaskForm();} renderReportDisplay();}}}); // --- Display Rendering --- // (Same as before - renderReportDisplay, createTaskLiElement) const renderReportDisplay = ()=>{ console.log("Rendering report display..."); const rType=reportTypeSelect.value; const selVal=dateSelectInput.value; const wkStartDay=parseInt(weekStartDaySelect.value,10); if(!isValidDateString(selVal)){console.warn("Render prevented: Invalid date", selVal); reportPeriodHeader.textContent="Invalid Date"; taskLogListDiv.innerHTML='

Select valid date.

'; totalTimeSummaryDiv.innerHTML='Total: 0h 0m'; return;} let startDS, endDS, pLabel=''; let filtTasks=[]; if(rType==='Weekly'){startDS=getStartOfWeek(selVal,wkStartDay); if(!startDS)return; endDS=addDaysToDate(startDS,6); if(!endDS)return; pLabel=`Week: ${formatDateShort(startDS)} - ${formatDateShort(endDS)}`; filtTasks=tasks.filter(t=>isValidDateString(t.date)&&dateDiffInDays(startDS,t.date)>=0&&dateDiffInDays(t.date,endDS)>=0);} else {startDS=selVal; endDS=selVal; pLabel=`Date: ${formatDateForDisplay(startDS)}`; filtTasks=tasks.filter(t=>t.date===startDS);} reportPeriodHeader.textContent=`Task Report for ${pLabel}`; taskLogListDiv.innerHTML=''; let totMins=0; if(rType==='Weekly'){const tasksByDay={}; for(let i=0;i<7;i++){const cd=addDaysToDate(startDS,i); if(cd)tasksByDay[cd]=[];} filtTasks.forEach(t=>{if(tasksByDay[t.date])tasksByDay[t.date].push(t); totMins+=t.timeMinutes;}); for(let i=0;i<7;i++){const cd=addDaysToDate(startDS,i); if(!cd)continue; const dTasks=tasksByDay[cd]||[]; const dGrp=document.createElement('div'); dGrp.className='day-group'; const dHead=document.createElement('h5'); dHead.textContent=`${formatDateWeekday(cd)} (${formatDateShort(cd)})`; dGrp.appendChild(dHead); const dUl=document.createElement('ul'); if(dTasks.length>0){dTasks.sort((a,b)=>a.description.localeCompare(b.description)); dTasks.forEach(t=>{dUl.appendChild(createTaskLiElement(t));});} else {dUl.innerHTML='
  • No tasks.
  • ';} dGrp.appendChild(dUl); taskLogListDiv.appendChild(dGrp);}} else {const dUl=document.createElement('ul'); if(filtTasks.length>0){filtTasks.sort((a,b)=>a.description.localeCompare(b.description)); filtTasks.forEach(t=>{dUl.appendChild(createTaskLiElement(t)); totMins+=t.timeMinutes;});} else {dUl.innerHTML='
  • No tasks.
  • ';} taskLogListDiv.appendChild(dUl);} totalTimeSummaryDiv.innerHTML=`Total Time: ${formatTimeMinutes(totMins)}`; }; const createTaskLiElement = (t)=>{const li=document.createElement('li'); li.innerHTML=`
    ${sanitizeHTML(t.description)} ${t.project?`(${sanitizeHTML(t.project)})`:''}
    ${formatTimeMinutes(t.timeMinutes)}
    `; return li;}; // --- PDF Download Logic --- // (Same prepare function as before) const preparePdfContent = () => { pdfOutputArea.innerHTML=''; const rType=reportTypeSelect.value; const selVal=dateSelectInput.value; const wkStartDay=parseInt(weekStartDaySelect.value,10); const name=employeeName||'Unknown Employee'; if(!isValidDateString(selVal))return null; let startDS, endDS, pLabel, pdfTitle; let filtTasks=[]; if(rType==='Weekly'){startDS=getStartOfWeek(selVal,wkStartDay); if(!startDS)return null; endDS=addDaysToDate(startDS,6); if(!endDS)return null; pLabel=`Week: ${formatDateShort(startDS)} - ${formatDateShort(endDS)}`; pdfTitle=`Weekly_Report_${name.replace(/ /g,'_')}_${startDS}`; filtTasks=tasks.filter(t=>isValidDateString(t.date)&&dateDiffInDays(startDS,t.date)>=0&&dateDiffInDays(t.date,endDS)>=0);} else {startDS=selVal; endDS=selVal; pLabel=`Date: ${formatDateForDisplay(startDS)}`; pdfTitle=`Daily_Report_${name.replace(/ /g,'_')}_${startDS}`; filtTasks=tasks.filter(t=>t.date===startDS);} let html=`

    Task Report

    ${sanitizeHTML(name)} - ${pLabel}

    `; let totMins=0; if(rType==='Weekly'){const tasksByDay={}; for(let i=0;i<7;i++){const d=addDaysToDate(startDS,i); if(d)tasksByDay[d]=[];} filtTasks.forEach(t=>{if(tasksByDay[t.date])tasksByDay[t.date].push(t); totMins+=t.timeMinutes;}); for(let i=0;i<7;i++){const cd=addDaysToDate(startDS,i); if(!cd)continue; const dTasks=tasksByDay[cd]||[]; if(dTasks.length>0){html+=`

    ${formatDateWeekday(cd)} (${formatDateShort(cd)})

    `; html+=''; dTasks.sort((a,b)=>a.description.localeCompare(b.description)); dTasks.forEach(t=>{html+=``;}); html+='
    TaskProject/ClientTime
    ${sanitizeHTML(t.description)}${sanitizeHTML(t.project||'-')}${formatTimeMinutes(t.timeMinutes)}
    ';}}} else {html+=''; if(filtTasks.length>0){filtTasks.sort((a,b)=>a.description.localeCompare(b.description)); filtTasks.forEach(t=>{html+=``; totMins+=t.timeMinutes;});} else {html+='';} html+='
    TaskProject/ClientTime
    ${sanitizeHTML(t.description)}${sanitizeHTML(t.project||'-')}${formatTimeMinutes(t.timeMinutes)}
    No tasks.
    ';} html+='
    Total Time'+formatTimeMinutes(totMins)+'
    '; pdfOutputArea.innerHTML=html; return pdfTitle.replace(/[^a-z0-9]/gi,'_').toLowerCase();}; // --- DEBUG: Attach listener to PDF download button --- console.log("Attempting to attach click listener to download button..."); downloadPdfBtn.addEventListener('click', async () => { console.log("DEBUG: Download PDF button clicked!"); // Check if this appears const selectedDate = dateSelectInput.value; // Use current date selection console.log(`DEBUG: Date for PDF: ${selectedDate}`); if (!isValidDateString(selectedDate)) { console.warn("DEBUG: PDF download prevented - Invalid date selected in input."); alert("Please select a valid date for the report."); return; } // Prepare the content based on current selections console.log("DEBUG: Preparing PDF content..."); const pdfTitle = preparePdfContent(); // This function uses current selections internally if (!pdfTitle) { console.warn("DEBUG: PDF download prevented - Content preparation failed (returned null)."); alert("Could not prepare PDF content. Please check selected date and report type."); return; } console.log(`DEBUG: PDF Title prepared: ${pdfTitle}`); pdfOutputArea.style.display = 'block'; container.style.boxShadow = 'none'; container.classList.add('pdf-generating'); console.log("Starting PDF generation process..."); const { jsPDF } = window.jspdf; const pdfElement = pdfOutputArea; try { const canvas = await html2canvas(pdfElement, { scale: 2, useCORS: true, logging: true }); const imgData = canvas.toDataURL('image/png'); if (!imgData || imgData === 'data:,') { throw new Error("Canvas empty."); } const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfW = pdf.internal.pageSize.getWidth(), pdfH = pdf.internal.pageSize.getHeight(); const m = 40; const imgP = pdf.getImageProperties(imgData); if (imgP.width === 0 || imgP.height === 0) { throw new Error("Image zero dimensions."); } const imgW = pdfW - 2 * m; const imgH = (imgP.height * imgW) / imgP.width; let hL = imgH; let pos = m; pdf.addImage(imgData, 'PNG', m, pos, imgW, imgH); hL -= (pdfH - 2 * m); while (hL > 0) { console.log("Adding PDF page..."); pos = hL - imgH + m; pdf.addPage(); pdf.addImage(imgData, 'PNG', m, pos, imgW, imgH); hL -= (pdfH - 2 * m); } const filename = `${pdfTitle}.pdf`; console.log(`Saving PDF: ${filename}`); pdf.save(filename); } catch (error) { console.error("Err generating PDF:", error); alert(`Failed PDF: ${error.message}.`); } finally { pdfOutputArea.style.display = 'none'; pdfOutputArea.innerHTML = ''; container.style.boxShadow = ''; container.classList.remove('pdf-generating'); console.log("PDF cleanup."); } }); console.log("Download listener attached."); // --- Initial Load --- const initializeTool = () => { console.log("Running initializeTool..."); loadData(); employeeNameInput.value = employeeName; const todayStr = getTodayDateString(); dateSelectInput.value = todayStr; console.log("Default date:", todayStr); updateDateLabel(); renderReportDisplay(); console.log("Initialization complete."); }; if (window.jspdf && window.html2canvas) { initializeTool(); } else { console.error("Libs not loaded"); alert("Error: Libs not loaded."); } }); // --- END OF JAVASCRIPT ---

    In any professional setting, clear and consistent reporting on daily activities and progress is fundamental for effective project management, performance evaluation, and maintaining transparency within a team. Whether you’re a team lead needing to understand individual contributions, an employee aiming to showcase your work, or a freelancer tracking billable hours, manually compiling daily or weekly reports can be time-consuming and prone to inconsistencies. This is precisely where a dedicated online employee task reporting tool becomes an invaluable asset, streamlining the reporting process and providing accurate, organized insights.

    Our Online Employee Task Reporting Tool at WorkToolz.com is designed to simplify how individuals log their work and generate comprehensive reports effortlessly. We believe that tracking and reporting on tasks should be intuitive and add value to your workday, not become another burden. Our tool provides a clean, user-friendly interface that allows employees to quickly record their activities and time spent, while enabling managers to easily review summarized reports. There’s no complex software to download, no cumbersome accounts to create, and no confusing features to navigate. Simply open your web browser, and you can begin logging and reporting on tasks instantly.

    The core strength of our online employee task reporting tool lies in its straightforward approach to capturing essential work details and generating flexible reports. To start, simply enter your “Employee Name” for clear identification. A key feature is the “Report Type” selector, allowing you to choose between generating a “Daily Report” or a “Weekly Report.” This adaptability ensures the tool fits various reporting cycles within organizations. You can also easily select the specific “Date” for your daily report or define the “Week Starts On” day (e.g., Monday, Sunday) for your weekly reports.

    Logging new tasks is incredibly simple. For each activity, you can provide a “Task Description,” clearly outlining “What did you work on?” This ensures that all contributions are documented. You can also specify the “Project / Client (Optional)” associated with the task, which is invaluable for project-based work, client billing, or simply categorizing your efforts. Crucially, the “Time Spent” field allows you to precisely record the duration of each task, whether it’s in hours and minutes (e.g., 1.5h, 45m, 2:30). This detailed time tracking provides accurate data for productivity analysis, resource allocation, and even payroll or invoicing purposes. As you add tasks, they populate into the “Task Report for Date” section, providing a real-time summary of your logged activities and the “Total Time” accumulated for the selected period.

    The benefits of using an online employee task reporting tool like ours extend beyond simple time tracking. It fosters transparency and accountability, as both employees and managers gain a clear understanding of work accomplished. It streamlines communication, reducing the need for lengthy manual updates. For employees, it helps in self-reflection and personal time management. For managers, it provides valuable data for project progress monitoring, resource planning, and performance reviews. It’s particularly useful for remote teams, ensuring that productivity is visible and measurable regardless of location.

    For sharing reports with management, clients, or for personal record-keeping, our Employee Task Reporting Tool includes a convenient “Download Report as PDF” feature. With a single click, you can generate a professional, printable document of your daily or weekly task report, including all logged tasks, projects, time spent, and total time. This is ideal for formal submissions, client billing, or maintaining an organized history of your work contributions.

    Utilizing an free online employee task reporting tool like ours empowers individuals to track their efforts diligently and provides organizations with vital insights into operational efficiency. It simplifies a often-cumbersome process, leading to improved accountability, better time management, and more accurate project oversight. At WorkToolz.com, we provide the solution to bring clarity and structure to your task reporting needs.

    Scroll to Top