{"id":25,"date":"2026-07-30T14:00:30","date_gmt":"2026-07-30T14:00:30","guid":{"rendered":"https:\/\/mahall.org\/?page_id=25"},"modified":"2026-07-30T14:02:14","modified_gmt":"2026-07-30T14:02:14","slug":"dashboard-v05","status":"publish","type":"page","link":"https:\/\/mahall.org\/index.php\/dashboard-v05\/","title":{"rendered":"DashBoard"},"content":{"rendered":"\n<!--\n  MAHALL \u2014 owner dashboard (v0.5)\n  ------------------------------------------------------------------\n  HOW TO USE\n  Paste into a WordPress page, e.g. mahall.org\/owner\/dashboard\n  Protect this page with a \"logged-in + role=venue_owner\" check in\n  your theme's template (or use a membership plugin) so it is not\n  publicly accessible.\n\n  WHAT'S REAL vs DEMO\n  - All UI, filtering, tab switching, lead status changes, and the\n    AI reply-draft button work entirely in the browser with mock data.\n  - Real data arrives via three REST calls (all fall back to mock):\n      GET \/wp-json\/mahall\/v1\/owner\/stats\n      GET \/wp-json\/mahall\/v1\/owner\/leads\n      GET \/wp-json\/mahall\/v1\/owner\/listing\n  - The AI \"Draft reply\" button calls \/wp-json\/mahall\/v1\/ai-concierge\n    (the same proxy from v0.1) with the lead context to suggest a\n    personalised first reply for the owner \u2014 no extra backend needed.\n  - Lead status changes (Accept \/ Decline \/ Archive) POST to\n      \/wp-json\/mahall\/v1\/owner\/lead-action\n    and fall back gracefully if not yet wired.\n------------------------------------------------------------------- -->\n<style>\n@import url('https:\/\/fonts.googleapis.com\/css2?family=Fraunces:ital,opsz,wght@0,9..144,300..700;1,9..144,400..600&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap');\n\n#mahall-dash{\n  --bg:#16130F; --bg-raised:#1E1A14; --bg-card:#241F18;\n  --ink:#F3ECE0; --ink-soft:#BBAE99; --ink-faint:#7A7163;\n  --gold:#D98E33; --gold-soft:#E8B978;\n  --teal:#2F6F62; --teal-soft:#5C988B;\n  --terracotta:#B5532D;\n  --line:rgba(243,236,224,0.12);\n  --radius:14px;\n  font-family:'Inter',sans-serif; background:var(--bg); color:var(--ink);\n  -webkit-font-smoothing:antialiased; display:flex; min-height:100vh;\n}\n#mahall-dash *{box-sizing:border-box; margin:0; padding:0;}\n#mahall-dash a{color:inherit; text-decoration:none;}\n#mahall-dash h1,#mahall-dash h2,#mahall-dash h3{font-family:'Fraunces',serif; font-weight:500; color:var(--ink); line-height:1.15;}\n#mahall-dash p{color:var(--ink-soft); line-height:1.6;}\n#mahall-dash .eyebrow{font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.12em; text-transform:uppercase; color:var(--gold-soft);}\n#mahall-dash .star{position:relative; width:14px; height:14px; flex:none;}\n#mahall-dash .star span{position:absolute; inset:0; border:1.4px solid var(--gold);}\n#mahall-dash .star span:last-child{transform:rotate(45deg);}\n#mahall-dash .btn{display:inline-flex; align-items:center; gap:7px; font-weight:500; font-size:13px; padding:9px 18px; border-radius:999px; border:1px solid var(--line); cursor:pointer; background:transparent; color:var(--ink); transition:border-color .2s, transform .15s, background .2s;}\n#mahall-dash .btn:hover{border-color:var(--gold-soft); transform:translateY(-1px);}\n#mahall-dash .btn-solid{background:var(--gold); border-color:var(--gold); color:#1A1305;}\n#mahall-dash .btn-solid:hover{background:var(--gold-soft);}\n#mahall-dash .btn-sm{padding:6px 13px; font-size:12px;}\n#mahall-dash .btn-teal{background:var(--teal); border-color:var(--teal); color:var(--ink);}\n#mahall-dash .btn-teal:hover{background:var(--teal-soft);}\n#mahall-dash .btn-danger{border-color:var(--terracotta); color:var(--terracotta);}\n#mahall-dash .btn-danger:hover{background:var(--terracotta); color:var(--ink);}\n\n\/* sidebar *\/\n#mahall-dash .sidebar{\n  width:220px; flex:none; border-right:1px solid var(--line);\n  background:var(--bg-raised); display:flex; flex-direction:column;\n  position:sticky; top:0; height:100vh; overflow-y:auto;\n}\n#mahall-dash .sidebar-logo{padding:20px 18px; border-bottom:1px solid var(--line); display:flex; align-items:center; gap:8px; font-family:'Fraunces',serif; font-size:17px;}\n#mahall-dash .sidebar-nav{padding:12px 8px; flex:1;}\n#mahall-dash .nav-label{font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-faint); padding:10px 10px 6px;}\n#mahall-dash .nav-item{display:flex; align-items:center; gap:10px; padding:10px 12px; border-radius:10px; font-size:13px; color:var(--ink-soft); cursor:pointer; margin-bottom:2px; transition:background .15s, color .15s;}\n#mahall-dash .nav-item:hover{background:var(--bg-card); color:var(--ink);}\n#mahall-dash .nav-item.active{background:rgba(217,142,51,.12); color:var(--gold-soft);}\n#mahall-dash .nav-item .badge{margin-left:auto; background:var(--gold); color:#1A1305; font-size:10px; font-family:'JetBrains Mono',monospace; padding:2px 7px; border-radius:999px;}\n#mahall-dash .sidebar-footer{padding:14px 18px; border-top:1px solid var(--line); font-size:12px; color:var(--ink-faint);}\n\n\/* main *\/\n#mahall-dash .main{flex:1; overflow-x:hidden;}\n#mahall-dash .topbar{display:flex; align-items:center; justify-content:space-between; padding:18px 28px; border-bottom:1px solid var(--line); position:sticky; top:0; background:rgba(22,19,15,.9); backdrop-filter:blur(10px); z-index:10;}\n#mahall-dash .topbar h2{font-size:18px;}\n#mahall-dash .content{padding:28px;}\n\n\/* stat cards *\/\n#mahall-dash .stat-grid{display:grid; grid-template-columns:repeat(4,1fr); gap:14px; margin-bottom:28px;}\n#mahall-dash .stat-card{background:var(--bg-raised); border:1px solid var(--line); border-radius:var(--radius); padding:18px 20px;}\n#mahall-dash .stat-card .label{font-size:11px; font-family:'JetBrains Mono',monospace; text-transform:uppercase; letter-spacing:.08em; color:var(--ink-faint); margin-bottom:10px;}\n#mahall-dash .stat-card .value{font-family:'Fraunces',serif; font-size:28px; color:var(--gold-soft); margin-bottom:4px;}\n#mahall-dash .stat-card .delta{font-size:12px; color:var(--ink-faint);}\n#mahall-dash .stat-card .delta.up{color:var(--teal-soft);}\n#mahall-dash .stat-card .delta.down{color:var(--terracotta);}\n\n\/* mini bar chart *\/\n#mahall-dash .chart-row{display:flex; align-items:flex-end; gap:5px; height:40px; margin-top:10px;}\n#mahall-dash .bar{flex:1; border-radius:3px 3px 0 0; background:var(--gold); opacity:.35; transition:opacity .2s;}\n#mahall-dash .bar.hi{opacity:.85;}\n#mahall-dash .bar:hover{opacity:1;}\n\n\/* tabs *\/\n#mahall-dash .tabs{display:flex; gap:6px; margin-bottom:20px;}\n#mahall-dash .tab{font-size:13px; font-family:'JetBrains Mono',monospace; padding:8px 16px; border-radius:999px; border:1px solid var(--line); color:var(--ink-soft); cursor:pointer; background:transparent;}\n#mahall-dash .tab.active{border-color:var(--gold); color:var(--gold-soft);}\n\n\/* leads *\/\n#mahall-dash .lead-card{background:var(--bg-raised); border:1px solid var(--line); border-radius:var(--radius); margin-bottom:12px; overflow:hidden; transition:border-color .2s;}\n#mahall-dash .lead-card:hover{border-color:rgba(243,236,224,.25);}\n#mahall-dash .lead-card.expanded .lead-body{display:block;}\n#mahall-dash .lead-head{display:flex; align-items:center; gap:14px; padding:14px 18px; cursor:pointer;}\n#mahall-dash .lead-avatar{width:36px; height:36px; border-radius:50%; background:var(--teal); flex:none; display:flex; align-items:center; justify-content:center; font-family:'Fraunces',serif; font-size:14px; color:var(--ink);}\n#mahall-dash .lead-meta{flex:1;}\n#mahall-dash .lead-meta b{display:block; font-size:14px; color:var(--ink);}\n#mahall-dash .lead-meta span{font-size:12px; color:var(--ink-faint);}\n#mahall-dash .lead-status{font-size:11px; font-family:'JetBrains Mono',monospace; padding:3px 9px; border-radius:999px; border:1px solid;}\n#mahall-dash .lead-status.new{border-color:var(--gold); color:var(--gold-soft);}\n#mahall-dash .lead-status.accepted{border-color:var(--teal-soft); color:var(--teal-soft);}\n#mahall-dash .lead-status.declined{border-color:var(--terracotta); color:var(--terracotta);}\n#mahall-dash .lead-status.archived{border-color:var(--ink-faint); color:var(--ink-faint);}\n#mahall-dash .lead-body{display:none; padding:0 18px 16px; border-top:1px solid var(--line);}\n#mahall-dash .lead-detail-grid{display:grid; grid-template-columns:repeat(4,1fr); gap:10px; margin:14px 0;}\n#mahall-dash .ld{font-size:12px;}\n#mahall-dash .ld span{display:block; color:var(--ink-faint); margin-bottom:3px;}\n#mahall-dash .ld b{color:var(--ink);}\n#mahall-dash .lead-msg{background:var(--bg-card); border-radius:10px; padding:12px 14px; font-size:13px; color:var(--ink-soft); margin-bottom:14px; font-style:italic;}\n#mahall-dash .lead-actions{display:flex; gap:8px; flex-wrap:wrap; align-items:center;}\n#mahall-dash .ai-draft-area{margin-top:14px; display:none;}\n#mahall-dash .ai-draft-area.show{display:block;}\n#mahall-dash .ai-draft-area textarea{width:100%; background:var(--bg); border:1px solid var(--line); border-radius:10px; padding:12px; color:var(--ink); font-size:13px; font-family:'Inter',sans-serif; outline:none; resize:vertical;}\n#mahall-dash .ai-draft-area textarea:focus{border-color:var(--gold-soft);}\n#mahall-dash .ai-thinking{font-size:12px; color:var(--gold-soft); display:none; font-family:'JetBrains Mono',monospace;}\n#mahall-dash .ai-thinking.show{display:block;}\n\n\/* listing status card *\/\n#mahall-dash .listing-card{background:var(--bg-raised); border:1px solid var(--line); border-radius:var(--radius); padding:20px; display:flex; gap:18px; align-items:flex-start; margin-bottom:28px;}\n#mahall-dash .listing-thumb{width:90px; height:72px; border-radius:10px; border:1px solid var(--line); flex:none; background:repeating-linear-gradient(45deg, rgba(217,142,51,.10) 0 10px, rgba(47,111,98,.10) 10px 20px);}\n#mahall-dash .listing-info{flex:1;}\n#mahall-dash .listing-info h3{font-size:16px; margin-bottom:4px;}\n#mahall-dash .listing-info p{font-size:13px; margin:0;}\n#mahall-dash .listing-badges{display:flex; gap:8px; margin-top:10px; flex-wrap:wrap;}\n#mahall-dash .lbadge{font-size:11px; font-family:'JetBrains Mono',monospace; padding:3px 10px; border-radius:999px; border:1px solid;}\n#mahall-dash .lbadge.live{border-color:var(--teal-soft); color:var(--teal-soft);}\n#mahall-dash .lbadge.featured{border-color:var(--gold); color:var(--gold-soft);}\n#mahall-dash .lbadge.pending{border-color:#E8B978; color:#E8B978;}\n\n\/* completion meter *\/\n#mahall-dash .completion{margin-top:18px; margin-bottom:28px; background:var(--bg-raised); border:1px solid var(--line); border-radius:var(--radius); padding:18px 20px;}\n#mahall-dash .completion h3{font-size:14px; margin-bottom:12px;}\n#mahall-dash .comp-bar-bg{height:6px; background:var(--line); border-radius:6px; overflow:hidden; margin-bottom:12px;}\n#mahall-dash .comp-bar{height:100%; border-radius:6px; background:linear-gradient(90deg, var(--teal), var(--gold)); transition:width .6s;}\n#mahall-dash .comp-items{display:grid; grid-template-columns:repeat(2,1fr); gap:8px;}\n#mahall-dash .comp-item{display:flex; align-items:center; gap:8px; font-size:12px; color:var(--ink-soft);}\n#mahall-dash .comp-item .dot{width:8px; height:8px; border-radius:50%; flex:none;}\n#mahall-dash .comp-item .dot.done{background:var(--teal-soft);}\n#mahall-dash .comp-item .dot.miss{background:var(--line);}\n\n\/* empty state *\/\n#mahall-dash .empty{text-align:center; padding:48px 20px; color:var(--ink-faint); font-size:13px;}\n#mahall-dash .empty .ic{font-size:32px; display:block; margin-bottom:12px; opacity:.4;}\n\n@media(max-width:860px){\n  #mahall-dash{flex-direction:column;}\n  #mahall-dash .sidebar{width:100%; height:auto; position:static; flex-direction:row; overflow-x:auto;}\n  #mahall-dash .sidebar-nav{display:flex; padding:8px; flex-direction:row;}\n  #mahall-dash .nav-label{display:none;}\n  #mahall-dash .sidebar-footer{display:none;}\n  #mahall-dash .stat-grid{grid-template-columns:1fr 1fr;}\n  #mahall-dash .lead-detail-grid{grid-template-columns:1fr 1fr;}\n}\n@media(max-width:560px){\n  #mahall-dash .stat-grid{grid-template-columns:1fr;}\n  #mahall-dash .content{padding:16px;}\n}\n<\/style>\n\n<div id=\"mahall-dash\">\n\n  <aside class=\"sidebar\">\n    <div class=\"sidebar-logo\"><span class=\"star\"><span><\/span><span><\/span><\/span> Mahall<\/div>\n    <nav class=\"sidebar-nav\">\n      <div class=\"nav-label\">Owner<\/div>\n      <div class=\"nav-item active\" data-view=\"overview\">&#128202; Overview<\/div>\n      <div class=\"nav-item\" data-view=\"leads\">&#9993; Leads <span class=\"badge\" id=\"sidebar-badge\">3<\/span><\/div>\n      <div class=\"nav-item\" data-view=\"listing\">&#127968; My listing<\/div>\n      <div class=\"nav-label\">Account<\/div>\n      <div class=\"nav-item\" data-view=\"billing\">&#128179; Plan &amp; billing<\/div>\n      <div class=\"nav-item\" data-view=\"settings\">&#9881; Settings<\/div>\n    <\/nav>\n    <div class=\"sidebar-footer\">Signed in as<br><b style=\"color:var(--ink)\">Amina K.<\/b><\/div>\n  <\/aside>\n\n  <div class=\"main\">\n    <div class=\"topbar\">\n      <h2 id=\"view-title\">Overview<\/h2>\n      <div style=\"display:flex;gap:10px;\">\n        <button class=\"btn btn-sm\" onclick=\"document.querySelector('[data-view=leads]').click()\">&#9993; Leads<\/button>\n        <a class=\"btn btn-sm btn-solid\" href=\"\/list-your-venue\">Edit listing &#10148;<\/a>\n      <\/div>\n    <\/div>\n\n    <div class=\"content\">\n\n      <!-- ===== OVERVIEW ===== -->\n      <div class=\"view active\" data-pane=\"overview\">\n        <span class=\"eyebrow\" style=\"margin-bottom:12px;display:block;\">Last 30 days<\/span>\n        <div class=\"stat-grid\" id=\"stat-grid\"><\/div>\n\n        <div class=\"listing-card\">\n          <div class=\"listing-thumb\"><\/div>\n          <div class=\"listing-info\">\n            <h3>Riad Zahra<\/h3>\n            <p>Medina, Marrakech &middot; Heritage &amp; cultural &middot; 80 guests<\/p>\n            <div class=\"listing-badges\">\n              <span class=\"lbadge live\">&#9679; Live<\/span>\n              <span class=\"lbadge featured\">&#10022; Featured<\/span>\n            <\/div>\n          <\/div>\n          <button class=\"btn btn-sm\" onclick=\"document.querySelector('[data-view=listing]').click()\">View listing &#8594;<\/button>\n        <\/div>\n\n        <h3 style=\"font-size:16px; margin-bottom:14px;\">Recent leads<\/h3>\n        <div id=\"recent-leads-list\"><\/div>\n      <\/div>\n\n      <!-- ===== LEADS ===== -->\n      <div class=\"view\" data-pane=\"leads\">\n        <div class=\"tabs\" id=\"lead-tabs\">\n          <button class=\"tab active\" data-ltab=\"all\">All<\/button>\n          <button class=\"tab\" data-ltab=\"new\">New<\/button>\n          <button class=\"tab\" data-ltab=\"accepted\">Accepted<\/button>\n          <button class=\"tab\" data-ltab=\"declined\">Declined<\/button>\n          <button class=\"tab\" data-ltab=\"archived\">Archived<\/button>\n        <\/div>\n        <div id=\"leads-list\"><\/div>\n      <\/div>\n\n      <!-- ===== LISTING ===== -->\n      <div class=\"view\" data-pane=\"listing\">\n        <div class=\"listing-card\">\n          <div class=\"listing-thumb\"><\/div>\n          <div class=\"listing-info\">\n            <h3>Riad Zahra<\/h3>\n            <p>Medina, Marrakech &middot; Heritage &amp; cultural<\/p>\n            <div class=\"listing-badges\">\n              <span class=\"lbadge live\">&#9679; Live<\/span>\n              <span class=\"lbadge featured\">&#10022; Featured \u2014 499 MAD\/mo<\/span>\n            <\/div>\n          <\/div>\n          <a class=\"btn btn-sm btn-solid\" href=\"\/list-your-venue\">Edit listing &#10148;<\/a>\n        <\/div>\n\n        <div class=\"completion\" id=\"completion-card\"><\/div>\n\n        <div style=\"background:var(--bg-raised);border:1px solid var(--line);border-radius:var(--radius);padding:20px;\">\n          <h3 style=\"font-size:15px;margin-bottom:14px;\">Quick stats<\/h3>\n          <div class=\"stat-grid\" id=\"listing-stats\" style=\"margin-bottom:0;\"><\/div>\n        <\/div>\n      <\/div>\n\n      <!-- ===== BILLING ===== -->\n      <div class=\"view\" data-pane=\"billing\">\n        <div style=\"background:var(--bg-raised);border:1px solid var(--line);border-radius:var(--radius);padding:24px;margin-bottom:18px;\">\n          <span class=\"eyebrow\" style=\"display:block;margin-bottom:8px;\">Current plan<\/span>\n          <h3 style=\"font-size:22px;margin-bottom:4px;\">Featured <span style=\"font-family:'JetBrains Mono',monospace;font-size:14px;color:var(--gold-soft)\">499 MAD\/mo<\/span><\/h3>\n          <p style=\"font-size:13px;\">Next renewal: 1 August 2026<\/p>\n          <div style=\"display:flex;gap:10px;margin-top:16px;\">\n            <button class=\"btn btn-solid btn-sm\">Upgrade to Premium<\/button>\n            <button class=\"btn btn-sm btn-danger\">Cancel plan<\/button>\n          <\/div>\n        <\/div>\n        <div style=\"background:var(--bg-raised);border:1px solid var(--line);border-radius:var(--radius);padding:20px;\">\n          <h3 style=\"font-size:15px;margin-bottom:14px;\">Invoice history<\/h3>\n          <table style=\"width:100%;font-size:13px;border-collapse:collapse;\">\n            <thead><tr style=\"color:var(--ink-faint);text-align:left;font-size:11px;font-family:'JetBrains Mono',monospace;\">\n              <th style=\"padding:6px 0;\">DATE<\/th><th>PLAN<\/th><th>AMOUNT<\/th><th>STATUS<\/th>\n            <\/tr><\/thead>\n            <tbody id=\"invoice-tbody\"><\/tbody>\n          <\/table>\n        <\/div>\n      <\/div>\n\n      <!-- ===== SETTINGS ===== -->\n      <div class=\"view\" data-pane=\"settings\">\n        <div style=\"background:var(--bg-raised);border:1px solid var(--line);border-radius:var(--radius);padding:24px;max-width:480px;\">\n          <h3 style=\"font-size:16px;margin-bottom:18px;\">Account settings<\/h3>\n          <div style=\"display:flex;flex-direction:column;gap:12px;\">\n            <div class=\"field\" style=\"display:flex;flex-direction:column;gap:6px;\">\n              <label style=\"font-size:12px;color:var(--ink-faint);\">Display name<\/label>\n              <input value=\"Amina K.\" style=\"background:var(--bg);border:1px solid var(--line);border-radius:8px;padding:10px 12px;color:var(--ink);font-size:14px;outline:none;\">\n            <\/div>\n            <div class=\"field\" style=\"display:flex;flex-direction:column;gap:6px;\">\n              <label style=\"font-size:12px;color:var(--ink-faint);\">Email<\/label>\n              <input value=\"amina@riadzahra.ma\" style=\"background:var(--bg);border:1px solid var(--line);border-radius:8px;padding:10px 12px;color:var(--ink);font-size:14px;outline:none;\">\n            <\/div>\n            <div class=\"field\" style=\"display:flex;flex-direction:column;gap:6px;\">\n              <label style=\"font-size:12px;color:var(--ink-faint);\">WhatsApp \/ phone<\/label>\n              <input value=\"+212 6...\" style=\"background:var(--bg);border:1px solid var(--line);border-radius:8px;padding:10px 12px;color:var(--ink);font-size:14px;outline:none;\">\n            <\/div>\n            <div style=\"display:flex;align-items:center;justify-content:space-between;padding:12px 0;border-top:1px solid var(--line);\">\n              <span style=\"font-size:13px;\">Email me new leads<\/span>\n              <input type=\"checkbox\" checked style=\"accent-color:var(--gold);width:16px;height:16px;\">\n            <\/div>\n            <div style=\"display:flex;align-items:center;justify-content:space-between;padding:12px 0;border-bottom:1px solid var(--line);\">\n              <span style=\"font-size:13px;\">WhatsApp notifications<\/span>\n              <input type=\"checkbox\" style=\"accent-color:var(--gold);width:16px;height:16px;\">\n            <\/div>\n            <button class=\"btn btn-solid\" style=\"align-self:flex-start;margin-top:6px;\">Save changes<\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n\n    <\/div><!-- \/content -->\n  <\/div><!-- \/main -->\n<\/div>\n\n<script>\n(function(){\n\n  \/* ---- mock data (replaced by REST calls once wired) ---- *\/\n  var MOCK_STATS = {\n    views:142, viewsDelta:'+18%',\n    leads:9, leadsDelta:'+3 this month',\n    inquiryRate:'6.3%', inquiryRateDelta:'up from 4.1%',\n    responseTime:'2.4h', responseTimeDelta:'last 30 days'\n  };\n\n  var MOCK_LEADS = [\n    {id:1, name:'Sarah M.', initials:'SM', event:'Wedding', date:'12 Oct 2026', guests:95, city:'Marrakech', msg:'We love the rooftop terrace \u2014 would it work for an evening ceremony followed by dinner for 90\u201395 guests?', status:'new', received:'2 hours ago'},\n    {id:2, name:'Karim A.', initials:'KA', event:'Corporate dinner', date:'8 Sep 2026', guests:40, city:'Marrakech', msg:'Looking for a private venue for an executive dinner, approx 40 people, need A\/V setup and catering option.', status:'new', received:'Yesterday'},\n    {id:3, name:'Lumi\u00e8re Events', initials:'LE', event:'Brand activation', date:'25 Nov 2026', guests:150, city:'Marrakech', msg:'We represent a luxury brand looking to shoot a campaign in a traditional riad environment. Flexible on dates Nov\/Dec.', status:'new', received:'3 days ago'},\n    {id:4, name:'Nadia B.', initials:'NB', event:'Birthday', date:'5 Aug 2026', guests:30, city:'Marrakech', msg:'Planning a 30th birthday dinner for about 30 guests, would love to use the courtyard space.', status:'accepted', received:'1 week ago'},\n    {id:5, name:'Atlas Corp', initials:'AC', event:'Conference', date:'18 Jul 2026', guests:200, city:'Marrakech', msg:'Capacity may exceed our limit but worth checking if overflow can be arranged.', status:'declined', received:'2 weeks ago'},\n    {id:6, name:'Omar T.', initials:'OT', event:'Engagement party', date:'3 Aug 2026', guests:55, city:'Marrakech', msg:'Interested in courtyard for evening engagement celebration.', status:'archived', received:'3 weeks ago'}\n  ];\n\n  var MOCK_COMPLETION = [\n    {label:'Venue name & description', done:true},\n    {label:'Category & location', done:true},\n    {label:'Capacity & pricing', done:true},\n    {label:'At least 6 photos', done:true},\n    {label:'Video tour', done:false},\n    {label:'3D \/ 360\u00b0 tour', done:false},\n    {label:'Amenities list', done:true},\n    {label:'WhatsApp \/ contact set', done:true}\n  ];\n\n  var INVOICES = [\n    {date:'1 Jul 2026', plan:'Featured', amount:'499 MAD', status:'Paid'},\n    {date:'1 Jun 2026', plan:'Featured', amount:'499 MAD', status:'Paid'},\n    {date:'1 May 2026', plan:'Free', amount:'0 MAD', status:'\u2014'}\n  ];\n\n  \/* ---- view routing ---- *\/\n  var currentView = 'overview';\n  document.querySelectorAll('.nav-item').forEach(function(item){\n    item.addEventListener('click', function(){\n      var view = this.getAttribute('data-view');\n      document.querySelectorAll('.nav-item').forEach(function(n){ n.classList.remove('active'); });\n      this.classList.add('active');\n      document.querySelectorAll('.view').forEach(function(v){ v.classList.toggle('active', v.getAttribute('data-pane')===view); });\n      var titles = {overview:'Overview', leads:'Leads inbox', listing:'My listing', billing:'Plan & billing', settings:'Settings'};\n      document.getElementById('view-title').textContent = titles[view] || view;\n      currentView = view;\n    });\n  });\n  document.querySelectorAll('.view').forEach(function(v){ v.style.display='none'; });\n  document.querySelector('.view[data-pane=\"overview\"]').style.display='block';\n  document.querySelectorAll('.view').forEach(function(v){\n    v.classList.toggle('active', v.getAttribute('data-pane')==='overview');\n  });\n  \/* show only active view *\/\n  document.querySelectorAll('.view').forEach(function(v){\n    Object.defineProperty(v,'_active',{get:function(){return v.classList.contains('active');}});\n  });\n  var styleTag = document.createElement('style');\n  styleTag.textContent = '#mahall-dash .view{display:none;} #mahall-dash .view.active{display:block;}';\n  document.head.appendChild(styleTag);\n\n  \/* ---- stats ---- *\/\n  function renderStats(data, containerId, bars){\n    var items = [\n      {label:'Listing views', value:data.views, delta:data.viewsDelta, up:true, barData:[30,45,38,60,55,72,80,65,90,100,88,95,110,142]},\n      {label:'Total leads', value:data.leads, delta:data.leadsDelta, up:true},\n      {label:'Inquiry rate', value:data.inquiryRate, delta:data.inquiryRateDelta, up:true},\n      {label:'Avg response time', value:data.responseTime, delta:data.responseTimeDelta, up:false}\n    ];\n    document.getElementById(containerId).innerHTML = items.map(function(it,i){\n      var barHtml = (bars && it.barData) ? '<div class=\"chart-row\">'+it.barData.map(function(v,j){\n        var h = Math.round((v\/Math.max.apply(null,it.barData))*36);\n        return '<div class=\"bar'+(j===it.barData.length-1?' hi':'')+'\" style=\"height:'+h+'px\" title=\"'+v+'\"><\/div>';\n      }).join('')+'<\/div>' : '';\n      return '<div class=\"stat-card\">'+\n        '<div class=\"label\">'+it.label+'<\/div>'+\n        '<div class=\"value\">'+it.value+'<\/div>'+\n        '<div class=\"delta '+(it.up?'up':'')+'\">'+it.delta+'<\/div>'+\n        barHtml+'<\/div>';\n    }).join('');\n  }\n\n  \/* ---- leads ---- *\/\n  var leadFilter = 'all';\n  function renderLeads(containerId, limit){\n    var list = MOCK_LEADS.filter(function(l){ return leadFilter==='all' || l.status===leadFilter; });\n    if(limit) list = list.slice(0,limit);\n    var el = document.getElementById(containerId);\n    if(!list.length){\n      el.innerHTML = '<div class=\"empty\"><span class=\"ic\">&#9993;<\/span>No leads in this category yet.<\/div>'; return;\n    }\n    el.innerHTML = list.map(function(lead){\n      return '<div class=\"lead-card\" data-id=\"'+lead.id+'\">'+\n        '<div class=\"lead-head\">'+\n        '<div class=\"lead-avatar\">'+lead.initials+'<\/div>'+\n        '<div class=\"lead-meta\"><b>'+lead.name+'<\/b><span>'+lead.event+' &middot; '+lead.received+'<\/span><\/div>'+\n        '<span class=\"lead-status '+lead.status+'\">'+lead.status.charAt(0).toUpperCase()+lead.status.slice(1)+'<\/span>'+\n        '<\/div>'+\n        '<div class=\"lead-body\">'+\n        '<div class=\"lead-detail-grid\">'+\n        '<div class=\"ld\"><span>Event type<\/span><b>'+lead.event+'<\/b><\/div>'+\n        '<div class=\"ld\"><span>Date<\/span><b>'+lead.date+'<\/b><\/div>'+\n        '<div class=\"ld\"><span>Guests<\/span><b>'+lead.guests+'<\/b><\/div>'+\n        '<div class=\"ld\"><span>City<\/span><b>'+lead.city+'<\/b><\/div>'+\n        '<\/div>'+\n        '<div class=\"lead-msg\">\"'+lead.msg+'\"<\/div>'+\n        '<div class=\"lead-actions\">'+\n        (lead.status==='new'?'<button class=\"btn btn-sm btn-teal\" data-act=\"accepted\">&#10003; Accept<\/button><button class=\"btn btn-sm btn-danger\" data-act=\"declined\">&#10005; Decline<\/button>':'') +\n        '<button class=\"btn btn-sm\" data-act=\"ai-draft\">&#10022; AI draft reply<\/button>'+\n        (lead.status!=='archived'?'<button class=\"btn btn-sm\" data-act=\"archived\" style=\"margin-left:auto\">Archive<\/button>':'')+\n        '<\/div>'+\n        '<div class=\"ai-thinking\" id=\"thinking-'+lead.id+'\">Drafting reply...<\/div>'+\n        '<div class=\"ai-draft-area\" id=\"draft-'+lead.id+'\">'+\n        '<textarea rows=\"5\" placeholder=\"AI-drafted reply will appear here...\"><\/textarea>'+\n        '<div style=\"display:flex;gap:8px;margin-top:8px;\"><button class=\"btn btn-sm btn-solid\">Copy reply<\/button><button class=\"btn btn-sm\">Discard<\/button><\/div>'+\n        '<\/div>'+\n        '<\/div>'+\n        '<\/div>';\n    }).join('');\n    wireLeadActions(containerId);\n  }\n\n  function wireLeadActions(containerId){\n    var el = document.getElementById(containerId);\n    el.addEventListener('click', async function(e){\n      var card = e.target.closest('.lead-card');\n      if(!card) return;\n      var id = parseInt(card.getAttribute('data-id'));\n      var lead = MOCK_LEADS.find(function(l){ return l.id===id; });\n\n      \/* expand\/collapse *\/\n      if(e.target.closest('.lead-head') && !e.target.closest('button')){\n        card.classList.toggle('expanded'); return;\n      }\n\n      var act = e.target.closest('[data-act]');\n      if(!act) return;\n      var action = act.getAttribute('data-act');\n\n      if(action==='ai-draft'){\n        var thinking = document.getElementById('thinking-'+id);\n        var draftArea = document.getElementById('draft-'+id);\n        var textarea = draftArea.querySelector('textarea');\n        thinking.classList.add('show');\n        draftArea.classList.remove('show');\n        var prompt = 'You are helping a Moroccan riad venue owner (Riad Zahra, Marrakech) draft a warm, professional reply to a venue inquiry. The inquiry is: Event type: '+lead.event+'. Date: '+lead.date+'. Guests: '+lead.guests+'. Message from client: \"'+lead.msg+'\". Write a concise, friendly reply (3-4 sentences) acknowledging their request, confirming availability interest, and inviting them to discuss further. Sign off as Amina from Riad Zahra.';\n        try{\n          var res = await fetch('\/wp-json\/mahall\/v1\/ai-concierge',{\n            method:'POST', headers:{'Content-Type':'application\/json'}, body:JSON.stringify({message:prompt})\n          });\n          var data = await res.json();\n          textarea.value = data.reply || '';\n        }catch(err){\n          \/* Scripted fallback when proxy isn't wired yet *\/\n          textarea.value = 'Dear '+lead.name.split(' ')[0]+',\\n\\nThank you so much for your inquiry about Riad Zahra \u2014 your '+lead.event.toLowerCase()+' sounds wonderful and we would love to host you. We can comfortably accommodate '+lead.guests+' guests and the '+new Date(lead.date).toLocaleDateString('en-GB',{month:'long',day:'numeric'})+' date looks promising on our end.\\n\\nCould we arrange a quick call this week to discuss the details further? Looking forward to hearing from you.\\n\\nWarm regards,\\nAmina \u2014 Riad Zahra';\n        }\n        thinking.classList.remove('show');\n        draftArea.classList.add('show');\n\n        \/* copy button *\/\n        draftArea.querySelector('.btn-solid').onclick = function(){\n          navigator.clipboard.writeText(textarea.value).catch(function(){});\n          this.textContent = 'Copied!';\n          var btn = this; setTimeout(function(){ btn.textContent='Copy reply'; }, 2000);\n        };\n        draftArea.querySelector('.btn:not(.btn-solid)').onclick = function(){\n          draftArea.classList.remove('show'); textarea.value='';\n        };\n        return;\n      }\n\n      if(['accepted','declined','archived'].includes(action)){\n        lead.status = action;\n        \/* update sidebar badge *\/\n        var newCount = MOCK_LEADS.filter(function(l){ return l.status==='new'; }).length;\n        document.getElementById('sidebar-badge').textContent = newCount;\n        renderLeads(containerId, containerId==='recent-leads-list'?3:undefined);\n        \/* fire action to backend *\/\n        fetch('\/wp-json\/mahall\/v1\/owner\/lead-action',{\n          method:'POST', headers:{'Content-Type':'application\/json'},\n          body:JSON.stringify({leadId:id, action:action})\n        }).catch(function(){});\n      }\n    });\n  }\n\n  \/* ---- lead tab filter ---- *\/\n  document.getElementById('lead-tabs').addEventListener('click', function(e){\n    var tab = e.target.closest('.tab');\n    if(!tab) return;\n    document.querySelectorAll('.tab').forEach(function(t){ t.classList.remove('active'); });\n    tab.classList.add('active');\n    leadFilter = tab.getAttribute('data-ltab');\n    renderLeads('leads-list');\n  });\n\n  \/* ---- listing completion ---- *\/\n  function renderCompletion(){\n    var done = MOCK_COMPLETION.filter(function(c){ return c.done; }).length;\n    var pct = Math.round((done\/MOCK_COMPLETION.length)*100);\n    document.getElementById('completion-card').innerHTML =\n      '<h3>Listing completeness \u2014 '+pct+'%<\/h3>'+\n      '<div class=\"comp-bar-bg\"><div class=\"comp-bar\" style=\"width:'+pct+'%\"><\/div><\/div>'+\n      '<div class=\"comp-items\">'+\n      MOCK_COMPLETION.map(function(c){\n        return '<div class=\"comp-item\"><div class=\"dot '+(c.done?'done':'miss')+'\"><\/div>'+c.label+'<\/div>';\n      }).join('')+'<\/div>';\n  }\n\n  \/* ---- invoices ---- *\/\n  function renderInvoices(){\n    document.getElementById('invoice-tbody').innerHTML = INVOICES.map(function(inv){\n      return '<tr style=\"border-top:1px solid var(--line)\">'+\n        '<td style=\"padding:10px 0;color:var(--ink-soft)\">'+inv.date+'<\/td>'+\n        '<td>'+inv.plan+'<\/td>'+\n        '<td style=\"font-family:\\'JetBrains Mono\\',monospace\">'+inv.amount+'<\/td>'+\n        '<td style=\"color:var(--teal-soft)\">'+inv.status+'<\/td>'+\n        '<\/tr>';\n    }).join('');\n  }\n\n  \/* ---- try REST, fall back to mock ---- *\/\n  async function loadData(){\n    try{\n      var res = await fetch('\/wp-json\/mahall\/v1\/owner\/stats');\n      if(res.ok){ var d = await res.json(); Object.assign(MOCK_STATS, d); }\n    }catch(e){}\n    try{\n      var lr = await fetch('\/wp-json\/mahall\/v1\/owner\/leads');\n      if(lr.ok){ var ld = await lr.json(); if(Array.isArray(ld)) MOCK_LEADS.splice(0,MOCK_LEADS.length,...ld); }\n    }catch(e){}\n\n    renderStats(MOCK_STATS, 'stat-grid', true);\n    renderStats(MOCK_STATS, 'listing-stats', false);\n    renderLeads('recent-leads-list', 3);\n    renderLeads('leads-list');\n    renderCompletion();\n    renderInvoices();\n    var newCount = MOCK_LEADS.filter(function(l){ return l.status==='new'; }).length;\n    document.getElementById('sidebar-badge').textContent = newCount;\n  }\n\n  loadData();\n})();\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"<p>Mahall Owner &#128202; Overview &#9993; Leads 3 &#127968; My listing Account &#128179; Plan &amp; billing &#9881; Settings Signed in asAmina K. Overview &#9993; Leads Edit listing &#10148; Last 30 days Riad Zahra Medina, Marrakech &middot; Heritage &amp; cultural &middot; 80 guests &#9679; Live &#10022; Featured View listing &#8594; Recent leads All New Accepted Declined Archived [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"folder":[],"class_list":["post-25","page","type-page","status-publish","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/mahall.org\/index.php\/wp-json\/wp\/v2\/pages\/25","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mahall.org\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/mahall.org\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/mahall.org\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mahall.org\/index.php\/wp-json\/wp\/v2\/comments?post=25"}],"version-history":[{"count":2,"href":"https:\/\/mahall.org\/index.php\/wp-json\/wp\/v2\/pages\/25\/revisions"}],"predecessor-version":[{"id":27,"href":"https:\/\/mahall.org\/index.php\/wp-json\/wp\/v2\/pages\/25\/revisions\/27"}],"wp:attachment":[{"href":"https:\/\/mahall.org\/index.php\/wp-json\/wp\/v2\/media?parent=25"}],"wp:term":[{"taxonomy":"folder","embeddable":true,"href":"https:\/\/mahall.org\/index.php\/wp-json\/wp\/v2\/folder?post=25"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}