Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 0 additions & 32 deletions app/api/artist/pin/route.ts

This file was deleted.

63 changes: 0 additions & 63 deletions app/api/artist/profile/route.ts

This file was deleted.

2 changes: 1 addition & 1 deletion components/VercelChat/tools/KnowledgeBaseSection.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { FileText, ExternalLink } from "lucide-react";
import Link from "next/link";
import { Knowledge } from "@/lib/supabase/artist/updateArtistProfile";
import { Knowledge } from "@/types/knowledge";

const KnowledgeBaseSection = ({ knowledges }: { knowledges: Knowledge[] }) => {
return (
Expand Down
2 changes: 1 addition & 1 deletion components/VercelChat/tools/UpdateArtistInfoSuccess.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect } from "react";
import ArtistHeroSection from "./ArtistHeroSection";
import KnowledgeBaseSection from "./KnowledgeBaseSection";
import { Knowledge } from "@/lib/supabase/artist/updateArtistProfile";
import { Knowledge } from "@/types/knowledge";
import { CheckCircle, FileText } from "lucide-react";
import { useArtistProvider } from "@/providers/ArtistProvider";
import { ArtistProfile } from "@/lib/supabase/artist/updateArtistProfile";
Expand Down
38 changes: 16 additions & 22 deletions hooks/useArtistPinToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,47 @@
import { useState } from "react";
import { usePrivy } from "@privy-io/react-auth";
import { useArtistProvider } from "@/providers/ArtistProvider";
import { useUserProvider } from "@/providers/UserProvder";
import saveArtist from "@/lib/saveArtist";
import { ArtistRecord } from "@/types/Artist";

export const useArtistPinToggle = (artist: ArtistRecord | null) => {
const { userData } = useUserProvider();
const { getArtists, setArtists } = useArtistProvider();
const { getAccessToken } = usePrivy();
const [isPinning, setIsPinning] = useState(false);

const handlePinToggle = async (e: React.MouseEvent) => {
e.stopPropagation();
if (!artist || !userData?.id || isPinning) return;

const newPinnedStatus = !artist.pinned;

// Optimistic update - immediately update the UI
const previousPinnedStatus = artist.pinned;

setArtists((prevArtists: ArtistRecord[]) =>
prevArtists.map((a: ArtistRecord) =>
a.account_id === artist.account_id ? { ...a, pinned: newPinnedStatus } : a
)
a.account_id === artist.account_id ? { ...a, pinned: newPinnedStatus } : a,
),
);

setIsPinning(true);

try {
const response = await fetch("/api/artist/pin", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
accountId: userData.id,
artistId: artist.account_id,
pinned: newPinnedStatus,
}),
});

if (!response.ok) {
throw new Error("Failed to toggle pin status");
const accessToken = await getAccessToken();
if (!accessToken) {
throw new Error("Missing access token");
}

// Refetch to ensure consistency with server
await saveArtist(accessToken, artist.account_id, { pinned: newPinnedStatus });

await getArtists();
} catch (error) {
console.error("Error toggling pin:", error);

// Rollback optimistic update on error

setArtists((prevArtists: ArtistRecord[]) =>
prevArtists.map((a: ArtistRecord) =>
a.account_id === artist.account_id ? { ...a, pinned: artist.pinned } : a
)
a.account_id === artist.account_id ? { ...a, pinned: previousPinnedStatus } : a,
),
);
} finally {
setIsPinning(false);
Expand Down
23 changes: 10 additions & 13 deletions hooks/useArtists.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useOrganization } from "@/providers/OrganizationProvider";
import { ArtistRecord } from "@/types/Artist";
import { useCallback, useEffect, useState } from "react";
import useArtistSetting from "./useArtistSetting";
import { SETTING_MODE } from "@/types/Setting";
import useArtistMode from "./useArtistMode";
import saveArtist from "@/lib/saveArtist";
import useInitialArtists from "./useInitialArtists";
Expand All @@ -15,7 +14,7 @@ import { sortArtistsWithPinnedFirst } from "@/lib/artists/sortArtistsWithPinnedF
const useArtists = () => {
const artistSetting = useArtistSetting();
const [isLoading, setIsLoading] = useState(true);
const { email, userData } = useUserProvider();
const { userData } = useUserProvider();
const { selectedOrgId } = useOrganization();
const { getAccessToken } = usePrivy();
const [artists, setArtists] = useState<ArtistRecord[]>([]);
Expand Down Expand Up @@ -117,8 +116,15 @@ const useArtists = () => {
overrideKnowledges?: Array<{ name: string; url: string; type: string }>,
) => {
setUpdating(true);
const saveMode = artistMode.settingMode;
try {
const accessToken = await getAccessToken();
const artistId = artistSetting.editableArtist?.account_id;

if (!accessToken || !artistId) {
setUpdating(false);
return null;
}

const profileUrls = {
TWITTER: artistSetting.twitter,
TIKTOK: artistSetting.tiktok,
Expand All @@ -129,25 +135,16 @@ const useArtists = () => {
FACEBOOK: artistSetting.facebook,
THREADS: artistSetting.threads,
};
const data = await saveArtist({
const data = await saveArtist(accessToken, artistId, {
name: artistSetting.name,
image: artistSetting.image,
profileUrls,
instruction: artistSetting.instruction,
label: artistSetting.label,
knowledges: overrideKnowledges ?? artistSetting.bases,
artistId:
saveMode === SETTING_MODE.CREATE
? ""
: artistSetting.editableArtist?.account_id,
email,
// Link new artist to selected org (only applies when creating)
organizationId: saveMode === SETTING_MODE.CREATE ? selectedOrgId : null,
});
await getArtists(data.artist?.account_id);
setUpdating(false);
if (artistMode.settingMode === SETTING_MODE.CREATE)
artistMode.setSettingMode(SETTING_MODE.UPDATE);
return data.artist;
} catch (error) {
console.error(error);
Expand Down
9 changes: 2 additions & 7 deletions lib/accounts/updateAccountProfile.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { getClientApiBaseUrl } from "@/lib/api/getClientApiBaseUrl";

type KnowledgeItem = {
name: string;
url: string;
type: string;
};
import type { Knowledge } from "@/types/knowledge";

type UpdateAccountProfileArgs = {
accountId: string;
Expand All @@ -16,7 +11,7 @@ type UpdateAccountProfileArgs = {
jobTitle?: string;
roleType?: string;
companyName?: string;
knowledges?: KnowledgeItem[];
knowledges?: Knowledge[];
};

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/files/getKnowledgeBaseText.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Knowledge } from "@/lib/supabase/artist/updateArtistProfile";
import type { Knowledge } from "@/types/knowledge";

/**
* Processes knowledge base files and extracts text content.
Expand Down
39 changes: 33 additions & 6 deletions lib/saveArtist.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,40 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const saveArtist = async (artist_data: any) => {
const response = await fetch("/api/artist/profile", {
method: "POST",
body: JSON.stringify(artist_data),
import { getClientApiBaseUrl } from "@/lib/api/getClientApiBaseUrl";
import type { ArtistRecord } from "@/types/Artist";
import type { Knowledge } from "@/types/knowledge";

interface SaveArtistPayload {
name?: string;
image?: string;
instruction?: string;
label?: string;
knowledges?: Knowledge[];
profileUrls?: Record<string, string>;
pinned?: boolean;
}

interface SaveArtistResponse {
artist?: ArtistRecord;
error?: string;
}

const saveArtist = async (
accessToken: string,
artistId: string,
artistData: SaveArtistPayload,
): Promise<SaveArtistResponse> => {
const response = await fetch(`${getClientApiBaseUrl()}/api/artists/${artistId}`, {
method: "PATCH",
body: JSON.stringify(artistData),
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
});
const data = await response.json();
const data: SaveArtistResponse = await response.json();

if (!response.ok || !data.artist) {
throw new Error(data.error || "Failed to save artist");
}

return data;
};
Expand Down
32 changes: 0 additions & 32 deletions lib/supabase/account_artist_ids/toggleArtistPin.ts

This file was deleted.

7 changes: 1 addition & 6 deletions lib/supabase/artist/updateArtistProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ import getAccountByEmail from "@/lib/supabase/accounts/getAccountByEmail";
import insertAccount from "@/lib/supabase/accounts/insertAccount";
import insertAccountArtistId from "@/lib/supabase/account_artist_ids/insertAccountArtistId";
import type { Tables } from "@/types/database.types";

export type Knowledge = {
url: string;
name: string;
type: string;
};
import type { Knowledge } from "@/types/knowledge";

export type ArtistProfile = Tables<"accounts"> & Tables<"account_info">;

Expand Down
9 changes: 3 additions & 6 deletions lib/supabase/getArtistKnowledge.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import supabase from "./serverClient";
import type { Knowledge } from "@/types/knowledge";

export interface KnowledgeBaseEntry {
url: string;
name: string;
type: string;
}
export type KnowledgeBaseEntry = Knowledge;

export async function getArtistKnowledge(artistId: string): Promise<KnowledgeBaseEntry[]> {
export async function getArtistKnowledge(artistId: string): Promise<Knowledge[]> {
const { data, error } = await supabase
.from("account_info")
.select("knowledges")
Expand Down
3 changes: 2 additions & 1 deletion types/Artist.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SOCIAL } from "./Agent";
import { FAN_TYPE } from "./fans";
import type { Knowledge } from "./knowledge";

export type Artist = {
name: string;
Expand All @@ -17,7 +18,7 @@ export type ArtistRecord = {
created_at?: string;
id?: string;
instruction?: string | null;
knowledges?: any;
knowledges?: Knowledge[] | null;
label?: string | null;
organization?: string | null;
pinned?: boolean;
Expand Down
Loading
Loading