| @@ -0,0 +1,166 @@ | |||
| import { Autocomplete, CircularProgress, Grid, TextField, Typography } from '@mui/material'; | |||
| import debounce from 'lodash/debounce'; | |||
| import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; | |||
| import { fetchOrgCombo, getOrgOptionLabel } from 'utils/OrgComboUtils'; | |||
| import { renderOrgOption } from 'components/OrgOptionLabel'; | |||
| const SEARCH_DEBOUNCE_MS = 300; | |||
| export default function OrgComboAutocomplete({ | |||
| value, | |||
| onChange, | |||
| register, | |||
| initialOrgId, | |||
| initialOrgName, | |||
| label = 'Organisation', | |||
| size = 'small', | |||
| sx, | |||
| clearText, | |||
| closeText, | |||
| openText, | |||
| noOptionsText, | |||
| }) { | |||
| const [options, setOptions] = useState([]); | |||
| const [inputValue, setInputValue] = useState(''); | |||
| const [loading, setLoading] = useState(false); | |||
| const requestIdRef = useRef(0); | |||
| const restoredRef = useRef(false); | |||
| const runFetch = useCallback((query, id, onComplete) => { | |||
| const requestId = ++requestIdRef.current; | |||
| setLoading(true); | |||
| fetchOrgCombo({ | |||
| query, | |||
| id, | |||
| onSuccess: (data) => { | |||
| if (requestId !== requestIdRef.current) return; | |||
| setOptions(data); | |||
| onComplete?.(data); | |||
| }, | |||
| onFinally: () => { | |||
| if (requestId === requestIdRef.current) { | |||
| setLoading(false); | |||
| } | |||
| }, | |||
| }); | |||
| }, []); | |||
| const debouncedSearch = useMemo( | |||
| () => debounce((query) => runFetch(query), SEARCH_DEBOUNCE_MS), | |||
| [runFetch] | |||
| ); | |||
| useEffect(() => () => debouncedSearch.cancel(), [debouncedSearch]); | |||
| useEffect(() => { | |||
| setInputValue(value ? getOrgOptionLabel(value) : ''); | |||
| }, [value]); | |||
| const onChangeRef = useRef(onChange); | |||
| onChangeRef.current = onChange; | |||
| useEffect(() => { | |||
| if (restoredRef.current) return; | |||
| if (!initialOrgId && !initialOrgName) return; | |||
| restoredRef.current = true; | |||
| if (initialOrgId) { | |||
| runFetch(null, initialOrgId, (data) => { | |||
| const org = data?.[0]; | |||
| if (org) { | |||
| onChangeRef.current(org); | |||
| } | |||
| }); | |||
| } else if (initialOrgName) { | |||
| runFetch(initialOrgName, null, (data) => { | |||
| const org = data?.find((item) => item.name === initialOrgName) ?? data?.[0]; | |||
| if (org) { | |||
| onChangeRef.current(org); | |||
| } | |||
| }); | |||
| } | |||
| }, [initialOrgId, initialOrgName, runFetch]); | |||
| const handleInputChange = (event, newInputValue, reason) => { | |||
| setInputValue(newInputValue); | |||
| if (reason === 'reset') { | |||
| return; | |||
| } | |||
| debouncedSearch.cancel(); | |||
| if (!newInputValue.trim()) { | |||
| requestIdRef.current += 1; | |||
| setOptions([]); | |||
| setLoading(false); | |||
| return; | |||
| } | |||
| debouncedSearch(newInputValue); | |||
| }; | |||
| return ( | |||
| <Autocomplete | |||
| {...(register ? register('orgId') : {})} | |||
| disablePortal | |||
| id="orgId" | |||
| options={options} | |||
| groupBy={(option) => option.groupType} | |||
| size={size} | |||
| value={value ?? null} | |||
| getOptionLabel={getOrgOptionLabel} | |||
| filterOptions={(opts) => opts} | |||
| renderOption={renderOrgOption} | |||
| loading={loading} | |||
| inputValue={inputValue} | |||
| onInputChange={handleInputChange} | |||
| onOpen={() => { | |||
| if (inputValue.trim() && options.length === 0) { | |||
| runFetch(inputValue); | |||
| } | |||
| }} | |||
| onChange={(event, newValue) => { | |||
| onChange(newValue); | |||
| }} | |||
| sx={{ | |||
| '& .MuiInputBase-root': { alignItems: 'center' }, | |||
| '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' }, | |||
| '& .MuiOutlinedInput-root': { height: 40 }, | |||
| ...sx, | |||
| }} | |||
| renderInput={(params) => ( | |||
| <TextField | |||
| {...params} | |||
| label={label} | |||
| InputLabelProps={{ | |||
| shrink: true, | |||
| }} | |||
| InputProps={{ | |||
| ...params.InputProps, | |||
| endAdornment: ( | |||
| <> | |||
| {loading ? <CircularProgress color="inherit" size={18} /> : null} | |||
| {params.InputProps.endAdornment} | |||
| </> | |||
| ), | |||
| }} | |||
| /> | |||
| )} | |||
| renderGroup={(params) => ( | |||
| <Grid item key={params.key}> | |||
| <Typography fontSize={20} fontStyle="italic" p={1}> | |||
| {params.group} | |||
| </Typography> | |||
| {params.children} | |||
| </Grid> | |||
| )} | |||
| clearText={clearText} | |||
| closeText={closeText} | |||
| openText={openText} | |||
| noOptionsText={noOptionsText} | |||
| /> | |||
| ); | |||
| } | |||
| @@ -0,0 +1,32 @@ | |||
| import { Box, Typography } from '@mui/material'; | |||
| import { getOrgDisplayNames } from 'utils/OrgComboUtils'; | |||
| export default function OrgOptionLabel({ option }) { | |||
| const { primary, secondary } = getOrgDisplayNames(option); | |||
| if (!primary) return null; | |||
| return ( | |||
| <Box sx={{ py: 0.25, width: '100%' }}> | |||
| <Typography variant="body2" lineHeight={1.3}> | |||
| {primary} | |||
| </Typography> | |||
| {secondary ? ( | |||
| <Typography | |||
| variant="body2" | |||
| color="text.secondary" | |||
| lineHeight={1.25} | |||
| sx={{ display: 'block', mt: 0.25, fontSize: '0.8125rem' }} | |||
| > | |||
| {secondary} | |||
| </Typography> | |||
| ) : null} | |||
| </Box> | |||
| ); | |||
| } | |||
| export const renderOrgOption = (props, option) => ( | |||
| <li {...props} key={option.key ?? option.id}> | |||
| <OrgOptionLabel option={option} /> | |||
| </li> | |||
| ); | |||
| @@ -6,6 +6,7 @@ import { | |||
| Typography | |||
| } from '@mui/material'; | |||
| import MainCard from "components/MainCard"; | |||
| import OrgComboAutocomplete from "components/OrgComboAutocomplete"; | |||
| import { useForm } from "react-hook-form"; | |||
| import * as React from "react"; | |||
| import * as ComboData from "utils/ComboData"; | |||
| @@ -21,12 +22,11 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo"; | |||
| import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; | |||
| import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issueComboData, onGridReady | |||
| const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData, onGridReady | |||
| }) => { | |||
| const [type, setType] = React.useState([]); | |||
| const [orgSelected, setOrgSelected] = React.useState({}); | |||
| const [orgCombo, setOrgCombo] = React.useState(); | |||
| const [issueSelected, setIssueSelected] = React.useState({}); | |||
| const [issueCombo, setIssueCombo] = React.useState([]); | |||
| const [selectedStatus, setSelectedStatus] = React.useState(ComboData.denmandNoteStatus[0]); | |||
| @@ -122,15 +122,6 @@ const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issue | |||
| }; | |||
| React.useEffect(() => { | |||
| if (orgComboData && orgComboData.length > 0) { | |||
| setOrgCombo(orgComboData); | |||
| if(searchCriteria.orgId!=undefined){ | |||
| setOrgSelected(orgComboData.find(item => item.key === searchCriteria.orgId)) | |||
| } | |||
| } | |||
| }, [orgComboData]); | |||
| React.useEffect(() => { | |||
| if (issueComboData && issueComboData.length > 0) { | |||
| setIssueCombo(issueComboData); | |||
| @@ -244,56 +235,20 @@ const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issue | |||
| /> | |||
| </Grid> | |||
| { | |||
| orgCombo ? | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <Autocomplete | |||
| {...register("orgId")} | |||
| disablePortal | |||
| id="orgId" | |||
| options={orgCombo} | |||
| groupBy={(option) => option.groupType} | |||
| size="small" | |||
| value={orgSelected} | |||
| getOptionLabel={(option) => option.name? option.name : ""} | |||
| inputValue={orgSelected ? orgSelected.name!=undefined?orgSelected.name:"" : ""} | |||
| onChange={(event, newValue) => { | |||
| if (newValue !== null) { | |||
| setOrgSelected(newValue); | |||
| }else{ | |||
| setOrgSelected({}); | |||
| } | |||
| }} | |||
| sx={{ | |||
| '& .MuiInputBase-root': { alignItems: 'center' }, | |||
| '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' }, | |||
| '& .MuiOutlinedInput-root': { height: 40 } | |||
| }} | |||
| renderInput={(params) => ( | |||
| <TextField {...params} | |||
| label="Organisation" | |||
| InputLabelProps={{ | |||
| shrink: true | |||
| }} | |||
| /> | |||
| )} | |||
| renderGroup={(params) => ( | |||
| <Grid item key={params.key}> | |||
| <Typography fontSize={20} fontStyle="italic" p={1}> | |||
| {params.group} | |||
| </Typography> | |||
| {params.children} | |||
| </Grid> | |||
| )} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| : <></> | |||
| } | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <OrgComboAutocomplete | |||
| register={register} | |||
| value={orgSelected?.key ? orgSelected : null} | |||
| initialOrgId={searchCriteria.orgId} | |||
| onChange={(newValue) => { | |||
| setOrgSelected(newValue ?? {}); | |||
| }} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <TextField | |||
| @@ -33,7 +33,6 @@ const BackgroundHead = { | |||
| const UserSearchPage_Individual = () => { | |||
| const [orgCombo, setOrgCombo] = React.useState([]); | |||
| const [issueCombo, setIssueCombo] = React.useState([]); | |||
| const [searchCriteria, setSearchCriteria] = React.useState({ | |||
| // dateTo: DateUtils.dateValue(new Date()), | |||
| @@ -45,7 +44,6 @@ const UserSearchPage_Individual = () => { | |||
| const [onGridReady, setGridOnReady] = React.useState(false); | |||
| React.useEffect(() => { | |||
| getOrgCombo(); | |||
| getIssueCombo(); | |||
| if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){ | |||
| setSearchCriteria(getSearchCriteria(window.location.pathname)) | |||
| @@ -63,16 +61,6 @@ const UserSearchPage_Individual = () => { | |||
| }, [searchCriteria]); | |||
| function getOrgCombo() { | |||
| HttpUtils.get({ | |||
| url: UrlUtils.GET_ORG_COMBO, | |||
| onSuccess: function (responseData) { | |||
| let combo = responseData; | |||
| setOrgCombo(combo); | |||
| } | |||
| }); | |||
| } | |||
| function getIssueCombo() { | |||
| HttpUtils.get({ | |||
| url: UrlUtils.GET_ISSUE_COMBO, | |||
| @@ -115,7 +103,6 @@ const UserSearchPage_Individual = () => { | |||
| <Grid item xs={12} md={12} lg={12} sx={{mb: -1}}> | |||
| <SearchForm | |||
| applySearch={applySearch} | |||
| orgComboData={orgCombo} | |||
| issueComboData={issueCombo} | |||
| searchCriteria={searchCriteria} | |||
| onGridReady={onGridReady} | |||
| @@ -7,7 +7,7 @@ import { | |||
| import MainCard from "components/MainCard"; | |||
| import * as React from "react"; | |||
| import {GET_ORG_COMBO, GET_ISSUE_COMBO} from "utils/ApiPathConst"; | |||
| import {GET_ISSUE_COMBO} from "utils/ApiPathConst"; | |||
| import * as HttpUtils from "utils/HttpUtils"; | |||
| import * as DateUtils from "utils/DateUtils"; | |||
| import { getSearchCriteria } from "auth/utils"; | |||
| @@ -34,14 +34,12 @@ const BackgroundHead = { | |||
| const SearchPage_DemandNote_Pub = () => { | |||
| usePageTitle("paymentInfoRecord"); | |||
| const [orgCombo, setOrgCombo] = React.useState([]); | |||
| const [issueCombo, setIssueCombo] = React.useState([]); | |||
| const [searchCriteria, setSearchCriteria] = React.useState({}); | |||
| const [onReady, setOnReady] = React.useState(false); | |||
| const [onGridReady, setGridOnReady] = React.useState(false); | |||
| React.useEffect(() => { | |||
| getOrgCombo(); | |||
| getIssueCombo(); | |||
| if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){ | |||
| setSearchCriteria(getSearchCriteria(window.location.pathname)) | |||
| @@ -59,16 +57,6 @@ const SearchPage_DemandNote_Pub = () => { | |||
| }, [searchCriteria]); | |||
| function getOrgCombo() { | |||
| HttpUtils.get({ | |||
| url: GET_ORG_COMBO, | |||
| onSuccess: function (responseData) { | |||
| let combo = responseData; | |||
| setOrgCombo(combo); | |||
| } | |||
| }); | |||
| } | |||
| function getIssueCombo() { | |||
| HttpUtils.get({ | |||
| url: GET_ISSUE_COMBO, | |||
| @@ -112,7 +100,6 @@ const SearchPage_DemandNote_Pub = () => { | |||
| <Grid item xs={12} md={12} lg={12} sx={{mb:-1}}> | |||
| <SearchForm | |||
| applySearch={applySearch} | |||
| orgComboData={orgCombo} | |||
| issueComboData={issueCombo} | |||
| searchCriteria={searchCriteria} | |||
| onGridReady={onGridReady} | |||
| @@ -5,6 +5,7 @@ import { | |||
| Autocomplete | |||
| } from '@mui/material'; | |||
| import MainCard from "components/MainCard"; | |||
| import OrgComboAutocomplete from "components/OrgComboAutocomplete"; | |||
| import { useForm } from "react-hook-form"; | |||
| import * as React from "react"; | |||
| import * as ComboData from "utils/ComboData"; | |||
| @@ -21,13 +22,12 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo"; | |||
| import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; | |||
| import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, issueComboData, onGridReady | |||
| const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData, onGridReady | |||
| }) => { | |||
| const [type, setType] = React.useState([]); | |||
| const [status, setStatus] = React.useState(searchCriteria.statusKey!=undefined?ComboData.proofStatus_GLD[searchCriteria.statusKey]:ComboData.proofStatus_GLD[0]); | |||
| const [orgSelected, setOrgSelected] = React.useState(null); | |||
| const [orgCombo, setOrgCombo] = React.useState(); | |||
| const [issueSelected, setIssueSelected] = React.useState(null); | |||
| const [issueCombo, setIssueCombo] = React.useState([]); | |||
| const [groupSelected, setGroupSelected] = React.useState( | |||
| @@ -119,15 +119,6 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss | |||
| applySearch(temp); | |||
| }; | |||
| React.useEffect(() => { | |||
| if (orgComboData && orgComboData.length > 0) { | |||
| setOrgCombo(orgComboData); | |||
| if(searchCriteria.orgId!=undefined){ | |||
| setOrgSelected(orgComboData.find(item => item.key === searchCriteria.orgId)) | |||
| } | |||
| } | |||
| }, [orgComboData]); | |||
| React.useEffect(() => { | |||
| if (issueComboData && issueComboData.length > 0) { | |||
| setIssueCombo(issueComboData); | |||
| @@ -384,48 +375,16 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss | |||
| /> | |||
| </Grid> | |||
| { | |||
| orgCombo ? | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <Autocomplete | |||
| {...register("orgId")} | |||
| disablePortal | |||
| id="orgId" | |||
| options={orgCombo} | |||
| groupBy={(option) => option.groupType} | |||
| size="small" | |||
| value={orgSelected} | |||
| getOptionLabel={(option) => option.name? option.name : ""} | |||
| inputValue={orgSelected ? orgSelected.name!=undefined?orgSelected.name:"" : ""} | |||
| onChange={(event, newValue) => { | |||
| setOrgSelected(newValue ?? null); | |||
| }} | |||
| sx={{ | |||
| '& .MuiInputBase-root': { alignItems: 'center' }, | |||
| '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' }, | |||
| '& .MuiOutlinedInput-root': { height: 40 } | |||
| }} | |||
| renderInput={(params) => ( | |||
| <TextField {...params} | |||
| label="Organisation" | |||
| InputLabelProps={{ | |||
| shrink: true | |||
| }} | |||
| /> | |||
| )} | |||
| renderGroup={(params) => ( | |||
| <Grid item key={params.key}> | |||
| <Typography fontSize={20} fontStyle="italic" p={1}> | |||
| {params.group} | |||
| </Typography> | |||
| {params.children} | |||
| </Grid> | |||
| )} | |||
| /> | |||
| </Grid> | |||
| : <></> | |||
| } | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <OrgComboAutocomplete | |||
| register={register} | |||
| value={orgSelected} | |||
| initialOrgId={searchCriteria.orgId} | |||
| onChange={(newValue) => { | |||
| setOrgSelected(newValue ?? null); | |||
| }} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| @@ -9,7 +9,7 @@ import MainCard from "components/MainCard"; | |||
| import * as React from "react"; | |||
| import * as HttpUtils from "utils/HttpUtils"; | |||
| import * as DateUtils from "utils/DateUtils"; | |||
| import {GET_ORG_COMBO, GET_ISSUE_COMBO} from "utils/ApiPathConst"; | |||
| import {GET_ISSUE_COMBO} from "utils/ApiPathConst"; | |||
| import { getSearchCriteria } from "auth/utils"; | |||
| import Loadable from 'components/Loadable'; | |||
| @@ -31,14 +31,12 @@ const BackgroundHead = { | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserSearchPage_Individual = () => { | |||
| const [orgCombo, setOrgCombo] = React.useState([]); | |||
| const [issueCombo, setIssueCombo] = React.useState([]); | |||
| const [searchCriteria, setSearchCriteria] = React.useState({}); | |||
| const [onReady, setOnReady] = React.useState(false); | |||
| const [onGridReady, setGridOnReady] = React.useState(false); | |||
| React.useEffect(() => { | |||
| getOrgCombo(); | |||
| getIssueCombo(); | |||
| if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){ | |||
| setSearchCriteria(getSearchCriteria(window.location.pathname)) | |||
| @@ -56,16 +54,6 @@ const UserSearchPage_Individual = () => { | |||
| }, [searchCriteria]); | |||
| function getOrgCombo() { | |||
| HttpUtils.get({ | |||
| url: GET_ORG_COMBO, | |||
| onSuccess: function (responseData) { | |||
| let combo = responseData; | |||
| setOrgCombo(combo); | |||
| } | |||
| }); | |||
| } | |||
| function getIssueCombo() { | |||
| HttpUtils.get({ | |||
| url: GET_ISSUE_COMBO, | |||
| @@ -106,7 +94,6 @@ const UserSearchPage_Individual = () => { | |||
| <Grid item xs={12} md={12} lg={12} sx={{mb:-1}}> | |||
| <SearchForm | |||
| applySearch={applySearch} | |||
| orgComboData={orgCombo} | |||
| issueComboData={issueCombo} | |||
| searchCriteria={searchCriteria} | |||
| onGridReady={onGridReady} | |||
| @@ -6,6 +6,7 @@ import { | |||
| Typography | |||
| } from '@mui/material'; | |||
| import MainCard from "components/MainCard"; | |||
| import OrgComboAutocomplete from "components/OrgComboAutocomplete"; | |||
| import { useForm } from "react-hook-form"; | |||
| import * as React from "react"; | |||
| import * as ComboData from "utils/ComboData"; | |||
| @@ -21,14 +22,11 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo"; | |||
| import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; | |||
| import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, issueComboData, onGridReady | |||
| const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData, onGridReady | |||
| }) => { | |||
| const [type, setType] = React.useState([]); | |||
| // const [status, setStatus] = React.useState({ key: 0, label: 'All', type: 'all' }); | |||
| const [orgSelected, setOrgSelected] = React.useState(null); | |||
| const [inputValue, setInputValue] = React.useState(""); | |||
| const [orgCombo, setOrgCombo] = React.useState(); | |||
| const [issueSelected, setIssueSelected] = React.useState({}); | |||
| const [issueCombo, setIssueCombo] = React.useState([]); | |||
| const [selectedStatus, setSelectedStatus] = React.useState({key: 0, label: 'All', type: 'all'}); | |||
| @@ -102,15 +100,6 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss | |||
| // setSearchReady(true) | |||
| }; | |||
| React.useEffect(() => { | |||
| if (orgComboData && orgComboData.length > 0) { | |||
| setOrgCombo(orgComboData); | |||
| if(searchCriteria.orgId!=undefined){ | |||
| setOrgSelected(orgComboData.find(item => item.key === searchCriteria.orgId)) | |||
| } | |||
| } | |||
| }, [orgComboData]); | |||
| React.useEffect(() => { | |||
| if (issueComboData && issueComboData.length > 0) { | |||
| setIssueCombo(issueComboData); | |||
| @@ -124,7 +113,6 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss | |||
| setType([]); | |||
| // setStatus({ key: 0, label: 'All', type: 'all' }); | |||
| setOrgSelected(null); | |||
| setInputValue(""); | |||
| setIssueSelected({}); | |||
| setGroupSelected({}); | |||
| setSelectedStatus({key: 0, label: 'All', type: 'all'}); | |||
| @@ -330,56 +318,16 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss | |||
| /> */} | |||
| </Grid> | |||
| { | |||
| orgCombo ? | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: marginBottom }}> | |||
| <Autocomplete | |||
| {...register("orgId")} | |||
| disablePortal | |||
| id="orgId" | |||
| options={orgCombo} | |||
| groupBy={(option) => option.groupType} | |||
| size="small" | |||
| value={orgSelected} | |||
| getOptionLabel={(option) => option?.name ?? ""} | |||
| inputValue={inputValue} | |||
| onInputChange={(event, newInputValue) => { | |||
| setInputValue(newInputValue); | |||
| }} | |||
| onChange={(event, newValue) => { | |||
| if (newValue) { | |||
| setOrgSelected(newValue); | |||
| } else { | |||
| setOrgSelected({}); | |||
| } | |||
| }} | |||
| sx={{ | |||
| '& .MuiInputBase-root': { alignItems: 'center' }, | |||
| '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' }, | |||
| '& .MuiOutlinedInput-root': { height: 40 } | |||
| }} | |||
| renderInput={(params) => ( | |||
| <TextField | |||
| {...params} | |||
| label="Organisation" | |||
| InputLabelProps={{ | |||
| shrink: true, | |||
| }} | |||
| /> | |||
| )} | |||
| renderGroup={(params) => ( | |||
| <Grid item key={params.key}> | |||
| <Typography fontSize={20} fontStyle="italic" p={1}> | |||
| {params.group} | |||
| </Typography> | |||
| {params.children} | |||
| </Grid> | |||
| )} | |||
| /> | |||
| </Grid> | |||
| : <></> | |||
| } | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: marginBottom }}> | |||
| <OrgComboAutocomplete | |||
| register={register} | |||
| value={orgSelected} | |||
| initialOrgId={searchCriteria.orgId} | |||
| onChange={(newValue) => { | |||
| setOrgSelected(newValue ?? null); | |||
| }} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: marginBottom }}> | |||
| <Autocomplete | |||
| @@ -30,14 +30,12 @@ const BackgroundHead = { | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserSearchPage_Individual = () => { | |||
| const [orgCombo, setOrgCombo] = React.useState([]); | |||
| const [issueCombo, setIssueCombo] = React.useState([]); | |||
| const [searchCriteria, setSearchCriteria] = React.useState({}); | |||
| const [onReady, setOnReady] = React.useState(false); | |||
| const [onGridReady, setGridOnReady] = React.useState(false); | |||
| React.useEffect(() => { | |||
| getOrgCombo(); | |||
| getIssueCombo(); | |||
| if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){ | |||
| setSearchCriteria(getSearchCriteria(window.location.pathname)) | |||
| @@ -54,16 +52,6 @@ const UserSearchPage_Individual = () => { | |||
| setOnReady(true); | |||
| }, [searchCriteria]); | |||
| function getOrgCombo() { | |||
| HttpUtils.get({ | |||
| url: UrlUtils.GET_ORG_COMBO, | |||
| onSuccess: function (responseData) { | |||
| let combo = responseData; | |||
| setOrgCombo(combo); | |||
| } | |||
| }); | |||
| } | |||
| function getIssueCombo() { | |||
| HttpUtils.get({ | |||
| url: UrlUtils.GET_ISSUE_COMBO, | |||
| @@ -104,7 +92,6 @@ const UserSearchPage_Individual = () => { | |||
| <Grid item xs={12} md={12} lg={12} sx={{mb: -1}}> | |||
| <SearchForm | |||
| applySearch={applySearch} | |||
| orgComboData={orgCombo} | |||
| issueComboData={issueCombo} | |||
| searchCriteria={searchCriteria} | |||
| onGridReady={onGridReady} | |||
| @@ -6,6 +6,7 @@ import { | |||
| Typography | |||
| } from '@mui/material'; | |||
| import MainCard from "components/MainCard"; | |||
| import OrgComboAutocomplete from "components/OrgComboAutocomplete"; | |||
| import { useForm } from "react-hook-form"; | |||
| import * as React from "react"; | |||
| import * as ComboData from "utils/ComboData"; | |||
| @@ -21,13 +22,11 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo"; | |||
| import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; | |||
| import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, issueComboData, onGridReady | |||
| const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData, onGridReady | |||
| }) => { | |||
| const [type, setType] = React.useState([]); | |||
| // const [status, setStatus] = React.useState({ key: 0, label: 'All', type: 'all' }); | |||
| const [orgSelected, setOrgSelected] = React.useState({}); | |||
| const [orgCombo, setOrgCombo] = React.useState(); | |||
| const [issueSelected, setIssueSelected] = React.useState({}); | |||
| const [issueCombo, setIssueCombo] = React.useState([]); | |||
| const [selectedStatus, setSelectedStatus] = React.useState({key: 0, label: 'All', type: 'all'}); | |||
| @@ -92,15 +91,6 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss | |||
| applySearch(temp); | |||
| }; | |||
| React.useEffect(() => { | |||
| if (orgComboData && orgComboData.length > 0) { | |||
| setOrgCombo(orgComboData); | |||
| if(searchCriteria.orgId!=undefined){ | |||
| setOrgSelected(orgComboData.find(item => item.key === searchCriteria.orgId)) | |||
| } | |||
| } | |||
| }, [orgComboData]); | |||
| React.useEffect(() => { | |||
| if (issueComboData && issueComboData.length > 0) { | |||
| setIssueCombo(issueComboData); | |||
| @@ -317,51 +307,16 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss | |||
| />*/} | |||
| </Grid> | |||
| { | |||
| orgCombo ? | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: marginBottom }}> | |||
| <Autocomplete | |||
| {...register("orgId")} | |||
| disablePortal | |||
| id="orgId" | |||
| options={orgCombo} | |||
| groupBy={(option) => option.groupType} | |||
| size="small" | |||
| value={orgSelected} | |||
| getOptionLabel={(option) => option.name? option.name : ""} | |||
| inputValue={orgSelected ? orgSelected.name!=undefined?orgSelected.name:"" : ""} | |||
| onChange={(event, newValue) => { | |||
| if (newValue !== null) { | |||
| setOrgSelected(newValue); | |||
| }else{ | |||
| setOrgSelected({}); | |||
| } | |||
| }} | |||
| sx={{ | |||
| '& .MuiInputBase-root': { alignItems: 'center' }, | |||
| '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' }, | |||
| '& .MuiOutlinedInput-root': { height: 40 } | |||
| }} | |||
| renderInput={(params) => ( | |||
| <TextField {...params} | |||
| label="Organisation" | |||
| InputLabelProps={{ | |||
| shrink: true | |||
| }} | |||
| /> | |||
| )} | |||
| renderGroup={(params) => ( | |||
| <Grid item key={params.key}> | |||
| <Typography fontSize={20} fontStyle="italic" p={1}> | |||
| {params.group} | |||
| </Typography> | |||
| {params.children} | |||
| </Grid> | |||
| )} | |||
| /> | |||
| </Grid> | |||
| : <></> | |||
| } | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: marginBottom }}> | |||
| <OrgComboAutocomplete | |||
| register={register} | |||
| value={orgSelected?.key ? orgSelected : null} | |||
| initialOrgId={searchCriteria.orgId} | |||
| onChange={(newValue) => { | |||
| setOrgSelected(newValue ?? {}); | |||
| }} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: marginBottom }}> | |||
| <Autocomplete | |||
| @@ -30,14 +30,12 @@ const BackgroundHead = { | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserSearchPage_Individual = () => { | |||
| const [orgCombo, setOrgCombo] = React.useState([]); | |||
| const [issueCombo, setIssueCombo] = React.useState([]); | |||
| const [searchCriteria, setSearchCriteria] = React.useState({}); | |||
| const [onReady, setOnReady] = React.useState(false); | |||
| const [onGridReady, setGridOnReady] = React.useState(false); | |||
| React.useEffect(() => { | |||
| getOrgCombo(); | |||
| getIssueCombo(); | |||
| if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){ | |||
| setSearchCriteria(getSearchCriteria(window.location.pathname)) | |||
| @@ -54,16 +52,6 @@ const UserSearchPage_Individual = () => { | |||
| setOnReady(true); | |||
| }, [searchCriteria]); | |||
| function getOrgCombo() { | |||
| HttpUtils.get({ | |||
| url: UrlUtils.GET_ORG_COMBO, | |||
| onSuccess: function (responseData) { | |||
| let combo = responseData; | |||
| setOrgCombo(combo); | |||
| } | |||
| }); | |||
| } | |||
| function getIssueCombo() { | |||
| HttpUtils.get({ | |||
| url: UrlUtils.GET_ISSUE_COMBO, | |||
| @@ -104,7 +92,6 @@ const UserSearchPage_Individual = () => { | |||
| <Grid item xs={12} md={12} lg={12} sx={{mb: -1}}> | |||
| <SearchForm | |||
| applySearch={applySearch} | |||
| orgComboData={orgCombo} | |||
| issueComboData={issueCombo} | |||
| searchCriteria={searchCriteria} | |||
| onGridReady={onGridReady} | |||
| @@ -10,6 +10,8 @@ import * as FieldUtils from "utils/FieldUtils"; | |||
| import * as HttpUtils from 'utils/HttpUtils'; | |||
| import { POST_ORG_USER, GET_IND_USER_VERIFY, GET_USER_LOCK, GET_USER_UNLOCK } from "utils/ApiPathConst"; | |||
| import * as ComboData from "utils/ComboData"; | |||
| import { filterOrgComboOptions, getOrgOptionLabel } from "utils/OrgComboUtils"; | |||
| import { renderOrgOption } from "components/OrgOptionLabel"; | |||
| import { useFormik } from 'formik'; | |||
| import * as yup from 'yup'; | |||
| @@ -315,7 +317,9 @@ const UserInformationCard_Organization = ({ userData, loadDataFun, orgData }) => | |||
| {FieldUtils.getComboField({ | |||
| label: "Organisation:", | |||
| valueName: "orgId", | |||
| getOptionLabel: (option) => option.enCompanyName ? option.enCompanyName : option.chCompanyName ? option.chCompanyName : "", | |||
| getOptionLabel: getOrgOptionLabel, | |||
| renderOption: renderOrgOption, | |||
| filterOptions: filterOrgComboOptions, | |||
| dataList: orgData, | |||
| disabled: (!editMode), | |||
| form: formik | |||
| @@ -6,6 +6,7 @@ import { | |||
| Typography | |||
| } from '@mui/material'; | |||
| import MainCard from "../../../components/MainCard"; | |||
| import OrgComboAutocomplete from "../../../components/OrgComboAutocomplete"; | |||
| import {useForm} from "react-hook-form"; | |||
| import { useState, useEffect} from "react"; | |||
| @@ -14,11 +15,10 @@ import {ThemeProvider} from "@emotion/react"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserSearchForm_Organization = ({applySearch, orgComboData, onGridReady, searchCriteria}) => { | |||
| const UserSearchForm_Organization = ({applySearch, onGridReady, searchCriteria}) => { | |||
| const [type, setType] = useState([]); | |||
| const [accountFilter, setAccountFilter] = useState("All"); | |||
| const [orgCombo, setOrgCombo] = useState(); | |||
| const [orgSelected, setOrgSelected] = useState({}); | |||
| const { reset, register, handleSubmit } = useForm() | |||
| @@ -58,15 +58,6 @@ const UserSearchForm_Organization = ({applySearch, orgComboData, onGridReady, se | |||
| applySearch(temp); | |||
| }; | |||
| useEffect(() => { | |||
| if (orgComboData && orgComboData.length > 0) { | |||
| setOrgCombo(orgComboData); | |||
| if(searchCriteria.orgName!=undefined){ | |||
| setOrgSelected(orgComboData.find(item => item.name === searchCriteria.orgName)) | |||
| } | |||
| } | |||
| }, [orgComboData]); | |||
| function resetForm(){ | |||
| setType([]); | |||
| setAccountFilter("All"); | |||
| @@ -98,52 +89,16 @@ const UserSearchForm_Organization = ({applySearch, orgComboData, onGridReady, se | |||
| {/*row 2*/} | |||
| <Grid container display="flex" alignItems={"center"}> | |||
| { | |||
| orgCombo ? | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <Autocomplete | |||
| {...register("orgId")} | |||
| disablePortal | |||
| id="orgId" | |||
| options={orgCombo} | |||
| groupBy={(option) => option.groupType} | |||
| size="small" | |||
| value={orgSelected} | |||
| getOptionLabel={(option) => option.name? option.name : ""} | |||
| inputValue={orgSelected ? orgSelected.name!=undefined?orgSelected.name:"" : ""} | |||
| onChange={(event, newValue) => { | |||
| if (newValue !== null) { | |||
| setOrgSelected(newValue); | |||
| }else{ | |||
| setOrgSelected({}); | |||
| } | |||
| }} | |||
| sx={{ | |||
| '& .MuiInputBase-root': { alignItems: 'center' }, | |||
| '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' }, | |||
| '& .MuiOutlinedInput-root': { height: 40 } | |||
| }} | |||
| renderInput={(params) => ( | |||
| <TextField {...params} | |||
| label="Organisation" | |||
| InputLabelProps={{ | |||
| shrink: true | |||
| }} | |||
| /> | |||
| )} | |||
| renderGroup={(params) => ( | |||
| <Grid item key={params.key}> | |||
| <Typography fontSize={20} fontStyle="italic" p={1}> | |||
| {params.group} | |||
| </Typography> | |||
| {params.children} | |||
| </Grid> | |||
| )} | |||
| /> | |||
| </Grid> | |||
| : <></> | |||
| } | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <OrgComboAutocomplete | |||
| register={register} | |||
| value={orgSelected?.key ? orgSelected : null} | |||
| initialOrgName={searchCriteria.orgName} | |||
| onChange={(newValue) => { | |||
| setOrgSelected(newValue ?? {}); | |||
| }} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| @@ -5,8 +5,6 @@ import { | |||
| import MainCard from "components/MainCard"; | |||
| import { useEffect, useState, lazy } from "react"; | |||
| import Loadable from 'components/Loadable'; | |||
| import * as HttpUtils from "utils/HttpUtils"; | |||
| import {GET_ORG_COMBO} from "utils/ApiPathConst"; | |||
| import { getSearchCriteria } from "auth/utils"; | |||
| import usePageTitle from "components/usePageTitle"; | |||
| @@ -31,14 +29,11 @@ const UserSearchPage_Organization = () => { | |||
| // Localized document title/meta for organization user search | |||
| usePageTitle("organizationProfile"); | |||
| const [orgCombo, setOrgCombo] = useState([]); | |||
| const [searchCriteria, setSearchCriteria] = useState({}); | |||
| const [onReady, setOnReady] = useState(false); | |||
| const [onGridReady, setGridOnReady] = useState(false); | |||
| useEffect(() => { | |||
| getOrgCombo(); | |||
| // getIssueCombo(); | |||
| if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){ | |||
| setSearchCriteria(getSearchCriteria(window.location.pathname)) | |||
| }else{ | |||
| @@ -47,16 +42,6 @@ const UserSearchPage_Organization = () => { | |||
| } | |||
| }, []); | |||
| function getOrgCombo() { | |||
| HttpUtils.get({ | |||
| url: GET_ORG_COMBO, | |||
| onSuccess: function (responseData) { | |||
| let combo = responseData; | |||
| setOrgCombo(combo); | |||
| } | |||
| }); | |||
| } | |||
| useEffect(() => { | |||
| setOnReady(true); | |||
| }, [searchCriteria]); | |||
| @@ -91,7 +76,6 @@ const UserSearchPage_Organization = () => { | |||
| <Grid item xs={12} md={12} lg={12} sx={{mb:-1}}> | |||
| <SearchForm | |||
| applySearch={applySearch} | |||
| orgComboData={orgCombo} | |||
| onGridReady={onGridReady} | |||
| searchCriteria={searchCriteria} | |||
| /> | |||
| @@ -0,0 +1,64 @@ | |||
| import { GET_ORG_COMBO } from 'utils/ApiPathConst'; | |||
| import * as HttpUtils from 'utils/HttpUtils'; | |||
| export const getOrgDisplayNames = (option) => { | |||
| if (!option) return { primary: "", secondary: "" }; | |||
| const en = option.enCompanyName?.trim() || ""; | |||
| const ch = option.chCompanyName?.trim() || ""; | |||
| if (en && ch) return { primary: en, secondary: ch }; | |||
| if (en) return { primary: en, secondary: "" }; | |||
| if (ch) return { primary: ch, secondary: "" }; | |||
| return { primary: option.name ?? "", secondary: "" }; | |||
| }; | |||
| export const getOrgOptionLabel = (option) => getOrgDisplayNames(option).primary; | |||
| const orgSearchFields = (option) => [ | |||
| option.name, | |||
| option.label, | |||
| option.brNo, | |||
| option.enCompanyName, | |||
| option.chCompanyName, | |||
| ]; | |||
| export const filterOrgComboOptions = (options, state) => { | |||
| const inputValue = state?.inputValue?.trim(); | |||
| if (!inputValue) return options; | |||
| const searchStr = inputValue.toLowerCase(); | |||
| return options.filter((option) => | |||
| orgSearchFields(option).some( | |||
| (field) => field != null && String(field).toLowerCase().includes(searchStr) | |||
| ) | |||
| ); | |||
| }; | |||
| export const fetchOrgCombo = ({ query, id, onSuccess, onFinally }) => { | |||
| const params = {}; | |||
| if (id) { | |||
| params.id = id; | |||
| } else if (query?.trim()) { | |||
| params.query = query.trim(); | |||
| } else { | |||
| onSuccess?.([]); | |||
| onFinally?.(); | |||
| return; | |||
| } | |||
| HttpUtils.get({ | |||
| url: GET_ORG_COMBO, | |||
| params, | |||
| onSuccess: (responseData) => { | |||
| onSuccess?.(Array.isArray(responseData) ? responseData : []); | |||
| }, | |||
| onFail: () => { | |||
| onSuccess?.([]); | |||
| }, | |||
| onError: () => { | |||
| onSuccess?.([]); | |||
| }, | |||
| onFinally, | |||
| }); | |||
| }; | |||