import { useEffect, useState } from 'react'; import { useCreateUserMutation, useInviteUserMutation } from './queries'; import { IUserSchema, IUserFilterOptionsSchema } from '@/src/entities/models/users/users.model'; import { toast } from 'sonner'; import { set } from 'date-fns'; import { CreateUserSchema, defaulICreateUserSchemaValues, ICreateUserSchema } from '@/src/entities/models/users/create-user.model'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { defaulIInviteUserSchemaValues, IInviteUserSchema, InviteUserSchema } from '@/src/entities/models/users/invite-user.model'; export const useAddUserDialogHandler = ({ onUserAdded, onOpenChange }: { onUserAdded: () => void; onOpenChange: (open: boolean) => void; }) => { const { createUser, isPending } = useCreateUserMutation(); const { register, handleSubmit, reset, formState: { errors: errors }, setError, getValues, clearErrors, watch, } = useForm({ resolver: zodResolver(CreateUserSchema), defaultValues: { email: "", password: "", email_confirm: true, } }); const emailConfirm = watch("email_confirm"); const onSubmit = handleSubmit(async (data) => { await createUser(data, { onSuccess: () => { toast.success("User created successfully."); onUserAdded(); onOpenChange(false); reset(); }, onError: (error) => { reset(); toast.error(error.message); }, }); }); const handleOpenChange = (open: boolean) => { if (!open) { reset(); } onOpenChange(open); }; return { register, handleSubmit: onSubmit, reset, errors, isPending, getValues, clearErrors, emailConfirm, handleOpenChange, }; } export const useInviteUserHandler = ({ onUserInvited, onOpenChange }: { onUserInvited: () => void; onOpenChange: (open: boolean) => void; }) => { const { inviteUser, isPending } = useInviteUserMutation(); const { register, handleSubmit, reset, formState: { errors: errors }, setError, getValues, clearErrors, watch, } = useForm({ resolver: zodResolver(InviteUserSchema), defaultValues: defaulIInviteUserSchemaValues }) const onSubmit = handleSubmit(async (data) => { await inviteUser(data, { onSuccess: () => { toast.success("Invitation sent"); onUserInvited(); onOpenChange(false); reset(); }, onError: () => { reset(); toast.error("Failed to send invitation"); }, }); }); const handleOpenChange = (open: boolean) => { if (!open) { reset(); } onOpenChange(open); }; return { register, handleSubmit: onSubmit, handleOpenChange, reset, getValues, clearErrors, watch, errors, isPending, }; } export const useUserManagementHandlers = (refetch: () => void) => { const [searchQuery, setSearchQuery] = useState("") const [detailUser, setDetailUser] = useState(null) const [updateUser, setUpdateUser] = useState(null) const [isSheetOpen, setIsSheetOpen] = useState(false) const [isUpdateOpen, setIsUpdateOpen] = useState(false) const [isAddUserOpen, setIsAddUserOpen] = useState(false) const [isInviteUserOpen, setIsInviteUserOpen] = useState(false) // Filter states const [filters, setFilters] = useState({ email: "", phone: "", lastSignIn: "", createdAt: "", status: [], }) // Handle opening the detail sheet const handleUserClick = (user: IUserSchema) => { setDetailUser(user) setIsSheetOpen(true) } // Handle opening the update sheet const handleUserUpdate = (user: IUserSchema) => { setUpdateUser(user) setIsUpdateOpen(true) } // Close detail sheet when update sheet opens useEffect(() => { if (isUpdateOpen) { setIsSheetOpen(false) } }, [isUpdateOpen]) // Reset detail user when sheet closes useEffect(() => { if (!isSheetOpen) { // Use a small delay to prevent flickering if another sheet is opening const timer = setTimeout(() => { if (!isSheetOpen && !isUpdateOpen) { setDetailUser(null) } }, 300) return () => clearTimeout(timer) } }, [isSheetOpen, isUpdateOpen]) // Reset update user when update sheet closes useEffect(() => { if (!isUpdateOpen) { // Use a small delay to prevent flickering if another sheet is opening const timer = setTimeout(() => { if (!isUpdateOpen) { setUpdateUser(null) } }, 300) return () => clearTimeout(timer) } }, [isUpdateOpen]) const clearFilters = () => { setFilters({ email: "", phone: "", lastSignIn: "", createdAt: "", status: [], }) } const getActiveFilterCount = () => { return Object.values(filters).filter( (value) => (typeof value === "string" && value !== "") || (Array.isArray(value) && value.length > 0), ).length } return { searchQuery, setSearchQuery, detailUser, updateUser, isSheetOpen, setIsSheetOpen, isUpdateOpen, setIsUpdateOpen, isAddUserOpen, setIsAddUserOpen, isInviteUserOpen, setIsInviteUserOpen, filters, setFilters, handleUserClick, handleUserUpdate, clearFilters, getActiveFilterCount, } } export const filterUsers = (users: IUserSchema[], searchQuery: string, filters: IUserFilterOptionsSchema): IUserSchema[] => { return users.filter((user) => { // Global search if (searchQuery) { const query = searchQuery.toLowerCase() const matchesSearch = user.email?.toLowerCase().includes(query) || user.phone?.toLowerCase().includes(query) || user.id.toLowerCase().includes(query) if (!matchesSearch) return false } // Email filter if (filters.email && !user.email?.toLowerCase().includes(filters.email.toLowerCase())) { return false } // Phone filter if (filters.phone && !user.phone?.toLowerCase().includes(filters.phone.toLowerCase())) { return false } // Last sign in filter if (filters.lastSignIn) { if (filters.lastSignIn === "never" && user.last_sign_in_at) { return false } else if (filters.lastSignIn === "today") { const today = new Date() today.setHours(0, 0, 0, 0) const signInDate = user.last_sign_in_at ? new Date(user.last_sign_in_at) : null if (!signInDate || signInDate < today) return false } else if (filters.lastSignIn === "week") { const weekAgo = new Date() weekAgo.setDate(weekAgo.getDate() - 7) const signInDate = user.last_sign_in_at ? new Date(user.last_sign_in_at) : null if (!signInDate || signInDate < weekAgo) return false } else if (filters.lastSignIn === "month") { const monthAgo = new Date() monthAgo.setMonth(monthAgo.getMonth() - 1) const signInDate = user.last_sign_in_at ? new Date(user.last_sign_in_at) : null if (!signInDate || signInDate < monthAgo) return false } } // Created at filter if (filters.createdAt) { if (filters.createdAt === "today") { const today = new Date() today.setHours(0, 0, 0, 0) const createdAt = user.created_at ? (user.created_at ? new Date(user.created_at) : new Date()) : new Date() if (createdAt < today) return false } else if (filters.createdAt === "week") { const weekAgo = new Date() weekAgo.setDate(weekAgo.getDate() - 7) const createdAt = user.created_at ? new Date(user.created_at) : new Date() if (createdAt < weekAgo) return false } else if (filters.createdAt === "month") { const monthAgo = new Date() monthAgo.setMonth(monthAgo.getMonth() - 1) const createdAt = user.created_at ? new Date(user.created_at) : new Date() if (createdAt < monthAgo) return false } } // Status filter if (filters.status.length > 0) { const userStatus = user.banned_until ? "banned" : !user.email_confirmed_at ? "unconfirmed" : "active" if (!filters.status.includes(userStatus)) { return false } } return true }) }