{"id":4959,"date":"2025-11-26T09:58:09","date_gmt":"2025-11-26T08:58:09","guid":{"rendered":"https:\/\/www.aviglianabasket.it\/?page_id=4959"},"modified":"2025-11-26T16:23:20","modified_gmt":"2025-11-26T15:23:20","slug":"gestione-ordini","status":"publish","type":"page","link":"https:\/\/www.aviglianabasket.it\/?page_id=4959","title":{"rendered":"Gestione Ordini"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"4959\" class=\"elementor elementor-4959\">\n\t\t\t\t<div class=\"elementor-element elementor-element-29f8e03 e-con-full e-flex e-con e-parent\" data-id=\"29f8e03\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-cfeb0d8 elementor-widget elementor-widget-spacer\" data-id=\"cfeb0d8\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-938ba1f e-con-full e-flex e-con e-child\" data-id=\"938ba1f\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-69a421d elementor-widget elementor-widget-html\" data-id=\"69a421d\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"it\" class=\"dark\">\n  <head>\n    <meta charset=\"UTF-8\" \/>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \/>\n    <title>OrderManager Pro<\/title>\n    \n    <!-- React & ReactDOM -->\n    <script crossorigin src=\"https:\/\/unpkg.com\/react@18\/umd\/react.production.min.js\"><\/script>\n    <script crossorigin src=\"https:\/\/unpkg.com\/react-dom@18\/umd\/react-dom.production.min.js\"><\/script>\n    \n    <!-- Babel for JSX -->\n    <script src=\"https:\/\/unpkg.com\/@babel\/standalone\/babel.min.js\"><\/script>\n    \n    <!-- Tailwind CSS -->\n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n    <script>\n      tailwind.config = {\n        darkMode: 'class',\n        theme: {\n          extend: {\n            colors: {\n              gray: {\n                850: '#1f2937', \n                950: '#030712',\n              }\n            },\n            boxShadow: {\n              'neon': '0 0 20px rgba(16, 185, 129, 0.15)',\n            },\n            animation: {\n              'fadeIn': 'fadeIn 0.5s ease-out forwards',\n              'bounce-in': 'bounceIn 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55)',\n            },\n            keyframes: {\n              fadeIn: {\n                '0%': { opacity: '0', transform: 'translateY(10px)' },\n                '100%': { opacity: '1', transform: 'translateY(0)' },\n              },\n              bounceIn: {\n                '0%': { opacity: '0', transform: 'scale(0.9)' },\n                '100%': { opacity: '1', transform: 'scale(1)' },\n              }\n            }\n          }\n        }\n      }\n    <\/script>\n    <style>\n      body {\n        background-color: #030712;\n        color: #e5e7eb;\n      }\n      \/* Custom scrollbar for webkit *\/\n      ::-webkit-scrollbar {\n        width: 8px;\n        height: 8px;\n      }\n      ::-webkit-scrollbar-track {\n        background: #111827; \n      }\n      ::-webkit-scrollbar-thumb {\n        background: #374151; \n        border-radius: 4px;\n      }\n      ::-webkit-scrollbar-thumb:hover {\n        background: #4b5563; \n      }\n    <\/style>\n<script type=\"importmap\">\n{\n  \"imports\": {\n    \"react\": \"https:\/\/aistudiocdn.com\/react@^19.2.0\",\n    \"react-dom\/\": \"https:\/\/aistudiocdn.com\/react-dom@^19.2.0\/\",\n    \"react\/\": \"https:\/\/aistudiocdn.com\/react@^19.2.0\/\"\n  }\n}\n<\/script>\n<\/head>\n  <body>\n    <div id=\"root\"><\/div>\n\n    <script type=\"text\/babel\">\n        const { useState, useEffect, useMemo } = React;\n\n        \/\/ --- CONSTANTS ---\n        const WEB_APP_URL = 'https:\/\/script.google.com\/macros\/s\/AKfycbx4mc5bUSU6PV_zGanzWKkaelSciBC63gFzbnc_zJAVbm7IVAtd08G-5q4Cv0VkunWJ\/exec';\n        const CORRECT_PASSWORD = 'Greens25!';\n\n        const SHEET_ITEM_ID_KEY = 'id';\n        const SHEET_ITEM_TITLE_KEY = 'titolo';\n        const SHEET_ITEM_SIZE_KEY = 'taglia';\n        const SHEET_ITEM_QTY_KEY = 'quantita';\n        const SHEET_ITEM_SUBTOTAL_KEY = 'subtotale';\n\n        \/\/ --- UTILS ---\n        \n        const formatCurrency = (amount) => {\n            if (amount === undefined || amount === null) return 'N\/A';\n            let numVal;\n            if (typeof amount === 'string') {\n                let clean = amount.replace(\/[^\\d.,-]\/g, ''); \n                if (clean.includes(',') && clean.indexOf(',') > clean.indexOf('.')) {\n                    clean = clean.replace(',', '.');\n                }\n                numVal = parseFloat(clean);\n            } else {\n                numVal = amount;\n            }\n            if (isNaN(numVal)) return 'N\/A';\n            return new Intl.NumberFormat('it-IT', {\n                style: 'currency',\n                currency: 'EUR',\n                minimumFractionDigits: 2\n            }).format(numVal);\n        };\n\n        const isPaid = (val) => {\n            const s = String(val).toUpperCase().trim();\n            return !(s === 'FALSO' || s === 'NON PAGATO' || s === '' || s === 'NULL' || s === '#N\/A' || s === 'FALSE' || s === '0');\n        };\n\n        const checkStatus = (val) => {\n            if (val === true) return true;\n            if (val === undefined || val === null || val === false) return false;\n            const s = String(val).toUpperCase().trim();\n            return s === 'VERO' || s === 'TRUE' || s === 'ON' || s === '1' || s === 'SI' || s === 'YES';\n        };\n\n        const isMailSent = (val) => {\n            if (val === undefined || val === null) return false;\n            const s = String(val).toUpperCase().trim();\n            \n            \/\/ Explicit positive checks\n            if (s === 'INVIATA' || s.includes('INVIATA')) return true;\n            if (s === 'VERO' || s === 'TRUE' || s === '1' || s === 'ON') return true;\n\n            \/\/ Strict blacklist for known negatives\n            const negatives = ['FALSE', 'FALSO', 'NO', '0', 'NULL', 'UNDEFINED', '#N\/A', '', 'NON INVIATA', 'NON INVIAT'];\n            if (negatives.includes(s)) return false;\n            \n            \/\/ Fallback: if it's not explicitly negative and not empty, assume it might be a date string or other confirmation\n            \/\/ But be careful about partial matches of negatives\n            if (s.includes('NON INVIAT')) return false;\n\n            return true;\n        };\n\n        const getPropCaseInsensitive = (obj, key) => {\n            if (!obj) return undefined;\n            const cleanKey = key.toLowerCase().replace(\/[^a-z0-9]\/g, '');\n            const foundKey = Object.keys(obj).find(k => \n                k.toLowerCase().replace(\/[^a-z0-9]\/g, '') === cleanKey\n            );\n            return foundKey ? obj[foundKey] : undefined;\n        };\n\n        const getValueFromPossibleKeys = (obj, keys) => {\n            for (const key of keys) {\n                const val = getPropCaseInsensitive(obj, key);\n                if (val !== undefined) return val;\n            }\n            return undefined;\n        };\n\n        const normalizeId = (id) => {\n            if (id === undefined || id === null) return '';\n            let str = String(id).trim();\n            if (str.endsWith('.0')) {\n                str = str.substring(0, str.length - 2);\n            }\n            return str.replace(\/\\s\/g, '').toUpperCase();\n        };\n        \n        const findItemsForOrder = (orderId, allItems) => {\n            const targetId = normalizeId(orderId);\n            if (!targetId || allItems.length === 0) return [];\n\n            return allItems.filter(item => {\n                if (item[SHEET_ITEM_ID_KEY] !== undefined) {\n                    return normalizeId(item[SHEET_ITEM_ID_KEY]) === targetId;\n                }\n                const keys = Object.keys(item);\n                const idKey = keys.find(k => {\n                    const clean = k.toLowerCase().replace(\/\\s\/g, '');\n                    return clean === 'idordine' || clean === 'orderid' || clean === 'id';\n                });\n                if (idKey && item[idKey] !== undefined) {\n                    return normalizeId(item[idKey]) === targetId;\n                }\n                return false;\n            });\n        };\n\n        \/\/ --- SERVICES ---\n        \n        const fetchOrdersData = async () => {\n            if (!WEB_APP_URL) throw new Error(\"WEB_APP_URL is not configured.\");\n            \n            const response = await fetch(`${WEB_APP_URL}?action=fetchData&t=${new Date().getTime()}`);\n            if (!response.ok) throw new Error(`HTTP Error: ${response.status}`);\n            \n            const text = await response.text();\n            try {\n                const data = JSON.parse(text);\n                if (data.error) throw new Error(data.error);\n                return data;\n            } catch (e) {\n                console.error(\"Invalid JSON:\", text);\n                throw new Error(\"Invalid JSON response from server.\");\n            }\n        };\n\n        const updateOrderStatus = async (orderId, column, newValue) => {\n            const response = await fetch(WEB_APP_URL, {\n                method: 'POST',\n                body: JSON.stringify({\n                    action: 'updateStatus',\n                    orderId: orderId,\n                    column: column,\n                    value: newValue\n                })\n            });\n            const text = await response.text();\n            if (!response.ok || text.includes('Errore') || text.includes('Exception')) {\n                throw new Error(text || 'Update failed');\n            }\n            return text;\n        };\n\n        \/\/ --- COMPONENTS ---\n\n        const Login = ({ onLogin }) => {\n            const [password, setPassword] = useState('');\n            const [error, setError] = useState(false);\n\n            const handleSubmit = (e) => {\n                if (e) e.preventDefault();\n                if (password === CORRECT_PASSWORD) {\n                    onLogin();\n                } else {\n                    setError(true);\n                    setPassword('');\n                }\n            };\n\n            return (\n                <div className=\"fixed inset-0 bg-gray-950 flex justify-center items-center z-50 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-gray-800 via-gray-950 to-black\">\n                    <div className=\"bg-gray-900\/60 backdrop-blur-xl border border-gray-800 p-8 md:p-10 rounded-2xl shadow-neon w-full max-w-sm relative overflow-hidden animate-fadeIn\">\n                        <div className=\"absolute -top-10 -left-10 w-20 h-20 bg-emerald-500 rounded-full blur-3xl opacity-20\"><\/div>\n                        <div className=\"absolute -bottom-10 -right-10 w-20 h-20 bg-blue-500 rounded-full blur-3xl opacity-20\"><\/div>\n\n                        <h2 className=\"text-4xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-emerald-400 to-cyan-500 mb-2 text-center tracking-tight\">\n                            Accesso\n                        <\/h2>\n                        <p className=\"text-gray-400 text-center mb-8 text-sm\">Inserisci la chiave di sicurezza<\/p>\n                        \n                        <form onSubmit={handleSubmit} className=\"space-y-5 relative z-10\">\n                            <div>\n                                <label className=\"block text-xs font-bold text-gray-500 uppercase tracking-widest mb-2 ml-1\">Password<\/label>\n                                <input\n                                    type=\"password\"\n                                    value={password}\n                                    onChange={(e) => { setError(false); setPassword(e.target.value); }}\n                                    placeholder=\"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\"\n                                    className=\"block w-full px-4 py-3 bg-gray-800\/50 border border-gray-700 rounded-xl text-white placeholder-gray-600 focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 focus:outline-none transition-all shadow-inner\"\n                                \/>\n                            <\/div>\n                            <button\n                                type=\"submit\"\n                                className=\"w-full mt-4 py-3 px-4 rounded-xl font-bold text-white bg-gradient-to-r from-emerald-600 to-teal-600 hover:from-emerald-500 hover:to-teal-500 focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:ring-offset-2 focus:ring-offset-gray-900 transition-all transform hover:scale-[1.02] shadow-lg shadow-emerald-900\/50\"\n                            >\n                                ENTRA NEL SISTEMA\n                            <\/button>\n                        <\/form>\n                        {error && (\n                            <p className=\"text-center text-red-400 mt-6 text-sm font-semibold bg-red-900\/20 py-2 rounded-lg border border-red-900\/50 animate-pulse\">\n                                Accesso Negato. Riprova.\n                            <\/p>\n                        )}\n                    <\/div>\n                <\/div>\n            );\n        };\n\n        const OrderDetail = ({ items, orderId }) => {\n            if (items.length === 0) {\n                return (\n                    <div className=\"p-8 bg-gray-900 text-center border-t border-gray-800 animate-fadeIn\">\n                        <p className=\"text-gray-400 font-medium\">\n                            Nessuna riga articolo trovata per <span className=\"font-bold text-emerald-400\">{orderId}<\/span>.\n                        <\/p>\n                        <p className=\"text-xs text-gray-600 mt-2 font-mono\">\n                            System Log: No matching ID found via \"id\" key\n                        <\/p>\n                    <\/div>\n                );\n            }\n\n            return (\n                <div className=\"p-6 bg-gray-850 border-t border-gray-700 animate-fadeIn shadow-inner\">\n                    <div className=\"flex items-center justify-between mb-4 pb-2 border-b border-gray-700\">\n                        <h4 className=\"text-sm font-bold text-gray-300 uppercase tracking-widest\">\n                            Specifiche Ordine <span className=\"text-emerald-500\">#{orderId}<\/span>\n                        <\/h4>\n                        <span className=\"text-xs bg-gray-800 text-gray-500 px-2 py-1 rounded\">items: {items.length}<\/span>\n                    <\/div>\n                    \n                    <div className=\"overflow-x-auto rounded-lg border border-gray-700\">\n                        <table className=\"min-w-full divide-y divide-gray-700\">\n                            <thead className=\"bg-gray-900\">\n                                <tr>\n                                    <th className=\"px-5 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider\">Articolo<\/th>\n                                    <th className=\"px-5 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider\">Taglia<\/th>\n                                    <th className=\"px-5 py-3 text-center text-xs font-bold text-gray-500 uppercase tracking-wider\">Qt\u00e0<\/th>\n                                    <th className=\"px-5 py-3 text-right text-xs font-bold text-gray-500 uppercase tracking-wider\">Subtotale<\/th>\n                                <\/tr>\n                            <\/thead>\n                            <tbody className=\"divide-y divide-gray-800 bg-gray-800\/50\">\n                                {items.map((item, idx) => {\n                                    const title = item[SHEET_ITEM_TITLE_KEY] || 'N\/D';\n                                    const size = item[SHEET_ITEM_SIZE_KEY] || '-';\n                                    const qty = item[SHEET_ITEM_QTY_KEY] || 0;\n                                    const sub = item[SHEET_ITEM_SUBTOTAL_KEY];\n\n                                    return (\n                                        <tr key={idx} className=\"hover:bg-gray-700\/50 transition-colors\">\n                                            <td className=\"px-5 py-3 text-sm text-gray-300 font-medium\">{title}<\/td>\n                                            <td className=\"px-5 py-3 text-sm text-gray-400\">{size}<\/td>\n                                            <td className=\"px-5 py-3 text-sm text-gray-400 text-center font-mono\">{qty}<\/td>\n                                            <td className=\"px-5 py-3 text-sm text-emerald-400 font-bold text-right font-mono tracking-tight\">\n                                                {formatCurrency(sub)}\n                                            <\/td>\n                                        <\/tr>\n                                    );\n                                })}\n                            <\/tbody>\n                        <\/table>\n                    <\/div>\n                <\/div>\n            );\n        };\n\n        const OrderRow = ({ order, items, onUpdateStatus }) => {\n            const [expanded, setExpanded] = useState(false);\n            \n            \/\/ Safety check for invalid order objects\n            if (!order) return null;\n\n            const paid = isPaid(order.pagato);\n\n            \/\/ --- SMART MAIL COLUMN DETECTION ---\n            const allKeys = Object.keys(order);\n            const mailKeys = allKeys.filter(k => k.toLowerCase().includes('mail'));\n            mailKeys.sort(); \n\n            \/\/ 1. Explicit search for \"Pronto (H)\" Mail (Column I)\n            let mailProntoVal = getValueFromPossibleKeys(order, [\n                'mail_1', 'mail1', \n                'mailpronto', 'mailh', 'mail_h', 'mail_i', 'maili', \n                'invio_h', 'stato_mail_h', \n                'i', 'col_i', 'column_i'\n            ]);\n\n            \/\/ 2. Fallback: If explicit lookup failed, use the 2nd mail key found (Index 1)\n            if (mailProntoVal === undefined && mailKeys.length > 1) {\n                mailProntoVal = order[mailKeys[1]];\n            }\n\n            \/\/ 3. Explicit search for \"In AB (J)\" Mail (Column K)\n            let mailInABVal = getValueFromPossibleKeys(order, [\n                'mail_2', 'mail2', \n                'mailinab', 'mailj', 'mail_j', 'mail_k', 'mailk', \n                'mailab', 'invio_j', 'stato_mail_j',\n                'k', 'col_k', 'column_k'\n            ]);\n\n            \/\/ 4. Fallback: If explicit lookup failed, use the 3rd mail key found (Index 2)\n            if (mailInABVal === undefined && mailKeys.length > 2) {\n                mailInABVal = order[mailKeys[2]];\n            }\n\n            const mailProntoSent = isMailSent(mailProntoVal);\n            const mailInABSent = isMailSent(mailInABVal);\n\n            \/\/ --- SMART FLAG DETECTION ---\n            \/\/ Handle 'Pronto' flag (Column H)\n            const prontoRaw = getValueFromPossibleKeys(order, ['pronto', 'h', 'col_h', 'pronto_h', 'flag_h']);\n            const isPronto = checkStatus(prontoRaw);\n\n            \/\/ Handle 'In AB' flag (Column J)\n            const inABRaw = getValueFromPossibleKeys(order, ['inAB', 'inab', 'in_ab', 'j', 'col_j', 'flag_j', 'in_ab_j']);\n            const isInAB = checkStatus(inABRaw);\n\n            return (\n                <React.Fragment>\n                    <tr className={`\n                        group relative transition-all duration-300 ease-out \n                        ${expanded \n                            ? 'bg-gray-800 scale-[1.01] shadow-2xl z-20 border-l-4 border-l-emerald-500' \n                            : 'bg-gray-900\/80 hover:bg-gray-800 hover:-translate-y-1 hover:shadow-neon hover:z-10 border-l-4 border-l-transparent'\n                        }\n                        rounded-xl\n                    `}>\n                        <td className=\"px-5 py-4 whitespace-nowrap rounded-l-xl\">\n                            <span className=\"font-mono text-emerald-400 font-bold tracking-wider text-lg drop-shadow-md\">{order.id}<\/span>\n                        <\/td>\n                        \n                        <td className=\"px-3 py-4 whitespace-nowrap text-sm text-gray-400 font-medium text-center\">\n                            {order.del || order.data}\n                        <\/td>\n                        \n                        <td className=\"px-5 py-4 text-sm w-full\">\n                            <div className=\"font-bold text-gray-200 text-base\">{order.cognome} {order.nome}<\/div>\n                            <div className=\"text-xs text-gray-500 truncate max-w-[200px] md:max-w-xs font-mono mt-0.5\">{order.mail}<\/div>\n                        <\/td>\n                        <td className=\"px-5 py-4 text-sm font-bold text-gray-200 whitespace-nowrap font-mono tracking-tight\">\n                            {formatCurrency(order.totale)}\n                        <\/td>\n                        <td className=\"px-5 py-4 text-center\">\n                            <span className={`inline-block px-3 py-1 rounded-lg text-[10px] font-extrabold tracking-widest uppercase shadow-sm border ${\n                                paid \n                                ? 'bg-emerald-950\/50 text-emerald-400 border-emerald-900\/50' \n                                : 'bg-red-950\/50 text-red-400 border-red-900\/50'\n                            }`}>\n                                {paid ? 'PAGATO' : 'PENDING'}\n                            <\/span>\n                        <\/td>\n                        \n                        <td className=\"px-5 py-4 text-center cursor-pointer\" onClick={(e) => { e.stopPropagation(); onUpdateStatus(order.id, 'H', isPronto); }}>\n                            <div className={`\n                                w-12 h-12 mx-auto rounded-full flex items-center justify-center transition-all duration-300 border-2\n                                ${isPronto \n                                ? 'bg-emerald-500 border-emerald-400 shadow-[0_0_15px_rgba(16,185,129,0.5)] scale-110' \n                                : 'bg-gray-800 border-gray-700 hover:border-gray-500 text-gray-600'\n                                }\n                            `}>\n                                <span className={`text-xs font-bold ${isPronto ? 'text-white' : 'text-gray-500'}`}>\n                                    {isPronto ? 'ON' : 'OFF'}\n                                <\/span>\n                            <\/div>\n                        <\/td>\n                        \n                        <td className=\"px-2 py-4 text-center\">\n                            {mailProntoSent \n                                ? <div className=\"w-3 h-3 rounded-full bg-emerald-400 shadow-[0_0_12px_#34d399] mx-auto animate-[pulse_3s_infinite]\" title={`Raw: \"${mailProntoVal}\"`}><\/div> \n                                : <div className=\"w-1.5 h-1.5 rounded-full bg-gray-700 mx-auto\" title={`Raw: \"${mailProntoVal || 'N\/D'}\"`}><\/div>}\n                        <\/td>\n\n                        <td className=\"px-5 py-4 text-center cursor-pointer\" onClick={(e) => { e.stopPropagation(); onUpdateStatus(order.id, 'J', isInAB); }}>\n                            <div className={`\n                                w-12 h-12 mx-auto rounded-full flex items-center justify-center transition-all duration-300 border-2\n                                ${isInAB \n                                ? 'bg-blue-600 border-blue-400 shadow-[0_0_15px_rgba(59,130,246,0.5)] scale-110' \n                                : 'bg-gray-800 border-gray-700 hover:border-gray-500 text-gray-600'\n                                }\n                            `}>\n                                <span className={`text-xs font-bold ${isInAB ? 'text-white' : 'text-gray-500'}`}>\n                                    {isInAB ? 'ON' : 'OFF'}\n                                <\/span>\n                            <\/div>\n                        <\/td>\n\n                        <td className=\"px-2 py-4 text-center\">\n                            {mailInABSent \n                                ? <div className=\"w-3 h-3 rounded-full bg-emerald-400 shadow-[0_0_12px_#34d399] mx-auto animate-[pulse_3s_infinite]\" title={`Raw: \"${mailInABVal}\"`}><\/div> \n                                : <div className=\"w-1.5 h-1.5 rounded-full bg-gray-700 mx-auto\" title={`Raw: \"${mailInABVal || 'N\/D'}\"`}><\/div>}\n                        <\/td>\n\n                        <td className=\"px-5 py-4 text-center rounded-r-xl\">\n                            <button \n                                onClick={() => setExpanded(!expanded)}\n                                className={`\n                                    p-2 rounded-full transition-all duration-300 outline-none\n                                    ${expanded ? 'bg-gray-700 text-white rotate-180 shadow-inner' : 'bg-gray-800 text-gray-400 hover:bg-gray-700 hover:text-white'}\n                                `}\n                            >\n                                <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n                                    <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" \/>\n                                <\/svg>\n                            <\/button>\n                        <\/td>\n                    <\/tr>\n                    \n                    {expanded && (\n                        <tr>\n                            <td colSpan={10} className=\"p-0 border-none\">\n                                <div className=\"mx-2 mb-4 rounded-b-xl overflow-hidden shadow-2xl relative -mt-2 z-0\">\n                                    <OrderDetail items={items} orderId={order.id} \/>\n                                <\/div>\n                            <\/td>\n                        <\/tr>\n                    )}\n                <\/React.Fragment>\n            );\n        };\n\n        const Dashboard = () => {\n            const [orders, setOrders] = useState([]);\n            const [items, setItems] = useState([]);\n            const [loading, setLoading] = useState(false);\n            const [error, setError] = useState(null);\n            const [msg, setMsg] = useState(null);\n            const [search, setSearch] = useState('');\n            const [filterStatus, setFilterStatus] = useState('all');\n\n            const loadData = async () => {\n                setLoading(true);\n                setError(null);\n                try {\n                    const data = await fetchOrdersData();\n                    \/\/ CRITICAL FIX: Ensure safely accessing arrays even if undefined\n                    const statusData = data.status || [];\n                    const itemsData = data.items || [];\n                    \n                    setOrders(statusData);\n                    setItems(itemsData);\n                    setMsg({ text: `Sistema aggiornato: ${statusData.length} ordini recuperati.`, type: 'success' });\n                } catch (err) {\n                    setError(err.message);\n                    setMsg({ text: 'Errore critico nel caricamento dati.', type: 'error' });\n                } finally {\n                    setLoading(false);\n                }\n            };\n\n            useEffect(() => {\n                loadData();\n            }, []);\n\n            const handleUpdateStatus = async (id, col, currentVal) => {\n                const newValueStr = currentVal ? 'FALSO' : 'VERO';\n                if (!window.confirm(`Modificare stato ${col} per ordine ${id} a \"${newValueStr}\"?`)) return;\n                \n                \/\/ Optimistic update\n                setOrders(prev => prev.map(o => {\n                    if (String(o.id) === String(id)) {\n                        return col === 'H' ? { ...o, pronto: !currentVal } : { ...o, inAB: !currentVal };\n                    }\n                    return o;\n                }));\n\n                try {\n                    const resultMsg = await updateOrderStatus(id, col, newValueStr);\n                    setMsg({ text: resultMsg, type: 'success' });\n                } catch (err) {\n                    \/\/ SPECIAL HANDLING: \"Failed to fetch\" usually means a network glitch or CORS redirect issue\n                    \/\/ but the request often succeeds on the server.\n                    const isNetworkError = err.message && (\n                        err.message.includes('Failed to fetch') || \n                        err.message.includes('NetworkError') ||\n                        err.message.includes('Network request failed')\n                    );\n\n                    if (isNetworkError) {\n                        \/\/ Suppress the red error message. Assume success and let loadData verify.\n                        console.warn(\"Network glitch during update, forcing reload...\");\n                        setMsg({ text: 'Sincronizzazione in corso...', type: 'info' });\n                        \/\/ Do NOT revert the optimistic update here; let loadData overwrite it with truth.\n                    } else {\n                        \/\/ Show actual logic errors\n                        setMsg({ text: `Errore aggiornamento: ${err.message}`, type: 'error' });\n                        \/\/ Revert optimistic update only on real logic errors\n                        setOrders(prev => prev.map(o => {\n                            if (String(o.id) === String(id)) {\n                                return col === 'H' ? { ...o, pronto: currentVal } : { ...o, inAB: currentVal };\n                            }\n                            return o;\n                        }));\n                    }\n                } finally {\n                    \/\/ ALWAYS reload data to ensure visual state matches backend file\n                    await loadData();\n                }\n            };\n\n            const filteredOrders = useMemo(() => {\n                return orders.filter(order => {\n                    if (!order) return false;\n                    const s = search.toLowerCase();\n                    const matchesSearch = \n                        normalizeId(order.id).toLowerCase().includes(s) ||\n                        (order.cognome || '').toLowerCase().includes(s) ||\n                        (order.nome || '').toLowerCase().includes(s) ||\n                        (order.mail || '').toLowerCase().includes(s);\n\n                    let matchesStatus = true;\n                    if (filterStatus !== 'all') {\n                        const [key, valStr] = filterStatus.split('_');\n                        const boolVal = valStr === 'true';\n                        if (key === 'pronto') matchesStatus = order.pronto === boolVal;\n                        if (key === 'inab') matchesStatus = order.inAB === boolVal;\n                    }\n                    return matchesSearch && matchesStatus;\n                });\n            }, [orders, search, filterStatus]);\n\n            useEffect(() => {\n                if (msg) {\n                    const timer = setTimeout(() => setMsg(null), 5000);\n                    return () => clearTimeout(timer);\n                }\n            }, [msg]);\n\n            return (\n                <div className=\"container mx-auto p-4 md:p-8 min-h-screen\">\n                    <header className=\"mb-10 text-center md:text-left animate-fadeIn\">\n                        <h1 className=\"text-5xl md:text-6xl font-extrabold mb-2 tracking-tight\">\n                            <span className=\"text-transparent bg-clip-text bg-gradient-to-r from-emerald-400 via-green-300 to-teal-400 drop-shadow-[0_2px_10px_rgba(52,211,153,0.3)]\">\n                                GESTIONE ORDINI\n                            <\/span>\n                        <\/h1>\n                        <p className=\"text-gray-400 text-lg font-light tracking-wide\">\n                            Dashboard Fornitori <span className=\"text-emerald-500 mx-2\">\u2022<\/span> Monitoraggio Live\n                        <\/p>\n                    <\/header>\n\n                    <div className=\"bg-gray-900\/40 backdrop-blur-md p-6 rounded-2xl border border-gray-800\/50 mb-8 flex flex-col md:flex-row gap-5 justify-between items-center shadow-lg relative overflow-hidden z-10 animate-fadeIn\">\n                        <div className=\"absolute top-0 left-0 w-full h-[1px] bg-gradient-to-r from-transparent via-gray-600 to-transparent opacity-30\"><\/div>\n\n                        <div className=\"flex flex-col md:flex-row gap-4 w-full md:w-auto z-10\">\n                            <div className=\"relative group w-full md:w-auto\">\n                                <input \n                                    type=\"text\" \n                                    placeholder=\"Cerca ID, Nome...\" \n                                    value={search}\n                                    onChange={(e) => setSearch(e.target.value)}\n                                    className=\"pl-11 pr-4 h-14 bg-gray-950\/80 border border-gray-700 rounded-xl focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none w-full md:w-72 text-gray-200 placeholder-gray-600 transition-all shadow-inner group-hover:border-gray-600\"\n                                \/>\n                                <svg className=\"w-5 h-5 text-gray-500 absolute left-4 top-4.5 group-hover:text-emerald-400 transition-colors\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"><\/path><\/svg>\n                            <\/div>\n\n                            <div className=\"relative w-full md:w-auto\">\n                                <select \n                                    value={filterStatus}\n                                    onChange={(e) => setFilterStatus(e.target.value)}\n                                    className=\"appearance-none pl-5 pr-12 h-14 bg-gray-950\/80 border border-gray-700 rounded-xl focus:ring-2 focus:ring-emerald-500 outline-none text-white text-lg font-medium cursor-pointer w-full md:w-[500px] hover:border-gray-600 transition-colors flex items-center\"\n                                >\n                                    <option value=\"all\">Tutti gli Stati<\/option>\n                                    <option value=\"pronto_true\">Pronto (H) VERO<\/option>\n                                    <option value=\"pronto_false\">Pronto (H) FALSO<\/option>\n                                    <option value=\"inab_true\">In AB (J) VERO<\/option>\n                                    <option value=\"inab_false\">In AB (J) FALSO<\/option>\n                                <\/select>\n                                <div className=\"pointer-events-none absolute inset-y-0 right-0 flex items-center px-4 text-gray-500\">\n                                    <svg className=\"h-6 w-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M19 9l-7 7-7-7\"><\/path><\/svg>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n\n                        <button \n                            onClick={loadData} \n                            disabled={loading}\n                            className=\"w-full md:w-auto z-10 h-14 bg-gradient-to-r from-emerald-600 to-teal-600 text-white px-8 rounded-xl shadow-lg shadow-emerald-900\/40 hover:shadow-emerald-500\/20 hover:-translate-y-0.5 hover:from-emerald-500 hover:to-teal-500 transition-all flex items-center justify-center font-bold tracking-wide disabled:opacity-50 disabled:cursor-not-allowed\"\n                        >\n                            {loading ? (\n                                <span className=\"animate-spin h-5 w-5 mr-2 border-2 border-white\/30 border-t-white rounded-full\"><\/span>\n                            ) : (\n                                <svg className=\"w-5 h-5 mr-2\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m15.356-2H15m-2-2l-2-2-2 2-2-2-2 2\"><\/path><\/svg>\n                            )}\n                            {loading ? 'SYNC...' : 'AGGIORNA'}\n                        <\/button>\n                    <\/div>\n\n                    {\/* Messages *\/}\n                    {msg && (\n                        <div className={`mb-8 p-4 rounded-xl border font-medium text-center animate-bounce-in shadow-lg backdrop-blur-sm ${\n                            msg.type === 'error' ? 'bg-red-900\/30 text-red-200 border-red-800' : \n                            msg.type === 'success' ? 'bg-emerald-900\/30 text-emerald-200 border-emerald-800' : 'bg-blue-900\/30 text-blue-200 border-blue-800'\n                        }`}>\n                            {msg.text}\n                        <\/div>\n                    )}\n\n                    {error && !msg && (\n                        <div className=\"mb-8 p-4 rounded-xl bg-red-950\/50 text-red-300 border border-red-900 text-center animate-fadeIn\">\n                            SYSTEM ERROR: {error}\n                        <\/div>\n                    )}\n\n                    {\/* 3D Table *\/}\n                    <div className=\"overflow-x-auto pb-10 px-1 animate-fadeIn\" style={{animationDelay: '0.2s'}}>\n                        <table className=\"min-w-full border-separate border-spacing-y-4\">\n                            <thead>\n                                <tr>\n                                    <th className=\"px-5 py-2 text-left text-xs font-bold text-gray-500 uppercase tracking-widest\">ID Ordine<\/th>\n                                    <th className=\"px-3 py-2 text-center text-xs font-bold text-gray-500 uppercase tracking-widest w-28\">Data<\/th>\n                                    <th className=\"px-5 py-2 text-left text-xs font-bold text-gray-500 uppercase tracking-widest min-w-[200px]\">Cliente<\/th>\n                                    <th className=\"px-5 py-2 text-left text-xs font-bold text-gray-500 uppercase tracking-widest\">Totale<\/th>\n                                    <th className=\"px-5 py-2 text-center text-xs font-bold text-gray-500 uppercase tracking-widest\">Pagato<\/th>\n                                    <th className=\"px-5 py-2 text-center text-xs font-bold text-emerald-500\/80 uppercase tracking-widest\">Pronto (H)<\/th>\n                                    <th className=\"px-2 py-2 text-center text-xs font-bold text-gray-600 uppercase tracking-widest\">Mail<\/th>\n                                    <th className=\"px-5 py-2 text-center text-xs font-bold text-blue-500\/80 uppercase tracking-widest\">In AB (J)<\/th>\n                                    <th className=\"px-2 py-2 text-center text-xs font-bold text-gray-600 uppercase tracking-widest\">Mail<\/th>\n                                    <th className=\"px-5 py-2 text-center text-xs font-bold text-gray-500 uppercase tracking-widest\">Azioni<\/th>\n                                <\/tr>\n                            <\/thead>\n                            <tbody>\n                                {filteredOrders.length > 0 ? (\n                                    filteredOrders.map(order => (\n                                        <OrderRow \n                                            key={order.id} \n                                            order={order} \n                                            items={findItemsForOrder(order.id, items)}\n                                            onUpdateStatus={handleUpdateStatus}\n                                        \/>\n                                    ))\n                                ) : (\n                                    <tr>\n                                        <td colSpan={10} className=\"text-center py-20 text-gray-500 bg-gray-900\/30 rounded-2xl border border-dashed border-gray-800\">\n                                            {loading ? 'Inizializzazione sistema...' : 'Nessun ordine trovato nel database.'}\n                                        <\/td>\n                                    <\/tr>\n                                )}\n                            <\/tbody>\n                        <\/table>\n                    <\/div>\n                <\/div>\n            );\n        };\n\n        const App = () => {\n            const [isLoggedIn, setIsLoggedIn] = useState(false);\n\n            return (\n                <div className=\"min-h-screen\">\n                    {!isLoggedIn ? (\n                        <Login onLogin={() => setIsLoggedIn(true)} \/>\n                    ) : (\n                        <Dashboard \/>\n                    )}\n                <\/div>\n            );\n        };\n\n        const root = ReactDOM.createRoot(document.getElementById('root'));\n        root.render(<App \/>);\n\n    <\/script>\n  <\/body>\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>OrderManager Pro<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":398,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"disabled","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-4959","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.aviglianabasket.it\/index.php?rest_route=\/wp\/v2\/pages\/4959","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aviglianabasket.it\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.aviglianabasket.it\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.aviglianabasket.it\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aviglianabasket.it\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4959"}],"version-history":[{"count":89,"href":"https:\/\/www.aviglianabasket.it\/index.php?rest_route=\/wp\/v2\/pages\/4959\/revisions"}],"predecessor-version":[{"id":5057,"href":"https:\/\/www.aviglianabasket.it\/index.php?rest_route=\/wp\/v2\/pages\/4959\/revisions\/5057"}],"up":[{"embeddable":true,"href":"https:\/\/www.aviglianabasket.it\/index.php?rest_route=\/wp\/v2\/pages\/398"}],"wp:attachment":[{"href":"https:\/\/www.aviglianabasket.it\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4959"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}