PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]; try { $pdo = new PDO($dsn, $db_user, $db_pass, $options); } catch (Exception $e) { // If DB fails, show helpful message and exit. http_response_code(500); echo "

Database connection failed

{$e->getMessage()}

"; exit; } /* ========================= Helper functions ========================= */ function json_response($data, $status = 200) { http_response_code($status); header('Content-Type: application/json; charset=utf-8'); echo json_encode($data); exit; } function require_auth() { if (empty($_SESSION['user'])) { json_response(['error' => 'unauthenticated'], 401); } } function current_user() { return $_SESSION['user'] ?? null; } /* ========================= API ROUTING (AJAX) Use ?action=xxx for GET/POST endpoints ========================= */ if (isset($_GET['action'])) { $action = $_GET['action']; // Auth endpoints if ($action === 'login' && $_SERVER['REQUEST_METHOD'] === 'POST') { // JSON body or form-encoded $email = $_POST['email'] ?? null; $password = $_POST['password'] ?? null; if (!$email || !$password) json_response(['error' => 'email and password required'], 400); $stmt = $pdo->prepare("SELECT id, name, email, password_hash, role FROM users WHERE email = :email LIMIT 1"); $stmt->execute(['email' => $email]); $user = $stmt->fetch(); if (!$user) json_response(['error' => 'invalid credentials'], 403); if (!password_verify($password, $user['password_hash'])) { json_response(['error' => 'invalid credentials'], 403); } // auth success unset($user['password_hash']); $_SESSION['user'] = $user; json_response(['ok' => true, 'user' => $user]); } if ($action === 'register' && $_SERVER['REQUEST_METHOD'] === 'POST') { // Basic registration $name = $_POST['name'] ?? null; $email = $_POST['email'] ?? null; $password = $_POST['password'] ?? null; if (!$name || !$email || !$password) json_response(['error' => 'name, email, password required'], 400); // check duplicate $stmt = $pdo->prepare("SELECT id FROM users WHERE email = :email"); $stmt->execute(['email' => $email]); if ($stmt->fetch()) json_response(['error' => 'email already exists'], 400); $hash = password_hash($password, PASSWORD_BCRYPT); $stmt = $pdo->prepare("INSERT INTO users (name, email, password_hash, role) VALUES (:name, :email, :hash, 'staff')"); $stmt->execute(['name' => $name, 'email' => $email, 'hash' => $hash]); $id = $pdo->lastInsertId(); $user = ['id' => (int)$id, 'name' => $name, 'email' => $email, 'role' => 'staff']; $_SESSION['user'] = $user; json_response(['ok' => true, 'user' => $user]); } if ($action === 'logout' && $_SERVER['REQUEST_METHOD'] === 'POST') { session_unset(); session_destroy(); json_response(['ok' => true]); } // Protected endpoints require authentication if (in_array($action, [ 'get_dashboard_counts','get_campaigns','create_campaign','update_campaign','delete_campaign', 'get_content','create_content','update_content','delete_content', 'get_customers','update_customer', 'get_users','create_user','update_user','delete_user', 'get_analytics' ])) { require_auth(); } /* ------------------------- Dashboard counts & analytics ------------------------- */ if ($action === 'get_dashboard_counts') { // active campaigns, total customers, engagement rate (simple calc), roi summary $row = $pdo->query("SELECT COUNT(*) as total FROM campaigns WHERE status='Active'")->fetch(); $activeCampaigns = (int)$row['total']; $totalCustomers = (int)$pdo->query("SELECT COUNT(*) FROM customers")->fetchColumn(); // quick engagement: sum of engagement metrics in analytics $engagement = (int)$pdo->prepare("SELECT COALESCE(SUM(metric_value),0) as v FROM analytics WHERE metric_type='Engagement'")->execute() + 0; // We'll do a safe query: $stmt = $pdo->query("SELECT COALESCE(SUM(case when metric_type='Engagement' then metric_value else 0 end),0) as engagement_sum, COALESCE(AVG(case when metric_type='ROI' then metric_value else NULL end),0) as avg_roi FROM analytics"); $vals = $stmt->fetch(); $engagementSum = (int)$vals['engagement_sum']; $avgRoi = (float)$vals['avg_roi']; json_response([ 'activeCampaigns' => $activeCampaigns, 'totalCustomers' => $totalCustomers, 'engagementSum' => $engagementSum, 'avgRoi' => round($avgRoi,2) ]); } if ($action === 'get_analytics') { // Return simple grouped analytics per platform $stmt = $pdo->query("SELECT platform, metric_type, SUM(metric_value) as value FROM analytics GROUP BY platform, metric_type ORDER BY platform"); $data = []; while ($r = $stmt->fetch()) { $data[] = $r; } json_response(['data' => $data]); } /* ------------------------- Campaigns ------------------------- */ if ($action === 'get_campaigns') { $stmt = $pdo->query("SELECT * FROM campaigns ORDER BY start_date DESC"); $campaigns = $stmt->fetchAll(); json_response(['campaigns' => $campaigns]); } if ($action === 'create_campaign' && $_SERVER['REQUEST_METHOD'] === 'POST') { $name = $_POST['name'] ?? ''; $budget = $_POST['budget'] ?? '0'; $start_date = $_POST['start_date'] ?? null; $end_date = $_POST['end_date'] ?? null; $description = $_POST['description'] ?? null; $platforms = $_POST['platforms'] ?? null; // CSV or array if (is_array($platforms)) $platforms = implode(',', $platforms); $status = $_POST['status'] ?? 'Active'; $stmt = $pdo->prepare("INSERT INTO campaigns (name, start_date, end_date, budget, description, status, platforms) VALUES (:name, :start_date, :end_date, :budget, :description, :status, :platforms)"); $stmt->execute([ 'name' => $name, 'start_date' => $start_date, 'end_date' => $end_date, 'budget' => $budget, 'description' => $description, 'status' => $status, 'platforms' => $platforms ]); json_response(['ok' => true, 'id' => $pdo->lastInsertId()]); } if ($action === 'update_campaign' && $_SERVER['REQUEST_METHOD'] === 'POST') { $id = $_POST['id'] ?? null; if (!$id) json_response(['error' => 'id required'], 400); $name = $_POST['name'] ?? ''; $budget = $_POST['budget'] ?? '0'; $start_date = $_POST['start_date'] ?? null; $end_date = $_POST['end_date'] ?? null; $description = $_POST['description'] ?? null; $platforms = $_POST['platforms'] ?? null; if (is_array($platforms)) $platforms = implode(',', $platforms); $status = $_POST['status'] ?? 'Active'; $stmt = $pdo->prepare("UPDATE campaigns SET name=:name, start_date=:start_date, end_date=:end_date, budget=:budget, description=:description, platforms=:platforms, status=:status WHERE id=:id"); $stmt->execute([ 'name' => $name, 'start_date' => $start_date, 'end_date' => $end_date, 'budget' => $budget, 'description' => $description, 'platforms' => $platforms, 'status' => $status, 'id' => $id ]); json_response(['ok' => true]); } if ($action === 'delete_campaign' && $_SERVER['REQUEST_METHOD'] === 'POST') { $id = $_POST['id'] ?? null; if (!$id) json_response(['error' => 'id required'], 400); $stmt = $pdo->prepare("DELETE FROM campaigns WHERE id = :id"); $stmt->execute(['id' => $id]); json_response(['ok' => true]); } /* ------------------------- Content CRUD ------------------------- */ if ($action === 'get_content') { $stmt = $pdo->query("SELECT c.*, cp.name as campaign_name FROM content c LEFT JOIN campaigns cp ON c.campaign_id = cp.id ORDER BY schedule DESC"); $items = $stmt->fetchAll(); json_response(['content' => $items]); } if ($action === 'create_content' && $_SERVER['REQUEST_METHOD'] === 'POST') { $campaign_id = $_POST['campaign_id'] ?: null; $title = $_POST['title'] ?? ''; $platform = $_POST['platform'] ?? ''; $schedule = $_POST['schedule'] ?: null; $body = $_POST['body'] ?? ''; $status = $_POST['status'] ?? 'Scheduled'; $stmt = $pdo->prepare("INSERT INTO content (campaign_id, title, platform, schedule, body, status) VALUES (:campaign_id, :title, :platform, :schedule, :body, :status)"); $stmt->execute([ 'campaign_id' => $campaign_id, 'title' => $title, 'platform' => $platform, 'schedule' => $schedule, 'body' => $body, 'status' => $status ]); json_response(['ok' => true, 'id' => $pdo->lastInsertId()]); } if ($action === 'update_content' && $_SERVER['REQUEST_METHOD'] === 'POST') { $id = $_POST['id'] ?? null; if (!$id) json_response(['error' => 'id required'], 400); $campaign_id = $_POST['campaign_id'] ?: null; $title = $_POST['title'] ?? ''; $platform = $_POST['platform'] ?? ''; $schedule = $_POST['schedule'] ?: null; $body = $_POST['body'] ?? ''; $status = $_POST['status'] ?? 'Scheduled'; $stmt = $pdo->prepare("UPDATE content SET campaign_id=:campaign_id, title=:title, platform=:platform, schedule=:schedule, body=:body, status=:status WHERE id=:id"); $stmt->execute([ 'campaign_id' => $campaign_id, 'title' => $title, 'platform' => $platform, 'schedule' => $schedule, 'body' => $body, 'status' => $status, 'id' => $id ]); json_response(['ok' => true]); } if ($action === 'delete_content' && $_SERVER['REQUEST_METHOD'] === 'POST') { $id = $_POST['id'] ?? null; if (!$id) json_response(['error' => 'id required'], 400); $stmt = $pdo->prepare("DELETE FROM content WHERE id = :id"); $stmt->execute(['id' => $id]); json_response(['ok' => true]); } /* ------------------------- Customers ------------------------- */ if ($action === 'get_customers') { $stmt = $pdo->query("SELECT * FROM customers ORDER BY id DESC"); $rows = $stmt->fetchAll(); json_response(['customers' => $rows]); } if ($action === 'update_customer' && $_SERVER['REQUEST_METHOD'] === 'POST') { $id = $_POST['id'] ?? null; $status = $_POST['status'] ?? null; if (!$id || $status === null) json_response(['error' => 'id and status required'], 400); $stmt = $pdo->prepare("UPDATE customers SET status = :status WHERE id = :id"); $stmt->execute(['status' => $status, 'id' => $id]); json_response(['ok' => true]); } /* ------------------------- Users (Admin) ------------------------- */ if ($action === 'get_users') { $stmt = $pdo->query("SELECT id, name, email, role FROM users ORDER BY id DESC"); $rows = $stmt->fetchAll(); json_response(['users' => $rows]); } if ($action === 'create_user' && $_SERVER['REQUEST_METHOD'] === 'POST') { // Only admin can create users realistically; we skip strict role-check for brevity but you should enforce. $name = $_POST['name'] ?? null; $email = $_POST['email'] ?? null; $password = $_POST['password'] ?? null; $role = $_POST['role'] ?? 'staff'; if (!$name || !$email || !$password) json_response(['error' => 'name,email,password required'], 400); // check exists $stmt = $pdo->prepare("SELECT id FROM users WHERE email = :email"); $stmt->execute(['email' => $email]); if ($stmt->fetch()) json_response(['error' => 'email exists'], 400); $hash = password_hash($password, PASSWORD_BCRYPT); $stmt = $pdo->prepare("INSERT INTO users (name, email, password_hash, role) VALUES (:name,:email,:hash,:role)"); $stmt->execute(['name'=>$name,'email'=>$email,'hash'=>$hash,'role'=>$role]); json_response(['ok'=>true,'id'=>$pdo->lastInsertId()]); } if ($action === 'update_user' && $_SERVER['REQUEST_METHOD'] === 'POST') { $id = $_POST['id'] ?? null; if (!$id) json_response(['error' => 'id required'], 400); $name = $_POST['name'] ?? null; $email = $_POST['email'] ?? null; $role = $_POST['role'] ?? null; $password = $_POST['password'] ?? null; $params = ['id' => $id]; $sets = []; if ($name !== null) { $sets[] = 'name=:name'; $params['name']=$name; } if ($email !== null) { $sets[] = 'email=:email'; $params['email']=$email; } if ($role !== null) { $sets[] = 'role=:role'; $params['role']=$role; } if ($password) { $sets[] = 'password_hash=:hash'; $params['hash'] = password_hash($password, PASSWORD_BCRYPT); } if (empty($sets)) json_response(['error' => 'nothing to update'], 400); $sql = "UPDATE users SET " . implode(',', $sets) . " WHERE id=:id"; $stmt = $pdo->prepare($sql); $stmt->execute($params); json_response(['ok' => true]); } if ($action === 'delete_user' && $_SERVER['REQUEST_METHOD'] === 'POST') { $id = $_POST['id'] ?? null; if (!$id) json_response(['error' => 'id required'], 400); $stmt = $pdo->prepare("DELETE FROM users WHERE id = :id"); $stmt->execute(['id' => $id]); json_response(['ok' => true]); } // If action not matched: json_response(['error' => 'unknown action'], 400); } /* ========================= If no action param => render main HTML app ========================= */ ?> JHM Microfinance | Campaign Management (SaaS)

Dashboard Overview

Active Campaigns

0

Engagement Sum

0

Total Customers

0

Avg ROI

0%

Performance Overview

Campaign Management

Create / Edit Campaign
Hold Ctrl/Cmd to select multiple
Existing Campaigns
NameStartEndBudgetStatusPlatformsActions

Content Management

Create / Edit Content
Content Library
TitlePlatformCampaignScheduleStatusActions

Analytics

Customer Interactions

CustomerPlatformMessageStatusActions

Admin Panel

Manage Users
UserEmailRoleActions
Raw Analytics