@syzy/apphost 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.js +83 -0
- package/dist/AppHostProvider.js +4 -0
- package/dist/AppHostRoutes.js +7 -0
- package/dist/api/image-api.js +45 -0
- package/dist/api/mapping-api.js +427 -0
- package/dist/bookingModule/components/AmenityForm.js +19 -0
- package/dist/bookingModule/components/BillingManagement.js +17 -0
- package/dist/bookingModule/components/CreateRoomForm.js +19 -0
- package/dist/bookingModule/components/ExtraRequirementForm.js +19 -0
- package/dist/bookingModule/components/ReservationForm.js +18 -0
- package/dist/bookingModule/components/RoomCategoryForm.js +19 -0
- package/dist/bookingModule/components/RoomCategoryPriceForm.js +20 -0
- package/dist/bookingModule/components/RoomExtraRequirementCapture.js +18 -0
- package/dist/bookingModule/components/RoomFacilityForm.js +19 -0
- package/dist/bookingModule/components/RoomReservationAction.js +18 -0
- package/dist/components/Home/Home.js +14 -0
- package/dist/components/Loader/Loader.js +5 -0
- package/dist/components/Login/Login.js +149 -0
- package/dist/components/Login/loginSchema.js +41 -0
- package/dist/components/Mappings/BranchMapping/Branch.js +135 -0
- package/dist/components/Mappings/BranchMapping/BranchTableColumns.js +21 -0
- package/dist/components/Mappings/BranchMapping/MappingFormBranchUser.js +150 -0
- package/dist/components/Mappings/BranchMapping/MappingTableColumns.js +29 -0
- package/dist/components/Mappings/BranchMapping/branchSchema.js +34 -0
- package/dist/components/Mappings/ComponentMapping/ComponentRoleMapping.js +98 -0
- package/dist/components/Mappings/ComponentMapping/componentRoleColumns.js +29 -0
- package/dist/components/Mappings/MappingForm/MappingForm.js +142 -0
- package/dist/components/Mappings/MappingForm/mappingSchema.js +32 -0
- package/dist/components/Mappings/RoleMapping/MappingFormUserRole.js +194 -0
- package/dist/components/Mappings/RoleMapping/UserRoleTableColumns.js +33 -0
- package/dist/components/NavBar/Sidebar.js +56 -0
- package/dist/components/ProfileForm/ProfileForm.js +190 -0
- package/dist/components/ProfileForm/ProfileList.js +33 -0
- package/dist/components/ProfileForm/profileColumns.js +67 -0
- package/dist/components/ProfileForm/profileSchema.js +50 -0
- package/dist/components/SettingsPage/SettingsPage.js +240 -0
- package/dist/components/api/settings-api.js +131 -0
- package/dist/components/common/Form/FormActionButtons.js +6 -0
- package/dist/components/common/Form/FormLabel.js +6 -0
- package/dist/components/common/ListTable/ListHeader.js +5 -0
- package/dist/components/common/ListTable/ListTable.js +31 -0
- package/dist/components/common/Modal/Modal.js +6 -0
- package/dist/config/EnvConfig.js +13 -0
- package/dist/config/amplifyConfig.js +45 -0
- package/dist/configureAppHost.js +5 -0
- package/dist/customGraphQL/customMutations.js +53 -0
- package/dist/customGraphQL/customQueries.js +104 -0
- package/dist/domain/input/input-types.js +1 -0
- package/dist/domain/model/BranchDto.js +8 -0
- package/dist/domain/model/ComponentMappingDto.js +19 -0
- package/dist/domain/model/MappingDto.js +16 -0
- package/dist/domain/model/PrefixDescriptionDto.js +13 -0
- package/dist/domain/model/ProfileDto.js +20 -0
- package/dist/domain/model/RoleMappingDto.js +19 -0
- package/dist/domain/model/SettingsDto.js +7 -0
- package/dist/domain/model/UserMappingDto.js +28 -0
- package/dist/domain/model/imageDto.js +1 -0
- package/dist/domain/type/EntityTypes.js +6 -0
- package/dist/domain/type/MappingOptions.js +1 -0
- package/dist/domain/type/MappingTypes.js +7 -0
- package/dist/domain/type/Nullable.js +1 -0
- package/dist/domain/type/ResettingPeriodOptions.js +8 -0
- package/dist/domain/type/RolesEnum.js +7 -0
- package/dist/domain/type/SelectType.js +1 -0
- package/dist/domain/type/StatusEnum.js +6 -0
- package/dist/domain/type/signUpOptions.js +4 -0
- package/dist/domain/type/statusOptions.js +4 -0
- package/dist/graphql/profileQueries.js +89 -0
- package/dist/hoc/withSyzyAuth.js +87 -0
- package/dist/hooks/useCurrentUser.js +6 -0
- package/dist/hooks/useDispatch.js +7 -0
- package/dist/hooks/usePermission.js +7 -0
- package/dist/index.js +3 -15
- package/dist/main.js +60 -0
- package/dist/services/Client.Service.js +96 -0
- package/dist/services/Storage-service.js +26 -0
- package/dist/services/navigationMenu.js +9 -0
- package/dist/static/constants.js +34 -0
- package/dist/store/AppAction.js +5 -0
- package/dist/store/AppContext.js +3 -0
- package/dist/store/AppContextType.js +6 -0
- package/dist/store/AppProvider.js +32 -0
- package/dist/store/HostedInContainerContext.js +11 -0
- package/dist/store/SesssionReducer.js +16 -0
- package/dist/types/App.d.ts +4 -0
- package/dist/types/AppHostProvider.d.ts +6 -0
- package/dist/types/AppHostRoutes.d.ts +1 -0
- package/dist/types/api/image-api.d.ts +8 -0
- package/dist/types/api/mapping-api.d.ts +80 -0
- package/dist/types/bookingModule/components/AmenityForm.d.ts +3 -0
- package/dist/types/bookingModule/components/BillingManagement.d.ts +3 -0
- package/dist/types/bookingModule/components/CreateRoomForm.d.ts +3 -0
- package/dist/types/bookingModule/components/ExtraRequirementForm.d.ts +3 -0
- package/dist/types/bookingModule/components/ReservationForm.d.ts +3 -0
- package/dist/types/bookingModule/components/RoomCategoryForm.d.ts +3 -0
- package/dist/types/bookingModule/components/RoomCategoryPriceForm.d.ts +3 -0
- package/dist/types/bookingModule/components/RoomExtraRequirementCapture.d.ts +3 -0
- package/dist/types/bookingModule/components/RoomFacilityForm.d.ts +3 -0
- package/dist/types/bookingModule/components/RoomReservationAction.d.ts +3 -0
- package/dist/types/components/Home/Home.d.ts +3 -0
- package/dist/types/components/Loader/Loader.d.ts +2 -0
- package/dist/types/components/Login/Login.d.ts +7 -0
- package/dist/types/components/Login/loginSchema.d.ts +27 -0
- package/dist/types/components/Mappings/BranchMapping/Branch.d.ts +5 -0
- package/dist/types/components/Mappings/BranchMapping/BranchTableColumns.d.ts +10 -0
- package/dist/types/components/Mappings/BranchMapping/MappingFormBranchUser.d.ts +3 -0
- package/dist/types/components/Mappings/BranchMapping/MappingTableColumns.d.ts +14 -0
- package/dist/types/components/Mappings/BranchMapping/branchSchema.d.ts +37 -0
- package/dist/types/components/Mappings/ComponentMapping/ComponentRoleMapping.d.ts +3 -0
- package/dist/types/components/Mappings/ComponentMapping/componentRoleColumns.d.ts +3 -0
- package/dist/types/components/Mappings/MappingForm/MappingForm.d.ts +35 -0
- package/dist/types/components/Mappings/MappingForm/mappingSchema.d.ts +23 -0
- package/dist/types/components/Mappings/RoleMapping/MappingFormUserRole.d.ts +5 -0
- package/dist/types/components/Mappings/RoleMapping/UserRoleTableColumns.d.ts +3 -0
- package/dist/types/components/NavBar/Sidebar.d.ts +4 -0
- package/dist/types/components/ProfileForm/ProfileForm.d.ts +3 -0
- package/dist/types/components/ProfileForm/ProfileList.d.ts +3 -0
- package/dist/types/components/ProfileForm/profileColumns.d.ts +3 -0
- package/dist/types/components/ProfileForm/profileSchema.d.ts +52 -0
- package/dist/types/components/SettingsPage/SettingsPage.d.ts +3 -0
- package/dist/types/components/api/settings-api.d.ts +26 -0
- package/dist/types/components/common/Form/FormActionButtons.d.ts +11 -0
- package/dist/types/components/common/Form/FormLabel.d.ts +8 -0
- package/dist/types/components/common/ListTable/ListHeader.d.ts +8 -0
- package/dist/types/components/common/ListTable/ListTable.d.ts +17 -0
- package/dist/types/components/common/Modal/Modal.d.ts +11 -0
- package/dist/types/config/EnvConfig.d.ts +13 -0
- package/dist/types/config/amplifyConfig.d.ts +1 -0
- package/dist/types/configureAppHost.d.ts +6 -0
- package/dist/types/customGraphQL/customMutations.d.ts +3 -0
- package/dist/types/customGraphQL/customQueries.d.ts +7 -0
- package/dist/types/domain/input/input-types.d.ts +47 -0
- package/dist/types/domain/model/BranchDto.d.ts +9 -0
- package/dist/types/domain/model/ComponentMappingDto.d.ts +24 -0
- package/dist/types/domain/model/MappingDto.d.ts +30 -0
- package/dist/types/domain/model/PrefixDescriptionDto.d.ts +16 -0
- package/dist/types/domain/model/ProfileDto.d.ts +21 -0
- package/dist/types/domain/model/RoleMappingDto.d.ts +14 -0
- package/dist/types/domain/model/SettingsDto.d.ts +8 -0
- package/dist/types/domain/model/UserMappingDto.d.ts +14 -0
- package/dist/types/domain/model/imageDto.d.ts +4 -0
- package/dist/types/domain/type/EntityTypes.d.ts +5 -0
- package/dist/types/domain/type/MappingOptions.d.ts +5 -0
- package/dist/types/domain/type/MappingTypes.d.ts +6 -0
- package/dist/types/domain/type/Nullable.d.ts +13 -0
- package/dist/types/domain/type/ResettingPeriodOptions.d.ts +2 -0
- package/dist/types/domain/type/RolesEnum.d.ts +6 -0
- package/dist/types/domain/type/SelectType.d.ts +16 -0
- package/dist/types/domain/type/StatusEnum.d.ts +5 -0
- package/dist/types/domain/type/signUpOptions.d.ts +2 -0
- package/dist/types/domain/type/statusOptions.d.ts +2 -0
- package/dist/types/graphql/profileQueries.d.ts +4 -0
- package/dist/types/hoc/withSyzyAuth.d.ts +2 -0
- package/dist/types/hooks/useCurrentUser.d.ts +3 -0
- package/dist/types/hooks/useDispatch.d.ts +3 -0
- package/dist/types/hooks/usePermission.d.ts +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/main.d.ts +4 -0
- package/dist/types/services/Client.Service.d.ts +12 -0
- package/dist/types/services/Storage-service.d.ts +2 -0
- package/dist/types/services/navigationMenu.d.ts +1 -0
- package/dist/types/static/constants.d.ts +34 -0
- package/dist/types/store/AppAction.d.ts +11 -0
- package/dist/types/store/AppContext.d.ts +3 -0
- package/dist/types/store/AppContextType.d.ts +12 -0
- package/dist/types/store/AppProvider.d.ts +7 -0
- package/dist/types/store/HostedInContainerContext.d.ts +5 -0
- package/dist/types/store/SesssionReducer.d.ts +4 -0
- package/dist/types/types.d.ts +26 -0
- package/dist/types/util/AuthUtils.d.ts +1 -0
- package/dist/types/util/LogEnum.d.ts +6 -0
- package/dist/types/util/Logger.d.ts +6 -0
- package/dist/types/util/SyzyDate.d.ts +69 -0
- package/dist/types/util/dateUtils.d.ts +10 -0
- package/dist/types/util/hostedinContainer.d.ts +1 -0
- package/dist/types/util/model-types.d.ts +96 -0
- package/dist/types/util/prefixAndResettingValidation.d.ts +9 -0
- package/dist/types/util/transformToData.d.ts +1 -0
- package/dist/types.js +14 -0
- package/dist/util/AuthUtils.js +10 -0
- package/dist/util/LogEnum.js +7 -0
- package/dist/util/Logger.js +18 -0
- package/dist/util/SyzyDate.js +265 -0
- package/dist/util/dateUtils.js +24 -0
- package/dist/util/hostedinContainer.js +9 -0
- package/dist/util/model-types.js +18 -0
- package/dist/util/prefixAndResettingValidation.js +54 -0
- package/dist/util/transformToData.js +9 -0
- package/package.json +14 -9
- package/dist/__federation_shared_@tanstack/react-query-DHuUsaNz.js +0 -2517
- package/dist/__federation_shared_react-CikWE6qG.js +0 -7
- package/dist/__federation_shared_react-bootstrap-BKlZRvMR.js +0 -7516
- package/dist/__federation_shared_react-dom-vrQ70Ay8.js +0 -372
- package/dist/__federation_shared_react-router-dom-BKminmS4.js +0 -10448
- package/dist/__federation_shared_react-select-B6kehBDI.js +0 -4056
- package/dist/__federation_shared_react-toastify-B0S0UGr3.js +0 -412
- package/dist/_commonjsHelpers-C6fGbg64.js +0 -6
- package/dist/_virtual___federation_fn_import-XZCKozko.js +0 -217
- package/dist/favicon.ico +0 -0
- package/dist/index-DgtWMtjZ.js +0 -184
- package/dist/index-eZknuYwc.js +0 -1219
- package/dist/jsx-runtime-D_t4bG-_.js +0 -264
- package/dist/manifest.webmanifest +0 -1
- package/dist/pwa/Hotel-icon.jpg +0 -0
- package/dist/pwa/apple-touch-icon-180x180.png +0 -0
- package/dist/pwa/favicon.ico +0 -0
- package/dist/pwa/maskable-icon-512x512.png +0 -0
- package/dist/pwa/pwa-192x192.png +0 -0
- package/dist/pwa/pwa-512x512.png +0 -0
- package/dist/pwa/pwa-64x64.png +0 -0
- package/dist/registerSW.js +0 -1
- package/dist/sw.js +0 -1
- package/dist/workbox-1ef09536.js +0 -1
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useForm } from "react-hook-form";
|
|
3
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
4
|
+
import { Form, Row, Col } from "react-bootstrap";
|
|
5
|
+
import { toast } from "react-toastify";
|
|
6
|
+
import { useCreateProfileMutation } from "../../api/mapping-api";
|
|
7
|
+
import { generateClient } from "aws-amplify/api";
|
|
8
|
+
import { useProfileSchema } from "./profileSchema";
|
|
9
|
+
import '../Mappings/MappingForm/MappingForm.css';
|
|
10
|
+
import { logger } from "../../util/Logger";
|
|
11
|
+
import { useLocation, useNavigate } from "react-router-dom";
|
|
12
|
+
import { useUpdateProfileMutation } from "../../api/mapping-api";
|
|
13
|
+
import { Status } from "../../domain/type/StatusEnum";
|
|
14
|
+
import { useEffect, useState } from "react";
|
|
15
|
+
import { useGetImageURL, useImageMutation } from "../../api/image-api";
|
|
16
|
+
import { SyzyDate } from "../../util/SyzyDate";
|
|
17
|
+
import { DATE_FORMAT_ISO_YYYY_MM_DD_HH_MM } from "../../util/dateUtils";
|
|
18
|
+
import LoadingSpinner from "../Loader/Loader";
|
|
19
|
+
const ProfileForm = () => {
|
|
20
|
+
const { profileSchema, initiateProfile } = useProfileSchema();
|
|
21
|
+
const createProfileMutation = useCreateProfileMutation();
|
|
22
|
+
const location = useLocation();
|
|
23
|
+
const navigate = useNavigate();
|
|
24
|
+
const editProfile = location.state;
|
|
25
|
+
const isEditMode = !!editProfile;
|
|
26
|
+
const [imgInfo, setImgInfo] = useState();
|
|
27
|
+
const imageMutation = useImageMutation(imgInfo);
|
|
28
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (isEditMode && editProfile) {
|
|
31
|
+
reset(mapProfileToFormValues(editProfile));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
reset(initiateProfile);
|
|
35
|
+
}
|
|
36
|
+
}, [editProfile]);
|
|
37
|
+
const mapProfileToFormValues = (profile) => ({
|
|
38
|
+
pk: profile.pk ?? "",
|
|
39
|
+
customId: profile.sk ?? "",
|
|
40
|
+
name: profile.name ?? "",
|
|
41
|
+
email: profile.email ?? "",
|
|
42
|
+
phoneNumber: profile.phoneNumber ?? "",
|
|
43
|
+
address: profile.address ?? "",
|
|
44
|
+
dob: profile.dob ?? "",
|
|
45
|
+
contactRelation: profile.contactRelation ?? "",
|
|
46
|
+
contactPersonName: profile.contactPersonName ?? "",
|
|
47
|
+
contactPersonNumber: profile.contactPersonNumber ?? "",
|
|
48
|
+
aadhaarNumber: profile.aadhaarNumber ?? "",
|
|
49
|
+
aadhaarFile: undefined,
|
|
50
|
+
status: profile.status ?? Status.Active,
|
|
51
|
+
});
|
|
52
|
+
const defaultValues = isEditMode
|
|
53
|
+
? mapProfileToFormValues(editProfile)
|
|
54
|
+
: initiateProfile;
|
|
55
|
+
const updateProfileMutation = useUpdateProfileMutation();
|
|
56
|
+
const { register, handleSubmit, formState: { errors }, reset, } = useForm({
|
|
57
|
+
resolver: zodResolver(profileSchema),
|
|
58
|
+
defaultValues,
|
|
59
|
+
mode: "onChange",
|
|
60
|
+
});
|
|
61
|
+
const handleAadhaarUploadAndNavigate = (file, customId) => {
|
|
62
|
+
if (file) {
|
|
63
|
+
const imageKey = `${customId}/profile-documents/${file.name}`;
|
|
64
|
+
const imgDto = { imageKey, file, };
|
|
65
|
+
imageMutation.mutate(imgDto);
|
|
66
|
+
setImgInfo(imgDto);
|
|
67
|
+
}
|
|
68
|
+
setTimeout(() => {
|
|
69
|
+
setIsSubmitting(false);
|
|
70
|
+
navigate("/profile-list");
|
|
71
|
+
}, 1200);
|
|
72
|
+
};
|
|
73
|
+
const aadhaarKey = isEditMode && editProfile?.aadhaarFile
|
|
74
|
+
? `${encodeURIComponent(editProfile.sk)}/profile-documents/${editProfile.aadhaarFile}`
|
|
75
|
+
: undefined;
|
|
76
|
+
const { fetchedImg } = useGetImageURL(aadhaarKey);
|
|
77
|
+
const onSubmit = async (data) => {
|
|
78
|
+
try {
|
|
79
|
+
const client = generateClient();
|
|
80
|
+
const file = data.aadhaarFile && data.aadhaarFile.length > 0 ? data.aadhaarFile[0] : null;
|
|
81
|
+
// Validate filename
|
|
82
|
+
const forbiddenCharsRegex = /[%#?&+\\/:*"<>|]/;
|
|
83
|
+
if (file && forbiddenCharsRegex.test(file.name)) {
|
|
84
|
+
toast.error("Filename contains unsupported characters.");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
setIsSubmitting(true);
|
|
88
|
+
const aadhaarFileName = file?.name ?? editProfile?.aadhaarFile ?? "";
|
|
89
|
+
// UPDATE PROFILE
|
|
90
|
+
if (editProfile) {
|
|
91
|
+
const updatePayload = {
|
|
92
|
+
pk: editProfile.pk,
|
|
93
|
+
sk: editProfile.sk,
|
|
94
|
+
customId: editProfile.customId,
|
|
95
|
+
name: data.name,
|
|
96
|
+
email: data.email,
|
|
97
|
+
phoneNumber: data.phoneNumber,
|
|
98
|
+
address: data.address,
|
|
99
|
+
dob: data.dob,
|
|
100
|
+
contactRelation: data.contactRelation,
|
|
101
|
+
contactPersonName: data.contactPersonName,
|
|
102
|
+
contactPersonNumber: data.contactPersonNumber,
|
|
103
|
+
aadhaarNumber: data.aadhaarNumber,
|
|
104
|
+
aadhaarFile: aadhaarFileName,
|
|
105
|
+
isAdmin: editProfile.isAdmin,
|
|
106
|
+
status: data.status ?? Status.Active,
|
|
107
|
+
createdDt: editProfile.createdDt,
|
|
108
|
+
createdBy: editProfile.createdBy,
|
|
109
|
+
};
|
|
110
|
+
updateProfileMutation.mutate(updatePayload, {
|
|
111
|
+
onSuccess: () => {
|
|
112
|
+
toast.success("Profile updated successfully!");
|
|
113
|
+
handleAadhaarUploadAndNavigate(file, editProfile.sk);
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// CREATE PROFILE
|
|
118
|
+
else {
|
|
119
|
+
const userId = `PROFILE#${Date.now()}`;
|
|
120
|
+
// Create Cognito User
|
|
121
|
+
await client.graphql({
|
|
122
|
+
query: `mutation CreateUserAccount($input: createUserAccountInput!) {
|
|
123
|
+
createUserAccount(input: $input) {
|
|
124
|
+
username
|
|
125
|
+
email
|
|
126
|
+
userId
|
|
127
|
+
response
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
`,
|
|
131
|
+
variables: {
|
|
132
|
+
input: {
|
|
133
|
+
username: data.customId,
|
|
134
|
+
email: data.email,
|
|
135
|
+
userId: userId,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
// Create Profile
|
|
140
|
+
await createProfileMutation.mutateAsync({
|
|
141
|
+
pk: userId,
|
|
142
|
+
sk: data.customId,
|
|
143
|
+
customId: data.customId,
|
|
144
|
+
name: data.name,
|
|
145
|
+
email: data.email,
|
|
146
|
+
phoneNumber: data.phoneNumber,
|
|
147
|
+
address: data.address,
|
|
148
|
+
dob: data.dob,
|
|
149
|
+
contactRelation: data.contactRelation,
|
|
150
|
+
contactPersonName: data.contactPersonName,
|
|
151
|
+
contactPersonNumber: data.contactPersonNumber,
|
|
152
|
+
aadhaarNumber: data.aadhaarNumber,
|
|
153
|
+
aadhaarFile: aadhaarFileName,
|
|
154
|
+
isAdmin: data.isAdmin ?? false,
|
|
155
|
+
status: data.status ?? Status.Active,
|
|
156
|
+
createdDt: new SyzyDate().toDateFormatString(DATE_FORMAT_ISO_YYYY_MM_DD_HH_MM),
|
|
157
|
+
createdBy: userId,
|
|
158
|
+
});
|
|
159
|
+
toast.success("Profile created successfully!");
|
|
160
|
+
handleAadhaarUploadAndNavigate(file, data.customId);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
setIsSubmitting(false);
|
|
165
|
+
const msg = err?.errors?.[0]?.message;
|
|
166
|
+
let errorMessage = "Failed to create profile!";
|
|
167
|
+
if (msg) {
|
|
168
|
+
if (msg === "Error creating user: UsernameExistsException: User account already exists") {
|
|
169
|
+
errorMessage = "Email ID already exists";
|
|
170
|
+
}
|
|
171
|
+
else if (msg === "Error creating user: UsernameExistsException: User account already exists and is expired. Please call with action RESEND to reset user account") {
|
|
172
|
+
errorMessage = "Employee ID already exists";
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
const splitMsg = msg.split(":").slice(1).join(":").trim();
|
|
176
|
+
errorMessage = splitMsg || "Failed to create profile!";
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
toast.error(errorMessage);
|
|
180
|
+
logger.error("Profile created error", err);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
if (isSubmitting) {
|
|
184
|
+
return _jsx(LoadingSpinner, {});
|
|
185
|
+
}
|
|
186
|
+
return (_jsxs(Form, { onSubmit: handleSubmit(onSubmit), className: "mapping-form mx-auto col-12 col-md-10 col-xl-10 shadow-lg py-3 mt-sm-4 py-sm-4 container", children: [_jsxs(Row, { className: "px-lg-5 px-2 align-items-center justify-content-around", children: [_jsx("h5", { className: "text-center font-title", children: "Employee Registration" }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Employee ID" }), _jsx(Form.Control, { type: "text", ...register("customId"), placeholder: "Enter Employee ID", isInvalid: !!errors.customId, disabled: isEditMode }), _jsx(Form.Control.Feedback, { type: "invalid", children: errors.customId?.message })] }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Name" }), _jsx(Form.Control, { type: "text", placeholder: "Enter Employee Name", ...register("name"), isInvalid: !!errors.name }), _jsx(Form.Control.Feedback, { type: "invalid", children: errors.name?.message })] }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Email" }), _jsx(Form.Control, { type: "email", placeholder: "Enter Employee Email address", ...register("email"), isInvalid: !!errors.email }), _jsx(Form.Control.Feedback, { type: "invalid", children: errors.email?.message })] }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Phone" }), _jsx(Form.Control, { type: "tel", placeholder: "Enter Employee Phone Number", ...register("phoneNumber"), isInvalid: !!errors.phoneNumber }), _jsx(Form.Control.Feedback, { type: "invalid", children: errors.phoneNumber?.message })] }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Address" }), _jsx(Form.Control, { type: "text", placeholder: "Enter Employee Address", ...register("address"), isInvalid: !!errors.address }), _jsx(Form.Control.Feedback, { type: "invalid", children: errors.address?.message })] }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Date of Birth" }), _jsx(Form.Control, { type: "date", ...register("dob"), isInvalid: !!errors.dob }), _jsx(Form.Control.Feedback, { type: "invalid", children: errors.dob?.message })] }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Contact Person Relation" }), _jsxs(Form.Control, { as: "select", ...register("contactRelation"), isInvalid: !!errors.contactRelation, children: [_jsx("option", { value: "", children: "Select Relation" }), _jsx("option", { value: "Mother", children: "Mother" }), _jsx("option", { value: "Father", children: "Father" }), _jsx("option", { value: "Sister", children: "Sister" }), _jsx("option", { value: "Brother", children: "Brother" }), _jsx("option", { value: "Spouse", children: "Spouse" }), _jsx("option", { value: "Other", children: "Other" })] }), _jsx(Form.Control.Feedback, { type: "invalid", children: errors.contactRelation?.message })] }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Contact Person Name" }), _jsx(Form.Control, { type: "text", placeholder: "Enter Employee Contact Person Name", ...register("contactPersonName"), isInvalid: !!errors.contactPersonName }), _jsx(Form.Control.Feedback, { type: "invalid", children: errors.contactPersonName?.message })] }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Contact Person Number" }), _jsx(Form.Control, { type: "tel", placeholder: "Enter Employee Contact Person Number", ...register("contactPersonNumber"), isInvalid: !!errors.contactPersonNumber }), _jsx(Form.Control.Feedback, { type: "invalid", children: errors.contactPersonNumber?.message })] }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Aadhaar Number" }), _jsx(Form.Control, { type: "text", placeholder: "Enter Employee Aadhaar Number", ...register("aadhaarNumber"), isInvalid: !!errors.aadhaarNumber }), _jsx(Form.Control.Feedback, { type: "invalid", children: errors.aadhaarNumber?.message })] }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Upload Aadhaar" }), _jsx(Form.Control, { type: "file", accept: "image/*,application/pdf", ...register("aadhaarFile"), isInvalid: !!errors.aadhaarFile }), _jsx(Form.Control.Feedback, { type: "invalid", children: typeof errors.aadhaarFile?.message === "string"
|
|
187
|
+
? errors.aadhaarFile?.message
|
|
188
|
+
: "" }), isEditMode && fetchedImg && (_jsxs("div", { className: "mt-2", children: [_jsx("small", { children: "Existing Aadhaar:" }), _jsx("br", {}), _jsx("a", { href: fetchedImg, target: "_blank", rel: "noopener noreferrer", children: editProfile.aadhaarFile })] }))] }), _jsxs(Col, { xs: 12, md: 8, lg: 5, className: "mb-2 px-2 px-sm-auto", children: [_jsx(Form.Label, { className: "mt-2 mb-1 form-label", children: "Status" }), _jsxs(Form.Select, { ...register("status"), isInvalid: !!errors.status, children: [_jsx("option", { value: Status.Active, children: "Active" }), _jsx("option", { value: Status.Inactive, children: "Inactive" })] }), _jsx(Form.Control.Feedback, { type: "invalid", children: errors.status?.message })] })] }), _jsx(Row, { className: "justify-content-center mt-3", children: _jsxs(Col, { xs: 12, md: 8, lg: 4, className: "d-flex gap-2", children: [_jsx("button", { className: "btn-primary-global w-100 py-2", type: "submit", disabled: isSubmitting, children: isEditMode ? "Update" : "Submit" }), _jsx("button", { className: "btn-secondary-global w-100 py-2", type: "button", onClick: () => reset(), children: "Clear" })] }) })] }));
|
|
189
|
+
};
|
|
190
|
+
export default ProfileForm;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { useNavigate } from "react-router-dom";
|
|
4
|
+
import { fetchUserRoleMappings, useListProfiles } from "../../api/mapping-api";
|
|
5
|
+
import ListHeader from "../common/ListTable/ListHeader";
|
|
6
|
+
import ListTable from "../common/ListTable/ListTable";
|
|
7
|
+
import { profileColumns } from "./profileColumns";
|
|
8
|
+
const ProfileList = () => {
|
|
9
|
+
const { data: profiles = [], isLoading } = useListProfiles();
|
|
10
|
+
const navigate = useNavigate();
|
|
11
|
+
const [roleMap, setRoleMap] = useState({});
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const loadRoles = async () => {
|
|
14
|
+
const mappings = await fetchUserRoleMappings();
|
|
15
|
+
const map = {};
|
|
16
|
+
mappings.forEach((m) => {
|
|
17
|
+
map[m.userId] = m.roleName;
|
|
18
|
+
});
|
|
19
|
+
setRoleMap(map);
|
|
20
|
+
};
|
|
21
|
+
loadRoles();
|
|
22
|
+
}, []);
|
|
23
|
+
const handleEdit = (row) => {
|
|
24
|
+
navigate("/profile-form", {
|
|
25
|
+
state: row,
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
const handleAdd = () => {
|
|
29
|
+
navigate("/profile-form");
|
|
30
|
+
};
|
|
31
|
+
return (_jsxs("div", { className: "container", children: [_jsx(ListHeader, { title: "Employees List", buttonLabel: "Add Employee", onButtonClick: handleAdd }), _jsx(ListTable, { columns: profileColumns(roleMap), data: profiles, loading: isLoading, emptyMessage: "No employees found", onEdit: handleEdit })] }));
|
|
32
|
+
};
|
|
33
|
+
export default ProfileList;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Badge } from "react-bootstrap";
|
|
3
|
+
import { Status } from "../../domain/type/StatusEnum";
|
|
4
|
+
export const profileColumns = (roleMap) => [
|
|
5
|
+
{
|
|
6
|
+
header: "S.No",
|
|
7
|
+
accessor: (_row, index) => index + 1,
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
header: "HMS ID",
|
|
11
|
+
accessor: "sk",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
header: "Name",
|
|
15
|
+
accessor: "name",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
header: "Email",
|
|
19
|
+
accessor: "email",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
header: "Phone",
|
|
23
|
+
accessor: "phoneNumber",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
header: "Address",
|
|
27
|
+
accessor: "address",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
header: "DOB",
|
|
31
|
+
accessor: (row) => row.dob ? new Date(row.dob).toLocaleDateString() : "-",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
header: "Relation",
|
|
35
|
+
accessor: "contactRelation",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
header: "Contact Name",
|
|
39
|
+
accessor: "contactPersonName",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
header: "Contact Phone",
|
|
43
|
+
accessor: "contactPersonNumber",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
header: "Aadhaar No",
|
|
47
|
+
accessor: "aadhaarNumber",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
header: "Admin",
|
|
51
|
+
accessor: (row) => roleMap[row.sk] ?? "NO ROLE",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
header: "Status",
|
|
55
|
+
accessor: (row) => (_jsx(Badge, { bg: row.status === Status.Active ? "success" : "danger", children: row.status })),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
header: "Created Date",
|
|
59
|
+
accessor: (row) => row.createdDt
|
|
60
|
+
? new Date(row.createdDt).toLocaleString()
|
|
61
|
+
: "-",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
header: "Created By",
|
|
65
|
+
accessor: "createdBy",
|
|
66
|
+
},
|
|
67
|
+
];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Status } from "../../domain/type/StatusEnum";
|
|
3
|
+
export const profileSchema = z.object({
|
|
4
|
+
pk: z.string().catch(""), // required output, never undefined
|
|
5
|
+
customId: z.string()
|
|
6
|
+
.min(5, "ID must be at least 5 characters"),
|
|
7
|
+
name: z.string()
|
|
8
|
+
.min(3, "Name must be at least 3 characters")
|
|
9
|
+
.regex(/^[A-Za-z\s]+$/, "Name should contain only letters"),
|
|
10
|
+
email: z.string()
|
|
11
|
+
.email("Invalid email address"),
|
|
12
|
+
phoneNumber: z.string()
|
|
13
|
+
.regex(/^[0-9]{10}$/, "Phone number must be 10 digits"),
|
|
14
|
+
address: z.string()
|
|
15
|
+
.min(5, "Address must be at least 5 characters"),
|
|
16
|
+
dob: z.string()
|
|
17
|
+
.min(1, "Date of Birth is required"),
|
|
18
|
+
contactRelation: z.string()
|
|
19
|
+
.min(1, "Contact person relation is required"),
|
|
20
|
+
contactPersonName: z.string()
|
|
21
|
+
.min(3, "Contact person name must be at least 3 characters")
|
|
22
|
+
.regex(/^[A-Za-z\s]+$/, "Contact person name must contain only letters"),
|
|
23
|
+
contactPersonNumber: z.string()
|
|
24
|
+
.regex(/^[0-9]{10}$/, "Contact person number must be 10 digits"),
|
|
25
|
+
aadhaarNumber: z.string()
|
|
26
|
+
.regex(/^[0-9]{12}$/, "Aadhaar number must be 12 digits"),
|
|
27
|
+
aadhaarFile: z
|
|
28
|
+
.any()
|
|
29
|
+
.optional(), // File input (image/pdf)
|
|
30
|
+
status: z.enum(Status).optional(),
|
|
31
|
+
isAdmin: z.boolean().optional(),
|
|
32
|
+
});
|
|
33
|
+
export const useProfileSchema = () => ({
|
|
34
|
+
profileSchema,
|
|
35
|
+
initiateProfile: {
|
|
36
|
+
pk: "",
|
|
37
|
+
customId: "",
|
|
38
|
+
name: "",
|
|
39
|
+
email: "",
|
|
40
|
+
phoneNumber: "",
|
|
41
|
+
address: "",
|
|
42
|
+
dob: "",
|
|
43
|
+
contactRelation: "",
|
|
44
|
+
contactPersonName: "",
|
|
45
|
+
contactPersonNumber: "",
|
|
46
|
+
aadhaarNumber: "",
|
|
47
|
+
aadhaarFile: undefined,
|
|
48
|
+
status: Status.Active,
|
|
49
|
+
}
|
|
50
|
+
});
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useContext, useEffect, useState } from "react";
|
|
3
|
+
import { transformdToPrefixDescription, useGetSettingsByPk, useUpdateSettingsMutation } from "../api/settings-api";
|
|
4
|
+
import { Button, Card, Col, Container, Form, Modal, Row } from "react-bootstrap";
|
|
5
|
+
import { toast } from "react-toastify";
|
|
6
|
+
import { BsPencilSquare, BsCheckCircle, BsXCircle, BsInfoCircle } from "react-icons/bs";
|
|
7
|
+
import './SettingsPage.css';
|
|
8
|
+
import { ALL, BOOKING_RECEIPT_PREFIX_FORMAT, BOOKING_RECEIPT_RESETTING_PERIOD, BOOKING_RECEIPT_SEQUENCE_PADDING, BOOKING_RECEIPT_SERIES_NUMBER, HIDE_SIGN_UP, INVOICE_PREFIX_FORMAT, INVOICE_RESETTING_PERIOD, INVOICE_SEQUENCE_PADDING, INVOICE_SERIES_NUMBER, NEVER, PURCHASE_ORDER_PREFIX_FORMAT, PURCHASE_ORDER_RESETTING_PERIOD, PURCHASE_ORDER_SEQUENCE_PADDING, RESERVATION_PREFIX_FORMAT, RESERVATION_RESETTING_PERIOD, RESERVATION_SEQUENCE_PADDING } from "../../static/constants";
|
|
9
|
+
import Select from "react-select";
|
|
10
|
+
import { ResettingPeriodOptions } from "../../domain/type/ResettingPeriodOptions";
|
|
11
|
+
import { initPrefixDescription } from "../../domain/model/PrefixDescriptionDto";
|
|
12
|
+
import { resettingOptions, validateFirstOccurance, validateFullWrapper } from "../../util/prefixAndResettingValidation";
|
|
13
|
+
import { logger } from "../../util/Logger";
|
|
14
|
+
import AppContext from "../../store/AppContext";
|
|
15
|
+
import { sighUpOptions } from "../../domain/type/signUpOptions";
|
|
16
|
+
import { Roles } from "../../domain/type/RolesEnum";
|
|
17
|
+
const SettingsPage = () => {
|
|
18
|
+
const { user } = useContext(AppContext) ?? { user: undefined };
|
|
19
|
+
const rawBranch = user?.branchId ?? "";
|
|
20
|
+
const parts = rawBranch.split("#");
|
|
21
|
+
const branchId = parts[1];
|
|
22
|
+
const userRoles = user?.roles ?? [];
|
|
23
|
+
const { settingsByPK } = useGetSettingsByPk(branchId);
|
|
24
|
+
const updateSettingsMutation = useUpdateSettingsMutation();
|
|
25
|
+
const [editStates, setEditStates] = useState({});
|
|
26
|
+
const [activeEditKey, setActiveEditKey] = useState(null);
|
|
27
|
+
const defaultInvResettingPeriodOption = ResettingPeriodOptions.find(option => option.value === "");
|
|
28
|
+
const [selectedInvResettingPeriod, setSelectedInvResettingPeriod] = useState(defaultInvResettingPeriodOption);
|
|
29
|
+
const defaultPurchaseOrderResetPeriodOption = ResettingPeriodOptions.find(option => option.value === "");
|
|
30
|
+
const [selectedPurchaseOrderResettingPeriod, setSelectedPurchaseOrdResettingPeriod] = useState(defaultPurchaseOrderResetPeriodOption);
|
|
31
|
+
const defaultReservationResetPeriodOption = ResettingPeriodOptions.find(option => option.value === "");
|
|
32
|
+
const [selectedReservationResettingPeriod, setSelectedReservationResettingPeriod] = useState(defaultReservationResetPeriodOption);
|
|
33
|
+
const defaultBookingReceiptResetPeriodOption = ResettingPeriodOptions.find(option => option.value === "");
|
|
34
|
+
const [selectedBookingReceiptResettingPeriod, setSelectedBookingReceiptResettingPeriod] = useState(defaultBookingReceiptResetPeriodOption);
|
|
35
|
+
const [showPrefixInfo, setShowPrefixInfo] = useState(false);
|
|
36
|
+
const [prefixDescription, setPrefixDescription] = useState(initPrefixDescription);
|
|
37
|
+
const defaultSignUpOption = sighUpOptions.find(option => option.value === "");
|
|
38
|
+
const [selectedSignUpOption, setSelectedSighUpOPtion] = useState(defaultSignUpOption);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (settingsByPK && settingsByPK.length > 0) {
|
|
41
|
+
const invResetPeriod = settingsByPK.find((setting) => setting.sk === INVOICE_RESETTING_PERIOD);
|
|
42
|
+
const purchaseOrdResetPeriod = settingsByPK.find((setting) => setting.sk === PURCHASE_ORDER_RESETTING_PERIOD);
|
|
43
|
+
const reservationResetPeriod = settingsByPK.find((setting) => setting.sk === RESERVATION_RESETTING_PERIOD);
|
|
44
|
+
const bookingReceiptResetPeriod = settingsByPK.find((setting) => setting.sk === BOOKING_RECEIPT_RESETTING_PERIOD);
|
|
45
|
+
const hideSignUp = settingsByPK.find((setting) => setting.sk === HIDE_SIGN_UP);
|
|
46
|
+
setSelectedInvResettingPeriod({ label: invResetPeriod?.value ?? '', value: invResetPeriod?.sk ?? '' });
|
|
47
|
+
setSelectedPurchaseOrdResettingPeriod({ label: purchaseOrdResetPeriod?.value ?? '', value: purchaseOrdResetPeriod?.sk ?? '' });
|
|
48
|
+
setSelectedReservationResettingPeriod({ label: reservationResetPeriod?.value ?? '', value: reservationResetPeriod?.sk ?? '' });
|
|
49
|
+
setSelectedBookingReceiptResettingPeriod({ label: bookingReceiptResetPeriod?.value ?? '', value: bookingReceiptResetPeriod?.sk ?? '' });
|
|
50
|
+
setSelectedSighUpOPtion({ label: hideSignUp?.value ?? '', value: hideSignUp?.sk ?? '' });
|
|
51
|
+
}
|
|
52
|
+
}, [settingsByPK]);
|
|
53
|
+
const handleEdit = (sk, currentValue) => {
|
|
54
|
+
setActiveEditKey(sk);
|
|
55
|
+
setEditStates((prev) => ({
|
|
56
|
+
...prev,
|
|
57
|
+
[sk]: { isEditing: true, value: currentValue }
|
|
58
|
+
}));
|
|
59
|
+
};
|
|
60
|
+
const handleCancel = (sk) => {
|
|
61
|
+
setActiveEditKey(null);
|
|
62
|
+
setEditStates((prev) => ({
|
|
63
|
+
...prev,
|
|
64
|
+
[sk]: { isEditing: false, value: prev[sk]?.value || "" },
|
|
65
|
+
}));
|
|
66
|
+
};
|
|
67
|
+
const handleChange = (sk, newValue) => {
|
|
68
|
+
setEditStates((prev) => ({ ...prev, [sk]: { ...prev[sk], value: newValue }, }));
|
|
69
|
+
};
|
|
70
|
+
const handleResettingPeriodChange = (sk, selectedOption) => {
|
|
71
|
+
if (selectedOption) {
|
|
72
|
+
const selectedVal = selectedOption.value;
|
|
73
|
+
setEditStates((prev) => ({ ...prev, [sk]: { ...prev[sk], value: selectedVal }, }));
|
|
74
|
+
if (sk === INVOICE_RESETTING_PERIOD) {
|
|
75
|
+
setSelectedInvResettingPeriod({ label: selectedVal, value: sk ?? '' });
|
|
76
|
+
}
|
|
77
|
+
else if (sk === PURCHASE_ORDER_RESETTING_PERIOD) {
|
|
78
|
+
setSelectedPurchaseOrdResettingPeriod({ label: selectedVal, value: sk ?? '' });
|
|
79
|
+
}
|
|
80
|
+
else if (sk === RESERVATION_RESETTING_PERIOD) {
|
|
81
|
+
setSelectedReservationResettingPeriod({ label: selectedVal, value: sk ?? '' });
|
|
82
|
+
}
|
|
83
|
+
else if (sk === BOOKING_RECEIPT_RESETTING_PERIOD) {
|
|
84
|
+
setSelectedBookingReceiptResettingPeriod({ label: selectedVal, value: sk ?? '' });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const upsertSettingsMutationFn = (settingsData) => {
|
|
89
|
+
try {
|
|
90
|
+
return new Promise((resolve, reject) => {
|
|
91
|
+
updateSettingsMutation.mutate(settingsData, {
|
|
92
|
+
onSuccess: (_res) => {
|
|
93
|
+
toast.success("Settings update successfully!");
|
|
94
|
+
resolve();
|
|
95
|
+
},
|
|
96
|
+
onError: (err) => {
|
|
97
|
+
toast.error("Error while request the Product");
|
|
98
|
+
reject(err);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
logger.error("error at product request updation", err);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const validatePrefixResetting = (prefixSk, resetSk) => {
|
|
108
|
+
const prefix = editStates[prefixSk]?.value ||
|
|
109
|
+
settingsByPK?.find(s => s.sk === prefixSk)?.value || "";
|
|
110
|
+
const resettingPeriod = editStates[resetSk]?.value ||
|
|
111
|
+
settingsByPK?.find(s => s.sk === resetSk)?.value || "";
|
|
112
|
+
const allowedPrefix = /^[a-zA-Z]+$/.test(prefix);
|
|
113
|
+
if (allowedPrefix) {
|
|
114
|
+
return true; // bypass resetting validation for custom prefixes
|
|
115
|
+
}
|
|
116
|
+
const allowedPeriods = getAllowedResettingPeriods(prefix).map(opt => opt.value);
|
|
117
|
+
if (!allowedPeriods.includes(resettingPeriod)) {
|
|
118
|
+
toast.info("Resetting period is not suitable for prefix format. Please select other resetting options before updating prefix.");
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
};
|
|
123
|
+
const handleUpdate = (settingData) => {
|
|
124
|
+
const newValue = editStates[settingData.sk]?.value;
|
|
125
|
+
// ✅ Series number validation (must be greater than existing)
|
|
126
|
+
if (settingData.sk === INVOICE_SERIES_NUMBER ||
|
|
127
|
+
settingData.sk === BOOKING_RECEIPT_SERIES_NUMBER) {
|
|
128
|
+
const existingValue = Number(settingData.value);
|
|
129
|
+
const enteredValue = Number(newValue);
|
|
130
|
+
if (isNaN(enteredValue)) {
|
|
131
|
+
toast.error("Please enter a valid number.");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (enteredValue <= existingValue) {
|
|
135
|
+
toast.error(`New series number must be greater than existing value (${existingValue}).`);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const allowedPrefix = (settingData.sk === INVOICE_PREFIX_FORMAT || settingData.sk === BOOKING_RECEIPT_PREFIX_FORMAT) && /^[a-zA-Z]+$/.test(newValue);
|
|
140
|
+
// check allowed predefined constant usage -----
|
|
141
|
+
if (settingData.sk === INVOICE_PREFIX_FORMAT || settingData.sk === PURCHASE_ORDER_PREFIX_FORMAT || settingData.sk === RESERVATION_PREFIX_FORMAT || settingData.sk === BOOKING_RECEIPT_PREFIX_FORMAT) {
|
|
142
|
+
const invalidWrapper = validateFullWrapper(newValue);
|
|
143
|
+
if (invalidWrapper && !allowedPrefix) {
|
|
144
|
+
toast.info("Predefined constants only allowed. Please check the prefix format.");
|
|
145
|
+
return; // stop update
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// first occurance check-------------
|
|
149
|
+
if (settingData.sk === INVOICE_PREFIX_FORMAT || settingData.sk === PURCHASE_ORDER_PREFIX_FORMAT || settingData.sk === RESERVATION_PREFIX_FORMAT || settingData.sk === BOOKING_RECEIPT_PREFIX_FORMAT) {
|
|
150
|
+
const { firstWrapper, validTokens } = validateFirstOccurance(newValue);
|
|
151
|
+
if (!allowedPrefix) {
|
|
152
|
+
if (!firstWrapper || !validTokens.includes(firstWrapper)) {
|
|
153
|
+
toast.info("Predefined constant must start with {FY}, {fy}, {Y}, {y}, {M}, or {D}.");
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// check prefix and resetting combination ----------
|
|
159
|
+
if (settingData.sk === INVOICE_PREFIX_FORMAT || settingData.sk === INVOICE_RESETTING_PERIOD) {
|
|
160
|
+
if (!validatePrefixResetting(INVOICE_PREFIX_FORMAT, INVOICE_RESETTING_PERIOD))
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (settingData.sk === PURCHASE_ORDER_PREFIX_FORMAT || settingData.sk === PURCHASE_ORDER_RESETTING_PERIOD) {
|
|
164
|
+
if (!validatePrefixResetting(PURCHASE_ORDER_PREFIX_FORMAT, PURCHASE_ORDER_RESETTING_PERIOD))
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (settingData.sk === RESERVATION_PREFIX_FORMAT || settingData.sk === RESERVATION_RESETTING_PERIOD) {
|
|
168
|
+
if (!validatePrefixResetting(RESERVATION_PREFIX_FORMAT, RESERVATION_RESETTING_PERIOD))
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (settingData.sk === BOOKING_RECEIPT_PREFIX_FORMAT || settingData.sk === BOOKING_RECEIPT_RESETTING_PERIOD) {
|
|
172
|
+
if (!validatePrefixResetting(BOOKING_RECEIPT_PREFIX_FORMAT, BOOKING_RECEIPT_RESETTING_PERIOD))
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
setActiveEditKey(null);
|
|
176
|
+
setEditStates((prev) => ({
|
|
177
|
+
...prev,
|
|
178
|
+
[settingData.sk]: { isEditing: false, value: newValue || "" }
|
|
179
|
+
}));
|
|
180
|
+
settingData.value = newValue;
|
|
181
|
+
// don't change pk for sign up option if super admin
|
|
182
|
+
settingData.pk = (settingData.pk === ALL && settingData.sk === HIDE_SIGN_UP && userRoles.includes(Roles.SuperAdmin)) ? settingData.pk : branchId;
|
|
183
|
+
upsertSettingsMutationFn(settingData);
|
|
184
|
+
};
|
|
185
|
+
const getAllowedResettingPeriods = (prefix) => {
|
|
186
|
+
if (!prefix) {
|
|
187
|
+
return ResettingPeriodOptions.filter(opt => opt.value === NEVER);
|
|
188
|
+
}
|
|
189
|
+
const firstMatch = resettingOptions(prefix);
|
|
190
|
+
if (firstMatch) {
|
|
191
|
+
return ResettingPeriodOptions.filter(opt => firstMatch.periods.includes(opt.value));
|
|
192
|
+
}
|
|
193
|
+
// NONE prefix → only NEVER
|
|
194
|
+
return ResettingPeriodOptions.filter(opt => opt.value === NEVER);
|
|
195
|
+
};
|
|
196
|
+
const handleSignUpOptionChange = (sk, selectedOption) => {
|
|
197
|
+
if (selectedOption) {
|
|
198
|
+
const selectedVal = selectedOption.value;
|
|
199
|
+
setEditStates((prev) => ({ ...prev, [sk]: { ...prev[sk], value: selectedVal }, }));
|
|
200
|
+
setSelectedSighUpOPtion({ label: selectedVal, value: sk ?? '' });
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
return (_jsxs(Container, { className: "mt-4", children: [settingsByPK && settingsByPK.length > 0 && (_jsxs(Card, { className: "shadow-lg settings-card", children: [_jsx(Card.Header, { className: "fw-bold", children: "Settings" }), _jsx(Card.Body, { children: settingsByPK.map((setting) => {
|
|
204
|
+
const editState = editStates[setting.sk] || { isEditing: false, value: setting.value };
|
|
205
|
+
const isActive = activeEditKey === setting.sk;
|
|
206
|
+
return (_jsxs(Row, { className: "align-items-center mb-3", children: [_jsxs(Col, { xs: 3, sm: 3, md: 3, lg: 5, xl: 5, className: "fw-bold settings-key-col", children: [setting.pk === ALL && setting.sk === HIDE_SIGN_UP && !userRoles.includes(Roles.SuperAdmin) ? "" : setting.sk, (setting.sk === INVOICE_PREFIX_FORMAT || setting.sk === PURCHASE_ORDER_PREFIX_FORMAT || setting.sk === RESERVATION_PREFIX_FORMAT || setting.sk === BOOKING_RECEIPT_PREFIX_FORMAT) && (_jsx(Button, { size: "sm", variant: "link", className: "ms-2 p-0 text-info mb-1", onClick: () => {
|
|
207
|
+
setShowPrefixInfo(true);
|
|
208
|
+
setPrefixDescription(transformdToPrefixDescription(setting.description));
|
|
209
|
+
}, children: _jsx(BsInfoCircle, { className: "info-icon" }) }))] }), _jsx(Col, { xs: 3, sm: 3, md: 5, lg: 5, xl: 5, className: "settings-value-col", children: !isActive ? (_jsx("span", { children: setting.pk === ALL && setting.sk === HIDE_SIGN_UP && !userRoles.includes(Roles.SuperAdmin) ? "" : setting.value })) : (_jsxs(_Fragment, { children: [(setting.sk === INVOICE_RESETTING_PERIOD || setting.sk === PURCHASE_ORDER_RESETTING_PERIOD || setting.sk === RESERVATION_RESETTING_PERIOD || setting.sk === BOOKING_RECEIPT_RESETTING_PERIOD) ?
|
|
210
|
+
_jsx(Select, { options: getAllowedResettingPeriods(setting.sk === INVOICE_RESETTING_PERIOD
|
|
211
|
+
? settingsByPK.find(s => s.sk === INVOICE_PREFIX_FORMAT)?.value ?? ""
|
|
212
|
+
: setting.sk === PURCHASE_ORDER_RESETTING_PERIOD
|
|
213
|
+
? settingsByPK.find(s => s.sk === PURCHASE_ORDER_PREFIX_FORMAT)?.value ?? ""
|
|
214
|
+
: setting.sk === RESERVATION_RESETTING_PERIOD
|
|
215
|
+
? settingsByPK.find(s => s.sk === RESERVATION_PREFIX_FORMAT)?.value ?? ""
|
|
216
|
+
: settingsByPK.find(s => s.sk === BOOKING_RECEIPT_PREFIX_FORMAT)?.value ?? ""), value: setting.sk === INVOICE_RESETTING_PERIOD
|
|
217
|
+
? selectedInvResettingPeriod
|
|
218
|
+
: setting.sk === PURCHASE_ORDER_RESETTING_PERIOD
|
|
219
|
+
? selectedPurchaseOrderResettingPeriod
|
|
220
|
+
: setting.sk === RESERVATION_RESETTING_PERIOD
|
|
221
|
+
? selectedReservationResettingPeriod
|
|
222
|
+
: selectedBookingReceiptResettingPeriod, onChange: (selectedOption) => selectedOption && handleResettingPeriodChange(setting.sk, selectedOption), placeholder: "Select resetting period", className: "resetting-period-select", maxMenuHeight: 200 }) : (setting.pk === ALL && setting.sk === HIDE_SIGN_UP && userRoles.includes(Roles.SuperAdmin)) ?
|
|
223
|
+
_jsx(Select, { options: sighUpOptions, value: selectedSignUpOption, onChange: (selectedOption) => selectedOption && handleSignUpOptionChange(setting.sk, selectedOption), placeholder: "Select Sign up option", className: "resetting-period-select", maxMenuHeight: 200 }) :
|
|
224
|
+
(setting.sk === INVOICE_PREFIX_FORMAT ||
|
|
225
|
+
setting.sk === PURCHASE_ORDER_PREFIX_FORMAT ||
|
|
226
|
+
setting.sk === RESERVATION_PREFIX_FORMAT ||
|
|
227
|
+
setting.sk === BOOKING_RECEIPT_PREFIX_FORMAT ||
|
|
228
|
+
setting.sk === INVOICE_SEQUENCE_PADDING ||
|
|
229
|
+
setting.sk === PURCHASE_ORDER_SEQUENCE_PADDING ||
|
|
230
|
+
setting.sk === RESERVATION_SEQUENCE_PADDING ||
|
|
231
|
+
setting.sk === BOOKING_RECEIPT_SEQUENCE_PADDING ||
|
|
232
|
+
setting.sk === INVOICE_SERIES_NUMBER ||
|
|
233
|
+
setting.sk === BOOKING_RECEIPT_SERIES_NUMBER) ?
|
|
234
|
+
_jsx(Form.Control, { type: (setting.sk === INVOICE_SEQUENCE_PADDING || setting.sk === PURCHASE_ORDER_SEQUENCE_PADDING || setting.sk === RESERVATION_SEQUENCE_PADDING || setting.sk === BOOKING_RECEIPT_SEQUENCE_PADDING) ? 'number' : 'text', value: editState.value, onChange: (e) => handleChange(setting.sk, e.target.value), className: "settings-value-form-control" })
|
|
235
|
+
: null, ((setting.sk === INVOICE_SEQUENCE_PADDING) || (setting.sk === PURCHASE_ORDER_SEQUENCE_PADDING) || (setting.sk === RESERVATION_SEQUENCE_PADDING) || (setting.sk === BOOKING_RECEIPT_SEQUENCE_PADDING)) &&
|
|
236
|
+
_jsx("label", { className: "seq-pad-info text-primary", children: setting.description })] })) }), setting.pk === ALL && setting.sk === HIDE_SIGN_UP && !userRoles.includes(Roles.SuperAdmin) ? null :
|
|
237
|
+
_jsx(Col, { xs: 3, sm: 3, md: 4, lg: 5, xl: 5, className: "text-end settings-btns", children: !isActive ? (_jsx(Button, { size: "sm", variant: "outline-primary", className: "edit-btn", onClick: () => handleEdit(setting.sk, setting.value), children: _jsx(BsPencilSquare, {}) })) : (_jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", variant: "success", className: "me-2 update-btn", onClick: () => handleUpdate(setting), children: _jsx(BsCheckCircle, {}) }), _jsx(Button, { size: "sm", variant: "secondary", className: "cancel-btn", onClick: () => handleCancel(setting.sk), children: _jsx(BsXCircle, {}) })] })) })] }, setting.sk));
|
|
238
|
+
}) })] })), _jsxs(Modal, { show: showPrefixInfo, onHide: () => setShowPrefixInfo(false), size: "lg", centered: true, children: [_jsx(Modal.Header, { closeButton: true, children: _jsx(Modal.Title, { children: "Prefix Format Info" }) }), _jsxs(Modal.Body, { children: [_jsx("p", { className: "fw-bold", children: prefixDescription.message }), prefixDescription.constants.map((constant, index) => (_jsxs("p", { children: [constant.constant, " - ", constant.description] }, index))), _jsx("b", { className: "text-success", children: "Example:" }), _jsxs("p", { children: [_jsx("strong", { children: "Prefix:" }), " ", prefixDescription.example.prefixFormat] }), _jsxs("p", { children: [_jsx("strong", { children: "Result:" }), " ", prefixDescription.example.outputValue] })] }), _jsx(Modal.Footer, { children: _jsx(Button, { variant: "secondary", onClick: () => setShowPrefixInfo(false), children: "Close" }) })] })] }));
|
|
239
|
+
};
|
|
240
|
+
export default SettingsPage;
|