getClientDBConnection() * - Status enum: draft, targeted, live, hold, closed (was launched/paused) * - Added client_id security check * - admin_id -> client_id */ require_once 'client-session.php'; requireClientLogin(); header('Content-Type: application/json'); if ($_SERVER['REQUEST_METHOD'] !== 'POST') { echo json_encode(['success' => false, 'message' => 'Invalid request method']); exit; } try { $pdo = getClientDBConnection(); $data = json_decode(file_get_contents('php://input'), true); $action = $data['action'] ?? ''; $selection_id = (int)($data['selection_id'] ?? 0); if (!$selection_id) { throw new Exception('Invalid selection ID'); } // Get selection and project details — with client_id check $stmt = $pdo->prepare(" SELECT ps.*, p.status as project_status FROM project_selections ps INNER JOIN projects p ON ps.project_id = p.id WHERE ps.id = ? AND ps.client_id = ? "); $stmt->execute([$selection_id, $_SESSION['client_id']]); $selection = $stmt->fetch(); if (!$selection) { throw new Exception('Selection not found or unauthorized'); } switch ($action) { case 'update_status': $new_status = $data['status'] ?? ''; // Valid status transitions matching DB enum: // draft -> targeted (auto, via assign-selection-urls) // targeted -> live (auto, via send-invitations) // live -> hold, closed // hold -> live, closed // closed -> (none) $allowed_transitions = [ 'draft' => [], 'targeted' => [], 'live' => ['hold', 'closed'], 'hold' => ['live', 'closed'], 'closed' => [] ]; $current_status = $selection['status']; // Check if project is closed — overrides everything if ($selection['project_status'] === 'Closed') { throw new Exception('Cannot change selection status when project is closed'); } // Check if transition is allowed if (!isset($allowed_transitions[$current_status]) || !in_array($new_status, $allowed_transitions[$current_status])) { throw new Exception("Cannot change status from '{$current_status}' to '{$new_status}'"); } // Update status $stmt = $pdo->prepare(" UPDATE project_selections SET status = ?, updated_at = NOW() WHERE id = ? AND client_id = ? "); $stmt->execute([$new_status, $selection_id, $_SESSION['client_id']]); // Log activity $stmt = $pdo->prepare(" INSERT INTO selection_activity_log (selection_id, action, description, performed_by) VALUES (?, ?, ?, ?) "); $stmt->execute([ $selection_id, 'status_changed', "Status changed from {$current_status} to {$new_status}", $_SESSION['client_id'] ]); echo json_encode([ 'success' => true, 'message' => "Selection status changed to " . ucfirst($new_status) ]); break; case 'delete': if ($selection['status'] !== 'draft') { throw new Exception('Can only delete draft selections'); } $stmt = $pdo->prepare("DELETE FROM project_selections WHERE id = ? AND client_id = ?"); $stmt->execute([$selection_id, $_SESSION['client_id']]); echo json_encode([ 'success' => true, 'message' => 'Selection deleted successfully' ]); break; default: throw new Exception('Unknown action'); } } catch (Exception $e) { error_log("Selection action error: " . $e->getMessage()); echo json_encode([ 'success' => false, 'message' => $e->getMessage() ]); }