mobileapp / src /hooks /useFriends.ts
Antaram Dev Bot
feat: complete ANTARAM.ORG ride-sharing app frontend
5c876be
import { useState, useEffect, useCallback } from 'react';
import { eq, desc, and } from 'drizzle-orm';
import { useDatabase } from './useDatabase';
import { friends } from '../db/schema';
// ─── Types ─────────────────────────────────────────────────────────────────────
type FriendStatus = 'pending' | 'accepted' | 'blocked';
interface FriendData {
id: string;
userId: string;
friendId: string;
friendFullName: string;
friendAvatar: string | null;
friendPhone: string | null;
status: FriendStatus;
createdAt: string | null;
}
interface NewFriend {
id: string;
userId: string;
friendId: string;
friendFullName: string;
friendAvatar?: string;
friendPhone?: string;
}
interface UseFriendsReturn {
friends: FriendData[];
pendingRequests: FriendData[];
loading: boolean;
acceptFriend: (friendId: string) => Promise<void>;
declineFriend: (friendId: string) => Promise<void>;
addFriend: (data: NewFriend) => Promise<FriendData | null>;
blockFriend: (friendId: string) => Promise<void>;
refresh: () => Promise<void>;
}
// ─── Hook ──────────────────────────────────────────────────────────────────────
export function useFriends(userId?: string): UseFriendsReturn {
const { db } = useDatabase();
const [friendsList, setFriendsList] = useState<FriendData[]>([]);
const [loading, setLoading] = useState(true);
// ── Load friends ─────────────────────────────────────────────────────────────
const loadFriends = useCallback(async () => {
try {
setLoading(true);
let results;
if (userId) {
results = await db
.select()
.from(friends)
.where(eq(friends.userId, userId))
.orderBy(desc(friends.createdAt))
.all();
} else {
results = await db
.select()
.from(friends)
.orderBy(desc(friends.createdAt))
.all();
}
setFriendsList(results as FriendData[]);
} catch (error) {
console.error('[useFriends] Failed to load friends:', error);
setFriendsList([]);
} finally {
setLoading(false);
}
}, [db, userId]);
useEffect(() => {
loadFriends();
}, [loadFriends]);
// ── Derived state ────────────────────────────────────────────────────────────
const pendingRequests = friendsList.filter(
(f) => f.status === 'pending',
);
// ── Accept friend request ────────────────────────────────────────────────────
const acceptFriend = useCallback(
async (friendId: string) => {
try {
await db
.update(friends)
.set({ status: 'accepted' })
.where(and(eq(friends.friendId, friendId), eq(friends.status, 'pending')))
.run();
await loadFriends();
} catch (error) {
console.error('[useFriends] Failed to accept friend:', error);
}
},
[db, loadFriends],
);
// ── Decline friend request ───────────────────────────────────────────────────
const declineFriend = useCallback(
async (friendId: string) => {
try {
// Delete the pending request
await db
.delete(friends)
.where(and(eq(friends.friendId, friendId), eq(friends.status, 'pending')))
.run();
await loadFriends();
} catch (error) {
console.error('[useFriends] Failed to decline friend:', error);
}
},
[db, loadFriends],
);
// ── Add friend (send request) ────────────────────────────────────────────────
const addFriend = useCallback(
async (data: NewFriend): Promise<FriendData | null> => {
try {
await db.insert(friends).values({
id: data.id,
userId: data.userId,
friendId: data.friendId,
friendFullName: data.friendFullName,
friendAvatar: data.friendAvatar ?? null,
friendPhone: data.friendPhone ?? null,
status: 'pending',
}).run();
await loadFriends();
return friendsList.find((f) => f.friendId === data.friendId) ?? null;
} catch (error) {
console.error('[useFriends] Failed to add friend:', error);
return null;
}
},
[db, loadFriends, friendsList],
);
// ── Block friend ─────────────────────────────────────────────────────────────
const blockFriend = useCallback(
async (friendId: string) => {
try {
await db
.update(friends)
.set({ status: 'blocked' })
.where(eq(friends.friendId, friendId))
.run();
await loadFriends();
} catch (error) {
console.error('[useFriends] Failed to block friend:', error);
}
},
[db, loadFriends],
);
return {
friends: friendsList,
pendingRequests,
loading,
acceptFriend,
declineFriend,
addFriend,
blockFriend,
refresh: loadFriends,
};
}