diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
index 085652c..042c5a4 100755
Binary files a/public/apple-touch-icon.png and b/public/apple-touch-icon.png differ
diff --git a/public/favicon.png b/public/favicon.png
index c430b05..b5b00b9 100755
Binary files a/public/favicon.png and b/public/favicon.png differ
diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx
index 5d02047..29c8bc4 100755
--- a/src/app/dashboard/page.tsx
+++ b/src/app/dashboard/page.tsx
@@ -1,13 +1,79 @@
import { Button } from "@/components/ui/button"
-import { IconExternalLink } from "@tabler/icons-react"
+import {
+ IconBrandGithub,
+ IconExternalLink,
+ IconGitCommit,
+ IconGitFork,
+ IconStar,
+ IconAlertCircle,
+ IconEye,
+} from "@tabler/icons-react"
-const GITHUB_URL =
- "https://github.com/High-Performance-Structures/compass"
+const REPO = "High-Performance-Structures/compass"
+const GITHUB_URL = `https://github.com/${REPO}`
+
+type RepoStats = {
+ stargazers_count: number
+ forks_count: number
+ open_issues_count: number
+ subscribers_count: number
+}
+
+type Commit = {
+ sha: string
+ commit: {
+ message: string
+ author: { name: string; date: string }
+ }
+ html_url: string
+}
+
+async function getRepoData() {
+ try {
+ const [repoRes, commitsRes] = await Promise.all([
+ fetch(`https://api.github.com/repos/${REPO}`, {
+ next: { revalidate: 300 },
+ headers: { Accept: "application/vnd.github+json" },
+ }),
+ fetch(`https://api.github.com/repos/${REPO}/commits?per_page=8`, {
+ next: { revalidate: 300 },
+ headers: { Accept: "application/vnd.github+json" },
+ }),
+ ])
+
+ if (!repoRes.ok || !commitsRes.ok) return null
+
+ const repo: RepoStats = await repoRes.json()
+ const commits: Commit[] = await commitsRes.json()
+ return { repo, commits }
+ } catch {
+ return null
+ }
+}
+
+function timeAgo(date: string) {
+ const seconds = Math.floor(
+ (Date.now() - new Date(date).getTime()) / 1000
+ )
+ if (seconds < 60) return "just now"
+ const minutes = Math.floor(seconds / 60)
+ if (minutes < 60) return `${minutes}m ago`
+ const hours = Math.floor(minutes / 60)
+ if (hours < 24) return `${hours}h ago`
+ const days = Math.floor(hours / 24)
+ if (days < 30) return `${days}d ago`
+ return new Date(date).toLocaleDateString("en-US", {
+ month: "short",
+ day: "numeric",
+ })
+}
+
+export default async function Page() {
+ const data = await getRepoData()
-export default function Page() {
return (
-
+
-
-
-
-
- Working
-
-
- - Projects — create and manage projects with D1 database
- - Schedule — Gantt chart with phases, tasks, dependencies, and critical path
- - File browser — drive-style UI with folder navigation
- - Settings — app preferences with theme and notifications
- - Sidebar navigation with contextual project/file views
- - Command palette search (Cmd+K)
-
-
+
+
+
+
+
+ Working
+
+
+ - Projects — create and manage projects with D1 database
+ - Schedule — Gantt chart with phases, tasks, dependencies, and critical path
+ - File browser — drive-style UI with folder navigation
+ - Settings — app preferences with theme and notifications
+ - Sidebar navigation with contextual project/file views
+ - Command palette search (Cmd+K)
+
+
-
-
-
- In Progress
-
-
- - Project auto-provisioning (code generation, CSI folder structure)
- - Budget tracking (CSI divisions, estimated vs actual, change orders)
- - Document management (S3/R2 storage, metadata, versioning)
- - Communication logging (manual entries, timeline view)
- - Dashboard — three-column layout (past due, due today, action items)
- - User authentication and roles (WorkOS)
- - Email notifications (Resend)
- - Basic reports (budget variance, overdue tasks, monthly actuals)
-
-
+
+
+
+ In Progress
+
+
+ - Project auto-provisioning (code generation, CSI folder structure)
+ - Budget tracking (CSI divisions, estimated vs actual, change orders)
+ - Document management (S3/R2 storage, metadata, versioning)
+ - Communication logging (manual entries, timeline view)
+ - Dashboard — three-column layout (past due, due today, action items)
+ - User authentication and roles (WorkOS)
+ - Email notifications (Resend)
+ - Basic reports (budget variance, overdue tasks, monthly actuals)
+
+
-
-
-
- Planned
-
-
- - Client portal with read-only views
- - BuilderTrend import wizard (CSV-based)
- - Daily logs
- - Time tracking
- - Report builder (custom fields and filters)
- - Bid package management
-
-
+
+
+
+ Planned
+
+
+ - Client portal with read-only views
+ - BuilderTrend import wizard (CSV-based)
+ - Daily logs
+ - Time tracking
+ - Report builder (custom fields and filters)
+ - Bid package management
+
+
-
-
-
- Future
-
-
- - Netsuite/QuickBooks API sync
- - Payment integration
- - RFI/Submittal tracking
- - Native mobile apps (iOS/Android)
- - Advanced scheduling (resource leveling, baseline comparison)
-
-
-
+
+
+
+ Future
+
+
+ - Netsuite/QuickBooks API sync
+ - Payment integration
+ - RFI/Submittal tracking
+ - Native mobile apps (iOS/Android)
+ - Advanced scheduling (resource leveling, baseline comparison)
+
+
-
+
+ {data && (
+
+
+
+
+
View on GitHub
+
{REPO}
+
+
+
+
+ }
+ label="Stars"
+ value={data.repo.stargazers_count}
+ />
+ }
+ label="Forks"
+ value={data.repo.forks_count}
+ />
+ }
+ label="Issues"
+ value={data.repo.open_issues_count}
+ />
+ }
+ label="Watchers"
+ value={data.repo.subscribers_count}
+ />
+
+
+
+
+ )}
)
}
+
+function StatCard({
+ icon,
+ label,
+ value,
+}: {
+ icon: React.ReactNode
+ label: string
+ value: number
+}) {
+ return (
+
+
+ {icon}
+ {label}
+
+
+ {value.toLocaleString()}
+
+
+ )
+}
diff --git a/src/components/app-sidebar.tsx b/src/components/app-sidebar.tsx
index 8959d6d..23cd6dc 100755
--- a/src/components/app-sidebar.tsx
+++ b/src/components/app-sidebar.tsx
@@ -78,7 +78,7 @@ function SidebarNav({
projects: { id: string; name: string }[]
}) {
const pathname = usePathname()
- const { state } = useSidebar()
+ const { state, setOpen } = useSidebar()
const { open: openSearch } = useCommandMenu()
const { open: openSettings } = useSettings()
const isExpanded = state === "expanded"
@@ -86,6 +86,13 @@ function SidebarNav({
const isProjectMode = /^\/dashboard\/projects\/[^/]+/.test(
pathname ?? ""
)
+
+ React.useEffect(() => {
+ if ((isFilesMode || isProjectMode) && !isExpanded) {
+ setOpen(true)
+ }
+ }, [isFilesMode, isProjectMode, isExpanded, setOpen])
+
const showContext = isExpanded && (isFilesMode || isProjectMode)
const mode = showContext && isFilesMode
diff --git a/src/components/files/storage-indicator.tsx b/src/components/files/storage-indicator.tsx
index 6ba9f7d..917354d 100755
--- a/src/components/files/storage-indicator.tsx
+++ b/src/components/files/storage-indicator.tsx
@@ -1,6 +1,5 @@
"use client"
-import { Progress } from "@/components/ui/progress"
import { formatFileSize } from "@/lib/file-utils"
import type { StorageUsage } from "@/lib/files-data"
@@ -8,14 +7,15 @@ export function StorageIndicator({ usage }: { usage: StorageUsage }) {
const percent = Math.round((usage.used / usage.total) * 100)
return (
-
-
-
Storage
-
{percent}% used
+
+
-
-
- {formatFileSize(usage.used)} of {formatFileSize(usage.total)}
+
+ {formatFileSize(usage.used)} of {formatFileSize(usage.total)} used
)
diff --git a/src/components/nav-files.tsx b/src/components/nav-files.tsx
index 8eabd3a..d618ff9 100755
--- a/src/components/nav-files.tsx
+++ b/src/components/nav-files.tsx
@@ -19,7 +19,6 @@ import {
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
- SidebarSeparator,
} from "@/components/ui/sidebar"
import { cn } from "@/lib/utils"
@@ -84,8 +83,7 @@ export function NavFiles() {
-
-
+
>
diff --git a/src/components/nav-user.tsx b/src/components/nav-user.tsx
index aac282e..3e0de3f 100755
--- a/src/components/nav-user.tsx
+++ b/src/components/nav-user.tsx
@@ -57,12 +57,12 @@ export function NavUser({
MV
- {user.name}
-
+ {user.name}
+
{user.email}
-
+