s21
This commit is contained in:
parent
3abb7cc4ae
commit
ffcaed889a
133
discover.php
133
discover.php
@ -1,88 +1,59 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
session_start();
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
if (!$user_id) { header('Location: login.php'); exit; }
|
||||
|
||||
$current_user_id = $_SESSION['user_id'];
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$current_user_id]);
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if (!$user) {
|
||||
session_destroy();
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
if (!$user) { header('Location: login.php'); exit; }
|
||||
|
||||
$user_role = $user['role'];
|
||||
$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
|
||||
// Blocked users filter
|
||||
$stmt = db()->prepare("SELECT blocked_id FROM blocked_users WHERE blocker_id = ?");
|
||||
$stmt->execute([$current_user_id]);
|
||||
$blocked_ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
$stmt = db()->prepare("SELECT blocker_id FROM blocked_users WHERE blocked_id = ?");
|
||||
$stmt->execute([$current_user_id]);
|
||||
$blocked_by_ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
$all_blocked = array_unique(array_merge($blocked_ids, $blocked_by_ids));
|
||||
$placeholders = empty($all_blocked) ? "0" : implode(',', array_fill(0, count($all_blocked), '?'));
|
||||
|
||||
// Leaderboard: Most Followed (All Time)
|
||||
$sql = "
|
||||
SELECT s.id, s.name, s.description, u.full_name as founder_name, COUNT(sf.id) as followers_count
|
||||
FROM startups s
|
||||
JOIN users u ON s.founder_id = u.id
|
||||
LEFT JOIN startup_followers sf ON s.id = sf.startup_id
|
||||
WHERE u.id NOT IN ($placeholders)
|
||||
GROUP BY s.id
|
||||
ORDER BY followers_count DESC
|
||||
LIMIT 10
|
||||
";
|
||||
$stmt = db()->prepare($sql);
|
||||
$stmt->execute($all_blocked ?: []);
|
||||
// Leaderboard: Most Followed
|
||||
$stmt = db()->query("
|
||||
SELECT s.*, u.full_name as founder_name, s.followers_count
|
||||
FROM startups s
|
||||
JOIN users u ON s.founder_id = u.id
|
||||
ORDER BY s.followers_count DESC
|
||||
LIMIT 3
|
||||
");
|
||||
$mostFollowed = $stmt->fetchAll();
|
||||
|
||||
// Leaderboard: Most Funded (All Time)
|
||||
$sql = "
|
||||
SELECT s.id, s.name, s.description, u.full_name as founder_name, s.funding_raised as funded_amount
|
||||
// Leaderboard: Most Funded (Total funding raised)
|
||||
$stmt = db()->query("
|
||||
SELECT s.id, s.name, u.full_name as founder_name, s.funding_raised as funded_amount
|
||||
FROM startups s
|
||||
JOIN users u ON s.founder_id = u.id
|
||||
WHERE u.id NOT IN ($placeholders)
|
||||
ORDER BY funded_amount DESC
|
||||
LIMIT 10
|
||||
";
|
||||
$stmt = db()->prepare($sql);
|
||||
$stmt->execute($all_blocked ?: []);
|
||||
ORDER BY s.funding_raised DESC
|
||||
LIMIT 3
|
||||
");
|
||||
$mostFunded = $stmt->fetchAll();
|
||||
|
||||
// Search logic
|
||||
// General Browse
|
||||
$q = $_GET['q'] ?? '';
|
||||
$browseStartups = [];
|
||||
$where = "s.status = 'public' AND u.id NOT IN ($placeholders)";
|
||||
$params = $all_blocked ?: [];
|
||||
$where = "onboarding_completed = 1";
|
||||
$params = [];
|
||||
if ($q) {
|
||||
$where .= " AND (s.name LIKE ? OR s.description LIKE ? OR u.full_name LIKE ?)";
|
||||
$where .= " AND (s.name LIKE ? OR s.description LIKE ? OR s.industry LIKE ?)";
|
||||
$params[] = "%$q%";
|
||||
$params[] = "%$q%";
|
||||
$params[] = "%$q%";
|
||||
}
|
||||
|
||||
$stmt = db()->prepare("
|
||||
SELECT s.*, u.full_name as founder_name
|
||||
FROM startups s
|
||||
JOIN users u ON s.founder_id = u.id
|
||||
WHERE $where
|
||||
ORDER BY s.created_at DESC
|
||||
LIMIT 20
|
||||
LIMIT 12
|
||||
");
|
||||
$stmt->execute($params);
|
||||
$browseStartups = $stmt->fetchAll();
|
||||
|
||||
$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
@ -90,13 +61,15 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Discovery Hub — <?= htmlspecialchars($platformName) ?></title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<style>
|
||||
.hub-header { padding: 60px 0 40px; text-align: center; }
|
||||
.hub-header h1 { font-size: 48px; font-weight: 800; background: var(--gradient-primary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 12px; }
|
||||
.hub-header p { color: var(--text-secondary); font-size: 18px; }
|
||||
.hub-header h1 { font-size: 56px; font-weight: 900; margin-bottom: 12px; background: var(--gradient-primary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
|
||||
.hub-header p { color: var(--text-secondary); font-size: 20px; }
|
||||
.leaderboard-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin-bottom: 60px; }
|
||||
@media (max-width: 900px) { .leaderboard-grid { grid-template-columns: 1fr; } }
|
||||
.lb-card { background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 24px; padding: 30px; backdrop-filter: blur(20px); }
|
||||
@ -130,11 +103,18 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<?php endif; ?>
|
||||
<a href="discover.php" class="active">Discovery Hub</a>
|
||||
<a href="messages.php">Messages</a>
|
||||
<a href="notifications.php">Notifications</a>
|
||||
</nav>
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<a href="dashboard.php" style="color: var(--text-secondary);"><i class="fas fa-th-large"></i></a>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 13px;">Log Out</a>
|
||||
<a href="notifications.php" style="color: var(--text-secondary); position: relative; font-size: 18px;">
|
||||
<i class="fas fa-bell"></i>
|
||||
</a>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 5px 12px; background: rgba(255,255,255,0.05); border-radius: 50px; border: 1px solid var(--border-color);">
|
||||
<div style="width: 24px; height: 24px; background: var(--gradient-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #fff; font-weight: 800;">
|
||||
<?= substr($user['full_name'], 0, 1) ?>
|
||||
</div>
|
||||
<span style="font-size: 13px; font-weight: 600;"><?= htmlspecialchars(explode(' ', $user['full_name'])[0]) ?></span>
|
||||
</div>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 12px; border-radius: 10px;">Log Out</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@ -199,27 +179,28 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<div style="font-size: 13px; color: var(--text-secondary);">by <?= htmlspecialchars($s['founder_name']) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<p style="color: var(--text-secondary); font-size: 14px; line-height: 1.6; margin-bottom: 20px; height: 66px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;">
|
||||
<?= htmlspecialchars($s['description']) ?>
|
||||
<p style="color: var(--text-secondary); font-size: 14px; margin-bottom: 20px; line-height: 1.6; height: 42px; overflow: hidden;">
|
||||
<?= htmlspecialchars(substr($s['description'], 0, 100)) ?>...
|
||||
</p>
|
||||
<div style="display: flex; justify-content: space-between; border-top: 1px solid var(--border-color); padding-top: 20px;">
|
||||
<div>
|
||||
<div style="font-size: 11px; color: var(--text-secondary); text-transform: uppercase;">Raised</div>
|
||||
<div style="font-weight: 700; color: #fff;">£<?= number_format($s['funding_raised']) ?></div>
|
||||
</div>
|
||||
<button class="btn btn-secondary" style="padding: 8px 16px; font-size: 12px;">Details</button>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span class="badge" style="font-size: 10px;"><?= ucfirst($s['industry']) ?></span>
|
||||
<span style="font-weight: 700; color: var(--accent-blue);">£<?= number_format($s['funding_raised']) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
header { background: rgba(10, 10, 15, 0.8); backdrop-filter: blur(20px); border-bottom: 1px solid var(--border-color); padding: 15px 0; position: sticky; top: 0; z-index: 1000; }
|
||||
.nav-links a { color: var(--text-secondary); text-decoration: none; margin: 0 15px; font-size: 14px; font-weight: 500; transition: color 0.2s; }
|
||||
.nav-links a:hover, .nav-links a.active { color: #fff; }
|
||||
.form-control:focus { outline: none; border-color: var(--accent-blue); }
|
||||
</style>
|
||||
<footer style="margin-top: 80px; padding: 60px 0; border-top: 1px solid var(--border-color); background: rgba(0,0,0,0.2);">
|
||||
<div class="container" style="text-align: center;">
|
||||
<div class="logo-container" style="justify-content: center; margin-bottom: 25px;">
|
||||
<img src="assets/images/logo.svg" alt="<?= htmlspecialchars($platformName) ?> Logo" class="logo-img" style="width: 30px; height: 30px;">
|
||||
<span class="logo-text" style="font-size: 20px;"><?= htmlspecialchars($platformName) ?></span>
|
||||
</div>
|
||||
<p style="color: var(--text-secondary); font-size: 14px;">© <?= date('Y') ?> <?= htmlspecialchars($platformName) ?>. All rights reserved.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="assets/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
225
edit_profile.php
225
edit_profile.php
@ -1,69 +1,54 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
session_start();
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
if (!$user_id) { header('Location: login.php'); exit; }
|
||||
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
if (!$user) { header('Location: login.php'); exit; }
|
||||
|
||||
$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
|
||||
$error = '';
|
||||
$success = '';
|
||||
|
||||
// Check for active funding rounds
|
||||
$stmt = db()->prepare("SELECT COUNT(*) FROM startups s JOIN funding_rounds fr ON s.id = fr.startup_id WHERE s.founder_id = ? AND fr.status = 'Active'");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$activeRoundsCount = $stmt->fetchColumn();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['action']) && $_POST['action'] === 'delete_account') {
|
||||
if ($user['role'] === 'founder' && $activeRoundsCount > 0) {
|
||||
$error = "You cannot delete your account with active funding rounds. Please finish or cancel them first.";
|
||||
} else {
|
||||
// Delete account
|
||||
db()->beginTransaction();
|
||||
try {
|
||||
// Remove profile (cascades or sets null according to our migration)
|
||||
$stmt = db()->prepare("DELETE FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
db()->commit();
|
||||
|
||||
session_destroy();
|
||||
header("Location: login.php?msg=account_deleted");
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
db()->rollBack();
|
||||
$error = "Account deletion failed: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$full_name = trim($_POST['full_name'] ?? '');
|
||||
$bio = trim($_POST['bio'] ?? '');
|
||||
$interests = trim($_POST['interests'] ?? '');
|
||||
$investment_appetite = trim($_POST['investment_appetite'] ?? '');
|
||||
if (isset($_POST['action']) && $_POST['action'] === 'update_profile') {
|
||||
$full_name = trim($_POST['full_name']);
|
||||
$bio = trim($_POST['bio']);
|
||||
$university = trim($_POST['university']);
|
||||
$degree_program = trim($_POST['degree_program']);
|
||||
$skills = trim($_POST['skills']);
|
||||
$startup_industries = trim($_POST['startup_industries']);
|
||||
|
||||
if (empty($full_name)) {
|
||||
$error = "Name cannot be empty.";
|
||||
if ($full_name) {
|
||||
$stmt = db()->prepare("UPDATE users SET full_name = ?, bio = ?, university = ?, degree_program = ?, skills = ?, startup_industries = ? WHERE id = ?");
|
||||
$stmt->execute([$full_name, $bio, $university, $degree_program, $skills, $startup_industries, $user_id]);
|
||||
$success = "Profile updated successfully!";
|
||||
// Refresh user data
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
} else {
|
||||
$stmt = db()->prepare("UPDATE users SET full_name = ?, bio = ?, interests = ?, investment_appetite = ? WHERE id = ?");
|
||||
try {
|
||||
$stmt->execute([$full_name, $bio, $interests, $investment_appetite, $_SESSION['user_id']]);
|
||||
$success = "Profile updated successfully!";
|
||||
// Update session if name changed
|
||||
$_SESSION['full_name'] = $full_name;
|
||||
// Refresh user data
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$user = $stmt->fetch();
|
||||
} catch (PDOException $e) {
|
||||
$error = "Update failed: " . $e->getMessage();
|
||||
}
|
||||
$error = "Full name is required.";
|
||||
}
|
||||
} elseif (isset($_POST['action']) && $_POST['action'] === 'delete_account') {
|
||||
try {
|
||||
db()->beginTransaction();
|
||||
db()->prepare("DELETE FROM startup_followers WHERE user_id = ?")->execute([$user_id]);
|
||||
db()->prepare("DELETE FROM matches WHERE user1_id = ? OR user2_id = ?")->execute([$user_id, $user_id]);
|
||||
db()->prepare("DELETE FROM swipes WHERE swiper_id = ? OR swiped_id = ?")->execute([$user_id, $user_id]);
|
||||
db()->prepare("DELETE FROM notifications WHERE user_id = ?")->execute([$user_id]);
|
||||
db()->prepare("DELETE FROM users WHERE id = ?")->execute([$user_id]);
|
||||
db()->commit();
|
||||
session_destroy();
|
||||
header("Location: login.php?msg=account_deleted");
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
db()->rollBack();
|
||||
$error = "Account deletion failed: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -74,120 +59,106 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Edit Profile — <?= htmlspecialchars($platformName) ?></title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
</head>
|
||||
<body style="padding-bottom: 60px;">
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<div class="container" style="display: flex; justify-content: space-between; align-items: center; width: 100%;">
|
||||
<div class="logo"><?= htmlspecialchars($platformName) ?></div>
|
||||
<a href="dashboard.php" class="logo-container">
|
||||
<img src="assets/images/logo.svg" alt="<?= htmlspecialchars($platformName) ?> Logo" class="logo-img">
|
||||
<span class="logo-text"><?= htmlspecialchars($platformName) ?></span>
|
||||
</a>
|
||||
<nav class="nav-links">
|
||||
<?php if ($user['role'] === 'founder'): ?>
|
||||
<a href="startups.php">My Startups</a>
|
||||
<a href="discover.php">Find Partners</a>
|
||||
<a href="partners.php">Find Partners</a>
|
||||
<?php else: ?>
|
||||
<a href="discover.php">Discover</a>
|
||||
<a href="startups.php">Browse Startups</a>
|
||||
<a href="portfolio.php">Portfolio</a>
|
||||
<?php endif; ?>
|
||||
<a href="discover.php">Discovery Hub</a>
|
||||
<a href="messages.php">Messages</a>
|
||||
<a href="notifications.php">Notifications</a>
|
||||
</nav>
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<a href="dashboard.php" class="btn btn-secondary" style="padding: 8px 16px;">Back to Dashboard</a>
|
||||
<a href="notifications.php" style="color: var(--text-secondary); position: relative; font-size: 18px;">
|
||||
<i class="fas fa-bell"></i>
|
||||
</a>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 5px 12px; background: rgba(255,255,255,0.05); border-radius: 50px; border: 1px solid var(--border-color);">
|
||||
<div style="width: 24px; height: 24px; background: var(--gradient-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #fff; font-weight: 800;">
|
||||
<?= substr($user['full_name'], 0, 1) ?>
|
||||
</div>
|
||||
<span style="font-size: 13px; font-weight: 600;"><?= htmlspecialchars(explode(' ', $user['full_name'])[0]) ?></span>
|
||||
</div>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 12px; border-radius: 10px;">Log Out</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container" style="padding-top: 50px;">
|
||||
<main class="container" style="padding-top: 50px; padding-bottom: 80px;">
|
||||
<div style="max-width: 600px; margin: 0 auto;">
|
||||
<h1>Edit Profile</h1>
|
||||
<p style="color: var(--text-secondary); margin-bottom: 40px;">Manage your public presence in the <?= htmlspecialchars($platformName) ?> community.</p>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div style="background: rgba(255, 0, 0, 0.1); border: 1px solid rgba(255, 0, 0, 0.3); color: #ff5555; padding: 12px; border-radius: 8px; margin-bottom: 20px;">
|
||||
<?= htmlspecialchars($error) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($error): ?><div class="alert alert-danger" style="margin-bottom: 30px;"><?= htmlspecialchars($error) ?></div><?php endif; ?>
|
||||
<?php if ($success): ?><div class="alert alert-success" style="margin-bottom: 30px;"><?= htmlspecialchars($success) ?></div><?php endif; ?>
|
||||
|
||||
<?php if ($success): ?>
|
||||
<div style="background: rgba(0, 255, 0, 0.1); border: 1px solid rgba(0, 255, 0, 0.3); color: #55ff55; padding: 12px; border-radius: 8px; margin-bottom: 20px;">
|
||||
<?= htmlspecialchars($success) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card" style="margin-bottom: 30px;">
|
||||
<div class="card">
|
||||
<form method="POST">
|
||||
<div style="margin-bottom: 20px;">
|
||||
<label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500;">Full Name</label>
|
||||
<input type="text" name="full_name" value="<?= htmlspecialchars($user['full_name']) ?>" required style="width: 100%; padding: 12px; border-radius: 12px; background: var(--surface-color); border: 1px solid var(--border-color); color: #fff;">
|
||||
<input type="hidden" name="action" value="update_profile">
|
||||
<div class="form-group" style="margin-bottom: 20px;">
|
||||
<label>Full Name</label>
|
||||
<input type="text" name="full_name" class="form-control" value="<?= htmlspecialchars($user['full_name']) ?>" required style="background: var(--surface-color); color: #fff; border: 1px solid var(--border-color);">
|
||||
</div>
|
||||
<div style="margin-bottom: 20px;">
|
||||
<label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500;">University</label>
|
||||
<input type="text" value="<?= htmlspecialchars($user['university']) ?>" disabled style="width: 100%; padding: 12px; border-radius: 12px; background: rgba(255,255,255,0.05); border: 1px solid var(--border-color); color: var(--text-secondary);">
|
||||
<span style="font-size: 12px; color: var(--text-secondary); margin-top: 4px; display: block;">University status is verified and cannot be changed.</span>
|
||||
<div class="form-group" style="margin-bottom: 20px;">
|
||||
<label>Bio</label>
|
||||
<textarea name="bio" class="form-control" rows="4" style="background: var(--surface-color); color: #fff; border: 1px solid var(--border-color);"><?= htmlspecialchars($user['bio']) ?></textarea>
|
||||
</div>
|
||||
<div style="margin-bottom: 20px;">
|
||||
<label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500;">Bio / Vision</label>
|
||||
<textarea name="bio" placeholder="What are you building or looking for?" style="width: 100%; padding: 12px; border-radius: 12px; background: var(--surface-color); border: 1px solid var(--border-color); color: #fff; height: 120px; resize: none;"><?= htmlspecialchars($user['bio'] ?? '') ?></textarea>
|
||||
<div class="form-group" style="margin-bottom: 20px;">
|
||||
<label>University</label>
|
||||
<input type="text" name="university" class="form-control" value="<?= htmlspecialchars($user['university']) ?>" style="background: var(--surface-color); color: #fff; border: 1px solid var(--border-color);">
|
||||
</div>
|
||||
<div style="margin-bottom: 20px;">
|
||||
<label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500;">Interests / Skills (Comma separated)</label>
|
||||
<input type="text" name="interests" value="<?= htmlspecialchars($user['interests'] ?? '') ?>" placeholder="Fintech, AI, Sustainable Fashion, Marketing" style="width: 100%; padding: 12px; border-radius: 12px; background: var(--surface-color); border: 1px solid var(--border-color); color: #fff;">
|
||||
<div class="form-group" style="margin-bottom: 20px;">
|
||||
<label>Degree Program</label>
|
||||
<input type="text" name="degree_program" class="form-control" value="<?= htmlspecialchars($user['degree_program']) ?>" style="background: var(--surface-color); color: #fff; border: 1px solid var(--border-color);">
|
||||
</div>
|
||||
<?php if ($user['role'] === 'investor'): ?>
|
||||
<div style="margin-bottom: 30px;">
|
||||
<label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500;">Investment Appetite</label>
|
||||
<select name="investment_appetite" style="width: 100%; padding: 12px; border-radius: 12px; background: var(--surface-color); border: 1px solid var(--border-color); color: #fff;">
|
||||
<option value="Micro (£50 - £500)" <?= ($user['investment_appetite'] === 'Micro (£50 - £500)') ? 'selected' : '' ?>>Micro (£50 - £500)</option>
|
||||
<option value="Standard (£500 - £5k)" <?= ($user['investment_appetite'] === 'Standard (£500 - £5k)') ? 'selected' : '' ?>>Standard (£500 - £5k)</option>
|
||||
<option value="Angel (£5k+)" <?= ($user['investment_appetite'] === 'Angel (£5k+)') ? 'selected' : '' ?>>Angel (£5k+)</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<button type="submit" class="btn btn-primary" style="width: 100%; padding: 15px;">Save Changes</button>
|
||||
<div class="form-group" style="margin-bottom: 20px;">
|
||||
<label>Skills (comma separated)</label>
|
||||
<input type="text" name="skills" class="form-control" value="<?= htmlspecialchars($user['skills']) ?>" style="background: var(--surface-color); color: #fff; border: 1px solid var(--border-color);">
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom: 30px;">
|
||||
<label>Industries of Interest (comma separated)</label>
|
||||
<input type="text" name="startup_industries" class="form-control" value="<?= htmlspecialchars($user['startup_industries']) ?>" style="background: var(--surface-color); color: #fff; border: 1px solid var(--border-color);">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" style="width: 100%;">Save Changes</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php if ($user['role'] === 'founder'): ?>
|
||||
<div class="card" style="border: 1px solid rgba(255, 85, 85, 0.3); background: rgba(255, 85, 85, 0.05);">
|
||||
<h3 style="color: #ff5555; margin-bottom: 15px;">Danger Zone</h3>
|
||||
<p style="color: var(--text-secondary); font-size: 14px; margin-bottom: 20px;">Deleting your account is permanent and cannot be undone. All your profile information will be removed, but your startup listings will remain.</p>
|
||||
|
||||
<button onclick="confirmDelete()" class="btn btn-secondary" style="border-color: #ff5555; color: #ff5555;">Delete My Account</button>
|
||||
|
||||
<form id="deleteForm" method="POST" style="display: none;">
|
||||
<div class="card" style="margin-top: 40px; border-color: rgba(255, 77, 77, 0.2);">
|
||||
<h3 style="color: #ff4d4d;">Danger Zone</h3>
|
||||
<p style="color: var(--text-secondary); font-size: 14px; margin-bottom: 25px;">Deleting your account is permanent. All your data, startups, and matches will be removed.</p>
|
||||
<form method="POST" onsubmit="return confirm('Are you absolutely sure you want to delete your account? This cannot be undone.');">
|
||||
<input type="hidden" name="action" value="delete_account">
|
||||
<button type="submit" class="btn btn-secondary" style="color: #ff4d4d; border-color: rgba(255, 77, 77, 0.2);">Delete My Account</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div id="deleteModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 2000; align-items: center; justify-content: center;">
|
||||
<div class="card" style="max-width: 400px; text-align: center; padding: 40px;">
|
||||
<i class="fas fa-exclamation-triangle" style="font-size: 48px; color: #ff5555; margin-bottom: 20px;"></i>
|
||||
<h3>Permanent Deletion</h3>
|
||||
<p style="color: var(--text-secondary); margin-bottom: 30px;">Are you sure you want to permanently delete your account? This action cannot be undone.</p>
|
||||
<div style="display: flex; gap: 15px;">
|
||||
<button onclick="closeModal()" class="btn btn-secondary" style="flex: 1;">Cancel</button>
|
||||
<button onclick="submitDelete()" class="btn btn-primary" style="flex: 1; background: #ff5555; border-color: #ff5555;">Yes, Delete</button>
|
||||
<footer style="margin-top: 80px; padding: 60px 0; border-top: 1px solid var(--border-color); background: rgba(0,0,0,0.2);">
|
||||
<div class="container" style="text-align: center;">
|
||||
<div class="logo-container" style="justify-content: center; margin-bottom: 25px;">
|
||||
<img src="assets/images/logo.svg" alt="<?= htmlspecialchars($platformName) ?> Logo" class="logo-img" style="width: 30px; height: 30px;">
|
||||
<span class="logo-text" style="font-size: 20px;"><?= htmlspecialchars($platformName) ?></span>
|
||||
</div>
|
||||
<p style="color: var(--text-secondary); font-size: 14px;">© <?= date('Y') ?> <?= htmlspecialchars($platformName) ?>. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function confirmDelete() {
|
||||
document.getElementById('deleteModal').style.display = 'flex';
|
||||
}
|
||||
function closeModal() {
|
||||
document.getElementById('deleteModal').style.display = 'none';
|
||||
}
|
||||
function submitDelete() {
|
||||
document.getElementById('deleteForm').submit();
|
||||
}
|
||||
</script>
|
||||
</footer>
|
||||
|
||||
<script src="assets/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
397
messages.php
397
messages.php
@ -1,53 +1,18 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
session_start();
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
if (!$user_id) { header('Location: login.php'); exit; }
|
||||
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
if (!$user) { header('Location: login.php'); exit; }
|
||||
|
||||
$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
|
||||
// Handle Actions (Accept/Reject/Unmatch/Block)
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && isset($_POST['other_user_id'])) {
|
||||
$other_id = (int)$_POST['other_user_id'];
|
||||
$action = $_POST['action'];
|
||||
|
||||
if ($action === 'accept') {
|
||||
$stmt = db()->prepare("UPDATE messages SET status = 'accepted' WHERE sender_id = ? AND receiver_id = ? AND status = 'pending'");
|
||||
$stmt->execute([$other_id, $user_id]);
|
||||
$stmt = db()->prepare("INSERT INTO notifications (user_id, content) VALUES (?, ?)");
|
||||
$stmt->execute([$other_id, "Your message request to " . $user['full_name'] . " has been accepted."]);
|
||||
header("Location: messages.php?chat_with=$other_id");
|
||||
exit;
|
||||
} elseif ($action === 'reject') {
|
||||
$stmt = db()->prepare("UPDATE messages SET status = 'rejected' WHERE sender_id = ? AND receiver_id = ? AND status = 'pending'");
|
||||
$stmt->execute([$other_id, $user_id]);
|
||||
header("Location: messages.php");
|
||||
exit;
|
||||
} elseif ($action === 'unmatch') {
|
||||
$stmt = db()->prepare("UPDATE matches SET status = 'unmatched' WHERE (user1_id = ? AND user2_id = ?) OR (user1_id = ? AND user2_id = ?)");
|
||||
$stmt->execute([$user_id, $other_id, $other_id, $user_id]);
|
||||
header("Location: messages.php");
|
||||
exit;
|
||||
} elseif ($action === 'block') {
|
||||
$stmt = db()->prepare("INSERT IGNORE INTO blocked_users (blocker_id, blocked_id) VALUES (?, ?)");
|
||||
$stmt->execute([$user_id, $other_id]);
|
||||
// Also unmatch if they were matched
|
||||
$stmt = db()->prepare("UPDATE matches SET status = 'unmatched' WHERE (user1_id = ? AND user2_id = ?) OR (user1_id = ? AND user2_id = ?)");
|
||||
$stmt->execute([$user_id, $other_id, $other_id, $user_id]);
|
||||
header("Location: messages.php");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch Blocked Users to filter them out
|
||||
// Fetch Blocked Users
|
||||
$stmt = db()->prepare("SELECT blocked_id FROM blocked_users WHERE blocker_id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$blocked_ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
@ -63,8 +28,7 @@ $placeholders = empty($all_blocked) ? "0" : implode(',', array_fill(0, count($al
|
||||
$matches = [];
|
||||
if ($user['role'] === 'founder') {
|
||||
$sql = "
|
||||
SELECT m.*,
|
||||
u.full_name as match_name,
|
||||
SELECT u.full_name as match_name,
|
||||
u.id as match_id,
|
||||
u.university,
|
||||
u.degree_program
|
||||
@ -89,7 +53,6 @@ $sql = "
|
||||
WHERE ((m.sender_id = ? OR m.receiver_id = ?) AND u.id != ?)
|
||||
AND (m.status = 'accepted' OR (m.status = 'pending' AND m.receiver_id = ?))
|
||||
AND u.id NOT IN ($placeholders)
|
||||
ORDER BY (SELECT MAX(created_at) FROM messages WHERE (sender_id = m.sender_id AND receiver_id = m.receiver_id) OR (sender_id = m.receiver_id AND receiver_id = m.sender_id)) DESC
|
||||
";
|
||||
$stmt = db()->prepare($sql);
|
||||
$params = array_merge([$user_id, $user_id, $user_id, $user_id], $all_blocked ?: []);
|
||||
@ -97,7 +60,6 @@ $stmt->execute($params);
|
||||
$conversations = $stmt->fetchAll();
|
||||
|
||||
$active_chat_id = isset($_GET['chat_with']) ? (int)$_GET['chat_with'] : null;
|
||||
$startup_id = isset($_GET['startup_id']) ? (int)$_GET['startup_id'] : null;
|
||||
$active_chat_user = null;
|
||||
$chat_messages = [];
|
||||
$can_reply = true;
|
||||
@ -105,75 +67,33 @@ $needs_acceptance = false;
|
||||
$is_currently_matched = false;
|
||||
|
||||
if ($active_chat_id) {
|
||||
// Check if blocked
|
||||
if (in_array($active_chat_id, $all_blocked)) {
|
||||
header("Location: messages.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (in_array($active_chat_id, $all_blocked)) { header("Location: messages.php"); exit; }
|
||||
$stmt = db()->prepare("SELECT id, full_name, role FROM users WHERE id = ?");
|
||||
$stmt->execute([$active_chat_id]);
|
||||
$active_chat_user = $stmt->fetch();
|
||||
|
||||
if ($active_chat_user) {
|
||||
$stmt = db()->prepare("
|
||||
SELECT * FROM messages
|
||||
WHERE ((sender_id = ? AND receiver_id = ?)
|
||||
OR (sender_id = ? AND receiver_id = ?))
|
||||
AND status != 'rejected'
|
||||
ORDER BY created_at ASC
|
||||
");
|
||||
$stmt = db()->prepare("SELECT * FROM messages WHERE ((sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)) AND status != 'rejected' ORDER BY created_at ASC");
|
||||
$stmt->execute([$user_id, $active_chat_id, $active_chat_id, $user_id]);
|
||||
$chat_messages = $stmt->fetchAll();
|
||||
|
||||
$stmt = db()->prepare("SELECT 1 FROM messages WHERE ((sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)) AND status = 'accepted'");
|
||||
$stmt->execute([$user_id, $active_chat_id, $active_chat_id, $user_id]);
|
||||
$has_accepted = (bool)$stmt->fetchColumn();
|
||||
|
||||
$stmt = db()->prepare("SELECT 1 FROM matches WHERE ((user1_id = ? AND user2_id = ?) OR (user1_id = ? AND user2_id = ?)) AND status = 'active'");
|
||||
$stmt->execute([$user_id, $active_chat_id, $active_chat_id, $user_id]);
|
||||
$is_currently_matched = (bool)$stmt->fetchColumn();
|
||||
|
||||
$stmt = db()->prepare("SELECT 1 FROM messages WHERE sender_id = ? AND receiver_id = ? AND status = 'pending'");
|
||||
$stmt->execute([$active_chat_id, $user_id]);
|
||||
$has_pending_from_other = (bool)$stmt->fetchColumn();
|
||||
|
||||
if (!$has_accepted && !$is_currently_matched && $has_pending_from_other) {
|
||||
$can_reply = false;
|
||||
$needs_acceptance = true;
|
||||
}
|
||||
if (!$has_accepted && !$is_currently_matched && (bool)$stmt->fetchColumn()) { $can_reply = false; $needs_acceptance = true; }
|
||||
}
|
||||
}
|
||||
|
||||
// Handle sending message
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['content']) && $active_chat_id && $can_reply) {
|
||||
$content = trim($_POST['content']);
|
||||
if (!empty($content)) {
|
||||
$status = 'accepted';
|
||||
$stmt = db()->prepare("SELECT 1 FROM matches WHERE ((user1_id = ? AND user2_id = ?) OR (user1_id = ? AND user2_id = ?)) AND status = 'active'");
|
||||
$stmt->execute([$user_id, $active_chat_id, $active_chat_id, $user_id]);
|
||||
$is_match = (bool)$stmt->fetchColumn();
|
||||
|
||||
$stmt = db()->prepare("SELECT 1 FROM messages WHERE ((sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)) AND status = 'accepted'");
|
||||
$stmt->execute([$user_id, $active_chat_id, $active_chat_id, $user_id]);
|
||||
$is_accepted = (bool)$stmt->fetchColumn();
|
||||
|
||||
if (!$is_match && !$is_accepted) {
|
||||
if ($startup_id) {
|
||||
$stmt = db()->prepare("SELECT status, name FROM startups WHERE id = ?");
|
||||
$stmt->execute([$startup_id]);
|
||||
$s = $stmt->fetch();
|
||||
if ($s && $s['status'] === 'private') {
|
||||
$status = 'pending';
|
||||
$stmt = db()->prepare("INSERT INTO notifications (user_id, content) VALUES (?, ?)");
|
||||
$stmt->execute([$active_chat_id, "New message request from " . $user['full_name'] . " regarding " . $s['name'] . "."]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = db()->prepare("INSERT INTO messages (sender_id, receiver_id, content, status, startup_id) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$user_id, $active_chat_id, $content, $status, $startup_id]);
|
||||
header("Location: messages.php?chat_with=$active_chat_id");
|
||||
$status = ($is_currently_matched || (isset($has_accepted) && $has_accepted)) ? 'accepted' : 'pending';
|
||||
$stmt = db()->prepare("INSERT INTO messages (sender_id, receiver_id, content, status) VALUES (?, ?, ?, ?)");
|
||||
$stmt->execute([$user_id, $active_chat_id, $content, $status]);
|
||||
header("Location: messages.php?chat_with=" . $active_chat_id);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@ -184,240 +104,155 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['content']) && $active
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Messages — <?= htmlspecialchars($platformName) ?></title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<style>
|
||||
.chat-container {
|
||||
display: grid;
|
||||
grid-template-columns: 350px 1fr;
|
||||
gap: 0;
|
||||
height: calc(100vh - 150px);
|
||||
background: var(--card-bg);
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
.chat-sidebar {
|
||||
border-right: 1px solid var(--border-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: rgba(255,255,255,0.02);
|
||||
}
|
||||
.chat-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: transparent;
|
||||
}
|
||||
.conv-item {
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
position: relative;
|
||||
}
|
||||
.conv-item:hover { background: rgba(255,255,255,0.05); }
|
||||
.conv-item.active { background: rgba(0, 122, 255, 0.1); border-left: 3px solid var(--accent-blue); }
|
||||
.avatar-sm {
|
||||
width: 40px; height: 40px; border-radius: 12px; background: var(--gradient-primary);
|
||||
display: flex; align-items: center; justify-content: center; font-weight: 700; color: #fff;
|
||||
}
|
||||
.chat-header { padding: 15px 25px; border-bottom: 1px solid var(--border-color); display: flex; align-items: center; justify-content: space-between; }
|
||||
.chat-messages { flex: 1; overflow-y: auto; padding: 25px; display: flex; flex-direction: column; gap: 15px; }
|
||||
.msg-bubble {
|
||||
max-width: 70%; padding: 12px 18px; border-radius: 18px; font-size: 14px; line-height: 1.5;
|
||||
position: relative;
|
||||
}
|
||||
.msg-sent { align-self: flex-end; background: var(--accent-blue); color: #fff; border-bottom-right-radius: 4px; }
|
||||
.msg-received { align-self: flex-start; background: var(--surface-color); border: 1px solid var(--border-color); border-bottom-left-radius: 4px; }
|
||||
.chat-input { padding: 20px; border-top: 1px solid var(--border-color); display: flex; gap: 15px; }
|
||||
.chat-input input {
|
||||
flex: 1; padding: 12px 20px; border-radius: 12px; background: var(--surface-color); border: 1px solid var(--border-color); color: #fff;
|
||||
}
|
||||
.status-badge {
|
||||
font-size: 10px; padding: 2px 6px; border-radius: 4px; font-weight: 700; text-transform: uppercase;
|
||||
}
|
||||
.status-pending { background: #ffcc00; color: #000; }
|
||||
.request-panel {
|
||||
padding: 20px; background: rgba(255, 204, 0, 0.1); border-top: 1px solid rgba(255, 204, 0, 0.2);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Action Menu */
|
||||
.action-menu { position: relative; }
|
||||
.action-menu-content {
|
||||
display: none; position: absolute; right: 0; top: 100%;
|
||||
background: var(--surface-color); border: 1px solid var(--border-color);
|
||||
border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.5);
|
||||
z-index: 100; min-width: 150px;
|
||||
}
|
||||
.action-menu:hover .action-menu-content { display: block; }
|
||||
.action-link {
|
||||
display: block; padding: 10px 15px; color: var(--text-secondary);
|
||||
text-decoration: none; font-size: 13px; transition: all 0.2s;
|
||||
background: none; border: none; width: 100%; text-align: left; cursor: pointer;
|
||||
}
|
||||
.action-link:hover { background: rgba(255,255,255,0.05); color: #fff; }
|
||||
.action-link.danger { color: #ff3b30; }
|
||||
.action-link.danger:hover { background: rgba(255, 59, 48, 0.1); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<div class="container" style="display: flex; justify-content: space-between; align-items: center; width: 100%;">
|
||||
<div class="logo"><?= htmlspecialchars($platformName) ?></div>
|
||||
<a href="dashboard.php" class="logo-container">
|
||||
<img src="assets/images/logo.svg" alt="<?= htmlspecialchars($platformName) ?> Logo" class="logo-img">
|
||||
<span class="logo-text"><?= htmlspecialchars($platformName) ?></span>
|
||||
</a>
|
||||
<nav class="nav-links">
|
||||
<?php if ($user['role'] === 'founder'): ?>
|
||||
<a href="startups.php">My Startups</a>
|
||||
<a href="discover.php">Find Partners</a>
|
||||
<a href="partners.php">Find Partners</a>
|
||||
<?php else: ?>
|
||||
<a href="startups.php">Browse Startups</a>
|
||||
<a href="portfolio.php">Portfolio</a>
|
||||
<?php endif; ?>
|
||||
<a href="discover.php">Discovery Hub</a>
|
||||
<a href="messages.php" class="active">Messages</a>
|
||||
<a href="notifications.php">Notifications</a>
|
||||
</nav>
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<a href="dashboard.php" style="color: var(--text-secondary);"><i class="fas fa-th-large"></i></a>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px;">Log Out</a>
|
||||
<a href="notifications.php" style="color: var(--text-secondary); position: relative; font-size: 18px;">
|
||||
<i class="fas fa-bell"></i>
|
||||
</a>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 5px 12px; background: rgba(255,255,255,0.05); border-radius: 50px; border: 1px solid var(--border-color);">
|
||||
<div style="width: 24px; height: 24px; background: var(--gradient-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #fff; font-weight: 800;">
|
||||
<?= substr($user['full_name'], 0, 1) ?>
|
||||
</div>
|
||||
<span style="font-size: 13px; font-weight: 600;"><?= htmlspecialchars(explode(' ', $user['full_name'])[0]) ?></span>
|
||||
</div>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 12px; border-radius: 10px;">Log Out</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container" style="padding-top: 30px;">
|
||||
<div class="chat-container">
|
||||
<div class="chat-sidebar">
|
||||
<div style="padding: 20px; font-weight: 700; border-bottom: 1px solid var(--border-color);">Conversations</div>
|
||||
|
||||
<?php if ($user['role'] === 'founder' && !empty($matches)): ?>
|
||||
<div style="padding: 10px 20px; font-size: 11px; text-transform: uppercase; color: var(--text-secondary); letter-spacing: 1px;">New Matches</div>
|
||||
<main class="container" style="padding-top: 30px; padding-bottom: 50px; height: calc(100vh - 100px); display: flex; gap: 30px;">
|
||||
<div style="width: 350px; flex-shrink: 0; background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 24px; display: flex; flex-direction: column; overflow: hidden;">
|
||||
<div style="padding: 25px; border-bottom: 1px solid var(--border-color);">
|
||||
<h2 style="margin: 0; font-size: 24px;">Inbox</h2>
|
||||
</div>
|
||||
|
||||
<?php if ($user['role'] === 'founder' && !empty($matches)): ?>
|
||||
<div style="padding: 15px 25px; font-size: 12px; text-transform: uppercase; letter-spacing: 1px; color: var(--text-secondary); font-weight: 700;">New Matches</div>
|
||||
<div style="padding: 0 15px 15px; display: flex; gap: 10px; overflow-x: auto; scrollbar-width: none;">
|
||||
<?php foreach ($matches as $match): ?>
|
||||
<?php
|
||||
$hasConv = false;
|
||||
foreach ($conversations as $c) { if ($c['other_user_id'] == $match['match_id']) $hasConv = true; }
|
||||
if ($hasConv) continue;
|
||||
?>
|
||||
<div class="conv-item <?= $active_chat_id == $match['match_id'] ? 'active' : '' ?>" onclick="window.location.href='messages.php?chat_with=<?= $match['match_id'] ?>'">
|
||||
<div class="avatar-sm" style="background: var(--accent-blue);"><?= substr($match['match_name'], 0, 1) ?></div>
|
||||
<div>
|
||||
<div style="font-weight: 600; font-size: 14px;"><?= htmlspecialchars($match['match_name']) ?></div>
|
||||
<div style="font-size: 11px; color: var(--accent-blue);">New Match! Say hi!</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="messages.php?chat_with=<?= $match['match_id'] ?>" style="flex-shrink: 0; width: 60px; height: 60px; background: var(--surface-color); border: 1px solid var(--accent-blue); border-radius: 18px; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 800; color: #fff; text-decoration: none;">
|
||||
<?= substr($match['match_name'], 0, 1) ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div style="padding: 15px 20px 10px; font-size: 11px; text-transform: uppercase; color: var(--text-secondary); letter-spacing: 1px;">Recent Chats</div>
|
||||
<div style="flex: 1; overflow-y: auto; padding: 10px;">
|
||||
<?php if (empty($conversations)): ?>
|
||||
<div style="padding: 20px; text-align: center; color: var(--text-secondary); font-size: 13px;">No active chats.</div>
|
||||
<div style="text-align: center; padding: 40px 20px; color: var(--text-secondary);">
|
||||
<i class="fas fa-comments" style="font-size: 32px; opacity: 0.2; margin-bottom: 15px;"></i>
|
||||
<p style="font-size: 14px;">No active conversations yet.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($conversations as $conv): ?>
|
||||
<?php
|
||||
$stmt = db()->prepare("SELECT 1 FROM messages WHERE sender_id = ? AND receiver_id = ? AND status = 'pending'");
|
||||
$stmt->execute([$conv['other_user_id'], $user_id]);
|
||||
$isPending = (bool)$stmt->fetchColumn();
|
||||
?>
|
||||
<div class="conv-item <?= $active_chat_id == $conv['other_user_id'] ? 'active' : '' ?>" onclick="window.location.href='messages.php?chat_with=<?= $conv['other_user_id'] ?>'">
|
||||
<div class="avatar-sm"><?= substr($conv['other_user_name'], 0, 1) ?></div>
|
||||
<div>
|
||||
<div style="font-weight: 600; font-size: 14px;"><?= htmlspecialchars($conv['other_user_name']) ?></div>
|
||||
<div style="font-size: 12px; color: var(--text-secondary);">
|
||||
<?= ucfirst($conv['other_role']) ?>
|
||||
<?php if ($isPending): ?>
|
||||
<span class="status-badge status-pending">Request</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<a href="messages.php?chat_with=<?= $conv['other_user_id'] ?>" style="display: flex; align-items: center; gap: 15px; padding: 15px; border-radius: 16px; text-decoration: none; color: inherit; transition: background 0.2s; margin-bottom: 5px; <?= $active_chat_id == $conv['other_user_id'] ? 'background: rgba(255,255,255,0.06); border: 1px solid var(--border-color);' : '' ?>">
|
||||
<div style="width: 48px; height: 48px; border-radius: 14px; background: var(--surface-color); display: flex; align-items: center; justify-content: center; font-weight: 800; border: 1px solid var(--border-color);">
|
||||
<?= substr($conv['other_user_name'], 0, 1) ?>
|
||||
</div>
|
||||
</div>
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<div style="font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;"><?= htmlspecialchars($conv['other_user_name']) ?></div>
|
||||
<div style="font-size: 12px; color: var(--text-secondary);"><?= ucfirst($conv['other_role']) ?></div>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chat-main">
|
||||
<?php if ($active_chat_user): ?>
|
||||
<div class="chat-header">
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<div class="avatar-sm"><?= substr($active_chat_user['full_name'], 0, 1) ?></div>
|
||||
<div>
|
||||
<div style="font-weight: 700;"><?= htmlspecialchars($active_chat_user['full_name']) ?></div>
|
||||
<div style="font-size: 12px; color: var(--text-secondary);"><?= ucfirst($active_chat_user['role']) ?></div>
|
||||
</div>
|
||||
<div style="flex: 1; background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 24px; display: flex; flex-direction: column; overflow: hidden; position: relative;">
|
||||
<?php if (!$active_chat_user): ?>
|
||||
<div style="flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--text-secondary); text-align: center; padding: 40px;">
|
||||
<div style="width: 100px; height: 100px; background: var(--surface-color); border-radius: 30px; display: flex; align-items: center; justify-content: center; font-size: 40px; margin-bottom: 30px; border: 1px solid var(--border-color);">
|
||||
<i class="fas fa-paper-plane" style="opacity: 0.1;"></i>
|
||||
</div>
|
||||
<h3>Your Conversations</h3>
|
||||
<p style="max-width: 300px;">Select a person from the sidebar to start chatting or view your match history.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div style="padding: 20px 30px; border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: center; background: rgba(255,255,255,0.02);">
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<div style="width: 40px; height: 40px; border-radius: 12px; background: var(--surface-color); display: flex; align-items: center; justify-content: center; font-weight: 800; border: 1px solid var(--border-color);">
|
||||
<?= substr($active_chat_user['full_name'], 0, 1) ?>
|
||||
</div>
|
||||
<div class="action-menu">
|
||||
<button class="btn btn-secondary" style="padding: 5px 12px;"><i class="fas fa-ellipsis-v"></i></button>
|
||||
<div class="action-menu-content">
|
||||
<form method="POST" onsubmit="return confirm('Unmatch with this founder?')">
|
||||
<input type="hidden" name="other_user_id" value="<?= $active_chat_id ?>">
|
||||
<input type="hidden" name="action" value="unmatch">
|
||||
<button type="submit" class="action-link">Unmatch</button>
|
||||
</form>
|
||||
<form method="POST" onsubmit="return confirm('Block this user? They will not be able to see you or message you.')">
|
||||
<input type="hidden" name="other_user_id" value="<?= $active_chat_id ?>">
|
||||
<input type="hidden" name="action" value="block">
|
||||
<button type="submit" class="action-link danger">Block User</button>
|
||||
</form>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 700;"><?= htmlspecialchars($active_chat_user['full_name']) ?></div>
|
||||
<div style="font-size: 12px; color: var(--accent-blue); font-weight: 600;">Online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-messages" id="chat-box">
|
||||
<?php if (empty($chat_messages)): ?>
|
||||
<div style="text-align: center; color: var(--text-secondary); margin-top: 50px;">
|
||||
<i class="fas fa-hand-sparkles" style="font-size: 40px; margin-bottom: 20px; opacity: 0.3;"></i>
|
||||
<p>This is the start of your conversation with <?= htmlspecialchars(explode(' ', $active_chat_user['full_name'])[0]) ?>.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($chat_messages as $msg): ?>
|
||||
<div class="msg-bubble <?= $msg['sender_id'] == $user_id ? 'msg-sent' : 'msg-received' ?>">
|
||||
<?= htmlspecialchars($msg['content']) ?>
|
||||
<?php if ($msg['status'] === 'pending'): ?>
|
||||
<div style="font-size: 9px; opacity: 0.8; margin-top: 5px;"><i class="fas fa-clock"></i> Pending Request</div>
|
||||
<?php endif; ?>
|
||||
<div style="font-size: 10px; opacity: 0.6; margin-top: 5px; text-align: right;">
|
||||
</div>
|
||||
|
||||
<div style="flex: 1; overflow-y: auto; padding: 30px; display: flex; flex-direction: column; gap: 15px;" id="chat-scroller">
|
||||
<?php if (empty($chat_messages)): ?>
|
||||
<div style="text-align: center; padding: 40px; color: var(--text-secondary);">
|
||||
<p style="font-size: 14px; font-style: italic;">No messages yet. Say hi!</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($chat_messages as $msg):
|
||||
$is_me = ($msg['sender_id'] == $user_id);
|
||||
?>
|
||||
<div style="display: flex; justify-content: <?= $is_me ? 'flex-end' : 'flex-start' ?>;">
|
||||
<div style="max-width: 70%; padding: 14px 20px; border-radius: 20px; font-size: 15px; line-height: 1.5; <?= $is_me ? 'background: var(--gradient-primary); color: #fff; border-bottom-right-radius: 4px;' : 'background: var(--surface-color); border: 1px solid var(--border-color); border-bottom-left-radius: 4px;' ?>">
|
||||
<?= nl2br(htmlspecialchars($msg['content'])) ?>
|
||||
<div style="font-size: 10px; margin-top: 8px; opacity: 0.6; text-align: right;">
|
||||
<?= date('H:i', strtotime($msg['created_at'])) ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($needs_acceptance): ?>
|
||||
<div class="request-panel">
|
||||
<p style="margin-bottom: 15px; font-weight: 600;">Would you like to accept this message request?</p>
|
||||
<form method="POST" style="display: flex; gap: 10px; justify-content: center;">
|
||||
<input type="hidden" name="other_user_id" value="<?= $active_chat_id ?>">
|
||||
<button type="submit" name="action" value="accept" class="btn btn-primary" style="padding: 8px 25px;">Accept</button>
|
||||
<button type="submit" name="action" value="reject" class="btn btn-secondary" style="padding: 8px 25px;">Reject</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php elseif ($can_reply): ?>
|
||||
<form class="chat-input" method="POST">
|
||||
<input type="text" name="content" placeholder="Type a message..." required autocomplete="off">
|
||||
<button type="submit" class="btn btn-primary" style="padding: 0 25px;"><i class="fas fa-paper-plane"></i></button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<div style="padding: 20px; text-align: center; color: var(--text-secondary);">
|
||||
Waiting for <?= htmlspecialchars($active_chat_user['full_name']) ?> to accept your request.
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($needs_acceptance): ?>
|
||||
<div style="padding: 20px 30px; background: rgba(0, 242, 255, 0.05); border-top: 1px solid var(--border-color); text-align: center;">
|
||||
<p style="font-size: 14px; margin-bottom: 15px;">Accept this message request to reply.</p>
|
||||
<form method="POST" action="api/chat.php">
|
||||
<input type="hidden" name="action" value="accept">
|
||||
<input type="hidden" name="sender_id" value="<?= $active_chat_id ?>">
|
||||
<button type="submit" class="btn btn-primary">Accept & Reply</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div style="flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; opacity: 0.5;">
|
||||
<i class="fas fa-comments" style="font-size: 100px; margin-bottom: 30px;"></i>
|
||||
<h3>Select a conversation to start chatting</h3>
|
||||
<p>Find co-founders in the matching section.</p>
|
||||
<div style="padding: 25px 30px; border-top: 1px solid var(--border-color);">
|
||||
<form method="POST" style="display: flex; gap: 15px;">
|
||||
<input type="text" name="content" placeholder="Type your message..." style="flex: 1; background: var(--surface-color); border: 1px solid var(--border-color); color: #fff; padding: 15px 20px; border-radius: 15px;" required autocomplete="off">
|
||||
<button type="submit" class="btn btn-primary" style="width: 50px; height: 50px; border-radius: 15px; padding: 0; display: flex; align-items: center; justify-content: center;">
|
||||
<i class="fas fa-paper-plane"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
const chatBox = document.getElementById('chat-box');
|
||||
if (chatBox) chatBox.scrollTop = chatBox.scrollHeight;
|
||||
const scroller = document.getElementById('chat-scroller');
|
||||
if (scroller) scroller.scrollTop = scroller.scrollHeight;
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@ -1,29 +1,25 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
session_start();
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
|
||||
$current_user_id = $_SESSION['user_id'];
|
||||
|
||||
// Mark all as read if requested
|
||||
if (isset($_POST['mark_read'])) {
|
||||
$stmt = db()->prepare("UPDATE notifications SET is_read = 1 WHERE user_id = ?");
|
||||
$stmt->execute([$current_user_id]);
|
||||
}
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
if (!$user_id) { header('Location: login.php'); exit; }
|
||||
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$current_user_id]);
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
$stmt = db()->prepare("SELECT * FROM notifications WHERE user_id = ? ORDER BY created_at DESC");
|
||||
$stmt->execute([$current_user_id]);
|
||||
$notifications = $stmt->fetchAll();
|
||||
if (!$user) { header('Location: login.php'); exit; }
|
||||
|
||||
$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
|
||||
if (isset($_POST['mark_read'])) {
|
||||
$stmt = db()->prepare("UPDATE notifications SET is_read = 1 WHERE user_id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
}
|
||||
|
||||
$stmt = db()->prepare("SELECT * FROM notifications WHERE user_id = ? ORDER BY created_at DESC");
|
||||
$stmt->execute([$user_id]);
|
||||
$notifications = $stmt->fetchAll();
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
@ -31,7 +27,9 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Notifications — <?= htmlspecialchars($platformName) ?></title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
</head>
|
||||
@ -39,7 +37,10 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
|
||||
<header>
|
||||
<div class="container" style="display: flex; justify-content: space-between; align-items: center; width: 100%;">
|
||||
<div class="logo"><?= htmlspecialchars($platformName) ?></div>
|
||||
<a href="dashboard.php" class="logo-container">
|
||||
<img src="assets/images/logo.svg" alt="<?= htmlspecialchars($platformName) ?> Logo" class="logo-img">
|
||||
<span class="logo-text"><?= htmlspecialchars($platformName) ?></span>
|
||||
</a>
|
||||
<nav class="nav-links">
|
||||
<?php if ($user['role'] === 'founder'): ?>
|
||||
<a href="startups.php">My Startups</a>
|
||||
@ -50,48 +51,62 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<?php endif; ?>
|
||||
<a href="discover.php">Discovery Hub</a>
|
||||
<a href="messages.php">Messages</a>
|
||||
<a href="notifications.php" class="active">Notifications</a>
|
||||
</nav>
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<a href="dashboard.php" style="color: var(--text-secondary);"><i class="fas fa-th-large"></i></a>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 13px;">Log Out</a>
|
||||
<a href="notifications.php" style="color: #fff; position: relative; font-size: 18px;">
|
||||
<i class="fas fa-bell"></i>
|
||||
</a>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 5px 12px; background: rgba(255,255,255,0.05); border-radius: 50px; border: 1px solid var(--border-color);">
|
||||
<div style="width: 24px; height: 24px; background: var(--gradient-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #fff; font-weight: 800;">
|
||||
<?= substr($user['full_name'], 0, 1) ?>
|
||||
</div>
|
||||
<span style="font-size: 13px; font-weight: 600;"><?= htmlspecialchars(explode(' ', $user['full_name'])[0]) ?></span>
|
||||
</div>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 12px; border-radius: 10px;">Log Out</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container" style="padding-top: 50px; padding-bottom: 50px;">
|
||||
<main class="container" style="padding-top: 50px; padding-bottom: 80px;">
|
||||
<div class="hero-bg">
|
||||
<div class="hero-blob" style="top: 10%; right: -10%;"></div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 40px;">
|
||||
<h1>Notifications</h1>
|
||||
<div>
|
||||
<h1>Activity Center</h1>
|
||||
<p style="color: var(--text-secondary);">Stay updated with your latest matches and investments.</p>
|
||||
</div>
|
||||
<?php if (!empty($notifications)): ?>
|
||||
<form method="POST">
|
||||
<button type="submit" name="mark_read" class="btn btn-secondary" style="font-size: 13px;">Mark all as read</button>
|
||||
<button type="submit" name="mark_read" class="btn btn-outline" style="font-size: 13px; border-radius: 50px;">Mark all as read</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card" style="padding: 0; overflow: hidden; border-color: var(--border-color);">
|
||||
<?php if (empty($notifications)): ?>
|
||||
<div style="text-align: center; padding: 60px 20px;">
|
||||
<i class="fas fa-bell-slash" style="font-size: 48px; color: var(--accent-blue); opacity: 0.2; margin-bottom: 20px;"></i>
|
||||
<p style="color: var(--text-secondary);">No notifications yet. We'll let you know when something happens!</p>
|
||||
<a href="partners.php" class="btn btn-primary" style="margin-top: 25px;">Find Partners</a>
|
||||
<div style="text-align: center; padding: 100px 20px;">
|
||||
<div style="width: 100px; height: 100px; background: var(--surface-color); border-radius: 30px; display: inline-flex; align-items: center; justify-content: center; font-size: 40px; margin-bottom: 30px; border: 1px solid var(--border-color);">
|
||||
<i class="fas fa-bell-slash" style="opacity: 0.1; color: var(--accent-blue);"></i>
|
||||
</div>
|
||||
<h3>All quiet for now</h3>
|
||||
<p style="color: var(--text-secondary); max-width: 300px; margin: 0 auto 30px;">We'll notify you when you get a new match or investment.</p>
|
||||
<a href="discover.php" class="btn btn-primary">Browse Ecosystem</a>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div style="display: flex; flex-direction: column; gap: 0;">
|
||||
<div style="display: flex; flex-direction: column;">
|
||||
<?php foreach ($notifications as $n): ?>
|
||||
<div style="padding: 20px; border-bottom: 1px solid var(--border-color); display: flex; align-items: flex-start; gap: 20px; <?= $n['is_read'] ? 'opacity: 0.6;' : 'background: rgba(0, 242, 255, 0.03);' ?>">
|
||||
<div style="width: 40px; height: 40px; border-radius: 12px; background: <?= $n['is_read'] ? 'var(--surface-color)' : 'var(--gradient-primary)' ?>; display: flex; align-items: center; justify-content: center; color: #fff;">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<div style="padding: 25px 30px; border-bottom: 1px solid var(--border-color); display: flex; align-items: flex-start; gap: 20px; transition: all 0.2s; <?= $n['is_read'] ? 'opacity: 0.5;' : 'background: rgba(0, 242, 255, 0.04);' ?>">
|
||||
<div style="width: 48px; height: 48px; border-radius: 14px; background: <?= $n['is_read'] ? 'var(--surface-color)' : 'var(--gradient-primary)' ?>; display: flex; align-items: center; justify-content: center; color: #fff; flex-shrink: 0; font-size: 18px;">
|
||||
<i class="fas <?= strpos($n['content'], 'match') !== false ? 'fa-heart' : (strpos($n['content'], 'invest') !== false ? 'fa-coins' : 'fa-bolt') ?>"></i>
|
||||
</div>
|
||||
<div style="flex: 1;">
|
||||
<p style="margin: 0; font-size: 15px; color: #fff; font-weight: <?= $n['is_read'] ? '400' : '600' ?>;">
|
||||
<div style="margin: 0; font-size: 16px; color: #fff; font-weight: <?= $n['is_read'] ? '500' : '700' ?>; line-height: 1.4;">
|
||||
<?= htmlspecialchars($n['content']) ?>
|
||||
</p>
|
||||
<div style="font-size: 12px; color: var(--text-secondary); margin-top: 8px;">
|
||||
</div>
|
||||
<div style="font-size: 12px; color: var(--text-secondary); margin-top: 10px; display: flex; align-items: center; gap: 6px;">
|
||||
<i class="fas fa-clock" style="font-size: 10px;"></i>
|
||||
<?= date('M d, Y • H:i', strtotime($n['created_at'])) ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -102,28 +117,16 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
header {
|
||||
background: rgba(10, 10, 15, 0.8);
|
||||
backdrop-filter: blur(20px);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding: 15px 0;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
.nav-links a {
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
margin: 0 15px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
.nav-links a:hover, .nav-links a.active {
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
<footer style="margin-top: 80px; padding: 60px 0; border-top: 1px solid var(--border-color); background: rgba(0,0,0,0.2);">
|
||||
<div class="container" style="text-align: center;">
|
||||
<div class="logo-container" style="justify-content: center; margin-bottom: 25px;">
|
||||
<img src="assets/images/logo.svg" alt="<?= htmlspecialchars($platformName) ?> Logo" class="logo-img" style="width: 30px; height: 30px;">
|
||||
<span class="logo-text" style="font-size: 20px;"><?= htmlspecialchars($platformName) ?></span>
|
||||
</div>
|
||||
<p style="color: var(--text-secondary); font-size: 14px;">© <?= date('Y') ?> <?= htmlspecialchars($platformName) ?>. All rights reserved.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="assets/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
346
partners.php
346
partners.php
@ -1,28 +1,19 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
session_start();
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
if (!$user_id) { header('Location: login.php'); exit; }
|
||||
|
||||
$current_user_id = $_SESSION['user_id'];
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$current_user_id]);
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
if (!$user) { header('Location: login.php'); exit; }
|
||||
|
||||
if (!$user || $user['role'] !== 'founder') {
|
||||
header("Location: dashboard.php");
|
||||
exit;
|
||||
}
|
||||
$current_user_id = $user_id;
|
||||
$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
|
||||
if (!$user['onboarding_completed']) {
|
||||
header("Location: founder_onboarding.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Blocked users filter
|
||||
// Blocked users logic
|
||||
$stmt = db()->prepare("SELECT blocked_id FROM blocked_users WHERE blocker_id = ?");
|
||||
$stmt->execute([$current_user_id]);
|
||||
$blocked_ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
@ -36,24 +27,19 @@ $placeholders = empty($all_blocked) ? "0" : implode(',', array_fill(0, count($al
|
||||
|
||||
function calculateMatchScore($me, $them) {
|
||||
$score = 0;
|
||||
$myNeeds = array_filter(array_map('trim', explode(',', strtolower($me['preferred_co_founder_skills'] ?? ''))));
|
||||
$theirSkills = array_filter(array_map('trim', explode(',', strtolower($them['skills'] ?? ''))));
|
||||
$skillMatches = array_intersect($myNeeds, $theirSkills);
|
||||
$score += count($skillMatches) * 10;
|
||||
$theirNeeds = array_filter(array_map('trim', explode(',', strtolower($them['preferred_co_founder_skills'] ?? ''))));
|
||||
$mySkills = array_filter(array_map('trim', explode(',', strtolower($me['skills'] ?? ''))));
|
||||
$reciprocalMatches = array_intersect($theirNeeds, $mySkills);
|
||||
$score += count($reciprocalMatches) * 10;
|
||||
$myIndustries = array_filter(array_map('trim', explode(',', strtolower($me['startup_industries'] ?? ''))));
|
||||
$theirIndustries = array_filter(array_map('trim', explode(',', strtolower($them['startup_industries'] ?? ''))));
|
||||
$mySkills = array_map('trim', explode(',', strtolower($me['skills'] ?? '')));
|
||||
$theirSkills = array_map('trim', explode(',', strtolower($them['skills'] ?? '')));
|
||||
$myPreferred = array_map('trim', explode(',', strtolower($me['preferred_co_founder_skills'] ?? '')));
|
||||
$theirPreferred = array_map('trim', explode(',', strtolower($them['preferred_co_founder_skills'] ?? '')));
|
||||
$myIndustries = array_map('trim', explode(',', strtolower($me['startup_industries'] ?? '')));
|
||||
$theirIndustries = array_map('trim', explode(',', strtolower($them['startup_industries'] ?? '')));
|
||||
|
||||
$skillMatches = array_intersect($theirSkills, $myPreferred);
|
||||
$score += count($skillMatches) * 5;
|
||||
$industryMatches = array_intersect($myIndustries, $theirIndustries);
|
||||
$score += count($industryMatches) * 5;
|
||||
$score += count($industryMatches) * 3;
|
||||
if (!empty($me['university']) && $me['university'] === $them['university']) { $score += 5; }
|
||||
return [
|
||||
'total' => $score,
|
||||
'skillMatches' => array_values($skillMatches),
|
||||
'industryMatches' => array_values($industryMatches)
|
||||
];
|
||||
return ['total' => $score, 'skillMatches' => array_values($skillMatches), 'industryMatches' => array_values($industryMatches)];
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'swipe') {
|
||||
@ -69,9 +55,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
$stmt->execute([$swiped_id, $current_user_id]);
|
||||
if ($stmt->fetch()) {
|
||||
$isMatch = true;
|
||||
$stmt = db()->prepare("INSERT INTO matches (user1_id, user2_id, status) VALUES (?, ?, 'active') ON DUPLICATE KEY UPDATE status = 'active'");
|
||||
$u1 = min($current_user_id, $swiped_id);
|
||||
$u2 = max($current_user_id, $swiped_id);
|
||||
$stmt = db()->prepare("INSERT INTO matches (user1_id, user2_id, status) VALUES (?, ?, 'active') ON DUPLICATE KEY UPDATE status = 'active'");
|
||||
$stmt->execute([$u1, $u2]);
|
||||
$stmt = db()->prepare("INSERT INTO notifications (user_id, content) VALUES (?, ?)");
|
||||
$stmt->execute([$swiped_id, "You have a new match! Start a conversation now."]);
|
||||
@ -85,65 +71,32 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch active matches not blocked
|
||||
$sql = "
|
||||
SELECT u.*, m.created_at as matched_at FROM matches m
|
||||
JOIN users u ON (m.user1_id = u.id OR m.user2_id = u.id)
|
||||
WHERE (m.user1_id = ? OR m.user2_id = ?)
|
||||
AND u.id != ?
|
||||
AND m.status = 'active'
|
||||
AND u.id NOT IN ($placeholders)
|
||||
ORDER BY m.created_at DESC
|
||||
";
|
||||
// Fetch active matches
|
||||
$sql = "SELECT u.*, m.created_at as matched_at FROM matches m JOIN users u ON (m.user1_id = u.id OR m.user2_id = u.id) WHERE (m.user1_id = ? OR m.user2_id = ?) AND u.id != ? AND m.status = 'active' AND u.id NOT IN ($placeholders) ORDER BY m.created_at DESC";
|
||||
$stmt = db()->prepare($sql);
|
||||
$stmt->execute(array_merge([$current_user_id, $current_user_id, $current_user_id], $all_blocked ?: []));
|
||||
$matches = $stmt->fetchAll();
|
||||
|
||||
// Fetch swipe candidates
|
||||
$sql = "
|
||||
SELECT * FROM users
|
||||
WHERE role = 'founder'
|
||||
AND id != ?
|
||||
AND onboarding_completed = 1
|
||||
AND id NOT IN (SELECT swiped_id FROM swipes WHERE swiper_id = ?)
|
||||
AND id NOT IN ($placeholders)
|
||||
LIMIT 50
|
||||
";
|
||||
$sql = "SELECT * FROM users WHERE role = 'founder' AND id != ? AND onboarding_completed = 1 AND id NOT IN (SELECT swiped_id FROM swipes WHERE swiper_id = ?) AND id NOT IN ($placeholders) LIMIT 50";
|
||||
$stmt = db()->prepare($sql);
|
||||
$stmt->execute(array_merge([$current_user_id, $current_user_id], $all_blocked ?: []));
|
||||
$allCandidates = $stmt->fetchAll();
|
||||
|
||||
foreach ($allCandidates as &$c) {
|
||||
$c['match_data'] = calculateMatchScore($user, $c);
|
||||
$c['score'] = $c['match_data']['total'];
|
||||
}
|
||||
foreach ($allCandidates as &$c) { $c['match_data'] = calculateMatchScore($user, $c); $c['score'] = $c['match_data']['total']; }
|
||||
usort($allCandidates, function($a, $b) { return $b['score'] <=> $a['score']; });
|
||||
$swipeCandidates = array_slice($allCandidates, 0, 10);
|
||||
|
||||
// Fetch partners for Browse view
|
||||
// Fetch partners for Browse
|
||||
$search = $_GET['q'] ?? '';
|
||||
$where = "role = 'founder' AND id != ? AND onboarding_completed = 1 AND id NOT IN (SELECT swiped_id FROM swipes WHERE swiper_id = ?) AND id NOT IN ($placeholders)";
|
||||
$params = array_merge([$current_user_id, $current_user_id], $all_blocked ?: []);
|
||||
if ($search) {
|
||||
$where .= " AND (full_name LIKE ? OR skills LIKE ? OR university LIKE ? OR startup_industries LIKE ?)";
|
||||
$params[] = "%$search%";
|
||||
$params[] = "%$search%";
|
||||
$params[] = "%$search%";
|
||||
$params[] = "%$search%";
|
||||
}
|
||||
if ($search) { $where .= " AND (full_name LIKE ? OR skills LIKE ? OR university LIKE ? OR startup_industries LIKE ?)"; $params[] = "%$search%"; $params[] = "%$search%"; $params[] = "%$search%"; $params[] = "%$search%"; }
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE $where LIMIT 40");
|
||||
$stmt->execute($params);
|
||||
$browseCandidates = $stmt->fetchAll();
|
||||
|
||||
foreach ($browseCandidates as &$c) {
|
||||
$c['match_data'] = calculateMatchScore($user, $c);
|
||||
$c['score'] = $c['match_data']['total'];
|
||||
}
|
||||
if (!$search) {
|
||||
usort($browseCandidates, function($a, $b) { return $b['score'] <=> $a['score']; });
|
||||
}
|
||||
|
||||
$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
foreach ($browseCandidates as &$c) { $c['match_data'] = calculateMatchScore($user, $c); $c['score'] = $c['match_data']['total']; }
|
||||
if (!$search) { usort($browseCandidates, function($a, $b) { return $b['score'] <=> $a['score']; }); }
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
@ -156,41 +109,6 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<style>
|
||||
.page-header { padding: 60px 0 40px; text-align: center; }
|
||||
.page-header h1 { font-size: 56px; font-weight: 900; margin-bottom: 12px; background: var(--gradient-primary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
|
||||
.page-header p { color: var(--text-secondary); font-size: 20px; }
|
||||
.matches-section { margin-bottom: 60px; }
|
||||
.matches-scroller { display: flex; gap: 24px; overflow-x: auto; padding: 20px 5px; scrollbar-width: none; }
|
||||
.matches-scroller::-webkit-scrollbar { display: none; }
|
||||
.match-card { flex: 0 0 85px; text-align: center; cursor: pointer; transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
|
||||
.match-card:hover { transform: scale(1.1) translateY(-5px); }
|
||||
.match-avatar { width: 85px; height: 85px; border-radius: 28px; background: var(--surface-color); border: 2px solid var(--accent-blue); display: flex; align-items: center; justify-content: center; font-size: 30px; font-weight: 800; color: #fff; margin-bottom: 12px; box-shadow: 0 15px 30px rgba(0, 242, 255, 0.2); position: relative; overflow: hidden; }
|
||||
.match-avatar img { width: 100%; height: 100%; object-fit: cover; }
|
||||
.match-name { font-size: 13px; font-weight: 700; color: var(--text-primary); }
|
||||
.tabs { display: flex; justify-content: center; gap: 20px; margin-bottom: 50px; }
|
||||
.tab-btn { padding: 14px 28px; border-radius: 50px; background: var(--surface-color); border: 1px solid var(--border-color); color: var(--text-secondary); font-weight: 700; cursor: pointer; transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
|
||||
.tab-btn.active { background: var(--gradient-primary); color: #fff; border-color: transparent; box-shadow: 0 15px 30px rgba(0, 122, 255, 0.3); transform: scale(1.05); }
|
||||
.swipe-container { display: flex; flex-direction: column; align-items: center; padding: 20px 0; }
|
||||
.card-stack { position: relative; width: 100%; max-width: 440px; height: 600px; perspective: 1000px; }
|
||||
.swipe-card { position: absolute; width: 100%; height: 100%; background: var(--surface-color); border: 1px solid var(--glass-border); border-radius: 40px; overflow: hidden; box-shadow: 0 30px 60px rgba(0,0,0,0.5); transition: transform 0.6s cubic-bezier(0.23, 1, 0.32, 1), opacity 0.6s ease; cursor: grab; display: flex; flex-direction: column; backdrop-filter: blur(20px); }
|
||||
.card-header-img { height: 320px; background: var(--gradient-primary); display: flex; align-items: center; justify-content: center; font-size: 120px; color: rgba(255,255,255,0.2); position: relative; }
|
||||
.match-badge { position: absolute; top: 25px; right: 25px; background: rgba(10, 10, 15, 0.8); backdrop-filter: blur(15px); padding: 10px 18px; border-radius: 50px; color: var(--accent-blue); font-weight: 800; font-size: 14px; border: 1px solid var(--accent-blue); display: flex; align-items: center; gap: 8px; box-shadow: 0 10px 20px rgba(0,0,0,0.3); z-index: 10; }
|
||||
.card-details { padding: 30px; flex-grow: 1; display: flex; flex-direction: column; background: linear-gradient(to bottom, transparent, rgba(0,0,0,0.4)); }
|
||||
.card-title { font-size: 28px; font-weight: 900; margin-bottom: 6px; letter-spacing: -0.5px; }
|
||||
.card-subtitle { font-size: 15px; color: var(--accent-blue); font-weight: 700; margin-bottom: 18px; display: flex; align-items: center; gap: 8px; }
|
||||
.card-bio { font-size: 16px; color: var(--text-secondary); line-height: 1.6; margin-bottom: 20px; font-weight: 400; }
|
||||
.card-tags { display: flex; flex-wrap: wrap; gap: 10px; }
|
||||
.card-tag { font-size: 12px; padding: 6px 14px; background: rgba(255,255,255,0.04); border-radius: 20px; border: 1px solid var(--glass-border); font-weight: 600; color: var(--text-secondary); }
|
||||
.card-tag.highlight { border-color: var(--accent-blue); color: var(--accent-blue); background: rgba(0, 242, 255, 0.1); }
|
||||
.browse-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 30px; }
|
||||
.candidate-card { background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: 32px; padding: 30px; transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); cursor: pointer; position: relative; backdrop-filter: blur(20px); }
|
||||
.candidate-card:hover { transform: translateY(-10px); border-color: var(--accent-blue); box-shadow: 0 20px 40px rgba(0, 242, 255, 0.1); background: rgba(255, 255, 255, 0.05); }
|
||||
.score-indicator { position: absolute; top: 30px; right: 30px; font-size: 11px; font-weight: 800; color: var(--accent-blue); text-transform: uppercase; letter-spacing: 1px; }
|
||||
#match-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(5, 5, 8, 0.98); z-index: 2000; display: none; align-items: center; justify-content: center; text-align: center; backdrop-filter: blur(30px); }
|
||||
.match-popup { max-width: 450px; padding: 60px; position: relative; }
|
||||
.match-title { font-size: 64px; font-weight: 950; background: var(--gradient-primary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 24px; letter-spacing: -2px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@ -207,95 +125,74 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<a href="messages.php">Messages</a>
|
||||
</nav>
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<a href="notifications.php" style="color: var(--text-secondary); position: relative; font-size: 20px;">
|
||||
<a href="notifications.php" style="color: var(--text-secondary); position: relative; font-size: 18px;">
|
||||
<i class="fas fa-bell"></i>
|
||||
</a>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 10px 20px; font-size: 14px; border-radius: 12px;">Log Out</a>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 5px 12px; background: rgba(255,255,255,0.05); border-radius: 50px; border: 1px solid var(--border-color);">
|
||||
<div style="width: 24px; height: 24px; background: var(--gradient-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #fff; font-weight: 800;">
|
||||
<?= substr($user['full_name'], 0, 1) ?>
|
||||
</div>
|
||||
<span style="font-size: 13px; font-weight: 600;"><?= htmlspecialchars(explode(' ', $user['full_name'])[0]) ?></span>
|
||||
</div>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 12px; border-radius: 10px;">Log Out</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
<div class="hero-bg">
|
||||
<div class="hero-blob" style="top: 10%; left: -10%;"></div>
|
||||
<div class="hero-blob" style="top: 40%; right: -10%; width: 500px; height: 500px; background: radial-gradient(circle, rgba(138, 43, 226, 0.1) 0%, rgba(0, 242, 255, 0.1) 100%);"></div>
|
||||
</div>
|
||||
|
||||
<div class="page-header">
|
||||
<div class="match-score-pill" style="margin-bottom: 20px;"><i class="fas fa-search-nodes"></i> Discovery Engine Active</div>
|
||||
<h1>Meet Your Team.</h1>
|
||||
<p>Connect with high-potential founders and engineers in the university ecosystem.</p>
|
||||
<div class="hero-bg"><div class="hero-blob" style="top: 10%; left: -10%;"></div></div>
|
||||
<div class="page-header" style="padding: 60px 0 40px; text-align: center;">
|
||||
<h1 style="font-size: 56px; font-weight: 900; background: var(--gradient-primary); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">Meet Your Team.</h1>
|
||||
<p style="color: var(--text-secondary); font-size: 20px;">Connect with high-potential founders and engineers in the university ecosystem.</p>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($matches)): ?>
|
||||
<section class="matches-section">
|
||||
<section class="matches-section" style="margin-bottom: 60px;">
|
||||
<h3 style="margin-bottom: 24px; font-size: 18px; font-weight: 800; color: var(--text-primary); text-transform: uppercase; letter-spacing: 1.5px; opacity: 0.7; display: flex; align-items: center; gap: 12px;">
|
||||
<i class="fas fa-fire" style="color: #ff4d4d;"></i> Active Connections
|
||||
</h3>
|
||||
<div class="matches-scroller">
|
||||
<div class="matches-scroller" style="display: flex; gap: 24px; overflow-x: auto; padding: 20px 5px; scrollbar-width: none;">
|
||||
<?php foreach ($matches as $match): ?>
|
||||
<div class="match-card" onclick="location.href='messages.php?chat_with=<?= $match['id'] ?>'">
|
||||
<div class="match-avatar">
|
||||
<?php if ($match['profile_photo']): ?>
|
||||
<img src="<?= htmlspecialchars($match['profile_photo']) ?>">
|
||||
<?php else: ?>
|
||||
<?= substr($match['full_name'], 0, 1) ?>
|
||||
<?php endif; ?>
|
||||
<div class="match-card" onclick="location.href='messages.php?chat_with=<?= $match['id'] ?>'" style="flex: 0 0 85px; text-align: center; cursor: pointer;">
|
||||
<div class="match-avatar" style="width: 85px; height: 85px; border-radius: 28px; background: var(--surface-color); border: 2px solid var(--accent-blue); display: flex; align-items: center; justify-content: center; font-size: 30px; font-weight: 800; color: #fff; margin-bottom: 12px; box-shadow: 0 15px 30px rgba(0, 242, 255, 0.2); position: relative; overflow: hidden;">
|
||||
<?php if ($match['profile_photo']): ?><img src="<?= htmlspecialchars($match['profile_photo']) ?>" style="width: 100%; height: 100%; object-fit: cover;"><?php else: ?><?= substr($match['full_name'], 0, 1) ?><?php endif; ?>
|
||||
</div>
|
||||
<div class="match-name"><?= htmlspecialchars(explode(' ', $match['full_name'])[0]) ?></div>
|
||||
<div class="match-name" style="font-size: 13px; font-weight: 700; color: var(--text-primary);"><?= htmlspecialchars(explode(' ', $match['full_name'])[0]) ?></div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="tabs">
|
||||
<button class="tab-btn active" id="tab-swipe" onclick="setTab('swipe')">
|
||||
<div class="tabs" style="display: flex; justify-content: center; gap: 20px; margin-bottom: 50px;">
|
||||
<button class="tab-btn active" id="tab-swipe" onclick="setTab('swipe')" style="padding: 14px 28px; border-radius: 50px; background: var(--surface-color); border: 1px solid var(--border-color); color: var(--text-secondary); font-weight: 700; cursor: pointer; transition: all 0.4s;">
|
||||
<i class="fas fa-layer-group"></i> Swipe Engine
|
||||
</button>
|
||||
<button class="tab-btn" id="tab-browse" onclick="setTab('browse')">
|
||||
<button class="tab-btn" id="tab-browse" onclick="setTab('browse')" style="padding: 14px 28px; border-radius: 50px; background: var(--surface-color); border: 1px solid var(--border-color); color: var(--text-secondary); font-weight: 700; cursor: pointer; transition: all 0.4s;">
|
||||
<i class="fas fa-list-ul"></i> Directory
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="swipe-view" class="swipe-container">
|
||||
<div class="card-stack" id="card-stack">
|
||||
<div id="swipe-view" class="swipe-container" style="display: flex; flex-direction: column; align-items: center; padding: 20px 0;">
|
||||
<div class="card-stack" id="card-stack" style="position: relative; width: 100%; max-width: 440px; height: 600px; perspective: 1000px;">
|
||||
<?php if (empty($swipeCandidates)): ?>
|
||||
<div style="text-align: center; color: var(--text-secondary); padding: 120px 40px; background: var(--glass-bg); border-radius: 48px; border: 1px solid var(--glass-border); width: 100%;">
|
||||
<div class="card-icon" style="margin: 0 auto 30px; width: 80px; height: 80px; font-size: 32px;"><i class="fas fa-wind"></i></div>
|
||||
<h3 style="font-size: 28px; font-weight: 900; color: #fff; margin-bottom: 10px;">The well is dry!</h3>
|
||||
<p style="font-size: 18px;">You've seen everyone for now. Check back tomorrow for more visionaries.</p>
|
||||
<h3>The well is dry!</h3>
|
||||
<p>Check back tomorrow for more visionaries.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach (array_reverse($swipeCandidates) as $c): ?>
|
||||
<div class="swipe-card" data-id="<?= $c['id'] ?>">
|
||||
<div class="card-header-img">
|
||||
<?php if ($c['score'] >= 10): ?>
|
||||
<div class="match-badge"><i class="fas fa-bolt"></i> <?= $c['score'] ?>% Match Score</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($c['profile_photo']): ?>
|
||||
<img src="<?= htmlspecialchars($c['profile_photo']) ?>" style="width: 100%; height: 100%; object-fit: cover;">
|
||||
<?php else: ?>
|
||||
<i class="fas fa-user-astronaut"></i>
|
||||
<?php endif; ?>
|
||||
<div class="swipe-card" data-id="<?= $c['id'] ?>" style="position: absolute; width: 100%; height: 100%; background: var(--surface-color); border: 1px solid var(--glass-border); border-radius: 40px; overflow: hidden; box-shadow: 0 30px 60px rgba(0,0,0,0.5); transition: transform 0.6s cubic-bezier(0.23, 1, 0.32, 1), opacity 0.6s ease; cursor: grab; display: flex; flex-direction: column; backdrop-filter: blur(20px);">
|
||||
<div class="card-header-img" style="height: 320px; background: var(--gradient-primary); display: flex; align-items: center; justify-content: center; font-size: 120px; color: rgba(255,255,255,0.2); position: relative;">
|
||||
<?php if ($c['score'] >= 10): ?><div class="match-badge" style="position: absolute; top: 25px; right: 25px; background: rgba(10, 10, 15, 0.8); backdrop-filter: blur(15px); padding: 10px 18px; border-radius: 50px; color: var(--accent-blue); font-weight: 800; font-size: 14px; border: 1px solid var(--accent-blue); display: flex; align-items: center; gap: 8px; z-index: 10;"><i class="fas fa-bolt"></i> <?= $c['score'] ?>% Match</div><?php endif; ?>
|
||||
<?php if ($c['profile_photo']): ?><img src="<?= htmlspecialchars($c['profile_photo']) ?>" style="width: 100%; height: 100%; object-fit: cover;"><?php else: ?><i class="fas fa-user-astronaut"></i><?php endif; ?>
|
||||
</div>
|
||||
<div class="card-details">
|
||||
<div class="card-title"><?= htmlspecialchars($c['full_name']) ?></div>
|
||||
<div class="card-subtitle"><i class="fas fa-university"></i> <?= htmlspecialchars($c['university']) ?></div>
|
||||
<p class="card-bio"><?= htmlspecialchars($c['bio'] ?: 'Building the next generation of startup infrastructure.') ?></p>
|
||||
<div class="card-tags">
|
||||
<?php
|
||||
$skills = explode(',', $c['skills']);
|
||||
$myNeeds = array_map('trim', explode(',', strtolower($user['preferred_co_founder_skills'] ?? '')));
|
||||
foreach (array_slice($skills, 0, 4) as $skill):
|
||||
if(empty(trim($skill))) continue;
|
||||
$isNeeded = in_array(trim(strtolower($skill)), $myNeeds);
|
||||
?>
|
||||
<span class="card-tag <?= $isNeeded ? 'highlight' : '' ?>">
|
||||
<?= $isNeeded ? '<i class="fas fa-check"></i> ' : '' ?>
|
||||
<?= htmlspecialchars(trim($skill)) ?>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
<div class="card-details" style="padding: 30px; flex-grow: 1; display: flex; flex-direction: column;">
|
||||
<div class="card-title" style="font-size: 28px; font-weight: 900; margin-bottom: 6px;"><?= htmlspecialchars($c['full_name']) ?></div>
|
||||
<div class="card-subtitle" style="font-size: 15px; color: var(--accent-blue); font-weight: 700; margin-bottom: 18px;"><i class="fas fa-university"></i> <?= htmlspecialchars($c['university']) ?></div>
|
||||
<p class="card-bio" style="font-size: 16px; color: var(--text-secondary); line-height: 1.6; margin-bottom: 20px;"><?= htmlspecialchars($c['bio'] ?: 'Building the next generation of startup infrastructure.') ?></p>
|
||||
<div class="card-tags" style="display: flex; flex-wrap: wrap; gap: 10px;">
|
||||
<?php foreach (array_slice(explode(',', $c['skills']), 0, 4) as $skill): if(empty(trim($skill))) continue; ?><span class="card-tag" style="font-size: 12px; padding: 6px 14px; background: rgba(255,255,255,0.04); border-radius: 20px; border: 1px solid var(--glass-border); font-weight: 600; color: var(--text-secondary);"><?= htmlspecialchars(trim($skill)) ?></span><?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -303,76 +200,41 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php if (!empty($swipeCandidates)): ?>
|
||||
<div class="swipe-actions">
|
||||
<button class="action-btn btn-dislike" onclick="handleSwipe('dislike')" title="Not for now">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
<button class="action-btn btn-like" onclick="handleSwipe('like')" title="Hell yes!">
|
||||
<i class="fas fa-heart"></i>
|
||||
</button>
|
||||
<div class="swipe-actions" style="margin-top: 40px; display: flex; gap: 30px;">
|
||||
<button class="btn btn-secondary" onclick="handleSwipe('dislike')" style="width: 70px; height: 70px; border-radius: 50%; font-size: 24px; display: flex; align-items: center; justify-content: center; background: rgba(255, 77, 77, 0.1); border-color: rgba(255, 77, 77, 0.2); color: #ff4d4d;"><i class="fas fa-times"></i></button>
|
||||
<button class="btn btn-primary" onclick="handleSwipe('like')" style="width: 85px; height: 85px; border-radius: 50%; font-size: 30px; display: flex; align-items: center; justify-content: center; box-shadow: 0 20px 40px rgba(0, 242, 255, 0.3);"><i class="fas fa-heart"></i></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div id="browse-view" style="display: none;">
|
||||
<div style="margin-bottom: 40px;">
|
||||
<form method="GET" style="display: flex; gap: 15px; max-width: 700px; margin: 0 auto; position: relative;">
|
||||
<input type="text" name="q" value="<?= htmlspecialchars($search) ?>" placeholder="Search by skill, university, or industry..." class="form-control" style="flex: 1; background: var(--glass-bg); border: 1px solid var(--glass-border); color: #fff; padding: 18px 25px; border-radius: 20px; font-size: 16px; backdrop-filter: blur(10px);">
|
||||
<button type="submit" class="btn btn-primary" style="border-radius: 16px;"><i class="fas fa-search"></i> Search</button>
|
||||
<form method="GET" style="display: flex; gap: 15px; max-width: 700px; margin: 0 auto;">
|
||||
<input type="text" name="q" value="<?= htmlspecialchars($search) ?>" placeholder="Search by skill, university..." class="form-control" style="flex: 1; background: var(--surface-color); border: 1px solid var(--border-color); color: #fff; padding: 15px 25px; border-radius: 18px;">
|
||||
<button type="submit" class="btn btn-primary">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="browse-container">
|
||||
<div class="browse-container" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 30px;">
|
||||
<?php foreach ($browseCandidates as $c): ?>
|
||||
<div class="candidate-card" onclick="location.href='messages.php?chat_with=<?= $c['id'] ?>'">
|
||||
<?php if ($c['score'] >= 10): ?>
|
||||
<div class="score-indicator"><i class="fas fa-sparkles"></i> <?= $c['score'] ?>% Match</div>
|
||||
<?php endif; ?>
|
||||
<div class="candidate-header" style="display: flex; gap: 20px; align-items: center; margin-bottom: 25px;">
|
||||
<div class="candidate-avatar" style="width: 70px; height: 70px; border-radius: 22px; background: var(--gradient-primary); display: flex; align-items: center; justify-content: center; font-weight: 900; color: #fff; font-size: 24px; box-shadow: 0 10px 20px rgba(0,0,0,0.2);">
|
||||
<?php if ($c['profile_photo']): ?>
|
||||
<img src="<?= htmlspecialchars($c['profile_photo']) ?>" style="width: 100%; height: 100%; object-fit: cover; border-radius: 20px;">
|
||||
<?php else: ?>
|
||||
<?= substr($c['full_name'], 0, 1) ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 900; font-size: 20px; letter-spacing: -0.5px;"><?= htmlspecialchars($c['full_name']) ?></div>
|
||||
<div style="font-size: 14px; color: var(--accent-blue); font-weight: 700; opacity: 0.8;"><?= htmlspecialchars($c['university']) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<p style="font-size: 15px; color: var(--text-secondary); margin-bottom: 20px; line-height: 1.6; height: 48px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;">
|
||||
<?= htmlspecialchars($c['bio'] ?: 'A visionary founder building something unique in the ecosystem.') ?>
|
||||
</p>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 8px;">
|
||||
<?php
|
||||
$skills = explode(',', $c['skills']);
|
||||
$myNeeds = array_map('trim', explode(',', strtolower($user['preferred_co_founder_skills'] ?? '')));
|
||||
foreach (array_slice($skills, 0, 3) as $skill):
|
||||
if(empty(trim($skill))) continue;
|
||||
$isNeeded = in_array(trim(strtolower($skill)), $myNeeds);
|
||||
?>
|
||||
<span style="font-size: 11px; padding: 5px 12px; background: <?= $isNeeded ? 'rgba(0, 242, 255, 0.12)' : 'rgba(255,255,255,0.05)' ?>; border-radius: 50px; color: <?= $isNeeded ? 'var(--accent-blue)' : 'var(--text-secondary)' ?>; border: 1px solid <?= $isNeeded ? 'var(--accent-blue)' : 'var(--glass-border)' ?>; font-weight: 600;">
|
||||
<?= htmlspecialchars(trim($skill)) ?>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
<div class="card" onclick="location.href='messages.php?chat_with=<?= $c['id'] ?>'" style="cursor: pointer; position: relative;">
|
||||
<?php if ($c['score'] >= 10): ?><div style="position: absolute; top: 20px; right: 20px; font-size: 11px; font-weight: 800; color: var(--accent-blue);"><i class="fas fa-bolt"></i> <?= $c['score'] ?>%</div><?php endif; ?>
|
||||
<div style="display: flex; gap: 15px; align-items: center; margin-bottom: 20px;">
|
||||
<div style="width: 50px; height: 50px; border-radius: 14px; background: var(--gradient-primary); display: flex; align-items: center; justify-content: center; font-weight: 900; color: #fff;"><?= substr($c['full_name'], 0, 1) ?></div>
|
||||
<div><div style="font-weight: 800;"><?= htmlspecialchars($c['full_name']) ?></div><div style="font-size: 12px; color: var(--text-secondary);"><?= htmlspecialchars($c['university']) ?></div></div>
|
||||
</div>
|
||||
<p style="font-size: 14px; color: var(--text-secondary); height: 40px; overflow: hidden;"><?= htmlspecialchars($c['bio'] ?: 'Building the future.') ?></p>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div id="match-modal">
|
||||
<div class="match-popup">
|
||||
<div class="match-score-pill" style="margin-bottom: 20px; font-size: 16px; padding: 10px 24px;"><i class="fas fa-heart"></i> Mutual Interest</div>
|
||||
<h1 class="match-title">It's a Match!</h1>
|
||||
<p style="color: var(--text-secondary); margin-bottom: 40px; font-size: 20px; line-height: 1.5;">You both saw something great in each other. Time to build the future together.</p>
|
||||
<button class="btn btn-primary" style="width: 100%; margin-bottom: 20px; padding: 20px; font-size: 18px; border-radius: 20px;" onclick="location.href='messages.php'">
|
||||
<i class="fas fa-comment"></i> Send a Message
|
||||
</button>
|
||||
<button class="btn btn-secondary" style="width: 100%; padding: 20px; font-size: 18px; border-radius: 20px;" onclick="closeMatch()">
|
||||
Keep Swiping
|
||||
</button>
|
||||
<div id="match-modal" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.95); z-index: 2000; display: none; align-items: center; justify-content: center; backdrop-filter: blur(20px);">
|
||||
<div style="text-align: center;">
|
||||
<h1 style="font-size: 80px; font-weight: 950; background: var(--gradient-primary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 30px;">It's a Match!</h1>
|
||||
<p style="font-size: 24px; color: #fff; margin-bottom: 40px;">You and this founder are ready to build together.</p>
|
||||
<button class="btn btn-primary" onclick="location.href='messages.php'">Start Conversation</button>
|
||||
<button class="btn btn-secondary" style="margin-left: 15px;" onclick="document.getElementById('match-modal').style.display='none'">Keep Swiping</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -380,35 +242,27 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
function setTab(tab) {
|
||||
document.getElementById('swipe-view').style.display = tab === 'swipe' ? 'flex' : 'none';
|
||||
document.getElementById('browse-view').style.display = tab === 'browse' ? 'block' : 'none';
|
||||
document.getElementById('tab-swipe').classList.toggle('active', tab === 'swipe');
|
||||
document.getElementById('tab-browse').classList.toggle('active', tab === 'browse');
|
||||
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
||||
document.getElementById('tab-' + tab).classList.add('active');
|
||||
}
|
||||
function handleSwipe(direction) {
|
||||
const stack = document.getElementById('card-stack');
|
||||
const cards = stack.querySelectorAll('.swipe-card');
|
||||
if (cards.length === 0) return;
|
||||
const topCard = cards[cards.length - 1];
|
||||
const swipedId = topCard.getAttribute('data-id');
|
||||
const rotate = direction === 'like' ? 30 : -30;
|
||||
const x = direction === 'like' ? 1200 : -1200;
|
||||
topCard.style.transform = `translateX(${x}px) rotate(${rotate}deg) scale(0.8)`;
|
||||
topCard.style.opacity = '0';
|
||||
const fd = new FormData();
|
||||
fd.append('action', 'swipe');
|
||||
fd.append('swiped_id', swipedId);
|
||||
fd.append('direction', direction);
|
||||
fetch('partners.php', { method: 'POST', body: fd })
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.match) { document.getElementById('match-modal').style.display = 'flex'; }
|
||||
setTimeout(() => {
|
||||
topCard.remove();
|
||||
if (stack.querySelectorAll('.swipe-card').length === 0) { location.reload(); }
|
||||
}, 600);
|
||||
});
|
||||
const card = stack.querySelector('.swipe-card:last-child');
|
||||
if (!card) return;
|
||||
const swiped_id = card.dataset.id;
|
||||
card.style.transform = `translateX(${direction === 'like' ? '1000px' : '-1000px'}) rotate(${direction === 'like' ? '30deg' : '-30deg'})`;
|
||||
card.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
card.remove();
|
||||
fetch('partners.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: `action=swipe&swiped_id=${swiped_id}&direction=${direction}`
|
||||
}).then(r => r.json()).then(data => {
|
||||
if (data.match) { document.getElementById('match-modal').style.display = 'flex'; }
|
||||
});
|
||||
}, 300);
|
||||
}
|
||||
function closeMatch() { document.getElementById('match-modal').style.display = 'none'; }
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@ -1,21 +1,27 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
session_start();
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
if (!$user_id) { header('Location: login.php'); exit; }
|
||||
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
if (!$user) { header('Location: login.php'); exit; }
|
||||
|
||||
if ($user['role'] !== 'investor') { header('Location: dashboard.php'); exit; }
|
||||
|
||||
$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
|
||||
$myInvestments = [];
|
||||
$stmt = db()->prepare("SELECT i.*, s.name as startup_name, s.description as startup_desc FROM investments i JOIN startups s ON i.startup_id = s.id WHERE i.investor_id = ? ORDER BY i.created_at DESC");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$stmt = db()->prepare("
|
||||
SELECT i.*, s.name as startup_name, s.description as startup_desc
|
||||
FROM investments i
|
||||
JOIN startups s ON i.startup_id = s.id
|
||||
WHERE i.investor_id = ?
|
||||
ORDER BY i.created_at DESC
|
||||
");
|
||||
$stmt->execute([$user_id]);
|
||||
$myInvestments = $stmt->fetchAll();
|
||||
|
||||
$totalInvested = 0;
|
||||
@ -30,8 +36,10 @@ foreach ($myInvestments as $inv) {
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>My Portfolio — <?= htmlspecialchars($platformName) ?></title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<title>Investment Portfolio — <?= htmlspecialchars($platformName) ?></title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
</head>
|
||||
@ -48,11 +56,18 @@ foreach ($myInvestments as $inv) {
|
||||
<a href="portfolio.php" class="active">Portfolio</a>
|
||||
<a href="discover.php">Discovery Hub</a>
|
||||
<a href="messages.php">Messages</a>
|
||||
<a href="notifications.php">Notifications</a>
|
||||
</nav>
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<a href="dashboard.php" style="color: var(--text-secondary);"><i class="fas fa-th-large"></i></a>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 13px;">Log Out</a>
|
||||
<a href="notifications.php" style="color: var(--text-secondary); position: relative; font-size: 18px;">
|
||||
<i class="fas fa-bell"></i>
|
||||
</a>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 5px 12px; background: rgba(255,255,255,0.05); border-radius: 50px; border: 1px solid var(--border-color);">
|
||||
<div style="width: 24px; height: 24px; background: var(--gradient-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #fff; font-weight: 800;">
|
||||
<?= substr($user['full_name'], 0, 1) ?>
|
||||
</div>
|
||||
<span style="font-size: 13px; font-weight: 600;"><?= htmlspecialchars(explode(' ', $user['full_name'])[0]) ?></span>
|
||||
</div>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 12px; border-radius: 10px;">Log Out</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@ -90,7 +105,7 @@ foreach ($myInvestments as $inv) {
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($myInvestments as $inv): ?>
|
||||
<div class="card" style="display: flex; justify-content: space-between; align-items: center; padding: 30px; transition: all 0.3s;" onclick="location.href='startup_details.php?id=<?= $inv['startup_id'] ?>'" style="cursor: pointer;">
|
||||
<div class="card" style="display: flex; justify-content: space-between; align-items: center; padding: 30px; transition: all 0.3s; cursor: pointer;" onclick="location.href='startup_details.php?id=<?= $inv['startup_id'] ?>'">
|
||||
<div style="display: flex; align-items: center; gap: 25px;">
|
||||
<div style="width: 60px; height: 60px; background: var(--gradient-primary); border-radius: 18px; display: flex; align-items: center; justify-content: center; font-size: 24px; color: #fff; font-weight: 800;">
|
||||
<?= substr($inv['startup_name'], 0, 1) ?>
|
||||
@ -120,11 +135,16 @@ foreach ($myInvestments as $inv) {
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
header { background: rgba(10, 10, 15, 0.8); backdrop-filter: blur(20px); border-bottom: 1px solid var(--border-color); padding: 15px 0; position: sticky; top: 0; z-index: 1000; }
|
||||
.nav-links a { color: var(--text-secondary); text-decoration: none; margin: 0 15px; font-size: 14px; font-weight: 500; transition: color 0.2s; }
|
||||
.nav-links a:hover, .nav-links a.active { color: #fff; }
|
||||
</style>
|
||||
<footer style="margin-top: 80px; padding: 60px 0; border-top: 1px solid var(--border-color); background: rgba(0,0,0,0.2);">
|
||||
<div class="container" style="text-align: center;">
|
||||
<div class="logo-container" style="justify-content: center; margin-bottom: 25px;">
|
||||
<img src="assets/images/logo.svg" alt="<?= htmlspecialchars($platformName) ?> Logo" class="logo-img" style="width: 30px; height: 30px;">
|
||||
<span class="logo-text" style="font-size: 20px;"><?= htmlspecialchars($platformName) ?></span>
|
||||
</div>
|
||||
<p style="color: var(--text-secondary); font-size: 14px;">© <?= date('Y') ?> <?= htmlspecialchars($platformName) ?>. All rights reserved.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="assets/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@ -1,215 +1,112 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
require_once 'mail/MailService.php';
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
if (!$user_id) { header('Location: login.php'); exit; }
|
||||
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
if (!$user) { header('Location: login.php'); exit; }
|
||||
|
||||
$startup_id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$startup_id = (int)($_GET['id'] ?? 0);
|
||||
$stmt = db()->prepare("SELECT * FROM startups WHERE id = ?");
|
||||
$stmt->execute([$startup_id]);
|
||||
$startup = $stmt->fetch();
|
||||
|
||||
if (!$startup) {
|
||||
header('Location: startups.php');
|
||||
exit;
|
||||
}
|
||||
if (!$startup) { header('Location: startups.php'); exit; }
|
||||
|
||||
// Check if blocked or blocker
|
||||
$stmt = db()->prepare("SELECT 1 FROM blocked_users WHERE (blocker_id = ? AND blocked_id = ?) OR (blocker_id = ? AND blocked_id = ?)");
|
||||
$stmt->execute([$user_id, $startup['founder_id'], $startup['founder_id'], $user_id]);
|
||||
if ($stmt->fetchColumn()) {
|
||||
header('Location: discover.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check if current user is following
|
||||
$stmt = db()->prepare("SELECT 1 FROM startup_followers WHERE startup_id = ? AND user_id = ?");
|
||||
$stmt->execute([$startup_id, $user_id]);
|
||||
$isFollowing = (bool)$stmt->fetchColumn();
|
||||
|
||||
// Check for active funding round
|
||||
$stmt = db()->prepare("SELECT * FROM funding_rounds WHERE startup_id = ? AND status = 'Active' LIMIT 1");
|
||||
$stmt->execute([$startup_id]);
|
||||
$activeRound = $stmt->fetch();
|
||||
|
||||
// Handle Actions
|
||||
$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
$error = '';
|
||||
$success = '';
|
||||
|
||||
// Check if user is following
|
||||
$stmt = db()->prepare("SELECT id FROM startup_followers WHERE user_id = ? AND startup_id = ?");
|
||||
$stmt->execute([$user_id, $startup_id]);
|
||||
$isFollowing = $stmt->fetch();
|
||||
|
||||
// Actions: follow/unfollow, invest, post_update
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
||||
$action = $_POST['action'];
|
||||
|
||||
// Follow/Unfollow Actions
|
||||
if ($action === 'follow' && $startup['founder_id'] != $user_id) {
|
||||
$stmt = db()->prepare("INSERT IGNORE INTO startup_followers (startup_id, user_id) VALUES (?, ?)");
|
||||
$stmt->execute([$startup_id, $user_id]);
|
||||
if ($_POST['action'] === 'follow') {
|
||||
$stmt = db()->prepare("INSERT IGNORE INTO startup_followers (user_id, startup_id) VALUES (?, ?)");
|
||||
$stmt->execute([$user_id, $startup_id]);
|
||||
$success = "You are now following " . $startup['name'] . "!";
|
||||
$isFollowing = true;
|
||||
} elseif ($action === 'unfollow' && $startup['founder_id'] != $user_id) {
|
||||
$stmt = db()->prepare("DELETE FROM startup_followers WHERE startup_id = ? AND user_id = ?");
|
||||
$stmt->execute([$startup_id, $user_id]);
|
||||
} elseif ($_POST['action'] === 'unfollow') {
|
||||
$stmt = db()->prepare("DELETE FROM startup_followers WHERE user_id = ? AND startup_id = ?");
|
||||
$stmt->execute([$user_id, $startup_id]);
|
||||
$success = "You have unfollowed " . $startup['name'] . ".";
|
||||
$isFollowing = false;
|
||||
}
|
||||
} elseif ($_POST['action'] === 'invest' && $user['role'] === 'investor') {
|
||||
$amount = (float)($_POST['amount'] ?? 0);
|
||||
if ($amount > 0) {
|
||||
$stmt = db()->prepare("SELECT * FROM funding_rounds WHERE startup_id = ? AND status = 'Active'");
|
||||
$stmt->execute([$startup_id]);
|
||||
$round = $stmt->fetch();
|
||||
if ($round) {
|
||||
$stmt = db()->prepare("INSERT INTO investments (investor_id, startup_id, amount, status) VALUES (?, ?, ?, 'approved')");
|
||||
$stmt->execute([$user_id, $startup_id, $amount]);
|
||||
|
||||
$stmt = db()->prepare("UPDATE funding_rounds SET funding_raised = funding_raised + ? WHERE id = ?");
|
||||
$stmt->execute([$amount, $round['id']]);
|
||||
|
||||
$stmt = db()->prepare("UPDATE startups SET funding_raised = funding_raised + ? WHERE id = ?");
|
||||
$stmt->execute([$amount, $startup_id]);
|
||||
|
||||
// Founder Actions
|
||||
if ($user['role'] === 'founder' && $startup['founder_id'] == $user_id) {
|
||||
$round_id = isset($_POST['round_id']) ? (int)$_POST['round_id'] : 0;
|
||||
if ($action === 'finish_round' && $activeRound && $activeRound['id'] == $round_id) {
|
||||
$stmt = db()->prepare("UPDATE funding_rounds SET status = 'Closed' WHERE id = ?");
|
||||
$stmt->execute([$round_id]);
|
||||
$success = "Funding round finished early. No new investments allowed.";
|
||||
$activeRound = null;
|
||||
} elseif ($action === 'cancel_round' && $activeRound && $activeRound['id'] == $round_id) {
|
||||
db()->beginTransaction();
|
||||
try {
|
||||
$stmt = db()->prepare("UPDATE funding_rounds SET status = 'Cancelled' WHERE id = ?");
|
||||
$stmt->execute([$round_id]);
|
||||
$stmt = db()->prepare("SELECT * FROM investments WHERE funding_round_id = ? AND status = 'approved'");
|
||||
$stmt->execute([$round_id]);
|
||||
$investmentsToRefund = $stmt->fetchAll();
|
||||
foreach ($investmentsToRefund as $inv) {
|
||||
$upd = db()->prepare("UPDATE investments SET status = 'Refunded' WHERE id = ?");
|
||||
$upd->execute([$inv['id']]);
|
||||
$notif = db()->prepare("INSERT INTO notifications (user_id, content) VALUES (?, ?)");
|
||||
$notif->execute([$inv['investor_id'], "The funding round for " . $startup['name'] . " has been cancelled. Your investment of £" . number_format($inv['amount']) . " has been refunded."]);
|
||||
}
|
||||
db()->commit();
|
||||
$success = "Funding round cancelled and investors refunded.";
|
||||
$activeRound = null;
|
||||
} catch (Exception $e) {
|
||||
db()->rollBack();
|
||||
$error = "Cancellation failed: " . $e->getMessage();
|
||||
}
|
||||
} elseif ($action === 'start_new_round') {
|
||||
$newTarget = (float)($_POST['new_target'] ?? 0);
|
||||
if ($newTarget < 50) {
|
||||
$error = "Minimum target for a new round is £50.";
|
||||
} elseif ($activeRound) {
|
||||
$error = "An active round already exists.";
|
||||
} else {
|
||||
$stmt = db()->prepare("INSERT INTO funding_rounds (startup_id, funding_goal, status) VALUES (?, ?, 'Active')");
|
||||
$stmt->execute([$startup_id, $newTarget]);
|
||||
$success = "New funding round launched!";
|
||||
$stmt = db()->prepare("SELECT * FROM funding_rounds WHERE startup_id = ? AND status = 'Active' LIMIT 1");
|
||||
// Create notification for founder
|
||||
$notif = db()->prepare("INSERT INTO notifications (user_id, content) VALUES (?, ?)");
|
||||
$notif->execute([$startup['founder_id'], $user['full_name'] . " just invested £" . number_format($amount) . " in " . $startup['name'] . "!"]);
|
||||
|
||||
$success = "Investment of £" . number_format($amount) . " successfully processed!";
|
||||
// Refresh data
|
||||
$stmt = db()->prepare("SELECT * FROM startups WHERE id = ?");
|
||||
$stmt->execute([$startup_id]);
|
||||
$activeRound = $stmt->fetch();
|
||||
}
|
||||
} elseif ($action === 'post_update') {
|
||||
$title = trim($_POST['update_title'] ?? '');
|
||||
$content = trim($_POST['update_content'] ?? '');
|
||||
if (empty($title) || empty($content)) {
|
||||
$error = "Update title and content are required.";
|
||||
} else {
|
||||
db()->beginTransaction();
|
||||
try {
|
||||
$stmt = db()->prepare("INSERT INTO startup_updates (startup_id, founder_id, title, content) VALUES (?, ?, ?, ?)");
|
||||
$stmt->execute([$startup_id, $user_id, $title, $content]);
|
||||
$stmt = db()->prepare("
|
||||
SELECT DISTINCT u.id, u.email, u.full_name
|
||||
FROM users u
|
||||
LEFT JOIN investments i ON i.investor_id = u.id AND i.startup_id = ? AND i.status = 'approved'
|
||||
LEFT JOIN startup_followers f ON f.user_id = u.id AND f.startup_id = ?
|
||||
WHERE i.investor_id IS NOT NULL OR f.user_id IS NOT NULL
|
||||
");
|
||||
$stmt->execute([$startup_id, $startup_id]);
|
||||
$peopleToNotify = $stmt->fetchAll();
|
||||
foreach ($peopleToNotify as $targetUser) {
|
||||
$notif = db()->prepare("INSERT INTO notifications (user_id, content) VALUES (?, ?)");
|
||||
$notif->execute([$targetUser['id'], "New progress update from " . $startup['name'] . ": " . $title]);
|
||||
$subject = "New Update: " . $startup['name'];
|
||||
$emailHtml = "<h1>New Update: " . htmlspecialchars($title) . "</h1><p>Hi " . htmlspecialchars($targetUser['full_name']) . ", <strong>" . htmlspecialchars($startup['name']) . "</strong> has posted a new progress update:</p><hr><p>" . nl2br(htmlspecialchars($content)) . "</p>";
|
||||
$emailText = "New Update: " . $title . "\n\nHi " . $targetUser['full_name'] . ", " . $startup['name'] . " has posted a new progress update: " . $content;
|
||||
MailService::sendMail($targetUser['email'], $subject, $emailHtml, $emailText);
|
||||
}
|
||||
db()->commit();
|
||||
$success = "Update posted and " . count($peopleToNotify) . " backers/followers notified.";
|
||||
} catch (Exception $e) {
|
||||
db()->rollBack();
|
||||
$error = "Failed to post update: " . $e->getMessage();
|
||||
}
|
||||
$startup = $stmt->fetch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Investor Actions
|
||||
if ($action === 'invest') {
|
||||
if ($user['role'] !== 'investor') {
|
||||
$error = "Founders cannot make investments.";
|
||||
} elseif (!$activeRound) {
|
||||
$error = "There is no active funding round for this startup.";
|
||||
} else {
|
||||
$amount = (float)($_POST['amount'] ?? 0);
|
||||
if ($amount < 50) {
|
||||
$error = "Minimum investment is £50.";
|
||||
} else {
|
||||
db()->beginTransaction();
|
||||
try {
|
||||
$stmt = db()->prepare("INSERT INTO investments (investor_id, startup_id, funding_round_id, amount, status) VALUES (?, ?, ?, ?, 'approved')");
|
||||
$stmt->execute([$_SESSION['user_id'], $startup_id, $activeRound['id'], $amount]);
|
||||
$stmt = db()->prepare("UPDATE funding_rounds SET funding_raised = funding_raised + ? WHERE id = ?");
|
||||
$stmt->execute([$amount, $activeRound['id']]);
|
||||
$stmt = db()->prepare("UPDATE startups SET funding_raised = funding_raised + ? WHERE id = ?");
|
||||
$stmt->execute([$amount, $startup_id]);
|
||||
$stmt = db()->prepare("INSERT INTO notifications (user_id, content) VALUES (?, ?)");
|
||||
$stmt->execute([$startup['founder_id'], "New investment of £" . number_format($amount) . " in " . $startup['name'] . "!"]);
|
||||
$stmt = db()->prepare("SELECT * FROM funding_rounds WHERE id = ?");
|
||||
$stmt->execute([$activeRound['id']]);
|
||||
$updatedRound = $stmt->fetch();
|
||||
if ($updatedRound['funding_raised'] >= $updatedRound['funding_goal']) {
|
||||
$stmt = db()->prepare("UPDATE funding_rounds SET status = 'Closed' WHERE id = ?");
|
||||
$stmt->execute([$updatedRound['id']]);
|
||||
$stmt = db()->prepare("INSERT INTO notifications (user_id, content) VALUES (?, ?)");
|
||||
$stmt->execute([$startup['founder_id'], "Congratulations! The funding round for " . $startup['name'] . " has reached its goal of £" . number_format($updatedRound['funding_goal']) . "!"]);
|
||||
$stmt = db()->prepare("SELECT DISTINCT u.id, u.email, u.full_name FROM investments i JOIN users u ON i.investor_id = u.id WHERE i.funding_round_id = ? AND i.status = 'approved'");
|
||||
$stmt->execute([$updatedRound['id']]);
|
||||
$investorsToNotify = $stmt->fetchAll();
|
||||
foreach ($investorsToNotify as $invUser) {
|
||||
$stmt = db()->prepare("INSERT INTO notifications (user_id, content) VALUES (?, ?)");
|
||||
$stmt->execute([$invUser['id'], "Great news! The funding round for " . $startup['name'] . " that you invested in has reached its goal!"]);
|
||||
$subject = "Funding Goal Reached for " . $startup['name'];
|
||||
$html = "<h1>Goal Reached!</h1><p>Hi " . htmlspecialchars($invUser['full_name']) . ", the funding round for <strong>" . htmlspecialchars($startup['name']) . "</strong> has successfully reached its goal. Thank you for being a part of this journey!</p>";
|
||||
$text = "Goal Reached! Hi " . $invUser['full_name'] . ", the funding round for " . $startup['name'] . " has successfully reached its goal. Thank you for being a part of this journey!";
|
||||
MailService::sendMail($invUser['email'], $subject, $html, $text);
|
||||
}
|
||||
$stmt = db()->prepare("SELECT email, full_name FROM users WHERE id = ?");
|
||||
$stmt->execute([$startup['founder_id']]);
|
||||
$founderUser = $stmt->fetch();
|
||||
if ($founderUser) {
|
||||
$subject = "Funding Goal Reached: " . $startup['name'];
|
||||
$html = "<h1>Congratulations!</h1><p>Your funding round for <strong>" . htmlspecialchars($startup['name']) . "</strong> has reached its goal of £" . number_format($updatedRound['funding_goal']) . ".</p>";
|
||||
$text = "Congratulations! Your funding round for " . $startup['name'] . " has reached its goal of £" . number_format($updatedRound['funding_goal']) . ".";
|
||||
MailService::sendMail($founderUser['email'], $subject, $html, $text);
|
||||
}
|
||||
}
|
||||
db()->commit();
|
||||
$success = "Investment successful! You've backed the current round.";
|
||||
$stmt = db()->prepare("SELECT * FROM funding_rounds WHERE id = ?");
|
||||
$stmt->execute([$activeRound['id']]);
|
||||
$activeRound = $stmt->fetch();
|
||||
// Refresh startup data to get updated total funding_raised
|
||||
$stmt = db()->prepare("SELECT * FROM startups WHERE id = ?");
|
||||
$stmt->execute([$startup_id]);
|
||||
$startup = $stmt->fetch();
|
||||
} catch (Exception $e) {
|
||||
db()->rollBack();
|
||||
$error = "Investment failed: " . $e->getMessage();
|
||||
} elseif ($_POST['action'] === 'post_update' && $user['role'] === 'founder' && $startup['founder_id'] == $user_id) {
|
||||
$title = $_POST['update_title'] ?? '';
|
||||
$content = $_POST['update_content'] ?? '';
|
||||
if ($title && $content) {
|
||||
$stmt = db()->prepare("INSERT INTO startup_updates (startup_id, title, content) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$startup_id, $title, $content]);
|
||||
|
||||
// Notify followers
|
||||
$stmt = db()->prepare("SELECT user_id FROM startup_followers WHERE startup_id = ?");
|
||||
$stmt->execute([$startup_id]);
|
||||
$followers = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
if (!empty($followers)) {
|
||||
$notif = db()->prepare("INSERT INTO notifications (user_id, content) VALUES (?, ?)");
|
||||
foreach ($followers as $f_id) {
|
||||
$notif->execute([$f_id, "New update from " . $startup['name'] . ": " . $title]);
|
||||
}
|
||||
}
|
||||
$success = "Update posted successfully!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
$stmt = db()->prepare("SELECT * FROM funding_rounds WHERE startup_id = ? AND status = 'Active'");
|
||||
$stmt->execute([$startup_id]);
|
||||
$activeRound = $stmt->fetch();
|
||||
|
||||
// Permission check for Funding History: Founders see their own, Investors see all.
|
||||
$canSeeHistory = ($user['role'] === 'investor' || ($user['role'] === 'founder' && $startup['founder_id'] == $user_id));
|
||||
|
||||
// Fetch Funding History
|
||||
$fundingHistory = [];
|
||||
if ($canSeeHistory) {
|
||||
$stmt = db()->prepare("
|
||||
SELECT i.*, u.full_name as investor_name, u.profile_photo as investor_photo
|
||||
FROM investments i
|
||||
JOIN users u ON i.investor_id = u.id
|
||||
WHERE i.startup_id = ? AND i.status = 'approved'
|
||||
ORDER BY i.created_at DESC
|
||||
");
|
||||
$stmt->execute([$startup_id]);
|
||||
$fundingHistory = $stmt->fetchAll();
|
||||
}
|
||||
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
@ -217,7 +114,9 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title><?= htmlspecialchars($startup['name']) ?> — <?= htmlspecialchars($platformName) ?></title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
</head>
|
||||
@ -239,11 +138,18 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<?php endif; ?>
|
||||
<a href="discover.php">Discovery Hub</a>
|
||||
<a href="messages.php">Messages</a>
|
||||
<a href="notifications.php">Notifications</a>
|
||||
</nav>
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<a href="dashboard.php" style="color: var(--text-secondary);"><i class="fas fa-th-large"></i></a>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 13px;">Log Out</a>
|
||||
<a href="notifications.php" style="color: var(--text-secondary); position: relative; font-size: 18px;">
|
||||
<i class="fas fa-bell"></i>
|
||||
</a>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 5px 12px; background: rgba(255,255,255,0.05); border-radius: 50px; border: 1px solid var(--border-color);">
|
||||
<div style="width: 24px; height: 24px; background: var(--gradient-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #fff; font-weight: 800;">
|
||||
<?= substr($user['full_name'], 0, 1) ?>
|
||||
</div>
|
||||
<span style="font-size: 13px; font-weight: 600;"><?= htmlspecialchars(explode(' ', $user['full_name'])[0]) ?></span>
|
||||
</div>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 12px; border-radius: 10px;">Log Out</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@ -287,6 +193,45 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<p style="font-size: 18px; line-height: 1.6; color: var(--text-secondary); white-space: pre-wrap;"><?= htmlspecialchars($startup['description']) ?></p>
|
||||
</section>
|
||||
|
||||
<!-- Funding History Section -->
|
||||
<?php if ($canSeeHistory): ?>
|
||||
<section class="card" style="margin-bottom: 40px;">
|
||||
<h2 style="margin-top: 0; margin-bottom: 25px; display: flex; align-items: center; gap: 12px;">
|
||||
<i class="fas fa-history" style="color: var(--accent-blue);"></i> Funding History
|
||||
</h2>
|
||||
<?php if (empty($fundingHistory)): ?>
|
||||
<div style="padding: 40px; text-align: center; background: rgba(255,255,255,0.02); border-radius: 20px; border: 1px dashed var(--border-color);">
|
||||
<i class="fas fa-coins" style="font-size: 32px; color: var(--text-secondary); opacity: 0.3; margin-bottom: 15px;"></i>
|
||||
<p style="color: var(--text-secondary); margin: 0; font-style: italic;">No investment history available yet.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div style="display: flex; flex-direction: column; gap: 15px;">
|
||||
<?php foreach ($fundingHistory as $inv): ?>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; padding: 20px; background: rgba(255,255,255,0.03); border-radius: 18px; border: 1px solid var(--border-color);">
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<div style="width: 45px; height: 45px; border-radius: 12px; background: var(--surface-color); border: 1px solid var(--border-color); display: flex; align-items: center; justify-content: center; overflow: hidden;">
|
||||
<?php if ($inv['investor_photo']): ?>
|
||||
<img src="<?= htmlspecialchars($inv['investor_photo']) ?>" style="width: 100%; height: 100%; object-fit: cover;">
|
||||
<?php else: ?>
|
||||
<span style="font-weight: 800; color: var(--accent-blue);"><?= substr($inv['investor_name'], 0, 1) ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 700; font-size: 16px;"><?= htmlspecialchars($inv['investor_name']) ?></div>
|
||||
<div style="font-size: 12px; color: var(--text-secondary);"><?= date('M d, Y', strtotime($inv['created_at'])) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div style="font-weight: 800; font-size: 18px; color: var(--accent-blue);">£<?= number_format($inv['amount']) ?></div>
|
||||
<div style="font-size: 11px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 1px;">Investment</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<section class="card" style="margin-bottom: 40px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||||
<h2 style="margin: 0;">Public Updates</h2>
|
||||
@ -331,132 +276,96 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<!-- Sidebar with Financial Stats -->
|
||||
<section class="card" style="margin-bottom: 30px; border-left: 4px solid var(--accent-blue);">
|
||||
<h4 style="margin-top: 0; color: var(--text-secondary); text-transform: uppercase; font-size: 12px; letter-spacing: 1px;">Venture Financials</h4>
|
||||
<div style="margin: 20px 0;">
|
||||
<div style="font-size: 32px; font-weight: 900; color: var(--text-primary);">£<?= number_format($startup['funding_raised']) ?></div>
|
||||
<div style="font-size: 13px; color: var(--text-secondary);">Total Raised All-Time</div>
|
||||
</div>
|
||||
<div style="height: 1px; background: var(--border-color); margin: 20px 0;"></div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div>
|
||||
<div style="font-weight: 700;"><?= count($fundingHistory) ?></div>
|
||||
<div style="font-size: 11px; color: var(--text-secondary);">Investors</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 700;"><?= $startup['followers_count'] ?? 0 ?></div>
|
||||
<div style="font-size: 11px; color: var(--text-secondary);">Followers</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 700;">Seed</div>
|
||||
<div style="font-size: 11px; color: var(--text-secondary);">Stage</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php if ($activeRound): ?>
|
||||
<section class="card" style="border-left: 5px solid var(--accent-blue);">
|
||||
<h3 style="margin-top: 0;">Active Funding Round</h3>
|
||||
<section class="card" style="margin-bottom: 30px; background: linear-gradient(135deg, rgba(0, 122, 255, 0.05) 0%, rgba(0, 242, 255, 0.05) 100%);">
|
||||
<h3 style="margin-top: 0;">Active Round</h3>
|
||||
<div style="margin: 20px 0;">
|
||||
<?php $percent = ($activeRound['funding_goal'] > 0) ? min(100, ($activeRound['funding_raised'] / $activeRound['funding_goal']) * 100) : 0; ?>
|
||||
<div style="width: 100%; height: 10px; background: var(--border-color); border-radius: 5px; overflow: hidden;">
|
||||
<div style="width: 100%; height: 10px; background: var(--border-color); border-radius: 5px; overflow: hidden; margin-bottom: 10px;">
|
||||
<div style="width: <?= $percent ?>%; height: 100%; background: var(--gradient-primary);"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; font-weight: 600; margin-bottom: 20px;">
|
||||
<span style="font-size: 24px;">£<?= number_format($activeRound['funding_raised']) ?> raised</span>
|
||||
<span style="color: var(--text-secondary);">Target: £<?= number_format($activeRound['funding_goal']) ?></span>
|
||||
</div>
|
||||
<?php if ($user['role'] === 'founder' && $startup['founder_id'] == $user_id): ?>
|
||||
<div style="display: flex; gap: 10px; margin-top: 20px;">
|
||||
<form method="POST" onsubmit="return confirm('Finish this round early? No more investments will be accepted.');">
|
||||
<input type="hidden" name="action" value="finish_round">
|
||||
<input type="hidden" name="round_id" value="<?= $activeRound['id'] ?>">
|
||||
<button type="submit" class="btn btn-secondary">Finish Round Early</button>
|
||||
</form>
|
||||
<form method="POST" onsubmit="return confirm('CANCEL this round? All investors in this specific round will be automatically refunded. This cannot be undone.');">
|
||||
<input type="hidden" name="action" value="cancel_round">
|
||||
<input type="hidden" name="round_id" value="<?= $activeRound['id'] ?>">
|
||||
<button type="submit" class="btn btn-outline" style="color: #ff3b30; border-color: #ff3b30;">Cancel Round & Refund</button>
|
||||
</form>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 14px; font-weight: 600;">
|
||||
<span>£<?= number_format($activeRound['funding_raised']) ?></span>
|
||||
<span style="color: var(--text-secondary);">£<?= number_format($activeRound['funding_goal']) ?> target</span>
|
||||
</div>
|
||||
<?php elseif ($user['role'] === 'investor'): ?>
|
||||
<form method="POST" style="background: rgba(255,255,255,0.02); padding: 25px; border-radius: 15px; margin-top: 20px; border: 1px solid var(--border-color);">
|
||||
</div>
|
||||
|
||||
<?php if ($user['role'] === 'investor'): ?>
|
||||
<form method="POST" style="margin-top: 25px;">
|
||||
<input type="hidden" name="action" value="invest">
|
||||
<label style="display: block; margin-bottom: 10px; font-weight: 600;">Investment Amount (£)</label>
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<input type="number" name="amount" min="50" step="10" value="100" class="form-control" style="flex: 1; background: var(--surface-color); color: #fff; border: 1px solid var(--border-color);">
|
||||
<button type="submit" class="btn btn-primary">Back this Venture</button>
|
||||
<div class="form-group" style="margin-bottom: 15px;">
|
||||
<label style="font-size: 13px; font-weight: 600;">Investment Amount (£)</label>
|
||||
<input type="number" name="amount" class="form-control" min="100" step="100" value="1000" style="background: var(--surface-color); color: #fff; border: 1px solid var(--border-color); font-size: 18px; font-weight: 700;">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" style="width: 100%; padding: 15px; font-weight: 700; font-size: 16px;">Back this Venture</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
<?php else: ?>
|
||||
<section class="card" style="background: rgba(255,255,255,0.02); text-align: center; padding: 40px; border: 1px dashed var(--border-color);">
|
||||
<div style="font-size: 48px; color: var(--text-secondary); margin-bottom: 20px;"><i class="fas fa-lock"></i></div>
|
||||
<h3>No Active Funding Round</h3>
|
||||
<?php if ($user['role'] === 'founder' && $startup['founder_id'] == $user_id): ?>
|
||||
<button class="btn btn-primary" style="margin-top: 20px;" onclick="document.getElementById('newRoundForm').style.display='block'">Launch New Funding Round</button>
|
||||
<div id="newRoundForm" style="display: none; margin-top: 30px; text-align: left; background: var(--surface-color); padding: 25px; border-radius: 15px; border: 1px solid var(--border-color);">
|
||||
<h4>Round Details</h4>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="action" value="start_new_round">
|
||||
<div class="form-group" style="margin-bottom: 20px;">
|
||||
<label>New Funding Target (£)</label>
|
||||
<input type="number" name="new_target" min="50" step="50" class="form-control" required style="background: var(--bg-color); color: #fff; border: 1px solid var(--border-color);">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Start Round</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="document.getElementById('newRoundForm').style.display='none'">Cancel</button>
|
||||
</form>
|
||||
<?php elseif ($user['role'] === 'founder' && $startup['founder_id'] == $user_id): ?>
|
||||
<div style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 12px; font-size: 13px; color: var(--text-secondary); line-height: 1.5;">
|
||||
<i class="fas fa-info-circle"></i> This is your active funding round. Share the link with potential investors to reach your goal.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<section class="card" style="margin-bottom: 30px;">
|
||||
<h3 style="margin-top: 0; margin-bottom: 20px;">Venture Stats</h3>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px;">
|
||||
<div style="background: rgba(255,255,255,0.02); padding: 15px; border-radius: 12px; text-align: center; border: 1px solid var(--border-color);">
|
||||
<div style="color: var(--text-secondary); font-size: 11px; text-transform: uppercase; margin-bottom: 5px; font-weight: 700;">Backers</div>
|
||||
<?php
|
||||
$stmt = db()->prepare("SELECT COUNT(DISTINCT investor_id) FROM investments WHERE startup_id = ? AND status = 'approved'");
|
||||
$stmt->execute([$startup_id]);
|
||||
$backerCount = $stmt->fetchColumn();
|
||||
?>
|
||||
<div style="font-size: 20px; font-weight: 700;"><?= $backerCount ?></div>
|
||||
</div>
|
||||
<div style="background: rgba(255,255,255,0.02); padding: 15px; border-radius: 12px; text-align: center; border: 1px solid var(--border-color);">
|
||||
<div style="color: var(--text-secondary); font-size: 11px; text-transform: uppercase; margin-bottom: 5px; font-weight: 700;">Followers</div>
|
||||
<?php
|
||||
$stmt = db()->prepare("SELECT COUNT(*) FROM startup_followers WHERE startup_id = ?");
|
||||
$stmt->execute([$startup_id]);
|
||||
$followerCount = $stmt->fetchColumn();
|
||||
?>
|
||||
<div style="font-size: 20px; font-weight: 700;"><?= $followerCount ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="background: var(--surface-color); padding: 20px; border-radius: 16px; border: 1px solid var(--border-color); text-align: center;">
|
||||
<div style="color: var(--text-secondary); font-size: 11px; text-transform: uppercase; margin-bottom: 5px; font-weight: 700;">Total Raised All-Time</div>
|
||||
<div style="font-size: 28px; font-weight: 900; color: #fff;">£<?= number_format($startup['funding_raised']) ?></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<h3 style="margin-top: 0; margin-bottom: 20px;">Founder</h3>
|
||||
<h3 style="margin-top: 0;">Founder</h3>
|
||||
<?php
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$startup['founder_id']]);
|
||||
$founder = $stmt->fetch();
|
||||
?>
|
||||
<?php if ($founder): ?>
|
||||
<div style="display: flex; align-items: center; gap: 15px; margin-bottom: 20px;">
|
||||
<div style="width: 50px; height: 50px; border-radius: 50%; background: var(--surface-color); overflow: hidden;">
|
||||
<?php if ($founder['profile_photo']): ?>
|
||||
<img src="<?= htmlspecialchars($founder['profile_photo']) ?>" style="width: 100%; height: 100%; object-fit: cover;">
|
||||
<?php else: ?>
|
||||
<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: var(--gradient-primary); color: white;">
|
||||
<?= substr($founder['full_name'], 0, 1) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 600;"><?= htmlspecialchars($founder['full_name']) ?></div>
|
||||
<div style="font-size: 13px; color: var(--text-secondary);">
|
||||
<?= htmlspecialchars($founder['university']) ?></div>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 15px; margin-top: 20px;">
|
||||
<div style="width: 50px; height: 50px; background: var(--surface-color); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 800; color: #fff; border: 2px solid var(--accent-blue);">
|
||||
<?= substr($founder['full_name'], 0, 1) ?>
|
||||
</div>
|
||||
<a href="messages.php?chat_with=<?= $founder['id'] ?>&startup_id=<?= $startup_id ?>" class="btn btn-outline" style="width: 100%; text-align: center; display: block; border-radius: 12px; border: 1px solid var(--border-color);">Send Message</a>
|
||||
<?php endif; ?>
|
||||
<div>
|
||||
<div style="font-weight: 700;"><?= htmlspecialchars($founder['full_name'] ?? 'Founder') ?></div>
|
||||
<div style="font-size: 13px; color: var(--text-secondary);"><?= htmlspecialchars($founder['university'] ?? 'Founder') ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="messages.php?chat_with=<?= $founder['id'] ?>" class="btn btn-secondary" style="width: 100%; margin-top: 20px; padding: 12px; border-radius: 12px;">Send Message</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
header { background: rgba(10, 10, 15, 0.8); backdrop-filter: blur(20px); border-bottom: 1px solid var(--border-color); padding: 15px 0; position: sticky; top: 0; z-index: 1000; }
|
||||
.nav-links a { color: var(--text-secondary); text-decoration: none; margin: 0 15px; font-size: 14px; font-weight: 500; transition: color 0.2s; }
|
||||
.nav-links a:hover { color: #fff; }
|
||||
</style>
|
||||
<footer style="margin-top: 80px; padding: 60px 0; border-top: 1px solid var(--border-color); background: rgba(0,0,0,0.2);">
|
||||
<div class="container" style="text-align: center;">
|
||||
<div class="logo-container" style="justify-content: center; margin-bottom: 25px;">
|
||||
<img src="assets/images/logo.svg" alt="<?= htmlspecialchars($platformName) ?> Logo" class="logo-img" style="width: 30px; height: 30px;">
|
||||
<span class="logo-text" style="font-size: 20px;"><?= htmlspecialchars($platformName) ?></span>
|
||||
</div>
|
||||
<p style="color: var(--text-secondary); font-size: 14px;">© <?= date('Y') ?> <?= htmlspecialchars($platformName) ?>. All rights reserved.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="assets/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
132
startups.php
132
startups.php
@ -1,46 +1,27 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
session_start();
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
if (!$user_id) { header('Location: login.php'); exit; }
|
||||
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
if (!$user) { header('Location: login.php'); exit; }
|
||||
|
||||
$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
|
||||
// Identify Trending Startups (Top 3 in followers or funding)
|
||||
$trendingIds = [];
|
||||
|
||||
// Top 3 Followed
|
||||
$stmt = db()->prepare("
|
||||
SELECT s.id
|
||||
FROM startups s
|
||||
LEFT JOIN startup_followers sf ON s.id = sf.startup_id
|
||||
GROUP BY s.id
|
||||
ORDER BY COUNT(sf.id) DESC
|
||||
LIMIT 3
|
||||
");
|
||||
$stmt->execute();
|
||||
$topFollowed = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
$trendingIds = array_merge($trendingIds, $topFollowed);
|
||||
|
||||
// Top 3 Funded (Total)
|
||||
// Fetch Trending Startups based on total funding raised
|
||||
$stmt = db()->prepare("
|
||||
SELECT id
|
||||
FROM startups
|
||||
ORDER BY funding_raised DESC
|
||||
LIMIT 3
|
||||
LIMIT 10
|
||||
");
|
||||
$stmt->execute();
|
||||
$topFunded = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
$trendingIds = array_unique(array_merge($trendingIds, $topFunded));
|
||||
$trendingIds = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
$myStartups = [];
|
||||
if ($user['role'] === 'founder') {
|
||||
$stmt = db()->prepare("
|
||||
SELECT s.*, fr.funding_goal as active_goal, fr.funding_raised as active_raised, fr.status as round_status
|
||||
@ -49,17 +30,16 @@ if ($user['role'] === 'founder') {
|
||||
WHERE s.founder_id = ?
|
||||
ORDER BY s.created_at DESC
|
||||
");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$stmt->execute([$user_id]);
|
||||
$myStartups = $stmt->fetchAll();
|
||||
} else {
|
||||
// Investors see all public startups and their active round if any
|
||||
// Browse all startups for investors
|
||||
$stmt = db()->prepare("
|
||||
SELECT s.*, u.full_name as founder_name, fr.funding_goal as active_goal, fr.funding_raised as active_raised, fr.status as round_status
|
||||
SELECT s.*, fr.funding_goal as active_goal, fr.funding_raised as active_raised, fr.status as round_status, u.full_name as founder_name
|
||||
FROM startups s
|
||||
LEFT JOIN users u ON s.founder_id = u.id
|
||||
LEFT JOIN funding_rounds fr ON s.id = fr.startup_id AND fr.status = 'Active'
|
||||
WHERE s.status = 'public'
|
||||
ORDER BY s.created_at DESC
|
||||
LEFT JOIN users u ON s.founder_id = u.id
|
||||
ORDER BY s.funding_raised DESC, s.created_at DESC
|
||||
");
|
||||
$stmt->execute();
|
||||
$myStartups = $stmt->fetchAll();
|
||||
@ -70,8 +50,10 @@ if ($user['role'] === 'founder') {
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title><?= $user['role'] === 'founder' ? 'My Startups' : 'Browse Startups' ?> — <?= htmlspecialchars($platformName) ?></title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<title><?= $user['role'] === 'founder' ? 'My Startups' : 'Student Startups' ?> — <?= htmlspecialchars($platformName) ?></title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<style>
|
||||
@ -118,11 +100,18 @@ if ($user['role'] === 'founder') {
|
||||
<?php endif; ?>
|
||||
<a href="discover.php">Discovery Hub</a>
|
||||
<a href="messages.php">Messages</a>
|
||||
<a href="notifications.php">Notifications</a>
|
||||
</nav>
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<a href="dashboard.php" style="color: var(--text-secondary);"><i class="fas fa-th-large"></i></a>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 13px;">Log Out</a>
|
||||
<a href="notifications.php" style="color: var(--text-secondary); position: relative; font-size: 18px;">
|
||||
<i class="fas fa-bell"></i>
|
||||
</a>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 5px 12px; background: rgba(255,255,255,0.05); border-radius: 50px; border: 1px solid var(--border-color);">
|
||||
<div style="width: 24px; height: 24px; background: var(--gradient-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #fff; font-weight: 800;">
|
||||
<?= substr($user['full_name'], 0, 1) ?>
|
||||
</div>
|
||||
<span style="font-size: 13px; font-weight: 600;"><?= htmlspecialchars(explode(' ', $user['full_name'])[0]) ?></span>
|
||||
</div>
|
||||
<a href="logout.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 12px; border-radius: 10px;">Log Out</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@ -138,7 +127,7 @@ if ($user['role'] === 'founder') {
|
||||
<p style="color: var(--text-secondary);"><?= $user['role'] === 'founder' ? 'Manage and track your ventures.' : 'Discover the next generation of student-led innovation.' ?></p>
|
||||
</div>
|
||||
<?php if ($user['role'] === 'founder'): ?>
|
||||
<a href="start_funding.php" class="btn btn-primary">List New Startup</a>
|
||||
<a href="founder_onboarding.php" class="btn btn-primary">List New Startup</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
@ -149,7 +138,7 @@ if ($user['role'] === 'founder') {
|
||||
<h3>No startups found</h3>
|
||||
<p style="color: var(--text-secondary);">Start your journey by listing your first startup or idea.</p>
|
||||
<?php if ($user['role'] === 'founder'): ?>
|
||||
<a href="start_funding.php" class="btn btn-primary" style="margin-top: 25px;">Start Funding Round</a>
|
||||
<a href="founder_onboarding.php" class="btn btn-primary" style="margin-top: 25px;">Start Funding Round</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
@ -179,25 +168,18 @@ if ($user['role'] === 'founder') {
|
||||
<p style="font-size: 14px; color: var(--text-secondary); margin-bottom: 25px; line-height: 1.6; height: 42px; overflow: hidden;">
|
||||
<?= htmlspecialchars(substr($startup['description'], 0, 120)) ?>...
|
||||
</p>
|
||||
<div style="margin-bottom: 20px;">
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 8px;">
|
||||
<span>Progress</span>
|
||||
<span><?= $progress ?>%</span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 8px; background: var(--border-color); border-radius: 4px; overflow: hidden;">
|
||||
<div style="width: <?= min(100, $progress) ?>%; height: 100%; background: var(--gradient-primary);"></div>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px; font-weight: 600; display: flex; justify-content: space-between; font-size: 13px;">
|
||||
<span>£<?= number_format($raised) ?> Raised</span>
|
||||
<span style="color: var(--text-secondary);"><?= $progress ?>%</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; border-top: 1px solid var(--border-color); padding-top: 20px;">
|
||||
<div>
|
||||
<div style="font-size: 10px; color: var(--text-secondary); text-transform: uppercase;">Raised</div>
|
||||
<div style="font-weight: 700; color: #fff;">£<?= number_format($raised, 0) ?></div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 10px; color: var(--text-secondary); text-transform: uppercase;">Goal</div>
|
||||
<div style="font-weight: 700; color: #fff;">£<?= number_format($goal, 0) ?></div>
|
||||
</div>
|
||||
<a href="startup_details.php?id=<?= $startup['id'] ?>" class="btn btn-secondary" style="padding: 8px 16px; font-size: 12px;"><?= $user['role'] === 'founder' ? 'Manage' : 'View' ?></a>
|
||||
<div style="width: 100%; height: 6px; background: var(--border-color); border-radius: 3px; overflow: hidden; margin-bottom: 25px;">
|
||||
<div style="width: <?= min(100, $progress) ?>%; height: 100%; background: var(--gradient-primary);"></div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<a href="startup_details.php?id=<?= $startup['id'] ?>" class="btn btn-outline" style="flex: 1; padding: 10px; font-size: 13px;">View Details</a>
|
||||
<?php if ($user['role'] === 'founder'): ?>
|
||||
<a href="start_funding.php?id=<?= $startup['id'] ?>" class="btn btn-secondary" style="padding: 10px; font-size: 13px;"><i class="fas fa-edit"></i></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
@ -205,28 +187,16 @@ if ($user['role'] === 'founder') {
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
header {
|
||||
background: rgba(10, 10, 15, 0.8);
|
||||
backdrop-filter: blur(20px);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding: 15px 0;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
.nav-links a {
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
margin: 0 15px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
.nav-links a:hover, .nav-links a.active {
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
<footer style="margin-top: 80px; padding: 60px 0; border-top: 1px solid var(--border-color); background: rgba(0,0,0,0.2);">
|
||||
<div class="container" style="text-align: center;">
|
||||
<div class="logo-container" style="justify-content: center; margin-bottom: 25px;">
|
||||
<img src="assets/images/logo.svg" alt="<?= htmlspecialchars($platformName) ?> Logo" class="logo-img" style="width: 30px; height: 30px;">
|
||||
<span class="logo-text" style="font-size: 20px;"><?= htmlspecialchars($platformName) ?></span>
|
||||
</div>
|
||||
<p style="color: var(--text-secondary); font-size: 14px;">© <?= date('Y') ?> <?= htmlspecialchars($platformName) ?>. All rights reserved.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="assets/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user