Scrapboard.org client
1"use client";
2
3import {
4 createContext,
5 useContext,
6 useState,
7 useEffect,
8 ReactNode,
9} from "react";
10import { AppBskyActorDefs } from "@atproto/api";
11import { useAuth } from "./hooks/useAuth";
12
13type Profile = AppBskyActorDefs.ProfileViewDetailed;
14
15type ProfileContextType = {
16 profile: Profile | null;
17 loading: boolean;
18 error: Error | null;
19};
20
21const ProfileContext = createContext<ProfileContextType | null>(null);
22
23export function ProfileProvider({ children }: { children: ReactNode }) {
24 const { agent, loading: authLoading, session } = useAuth();
25 const [profile, setProfile] = useState<Profile | null>(null);
26 const [loading, setLoading] = useState(true);
27 const [error, setError] = useState<Error | null>(null);
28
29 useEffect(() => {
30 const fetchProfile = async () => {
31 if (!agent || authLoading || !session?.did)
32 return console.warn(
33 "No agent or session available",
34 !agent,
35 authLoading,
36 session?.did
37 );
38
39 setLoading(true);
40 setError(null);
41
42 try {
43 const res = await agent.getProfile({
44 actor: session!.did,
45 });
46 setProfile(res.data);
47 } catch (err) {
48 setError(
49 err instanceof Error ? err : new Error("Failed to fetch profile")
50 );
51 setProfile(null);
52 console.error("Error fetching profile:", err);
53 } finally {
54 setLoading(false);
55 }
56 };
57
58 fetchProfile();
59 }, [agent, authLoading, session]);
60
61 return (
62 <ProfileContext.Provider value={{ profile, loading, error }}>
63 {children}
64 </ProfileContext.Provider>
65 );
66}
67
68export function useProfile() {
69 const ctx = useContext(ProfileContext);
70 if (!ctx) throw new Error("useProfile must be used inside <ProfileProvider>");
71 return ctx;
72}