« Back to History
loom_machine_status.php
|
20260722_120325.php
Initial Domain Snapshot
Copy Code
<?php /* ========================================================================= File: /erp/loom_machine_status.php Purpose: Loom Machine Status Management with Remarks for Deactivation ========================================================================= */ error_reporting(E_ALL); ini_set('display_errors', 1); /* --- DB + Auth --- */ if (!isset($pdo) || !($pdo instanceof PDO)) { require __DIR__ . '/core/db.php'; } require __DIR__ . '/modules/auth/auth.php'; require_once __DIR__ . '/modules/activity/activity_logger.php'; require_login(); $u = auth_user(); $company_id = (int)($u['company_id'] ?? 0); /* --- Helpers --- */ function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } function postv(string $k, $def=''){ return array_key_exists($k, $_POST) ? $_POST[$k] : $def; } function normalize_date($value) { $dt = DateTime::createFromFormat('Y-m-d', $value); return ($dt && $dt->format('Y-m-d') === $value) ? $value : date('Y-m-d'); } function normalize_shift(string $value): string { $value = strtolower(trim($value)); return $value === 'night' ? 'Night' : 'Day'; } function normalize_shift_filter(string $value): string { $value = strtolower(trim($value)); if ($value === 'day') { return 'Day'; } if ($value === 'night') { return 'Night'; } return 'Both'; } function loom_machine_key(string $value): string { $value = trim(strtolower($value)); if (preg_match('/(\d+)$/', $value, $m)) { return (string)((int)$m[1]); } return preg_replace('/\s+/', ' ', $value); } $msg = ''; $err = ''; $selected_date = normalize_date($_GET['date'] ?? postv('status_date', date('Y-m-d'))); $shift_filter = normalize_shift_filter((string)($_GET['shift_filter'] ?? postv('shift_filter', 'Both'))); $shift_labels = $shift_filter === 'Both' ? ['Day', 'Night'] : [$shift_filter]; /* --- Toggle Logic --- */ if ($_SERVER['REQUEST_METHOD'] === 'POST' && postv('_action') === 'toggle') { $machine_no = trim((string)postv('machine_no', '')); $new_status = postv('new_status', 'Stopped'); $remarks = trim((string)postv('remarks', '')); $status_date = normalize_date(postv('status_date', $selected_date)); $shift = normalize_shift((string)postv('shift', 'Day')); if ($machine_no === '') { $err = 'Machine number is required.'; } else { try { $pdo->beginTransaction(); // Delete-then-Insert pattern $del = $pdo->prepare("DELETE FROM loom_machine_status WHERE company_id = ? AND machine_no = ? AND shift = ? AND status_date = ?"); $del->execute([$company_id, $machine_no, $shift, $status_date]); $ins = $pdo->prepare("INSERT INTO loom_machine_status (company_id, machine_no, shift, status, status_date, remarks, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, NOW(), NOW())"); $ins->execute([$company_id, $machine_no, $shift, $new_status, $status_date, $remarks]); $insert_id = (int)$pdo->lastInsertId(); $pdo->commit(); activity_log([ 'company_id' => $company_id ?? 0, 'user_id' => $u['id'] ?? ($_SESSION['user_id'] ?? 0), 'module' => 'loom', 'action_name' => 'edit', 'entity_type' => 'loom_machine_status', 'entity_id' => $insert_id ?? 0, 'remarks' => 'Loom machine status updated' ]); $msg = "Machine $machine_no $shift updated to $new_status."; } catch (Exception $e) { if ($pdo->inTransaction()) { $pdo->rollBack(); } $err = 'Error: ' . $e->getMessage(); } } if ($err === '') { header('Location: loom_machine_status.php?date=' . urlencode($status_date) . '&msg=' . urlencode($msg)); exit; } } if (isset($_GET['msg'])) $msg = $_GET['msg']; /* --- Fetch Loom Machines --- */ $machines = []; try { $st = $pdo->prepare("SELECT code FROM machines WHERE company_id = ? AND machine_type = 'Power Loom' AND COALESCE(is_active, 1) = 1 ORDER BY code ASC"); $st->execute([$company_id]); $machines = $st->fetchAll(PDO::FETCH_ASSOC); } catch (Exception $e) { $err = $e->getMessage(); } /* --- Fetch Statuses for Selected Date --- */ $status_rows = []; try { $st = $pdo->prepare("SELECT machine_no, shift, status, remarks FROM loom_machine_status WHERE company_id = ? AND status_date = ? ORDER BY id DESC"); $st->execute([$company_id, $selected_date]); foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $row) { $machine_no = loom_machine_key((string)($row['machine_no'] ?? '')); $shift = normalize_shift((string)($row['shift'] ?? 'Day')); if ($machine_no !== '' && !isset($status_rows[$machine_no][$shift])) { $status_rows[$machine_no][$shift] = $row; } } } catch (Exception $e) { $err = $e->getMessage(); } $date_obj = new DateTime($selected_date); $prev_date = (clone $date_obj)->modify('-1 day')->format('Y-m-d'); $next_date = (clone $date_obj)->modify('+1 day')->format('Y-m-d'); /* --- Header --- */ $page_title = 'Loom Machine Status'; $__header = __DIR__ . '/partials/header.php'; if (is_file($__header)) { include_once $__header; } ?> <div class="container-fluid mt-3"> <style> .status-date-nav { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 20px; } .status-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 1rem; } .machine-card { border-radius: 1rem; padding: 1rem; background: #fff; border: 1px solid rgba(148, 163, 184, 0.2); box-shadow: 0 8px 20px rgba(0,0,0,0.06); } .machine-title { margin: 0 0 0.75rem; font-weight: 700; color: #0f172a; } .shift-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; } .status-tile { width: 100%; border: 0; border-radius: 1rem; padding: 1.2rem; color: #fff; text-align: left; box-shadow: 0 8px 20px rgba(0,0,0,0.1); transition: 0.2s; position: relative; } .status-tile:hover { transform: translateY(-3px); } .active-tile { background: linear-gradient(135deg, #28a745, #20c997); } .deactive-tile { background: linear-gradient(135deg, #dc3545, #f46b45); } .nodata-tile { background: linear-gradient(135deg, #9ca3af, #6b7280); color: #f8fafc; } .tile-shift-label { display: block; font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.78; } .tile-shift-value { display: block; margin-top: 0.15rem; font-size: 1rem; font-weight: 600; } .tile-status-text { display: block; margin-top: 0.85rem; font-size: 1.45rem; font-weight: 800; line-height: 1.05; letter-spacing: 0.01em; } .remarks-text { font-size: 0.75rem; background: rgba(0,0,0,0.2); padding: 4px 8px; border-radius: 5px; margin-top: 10px; display: block; } @media (max-width: 576px) { .status-grid { grid-template-columns: 1fr; } } </style> <?php if($msg): ?> <div class="alert alert-success alert-dismissible fade show"><?= h($msg) ?> <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div> <?php endif; ?> <?php if($err): ?> <div class="alert alert-danger"><?= h($err) ?></div> <?php endif; ?> <div class="card shadow-sm border-0 mb-4"> <div class="card-body bg-light"> <div class="status-date-nav"> <a href="?date=<?= h($prev_date) ?>&shift_filter=<?= h($shift_filter) ?>" class="btn btn-dark px-4">← Previous</a> <div class="text-center"> <h2 class="mb-0 fw-bold text-uppercase"><?= h(date('d M Y', strtotime($selected_date))) ?></h2> <span class="badge bg-secondary">Loom Machine Monitoring</span> </div> <a href="?date=<?= h($next_date) ?>&shift_filter=<?= h($shift_filter) ?>" class="btn btn-dark px-4">Next →</a> </div> <form method="get" class="row g-3 align-items-end mb-3"> <input type="hidden" name="date" value="<?= h($selected_date) ?>"> <div class="col-md-3 col-lg-2"> <label class="form-label fw-bold">Shift View</label> <select name="shift_filter" class="form-select" onchange="this.form.submit()"> <option value="Both" <?= $shift_filter === 'Both' ? 'selected' : '' ?>>Both</option> <option value="Day" <?= $shift_filter === 'Day' ? 'selected' : '' ?>>Day</option> <option value="Night" <?= $shift_filter === 'Night' ? 'selected' : '' ?>>Night</option> </select> </div> <div class="col-md-3 col-lg-2"> <a href="loom_machine_status.php?date=<?= h($selected_date) ?>&shift_filter=Both" class="btn btn-outline-secondary w-100">Show Both</a> </div> </div> <div class="status-grid"> <?php foreach ($machines as $m): $code = $m['code']; $machine_key = loom_machine_key((string)$code); ?> <div class="machine-card"> <h4 class="machine-title"><?= h($code) ?></h4> <div class="shift-grid"> <?php foreach ($shift_labels as $shift_label): ?> <?php $row = $status_rows[$machine_key][$shift_label] ?? null; $curr = (string)($row['status'] ?? ''); $rem = (string)($row['remarks'] ?? ''); $has_data = is_array($row); $is_running = $has_data && strcasecmp($curr, 'Running') === 0; $tile_class = !$has_data ? 'nodata-tile' : ($is_running ? 'active-tile' : 'deactive-tile'); $next_status = $is_running ? 'Stopped' : 'Running'; ?> <div class="status-tile <?= $tile_class ?>" onclick="handleToggle('<?= h($code) ?>', '<?= h($shift_label) ?>', '<?= $has_data ? $next_status : 'Stopped' ?>', <?= $has_data ? 'true' : 'false' ?>)"> <span class="tile-shift-label">Shift</span> <span class="tile-shift-value"><?= h($shift_label) ?></span> <span class="tile-status-text"><?= $has_data ? h($curr) : 'No data found' ?></span> <?php if($has_data && !$is_running && $rem): ?> <div class="remarks-text"><strong>Reason:</strong> <?= h($rem) ?></div> <?php endif; ?> <div class="mt-3 small opacity-75"> <?= $has_data ? 'Click to toggle status' : 'No data found for this date' ?> </div> </div> <?php endforeach; ?> </div> </div> <?php endforeach; ?> </div> </div> </div> </div> <!-- Remark Modal --> <div class="modal fade" id="remarkModal" tabindex="-1"> <div class="modal-dialog modal-dialog-centered"> <form method="POST" class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Stop Machine <span id="modal_m_no"></span></h5> <button type="button" class="btn-close" data-bs-dismiss="modal"></button> </div> <div class="modal-body"> <input type="hidden" name="_action" value="toggle"> <input type="hidden" name="machine_no" id="form_m_no"> <input type="hidden" name="shift" id="form_shift"> <input type="hidden" name="new_status" value="Stopped"> <input type="hidden" name="status_date" value="<?= h($selected_date) ?>"> <label class="form-label fw-bold">Reason for stopping?</label> <textarea name="remarks" class="form-control" rows="3" required placeholder="e.g. Maintenance, No Karigar, Warp Cut etc."></textarea> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> <button type="submit" class="btn btn-danger">Confirm Stop</button> </div> </form> </div> </div> <!-- Hidden Form for Direct Running Toggle --> <form id="runningForm" method="POST" style="display:none;"> <input type="hidden" name="_action" value="toggle"> <input type="hidden" name="machine_no" id="run_m_no"> <input type="hidden" name="shift" id="run_shift"> <input type="hidden" name="new_status" value="Running"> <input type="hidden" name="status_date" value="<?= h($selected_date) ?>"> <input type="hidden" name="remarks" value=""> </form> <script> const remarkModal = new bootstrap.Modal(document.getElementById('remarkModal')); function handleToggle(mNo, shift, newStatus, hasData) { if (!hasData) { return; } if (newStatus === 'Stopped') { document.getElementById('modal_m_no').innerText = mNo; document.getElementById('form_m_no').value = mNo; document.getElementById('form_shift').value = shift; remarkModal.show(); } else { if(confirm(`Set Loom ${mNo} ${shift} to Running?`)) { document.getElementById('run_m_no').value = mNo; document.getElementById('run_shift').value = shift; document.getElementById('runningForm').submit(); } } } </script> <?php $__footer = __DIR__ . '/partials/footer.php'; if (is_file($__footer)) { include_once $__footer; } ?>