veza/apps/web/src/features/profile/components/FollowButton.tsx
senke eeaf8de57e [FE-PAGE-010] fe-page: Complete User Profile page (public)
- 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
2025-12-24 13:09:30 +01:00

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>
);
}