133 lines
5.9 KiB
TypeScript
133 lines
5.9 KiB
TypeScript
"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>
|
|
)
|
|
}
|