View file File name : api.php Content :<?php // Use folder name to generate a unique session name $folder = basename(dirname($_SERVER['PHP_SELF'])); $session_name = 'SESS_' . preg_replace('/[^a-zA-Z0-9_]/', '', $folder); session_name($session_name); // Dynamically set session cookie path for this business's folder $cookie_path = rtrim(dirname($_SERVER['PHP_SELF']), '/\\') . '/'; session_set_cookie_params(0, $cookie_path); session_start(); date_default_timezone_set('America/Belize'); require 'db_config.php'; // --- HELPER FUNCTIONS --- function send_json_error($message, $code = 400) { http_response_code($code); error_log("API Error: " . $message); echo json_encode(['success' => false, 'message' => $message]); exit(); } function send_json_success($data = []) { echo json_encode(['success' => true, 'data' => $data]); exit(); } function get_db_connection() { global $servername, $username, $password, $dbname; try { $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { throw new Exception('Database connection failed: ' . $conn->connect_error); } return $conn; } catch (Exception $e) { throw $e; } } function get_stmt_result($stmt) { $result = []; $stmt->store_result(); if ($stmt->num_rows === 0) { $stmt->free_result(); return $result; } $meta = $stmt->result_metadata(); if (!$meta) { $stmt->free_result(); return []; } $fields = []; $row = []; while ($field = $meta->fetch_field()) { $fields[] = &$row[$field->name]; } call_user_func_array([$stmt, 'bind_result'], $fields); while ($stmt->fetch()) { $result_row = []; foreach ($row as $key => $val) { $result_row[$key] = $val; } $result[] = $result_row; } $stmt->free_result(); return $result; } function generate_referral_code($conn) { $is_unique = false; while (!$is_unique) { $referral_code = 'REF' . strtoupper(substr(md5(uniqid(rand(), true)), 0, 6)); $stmt = $conn->prepare("SELECT id FROM customers WHERE referral_code = ?"); $stmt->bind_param("s", $referral_code); $stmt->execute(); $stmt->store_result(); if ($stmt->num_rows == 0) { $is_unique = true; } $stmt->close(); } return $referral_code; } // --- MAIN EXECUTION --- try { $conn = get_db_connection(); $action = $_POST['action'] ?? $_GET['action'] ?? ''; if (empty($action)) { send_json_error('No action specified.'); } $public_actions = ['login', 'register_customer']; // --- ROUTING LOGIC --- if (in_array($action, $public_actions)) { // --- PUBLIC ACTIONS (NO SESSION REQUIRED) --- switch ($action) { case 'login': $type = $_POST['type'] ?? ''; $user = null; if ($type === 'customer') { $phone = $_POST['customer_phone'] ?? ''; $pass = $_POST['customer_password'] ?? ''; $stmt = $conn->prepare("SELECT id, name, phone, password, qrCodeValue, points, rewards, joinedDate, tier, total_points_earned, referral_code FROM customers WHERE phone = ? AND password = ?"); if (!$stmt) send_json_error('Database error preparing customer login.', 500); $stmt->bind_param("ss", $phone, $pass); $stmt->execute(); $result_array = get_stmt_result($stmt); if (!empty($result_array)) $user = $result_array[0]; $stmt->close(); } elseif ($type === 'admin') { $user_in = $_POST['admin_username'] ?? ''; $pass_in = $_POST['admin_password'] ?? ''; $stmt = $conn->prepare("SELECT id, name, username, password FROM admins WHERE username = ? AND password = ?"); if (!$stmt) send_json_error('Database error preparing admin login.', 500); $stmt->bind_param("ss", $user_in, $pass_in); $stmt->execute(); $result_array = get_stmt_result($stmt); if (!empty($result_array)) $user = $result_array[0]; $stmt->close(); } else { send_json_error('Invalid login type.'); } if ($user) { $_SESSION['user_id'] = $user['id']; $_SESSION['user_type'] = $type; $_SESSION['user_name'] = $user['name']; send_json_success(['userType' => $type, 'user' => $user]); } else { send_json_error('Invalid credentials.', 401); } break; case 'register_customer': $name = $_POST['name'] ?? null; $phone = $_POST['phone'] ?? null; $password = $_POST['password'] ?? null; $referral_code_used = $_POST['referral_code'] ?? null; if (!$name || !$phone || !$password) send_json_error('All fields are required.'); if (strlen($password) < 6) send_json_error('Password must be at least 6 characters long.'); $stmt = $conn->prepare("SELECT id FROM customers WHERE phone = ?"); $stmt->bind_param("s", $phone); $stmt->execute(); $stmt->store_result(); if ($stmt->num_rows > 0) { $stmt->close(); send_json_error('A customer with this phone number already exists.'); } $stmt->close(); $referrer_id = null; if (!empty($referral_code_used)) { $stmt = $conn->prepare("SELECT id FROM customers WHERE referral_code = ?"); $stmt->bind_param("s", $referral_code_used); $stmt->execute(); $referrer_result = get_stmt_result($stmt); if (!empty($referrer_result)) $referrer_id = $referrer_result[0]['id']; $stmt->close(); } $id = 'cust' . time(); $qrCodeValue = $id; $points = 0; $rewards = 0; $joinedDate = date("Y-m-d H:i:s"); $new_referral_code = generate_referral_code($conn); $stmt = $conn->prepare("INSERT INTO customers (id, name, phone, password, qrCodeValue, points, rewards, joinedDate, referral_code, referred_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->bind_param("sssssiisss", $id, $name, $phone, $password, $qrCodeValue, $points, $rewards, $joinedDate, $new_referral_code, $referrer_id); if ($stmt->execute()) { $new_customer = [ 'id' => $id, 'name' => $name, 'phone' => $phone, 'password' => $password, 'qrCodeValue' => $qrCodeValue, 'points' => $points, 'rewards' => $rewards, 'joinedDate' => $joinedDate, 'history' => [], 'tier' => 'Bronze', 'total_points_earned' => 0, 'referral_code' => $new_referral_code ]; $_SESSION['user_id'] = $id; $_SESSION['user_type'] = 'customer'; $_SESSION['user_name'] = $name; send_json_success(['user' => $new_customer, 'message' => "Registration successful. Welcome, {$name}!"]); } else { send_json_error('Failed to create customer account.', 500); } $stmt->close(); break; } } else { // --- AUTHENTICATED ACTIONS --- if (!isset($_SESSION['user_id'])) { send_json_error('Authentication required.', 401); } switch($action) { case 'getData': $response_data = []; $settings_defaults = ['businessName' => 'Omni Rewards', 'logoUrl' => '', 'faviconUrl' => '', 'primaryColor' => '262 83% 57%', 'backgroundColor' => '240 60% 99%', 'accentColor' => '220 14% 96%', 'api_key' => null]; $settings_result = $conn->query("SELECT businessName, logoUrl, faviconUrl, primaryColor, backgroundColor, accentColor, api_key FROM business_settings LIMIT 1"); $db_settings = $settings_result ? $settings_result->fetch_assoc() : []; $response_data['settings'] = array_merge($settings_defaults, array_filter($db_settings ?: [])); $customers_query = " SELECT c.*, (SELECT COUNT(*) FROM point_history ph WHERE ph.customer_id = c.id AND ph.description = 'Reward Redeemed') as redeemed_rewards_count FROM customers c "; $customers_result = $conn->query($customers_query); $customers_array = []; if ($customers_result) { while ($row = $customers_result->fetch_assoc()) { $row['isVIP'] = ($row['redeemed_rewards_count'] >= 5); $customers_array[] = $row; } } $response_data['customers'] = $customers_array; $admins_result = $conn->query("SELECT id, name, username, password FROM admins"); $admins_array = []; if($admins_result){ while($row = $admins_result->fetch_assoc()) { $admins_array[] = $row; } } $response_data['admins'] = $admins_array; $stats = ['totalCustomers' => count($customers_array), 'pointsThisMonth' => 0, 'totalPoints' => 0, 'rewardsClaimed' => 0]; $current_month_start = date('Y-m-01 00:00:00'); $stmt_month = $conn->prepare("SELECT SUM(points) as total FROM point_history WHERE points > 0 AND date >= ?"); if ($stmt_month) { $stmt_month->bind_param("s", $current_month_start); $stmt_month->execute(); $month_result = get_stmt_result($stmt_month); if (!empty($month_result)) { $stats['pointsThisMonth'] = (int)($month_result[0]['total'] ?? 0); } $stmt_month->close(); } $stmt_total = $conn->query("SELECT SUM(total_points_earned) as total FROM customers"); if ($stmt_total) { $total_result = $stmt_total->fetch_assoc(); $stats['totalPoints'] = (int)($total_result['total'] ?? 0); } $stmt_claimed = $conn->query("SELECT COUNT(*) as total FROM point_history WHERE description = 'Reward Redeemed'"); if($stmt_claimed) { $claimed_result = $stmt_claimed->fetch_assoc(); $stats['rewardsClaimed'] = (int)($claimed_result['total'] ?? 0); } $response_data['stats'] = $stats; send_json_success($response_data); break; case 'get_chart_data': $monthly_data = []; for ($i = 5; $i >= 0; $i--) { $date = new DateTime("first day of -$i months"); $month_key = $date->format('Y-m'); $monthly_data[$month_key] = ['totalPoints' => 0, 'rewardsClaimed' => 0]; } $five_months_ago = new DateTime("first day of -5 months"); $start_date = $five_months_ago->format('Y-m-d 00:00:00'); $stmt = $conn->prepare(" SELECT DATE_FORMAT(date, '%Y-%m') as month, SUM(CASE WHEN points > 0 THEN points ELSE 0 END) as total_points, SUM(CASE WHEN description = 'Reward Redeemed' THEN 1 ELSE 0 END) as rewards_claimed_count FROM point_history WHERE date >= ? GROUP BY month "); $stmt->bind_param("s", $start_date); $stmt->execute(); $results = get_stmt_result($stmt); $stmt->close(); foreach ($results as $row) { if (isset($monthly_data[$row['month']])) { $monthly_data[$row['month']]['totalPoints'] = (int)$row['total_points']; $monthly_data[$row['month']]['rewardsClaimed'] = (int)$row['rewards_claimed_count']; } } $chart_data = []; foreach($monthly_data as $month => $data) { $date_obj = DateTime::createFromFormat('Y-m', $month); $chart_data[] = [ 'month' => $date_obj->format('M'), 'totalPoints' => $data['totalPoints'], 'rewardsClaimed' => $data['rewardsClaimed'] ]; } send_json_success($chart_data); break; case 'get_customer_history': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $customer_id = $_POST['customer_id'] ?? null; if (!$customer_id) send_json_error('Customer ID not provided.'); $stmt = $conn->prepare("SELECT * FROM point_history WHERE customer_id = ? ORDER BY date DESC"); $stmt->bind_param("s", $customer_id); $stmt->execute(); $history = get_stmt_result($stmt); $stmt->close(); send_json_success($history); break; case 'generate_api_key': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $new_key = bin2hex(random_bytes(16)); $stmt = $conn->prepare("UPDATE business_settings SET api_key = ?"); $stmt->bind_param("s", $new_key); if ($stmt->execute()) { send_json_success(['message' => 'New API key generated successfully.', 'new_key' => $new_key]); } else { send_json_error('Failed to generate new API key.', 500); } $stmt->close(); break; case 'logout': session_unset(); session_destroy(); send_json_success(['message' => 'Logged out successfully.']); break; case 'add_point_from_scan': case 'add_point': case 'remove_point': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $customerId = $_POST['customerId'] ?? null; if ($action === 'add_point_from_scan') { $qrCodeValue = $_POST['qrCodeValue'] ?? null; if (!$qrCodeValue) send_json_error('QR Code value not provided.'); $stmt_find = $conn->prepare("SELECT id FROM customers WHERE qrCodeValue = ?"); $stmt_find->bind_param("s", $qrCodeValue); $stmt_find->execute(); $result_array = get_stmt_result($stmt_find); if (empty($result_array)) { $stmt_find->close(); send_json_error('No customer found for this QR code.'); } $customerId = $result_array[0]['id']; $stmt_find->close(); } if (!$customerId) send_json_error('Customer ID not provided.'); $conn->begin_transaction(); try { $stmt = $conn->prepare("SELECT name, points, rewards, total_points_earned, referred_by, tier FROM customers WHERE id = ? FOR UPDATE"); $stmt->bind_param("s", $customerId); $stmt->execute(); $result_array = get_stmt_result($stmt); if (empty($result_array)) throw new Exception('Customer not found.'); $customer = $result_array[0]; $stmt->close(); $name = $customer['name']; $points = (int)$customer['points']; $rewards = (int)$customer['rewards']; $total_points_earned = (int)$customer['total_points_earned']; $current_tier = $customer['tier']; $new_rewards_earned = 0; $points_change = 0; $desc = ''; $admin_name = $_SESSION['user_name'] ?? 'Admin'; if ($action !== 'remove_point') { $points_change = 1; $desc = "Point added by {$admin_name}"; $points++; $total_points_earned++; if ($total_points_earned == 1 && !empty($customer['referred_by'])) { $referrer_id = $customer['referred_by']; $bonus_points = 5; $bonus_desc = "Referral bonus for {$name}"; $stmt_ref = $conn->prepare("UPDATE customers SET points = points + ? WHERE id = ?"); $stmt_ref->bind_param("is", $bonus_points, $referrer_id); $stmt_ref->execute(); $stmt_ref->close(); $ref_history_id = 'h_' . time() . rand(100,999); $date = date("Y-m-d H:i:s"); $stmt_ref_hist = $conn->prepare("INSERT INTO point_history (id, customer_id, date, description, points) VALUES (?, ?, ?, ?, ?)"); $stmt_ref_hist->bind_param("ssssi", $ref_history_id, $referrer_id, $date, $bonus_desc, $bonus_points); $stmt_ref_hist->execute(); $stmt_ref_hist->close(); } $new_rewards_earned = floor($points / 10); $points = $points % 10; $rewards += $new_rewards_earned; $new_tier = $current_tier; if ($total_points_earned >= 100) $new_tier = 'Gold'; else if ($total_points_earned >= 50) $new_tier = 'Silver'; } else { if ($points <= 0) throw new Exception("{$name} has no points to remove."); $points_change = -1; $desc = "Point removed by {$admin_name}"; $points--; $total_points_earned--; $new_tier = $current_tier; } $stmt = $conn->prepare("UPDATE customers SET points = ?, rewards = ?, total_points_earned = ?, tier = ? WHERE id = ?"); $stmt->bind_param("iiiss", $points, $rewards, $total_points_earned, $new_tier, $customerId); $stmt->execute(); $stmt->close(); $history_id = 'h_' . time() . rand(100,999); $date = date("Y-m-d H:i:s"); $stmt = $conn->prepare("INSERT INTO point_history (id, customer_id, date, description, points) VALUES (?, ?, ?, ?, ?)"); $stmt->bind_param("ssssi", $history_id, $customerId, $date, $desc, $points_change); $stmt->execute(); $stmt->close(); $conn->commit(); $message = $action === 'remove_point' ? "Removed 1 point from {$name}." : "Added 1 point to {$name}."; if ($action !== 'remove_point' && $new_rewards_earned > 0) $message .= " They earned a reward!"; if ($new_tier !== $current_tier) $message .= " And they've been promoted to the {$new_tier} tier!"; send_json_success(['message' => $message]); } catch (Exception $e) { $conn->rollback(); send_json_error($e->getMessage(), 500); } break; case 'redeem_reward': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $customerId = $_POST['customerId'] ?? null; if (!$customerId) send_json_error('Customer ID not provided.'); $conn->begin_transaction(); try { $stmt = $conn->prepare("SELECT name, rewards FROM customers WHERE id = ? FOR UPDATE"); $stmt->bind_param("s", $customerId); $stmt->execute(); $result_array = get_stmt_result($stmt); if (empty($result_array)) throw new Exception('Customer not found.'); $customer = $result_array[0]; $stmt->close(); if ($customer['rewards'] < 1) throw new Exception("{$customer['name']} has no rewards to redeem."); $newRewards = $customer['rewards'] - 1; $stmt = $conn->prepare("UPDATE customers SET rewards = ? WHERE id = ?"); $stmt->bind_param("is", $newRewards, $customerId); $stmt->execute(); $stmt->close(); $history_id = 'h_' . time() . rand(100,999); $date = date("Y-m-d H:i:s"); $admin_name = $_SESSION['user_name'] ?? 'Admin'; $desc = "Reward Redeemed"; $points_change = -10; $stmt = $conn->prepare("INSERT INTO point_history (id, customer_id, date, description, points) VALUES (?, ?, ?, ?, ?)"); $stmt->bind_param("ssssi", $history_id, $customerId, $date, $desc, $points_change); $stmt->execute(); $stmt->close(); $conn->commit(); send_json_success(['message' => "Reward redeemed for {$customer['name']}."]); } catch (Exception $e) { $conn->rollback(); send_json_error($e->getMessage(), 500); } break; case 'add_customer': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $name = $_POST['name'] ?? null; $phone = $_POST['phone'] ?? null; $password = $_POST['password'] ?? null; if (!$name || !$phone || !$password) send_json_error('All fields are required.'); $stmt_check = $conn->prepare("SELECT id FROM customers WHERE phone = ?"); $stmt_check->bind_param("s", $phone); $stmt_check->execute(); $stmt_check->store_result(); if ($stmt_check->num_rows > 0) { $stmt_check->close(); send_json_error('A customer with this phone number already exists.'); } $stmt_check->close(); $id = 'cust' . time(); $qrCodeValue = $id; $points = 0; $rewards = 0; $joinedDate = date("Y-m-d H:i:s"); $referral_code = generate_referral_code($conn); $stmt = $conn->prepare("INSERT INTO customers (id, name, phone, password, qrCodeValue, points, rewards, joinedDate, referral_code) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->bind_param("sssssiiss", $id, $name, $phone, $password, $qrCodeValue, $points, $rewards, $joinedDate, $referral_code); if ($stmt->execute()) { $new_customer = [ 'id' => $id, 'name' => $name, 'phone' => $phone, 'password' => $password, 'qrCodeValue' => $qrCodeValue, 'points' => $points, 'rewards' => $rewards, 'joinedDate' => $joinedDate, 'history' => [], 'tier' => 'Bronze', 'total_points_earned' => 0, 'referral_code' => $referral_code ]; send_json_success(['customer' => $new_customer, 'message' => "Customer {$name} added successfully."]); } else { send_json_error('Failed to create customer.', 500); } $stmt->close(); break; case 'reset_points': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $customerId = $_POST['customerId'] ?? null; if (!$customerId) send_json_error('Customer ID not provided.'); $conn->begin_transaction(); try { $stmt = $conn->prepare("SELECT points FROM customers WHERE id = ?"); $stmt->bind_param("s", $customerId); $stmt->execute(); $result_array = get_stmt_result($stmt); $stmt->close(); if (empty($result_array)) throw new Exception("Customer not found."); $points_lost = $result_array[0]['points']; if ($points_lost > 0) { $stmt_update = $conn->prepare("UPDATE customers SET points = 0 WHERE id = ?"); $stmt_update->bind_param("s", $customerId); $stmt_update->execute(); $stmt_update->close(); $history_id = 'h_' . time() . rand(100,999); $date = date("Y-m-d H:i:s"); $admin_name = $_SESSION['user_name'] ?? 'Admin'; $desc = "Points reset by {$admin_name}"; $points_change = -$points_lost; $stmt_history = $conn->prepare("INSERT INTO point_history (id, customer_id, date, description, points) VALUES (?, ?, ?, ?, ?)"); $stmt_history->bind_param("ssssi", $history_id, $customerId, $date, $desc, $points_change); $stmt_history->execute(); $stmt_history->close(); } $conn->commit(); send_json_success(['message' => 'Points reset successfully.']); } catch (Exception $e) { $conn->rollback(); send_json_error($e->getMessage(), 500); } break; case 'reset_password': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $customerId = $_POST['customerId'] ?? null; if (!$customerId) send_json_error('Customer ID not provided.'); $new_password = substr(md5(rand()), 0, 8); $stmt = $conn->prepare("UPDATE customers SET password = ? WHERE id = ?"); $stmt->bind_param("ss", $new_password, $customerId); if ($stmt->execute()) { send_json_success(['newPassword' => $new_password, 'message' => 'Password has been reset.']); } else { send_json_error('Failed to reset password.', 500); } $stmt->close(); break; case 'delete_customer': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $customerId = $_POST['customerId'] ?? null; if (!$customerId) send_json_error('Customer ID not provided.'); $conn->begin_transaction(); try { $stmt_hist = $conn->prepare("DELETE FROM point_history WHERE customer_id = ?"); $stmt_hist->bind_param("s", $customerId); $stmt_hist->execute(); $stmt_hist->close(); $stmt_cust = $conn->prepare("DELETE FROM customers WHERE id = ?"); $stmt_cust->bind_param("s", $customerId); $stmt_cust->execute(); $stmt_cust->close(); $conn->commit(); send_json_success(['message' => 'Customer deleted.']); } catch(Exception $e) { $conn->rollback(); send_json_error('Failed to delete customer.', 500); } break; case 'update_settings': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $current_admin_id = $_SESSION['user_id']; $business_name = $_POST['businessName'] ?? null; $admin_username = $_POST['adminUsername'] ?? null; $new_password = $_POST['newPassword'] ?? null; $primary_color = $_POST['primaryColor'] ?? null; $bg_color = $_POST['backgroundColor'] ?? null; $accent_color = $_POST['accentColor'] ?? null; if (!$business_name || !$admin_username) send_json_error('Business Name and Admin Username are required.'); $conn->begin_transaction(); try { $result = $conn->query("SELECT * FROM business_settings LIMIT 1"); $current_settings = $result->fetch_assoc(); $logo_url_to_save = $current_settings['logoUrl'] ?? ''; $favicon_url_to_save = $current_settings['faviconUrl'] ?? ''; $upload_dir = 'uploads/'; if (!is_dir($upload_dir)) mkdir($upload_dir, 0755, true); $allowed_types = ['image/jpeg', 'image/png', 'image/gif', 'image/x-icon', 'image/svg+xml']; if (isset($_FILES['logoFile']) && $_FILES['logoFile']['error'] == 0) { if (!in_array($_FILES['logoFile']['type'], $allowed_types)) throw new Exception('Invalid logo file type.'); $ext = pathinfo($_FILES['logoFile']['name'], PATHINFO_EXTENSION); $dest = $upload_dir . 'logo.' . $ext; if (move_uploaded_file($_FILES['logoFile']['tmp_name'], $dest)) $logo_url_to_save = $dest . '?v=' . time(); else throw new Exception('Failed to move uploaded logo file.'); } if (isset($_FILES['faviconFile']) && $_FILES['faviconFile']['error'] == 0) { if (!in_array($_FILES['faviconFile']['type'], $allowed_types)) throw new Exception('Invalid favicon file type.'); $ext = pathinfo($_FILES['faviconFile']['name'], PATHINFO_EXTENSION); $dest = $upload_dir . 'favicon.' . $ext; if (move_uploaded_file($_FILES['faviconFile']['tmp_name'], $dest)) $favicon_url_to_save = $dest . '?v=' . time(); else throw new Exception('Failed to move uploaded favicon file.'); } $stmt = $conn->prepare("UPDATE business_settings SET businessName = ?, logoUrl = ?, faviconUrl = ?, primaryColor = ?, backgroundColor = ?, accentColor = ?"); if (!$stmt) throw new Exception("Prepare failed: " . $conn->error); $stmt->bind_param("ssssss", $business_name, $logo_url_to_save, $favicon_url_to_save, $primary_color, $bg_color, $accent_color); $stmt->execute(); $stmt->close(); if (!empty($new_password)) { $stmt = $conn->prepare("UPDATE admins SET username = ?, password = ? WHERE id = ?"); $stmt->bind_param("sss", $admin_username, $new_password, $current_admin_id); } else { $stmt = $conn->prepare("UPDATE admins SET username = ? WHERE id = ?"); $stmt->bind_param("ss", $admin_username, $current_admin_id); } $stmt->execute(); $stmt->close(); $conn->commit(); send_json_success(['message' => 'Settings updated successfully.']); } catch (Exception $e) { $conn->rollback(); send_json_error('Failed to update settings: ' . $e->getMessage(), 500); } break; case 'add_admin': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $name = $_POST['name'] ?? null; $username = $_POST['username'] ?? null; $password = $_POST['password'] ?? null; if (!$name || !$username || !$password) send_json_error('All fields are required.'); $id = 'admin' . time(); $stmt = $conn->prepare("INSERT INTO admins (id, name, username, password) VALUES (?, ?, ?, ?)"); $stmt->bind_param("ssss", $id, $name, $username, $password); if ($stmt->execute()) send_json_success(['message' => "Admin {$name} added."]); else send_json_error('Failed to add admin.', 500); break; case 'delete_admin': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $adminId = $_POST['adminId'] ?? null; if (!$adminId) send_json_error('Admin ID not provided.'); $stmt = $conn->prepare("DELETE FROM admins WHERE id = ?"); $stmt->bind_param("s", $adminId); if ($stmt->execute()) send_json_success(['message' => 'Admin deleted.']); else send_json_error('Failed to delete admin.', 500); break; case 'delete_all_customers': if ($_SESSION['user_type'] !== 'admin') send_json_error('Unauthorized', 403); $conn->begin_transaction(); try { $conn->query("DELETE FROM point_history"); $conn->query("DELETE FROM customers"); $conn->commit(); send_json_success(['message' => 'All customer data has been deleted.']); } catch (Exception $e) { $conn->rollback(); send_json_error('Failed to delete customer data.', 500); } break; case 'update_customer_details': if ($_SESSION['user_type'] !== 'customer') send_json_error('Unauthorized', 403); $customerId = $_SESSION['user_id']; $update_type = $_POST['update_type'] ?? ''; if ($update_type === 'phone') { $new_phone = $_POST['new_phone'] ?? null; if (!$new_phone) send_json_error('Phone number not provided.'); $stmt = $conn->prepare("UPDATE customers SET phone = ? WHERE id = ?"); $stmt->bind_param("ss", $new_phone, $customerId); if ($stmt->execute()) send_json_success(['message' => 'Phone number updated successfully.']); else send_json_error('Failed to update phone number.', 500); $stmt->close(); } elseif ($update_type === 'password') { $new_password = $_POST['new_password'] ?? null; $confirm_password = $_POST['confirm_password'] ?? null; if (!$new_password || !$confirm_password) send_json_error('Password fields are required.'); if ($new_password !== $confirm_password) send_json_error('Passwords do not match.'); if (strlen($new_password) < 6) send_json_error('Password must be at least 6 characters.'); $stmt = $conn->prepare("UPDATE customers SET password = ? WHERE id = ?"); $stmt->bind_param("ss", $new_password, $customerId); if ($stmt->execute()) send_json_success(['message' => 'Password updated successfully.']); else send_json_error('Failed to update password.', 500); $stmt->close(); } else { send_json_error('Invalid update type specified.'); } break; default: send_json_error('Invalid authenticated action specified: ' . htmlspecialchars($action)); break; } } } catch (Exception $e) { if (isset($conn) && $conn->ping()) { try { $conn->rollback(); } catch (Exception $rollback_e) {} } send_json_error('A critical server error occurred: ' . $e->getMessage(), 500); } if (isset($conn)) { $conn->close(); } ?>