403Webshell
Server IP : 69.72.244.102  /  Your IP : 216.73.216.164
Web Server : LiteSpeed
System : Linux s3434.fra1.stableserver.net 4.18.0-513.24.1.lve.2.el8.x86_64 #1 SMP Fri May 24 12:42:50 UTC 2024 x86_64
User : konzalta ( 1271)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/konzalta/constituency.work/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/konzalta/constituency.work//reports_analytics.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ConstituencyOS – Reports & Analytics</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
:root{
  --green:#1a7a4a;--green-light:#e8f5ee;--green-mid:#2d9e63;
  --red:#dc2626;--red-light:#fdecea;
  --amber:#f59e0b;--amber-light:#fffbeb;
  --blue:#2563eb;--blue-light:#eff6ff;
  --purple:#7c3aed;--purple-light:#f5f3ff;
  --teal:#0891b2;--teal-light:#ecfeff;
  --text:#111827;--muted:#6b7280;--light:#9ca3af;
  --border:#e5e7eb;--bg:#f3f4f6;--white:#ffffff;
  --sidebar-w:216px;--radius:10px;--radius-sm:6px;
  --shadow:0 1px 3px rgba(0,0,0,.08);
}
html,body{height:100%;margin:0;padding:0;}
body{font-family:'Inter',sans-serif;font-size:13px;color:var(--text);background:var(--bg);}
.sidebar{position:fixed;top:0;left:0;bottom:0;width:var(--sidebar-w);background:var(--white);border-right:1px solid var(--border);display:flex;flex-direction:column;overflow-y:auto;overflow-x:hidden;z-index:40;}
.sidebar-logo{display:flex;align-items:center;gap:9px;padding:14px 14px 12px;border-bottom:1px solid var(--border);flex-shrink:0;}
.logo-icon{width:38px;height:38px;background:linear-gradient(135deg,#b91c1c,#1a7a4a);border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:17px;flex-shrink:0;}
.logo-text strong{display:block;font-size:12.5px;font-weight:700;color:var(--green);}
.logo-text small{font-size:10px;color:var(--muted);line-height:1.3;}
.sidebar-profile{display:flex;align-items:center;gap:9px;padding:11px 14px;border-bottom:1px solid var(--border);flex-shrink:0;}
.s-av{width:36px;height:36px;border-radius:50%;background:#374151;color:white;font-weight:600;font-size:13px;display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;}
.s-av .dot{position:absolute;bottom:1px;right:1px;width:8px;height:8px;border-radius:50%;background:var(--green-mid);border:2px solid white;}
.pname{font-size:11.5px;font-weight:600;}.psub{font-size:10.5px;color:var(--muted);}
.sidebar-nav{flex:1;padding:6px 0;}
.nav-item{display:flex;align-items:center;gap:9px;padding:8px 14px;font-size:12px;font-weight:500;color:var(--muted);cursor:pointer;position:relative;transition:background .12s,color .12s;white-space:nowrap;}
.nav-item:hover{background:var(--bg);color:var(--text);}
.nav-item.active{background:var(--green-light);color:var(--green);font-weight:600;}
.nav-item.active::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--green);border-radius:0 2px 2px 0;}
.nav-icon{font-size:14px;width:16px;text-align:center;flex-shrink:0;}
.nav-badge{margin-left:auto;background:var(--red);color:white;font-size:9.5px;font-weight:700;padding:1px 5px;border-radius:10px;}
.nav-new{margin-left:auto;background:var(--green);color:white;font-size:9px;font-weight:700;padding:2px 5px;border-radius:4px;}
.nav-chev{margin-left:auto;font-size:10px;color:var(--light);}
.sidebar-footer{padding:12px 14px;border-top:1px solid var(--border);flex-shrink:0;}
.right-panel{margin-left:var(--sidebar-w);display:flex;flex-direction:column;min-height:100vh;}
.topbar{position:sticky;top:0;z-index:30;height:52px;background:var(--white);border-bottom:1px solid var(--border);display:flex;align-items:center;gap:10px;padding:0 18px;}
.menu-btn{font-size:17px;cursor:pointer;color:var(--muted);}
.const-sel{display:flex;align-items:center;gap:6px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:5px 10px;cursor:pointer;font-size:12px;font-weight:500;}
.srch{flex:1;max-width:360px;display:flex;align-items:center;gap:7px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:6px 11px;color:var(--muted);font-size:12px;}
.srch input{border:none;background:transparent;outline:none;width:100%;font-size:12px;font-family:inherit;}
.srch kbd{margin-left:auto;font-size:9.5px;background:var(--border);padding:1px 5px;border-radius:3px;font-family:inherit;}
.tbr{margin-left:auto;display:flex;align-items:center;gap:8px;}
.ibt{position:relative;width:32px;height:32px;border-radius:50%;background:var(--bg);border:1px solid var(--border);display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:15px;}
.ibt .bdg{position:absolute;top:-3px;right:-3px;background:var(--red);color:white;font-size:9px;font-weight:700;width:15px;height:15px;border-radius:50%;display:flex;align-items:center;justify-content:center;border:1.5px solid white;}
.ibt .bdg.grn{background:var(--green-mid);}
.upill{display:flex;align-items:center;gap:7px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:3px 8px;cursor:pointer;font-size:12px;font-weight:500;}
.content{padding:18px 18px 40px;display:flex;flex-direction:column;gap:14px;}
.btn{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;border-radius:var(--radius-sm);font-size:12px;font-weight:600;cursor:pointer;border:none;transition:background .15s;}
.btn-primary{background:var(--green);color:white;}.btn-primary:hover{background:var(--green-mid);}
.btn-ghost{background:var(--white);color:var(--text);border:1px solid var(--border);}.btn-ghost:hover{background:var(--bg);}
.page-hdr{display:flex;align-items:flex-start;justify-content:space-between;}
.page-title{font-size:19px;font-weight:700;}
.page-sub{font-size:12px;color:var(--muted);margin-top:2px;}

/* TABS + DATE RANGE */
.controls-row{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;}
.tabs{display:flex;gap:2px;background:var(--white);border:1px solid var(--border);border-radius:var(--radius);padding:4px;}
.tab{padding:8px 16px;border-radius:var(--radius-sm);font-size:12px;font-weight:600;color:var(--muted);cursor:pointer;transition:background .15s,color .15s;white-space:nowrap;}
.tab:hover{background:var(--bg);}
.tab.active{background:var(--green);color:white;}
.daterange{display:flex;align-items:center;gap:6px;background:var(--white);border:1px solid var(--border);border-radius:var(--radius-sm);padding:6px 12px;font-size:12px;font-weight:500;cursor:pointer;}

/* METRIC CARDS */
.metrics{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;}
.mc{background:var(--white);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;}
.mc-top{display:flex;align-items:center;justify-content:space-between;}
.mc-icon{font-size:20px;}
.mc-trend{font-size:10.5px;font-weight:700;padding:2px 7px;border-radius:20px;}
.mc-trend.up{background:#ecfdf5;color:#16a34a;}
.mc-trend.down{background:#fdecea;color:#dc2626;}
.mc-val{font-size:24px;font-weight:700;margin-top:8px;}
.mc-lbl{font-size:11px;color:var(--muted);margin-top:2px;}
.sparkline{margin-top:8px;}

/* CHART CARDS */
.charts-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
.card{background:var(--white);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;}
.card-hdr{display:flex;align-items:center;justify-content:space-between;padding:13px 16px;border-bottom:1px solid var(--border);}
.card-title{font-size:13px;font-weight:600;}
.vlink{font-size:11px;color:var(--green);cursor:pointer;font-weight:500;}
.chart-body{padding:16px;}

/* BAR CHART */
.bar-chart{display:flex;align-items:flex-end;gap:10px;height:180px;padding:10px 4px 0;}
.bar-col{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:6px;height:100%;}
.bar-stack{width:100%;max-width:36px;display:flex;flex-direction:column-reverse;border-radius:4px 4px 0 0;overflow:hidden;}
.bar-seg{width:100%;}
.bar-label{font-size:10px;color:var(--muted);margin-top:4px;}
.bar-val{font-size:10px;font-weight:700;color:var(--text);}

/* LINE CHART (SVG) */
.line-chart-wrap{padding:8px 0;}

/* DONUT */
.donut-row{display:flex;align-items:center;gap:20px;padding:6px 0;}
.donut-legend{flex:1;}
.dl-item{display:flex;align-items:center;gap:8px;padding:5px 0;font-size:12px;}
.dl-dot{width:9px;height:9px;border-radius:2px;flex-shrink:0;}
.dl-count{margin-left:auto;font-weight:700;}

/* WARD COMPARISON TABLE */
.cmp-table{width:100%;border-collapse:collapse;}
.cmp-table th{padding:8px 12px;font-size:10.5px;font-weight:600;color:var(--muted);text-align:left;border-bottom:1px solid var(--border);background:var(--bg);}
.cmp-table td{padding:8px 12px;font-size:11.5px;border-bottom:1px solid var(--border);}
.cmp-table tr:last-child td{border-bottom:none;}
.heat-cell{display:inline-block;width:100%;padding:3px 8px;border-radius:4px;font-weight:600;text-align:center;}

/* RESPONSE TIME GAUGE */
.gauge-wrap{display:flex;align-items:center;justify-content:center;flex-direction:column;padding:10px 0;}
.gauge-val{font-size:13px;color:var(--muted);margin-top:4px;}

/* TREND ROWS */
.trend-row{display:flex;align-items:center;gap:10px;padding:9px 16px;border-bottom:1px solid var(--border);}
.trend-row:last-child{border-bottom:none;}
.trend-icon{font-size:16px;width:24px;text-align:center;}
.trend-label{flex:1;font-size:12px;font-weight:500;}
.trend-bar-wrap{width:90px;height:6px;background:var(--border);border-radius:6px;overflow:hidden;}
.trend-bar-fill{height:100%;border-radius:6px;}
.trend-pct{width:38px;text-align:right;font-size:11px;font-weight:700;}

/* INSIGHTS */
.insight-item{display:flex;gap:10px;padding:11px 16px;border-bottom:1px solid var(--border);}
.insight-item:last-child{border-bottom:none;}
.insight-icon{font-size:18px;flex-shrink:0;}
.insight-title{font-size:12px;font-weight:700;}
.insight-text{font-size:11px;color:var(--muted);margin-top:2px;line-height:1.5;}
</style>
</head>
<body>
<aside class="sidebar">
  <div class="sidebar-logo"><div class="logo-icon">πŸ›οΈ</div><div class="logo-text"><strong>ConstituencyOS</strong><small>Everything in your constituency,<br>in one place.</small></div></div>
  <div class="sidebar-profile"><div class="s-av">DM<div class="dot"></div></div><div><div class="pname">Hon. David Mwangi, MP</div><div class="psub">Embakasi South</div></div></div>
  <nav class="sidebar-nav">
    <div class="nav-item" onclick="location.href='index.html'"><span class="nav-icon">🏠</span>Dashboard</div>
    <div class="nav-item" onclick="location.href='constituents.html'"><span class="nav-icon">πŸ‘₯</span>Constituents</div>
    <div class="nav-item" onclick="location.href='complaints.html'"><span class="nav-icon">πŸ“‹</span>Complaints<span class="nav-badge">9</span></div>
    <div class="nav-item" onclick="location.href='projects.html'"><span class="nav-icon">πŸ“</span>Projects</div>
    <div class="nav-item" onclick="location.href='bursaries.html'"><span class="nav-icon">πŸŽ“</span>Bursaries</div>
    <div class="nav-item" onclick="location.href='events.html'"><span class="nav-icon">πŸ“…</span>Events</div>
    <div class="nav-item" onclick="location.href='social_protection.html'"><span class="nav-icon">πŸ›‘οΈ</span>Social Protection</div>
    <div class="nav-item" onclick="location.href='ward_management.html'"><span class="nav-icon">🏘️</span>Ward Management</div>
    <div class="nav-item" onclick="location.href='finance.html'"><span class="nav-icon">πŸ’°</span>Finance</div>
    <div class="nav-item" onclick="location.href='documents.html'"><span class="nav-icon">πŸ“„</span>Documents</div>
    <div class="nav-item" onclick="location.href='staff_management.html'"><span class="nav-icon">πŸ‘€</span>Staff Management</div>
    <div class="nav-item" onclick="location.href='reports_analytics.html'"><span class="nav-icon">πŸ“Š</span>Reports & Analytics</div>
    <div class="nav-item active"><span class="nav-icon">πŸ€–</span>AI Assistant<span class="nav-new">New</span></div>
    <div class="nav-item" onclick="location.href='settings.html'"><span class="nav-icon">βš™οΈ</span>Settings</div>
    <div class="nav-item" onclick="location.href='public_portal.html'"><span class="nav-icon">🌐</span>Public Portal</div>
  </nav>
  <div class="sidebar-footer"><div style="display:flex;align-items:center;gap:9px;cursor:pointer"><span>❓</span><div><div style="font-size:11.5px;font-weight:600">Need Help?</div><div style="font-size:10.5px;color:var(--muted)">Contact Support</div></div></div></div>
</aside>

<div class="right-panel">
  <header class="topbar">
    <span class="menu-btn">☰</span>
    <div class="const-sel"><span style="font-size:13px">πŸ›οΈ</span>Embakasi South Constituency<span style="font-size:10px;color:var(--muted)">β–Ό</span></div>
    <div class="srch"><span>πŸ”</span><input type="text" placeholder="Search for anything…"><kbd>⌘K</kbd></div>
    <div class="tbr">
      <div class="ibt">πŸ””<div class="bdg">8</div></div>
      <div class="ibt">βœ‰οΈ<div class="bdg grn">3</div></div>
      <div class="upill"><div class="s-av" style="width:26px;height:26px;font-size:10px">DM</div>Hon. David Mwangi<span style="font-size:10px;color:var(--muted)">β–Ό</span></div>
    </div>
  </header>

  <main class="content">
    <div class="page-hdr">
      <div><div class="page-title">Reports &amp; Analytics</div><div class="page-sub">Constituency-wide performance insights and trends</div></div>
      <div style="display:flex;gap:8px;">
        <button class="btn btn-ghost">⬇ Export PDF</button>
        <button class="btn btn-primary">πŸ“Š Custom Report</button>
      </div>
    </div>

    <div class="controls-row">
      <div class="tabs">
        <div class="tab active" onclick="switchTab('overview',this)">Overview</div>
        <div class="tab" onclick="switchTab('complaints',this)">Complaints</div>
        <div class="tab" onclick="switchTab('projects',this)">Projects</div>
        <div class="tab" onclick="switchTab('wards',this)">Ward Comparison</div>
      </div>
      <div class="daterange">πŸ“… Last 6 Months β–Ό</div>
    </div>

    <!-- TAB: OVERVIEW -->
    <div id="tab-overview">
      <div class="metrics">
        <div class="mc">
          <div class="mc-top"><span class="mc-icon">πŸ“‹</span><span class="mc-trend down">β–Ό 8%</span></div>
          <div class="mc-val">487</div>
          <div class="mc-lbl">Total Complaints (6mo)</div>
          <svg class="sparkline" width="100%" height="28" viewBox="0 0 200 28" preserveAspectRatio="none"><polyline points="0,18 33,22 66,12 100,16 133,8 166,14 200,6" fill="none" stroke="#dc2626" stroke-width="2"/></svg>
        </div>
        <div class="mc">
          <div class="mc-top"><span class="mc-icon">βœ…</span><span class="mc-trend up">β–² 14%</span></div>
          <div class="mc-val">91.2%</div>
          <div class="mc-lbl">Resolution Rate</div>
          <svg class="sparkline" width="100%" height="28" viewBox="0 0 200 28" preserveAspectRatio="none"><polyline points="0,22 33,18 66,17 100,12 133,10 166,7 200,4" fill="none" stroke="#16a34a" stroke-width="2"/></svg>
        </div>
        <div class="mc">
          <div class="mc-top"><span class="mc-icon">πŸ“</span><span class="mc-trend up">β–² 11%</span></div>
          <div class="mc-val">47</div>
          <div class="mc-lbl">Active Projects</div>
          <svg class="sparkline" width="100%" height="28" viewBox="0 0 200 28" preserveAspectRatio="none"><polyline points="0,20 33,18 66,14 100,15 133,10 166,8 200,5" fill="none" stroke="#2563eb" stroke-width="2"/></svg>
        </div>
        <div class="mc">
          <div class="mc-top"><span class="mc-icon">πŸ’°</span><span class="mc-trend up">β–² 6%</span></div>
          <div class="mc-val">63%</div>
          <div class="mc-lbl">Budget Utilisation</div>
          <svg class="sparkline" width="100%" height="28" viewBox="0 0 200 28" preserveAspectRatio="none"><polyline points="0,24 33,20 66,19 100,15 133,13 166,10 200,8" fill="none" stroke="#7c3aed" stroke-width="2"/></svg>
        </div>
      </div>

      <div class="charts-grid" style="margin-top:14px;">
        <!-- Complaints trend line chart -->
        <div class="card">
          <div class="card-hdr"><span class="card-title">Complaints Trend β€” Filed vs Resolved</span><span class="vlink">Details</span></div>
          <div class="chart-body line-chart-wrap" id="complaintsLineChart"></div>
        </div>

        <!-- Project status donut -->
        <div class="card">
          <div class="card-hdr"><span class="card-title">Project Status Distribution</span></div>
          <div class="chart-body">
            <div class="donut-row">
              <svg width="110" height="110" viewBox="0 0 110 110">
                <circle cx="55" cy="55" r="42" fill="none" stroke="#e5e7eb" stroke-width="16"/>
                <circle cx="55" cy="55" r="42" fill="none" stroke="#2563eb" stroke-width="16" stroke-dasharray="145 119" stroke-dashoffset="0" transform="rotate(-90 55 55)"/>
                <circle cx="55" cy="55" r="42" fill="none" stroke="#16a34a" stroke-width="16" stroke-dasharray="67 197" stroke-dashoffset="-145" transform="rotate(-90 55 55)"/>
                <circle cx="55" cy="55" r="42" fill="none" stroke="#f59e0b" stroke-width="16" stroke-dasharray="28 236" stroke-dashoffset="-212" transform="rotate(-90 55 55)"/>
                <circle cx="55" cy="55" r="42" fill="none" stroke="#9ca3af" stroke-width="16" stroke-dasharray="24 240" stroke-dashoffset="-240" transform="rotate(-90 55 55)"/>
              </svg>
              <div class="donut-legend">
                <div class="dl-item"><div class="dl-dot" style="background:#2563eb"></div>In Progress<span class="dl-count">26</span></div>
                <div class="dl-item"><div class="dl-dot" style="background:#16a34a"></div>Completed<span class="dl-count">12</span></div>
                <div class="dl-item"><div class="dl-dot" style="background:#f59e0b"></div>Delayed<span class="dl-count">5</span></div>
                <div class="dl-item"><div class="dl-dot" style="background:#9ca3af"></div>Not Started<span class="dl-count">4</span></div>
              </div>
            </div>
          </div>
        </div>

        <!-- Budget by sector bar chart -->
        <div class="card">
          <div class="card-hdr"><span class="card-title">Budget Allocation by Sector</span></div>
          <div class="chart-body">
            <div class="bar-chart" id="sectorBarChart"></div>
          </div>
        </div>

        <!-- Average response time gauge -->
        <div class="card">
          <div class="card-hdr"><span class="card-title">Avg. Complaint Response Time</span></div>
          <div class="chart-body gauge-wrap">
            <svg width="180" height="100" viewBox="0 0 180 100">
              <path d="M 10 90 A 80 80 0 0 1 170 90" fill="none" stroke="#e5e7eb" stroke-width="14" stroke-linecap="round"/>
              <path d="M 10 90 A 80 80 0 0 1 130 22" fill="none" stroke="#1a7a4a" stroke-width="14" stroke-linecap="round"/>
              <text x="90" y="78" text-anchor="middle" font-size="22" font-weight="700" fill="#111827" font-family="Inter,sans-serif">2.4</text>
              <text x="90" y="94" text-anchor="middle" font-size="10" fill="#6b7280" font-family="Inter,sans-serif">days average</text>
            </svg>
            <div class="gauge-val">Target: 3.0 days Β· <span style="color:var(--green);font-weight:700;">20% faster</span></div>
          </div>
        </div>
      </div>

      <!-- Key Insights -->
      <div class="card" style="margin-top:14px;">
        <div class="card-hdr"><span class="card-title">Key Insights</span></div>
        <div class="insight-item">
          <span class="insight-icon">πŸ“ˆ</span>
          <div><div class="insight-title">Resolution rate improved 14% this quarter</div><div class="insight-text">Faster response times in Pipeline and Mabatini wards are driving the overall improvement. Water-related complaints saw the biggest gain.</div></div>
        </div>
        <div class="insight-item">
          <span class="insight-icon">⚠️</span>
          <div><div class="insight-title">5 projects flagged as delayed</div><div class="insight-text">Pipeline Road Rehabilitation and Imara Daima Footbridge Repair are the most overdue β€” both blocked on contractor materials procurement.</div></div>
        </div>
        <div class="insight-item">
          <span class="insight-icon">πŸ’§</span>
          <div><div class="insight-title">Water complaints up 22% in Kwa Njenga</div><div class="insight-text">Borehole and pipeline issues are concentrated in Kware area β€” consider prioritising the drainage and water infrastructure project there.</div></div>
        </div>
        <div class="insight-item">
          <span class="insight-icon">πŸŽ“</span>
          <div><div class="insight-title">Bursary approval rate steady at 58%</div><div class="insight-text">Consistent with last year. Pipeline and Imara Daima wards have the highest application volume relative to population.</div></div>
        </div>
      </div>
    </div>

    <!-- TAB: COMPLAINTS -->
    <div id="tab-complaints" style="display:none;">
      <div class="charts-grid">
        <div class="card">
          <div class="card-hdr"><span class="card-title">Complaints by Category</span></div>
          <div id="complaintsByCategory"></div>
        </div>
        <div class="card">
          <div class="card-hdr"><span class="card-title">Complaints by Ward</span></div>
          <div id="complaintsByWard"></div>
        </div>
      </div>
      <div class="card" style="margin-top:14px;">
        <div class="card-hdr"><span class="card-title">Resolution Time by Priority</span></div>
        <div id="resByPriority"></div>
      </div>
    </div>

    <!-- TAB: PROJECTS -->
    <div id="tab-projects" style="display:none;">
      <div class="charts-grid">
        <div class="card">
          <div class="card-hdr"><span class="card-title">Projects by Sector</span></div>
          <div id="projByCategory"></div>
        </div>
        <div class="card">
          <div class="card-hdr"><span class="card-title">Budget Spent vs Allocated by Sector</span></div>
          <div class="chart-body" id="budgetVsSpentChart"></div>
        </div>
      </div>
    </div>

    <!-- TAB: WARD COMPARISON -->
    <div id="tab-wards" style="display:none;">
      <div class="card">
        <div class="card-hdr"><span class="card-title">Ward Performance Comparison</span></div>
        <div style="overflow-x:auto;">
          <table class="cmp-table" id="wardCmpTable"></table>
        </div>
      </div>
    </div>

  </main>
</div>

<script>
// ===== LINE CHART: Complaints Filed vs Resolved =====
function renderLineChart(){
  const months = ['Dec','Jan','Feb','Mar','Apr','May'];
  const filed =    [78, 92, 71, 88, 84, 74];
  const resolved = [65, 80, 68, 82, 79, 71];
  const W=560, H=200, pad=30;
  const maxVal = 100;
  const xStep = (W-pad*2)/(months.length-1);
  const yScale = v => H-pad - (v/maxVal)*(H-pad*1.6);
  const filedPts = filed.map((v,i)=>`${pad+i*xStep},${yScale(v)}`).join(' ');
  const resolvedPts = resolved.map((v,i)=>`${pad+i*xStep},${yScale(v)}`).join(' ');

  let gridLines='';
  for(let i=0;i<=4;i++){
    const y = pad*0.4 + i*(H-pad*1.6)/4;
    gridLines += `<line x1="${pad}" y1="${y}" x2="${W-10}" y2="${y}" stroke="#f0f0f0" stroke-width="1"/>`;
  }

  let xLabels = months.map((m,i)=>`<text x="${pad+i*xStep}" y="${H-6}" font-size="10" fill="#6b7280" text-anchor="middle" font-family="Inter,sans-serif">${m}</text>`).join('');

  let filedDots = filed.map((v,i)=>`<circle cx="${pad+i*xStep}" cy="${yScale(v)}" r="3.5" fill="#dc2626"/>`).join('');
  let resolvedDots = resolved.map((v,i)=>`<circle cx="${pad+i*xStep}" cy="${yScale(v)}" r="3.5" fill="#16a34a"/>`).join('');

  document.getElementById('complaintsLineChart').innerHTML = `
    <svg width="100%" height="220" viewBox="0 0 ${W} ${H}" style="overflow:visible">
      ${gridLines}
      <polyline points="${filedPts}" fill="none" stroke="#dc2626" stroke-width="2.5"/>
      <polyline points="${resolvedPts}" fill="none" stroke="#16a34a" stroke-width="2.5"/>
      ${filedDots}${resolvedDots}
      ${xLabels}
    </svg>
    <div style="display:flex;gap:16px;justify-content:center;margin-top:6px;font-size:11px;color:var(--muted);">
      <span><span style="display:inline-block;width:9px;height:9px;border-radius:50%;background:#dc2626;margin-right:5px;"></span>Filed</span>
      <span><span style="display:inline-block;width:9px;height:9px;border-radius:50%;background:#16a34a;margin-right:5px;"></span>Resolved</span>
    </div>
  `;
}

// ===== BAR CHART: Sector budget =====
function renderSectorBars(){
  const sectors = [
    {name:'Water',val:72,color:'#2563eb'},
    {name:'Roads',val:56,color:'#d97706'},
    {name:'Health',val:73,color:'#dc2626'},
    {name:'Education',val:73,color:'#7c3aed'},
    {name:'Social',val:50,color:'#0891b2'},
    {name:'Admin',val:50,color:'#374151'},
  ];
  document.getElementById('sectorBarChart').innerHTML = sectors.map(s=>`
    <div class="bar-col">
      <div class="bar-val">${s.val}%</div>
      <div class="bar-stack" style="height:${s.val*1.4}px">
        <div class="bar-seg" style="height:100%;background:${s.color}"></div>
      </div>
      <div class="bar-label">${s.name}</div>
    </div>
  `).join('');
}

// ===== COMPLAINTS BY CATEGORY =====
function renderComplaintsByCategory(){
  const cats = [
    {name:'Water',count:142,icon:'πŸ’§',color:'#2563eb'},
    {name:'Roads',count:118,icon:'πŸ›£οΈ',color:'#d97706'},
    {name:'Sanitation',count:89,icon:'πŸ—‘οΈ',color:'#7c3aed'},
    {name:'Electricity',count:64,icon:'⚑',color:'#f59e0b'},
    {name:'Health',count:42,icon:'πŸ₯',color:'#dc2626'},
    {name:'Security',count:32,icon:'πŸ›‘οΈ',color:'#374151'},
  ];
  const max = Math.max(...cats.map(c=>c.count));
  document.getElementById('complaintsByCategory').innerHTML = cats.map(c=>`
    <div class="trend-row">
      <div class="trend-icon">${c.icon}</div>
      <div class="trend-label">${c.name}</div>
      <div class="trend-bar-wrap"><div class="trend-bar-fill" style="width:${c.count/max*100}%;background:${c.color}"></div></div>
      <div class="trend-pct">${c.count}</div>
    </div>
  `).join('');
}

function renderComplaintsByWard(){
  const wards = [
    {name:'Pipeline',count:98,color:'#2563eb'},
    {name:'Imara Daima',count:87,color:'#dc2626'},
    {name:'Mabatini',count:71,color:'#f59e0b'},
    {name:'Umoja',count:69,color:'#7c3aed'},
    {name:'Kwa Njenga',count:94,color:'#0891b2'},
    {name:'Mihango',count:68,color:'#1a7a4a'},
  ];
  const max = Math.max(...wards.map(w=>w.count));
  document.getElementById('complaintsByWard').innerHTML = wards.map(w=>`
    <div class="trend-row">
      <div class="trend-icon">🏘️</div>
      <div class="trend-label">${w.name}</div>
      <div class="trend-bar-wrap"><div class="trend-bar-fill" style="width:${w.count/max*100}%;background:${w.color}"></div></div>
      <div class="trend-pct">${w.count}</div>
    </div>
  `).join('');
}

function renderResByPriority(){
  const pri = [
    {name:'High Priority',days:'1.2 days',pct:92,color:'#dc2626'},
    {name:'Medium Priority',days:'2.8 days',pct:85,color:'#f59e0b'},
    {name:'Low Priority',days:'5.4 days',pct:78,color:'#16a34a'},
  ];
  document.getElementById('resByPriority').innerHTML = pri.map(p=>`
    <div class="trend-row">
      <div class="trend-icon">⏱️</div>
      <div class="trend-label">${p.name} <span style="color:var(--muted);font-weight:400;">β€” avg ${p.days}</span></div>
      <div class="trend-bar-wrap"><div class="trend-bar-fill" style="width:${p.pct}%;background:${p.color}"></div></div>
      <div class="trend-pct">${p.pct}%</div>
    </div>
  `).join('');
}

function renderProjByCategory(){
  const cats = [
    {name:'Water',count:9,icon:'πŸ’§',color:'#2563eb'},
    {name:'Roads',count:13,icon:'πŸ›£οΈ',color:'#d97706'},
    {name:'Health',count:7,icon:'πŸ₯',color:'#dc2626'},
    {name:'Education',count:8,icon:'🏫',color:'#7c3aed'},
    {name:'Sanitation',count:6,icon:'πŸ—‘οΈ',color:'#0891b2'},
    {name:'Energy',count:4,icon:'⚑',color:'#f59e0b'},
  ];
  const max = Math.max(...cats.map(c=>c.count));
  document.getElementById('projByCategory').innerHTML = cats.map(c=>`
    <div class="trend-row">
      <div class="trend-icon">${c.icon}</div>
      <div class="trend-label">${c.name}</div>
      <div class="trend-bar-wrap"><div class="trend-bar-fill" style="width:${c.count/max*100}%;background:${c.color}"></div></div>
      <div class="trend-pct">${c.count}</div>
    </div>
  `).join('');
}

function renderBudgetVsSpent(){
  const sectors = [
    {name:'Water',spent:32.5,total:45,color:'#2563eb'},
    {name:'Roads',spent:28.1,total:50,color:'#d97706'},
    {name:'Health',spent:18.2,total:25,color:'#dc2626'},
    {name:'Education',spent:22.0,total:30,color:'#7c3aed'},
  ];
  document.getElementById('budgetVsSpentChart').innerHTML = sectors.map(s=>`
    <div style="margin-bottom:14px;">
      <div style="display:flex;justify-content:space-between;font-size:11.5px;margin-bottom:5px;">
        <span style="font-weight:600;">${s.name}</span>
        <span style="color:var(--muted);">KSh ${s.spent}M / ${s.total}M</span>
      </div>
      <div style="height:8px;background:var(--border);border-radius:8px;overflow:hidden;">
        <div style="height:100%;width:${(s.spent/s.total*100)}%;background:${s.color};border-radius:8px;"></div>
      </div>
    </div>
  `).join('');
}

function renderWardCmpTable(){
  const wards = [
    {name:'Pipeline Ward',pop:24800,complaints:98,resRate:94,projects:4,budget:88,bursaries:312},
    {name:'Imara Daima',pop:22400,complaints:87,resRate:90,projects:4,budget:72,bursaries:286},
    {name:'Mabatini Ward',pop:19600,complaints:71,resRate:96,projects:3,budget:81,bursaries:248},
    {name:'Umoja Ward',pop:21200,complaints:69,resRate:97,projects:3,budget:65,bursaries:275},
    {name:'Kwa Njenga Ward',pop:20100,complaints:94,resRate:84,projects:3,budget:79,bursaries:263},
    {name:'Mihango Ward',pop:16750,complaints:68,resRate:91,projects:3,budget:70,bursaries:218},
  ];
  function heat(val, good){
    const color = good
      ? (val>=90?'#dcfce7':val>=80?'#fef9c3':'#fee2e2')
      : (val<=70?'#dcfce7':val<=85?'#fef9c3':'#fee2e2');
    const tcolor = good
      ? (val>=90?'#166534':val>=80?'#854d0e':'#991b1b')
      : (val<=70?'#166534':val<=85?'#854d0e':'#991b1b');
    return `<span class="heat-cell" style="background:${color};color:${tcolor}">${val}%</span>`;
  }
  document.getElementById('wardCmpTable').innerHTML = `
    <thead><tr>
      <th>Ward</th><th>Population</th><th>Complaints</th><th>Resolution Rate</th>
      <th>Active Projects</th><th>Budget Utilised</th><th>Bursary Recipients</th>
    </tr></thead>
    <tbody>
      ${wards.map(w=>`
        <tr>
          <td style="font-weight:600;">${w.name}</td>
          <td>${w.pop.toLocaleString()}</td>
          <td>${w.complaints}</td>
          <td>${heat(w.resRate,true)}</td>
          <td>${w.projects}</td>
          <td>${heat(w.budget,false)}</td>
          <td>${w.bursaries}</td>
        </tr>
      `).join('')}
    </tbody>
  `;
}

function switchTab(name, el){
  document.querySelectorAll('.tab').forEach(t=>t.classList.remove('active'));
  el.classList.add('active');
  ['overview','complaints','projects','wards'].forEach(t=>{
    document.getElementById('tab-'+t).style.display = t===name ? 'block' : 'none';
  });
}

// Init
renderLineChart();
renderSectorBars();
renderComplaintsByCategory();
renderComplaintsByWard();
renderResByPriority();
renderProjByCategory();
renderBudgetVsSpent();
renderWardCmpTable();
</script>
</body>
</html>

Youez - 2016 - github.com/yon3zu
LinuXploit