← back to Cypress Awards

frontend/src/outreach.html

272 lines

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Outreach Dashboard - CyPresAwards</title>
    <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>⚖️</text></svg>">
    <link rel="stylesheet" href="styles.css">
    <style>
        .outreach-container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }

        .stats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-bottom: 40px;
        }

        .stat-card {
            background: white;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }

        .stat-value {
            font-size: 2rem;
            font-weight: bold;
            color: #2563eb;
        }

        .stat-label {
            color: #64748b;
            font-size: 0.875rem;
            margin-top: 5px;
        }

        .org-list {
            background: white;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }

        .org-item {
            padding: 15px;
            border-bottom: 1px solid #e2e8f0;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .org-item:last-child {
            border-bottom: none;
        }

        .org-url {
            color: #2563eb;
            text-decoration: none;
            font-weight: 500;
        }

        .org-url:hover {
            text-decoration: underline;
        }

        .org-date {
            color: #64748b;
            font-size: 0.875rem;
        }

        .export-btn {
            background: #10b981;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 6px;
            cursor: pointer;
            font-weight: 600;
            margin-bottom: 20px;
        }

        .export-btn:hover {
            background: #059669;
        }

        .pagination {
            display: flex;
            gap: 10px;
            justify-content: center;
            margin-top: 20px;
        }

        .pagination button {
            padding: 8px 16px;
            border: 1px solid #e2e8f0;
            background: white;
            border-radius: 6px;
            cursor: pointer;
        }

        .pagination button:hover {
            background: #f1f5f9;
        }

        .pagination button:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }
    </style>
</head>
<body>
    <div class="outreach-container">
        <h1><a href="index.html" style="color: inherit; text-decoration: none;">⚖️ CyPresAwards</a> - 🎯 Outreach Dashboard</h1>
        <p>Organizations without cy pres pages - potential outreach targets</p>

        <div class="stats-grid" id="statsGrid">
            <div class="stat-card">
                <div class="stat-value" id="withCypres">-</div>
                <div class="stat-label">With Cy Pres Pages</div>
            </div>
            <div class="stat-card">
                <div class="stat-value" id="withoutCypres">-</div>
                <div class="stat-label">Without Cy Pres Pages</div>
            </div>
            <div class="stat-card">
                <div class="stat-value" id="manualSubmissions">-</div>
                <div class="stat-label">Manual Submissions</div>
            </div>
            <div class="stat-card">
                <div class="stat-value" id="totalScraped">-</div>
                <div class="stat-label">Total Scraped</div>
            </div>
        </div>

        <button class="export-btn" onclick="exportToCSV()">📊 Export to CSV</button>

        <div class="org-list">
            <h2>Organizations Without Cy Pres Pages</h2>
            <div id="orgList">
                <p>Loading...</p>
            </div>
            <div class="pagination">
                <button id="prevBtn" onclick="previousPage()">← Previous</button>
                <span id="pageInfo">Page 1</span>
                <button id="nextBtn" onclick="nextPage()">Next →</button>
            </div>
        </div>
    </div>

    <script>
        const API_BASE_URL = window.location.origin + '/api';
        let currentPage = 0;
        const itemsPerPage = 50;
        let totalItems = 0;
        let allOrgs = [];

        async function loadStats() {
            try {
                const response = await fetch(`${API_BASE_URL}/outreach/stats`);
                const data = await response.json();

                if (data.success) {
                    document.getElementById('withCypres').textContent = data.data.with_cypres || 0;
                    document.getElementById('withoutCypres').textContent = data.data.without_cypres || 0;
                    document.getElementById('manualSubmissions').textContent = data.data.manual_submissions || 0;
                    document.getElementById('totalScraped').textContent = data.data.total || 0;
                }
            } catch (error) {
                console.error('Error loading stats:', error);
            }
        }

        async function loadOrganizations() {
            try {
                const response = await fetch(
                    `${API_BASE_URL}/outreach/no-cypres-page?limit=${itemsPerPage}&offset=${currentPage * itemsPerPage}`
                );
                const data = await response.json();

                if (data.success) {
                    totalItems = data.meta.total;
                    allOrgs = data.data;
                    renderOrganizations(data.data);
                    updatePagination();
                }
            } catch (error) {
                console.error('Error loading organizations:', error);
                document.getElementById('orgList').innerHTML = '<p>Error loading organizations</p>';
            }
        }

        function renderOrganizations(orgs) {
            const orgList = document.getElementById('orgList');

            if (orgs.length === 0) {
                orgList.innerHTML = '<p>No organizations found</p>';
                return;
            }

            orgList.innerHTML = orgs.map(org => `
                <div class="org-item">
                    <a href="${org.url}" target="_blank" rel="noopener noreferrer" class="org-url">${org.url}</a>
                    <span class="org-date">${new Date(org.scraped_at).toLocaleDateString()}</span>
                </div>
            `).join('');
        }

        function updatePagination() {
            const totalPages = Math.ceil(totalItems / itemsPerPage);
            document.getElementById('pageInfo').textContent = `Page ${currentPage + 1} of ${totalPages}`;
            document.getElementById('prevBtn').disabled = currentPage === 0;
            document.getElementById('nextBtn').disabled = currentPage >= totalPages - 1;
        }

        function previousPage() {
            if (currentPage > 0) {
                currentPage--;
                loadOrganizations();
            }
        }

        function nextPage() {
            const totalPages = Math.ceil(totalItems / itemsPerPage);
            if (currentPage < totalPages - 1) {
                currentPage++;
                loadOrganizations();
            }
        }

        async function exportToCSV() {
            try {
                // Fetch all organizations
                const response = await fetch(`${API_BASE_URL}/outreach/no-cypres-page?limit=10000`);
                const data = await response.json();

                if (data.success) {
                    const csv = 'URL,Scraped Date\n' + data.data.map(org =>
                        `"${org.url}","${new Date(org.scraped_at).toLocaleDateString()}"`
                    ).join('\n');

                    const blob = new Blob([csv], { type: 'text/csv' });
                    const url = window.URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = `outreach-orgs-${new Date().toISOString().split('T')[0]}.csv`;
                    a.click();
                    window.URL.revokeObjectURL(url);
                }
            } catch (error) {
                console.error('Error exporting CSV:', error);
                alert('Failed to export CSV');
            }
        }

        // Load data on page load
        loadStats();
        loadOrganizations();

        // Refresh every 30 seconds
        setInterval(() => {
            loadStats();
            loadOrganizations();
        }, 30000);
    </script>
</body>
</html>