KAAUH Lab Suite - Verification, Alerts & Enhancements

Combines verification buttons (F7/F8), dynamic alerts (>, NO RESULT, X-NORESULT, CL/CH) showing alerts once per trigger per page visit, checkbox automation, toggle back-nav, and inline sample counters.

当前为 2025-05-16 提交的版本,查看 最新版本

// ==UserScript==
// @name         KAAUH Lab Suite - Verification, Alerts & Enhancements
// @namespace    Violentmonkey Scripts
// @version      7.1
// @description  Combines verification buttons (F7/F8), dynamic alerts (>, NO RESULT, X-NORESULT, CL/CH) showing alerts once per trigger per page visit, checkbox automation, toggle back-nav, and inline sample counters.
// @match        *://his.kaauh.org/lab/*
// @grant        none
// @author       Hamad AlShegifi
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // --- Styling Adjustments (Global) ---
    function applySingleLineStyles() {
        const anchor = document.querySelector('li > a[href="#/lab-orders/doctor-request"]');
        if (anchor) {
            anchor.style.setProperty('white-space', 'nowrap', 'important');
            anchor.style.setProperty('overflow', 'visible', 'important');
            anchor.style.setProperty('text-overflow', 'unset', 'important');
            const spans = anchor.querySelectorAll('span');
            spans.forEach(span => {
                span.style.setProperty('display', 'inline', 'important');
                span.style.setProperty('font-size', '13px', 'important');
                span.style.setProperty('white-space', 'nowrap', 'important');
            });
        }

        const simplifySpan = (selector) => {
            const span = document.querySelector(selector);
            if (span) {
                span.style.setProperty('display', 'inline', 'important');
                span.style.setProperty('font-size', '20px', 'important');
                span.style.setProperty('white-space', 'nowrap', 'important');
                span.style.setProperty('overflow', 'visible', 'important');
                span.style.setProperty('text-overflow', 'unset', 'important');
                span.textContent = span.textContent.replace(/\s+/g, '');
            }
        };
        simplifySpan('span.to-do');
        simplifySpan('span.pending-orders');
    }

    function debounce(func, wait) {
        let timeout;
        return function(...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }

    const debouncedStyleUpdater = debounce(applySingleLineStyles, 300);
    const styleObserver = new MutationObserver(debouncedStyleUpdater);
    styleObserver.observe(document.body, { childList: true, subtree: true });
    applySingleLineStyles(); // Initial application
})();

// Main Userscript Logic (Alerts, F7/F8 buttons, etc.)
(function () {
    'use strict';

    const CONFIG_MAIN = {
        URLS: {
            EDIT_PAGE_PREFIX: 'https://his.kaauh.org/lab/#/lab-orders/edit-lab-order/',
        },
        SELECTORS: {
            VERIFY1_BTN: '#custom-script-buttons button.verify1-btn',
            VERIFY2_BTN: '#custom-script-buttons button.verify2-btn',
            COMPLETE_TECH: 'button.dropdown-item[translateid="test-results.CompleteTechnicalVerification"]',
            COMPLETE_MED: 'button.dropdown-item[translateid="test-results.CompleteMedicalVerification"]',
            FINAL_VERIFY: 'button.btn-success.btn-sm.min-width[translateid="test-verification.Verify"]',
            NEXT_BTN: 'button#btnNext',
            UNCHECKED_BOX: 'span.ag-icon-checkbox-unchecked[unselectable="on"]',
            CHECKBOX_ROW: '.ag-row',
            TEST_DESC_CELL: '[col-id="TestDesc"]',
            ORDERED_STATUS_CELL: 'div[col-id="ResultStatus"]',
            TOAST: {
                CONTAINER: '#toast-container',
                CLOSE_BTN: 'button.toast-close-button',
                SUCCESS: '.toast-success',
            },
            SAMPLE_RECEIVE_MODAL: 'modal-container.show', // Used by the sample counter part
        },
        CHECK_INTERVALS: {
            UNDEFINED_URL: 200,
            ORDERED_SCAN: 500,
            DISABLED_BTN_CHECK: 1000,
        },
        EXCLUDE_WORDS: [ // Words to exclude from auto-checkbox selection
            'culture', "gram's stain", 'stain', 'bacterial', 'fungal',
            'pcr', 'meningitis', 'mrsa', 'mid', 'stream', 'cryptococcus'
        ]
    };

    let verify1Clicked = false;
    let verify2Clicked = false;
    let verify1Toggle = localStorage.getItem('verify1Toggle') === 'true';
    let verify2Toggle = localStorage.getItem('verify2Toggle') === 'true';
    let hasScrolledToOrderedRow = false;
    let lastDisabledButtonAlertTime = 0;
    const DISABLED_ALERT_COOLDOWN = 30000; // 30 seconds

    const logDebugMain = msg => console.debug(`[LabScript Main] ${msg}`);
    const isCorrectPage = () => window.location.href.startsWith(CONFIG_MAIN.URLS.EDIT_PAGE_PREFIX);

    function showDisabledButtonAlert(message) {
        const now = Date.now();
        if (now - lastDisabledButtonAlertTime < DISABLED_ALERT_COOLDOWN) return;
        lastDisabledButtonAlertTime = now;

        const modalOverlay = document.createElement('div');
        modalOverlay.id = 'disabled-button-alert-overlay';
        Object.assign(modalOverlay.style, {
            position: 'fixed', top: '0', left: '0', width: '100vw', height: '100vh',
            backgroundColor: 'rgba(0, 0, 0, 0.7)', zIndex: '10000', display: 'flex',
            justifyContent: 'center', alignItems: 'center'
        });

        const modalBox = document.createElement('div');
        Object.assign(modalBox.style, {
            backgroundColor: '#fff', padding: '25px', borderRadius: '8px',
            boxShadow: '0 5px 15px rgba(0,0,0,0.3)', width: 'auto', maxWidth: '80%',
            textAlign: 'center', borderTop: '5px solid #f0ad4e' // Warning color
        });

        const title = document.createElement('h3');
        title.textContent = 'Button Disabled';
        title.style.color = '#d9534f'; // Danger color for title
        title.style.marginTop = '0';
        modalBox.appendChild(title);

        const messageElem = document.createElement('p');
        messageElem.textContent = message;
        messageElem.style.fontSize = '16px';
        messageElem.style.marginBottom = '20px';
        modalBox.appendChild(messageElem);

        const okButton = document.createElement('button');
        okButton.textContent = 'OK';
        Object.assign(okButton.style, {
            padding: '8px 20px', borderRadius: '5px', backgroundColor: '#5cb85c', // Success color for button
            color: '#fff', border: 'none', cursor: 'pointer', fontSize: '16px'
        });
        okButton.onclick = () => document.body.removeChild(modalOverlay);
        modalBox.appendChild(okButton);

        modalOverlay.appendChild(modalBox);
        document.body.appendChild(modalOverlay);
        okButton.focus(); // Focus on OK button for accessibility
    }

    function addFontAwesome() {
        const fontAwesomeLink = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css';
        if (!document.querySelector(`link[href="${fontAwesomeLink}"]`)) {
            const link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = fontAwesomeLink;
            const head = document.head || document.body; // Prefer document.head
            if (head) head.appendChild(link);
        }
    }

    function createVerifyButton(label, className, onClick, id) {
        const button = document.createElement('button');
        button.type = 'button';
        button.className = className; // Base classes like 'btn btn-sm'
        button.classList.add(id); // Specific ID class like 'verify1-btn'
        button.innerText = label;
        // Common styles, ensuring they override existing ones if necessary
        const styles = {
            'font-family': 'Arial, sans-serif',
            'font-size': '14px',
            'font-weight': 'normal', // Bootstrap buttons often have bolder weight
            'color': '#ffffff',
            'background-color': className.includes('success') ? '#28a745' : '#2594d9', // Green for success, blue for primary
            'padding': '8px 16px',
            'border': 'none',
            'border-radius': '5px',
            'text-shadow': 'none', // Remove any default text shadow
            'cursor': 'pointer',
            'margin-right': '5px',
            'line-height': '1.5', // Standard line height
            'vertical-align': 'middle', // Align with other inline elements
        };
        for (const [prop, value] of Object.entries(styles)) {
            button.style.setProperty(prop, value, 'important');
        }
        button.onclick = onClick;
        return button;
    }

    function createToggleIcon(id, isActive, onClick) {
        const icon = document.createElement('span');
        icon.id = id;
        // Using FontAwesome icon for toggle
        icon.innerHTML = `<i class="fas fa-arrow-circle-left" style="color: ${isActive ? '#008000' : '#d1cfcf'}; font-size: 1.3em; vertical-align: middle;"></i>`;
        icon.style.cursor = 'pointer';
        icon.style.marginRight = '10px';
        icon.style.marginLeft = '-1px'; // Slight adjustment for alignment
        icon.title = "Toggle: Go back automatically after this verification success toast is clicked";
        icon.onclick = onClick;
        return icon;
    }

    function handleVerifyToggle(type) {
        const toggle = type === 'verify1' ? !verify1Toggle : !verify2Toggle;
        localStorage.setItem(type + 'Toggle', toggle); // Save preference
        const icon = document.querySelector(`#${type}Icon i`);
        if (icon) icon.style.setProperty('color', toggle ? '#008000' : '#d1cfcf', 'important'); // Green for active, grey for inactive

        if (type === 'verify1') verify1Toggle = toggle;
        else verify2Toggle = toggle;
    }

    function addButtons() {
        if (document.getElementById('custom-script-buttons') || !isCorrectPage()) return;
        const nextButton = document.querySelector(CONFIG_MAIN.SELECTORS.NEXT_BTN);
        if (!nextButton || !nextButton.parentNode) {
            setTimeout(addButtons, 500); // Retry if next button not found yet
            return;
        }

        const buttonDiv = document.createElement('div');
        buttonDiv.id = 'custom-script-buttons';
        buttonDiv.style.setProperty('display', 'inline-block', 'important');
        buttonDiv.style.setProperty('margin-left', '10px', 'important');
        buttonDiv.style.setProperty('vertical-align', 'middle', 'important');


        const verify1Button = createVerifyButton('VERIFY1 (F7)', 'btn btn-success btn-sm', () => {
            verify1Clicked = true;
            verify2Clicked = false;
            checkAllVisibleBoxesWithoutDuplicates();
            setTimeout(clickCompleteTechnicalVerificationButton, 500); // Delay to allow checkboxes to register
        }, 'verify1-btn');

        const verify2Button = createVerifyButton('VERIFY2 (F8)', 'btn btn-primary btn-sm', () => {
            verify2Clicked = true;
            verify1Clicked = false;
            checkAllVisibleBoxesWithoutDuplicates();
            setTimeout(clickCompleteMedicalVerificationButton, 500); // Delay
        }, 'verify2-btn');

        const verify1Icon = createToggleIcon('verify1Icon', verify1Toggle, () => handleVerifyToggle('verify1'));
        const verify2Icon = createToggleIcon('verify2Icon', verify2Toggle, () => handleVerifyToggle('verify2'));

        // Credit span
        const credit = document.createElement('span');
        credit.textContent = "Modded by: Hamad AlShegifi";
        credit.style.cssText =
            `font-size: 11px !important;
            font-weight: bold !important;
            color: #e60000 !important; /* Bright red for visibility */
            margin-left: 15px !important;
            border: 1px solid #e60000 !important;
            border-radius: 5px !important;
            padding: 3px 6px !important;
            background-color: #ffffff !important; /* White background for contrast */
            vertical-align: middle !important;
            `;

        buttonDiv.append(verify1Button, verify1Icon, verify2Button, verify2Icon, credit);
        nextButton.parentNode.insertBefore(buttonDiv, nextButton.nextSibling);
        logDebugMain("Custom buttons added.");
    }

    function checkAllVisibleBoxesWithoutDuplicates() {
        const selectedTests = new Set(); // To track selected test descriptions and avoid duplicates
        const boxes = document.querySelectorAll(CONFIG_MAIN.SELECTORS.UNCHECKED_BOX);
        boxes.forEach(box => {
            const row = box.closest(CONFIG_MAIN.SELECTORS.CHECKBOX_ROW);
            // Check if the row is visible (offsetParent is not null)
            if (row && row.offsetParent !== null) {
                const testDescElement = row.querySelector(CONFIG_MAIN.SELECTORS.TEST_DESC_CELL);
                const descText = testDescElement?.textContent.trim().toLowerCase();

                if (descText) {
                    // Check if any part of the description text includes an excluded word
                    const isExcluded = CONFIG_MAIN.EXCLUDE_WORDS.some(word => descText.includes(word));
                    if (!selectedTests.has(descText) && !isExcluded) {
                        selectedTests.add(descText); // Add to set to prevent re-checking if description is identical
                        box.click();
                    }
                }
            }
        });
        logDebugMain(`Checked ${selectedTests.size} unique, non-excluded, visible boxes.`);
    }

    const clickButton = (selector, callback) => {
        const btn = document.querySelector(selector);
        if (btn && !btn.disabled) {
            btn.click();
            if (callback) setTimeout(callback, 500); // Short delay for UI updates
            return true;
        } else if (btn && btn.disabled) {
            const buttonName = selector.includes('CompleteTechnicalVerification') ?
                'Complete Technical Verification' :
                selector.includes('CompleteMedicalVerification') ?
                'Complete Medical Verification' :
                selector.includes('Verify') ?
                'Final Verify' : 'Button';
            showDisabledButtonAlert(`${buttonName} button is disabled. Please check if you have selected all required tests or if verification is already done.`);
        }
        return false;
    };

    const clickCompleteTechnicalVerificationButton = () => clickButton(CONFIG_MAIN.SELECTORS.COMPLETE_TECH, clickFinalVerifyButton);
    const clickCompleteMedicalVerificationButton = () => clickButton(CONFIG_MAIN.SELECTORS.COMPLETE_MED, clickFinalVerifyButton);
    const clickFinalVerifyButton = () => clickButton(CONFIG_MAIN.SELECTORS.FINAL_VERIFY);

    function checkForDisabledButtons() {
        if (!isCorrectPage()) return;
        const verify1Btn = document.querySelector(CONFIG_MAIN.SELECTORS.VERIFY1_BTN);
        const verify2Btn = document.querySelector(CONFIG_MAIN.SELECTORS.VERIFY2_BTN);
        // This function is more for proactive checks if needed, showDisabledButtonAlert is called on actual click attempt.
        // Could be used to visually indicate disabled state if desired.
        if (verify1Btn && verify1Btn.disabled) {
            // logDebugMain("VERIFY1 button is currently disabled on page.");
        }
        if (verify2Btn && verify2Btn.disabled) {
            // logDebugMain("VERIFY2 button is currently disabled on page.");
        }
    }

    function checkUrlAndTriggerClickForUndefined() {
        if (window.location.href.endsWith('/undefined')) {
            const closeBtn = document.querySelector(`${CONFIG_MAIN.SELECTORS.TOAST.CONTAINER} ${CONFIG_MAIN.SELECTORS.TOAST.CLOSE_BTN}`);
            if (closeBtn) {
                logDebugMain("URL ends with /undefined, attempting to close toast.");
                closeBtn.click();
            }
        }
    }

    function monitorOrderedStatus() {
        if (!isCorrectPage()) return;
        const rows = document.querySelectorAll('div[role="row"]'); // More generic row selector
        let hasOrdered = false;
        let firstOrderedRow = null;

        rows.forEach(row => {
            // Ensure row is visible
            if (row.offsetParent !== null) { // Check if element is visible on the page
                const cell = row.querySelector(CONFIG_MAIN.SELECTORS.ORDERED_STATUS_CELL);
                if (cell?.textContent.includes('Ordered')) {
                    if (!firstOrderedRow) firstOrderedRow = row; // Get the first visible ordered row
                    hasOrdered = true;
                }
            }
        });

        const btn = document.querySelector(CONFIG_MAIN.SELECTORS.VERIFY1_BTN);
        if (btn) {
            if (hasOrdered) {
                if (!btn.classList.contains('btn-warning')) { // Check if already warning
                    btn.className = 'btn btn-warning verify1-btn'; // Change class for styling
                    btn.innerText = 'VERIFY1 (F7)'; // Keep text consistent
                    btn.style.setProperty('background-color', '#fab641', 'important'); // Orange/yellow
                    btn.style.setProperty('color', '#050505', 'important'); // Dark text for contrast
                    logDebugMain("Ordered status detected. VERIFY1 button changed to warning.");
                }
                if (firstOrderedRow && !hasScrolledToOrderedRow) {
                    document.documentElement.style.scrollBehavior = 'smooth'; // Smooth scroll
                    firstOrderedRow.scrollIntoView({ behavior: 'auto', block: 'center' });
                    hasScrolledToOrderedRow = true;
                    setTimeout(() => document.documentElement.style.scrollBehavior = 'auto', 1000); // Reset scroll behavior
                    logDebugMain("Scrolled to first 'Ordered' row.");
                }
            } else { // No 'Ordered' status found
                if (btn.classList.contains('btn-warning')) { // Check if it was warning
                    btn.className = 'btn btn-success btn-sm verify1-btn'; // Revert to success
                    btn.innerText = 'VERIFY1 (F7)';
                    btn.style.setProperty('background-color', '#28a745', 'important'); // Green
                    btn.style.setProperty('color', '#ffffff', 'important'); // White text
                    logDebugMain("No ordered status. VERIFY1 button reverted to success.");
                }
                hasScrolledToOrderedRow = false; // Reset scroll flag
            }
        }
    }
    setInterval(monitorOrderedStatus, CONFIG_MAIN.CHECK_INTERVALS.ORDERED_SCAN);


    // --- Toast Observer for Auto Back Navigation ---
    const toastObserver = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            mutation.addedNodes.forEach(node => {
                if (node.nodeType === Node.ELEMENT_NODE) { // Check if it's an element node
                    let successToast = null;
                    if (node.matches(CONFIG_MAIN.SELECTORS.TOAST.SUCCESS)) {
                        successToast = node;
                    } else if (node.querySelector) { // Check if it's a container with the toast inside
                        successToast = node.querySelector(CONFIG_MAIN.SELECTORS.TOAST.SUCCESS);
                    }

                    if (successToast) {
                        logDebugMain("Success toast detected.");
                        successToast.addEventListener('click', () => {
                            if ((verify1Clicked && verify1Toggle) || (verify2Clicked && verify2Toggle)) {
                                logDebugMain("Navigating back due to toast click and toggle state.");
                                window.history.back();
                            }
                            // Reset click flags after any toast interaction
                            verify1Clicked = false;
                            verify2Clicked = false;
                        }, { once: true }); // Ensure listener is added only once
                    }
                }
            });
        });
    });
    // Observe the body for toast container additions, common for many toast libraries
    toastObserver.observe(document.body, { childList: true, subtree: true });

    // --- Keyboard Shortcuts (F7/F8) ---
    document.addEventListener('keydown', e => {
        // Ignore keydown events if focus is on an input, textarea, or select element
        if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') {
            return;
        }

        if (e.key === 'F7') {
            e.preventDefault(); // Prevent default F7 browser action
            document.querySelector(CONFIG_MAIN.SELECTORS.VERIFY1_BTN)?.click();
        } else if (e.key === 'F8') {
            e.preventDefault(); // Prevent default F8 browser action
            document.querySelector(CONFIG_MAIN.SELECTORS.VERIFY2_BTN)?.click();
        }
    });


    // --- Integrated Alerts Scanner Code (Critical, Dilution, No-Result) ---
    // Ensure SheetJS (XLSX) is available if local saving is intended (not included in this script)
    if (typeof XLSX === 'undefined') {
        console.warn("[Alerts Scanner] SheetJS library (XLSX) not found. Local XLSX saving will not work.");
    }

    const CONFIG_ALERTS = {
        SCAN_INTERVAL: 750, // ms
        FLASH_COLOR: "pink",
        FLASH_INTERVAL: 700, // ms for flashing
        RESULT_CELL_SELECTOR: 'div[role="gridcell"][col-id="TestResult"] app-result-value-render div',
        UOM_CELL_SELECTOR: 'div[col-id="UomValue"]',
        CRITICAL_FLAG_SELECTOR: 'div[role="gridcell"][col-id="LTFlag"] app-ref-high-low div span.critial-alret-indication',
        TEST_DESC_PINNED_SELECTOR: '.ag-pinned-left-cols-container .ag-row div[col-id="TestDesc"]', // For AG-Grid pinned columns
        NO_RESULT_MESSAGE: "NO-RESULT DETECTED!",
        DILUTION_MESSAGE: "DILUTION REQUIRED!",
        PATIENT_NAME_SELECTOR: 'div.patient-name-full',
        PATIENT_MRN_SELECTOR: 'div.mid.renal-demography span', // More specific MRN selector
        PATIENT_LOCATION_SELECTOR: 'span[title*="UNIT/"]', // Assuming location is in a title attribute
        USER_NAME_SELECTOR: 'div.profile-wrapper span.csi-dropdown-btn-text', // User ID/Name
        SAMPLE_BARCODE_SELECTOR: 'div[style*="font-size: 13px; color: rgb(68, 68, 68);"]', // Example selector, adjust if needed
        LOCAL_SERVER_SAVE_URL: 'http://localhost:5000/save-alerts' // Example URL for local server
    };

    let isScanningActive = false;
    let issueScanIntervalId = null;
    let isAlertModalOpen = false; // Flag to prevent multiple modals

    const logAlertDebug = msg => console.debug(`[Alerts Scanner DEBUG] ${msg}`);
    const logAlertError = msg => console.error(`[Alerts Scanner ERROR] ${msg}`);

    function applyFlashingEffect(row) {
        if (!row || row.dataset.flashing === 'true') return;
        row.dataset.flashing = 'true';
        const originalBg = row.style.backgroundColor || 'transparent'; // Store original
        row.dataset.originalBg = originalBg;
        row.style.transition = "background-color 0.5s ease"; // Smooth transition
        let isPink = false;
        const intervalId = setInterval(() => {
            if (!document.body.contains(row) || row.dataset.flashing === 'false') { // Stop if row removed or flashing stopped
                clearInterval(intervalId);
                row.style.transition = ''; // Remove transition
                row.style.setProperty("background-color", row.dataset.originalBg || 'transparent', "important");
                delete row.dataset.flashing;
                delete row.dataset.originalBg;
                delete row.dataset.flashIntervalId;
                return;
            }
            isPink = !isPink;
            row.style.setProperty("background-color", isPink ? CONFIG_ALERTS.FLASH_COLOR : originalBg, "important");
        }, CONFIG_ALERTS.FLASH_INTERVAL);
        row.dataset.flashIntervalId = intervalId.toString(); // Store interval ID to clear it
    }

    function stopFlashingEffect(row) {
        if (row && row.dataset.flashing === 'true') {
            row.dataset.flashing = 'false'; // Signal to stop flashing
            const intervalId = parseInt(row.dataset.flashIntervalId, 10);
            if (!isNaN(intervalId)) {
                clearInterval(intervalId);
            }
            // The interval itself will handle reverting the style
        }
    }


    function getNotificationSessionKey(type, identifier = 'general') {
        // Sanitize identifier to prevent issues with special characters in sessionStorage keys
        const safeIdentifier = String(identifier).replace(/[^a-zA-Z0-9_-]/g, '');
        return `labAlertNotified_${window.location.pathname}${window.location.hash}_${type}_${safeIdentifier}`;
    }

    function hasAlreadyNotified(type, identifier = 'general') {
        const key = getNotificationSessionKey(type, identifier);
        return sessionStorage.getItem(key) === 'true';
    }

    function setNotificationFlag(type, identifier = 'general') {
        const key = getNotificationSessionKey(type, identifier);
        logAlertDebug(`Setting notification flag for key: "${key}"`);
        sessionStorage.setItem(key, 'true');
    }

    function getNextEntryID() {
        const counterKey = 'labAlertEntryCounter';
        let currentID = parseInt(localStorage.getItem(counterKey), 10) || 0;
        currentID++;
        localStorage.setItem(counterKey, String(currentID));
        logAlertDebug(`Next Entry ID: ${currentID}`);
        return currentID;
    }

    async function sendAlertDataToServer(alertData) {
        logAlertDebug("Attempting to send data to local server.");
        if (!CONFIG_ALERTS.LOCAL_SERVER_SAVE_URL) {
            logAlertError("LOCAL_SERVER_SAVE_URL is not configured.");
            console.error("Local server save URL is not configured for alerts.");
            return false;
        }

        // Get values from the modal inputs
        const notifiedPersonNameInput = document.getElementById('notifiedPersonNameInput');
        const notifiedPersonTelExtInput = document.getElementById('notifiedPersonTelExtInput');
        const readBackCheckbox = document.getElementById('readBackCheckbox');
        const userIdInput = document.getElementById('userIdInput'); // User ID from modal

        const now = new Date();
        const date = `${String(now.getDate()).padStart(2, '0')}/${String(now.getMonth() + 1).padStart(2, '0')}/${now.getFullYear()}`;
        const hours = now.getHours();
        const minutes = String(now.getMinutes()).padStart(2, '0');
        const ampm = hours >= 12 ? 'pm' : 'am';
        const formattedHours = hours % 12 || 12; // Convert 0 to 12 for 12 AM/PM
        const time = `${formattedHours}:${minutes} ${ampm}`;
        const entryID = getNextEntryID(); // Get a unique ID for this entry

        const dataToSend = {
            entryID: entryID,
            date: date,
            time: time,
            patientName: alertData.patientName || 'N/A',
            patientMRN: alertData.patientId || 'N/A',
            patientLocation: alertData.patientLocation || 'N/A',
            sampleBarcode: alertData.sampleBarcode || 'N/A',
            userName: userIdInput ? userIdInput.value : (alertData.userId || 'N/A'), // Use modal input if available
            notifiedPersonName: notifiedPersonNameInput ? notifiedPersonNameInput.value : '',
            notifiedPersonTelExt: notifiedPersonTelExtInput ? notifiedPersonTelExtInput.value : '',
            readBack: readBackCheckbox ? readBackCheckbox.checked : false,
            alerts: alertData.alertsToList.map(alert => ({
                testName: alert.testName,
                result: alert.result,
                uom: alert.uom || '',
                flag: alert.flag,
                type: alert.type, // e.g., 'critical', 'noresult'
                comment: alert.comment || ''
            })),
        };

        try {
            const response = await fetch(CONFIG_ALERTS.LOCAL_SERVER_SAVE_URL, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(dataToSend)
            });

            if (response.ok) {
                logAlertDebug("Data successfully sent to local server.");
                return true;
            } else {
                const errorText = await response.text();
                logAlertError(`Failed to send data to local server: ${response.status} ${response.statusText} - ${errorText}`);
                console.error(`Failed to save alert data to local server. Status: ${response.status}. Details: ${errorText}`);
                return false;
            }
        } catch (error) {
            logAlertError("Error sending data to local server:", error);
            // This usually means the server is not running or not accessible (CORS, network issue)
            console.error("An error occurred while trying to send data to the local server. Ensure the server is running and accessible.");
            return false;
        }
    }


    function closeAlertModalAction() {
        logAlertDebug("closeAlertModalAction triggered.");
        const overlay = document.getElementById('custom-alert-modal-overlay');
        if (overlay) {
            const modalContent = overlay.querySelector('#custom-alert-modal-content');
            if (modalContent && modalContent.dataset.alerts) {
                try {
                    const alertsToMark = JSON.parse(modalContent.dataset.alerts);
                    alertsToMark.forEach(alert => {
                        if (alert.type && alert.rowId) { // Ensure type and rowId exist
                            // The rowId is already prefixed like 'critical_ag-row-id-123'
                            // We need to extract the type and the base identifier
                            const parts = alert.rowId.split('_'); // e.g., ['critical', 'ag-row-id-123'] or ['noresult', 'idx', '0']
                            const type = parts[0];
                            const baseIdentifier = parts.slice(1).join('_'); // Reconstruct identifier if it had underscores
                            setNotificationFlag(type, baseIdentifier);
                            logAlertDebug(`Marked alert as notified: Type=${type}, Identifier=${baseIdentifier} (from full key ${alert.rowId})`);
                        }
                    });
                } catch (e) {
                    console.error("Error parsing alerts data from modal dataset:", e);
                }
            }

            // Smooth fade out
            overlay.style.opacity = '0';
            if (modalContent) {
                modalContent.style.opacity = '0';
                modalContent.style.transform = 'translateY(-30px) scale(0.95)';
            }

            // Remove after transition
            overlay.addEventListener('transitionend', () => {
                if (overlay.parentNode) {
                    overlay.parentNode.removeChild(overlay);
                    isAlertModalOpen = false; // Reset flag
                    document.body.style.overflow = ''; // Restore body scroll
                    logAlertDebug("Alert modal overlay removed, isAlertModalOpen = false");
                }
            }, { once: true });
            // Fallback removal if transitionend doesn't fire (e.g., element removed abruptly)
            setTimeout(() => {
                if (overlay && overlay.parentNode) {
                    overlay.parentNode.removeChild(overlay);
                    isAlertModalOpen = false;
                    document.body.style.overflow = '';
                    logAlertDebug("Alert modal overlay removed by fallback, isAlertModalOpen = false");
                }
            }, 400); // Slightly longer than transition
        } else {
            isAlertModalOpen = false; // Ensure flag is reset even if overlay wasn't found
            document.body.style.overflow = '';
            logAlertDebug("closeAlertModalAction called but overlay not found, isAlertModalOpen = false");
        }
    }

    function createCustomAlert(alertData, alertsDisplayedInModal) {
        logAlertDebug(`Attempting to create alert modal. isAlertModalOpen: ${isAlertModalOpen}, Existing overlay: ${document.getElementById('custom-alert-modal-overlay')}`);
        if (document.getElementById('custom-alert-modal-overlay') || isAlertModalOpen) {
            logAlertDebug("Alert modal already open or overlay element exists. Aborting creation.");
            return;
        }
        isAlertModalOpen = true;
        logDebugMain("Alert modal creation initiated. isAlertModalOpen set to true.");

        const overlay = document.createElement('div');
        overlay.id = 'custom-alert-modal-overlay';
        Object.assign(overlay.style, {
            position: 'fixed', top: '0', left: '0', width: '100%', height: '100%',
            backgroundColor: 'rgba(0, 0, 0, 0.65)', // Darker overlay
            zIndex: '10001', // Ensure it's on top
            display: 'flex', justifyContent: 'center', alignItems: 'center',
            opacity: '0', transition: 'opacity 0.3s ease-out', // Fade-in transition
            padding: '20px' // Padding for smaller screens so modal isn't edge-to-edge
        });
        document.body.style.overflow = 'hidden'; // Prevent background scrolling

        const modalBox = document.createElement('div');
        modalBox.id = 'custom-alert-modal-content';
        Object.assign(modalBox.style, {
            backgroundColor: '#ffffff',
            borderRadius: '12px', // Softer corners
            boxShadow: '0 16px 32px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.08)', // Enhanced shadow
            width: 'calc(100% - 40px)', // Responsive width with padding
            maxWidth: '1100px', // Max width for large screens
            maxHeight: '90vh', // Max height to prevent overflow on short screens
            overflowY: 'auto', // Scroll for content overflow
            padding: '32px', // Generous padding
            position: 'relative', // For absolute positioning of close button
            opacity: '0', transform: 'translateY(-20px) scale(0.98)', // Entry animation
            transition: 'opacity 0.3s ease-out, transform 0.3s ease-out',
            fontFamily: "'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
            color: '#343a40', // Dark grey for text
            display: 'flex', flexDirection: 'column', gap: '16px' // Use flex for layout
        });

        // Close Button (X)
        const closeButton = document.createElement('button');
        closeButton.innerHTML = '&times;'; // HTML entity for 'X'
        Object.assign(closeButton.style, {
            position: 'absolute', top: '18px', right: '18px',
            fontSize: '30px', lineHeight: '1', cursor: 'pointer', color: '#adb5bd', // Light grey
            background: 'transparent', border: 'none', padding: '0', width: '30px', height: '30px',
            display: 'flex', alignItems: 'center', justifyContent: 'center'
        });
        closeButton.onmouseover = () => closeButton.style.color = '#495057'; // Darken on hover
        closeButton.onmouseout = () => closeButton.style.color = '#adb5bd';
        closeButton.onclick = closeAlertModalAction;
        modalBox.appendChild(closeButton);

        // Header Section (Icon, Title, DateTime)
        const headerDiv = document.createElement('div');
        Object.assign(headerDiv.style, {
            display: 'flex', alignItems: 'center',
            gap: '12px', // Space between icon and title
            paddingBottom: '18px', borderBottom: '1px solid #dee2e6', marginBottom: '16px'
        });

        const alertIcon = document.createElement('i'); // FontAwesome icon
        alertIcon.className = 'fas fa-exclamation-triangle'; // Default icon
        let iconColor = '#17a2b8'; // Info blue as default

        let alertTitleText = 'Lab Alert Detected';
        if (alertData.overallSeverity === 'critical') {
            alertTitleText = 'Critical Lab Alert!'; iconColor = '#d9534f'; // Red for critical
        } else if (alertData.overallSeverity === 'noresult') {
            alertTitleText = 'No Result Detected'; iconColor = '#ffc107'; // Yellow for warning/no-result
        } else if (alertData.overallSeverity === 'greaterThan') {
            alertTitleText = 'Dilution Required'; iconColor = '#ffc107'; // Yellow for dilution
        }
        alertIcon.style.fontSize = '26px';
        alertIcon.style.color = iconColor;
        headerDiv.appendChild(alertIcon);

        const title = document.createElement('h2');
        title.textContent = alertTitleText;
        Object.assign(title.style, { fontSize: '26px', fontWeight: '600', color: iconColor, margin: '0' });
        headerDiv.appendChild(title);

        const dateTime = document.createElement('p');
        dateTime.id = 'currentDateTime';
        const now = new Date();
        dateTime.textContent = now.toLocaleString([], { dateStyle: 'medium', timeStyle: 'short' });
        Object.assign(dateTime.style, { fontSize: '14px', color: '#6c757d', margin: '0', marginLeft: 'auto' }); // Align to right
        headerDiv.appendChild(dateTime);
        modalBox.appendChild(headerDiv);


        // Patient Information Section
        const allPatientInfoContainer = document.createElement('div');
        Object.assign(allPatientInfoContainer.style, {
            display: 'flex',
            flexDirection: 'column', // Stack items vertically
            gap: '18px', // Space between info groups
            paddingBottom: '18px',
            borderBottom: '1px solid #dee2e6',
            marginBottom: '16px'
        });

        const createInfoItem = (label, value, iconClass) => {
            if (!value) value = 'N/A'; // Handle undefined/empty values
            const itemDiv = document.createElement('div');
            Object.assign(itemDiv.style, {
                backgroundColor: '#f8f9fa', borderRadius: '8px', padding: '16px',
                border: '1px solid #e9ecef', boxShadow: '0 3px 6px rgba(0,0,0,0.06)',
                display: 'flex', flexDirection: 'column', gap: '10px'
            });

            const header = document.createElement('div');
            Object.assign(header.style, { display: 'flex', alignItems: 'center', gap: '12px', color: '#495057' });

            if (iconClass) {
                const iconElem = document.createElement('i');
                iconElem.className = `fas ${iconClass}`;
                Object.assign(iconElem.style, { fontSize: '1.4em', color: '#007bff' }); // Blue icon
                header.appendChild(iconElem);
            }

            const labelElem = document.createElement('strong');
            labelElem.textContent = `${label}:`;
            labelElem.style.fontSize = '15px'; labelElem.style.fontWeight = '600';
            header.appendChild(labelElem);
            itemDiv.appendChild(header);

            const valueElem = document.createElement('span');
            valueElem.textContent = value;
            Object.assign(valueElem.style, {
                fontSize: '16px', color: '#212529', wordBreak: 'break-word',
                paddingLeft: iconClass ? '32px' : '0' // Indent value if icon present
            });
            itemDiv.appendChild(valueElem);
            return itemDiv;
        };

        // Patient Name (full width)
        const pNameItem = createInfoItem('Patient Name', alertData.patientName, 'fa-user');
        if (pNameItem) {
            allPatientInfoContainer.appendChild(pNameItem);
        }

        // Other Patient Info (Grid for MRN, Location, Barcode)
        const otherPatientInfoRow = document.createElement('div');
        Object.assign(otherPatientInfoRow.style, {
            display: 'grid',
            gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))', // Responsive grid
            gap: '18px',
        });

        const pIdElem = createInfoItem('MRN', alertData.patientId, 'fa-id-card');
        if (pIdElem) { otherPatientInfoRow.appendChild(pIdElem); }

        const pLocElem = createInfoItem('Location', alertData.patientLocation, 'fa-hospital-alt');
        if (pLocElem) { otherPatientInfoRow.appendChild(pLocElem); }

        const pBarcodeElem = createInfoItem('Sample Barcode', alertData.sampleBarcode, 'fa-barcode');
        if (pBarcodeElem) { otherPatientInfoRow.appendChild(pBarcodeElem); }

        if (otherPatientInfoRow.hasChildNodes()){
            allPatientInfoContainer.appendChild(otherPatientInfoRow);
        }

        if (allPatientInfoContainer.hasChildNodes()){
            modalBox.appendChild(allPatientInfoContainer);
        }


        // Alerts List Section
        if (alertData.alertsToList && alertData.alertsToList.length > 0) {
            const alertsListTitle = document.createElement('h3');
            alertsListTitle.textContent = 'Alert Details:';
            Object.assign(alertsListTitle.style, {
                fontSize: '19px', fontWeight: '600', color: '#343a40',
                margin: '0 0 12px 0', // Spacing
            });
            modalBox.appendChild(alertsListTitle);

            const alertsContainer = document.createElement('div');
            Object.assign(alertsContainer.style, {
                display: 'grid',
                gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', // Responsive grid for alert cards
                gap: '18px',
                padding: '5px 0' // Small padding for internal spacing
            });

            alertData.alertsToList.forEach(alert => {
                const alertCard = document.createElement('div');
                let borderColor = '#6c757d', bgColor = '#f8f9fa', textColor = '#343a40'; // Default styling

                // Customize card style based on alert type/flag
                if (alert.type === 'critical') {
                    if (alert.flag === 'CL') { // Critical Low
                        borderColor = '#007bff'; bgColor = '#e7f3ff'; // Blue theme
                    } else if (alert.flag === 'CH') { // Critical High
                        borderColor = '#dc3545'; bgColor = '#f8d7da'; // Red theme
                    } else { // General critical
                        borderColor = '#d9534f'; bgColor = '#fdf7f7';
                    }
                } else if (alert.type === 'greaterThan') { // Dilution
                    borderColor = '#ffc107'; bgColor = '#fff9e6'; // Yellow theme
                } else if (alert.type === 'noresult') { // No Result
                    borderColor = '#6c757d'; bgColor = '#f8f9fa'; // Grey theme
                }

                Object.assign(alertCard.style, {
                    borderLeft: `6px solid ${borderColor}`, padding: '18px', borderRadius: '10px',
                    backgroundColor: bgColor, color: textColor, boxShadow: '0 5px 10px rgba(0,0,0,0.08)',
                    display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: '130px'
                });

                const testNameElem = document.createElement('p');
                testNameElem.innerHTML = `<strong style="font-size: 17px; color: #212529;">${alert.testName}</strong>`;
                testNameElem.style.margin = '0 0 10px 0';
                alertCard.appendChild(testNameElem);

                const resultElem = document.createElement('p');
                const resultText = alert.result || 'N/A';
                const uomText = alert.uom ? ` ${alert.uom}` : '';
                resultElem.textContent = `Result: ${resultText}${uomText}`;
                resultElem.style.margin = '0 0 10px 0';
                resultElem.style.fontSize = '15px';
                alertCard.appendChild(resultElem);

                if (alert.flag) {
                    const flagElem = document.createElement('p');
                    let flagDescription = `Flag: ${alert.flag}`;
                    if (alert.flag === 'CL') flagDescription = 'Flag: CL (Critical Low)';
                    else if (alert.flag === 'CH') flagDescription = 'Flag: CH (Critical High)';
                    flagElem.textContent = flagDescription;
                    Object.assign(flagElem.style, {margin: '0', fontSize: '15px', fontWeight: '600', color: borderColor });
                    alertCard.appendChild(flagElem);
                }
                 if (alert.comment) { // Display comment if present
                    const commentElem = document.createElement('p');
                    commentElem.textContent = alert.comment;
                    Object.assign(commentElem.style, {
                        fontSize: '13px', fontStyle: 'italic', color: '#555',
                        marginTop: '8px', paddingTop: '8px', borderTop: '1px dashed #ccc'
                    });
                    alertCard.appendChild(commentElem);
                }

                alertsContainer.appendChild(alertCard);
            });
            modalBox.appendChild(alertsContainer);
        } else if (alertData.primaryMessage) { // Fallback for single message if no list
            const primaryMessageElem = document.createElement('p');
            primaryMessageElem.textContent = alertData.primaryMessage;
            Object.assign(primaryMessageElem.style, { fontSize: '16px', fontWeight: '500', margin: '12px 0', color: '#555' });
            modalBox.appendChild(primaryMessageElem);
        }


        // Notification Details Form (for Critical Alerts)
        if (alertData.overallSeverity === 'critical') {
            const notifiedDetailsDiv = document.createElement('div');
            Object.assign(notifiedDetailsDiv.style, {
                marginTop: '24px', paddingTop: '20px', borderTop: '1px solid #dee2e6'
            });

            const h3 = document.createElement('h3');
            h3.textContent = 'Notification Details (Critical)';
            Object.assign(h3.style, { fontSize: '17px', fontWeight: '600', marginBottom: '16px', color: '#343a40'});
            notifiedDetailsDiv.appendChild(h3);

            const formGrid = document.createElement('div');
            Object.assign(formGrid.style, { display: 'grid', gridTemplateColumns: '1fr', gap: '14px' }); // Single column for simplicity

            const createFormGroup = (label, inputId, placeholder, type = 'text') => {
                const formGroup = document.createElement('div');
                const formLabel = document.createElement('label');
                formLabel.textContent = label;
                formLabel.htmlFor = inputId;
                Object.assign(formLabel.style, { display: 'block', fontSize: '14px', fontWeight: '500', marginBottom: '6px', color: '#495057' });
                formGroup.appendChild(formLabel);

                const formInput = document.createElement('input');
                formInput.type = type;
                formInput.id = inputId;
                formInput.placeholder = placeholder;
                Object.assign(formInput.style, {
                    width: '100%', padding: '12px', border: '1px solid #ced4da',
                    borderRadius: '6px', fontSize: '14px', boxSizing: 'border-box',
                    transition: 'border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out'
                });
                formInput.onfocus = () => { formInput.style.borderColor = '#80bdff'; formInput.style.boxShadow = '0 0 0 0.2rem rgba(0,123,255,.25)';};
                formInput.onblur = () => { formInput.style.borderColor = '#ced4da'; formInput.style.boxShadow = 'none';};
                formGroup.appendChild(formInput);
                return formGroup;
            };

            const userIdGroup = createFormGroup('User ID', 'userIdInput', 'Enter your User ID');
            formGrid.appendChild(userIdGroup);
            const userIdInputElem = userIdGroup.querySelector('#userIdInput'); // Get the input element
            if (userIdInputElem && alertData.userId && alertData.userId !== 'N/A') { // Pre-fill if available
                userIdInputElem.value = alertData.userId;
            }

            formGrid.appendChild(createFormGroup('Notified Person Name', 'notifiedPersonNameInput', 'Name of person notified'));
            formGrid.appendChild(createFormGroup('Extension / Contact', 'notifiedPersonTelExtInput', 'Phone or extension'));

            const readBackGroup = document.createElement('div');
            Object.assign(readBackGroup.style, { display: 'flex', alignItems: 'center', marginTop: '10px'});
            const readBackCheckbox = document.createElement('input');
            readBackCheckbox.type = 'checkbox'; readBackCheckbox.id = 'readBackCheckbox';
            Object.assign(readBackCheckbox.style, { marginRight: '10px', height: '18px', width: '18px', cursor: 'pointer', accentColor: '#007bff'});
            const readBackLabel = document.createElement('label');
            readBackLabel.textContent = 'Read-Back Confirmed'; readBackLabel.htmlFor = 'readBackCheckbox';
            Object.assign(readBackLabel.style, { fontSize: '14px', fontWeight: '500', color: '#495057', cursor: 'pointer'});
            readBackGroup.appendChild(readBackCheckbox); readBackGroup.appendChild(readBackLabel);
            formGrid.appendChild(readBackGroup);

            notifiedDetailsDiv.appendChild(formGrid);
            modalBox.appendChild(notifiedDetailsDiv);
        }

        // Button Container
        const buttonContainer = document.createElement('div');
        Object.assign(buttonContainer.style, {
            display: 'flex', justifyContent: 'flex-end', // Align buttons to the right
            paddingTop: '24px', marginTop: 'auto', // Push to bottom if content is short
            gap: '12px', borderTop: '1px solid #dee2e6'
        });

        const createModalButton = (text, styleType = 'primary') => {
            const button = document.createElement('button');
            button.textContent = text;
            Object.assign(button.style, {
                padding: '12px 24px', borderRadius: '8px', fontWeight: '600', fontSize: '15px',
                border: 'none', cursor: 'pointer',
                transition: 'background-color 0.2s ease, box-shadow 0.2s ease, transform 0.1s ease'
            });
            if (styleType === 'primary') {
                button.style.backgroundColor = '#007bff'; button.style.color = 'white';
                button.onmouseover = () => button.style.backgroundColor = '#0069d9';
                button.onmouseout = () => button.style.backgroundColor = '#007bff';
            } else if (styleType === 'success') { // For Acknowledge & Save
                 button.style.backgroundColor = '#28a745'; button.style.color = 'white';
                button.onmouseover = () => button.style.backgroundColor = '#218838';
                button.onmouseout = () => button.style.backgroundColor = '#28a745';
            } else { // Default/secondary
                button.style.backgroundColor = '#6c757d'; button.style.color = 'white';
                button.onmouseover = () => button.style.backgroundColor = '#5a6268';
                button.onmouseout = () => button.style.backgroundColor = '#6c757d';
            }
            button.onmousedown = () => button.style.transform = 'scale(0.98)'; // Click effect
            button.onmouseup = () => button.style.transform = 'scale(1)';
            return button;
        };


        if (alertData.overallSeverity === 'critical') {
            const acknowledgeButton = createModalButton('Acknowledge & Save', 'success');
            acknowledgeButton.onclick = async () => {
                logAlertDebug("Acknowledge & Save button clicked.");
                const success = await sendAlertDataToServer(alertData);
                if (success) {
                    logAlertDebug("Data sent successfully. Closing modal.");
                    closeAlertModalAction();
                } else {
                    logAlertDebug("Data send failed. Modal remains open.");
                    const errorMsgElem = document.getElementById('sendErrorMsg');
                    if (errorMsgElem) errorMsgElem.textContent = 'Failed to save. Check server or try again.';
                }
            };
            buttonContainer.appendChild(acknowledgeButton);
            // Error message placeholder for send failure
            const sendErrorMsg = document.createElement('p');
            sendErrorMsg.id = 'sendErrorMsg';
            Object.assign(sendErrorMsg.style, {color: 'red', fontSize: '13px', margin: '0 auto 0 0', flexGrow: 1, alignSelf: 'center'});
            buttonContainer.insertBefore(sendErrorMsg, acknowledgeButton); // Place error message before buttons

        } else { // For non-critical, just an OK button
            const okButton = createModalButton('OK', 'primary');
            okButton.onclick = closeAlertModalAction;
            buttonContainer.appendChild(okButton);
        }

        modalBox.appendChild(buttonContainer);
        // Store a list of alerts that were shown in this modal instance for later marking as notified
        modalBox.dataset.alerts = JSON.stringify(alertsDisplayedInModal.map(a => ({ type: a.type, rowId: a.rowId })));


        overlay.appendChild(modalBox);
        document.body.appendChild(overlay);

        // Trigger fade-in and animation
        setTimeout(() => {
            overlay.style.opacity = '1';
            modalBox.style.opacity = '1';
            modalBox.style.transform = 'translateY(0) scale(1)';
            logAlertDebug("Alert modal fade-in and animation triggered.");
        }, 10); // Small delay to ensure styles are applied before transition starts

        // Close modal on Escape key or click outside
        overlay.addEventListener('click', (event) => {
            if (event.target === overlay) { // Clicked on overlay itself
                closeAlertModalAction();
            }
        });
        const escapeKeyListener = (event) => {
            if (event.key === 'Escape' && document.body.contains(overlay)) { // Check if modal is still in DOM
                closeAlertModalAction();
                document.removeEventListener('keydown', escapeKeyListener); // Clean up listener
            }
        };
        document.addEventListener('keydown', escapeKeyListener);

    }

    function scrollToRowNearest(row) {
        if (!row) return false;
        let rowToScroll = row;
        // If the row is in the center container, try to find its corresponding pinned row for scrolling
        // This helps if the test description (usually pinned) is what needs to be visible
        if (row.closest('.ag-center-cols-container')) {
            const rowIndex = row.getAttribute('row-index'); // AG-Grid often uses row-index
            if (rowIndex) {
                const pinnedRow = document.querySelector(`.ag-pinned-left-cols-container .ag-row[row-index="${rowIndex}"]`);
                if (pinnedRow) rowToScroll = pinnedRow;
            }
        }

        document.documentElement.style.scrollBehavior = 'smooth';
        rowToScroll.scrollIntoView({ behavior: 'auto', block: 'center' }); // 'auto' for behavior if smooth is too slow
        setTimeout(() => document.documentElement.style.scrollBehavior = 'auto', 500); // Reset scroll behavior
        return true;
    }

    async function getPatientDataWithRetry(selectors, maxWaitTime = 2000, checkInterval = 100) {
        let elapsedTime = 0;
        let patientData = { patientName: 'N/A', patientId: 'N/A', patientLocation: 'N/A', sampleBarcode: 'N/A' };

        // Helper to check if essential elements are present
        function elementsPresent() {
            return document.querySelector(selectors.name) &&
                   document.querySelector(selectors.mrn) &&
                   document.querySelector(selectors.location); // Barcode is optional for this check
        }

        // Wait for essential elements to be available
        while (elapsedTime < maxWaitTime) {
            if (elementsPresent()) {
                logAlertDebug("Essential patient data elements detected.");
                break;
            }
            await new Promise(resolve => setTimeout(resolve, checkInterval));
            elapsedTime += checkInterval;
            if (elapsedTime % 500 === 0) { // Log progress occasionally
                logAlertDebug(`Waiting for patient data elements... ${elapsedTime}ms`);
            }
        }

        if (!elementsPresent() && elapsedTime >= maxWaitTime) {
            logAlertDebug(`Essential patient data elements not found after ${maxWaitTime}ms. Using N/A for some fields.`);
        }

        // Retrieve data, providing 'N/A' if elements are not found or empty
        const nameEl = document.querySelector(selectors.name);
        patientData.patientName = nameEl ? nameEl.textContent.trim().replace(/\s+/g, ' ') : 'N/A'; // Normalize whitespace

        const mrnEl = document.querySelector(selectors.mrn);
        patientData.patientId = mrnEl ? mrnEl.textContent.trim() : 'N/A';

        const locElement = document.querySelector(selectors.location);
        // Prefer title attribute for location if available, otherwise textContent
        patientData.patientLocation = locElement ? (locElement.title?.trim() || locElement.textContent?.trim()) : 'N/A';
        if (patientData.patientLocation === '') patientData.patientLocation = 'N/A'; // Ensure not empty string

        const barcodeEl = document.querySelector(selectors.barcode);
        patientData.sampleBarcode = barcodeEl ? barcodeEl.textContent.trim() : 'N/A';
        if (patientData.sampleBarcode === '') patientData.sampleBarcode = 'N/A';

        return patientData;
    }


    async function checkForIssues() {
        if (!isScanningActive || isAlertModalOpen) return false; // Don't scan if paused or modal is already open

        const patientDataSelectors = {
            name: CONFIG_ALERTS.PATIENT_NAME_SELECTOR,
            mrn: CONFIG_ALERTS.PATIENT_MRN_SELECTOR,
            location: CONFIG_ALERTS.PATIENT_LOCATION_SELECTOR,
            barcode: CONFIG_ALERTS.SAMPLE_BARCODE_SELECTOR
        };

        const patientDataSource = await getPatientDataWithRetry(patientDataSelectors);

        const patientName = patientDataSource.patientName;
        const patientId = patientDataSource.patientId;
        const patientLocation = patientDataSource.patientLocation;
        const sampleBarcode = patientDataSource.sampleBarcode;

        const userIdElement = document.querySelector(CONFIG_ALERTS.USER_NAME_SELECTOR);
        const currentUserId = userIdElement ? userIdElement.textContent.trim() : 'N/A';

        const centerRows = document.querySelectorAll('.ag-center-cols-container .ag-row');
        const pinnedRows = document.querySelectorAll('.ag-pinned-left-cols-container .ag-row');
        const potentialAlerts = [];

        centerRows.forEach((centerRow, index) => {
            const pinnedRow = pinnedRows[index]; // Assumes matching indices for pinned and center rows
            if (!centerRow || !pinnedRow || centerRow.offsetParent === null) return; // Skip if not visible or no matching pinned row

            const testDescElement = pinnedRow.querySelector('div[col-id="TestDesc"]');
            const testDesc = testDescElement?.textContent?.trim() || 'Unknown Test';
            const resultDiv = centerRow.querySelector(CONFIG_ALERTS.RESULT_CELL_SELECTOR);
            const flagSpan = centerRow.querySelector(CONFIG_ALERTS.CRITICAL_FLAG_SELECTOR);
            const uomCell = centerRow.querySelector(CONFIG_ALERTS.UOM_CELL_SELECTOR);

            // Create a unique identifier for the row for sessionStorage tracking
            const baseRowIdentifier = centerRow.getAttribute('row-id') || centerRow.getAttribute('row-index') || `idx_${index}`;
            const resultText = resultDiv?.textContent?.trim() || '';
            const uomText = uomCell?.textContent?.trim() || '';
            const normalizedResultText = resultText.toLowerCase().replace(/[- ]/g, ''); // Normalize for "no-result" checks
            const flagText = flagSpan?.textContent?.trim()?.toUpperCase() || ''; // CL, CH

            // Determine alert type
            const isNoResult = ["noresult", "noxresult", "x-noresult"].includes(normalizedResultText);
            const isDilution = resultText.includes(">"); // Simple check for dilution needed
            const isCritical = (flagSpan && (flagText === "CL" || flagText === "CH"));

            let alertType = null;
            let alertMessage = "";
            let alertComment = null; // For additional context like "Sample needs dilution"

            if (isCritical) {
                alertType = "critical";
                alertMessage = `CRITICAL ${flagText === "CL" ? "LOW" : "HIGH"} RESULT!`;
            } else if (isNoResult) {
                alertType = "noresult";
                alertMessage = CONFIG_ALERTS.NO_RESULT_MESSAGE;
            } else if (isDilution) {
                alertType = "greaterThan";
                alertMessage = CONFIG_ALERTS.DILUTION_MESSAGE;
                alertComment = "Sample needs dilution"; // Add specific comment for dilution
            }

            if (alertType) {
                if (!hasAlreadyNotified(alertType, baseRowIdentifier)) {
                    potentialAlerts.push({
                        rowElement: centerRow, type: alertType,
                        rowId: `${alertType}_${baseRowIdentifier}`, // Composite key for session storage
                        baseIdentifier: baseRowIdentifier, // Store base for easier reference
                        message: alertMessage,
                        comment: alertComment,
                        testName: testDesc, result: resultText, uom: uomText, flag: flagText
                    });
                }
                applyFlashingEffect(centerRow); // Flash the center row
                applyFlashingEffect(pinnedRow); // Flash the corresponding pinned row
            } else {
                stopFlashingEffect(centerRow);
                stopFlashingEffect(pinnedRow);
            }
        });

        if (potentialAlerts.length > 0 && !isAlertModalOpen && !document.getElementById('custom-alert-modal-overlay')) {
            // Prioritize showing critical alerts first if multiple types are present
            const firstSignificantAlert =
                potentialAlerts.find(a => a.type === 'critical') ||
                potentialAlerts.find(a => a.type === 'noresult') ||
                potentialAlerts.find(a => a.type === 'greaterThan') ||
                potentialAlerts[0]; // Fallback to the first alert

            scrollToRowNearest(firstSignificantAlert.rowElement); // Scroll to the most significant alert

            const modalData = {
                alertsToList: potentialAlerts.map(a => ({ // Pass all details for display
                    testName: a.testName, result: a.result, uom: a.uom, flag: a.flag, type: a.type,
                    rowId: a.rowId, // Pass the full rowId used for notification tracking
                    comment: a.comment
                })),
                overallSeverity: firstSignificantAlert.type, // Used for modal title and icon
                primaryMessage: firstSignificantAlert.message, // Main message for the modal
                patientName: patientName,
                patientId: patientId,
                patientLocation: patientLocation,
                sampleBarcode: sampleBarcode,
                userId: currentUserId
            };
            createCustomAlert(modalData, potentialAlerts); // Pass all potential alerts for marking

            // Pause scanner after showing alerts for this patient to avoid repeated modals for same data
            logAlertDebug("Alerts shown for patient. Pausing scanner.");
            if (window.stopAlertsScanner) window.stopAlertsScanner(); // Call the global pause function

            return true; // Alerts were found and processed
        } else if (potentialAlerts.length === 0) {
            // If no alerts, ensure any residual flashing is stopped
            document.querySelectorAll('.ag-center-cols-container .ag-row[data-flashing="true"]').forEach(stopFlashingEffect);
            document.querySelectorAll('.ag-pinned-left-cols-container .ag-row[data-flashing="true"]').forEach(stopFlashingEffect);
        }
        return false; // No new alerts to show
    }

    function startAlertsScannerInternal() {
        logAlertDebug("startAlertsScannerInternal called.");
        if (!isScanningActive && issueScanIntervalId === null) { // Only start if not already active and no interval ID
            logAlertDebug("Alert Scanner starting/resuming...");
            isScanningActive = true;
            if (issueScanIntervalId) clearInterval(issueScanIntervalId); // Clear any old interval just in case
            checkForIssues(); // Initial check
            issueScanIntervalId = setInterval(checkForIssues, CONFIG_ALERTS.SCAN_INTERVAL);
            logAlertDebug(`Alert Scanner interval set: ${issueScanIntervalId}`);
        } else {
            logAlertDebug(`Alert Scanner already active or interval set. Active: ${isScanningActive}, IntervalID: ${issueScanIntervalId}`);
        }
    }

    function stopAlertsScannerInternal() { // This acts more like a "pause"
        logAlertDebug("stopAlertsScannerInternal called (pause).");
        if (isScanningActive) { // Only act if it was active
            logAlertDebug("Alert Scanner pausing...");
            clearInterval(issueScanIntervalId);
            issueScanIntervalId = null; // Clear interval ID, but keep isScanningActive = true
                                        // This indicates it's paused but should resume on new patient/page
            // Flashing rows will stop naturally when modal is closed or page changes.
            logAlertDebug("Scanner interval cleared for pause. isScanningActive remains true (paused state).");
        } else {
             logAlertDebug("Alert Scanner not active, no action taken by stop/pause.");
        }
    }

    // Expose scanner controls globally for external management (e.g., on page change)
    window.startAlertsScanner = startAlertsScannerInternal;
    window.stopAlertsScanner = stopAlertsScannerInternal; // This is now a "pause"

    // --- Page Navigation Observer (for starting/stopping scanner and features) ---
    let previousObservedUrl = window.location.href;
    let currentPatientProcessed = false; // Flag to manage scanner pause/resume per patient view

    const pageUrlObserver = new MutationObserver(() => {
        const newObservedUrl = window.location.href;

        if (newObservedUrl !== previousObservedUrl) {
            logDebugMain(`URL changed from: ${previousObservedUrl} to: ${newObservedUrl}.`);
            currentPatientProcessed = false; // Reset flag, indicating a new patient/context

            const wasOnEditPage = previousObservedUrl.startsWith(CONFIG_MAIN.URLS.EDIT_PAGE_PREFIX);
            const nowOnEditPage = newObservedUrl.startsWith(CONFIG_MAIN.URLS.EDIT_PAGE_PREFIX);

            if (wasOnEditPage && !nowOnEditPage) { // Navigated AWAY from an edit page
                logDebugMain(`Left an edit page (${previousObservedUrl}). Fully stopping scanner and cleaning UI.`);
                isScanningActive = false; // Truly stop the scanner
                if (window.stopAlertsScanner) window.stopAlertsScanner(); // Call the pause, but isScanningActive=false prevents restart

                // Clear session storage flags for the *specific page* being left
                 try {
                    const oldUrlObject = new URL(previousObservedUrl, window.location.origin); // Ensure base URL for relative paths
                    const oldPageKeyPrefix = `labAlertNotified_${oldUrlObject.pathname}${oldUrlObject.hash}_`;
                    logAlertDebug(`Attempting to clear session flags with prefix: "${oldPageKeyPrefix}"`);
                    Object.keys(sessionStorage)
                        .filter(key => key.startsWith(oldPageKeyPrefix))
                        .forEach(key => {
                            sessionStorage.removeItem(key);
                            logAlertDebug(`Cleared session flag: ${key}`);
                        });
                    logAlertDebug(`Session flags for prefix "${oldPageKeyPrefix}" cleared.`);
                } catch (e) {
                    logAlertError(`Error processing old URL (${previousObservedUrl}) for flag clearing: ${e}`);
                }
                // Remove buttons if they exist
                const customButtons = document.getElementById('custom-script-buttons');
                if (customButtons) customButtons.remove();
            }

            if (nowOnEditPage) {
                logDebugMain(`Now on a new edit page (${newObservedUrl}). Setting up features and (re)starting scanner.`);
                hasScrolledToOrderedRow = false; // Reset for new page
                isAlertModalOpen = false; // Reset modal flag
                // Close any existing alert modal forcefully if navigation happened while it was open
                const existingAlertOverlay = document.getElementById('custom-alert-modal-overlay');
                if (existingAlertOverlay) existingAlertOverlay.remove();


                setTimeout(() => {
                    // Start scanner only if not already "processed" (i.e., paused after showing alerts for this patient)
                    if (!currentPatientProcessed && window.startAlertsScanner) {
                         window.startAlertsScanner();
                    }
                    addButtons(); // Add F7/F8 buttons
                    addFontAwesome(); // Ensure icons are available
                    monitorOrderedStatus(); // Initial check for 'Ordered' status
                }, 700); // Delay to allow page elements to load
            } else { // Not on an edit page
                logDebugMain(`Not on an edit page (${newObservedUrl}). Ensuring UI cleanup.`);
                const customButtons = document.getElementById('custom-script-buttons');
                if (customButtons) customButtons.remove();
                // If truly leaving edit pages, ensure scanner is fully stopped
                if (isScanningActive && window.stopAlertsScanner) {
                    isScanningActive = false; // Mark as not active
                    window.stopAlertsScanner(); // Call the pause/clear interval
                }
            }
            previousObservedUrl = newObservedUrl;
        } else { // URL has not changed, but mutations occurred
            const stillOnEditPage = newObservedUrl.startsWith(CONFIG_MAIN.URLS.EDIT_PAGE_PREFIX);
            if (stillOnEditPage) {
                // Check if buttons are missing (e.g., due to SPA re-render without URL change)
                if (!document.getElementById('custom-script-buttons')) {
                    logDebugMain("Buttons missing on edit page (no URL change), re-adding.");
                    addButtons();
                }
                addFontAwesome(); // Ensure icons are still there
                // If scanner was paused (isScanningActive=true, but intervalId=null) and it's still the same patient page,
                // it should remain paused.
                // If it's a page refresh for a new patient (somehow URL didn't change initially),
                // startAlertsScanner will handle it if currentPatientProcessed is false.
                if (!isScanningActive && !currentPatientProcessed && window.startAlertsScanner) {
                     // This case might be rare, but handles if scanner was fully stopped and needs restart on same URL
                     logDebugMain("Scanner not active on current edit page (no URL change), attempting restart.");
                     window.startAlertsScanner();
                }
            }
        }
    });
    pageUrlObserver.observe(document.body, { childList: true, subtree: true });

    // --- Initial Setup on Load ---
    if (isCorrectPage()) {
        logDebugMain("Initial page load on correct page. Setting up features.");
        currentPatientProcessed = false; // Reset for initial load
        setTimeout(() => {
            if (window.startAlertsScanner) window.startAlertsScanner();
            addFontAwesome();
            addButtons();
            monitorOrderedStatus();
        }, 700); // Delay for page elements
    } else {
        logDebugMain("Initial page load not on correct page. No features started.");
    }

    // --- Periodic Checks ---
    setInterval(checkUrlAndTriggerClickForUndefined, CONFIG_MAIN.CHECK_INTERVALS.UNDEFINED_URL);
    setInterval(checkForDisabledButtons, CONFIG_MAIN.CHECK_INTERVALS.DISABLED_BTN_CHECK); // Less frequent check for disabled buttons

})();


// User's SAMPLES COUNT Logic (IIFE) - Integrated and Styles Updated
// This is the logic from the original "1.js" script, integrated here.
(function () {
    'use strict';

    const SCRIPT_PREFIX_SAMPLES = "[SAMPLES COUNT 통합]"; // Changed prefix for clarity
    const logSampleCountDebug = msg => console.debug(`${SCRIPT_PREFIX_SAMPLES} ${msg}`);
    // const logSampleCountError = msg => console.error(`${SCRIPT_PREFIX_SAMPLES} ${msg}`); // Already defined in main script

    function createCounterElementSamples(id) { // Renamed to avoid conflict if any global function existed
        const wrapper = document.createElement('span');
        wrapper.id = id;
        Object.assign(wrapper.style, {
            display: 'inline-flex',
            alignItems: 'center',
            padding: '6px 12px',
            backgroundColor: '#e9ecef', // Light grey background
            borderRadius: '20px', // Rounded corners
            boxShadow: '0 2px 5px rgba(0,0,0,0.1)', // Subtle shadow
            marginRight: 'auto', // Pushes to the left if in a flex container
            marginLeft: '10px', // Margin from other elements
            fontSize: '14px',
            fontWeight: '500',
            color: '#495057', // Dark grey text
            verticalAlign: 'middle'
        });

        const label = document.createElement('span');
        label.textContent = 'SAMPLES COUNT: ';
        label.style.marginRight = '8px';

        const badge = document.createElement('span');
        badge.className = 'sample-count-badge'; // For potential specific styling via CSS
        badge.textContent = '0'; // Initialize with 0
        Object.assign(badge.style, {
            backgroundColor: '#6c757d', // Default grey for 0
            color: '#ffffff', // White text
            padding: '4px 10px',
            borderRadius: '12px', // Rounded badge
            fontSize: '14px',
            fontWeight: 'bold',
            minWidth: '26px', // Ensure badge has some width even for single digit
            textAlign: 'center',
            lineHeight: '1' // Ensure text is centered vertically
        });

        wrapper.appendChild(label);
        wrapper.appendChild(badge);
        return wrapper;
    }

    function updateSpecificCounterSamples(modalElementForInputs, counterElement, inputSelector) {
        const badge = counterElement.querySelector('.sample-count-badge');
        // Ensure all elements are valid and connected to the DOM
        if (!badge || !modalElementForInputs || !document.body.contains(modalElementForInputs) || !counterElement.isConnected) {
            return;
        }
        const inputs = modalElementForInputs.querySelectorAll(inputSelector);
        const count = inputs.length;
        badge.textContent = count;
        badge.style.backgroundColor = count > 0 ? '#28a745' : '#6c757d'; // Green if > 0, else grey
    }

    // This function sets up a counter for a specific modal type
    function setupModalCounterSamples(modalConfig) {
        const { modalKeyElement, targetFooter, counterId, inputSelector, activeIntervalsMap, buttonIdForLog } = modalConfig;
        logSampleCountDebug(`Setup for ${buttonIdForLog}: ModalKeyElement found: ${!!modalKeyElement}, TargetFooter found: ${!!targetFooter}`);

        if (targetFooter.querySelector('#' + counterId)) {
            logSampleCountDebug(`Setup for ${buttonIdForLog}: Counter (ID: ${counterId}) already exists in footer. Skipping.`);
            return false; // Counter already exists
        }

        logSampleCountDebug(`Setup for ${buttonIdForLog}: Creating counter (ID: ${counterId}).`);
        const counter = createCounterElementSamples(counterId);
        targetFooter.insertBefore(counter, targetFooter.firstChild); // Insert at the beginning of the footer
        logSampleCountDebug(`Setup for ${buttonIdForLog}: Counter (ID: ${counterId}) CREATED and INSERTED.`);

        // Determine the element within the modal to search for inputs
        const modalElementForInputs = modalKeyElement.querySelector('.modal-body') || modalKeyElement.querySelector('.modal-content') || modalKeyElement;

        const interval = setInterval(() => {
            const modalStillTracked = document.body.contains(modalKeyElement);
            const counterStillPresent = counter.isConnected;
            // Check modal visibility (common classes and style checks)
            const modalVisible = modalStillTracked && (
                modalKeyElement.classList.contains('show') ||
                modalKeyElement.classList.contains('modal-open') ||
                (modalKeyElement.style.display && modalKeyElement.style.display !== 'none') ||
                (!modalKeyElement.style.display && modalKeyElement.offsetParent !== null) // Check if rendered
            );

            if (!modalStillTracked || !counterStillPresent || !modalVisible) {
                logSampleCountDebug(`Interval for ${buttonIdForLog} (Counter ID: ${counterId}): Cleaning up. ModalTracked: ${modalStillTracked}, CounterPresent: ${counterStillPresent}, ModalVisible: ${modalVisible}`);
                clearInterval(interval);
                activeIntervalsMap.delete(modalKeyElement); // Remove from active tracking
                if (counter.isConnected) { // Remove counter from DOM if it's still there
                    counter.remove();
                }
                return;
            }
            updateSpecificCounterSamples(modalElementForInputs, counter, inputSelector);
        }, 500); // Update interval

        activeIntervalsMap.set(modalKeyElement, { interval, counterId }); // Track active interval
        return true;
    }


    function observeModalsSamples() { // Renamed to avoid conflict
        const activeModalIntervals = new Map(); // Tracks modals and their counter intervals
        logSampleCountDebug("Sample Count Modal observer callback function defined.");

        const getModalKeyDetails = (el) => { // Helper for logging
            if (!el) return "null";
            const tagName = el.tagName || "UNKNOWN_TAG";
            let className = "";
            if (el.className && typeof el.className === 'string') {
                className = el.className.trim().replace(/\s+/g, '.');
            } else if (el.className && typeof el.className.baseVal === 'string') { // For SVG elements
                className = el.className.baseVal.trim().replace(/\s+/g, '.');
            }
            return `${tagName}${className ? '.' + className : ''}`;
        };

        const observer = new MutationObserver((mutationsList) => {
            // --- Target Modal Type 1 (Sample Collection / CPL Receptionist Modal) ---
            // Usually identified by a button like 'btnclose-smplcollection' or specific app component
            const buttonSmplCollection = document.querySelector('button#btnclose-smplcollection'); // Or other unique element in this modal
            if (buttonSmplCollection) {
                const footerSmplCollection = buttonSmplCollection.closest('.modal-footer');
                if (footerSmplCollection) {
                    // The modalKeyElement should be the main modal container that stays in the DOM while the modal is open
                    // and is removed or hidden when closed. '.modal' or '.modal-dialog' are common.
                    const modalKeyElement = footerSmplCollection.closest('.modal.show, .modal-dialog, modal-container.show'); // More robust selector
                    if (modalKeyElement && !activeModalIntervals.has(modalKeyElement)) {
                        logSampleCountDebug(`Found potential modal for 'btnclose-smplcollection' (modal key: ${getModalKeyDetails(modalKeyElement)}). Attempting setup.`);
                        setupModalCounterSamples({
                            buttonIdForLog: 'btnclose-smplcollection',
                            counterId: 'inline-counter-smplcollection',
                            inputSelector: 'tbody[formarrayname="TubeTypeList"] input[formcontrolname="PatientID"]', // Specific to this modal
                            modalKeyElement: modalKeyElement,
                            targetFooter: footerSmplCollection,
                            activeIntervalsMap: activeModalIntervals
                        });
                    }
                }
            }

            // --- Target Modal Type 2 (Sample Receive / WB Modal) ---
            // Usually identified by a button like 'closebtn-smplrecieve' or specific app component
            const buttonSmplRecieve = document.querySelector('button#closebtn-smplrecieve'); // Or other unique element
            if (buttonSmplRecieve) {
                const footerSmplRecieve = buttonSmplRecieve.closest('.modal-footer');
                if (footerSmplRecieve) {
                    const modalKeyElement = footerSmplRecieve.closest('.modal.show, .modal-dialog, modal-container.show');
                    if (modalKeyElement && !activeModalIntervals.has(modalKeyElement)) {
                        logSampleCountDebug(`Found potential modal for 'closebtn-smplrecieve' (modal key: ${getModalKeyDetails(modalKeyElement)}). Attempting setup.`);
                        setupModalCounterSamples({
                            buttonIdForLog: 'closebtn-smplrecieve',
                            counterId: 'inline-counter-smplrecieve',
                            inputSelector: 'td input[formcontrolname="PatientID"]', // Specific to this modal's table structure
                            modalKeyElement: modalKeyElement,
                            targetFooter: footerSmplRecieve,
                            activeIntervalsMap: activeModalIntervals
                        });
                    }
                }
            }

            // Fallback cleanup for modals that might have been missed by interval cleanup
            activeModalIntervals.forEach((data, modalElemKey) => {
                const modalStillPresent = document.body.contains(modalElemKey);
                const counterElem = document.getElementById(data.counterId);
                const modalStillVisible = modalStillPresent && (
                    modalElemKey.classList.contains('show') ||
                    modalElemKey.classList.contains('modal-open') ||
                    (modalElemKey.style.display && modalElemKey.style.display !== 'none') ||
                    (!modalElemKey.style.display && modalElemKey.offsetParent !== null)
                );

                if (!modalStillPresent || !modalStillVisible) {
                    logSampleCountDebug(`Fallback Cleanup: Modal for counter ID ${data.counterId} (key: ${getModalKeyDetails(modalElemKey)}) no longer present/visible. Cleaning up.`);
                    clearInterval(data.interval);
                    if (counterElem && counterElem.isConnected) {
                        counterElem.remove();
                    }
                    activeModalIntervals.delete(modalElemKey);
                } else if (counterElem && !counterElem.isConnected) { // Counter removed but modal still there (e.g. by other script)
                    logSampleCountDebug(`Fallback Cleanup: Counter ID ${data.counterId} (key: ${getModalKeyDetails(modalElemKey)}) is disconnected but modal still present. Cleaning interval.`);
                     clearInterval(data.interval);
                     activeModalIntervals.delete(modalElemKey);
                }
            });
        });

        observer.observe(document.body, { childList: true, subtree: true });
        logSampleCountDebug("Sample Count Modal observer INSTANCE started watching document.body.");
    }

    window.addEventListener('load', () => {
        logSampleCountDebug("Window 'load' event fired for SAMPLES COUNT. Initializing modal observer.");
        try {
            observeModalsSamples();
        } catch (e) {
            console.error(`${SCRIPT_PREFIX_SAMPLES} Error during observeModalsSamples initialization: ${e.message} \n${e.stack}`);
        }
    });

    logSampleCountDebug("UserScript SAMPLES COUNT logic loaded and IIFE executed.");

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址