« Back to History
daily_work_report.php
|
20260721_154032.php
Initial Bulk Import
Copy Code
<?php error_reporting(E_ALL); ini_set('display_errors', 1); require_once __DIR__ . '/modules/auth/page_acl.php'; $ctx = page_require_access('daily_work_report'); $pdo = $ctx['pdo']; $company_id = (int)$ctx['company_id']; $today_date = date('Y-m-d'); $today_num = (int)date('j'); $day_name = date('l'); $tomorrow_name = date('l', strtotime('+1 day')); $task_type_options = ['daily', 'weekly', 'monthly', 'on_demand', 'temp']; require_once __DIR__ . '/helpers/activity_helper.php'; function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } function is_waiting_monthly_task(array $task, int $today_num): bool { if (($task['task_type'] ?? '') !== 'monthly') { return false; } $show_from = !empty($task['gray_date_start']) ? (int)$task['gray_date_start'] : null; $highlight_on = !empty($task['highlight_date']) ? (int)$task['highlight_date'] : null; if ($show_from === null || $today_num < $show_from) { return false; } return $highlight_on !== null && $today_num < $highlight_on; } function get_report_task_status(array $task): string { $status = trim(strtolower((string)($task['status'] ?? ''))); if (($task['task_type'] ?? '') === 'on_demand') { // DB stores: 'pending'=WAIT, 'in progress'=PEND, 'done'=COMP if ($status === 'done') return 'complete'; if ($status === 'in progress' || $status === 'in_progress') return 'pending'; return 'wait'; // 'pending' in DB or anything else = WAIT } if ($status === 'in_progress') { return 'in progress'; } return $status === '' ? 'pending' : $status; } function get_report_task_priority(array $task, int $today_num, string $tomorrow_name): int { $status = get_report_task_status($task); if (($task['task_type'] ?? '') === 'on_demand' && $status === 'wait') { return 4; } if (is_waiting_monthly_task($task, $today_num)) { return 4; } if (($task['task_type'] ?? '') === 'weekly' && ($task['rule_value'] ?? '') === $tomorrow_name) { return 4; } if ($status === 'pending') { return 1; } if ($status === 'complete' || $status === 'done') { return 2; } if ($status === 'in progress') { return 3; } return 1; } // --- ACTION: AJAX REMARK UPDATE (For Clean UI) --- if (isset($_GET['ajax_update_remark'])) { $tid = (int)$_GET['tid']; $remark = $_GET['remark']; $pdo->prepare("UPDATE daily_tasks SET remark = ? WHERE id = ? AND company_id = ?") ->execute([$remark, $tid, $company_id]); activity_update('production', 'daily_task_remark_update', $tid, 'Updated daily task remark'); echo "OK"; exit; } // --- 1. ACTION: STATUS UPDATE --- if (isset($_GET['set_status'])) { $tid = (int)$_GET['tid']; $new_status = trim((string)$_GET['set_status']); $task_type_stmt = $pdo->prepare("SELECT task_type FROM daily_tasks WHERE id = ? AND company_id = ? LIMIT 1"); $task_type_stmt->execute([$tid, $company_id]); $task_type = (string)$task_type_stmt->fetchColumn(); if ($task_type === 'on_demand') { // Map display value → DB value: wait→pending, pending→in progress, complete→done $map = ['wait' => 'pending', 'pending' => 'in progress', 'complete' => 'done']; $new_status = $map[strtolower($new_status)] ?? 'pending'; } $pdo->prepare("UPDATE daily_tasks SET status = ?, last_reset_date = ? WHERE id = ? AND company_id = ?") ->execute([$new_status, $today_date, $tid, $company_id]); activity_status_change('production', 'daily_task_status_update', $tid, 'Updated daily task status'); header("Location: daily_work_report.php"); exit; } // --- 2. ACTION: ADD TO TODAY (For On-Demand/Temp) --- if (isset($_GET['add_to_today'])) { $tid = (int)$_GET['add_to_today']; $pdo->prepare("UPDATE daily_tasks SET last_reset_date = ?, status = 'pending' WHERE id = ? AND company_id = ?") ->execute([$today_date, $tid, $company_id]); activity_update('production', 'daily_task_reset_today', $tid, 'Moved daily task to today'); header("Location: daily_work_report.php"); exit; } // --- 3. ACTION: DELETE MASTER TASK --- if (isset($_POST['delete_task'])) { $tid = (int)$_POST['delete_task']; $redirect_filter = isset($_POST['list_filter_type']) ? trim((string)$_POST['list_filter_type']) : ''; if (!in_array($redirect_filter, $task_type_options, true)) { $redirect_filter = ''; } $pdo->prepare("DELETE FROM daily_tasks WHERE id = ? AND company_id = ?") ->execute([$tid, $company_id]); activity_delete('production', 'daily_task_delete', $tid, 'Deleted daily task'); $redirect = 'daily_work_report.php'; if ($redirect_filter !== '') { $redirect .= '?filter_task_type=' . urlencode($redirect_filter); } header('Location: ' . $redirect); exit; } // --- 4. ACTION: SAVE/UPDATE MASTER --- if (isset($_POST['save_task'])) { $name = trim($_POST['task_name']); $type = $_POST['task_type']; $g_start = !empty($_POST['gray_start']) ? (int)$_POST['gray_start'] : null; $h_date = !empty($_POST['high_date']) ? (int)$_POST['high_date'] : null; $d_date = !empty($_POST['dis_date']) ? (int)$_POST['dis_date'] : null; $rule = trim($_POST['rule_value']); $tid = !empty($_POST['task_id']) ? (int)$_POST['task_id'] : null; if ($tid) { $pdo->prepare("UPDATE daily_tasks SET task_name=?, task_type=?, rule_value=?, gray_date_start=?, highlight_date=?, disappear_date=? WHERE id=? AND company_id=?") ->execute([$name, $type, $rule, $g_start, $h_date, $d_date, $tid, $company_id]); activity_update('production', 'daily_task_save', $tid, 'Updated daily task'); } else { // on_demand: store 'pending' in DB (= WAIT on display). Other types: 'pending' normally. $default_status = 'pending'; $pdo->prepare("INSERT INTO daily_tasks (company_id, task_name, task_type, rule_value, gray_date_start, highlight_date, disappear_date, last_reset_date, status) VALUES (?,?,?,?,?,?,?,?, ?)") ->execute([$company_id, $name, $type, $rule, $g_start, $h_date, $d_date, $today_date, $default_status]); activity_create('production', 'daily_task_create', (int)$pdo->lastInsertId(), 'Created daily task'); } header("Location: daily_work_report.php"); exit; } // --- 5. AUTO RESET & PERSISTENCE LOGIC --- $pdo->prepare("DELETE FROM daily_tasks WHERE company_id = ? AND task_type = 'temp' AND status = 'done' AND last_reset_date != ?") ->execute([$company_id, $today_date]); $pdo->prepare("UPDATE daily_tasks SET status = 'pending', last_reset_date = ? WHERE company_id = ? AND task_type = 'daily' AND last_reset_date != ?") ->execute([$today_date, $company_id, $today_date]); // On-demand next-day reset: 'done' (=COMP in DB) → 'pending' (=WAIT in DB) // Using PHP date comparison to avoid MySQL timezone issues $pdo->prepare("UPDATE daily_tasks SET status = 'pending', last_reset_date = ? WHERE company_id = ? AND task_type = 'on_demand' AND status = 'done' AND last_reset_date < ?") ->execute([$today_date, $company_id, $today_date]); $pdo->prepare("UPDATE daily_tasks SET last_reset_date = ? WHERE company_id = ? AND task_type = 'temp' AND status != 'done' AND last_reset_date != ?") ->execute([$today_date, $company_id, $today_date]); // --- 6. DATA FETCHING --- $filter_task_type = isset($_GET['filter_task_type']) ? trim((string)$_GET['filter_task_type']) : ''; if (!in_array($filter_task_type, $task_type_options, true)) { $filter_task_type = ''; } $st = $pdo->prepare("SELECT * FROM daily_tasks WHERE company_id = ? AND ( task_type = 'daily' OR (task_type = 'weekly' AND (rule_value = ? OR rule_value = ?)) OR (task_type = 'monthly' AND ($today_num >= gray_date_start AND ($today_num <= disappear_date OR disappear_date < gray_date_start))) OR (task_type = 'temp' AND last_reset_date = ?) OR task_type = 'on_demand' ) ORDER BY CASE WHEN task_name LIKE 'Loom%' THEN 1 ELSE 2 END, id ASC"); $st->execute([$company_id, $day_name, $tomorrow_name, $today_date]); $report_tasks = $st->fetchAll(PDO::FETCH_ASSOC); usort($report_tasks, static function (array $left, array $right) use ($today_num, $tomorrow_name): int { $left_priority = get_report_task_priority($left, $today_num, $tomorrow_name); $right_priority = get_report_task_priority($right, $today_num, $tomorrow_name); if ($left_priority !== $right_priority) { return $left_priority <=> $right_priority; } $left_loom = stripos((string)($left['task_name'] ?? ''), 'Loom') === 0 ? 0 : 1; $right_loom = stripos((string)($right['task_name'] ?? ''), 'Loom') === 0 ? 0 : 1; if ($left_loom !== $right_loom) { return $left_loom <=> $right_loom; } return ((int)($left['id'] ?? 0)) <=> ((int)($right['id'] ?? 0)); }); $all_task_sql = "SELECT * FROM daily_tasks WHERE company_id = ?"; $all_task_params = [$company_id]; if ($filter_task_type !== '') { $all_task_sql .= " AND task_type = ?"; $all_task_params[] = $filter_task_type; } $all_task_sql .= " ORDER BY id DESC"; $st_all = $pdo->prepare($all_task_sql); $st_all->execute($all_task_params); $all_tasks = $st_all->fetchAll(PDO::FETCH_ASSOC); require_once __DIR__ . '/partials/header.php'; ?> <style> /* Remark column styling to keep it clean */ .remark-box { width: 100%; border: none; background: transparent; font-weight: 700; text-transform: uppercase; color: inherit; outline: none; padding: 5px; font-size: 13px; min-height: 30px; } /* Hide placeholder color during PNG export (kept for safety) */ .remark-box::placeholder { color: transparent; } .task-field-label { display: block; font-size: 11px; font-weight: 700; text-transform: uppercase; color: #495057; margin-bottom: 4px; } .task-form-help { margin-top: 10px; font-size: 12px; color: #495057; font-weight: 600; } .task-master-tools { display: flex; flex-wrap: wrap; gap: 10px; align-items: end; margin-top: 12px; margin-bottom: 12px; } .task-master-tools .filter-box { min-width: 220px; } .task-action-group { display: flex; flex-wrap: wrap; gap: 6px; } .task-action-inline { display: inline; } .report-row-on-demand-wait { opacity: 0.72; } .report-row-on-demand-wait td { border-width: 1px !important; } .report-row-on-demand-wait .task-name-cell { font-weight: 600 !important; letter-spacing: 0.02em; } .report-row-on-demand-wait .status-shell { border-color: #8aa5b1 !important; background: #f4f7f8 !important; transform: scale(0.96); } .status-track { position: absolute; inset: 0; display: flex; align-items: center; justify-content: stretch; z-index: 1; pointer-events: none; } .status-option-label { flex: 1; text-align: center; font-size: 9px; font-weight: 800; text-transform: uppercase; color: #5c636a; line-height: 1; pointer-events: none; position: relative; z-index: 11; transition: color .15s ease; } .status-option-label.is-active { color: #fff; } .status-click-zone { position: absolute; top: 0; bottom: 0; width: 33.3333%; z-index: 3; } .status-click-zone-left { left: 0; } .status-click-zone-center { left: 33.3333%; } .status-click-zone-right { right: 0; } </style> <div class="container-fluid py-4"> <div class="card mb-4 no-print border-0 shadow-sm" style="background: #f8f9fa; border: 1px solid #ccc !important;"> <div class="card-body"> <h6 style="font-weight: 900;">ADD / EDIT TASK MASTER</h6> <form method="post" class="row g-2"> <input type="hidden" name="task_id" id="edit_id"> <div class="col-md-3"> <label class="task-field-label" for="edit_name">Task Name</label> <input type="text" name="task_name" id="edit_name" placeholder="Task Name" class="form-control form-control-sm" required> </div> <div class="col-md-2"> <label class="task-field-label" for="edit_type">Task Type</label> <select name="task_type" id="edit_type" class="form-select form-select-sm"> <option value="daily">Daily</option><option value="weekly">Weekly</option> <option value="monthly">Monthly</option><option value="on_demand">On Demand</option> <option value="temp">Temporary</option> </select> </div> <div class="col-md-1"> <label class="task-field-label" for="edit_gray">Show From</label> <input type="number" name="gray_start" id="edit_gray" placeholder="17" class="form-control form-control-sm"> </div> <div class="col-md-1"> <label class="task-field-label" for="edit_high">Highlight On</label> <input type="number" name="high_date" id="edit_high" placeholder="19" class="form-control form-control-sm"> </div> <div class="col-md-1"> <label class="task-field-label" for="edit_dis">Hide After</label> <input type="number" name="dis_date" id="edit_dis" placeholder="23" class="form-control form-control-sm"> </div> <div class="col-md-2"> <label class="task-field-label" for="edit_rule">Rule / Day / Note</label> <input type="text" name="rule_value" id="edit_rule" placeholder="Example: Monday or 19-22" class="form-control form-control-sm"> </div> <div class="col-md-2"> <label class="task-field-label" for="save_task_btn"> </label> <button type="submit" name="save_task" id="save_task_btn" class="btn btn-dark btn-sm w-100 fw-bold">SAVE</button> </div> </form> <div id="taskTypeHelp" class="task-form-help"></div> </div> </div> <div id="captureArea" style="background: #fff; padding: 20px; border: 2px solid #000; border-radius: 10px;"> <h2 style="text-align: center; font-weight: 900; margin-bottom: 20px;">DAILY WORK REPORT (<?= date('d-m-Y') ?>)</h2> <table style="width: 100%; border-collapse: collapse; border: 2px solid #000;"> <thead> <tr style="background: #000; color: #fff;"> <th style="padding: 10px; border: 1px solid #444;">SR</th> <th style="padding: 10px; border: 1px solid #444; text-align: left;">WORK DESCRIPTION</th> <th style="padding: 10px; border: 1px solid #444; width: 170px;">STATUS</th> <th style="padding: 10px; border: 1px solid #444;">REMARK</th> </tr> </thead> <tbody> <?php foreach($report_tasks as $i => $t): $st = get_report_task_status($t); $bg = "#f8d7da"; $txt = "#842029"; $p = "4px"; $c = "#dc3545"; $is_waiting = false; $row_class = ''; $active_index = 0; $status_links = [ ['pending', '?set_status=pending&tid=' . $t['id']], ['progress', '?set_status=in progress&tid=' . $t['id']], ['done', '?set_status=done&tid=' . $t['id']], ]; $status_text_labels = ['PEND', 'PROG', 'DONE']; if ($t['task_type'] === 'on_demand') { $status_links = [ ['wait', '?set_status=wait&tid=' . $t['id']], ['pending', '?set_status=pending&tid=' . $t['id']], ['complete', '?set_status=complete&tid=' . $t['id']], ]; $status_text_labels = ['WAIT', 'PEND', 'COMP']; if ($st === 'pending') { $active_index = 1; } elseif ($st === 'complete') { $active_index = 2; } } else { if ($st === 'in progress' || $st === 'in_progress') { $active_index = 1; } elseif ($st === 'done') { $active_index = 2; } } if ($st === 'done' || $st === 'complete') { $bg = "#d1e7dd"; $txt = "#0f5132"; $p = "104px"; $c = "#198754"; } elseif ($st === 'in progress' || $st === 'in_progress') { $bg = "#fff3cd"; $txt = "#856404"; $p = "54px"; $c = "#ffc107"; } if ($t['task_type'] === 'on_demand' && $st === 'wait') { $is_waiting = true; } if (is_waiting_monthly_task($t, $today_num)) { $is_waiting = true; } if($t['task_type'] == 'weekly' && $t['rule_value'] == $tomorrow_name) { $is_waiting = true; } if ($is_waiting) { $bg = "#d7eefc"; $txt = "#0b4f6c"; $p = "4px"; $c = "#2f9ed8"; } if ($t['task_type'] === 'on_demand' && $st === 'wait') { $row_class = 'report-row-on-demand-wait'; $bg = "#f3f7f9"; $txt = "#5d7681"; $p = "4px"; $c = "#9bb8c6"; } ?> <tr class="<?= trim($row_class . ($is_waiting ? ' export-skip' : '')) ?>" style="background-color: <?= $bg ?>; color: <?= $txt ?>;"> <td style="padding: 10px; border: 1px solid #000; text-align: center; font-weight: bold;"><?= $i+1 ?></td> <td class="task-name-cell" style="padding: 10px; border: 1px solid #000; font-weight: 900; text-transform: uppercase;"><?= h($t['task_name']) ?> <small style="font-size: 0.7em;">(<?= h($t['task_type']) ?>)</small></td> <td style="padding: 10px; border: 1px solid #000; text-align: center;"> <?php if ($t['task_type'] === 'on_demand'): ?> <?php $od_btns = [ 'wait' => ['WAIT', '#9bb8c6', '#fff'], 'pending' => ['PEND', '#dc3545', '#fff'], 'complete' => ['COMP', '#198754', '#fff'], ]; ?> <div style="display:flex; gap:3px; justify-content:center; align-items:center;"> <?php foreach ($od_btns as $od_key => [$od_lbl, $od_col, $od_txt]): ?> <?php $is_cur = ($st === $od_key); ?> <a href="?set_status=<?= urlencode($od_key) ?>&tid=<?= $t['id'] ?>" style="display:inline-flex; align-items:center; justify-content:center; width:46px; height:28px; border-radius:6px; font-size:9px; font-weight:900; text-decoration:none; letter-spacing:.04em; background:<?= $is_cur ? $od_col : '#e9ecef' ?>; color:<?= $is_cur ? $od_txt : '#6c757d' ?>; border:2px solid <?= $is_cur ? $od_col : '#ced4da' ?>; pointer-events:<?= $is_cur ? 'none' : 'auto' ?>;" ><?= $od_lbl ?></a> <?php endforeach; ?> </div> <?php else: ?> <div class="status-shell" style="width: 160px; height: 36px; background: #eee; border: 2px solid #333; border-radius: 20px; position: relative; display: flex; align-items: center; margin: 0 auto; cursor: pointer;"> <div class="status-track"> <?php foreach ($status_text_labels as $label_index => $status_text_label): ?> <span class="status-option-label <?= $label_index === $active_index ? 'is-active' : '' ?>"><?= h($status_text_label) ?></span> <?php endforeach; ?> </div> <?php foreach ($status_links as $status_index => $status_link): ?> <a href="<?= h($status_link[1]) ?>" class="status-click-zone <?= $status_index === 0 ? 'status-click-zone-left' : ($status_index === 1 ? 'status-click-zone-center' : 'status-click-zone-right') ?>" aria-label="<?= h($status_link[0]) ?>"></a> <?php endforeach; ?> <div style="position: absolute; left: <?= $p ?>; width: 52px; height: 28px; border-radius: 15px; background: <?= $c ?>; pointer-events: none; z-index: 10; border: 1px solid rgba(0,0,0,0.2);"></div> </div> <?php endif; ?> </td> <td style="padding: 0; border: 1px solid #000;"> <input type="text" value="<?= h($t['remark']) ?>" class="remark-box" onchange="saveRemark(<?= $t['id'] ?>, this.value)" placeholder="Type here..."> </td> </tr> <?php endforeach; ?> </tbody> </table> </div> <div class="mt-4 no-print text-center"> <button onclick="downloadPNG()" class="btn btn-success fw-bold px-5">DOWNLOAD PNG</button> </div> <div class="mt-5 no-print"> <h5 style="font-weight: 900; border-bottom: 2px solid #000;">TASK MASTER LIST</h5> <div class="task-master-tools"> <form method="get" class="row g-2 align-items-end m-0"> <div class="filter-box"> <label class="task-field-label" for="filter_task_type">Filter By Type</label> <select name="filter_task_type" id="filter_task_type" class="form-select form-select-sm"> <option value="">All Types</option> <?php foreach ($task_type_options as $task_type_option): ?> <option value="<?= h($task_type_option) ?>" <?= $filter_task_type === $task_type_option ? 'selected' : '' ?>><?= h(ucwords(str_replace('_', ' ', $task_type_option))) ?></option> <?php endforeach; ?> </select> </div> <div class="col-auto"> <button type="submit" class="btn btn-dark btn-sm fw-bold">FILTER</button> </div> <?php if ($filter_task_type !== ''): ?> <div class="col-auto"> <a href="daily_work_report.php" class="btn btn-outline-secondary btn-sm fw-bold">CLEAR</a> </div> <?php endif; ?> </form> </div> <div class="table-responsive"> <table class="table table-sm table-bordered mt-3"> <thead class="table-dark"> <tr> <th>ID</th><th>Task Name</th><th>Type</th><th>Rule/Dates</th><th>Action</th> </tr> </thead> <tbody> <?php foreach($all_tasks as $at): ?> <tr> <td><?= $at['id'] ?></td> <td><?= h($at['task_name']) ?></td> <td><span class="badge bg-secondary"><?= h($at['task_type']) ?></span></td> <td> <small> Rule/Note: <?= h($at['rule_value']) ?> | Show From: <?= h($at['gray_date_start']) ?> | Highlight On: <?= h($at['highlight_date']) ?> | Hide After: <?= h($at['disappear_date']) ?> </small> </td> <td> <div class="task-action-group"> <button type="button" class="btn btn-primary btn-sm" onclick='editTask(<?= json_encode($at) ?>)'>EDIT</button> <?php if($at['task_type'] === 'temp'): ?> <a href="?add_to_today=<?= $at['id'] ?>" class="btn btn-success btn-sm">ADD TO REPORT</a> <?php endif; ?> <form method="post" class="task-action-inline" onsubmit="return confirm('Delete this task from task master?');"> <input type="hidden" name="delete_task" value="<?= $at['id'] ?>"> <input type="hidden" name="list_filter_type" value="<?= h($filter_task_type) ?>"> <button type="submit" class="btn btn-danger btn-sm">DELETE</button> </form> </div> </td> </tr> <?php endforeach; ?> </tbody> </table> </div> </div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script> <script> function saveRemark(tid, val) { fetch(`?ajax_update_remark=1&tid=${tid}&remark=${encodeURIComponent(val)}`) .then(r => console.log('Saved')); } function editTask(t) { document.getElementById('edit_id').value = t.id; document.getElementById('edit_name').value = t.task_name; document.getElementById('edit_type').value = t.task_type; document.getElementById('edit_gray').value = t.gray_date_start; document.getElementById('edit_high').value = t.highlight_date; document.getElementById('edit_dis').value = t.disappear_date; document.getElementById('edit_rule').value = t.rule_value; updateTaskTypeHelp(); window.scrollTo({top: 0, behavior: 'smooth'}); } function updateTaskTypeHelp() { const type = document.getElementById('edit_type').value; const help = document.getElementById('taskTypeHelp'); if (type === 'monthly') { help.textContent = 'Monthly: Show From se task report me blue waiting ke roop me dikhna shuru hoga. Highlight On se task normal pending flow me aayega, aur Hide After ke baad task hat jayega.'; return; } if (type === 'weekly') { help.textContent = 'Weekly: Rule / Day / Note me day name likho, jaise Monday. Baaki date fields optional hain agar aap reference ke liye rakhna chahte ho.'; return; } if (type === 'daily') { help.textContent = 'Daily: Task har din report me aayega. Date fields aur Rule / Note optional reference fields hain.'; return; } if (type === 'on_demand' || type === 'temp') { help.textContent = 'On Demand: left me Wait, center me Pending aur right me Complete rahega. Complete task agle din auto Wait me aa jayega, aur Wait wale task report ke niche halki style me dikhenge. Temporary: Add To Report ke baad dikhai dega aur done hone ke agle din auto delete ho jayega.'; return; } help.textContent = ''; } document.getElementById('edit_type').addEventListener('change', updateTaskTypeHelp); updateTaskTypeHelp(); function downloadPNG() { const captureArea = document.getElementById('captureArea'); const table = captureArea.querySelector('table'); const originalAreaStyle = captureArea.getAttribute('style'); const originalTableStyle = table.getAttribute('style'); const waitingRows = Array.from(captureArea.querySelectorAll('tr.export-skip')); const waitingDisplay = waitingRows.map(row => row.style.display); // Temporarily clear placeholders (and keep current values) so "Type here..." doesn't render in PNG const remarkEls = Array.from(captureArea.querySelectorAll('.remark-box')); const saved = remarkEls.map(el => ({ el, placeholder: el.getAttribute('placeholder') || '', value: el.value })); remarkEls.forEach(el => el.setAttribute('placeholder', '')); // remove focus to hide caret if (document.activeElement && document.activeElement.blur) document.activeElement.blur(); waitingRows.forEach(row => { row.style.display = 'none'; }); captureArea.style.cssText = "background: #fff; padding: 10px; border: 2px solid #000; border-radius: 10px; width: 600px; margin: 0 auto;"; table.style.cssText = "width: 100%; border-collapse: collapse; border: 2px solid #000; font-size: 11px;"; html2canvas(captureArea, { scale: 3 }).then(canvas => { const link = document.createElement('a'); link.download = 'Work_Report_<?= date('d_m_Y') ?>.png'; link.href = canvas.toDataURL(); link.click(); // restore placeholders & values saved.forEach(s => { if (s.placeholder) s.el.setAttribute('placeholder', s.placeholder); else s.el.removeAttribute('placeholder'); s.el.value = s.value; }); captureArea.setAttribute('style', originalAreaStyle); table.setAttribute('style', originalTableStyle); waitingRows.forEach((row, index) => { row.style.display = waitingDisplay[index]; }); }).catch(() => { waitingRows.forEach((row, index) => { row.style.display = waitingDisplay[index]; }); captureArea.setAttribute('style', originalAreaStyle); table.setAttribute('style', originalTableStyle); }); } </script> <?php require_once __DIR__ . '/partials/footer.php'; ?>