Initial commit
This commit is contained in:
162
app/(dashboard)/dashboard/page.tsx
Normal file
162
app/(dashboard)/dashboard/page.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
import { auth } from '@/auth'
|
||||
import { db } from '@/lib/db'
|
||||
import { machines, sessions } from '@/lib/db/schema'
|
||||
import { eq, desc } from 'drizzle-orm'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import Link from 'next/link'
|
||||
import {
|
||||
Laptop,
|
||||
History,
|
||||
Link2,
|
||||
ArrowRight,
|
||||
Clock,
|
||||
CheckCircle2,
|
||||
Circle
|
||||
} from 'lucide-react'
|
||||
import { formatDistanceToNow } from 'date-fns'
|
||||
|
||||
export default async function DashboardPage() {
|
||||
const session = await auth()
|
||||
const userId = session!.user.id
|
||||
|
||||
const [machineList, sessionList] = await Promise.all([
|
||||
db.select().from(machines).where(eq(machines.userId, userId)).orderBy(desc(machines.lastSeen)),
|
||||
db.select().from(sessions).where(eq(sessions.viewerUserId, userId)).orderBy(desc(sessions.startedAt)).limit(5),
|
||||
])
|
||||
|
||||
const onlineMachines = machineList.filter((m) => m.isOnline)
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="grid gap-4 md:grid-cols-3">
|
||||
<Card className="border-border/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between pb-2">
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">Total Machines</CardTitle>
|
||||
<Laptop className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{machineList.length}</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">{onlineMachines.length} online</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-border/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between pb-2">
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">Recent Sessions</CardTitle>
|
||||
<History className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{sessionList.length}</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">Last 5 sessions</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-border/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between pb-2">
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">Quick Connect</CardTitle>
|
||||
<Link2 className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Button asChild size="sm" className="w-full">
|
||||
<Link href="/dashboard/connect">
|
||||
Enter Code <ArrowRight className="ml-2 h-4 w-4" />
|
||||
</Link>
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 lg:grid-cols-2">
|
||||
<Card className="border-border/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between">
|
||||
<div>
|
||||
<CardTitle>Your Machines</CardTitle>
|
||||
<CardDescription>Registered remote machines</CardDescription>
|
||||
</div>
|
||||
<Button variant="outline" size="sm" asChild>
|
||||
<Link href="/dashboard/machines">View all</Link>
|
||||
</Button>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{machineList.length > 0 ? (
|
||||
<div className="space-y-3">
|
||||
{machineList.slice(0, 5).map((machine) => (
|
||||
<div key={machine.id} className="flex items-center justify-between p-3 rounded-lg bg-muted/30">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`h-2 w-2 rounded-full ${machine.isOnline ? 'bg-green-500' : 'bg-muted-foreground/30'}`} />
|
||||
<div>
|
||||
<p className="text-sm font-medium">{machine.name}</p>
|
||||
<p className="text-xs text-muted-foreground">{machine.os} {machine.osVersion}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
{machine.lastSeen
|
||||
? formatDistanceToNow(new Date(machine.lastSeen), { addSuffix: true })
|
||||
: 'Never connected'}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center py-8 text-center">
|
||||
<Laptop className="h-10 w-10 text-muted-foreground/30 mb-4" />
|
||||
<p className="text-sm text-muted-foreground mb-4">No machines registered yet</p>
|
||||
<Button variant="outline" size="sm" asChild>
|
||||
<Link href="/download">Download Agent</Link>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-border/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between">
|
||||
<div>
|
||||
<CardTitle>Recent Sessions</CardTitle>
|
||||
<CardDescription>Your connection history</CardDescription>
|
||||
</div>
|
||||
<Button variant="outline" size="sm" asChild>
|
||||
<Link href="/dashboard/sessions">View all</Link>
|
||||
</Button>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{sessionList.length > 0 ? (
|
||||
<div className="space-y-3">
|
||||
{sessionList.map((s) => (
|
||||
<div key={s.id} className="flex items-center justify-between p-3 rounded-lg bg-muted/30">
|
||||
<div className="flex items-center gap-3">
|
||||
{s.endedAt ? (
|
||||
<CheckCircle2 className="h-4 w-4 text-muted-foreground" />
|
||||
) : (
|
||||
<Circle className="h-4 w-4 text-green-500" />
|
||||
)}
|
||||
<div>
|
||||
<p className="text-sm font-medium">{s.machineName || 'Unknown Machine'}</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{s.connectionType === 'session_code' ? 'Session Code' : 'Direct'} connection
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs text-muted-foreground">
|
||||
<Clock className="h-3 w-3" />
|
||||
{formatDistanceToNow(new Date(s.startedAt), { addSuffix: true })}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center py-8 text-center">
|
||||
<History className="h-10 w-10 text-muted-foreground/30 mb-4" />
|
||||
<p className="text-sm text-muted-foreground mb-4">No sessions yet</p>
|
||||
<Button variant="outline" size="sm" asChild>
|
||||
<Link href="/dashboard/connect">Start connecting</Link>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user