{"id":8,"date":"2025-11-29T08:43:27","date_gmt":"2025-11-29T08:43:27","guid":{"rendered":"https:\/\/emfulenihub.co.za\/?page_id=8"},"modified":"2025-11-29T10:20:44","modified_gmt":"2025-11-29T10:20:44","slug":"emfuleni-bxc-smart-meter-information","status":"publish","type":"page","link":"https:\/\/emfulenihub.co.za\/","title":{"rendered":"Emfuleni BXC Smart Meter Information"},"content":{"rendered":"\n<div class=\"mz-electricity-card\">\n  <h3 class=\"mz-title\">Electricity Block Tariff Calculator<\/h3>\n  <div class=\"mz-subtitle\">Applicable to 2024\/2025 Domestic Supply Tariffs<\/div>\n\n  <div class=\"mz-form\">\n    <div class=\"mz-field\">\n      <label for=\"tariff_season\">Tariff season<\/label>\n      <select id=\"tariff_season\" class=\"mz-input\">\n        <option value=\"summer\" selected>Summer<\/option>\n        <option value=\"winter\">Winter<\/option>\n      <\/select>\n    <\/div>\n\n    <div class=\"mz-field\">\n      <label for=\"kwh_input\">Monthly usage (kWh)<\/label>\n      <input type=\"number\" id=\"kwh_input\" min=\"0\" step=\"1\" class=\"mz-input\" placeholder=\"e.g. 800\">\n    <\/div>\n\n    <button type=\"button\" class=\"mz-button\" onclick=\"mzCalcTariff()\">\n      Calculate\n    <\/button>\n  <\/div>\n\n  <div id=\"kwh_result\" class=\"mz-result\"><\/div>\n\n  <div class=\"mz-chart-wrapper\">\n    <canvas id=\"kwh_chart\"><\/canvas>\n  <\/div>\n\n  <div id=\"kwh_table\" class=\"mz-table-wrapper\"><\/div>\n\n  <div class=\"mz-disclaimer\">\n    Information based on tariffs provided by BXC.  \n    We accept no responsibility or liability for errors, omissions, or usage outcomes.\n  <\/div>\n<\/div>\n\n<style>\n  .mz-electricity-card {\n    max-width: 760px;\n    margin: 1.5rem auto;\n    padding: 1.75rem 1.5rem;\n    border-radius: 14px;\n    border: 1px solid rgba(0,0,0,0.06);\n    background: #ffffff;\n    box-shadow: 0 10px 30px rgba(0,0,0,0.03);\n    font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n    color: #111827;\n  }\n\n  .mz-title {\n    margin: 0;\n    font-size: 1.4rem;\n    font-weight: 600;\n  }\n\n  .mz-subtitle {\n    font-size: 0.85rem;\n    color: #6b7280;\n    margin-top: 0.25rem;\n    margin-bottom: 1rem;\n  }\n\n  .mz-form {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n    gap: 0.75rem 1rem;\n    align-items: end;\n    margin-bottom: 0.75rem;\n  }\n\n  .mz-field {\n    display: flex;\n    flex-direction: column;\n    gap: 0.25rem;\n  }\n\n  .mz-field label {\n    font-size: 0.85rem;\n    font-weight: 500;\n    color: #4b5563;\n  }\n\n  .mz-input {\n    padding: 0.45rem 0.6rem;\n    border-radius: 8px;\n    border: 1px solid #d1d5db;\n    font-size: 0.95rem;\n    background: #f9fafb;\n  }\n\n  .mz-button {\n    padding: 0.55rem 1rem;\n    border-radius: 999px;\n    border: none;\n    font-size: 0.95rem;\n    font-weight: 500;\n    cursor: pointer;\n    background: linear-gradient(135deg, #2563eb, #1d4ed8);\n    color: #ffffff;\n    box-shadow: 0 8px 20px rgba(37,99,235,0.25);\n  }\n\n  .mz-result {\n    margin-top: 0.5rem;\n    font-weight: 600;\n    font-size: 0.98rem;\n  }\n\n  .mz-chart-wrapper {\n    margin-top: 1.25rem;\n    height: 260px;\n  }\n\n  .mz-chart-wrapper canvas { width: 100%!important; height: 100%!important; }\n\n  .mz-table-wrapper {\n    margin-top: 1.5rem;\n    font-size: 0.9rem;\n  }\n\n  .mz-table-wrapper h4 { margin-bottom: 0.4rem; font-size: 1rem; }\n\n  .mz-table-wrapper table {\n    width: 100%;\n    border-collapse: collapse;\n    border-radius: 10px;\n    overflow: hidden;\n    background: #f9fafb;\n  }\n\n  .mz-table-wrapper thead { background: #e5e7eb; }\n\n  .mz-table-wrapper th,\n  .mz-table-wrapper td {\n    padding: 0.45rem 0.6rem;\n    border-bottom: 1px solid #e5e7eb;\n  }\n\n  .mz-table-wrapper th { text-align: left; font-size: 0.8rem; text-transform: uppercase; }\n\n  .mz-table-wrapper td:nth-child(3),\n  .mz-table-wrapper td:nth-child(4),\n  .mz-table-wrapper td:last-child {\n    text-align: right;\n  }\n\n  .mz-table-wrapper tbody tr:nth-child(even) { background: #f3f4f6; }\n\n  .mz-table-wrapper tfoot td {\n    background: #eef2ff;\n    font-weight: 600;\n  }\n\n  .mz-disclaimer {\n    margin-top: 1.25rem;\n    font-size: 0.75rem;\n    color: #6b7280;\n    border-top: 1px solid #e5e7eb;\n    padding-top: 0.75rem;\n    text-align: center;\n    line-height: 1.3;\n  }\n\n  @media (max-width: 640px) {\n    .mz-electricity-card { padding: 1.25rem 1rem; }\n    .mz-title { font-size: 1.2rem; }\n  }\n<\/style>\n\n\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js@4.4.1\/dist\/chart.umd.min.js\"><\/script>\n\n<script>\n\/\/ Summer & winter tariffs\nconst TARIFFS = {\n  summer: {\n    block1: 2.066,\n    block2: 2.416,\n    block3: 3.228,\n    block4: 3.882\n  },\n  winter: {\n    block1: 2.70,\n    block2: 3.041,\n    block3: 4.069,\n    block4: 4.882\n  }\n};\n\nlet kwhChart = null;\n\n\/\/ Custom plugin for block shading\nconst blockShadingPlugin = {\n  id: 'blockShading',\n  beforeDatasetsDraw(chart, args, pluginOptions) {\n    const { ctx, chartArea, scales } = chart;\n    if (!chartArea) return;\n\n    const xScale = scales.x;\n    const { top, bottom } = chartArea;\n    const blocks = pluginOptions.blocks || [];\n\n    ctx.save();\n    blocks.forEach(block => {\n      if (block.to <= block.from) return;\n      const xStart = xScale.getPixelForValue(block.from);\n      const xEnd = xScale.getPixelForValue(block.to);\n      ctx.fillStyle = block.color;\n      ctx.fillRect(xStart, top, xEnd - xStart, bottom - top);\n    });\n    ctx.restore();\n  }\n};\n\nChart.register(blockShadingPlugin);\n\n\/\/ Breakdown per block\n\/\/ Block 1: 0\u201350\n\/\/ Block 2: 51\u2013350 (300 kWh range: 50\u2013350)\n\/\/ Block 3: 351\u2013600 (250 kWh range: 350\u2013600)\n\/\/ Block 4: 601+\nfunction calculateCostBreakdown(kwh, season) {\n  const t = TARIFFS[season] || TARIFFS.summer;\n  const usage = Math.max(0, kwh);\n\n  const b1Units = Math.max(0, Math.min(usage, 50));\n  const b2Units = Math.max(0, Math.min(usage, 350) - 50);\n  const b3Units = Math.max(0, Math.min(usage, 600) - 350);\n  const b4Units = Math.max(0, usage - 600);\n\n  const block1Cost = b1Units * t.block1;\n  const block2Cost = b2Units * t.block2;\n  const block3Cost = b3Units * t.block3;\n  const block4Cost = b4Units * t.block4;\n\n  const totalCost = block1Cost + block2Cost + block3Cost + block4Cost;\n  const totalUnits = b1Units + b2Units + b3Units + b4Units;\n  const avgCost = totalUnits > 0 ? (totalCost \/ totalUnits) : 0;\n\n  return {\n    totalCost,\n    totalUnits,\n    avgCost,\n    blocks: [\n      { name: 'Block 1', range: '0 \u2013 50 kWh',   units: b1Units, rate: t.block1, cost: block1Cost },\n      { name: 'Block 2', range: '51 \u2013 350 kWh', units: b2Units, rate: t.block2, cost: block2Cost },\n      { name: 'Block 3', range: '351 \u2013 600 kWh',units: b3Units, rate: t.block3, cost: block3Cost },\n      { name: 'Block 4', range: '601+ kWh',     units: b4Units, rate: t.block4, cost: block4Cost }\n    ]\n  };\n}\n\nfunction calculateCost(kwh, season) {\n  return calculateCostBreakdown(kwh, season).totalCost;\n}\n\nfunction mzCalcTariff() {\n  const usageEl = document.getElementById(\"kwh_input\");\n  const resultEl = document.getElementById(\"kwh_result\");\n  const seasonEl = document.getElementById(\"tariff_season\");\n\n  const U = parseFloat(usageEl.value);\n  const season = seasonEl.value;\n\n  if (isNaN(U) || U < 0) {\n    resultEl.textContent = \"Please enter a valid kWh value.\";\n    document.getElementById(\"kwh_table\").innerHTML = \"\";\n    return;\n  }\n\n  const breakdown = calculateCostBreakdown(U, season);\n  const totalCost = breakdown.totalCost;\n\n  const labelSeason = season.charAt(0).toUpperCase() + season.slice(1);\n  resultEl.textContent = `Estimated cost (${labelSeason}, ${U.toFixed(0)} kWh): R ${totalCost.toFixed(2)}`;\n\n  updateChart(U, season);\n  renderBreakdownTable(breakdown, U, season);\n}\n\nfunction updateChart(maxKwh, season) {\n  const points = [];\n  const max = Math.round(maxKwh);\n  const safeMax = Math.min(max, 2000);\n\n  let maxCost = 0;\n  for (let i = 0; i <= safeMax; i++) {\n    const c = calculateCost(i, season);\n    points.push({ x: i, y: c });\n    if (c > maxCost) maxCost = c;\n  }\n\n  const ctx = document.getElementById('kwh_chart').getContext('2d');\n  if (kwhChart) kwhChart.destroy();\n\n  const blocks = [];\n  const addBlock = (from, to, color) => {\n    const clampedFrom = Math.max(0, from);\n    const clampedTo = Math.min(safeMax, to);\n    if (clampedTo > clampedFrom) blocks.push({ from: clampedFrom, to: clampedTo, color });\n  };\n\n  addBlock(0,   50,  'rgba(16,185,129,0.08)'); \/\/ Block 1\n  addBlock(50,  350, 'rgba(59,130,246,0.07)'); \/\/ Block 2\n  addBlock(350, 600, 'rgba(234,179,8,0.08)');  \/\/ Block 3\n  addBlock(600, safeMax, 'rgba(248,113,113,0.07)'); \/\/ Block 4\n\n  const breakpointDatasets = [];\n  const addBreakpoint = (xPos, label, color) => {\n    if (xPos > safeMax) return;\n    breakpointDatasets.push({\n      label,\n      data: [\n        { x: xPos, y: 0 },\n        { x: xPos, y: maxCost }\n      ],\n      borderColor: color,\n      borderWidth: 1,\n      borderDash: [4, 4],\n      pointRadius: 0,\n      fill: false\n    });\n  };\n\n  addBreakpoint(50,  \"50 kWh\",  \"rgba(16,185,129,0.9)\");\n  addBreakpoint(350, \"350 kWh\", \"rgba(59,130,246,0.9)\");\n  addBreakpoint(600, \"600 kWh\", \"rgba(248,113,113,0.9)\");\n\n  const labelSeason = season.charAt(0).toUpperCase() + season.slice(1);\n\n  kwhChart = new Chart(ctx, {\n    type: 'line',\n    data: {\n      datasets: [\n        {\n          label: `Cost (R) \u2013 ${labelSeason}`,\n          data: points,\n          borderWidth: 2,\n          borderColor: '#1d4ed8',\n          tension: 0.18,\n          pointRadius: 0\n        },\n        ...breakpointDatasets\n      ]\n    },\n    options: {\n      responsive: true,\n      maintainAspectRatio: false,\n      parsing: false,\n      plugins: {\n        legend: { display: true },\n        tooltip: {\n          callbacks: {\n            label: (ctx) => `${ctx.parsed.x} kWh \u2192 R ${ctx.parsed.y.toFixed(2)}`\n          }\n        },\n        blockShading: { blocks }\n      },\n      scales: {\n        x: {\n          type: 'linear',\n          title: { display: true, text: 'Usage (kWh)' }\n        },\n        y: {\n          beginAtZero: true,\n          title: { display: true, text: 'Cost (R)' }\n        }\n      }\n    }\n  });\n}\n\nfunction renderBreakdownTable(breakdown, kwh, season) {\n  const container = document.getElementById(\"kwh_table\");\n  const niceSeason = season.charAt(0).toUpperCase() + season.slice(1);\n\n  let rowsHtml = \"\";\n  breakdown.blocks.forEach(b => {\n    rowsHtml += `\n      <tr${b.units <= 0 ? ' style=\"opacity:0.5;\"' : ''}>\n        <td>${b.name}<\/td>\n        <td>${b.range}<\/td>\n        <td>${b.units.toFixed(2)}<\/td>\n        <td>R ${b.rate.toFixed(3)}<\/td>\n        <td>R ${b.cost.toFixed(2)}<\/td>\n      <\/tr>\n    `;\n  });\n\n  const html = `\n    <h4>Cost breakdown \u2013 ${niceSeason}<\/h4>\n    <div class=\"mz-table-subtle\" style=\"margin-bottom:0.4rem;\">\n      Showing how your ${kwh.toFixed(0)} kWh is split across the blocks.\n    <\/div>\n    <div style=\"overflow-x:auto;\">\n      <table>\n        <thead>\n          <tr>\n            <th>Block<\/th>\n            <th>Range<\/th>\n            <th>kWh in block<\/th>\n            <th>Rate (R\/kWh)<\/th>\n            <th>Cost (R)<\/th>\n          <\/tr>\n        <\/thead>\n        <tbody>\n          ${rowsHtml}\n        <\/tbody>\n        <tfoot>\n          <tr>\n            <td colspan=\"2\">Totals<\/td>\n            <td>${breakdown.totalUnits.toFixed(2)}<\/td>\n            <td class=\"mz-table-subtle\">Avg R\/kWh<\/td>\n            <td>\n              R ${breakdown.totalCost.toFixed(2)}<br>\n              <span class=\"mz-table-subtle\">(R ${breakdown.avgCost.toFixed(3)} \/ kWh)<\/span>\n            <\/td>\n          <\/tr>\n        <\/tfoot>\n      <\/table>\n    <\/div>\n  `;\n\n  container.innerHTML = html;\n}\n<\/script>\n\n\n\n<div class=\"mz-electricity-card\">\n  <h3 class=\"mz-title\">BXC Support Contacts<\/h3>\n  <div class=\"mz-subtitle\">For electricity-related billing or metering queries<\/div>\n\n  <div class=\"mz-contact-table\">\n    <div class=\"mz-row\">\n      <div class=\"mz-label\">Reception<\/div>\n      <div class=\"mz-value\">\n        <a href=\"tel:0161006170\">016 100 6170<\/a>\n        <span class=\"mz-hours\">(Office Hours)<\/span>\n      <\/div>\n    <\/div>\n\n    <div class=\"mz-row\">\n      <div class=\"mz-label\">Call Centre<\/div>\n      <div class=\"mz-value\">\n        <a href=\"tel:0871472580\">087 147 2580<\/a>\n        <span class=\"mz-hours\">(24\/7)<\/span>\n      <\/div>\n    <\/div>\n\n    <div class=\"mz-row\">\n      <div class=\"mz-label\">Standby<\/div>\n      <div class=\"mz-value\">\n        <a href=\"tel:0636760397\">063 676 0397<\/a>\n        <span class=\"mz-hours\">(24\/7)<\/span>\n      <\/div>\n    <\/div>\n\n    <div class=\"mz-row\">\n      <div class=\"mz-label\">WhatsApp<\/div>\n      <div class=\"mz-value\">\n        <a href=\"https:\/\/wa.me\/27636760397\" target=\"_blank\">063 676 0397<\/a>\n        <span class=\"mz-hours\">(24\/7)<\/span>\n      <\/div>\n    <\/div>\n\n    <div class=\"mz-row\">\n      <div class=\"mz-label\">Email<\/div>\n      <div class=\"mz-value\">\n        <a href=\"mailto:admin@bxcsa.co.za\">admin@bxcsa.co.za<\/a>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<style>\n  .mz-contact-table {\n    margin-top: 0.8rem;\n    display: grid;\n    grid-template-columns: 1fr;\n    gap: 0.5rem 0;\n  }\n\n  @media (min-width: 520px) {\n    .mz-contact-table {\n      grid-template-columns: 180px 1fr;\n      align-items: center;\n    }\n    .mz-label {\n      text-align: right;\n      padding-right: 1rem;\n    }\n  }\n\n  .mz-row {\n    display: contents;\n  }\n\n  .mz-label {\n    font-weight: 600;\n    color: #1d4ed8;\n    font-size: 0.95rem;\n  }\n\n  .mz-value a {\n    color: #1d4ed8;\n    text-decoration: none;\n    font-size: 0.95rem;\n    font-weight: 500;\n  }\n\n  .mz-value a:hover {\n    text-decoration: underline;\n  }\n\n  .mz-hours {\n    margin-left: 6px;\n    font-size: 0.75rem;\n    color: #6b7280;\n  }\n<\/style>\n\n\n\n<div class=\"mz-disclaimer-card\">\n  <div class=\"mz-disclaimer-icon\">\u2139\ufe0f<\/div>\n  <div class=\"mz-disclaimer-text\">\n    This platform is privately maintained and does not represent, operate under,\n    or speak on behalf of the Emfuleni Local Municipality or BXC.\n    The information presented is unofficial and provided on a best-effort basis\n    for general community awareness.\n  <\/div>\n<\/div>\n\n<style>\n  .mz-disclaimer-card {\n    max-width: 760px;\n    margin: 1.25rem auto;\n    padding: 1rem 1.25rem;\n    border-radius: 12px;\n    background: #e0f2fe;\n    border: 1px solid #bae6fd;\n    display: flex;\n    gap: 0.75rem;\n    align-items: flex-start;\n    color: #0c4a6e;\n    font-family: system-ui, sans-serif;\n    font-size: 0.9rem;\n    box-shadow: 0 2px 8px rgba(8, 145, 178, 0.08);\n  }\n\n  .mz-disclaimer-icon {\n    font-size: 1.4rem;\n    line-height: 1;\n    flex-shrink: 0;\n    margin-top: 1px;\n  }\n\n  .mz-disclaimer-text {\n    line-height: 1.35;\n  }\n\n  @media (max-width: 640px) {\n    .mz-disclaimer-card {\n      padding: 0.85rem 1rem;\n      font-size: 0.88rem;\n    }\n    .mz-disclaimer-icon {\n      font-size: 1.25rem;\n    }\n  }\n<\/style>\n\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Electricity Block Tariff Calculator Applicable to 2024\/2025 Domestic Supply Tariffs Tariff season SummerWinter Monthly usage (kWh) Calculate Information based on tariffs provided by BXC. We accept no responsibility or liability for errors, omissions, or usage outcomes. BXC Support Contacts For electricity-related billing or metering queries Reception 016 100 6170 (Office Hours) Call Centre 087 147 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-8","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/emfulenihub.co.za\/index.php?rest_route=\/wp\/v2\/pages\/8","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/emfulenihub.co.za\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/emfulenihub.co.za\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/emfulenihub.co.za\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/emfulenihub.co.za\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=8"}],"version-history":[{"count":10,"href":"https:\/\/emfulenihub.co.za\/index.php?rest_route=\/wp\/v2\/pages\/8\/revisions"}],"predecessor-version":[{"id":38,"href":"https:\/\/emfulenihub.co.za\/index.php?rest_route=\/wp\/v2\/pages\/8\/revisions\/38"}],"wp:attachment":[{"href":"https:\/\/emfulenihub.co.za\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=8"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}