From d1ee4e54172500aa436e303c79c60d6746beb64b Mon Sep 17 00:00:00 2001 From: Arpit Gupta Date: Thu, 16 Apr 2026 02:08:50 +0530 Subject: [PATCH 1/2] feat(chat): cut useCreateSegments over to POST /api/artists/{id}/segments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate `hooks/useCreateSegments` from the local `POST /api/segments/create` route to the dedicated `POST /api/artists/{id}/segments` endpoint with Privy bearer auth (matches the pattern in `lib/artists/deleteArtist.ts`). The artist target is now path-encoded and only `prompt` goes in the body. Success is now `{ status: "success" }`-gated rather than response-level `error` presence. Error toast surfacing is unchanged — `data.error` still carries the handler message (including the 409 no-socials/no-fans case). Deletes `app/api/segments/create/route.ts` since the sole caller (`components/Segments/NoSegmentsFound.tsx` via the hook) is now cut over. Grep confirms zero remaining references to `/api/segments/create`. --- app/api/segments/create/route.ts | 24 ----------------------- hooks/useCreateSegments.ts | 33 ++++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 34 deletions(-) delete mode 100644 app/api/segments/create/route.ts diff --git a/app/api/segments/create/route.ts b/app/api/segments/create/route.ts deleted file mode 100644 index 7540fae5c..000000000 --- a/app/api/segments/create/route.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { NextRequest, NextResponse } from "next/server"; -import { createSegments } from "@/lib/segments/createSegments"; - -export async function POST(req: NextRequest) { - try { - const { artist_account_id, prompt } = await req.json(); - if (!artist_account_id || !prompt) { - return NextResponse.json( - { error: "artist_account_id and prompt are required" }, - { status: 400 } - ); - } - const result = await createSegments({ artist_account_id, prompt }); - return NextResponse.json(result); - } catch (error) { - return NextResponse.json( - { - error: - error instanceof Error ? error.message : "Failed to create segments", - }, - { status: 500 } - ); - } -} diff --git a/hooks/useCreateSegments.ts b/hooks/useCreateSegments.ts index 80ebb5d33..ff04e57d9 100644 --- a/hooks/useCreateSegments.ts +++ b/hooks/useCreateSegments.ts @@ -1,8 +1,11 @@ import { useState } from "react"; import { toast } from "react-toastify"; +import { usePrivy } from "@privy-io/react-auth"; import { useArtistProvider } from "@/providers/ArtistProvider"; +import { getClientApiBaseUrl } from "@/lib/api/getClientApiBaseUrl"; export function useCreateSegments() { + const { getAccessToken } = usePrivy(); const { selectedArtist } = useArtistProvider(); const artist_account_id = selectedArtist?.account_id; const [loading, setLoading] = useState(false); @@ -11,23 +14,33 @@ export function useCreateSegments() { if (!artist_account_id) return; setLoading(true); try { - const response = await fetch("/api/segments/create", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - artist_account_id, - prompt: "Segment my fans to help me fund my next project.", - }), - }); + const accessToken = await getAccessToken(); + if (!accessToken) { + throw new Error("Please sign in to generate segments"); + } + + const response = await fetch( + `${getClientApiBaseUrl()}/api/artists/${artist_account_id}/segments`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${accessToken}`, + }, + body: JSON.stringify({ + prompt: "Segment my fans to help me fund my next project.", + }), + }, + ); const data = await response.json(); - if (!response.ok || data.error) { + if (!response.ok || data.status !== "success") { throw new Error(data.error || "Failed to generate segments"); } toast.success("Segments generated successfully!"); if (onSuccess) onSuccess(); } catch (error) { toast.error( - error instanceof Error ? error.message : "Failed to generate segments" + error instanceof Error ? error.message : "Failed to generate segments", ); console.error(error); } finally { From 07ffb222076a044a921ff05d0e615d0b6476962f Mon Sep 17 00:00:00 2001 From: Arpit Gupta Date: Thu, 16 Apr 2026 02:44:26 +0530 Subject: [PATCH 2/2] refactor(chat): extract createArtistSegments lib helper from hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following project pattern (fetchArtists, deleteArtist) — network call lives in lib/artists/*, the hook just wires Privy auth + toast feedback. --- hooks/useCreateSegments.ts | 23 ++++------------- lib/artists/createArtistSegments.ts | 39 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 18 deletions(-) create mode 100644 lib/artists/createArtistSegments.ts diff --git a/hooks/useCreateSegments.ts b/hooks/useCreateSegments.ts index ff04e57d9..6717c6112 100644 --- a/hooks/useCreateSegments.ts +++ b/hooks/useCreateSegments.ts @@ -2,7 +2,7 @@ import { useState } from "react"; import { toast } from "react-toastify"; import { usePrivy } from "@privy-io/react-auth"; import { useArtistProvider } from "@/providers/ArtistProvider"; -import { getClientApiBaseUrl } from "@/lib/api/getClientApiBaseUrl"; +import { createArtistSegments } from "@/lib/artists/createArtistSegments"; export function useCreateSegments() { const { getAccessToken } = usePrivy(); @@ -18,24 +18,11 @@ export function useCreateSegments() { if (!accessToken) { throw new Error("Please sign in to generate segments"); } - - const response = await fetch( - `${getClientApiBaseUrl()}/api/artists/${artist_account_id}/segments`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${accessToken}`, - }, - body: JSON.stringify({ - prompt: "Segment my fans to help me fund my next project.", - }), - }, + await createArtistSegments( + accessToken, + artist_account_id, + "Segment my fans to help me fund my next project.", ); - const data = await response.json(); - if (!response.ok || data.status !== "success") { - throw new Error(data.error || "Failed to generate segments"); - } toast.success("Segments generated successfully!"); if (onSuccess) onSuccess(); } catch (error) { diff --git a/lib/artists/createArtistSegments.ts b/lib/artists/createArtistSegments.ts new file mode 100644 index 000000000..5f741a9f8 --- /dev/null +++ b/lib/artists/createArtistSegments.ts @@ -0,0 +1,39 @@ +import { getClientApiBaseUrl } from "@/lib/api/getClientApiBaseUrl"; + +interface CreateArtistSegmentsResponse { + status: "success" | "error"; + segments_created?: number; + message?: string; + error?: string; +} + +/** + * Creates segments for an artist via the dedicated API. + * + * @param accessToken - Privy access token for Bearer auth + * @param artistId - Artist account ID (path-encoded) + * @param prompt - Segmentation prompt + */ +export async function createArtistSegments( + accessToken: string, + artistId: string, + prompt: string, +): Promise { + const response = await fetch( + `${getClientApiBaseUrl()}/api/artists/${artistId}/segments`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${accessToken}`, + }, + body: JSON.stringify({ prompt }), + }, + ); + + const data: CreateArtistSegmentsResponse = await response.json(); + + if (!response.ok || data.status !== "success") { + throw new Error(data.error || "Failed to generate segments"); + } +}