import { MouseEvent, useCallback, useEffect, useRef, useState } from 'react'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Dialog, DialogBody, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/components/ui/command'; import { ChevronDown } from 'lucide-react'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { useUserContext } from '../hooks'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { apiConfig } from '@/config/api.config'; import { Alert, KeenIcon, useDataGrid } from '@/components'; import { toast } from 'sonner'; import { useCallApi } from '@/hooks'; import { doSaveLogActivity } from '@/actions/GlobalActions'; import clsx from 'clsx'; import { CustomerProps, initialStateCreateUser, RoleListProps, validateFormCreateUser } from './Types'; const API_URL_CUSTOMER = apiConfig.service_customer; const API_URL = apiConfig.service_dashboard; type PasswordType = 'password' | 'retype_password'; const AddDialog = () => { const parentRef = useRef(null); const { showAddDialog, handleAddDialog } = useUserContext(); const { reload } = useDataGrid(); const { PostData, GetData } = useCallApi(); const [roles, setRoles] = useState([]); const [errors, setErrors] = useState>({}); const [formField, setFormField] = useState(initialStateCreateUser); const [showPassword, setShowPassword] = useState({ password: false, retype_password: false }); const [searchTerm, setSearchTerm] = useState(''); const [selectedCustomerName, setSelectedCustomerName] = useState(''); const [dropdownOpen, setDropdownOpen] = useState(false); const [isLoading, setIsLoading] = useState(false); const dropdownRef = useRef(null); const [messagePassword, setMessagePassword] = useState(true); const [open, setOpen] = useState(false); const [customers, setCustomers] = useState([]); const [isSubmitting, setIsSubmitting] = useState(false); const [passwordErrors, setPasswordErrors] = useState([]); const [notMatch, setNotMatch] = useState([]); const validatePassword = (password: string, confirmPassword: string) => { const errors: string[] = []; const notMatch: string[] = []; if (password) { if (password.length < 8) { errors.push('Password must be at least 8 characters long'); } if (!/[A-Z]/.test(password)) { errors.push('Password must contain at least one capital letter'); } if (!/[0-9]/.test(password)) { errors.push('Password must contain at least one number'); } if (!/[!@#$%^&*(),.?":{}|<>]/.test(password)) { errors.push('Password must contain at least one special character'); } if (password !== confirmPassword) { notMatch.push('Passwords do not match'); } } return { isValid: errors.length === 0, errors, notMatch }; }; const resetForm = () => { setFormField(initialStateCreateUser); setSelectedCustomerName(''); setSearchTerm(''); setErrors({}); }; /* actions */ const doCreateUser = useCallback( async (e: React.FormEvent) => { e.preventDefault(); setIsSubmitting(true); try { const response = await PostData(`${API_URL}/user/create`, formField); if (response?.status) { handleAddDialog(false); resetForm(); reload(); const createActivity = { module: 'Manage User', description: `Create New User => ${formField.username}`, action: 'C' }; doSaveLogActivity(createActivity); toast.success('Success Create User'); } else { toast.error(response?.message); } } catch (err) { toast.error('Something went wrong'); console.log(err); } finally { setIsSubmitting(false); } }, [formField] ); const fetchRoles = useCallback(async () => { const params = { limit: 100, page: 1, with_deleted: false, order_field: 'name', order_direction: 'ASC', filter: JSON.stringify({ status: 'Y' }) }; const response = await GetData(`${API_URL}/user_role/list`, params); if (response?.status) { const roleList = response.data?.list || []; setRoles(roleList); } else { setRoles(() => []); } }, []); const getCustomerList = async (sorting: any, filterValue: string) => { const filter: any = filterValue?.trim().length === 0 ? {} : { fullname: { like: `%${filterValue}%` } }; sorting = sorting.length == 0 ? [{ id: 'created_at', desc: false }] : sorting; const query: any = { limit: 100, page: 1, with_deleted: false, order_field: sorting[0].id, order_direction: sorting[0].desc ? 'DESC' : 'ASC' }; if (filter && Object.keys(filter).length > 0) { query.filter = JSON.stringify(filter); } try { const response = await GetData(`${API_URL_CUSTOMER}/customer/list`, query); if (response?.status) { setCustomers(response?.data.list); } else { toast.error(response?.message); } } catch (error) { toast.error('Failed to fetch customer list'); } finally { setIsLoading(false); } }; const handleCustomerSearch = (e: React.ChangeEvent) => { setIsLoading(true); setSearchTerm(e.target.value); setSelectedCustomerName(e.target.value); setDropdownOpen(true); const timer = setTimeout(() => { getCustomerList([{ id: 'fullname', desc: false }], e.target.value); }, 500); return () => clearTimeout(timer); }; const handleCustomerSelect = (customer: CustomerProps) => { setFormField({ ...formField, customerid: customer.id }); setSelectedCustomerName(customer.fullname); setDropdownOpen(false); }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (isSubmitting) return; if (!validateFormCreateUser(formField, setErrors, 'create')) { return; } doCreateUser(e); }; const isButtonDisabled = !messagePassword || isSubmitting || passwordErrors.length > 0; const filteredCustomer = customers .filter((item) => item.fullname.toLowerCase().includes(searchTerm.toLowerCase())) .slice(0, 10); useEffect(() => { fetchRoles(); }, [fetchRoles]); useEffect(() => { const validation = validatePassword(formField.password, formField.retype_password); setMessagePassword(validation.isValid); setPasswordErrors(validation.errors); setNotMatch(validation.notMatch); }, [formField.password, formField.retype_password]); useEffect(() => { if (showAddDialog === false) { resetForm(); setDropdownOpen(false); } }, [showAddDialog]); useEffect(() => { getCustomerList([{ id: 'created_at', desc: false }], ''); const handleClickOutside = (event: any) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { setDropdownOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, []); const togglePassword = useCallback((event: MouseEvent, key: string) => { event.preventDefault(); setShowPassword((prev) => ({ ...prev, [key]: !prev[key as PasswordType] })); }, []); return ( handleAddDialog(open)}>

User - Create

{ handleAddDialog(false); resetForm(); }} >
{/* Name */}
{ setFormField((prev) => ({ ...prev, name: target.value })); setErrors((prev) => ({ ...prev, name: '' })); }} /> {errors.name && {errors.name}}
{/* Username */}
{ setFormField((prev) => ({ ...prev, username: target.value })); setErrors((prev) => ({ ...prev, username: '' })); }} /> {errors.username && ( {errors.username} )}
{/* Customer */}
setDropdownOpen(true)} className={`input ${errors.customerid ? 'border-red-500' : ''}`} /> {dropdownOpen && (
{filteredCustomer.length > 0 ? ( filteredCustomer.map((item) => (
handleCustomerSelect(item)} > {item.fullname}
)) ) : (
{isLoading ? 'Loading...' : 'No results found'}
)}
)} {errors.customerid && ( {errors.customerid} )}
{/* Email */}
{ setFormField((prev) => ({ ...prev, email: target.value })); setErrors((prev) => ({ ...prev, email: '' })); }} /> {errors.email && {errors.email}}
{/* Role */}
{errors.id_role && ( {errors.id_role} )}
{/* Status */}
{errors.status && ( {errors.status} )}
{/* Password */}
{ setFormField((prev) => ({ ...prev, password: target.value })); setErrors((prev) => ({ ...prev, password: '' })); }} />
{passwordErrors.length > 0 && (
{passwordErrors.map((error, index) => (

{error}

))}
)} {errors.password && ( {errors.password} )}
{/* Confirm Password */}
0 ? 'border-red-500' : ''}`} type={showPassword.retype_password ? 'text' : 'password'} autoComplete="off" value={formField.retype_password} onChange={({ target }) => { setFormField((prev) => ({ ...prev, retype_password: target.value })); setErrors((prev) => ({ ...prev, retype_password: '' })); }} />
{notMatch.length > 0 && (
{notMatch.map((error, index) => (

{error}

))}
)} {errors.retype_password && ( {errors.retype_password} )}
{/* Submit Button */}
); }; export { AddDialog };