feat: Implement core application structure with new dashboard, settings, and help pages, and enhance opportunities management with persistence and filtering.
This commit is contained in:
132
app/(app)/dashboard/page.tsx
Normal file
132
app/(app)/dashboard/page.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
"use client"
|
||||
|
||||
import { useQuery } from "convex/react"
|
||||
import { api } from "@/convex/_generated/api"
|
||||
import { useProject } from "@/components/project-context"
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
|
||||
export default function Page() {
|
||||
const { selectedProjectId } = useProject()
|
||||
const projects = useQuery(api.projects.getProjects)
|
||||
const analysis = useQuery(
|
||||
api.analyses.getLatestByProject,
|
||||
selectedProjectId ? { projectId: selectedProjectId as any } : "skip"
|
||||
)
|
||||
|
||||
const selectedProject = projects?.find((project) => project._id === selectedProjectId)
|
||||
const isLoading = selectedProjectId && analysis === undefined
|
||||
|
||||
if (!selectedProjectId && projects && projects.length === 0) {
|
||||
return (
|
||||
<div className="flex flex-1 items-center justify-center p-10 text-center">
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-xl font-semibold">No projects yet</h2>
|
||||
<p className="text-muted-foreground">Complete onboarding to create your first project.</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex flex-1 items-center justify-center p-10 text-center text-muted-foreground">
|
||||
Loading analysis...
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (!analysis) {
|
||||
return (
|
||||
<div className="flex flex-1 items-center justify-center p-10 text-center">
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-xl font-semibold">No analysis yet</h2>
|
||||
<p className="text-muted-foreground">Run onboarding to analyze a product for this project.</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-1 flex-col gap-6 p-4 lg:p-8">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<h1 className="text-2xl font-semibold">{analysis.productName}</h1>
|
||||
{selectedProject?.name && (
|
||||
<Badge variant="outline">{selectedProject.name}</Badge>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-muted-foreground">{analysis.tagline}</p>
|
||||
<p className="max-w-3xl text-sm text-muted-foreground">{analysis.description}</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-5">
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm">Features</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="text-2xl font-semibold">{analysis.features.length}</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm">Keywords</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="text-2xl font-semibold">{analysis.keywords.length}</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm">Personas</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="text-2xl font-semibold">{analysis.personas.length}</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm">Competitors</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="text-2xl font-semibold">{analysis.competitors.length}</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm">Use Cases</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="text-2xl font-semibold">{analysis.useCases.length}</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 lg:grid-cols-2">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base">Top Features</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2">
|
||||
{analysis.features.slice(0, 6).map((feature, index) => (
|
||||
<div key={`${feature.name}-${index}`} className="flex items-start gap-2">
|
||||
<span className="mt-1 h-2 w-2 rounded-full bg-primary" />
|
||||
<div>
|
||||
<p className="text-sm font-medium">{feature.name}</p>
|
||||
<p className="text-xs text-muted-foreground">{feature.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base">Top Problems Solved</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2">
|
||||
{analysis.problemsSolved.slice(0, 6).map((problem, index) => (
|
||||
<div key={`${problem.problem}-${index}`} className="flex items-start gap-2">
|
||||
<span className="mt-1 h-2 w-2 rounded-full bg-primary" />
|
||||
<div>
|
||||
<p className="text-sm font-medium">{problem.problem}</p>
|
||||
<p className="text-xs text-muted-foreground">{problem.emotionalImpact}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user