- Added user tracks display with grid layout and pagination - Added user playlists display with grid layout and pagination - Added stats section showing tracks, playlists, and followers count - Implemented tabs for switching between tracks and playlists - Enhanced FollowButton with API integration (follow/unfollow) - Added follow/unfollow API functions in profileService - Added followers/following API functions (getFollowers, getFollowing) - Added View All links for tracks and playlists when count > 12 - Improved profile layout with better organization - Added empty states for tracks and playlists sections
89 lines
2.5 KiB
TypeScript
89 lines
2.5 KiB
TypeScript
import { useState } from 'react';
|
|
import { useQueryClient } from '@tanstack/react-query';
|
|
import { Button } from '@/components/ui/button';
|
|
import { UserPlus, UserCheck, Loader2 } from 'lucide-react';
|
|
import { followUser, unfollowUser } from '../services/profileService';
|
|
import { useToast } from '@/hooks/useToast';
|
|
import { useAuthStore } from '@/stores/auth';
|
|
|
|
// FE-PAGE-010: Complete User Profile page implementation - Follow Button
|
|
|
|
interface FollowButtonProps {
|
|
userId: string;
|
|
initialFollowing?: boolean;
|
|
initialFollowerCount?: number;
|
|
onFollowChange?: (isFollowing: boolean) => void;
|
|
}
|
|
|
|
export function FollowButton({
|
|
userId,
|
|
initialFollowing = false,
|
|
initialFollowerCount = 0,
|
|
onFollowChange,
|
|
}: FollowButtonProps) {
|
|
const { user } = useAuthStore();
|
|
const toast = useToast();
|
|
const queryClient = useQueryClient();
|
|
const [following, setFollowing] = useState(initialFollowing);
|
|
const [followerCount, setFollowerCount] = useState(initialFollowerCount);
|
|
const [isUpdating, setIsUpdating] = useState(false);
|
|
|
|
// Don't show follow button if viewing own profile
|
|
if (user?.id === userId) {
|
|
return null;
|
|
}
|
|
|
|
const handleClick = async () => {
|
|
if (isUpdating || !user) return;
|
|
|
|
setIsUpdating(true);
|
|
const newFollowing = !following;
|
|
|
|
try {
|
|
if (newFollowing) {
|
|
await followUser(userId);
|
|
toast.success('Now following user');
|
|
} else {
|
|
await unfollowUser(userId);
|
|
toast.success('Unfollowed user');
|
|
}
|
|
setFollowing(newFollowing);
|
|
setFollowerCount((prev) => (newFollowing ? prev + 1 : prev - 1));
|
|
onFollowChange?.(newFollowing);
|
|
// Invalidate profile query to refresh follower count
|
|
queryClient.invalidateQueries({ queryKey: ['userProfile'] });
|
|
} catch (error: any) {
|
|
const errorMessage =
|
|
error.response?.data?.error?.message ||
|
|
error.response?.data?.message ||
|
|
error.message ||
|
|
'Failed to toggle follow';
|
|
toast.error(errorMessage);
|
|
} finally {
|
|
setIsUpdating(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Button
|
|
onClick={handleClick}
|
|
disabled={isUpdating}
|
|
variant={following ? 'outline' : 'default'}
|
|
className="min-w-[100px]"
|
|
>
|
|
{isUpdating ? (
|
|
<Loader2 className="h-4 w-4 animate-spin mr-2" />
|
|
) : following ? (
|
|
<>
|
|
<UserCheck className="h-4 w-4 mr-2" />
|
|
Following
|
|
</>
|
|
) : (
|
|
<>
|
|
<UserPlus className="h-4 w-4 mr-2" />
|
|
Follow
|
|
</>
|
|
)}
|
|
</Button>
|
|
);
|
|
}
|