v6
This commit is contained in:
parent
844a54704c
commit
2f6215ae8e
@ -37,7 +37,14 @@ $myStartups = [];
|
||||
$myInvestments = [];
|
||||
|
||||
if ($user['role'] === 'founder') {
|
||||
$stmt = db()->prepare("SELECT * FROM startups WHERE founder_id = ? ORDER BY created_at DESC");
|
||||
// Fetch startups and their active round if any
|
||||
$stmt = db()->prepare("
|
||||
SELECT s.*, fr.funding_goal as active_goal, fr.funding_raised as active_raised, fr.status as round_status
|
||||
FROM startups s
|
||||
LEFT JOIN funding_rounds fr ON s.id = fr.startup_id AND fr.status = 'Active'
|
||||
WHERE s.founder_id = ?
|
||||
ORDER BY s.created_at DESC
|
||||
");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$myStartups = $stmt->fetchAll();
|
||||
} else {
|
||||
@ -93,7 +100,7 @@ function number_get_formatted($num) {
|
||||
<div class="card" style="margin-bottom: 30px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px;">
|
||||
<h3 style="margin: 0;">My Ventures</h3>
|
||||
<a href="start_funding.php" class="btn btn-primary" style="padding: 10px 20px; font-size: 14px;">+ Launch Round</a>
|
||||
<a href="start_funding.php" class="btn btn-primary" style="padding: 10px 20px; font-size: 14px;">+ Launch New Startup</a>
|
||||
</div>
|
||||
|
||||
<?php if (empty($myStartups)): ?>
|
||||
@ -104,18 +111,23 @@ function number_get_formatted($num) {
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div style="display: grid; grid-template-columns: 1fr; gap: 15px;">
|
||||
<?php foreach ($myStartups as $startup): ?>
|
||||
<?php foreach ($myStartups as $startup):
|
||||
$goal = $startup['active_goal'] ?? $startup['funding_target'];
|
||||
$raised = $startup['active_raised'] ?? $startup['funding_raised'];
|
||||
?>
|
||||
<div style="padding: 20px; background: var(--surface-color); border-radius: 16px; border: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: center; transition: all 0.2s; cursor: pointer;" onclick="window.location.href='startup_details.php?id=<?= $startup['id'] ?>'">
|
||||
<div>
|
||||
<div style="font-weight: 600; font-size: 18px; margin-bottom: 4px;"><?= htmlspecialchars($startup['name']) ?></div>
|
||||
<div style="font-size: 13px; color: var(--text-secondary); display: flex; align-items: center; gap: 10px;">
|
||||
<span style="padding: 2px 8px; background: rgba(0, 122, 255, 0.1); color: var(--accent-blue); border-radius: 4px; font-weight: 600;"><?= strtoupper($startup['status']) ?></span>
|
||||
<span>Target: £<?= number_get_formatted($startup['funding_target']) ?></span>
|
||||
<span style="padding: 2px 8px; background: rgba(0, 122, 255, 0.1); color: var(--accent-blue); border-radius: 4px; font-weight: 600;">
|
||||
<?= $startup['round_status'] === 'Active' ? 'ROUND ACTIVE' : 'NO ACTIVE ROUND' ?>
|
||||
</span>
|
||||
<span>Target: £<?= number_get_formatted($goal) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div style="font-size: 18px; font-weight: 700; color: #fff;">£<?= number_get_formatted($startup['funding_raised']) ?></div>
|
||||
<div style="font-size: 12px; color: var(--text-secondary);">Raised so far</div>
|
||||
<div style="font-size: 18px; font-weight: 700; color: #fff;">£<?= number_get_formatted($raised) ?></div>
|
||||
<div style="font-size: 12px; color: var(--text-secondary);">Raised in round</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
@ -145,7 +157,7 @@ function number_get_formatted($num) {
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div style="font-size: 18px; font-weight: 700; color: var(--accent-blue);">£<?= number_get_formatted($inv['amount']) ?></div>
|
||||
<div style="font-size: 12px; font-weight: 600; color: <?= $inv['status'] === 'approved' ? '#4cd964' : ($inv['status'] === 'rejected' ? '#ff3b30' : '#ffcc00') ?>;">
|
||||
<div style="font-size: 12px; font-weight: 600; color: <?= $inv['status'] === 'approved' ? '#4cd964' : ($inv['status'] === 'rejected' ? '#ff3b30' : ($inv['status'] === 'Refunded' ? '#ff9500' : '#ffcc00')) ?>;">
|
||||
<?= strtoupper($inv['status']) ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -236,4 +248,4 @@ function number_get_formatted($num) {
|
||||
</style>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
30
db/migrations/04_funding_rounds.sql
Normal file
30
db/migrations/04_funding_rounds.sql
Normal file
@ -0,0 +1,30 @@
|
||||
-- Migration: Independent Funding Rounds and Pot System
|
||||
|
||||
-- 1. Create funding_rounds table
|
||||
CREATE TABLE IF NOT EXISTS funding_rounds (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
startup_id INT NOT NULL,
|
||||
funding_goal DECIMAL(15, 2) NOT NULL,
|
||||
funding_raised DECIMAL(15, 2) DEFAULT 0.00,
|
||||
status ENUM('Active', 'Closed', 'Cancelled') DEFAULT 'Active',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (startup_id) REFERENCES startups(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 2. Modify investments table to link to funding_rounds
|
||||
ALTER TABLE investments ADD COLUMN funding_round_id INT AFTER startup_id;
|
||||
ALTER TABLE investments ADD FOREIGN KEY (funding_round_id) REFERENCES funding_rounds(id) ON DELETE CASCADE;
|
||||
|
||||
-- 3. Update startups table to allow NULL founder_id (for deleted accounts)
|
||||
ALTER TABLE startups DROP FOREIGN KEY startups_ibfk_1;
|
||||
ALTER TABLE startups MODIFY founder_id INT NULL;
|
||||
ALTER TABLE startups ADD CONSTRAINT startups_founder_fk FOREIGN KEY (founder_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||
|
||||
-- 4. Seed initial funding rounds from existing startup data if any
|
||||
INSERT INTO funding_rounds (startup_id, funding_goal, funding_raised, status, created_at)
|
||||
SELECT id, funding_target, funding_raised, 'Active', created_at FROM startups;
|
||||
|
||||
-- 5. Link existing investments to the newly created rounds
|
||||
UPDATE investments i
|
||||
JOIN funding_rounds fr ON i.startup_id = fr.startup_id
|
||||
SET i.funding_round_id = fr.id;
|
||||
108
edit_profile.php
108
edit_profile.php
@ -16,27 +16,54 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
$error = '';
|
||||
$success = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$full_name = trim($_POST['full_name'] ?? '');
|
||||
$bio = trim($_POST['bio'] ?? '');
|
||||
$interests = trim($_POST['interests'] ?? '');
|
||||
$investment_appetite = trim($_POST['investment_appetite'] ?? '');
|
||||
// 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 (empty($full_name)) {
|
||||
$error = "Name cannot be empty.";
|
||||
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 {
|
||||
$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();
|
||||
$full_name = trim($_POST['full_name'] ?? '');
|
||||
$bio = trim($_POST['bio'] ?? '');
|
||||
$interests = trim($_POST['interests'] ?? '');
|
||||
$investment_appetite = trim($_POST['investment_appetite'] ?? '');
|
||||
|
||||
if (empty($full_name)) {
|
||||
$error = "Name cannot be empty.";
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -59,7 +86,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
<nav class="nav-links">
|
||||
<?php if ($user['role'] === 'founder'): ?>
|
||||
<a href="startups.php">My Startups</a>
|
||||
<a href="partners.php">Find Partners</a>
|
||||
<a href="discover.php">Find Partners</a>
|
||||
<?php else: ?>
|
||||
<a href="discover.php">Discover</a>
|
||||
<a href="portfolio.php">Portfolio</a>
|
||||
@ -90,7 +117,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card">
|
||||
<div class="card" style="margin-bottom: 30px;">
|
||||
<form method="POST">
|
||||
<div style="margin-bottom: 20px;">
|
||||
<label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500;">Full Name</label>
|
||||
@ -122,8 +149,45 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
<button type="submit" class="btn btn-primary" style="width: 100%; padding: 15px;">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;">
|
||||
<input type="hidden" name="action" value="delete_account">
|
||||
</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>
|
||||
</div>
|
||||
</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>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@ -19,12 +19,22 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (empty($name) || empty($description) || $target < 50) {
|
||||
$error = "Please fill in all required fields. Minimum target is £50.";
|
||||
} else {
|
||||
$stmt = db()->prepare("INSERT INTO startups (name, description, founder_id, funding_target, status) VALUES (?, ?, ?, ?, ?)");
|
||||
db()->beginTransaction();
|
||||
try {
|
||||
// 1. Insert startup (keep target/raised for compatibility/legacy but we'll use funding_rounds)
|
||||
$stmt = db()->prepare("INSERT INTO startups (name, description, founder_id, funding_target, status) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$name, $description, $_SESSION['user_id'], $target, $status]);
|
||||
$startup_id = db()->lastInsertId();
|
||||
|
||||
// 2. Insert initial funding round
|
||||
$stmt = db()->prepare("INSERT INTO funding_rounds (startup_id, funding_goal, status) VALUES (?, ?, 'Active')");
|
||||
$stmt->execute([$startup_id, $target]);
|
||||
|
||||
db()->commit();
|
||||
$success = "Startup listed successfully! Your funding round is now active.";
|
||||
header("refresh:2;url=dashboard.php");
|
||||
} catch (PDOException $e) {
|
||||
db()->rollBack();
|
||||
$error = "Database error: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
@ -86,4 +96,4 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@ -13,7 +13,8 @@ if (!$startup_id) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = db()->prepare("SELECT s.*, u.full_name as founder_name, u.university as founder_uni, u.graduation_year FROM startups s JOIN users u ON s.founder_id = u.id WHERE s.id = ?");
|
||||
// Fetch startup details (handle missing founder due to account deletion)
|
||||
$stmt = db()->prepare("SELECT s.*, u.full_name as founder_name, u.university as founder_uni, u.graduation_year FROM startups s LEFT JOIN users u ON s.founder_id = u.id WHERE s.id = ?");
|
||||
$stmt->execute([$startup_id]);
|
||||
$startup = $stmt->fetch();
|
||||
|
||||
@ -26,13 +27,82 @@ $stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
// Fetch 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();
|
||||
|
||||
// Fetch round history
|
||||
$stmt = db()->prepare("SELECT * FROM funding_rounds WHERE startup_id = ? ORDER BY created_at DESC");
|
||||
$stmt->execute([$startup_id]);
|
||||
$rounds = $stmt->fetchAll();
|
||||
|
||||
$error = '';
|
||||
$success = '';
|
||||
|
||||
// Handle Investment
|
||||
// Handle Round Controls (Founder Only)
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $startup['founder_id'] == $_SESSION['user_id']) {
|
||||
$action = $_POST['action'];
|
||||
$round_id = (int)($_POST['round_id'] ?? 0);
|
||||
|
||||
if ($action === 'finish_round_early' && $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; // Refresh for UI
|
||||
} elseif ($action === 'cancel_round' && $activeRound && $activeRound['id'] == $round_id) {
|
||||
db()->beginTransaction();
|
||||
try {
|
||||
// 1. Cancel round
|
||||
$stmt = db()->prepare("UPDATE funding_rounds SET status = 'Cancelled' WHERE id = ?");
|
||||
$stmt->execute([$round_id]);
|
||||
|
||||
// 2. Refund all investors for this round
|
||||
$stmt = db()->prepare("SELECT * FROM investments WHERE funding_round_id = ? AND status = 'approved'");
|
||||
$stmt->execute([$round_id]);
|
||||
$investmentsToRefund = $stmt->fetchAll();
|
||||
|
||||
foreach ($investmentsToRefund as $inv) {
|
||||
// Mark investment as refunded
|
||||
$upd = db()->prepare("UPDATE investments SET status = 'Refunded' WHERE id = ?");
|
||||
$upd->execute([$inv['id']]);
|
||||
|
||||
// Notify investor
|
||||
$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; // Refresh for UI
|
||||
} 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!";
|
||||
// Refresh active round
|
||||
$stmt = db()->prepare("SELECT * FROM funding_rounds WHERE startup_id = ? AND status = 'Active' LIMIT 1");
|
||||
$stmt->execute([$startup_id]);
|
||||
$activeRound = $stmt->fetch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Investment (Investor Only)
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['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) {
|
||||
@ -40,9 +110,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
} else {
|
||||
db()->beginTransaction();
|
||||
try {
|
||||
$stmt = db()->prepare("INSERT INTO investments (investor_id, startup_id, amount, status) VALUES (?, ?, ?, 'approved')");
|
||||
$stmt->execute([$_SESSION['user_id'], $startup_id, $amount]);
|
||||
// Use funding_round_id for the investment
|
||||
$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]);
|
||||
|
||||
// Update funding_raised in funding_rounds (the dedicated pot)
|
||||
$stmt = db()->prepare("UPDATE funding_rounds SET funding_raised = funding_raised + ? WHERE id = ?");
|
||||
$stmt->execute([$amount, $activeRound['id']]);
|
||||
|
||||
// Update legacy field for backward compatibility in listing pages if needed
|
||||
$stmt = db()->prepare("UPDATE startups SET funding_raised = funding_raised + ? WHERE id = ?");
|
||||
$stmt->execute([$amount, $startup_id]);
|
||||
|
||||
@ -50,8 +126,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
$stmt->execute([$startup['founder_id'], "New investment of £" . number_format($amount) . " in " . $startup['name'] . "!"]);
|
||||
|
||||
db()->commit();
|
||||
$success = "Investment successful! You've successfully backed " . htmlspecialchars($startup['name']) . ".";
|
||||
header("refresh:2;url=portfolio.php");
|
||||
$success = "Investment successful! You've backed the current round.";
|
||||
// Refresh active round data
|
||||
$stmt = db()->prepare("SELECT * FROM funding_rounds WHERE id = ?");
|
||||
$stmt->execute([$activeRound['id']]);
|
||||
$activeRound = $stmt->fetch();
|
||||
} catch (Exception $e) {
|
||||
db()->rollBack();
|
||||
$error = "Investment failed: " . $e->getMessage();
|
||||
@ -105,7 +184,8 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<div>
|
||||
<h1 style="margin-bottom: 5px;"><?= htmlspecialchars($startup['name']) ?></h1>
|
||||
<div style="color: var(--text-secondary); font-size: 14px;">
|
||||
Founded by <?= htmlspecialchars($startup['founder_name']) ?> (<?= htmlspecialchars($startup['founder_uni']) ?>)
|
||||
Founded by <?= $startup['founder_name'] ? htmlspecialchars($startup['founder_name']) : '<em>Account Deleted</em>' ?>
|
||||
<?php if ($startup['founder_uni']): ?> (<?= htmlspecialchars($startup['founder_uni']) ?>)<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -117,7 +197,7 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card" style="margin-bottom: 30px;">
|
||||
<h3>Investment Terms (Dividend-Only Returns)</h3>
|
||||
<div style="padding: 20px; background: rgba(0, 122, 255, 0.05); border: 1px solid rgba(0, 122, 255, 0.2); border-radius: 12px; margin-top: 15px;">
|
||||
<p style="font-size: 14px; margin-bottom: 10px;"><i class="fas fa-info-circle"></i> <strong>How it works:</strong></p>
|
||||
@ -125,31 +205,52 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
<li>Investors are entitled to a share of future profits as **dividends**.</li>
|
||||
<li>No voting rights or equity control are granted to investors.</li>
|
||||
<li>Returns are primarily distributed through profit-sharing mechanisms.</li>
|
||||
<li>This model focuses on sustainable student-led business growth.</li>
|
||||
<li>Each funding round is independent and maintains its own investment pot.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Funding Round History</h3>
|
||||
<div style="margin-top: 20px;">
|
||||
<?php foreach ($rounds as $r): ?>
|
||||
<div style="display: flex; justify-content: space-between; padding: 15px 0; border-bottom: 1px solid var(--border-color); font-size: 14px;">
|
||||
<div>
|
||||
<div style="font-weight: 600;"><?= date('M d, Y', strtotime($r['created_at'])) ?> Round</div>
|
||||
<div style="color: var(--text-secondary);">Target: £<?= number_format($r['funding_goal']) ?></div>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div style="font-weight: 700;">£<?= number_format($r['funding_raised']) ?> Raised</div>
|
||||
<span style="font-size: 10px; text-transform: uppercase; color: <?= $r['status'] === 'Active' ? '#00f2ff' : ($r['status'] === 'Closed' ? '#55ff55' : '#ff5555') ?>;">
|
||||
<?= $r['status'] ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<?php if ($activeRound): ?>
|
||||
<div class="card" style="margin-bottom: 30px; background: var(--surface-color); border: 1px solid var(--border-color);">
|
||||
<h3 style="margin-bottom: 25px;">Funding Progress</h3>
|
||||
<h3 style="margin-bottom: 25px;">Current Funding Round</h3>
|
||||
|
||||
<div style="margin-bottom: 30px;">
|
||||
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
|
||||
<span style="font-weight: 700; font-size: 24px;">£<?= number_format($startup['funding_raised'], 0) ?></span>
|
||||
<span style="color: var(--text-secondary); font-size: 14px; align-self: flex-end;">of £<?= number_format($startup['funding_target'], 0) ?></span>
|
||||
<span style="font-weight: 700; font-size: 24px;">£<?= number_format($activeRound['funding_raised'], 0) ?></span>
|
||||
<span style="color: var(--text-secondary); font-size: 14px; align-self: flex-end;">of £<?= number_format($activeRound['funding_goal'], 0) ?></span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 12px; background: var(--border-color); border-radius: 6px; overflow: hidden;">
|
||||
<div style="width: <?= min(100, ($startup['funding_raised'] / ($startup['funding_target'] ?: 1)) * 100) ?>%; height: 100%; background: var(--gradient-primary); box-shadow: 0 0 20px rgba(0, 122, 255, 0.5);"></div>
|
||||
<div style="width: <?= min(100, ($activeRound['funding_raised'] / ($activeRound['funding_goal'] ?: 1)) * 100) ?>%; height: 100%; background: var(--gradient-primary); box-shadow: 0 0 20px rgba(0, 122, 255, 0.5);"></div>
|
||||
</div>
|
||||
<div style="text-align: right; font-size: 12px; color: var(--text-secondary); margin-top: 8px;">
|
||||
<?= round(($startup['funding_raised'] / ($startup['funding_target'] ?: 1)) * 100) ?>% Raised
|
||||
<?= round(($activeRound['funding_raised'] / ($activeRound['funding_goal'] ?: 1)) * 100) ?>% Raised
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?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;">
|
||||
<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 elseif ($error): ?>
|
||||
@ -158,32 +259,56 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!$success): ?>
|
||||
<?php if ($user['role'] === 'investor'): ?>
|
||||
<?php if ($user['role'] === 'investor'): ?>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="action" value="invest">
|
||||
<div style="margin-bottom: 20px;">
|
||||
<label style="display: block; margin-bottom: 8px; font-size: 14px;">Investment Amount (£)</label>
|
||||
<input type="number" name="amount" min="50" step="50" required style="width: 100%; padding: 12px; border-radius: 12px; background: rgba(255,255,255,0.05); border: 1px solid var(--border-color); color: #fff; font-size: 18px; font-weight: 700;">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" style="width: 100%; padding: 15px;">Back This Project</button>
|
||||
</form>
|
||||
<?php elseif ($startup['founder_id'] == $_SESSION['user_id']): ?>
|
||||
<div style="display: flex; flex-direction: column; gap: 10px;">
|
||||
<form method="POST">
|
||||
<input type="hidden" name="action" value="invest">
|
||||
<div style="margin-bottom: 20px;">
|
||||
<label style="display: block; margin-bottom: 8px; font-size: 14px;">Investment Amount (£)</label>
|
||||
<input type="number" name="amount" min="50" step="50" required style="width: 100%; padding: 12px; border-radius: 12px; background: rgba(255,255,255,0.05); border: 1px solid var(--border-color); color: #fff; font-size: 18px; font-weight: 700;">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" style="width: 100%; padding: 15px;">Back This Project</button>
|
||||
<input type="hidden" name="action" value="finish_round_early">
|
||||
<input type="hidden" name="round_id" value="<?= $activeRound['id'] ?>">
|
||||
<button type="submit" class="btn btn-secondary" style="width: 100%; padding: 12px; font-size: 14px;">Finish Round Early</button>
|
||||
</form>
|
||||
<?php elseif ($startup['founder_id'] == $_SESSION['user_id']): ?>
|
||||
<div style="padding: 20px; text-align: center; border: 1px dashed var(--border-color); border-radius: 12px;">
|
||||
<p style="font-size: 14px; color: var(--text-secondary); margin-bottom: 0;">This is your startup listing. You can't invest in your own project.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div style="padding: 20px; text-align: center; border: 1px dashed var(--border-color); border-radius: 12px;">
|
||||
<p style="font-size: 14px; color: var(--text-secondary); margin-bottom: 0;">Only verified investors can participate in funding rounds.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<form method="POST" onsubmit="return confirm('Are you sure you want to cancel this funding round? All investors will be automatically refunded.')">
|
||||
<input type="hidden" name="action" value="cancel_round">
|
||||
<input type="hidden" name="round_id" value="<?= $activeRound['id'] ?>">
|
||||
<button type="submit" class="btn btn-secondary" style="width: 100%; padding: 12px; font-size: 14px; border-color: #ff5555; color: #ff5555;">Cancel Funding Round</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="card" style="margin-bottom: 30px; text-align: center; border: 1px dashed var(--border-color);">
|
||||
<i class="fas fa-hourglass-end" style="font-size: 32px; color: var(--text-secondary); margin-bottom: 15px; opacity: 0.5;"></i>
|
||||
<h3>No Active Round</h3>
|
||||
<p style="color: var(--text-secondary); font-size: 14px;">This startup is not currently seeking investment.</p>
|
||||
|
||||
<?php if ($startup['founder_id'] == $_SESSION['user_id']): ?>
|
||||
<div style="margin-top: 25px; text-align: left;">
|
||||
<h4 style="margin-bottom: 15px; font-size: 14px;">Start a New Round</h4>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="action" value="start_new_round">
|
||||
<div style="margin-bottom: 15px;">
|
||||
<label style="display: block; margin-bottom: 5px; font-size: 12px; color: var(--text-secondary);">New Funding Goal (£)</label>
|
||||
<input type="number" name="new_target" min="50" step="50" required style="width: 100%; padding: 10px; border-radius: 8px; background: var(--surface-color); border: 1px solid var(--border-color); color: #fff;">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" style="width: 100%; padding: 10px; font-size: 14px;">Launch Round</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card">
|
||||
<h3>Risk Disclosure</h3>
|
||||
<p style="font-size: 12px; color: var(--text-secondary); line-height: 1.5;">
|
||||
Student startups carry high risk. Dividends are not guaranteed and depend on the profitability of the venture. This is not financial advice. All student entrepreneurs are verified, but Gatsby does not conduct full financial audits of individual ideas.
|
||||
Student startups carry high risk. Dividends are not guaranteed and depend on the profitability of the venture. Each round is independent.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -191,4 +316,4 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
41
startups.php
41
startups.php
@ -15,12 +15,25 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
|
||||
|
||||
$myStartups = [];
|
||||
if ($user['role'] === 'founder') {
|
||||
$stmt = db()->prepare("SELECT * FROM startups WHERE founder_id = ? ORDER BY created_at DESC");
|
||||
$stmt = db()->prepare("
|
||||
SELECT s.*, fr.funding_goal as active_goal, fr.funding_raised as active_raised, fr.status as round_status
|
||||
FROM startups s
|
||||
LEFT JOIN funding_rounds fr ON s.id = fr.startup_id AND fr.status = 'Active'
|
||||
WHERE s.founder_id = ?
|
||||
ORDER BY s.created_at DESC
|
||||
");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$myStartups = $stmt->fetchAll();
|
||||
} else {
|
||||
// Investors see all public startups
|
||||
$stmt = db()->prepare("SELECT s.*, u.full_name as founder_name FROM startups s JOIN users u ON s.founder_id = u.id WHERE s.status = 'public' ORDER BY s.created_at DESC");
|
||||
// Investors see all public startups and their active round if any
|
||||
$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
|
||||
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
|
||||
");
|
||||
$stmt->execute();
|
||||
$myStartups = $stmt->fetchAll();
|
||||
}
|
||||
@ -80,17 +93,21 @@ if ($user['role'] === 'founder') {
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($myStartups as $startup): ?>
|
||||
<?php foreach ($myStartups as $startup):
|
||||
$goal = $startup['active_goal'] ?? $startup['funding_target'];
|
||||
$raised = $startup['active_raised'] ?? $startup['funding_raised'];
|
||||
$progress = round(($raised / ($goal ?: 1)) * 100);
|
||||
?>
|
||||
<div class="card">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 15px;">
|
||||
<div>
|
||||
<h3 style="margin: 0;"><?= htmlspecialchars($startup['name']) ?></h3>
|
||||
<?php if ($user['role'] === 'investor'): ?>
|
||||
<div style="font-size: 12px; color: var(--text-secondary); margin-top: 4px;">by <?= htmlspecialchars($startup['founder_name']) ?></div>
|
||||
<div style="font-size: 12px; color: var(--text-secondary); margin-top: 4px;">by <?= $startup['founder_name'] ? htmlspecialchars($startup['founder_name']) : 'Account Deleted' ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<span style="font-size: 10px; text-transform: uppercase; padding: 4px 8px; background: rgba(0, 242, 255, 0.1); color: var(--accent-blue); border-radius: 4px; border: 1px solid rgba(0, 242, 255, 0.3);">
|
||||
<?= htmlspecialchars($startup['status']) ?>
|
||||
<?= $startup['round_status'] === 'Active' ? 'Active Round' : 'No Active Round' ?>
|
||||
</span>
|
||||
</div>
|
||||
<p style="font-size: 14px; color: var(--text-secondary); margin-bottom: 25px; line-height: 1.6;">
|
||||
@ -99,20 +116,20 @@ if ($user['role'] === 'founder') {
|
||||
<div style="margin-bottom: 20px;">
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 8px;">
|
||||
<span>Progress</span>
|
||||
<span><?= round(($startup['funding_raised'] / ($startup['funding_target'] ?: 1)) * 100) ?>%</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, ($startup['funding_raised'] / ($startup['funding_target'] ?: 1)) * 100) ?>%; height: 100%; background: var(--gradient-primary);"></div>
|
||||
<div style="width: <?= min(100, $progress) ?>%; height: 100%; background: var(--gradient-primary);"></div>
|
||||
</div>
|
||||
</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($startup['funding_raised'], 0) ?></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;">Target</div>
|
||||
<div style="font-weight: 700; color: #fff;">£<?= number_format($startup['funding_target'], 0) ?></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>
|
||||
@ -146,4 +163,4 @@ if ($user['role'] === 'founder') {
|
||||
</style>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user