Update package dependencies, enhance README for clarity, and implement new features in the admin panel and script detail pages. Added support for collections, improved script submission previews, and refactored comment handling in the script detail view.
This commit is contained in:
57
src/hooks/useAnalytics.ts
Normal file
57
src/hooks/useAnalytics.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import { useQuery, useMutation } from '@tanstack/react-query';
|
||||
import * as analyticsApi from '@/lib/api/analytics';
|
||||
|
||||
// Query keys
|
||||
export const analyticsKeys = {
|
||||
all: ['analytics'] as const,
|
||||
script: (scriptId: string) => [...analyticsKeys.all, 'script', scriptId] as const,
|
||||
platform: (days: number) => [...analyticsKeys.all, 'platform', days] as const,
|
||||
user: (userId: string, days: number) => [...analyticsKeys.all, 'user', userId, days] as const,
|
||||
events: (filters: analyticsApi.AnalyticsFilters) => [...analyticsKeys.all, 'events', filters] as const,
|
||||
};
|
||||
|
||||
// Track event mutation
|
||||
export function useTrackEvent() {
|
||||
return useMutation({
|
||||
mutationFn: analyticsApi.trackEvent,
|
||||
// Don't show success/error messages for event tracking
|
||||
});
|
||||
}
|
||||
|
||||
// Get analytics events
|
||||
export function useAnalyticsEvents(filters: analyticsApi.AnalyticsFilters = {}) {
|
||||
return useQuery({
|
||||
queryKey: analyticsKeys.events(filters),
|
||||
queryFn: () => analyticsApi.getAnalyticsEvents(filters),
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
});
|
||||
}
|
||||
|
||||
// Get script analytics
|
||||
export function useScriptAnalytics(scriptId: string, days: number = 30) {
|
||||
return useQuery({
|
||||
queryKey: analyticsKeys.script(scriptId),
|
||||
queryFn: () => analyticsApi.getScriptAnalytics(scriptId, days),
|
||||
enabled: !!scriptId,
|
||||
staleTime: 10 * 60 * 1000, // 10 minutes
|
||||
});
|
||||
}
|
||||
|
||||
// Get platform analytics (admin only)
|
||||
export function usePlatformAnalytics(days: number = 30) {
|
||||
return useQuery({
|
||||
queryKey: analyticsKeys.platform(days),
|
||||
queryFn: () => analyticsApi.getPlatformAnalytics(days),
|
||||
staleTime: 15 * 60 * 1000, // 15 minutes
|
||||
});
|
||||
}
|
||||
|
||||
// Get user analytics
|
||||
export function useUserAnalytics(userId: string, days: number = 30) {
|
||||
return useQuery({
|
||||
queryKey: analyticsKeys.user(userId, days),
|
||||
queryFn: () => analyticsApi.getUserAnalytics(userId, days),
|
||||
enabled: !!userId,
|
||||
staleTime: 10 * 60 * 1000,
|
||||
});
|
||||
}
|
94
src/hooks/useAuth.ts
Normal file
94
src/hooks/useAuth.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import * as authApi from '@/lib/api/auth';
|
||||
// Note: This would create circular dependency, import useAuth from context directly where needed
|
||||
import { showSuccess, showError } from '@/utils/toast';
|
||||
|
||||
// Login mutation
|
||||
export function useLogin() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: authApi.login,
|
||||
onSuccess: (data) => {
|
||||
// Store token in localStorage
|
||||
localStorage.setItem('scriptshare-auth-token', data.token);
|
||||
localStorage.setItem('scriptshare-user-data', JSON.stringify(data.user));
|
||||
|
||||
// Update auth context
|
||||
setUser(data.user as any);
|
||||
|
||||
showSuccess('Login successful!');
|
||||
navigate('/dashboard');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Login failed');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Register mutation
|
||||
export function useRegister() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: authApi.register,
|
||||
onSuccess: (data) => {
|
||||
// Store token in localStorage
|
||||
localStorage.setItem('scriptshare-auth-token', data.token);
|
||||
localStorage.setItem('scriptshare-user-data', JSON.stringify(data.user));
|
||||
|
||||
// Update auth context
|
||||
setUser(data.user as any);
|
||||
|
||||
showSuccess('Registration successful!');
|
||||
navigate('/dashboard');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Registration failed');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Logout mutation
|
||||
export function useLogout() {
|
||||
const navigate = useNavigate();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async () => {
|
||||
// Clear local storage
|
||||
localStorage.removeItem('scriptshare-auth-token');
|
||||
localStorage.removeItem('scriptshare-user-data');
|
||||
|
||||
// Auth context will be updated by the context provider
|
||||
// In a real app, you would update the auth context here
|
||||
|
||||
// Clear query cache
|
||||
queryClient.clear();
|
||||
|
||||
return { success: true };
|
||||
},
|
||||
onSuccess: () => {
|
||||
showSuccess('Logged out successfully');
|
||||
navigate('/');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Change password mutation
|
||||
export function useChangePassword() {
|
||||
return useMutation({
|
||||
mutationFn: ({ userId, currentPassword, newPassword }: {
|
||||
userId: string;
|
||||
currentPassword: string;
|
||||
newPassword: string;
|
||||
}) => authApi.changePassword(userId, currentPassword, newPassword),
|
||||
onSuccess: () => {
|
||||
showSuccess('Password changed successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to change password');
|
||||
},
|
||||
});
|
||||
}
|
149
src/hooks/useCollections.ts
Normal file
149
src/hooks/useCollections.ts
Normal file
@ -0,0 +1,149 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import * as collectionsApi from '@/lib/api/collections';
|
||||
import { showSuccess, showError } from '@/utils/toast';
|
||||
|
||||
// Query keys
|
||||
export const collectionKeys = {
|
||||
all: ['collections'] as const,
|
||||
lists: () => [...collectionKeys.all, 'list'] as const,
|
||||
details: () => [...collectionKeys.all, 'detail'] as const,
|
||||
detail: (id: string) => [...collectionKeys.details(), id] as const,
|
||||
user: (userId: string) => [...collectionKeys.all, 'user', userId] as const,
|
||||
public: () => [...collectionKeys.all, 'public'] as const,
|
||||
};
|
||||
|
||||
// Get collection by ID
|
||||
export function useCollection(id: string) {
|
||||
return useQuery({
|
||||
queryKey: collectionKeys.detail(id),
|
||||
queryFn: () => collectionsApi.getCollectionById(id),
|
||||
enabled: !!id,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
// Get user collections
|
||||
export function useUserCollections(userId: string) {
|
||||
return useQuery({
|
||||
queryKey: collectionKeys.user(userId),
|
||||
queryFn: () => collectionsApi.getUserCollections(userId),
|
||||
enabled: !!userId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
// Get public collections
|
||||
export function usePublicCollections(limit?: number, offset?: number) {
|
||||
return useQuery({
|
||||
queryKey: [...collectionKeys.public(), limit, offset],
|
||||
queryFn: () => collectionsApi.getPublicCollections(limit, offset),
|
||||
staleTime: 10 * 60 * 1000, // 10 minutes
|
||||
});
|
||||
}
|
||||
|
||||
// Create collection mutation
|
||||
export function useCreateCollection() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: collectionsApi.createCollection,
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({ queryKey: collectionKeys.user(data.authorId) });
|
||||
queryClient.invalidateQueries({ queryKey: collectionKeys.public() });
|
||||
showSuccess('Collection created successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to create collection');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Update collection mutation
|
||||
export function useUpdateCollection() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ id, data, userId }: {
|
||||
id: string;
|
||||
data: collectionsApi.UpdateCollectionData;
|
||||
userId: string
|
||||
}) => collectionsApi.updateCollection(id, data, userId),
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({ queryKey: collectionKeys.detail(data.id) });
|
||||
queryClient.invalidateQueries({ queryKey: collectionKeys.user(data.authorId) });
|
||||
queryClient.invalidateQueries({ queryKey: collectionKeys.public() });
|
||||
showSuccess('Collection updated successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to update collection');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Delete collection mutation
|
||||
export function useDeleteCollection() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ id, userId }: { id: string; userId: string }) =>
|
||||
collectionsApi.deleteCollection(id, userId),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: collectionKeys.lists() });
|
||||
queryClient.removeQueries({ queryKey: collectionKeys.detail(variables.id) });
|
||||
showSuccess('Collection deleted successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to delete collection');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Add script to collection mutation
|
||||
export function useAddScriptToCollection() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ collectionId, scriptId, userId }: {
|
||||
collectionId: string;
|
||||
scriptId: string;
|
||||
userId: string
|
||||
}) => collectionsApi.addScriptToCollection(collectionId, scriptId, userId),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: collectionKeys.detail(variables.collectionId) });
|
||||
showSuccess('Script added to collection!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to add script to collection');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Remove script from collection mutation
|
||||
export function useRemoveScriptFromCollection() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ collectionId, scriptId, userId }: {
|
||||
collectionId: string;
|
||||
scriptId: string;
|
||||
userId: string
|
||||
}) => collectionsApi.removeScriptFromCollection(collectionId, scriptId, userId),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: collectionKeys.detail(variables.collectionId) });
|
||||
showSuccess('Script removed from collection!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to remove script from collection');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Check if script is in collection
|
||||
export function useIsScriptInCollection(collectionId: string, scriptId: string) {
|
||||
return useQuery({
|
||||
queryKey: [...collectionKeys.all, 'check', collectionId, scriptId],
|
||||
queryFn: () => collectionsApi.isScriptInCollection(collectionId, scriptId),
|
||||
enabled: !!collectionId && !!scriptId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
88
src/hooks/useRatings.ts
Normal file
88
src/hooks/useRatings.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import * as ratingsApi from '@/lib/api/ratings';
|
||||
import { showSuccess, showError } from '@/utils/toast';
|
||||
|
||||
// Query keys
|
||||
export const ratingKeys = {
|
||||
all: ['ratings'] as const,
|
||||
script: (scriptId: string) => [...ratingKeys.all, 'script', scriptId] as const,
|
||||
userRating: (scriptId: string, userId: string) => [...ratingKeys.all, 'user', scriptId, userId] as const,
|
||||
stats: (scriptId: string) => [...ratingKeys.all, 'stats', scriptId] as const,
|
||||
};
|
||||
|
||||
// Get user's rating for a script
|
||||
export function useUserRating(scriptId: string, userId?: string) {
|
||||
return useQuery({
|
||||
queryKey: ratingKeys.userRating(scriptId, userId || ''),
|
||||
queryFn: () => ratingsApi.getUserRating(scriptId, userId!),
|
||||
enabled: !!scriptId && !!userId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
// Get all ratings for a script
|
||||
export function useScriptRatings(scriptId: string) {
|
||||
return useQuery({
|
||||
queryKey: ratingKeys.script(scriptId),
|
||||
queryFn: () => ratingsApi.getScriptRatings(scriptId),
|
||||
enabled: !!scriptId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
// Get rating statistics for a script
|
||||
export function useScriptRatingStats(scriptId: string) {
|
||||
return useQuery({
|
||||
queryKey: ratingKeys.stats(scriptId),
|
||||
queryFn: () => ratingsApi.getScriptRatingStats(scriptId),
|
||||
enabled: !!scriptId,
|
||||
staleTime: 10 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
// Rate script mutation
|
||||
export function useRateScript() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ratingsApi.rateScript,
|
||||
onSuccess: (_, variables) => {
|
||||
// Invalidate related queries
|
||||
queryClient.invalidateQueries({ queryKey: ratingKeys.script(variables.scriptId) });
|
||||
queryClient.invalidateQueries({ queryKey: ratingKeys.userRating(variables.scriptId, variables.userId) });
|
||||
queryClient.invalidateQueries({ queryKey: ratingKeys.stats(variables.scriptId) });
|
||||
|
||||
// Also invalidate script details to update average rating
|
||||
queryClient.invalidateQueries({ queryKey: ['scripts', 'detail', variables.scriptId] });
|
||||
|
||||
showSuccess('Rating submitted successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to submit rating');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Delete rating mutation
|
||||
export function useDeleteRating() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ scriptId, userId }: { scriptId: string; userId: string }) =>
|
||||
ratingsApi.deleteRating(scriptId, userId),
|
||||
onSuccess: (_, variables) => {
|
||||
// Invalidate related queries
|
||||
queryClient.invalidateQueries({ queryKey: ratingKeys.script(variables.scriptId) });
|
||||
queryClient.invalidateQueries({ queryKey: ratingKeys.userRating(variables.scriptId, variables.userId) });
|
||||
queryClient.invalidateQueries({ queryKey: ratingKeys.stats(variables.scriptId) });
|
||||
|
||||
// Also invalidate script details to update average rating
|
||||
queryClient.invalidateQueries({ queryKey: ['scripts', 'detail', variables.scriptId] });
|
||||
|
||||
showSuccess('Rating removed successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to remove rating');
|
||||
},
|
||||
});
|
||||
}
|
139
src/hooks/useScripts.ts
Normal file
139
src/hooks/useScripts.ts
Normal file
@ -0,0 +1,139 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import * as scriptsApi from '@/lib/api/scripts';
|
||||
import { showSuccess, showError } from '@/utils/toast';
|
||||
|
||||
// Query keys
|
||||
export const scriptKeys = {
|
||||
all: ['scripts'] as const,
|
||||
lists: () => [...scriptKeys.all, 'list'] as const,
|
||||
list: (filters: scriptsApi.ScriptFilters) => [...scriptKeys.lists(), filters] as const,
|
||||
details: () => [...scriptKeys.all, 'detail'] as const,
|
||||
detail: (id: string) => [...scriptKeys.details(), id] as const,
|
||||
popular: () => [...scriptKeys.all, 'popular'] as const,
|
||||
recent: () => [...scriptKeys.all, 'recent'] as const,
|
||||
};
|
||||
|
||||
// Get scripts with filters
|
||||
export function useScripts(filters: scriptsApi.ScriptFilters = {}) {
|
||||
return useQuery({
|
||||
queryKey: scriptKeys.list(filters),
|
||||
queryFn: () => scriptsApi.getScripts(filters),
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
});
|
||||
}
|
||||
|
||||
// Get script by ID
|
||||
export function useScript(id: string) {
|
||||
return useQuery({
|
||||
queryKey: scriptKeys.detail(id),
|
||||
queryFn: () => scriptsApi.getScriptById(id),
|
||||
enabled: !!id,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
// Get popular scripts
|
||||
export function usePopularScripts(limit?: number) {
|
||||
return useQuery({
|
||||
queryKey: [...scriptKeys.popular(), limit],
|
||||
queryFn: () => scriptsApi.getPopularScripts(limit),
|
||||
staleTime: 10 * 60 * 1000, // 10 minutes
|
||||
});
|
||||
}
|
||||
|
||||
// Get recent scripts
|
||||
export function useRecentScripts(limit?: number) {
|
||||
return useQuery({
|
||||
queryKey: [...scriptKeys.recent(), limit],
|
||||
queryFn: () => scriptsApi.getRecentScripts(limit),
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
// Create script mutation
|
||||
export function useCreateScript() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: scriptsApi.createScript,
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({ queryKey: scriptKeys.lists() });
|
||||
showSuccess('Script created successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to create script');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Update script mutation
|
||||
export function useUpdateScript() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ id, data, userId }: { id: string; data: scriptsApi.UpdateScriptData; userId: string }) =>
|
||||
scriptsApi.updateScript(id, data, userId),
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({ queryKey: scriptKeys.detail(data.id) });
|
||||
queryClient.invalidateQueries({ queryKey: scriptKeys.lists() });
|
||||
showSuccess('Script updated successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to update script');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Delete script mutation
|
||||
export function useDeleteScript() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ id, userId }: { id: string; userId: string }) =>
|
||||
scriptsApi.deleteScript(id, userId),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: scriptKeys.lists() });
|
||||
queryClient.removeQueries({ queryKey: scriptKeys.detail(variables.id) });
|
||||
showSuccess('Script deleted successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to delete script');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Moderate script mutation (admin only)
|
||||
export function useModerateScript() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ id, isApproved, moderatorId }: { id: string; isApproved: boolean; moderatorId: string }) =>
|
||||
scriptsApi.moderateScript(id, isApproved, moderatorId),
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({ queryKey: scriptKeys.detail(data.id) });
|
||||
queryClient.invalidateQueries({ queryKey: scriptKeys.lists() });
|
||||
showSuccess(`Script ${data.isApproved ? 'approved' : 'rejected'} successfully!`);
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to moderate script');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Track view mutation
|
||||
export function useTrackView() {
|
||||
return useMutation({
|
||||
mutationFn: scriptsApi.incrementViewCount,
|
||||
// Don't show success/error messages for view tracking
|
||||
});
|
||||
}
|
||||
|
||||
// Track download mutation
|
||||
export function useTrackDownload() {
|
||||
return useMutation({
|
||||
mutationFn: scriptsApi.incrementDownloadCount,
|
||||
onSuccess: () => {
|
||||
showSuccess('Download started!');
|
||||
},
|
||||
});
|
||||
}
|
95
src/hooks/useUsers.ts
Normal file
95
src/hooks/useUsers.ts
Normal file
@ -0,0 +1,95 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import * as usersApi from '@/lib/api/users';
|
||||
import { showSuccess, showError } from '@/utils/toast';
|
||||
|
||||
// Query keys
|
||||
export const userKeys = {
|
||||
all: ['users'] as const,
|
||||
lists: () => [...userKeys.all, 'list'] as const,
|
||||
details: () => [...userKeys.all, 'detail'] as const,
|
||||
detail: (id: string) => [...userKeys.details(), id] as const,
|
||||
search: (query: string) => [...userKeys.all, 'search', query] as const,
|
||||
};
|
||||
|
||||
// Get user by ID
|
||||
export function useUser(id: string) {
|
||||
return useQuery({
|
||||
queryKey: userKeys.detail(id),
|
||||
queryFn: () => usersApi.getUserById(id),
|
||||
enabled: !!id,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
// Get all users (admin only)
|
||||
export function useUsers(limit?: number, offset?: number) {
|
||||
return useQuery({
|
||||
queryKey: [...userKeys.lists(), limit, offset],
|
||||
queryFn: () => usersApi.getAllUsers(limit, offset),
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
// Search users
|
||||
export function useSearchUsers(query: string, limit?: number) {
|
||||
return useQuery({
|
||||
queryKey: userKeys.search(query),
|
||||
queryFn: () => usersApi.searchUsers(query, limit),
|
||||
enabled: !!query && query.length >= 2,
|
||||
staleTime: 2 * 60 * 1000, // 2 minutes for search results
|
||||
});
|
||||
}
|
||||
|
||||
// Create user mutation
|
||||
export function useCreateUser() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: usersApi.createUser,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: userKeys.lists() });
|
||||
showSuccess('User created successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to create user');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Update user mutation
|
||||
export function useUpdateUser() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ id, data }: { id: string; data: usersApi.UpdateUserData }) =>
|
||||
usersApi.updateUser(id, data),
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({ queryKey: userKeys.detail(data.id) });
|
||||
queryClient.invalidateQueries({ queryKey: userKeys.lists() });
|
||||
showSuccess('User updated successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to update user');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Update user permissions mutation (admin only)
|
||||
export function useUpdateUserPermissions() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ id, permissions }: {
|
||||
id: string;
|
||||
permissions: { isAdmin?: boolean; isModerator?: boolean }
|
||||
}) => usersApi.updateUserPermissions(id, permissions),
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({ queryKey: userKeys.detail(data.id) });
|
||||
queryClient.invalidateQueries({ queryKey: userKeys.lists() });
|
||||
showSuccess('User permissions updated successfully!');
|
||||
},
|
||||
onError: (error: any) => {
|
||||
showError(error.message || 'Failed to update user permissions');
|
||||
},
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user