Enable users to manage video playlists and mark favorite content
Adds new user, playlist, and favorites management API endpoints and React components. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 50814a1e-92e4-4968-856f-7bc7eedf5e8f Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/50814a1e-92e4-4968-856f-7bc7eedf5e8f/hISDNbZ
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { apiRequest } from "@/lib/queryClient";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
|
||||
const CURRENT_USER_ID = "test-user-123"; // For demo purposes
|
||||
|
||||
export function useFavorites() {
|
||||
const queryClient = useQueryClient();
|
||||
const { toast } = useToast();
|
||||
|
||||
// Check if video is favorited
|
||||
const useIsFavorited = (videoId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["/api/favorites", CURRENT_USER_ID, videoId],
|
||||
queryFn: async () => {
|
||||
const response = await fetch(`/api/favorites/${CURRENT_USER_ID}/${videoId}`);
|
||||
if (!response.ok) throw new Error('Failed to check favorite status');
|
||||
return response.json();
|
||||
},
|
||||
enabled: !!videoId,
|
||||
});
|
||||
};
|
||||
|
||||
// Add to favorites
|
||||
const addToFavoritesMutation = useMutation({
|
||||
mutationFn: (videoId: string) =>
|
||||
apiRequest("/api/favorites", "POST", {
|
||||
userId: CURRENT_USER_ID,
|
||||
videoId,
|
||||
}),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["/api/favorites"] });
|
||||
toast({ title: "Added to favorites!" });
|
||||
},
|
||||
onError: (error: any) => {
|
||||
if (error.message?.includes("already in favorites")) {
|
||||
toast({ title: "Already in favorites", variant: "destructive" });
|
||||
} else {
|
||||
toast({ title: "Failed to add to favorites", variant: "destructive" });
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Remove from favorites
|
||||
const removeFromFavoritesMutation = useMutation({
|
||||
mutationFn: (videoId: string) =>
|
||||
apiRequest(`/api/favorites/${CURRENT_USER_ID}/${videoId}`, "DELETE"),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["/api/favorites"] });
|
||||
toast({ title: "Removed from favorites" });
|
||||
},
|
||||
onError: () => {
|
||||
toast({ title: "Failed to remove from favorites", variant: "destructive" });
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
useIsFavorited,
|
||||
addToFavorites: addToFavoritesMutation.mutate,
|
||||
removeFromFavorites: removeFromFavoritesMutation.mutate,
|
||||
isAddingToFavorites: addToFavoritesMutation.isPending,
|
||||
isRemovingFromFavorites: removeFromFavoritesMutation.isPending,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { apiRequest } from "@/lib/queryClient";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import type { Playlist, InsertPlaylist } from "@shared/schema";
|
||||
|
||||
const CURRENT_USER_ID = "test-user-123"; // For demo purposes
|
||||
|
||||
export function usePlaylists() {
|
||||
const queryClient = useQueryClient();
|
||||
const { toast } = useToast();
|
||||
|
||||
// Get user playlists
|
||||
const useUserPlaylists = () => {
|
||||
return useQuery({
|
||||
queryKey: ["/api/playlists", CURRENT_USER_ID],
|
||||
});
|
||||
};
|
||||
|
||||
// Get single playlist
|
||||
const usePlaylist = (playlistId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["/api/playlists", playlistId],
|
||||
enabled: !!playlistId,
|
||||
});
|
||||
};
|
||||
|
||||
// Get playlist videos
|
||||
const usePlaylistVideos = (playlistId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["/api/playlists", playlistId, "videos"],
|
||||
enabled: !!playlistId,
|
||||
});
|
||||
};
|
||||
|
||||
// Add video to playlist
|
||||
const addVideoToPlaylistMutation = useMutation({
|
||||
mutationFn: ({ playlistId, videoId }: { playlistId: string; videoId: string }) =>
|
||||
apiRequest(`/api/playlists/${playlistId}/videos`, "POST", {
|
||||
videoId,
|
||||
position: 0,
|
||||
}),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["/api/playlists"] });
|
||||
toast({ title: "Added to playlist!" });
|
||||
},
|
||||
onError: (error: any) => {
|
||||
if (error.message?.includes("already in playlist")) {
|
||||
toast({ title: "Video is already in this playlist", variant: "destructive" });
|
||||
} else {
|
||||
toast({ title: "Failed to add to playlist", variant: "destructive" });
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Remove video from playlist
|
||||
const removeVideoFromPlaylistMutation = useMutation({
|
||||
mutationFn: ({ playlistId, videoId }: { playlistId: string; videoId: string }) =>
|
||||
apiRequest(`/api/playlists/${playlistId}/videos/${videoId}`, "DELETE"),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["/api/playlists"] });
|
||||
toast({ title: "Removed from playlist" });
|
||||
},
|
||||
onError: () => {
|
||||
toast({ title: "Failed to remove from playlist", variant: "destructive" });
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
useUserPlaylists,
|
||||
usePlaylist,
|
||||
usePlaylistVideos,
|
||||
addVideoToPlaylist: addVideoToPlaylistMutation.mutate,
|
||||
removeVideoFromPlaylist: removeVideoFromPlaylistMutation.mutate,
|
||||
isAddingToPlaylist: addVideoToPlaylistMutation.isPending,
|
||||
isRemovingFromPlaylist: removeVideoFromPlaylistMutation.isPending,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user