pdo = $connection->getPdo(); } /** * List all organizations with filters. */ public function index(Request $request, Response $response): string { $type = $request->get('type', ''); $search = $request->get('search', ''); $page = max(1, (int)$request->get('page', 1)); $perPage = 20; $offset = ($page - 1) * $perPage; $where = ['o.deleted_at IS NULL']; $params = []; if ($type) { $where[] = 'o.type = ?'; $params[] = $type; } if ($search) { $where[] = '(o.name LIKE ? OR o.domain LIKE ? OR o.description LIKE ?)'; $params[] = "%{$search}%"; $params[] = "%{$search}%"; $params[] = "%{$search}%"; } $whereClause = implode(' AND ', $where); // Count total $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM organizations o WHERE {$whereClause}"); $stmt->execute($params); $total = (int)$stmt->fetchColumn(); // Fetch page $stmt = $this->pdo->prepare( "SELECT o.*, (SELECT COUNT(*) FROM opportunities WHERE organization_id = o.id AND deleted_at IS NULL) as opportunities_count FROM organizations o WHERE {$whereClause} ORDER BY o.updated_at DESC LIMIT ? OFFSET ?" ); $stmt->execute(array_merge($params, [$perPage, $offset])); $organizations = $stmt->fetchAll(); return $this->render('admin/organizations/index', [ 'organizations' => $organizations, 'total' => $total, 'page' => $page, 'perPage' => $perPage, 'type' => $type, 'search' => $search, 'types' => ['vc', 'angel', 'accelerator', 'incubator', 'venture_studio', 'partner'], 'statuses' => ['New', 'Researching', 'Contacted', 'Follow Up', 'Meeting Scheduled', 'Interested', 'Rejected', 'Invested'], ], 'admin'); } /** * Show single organization. */ public function show(Request $request, Response $response, int $id): string { $stmt = $this->pdo->prepare("SELECT * FROM organizations WHERE id = ? AND deleted_at IS NULL"); $stmt->execute([$id]); $org = $stmt->fetch(); if (!$org) { $response->redirect('/admin/organizations'); return ''; } // Get opportunities for this org $stmt = $this->pdo->prepare( "SELECT o.*, GROUP_CONCAT(t.name) as tag_names FROM opportunities o LEFT JOIN opportunity_tags ot ON ot.opportunity_id = o.id LEFT JOIN tags t ON t.id = ot.tag_id WHERE o.organization_id = ? AND o.deleted_at IS NULL GROUP BY o.id ORDER BY o.score DESC" ); $stmt->execute([$id]); $opportunities = $stmt->fetchAll(); // Get contacts for this org $stmt = $this->pdo->prepare( "SELECT c.*, (SELECT COUNT(*) FROM interactions WHERE contact_id = c.id) as interaction_count FROM contacts c WHERE c.organization_id = ? AND c.deleted_at IS NULL ORDER BY c.created_at DESC" ); $stmt->execute([$id]); $contacts = $stmt->fetchAll(); // Get activity logs $stmt = $this->pdo->prepare( "SELECT * FROM activity_logs WHERE description LIKE ? ORDER BY created_at DESC LIMIT 20" ); $stmt->execute(['%' . $org['name'] . '%']); $activities = $stmt->fetchAll(); return $this->render('admin/organizations/show', [ 'org' => $org, 'opportunities' => $opportunities, 'contacts' => $contacts, 'activities' => $activities, ], 'admin'); } /** * Show create/edit form. */ public function create(Request $request, Response $response): string { return $this->render('admin/organizations/form', [ 'org' => null, 'types' => ['vc', 'angel', 'accelerator', 'incubator', 'venture_studio', 'partner'], 'statuses' => ['New', 'Researching', 'Contacted', 'Follow Up', 'Meeting Scheduled', 'Interested', 'Rejected', 'Invested'], ], 'admin'); } /** * Show edit form. */ public function edit(Request $request, Response $response, int $id): string { $stmt = $this->pdo->prepare("SELECT * FROM organizations WHERE id = ? AND deleted_at IS NULL"); $stmt->execute([$id]); $org = $stmt->fetch(); if (!$org) { $response->redirect('/admin/organizations'); return ''; } return $this->render('admin/organizations/form', [ 'org' => $org, 'types' => ['vc', 'angel', 'accelerator', 'incubator', 'venture_studio', 'partner'], 'statuses' => ['New', 'Researching', 'Contacted', 'Follow Up', 'Meeting Scheduled', 'Interested', 'Rejected', 'Invested'], ], 'admin'); } /** * Save organization (create or update). */ public function store(Request $request, Response $response): void { $id = $request->post('id', ''); $name = $request->post('name', ''); $domain = $request->post('domain', ''); $type = $request->post('type', 'partner'); $country = $request->post('country', ''); $city = $request->post('city', ''); $websiteUrl = $request->post('website_url', ''); $description = $request->post('description', ''); $crmStatus = $request->post('crm_status', 'New'); $fundingStage = $request->post('funding_stage', ''); try { if ($id) { $stmt = $this->pdo->prepare( "UPDATE organizations SET name=?, domain=?, type=?, country=?, city=?, website_url=?, description=?, crm_status=?, funding_stage=? WHERE id=?" ); $stmt->execute([$name, $domain ?: null, $type, $country ?: null, $city ?: null, $websiteUrl ?: null, $description, $crmStatus, $fundingStage ?: null, $id]); $this->session->setFlash('success', 'Organization updated successfully.'); } else { $stmt = $this->pdo->prepare( "INSERT INTO organizations (name, domain, type, country, city, website_url, description, crm_status, funding_stage) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" ); $stmt->execute([$name, $domain ?: null, $type, $country ?: null, $city ?: null, $websiteUrl ?: null, $description, $crmStatus, $fundingStage ?: null]); $id = $this->pdo->lastInsertId(); $this->session->setFlash('success', 'Organization created successfully.'); } $response->redirect('/admin/organizations/' . $id); } catch (Throwable $e) { $this->session->setFlash('error', 'Error saving organization: ' . $e->getMessage()); $response->redirect('/admin/organizations' . ($id ? '/' . $id : '/create')); } } /** * Delete organization (soft delete). */ public function delete(Request $request, Response $response, int $id): void { try { $stmt = $this->pdo->prepare("UPDATE organizations SET deleted_at = NOW() WHERE id = ?"); $stmt->execute([$id]); $this->session->setFlash('success', 'Organization deleted.'); } catch (Throwable $e) { $this->session->setFlash('error', 'Error deleting organization.'); } $response->redirect('/admin/organizations'); } }