// ... (Keep the global variable initializations as they are) // let rawData = window.AT_DASHBOARD_DATA.csvData.rawData; // let headers = window.AT_DASHBOARD_DATA.csvData.headers; // ... function handleFileSelect(e) { const file = e.target.files[0]; if (!file) return; const fileName = file.name.toLowerCase(); showLoading(); if (fileName.endsWith('.atdash')) { const reader = new FileReader(); reader.onload = (event) => { try { restoreFullDashboard(JSON.parse(event.target.result)); } // restoreFullDashboard will handle global vars catch (err) { hideLoading(); alert('Error reading .atdash: ' + err.message); } }; reader.readAsText(file); } else if (fileName.endsWith('.csv')) { Papa.parse(file, { complete: (results) => { hideLoading(); if (results.data && results.data.length > 1) { const clean = results.data.filter(r => r.length > 20 && !r[0]?.toString().includes('console.log') && r.some(c => c && c.toString().trim() !== '')); window.AT_DASHBOARD_DATA.csvData.headers = clean[0] || []; // Ensure it's an array window.AT_DASHBOARD_DATA.csvData.rawData = clean.slice(1); window.AT_DASHBOARD_DATA.csvData.dataLoadTime = new Date().toISOString(); // CRITICAL: Update global vars AFTER populating window object headers = window.AT_DASHBOARD_DATA.csvData.headers; rawData = window.AT_DASHBOARD_DATA.csvData.rawData; storeCsvDataInLocalStorage(); updateDataStatus(); processData(); // This will now use the correctly updated globals } else { alert('CSV empty or invalid.'); } }, error: (err) => { hideLoading(); alert('Error parsing CSV: ' + err.message); } }); } else { hideLoading(); alert('Unsupported file. Please use .csv or .atdash.'); } } // ... function loadCsvDataFromLocalStorage() { try { const storedHeadersString = localStorage.getItem(LS_CSV_HEADERS_KEY); const storedLoadTimeString = localStorage.getItem(LS_CSV_LOAD_TIME_KEY); const numChunksString = localStorage.getItem(LS_CSV_CHUNK_COUNT_KEY); if (!storedHeadersString || !numChunksString) { console.log("No main CSV data in localStorage or incomplete."); return false; } window.AT_DASHBOARD_DATA.csvData.headers = JSON.parse(storedHeadersString); window.AT_DASHBOARD_DATA.csvData.dataLoadTime = storedLoadTimeString || new Date().toISOString(); // CRITICAL: Update global var headers = window.AT_DASHBOARD_DATA.csvData.headers; const numChunks = parseInt(numChunksString); if (isNaN(numChunks) || numChunks < 0) { throw new Error("Invalid chunk count."); } if (numChunks === 0) { window.AT_DASHBOARD_DATA.csvData.rawData = []; rawData = []; // CRITICAL console.log("Loaded empty main CSV rawData (with headers) from localStorage."); return true; } let rawDataString = ''; for (let i = 0; i < numChunks; i++) { const chunk = localStorage.getItem(LS_CSV_CHUNK_KEY_PREFIX + i); if (chunk === null) throw new Error(`Missing localStorage chunk ${i}.`); rawDataString += chunk; } window.AT_DASHBOARD_DATA.csvData.rawData = JSON.parse(rawDataString); // CRITICAL: Update global var rawData = window.AT_DASHBOARD_DATA.csvData.rawData; console.log(`Main CSV data (${rawData.length} rows) loaded from localStorage.`); return true; } catch (e) { console.error('Error loading main CSV data from localStorage:', e); clearCsvDataFromLocalStorage(false); window.AT_DASHBOARD_DATA.csvData = { headers: [], rawData: [], dataLoadTime: null }; // CRITICAL: Reset globals on error headers = []; rawData = []; return false; } } // ... function restoreFullDashboard(backup) { try { showLoading(); if (backup.csvData) { window.AT_DASHBOARD_DATA.csvData = backup.csvData; // CRITICAL: Update global vars headers = window.AT_DASHBOARD_DATA.csvData.headers || []; rawData = window.AT_DASHBOARD_DATA.csvData.rawData || []; storeCsvDataInLocalStorage(); } else { // If no CSV data in backup, ensure globals are also empty window.AT_DASHBOARD_DATA.csvData = { headers: [], rawData: [], dataLoadTime: null }; headers = []; rawData = []; } if (backup.scenarioData) window.AT_DASHBOARD_DATA.scenarioData = backup.scenarioData; updateDataStatus(); processData(); // Will use the correctly updated globals setTimeout(() => { // ... (rest of timeout logic is likely fine) if (backup.dashboardState) { // ... (filter restoration) ... const filters = backup.dashboardState.filters; if (filters.tierFilter && document.getElementById('tierFilter')) document.getElementById('tierFilter').value = filters.tierFilter; if (filters.deptFilter && document.getElementById('deptFilter')) document.getElementById('deptFilter').value = filters.deptFilter; if (filters.managerLevel && document.getElementById('managerLevelSelect')) document.getElementById('managerLevelSelect').value = filters.managerLevel; if (filters.deptLevel && document.getElementById('deptLevelSelect')) document.getElementById('deptLevelSelect').value = filters.deptLevel; if (filters.deptMetric && document.getElementById('deptMetricSelect')) document.getElementById('deptMetricSelect').value = filters.deptMetric; if (filters.scenarioView && document.getElementById('scenarioSelect')) document.getElementById('scenarioSelect').value = filters.scenarioView; currentTierExplorerTier = backup.dashboardState.lastTierExplorerTier || null; currentTierExplorerMetric = backup.dashboardState.lastTierExplorerMetric || 'FTE'; window.AT_DASHBOARD_DATA.tierExplorerState.currentTier = currentTierExplorerTier; window.AT_DASHBOARD_DATA.tierExplorerState.currentMetric = currentTierExplorerMetric; if (document.getElementById('metricSelectTierExplorer')) { document.getElementById('metricSelectTierExplorer').value = currentTierExplorerMetric; } const lastViewId = backup.dashboardState.lastViewId; if (lastViewId) { let tierForNav = lastViewId === 'tierExplorer' ? currentTierExplorerTier : null; // Construct selector carefully let selector = `.nav-item[onclick*="showView('${lastViewId}'`; if (tierForNav) { selector += `, this, '${tierForNav}'`; } selector += `)"]`; const navBtn = document.querySelector(selector); if (navBtn) { navBtn.click(); } else if (lastViewId === 'tierExplorer' && currentTierExplorerTier) { // Fallback const genericTierExplorerButton = document.querySelector(`.nav-item[onclick*="'tierExplorer', this, '${currentTierExplorerTier}'"]`); if (genericTierExplorerButton) genericTierExplorerButton.click(); } else { // Default to overview if specific button not found document.querySelector('.nav-item[onclick*="showView(\'overview\'"]').click(); } } else { // Default to overview if no lastViewId document.querySelector('.nav-item[onclick*="showView(\'overview\'"]').click(); } } hideLoading(); alert(`Dashboard restored from .atdash (Backup: ${new Date(backup.timestamp).toLocaleString()}).`); }, 300); // Slightly increased delay } catch (e) { hideLoading(); console.error('Error restoring .atdash:', e); alert('Error restoring .atdash: ' + e.message); } } // ... function clearData() { if (confirm('Clear all data (CSV, session, browser storage) and reset dashboard? Download .atdash backup first if needed.')) { clearCsvDataFromLocalStorage(false); window.AT_DASHBOARD_DATA.csvData = { headers: [], rawData: [], dataLoadTime: null }; // CRITICAL: Reset globals headers = []; rawData = []; Object.values(charts).forEach(c => { if (c && typeof c.destroy === 'function') c.destroy(); }); charts = {}; window.AT_DASHBOARD_DATA.charts = {}; window.AT_DASHBOARD_DATA.tierExplorerState = { currentTier: null, currentMetric: 'FTE' }; currentTierExplorerTier = null; currentTierExplorerMetric = 'FTE'; location.reload(); } }
Auckland Transport - Advanced Analytics Dashboard

Auckland Transport Analytics Dashboard

📊 Drop your CSV or .atdash file here or to begin analysis

Organization Overview

Total Positions

0
Across all departments

Total Headcount

0
Active employees

Average FTE

0
Full-time equivalent

Departments

0
Organizational units

Tier Distribution

Employee Group Distribution

Hierarchy Analysis

Span of Control by Manager

Organization Tree Depth

Department Metrics

Department Size Comparison

Department Tier Distribution

Workforce Analytics

Full-Time Positions

0
FTE = 1.0

Part-Time Positions

0
0 < FTE < 1.0

Vacant Positions

0
HC = 0

Fill Rate

0%
Positions filled

FTE Distribution (by Position)

Employee Group by Tier

Cost Center Analysis (Overall)

Top 15 Cost Centers by Headcount

Cost Center Count by Size (HC)

Key Insights & Recommendations

AT Reintegration Scenarios (2025-2027)

Total Staff Transition

1,804

Annual Savings

$18-22M

Target Public Trust

55%

Timeline

2027

Staff Reallocation by Function

Scenario Comparison

🎯 Alignment

Integration aligns transport with housing, climate, resilience under one LTP.

💰 Benefits

$18-22M annual savings via shared services for safety & transit.

📈 Targets

2030: Trust 55%, DSI <400, PT trips 140M, Farebox 40%.

🏗️ Plan

Phase 1 (Corp) mid-2026, Ph 2 (Ops) mid-2027; TCAMP in 2027-37 LTP.

Mayoral Expectations Analysis

LoE Dec 2023 - One Year Review

Expectations Met

3/15

Savings Target

$12M
vs $20M

Public Trust

27%

Enforcement Rev

+15%

Performance vs Mayoral Priorities

Detailed Assessment

PriorityStatusEvidenceAssessment
Listen to Akl❌ FailTrust 27%No imprv.
Fix roads❌ Fail$37M capex lowDeteriorating
$50 PT pass⚠️ PartLow uptakePrice OK
Savings ($20M)❌ Fail$12M (Y1)40% short
Enforce revenue✅ OK+15% park revSuccess
Cycling network❌ FailCancelledUnaffordable

🚨 Gov. Disconnect

AT failed "take direction". 20% success shows misalignment. Validates reintegration.

💸 Financial Non-Comp.

Missed savings by 40%, $36M surplus, $37M capex underspend. Defiance.

Timeline: 1 Year Non-Delivery

Critical Verdict

AT's failure to deliver on mayoral expectations provides compelling evidence for reintegration.

  • ✗ 3/15 expectations met
  • ✗ Trust static at crisis levels
  • ✗ Financial directives ignored

Conclusion: LoE shows arm's-length model enables defiance. Reintegration is a necessity.

Data Explorer

CSV
JSON

Position Details

0 records

Tier Cost Composition Explorer

0Tier X Positions
0Tier X FTE
0Tier X Headcount
0Cost Centers (Tier X)

Cost-Center Composition (Tier X Roles)

Cost Center IDCost Center TextTier X FTETier X HeadcountShare of Total Tier X FTE

Processing...