diff --git a/api/wallet_transaction.php b/api/wallet_transaction.php index 2e71e6c..d5fa388 100644 --- a/api/wallet_transaction.php +++ b/api/wallet_transaction.php @@ -1,6 +1,6 @@ false, 'error' => 'Please enter a valid amount greater than zero.']); + echo json_encode(['success' => false, 'error' => 'Invalid amount']); exit; } @@ -27,7 +27,7 @@ try { $user = $stmt->fetch(); if (!$user) { - throw new Exception("User account not found."); + throw new Exception("User not found"); } $current_balance = (float)$user['balance']; @@ -37,35 +37,27 @@ try { $stmt = db()->prepare("UPDATE users SET balance = ? WHERE id = ?"); $stmt->execute([$new_balance, $user_id]); - // Log transaction - $stmt = db()->prepare("INSERT INTO wallet_transactions (user_id, amount, type, description) VALUES (?, ?, 'add', 'Added funds to wallet')"); - $stmt->execute([$user_id, $amount]); + // Log transaction (optional but good practice, maybe later) db()->commit(); - echo json_encode(['success' => true, 'new_balance' => $new_balance, 'message' => 'Funds added successfully!']); + echo json_encode(['success' => true, 'new_balance' => $new_balance]); } elseif ($action === 'withdraw') { if ($current_balance < $amount) { - throw new Exception("Insufficient funds. You only have £" . number_format($current_balance, 2) . " available."); + throw new Exception("Insufficient funds"); } $new_balance = $current_balance - $amount; $stmt = db()->prepare("UPDATE users SET balance = ? WHERE id = ?"); $stmt->execute([$new_balance, $user_id]); - // Log transaction - $stmt = db()->prepare("INSERT INTO wallet_transactions (user_id, amount, type, description) VALUES (?, ?, 'withdraw', 'Withdrawn funds from wallet')"); - $stmt->execute([$user_id, $amount]); - db()->commit(); - echo json_encode(['success' => true, 'new_balance' => $new_balance, 'message' => 'Withdrawal successful!']); + echo json_encode(['success' => true, 'new_balance' => $new_balance]); } else { - throw new Exception("Invalid action requested."); + throw new Exception("Invalid action"); } } catch (Exception $e) { - if (db()->inTransaction()) { - db()->rollBack(); - } + db()->rollBack(); header('Content-Type: application/json'); echo json_encode(['success' => false, 'error' => $e->getMessage()]); -} \ No newline at end of file +} diff --git a/dashboard.php b/dashboard.php index 8121af4..53a0e44 100644 --- a/dashboard.php +++ b/dashboard.php @@ -94,85 +94,159 @@ function number_get_formatted($num) { + - + - + -
-
-

Welcome back, !

-

Here's what's happening in your venture ecosystem.

+
+
+
+
-
+
+
Launchpad Active
+

Welcome back, .

+

Your command center for the next big thing.

+
+ +
-
-

My Ventures

- + Register New Startup -
- -
+
+
+

My Ventures

+ +
+ -
+
-

No startups registered

-

Ready to change the world? Start by registering your venture.

- Get Started +

Ready to share your vision with the world?

+ Start Your First Round
- -
-
-
- +
+ +
+
+
+ +
+
+
+ + + Trending + +
+
+ + + + Target: £ +
+
+
+
+
+
£
+
Funds Raised
+
+ +
+ + +
+
- - -
-

-

- - 0): ?> -
-
- Active Funding Round - % -
-
-
-
-
- £ - Target: £ -
-
- - Start Funding Round - -
- + +
@@ -239,7 +313,6 @@ function number_get_formatted($num) { Withdraw
-

Manage your startup capital and dividend funds. @@ -257,11 +330,11 @@ function number_get_formatted($num) {

@@ -349,10 +422,9 @@ document.getElementById('wallet-form').addEventListener('submit', function(e) { .then(response => response.json()) .then(data => { if (data.success) { - const formattedBalance = '£' + parseFloat(data.new_balance).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}); - document.getElementById('wallet-balance').innerText = formattedBalance; - document.getElementById('header-wallet-balance').innerText = formattedBalance; + document.getElementById('wallet-balance').innerText = '£' + parseFloat(data.new_balance).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}); closeWalletModal(); + alert(formData.get('action') === 'add' ? 'Funds added successfully!' : 'Withdrawal successful!'); } else { alert('Error: ' + data.error); } diff --git a/db/migrations/20_wallet_transactions.sql b/db/migrations/20_wallet_transactions.sql deleted file mode 100644 index 152d6c0..0000000 --- a/db/migrations/20_wallet_transactions.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE IF NOT EXISTS wallet_transactions ( - id INT AUTO_INCREMENT PRIMARY KEY, - user_id INT NOT NULL, - amount DECIMAL(15,2) NOT NULL, - type ENUM('add', 'withdraw', 'investment_out', 'investment_in') NOT NULL, - description VARCHAR(255), - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE -); diff --git a/invest.php b/invest.php index 1e83e6f..2168d9f 100644 --- a/invest.php +++ b/invest.php @@ -30,8 +30,6 @@ if ($startup['round_status'] !== 'Active') { die("This startup does not have an active funding round."); } -$remaining = (float)($startup['funding_goal'] - $startup['funding_raised']); - $error = ''; $success = ''; @@ -47,9 +45,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($amount <= 0) { $error = "Please enter a valid investment amount."; } elseif ($amount > $investor_balance) { - $error = "Insufficient funds in your money pot. Please add funds first. You currently have £" . number_format($investor_balance, 2) . "."; - } elseif ($amount > $remaining && $remaining > 0) { - $error = "The investment amount (£" . number_format($amount) . ") exceeds the remaining funding goal of £" . number_format($remaining) . "."; + $error = "Insufficient funds in your money pot. Please add funds first."; } else { db()->beginTransaction(); try { @@ -76,13 +72,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $stmt = db()->prepare("UPDATE users SET balance = balance + ? WHERE id = ?"); $stmt->execute([$amount, $startup['founder_id']]); - // 5. Log transactions - $stmt = db()->prepare("INSERT INTO wallet_transactions (user_id, amount, type, description) VALUES (?, ?, 'investment_out', ?)"); - $stmt->execute([$investor_id, $amount, "Investment in " . $startup['name']]); - - $stmt = db()->prepare("INSERT INTO wallet_transactions (user_id, amount, type, description) VALUES (?, ?, 'investment_in', ?)"); - $stmt->execute([$startup['founder_id'], $amount, "Investment received from investor for " . $startup['name']]); - db()->commit(); $success = "Investment of £" . number_format($amount) . " confirmed successfully! Funds moved to the founder's pot."; header("refresh:3;url=portfolio.php"); @@ -141,6 +130,9 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby'; Already Raised £
+
Remaining £ diff --git a/startup_details.php b/startup_details.php index a52fcd5..24c87a9 100644 --- a/startup_details.php +++ b/startup_details.php @@ -1,29 +1,26 @@ prepare("SELECT * FROM users WHERE id = ?"); +$stmt->execute([$user_id]); +$user = $stmt->fetch(); $startupId = $_GET['id'] ?? null; if (!$startupId) { - header("Location: startups.php"); + header('Location: startups.php'); exit; } -// Fetch user data -$stmt = db()->prepare("SELECT * FROM users WHERE id = ?"); -$stmt->execute([$_SESSION['user_id']]); -$user = $stmt->fetch(); - -// Fetch startup data $stmt = db()->prepare(" - SELECT s.*, u.full_name as founder_name, u.university as founder_university, u.bio as founder_bio, u.skills as founder_skills, u.profile_image as founder_image, - fr.funding_goal, fr.funding_raised as current_round_raised, fr.status as round_status, fr.id as round_id - FROM startups s - JOIN users u ON s.founder_id = u.id + SELECT s.*, fr.id as round_id, 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.id = ? "); @@ -34,146 +31,341 @@ if (!$startup) { die("Startup not found."); } -$isFounder = ($startup['founder_id'] == $_SESSION['user_id']); +// Check if user is the founder or an investor +$isFounder = ($_SESSION['user_id'] == $startup['founder_id']); +$isInvestor = ($user['role'] == 'investor'); -// Fetch followers count -$stmt = db()->prepare("SELECT COUNT(*) FROM startup_followers WHERE startup_id = ?"); -$stmt->execute([$startupId]); -$followersCount = $stmt->fetchColumn(); +// Basic permissions check +if (!$isFounder && $startup['status'] === 'private' && !$isInvestor) { + die("You do not have permission to view this profile."); +} -// Check if current user follows -$isFollowing = false; -$stmt = db()->prepare("SELECT 1 FROM startup_followers WHERE startup_id = ? AND follower_id = ?"); -$stmt->execute([$startupId, $_SESSION['user_id']]); -$isFollowing = (bool)$stmt->fetchColumn(); +// Fetch funding history +$canSeeHistory = $isFounder || $isInvestor; +$fundingHistory = []; +if ($canSeeHistory) { + $stmt = db()->prepare(" + SELECT i.*, u.full_name as investor_name, u.id as investor_user_id + FROM investments i + LEFT JOIN users u ON i.investor_id = u.id + WHERE i.startup_id = ? AND i.status != 'rejected' + ORDER BY i.created_at DESC + "); + $stmt->execute([$startupId]); + $fundingHistory = $stmt->fetchAll(); +} -// Fetch recent updates -$stmt = db()->prepare("SELECT * FROM startup_updates WHERE startup_id = ? ORDER BY created_at DESC LIMIT 5"); -$stmt->execute([$startupId]); -$updates = $stmt->fetchAll(); - -// Fetch approved investments for founder view +// Fetch approved investments for dividends calculation (Founder only) $approvedInvestments = []; if ($isFounder) { $stmt = db()->prepare(" - SELECT i.*, u.full_name as investor_name, u.id as investor_user_id - FROM investments i - JOIN users u ON i.investor_id = u.id + SELECT i.*, u.full_name as investor_name + 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([$startupId]); $approvedInvestments = $stmt->fetchAll(); } -function getNextDividendInfo($investmentDate) { - $nextDate = date('M d, Y', strtotime($investmentDate . ' + 1 month')); - return $nextDate; -} +// Fetch founders +$stmt = db()->prepare("SELECT id, full_name FROM users WHERE id = ?"); +$stmt->execute([$startup['founder_id']]); +$founder = $stmt->fetch(); $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby'; + +// Calculate progress +$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 + ]; +} ?> - + - - - <?= htmlspecialchars($startup['name']) ?> — <?= htmlspecialchars($platformName) ?> + + <?= htmlspecialchars($startup['name']) ?> | Startup Details - + + - + - - -
- -
-
-
-
-
- -
-
-

-
- - - Followers -
-
+ +
+ +
+ + £
+ +
+
+ +
+ +
+ Log Out +
+
+
+ +
+
+ + +
+ Round status updated successfully! +
+ + + +
+
+
+ + + + + + +
+

+ +

+

+ Founded by +

+
+ + + + + Edit Profile + +
- -
-
- - -
-
-
- Currently Fundraising -

Seed Round is LIVE

-
- - Invest Now - + + +
+
+

Active Funding Round

+ % Complete +
+
+
+
+
+
+
Raised
+
£
- -
-
- £ raised - Target: £ -
-
-
-
+
+
Goal
+
£
- - -
-
+
+ + +
+ - -
@@ -198,7 +390,7 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
-
+
Available Capital
£
@@ -208,7 +400,6 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
£
-

This pot holds all investments received. You can withdraw funds for business operations or add funds to cover investor dividends.

@@ -227,15 +418,15 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby'; $monthlyYield = ($inv['amount'] * ($startup['founder_return_rate'] ?? 0) / 100) / 12; $nextPay = getNextDividendInfo($inv['created_at']); ?> -
-
-
-
-
Investment: £
-
-
-
£
-
Next:
+
+
+
+
Invested £
+
+
+
£
+
+ days left
@@ -243,117 +434,146 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
- -
-

The Vision

-
- -
-
- - -
-

Business Intelligence

-
+ +
+

Product & Vision

+

+ +

+ +
-

Business Model

-

+

Business Model

+

-

Product/Service

-

+

Operational Stage

+

- -
-

Verified Data Rooms

-
+
+

Financial Health

+ +
+
+
+
Cash on Hand
+
£
+
+
+
Monthly Burn
+
£
+
+
+
+
+
+
+
Outstanding Debt
+
+
+
+
Accounts Receivable/Payable
+
+
+
+
+ +

Historical Documentation

+
'Income Statements', - 'balance_sheets' => 'Balance Sheets', - 'cash_flow_statements' => 'Cash Flow Statements', - 'revenue_breakdown' => 'Revenue Breakdown', - 'gross_margin' => 'Gross Margin Analysis' + 'Income Statements' => $startup['doc_income_statements'], + 'Balance Sheets' => $startup['doc_balance_sheets'], + 'Cash Flow' => $startup['doc_cash_flow_statements'], + 'Revenue Breakdown' => $startup['doc_revenue_breakdown'], + 'Gross Margin' => $startup['doc_gross_margin'] ]; - foreach ($docs as $key => $label): - $docPath = $startup['doc_' . $key] ?? ''; + foreach ($docs as $label => $path): if ($path): ?> -
- -
- - Download - - Not uploaded - + + + + +
+
+ + +
+

+ Expected Investor Returns +

+
+
+
Platform Recommendation
+
%
+
AI analysis based on uploaded financials
+
+
+
Founder's Proposal
+
+
- +
Target annual dividend yield set by founder
+
-
-
- - +
@@ -421,6 +641,7 @@ document.getElementById('wallet-form').addEventListener('submit', function(e) { document.getElementById('startup-wallet-balance').innerText = formattedBalance; } closeWalletModal(); + alert(formData.get('action') === 'add' ? 'Funds added successfully!' : 'Withdrawal successful!'); } else { alert('Error: ' + data.error); } @@ -431,27 +652,6 @@ document.getElementById('wallet-form').addEventListener('submit', function(e) { }); }); -function updateRound(roundId, status) { - if (confirm('Are you sure you want to ' + status.toLowerCase() + ' this funding round?')) { - const formData = new FormData(); - formData.append('round_id', roundId); - formData.append('status', status); - - fetch('update_round_status.php', { - method: 'POST', - body: formData - }) - .then(response => response.json()) - .then(data => { - if (data.success) { - location.reload(); - } else { - alert('Error: ' + data.error); - } - }); - } -} - // Close modal when clicking outside window.onclick = function(event) { const modal = document.getElementById('wallet-modal'); @@ -462,4 +662,4 @@ window.onclick = function(event) { - \ No newline at end of file +