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//finance.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ConstituencyOS – Finance</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 */
.tabs{display:flex;gap:2px;background:var(--white);border:1px solid var(--border);border-radius:var(--radius);padding:4px;}
.tab{flex:1;text-align:center;padding:8px 14px;border-radius:var(--radius-sm);font-size:12px;font-weight:600;color:var(--muted);cursor:pointer;transition:background .15s,color .15s;}
.tab:hover{background:var(--bg);}
.tab.active{background:var(--green);color:white;}

/* 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-icon{font-size:22px;margin-bottom:6px;}
.mc-val{font-size:24px;font-weight:700;line-height:1;}
.mc-lbl{font-size:11px;color:var(--muted);margin-top:3px;}
.mc-sub{font-size:10.5px;margin-top:5px;}
.mc-sub.up{color:#16a34a;}.mc-sub.warn{color:var(--red);}.mc-sub.muted{color:var(--muted);}

/* MAIN LAYOUT */
.fin-layout{display:grid;grid-template-columns:1fr 320px;gap:14px;align-items:start;}
.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;}

/* BUDGET BAR OVERVIEW */
.budget-overview{padding:16px;}
.bo-row{display:flex;gap:24px;margin-bottom:14px;}
.bo-item{flex:1;}
.bo-val{font-size:20px;font-weight:700;}
.bo-lbl{font-size:10.5px;color:var(--muted);margin-top:2px;}
.stacked-bar{height:28px;border-radius:6px;overflow:hidden;display:flex;margin-bottom:8px;}
.stacked-seg{height:100%;display:flex;align-items:center;justify-content:center;color:white;font-size:10px;font-weight:700;}
.bo-legend{display:flex;gap:16px;flex-wrap:wrap;font-size:10.5px;color:var(--muted);}
.bo-leg-dot{width:9px;height:9px;border-radius:2px;display:inline-block;margin-right:4px;}

/* SECTOR ALLOCATION BARS */
.sector-list{padding:6px 16px 16px;}
.sector-row{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid var(--border);}
.sector-row:last-child{border-bottom:none;}
.sector-icon{width:30px;height:30px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;font-size:14px;flex-shrink:0;}
.sector-info{flex:1;min-width:0;}
.sector-name{font-size:12px;font-weight:600;}
.sector-bar-wrap{height:6px;background:var(--border);border-radius:6px;margin-top:5px;overflow:hidden;}
.sector-bar-fill{height:100%;border-radius:6px;}
.sector-amt{text-align:right;flex-shrink:0;}
.sector-spent{font-size:12px;font-weight:700;}
.sector-total{font-size:10px;color:var(--muted);}

/* TRANSACTIONS TABLE */
.toolbar{display:flex;align-items:center;gap:10px;padding:10px 16px;border-bottom:1px solid var(--border);flex-wrap:wrap;}
.sb{flex:1;min-width:160px;display:flex;align-items:center;gap:7px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:6px 10px;}
.sb input{border:none;background:transparent;outline:none;width:100%;font-size:12px;font-family:inherit;color:var(--text);}
.fsel{display:flex;align-items:center;gap:5px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:5px 9px;font-size:11.5px;white-space:nowrap;}
.fsel select{border:none;background:transparent;outline:none;font-size:11.5px;font-family:inherit;color:var(--text);cursor:pointer;}
table{width:100%;border-collapse:collapse;}
thead tr{background:var(--bg);border-bottom:1px solid var(--border);}
th{padding:9px 14px;font-size:11px;font-weight:600;color:var(--muted);text-align:left;white-space:nowrap;cursor:pointer;}
th:hover{color:var(--text);}
tbody tr{border-bottom:1px solid var(--border);transition:background .1s;cursor:pointer;}
tbody tr:last-child{border-bottom:none;}
tbody tr:hover{background:#f9fafb;}
td{padding:9px 14px;font-size:11.5px;vertical-align:middle;}
.amt-out{color:var(--red);font-weight:600;}
.amt-in{color:var(--green);font-weight:600;}
.ttag{display:inline-flex;align-items:center;gap:4px;font-size:10px;font-weight:600;padding:2px 8px;border-radius:20px;}
.ttag.disbursement{background:var(--blue-light);color:#1d4ed8;}
.ttag.allocation{background:var(--green-light);color:#065f46;}
.ttag.payment{background:var(--amber-light);color:#92400e;}
.pgn{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-top:1px solid var(--border);}
.pg-info{font-size:11.5px;color:var(--muted);}
.pg-btns{display:flex;gap:4px;}
.pg-btn{width:26px;height:26px;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--white);display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:11.5px;font-weight:500;}
.pg-btn.active{background:var(--green);color:white;border-color:var(--green);}
.pg-btn:hover:not(.active){background:var(--bg);}

/* WARD SPEND COMPARISON */
.ward-cmp-row{display:flex;align-items:center;gap:8px;padding:8px 16px;border-bottom:1px solid var(--border);font-size:11.5px;}
.ward-cmp-row:last-child{border-bottom:none;}
.ward-cmp-name{width:84px;flex-shrink:0;font-weight:500;}
.ward-cmp-bar{flex:1;height:7px;background:var(--border);border-radius:7px;overflow:hidden;}
.ward-cmp-fill{height:100%;border-radius:7px;background:var(--green);}
.ward-cmp-pct{width:36px;text-align:right;font-weight:700;font-size:11px;}

/* DOWNLOADS */
.dl-item{display:flex;align-items:center;gap:10px;padding:9px 16px;border-bottom:1px solid var(--border);cursor:pointer;}
.dl-item:last-child{border-bottom:none;}
.dl-item:hover{background:var(--bg);}
.dl-icon{font-size:16px;}
.dl-name{font-size:11.5px;font-weight:600;}
.dl-meta{font-size:10px;color:var(--muted);}
.dl-btn{margin-left:auto;font-size:11px;color:var(--green);font-weight:600;}

/* PIE CHART for spend category */
.pie-row{display:flex;align-items:center;gap:16px;padding:16px;}
.pie-legend{flex:1;}
.pl-item{display:flex;align-items:center;gap:7px;padding:4px 0;font-size:11.5px;}
.pl-dot{width:9px;height:9px;border-radius:2px;flex-shrink:0;}
.pl-count{margin-left:auto;font-weight:700;}
</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">Finance</div><div class="page-sub">CDF and constituency fund management β€” FY 2023/2024</div></div>
      <div style="display:flex;gap:8px;">
        <button class="btn btn-ghost">⬇ Export Report</button>
        <button class="btn btn-primary">οΌ‹ Record Transaction</button>
      </div>
    </div>

    <!-- Tabs -->
    <div class="tabs">
      <div class="tab active" onclick="switchTab('overview',this)">Overview</div>
      <div class="tab" onclick="switchTab('transactions',this)">Transactions</div>
      <div class="tab" onclick="switchTab('wards',this)">Ward Comparison</div>
      <div class="tab" onclick="switchTab('reports',this)">Reports &amp; Statements</div>
    </div>

    <!-- Metrics -->
    <div class="metrics">
      <div class="mc">
        <div class="mc-icon">πŸ’°</div>
        <div class="mc-val">KSh 195.2M</div>
        <div class="mc-lbl">Total Allocation FY24</div>
        <div class="mc-sub muted">National + County CDF</div>
      </div>
      <div class="mc">
        <div class="mc-icon">πŸ“€</div>
        <div class="mc-val" style="color:var(--green)">KSh 123.4M</div>
        <div class="mc-lbl">Disbursed</div>
        <div class="mc-sub up">β–² 63% of total budget</div>
      </div>
      <div class="mc">
        <div class="mc-icon">πŸ“Š</div>
        <div class="mc-val" style="color:var(--blue)">KSh 71.8M</div>
        <div class="mc-lbl">Remaining Balance</div>
        <div class="mc-sub muted">37% unutilised</div>
      </div>
      <div class="mc">
        <div class="mc-icon">⚠️</div>
        <div class="mc-val" style="color:var(--red)">KSh 4.2M</div>
        <div class="mc-lbl">Pending Audits</div>
        <div class="mc-sub warn">3 projects flagged</div>
      </div>
    </div>

    <!-- TAB: OVERVIEW -->
    <div id="tab-overview">
      <div class="fin-layout">
        <div style="display:flex;flex-direction:column;gap:14px;">

          <!-- Budget Overview Stacked Bar -->
          <div class="card">
            <div class="card-hdr"><span class="card-title">Budget Utilisation Overview</span><span class="vlink">FY 2023/2024</span></div>
            <div class="budget-overview">
              <div class="bo-row">
                <div class="bo-item"><div class="bo-val">KSh 195.2M</div><div class="bo-lbl">Total Budget</div></div>
                <div class="bo-item"><div class="bo-val" style="color:var(--green)">KSh 123.4M</div><div class="bo-lbl">Disbursed</div></div>
                <div class="bo-item"><div class="bo-val" style="color:var(--amber)">KSh 18.6M</div><div class="bo-lbl">Committed</div></div>
                <div class="bo-item"><div class="bo-val" style="color:var(--light)">KSh 53.2M</div><div class="bo-lbl">Uncommitted</div></div>
              </div>
              <div class="stacked-bar">
                <div class="stacked-seg" style="width:63%;background:var(--green)">63%</div>
                <div class="stacked-seg" style="width:10%;background:var(--amber)">10%</div>
                <div class="stacked-seg" style="width:27%;background:var(--border);color:var(--muted)"></div>
              </div>
              <div class="bo-legend">
                <span><span class="bo-leg-dot" style="background:var(--green)"></span>Disbursed</span>
                <span><span class="bo-leg-dot" style="background:var(--amber)"></span>Committed (approved, not paid)</span>
                <span><span class="bo-leg-dot" style="background:var(--border)"></span>Uncommitted</span>
              </div>
            </div>
          </div>

          <!-- Sector Allocation -->
          <div class="card">
            <div class="card-hdr"><span class="card-title">Allocation by Sector</span><span class="vlink">View breakdown</span></div>
            <div class="sector-list" id="sectorList"></div>
          </div>

          <!-- Pie: spend by type -->
          <div class="card">
            <div class="card-hdr"><span class="card-title">Disbursement by Fund Type</span></div>
            <div class="pie-row">
              <svg width="120" height="120" viewBox="0 0 120 120">
                <circle cx="60" cy="60" r="46" fill="none" stroke="#e5e7eb" stroke-width="18"/>
                <circle cx="60" cy="60" r="46" fill="none" stroke="#1a7a4a" stroke-width="18" stroke-dasharray="173 116" stroke-dashoffset="0" transform="rotate(-90 60 60)"/>
                <circle cx="60" cy="60" r="46" fill="none" stroke="#2563eb" stroke-width="18" stroke-dasharray="72 217" stroke-dashoffset="-173" transform="rotate(-90 60 60)"/>
                <circle cx="60" cy="60" r="46" fill="none" stroke="#7c3aed" stroke-width="18" stroke-dasharray="43 246" stroke-dashoffset="-245" transform="rotate(-90 60 60)"/>
                <circle cx="60" cy="60" r="46" fill="none" stroke="#f59e0b" stroke-width="18" stroke-dasharray="1 288" stroke-dashoffset="-288" transform="rotate(-90 60 60)"/>
              </svg>
              <div class="pie-legend">
                <div class="pl-item"><div class="pl-dot" style="background:#1a7a4a"></div>CDF β€” Infrastructure<span class="pl-count">KSh 60.0M</span></div>
                <div class="pl-item"><div class="pl-dot" style="background:#2563eb"></div>Bursary Fund<span class="pl-count">KSh 25.0M</span></div>
                <div class="pl-item"><div class="pl-dot" style="background:#7c3aed"></div>Social Protection<span class="pl-count">KSh 18.4M</span></div>
                <div class="pl-item"><div class="pl-dot" style="background:#f59e0b"></div>Emergency Fund<span class="pl-count">KSh 20.0M</span></div>
              </div>
            </div>
          </div>

        </div>

        <!-- Right column -->
        <div style="display:flex;flex-direction:column;gap:14px;">
          <div class="card">
            <div class="card-hdr"><span class="card-title">Recent Transactions</span><span class="vlink" onclick="switchTabByName('transactions')">View all β†’</span></div>
            <div id="recentTx"></div>
          </div>
          <div class="card">
            <div class="card-hdr"><span class="card-title">Reports &amp; Statements</span></div>
            <div id="dlListMini"></div>
          </div>
        </div>
      </div>
    </div>

    <!-- TAB: TRANSACTIONS -->
    <div id="tab-transactions" style="display:none;">
      <div class="card">
        <div class="toolbar">
          <div class="sb"><span>πŸ”</span><input type="text" id="searchInput" placeholder="Search transactions…" oninput="applyFilters()"></div>
          <div class="fsel">πŸ“‚ <select id="typeFilter" onchange="applyFilters()">
            <option value="">All Types</option>
            <option>Disbursement</option><option>Allocation</option><option>Payment</option>
          </select></div>
          <div class="fsel">🏷️ <select id="sectorFilter" onchange="applyFilters()">
            <option value="">All Sectors</option>
            <option>Water</option><option>Roads</option><option>Health</option><option>Education</option>
            <option>Sanitation</option><option>Energy</option><option>Bursary</option><option>Social Protection</option><option>Administration</option>
          </select></div>
          <div class="fsel">🏘️ <select id="wardFilter" onchange="applyFilters()">
            <option value="">All Wards</option>
            <option>Pipeline Ward</option><option>Imara Daima</option><option>Mabatini Ward</option>
            <option>Umoja Ward</option><option>Kwa Njenga Ward</option><option>Mihango Ward</option><option>All Wards</option>
          </select></div>
        </div>
        <div style="overflow-x:auto;">
          <table>
            <thead><tr>
              <th>Ref No.</th><th onclick="sortBy('date')">Date ↕</th><th onclick="sortBy('desc')">Description ↕</th>
              <th>Sector</th><th>Ward</th><th>Type</th><th onclick="sortBy('amount')">Amount (KSh) ↕</th>
            </tr></thead>
            <tbody id="tableBody"></tbody>
          </table>
        </div>
        <div class="pgn">
          <div class="pg-info" id="pgInfo"></div>
          <div class="pg-btns" id="pgBtns"></div>
        </div>
      </div>
    </div>

    <!-- TAB: WARD COMPARISON -->
    <div id="tab-wards" style="display:none;">
      <div class="fin-layout" style="grid-template-columns:1fr 1fr;">
        <div class="card">
          <div class="card-hdr"><span class="card-title">Budget Utilisation by Ward</span></div>
          <div id="wardCmp"></div>
        </div>
        <div class="card">
          <div class="card-hdr"><span class="card-title">Per Capita Spending by Ward</span></div>
          <div style="padding:14px 16px;">
            <table style="width:100%;font-size:11.5px;">
              <thead><tr style="border-bottom:1px solid var(--border);"><th style="text-align:left;padding:6px 0;color:var(--muted);font-weight:600;">Ward</th><th style="text-align:right;padding:6px 0;color:var(--muted);font-weight:600;">Spend</th><th style="text-align:right;padding:6px 0;color:var(--muted);font-weight:600;">Pop.</th><th style="text-align:right;padding:6px 0;color:var(--muted);font-weight:600;">Per Capita</th></tr></thead>
              <tbody id="perCapitaBody"></tbody>
            </table>
          </div>
        </div>
      </div>
    </div>

    <!-- TAB: REPORTS -->
    <div id="tab-reports" style="display:none;">
      <div class="card">
        <div class="card-hdr"><span class="card-title">Financial Reports &amp; Statements</span></div>
        <div id="dlListFull"></div>
      </div>
    </div>

  </main>
</div>

<script>
const SECTORS = [
  {name:'Water & Sanitation',icon:'πŸ’§',color:'#2563eb',bg:'#eff6ff',spent:32500000,total:45000000},
  {name:'Roads & Infrastructure',icon:'πŸ›£οΈ',color:'#d97706',bg:'#fff7ed',spent:28100000,total:50000000},
  {name:'Health',icon:'πŸ₯',color:'#dc2626',bg:'#fdecea',spent:18200000,total:25000000},
  {name:'Education / Bursaries',icon:'πŸŽ“',color:'#7c3aed',bg:'#f5f3ff',spent:22000000,total:30000000},
  {name:'Social Protection',icon:'πŸ›‘οΈ',color:'#0891b2',bg:'#ecfeff',spent:9200000,total:18400000},
  {name:'Administration',icon:'🏒',color:'#374151',bg:'#f3f4f6',spent:13400000,total:26800000},
];

const TRANSACTIONS = [
  {ref:'TXN-2024-0512',date:'2024-05-20',desc:'Disbursement β€” Kwa Njenga Water Pipeline (Phase 2)',sector:'Water',ward:'Kwa Njenga Ward',type:'Disbursement',amount:2400000},
  {ref:'TXN-2024-0511',date:'2024-05-19',desc:'Payment β€” Tarmac East Africa (Pipeline Road)',sector:'Roads',ward:'Pipeline Ward',type:'Payment',amount:3100000},
  {ref:'TXN-2024-0510',date:'2024-05-18',desc:'Bursary disbursement batch β€” 42 students',sector:'Bursary',ward:'All Wards',type:'Disbursement',amount:1260000},
  {ref:'TXN-2024-0509',date:'2024-05-17',desc:'Social Protection stipends β€” May 2024',sector:'Social Protection',ward:'All Wards',type:'Payment',amount:1533000},
  {ref:'TXN-2024-0508',date:'2024-05-16',desc:'Allocation β€” Mihango Primary classrooms (Q2)',sector:'Education',ward:'Mihango Ward',type:'Allocation',amount:1700000},
  {ref:'TXN-2024-0507',date:'2024-05-15',desc:'Payment β€” BuildRight Contractors (Imara Daima Dispensary)',sector:'Health',ward:'Imara Daima',type:'Payment',amount:2050000},
  {ref:'TXN-2024-0506',date:'2024-05-14',desc:'Office operations & administration β€” May',sector:'Administration',ward:'All Wards',type:'Payment',amount:840000},
  {ref:'TXN-2024-0505',date:'2024-05-12',desc:'Allocation β€” Mabatini Health Centre Upgrade',sector:'Health',ward:'Mabatini Ward',type:'Allocation',amount:3900000},
  {ref:'TXN-2024-0504',date:'2024-05-10',desc:'Disbursement β€” Aqua Works Ltd (Pipeline borehole)',sector:'Water',ward:'Pipeline Ward',type:'Disbursement',amount:1980000},
  {ref:'TXN-2024-0503',date:'2024-05-08',desc:'Payment β€” SolarTech EA (Mabatini street lights, retention)',sector:'Roads',ward:'Mabatini Ward',type:'Payment',amount:160000},
  {ref:'TXN-2024-0502',date:'2024-05-06',desc:'Bursary disbursement batch β€” 28 students',sector:'Bursary',ward:'All Wards',type:'Disbursement',amount:920000},
  {ref:'TXN-2024-0501',date:'2024-05-03',desc:'Allocation β€” Umoja Youth Sports Complex (Phase 2)',sector:'Roads',ward:'Umoja Ward',type:'Allocation',amount:4400000},
  {ref:'TXN-2024-0500',date:'2024-05-01',desc:'Social Protection stipends β€” April top-up',sector:'Social Protection',ward:'All Wards',type:'Payment',amount:412000},
  {ref:'TXN-2024-0499',date:'2024-04-28',desc:'Payment β€” FastFix Contractors (Imara footbridge, mobilisation)',sector:'Roads',ward:'Imara Daima',type:'Payment',amount:210000},
  {ref:'TXN-2024-0498',date:'2024-04-25',desc:'Disbursement β€” EduBuild Ltd (Mihango classrooms Phase 1)',sector:'Education',ward:'Mihango Ward',type:'Disbursement',amount:1740000},
  {ref:'TXN-2024-0497',date:'2024-04-22',desc:'Office operations & administration β€” April',sector:'Administration',ward:'All Wards',type:'Payment',amount:795000},
  {ref:'TXN-2024-0496',date:'2024-04-18',desc:'Allocation β€” Kwa Njenga Drainage System (design)',sector:'Sanitation',ward:'Kwa Njenga Ward',type:'Allocation',amount:950000},
  {ref:'TXN-2024-0495',date:'2024-04-15',desc:'Payment β€” Eng. Kamau retainer (Q2)',sector:'Administration',ward:'All Wards',type:'Payment',amount:180000},
  {ref:'TXN-2024-0494',date:'2024-04-10',desc:'Bursary disbursement batch β€” 35 students',sector:'Bursary',ward:'All Wards',type:'Disbursement',amount:1190000},
  {ref:'TXN-2024-0493',date:'2024-04-05',desc:'Disbursement β€” Tarmac East Africa (Mihango storm drains, final)',sector:'Sanitation',ward:'Mihango Ward',type:'Disbursement',amount:1100000},
];

const WARD_SPEND = [
  {ward:'Pipeline',spend:21600000,pop:24800,color:'#2563eb'},
  {ward:'Imara Daima',spend:19800000,pop:22400,color:'#dc2626'},
  {ward:'Mabatini',spend:16400000,pop:19600,color:'#f59e0b'},
  {ward:'Umoja',spend:18200000,pop:21200,color:'#7c3aed'},
  {ward:'Kwa Njenga',spend:14900000,pop:20100,color:'#0891b2'},
  {ward:'Mihango',spend:12500000,pop:16750,color:'#1a7a4a'},
];

const REPORTS = [
  {name:'Q3 FY2023/2024 Financial Statement',type:'PDF',size:'2.4 MB',date:'31 Mar 2024'},
  {name:'Annual CDF Utilisation Report 2023',type:'PDF',size:'5.1 MB',date:'15 Jan 2024'},
  {name:'Bursary Fund Audit Report',type:'PDF',size:'1.8 MB',date:'10 Mar 2024'},
  {name:'Social Protection Disbursement Log β€” Q1 2024',type:'XLSX',size:'640 KB',date:'5 Apr 2024'},
  {name:'Project Expenditure Summary β€” May 2024',type:'XLSX',size:'480 KB',date:'21 May 2024'},
  {name:'Office Operations Statement β€” April 2024',type:'PDF',size:'320 KB',date:'2 May 2024'},
];

let filtered=[...TRANSACTIONS];
let sortKey='date';
let sortDir=-1;
let currentPage=1;
const PAGE_SIZE=10;

function fmt(n){return 'KSh '+n.toLocaleString();}

function renderSectors(){
  document.getElementById('sectorList').innerHTML = SECTORS.map(s=>{
    const pct = Math.round(s.spent/s.total*100);
    return `<div class="sector-row">
      <div class="sector-icon" style="background:${s.bg}">${s.icon}</div>
      <div class="sector-info">
        <div class="sector-name">${s.name}</div>
        <div class="sector-bar-wrap"><div class="sector-bar-fill" style="width:${pct}%;background:${s.color}"></div></div>
      </div>
      <div class="sector-amt">
        <div class="sector-spent" style="color:${s.color}">${pct}%</div>
        <div class="sector-total">${fmt(s.spent)} / ${fmt(s.total)}</div>
      </div>
    </div>`;
  }).join('');
}

function txTag(t){
  const cls = t.toLowerCase();
  const icon = t==='Disbursement'?'πŸ“€':t==='Allocation'?'πŸ“‹':'πŸ’³';
  return `<span class="ttag ${cls}">${icon} ${t}</span>`;
}

function renderRecentTx(){
  const recent = [...TRANSACTIONS].sort((a,b)=>new Date(b.date)-new Date(a.date)).slice(0,6);
  document.getElementById('recentTx').innerHTML = recent.map(t=>`
    <div style="display:flex;align-items:center;gap:10px;padding:9px 16px;border-bottom:1px solid var(--border);">
      <div style="flex:1;min-width:0;">
        <div style="font-size:11.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">${t.desc}</div>
        <div style="font-size:10px;color:var(--muted);margin-top:1px;">${t.date} Β· ${t.ward}</div>
      </div>
      <div class="amt-out" style="font-size:11.5px;flex-shrink:0;">-${(t.amount/1000000).toFixed(2)}M</div>
    </div>
  `).join('');
}

function renderDownloads(containerId, limit){
  const list = limit ? REPORTS.slice(0,limit) : REPORTS;
  document.getElementById(containerId).innerHTML = list.map(r=>`
    <div class="dl-item">
      <span class="dl-icon">${r.type==='PDF'?'πŸ“„':'πŸ“Š'}</span>
      <div>
        <div class="dl-name">${r.name}</div>
        <div class="dl-meta">${r.type} Β· ${r.size} Β· ${r.date}</div>
      </div>
      <span class="dl-btn">⬇ Download</span>
    </div>
  `).join('');
}

function applyFilters(){
  const q = document.getElementById('searchInput').value.toLowerCase();
  const type = document.getElementById('typeFilter').value;
  const sector = document.getElementById('sectorFilter').value;
  const ward = document.getElementById('wardFilter').value;
  filtered = TRANSACTIONS.filter(t=>{
    if(type && t.type!==type) return false;
    if(sector && t.sector!==sector) return false;
    if(ward && t.ward!==ward) return false;
    if(q && !`${t.ref} ${t.desc} ${t.sector} ${t.ward}`.toLowerCase().includes(q)) return false;
    return true;
  });
  filtered.sort((a,b)=>{
    let av=a[sortKey],bv=b[sortKey];
    if(sortKey==='date'){av=new Date(av);bv=new Date(bv);}
    return av>bv?sortDir:av<bv?-sortDir:0;
  });
  currentPage=1; render();
}

function sortBy(key){
  if(sortKey===key) sortDir*=-1; else {sortKey=key; sortDir=1;}
  applyFilters();
}

function render(){
  const start=(currentPage-1)*PAGE_SIZE, end=start+PAGE_SIZE;
  const page=filtered.slice(start,end);
  document.getElementById('tableBody').innerHTML = page.map(t=>`
    <tr>
      <td style="font-size:10.5px;color:var(--muted);font-weight:600">${t.ref}</td>
      <td style="color:var(--muted);white-space:nowrap;">${t.date}</td>
      <td style="font-weight:500;">${t.desc}</td>
      <td>${t.sector}</td>
      <td>${t.ward}</td>
      <td>${txTag(t.type)}</td>
      <td class="amt-out" style="text-align:right;">-${t.amount.toLocaleString()}</td>
    </tr>
  `).join('');

  const total=filtered.length, pages=Math.ceil(total/PAGE_SIZE);
  document.getElementById('pgInfo').textContent = `Showing ${Math.min(start+1,total)}–${Math.min(end,total)} of ${total} transactions`;
  const pb=document.getElementById('pgBtns'); pb.innerHTML='';
  const add=(l,p,a)=>{const d=document.createElement('div');d.className='pg-btn'+(a?' active':'');d.textContent=l;d.onclick=()=>{currentPage=p;render();};pb.appendChild(d);};
  if(currentPage>1) add('β€Ή',currentPage-1,false);
  for(let i=1;i<=Math.min(pages,7);i++) add(i,i,i===currentPage);
  if(currentPage<pages) add('β€Ί',currentPage+1,false);
}

function renderWardCmp(){
  const max = Math.max(...WARD_SPEND.map(w=>w.spend));
  document.getElementById('wardCmp').innerHTML = WARD_SPEND.map(w=>{
    const pct = Math.round(w.spend/max*100);
    return `<div class="ward-cmp-row">
      <div class="ward-cmp-name">${w.ward}</div>
      <div class="ward-cmp-bar"><div class="ward-cmp-fill" style="width:${pct}%;background:${w.color}"></div></div>
      <div class="ward-cmp-pct">${fmt(Math.round(w.spend/1000000))}M</div>
    </div>`;
  }).join('');
}

function renderPerCapita(){
  document.getElementById('perCapitaBody').innerHTML = WARD_SPEND.map(w=>{
    const perCapita = Math.round(w.spend/w.pop);
    return `<tr style="border-bottom:1px solid var(--border);">
      <td style="padding:7px 0;font-weight:500;">${w.ward}</td>
      <td style="padding:7px 0;text-align:right;">${fmt(Math.round(w.spend/1000000))}M</td>
      <td style="padding:7px 0;text-align:right;color:var(--muted);">${w.pop.toLocaleString()}</td>
      <td style="padding:7px 0;text-align:right;font-weight:700;color:var(--green);">KSh ${perCapita.toLocaleString()}</td>
    </tr>`;
  }).join('');
}

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

// Init
renderSectors();
renderRecentTx();
renderDownloads('dlListMini', 4);
renderDownloads('dlListFull');
renderWardCmp();
renderPerCapita();
applyFilters();
</script>
</body>
</html>

Youez - 2016 - github.com/yon3zu
LinuXploit