diff --git a/api/wallet_transaction.php b/api/wallet_transaction.php index d5fa388..2e71e6c 100644 --- a/api/wallet_transaction.php +++ b/api/wallet_transaction.php @@ -1,6 +1,6 @@ false, 'error' => 'Invalid amount']); + echo json_encode(['success' => false, 'error' => 'Please enter a valid amount greater than zero.']); exit; } @@ -27,7 +27,7 @@ try { $user = $stmt->fetch(); if (!$user) { - throw new Exception("User not found"); + throw new Exception("User account not found."); } $current_balance = (float)$user['balance']; @@ -37,27 +37,35 @@ try { $stmt = db()->prepare("UPDATE users SET balance = ? WHERE id = ?"); $stmt->execute([$new_balance, $user_id]); - // Log transaction (optional but good practice, maybe later) + // 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]); db()->commit(); - echo json_encode(['success' => true, 'new_balance' => $new_balance]); + echo json_encode(['success' => true, 'new_balance' => $new_balance, 'message' => 'Funds added successfully!']); } elseif ($action === 'withdraw') { if ($current_balance < $amount) { - throw new Exception("Insufficient funds"); + throw new Exception("Insufficient funds. You only have £" . number_format($current_balance, 2) . " available."); } $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]); + echo json_encode(['success' => true, 'new_balance' => $new_balance, 'message' => 'Withdrawal successful!']); } else { - throw new Exception("Invalid action"); + throw new Exception("Invalid action requested."); } } catch (Exception $e) { - db()->rollBack(); + if (db()->inTransaction()) { + 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 53a0e44..5e7aa00 100644 --- a/dashboard.php +++ b/dashboard.php @@ -79,6 +79,11 @@ if ($user['role'] === 'founder') { $myInvestments = $stmt->fetchAll(); } +// Fetch Wallet Transactions +$stmt = db()->prepare("SELECT * FROM wallet_transactions WHERE user_id = ? ORDER BY created_at DESC LIMIT 5"); +$stmt->execute([$_SESSION['user_id']]); +$transactions = $stmt->fetchAll(); + function number_get_formatted($num) { return number_format((float)$num, 0, '.', ','); } @@ -98,155 +103,106 @@ function number_get_formatted($num) { .trending-pill { background: linear-gradient(45deg, #FFD700, #FFA500); color: #000; - padding: 2px 8px; - border-radius: 4px; - font-size: 10px; + padding: 4px 12px; + border-radius: 50px; + font-size: 11px; font-weight: 800; text-transform: uppercase; + letter-spacing: 0.5px; display: inline-flex; align-items: center; - gap: 3px; - margin-left: 8px; - vertical-align: middle; + gap: 5px; } - .profile-link-card { - text-decoration: none; - color: inherit; - transition: transform 0.2s; - display: block; + .transaction-item { + padding: 12px 0; + border-bottom: 1px solid rgba(255,255,255,0.05); + display: flex; + justify-content: space-between; + align-items: center; } - .profile-link-card:hover { - transform: translateY(-2px); - } - - /* Modal Styles */ - .modal { - display: none; - position: fixed; - z-index: 1000; - left: 0; - top: 0; - width: 100%; - height: 100%; - background-color: rgba(0,0,0,0.8); - backdrop-filter: blur(5px); - } - .modal-content { - background-color: #1a1a24; - margin: 10% auto; - padding: 40px; - border: 1px solid var(--border-color); - width: 400px; - border-radius: 32px; - box-shadow: 0 25px 50px rgba(0,0,0,0.5); + .transaction-item:last-child { + border-bottom: none; } - + -
-
- - <?= htmlspecialchars($platformName) ?> Logo - +
+
+
+ + £ +
+ Logout +
+ -
-
-
-
+
+
+

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

- -
- +
+

My Ventures

+ + Register New Startup +
+ +
-
+
-

Ready to share your vision with the world?

- Start Your First Round +

No startups registered

+

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

+ Get Started
-
- -
-
-
- -
-
-
- - - Trending - -
-
- - - - Target: £ -
-
-
-
-
-
£
-
Funds Raised
-
- -
- - -
- + +
+
+
+
+ + +
- -
+

+

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

Recent Transactions

+ +

No transactions yet.

+ +
+ +
+
+
+
+
+
+ £ +
+
+ +
+ +
+

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

@@ -423,8 +402,9 @@ document.getElementById('wallet-form').addEventListener('submit', function(e) { .then(data => { if (data.success) { document.getElementById('wallet-balance').innerText = '£' + parseFloat(data.new_balance).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}); + document.getElementById('header-wallet-balance').innerText = '£' + parseFloat(data.new_balance).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}); closeWalletModal(); - alert(formData.get('action') === 'add' ? 'Funds added successfully!' : 'Withdrawal successful!'); + location.reload(); // Reload to show new transaction } else { alert('Error: ' + data.error); } diff --git a/db/migrations/20_wallet_transactions.sql b/db/migrations/20_wallet_transactions.sql new file mode 100644 index 0000000..152d6c0 --- /dev/null +++ b/db/migrations/20_wallet_transactions.sql @@ -0,0 +1,9 @@ +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 2168d9f..1e83e6f 100644 --- a/invest.php +++ b/invest.php @@ -30,6 +30,8 @@ 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 = ''; @@ -45,7 +47,9 @@ 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."; + $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) . "."; } else { db()->beginTransaction(); try { @@ -72,6 +76,13 @@ 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"); @@ -130,9 +141,6 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby'; Already Raised £
-
Remaining £ diff --git a/startup_details.php b/startup_details.php index 24c87a9..03f26e9 100644 --- a/startup_details.php +++ b/startup_details.php @@ -1,26 +1,29 @@ prepare("SELECT * FROM users WHERE id = ?"); -$stmt->execute([$user_id]); -$user = $stmt->fetch(); +require_once __DIR__ . '/db/config.php'; $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.*, 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 + 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 LEFT JOIN funding_rounds fr ON s.id = fr.startup_id AND fr.status = 'Active' WHERE s.id = ? "); @@ -31,341 +34,163 @@ if (!$startup) { die("Startup not found."); } -// Check if user is the founder or an investor -$isFounder = ($_SESSION['user_id'] == $startup['founder_id']); -$isInvestor = ($user['role'] == 'investor'); +$isFounder = ($startup['founder_id'] == $_SESSION['user_id']); -// Basic permissions check -if (!$isFounder && $startup['status'] === 'private' && !$isInvestor) { - die("You do not have permission to view this profile."); -} +// Fetch followers count +$stmt = db()->prepare("SELECT COUNT(*) FROM startup_followers WHERE startup_id = ?"); +$stmt->execute([$startupId]); +$followersCount = $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(); -} +// 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 approved investments for dividends calculation (Founder only) +// 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 $approvedInvestments = []; if ($isFounder) { $stmt = db()->prepare(" - SELECT i.*, u.full_name as investor_name - FROM investments i - JOIN users u ON i.investor_id = u.id + 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 WHERE i.startup_id = ? AND i.status = 'approved' + ORDER BY i.created_at DESC "); $stmt->execute([$startupId]); $approvedInvestments = $stmt->fetchAll(); + + // Fetch Wallet Transactions for Founder + $stmt = db()->prepare("SELECT * FROM wallet_transactions WHERE user_id = ? ORDER BY created_at DESC LIMIT 5"); + $stmt->execute([$_SESSION['user_id']]); + $transactions = $stmt->fetchAll(); } -// Fetch founders -$stmt = db()->prepare("SELECT id, full_name FROM users WHERE id = ?"); -$stmt->execute([$startup['founder_id']]); -$founder = $stmt->fetch(); +function getNextDividendInfo($investmentDate) { + $nextDate = date('M d, Y', strtotime($investmentDate . ' + 1 month')); + return $nextDate; +} $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']) ?> | Startup Details + + + <?= htmlspecialchars($startup['name']) ?> — <?= htmlspecialchars($platformName) ?> - + - + -
-
- -
-
- - -
- Round status updated successfully! -
- - - -
-
-
- - - - - - -
-

- -

-

- Founded by -

-
- - - - - - Edit Profile - - +
+
+ + £
+ Logout +
+ - - -
-
-

Active Funding Round

- % Complete -
-
-
-
-
+
+ +
+
+
+
+
+ +
-
Raised
-
£
-
-
-
Goal
-
£
+

+
+ + + Followers +
+
+ + Edit Startup + +
+ + +
+ Message Founder + +
+
+
- -
-
+
+
+ + +
+
+
+ Currently Fundraising +

Seed Round is LIVE

+
+ + Invest Now + +
+ +
+
+ £ raised + Target: £ +
+
+
+
+
+ + +
+ - -
@@ -390,7 +215,7 @@ function getNextDividendInfo($createdAt) {
-
+
Available Capital
£
@@ -400,6 +225,29 @@ function getNextDividendInfo($createdAt) {
£
+ + +
+

Recent Pot Transactions

+ +

No transactions yet.

+ +
+ +
+
+
+
+
+
+ £ +
+
+ +
+ +
+

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

@@ -418,15 +266,15 @@ function getNextDividendInfo($createdAt) { $monthlyYield = ($inv['amount'] * ($startup['founder_return_rate'] ?? 0) / 100) / 12; $nextPay = getNextDividendInfo($inv['created_at']); ?> -
-
-
-
Invested £
-
-
-
£
-
- days left +
+
+
+
+
Investment: £
+
+
+
£
+
Next:
@@ -434,146 +282,117 @@ function getNextDividendInfo($createdAt) {
- -
-

Product & Vision

-

- -

- -
+ +
+

The Vision

+
+ +
+
+ + +
+

Business Intelligence

+
-

Business Model

-

+

Business Model

+

-

Operational Stage

-

+

Product/Service

+

-
-

Financial Health

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

Historical Documentation

-
+ +
+

Verified Data Rooms

+
$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'] + 'income_statements' => 'Income Statements', + 'balance_sheets' => 'Balance Sheets', + 'cash_flow_statements' => 'Cash Flow Statements', + 'revenue_breakdown' => 'Revenue Breakdown', + 'gross_margin' => 'Gross Margin Analysis' ]; - foreach ($docs as $label => $path): if ($path): + foreach ($docs as $key => $label): + $docPath = $startup['doc_' . $key] ?? ''; ?> - - - - +
+ +
+ + Download + + Not uploaded + +
+
+
- -
-

- Expected Investor Returns -

-
-
-
Platform Recommendation
-
%
-
AI analysis based on uploaded financials
-
-
-
Founder's Proposal
-
- -
-
Target annual dividend yield set by founder
-
+
+
@@ -641,7 +460,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!'); + location.reload(); // Reload to show new transaction } else { alert('Error: ' + data.error); } @@ -652,6 +471,27 @@ 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'); @@ -662,4 +502,4 @@ window.onclick = function(event) { - + \ No newline at end of file