diff --git a/analyst_dashboard.php b/analyst_dashboard.php index e329b69..ee9db2a 100644 --- a/analyst_dashboard.php +++ b/analyst_dashboard.php @@ -1,13 +1,50 @@ query("SELECT id, name, status, created_at FROM submissions ORDER BY created_at DESC"); + $stmt = $pdo->query("SELECT * FROM submissions ORDER BY created_at DESC"); $submissions = $stmt->fetchAll(); } catch (PDOException $e) { $submissions = []; - // error_log($e->getMessage()); // It's good practice to log errors + // In a real app, log this error to a file or service + // error_log($e->getMessage()); +} + +// Handle notifications from query parameters +$notification = null; +if (isset($_GET['success'])) { + $count = (int)$_GET['success']; + $notification = [ + 'type' => 'success', + 'message' => "Successfully imported {$count} records from the CSV." + ]; +} elseif (isset($_GET['error'])) { + $notification = [ + 'type' => 'danger', + 'message' => "An error occurred: " . htmlspecialchars($_GET['error']) + ]; +} elseif (isset($_GET['refreshed'])) { + $notification = [ + 'type' => 'info', + 'message' => "Submission has been queued for refresh." + ]; +} + +// Helper to determine badge color based on status +function get_status_badge_class($status) { + switch (strtolower($status)) { + case 'completed': + return 'bg-success-subtle text-success-emphasis'; + case 'processing': + return 'bg-primary-subtle text-primary-emphasis'; + case 'error': + return 'bg-danger-subtle text-danger-emphasis'; + case 'pending': + default: + return 'bg-secondary-subtle text-secondary-emphasis'; + } } ?> @@ -16,7 +53,7 @@ try { Analyst Dashboard - + @@ -42,15 +79,22 @@ try {
+ + + +

Analyst Dashboard

@@ -61,9 +105,10 @@ try { Name + Company + Location Social Profiles Industry - Geo-Location Status Actions @@ -71,28 +116,34 @@ try { - + No data submitted yet. - + - + + + - + + + + + - - + - - + + - - + + + @@ -104,6 +155,38 @@ try {
- + + + + + \ No newline at end of file diff --git a/db/migrate.php b/db/migrate.php index 3c2dca8..c15b2fe 100644 --- a/db/migrate.php +++ b/db/migrate.php @@ -2,35 +2,55 @@ require_once __DIR__ . '/config.php'; try { - // Connect without specifying a database + // Connect without specifying a database to create it if it doesn't exist $pdo = new PDO('mysql:host='.DB_HOST, DB_USER, DB_PASS, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, ]); $pdo->exec('CREATE DATABASE IF NOT EXISTS '.DB_NAME); echo "Database ".DB_NAME." created or already exists.\n"; } catch (PDOException $e) { - echo "Error creating database: " . $e->getMessage() . "\n"; - // If the user already exists, we might not have permission to create a database. - // Let's assume the DB is there and try to connect anyway for the next step. + // Suppress error if DB exists but user lacks CREATE DB permissions } -// Now, connect to the database and run migrations +// Now, connect to the specific database $pdo = db(); + +// 1. Create migrations table if it doesn't exist +try { + $pdo->exec("\n CREATE TABLE IF NOT EXISTS `migrations` (\n `id` INT AUTO_INCREMENT PRIMARY KEY,\n `migration` VARCHAR(255) NOT NULL,\n `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n )\n "); +} catch (PDOException $e) { + echo "Error creating migrations table: " . $e->getMessage() . "\n"; + exit(1); +} + +// 2. Get all migrations that have been run +$stmt = $pdo->query("SELECT `migration` FROM `migrations`"); +$runMigrations = $stmt->fetchAll(PDO::FETCH_COLUMN); + +// 3. Get all available migration files $migrationsDir = __DIR__ . '/migrations'; $files = glob($migrationsDir . '/*.sql'); - sort($files); +// 4. Run migrations that have not been run yet foreach ($files as $file) { - echo "Applying migration: " . basename($file) . "\n"; - $sql = file_get_contents($file); - try { - $pdo->exec($sql); - echo "Success\n"; - } catch (PDOException $e) { - echo "Error applying migration: " . $e->getMessage() . "\n"; - exit(1); + $migrationName = basename($file); + if (!in_array($migrationName, $runMigrations)) { + echo "Applying migration: " . $migrationName . "\n"; + $sql = file_get_contents($file); + try { + $pdo->exec($sql); + + // Add the migration to the migrations table + $insertStmt = $pdo->prepare("INSERT INTO `migrations` (`migration`) VALUES (?)"); + $insertStmt->execute([$migrationName]); + + echo "Success\n"; + } catch (PDOException $e) { + echo "Error applying migration: " . $e->getMessage() . "\n"; + // Don't exit, allow other migrations to run + } } } -echo "All migrations applied successfully.\n"; \ No newline at end of file +echo "Migration check complete.\n"; diff --git a/db/migrations/002_add_status_and_profile_data_to_submissions.sql b/db/migrations/002_add_status_and_profile_data_to_submissions.sql new file mode 100644 index 0000000..50704a2 --- /dev/null +++ b/db/migrations/002_add_status_and_profile_data_to_submissions.sql @@ -0,0 +1,13 @@ +ALTER TABLE `submissions` +ADD COLUMN `status` VARCHAR(255) NOT NULL DEFAULT 'Pending', +ADD COLUMN `company` VARCHAR(255) NULL, +ADD COLUMN `profile_image_url` VARCHAR(2048) NULL, +ADD COLUMN `location` VARCHAR(255) NULL, +ADD COLUMN `linkedin_url` VARCHAR(2048) NULL, +ADD COLUMN `twitter_url` VARCHAR(2048) NULL, +ADD COLUMN `facebook_url` VARCHAR(2048) NULL, +ADD COLUMN `instagram_url` VARCHAR(2048) NULL, +ADD COLUMN `youtube_url` VARCHAR(2048) NULL, +ADD COLUMN `industry` VARCHAR(255) NULL, +ADD COLUMN `geo_location` VARCHAR(255) NULL, +ADD COLUMN `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; diff --git a/index.php b/index.php index 33ad0dc..69a343f 100644 --- a/index.php +++ b/index.php @@ -10,6 +10,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['name'])) { $stmt = $pdo->prepare("INSERT INTO submissions (name) VALUES (?)"); $stmt->execute([$name]); $success_toast = true; + // Trigger the background worker + shell_exec('php /home/ubuntu/executor/workspace/worker.php > /dev/null 2>&1 &'); } catch (PDOException $e) { // For now, we'll just prevent the success toast on db error. } diff --git a/refresh_submission.php b/refresh_submission.php new file mode 100644 index 0000000..fcda893 --- /dev/null +++ b/refresh_submission.php @@ -0,0 +1,28 @@ +prepare("UPDATE submissions SET status = 'Pending' WHERE id = ?"); + $stmt->execute([$submissionId]); + + // Trigger the background worker + shell_exec('php /home/ubuntu/executor/workspace/worker.php > /dev/null 2>&1 &'); +} catch (PDOException $e) { + // In a real app, log this error + header('Location: analyst_dashboard.php?error=' . urlencode($e->getMessage())); + exit; +} + +// Redirect back with a success message +header('Location: analyst_dashboard.php?refreshed=1'); +exit; diff --git a/upload_csv.php b/upload_csv.php new file mode 100644 index 0000000..8b4d38f --- /dev/null +++ b/upload_csv.php @@ -0,0 +1,76 @@ +prepare("INSERT INTO submissions (name) VALUES (:name)"); + +$importedCount = 0; +$rowCount = 0; + +while (($data = fgetcsv($handle)) !== false) { + $rowCount++; + if ($rowCount > 1000) { + // Stop processing if the file exceeds the row limit + break; + } + + if (isset($data[0]) && !empty(trim($data[0]))) { + try { + $stmt->execute(['name' => trim($data[0])]); + $importedCount++; + } catch (PDOException $e) { + // You might want to log this error instead of ignoring it + // error_log("CSV Import Error: " . $e->getMessage()); + continue; // Continue to the next row + } + } +} + +fclose($handle); + +// Trigger the background worker now that new submissions are in +if ($importedCount > 0) { + shell_exec('php /home/ubuntu/executor/workspace/worker.php > /dev/null 2>&1 &'); +} + +if ($rowCount > 1000) { + header('Location: analyst_dashboard.php?error=' . urlencode('CSV file exceeds the 1000-row limit. Only the first 1000 rows were processed.') . '&success=' . $importedCount); +} else { + header('Location: analyst_dashboard.php?success=' . $importedCount); +} +exit; diff --git a/worker.php b/worker.php new file mode 100644 index 0000000..671d021 --- /dev/null +++ b/worker.php @@ -0,0 +1,93 @@ +prepare($sql); + $stmt->execute([$status, $id]); +} + +/** + * A simple function to extract a domain from a URL. + */ +function get_domain($url) { + $pieces = parse_url($url); + if (isset($pieces['host'])) { + return preg_replace('/^www\./', '', $pieces['host']); + } + return null; +} + +// --- Main Worker Logic --- + +$pdo = db(); + +// 1. Find submissions that are 'Pending' or those that have been 'Processing' for a while (e.g., > 15 mins) +// This helps recover from script crashes. +$stmt = $pdo->query("SELECT * FROM submissions WHERE status = 'Pending' OR (status = 'Processing' AND updated_at < NOW() - INTERVAL 15 MINUTE)"); +$pending_submissions = $stmt->fetchAll(); + +if (empty($pending_submissions)) { + // No work to do, just redirect back. + header('Location: analyst_dashboard.php'); + exit; +} + +foreach ($pending_submissions as $sub) { + $id = $sub['id']; + $name = $sub['name']; + + // 2. Mark as 'Processing' + update_status($pdo, $id, 'Processing'); + + // 3. Simulate fetching data (This is where the Gemini API calls will go) + // For now, we'll use a mock implementation that just populates some data. + try { + // --- MOCK DATA IMPLEMENTATION --- + // In a real scenario, you would use a proper web scraping or API service. + // This is a placeholder to simulate finding profiles. + $social_profiles = [ + 'linkedin_url' => 'https://linkedin.com/in/' . strtolower(str_replace(' ', '', $name)) . rand(1, 99), + 'twitter_url' => 'https://twitter.com/' . strtolower(str_replace(' ', '', $name)), + ]; + + $update_data = array_merge($social_profiles, [ + 'company' => 'Mock Company ' . rand(100, 999), + 'location' => 'Mock Location', + 'industry' => 'Mock Industry', + 'geo_location' => 'Mock Geo', + 'status' => 'Completed' + ]); + + $sql_parts = []; + foreach ($update_data as $key => $value) { + $sql_parts[] = "`$key` = :$key"; + } + $sql = "UPDATE submissions SET " . implode(', ', $sql_parts) . " WHERE id = :id"; + + $stmt = $pdo->prepare($sql); + $update_data['id'] = $id; + $stmt->execute($update_data); + + } catch (Exception $e) { + // If something goes wrong, mark as 'Error' + update_status($pdo, $id, 'Error', $e->getMessage()); + } +} + +// 4. Redirect back to the dashboard +header('Location: analyst_dashboard.php?refreshed=all'); +exit;