Initial commit: Second Brain Platform

Complete platform with unified design system and real API integration.

Apps: Dashboard, Fitness, Budget, Inventory, Trips, Reader, Media, Settings
Infrastructure: SvelteKit + Python gateway + Docker Compose
This commit is contained in:
Yusuf Suleman
2026-03-28 23:20:40 -05:00
commit d3e250e361
159 changed files with 44797 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
<script lang="ts">
import { onMount } from 'svelte';
import DashboardActionCard from '$lib/components/dashboard/DashboardActionCard.svelte';
import BudgetModule from '$lib/components/dashboard/BudgetModule.svelte';
import FitnessModule from '$lib/components/dashboard/FitnessModule.svelte';
import IssuesModule from '$lib/components/dashboard/IssuesModule.svelte';
let inventoryIssueCount = $state(0);
let inventoryReviewCount = $state(0);
let budgetUncatCount = $state(0);
let budgetSpending = $state('');
let budgetIncome = $state('');
let fitnessCalRemaining = $state(0);
let fitnessCalLogged = $state(0);
let fitnessProtein = $state(0);
let fitnessCarbs = $state(0);
onMount(async () => {
const n = new Date();
const today = `${n.getFullYear()}-${String(n.getMonth() + 1).padStart(2, '0')}-${String(n.getDate()).padStart(2, '0')}`;
try {
const [invRes, budgetRes, uncatRes, fitTotalsRes, fitGoalsRes] = await Promise.all([
fetch('/api/inventory/summary', { credentials: 'include' }),
fetch('/api/budget/summary', { credentials: 'include' }),
fetch('/api/budget/uncategorized-count', { credentials: 'include' }),
fetch(`/api/fitness/entries/totals?date=${today}`, { credentials: 'include' }),
fetch(`/api/fitness/goals/for-date?date=${today}`, { credentials: 'include' }),
]);
if (invRes.ok) {
const data = await invRes.json();
inventoryIssueCount = data.issueCount || 0;
inventoryReviewCount = data.reviewCount || 0;
}
if (budgetRes.ok) {
const data = await budgetRes.json();
budgetSpending = '$' + Math.abs(data.spendingDollars || 0).toLocaleString('en-US');
budgetIncome = '$' + Math.abs(data.incomeDollars || 0).toLocaleString('en-US');
}
if (uncatRes.ok) {
const data = await uncatRes.json();
budgetUncatCount = data.count || 0;
}
if (fitTotalsRes.ok) {
const t = await fitTotalsRes.json();
fitnessCalLogged = Math.round(t.total_calories || 0);
fitnessProtein = Math.round(t.total_protein || 0);
fitnessCarbs = Math.round(t.total_carbs || 0);
}
if (fitGoalsRes.ok) {
const g = await fitGoalsRes.json();
fitnessCalRemaining = Math.max(0, (g.calories || 2000) - fitnessCalLogged);
}
} catch { /* silent */ }
});
</script>
<div class="page">
<div class="app-surface">
<div class="page-header">
<div class="page-title">Dashboard</div>
<div class="page-greeting">Good to see you, <strong>Yusuf</strong></div>
</div>
<div class="action-cards">
<DashboardActionCard
title="{budgetUncatCount} uncategorized transactions"
description="{budgetSpending} spent &middot; {budgetIncome} income"
action="Review"
variant="budget"
size="primary"
href="/budget"
/>
<DashboardActionCard
title="{inventoryIssueCount} issue{inventoryIssueCount !== 1 ? 's' : ''} · {inventoryReviewCount} needs review"
description="{inventoryIssueCount + inventoryReviewCount} items need attention"
action="View"
variant="inventory"
href="/inventory"
/>
<DashboardActionCard
title="{fitnessCalRemaining.toLocaleString()} calories remaining today"
description="{fitnessCalLogged.toLocaleString()} cal logged &middot; {fitnessProtein}g protein &middot; {fitnessCarbs}g carbs"
action="Log food"
variant="fitness"
href="/fitness"
/>
</div>
<div class="modules-grid">
<BudgetModule />
<div class="right-stack">
<FitnessModule />
<IssuesModule />
</div>
</div>
</div>
</div>
<style>
.action-cards {
display: flex;
flex-direction: column;
gap: var(--section-gap);
margin-bottom: calc(var(--section-gap) + 8px);
padding-top: 4px;
}
.modules-grid {
display: grid;
grid-template-columns: 1.3fr 0.7fr;
gap: var(--module-gap);
align-items: start;
}
.right-stack {
display: flex;
flex-direction: column;
gap: var(--module-gap);
}
@media (max-width: 768px) {
.modules-grid {
grid-template-columns: 1fr;
}
}
</style>