-
Notifications
You must be signed in to change notification settings - Fork 18
feat: catalog landing header + onboarding empty state #1803
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: test
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| "use client"; | ||
|
|
||
| import Link from "next/link"; | ||
| import { Sparkles } from "lucide-react"; | ||
| import { Button } from "@/components/ui/button"; | ||
| import { Skeleton } from "@/components/ui/skeleton"; | ||
| import useCatalogs from "@/hooks/useCatalogs"; | ||
| import useArtistCatalogSongs from "@/hooks/useArtistCatalogSongs"; | ||
|
|
||
| interface CatalogLandingHeaderProps { | ||
| catalogId: string; | ||
| } | ||
|
|
||
| /** | ||
| * Landing header for a catalog deep-link (e.g. a warm lead arriving from a | ||
| * marketing valuation). Shows the catalog name, how many tracks it holds, and | ||
| * a single clear next action — open the agent pre-asked about this catalog — | ||
| * so the work the lead just did has an obvious continuation. | ||
| */ | ||
| const CatalogLandingHeader = ({ catalogId }: CatalogLandingHeaderProps) => { | ||
| const { data: catalogsData } = useCatalogs(); | ||
| const catalog = catalogsData?.catalogs?.find((c) => c.id === catalogId); | ||
|
|
||
| const { data, isLoading } = useArtistCatalogSongs({ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Prompt for AI agents |
||
| catalogId, | ||
| pageSize: 1, | ||
| }); | ||
| const trackCount = data?.pages?.[0]?.pagination?.total_count ?? 0; | ||
|
Comment on lines
+24
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In accounts where an active artist is selected and this catalog includes tracks by multiple artists, Useful? React with 👍 / 👎. |
||
|
|
||
| const name = catalog?.name ?? "Your catalog"; | ||
| const prompt = `Tell me about my catalog "${name}" — what stands out across these tracks, and what should I do next?`; | ||
|
|
||
| return ( | ||
| <div className="rounded-xl bg-card shadow p-5 mb-6 flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between"> | ||
| <div className="min-w-0"> | ||
| <h1 className="text-lg md:text-xl font-semibold truncate">{name}</h1> | ||
| <p className="text-sm text-muted-foreground mt-1"> | ||
| {isLoading ? ( | ||
| <Skeleton className="h-4 w-24" /> | ||
| ) : ( | ||
| <> | ||
| {trackCount} {trackCount === 1 ? "track" : "tracks"} in this catalog | ||
| </> | ||
| )} | ||
| </p> | ||
| </div> | ||
| <Button asChild className="shrink-0"> | ||
| <Link href={`/?q=${encodeURIComponent(prompt)}`}> | ||
| <Sparkles /> | ||
| Ask the agent about this catalog | ||
| </Link> | ||
| </Button> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default CatalogLandingHeader; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| "use client"; | ||
|
|
||
| import Link from "next/link"; | ||
| import { Sparkles, BarChart3 } from "lucide-react"; | ||
| import { Button } from "@/components/ui/button"; | ||
|
|
||
| const VALUATION_URL = "https://recoupable.com/valuation"; | ||
| const AGENT_PROMPT = | ||
| "Help me set up my first catalog and understand what my music is worth."; | ||
|
|
||
| /** | ||
| * Onboarding empty state for an account with no catalogs yet. Replaces the bare | ||
| * "No catalogs found." text with a guided next step: run a free valuation (the | ||
| * same flow that materializes a catalog) or ask the agent to help build one. | ||
| */ | ||
| const EmptyCatalogsState = () => { | ||
| return ( | ||
| <div className="rounded-xl bg-card shadow p-8 text-center max-w-xl mx-auto"> | ||
| <h2 className="text-lg font-semibold">No catalogs yet</h2> | ||
| <p className="text-sm text-muted-foreground mt-2"> | ||
| A catalog is your collection of tracks with their play counts and | ||
| estimated value. Run a free valuation to measure your catalog, or ask the | ||
| agent to help you build one. | ||
| </p> | ||
| <div className="flex flex-col sm:flex-row gap-3 justify-center mt-6"> | ||
| <Button asChild> | ||
| <a href={VALUATION_URL} target="_blank" rel="noreferrer"> | ||
| <BarChart3 /> | ||
| Measure your catalog value | ||
| </a> | ||
| </Button> | ||
| <Button asChild variant="outline"> | ||
| <Link href={`/?q=${encodeURIComponent(AGENT_PROMPT)}`}> | ||
| <Sparkles /> | ||
| Ask the agent | ||
| </Link> | ||
| </Button> | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default EmptyCatalogsState; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Fetches ALL catalogs via useCatalogs() just to extract one catalog name with
.find(). For a warm-lead deep-link page where the catalog list cache may be cold, this is an unnecessary full-list fetch. A targeteduseCatalog(id)hook or accepting catalogName as a prop would be more efficient.Prompt for AI agents