diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 2f32cd09..f132158b 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -58,7 +58,9 @@ "ALL_BLOCKS": "All Blocks", "NEW_FACILITATOR": "New Facilitator", "SEARCHBAR_PLACEHOLDER": "Search Facilitators..", - "FACILITATOR_CREATED_SUCCESSFULLY": "Teacher has been Successfully Created" + "FACILITATOR_CREATED_SUCCESSFULLY": "Teacher has been Successfully Created", + "FACILITATOR_UPDATED_SUCCESSFULLY": "Teacher has been Successfully Updated!" + }, "NAVBAR": { "SEARCHBAR_PLACEHOLDER": "Search course, topic, student, pdf etc.." @@ -67,7 +69,9 @@ "SEARCHBAR_PLACEHOLDER": "Search Learners..", "NEW_LEARNER": "New Learner", "FIRST_SELECT_REQUIRED_FIELDS": "First select required fields", - "LEARNER_CREATED_SUCCESSFULLY": "Leaner has been Successfully Created!" + "LEARNER_CREATED_SUCCESSFULLY": "Leaner has been Successfully Created!", + "LEARNER_UPDATED_SUCCESSFULLY": "Leaner has been Successfully Updated!" + }, "TEAM_LEADERS": { "SEARCHBAR_PLACEHOLDER": "Search Team leaders.." diff --git a/src/components/ActionIcon.tsx b/src/components/ActionIcon.tsx index 39031ee3..ee1f1447 100644 --- a/src/components/ActionIcon.tsx +++ b/src/components/ActionIcon.tsx @@ -7,7 +7,7 @@ import React from "react"; import MoreVertIcon from "@mui/icons-material/MoreVert"; import { useTranslation } from "next-i18next"; import { Box, Typography, Tooltip } from "@mui/material"; -import EditIcon from "@mui/icons-material/Edit"; +import EditIcon from '@mui/icons-material/Edit'; import DeleteIcon from "@mui/icons-material/Delete"; interface ActionCellProps { @@ -41,11 +41,11 @@ const ActionIcon: React.FC = ({ flexDirection: "column", alignItems: "center", cursor: "pointer", - opacity: 0.5, // Reduced opacity to make it appear disabled + // opacity: 0.5, // Reduced opacity to make it appear disabled pointerEvents: "auto", // Enable pointer events to allow click }} > - + Edit diff --git a/src/components/AddFacilitator.tsx b/src/components/AddFacilitator.tsx index 442c0c6a..32b56388 100644 --- a/src/components/AddFacilitator.tsx +++ b/src/components/AddFacilitator.tsx @@ -7,11 +7,11 @@ import { GenerateSchemaAndUiSchema, customFields, } from "@/components/GeneratedSchemas"; -import { FormContext, FormContextType } from "@/utils/app.constant"; +import { FormContext, FormContextType, Role } from "@/utils/app.constant"; import DynamicForm from "@/components/DynamicForm"; import SendCredentialModal from "@/components/SendCredentialModal"; import SimpleModal from "@/components/SimpleModal"; -import { createUser, getFormRead } from "@/services/CreateUserService"; +import { createUser, getFormRead, updateUser } from "@/services/CreateUserService"; import { generateUsernameAndPassword } from "@/utils/Helper"; import { FormData } from "@/utils/Interfaces"; import { RoleId } from "@/utils/app.constant"; @@ -23,10 +23,16 @@ import { useLocationState } from "@/utils/useLocationState"; interface AddFacilitatorModalprops { open: boolean; onClose: () => void; + formData?:object; + isEditModal?:boolean; + userId?:string } const AddFacilitatorModal: React.FC = ({ open, + formData, + isEditModal=false, + userId, onClose, }) => { const { t } = useTranslation(); @@ -98,7 +104,7 @@ const AddFacilitatorModal: React.FC = ({ console.log("Form data submitted:", formData); const schemaProperties = schema.properties; - const { username, password } = generateUsernameAndPassword("MH", "F"); + const { username, password } = generateUsernameAndPassword(selectedStateCode,Role.TEACHER); let apiBody: any = { username: username, @@ -143,10 +149,45 @@ const AddFacilitatorModal: React.FC = ({ }); console.log(apiBody); + if(!isEditModal) + { + apiBody.customFields.push({ + fieldId: "a717bb68-5c8a-45cb-b6dd-376caa605736", + value: [selectedBlockCode], + }); + apiBody.customFields.push({ + fieldId: "61b5909a-0b45-4282-8721-e614fd36d7bd", + value: [selectedStateCode], + }); + apiBody.customFields.push({ + fieldId: "aecb84c9-fe4c-4960-817f-3d228c0c7300", + value: [selectedDistrictCode], + }); + } try{ - const response = await createUser(apiBody); + if(isEditModal && userId) + { + const userData={ + "name":apiBody.name, + "mobile": apiBody.mobile, + + }; + const customFields=apiBody.customFields; + console.log(customFields) + const object= + { + "userData":userData, + "customFields":customFields + } + const response = await updateUser(userId,object) + showToastMessage(t("LEARNERS.LEARNER_UPDATED_SUCCESSFULLY"), "success"); + }else{ + const response = await createUser(apiBody); + showToastMessage(t('FACILITATORS.FACILITATOR_CREATED_SUCCESSFULLY'), 'success'); + } onClose(); - showToastMessage(t('FACILITATORS.FACILITATOR_CREATED_SUCCESSFULLY'), 'success'); + + } catch(error) { @@ -197,7 +238,9 @@ catch(error) selectedCenter={selectedCenter} handleCenterChangeWrapper={handleCenterChangeWrapper} /> - {dynamicForm && schema && uiSchema && ( + + +{formData ? ( schema && uiSchema && ( - )} + formData={formData} + > + {/* */} + + )) :( dynamicForm && schema && uiSchema && ( + + {/* */} + + ))} diff --git a/src/components/AddLeanerModal.tsx b/src/components/AddLeanerModal.tsx index 9ce872a5..6c6f8e03 100644 --- a/src/components/AddLeanerModal.tsx +++ b/src/components/AddLeanerModal.tsx @@ -4,7 +4,7 @@ import { customFields, } from "@/components/GeneratedSchemas"; import SimpleModal from "@/components/SimpleModal"; -import { createUser, getFormRead } from "@/services/CreateUserService"; +import { createUser, getFormRead , updateUser} from "@/services/CreateUserService"; import { generateUsernameAndPassword } from "@/utils/Helper"; import { FormData } from "@/utils/Interfaces"; import { @@ -31,12 +31,15 @@ import { showToastMessage } from "./Toastify"; interface AddLearnerModalProps { open: boolean; onClose: () => void; + formData?:object; + isEditModal?:boolean; + userId?:string } interface FieldProp { value: string; label: string; } -const AddLearnerModal: React.FC = ({ open, onClose }) => { +const AddLearnerModal: React.FC = ({ open, onClose, formData , isEditModal=false, userId}) => { const [schema, setSchema] = React.useState(); const [uiSchema, setUiSchema] = React.useState(); @@ -80,6 +83,7 @@ const AddLearnerModal: React.FC = ({ open, onClose }) => { if (response) { const { schema, uiSchema } = GenerateSchemaAndUiSchema(response, t); setSchema(schema); + console.log(schema) setUiSchema(uiSchema); } } catch (error) { @@ -143,6 +147,7 @@ const AddLearnerModal: React.FC = ({ open, onClose }) => { console.log( `FieldID: ${fieldId}, FieldValue: ${fieldValue}, type: ${typeof fieldValue}` ); + if (fieldId === null || fieldId === "null") { if (typeof fieldValue !== "object") { @@ -164,8 +169,11 @@ const AddLearnerModal: React.FC = ({ open, onClose }) => { }); } } - }); + + }); + if(!isEditModal) + { apiBody.customFields.push({ fieldId: "a717bb68-5c8a-45cb-b6dd-376caa605736", value: [selectedBlockCode], @@ -178,10 +186,36 @@ const AddLearnerModal: React.FC = ({ open, onClose }) => { fieldId: "aecb84c9-fe4c-4960-817f-3d228c0c7300", value: [selectedDistrictCode], }); + } + try { - const response = await createUser(apiBody); + if(isEditModal && userId) + { + console.log(apiBody) + const userData={ + "name":apiBody.name, + "mobile": apiBody.mobile, + "father_name":apiBody.father_name + + }; + const customFields=apiBody.customFields; + console.log(customFields) + const object= + { + "userData":userData, + "customFields":customFields + } + const response = await updateUser(userId,object) + showToastMessage(t("LEARNERS.LEARNER_UPDATED_SUCCESSFULLY"), "success"); + + + } + else{ + const response = await createUser(apiBody); + showToastMessage(t("LEARNERS.LEARNER_CREATED_SUCCESSFULLY"), "success"); + + } onClose(); - showToastMessage(t("LEARNERS.LEARNER_CREATED_SUCCESSFULLY"), "success"); } catch (error) { onClose(); console.log(error); @@ -307,7 +341,23 @@ const AddLearnerModal: React.FC = ({ open, onClose }) => { /> - {dynamicForm && schema && uiSchema && ( + + + {formData ? ( schema && uiSchema && ( + + {/* */} + + )) :( dynamicForm && schema && uiSchema && ( = ({ open, onClose }) => { > {/* */} - )} + ))} + ); diff --git a/src/components/DynamicForm.tsx b/src/components/DynamicForm.tsx index 0117402a..717ef03d 100644 --- a/src/components/DynamicForm.tsx +++ b/src/components/DynamicForm.tsx @@ -20,6 +20,8 @@ interface DynamicFormProps { onChange: (event: IChangeEvent) => void; onError: (errors: any) => void; showErrorList: boolean; + + widgets: { [key: string]: React.FC>; }; @@ -39,6 +41,7 @@ const DynamicForm: React.FC = ({ customFields, children, }) => { + console.log(formData) const widgets = { MultiSelectCheckboxes: MultiSelectCheckboxes, CustomRadioWidget: CustomRadioWidget, @@ -113,7 +116,7 @@ const DynamicForm: React.FC = ({ } function handleChange(event: any) { - console.log('Form data event:', event); + console.log('Form data changed:', event.formData); onChange(event); } @@ -123,7 +126,7 @@ const DynamicForm: React.FC = ({ = ({ @@ -45,6 +46,7 @@ const KaTableComponent: React.FC = ({ showIcons, pageSizes, noData, + pagination = true, }) => { const [selectedRowIds, setSelectedRowIds] = useState([]); @@ -61,6 +63,15 @@ const KaTableComponent: React.FC = ({ data, rowKeyField: "id", sortingMode: SortingMode.Single, + ...(pagination && { + paging: { + enabled: paginationEnable, + pageIndex: 0, + pageSize: limit, + pageSizes: pageSizes, + position: PagingPosition.Bottom, + }, + }), }; return ( diff --git a/src/components/UserTable.tsx b/src/components/UserTable.tsx index 87843bd4..6ce23a90 100644 --- a/src/components/UserTable.tsx +++ b/src/components/UserTable.tsx @@ -17,8 +17,12 @@ import KaTableComponent from "../components/KaTableComponent"; import Loader from "../components/Loader"; import { deleteUser } from "../services/DeleteUser"; import { getCohortList } from "../services/GetCohortList"; -import { userList } from "../services/UserList"; -import PersonSearchIcon from '@mui/icons-material/PersonSearch'; +import { userList, getUserDetails } from "../services/UserList"; +import PersonSearchIcon from "@mui/icons-material/PersonSearch"; +import AddLearnerModal from "@/components/AddLeanerModal"; +import AddFacilitatorModal from "./AddFacilitator"; +import { Role } from "@/utils/app.constant"; +import { getFormRead } from "@/services/CreateUserService"; type UserDetails = { userId: any; username: any; @@ -48,11 +52,11 @@ interface Cohort { customField: any[]; } interface UserTableProps { - role: string; - userType: string, - searchPlaceholder: string, - handleAddUserClick: any - } + role: string; + userType: string; + searchPlaceholder: string; + handleAddUserClick: any; +} const columns = [ // { // key: "userId", @@ -130,8 +134,13 @@ const columns = [ }, ]; -const UserTable: React.FC = ({ role , userType, searchPlaceholder, handleAddUserClick}) => { - const [selectedState, setSelectedState] = React.useState([]); +const UserTable: React.FC = ({ + role, + userType, + searchPlaceholder, + handleAddUserClick, +}) => { + const [selectedState, setSelectedState] = React.useState([]); const [selectedStateCode, setSelectedStateCode] = useState(""); const [selectedDistrict, setSelectedDistrict] = React.useState([]); const [selectedDistrictCode, setSelectedDistrictCode] = useState(""); @@ -152,8 +161,38 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde const [selectedReason, setSelectedReason] = useState(""); const [otherReason, setOtherReason] = useState(""); const [confirmButtonDisable, setConfirmButtonDisable] = useState(false); + const [pagination, setPagination] = useState(true); const [selectedFilter, setSelectedFilter] = useState("All"); + const [formdata, setFormData] = useState(); + const [loading, setLoading] = useState(undefined); + const [openAddLearnerModal, setOpenAddLearnerModal] = React.useState(false); + const [userId, setUserId] = useState(); + + const handleOpenAddLearnerModal = () => { + console.log("hello"); + setOpenAddLearnerModal(true); + }; + + const handleCloseAddLearnerModal = () => { + setOpenAddLearnerModal(false); + }; + const handleAddLearnerClick = () => { + handleOpenAddLearnerModal(); + }; + const [openAddFacilitatorModal, setOpenAddFacilitatorModal] = + React.useState(false); + const handleOpenAddFacilitatorModal = () => { + setOpenAddFacilitatorModal(true); + }; + + const handleCloseAddFacilitatorModal = () => { + setOpenAddFacilitatorModal(false); + }; + + const handleAddFaciliatorClick = () => { + handleOpenAddFacilitatorModal(); + }; const [filters, setFilters] = useState({ role: role, @@ -166,7 +205,7 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde const handlePaginationChange = ( event: React.ChangeEvent, - value: number, + value: number ) => { setPageOffset(value - 1); }; @@ -194,14 +233,14 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde setSelectedState(selected); if (selected[0] === "") { - if (filters.status) setFilters({ status: filters.status, role: role }); + if (filters.status) setFilters({ status: filters.status, role: role }); else setFilters({ role: role }); } else { const stateCodes = code?.join(","); setSelectedStateCode(stateCodes); if (filters.status) - setFilters({ status: filters.status, states: stateCodes, role: role }); - else setFilters({ states: stateCodes , role: role}); + setFilters({ status: filters.status, states: stateCodes, role: role }); + else setFilters({ states: stateCodes, role: role }); } console.log("Selected categories:", typeof code[0]); @@ -240,14 +279,12 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde setFilters({ status: filters.status, states: selectedStateCode, - role: role - + role: role, }); } else { setFilters({ states: selectedStateCode, - role: role - + role: role, }); } } else { @@ -258,15 +295,13 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde status: filters.status, states: selectedStateCode, districts: districts, - role: role - + role: role, }); } else { setFilters({ states: selectedStateCode, districts: districts, - role: role - + role: role, }); } } @@ -280,15 +315,13 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde status: filters.status, states: selectedStateCode, districts: selectedDistrictCode, - role: role - + role: role, }); } else { setFilters({ states: selectedStateCode, districts: selectedDistrictCode, - role: role - + role: role, }); } } else { @@ -300,16 +333,14 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde states: selectedStateCode, districts: selectedDistrictCode, blocks: blocks, - role: role - + role: role, }); } else { setFilters({ states: selectedStateCode, districts: selectedDistrictCode, blocks: blocks, - role: role - + role: role, }); } } @@ -327,8 +358,67 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde setSelectedSort(event.target.value as string); }; - const handleEdit = (rowData: any) => { + const handleEdit = async (rowData: any) => { console.log("Edit row:", rowData); + + try { + const userId = rowData.userId; + setUserId(userId); + const fieldValue = true; + const response = await getUserDetails(userId, fieldValue); + if(Role.STUDENT === role) + { + const formFields = await getFormRead("USERS", "STUDENT"); + + console.log("response", response); + console.log("formFields", formFields); + // map according to formFields + + let initialFormData: any = {}; + formFields.fields.map((item: any) => { + if (item.coreField) { + // initialFormData[item.name] = response?.userData[item.name] || ""; + + if (item?.isMultiSelect) { + initialFormData[item.name] = response?.userData[item.name] ? [response.userData[item.name]] : response.userData[item.name] || ''; + } else { + if (item?.type === 'numeric') { + initialFormData[item.name] = Number(response.userData[item.name]); + } else if (item?.type === 'text') { + initialFormData[item.name] = String(response.userData[item.name]); + } else { + initialFormData[item.name] = response?.userData[item.name]; + } + } + + } else { + const field = response?.userData?.customFields.find( (field: any) => field.fieldId === item.fieldId); + + if (item?.isMultiSelect) { + initialFormData[item.name] = [field.value]; + } else { + if (item?.type === 'numeric') { + initialFormData[item.name] = Number(field.value); + } else if (item?.type === 'text') { + initialFormData[item.name] = String(field.value); + } else { + initialFormData[item.name] = field.value; + } + } + } + }); + + setFormData(initialFormData); + handleOpenAddLearnerModal(); + + console.log("initialFormData", initialFormData); + } + + + } catch (error) { + console.log(error); + } + // console.log("responce",responce) // Handle edit action here }; @@ -364,9 +454,13 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde } else if (resp?.totalCount >= 10) { // setPageSize(resp?.totalCount); setPageSizeArray([5, 10]); - } else if (resp?.totalCount >= 5 || resp?.totalCount < 5) { - // setPageSize(resp?.totalCount); + } else if (resp?.totalCount > 5) { + setPagination(false); + setPageSizeArray([5]); + } else if (resp?.totalCount <= 5) { + setPagination(false); + // setPageSize(resp?.totalCount); //PageSizeSelectorFunction(); } @@ -374,26 +468,27 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde console.log(result); const finalResult = result.map((user: any) => { const ageField = user.customFields.find( - (field: any) => field.name === "age", + (field: any) => field.name === "age" ); const blockField = user.customFields.find( - (field: any) => field.name === "blocks", + (field: any) => field.name === "blocks" ); const districtField = user.customFields.find( - (field: any) => field.name === "districts", + (field: any) => field.name === "districts" ); const stateField = user.customFields.find( - (field: any) => field.name === "states", + (field: any) => field.name === "states" ); - return { userId: user.userId, username: user.username, - name: user.name.charAt(0).toUpperCase() + user.name.slice(1).toLowerCase(), + name: + user.name.charAt(0).toUpperCase() + + user.name.slice(1).toLowerCase(), role: user.role, - gender:user.gender, - mobile: user.mobile==="NaN"?"":user.mobile, + gender: user.gender, + mobile: user.mobile === "NaN" ? "" : user.mobile, age: ageField ? ageField.value : null, district: districtField ? districtField.value : null, state: stateField ? stateField.value : null, @@ -429,14 +524,14 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde data.map(async (user) => { const response = await getCohortList(user.userId); const cohortNames = response?.result?.cohortData?.map( - (cohort: Cohort) => cohort.name, + (cohort: Cohort) => cohort.name ); return { ...user, centers: cohortNames?.join(" , "), }; - }), + }) ); setData(newData); @@ -453,7 +548,7 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde setOtherReason(""); setIsDeleteModalOpen(false); }; - + const handleDeleteUser = async (category: string) => { try { console.log(selectedUserId); @@ -491,9 +586,9 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde handleSortChange: handleSortChange, selectedFilter: selectedFilter, handleFilterChange: handleFilterChange, - handleSearch:handleSearch, - handleAddUserClick: handleAddUserClick - }; + handleSearch: handleSearch, + handleAddUserClick: handleAddUserClick, + }; return ( @@ -512,6 +607,7 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde showIcons={true} onEdit={handleEdit} onDelete={handleDelete} + pagination={pagination} /> ) : ( loading === false && @@ -551,6 +647,20 @@ const UserTable: React.FC = ({ role , userType, searchPlaceholde confirmButtonDisable={confirmButtonDisable} setConfirmButtonDisable={setConfirmButtonDisable} /> + + ); }; diff --git a/src/services/CreateUserService.ts b/src/services/CreateUserService.ts index 367144a9..23a5f95d 100644 --- a/src/services/CreateUserService.ts +++ b/src/services/CreateUserService.ts @@ -1,6 +1,11 @@ -import { get, post } from './RestClient'; +import { get, post, patch } from './RestClient'; import { createUserParam } from '../utils/Interfaces'; - +export interface UserDetailParam { + userData?: object; + + customFields?: any; + +} export const getFormRead = async ( context: string, contextType: string @@ -34,4 +39,19 @@ export const createUser = async (userData: any): Promise => { console.error('error in getting cohort list', error); // throw error; } +}; + +export const updateUser = async ( + userId: string, + {userData, + customFields}: UserDetailParam +): Promise => { + const apiUrl: string = `${process.env.NEXT_PUBLIC_BASE_URL}/update/${userId}`; + try { + const response = await patch(apiUrl, {userData, customFields}); + return response; + } catch (error) { + console.error("error in fetching user details", error); + return error; + } }; \ No newline at end of file diff --git a/src/services/UserList.ts b/src/services/UserList.ts index f62e793e..fbcc1513 100644 --- a/src/services/UserList.ts +++ b/src/services/UserList.ts @@ -1,4 +1,4 @@ -import { post } from "./RestClient"; +import { post, get } from "./RestClient"; export interface userListParam { limit: number; @@ -38,3 +38,22 @@ export const userList = async ({ throw error; } }; + + +export const getUserDetails = async ( + userId?: string | string[], + fieldValue?: boolean +): Promise => { + const apiUrl: string = `${process.env.NEXT_PUBLIC_BASE_URL}/read/${userId}?fieldvalue=${fieldValue}`; + try { + const response = await get(apiUrl); + return response?.data?.result; + } catch (error) { + console.error('error in fetching user details', error); + return error; + } +}; + + + + diff --git a/src/utils/app.constant.ts b/src/utils/app.constant.ts index 7b35bfa5..6e5b595a 100644 --- a/src/utils/app.constant.ts +++ b/src/utils/app.constant.ts @@ -36,3 +36,4 @@ export enum RoleId { } +