ui-soxo-bootstrap-core 2.6.5 → 2.6.6
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/.babelrc +8 -8
- package/.github/workflows/npm-publish.yml +33 -33
- package/.husky/pre-commit +11 -11
- package/.prettierrc.json +10 -10
- package/babel.config.js +2 -2
- package/core/components/component-loader/component-loader.js +125 -125
- package/core/components/component-wrapper/component-wrapper.js +121 -121
- package/core/components/external-window/DEVELOPER_GUIDE.md +705 -705
- package/core/components/external-window/external-window.js +236 -236
- package/core/components/external-window/external-window.test.js +80 -80
- package/core/components/extra-info/extra-info-details.js +155 -155
- package/core/components/extra-info/extra-info-details.scss +26 -26
- package/core/components/extra-info/extra-info.js +134 -134
- package/core/components/index.js +20 -20
- package/core/components/landing-api/landing-api.js +492 -492
- package/core/components/landing-api/landing-api.scss +19 -19
- package/core/components/menu-template-api/menu-template-api.js +321 -321
- package/core/components/root-application-api/root-application-api.js +174 -174
- package/core/index.js +13 -13
- package/core/lib/Store.js +365 -365
- package/core/lib/components/application-bootstrap/application-bootstrap.js +115 -115
- package/core/lib/components/approval-form/approval-form.js +280 -280
- package/core/lib/components/approval-form/approval-form.scss +183 -183
- package/core/lib/components/approval-list/approval-list.js +143 -143
- package/core/lib/components/approval-list/approval-list.scss +2 -2
- package/core/lib/components/approval-list/components/request-card/request-card.js +42 -42
- package/core/lib/components/approval-list/components/request-card/request-card.scss +30 -30
- package/core/lib/components/camera/camera.js +230 -230
- package/core/lib/components/camera/camera.scss +86 -86
- package/core/lib/components/comment-block/comment-block.js +138 -138
- package/core/lib/components/comment-block/comment-block.scss +3 -3
- package/core/lib/components/confirm-modal/confirm-modal.js +82 -82
- package/core/lib/components/confirm-modal/confirm-modal.scss +2 -2
- package/core/lib/components/consent/consent.js +67 -67
- package/core/lib/components/consent/pdf-signature.js +299 -299
- package/core/lib/components/consent/signature-pad.js +90 -90
- package/core/lib/components/consent/signature-pad.scss +14 -14
- package/core/lib/components/file-upload/file-upload.js +133 -133
- package/core/lib/components/finger-print-reader/finger-print-reader.js +295 -295
- package/core/lib/components/finger-print-reader/finger-print-reader.scss +47 -47
- package/core/lib/components/finger-print-search/finger-print-search.js +200 -200
- package/core/lib/components/finger-print-search/finger-print-search.scss +47 -47
- package/core/lib/components/global-header/animations.js +18 -18
- package/core/lib/components/global-header/global-header.js +413 -413
- package/core/lib/components/global-header/global-header.scss +369 -369
- package/core/lib/components/header/generic-header.js +76 -76
- package/core/lib/components/header/generic-header.scss +99 -99
- package/core/lib/components/image-preview/image-preview.js +33 -33
- package/core/lib/components/image-wrapper/image-wrapper.js +108 -108
- package/core/lib/components/image-wrapper/image-wrapper.scss +12 -12
- package/core/lib/components/index.js +206 -206
- package/core/lib/components/landing/landing.js +403 -403
- package/core/lib/components/language-switcher/language-switcher.js +49 -49
- package/core/lib/components/menu-context/menu-context.js +69 -69
- package/core/lib/components/menu-template/menu-template.js +249 -249
- package/core/lib/components/menu-template/menu-template.scss +9 -9
- package/core/lib/components/modal-search/modal-search.js +153 -153
- package/core/lib/components/modal-search/modal-search.scss +78 -78
- package/core/lib/components/modal-wrapper/modal-manager.js +15 -15
- package/core/lib/components/modal-wrapper/modal-wrapper.js +108 -108
- package/core/lib/components/modal-wrapper/modal-wrapper.scss +13 -13
- package/core/lib/components/notice-board/notice-board.js +132 -132
- package/core/lib/components/notice-board/notice-board.scss +65 -65
- package/core/lib/components/page-container/page-container.js +55 -55
- package/core/lib/components/page-container/page-container.scss +8 -8
- package/core/lib/components/page-header/page-header.js +23 -23
- package/core/lib/components/page-header/page-header.scss +17 -17
- package/core/lib/components/pdf-viewer/pdf-viewer.js +56 -56
- package/core/lib/components/portlet-table/components/table-actions/table-actions.js +58 -58
- package/core/lib/components/portlet-table/components/table-actions/table-actions.scss +1 -1
- package/core/lib/components/portlet-table/components/table-data/table-data.js +106 -106
- package/core/lib/components/portlet-table/portlet-table.js +63 -63
- package/core/lib/components/portlet-table/portlet-table.scss +90 -90
- package/core/lib/components/progress-bar/progress-bar.js +58 -58
- package/core/lib/components/progress-bar/progress-bar.scss +15 -15
- package/core/lib/components/request-form/request-form.js +110 -110
- package/core/lib/components/root-application/root-application.js +70 -70
- package/core/lib/components/rupee/rupee.js +14 -14
- package/core/lib/components/script-input/script-input.js +169 -169
- package/core/lib/components/script-input/script-input.scss +8 -8
- package/core/lib/components/sidemenu/animations.js +51 -51
- package/core/lib/components/sidemenu/sidemenu.js +578 -578
- package/core/lib/components/sidemenu/sidemenu.scss +277 -277
- package/core/lib/components/spotlight-search/spotlight-search.component.js +635 -635
- package/core/lib/components/spotlight-search/spotlight-search.component.scss +78 -78
- package/core/lib/components/table-wrapper/table-wrapper.js +135 -135
- package/core/lib/components/table-wrapper/table-wrapper.scss +72 -72
- package/core/lib/components/ui_elements/Loader.js +12 -12
- package/core/lib/components/ui_elements/Notify.js +12 -12
- package/core/lib/components/ui_elements/PlaceHolder.js +33 -33
- package/core/lib/components/web-camera/web-camera.js +161 -161
- package/core/lib/components/web-camera/web-camera.scss +28 -28
- package/core/lib/core.md +9 -9
- package/core/lib/elements/Elements.md +2 -2
- package/core/lib/elements/basic/LoggedUserRedirect.js +21 -21
- package/core/lib/elements/basic/PrivateRoute.js +16 -16
- package/core/lib/elements/basic/button/Button.md +43 -43
- package/core/lib/elements/basic/button/button.js +170 -170
- package/core/lib/elements/basic/card/Card.md +15 -15
- package/core/lib/elements/basic/card/card.js +40 -40
- package/core/lib/elements/basic/card/card.scss +13 -13
- package/core/lib/elements/basic/checkbox/checkbox.js +23 -23
- package/core/lib/elements/basic/col/col.js +15 -15
- package/core/lib/elements/basic/copy-to-clipboard/Readme.md +40 -40
- package/core/lib/elements/basic/copy-to-clipboard/copy-to-clipboard.js +61 -61
- package/core/lib/elements/basic/country-phone-input/Readme.md +98 -98
- package/core/lib/elements/basic/country-phone-input/country-phone-input.js +106 -106
- package/core/lib/elements/basic/country-phone-input/phone-input.scss +61 -61
- package/core/lib/elements/basic/datepicker/datepicker.js +33 -33
- package/core/lib/elements/basic/dragabble-wrapper/draggable-wrapper.js +136 -136
- package/core/lib/elements/basic/empty/empty.js +14 -14
- package/core/lib/elements/basic/fingerprint-protrected/fingerprint-protected.js +118 -118
- package/core/lib/elements/basic/fingerprint-protrected/fingerprint-protected.scss +10 -10
- package/core/lib/elements/basic/form/form.js +70 -70
- package/core/lib/elements/basic/form/form.scss +3 -3
- package/core/lib/elements/basic/image/image.js +45 -45
- package/core/lib/elements/basic/image/image.scss +17 -17
- package/core/lib/elements/basic/image/readme.md +26 -26
- package/core/lib/elements/basic/image-viewer/image-viewer.js +108 -108
- package/core/lib/elements/basic/image-viewer/image-viewer.scss +7 -7
- package/core/lib/elements/basic/input/input.js +81 -81
- package/core/lib/elements/basic/input/readme.md +77 -77
- package/core/lib/elements/basic/json-input/json-input.js +51 -51
- package/core/lib/elements/basic/menu-dashboard/menu-dashboard.js +216 -216
- package/core/lib/elements/basic/menu-dashboard/menu-dashboard.scss +28 -28
- package/core/lib/elements/basic/menu-tree/menu-tree.js +114 -114
- package/core/lib/elements/basic/modal/modal.js +64 -64
- package/core/lib/elements/basic/modal/readme.md +62 -62
- package/core/lib/elements/basic/popconfirm/popconfirm.js +17 -17
- package/core/lib/elements/basic/popover/popover.js +12 -12
- package/core/lib/elements/basic/radio/radio.js +18 -18
- package/core/lib/elements/basic/rangepicker/rangepicker.js +141 -141
- package/core/lib/elements/basic/rangepicker/rangepicker.scss +24 -24
- package/core/lib/elements/basic/rangepicker/readme.md +81 -81
- package/core/lib/elements/basic/reference-select/readme.md +18 -18
- package/core/lib/elements/basic/reference-select/reference-select.js +337 -337
- package/core/lib/elements/basic/row/row.js +15 -15
- package/core/lib/elements/basic/select/select.js +46 -46
- package/core/lib/elements/basic/select-box/readme.md +52 -52
- package/core/lib/elements/basic/select-box/select-box.js +63 -63
- package/core/lib/elements/basic/skeleton/readme.md +35 -35
- package/core/lib/elements/basic/skeleton/skeleton.js +35 -35
- package/core/lib/elements/basic/skeleton/skeleton.scss +53 -53
- package/core/lib/elements/basic/space/space.js +12 -12
- package/core/lib/elements/basic/switch/readme.md +29 -29
- package/core/lib/elements/basic/switch/switch.js +67 -67
- package/core/lib/elements/basic/tab/tab.js +14 -14
- package/core/lib/elements/basic/table/readme.md +8 -8
- package/core/lib/elements/basic/table/table.js +100 -100
- package/core/lib/elements/basic/tag/tag.js +63 -63
- package/core/lib/elements/basic/tag/tag.scss +2 -2
- package/core/lib/elements/basic/timeline/timeline.js +13 -13
- package/core/lib/elements/basic/title/readme.md +20 -20
- package/core/lib/elements/basic/title/title.js +37 -37
- package/core/lib/elements/basic/user-search/user-search.js +192 -192
- package/core/lib/elements/complex/barcode/barcode.js +27 -27
- package/core/lib/elements/complex/bargraph/bar-graph.js +262 -262
- package/core/lib/elements/complex/basic-table/basic-table.js +110 -110
- package/core/lib/elements/complex/basic-table/basic-table.scss +4 -4
- package/core/lib/elements/complex/date-display/date-display.js +37 -37
- package/core/lib/elements/complex/error-boundary/error-boundary.js +29 -29
- package/core/lib/elements/complex/google-location-input/map-container-library-load.js +92 -92
- package/core/lib/elements/complex/google-map/google-map.js +230 -230
- package/core/lib/elements/complex/google-map/google-map.scss +13 -13
- package/core/lib/elements/complex/line-graph/line-graph.js +108 -108
- package/core/lib/elements/complex/location-search-input/location-search-input.js +100 -100
- package/core/lib/elements/complex/pie-chart/pie-chart.js +202 -202
- package/core/lib/elements/complex/qr-code/qr-code.js +27 -27
- package/core/lib/elements/complex/qrscanner/qrscanner.js +57 -57
- package/core/lib/elements/complex/search-debounce/search-debounce.js +37 -37
- package/core/lib/elements/complex/statistic-card/dashboard-statistic-card.js +75 -75
- package/core/lib/elements/complex/statistic-card/statistic-card.js +28 -28
- package/core/lib/elements/index.js +226 -226
- package/core/lib/hooks/device-detect.js +25 -25
- package/core/lib/hooks/index.js +9 -9
- package/core/lib/hooks/use-location.js +33 -33
- package/core/lib/hooks/use-otp-timer.js +80 -80
- package/core/lib/hooks/use-window-size.js +34 -34
- package/core/lib/i18n.js +69 -69
- package/core/lib/index.js +106 -106
- package/core/lib/introduction.md +73 -73
- package/core/lib/js-styleguide.md +4112 -4112
- package/core/lib/models/actions/actions.js +127 -127
- package/core/lib/models/actions/components/action-detail/action-detail.js +190 -190
- package/core/lib/models/actions/components/custom-actions/custom-actions.js +185 -185
- package/core/lib/models/attachments/attachments.js +231 -231
- package/core/lib/models/base-loader.js +99 -99
- package/core/lib/models/base.js +716 -716
- package/core/lib/models/branches/branches.js +125 -125
- package/core/lib/models/checklists/checklists.js +114 -114
- package/core/lib/models/columns/columns.js +169 -169
- package/core/lib/models/columns/components/columns-add/columns-add.js +171 -171
- package/core/lib/models/comments/comments.js +213 -213
- package/core/lib/models/departments/departments.js +107 -107
- package/core/lib/models/financial-years/financial_years.js +127 -127
- package/core/lib/models/forms/components/form-creator/form-creator.js +624 -624
- package/core/lib/models/forms/components/form-creator/form-creator.scss +30 -29
- package/core/lib/models/forms/components/form-detail/form-detail.js +224 -224
- package/core/lib/models/forms/forms.js +121 -121
- package/core/lib/models/index.js +203 -203
- package/core/lib/models/invoice-numbers/invoice_numbers.js +204 -204
- package/core/lib/models/lookup-types/components/lookup-detail/lookup-detail.js +145 -145
- package/core/lib/models/lookup-types/lookup-types.js +113 -113
- package/core/lib/models/lookup-values/components/lookup-values-add/lookup-values-add.js +126 -126
- package/core/lib/models/lookup-values/lookup-values.js +107 -107
- package/core/lib/models/menu-roles/menu-roles.js +127 -127
- package/core/lib/models/menus/components/menu-add/menu-add.js +228 -228
- package/core/lib/models/menus/components/menu-detail/menu-detail.js +170 -170
- package/core/lib/models/menus/components/menu-list/menu-list.js +593 -593
- package/core/lib/models/menus/components/menu-list/menu-list.scss +5 -5
- package/core/lib/models/menus/components/menu-roles-add/menu-roles-add.js +183 -183
- package/core/lib/models/menus/menus.js +499 -499
- package/core/lib/models/models/components/model-detail/model-detail.js +137 -137
- package/core/lib/models/models/components/models.js +128 -128
- package/core/lib/models/modules/modules.js +204 -204
- package/core/lib/models/outbox/outbox.js +73 -73
- package/core/lib/models/pages/pages.js +107 -107
- package/core/lib/models/permissions/permissions.js +71 -71
- package/core/lib/models/process/components/process-add/process-add.js +181 -181
- package/core/lib/models/process/components/process-dashboard/process-dashboard.js +601 -601
- package/core/lib/models/process/components/process-dashboard/process-dashboard.scss +62 -62
- package/core/lib/models/process/components/process-detail/process-detail.js +140 -140
- package/core/lib/models/process/components/process-timeline/process-timeline.js +139 -139
- package/core/lib/models/process/components/task-detail/task-detail.js +240 -240
- package/core/lib/models/process/components/task-detail/task-detail.scss +27 -27
- package/core/lib/models/process/components/task-form/task-form.js +528 -528
- package/core/lib/models/process/components/task-form/task-form.scss +7 -7
- package/core/lib/models/process/components/task-list/task-list.js +221 -221
- package/core/lib/models/process/components/task-list/task-list.scss +14 -14
- package/core/lib/models/process/components/task-overview/task-overview.js +299 -299
- package/core/lib/models/process/components/task-overview-legacy/task-overview-legacy.js +192 -192
- package/core/lib/models/process/components/task-routes/task-routes.js +45 -45
- package/core/lib/models/process/components/task-status/task-status.js +175 -175
- package/core/lib/models/process/components/task-status/task-status.scss +11 -11
- package/core/lib/models/process/process.js +780 -780
- package/core/lib/models/process-transactions/process-transactions.js +123 -123
- package/core/lib/models/roles/roles.js +106 -106
- package/core/lib/models/scripts/scripts.js +111 -111
- package/core/lib/models/step-transactions/step-transcations.js +147 -147
- package/core/lib/models/steps/components/step-add/step-add.js +261 -261
- package/core/lib/models/steps/components/step-detail/step-detail.js +157 -157
- package/core/lib/models/steps/steps.js +356 -356
- package/core/lib/models/user-preferences/user-preferences.js +83 -83
- package/core/lib/models/users/components/user-add/user-add.js +226 -226
- package/core/lib/models/users/users.js +119 -119
- package/core/lib/modules/business/launch-page/launch-page.js +29 -29
- package/core/lib/modules/business/launch-page/launch-page.scss +5 -5
- package/core/lib/modules/business/slots/slots.js +231 -231
- package/core/lib/modules/business/slots/slots.scss +108 -108
- package/core/lib/modules/forms/components/field-customizer/field-customizer.js +138 -138
- package/core/lib/modules/forms/components/field-selector/field-selector.js +157 -157
- package/core/lib/modules/forms/components/field-selector/field-selector.scss +25 -25
- package/core/lib/modules/forms/components/form-display/form-display.js +203 -203
- package/core/lib/modules/forms/components/form-display/form-display.scss +9 -9
- package/core/lib/modules/forms/components/tab-customizer/tab-customizer.js +124 -124
- package/core/lib/modules/generic/generic-add/generic-add.js +213 -213
- package/core/lib/modules/generic/generic-detail/generic-detail.js +199 -199
- package/core/lib/modules/generic/generic-edit/generic-edit.js +120 -120
- package/core/lib/modules/generic/generic-list/ExportReactCSV.js +62 -62
- package/core/lib/modules/generic/generic-list/generic-list.js +705 -705
- package/core/lib/modules/generic/generic-list/generic-list.scss +34 -34
- package/core/lib/modules/generic/generic-upload/generic-upload.js +483 -483
- package/core/lib/modules/generic/table-settings/table-settings.js +226 -226
- package/core/lib/modules/generic/table-settings/table-settings.scss +37 -37
- package/core/lib/modules/index.js +52 -52
- package/core/lib/modules/modules-routes/module-routes.js +35 -35
- package/core/lib/pages/change-password/change-password.js +201 -201
- package/core/lib/pages/change-password/change-password.scss +73 -73
- package/core/lib/pages/homepage/homepage.js +53 -53
- package/core/lib/pages/index.js +19 -19
- package/core/lib/pages/login/commnication-mode-selection.js +46 -46
- package/core/lib/pages/login/communication-mode-selection.scss +60 -60
- package/core/lib/pages/login/login.js +864 -864
- package/core/lib/pages/login/login.scss +344 -344
- package/core/lib/pages/login/reset-password.js +125 -125
- package/core/lib/pages/login/reset-password.scss +22 -22
- package/core/lib/pages/manage-users/manage-users.js +429 -429
- package/core/lib/pages/manage-users/manage-users.scss +25 -25
- package/core/lib/pages/profile/profile.js +247 -247
- package/core/lib/pages/profile/profile.scss +107 -107
- package/core/lib/pages/profile/theme-config.js +18 -18
- package/core/lib/pages/profile/themes-backup.json +310 -310
- package/core/lib/pages/profile/themes.json +254 -254
- package/core/lib/pages/register/register.js +176 -176
- package/core/lib/pages/register/register.scss +128 -128
- package/core/lib/react-styleguide.md +756 -756
- package/core/lib/utils/api/api.utils.js +211 -211
- package/core/lib/utils/api/readme.md +426 -426
- package/core/lib/utils/async.js +35 -35
- package/core/lib/utils/common/common.utils.js +223 -223
- package/core/lib/utils/common/readme.md +30 -30
- package/core/lib/utils/date/date.utils.js +295 -295
- package/core/lib/utils/date/readme.md +2 -2
- package/core/lib/utils/firebase.support.utils.js +98 -98
- package/core/lib/utils/firebase.utils.js +808 -808
- package/core/lib/utils/form/form.utils.js +255 -255
- package/core/lib/utils/generic/generic.utils.js +69 -69
- package/core/lib/utils/http/auth.helper.js +95 -95
- package/core/lib/utils/http/http.utils.js +158 -158
- package/core/lib/utils/http/readme.md +14 -14
- package/core/lib/utils/index.js +40 -40
- package/core/lib/utils/location/location.utils.js +137 -137
- package/core/lib/utils/location/readme.md +18 -18
- package/core/lib/utils/modal.utils.js +15 -15
- package/core/lib/utils/notification.utils.js +34 -34
- package/core/lib/utils/pwa/pwa.utils.js +88 -88
- package/core/lib/utils/script.utils.js +235 -235
- package/core/lib/utils/setting.utils.js +68 -68
- package/core/lib/utils/upload.utils.js +29 -29
- package/core/models/Preference/Preferences.js +46 -46
- package/core/models/base/base.js +403 -403
- package/core/models/base-clone-loader.js +107 -107
- package/core/models/base-clone.js +187 -187
- package/core/models/base-loader.js +97 -97
- package/core/models/core-scripts/core-scripts.js +150 -150
- package/core/models/dashboard/dashboard.js +201 -201
- package/core/models/detail-loader.js +88 -88
- package/core/models/doctor/components/doctor-add/doctor-add.js +427 -427
- package/core/models/doctor/components/doctor-add/doctor-add.scss +32 -32
- package/core/models/groups.js +82 -82
- package/core/models/index.js +100 -100
- package/core/models/lookup-types/components/lookup-detail/lookup-detail.js +129 -129
- package/core/models/lookup-types/lookup-types.js +96 -96
- package/core/models/lookup-values/components/lookup-values-modal/lookup-values-modal.js +95 -95
- package/core/models/lookup-values/lookup-values.js +92 -92
- package/core/models/menu-roles/components/menu-roles-add/menu-roles-add.js +153 -153
- package/core/models/menu-roles/menu-roles.js +158 -158
- package/core/models/menus/components/menu-add/menu-add.js +288 -288
- package/core/models/menus/components/menu-add/menu-add.scss +31 -31
- package/core/models/menus/components/menu-detail/menu-detail.js +263 -263
- package/core/models/menus/components/menu-list/menu-list.js +392 -392
- package/core/models/menus/components/menu-lists/menu-lists.js +585 -585
- package/core/models/menus/components/menu-lists/menu-lists.scss +46 -46
- package/core/models/menus/menus.js +310 -310
- package/core/models/model-columns.js +121 -121
- package/core/models/models/components/model-detail/model-add.js +120 -120
- package/core/models/models/components/model-detail/model-detail.js +133 -133
- package/core/models/models/models.js +154 -154
- package/core/models/pages/components/page-add/page-add.js +163 -163
- package/core/models/pages/components/page-add/page-add.scss +30 -30
- package/core/models/pages/components/page-details/page-details.js +209 -209
- package/core/models/pages/components/page-list/page-list.js +248 -248
- package/core/models/pages/pages.js +142 -142
- package/core/models/pages.js +142 -142
- package/core/models/roles/components/role-add/role-add.js +312 -312
- package/core/models/roles/components/role-add/role-add.scss +4 -4
- package/core/models/roles/components/role-list/role-list.js +386 -386
- package/core/models/roles/roles.js +196 -196
- package/core/models/staff/components/staff-add/staff-add.js +467 -467
- package/core/models/user-roles/components/user-roles-add/user-roles-add.js +149 -149
- package/core/models/user-roles/user-roles.js +113 -113
- package/core/models/users/components/assign-role/assign-role.js +406 -406
- package/core/models/users/components/assign-role/assign-role.scss +281 -281
- package/core/models/users/components/assign-role/avatar-props.js +45 -45
- package/core/models/users/components/user-add/user-add.js +856 -856
- package/core/models/users/components/user-add/user-edit.js +106 -106
- package/core/models/users/components/user-detail/user-detail.js +236 -236
- package/core/models/users/components/user-list/user-list.js +397 -397
- package/core/models/users/users.js +379 -379
- package/core/modules/Informations/change-info/change-info.js +618 -618
- package/core/modules/Informations/change-info/change-info.scss +134 -134
- package/core/modules/dashboard/components/dashboard-card/animations.js +64 -64
- package/core/modules/dashboard/components/dashboard-card/dashboard-card.js +197 -197
- package/core/modules/dashboard/components/dashboard-card/menu-dashboard-card.js +430 -430
- package/core/modules/dashboard/components/dashboard-card/menu-dashboard-card.scss +59 -59
- package/core/modules/dashboard/components/pop-query-dashboard/pop-query-dashboard.js +66 -66
- package/core/modules/generic/components/generic-add/generic-add.js +121 -121
- package/core/modules/generic/components/generic-add/generic-add.scss +13 -13
- package/core/modules/generic/components/generic-add-modal/generic-add-modal.js +125 -125
- package/core/modules/generic/components/generic-add-modal/generic-add-modal.scss +13 -13
- package/core/modules/generic/components/generic-detail/generic-detail.js +184 -184
- package/core/modules/generic/components/generic-detail/generic-detail.scss +25 -25
- package/core/modules/generic/components/generic-edit/generic-edit.js +123 -123
- package/core/modules/generic/components/generic-list/generic-list.js +335 -335
- package/core/modules/generic/components/generic-list/generic-list.scss +35 -35
- package/core/modules/index.js +42 -42
- package/core/modules/module-routes/module-routes.js +37 -37
- package/core/modules/reporting/components/index.js +6 -6
- package/core/modules/reporting/components/reporting-dashboard/README.md +316 -0
- package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.js +74 -0
- package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.test.js +74 -0
- package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.js +252 -0
- package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.test.js +126 -0
- package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +880 -1206
- package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.scss +171 -171
- package/core/modules/steps/action-buttons.js +74 -76
- package/core/modules/steps/action-buttons.scss +44 -15
- package/core/modules/steps/steps.js +348 -346
- package/core/modules/steps/steps.scss +357 -159
- package/core/modules/steps/timeline.js +56 -54
- package/core/pages/homepage-api/homepage-api.js +106 -106
- package/core/pages/homepage-api/homepage-api.scss +233 -233
- package/core/pages/homepage-api/menu-dashboard.js +169 -169
- package/core/pages/homepage-api/menu-dashboard.scss +11 -11
- package/core/translation.json +53 -53
- package/core/translations.json +19 -19
- package/core/utils/script.utils.js +129 -129
- package/core/utils/settings.utils.js +25 -25
- package/eslint.config.mjs +79 -79
- package/index.js +35 -35
- package/jest.config.js +7 -7
- package/jest.setup.js +1 -1
- package/package.json +123 -123
- package/tsconfig.json +26 -26
- package/webpack.config.js +173 -173
|
@@ -1,467 +1,467 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
-
|
|
3
|
-
import { Modal, Tabs, Input, Form, Row, Col, message, Checkbox, Select } from 'antd';
|
|
4
|
-
import { useTranslation, Button } from './../../../../lib/';
|
|
5
|
-
import { UsersAPI } from '../../..';
|
|
6
|
-
|
|
7
|
-
const StaffAdd = ({ visible, onCancel, staffId, staffData, onSuccess }) => {
|
|
8
|
-
const [form] = Form.useForm();
|
|
9
|
-
const { t } = useTranslation();
|
|
10
|
-
|
|
11
|
-
/** -------------------------------
|
|
12
|
-
* STATE
|
|
13
|
-
* ------------------------------- */
|
|
14
|
-
const [loading, setLoading] = useState(false);
|
|
15
|
-
const [designations, setDesignations] = useState([]);
|
|
16
|
-
const [staffList, setStaffList] = useState([]);
|
|
17
|
-
const [isSubmitDisabled, setIsSubmitDisabled] = useState(true);
|
|
18
|
-
const [codeStatus, setCodeStatus] = useState({ status: '', message: '' });
|
|
19
|
-
|
|
20
|
-
const nameInputRef = useRef(null);
|
|
21
|
-
|
|
22
|
-
const editMode = Boolean(staffId);
|
|
23
|
-
|
|
24
|
-
/** -------------------------------
|
|
25
|
-
* FORM WATCHERS
|
|
26
|
-
* ------------------------------- */
|
|
27
|
-
const watchedName = Form.useWatch('shortName', form);
|
|
28
|
-
const watchedCode = Form.useWatch('id', form);
|
|
29
|
-
const watchedDesc = Form.useWatch('description', form);
|
|
30
|
-
|
|
31
|
-
/** -------------------------------
|
|
32
|
-
* EFFECTS
|
|
33
|
-
* ------------------------------- */
|
|
34
|
-
|
|
35
|
-
// Auto-focus on open
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
if (visible) {
|
|
38
|
-
setTimeout(() => nameInputRef.current?.focus(), 200);
|
|
39
|
-
}
|
|
40
|
-
}, [visible]);
|
|
41
|
-
|
|
42
|
-
// Control submit button
|
|
43
|
-
useEffect(() => {
|
|
44
|
-
setIsSubmitDisabled(!(watchedName && watchedCode && watchedDesc));
|
|
45
|
-
}, [watchedName, watchedCode, watchedDesc]);
|
|
46
|
-
|
|
47
|
-
// Load designations and staff list when modal opens
|
|
48
|
-
useEffect(() => {
|
|
49
|
-
if (visible) {
|
|
50
|
-
getDesignations();
|
|
51
|
-
getStaffList();
|
|
52
|
-
}
|
|
53
|
-
}, [visible]);
|
|
54
|
-
|
|
55
|
-
// Reset or fill edit form
|
|
56
|
-
useEffect(() => {
|
|
57
|
-
if (visible) {
|
|
58
|
-
if (editMode && staffData) fillEditForm(staffData);
|
|
59
|
-
} else {
|
|
60
|
-
form.resetFields();
|
|
61
|
-
}
|
|
62
|
-
}, [visible]);
|
|
63
|
-
|
|
64
|
-
const phoneValidator = (_, value) => {
|
|
65
|
-
if (!value) {
|
|
66
|
-
return Promise.resolve(); // not required
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (!/^\d{10}$/.test(value)) {
|
|
70
|
-
return Promise.reject('Phone number must be 10 digits');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return Promise.resolve();
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
/** -------------------------------
|
|
77
|
-
* API CALL – Designations
|
|
78
|
-
* ------------------------------- */
|
|
79
|
-
const getDesignations = () => {
|
|
80
|
-
setLoading(true);
|
|
81
|
-
UsersAPI.getDesignations()
|
|
82
|
-
.then((res) => {
|
|
83
|
-
if (res?.success && Array.isArray(res.result)) {
|
|
84
|
-
const formatted = res.result.map((ele) => ({
|
|
85
|
-
label: ele.dg_desc?.trim() || '',
|
|
86
|
-
value: ele.dg_code,
|
|
87
|
-
}));
|
|
88
|
-
setDesignations(formatted);
|
|
89
|
-
} else {
|
|
90
|
-
setDesignations([]);
|
|
91
|
-
}
|
|
92
|
-
})
|
|
93
|
-
.catch((err) => {
|
|
94
|
-
console.error('Error fetching designations:', err);
|
|
95
|
-
setDesignations([]);
|
|
96
|
-
})
|
|
97
|
-
.finally(() => setLoading(false));
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
/** -------------------------------
|
|
101
|
-
* API CALL – Staff List
|
|
102
|
-
* ------------------------------- */
|
|
103
|
-
const getStaffList = () => {
|
|
104
|
-
UsersAPI.getAllStaff()
|
|
105
|
-
.then((res) => {
|
|
106
|
-
if (Array.isArray(res)) {
|
|
107
|
-
setStaffList(res);
|
|
108
|
-
}
|
|
109
|
-
})
|
|
110
|
-
.catch((err) => console.error(err));
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
/** -------------------------------
|
|
114
|
-
* VALIDATION – Input
|
|
115
|
-
* ------------------------------- */
|
|
116
|
-
const validateInput = async (rule, value) => {
|
|
117
|
-
// Common check: Starting space
|
|
118
|
-
if (value && value.startsWith(' ')) {
|
|
119
|
-
const msg = rule.message || 'Cannot start with a space';
|
|
120
|
-
if (rule.field === 'id') {
|
|
121
|
-
setCodeStatus({ status: 'error', message: msg });
|
|
122
|
-
}
|
|
123
|
-
return Promise.reject(new Error(msg));
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Specific check: Code (id)
|
|
127
|
-
if (rule.field === 'id') {
|
|
128
|
-
if (editMode) return Promise.resolve();
|
|
129
|
-
|
|
130
|
-
if (!value) {
|
|
131
|
-
setCodeStatus({ status: '', message: '' });
|
|
132
|
-
return Promise.resolve();
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Any space check
|
|
136
|
-
if (/\s/.test(value)) {
|
|
137
|
-
setCodeStatus({ status: 'error', message: 'Spaces are not allowed in the code' });
|
|
138
|
-
return Promise.reject(new Error('Spaces are not allowed in the code'));
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// API Check
|
|
142
|
-
try {
|
|
143
|
-
const res = await UsersAPI.getStaffCode(value);
|
|
144
|
-
|
|
145
|
-
if (res?.status === 409 || res?.success === false) {
|
|
146
|
-
setCodeStatus({ status: 'error', message: res.message || 'Code already exists' });
|
|
147
|
-
return Promise.reject(new Error(res.message || 'Code already exists'));
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (res?.status === 200 && res?.success === true) {
|
|
151
|
-
setCodeStatus({ status: 'success', message: 'The entered code is valid for assigning a staff.' });
|
|
152
|
-
return Promise.resolve();
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
setCodeStatus({ status: 'error', message: 'Please enter a valid code' });
|
|
156
|
-
return Promise.reject(new Error('Please enter a valid code'));
|
|
157
|
-
} catch {
|
|
158
|
-
setCodeStatus({ status: 'error', message: 'Validation failed' });
|
|
159
|
-
return Promise.reject(new Error('Validation failed'));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return Promise.resolve();
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
const validateSerial = (_, value) => {
|
|
167
|
-
if (!value) {
|
|
168
|
-
return Promise.resolve();
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Allow same serial number for the same staff in edit mode
|
|
172
|
-
if (editMode && String(value) === String(staffData?.slNo)) {
|
|
173
|
-
return Promise.resolve();
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const exists = staffList.some((staff) => String(staff.slNo) === String(value));
|
|
177
|
-
|
|
178
|
-
return exists ? Promise.reject('Serial Number already exists') : Promise.resolve();
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
/** -------------------------------
|
|
182
|
-
* UTIL – Enter Key Navigation
|
|
183
|
-
* ------------------------------- */
|
|
184
|
-
const handleEnterKey = (e) => {
|
|
185
|
-
if (e.key === 'Enter') {
|
|
186
|
-
e.preventDefault();
|
|
187
|
-
const fields = Array.from(document.querySelectorAll('.ant-input'));
|
|
188
|
-
const index = fields.indexOf(e.target);
|
|
189
|
-
if (index > -1 && index < fields.length - 1) {
|
|
190
|
-
fields[index + 1].focus();
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
/** -------------------------------
|
|
196
|
-
* FORM FILL – Edit Mode
|
|
197
|
-
* ------------------------------- */
|
|
198
|
-
const fillEditForm = (data) => {
|
|
199
|
-
form.setFieldsValue({
|
|
200
|
-
id: data.id,
|
|
201
|
-
shortName: data.shortName,
|
|
202
|
-
description: data.description,
|
|
203
|
-
designation: data.designationPtr,
|
|
204
|
-
phone1: data.phone || data.mobile,
|
|
205
|
-
phone2: data.alternateMobile,
|
|
206
|
-
email1: data.email,
|
|
207
|
-
email2: data.alternateEmail,
|
|
208
|
-
slno: data.slNo,
|
|
209
|
-
active: data.active === 'Y' ? 'Y' : 'N',
|
|
210
|
-
remarks: data.remarks,
|
|
211
|
-
address1: data.address1,
|
|
212
|
-
address2: data.address2,
|
|
213
|
-
place: data.place,
|
|
214
|
-
zip: data.zip,
|
|
215
|
-
});
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
const existing = staffData || {};
|
|
219
|
-
|
|
220
|
-
/** -------------------------------
|
|
221
|
-
* SUBMIT HANDLER
|
|
222
|
-
* ------------------------------- */
|
|
223
|
-
const handleFinish = async (values) => {
|
|
224
|
-
setLoading(true);
|
|
225
|
-
|
|
226
|
-
const payload = {
|
|
227
|
-
id: values.id,
|
|
228
|
-
shortName: values.shortName,
|
|
229
|
-
description: values.description,
|
|
230
|
-
designationPtr: values.designation ?? existing.designationPtr ?? null,
|
|
231
|
-
phone: values.phone1 ?? existing.phone ?? null,
|
|
232
|
-
mobile: values.phone1 ?? existing.mobile ?? null,
|
|
233
|
-
alternateMobile: values.phone2 ?? existing.alternateMobile ?? null,
|
|
234
|
-
email: values.email1 ?? existing.email ?? null,
|
|
235
|
-
alternateEmail: values.email2 ?? existing.alternateEmail ?? null,
|
|
236
|
-
remarks: values.remarks ?? existing.remarks ?? null,
|
|
237
|
-
slNo: values.slno ?? existing.slNo ?? null,
|
|
238
|
-
active: values.active === 'Y' ? 'Y' : 'N',
|
|
239
|
-
address1: values.address1 ?? existing.address1 ?? null,
|
|
240
|
-
address2: values.address2 ?? existing.address2 ?? null,
|
|
241
|
-
place: values.place ?? existing.place ?? null,
|
|
242
|
-
zip: values.zip ?? existing.zip ?? null,
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
try {
|
|
246
|
-
const res = editMode ? await UsersAPI.updateStaff(payload, staffData.id) : await UsersAPI.createStaff(payload);
|
|
247
|
-
|
|
248
|
-
if (res?.success) {
|
|
249
|
-
message.success(editMode ? 'Staff updated successfully' : 'Staff created successfully');
|
|
250
|
-
onSuccess?.();
|
|
251
|
-
onCancel();
|
|
252
|
-
} else {
|
|
253
|
-
message.error(res?.message || 'Operation failed');
|
|
254
|
-
}
|
|
255
|
-
} catch {
|
|
256
|
-
message.error('Something went wrong');
|
|
257
|
-
} finally {
|
|
258
|
-
setLoading(false);
|
|
259
|
-
}
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
/** -------------------------------
|
|
263
|
-
* RENDER
|
|
264
|
-
* ------------------------------- */
|
|
265
|
-
return (
|
|
266
|
-
<Modal
|
|
267
|
-
title={editMode ? 'Edit Staff' : 'Add Staff'}
|
|
268
|
-
open={visible}
|
|
269
|
-
onCancel={onCancel}
|
|
270
|
-
width={950}
|
|
271
|
-
footer={null}
|
|
272
|
-
destroyOnClose
|
|
273
|
-
style={{ top: 10 }}
|
|
274
|
-
>
|
|
275
|
-
<Form form={form} layout="vertical" onFinish={handleFinish}>
|
|
276
|
-
{/* TOP SECTION */}
|
|
277
|
-
<Row gutter={16}>
|
|
278
|
-
<Col span={6}>
|
|
279
|
-
<Form.Item
|
|
280
|
-
label="Code"
|
|
281
|
-
name="id"
|
|
282
|
-
validateTrigger="onChange"
|
|
283
|
-
hasFeedback={!editMode}
|
|
284
|
-
rules={[{ required: true, message: 'Code is required' }, { validator: validateInput }]}
|
|
285
|
-
>
|
|
286
|
-
<Input placeholder="Enter Code" autoComplete="off" maxLength={10} ref={nameInputRef} onKeyDown={handleEnterKey} disabled={editMode} />
|
|
287
|
-
</Form.Item>
|
|
288
|
-
</Col>
|
|
289
|
-
|
|
290
|
-
<Col span={12}>
|
|
291
|
-
<Form.Item
|
|
292
|
-
label="Name"
|
|
293
|
-
name="description"
|
|
294
|
-
rules={[
|
|
295
|
-
{ required: true, message: 'Name is required' },
|
|
296
|
-
{ pattern: /^[A-Za-z\s]+$/, message: 'Name should contain only alphabets' },
|
|
297
|
-
{ validator: validateInput, message: 'Name cannot start with a space' },
|
|
298
|
-
]}
|
|
299
|
-
>
|
|
300
|
-
<Input placeholder="Enter Description" autoComplete="off" onKeyDown={handleEnterKey} />
|
|
301
|
-
</Form.Item>
|
|
302
|
-
</Col>
|
|
303
|
-
<Col span={6}>
|
|
304
|
-
<Form.Item
|
|
305
|
-
label="Short Name"
|
|
306
|
-
name="shortName"
|
|
307
|
-
rules={[
|
|
308
|
-
{ required: true, message: 'Short Name is required' },
|
|
309
|
-
{ pattern: /^[A-Za-z\s]+$/, message: 'Name should contain only alphabets' },
|
|
310
|
-
{ validator: validateInput, message: 'Short Name cannot start with a space' },
|
|
311
|
-
]}
|
|
312
|
-
>
|
|
313
|
-
<Input placeholder="Enter Short Name" autoComplete="off" onKeyDown={handleEnterKey} maxLength={10} />
|
|
314
|
-
</Form.Item>
|
|
315
|
-
</Col>
|
|
316
|
-
</Row>
|
|
317
|
-
|
|
318
|
-
<Tabs defaultActiveKey="1" destroyInactiveTabPane={false}>
|
|
319
|
-
{/* GENERAL TAB */}
|
|
320
|
-
<Tabs.TabPane tab="GENERAL" key="1">
|
|
321
|
-
<Row gutter={16}>
|
|
322
|
-
{/* <Col span={6}>
|
|
323
|
-
<Form.Item label="Phone Number 1" name="phone1">
|
|
324
|
-
<Input maxLength={10} placeholder="Enter Phone Number" onKeyDown={handleEnterKey} />
|
|
325
|
-
</Form.Item>
|
|
326
|
-
</Col>
|
|
327
|
-
|
|
328
|
-
<Col span={6}>
|
|
329
|
-
<Form.Item label="Phone Number 2" name="phone2">
|
|
330
|
-
<Input maxLength={10} placeholder="Enter Phone Number" onKeyDown={handleEnterKey} />
|
|
331
|
-
</Form.Item>
|
|
332
|
-
</Col> */}
|
|
333
|
-
<Col span={6}>
|
|
334
|
-
<Form.Item label="Phone Number" name="phone1" rules={[{ validator: phoneValidator }]}>
|
|
335
|
-
<Input
|
|
336
|
-
maxLength={10}
|
|
337
|
-
autoComplete="off"
|
|
338
|
-
placeholder="Enter Phone Number"
|
|
339
|
-
inputMode="numeric"
|
|
340
|
-
onChange={(e) => (e.target.value = e.target.value.replace(/\D/g, ''))}
|
|
341
|
-
onKeyDown={handleEnterKey}
|
|
342
|
-
/>
|
|
343
|
-
</Form.Item>
|
|
344
|
-
</Col>
|
|
345
|
-
|
|
346
|
-
<Col span={6}>
|
|
347
|
-
<Form.Item label="Alternate Phone Number" name="phone2" rules={[{ validator: phoneValidator }]}>
|
|
348
|
-
<Input
|
|
349
|
-
maxLength={10}
|
|
350
|
-
placeholder="Enter Phone Number"
|
|
351
|
-
autoComplete="off"
|
|
352
|
-
inputMode="numeric"
|
|
353
|
-
onChange={(e) => (e.target.value = e.target.value.replace(/\D/g, ''))}
|
|
354
|
-
onKeyDown={handleEnterKey}
|
|
355
|
-
/>
|
|
356
|
-
</Form.Item>
|
|
357
|
-
</Col>
|
|
358
|
-
|
|
359
|
-
<Col span={6}>
|
|
360
|
-
<Form.Item label="Email ID" name="email1" rules={[{ type: 'email', message: 'Please enter a valid email' }]}>
|
|
361
|
-
<Input autoComplete="off" placeholder="Enter Email" onKeyDown={handleEnterKey} />
|
|
362
|
-
</Form.Item>
|
|
363
|
-
</Col>
|
|
364
|
-
|
|
365
|
-
<Col span={6}>
|
|
366
|
-
<Form.Item label="Alternate Email" name="email2" rules={[{ type: 'email', message: 'Please enter a valid email' }]}>
|
|
367
|
-
<Input autoComplete="off" placeholder="Enter Email" onKeyDown={handleEnterKey} />
|
|
368
|
-
</Form.Item>
|
|
369
|
-
</Col>
|
|
370
|
-
</Row>
|
|
371
|
-
|
|
372
|
-
<Row gutter={16}>
|
|
373
|
-
<Col span={8}>
|
|
374
|
-
<Form.Item name="designation" label="Designation">
|
|
375
|
-
<Select placeholder="Select Designation" options={designations} allowClear showSearch optionFilterProp="label" />
|
|
376
|
-
</Form.Item>
|
|
377
|
-
</Col>
|
|
378
|
-
|
|
379
|
-
<Col span={8}>
|
|
380
|
-
<Form.Item
|
|
381
|
-
label="Serial Number"
|
|
382
|
-
name="slno"
|
|
383
|
-
rules={[{ message: 'only numbers are allowed', pattern: /^\d*$/ }, { validator: validateSerial }]}
|
|
384
|
-
>
|
|
385
|
-
<Input autoComplete="off" maxLength={5} placeholder="Enter Serial Number" onKeyDown={handleEnterKey} />
|
|
386
|
-
</Form.Item>
|
|
387
|
-
</Col>
|
|
388
|
-
|
|
389
|
-
<Col span={8}>
|
|
390
|
-
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 30 }}>
|
|
391
|
-
<label>Active</label>
|
|
392
|
-
<Form.Item
|
|
393
|
-
name="active"
|
|
394
|
-
valuePropName="checked"
|
|
395
|
-
getValueFromEvent={(e) => (e.target.checked ? 'Y' : 'N')}
|
|
396
|
-
getValueProps={(value) => ({ checked: value === 'Y' })}
|
|
397
|
-
style={{ marginBottom: 0 }}
|
|
398
|
-
>
|
|
399
|
-
<Checkbox />
|
|
400
|
-
</Form.Item>
|
|
401
|
-
</div>
|
|
402
|
-
</Col>
|
|
403
|
-
</Row>
|
|
404
|
-
|
|
405
|
-
<Row>
|
|
406
|
-
<Col span={24}>
|
|
407
|
-
<Form.Item
|
|
408
|
-
label="Remarks"
|
|
409
|
-
name="remarks"
|
|
410
|
-
rules={[
|
|
411
|
-
{ max: 50, message: 'Remarks must be less than 50 characters' },
|
|
412
|
-
{ validator: validateInput, message: 'Remarks cannot start with a space' },
|
|
413
|
-
]}
|
|
414
|
-
>
|
|
415
|
-
<Input autoComplete="off" placeholder="Enter Remarks" onKeyDown={handleEnterKey} />
|
|
416
|
-
</Form.Item>
|
|
417
|
-
</Col>
|
|
418
|
-
</Row>
|
|
419
|
-
</Tabs.TabPane>
|
|
420
|
-
|
|
421
|
-
{/* ADDRESS TAB */}
|
|
422
|
-
<Tabs.TabPane tab="ADDRESS" key="2">
|
|
423
|
-
<Row gutter={16}>
|
|
424
|
-
<Col span={12}>
|
|
425
|
-
<Form.Item label="Address Line 1" name="address1">
|
|
426
|
-
<Input autoComplete="off" placeholder="Enter Address" onKeyDown={handleEnterKey} />
|
|
427
|
-
</Form.Item>
|
|
428
|
-
</Col>
|
|
429
|
-
|
|
430
|
-
<Col span={12}>
|
|
431
|
-
<Form.Item label="Address Line 2" name="address2">
|
|
432
|
-
<Input autoComplete="off" placeholder="Enter Address" onKeyDown={handleEnterKey} />
|
|
433
|
-
</Form.Item>
|
|
434
|
-
</Col>
|
|
435
|
-
</Row>
|
|
436
|
-
|
|
437
|
-
<Row gutter={16}>
|
|
438
|
-
<Col span={12}>
|
|
439
|
-
<Form.Item label="Place" name="place">
|
|
440
|
-
<Input autoComplete="off" placeholder="Enter Place" onKeyDown={handleEnterKey} />
|
|
441
|
-
</Form.Item>
|
|
442
|
-
</Col>
|
|
443
|
-
|
|
444
|
-
<Col span={12}>
|
|
445
|
-
<Form.Item label="Zip Code" name="zip">
|
|
446
|
-
<Input autoComplete="off" placeholder="Enter Zip Code" maxLength={7} onKeyDown={handleEnterKey} />
|
|
447
|
-
</Form.Item>
|
|
448
|
-
</Col>
|
|
449
|
-
</Row>
|
|
450
|
-
</Tabs.TabPane>
|
|
451
|
-
</Tabs>
|
|
452
|
-
|
|
453
|
-
{/* FOOTER BUTTONS */}
|
|
454
|
-
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10 }}>
|
|
455
|
-
<Button onClick={onCancel} type="secondary">
|
|
456
|
-
Cancel
|
|
457
|
-
</Button>
|
|
458
|
-
<Button type="primary" htmlType="submit" loading={loading} disabled={isSubmitDisabled}>
|
|
459
|
-
{editMode ? 'Update' : 'Save'}
|
|
460
|
-
</Button>
|
|
461
|
-
</div>
|
|
462
|
-
</Form>
|
|
463
|
-
</Modal>
|
|
464
|
-
);
|
|
465
|
-
};
|
|
466
|
-
|
|
467
|
-
export default StaffAdd;
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Modal, Tabs, Input, Form, Row, Col, message, Checkbox, Select } from 'antd';
|
|
4
|
+
import { useTranslation, Button } from './../../../../lib/';
|
|
5
|
+
import { UsersAPI } from '../../..';
|
|
6
|
+
|
|
7
|
+
const StaffAdd = ({ visible, onCancel, staffId, staffData, onSuccess }) => {
|
|
8
|
+
const [form] = Form.useForm();
|
|
9
|
+
const { t } = useTranslation();
|
|
10
|
+
|
|
11
|
+
/** -------------------------------
|
|
12
|
+
* STATE
|
|
13
|
+
* ------------------------------- */
|
|
14
|
+
const [loading, setLoading] = useState(false);
|
|
15
|
+
const [designations, setDesignations] = useState([]);
|
|
16
|
+
const [staffList, setStaffList] = useState([]);
|
|
17
|
+
const [isSubmitDisabled, setIsSubmitDisabled] = useState(true);
|
|
18
|
+
const [codeStatus, setCodeStatus] = useState({ status: '', message: '' });
|
|
19
|
+
|
|
20
|
+
const nameInputRef = useRef(null);
|
|
21
|
+
|
|
22
|
+
const editMode = Boolean(staffId);
|
|
23
|
+
|
|
24
|
+
/** -------------------------------
|
|
25
|
+
* FORM WATCHERS
|
|
26
|
+
* ------------------------------- */
|
|
27
|
+
const watchedName = Form.useWatch('shortName', form);
|
|
28
|
+
const watchedCode = Form.useWatch('id', form);
|
|
29
|
+
const watchedDesc = Form.useWatch('description', form);
|
|
30
|
+
|
|
31
|
+
/** -------------------------------
|
|
32
|
+
* EFFECTS
|
|
33
|
+
* ------------------------------- */
|
|
34
|
+
|
|
35
|
+
// Auto-focus on open
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (visible) {
|
|
38
|
+
setTimeout(() => nameInputRef.current?.focus(), 200);
|
|
39
|
+
}
|
|
40
|
+
}, [visible]);
|
|
41
|
+
|
|
42
|
+
// Control submit button
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
setIsSubmitDisabled(!(watchedName && watchedCode && watchedDesc));
|
|
45
|
+
}, [watchedName, watchedCode, watchedDesc]);
|
|
46
|
+
|
|
47
|
+
// Load designations and staff list when modal opens
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (visible) {
|
|
50
|
+
getDesignations();
|
|
51
|
+
getStaffList();
|
|
52
|
+
}
|
|
53
|
+
}, [visible]);
|
|
54
|
+
|
|
55
|
+
// Reset or fill edit form
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (visible) {
|
|
58
|
+
if (editMode && staffData) fillEditForm(staffData);
|
|
59
|
+
} else {
|
|
60
|
+
form.resetFields();
|
|
61
|
+
}
|
|
62
|
+
}, [visible]);
|
|
63
|
+
|
|
64
|
+
const phoneValidator = (_, value) => {
|
|
65
|
+
if (!value) {
|
|
66
|
+
return Promise.resolve(); // not required
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!/^\d{10}$/.test(value)) {
|
|
70
|
+
return Promise.reject('Phone number must be 10 digits');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return Promise.resolve();
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** -------------------------------
|
|
77
|
+
* API CALL – Designations
|
|
78
|
+
* ------------------------------- */
|
|
79
|
+
const getDesignations = () => {
|
|
80
|
+
setLoading(true);
|
|
81
|
+
UsersAPI.getDesignations()
|
|
82
|
+
.then((res) => {
|
|
83
|
+
if (res?.success && Array.isArray(res.result)) {
|
|
84
|
+
const formatted = res.result.map((ele) => ({
|
|
85
|
+
label: ele.dg_desc?.trim() || '',
|
|
86
|
+
value: ele.dg_code,
|
|
87
|
+
}));
|
|
88
|
+
setDesignations(formatted);
|
|
89
|
+
} else {
|
|
90
|
+
setDesignations([]);
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
.catch((err) => {
|
|
94
|
+
console.error('Error fetching designations:', err);
|
|
95
|
+
setDesignations([]);
|
|
96
|
+
})
|
|
97
|
+
.finally(() => setLoading(false));
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/** -------------------------------
|
|
101
|
+
* API CALL – Staff List
|
|
102
|
+
* ------------------------------- */
|
|
103
|
+
const getStaffList = () => {
|
|
104
|
+
UsersAPI.getAllStaff()
|
|
105
|
+
.then((res) => {
|
|
106
|
+
if (Array.isArray(res)) {
|
|
107
|
+
setStaffList(res);
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
.catch((err) => console.error(err));
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/** -------------------------------
|
|
114
|
+
* VALIDATION – Input
|
|
115
|
+
* ------------------------------- */
|
|
116
|
+
const validateInput = async (rule, value) => {
|
|
117
|
+
// Common check: Starting space
|
|
118
|
+
if (value && value.startsWith(' ')) {
|
|
119
|
+
const msg = rule.message || 'Cannot start with a space';
|
|
120
|
+
if (rule.field === 'id') {
|
|
121
|
+
setCodeStatus({ status: 'error', message: msg });
|
|
122
|
+
}
|
|
123
|
+
return Promise.reject(new Error(msg));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Specific check: Code (id)
|
|
127
|
+
if (rule.field === 'id') {
|
|
128
|
+
if (editMode) return Promise.resolve();
|
|
129
|
+
|
|
130
|
+
if (!value) {
|
|
131
|
+
setCodeStatus({ status: '', message: '' });
|
|
132
|
+
return Promise.resolve();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Any space check
|
|
136
|
+
if (/\s/.test(value)) {
|
|
137
|
+
setCodeStatus({ status: 'error', message: 'Spaces are not allowed in the code' });
|
|
138
|
+
return Promise.reject(new Error('Spaces are not allowed in the code'));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// API Check
|
|
142
|
+
try {
|
|
143
|
+
const res = await UsersAPI.getStaffCode(value);
|
|
144
|
+
|
|
145
|
+
if (res?.status === 409 || res?.success === false) {
|
|
146
|
+
setCodeStatus({ status: 'error', message: res.message || 'Code already exists' });
|
|
147
|
+
return Promise.reject(new Error(res.message || 'Code already exists'));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (res?.status === 200 && res?.success === true) {
|
|
151
|
+
setCodeStatus({ status: 'success', message: 'The entered code is valid for assigning a staff.' });
|
|
152
|
+
return Promise.resolve();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
setCodeStatus({ status: 'error', message: 'Please enter a valid code' });
|
|
156
|
+
return Promise.reject(new Error('Please enter a valid code'));
|
|
157
|
+
} catch {
|
|
158
|
+
setCodeStatus({ status: 'error', message: 'Validation failed' });
|
|
159
|
+
return Promise.reject(new Error('Validation failed'));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return Promise.resolve();
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const validateSerial = (_, value) => {
|
|
167
|
+
if (!value) {
|
|
168
|
+
return Promise.resolve();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Allow same serial number for the same staff in edit mode
|
|
172
|
+
if (editMode && String(value) === String(staffData?.slNo)) {
|
|
173
|
+
return Promise.resolve();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const exists = staffList.some((staff) => String(staff.slNo) === String(value));
|
|
177
|
+
|
|
178
|
+
return exists ? Promise.reject('Serial Number already exists') : Promise.resolve();
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/** -------------------------------
|
|
182
|
+
* UTIL – Enter Key Navigation
|
|
183
|
+
* ------------------------------- */
|
|
184
|
+
const handleEnterKey = (e) => {
|
|
185
|
+
if (e.key === 'Enter') {
|
|
186
|
+
e.preventDefault();
|
|
187
|
+
const fields = Array.from(document.querySelectorAll('.ant-input'));
|
|
188
|
+
const index = fields.indexOf(e.target);
|
|
189
|
+
if (index > -1 && index < fields.length - 1) {
|
|
190
|
+
fields[index + 1].focus();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/** -------------------------------
|
|
196
|
+
* FORM FILL – Edit Mode
|
|
197
|
+
* ------------------------------- */
|
|
198
|
+
const fillEditForm = (data) => {
|
|
199
|
+
form.setFieldsValue({
|
|
200
|
+
id: data.id,
|
|
201
|
+
shortName: data.shortName,
|
|
202
|
+
description: data.description,
|
|
203
|
+
designation: data.designationPtr,
|
|
204
|
+
phone1: data.phone || data.mobile,
|
|
205
|
+
phone2: data.alternateMobile,
|
|
206
|
+
email1: data.email,
|
|
207
|
+
email2: data.alternateEmail,
|
|
208
|
+
slno: data.slNo,
|
|
209
|
+
active: data.active === 'Y' ? 'Y' : 'N',
|
|
210
|
+
remarks: data.remarks,
|
|
211
|
+
address1: data.address1,
|
|
212
|
+
address2: data.address2,
|
|
213
|
+
place: data.place,
|
|
214
|
+
zip: data.zip,
|
|
215
|
+
});
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const existing = staffData || {};
|
|
219
|
+
|
|
220
|
+
/** -------------------------------
|
|
221
|
+
* SUBMIT HANDLER
|
|
222
|
+
* ------------------------------- */
|
|
223
|
+
const handleFinish = async (values) => {
|
|
224
|
+
setLoading(true);
|
|
225
|
+
|
|
226
|
+
const payload = {
|
|
227
|
+
id: values.id,
|
|
228
|
+
shortName: values.shortName,
|
|
229
|
+
description: values.description,
|
|
230
|
+
designationPtr: values.designation ?? existing.designationPtr ?? null,
|
|
231
|
+
phone: values.phone1 ?? existing.phone ?? null,
|
|
232
|
+
mobile: values.phone1 ?? existing.mobile ?? null,
|
|
233
|
+
alternateMobile: values.phone2 ?? existing.alternateMobile ?? null,
|
|
234
|
+
email: values.email1 ?? existing.email ?? null,
|
|
235
|
+
alternateEmail: values.email2 ?? existing.alternateEmail ?? null,
|
|
236
|
+
remarks: values.remarks ?? existing.remarks ?? null,
|
|
237
|
+
slNo: values.slno ?? existing.slNo ?? null,
|
|
238
|
+
active: values.active === 'Y' ? 'Y' : 'N',
|
|
239
|
+
address1: values.address1 ?? existing.address1 ?? null,
|
|
240
|
+
address2: values.address2 ?? existing.address2 ?? null,
|
|
241
|
+
place: values.place ?? existing.place ?? null,
|
|
242
|
+
zip: values.zip ?? existing.zip ?? null,
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
const res = editMode ? await UsersAPI.updateStaff(payload, staffData.id) : await UsersAPI.createStaff(payload);
|
|
247
|
+
|
|
248
|
+
if (res?.success) {
|
|
249
|
+
message.success(editMode ? 'Staff updated successfully' : 'Staff created successfully');
|
|
250
|
+
onSuccess?.();
|
|
251
|
+
onCancel();
|
|
252
|
+
} else {
|
|
253
|
+
message.error(res?.message || 'Operation failed');
|
|
254
|
+
}
|
|
255
|
+
} catch {
|
|
256
|
+
message.error('Something went wrong');
|
|
257
|
+
} finally {
|
|
258
|
+
setLoading(false);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
/** -------------------------------
|
|
263
|
+
* RENDER
|
|
264
|
+
* ------------------------------- */
|
|
265
|
+
return (
|
|
266
|
+
<Modal
|
|
267
|
+
title={editMode ? 'Edit Staff' : 'Add Staff'}
|
|
268
|
+
open={visible}
|
|
269
|
+
onCancel={onCancel}
|
|
270
|
+
width={950}
|
|
271
|
+
footer={null}
|
|
272
|
+
destroyOnClose
|
|
273
|
+
style={{ top: 10 }}
|
|
274
|
+
>
|
|
275
|
+
<Form form={form} layout="vertical" onFinish={handleFinish}>
|
|
276
|
+
{/* TOP SECTION */}
|
|
277
|
+
<Row gutter={16}>
|
|
278
|
+
<Col span={6}>
|
|
279
|
+
<Form.Item
|
|
280
|
+
label="Code"
|
|
281
|
+
name="id"
|
|
282
|
+
validateTrigger="onChange"
|
|
283
|
+
hasFeedback={!editMode}
|
|
284
|
+
rules={[{ required: true, message: 'Code is required' }, { validator: validateInput }]}
|
|
285
|
+
>
|
|
286
|
+
<Input placeholder="Enter Code" autoComplete="off" maxLength={10} ref={nameInputRef} onKeyDown={handleEnterKey} disabled={editMode} />
|
|
287
|
+
</Form.Item>
|
|
288
|
+
</Col>
|
|
289
|
+
|
|
290
|
+
<Col span={12}>
|
|
291
|
+
<Form.Item
|
|
292
|
+
label="Name"
|
|
293
|
+
name="description"
|
|
294
|
+
rules={[
|
|
295
|
+
{ required: true, message: 'Name is required' },
|
|
296
|
+
{ pattern: /^[A-Za-z\s]+$/, message: 'Name should contain only alphabets' },
|
|
297
|
+
{ validator: validateInput, message: 'Name cannot start with a space' },
|
|
298
|
+
]}
|
|
299
|
+
>
|
|
300
|
+
<Input placeholder="Enter Description" autoComplete="off" onKeyDown={handleEnterKey} />
|
|
301
|
+
</Form.Item>
|
|
302
|
+
</Col>
|
|
303
|
+
<Col span={6}>
|
|
304
|
+
<Form.Item
|
|
305
|
+
label="Short Name"
|
|
306
|
+
name="shortName"
|
|
307
|
+
rules={[
|
|
308
|
+
{ required: true, message: 'Short Name is required' },
|
|
309
|
+
{ pattern: /^[A-Za-z\s]+$/, message: 'Name should contain only alphabets' },
|
|
310
|
+
{ validator: validateInput, message: 'Short Name cannot start with a space' },
|
|
311
|
+
]}
|
|
312
|
+
>
|
|
313
|
+
<Input placeholder="Enter Short Name" autoComplete="off" onKeyDown={handleEnterKey} maxLength={10} />
|
|
314
|
+
</Form.Item>
|
|
315
|
+
</Col>
|
|
316
|
+
</Row>
|
|
317
|
+
|
|
318
|
+
<Tabs defaultActiveKey="1" destroyInactiveTabPane={false}>
|
|
319
|
+
{/* GENERAL TAB */}
|
|
320
|
+
<Tabs.TabPane tab="GENERAL" key="1">
|
|
321
|
+
<Row gutter={16}>
|
|
322
|
+
{/* <Col span={6}>
|
|
323
|
+
<Form.Item label="Phone Number 1" name="phone1">
|
|
324
|
+
<Input maxLength={10} placeholder="Enter Phone Number" onKeyDown={handleEnterKey} />
|
|
325
|
+
</Form.Item>
|
|
326
|
+
</Col>
|
|
327
|
+
|
|
328
|
+
<Col span={6}>
|
|
329
|
+
<Form.Item label="Phone Number 2" name="phone2">
|
|
330
|
+
<Input maxLength={10} placeholder="Enter Phone Number" onKeyDown={handleEnterKey} />
|
|
331
|
+
</Form.Item>
|
|
332
|
+
</Col> */}
|
|
333
|
+
<Col span={6}>
|
|
334
|
+
<Form.Item label="Phone Number" name="phone1" rules={[{ validator: phoneValidator }]}>
|
|
335
|
+
<Input
|
|
336
|
+
maxLength={10}
|
|
337
|
+
autoComplete="off"
|
|
338
|
+
placeholder="Enter Phone Number"
|
|
339
|
+
inputMode="numeric"
|
|
340
|
+
onChange={(e) => (e.target.value = e.target.value.replace(/\D/g, ''))}
|
|
341
|
+
onKeyDown={handleEnterKey}
|
|
342
|
+
/>
|
|
343
|
+
</Form.Item>
|
|
344
|
+
</Col>
|
|
345
|
+
|
|
346
|
+
<Col span={6}>
|
|
347
|
+
<Form.Item label="Alternate Phone Number" name="phone2" rules={[{ validator: phoneValidator }]}>
|
|
348
|
+
<Input
|
|
349
|
+
maxLength={10}
|
|
350
|
+
placeholder="Enter Phone Number"
|
|
351
|
+
autoComplete="off"
|
|
352
|
+
inputMode="numeric"
|
|
353
|
+
onChange={(e) => (e.target.value = e.target.value.replace(/\D/g, ''))}
|
|
354
|
+
onKeyDown={handleEnterKey}
|
|
355
|
+
/>
|
|
356
|
+
</Form.Item>
|
|
357
|
+
</Col>
|
|
358
|
+
|
|
359
|
+
<Col span={6}>
|
|
360
|
+
<Form.Item label="Email ID" name="email1" rules={[{ type: 'email', message: 'Please enter a valid email' }]}>
|
|
361
|
+
<Input autoComplete="off" placeholder="Enter Email" onKeyDown={handleEnterKey} />
|
|
362
|
+
</Form.Item>
|
|
363
|
+
</Col>
|
|
364
|
+
|
|
365
|
+
<Col span={6}>
|
|
366
|
+
<Form.Item label="Alternate Email" name="email2" rules={[{ type: 'email', message: 'Please enter a valid email' }]}>
|
|
367
|
+
<Input autoComplete="off" placeholder="Enter Email" onKeyDown={handleEnterKey} />
|
|
368
|
+
</Form.Item>
|
|
369
|
+
</Col>
|
|
370
|
+
</Row>
|
|
371
|
+
|
|
372
|
+
<Row gutter={16}>
|
|
373
|
+
<Col span={8}>
|
|
374
|
+
<Form.Item name="designation" label="Designation">
|
|
375
|
+
<Select placeholder="Select Designation" options={designations} allowClear showSearch optionFilterProp="label" />
|
|
376
|
+
</Form.Item>
|
|
377
|
+
</Col>
|
|
378
|
+
|
|
379
|
+
<Col span={8}>
|
|
380
|
+
<Form.Item
|
|
381
|
+
label="Serial Number"
|
|
382
|
+
name="slno"
|
|
383
|
+
rules={[{ message: 'only numbers are allowed', pattern: /^\d*$/ }, { validator: validateSerial }]}
|
|
384
|
+
>
|
|
385
|
+
<Input autoComplete="off" maxLength={5} placeholder="Enter Serial Number" onKeyDown={handleEnterKey} />
|
|
386
|
+
</Form.Item>
|
|
387
|
+
</Col>
|
|
388
|
+
|
|
389
|
+
<Col span={8}>
|
|
390
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 30 }}>
|
|
391
|
+
<label>Active</label>
|
|
392
|
+
<Form.Item
|
|
393
|
+
name="active"
|
|
394
|
+
valuePropName="checked"
|
|
395
|
+
getValueFromEvent={(e) => (e.target.checked ? 'Y' : 'N')}
|
|
396
|
+
getValueProps={(value) => ({ checked: value === 'Y' })}
|
|
397
|
+
style={{ marginBottom: 0 }}
|
|
398
|
+
>
|
|
399
|
+
<Checkbox />
|
|
400
|
+
</Form.Item>
|
|
401
|
+
</div>
|
|
402
|
+
</Col>
|
|
403
|
+
</Row>
|
|
404
|
+
|
|
405
|
+
<Row>
|
|
406
|
+
<Col span={24}>
|
|
407
|
+
<Form.Item
|
|
408
|
+
label="Remarks"
|
|
409
|
+
name="remarks"
|
|
410
|
+
rules={[
|
|
411
|
+
{ max: 50, message: 'Remarks must be less than 50 characters' },
|
|
412
|
+
{ validator: validateInput, message: 'Remarks cannot start with a space' },
|
|
413
|
+
]}
|
|
414
|
+
>
|
|
415
|
+
<Input autoComplete="off" placeholder="Enter Remarks" onKeyDown={handleEnterKey} />
|
|
416
|
+
</Form.Item>
|
|
417
|
+
</Col>
|
|
418
|
+
</Row>
|
|
419
|
+
</Tabs.TabPane>
|
|
420
|
+
|
|
421
|
+
{/* ADDRESS TAB */}
|
|
422
|
+
<Tabs.TabPane tab="ADDRESS" key="2">
|
|
423
|
+
<Row gutter={16}>
|
|
424
|
+
<Col span={12}>
|
|
425
|
+
<Form.Item label="Address Line 1" name="address1">
|
|
426
|
+
<Input autoComplete="off" placeholder="Enter Address" onKeyDown={handleEnterKey} />
|
|
427
|
+
</Form.Item>
|
|
428
|
+
</Col>
|
|
429
|
+
|
|
430
|
+
<Col span={12}>
|
|
431
|
+
<Form.Item label="Address Line 2" name="address2">
|
|
432
|
+
<Input autoComplete="off" placeholder="Enter Address" onKeyDown={handleEnterKey} />
|
|
433
|
+
</Form.Item>
|
|
434
|
+
</Col>
|
|
435
|
+
</Row>
|
|
436
|
+
|
|
437
|
+
<Row gutter={16}>
|
|
438
|
+
<Col span={12}>
|
|
439
|
+
<Form.Item label="Place" name="place">
|
|
440
|
+
<Input autoComplete="off" placeholder="Enter Place" onKeyDown={handleEnterKey} />
|
|
441
|
+
</Form.Item>
|
|
442
|
+
</Col>
|
|
443
|
+
|
|
444
|
+
<Col span={12}>
|
|
445
|
+
<Form.Item label="Zip Code" name="zip">
|
|
446
|
+
<Input autoComplete="off" placeholder="Enter Zip Code" maxLength={7} onKeyDown={handleEnterKey} />
|
|
447
|
+
</Form.Item>
|
|
448
|
+
</Col>
|
|
449
|
+
</Row>
|
|
450
|
+
</Tabs.TabPane>
|
|
451
|
+
</Tabs>
|
|
452
|
+
|
|
453
|
+
{/* FOOTER BUTTONS */}
|
|
454
|
+
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10 }}>
|
|
455
|
+
<Button onClick={onCancel} type="secondary">
|
|
456
|
+
Cancel
|
|
457
|
+
</Button>
|
|
458
|
+
<Button type="primary" htmlType="submit" loading={loading} disabled={isSubmitDisabled}>
|
|
459
|
+
{editMode ? 'Update' : 'Save'}
|
|
460
|
+
</Button>
|
|
461
|
+
</div>
|
|
462
|
+
</Form>
|
|
463
|
+
</Modal>
|
|
464
|
+
);
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
export default StaffAdd;
|