This commit is contained in:
Flatlogic Bot 2026-03-01 09:49:02 +00:00
parent d2d6703960
commit 0053cb8830
10 changed files with 408 additions and 214 deletions

View File

@ -126,7 +126,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
cofounder_equity_pct = ?, cofounder_equity_type = ?, cofounder_responsibilities = ?, desired_cofounder_experience = ?, cofounder_commitment = ?, other_partnership_details = ?,
current_cash_balance = ?, burn_rate = ?,
doc_income_statements = ?, doc_balance_sheets = ?, doc_cash_flow_statements = ?, doc_revenue_breakdown = ?, doc_gross_margin = ?,
recommended_return_rate = ?, recommended_return_reasoning = ?, founder_return_rate = ?
recommended_return_rate = ?, recommended_return_reasoning = ?, founder_return_rate = ?, repayment_term = ?
WHERE id = ? AND founder_id = ?");
$stmt->execute([
@ -135,7 +135,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$current_cash_balance, $burn_rate,
$uploaded_paths['doc_income_statements'], $uploaded_paths['doc_balance_sheets'], $uploaded_paths['doc_cash_flow_statements'],
$uploaded_paths['doc_revenue_breakdown'], $uploaded_paths['doc_gross_margin'],
$recommended_return_rate, $recommended_return_reasoning, $founder_return_rate,
$recommended_return_rate, $recommended_return_reasoning, $founder_return_rate, $repayment_term,
$existingStartup['id'], $_SESSION['user_id']
]);
$final_id = $existingStartup['id'];
@ -145,7 +145,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
cofounder_equity_pct, cofounder_equity_type, cofounder_responsibilities, desired_cofounder_experience, cofounder_commitment, other_partnership_details,
current_cash_balance, burn_rate,
doc_income_statements, doc_balance_sheets, doc_cash_flow_statements, doc_revenue_breakdown, doc_gross_margin,
founder_id, recommended_return_rate, recommended_return_reasoning, founder_return_rate, status
founder_id, recommended_return_rate, recommended_return_reasoning, founder_return_rate, repayment_term, status
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'private')");
$stmt->execute([
@ -290,6 +290,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
</div>
<div style="margin-top: 20px; border-top: 1px solid #333; padding-top: 20px;">
<div style="margin-bottom: 20px;">
<label style="display: block; margin-bottom: 8px; font-weight: 700;">Repayment Term (Months)</label>
<input type="number" name="repayment_term" value="<?= htmlspecialchars($existingStartup["repayment_term"] ?? "12") ?>" min="1" max="60" required style="width: 100%; padding: 12px; border-radius: 8px; background: #222; border: 1px solid var(--accent-color); color: #fff; font-size: 16px; font-weight: 700;">
<small style="color: #aaa; display: block; margin-top: 8px;">The duration over which you will repay the investment plus interest.</small>
</div>
<label style="display: block; margin-bottom: 8px; font-weight: 700;">Proposed Investor Return (%)</label>
<input type="number" step="0.1" name="founder_return_rate" value="<?= htmlspecialchars($existingStartup['founder_return_rate'] ?? '') ?>" placeholder="e.g. 8.5" style="width: 100%; padding: 12px; border-radius: 8px; background: #222; border: 1px solid var(--accent-color); color: #fff; font-size: 16px; font-weight: 700;">
<small style="color: #aaa; display: block; margin-top: 8px;">Your proposed annual dividend yield. The platform also computes a recommendation based on your financials.</small>

View File

@ -6,6 +6,8 @@ if (!isset($_SESSION['user_id'])) {
}
require_once __DIR__ . '/db/config.php';
require_once __DIR__ . "/sync_funding.php";
syncRepayments();
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
@ -17,14 +19,12 @@ if (!$user) {
exit;
}
// Security: Check if verified
if ($user['verified'] == 0) {
session_destroy();
header("Location: login.php?error=not_verified");
exit;
}
// Check if onboarding is complete
if ($user['role'] === 'founder' && $user['onboarding_completed'] == 0) {
header("Location: founder_onboarding.php");
exit;
@ -32,10 +32,7 @@ if ($user['role'] === 'founder' && $user['onboarding_completed'] == 0) {
$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
@ -48,7 +45,6 @@ $stmt->execute();
$topFollowed = $stmt->fetchAll(PDO::FETCH_COLUMN);
$trendingIds = array_merge($trendingIds, $topFollowed);
// Top 3 Funded (Total)
$stmt = db()->prepare("
SELECT id
FROM startups
@ -59,9 +55,15 @@ $stmt->execute();
$topFunded = $stmt->fetchAll(PDO::FETCH_COLUMN);
$trendingIds = array_unique(array_merge($trendingIds, $topFunded));
// Fetch user's data based on role
$myStartups = [];
$myInvestments = [];
$repaymentSummary = [
'total_raised' => 0,
'total_obligation' => 0,
'monthly_outgoing' => 0,
'active_investors' => 0,
'next_payment_date' => null
];
if ($user['role'] === 'founder') {
$stmt = db()->prepare("
@ -73,6 +75,21 @@ if ($user['role'] === 'founder') {
");
$stmt->execute([$_SESSION['user_id']]);
$myStartups = $stmt->fetchAll();
// Repayment Summary Calculation
$stmt = db()->prepare("
SELECT
SUM(i.amount) as total_raised,
SUM(i.total_return) as total_obligation,
SUM(CASE WHEN i.status = 'approved' THEN i.monthly_dividend ELSE 0 END) as monthly_outgoing,
COUNT(DISTINCT CASE WHEN i.status = 'approved' THEN i.investor_id END) as active_investors,
MIN(CASE WHEN i.status = 'approved' THEN i.next_payment_date END) as next_payment_date
FROM investments i
JOIN startups s ON i.startup_id = s.id
WHERE s.founder_id = ?
");
$stmt->execute([$_SESSION['user_id']]);
$repaymentSummary = $stmt->fetch();
} else {
$stmt = db()->prepare("SELECT i.*, s.name as startup_name 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']]);
@ -104,8 +121,6 @@ function number_get_formatted($num) {
.profile-link-card:hover {
transform: translateY(-2px);
}
/* Modal Styles */
.modal {
display: none;
position: fixed;
@ -117,6 +132,26 @@ function number_get_formatted($num) {
background-color: rgba(0,0,0,0.9);
backdrop-filter: blur(4px);
}
.repayment-stat-card {
background: rgba(255,255,255,0.03);
border: 1px solid var(--border-color);
border-radius: 16px;
padding: 20px;
text-align: left;
}
.repayment-stat-label {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 1px;
color: var(--text-secondary);
font-weight: 700;
margin-bottom: 8px;
}
.repayment-stat-value {
font-size: 20px;
font-weight: 900;
color: #fff;
}
</style>
</head>
<body>
@ -167,6 +202,35 @@ function number_get_formatted($num) {
<p style="color: var(--text-secondary); font-size: 20px; margin-top: 10px;">Your command center for the next big thing.</p>
</div>
<?php if ($user['role'] === 'founder'): ?>
<!-- Founder Repayment Dashboard -->
<div class="card" style="margin-bottom: 40px; padding: 35px; border: 1px solid var(--accent-primary)33; background: linear-gradient(145deg, rgba(0, 242, 255, 0.05), transparent);">
<h3 style="margin-bottom: 25px; font-size: 22px; font-weight: 800;"><i class="fas fa-chart-pie" style="color: var(--accent-primary); margin-right: 10px;"></i> Funding & Repayment Overview</h3>
<div style="display: grid; grid-template-columns: repeat(5, 1fr); gap: 15px;">
<div class="repayment-stat-card">
<div class="repayment-stat-label">Total Raised</div>
<div class="repayment-stat-value">£<?= number_format($repaymentSummary['total_raised'] ?? 0, 0) ?></div>
</div>
<div class="repayment-stat-card">
<div class="repayment-stat-label">Total Obligation</div>
<div class="repayment-stat-value" style="color: var(--error-color);">£<?= number_format($repaymentSummary['total_obligation'] ?? 0, 0) ?></div>
</div>
<div class="repayment-stat-card">
<div class="repayment-stat-label">Monthly Outgoing</div>
<div class="repayment-stat-value" style="color: var(--warning-color);">£<?= number_format($repaymentSummary['monthly_outgoing'] ?? 0, 0) ?></div>
</div>
<div class="repayment-stat-card">
<div class="repayment-stat-label">Active Investors</div>
<div class="repayment-stat-value"><?= $repaymentSummary['active_investors'] ?? 0 ?></div>
</div>
<div class="repayment-stat-card">
<div class="repayment-stat-label">Next Due Date</div>
<div class="repayment-stat-value" style="font-size: 16px;"><?= $repaymentSummary['next_payment_date'] ? date('M d, Y', strtotime($repaymentSummary['next_payment_date'])) : 'None' ?></div>
</div>
</div>
</div>
<?php endif; ?>
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 40px;">
<div>
<?php if ($user['role'] === 'founder'): ?>
@ -433,7 +497,6 @@ function updateRound(roundId, status) {
}
}
// Close modal when clicking outside
window.onclick = function(event) {
const modal = document.getElementById('wallet-modal');
if (event.target == modal) {
@ -443,4 +506,4 @@ window.onclick = function(event) {
</script>
</body>
</html>
</html>

View File

@ -0,0 +1,16 @@
-- Migration: Repayment and Dividend System
-- 1. Add repayment_term to startups table
ALTER TABLE startups ADD COLUMN repayment_term INT DEFAULT 12 AFTER founder_return_rate;
-- 2. Update investments table with locked terms and payment tracking
ALTER TABLE investments
ADD COLUMN interest_rate DECIMAL(5, 2) AFTER amount,
ADD COLUMN repayment_term INT AFTER interest_rate,
ADD COLUMN total_return DECIMAL(15, 2) AFTER repayment_term,
ADD COLUMN monthly_dividend DECIMAL(15, 2) AFTER total_return,
ADD COLUMN paid_amount DECIMAL(15, 2) DEFAULT 0.00 AFTER monthly_dividend,
ADD COLUMN next_payment_date DATE AFTER paid_amount;
-- 3. Update status enum in investments table
ALTER TABLE investments MODIFY COLUMN status ENUM('pending', 'approved', 'rejected', 'completed') DEFAULT 'pending';

View File

@ -209,13 +209,13 @@ $browseStartups = $stmt->fetchAll();
$isFollowing = in_array($s['id'], $followedStartups);
?>
<div class="card" onclick="location.href='startup_details.php?id=<?= $s['id'] ?>'" style="cursor: pointer; position: relative;">
<div style="display: flex; gap: 20px; align-items: center; margin-bottom: 24px;">
<div style="width: 60px; height: 60px; background: var(--accent-primary); border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: 900; color: #000;">
<div style="display: flex; gap: 20px; align-items: center; margin-bottom: 20px;">
<div style="width: 50px; height: 50px; background: var(--accent-primary); border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 900; color: #000;">
<?= substr($s['name'], 0, 1) ?>
</div>
<div style="flex: 1;">
<div style="font-weight: 800; font-size: 20px; color: var(--text-primary);"><?= htmlspecialchars($s['name']) ?></div>
<div style="font-size: 13px; color: var(--text-secondary);">by <?= htmlspecialchars($s['founder_name']) ?></div>
<div style="font-weight: 800; font-size: 18px; color: var(--text-primary);"><?= htmlspecialchars($s['name']) ?></div>
<div style="font-size: 12px; color: var(--text-secondary);">by <?= htmlspecialchars($s['founder_name']) ?></div>
</div>
<button class="follow-btn <?= $isFollowing ? 'active' : '' ?>"
data-id="<?= $s['id'] ?>"
@ -224,14 +224,24 @@ $browseStartups = $stmt->fetchAll();
<i class="<?= $isFollowing ? 'fas' : 'far' ?> fa-heart"></i>
</button>
</div>
<p style="color: var(--text-secondary); font-size: 14px; margin-bottom: 24px; line-height: 1.6; height: 42px; overflow: hidden;">
<p style="color: var(--text-secondary); font-size: 13px; margin-bottom: 20px; line-height: 1.5; height: 39px; overflow: hidden;">
<?= htmlspecialchars(substr($s['description'], 0, 100)) ?>...
</p>
<div style="display: flex; justify-content: space-between; align-items: center;">
<?php if (!empty($s['industry'])): ?>
<span style="font-size: 11px; font-weight: 700; color: var(--accent-primary); text-transform: uppercase; background: var(--bg-color); padding: 4px 10px; border-radius: 6px; border: 1px solid var(--border-color);"><?= htmlspecialchars($s['industry']) ?></span>
<?php endif; ?>
<span style="font-weight: 900; color: var(--text-primary);">£<?= number_format($s['active_raised']) ?></span>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 20px;">
<div style="background: rgba(255,255,255,0.03); padding: 8px; border-radius: 8px; border: 1px solid var(--border-color); text-align: center;">
<div style="font-size: 9px; color: var(--text-secondary); text-transform: uppercase;">Rate</div>
<div style="font-size: 13px; font-weight: 800; color: var(--accent-primary);"><?= number_format($s['founder_return_rate'] ?? 0, 1) ?>%</div>
</div>
<div style="background: rgba(255,255,255,0.03); padding: 8px; border-radius: 8px; border: 1px solid var(--border-color); text-align: center;">
<div style="font-size: 9px; color: var(--text-secondary); text-transform: uppercase;">Term</div>
<div style="font-size: 13px; font-weight: 800; color: #fff;"><?= $s['repayment_term'] ?? 12 ?> Mo</div>
</div>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; border-top: 1px solid var(--border-color); padding-top: 15px;">
<span style="font-size: 11px; font-weight: 700; color: var(--text-secondary); text-transform: uppercase;"><?= htmlspecialchars($s['industry']) ?></span>
<span style="font-weight: 900; color: var(--text-primary);">£<?= number_format($s['active_raised']) ?> Raised</span>
</div>
</div>
<?php endforeach; ?>
@ -298,4 +308,4 @@ document.querySelectorAll('.follow-btn').forEach(btn => {
</script>
<script src="assets/js/main.js"></script>
</body>
</html>
</html>

View File

@ -104,18 +104,18 @@ $activeRounds = $stmt->fetchAll();
<span style="color: var(--accent-primary);">£<?= number_format($raised) ?> Secured</span>
<span style="color: var(--text-secondary);"><?= $progress ?>%</span>
</div>
<div style="width: 100%; height: 8px; background: var(--bg-color); border-radius: 100px; overflow: hidden; margin-bottom: 30px; border: 1px solid var(--border-color);">
<div style="width: 100%; height: 8px; background: var(--bg-color); border-radius: 100px; overflow: hidden; margin-bottom: 25px; border: 1px solid var(--border-color);">
<div style="width: <?= min(100, $progress) ?>%; height: 100%; background: var(--accent-primary);"></div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 30px;">
<div style="background: var(--bg-color); padding: 12px; border-radius: 12px; border: 1px solid var(--border-color);">
<div style="font-size: 10px; color: var(--text-secondary); text-transform: uppercase; margin-bottom: 4px;">Platform Yield</div>
<div style="font-weight: 800; color: #fff;"><?= number_format($round['recommended_return_rate'] ?? 5.0, 1) ?>%</div>
<div style="font-size: 10px; color: var(--text-secondary); text-transform: uppercase; margin-bottom: 4px;">Return Rate</div>
<div style="font-weight: 800; color: var(--accent-primary);"><?= number_format($round['founder_return_rate'] ?? 0, 1) ?>%</div>
</div>
<div style="background: var(--bg-color); padding: 12px; border-radius: 12px; border: 1px solid var(--border-color);">
<div style="font-size: 10px; color: var(--text-secondary); text-transform: uppercase; margin-bottom: 4px;">Founder Yield</div>
<div style="font-weight: 800; color: #fff;"><?= $round['founder_return_rate'] ? number_format($round['founder_return_rate'], 1) . '%' : 'N/A' ?></div>
<div style="font-size: 10px; color: var(--text-secondary); text-transform: uppercase; margin-bottom: 4px;">Term</div>
<div style="font-weight: 800; color: #fff;"><?= $round['repayment_term'] ?? 12 ?> Months</div>
</div>
</div>
@ -137,4 +137,4 @@ $activeRounds = $stmt->fetchAll();
<script src="assets/js/main.js"></script>
</body>
</html>
</html>

View File

@ -43,8 +43,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$investor_id = $_SESSION['user_id'];
$remaining = $startup['funding_goal'] - $startup['funding_raised'];
if ($amount <= 0) {
$error = "Please enter a valid investment amount.";
if ($amount < 50) {
$error = "Minimum investment is £50.";
} elseif ($amount > $investor_balance) {
$error = "Insufficient funds in your money pot. Please add funds first.";
} elseif ($amount > $remaining) {
@ -52,11 +52,28 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
} else {
db()->beginTransaction();
try {
// Repayment & Dividend Logic
$interest_rate = (float)($startup['founder_return_rate'] ?? 0);
$repayment_term = (int)($startup['repayment_term'] ?? 12);
if ($repayment_term <= 0) $repayment_term = 12;
$total_return = $amount + ($amount * ($interest_rate / 100));
$monthly_dividend = $total_return / $repayment_term;
// First payment is one month after investment date
$next_payment_date = date('Y-m-d', strtotime('+1 month'));
// 1. Create investment record
$equity_pct = 0.00; // Mock logic for equity
$stmt = db()->prepare("INSERT INTO investments (startup_id, investor_id, funding_round_id, amount, equity_pct, status) VALUES (?, ?, ?, ?, ?, 'approved')");
$stmt->execute([$startupId, $investor_id, $startup['round_id'], $amount, $equity_pct]);
$stmt = db()->prepare("INSERT INTO investments (
startup_id, investor_id, funding_round_id, amount, interest_rate, repayment_term, total_return, monthly_dividend, next_payment_date, equity_pct, status
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'approved')");
$stmt->execute([
$startupId, $investor_id, $startup['round_id'], $amount,
$interest_rate, $repayment_term, $total_return, $monthly_dividend, $next_payment_date,
$equity_pct
]);
// 2. Update funding_rounds raised amount
$stmt = db()->prepare("UPDATE funding_rounds SET funding_raised = funding_raised + ? WHERE id = ?");
@ -76,7 +93,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$stmt->execute([$amount, $startup['founder_id']]);
db()->commit();
$success = "Investment of £" . number_format($amount, 2) . " confirmed successfully! Funds moved to the founder's pot.";
$success = "Investment of £" . number_format($amount, 2) . " confirmed successfully! Repayment schedule: £" . number_format($monthly_dividend, 2) . "/month for $repayment_term months.";
header("refresh:3;url=portfolio.php");
} catch (Exception $e) {
db()->rollBack();
@ -129,18 +146,16 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
<?php else: ?>
<div style="background: rgba(255,255,255,0.03); padding: 25px; border-radius: 16px; border: 1px solid rgba(255,255,255,0.05); margin-bottom: 30px;">
<div style="display: flex; justify-content: space-between; margin-bottom: 15px;">
<span style="color: #999;">Funding Goal</span>
<span style="font-weight: 700;">£<?= number_format($startup['funding_goal'], 2) ?></span>
<span style="color: #999;">Interest Rate</span>
<span style="font-weight: 700; color: #fff;"><?= number_format($startup['founder_return_rate'] ?? 0, 1) ?>%</span>
</div>
<div style="display: flex; justify-content: space-between; margin-bottom: 15px;">
<span style="color: #999;">Already Raised</span>
<span style="font-weight: 700;">£<?= number_format($startup['funding_raised'], 2) ?></span>
<span style="color: #999;">Repayment Term</span>
<span style="font-weight: 700; color: #fff;"><?= htmlspecialchars($startup['repayment_term'] ?? 12) ?> Months</span>
</div>
<?php
$remaining = $startup['funding_goal'] - $startup['funding_raised'];
?>
<div style="display: flex; justify-content: space-between; padding-top: 15px; border-top: 1px solid rgba(255,255,255,0.05);">
<span style="color: #999;">Remaining</span>
<span style="color: #999;">Remaining Allocation</span>
<?php $remaining = $startup['funding_goal'] - $startup['funding_raised']; ?>
<span style="font-weight: 900; color: var(--accent-blue);">£<?= number_format(max(0, $remaining), 2) ?></span>
</div>
</div>
@ -148,8 +163,9 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
<form method="POST">
<div style="margin-bottom: 30px;">
<label style="display: block; margin-bottom: 10px; font-weight: 600; color: #999; text-transform: uppercase; font-size: 12px; letter-spacing: 1px;">Investment Amount (£)</label>
<input type="number" name="amount" min="1" step="0.01" required placeholder="Enter amount..."
<input type="number" name="amount" min="50" step="0.01" required placeholder="Min £50..."
style="width: 100%; padding: 20px; background: #000; border: 1px solid rgba(255,255,255,0.1); border-radius: 16px; color: #fff; font-size: 24px; font-weight: 900;">
<p style="margin-top: 10px; font-size: 13px; color: #777;">The minimum investment is £50. Terms are locked upon confirmation.</p>
</div>
<button type="submit" class="btn btn-primary" style="width: 100%; padding: 20px; font-size: 18px; font-weight: 800; border-radius: 16px; background: var(--accent-blue); color: #000; border: none; cursor: pointer;">
@ -162,4 +178,4 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
</div>
</body>
</html>
</html>

View File

@ -1,5 +1,7 @@
<?php
require_once 'db/config.php';
require_once __DIR__ . "/sync_funding.php";
syncRepayments();
session_start();
$user_id = $_SESSION['user_id'] ?? null;
@ -26,7 +28,7 @@ $myInvestments = $stmt->fetchAll();
$totalInvested = 0;
foreach ($myInvestments as $inv) {
if ($inv['status'] === 'approved') {
if ($inv['status'] === 'approved' || $inv['status'] === 'completed') {
$totalInvested += $inv['amount'];
}
}
@ -43,7 +45,30 @@ foreach ($myInvestments as $inv) {
<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>
/* Modal Styles */
.repayment-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15px;
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid rgba(255,255,255,0.05);
}
.repayment-item {
text-align: left;
}
.repayment-label {
font-size: 10px;
text-transform: uppercase;
color: var(--text-secondary);
font-weight: 700;
letter-spacing: 1px;
margin-bottom: 5px;
}
.repayment-value {
font-size: 14px;
font-weight: 800;
color: #fff;
}
.modal {
display: none;
position: fixed;
@ -75,23 +100,16 @@ foreach ($myInvestments as $inv) {
<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="partners.php">Find Partners</a>
<?php else: ?>
<a href="funding_rounds.php">Founding Rounds</a>
<a href="portfolio.php" class="active">Portfolio</a>
<a href="discover.php">Discovery Hub</a>
<?php endif; ?>
<a href="funding_rounds.php">Founding Rounds</a>
<a href="portfolio.php" class="active">Portfolio</a>
<a href="discover.php">Discovery Hub</a>
<a href="messages.php">Messages</a>
</nav>
<div style="display: flex; align-items: center; gap: 15px;">
<!-- Money Pot Widget in Header -->
<div onclick="openWalletModal('add')" style="cursor: pointer; display: flex; align-items: center; gap: 8px; padding: 5px 12px; background: rgba(0, 242, 255, 0.1); border-radius: 50px; border: 1px solid rgba(0, 242, 255, 0.2);">
<i class="fas fa-wallet" style="color: var(--accent-blue); font-size: 12px;"></i>
<span id="header-wallet-balance" style="font-size: 13px; font-weight: 800; color: #fff;">£<?= number_format($user['balance'], 2) ?></span>
</div>
<a href="notifications.php" style="color: var(--text-secondary); position: relative; font-size: 18px;">
<i class="fas fa-bell"></i>
</a>
@ -114,11 +132,11 @@ foreach ($myInvestments as $inv) {
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 40px;">
<div>
<h1>Investment Portfolio</h1>
<p style="color: var(--text-secondary);">Manage your stakes in student-led startups.</p>
<p style="color: var(--text-secondary);">Manage your stakes and track your repayments.</p>
</div>
<div class="card" style="padding: 20px 30px; display: flex; align-items: center; gap: 30px; border: 1px solid var(--border-color); background: var(--card-bg);">
<div>
<div style="font-size: 10px; text-transform: uppercase; color: var(--text-secondary); font-weight: 700; letter-spacing: 1px; margin-bottom: 5px;">Total Invested</div>
<div style="font-size: 10px; text-transform: uppercase; color: var(--text-secondary); font-weight: 700; letter-spacing: 1px; margin-bottom: 5px;">Total Principal</div>
<div style="font-size: 28px; font-weight: 900; color: var(--accent-blue);">£<?= number_format($totalInvested, 0) ?></div>
</div>
<div style="width: 1px; height: 40px; background: var(--border-color);"></div>
@ -129,7 +147,7 @@ foreach ($myInvestments as $inv) {
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr; gap: 20px;">
<div style="display: grid; grid-template-columns: 1fr; gap: 25px;">
<?php if (empty($myInvestments)): ?>
<div class="card" style="text-align: center; padding: 80px 20px; border: 1px dashed var(--border-color);">
<i class="fas fa-chart-line" style="font-size: 64px; color: var(--accent-blue); opacity: 0.2; margin-bottom: 30px;"></i>
@ -138,30 +156,79 @@ foreach ($myInvestments as $inv) {
<a href="discover.php" class="btn btn-primary" style="margin-top: 25px;">Go to Discovery Hub</a>
</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; 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) ?>
</div>
<div>
<div style="font-size: 11px; text-transform: uppercase; color: var(--accent-blue); margin-bottom: 5px; font-weight: 700;">Invested on <?= date('M d, Y', strtotime($inv['created_at'])) ?></div>
<h3 style="margin-bottom: 5px; font-size: 22px; font-weight: 800;"><?= htmlspecialchars($inv['startup_name']) ?></h3>
<p style="font-size: 14px; color: var(--text-secondary); margin: 0; opacity: 0.8;"><?= htmlspecialchars(substr($inv['startup_desc'], 0, 100)) ?>...</p>
</div>
</div>
<div style="text-align: right; display: flex; align-items: center; gap: 50px;">
<div>
<div style="font-size: 10px; text-transform: uppercase; color: var(--text-secondary); font-weight: 700; letter-spacing: 1px; margin-bottom: 5px;">Amount</div>
<div style="font-size: 22px; font-weight: 900; color: #fff;">£<?= number_format($inv['amount'], 0) ?></div>
</div>
<div style="min-width: 100px;">
<div style="font-size: 10px; text-transform: uppercase; color: var(--text-secondary); font-weight: 700; letter-spacing: 1px; margin-bottom: 5px;">Status</div>
<div style="font-size: 13px; font-weight: 800; color: <?= $inv['status'] === 'approved' ? '#4cd964' : ($inv['status'] === 'pending' ? '#ffcc00' : '#ff3b30') ?>; letter-spacing: 1px;">
<?= strtoupper($inv['status']) ?>
<?php foreach ($myInvestments as $inv):
$interest = $inv['interest_rate'] ?? 0;
$totalReturn = $inv['total_return'] ?? ($inv['amount'] * (1 + $interest / 100));
$monthlyDiv = $inv['monthly_dividend'] ?? ($totalReturn / ($inv['repayment_term'] ?: 12));
$paid = $inv['paid_amount'] ?? 0;
$remainingAmount = $totalReturn - $paid;
$paymentsRemaining = $monthlyDiv > 0 ? ceil($remainingAmount / $monthlyDiv) : 0;
$status = ($inv['status'] === 'completed') ? 'Completed' : 'Active';
$statusColor = ($inv['status'] === 'completed') ? '#4cd964' : '#00f2ff';
if ($inv['status'] === 'pending') {
$status = 'Pending';
$statusColor = '#ffcc00';
} elseif ($inv['status'] === 'rejected') {
$status = 'Rejected';
$statusColor = '#ff3b30';
}
?>
<div class="card" style="padding: 30px; transition: all 0.3s; position: relative; overflow: hidden;">
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 25px;">
<div style="display: flex; align-items: center; gap: 20px;">
<div style="width: 50px; height: 50px; background: var(--gradient-primary); border-radius: 14px; display: flex; align-items: center; justify-content: center; font-size: 20px; color: #fff; font-weight: 800;">
<?= substr($inv['startup_name'], 0, 1) ?>
</div>
<div>
<h3 style="margin: 0; font-size: 20px; font-weight: 800;"><?= htmlspecialchars($inv['startup_name']) ?></h3>
<div style="font-size: 12px; color: var(--text-secondary); margin-top: 4px;">
Invested on <?= date('M d, Y', strtotime($inv['created_at'])) ?>
</div>
</div>
</div>
<a href="startup_details.php?id=<?= $inv['startup_id'] ?>" class="btn btn-secondary" style="padding: 10px 20px; border-radius: 12px; font-size: 13px; font-weight: 700;">Details</a>
<div style="text-align: right;">
<div style="font-size: 10px; text-transform: uppercase; color: var(--text-secondary); font-weight: 700; letter-spacing: 1px; margin-bottom: 5px;">Status</div>
<div style="font-size: 12px; font-weight: 900; color: <?= $statusColor ?>; background: rgba(255,255,255,0.05); padding: 4px 12px; border-radius: 20px; border: 1px solid <?= $statusColor ?>33;">
<?= strtoupper($status) ?>
</div>
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; background: rgba(255,255,255,0.02); padding: 20px; border-radius: 16px; border: 1px solid rgba(255,255,255,0.05);">
<div>
<div class="repayment-label">Invested</div>
<div class="repayment-value">£<?= number_format($inv['amount'], 2) ?></div>
</div>
<div>
<div class="repayment-label">Interest Rate</div>
<div class="repayment-value"><?= number_format($interest, 1) ?>%</div>
</div>
<div>
<div class="repayment-label">Total Return</div>
<div class="repayment-value" style="color: var(--accent-blue);">£<?= number_format($totalReturn, 2) ?></div>
</div>
<div>
<div class="repayment-label">Monthly Div</div>
<div class="repayment-value" style="color: #4cd964;">£<?= number_format($monthlyDiv, 2) ?></div>
</div>
</div>
<div class="repayment-grid">
<div class="repayment-item">
<div class="repayment-label">Term</div>
<div class="repayment-value"><?= $inv['repayment_term'] ?? 12 ?> Months</div>
</div>
<div class="repayment-item">
<div class="repayment-label">Remaining Payouts</div>
<div class="repayment-value"><?= $paymentsRemaining ?></div>
</div>
<div class="repayment-item">
<div class="repayment-label">Next Payment</div>
<div class="repayment-value"><?= $inv['next_payment_date'] ? date('M d, Y', strtotime($inv['next_payment_date'])) : 'N/A' ?></div>
</div>
<div class="repayment-item" style="text-align: right;">
<a href="startup_details.php?id=<?= $inv['startup_id'] ?>" style="color: var(--accent-blue); text-decoration: none; font-size: 13px; font-weight: 700;">View Profile <i class="fas fa-chevron-right" style="font-size: 10px; margin-left: 5px;"></i></a>
</div>
</div>
</div>
<?php endforeach; ?>
@ -248,7 +315,6 @@ document.getElementById('wallet-form').addEventListener('submit', function(e) {
});
});
// Close modal when clicking outside
window.onclick = function(event) {
const modal = document.getElementById('wallet-modal');
if (event.target == modal) {
@ -258,4 +324,4 @@ window.onclick = function(event) {
</script>
</body>
</html>
</html>

View File

@ -47,8 +47,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
// Update startup with round-specific settings
// We also update funding_target so that general views show the current target
$stmt = db()->prepare("UPDATE startups SET status = ?, founder_return_rate = ?, funding_target = ? WHERE id = ?");
$stmt->execute([$status, $founder_rate, $goal, $startup_id]);
$stmt = db()->prepare("UPDATE startups SET status = ?, founder_return_rate = ?, funding_target = ?, repayment_term = ? WHERE id = ?");
$stmt->execute([$status, $founder_rate, $goal, $repayment_term, $startup_id]);
// Create the round
$stmt = db()->prepare("INSERT INTO funding_rounds (startup_id, funding_goal, status) VALUES (?, ?, 'Active')");
@ -110,6 +110,15 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
style="width: 100%; padding: 14px; background: var(--surface-color); border: 1px solid var(--border-color); border-radius: 12px; color: #fff; font-size: 18px; font-weight: 700;">
</div>
<div style="margin-bottom: 20px;">
<label style="display: block; margin-bottom: 8px; font-weight: 600; font-size: 14px;">Repayment Term (Months) *</label>
<input type="number" name="repayment_term" min="1" max="60" required placeholder="e.g. 12"
value="<?= htmlspecialchars($startup["repayment_term"] ?: "12") ?>"
style="width: 100%; padding: 14px; background: var(--surface-color); border: 1px solid var(--border-color); border-radius: 12px; color: #fff; font-size: 16px; font-weight: 700;">
<small style="color: var(--text-secondary); display: block; margin-top: 8px; line-height: 1.4;">
The duration over which you will repay the investment plus interest.
</small>
</div>
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 8px; font-weight: 600; font-size: 14px;">Your Proposed Dividend (%) <span style="font-weight: 400; opacity: 0.6;">(Optional)</span></label>
<input type="number" name="founder_return_rate" step="0.1" min="0" max="100" placeholder="e.g. 8.5"

View File

@ -1,6 +1,8 @@
<?php
session_start();
require_once 'db/config.php';
require_once __DIR__ . "/sync_funding.php";
syncRepayments();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
@ -60,6 +62,14 @@ if ($canSeeHistory) {
$fundingHistory = $stmt->fetchAll();
}
// Check if the current user (investor) has an investment here
$myInvestment = null;
if ($isInvestor) {
$stmt = db()->prepare("SELECT * FROM investments WHERE investor_id = ? AND startup_id = ? AND status != 'rejected' LIMIT 1");
$stmt->execute([$user_id, $startupId]);
$myInvestment = $stmt->fetch();
}
// Fetch approved investments for dividends calculation (Founder only)
$approvedInvestments = [];
if ($isFounder) {
@ -85,32 +95,6 @@ $goal = $startup['active_goal'] ?: 0;
$raised = $startup['active_raised'] ?: 0;
$progress = ($goal > 0) ? round(($raised / $goal) * 100) : 0;
/**
* Helper to calculate time left for next dividend
*/
function getNextDividendInfo($createdAt) {
$created = new DateTime($createdAt);
$day = $created->format('d');
$now = new DateTime();
$thisMonth = new DateTime($now->format('Y-m-') . $day);
// If today is past the day, next is next month
if ($thisMonth <= $now) {
$next = clone $thisMonth;
$next->modify('+1 month');
} else {
$next = $thisMonth;
}
$interval = $now->diff($next);
$days = $interval->days;
return [
'date' => $next->format('M d, Y'),
'days_left' => $days
];
}
?>
<!DOCTYPE html>
<html lang="en">
@ -228,8 +212,6 @@ function getNextDividendInfo($createdAt) {
background: var(--success-color);
color: #000;
}
/* Modal Styles */
.modal {
display: none;
position: fixed;
@ -241,7 +223,6 @@ function getNextDividendInfo($createdAt) {
background-color: rgba(0,0,0,0.9);
backdrop-filter: blur(4px);
}
.follow-btn {
padding: 16px 24px;
border-radius: 999px;
@ -354,9 +335,11 @@ function getNextDividendInfo($createdAt) {
<a href="messages.php?chat_with=<?= $startup['founder_id'] ?>" class="btn btn-secondary" style="padding: 16px 24px;">
<i class="far fa-comment-dots"></i> Message Founder
</a>
<a href="invest.php?id=<?= $startup['id'] ?>" class="invest-btn">
<i class="fas fa-rocket"></i> Invest Now
</a>
<?php if ($startup['round_status'] === 'Active'): ?>
<a href="invest.php?id=<?= $startup['id'] ?>" class="invest-btn">
<i class="fas fa-rocket"></i> Invest Now
</a>
<?php endif; ?>
<?php elseif ($isFounder): ?>
<a href="create_startup.php?id=<?= $startup['id'] ?>" class="btn btn-secondary" style="padding: 16px 24px;">
<i class="fas fa-edit"></i> Edit Profile
@ -365,9 +348,42 @@ function getNextDividendInfo($createdAt) {
</div>
</div>
<?php if ($myInvestment): ?>
<!-- My Investment Card -->
<section class="card" style="margin-bottom: 40px; border: 2px solid var(--accent-primary) !important; background: linear-gradient(145deg, rgba(0, 242, 255, 0.05), transparent);">
<h2 class="section-title"><i class="fas fa-piggy-bank" style="color: var(--accent-primary);"></i> My Investment</h2>
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px;">
<div>
<div class="data-label">Invested</div>
<div style="font-size: 20px; font-weight: 900;">£<?= number_format($myInvestment['amount'], 2) ?></div>
</div>
<div>
<div class="data-label">Total Return</div>
<div style="font-size: 20px; font-weight: 900; color: var(--accent-primary);">£<?= number_format($myInvestment['total_return'], 2) ?></div>
</div>
<div>
<div class="data-label">Monthly Div</div>
<div style="font-size: 20px; font-weight: 900; color: #4cd964;">£<?= number_format($myInvestment['monthly_dividend'], 2) ?></div>
</div>
<div>
<div class="data-label">Next Payment</div>
<div style="font-size: 16px; font-weight: 900;"><?= date('M d, Y', strtotime($myInvestment['next_payment_date'])) ?></div>
</div>
</div>
<div style="margin-top: 20px; padding-top: 20px; border-top: 1px solid rgba(255,255,255,0.05); display: flex; justify-content: space-between; align-items: center;">
<div style="font-size: 13px; color: var(--text-secondary);">
Interest: <strong><?= number_format($myInvestment['interest_rate'], 1) ?>%</strong> |
Term: <strong><?= $myInvestment['repayment_term'] ?> Months</strong> |
Status: <strong style="color: var(--accent-primary);"><?= ($myInvestment['status'] === 'approved' ? 'ACTIVE' : strtoupper($myInvestment['status'])) ?></strong>
</div>
<a href="portfolio.php" class="btn btn-secondary" style="padding: 8px 16px; font-size: 12px;">Full Portfolio</a>
</div>
</section>
<?php endif; ?>
<?php if ($startup['round_status'] === 'Active'): ?>
<!-- Funding Progress -->
<section class="card" style="margin-bottom: 40px; border-color: var(--accent-primary) !important;">
<section class="card" style="margin-bottom: 40px;">
<div style="display: flex; justify-content: space-between; align-items: center;">
<h2 class="section-title" style="margin-bottom: 0;"><i class="fas fa-chart-pie" style="color: var(--accent-primary);"></i> Active Funding Round</h2>
<span style="font-weight: 800; color: var(--accent-primary);"><?= $progress ?>% Complete</span>
@ -427,33 +443,33 @@ function getNextDividendInfo($createdAt) {
<div style="font-size: 24px; font-weight: 900; color: var(--accent-primary); margin-top: 5px;">£<?= number_format($startup['funding_raised'], 2) ?></div>
</div>
</div>
<p style="margin-top: 20px; color: var(--text-secondary); font-size: 13px; opacity: 0.8;">
<i class="fas fa-info-circle"></i> This pot holds all investments received. You can withdraw funds for business operations or add funds to cover investor dividends.
</p>
</section>
<?php endif; ?>
<?php if ($isFounder && !empty($approvedInvestments)): ?>
<!-- Dividend Management (Founder Only) -->
<section class="card" style="margin-bottom: 40px; border-color: var(--success-color) !important;">
<h2 class="section-title"><i class="fas fa-hand-holding-usd" style="color: var(--success-color);"></i> Monthly Dividends Due</h2>
<h2 class="section-title"><i class="fas fa-hand-holding-usd" style="color: var(--success-color);"></i> Active Repayments</h2>
<div style="margin-bottom: 20px;">
<p style="color: var(--text-secondary); font-size: 14px;">Track upcoming monthly payments to your investors based on your <strong><?= number_format($startup['founder_return_rate'] ?? 0, 1) ?>%</strong> offered return.</p>
<p style="color: var(--text-secondary); font-size: 14px;">Tracking monthly payments to your active investors.</p>
</div>
<?php foreach ($approvedInvestments as $inv):
$monthlyYield = ($inv['amount'] * ($startup['founder_return_rate'] ?? 0) / 100) / 12;
$nextPay = getNextDividendInfo($inv['created_at']);
$monthlyYield = $inv['monthly_dividend'];
$nextPayDate = $inv['next_payment_date'];
$daysLeft = (new DateTime())->diff(new DateTime($nextPayDate))->days;
?>
<div class="dividend-item">
<div>
<div style="font-weight: 700; font-size: 15px;"><?= htmlspecialchars($inv['investor_name']) ?></div>
<div style="font-size: 12px; color: var(--text-secondary);">Invested £<?= number_format($inv['amount']) ?></div>
<div style="font-size: 12px; color: var(--text-secondary);">
£<?= number_format($inv['amount']) ?> @ <?= number_format($inv['interest_rate'], 1) ?>% over <?= $inv['repayment_term'] ?>mo
</div>
</div>
<div style="text-align: right;">
<div style="font-size: 18px; font-weight: 900; color: #fff;">£<?= number_format($monthlyYield, 2) ?></div>
<div style="font-size: 11px; color: <?= $nextPay['days_left'] < 7 ? 'var(--error-color)' : 'var(--success-color)' ?>; font-weight: 700;">
<i class="far fa-clock"></i> <?= $nextPay['days_left'] ?> days left
<div style="font-size: 11px; color: <?= $daysLeft < 7 ? 'var(--error-color)' : 'var(--success-color)' ?>; font-weight: 700;">
<i class="far fa-clock"></i> Next: <?= date('M d', strtotime($nextPayDate)) ?> (<?= $daysLeft ?>d)
</div>
</div>
</div>
@ -467,19 +483,9 @@ function getNextDividendInfo($createdAt) {
<p style="font-size: 18px; line-height: 1.6; color: var(--text-primary);">
<?= nl2br(htmlspecialchars($startup['product_service'])) ?>
</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin-top: 40px;">
<div>
<h4 style="color: var(--text-secondary); text-transform: uppercase; font-size: 12px; letter-spacing: 1px;">Business Model</h4>
<p style="font-weight: 700; font-size: 16px; color: var(--text-primary);"><?= htmlspecialchars($startup['business_model']) ?></p>
</div>
<div>
<h4 style="color: var(--text-secondary); text-transform: uppercase; font-size: 12px; letter-spacing: 1px;">Operational Stage</h4>
<p style="font-weight: 700; font-size: 16px; color: var(--text-primary);"><?= htmlspecialchars($startup['operational_stage']) ?></p>
</div>
</div>
</section>
<!-- Financial Health -->
<section class="card" style="margin-bottom: 40px;">
<h2 class="section-title"><i class="fas fa-chart-line" style="color: var(--accent-primary);"></i> Financial Health</h2>
@ -495,19 +501,7 @@ function getNextDividendInfo($createdAt) {
</div>
</div>
</div>
<div style="background: var(--bg-color); padding: 15px; border-radius: 12px; margin-bottom: 25px; border: 1px solid var(--border-color);">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
<div>
<div class="data-label" style="font-size: 10px;">Outstanding Debt</div>
<div style="font-size: 14px; color: var(--text-primary);"><?= htmlspecialchars($startup['outstanding_debt'] ?: 'None') ?></div>
</div>
<div>
<div class="data-label" style="font-size: 10px;">Accounts Receivable/Payable</div>
<div style="font-size: 14px; color: var(--text-primary);"><?= htmlspecialchars($startup['accounts_receivable_payable'] ?: 'N/A') ?></div>
</div>
</div>
</div>
<h4 style="margin-bottom: 15px; font-size: 14px; text-transform: uppercase; color: var(--text-secondary); opacity: 0.7;">Historical Documentation</h4>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
<?php
@ -530,25 +524,25 @@ function getNextDividendInfo($createdAt) {
<!-- Return Rates Comparison -->
<section class="card" style="margin-bottom: 40px; border-color: var(--accent-primary) !important;">
<h2 style="margin-top: 0; margin-bottom: 25px; display: flex; align-items: center; gap: 12px;">
<i class="fas fa-percentage" style="color: var(--accent-primary);"></i> Expected Investor Returns
<i class="fas fa-percentage" style="color: var(--accent-primary);"></i> Investment Terms
</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px;">
<div style="padding: 20px; background: var(--bg-color); border-radius: 12px; border: 1px solid var(--border-color); text-align: center;">
<div style="font-size: 12px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 10px;">Platform Recommendation</div>
<div style="font-size: 32px; font-weight: 900; color: var(--accent-primary);"><?= number_format($startup['recommended_return_rate'] ?? 5.0, 1) ?>%</div>
<div style="font-size: 11px; color: var(--text-secondary); margin-top: 5px;">AI analysis based on uploaded financials</div>
<div style="font-size: 11px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 10px;">Interest Rate</div>
<div style="font-size: 28px; font-weight: 900; color: var(--accent-primary);"><?= number_format($startup['founder_return_rate'] ?? 0, 1) ?>%</div>
</div>
<div style="padding: 20px; background: var(--bg-color); border-radius: 12px; border: 1px solid var(--border-color); text-align: center;">
<div style="font-size: 12px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 10px;">Founder's Proposal</div>
<div style="font-size: 32px; font-weight: 900; color: #fff;">
<?= $startup['founder_return_rate'] !== null ? number_format($startup['founder_return_rate'], 1) . '%' : 'N/A' ?>
</div>
<div style="font-size: 11px; color: var(--text-secondary); margin-top: 5px;">Target annual dividend yield set by founder</div>
<div style="font-size: 11px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 10px;">Repayment Term</div>
<div style="font-size: 28px; font-weight: 900; color: #fff;"><?= $startup['repayment_term'] ?? 12 ?> Mo</div>
</div>
<div style="padding: 20px; background: var(--bg-color); border-radius: 12px; border: 1px solid var(--border-color); text-align: center;">
<div style="font-size: 11px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 10px;">Min Invest</div>
<div style="font-size: 28px; font-weight: 900; color: #fff;">£50</div>
</div>
</div>
<?php if (!empty($startup['recommended_return_reasoning'])): ?>
<div style="margin-top: 20px; padding: 15px; background: var(--surface-color); border-radius: 12px; border: 1px solid var(--border-color); font-size: 13px; line-height: 1.5; color: var(--text-secondary);">
<div style="font-weight: 700; margin-bottom: 5px; color: var(--accent-primary); text-transform: uppercase; font-size: 10px; letter-spacing: 0.5px;">Calculation Reasoning</div>
<div style="font-weight: 700; margin-bottom: 5px; color: var(--accent-primary); text-transform: uppercase; font-size: 10px; letter-spacing: 0.5px;">AI Yield Recommendation: <?= number_format($startup['recommended_return_rate'] ?? 5.0, 1) ?>%</div>
<?= htmlspecialchars($startup['recommended_return_reasoning']) ?>
</div>
<?php endif; ?>
@ -569,25 +563,11 @@ function getNextDividendInfo($createdAt) {
?>
<div style="display: flex; align-items: center; justify-content: space-between; padding: 20px; background: var(--elevated-color); border-radius: 12px; border: 1px solid var(--border-color);">
<div style="display: flex; align-items: center; gap: 15px;">
<?php if ($inv['investor_user_id']): ?>
<a href="profile.php?id=<?= $inv['investor_user_id'] ?>" style="text-decoration: none;">
<div style="width: 45px; height: 45px; border-radius: 8px; background: var(--surface-color); display: flex; align-items: center; justify-content: center;">
<span style="font-weight: 800; color: var(--accent-primary);"><?= substr($investorName, 0, 1) ?></span>
</div>
</a>
<?php else: ?>
<div style="width: 45px; height: 45px; border-radius: 8px; background: var(--surface-color); display: flex; align-items: center; justify-content: center;">
<span style="font-weight: 800; color: var(--accent-primary);"><?= substr($investorName, 0, 1) ?></span>
</div>
<?php endif; ?>
<div style="width: 45px; height: 45px; border-radius: 8px; background: var(--surface-color); display: flex; align-items: center; justify-content: center;">
<span style="font-weight: 800; color: var(--accent-primary);"><?= substr($investorName, 0, 1) ?></span>
</div>
<div>
<div style="font-weight: 700; color: var(--text-primary);">
<?php if ($inv['investor_user_id']): ?>
<a href="profile.php?id=<?= $inv['investor_user_id'] ?>" style="color: inherit; text-decoration: none;"><?= htmlspecialchars($investorName) ?></a>
<?php else: ?>
<?= htmlspecialchars($investorName) ?>
<?php endif; ?>
</div>
<div style="font-weight: 700; color: var(--text-primary);"><?= htmlspecialchars($investorName) ?></div>
<div style="font-size: 12px; color: var(--text-secondary);"><?= date('M d, Y', strtotime($inv['created_at'])) ?></div>
</div>
</div>
@ -679,7 +659,6 @@ document.getElementById('wallet-form').addEventListener('submit', function(e) {
});
});
// Close modal when clicking outside
window.onclick = function(event) {
const modal = document.getElementById('wallet-modal');
if (event.target == modal) {
@ -730,4 +709,4 @@ function toggleFollow(startupId) {
</script>
</body>
</html>
</html>

View File

@ -1,32 +1,62 @@
<?php
require_once 'db/config.php';
require_once __DIR__ . '/db/config.php';
echo "Recalculating funding totals...\n";
// 1. Reset all funding_raised to 0
db()->exec("UPDATE startups SET funding_raised = 0");
db()->exec("UPDATE funding_rounds SET funding_raised = 0");
// 2. Update funding_rounds totals
$stmt = db()->query("SELECT funding_round_id, SUM(amount) as total FROM investments WHERE status != 'rejected' GROUP BY funding_round_id");
$roundTotals = $stmt->fetchAll();
foreach ($roundTotals as $t) {
if (!$t['funding_round_id']) continue;
echo "Updating Round ID: {$t['funding_round_id']} with £{$t['total']}\n";
$stmt2 = db()->prepare("UPDATE funding_rounds SET funding_raised = ? WHERE id = ?");
$stmt2->execute([$t['total'], $t['funding_round_id']]);
function syncRepayments() {
$db = db();
$now = date('Y-m-d');
// Find all active investments where a payment is due
$stmt = $db->prepare("
SELECT i.*, s.founder_id
FROM investments i
JOIN startups s ON i.startup_id = s.id
WHERE i.status = 'approved' AND i.next_payment_date <= ? AND i.next_payment_date IS NOT NULL
");
$stmt->execute([$now]);
$dueInvestments = $stmt->fetchAll();
foreach ($dueInvestments as $inv) {
$db->beginTransaction();
try {
$amountToPay = $inv['monthly_dividend'];
// Ensure we don't overpay
if ($inv['paid_amount'] + $amountToPay > $inv['total_return']) {
$amountToPay = $inv['total_return'] - $inv['paid_amount'];
}
if ($amountToPay > 0) {
// 1. Deduct from founder
$stmt = $db->prepare("UPDATE users SET balance = balance - ? WHERE id = ?");
$stmt->execute([$amountToPay, $inv['founder_id']]);
// 2. Add to investor
$stmt = $db->prepare("UPDATE users SET balance = balance + ? WHERE id = ?");
$stmt->execute([$amountToPay, $inv['investor_id']]);
// 3. Update investment record
$newPaidAmount = $inv['paid_amount'] + $amountToPay;
$newStatus = ($newPaidAmount >= $inv['total_return']) ? 'completed' : 'approved';
$nextPayment = date('Y-m-d', strtotime($inv['next_payment_date'] . ' +1 month'));
// If completed, clear next payment date
if ($newStatus === 'completed') {
$nextPayment = null;
}
$stmt = $db->prepare("UPDATE investments SET paid_amount = ?, status = ?, next_payment_date = ? WHERE id = ?");
$stmt->execute([$newPaidAmount, $newStatus, $nextPayment, $inv['id']]);
// 4. Create a notification for both parties (Optional but good)
$stmt = $db->prepare("INSERT INTO notifications (user_id, content) VALUES (?, ?)");
$stmt->execute([$inv['investor_id'], "You received a dividend payment of £" . number_format($amountToPay, 2) . " from " . $inv['id']]);
$stmt->execute([$inv['founder_id'], "A dividend payment of £" . number_format($amountToPay, 2) . " was paid to an investor."]);
}
$db->commit();
} catch (Exception $e) {
$db->rollBack();
// Log error or ignore for now
}
}
}
// 3. Update startups totals (sum of all their rounds)
$stmt = db()->query("SELECT startup_id, SUM(amount) as total FROM investments WHERE status != 'rejected' GROUP BY startup_id");
$startupTotals = $stmt->fetchAll();
foreach ($startupTotals as $t) {
if (!$t['startup_id']) continue;
echo "Updating Startup ID: {$t['startup_id']} with £{$t['total']}\n";
$stmt3 = db()->prepare("UPDATE startups SET funding_raised = ? WHERE id = ?");
$stmt3->execute([$t['total'], $t['startup_id']]);
}
echo "Done!\n";