fixing manage user & add field customer

This commit is contained in:
Raja Oktafrianto
2025-04-12 10:54:56 +07:00
parent 211392c7b3
commit 115fb9c001
6 changed files with 231 additions and 12 deletions

View File

@ -23,6 +23,7 @@ import {
SelectTrigger,
SelectValue
} from '@/components/ui/select';
import { doSaveLogActivity } from '@/actions/GlobalActions';
const API_URL = apiConfig.service_master_data;
@ -75,6 +76,13 @@ const AddDialog = () => {
resetForm();
reload();
toast.success('Reward Create successfully!');
const createActivity = {
module: 'Manage Reward',
description: `Create New Reward => ${formField.name}`,
action: 'C'
};
doSaveLogActivity(createActivity);
} else {
toast.error('Failed to create reward.');
setAlert({ show: true, message: 'Failed to create reward. Please try again.' });

View File

@ -13,6 +13,7 @@ import {
import { Button } from '@/components/ui/button';
import { DialogDescription } from '@radix-ui/react-dialog';
import { useManageRewardContext } from '../hooks/useManageRewardContext';
import { doSaveLogActivity } from '@/actions/GlobalActions';
const API_URL = apiConfig.service_master_data;
@ -42,6 +43,13 @@ const DeleteDialog = () => {
handleDeleteDialog(false, null);
toast.success('Success Delete Reward');
reload();
const deleteActivity = {
module: 'Manage Reward',
description: `Delete Reward => ${selectedReward}`,
action: 'D'
};
doSaveLogActivity(deleteActivity);
} else {
setAlert({ show: true, message: response?.message });
toast.error('Failed Delete Reward');

View File

@ -23,6 +23,7 @@ import {
SelectValue
} from '@/components/ui/select';
import { useManageRewardContext } from '../hooks/useManageRewardContext';
import { doSaveLogActivity } from '@/actions/GlobalActions';
const API_URL = apiConfig.service_master_data;
@ -74,6 +75,13 @@ const EditDialog = () => {
handleEditDialog(false, null);
toast.success('Success Update Reward');
reload();
const editActivity = {
module: 'Manage Reward',
description: `Edit Reward => ${formField.name}`,
action: 'U'
};
doSaveLogActivity(editActivity);
} else {
toast.error('Error Update Reward');
setAlert({ show: true, message: 'Failed to Update Reward. Please try again.' });

View File

@ -15,6 +15,16 @@ import {
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';
@ -25,6 +35,14 @@ import { useCallApi } from '@/hooks';
import { doSaveLogActivity } from '@/actions/GlobalActions';
import clsx from 'clsx';
export interface CustomerProps {
id: string;
msisdn: string;
email: string;
fullname: string;
username: string;
}
interface RoleListProps {
id: string;
name: string;
@ -42,7 +60,9 @@ interface CreateUserParams {
status: string;
}
const API_URL_CUSTOMER = apiConfig.service_customer;
const API_URL = apiConfig.service_dashboard;
type PasswordType = 'password' | 'retype_password';
const AddDialog = () => {
@ -62,7 +82,8 @@ const AddDialog = () => {
retype_password: '',
name: '',
id_role: '',
status: ''
status: '',
customerid: ''
};
const [formField, setFormField] = useState(initialState);
const [showPassword, setShowPassword] = useState({
@ -71,6 +92,8 @@ const AddDialog = () => {
});
const [messagePassword, setMessagePassword] = useState(true);
const [open, setOpen] = useState(false);
const [customers, setCustomers] = useState<CustomerProps[]>([]);
const [isSubmitting, setIsSubmitting] = useState(false);
const [passwordErrors, setPasswordErrors] = useState<string[]>([]);
@ -155,6 +178,23 @@ const AddDialog = () => {
// console.log('ini data user_role:', response?.data);
}, []);
const getCustomerList = async (sorting: any) => {
try {
sorting = sorting.length == 0 ? [{ id: 'name', desc: false }] : sorting;
const response = await GetData(`${API_URL_CUSTOMER}/customer/list`, {
limit: 100,
page: 1,
with_deleted: false,
order_field: sorting[0].id,
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC'
});
setCustomers(response?.data.list);
} catch (error) {
console.error('Error fetching customer', error);
}
};
useEffect(() => {
fetchRoles();
}, [fetchRoles]);
@ -162,7 +202,7 @@ const AddDialog = () => {
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log('Form data before submit:', formField);
// console.log('Form data before submit:', formField);
if (
formField.email.trim() === '' ||
@ -171,7 +211,8 @@ const AddDialog = () => {
formField.retype_password.trim() === '' ||
formField.name.trim() === '' ||
formField.id_role.trim() === '' ||
formField.status.trim() === ''
formField.status.trim() === '' ||
formField.customerid.trim() === ''
) {
setAlert({ show: true, message: 'Please fill name field.' });
return;
@ -196,6 +237,10 @@ const AddDialog = () => {
}
}, [showAddDialog]);
useEffect(() => {
getCustomerList([{ id: 'id', desc: false }]);
}, []);
const togglePassword = useCallback((event: MouseEvent<HTMLButtonElement>, key: string) => {
event.preventDefault();
setShowPassword((prev) => ({ ...prev, [key]: !prev[key as PasswordType] }));
@ -262,6 +307,58 @@ const AddDialog = () => {
</div>
</div>
<div className="w-full">
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label className="form-label flex items-center gap-1 max-w-56">Customer</label>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<button
type="button"
className="input col-span-5 text-left flex justify-between"
style={{ color: 'inherit' }}
>
<span>
{customers.find((customer) => customer.id === formField.customerid)
?.username || 'Select Customer'}
</span>
<ChevronDown className="w-4 h-4 opacity-70" />
</button>
</PopoverTrigger>
<PopoverContent className="w-[400px] p-0">
<Command>
<CommandInput placeholder="Search Customer..." />
<CommandList
className="max-h-[300px] overflow-y-auto"
style={{ touchAction: 'pan-y' }}
onWheel={(e) => {
e.currentTarget.scrollTop += e.deltaY;
}}
>
<CommandEmpty>No Customer found.</CommandEmpty>
<CommandGroup>
{customers.map((customer) => (
<CommandItem
key={customer.id}
value={customer.username}
onSelect={() => {
setFormField({
...formField,
customerid: customer.id
});
setOpen(false);
}}
>
{customer.username}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</div>
</div>
<div className="w-full">
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label className="form-label flex items-center gap-1 max-w-56">Email</label>

View File

@ -6,7 +6,15 @@ import {
SelectTrigger,
SelectValue
} from '@/components/ui/select';
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList
} from '@/components/ui/command';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import {
Dialog,
DialogBody,
@ -15,6 +23,7 @@ import {
DialogHeader,
DialogTitle
} from '@/components/ui/dialog';
import { CustomerProps } from './AddDialog';
import { useUserContext } from '../hooks';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
@ -30,6 +39,7 @@ interface RoleListProps {
status: string;
}
const API_URL_CUSTOMER = apiConfig.service_customer;
const API_URL = apiConfig.service_dashboard;
const initialState = {
@ -37,7 +47,8 @@ const initialState = {
username: '',
email: '',
id_role: '',
status: ''
status: '',
customerid: ''
};
const EditDialog = () => {
@ -45,7 +56,9 @@ const EditDialog = () => {
const { showEditDialog, selectedUser, handleEditDialog } = useUserContext();
const { reload } = useDataGrid();
const { GetData, PutData } = useCallApi();
const [open, setOpen] = useState(false);
const [roles, setRoles] = useState<RoleListProps[]>([]);
const [customers, setCustomers] = useState<CustomerProps[]>([]);
const [alert, setAlert] = useState({
show: false,
message: ''
@ -109,9 +122,27 @@ const EditDialog = () => {
}
}, []);
const getCustomerList = async (sorting: any) => {
try {
sorting = sorting.length == 0 ? [{ id: 'name', desc: false }] : sorting;
const response = await GetData(`${API_URL_CUSTOMER}/customer/list`, {
limit: 100,
page: 1,
with_deleted: false,
order_field: sorting[0].id,
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC'
});
// console.log('CUSTOMER: ', response?.data);
setCustomers(response?.data.list);
} catch (error) {
console.error('Error fetching customer', error);
}
};
const doFetchUserData = useCallback(async (id: string) => {
const response = await GetData(`${API_URL}/user/detail/${id}`, { id });
// console.log('User detail response:', response);
console.log('User detail response:', response?.data);
if (response?.status) {
setFormField((prev) => ({
@ -120,8 +151,10 @@ const EditDialog = () => {
username: response.data.username,
email: response.data.email,
id_role: response.data.idRole,
status: response.data.status
status: response.data.status,
customerid: response.data.customerid
}));
console.log('Customer ID dari user detail:', response.data.customerid);
} else {
setFormField((prev) => ({
...prev,
@ -129,7 +162,8 @@ const EditDialog = () => {
username: '',
email: '',
id_role: '0',
status: ''
status: '',
customerid: ''
}));
}
// console.log('Fetched ID Role:', response?.data.id_role);
@ -141,6 +175,10 @@ const EditDialog = () => {
}
}, [selectedUser]);
useEffect(() => {
getCustomerList([{ id: 'id', desc: false }]);
}, []);
useEffect(() => {
if (showEditDialog === false) {
resetForm();
@ -192,6 +230,55 @@ const EditDialog = () => {
)}
<form onSubmit={doUpdateUser}>
<div className="card-body grid gap-5 p-0">
<div className="w-full">
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label className="form-label flex items-center gap-1 max-w-56">Customer</label>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<button
type="button"
className="input col-span-5 text-left"
style={{ color: 'inherit' }}
>
{customers.find((customer) => customer.id === formField.customerid)
?.username || 'Select Customer'}
</button>
</PopoverTrigger>
<PopoverContent className="w-[400px] p-0">
<Command>
<CommandInput placeholder="Search Customer..." />
<CommandList
className="max-h-[300px] overflow-y-auto"
style={{ touchAction: 'pan-y' }}
onWheel={(e) => {
e.currentTarget.scrollTop += e.deltaY;
}}
>
<CommandEmpty>No Customer found.</CommandEmpty>
<CommandGroup>
{customers.map((customer) => (
<CommandItem
key={customer.id}
value={customer.username}
onSelect={() => {
setFormField({
...formField,
customerid: customer.id
});
setOpen(false);
}}
>
{customer.username}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</div>
</div>
<div className="w-full">
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label className="form-label flex items-center gap-1 max-w-56">Name</label>

View File

@ -27,6 +27,7 @@ interface SelectedUser {
role: string;
new_password: string;
check_new_password: string;
customer: string;
}
const initialProps: ContextProps = {
@ -83,6 +84,16 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode })
enableSorting: true,
enableHiding: false
},
{
accessorFn: (row) => row.customer?.username,
id: 'customer',
header: ({ column }) => <DataGridColumnHeader title="Customer" column={column} />,
enableSorting: false,
enableHiding: false,
meta: {
headerClassName: 'w-[300px]'
}
},
{
accessorFn: (row) => row.email,
id: 'email',
@ -100,7 +111,7 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode })
enableSorting: false,
enableHiding: false,
meta: {
headerClassName: 'w-[350px]'
headerClassName: 'w-[250px]'
}
},
{
@ -179,7 +190,7 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode })
);
const doGetListData = async (page: number, limit: number, sorting: any, filter: any) => {
sorting = sorting.length == 0 ? [{ id: 'username', desc: false }] : sorting;
sorting = sorting.length == 0 ? [{ id: 'Users.username', desc: false }] : sorting;
filter = filter.length == 0 ? {} : { any: filter[0].value.toLowerCase() };
const response = await GetData(`${API_URL}/user/list`, {
limit: limit,
@ -189,7 +200,7 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode })
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC',
filter: JSON.stringify(filter)
});
console.log('response api:', response);
// console.log('response api:', response);
return { data: response?.data.list, totalCount: response?.data.total_count };
};
@ -215,7 +226,7 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode })
pagination={{ size: 10 }}
toolbar={<ListToolBar />}
layout={{ card: true }}
sorting={[{ id: 'username', desc: false }]}
sorting={[{ id: 'Users.username', desc: false }]}
serverSide={true}
onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) =>
doGetListData(pageIndex, pageSize, sorting, columnFilters)