\n )}\n\n {add && (\n \n )}\n >\n }\n actions={noActionsColumn ? customActionsWithoutColumn : actions}\n titleName={title}\n options={{\n filtering,\n selection,\n selectionProps,\n showSelectAllCheckbox,\n exportAllData: true,\n search: filterable,\n exportButton: !noExport && { csv: true, pdf: true },\n headerStyle: {\n position: 'sticky',\n top: 0,\n },\n cellStyle: { textAlign: 'left', wordWrap: 'break-word' },\n columnsButton: !noColumnsButton,\n resetColumnsButton: !noColumnsButton,\n maxBodyHeight,\n exportFileName: `${title}_Table_Export`,\n paging: true,\n addRowPosition: 'first',\n grouping,\n actionsColumnIndex: -1,\n pageSizeOptions: [50, 100, 250, 500],\n toolbarButtonAlignment,\n pageSize: 50,\n searchAutoFocus: false,\n showTextRowsSelected: false,\n emptyRowsWhenPaging: false,\n }}\n addActionRef={addActionRef}\n state={{\n columns: columns || transformColumns || loadingColumns,\n data: data || state?.data,\n }}\n editable={editable}\n parentChildData={parentChildData}\n remoteData={remoteData}\n tableRef={tableRef}\n detailPanel={detailPanel}\n overrideOnRowSelected={overrideOnRowSelected}\n defaultColumns={defaultColumns}\n />\n >\n );\n}\n","/* eslint-disable react-refresh/only-export-components */\nimport { useEffect, useMemo } from 'react';\nimport { useSelector, useDispatch } from 'react-redux';\nimport store from '../../store/store';\n\nimport Table, { loadingColumnsConstructor } from './ReduxTable';\nimport { axios } from '../../services/axios';\nimport { Error, EditForm, Modal } from '..';\n\n// A search function exported and used by only a few tables in the app\nexport const floatSearch = (v, rowData, field) => {\n return Math.abs(parseFloat(v) - rowData[field]) < Number.EPSILON;\n};\n\n// a custom function to create the title of the modal when clicking on a table entry\nexport const modalTitle = (data, attribute, section, mode) => {\n if (data !== null && data[attribute]) {\n return mode + section + ' : ' + data[attribute];\n }\n return mode + section;\n};\n\n// A function to dispatch the error in the modal to the state\nexport const onModalError = (e) => {\n store.dispatch({\n type: 'CHANGE_MODAL_BACKEND_ERROR',\n payload: e,\n });\n};\n\n/*\n * Table And Modal Function that takes in a series of props\n * This component is reponsible for fetching table data and displaying it as listed by the ReduxTable.jsx\n * This compoent is responsible for passing through data that is fetched to the modal so when a user clicks on a entry ->\n * The entry opens in a modal with all the required data that the entry has in the database\n * ReduxTable and ReduxModal are the two components that this uses to render those pages\n */\nexport default function TableAndModal(props) {\n const {\n // defaultColumns is used to set the columns for the table\n defaultColumns,\n // tableFetch is the url for the api to perform a get request to\n tableFetch,\n // onTableFetch is triggered when the fetch is performed\n onTableFetch,\n // onModalSucceed is used to trigger somethin when the modal request(whatever it is) returns a 200 - ie redirect to edit after add is successfull\n onModalSucceed,\n // overrideModalAdd is used to override the method for the add request of the modal\n overrideModalAdd,\n // overrideModalUpdate is used to override the method for the edit reuqest of the modal\n overrideModalUpdate,\n // onModalCopy is something that triggers after the 'Copy' functionality returns successfully\n onModalCopy,\n // overrideTableLoading overrides the loading method for the table\n overrideTableLoading,\n // modalFetch is the URL for the get request when you click the edit button on any of the tables\n modalFetch,\n // I am not sure what this does but it seems to take a series of 3 different data sets\n modalUpload,\n // onModalUpdate is a function that is triggered when the modalUpdate is sucessful\n onModalUpdate,\n // overrideOnModalError is a way to override the default error handling process of this component\n onModalError: overrideOnModalError,\n // modalAdd is the URL for the add option of a modal\n modalAdd,\n // modalConvert is the URL for the convert option of a modal\n modalConvert,\n // modalDelete is the URL for the delete option for a modal\n modalDelete,\n // modalUpdate is the URL for the put request when updating any entity that you have opened in a modal\n modalUpdate,\n // modalApproval is the URL for any reuqests made to approve a company using a modal\n modalApproval,\n // modalCopy is the URL for any requests made to modals using the copy mode\n modalCopy,\n // onModalAdd is a function that happens after a post request is sucessful, like redirecting to the edit page once a trunk is created\n onModalAdd,\n // the validation logic for a modal, it is presented as a combined error state for whatever is listed. Easier to understand looking a trunks.jsx\n modalValidate,\n // determines if the edit icon is shown in the table, bool\n editable,\n // I do not know what this does and have never seen it\n onModalChangeLogo,\n // If you want to pass static data to the table instead of fetching data this prop is used for that\n data,\n // determines if the modal will be a full page or if it wil be a pop up -> true is full page\n newPage,\n // Determines whether there is a alphabet based filter field on the Table component\n alphabetFilterField,\n // a way to override table rows actions for the Table - If you would like to have anything specific that isnt a option below\n rowActions: tableRowActions,\n // onTableSucceed is a method that is called once the table has successfully loaded\n onTableSucceed,\n // Set to true if implementing custom actions column\n noActionsColumn,\n } = props;\n\n // tableloading and error state\n const { loading: tableLoading, error } = useSelector((state) => {\n return { ...state.table };\n });\n\n // State of the modal destructured into many variables\n // TODO: Figure out what modalFreshData is, most likely something to do with the state hashing to stop leaving a page with unsaved changes\n const {\n loading: modalLoading,\n state: modalState,\n mode: modalMode,\n uploading: modalUploading,\n freshData: modalFreshData,\n show: modalShow,\n data: modalData,\n } = useSelector((state) => {\n return {\n ...state.modal,\n };\n });\n\n const dispatch = useDispatch();\n\n /*\n * Initial Table loading and fetching logic\n * if data and overrideTableLoading are not specificied AND tableLoading ->\n * Either make a fetch request of onTableFetch or axios.get with the tableFetch url passed in from props\n */\n useEffect(() => {\n if (!(data || overrideTableLoading) && tableLoading) {\n const fetchRequest = onTableFetch\n ? onTableFetch()\n : axios.get(tableFetch);\n fetchRequest\n .then((res) => {\n dispatch({\n type: 'CHANGE_TABLE_STATE',\n payload: {\n //transform data when data is fetched using default columns and onTableSuceed prop if its passsed in\n columns: defaultColumns,\n data: onTableSucceed\n ? onTableSucceed(res.data)\n : res.data,\n },\n });\n //custom sort by alphabet functionality only used once\n if (alphabetFilterField) {\n dispatch({ type: 'CHANGE_TABLE_INDEXING' });\n }\n dispatch({ type: 'CHANGE_TABLE_LOADING' });\n })\n .catch((e) => {\n if (e.response?.status !== 401) {\n dispatch({\n type: 'CHANGE_TABLE_ERROR',\n payload: e,\n });\n } else {\n dispatch({ type: 'CHANGE_TABLE_LOADING' });\n }\n });\n }\n }, [tableLoading]);\n\n /*\n * Loading of modal data if modalShow, modalLoading and modalFetch exist\n * modalFetch is used for axios request, this result is then dispatched to the modal State\n * loading and hash are then dispatched, else no modal is loaded\n */\n useEffect(() => {\n if (modalShow && modalLoading && modalFetch) {\n axios\n .get(modalFetch)\n .then((res) => {\n dispatch({\n type: 'CHANGE_MODAL_STATE',\n payload: {\n ...res.data,\n },\n });\n dispatch({ type: 'CHANGE_MODAL_LOADING', payload: false });\n dispatch({\n type: 'CHANGE_MODAL_HASH',\n });\n })\n .catch((e) => {\n onModalError(e);\n });\n } else if (modalShow && modalLoading && !modalFetch) {\n dispatch({ type: 'CHANGE_MODAL_LOADING', payload: false });\n dispatch({\n type: 'CHANGE_MODAL_HASH',\n });\n }\n }, [modalLoading, modalShow]);\n\n /*\n * A function to determine what tableRow actions to show based on either its a Add or Edit modal\n * tableRowActions are determined and based on some factors I don't understand a breadcrumb view is added\n * Breadcrumb view shows where the modal came from and some information around it in the title\n */\n const onSucceed = (res) => {\n if (modalMode === 'Add') {\n if (tableRowActions?.multiChildTable) {\n dispatch({\n type: 'OPEN_CHILD_TABLE',\n payload: { ...res.data, append: true },\n });\n dispatch({\n type: 'CHANGE_BREADCRUMB_VIEW',\n payload: tableRowActions?.multiChildTable?.to ?? 0,\n });\n dispatch({\n type: 'RESET_MODAL',\n });\n return;\n }\n if (\n tableRowActions?.childTable &&\n !tableRowActions?.childTable?.doNotOverrideOnModalSucceed\n ) {\n dispatch({\n type: 'OPEN_CHILD_TABLE',\n payload: { ...res.data, append: true },\n });\n dispatch({\n type: 'RESET_MODAL',\n });\n return;\n }\n }\n //this is how the table is loaded by default\n dispatch({\n type: 'ON_MODAL_SUBMIT_SUCCEED',\n });\n // change the table loading state\n dispatch({\n type: 'CHANGE_TABLE_LOADING',\n });\n // load the colums and data into the table state\n // dispatch({\n // type: 'CHANGE_TABLE_STATE',\n // payload: {columns: loadingColumns, data: loadingData},\n // });\n };\n\n /*\n * This fucntion determines what data you want to submit\n * And it also determins how you want to submit it\n */\n useEffect(() => {\n // whenever the modal is uploading, this effect checks what type the mode is and acts accordingly\n if (modalUploading) {\n var axiosResponse = null;\n switch (modalMode) {\n // change logo case: if validation happens and its false, return a error.\n // Otherwise use the provided axios endpoint\n case 'Change Logo':\n if (\n modalValidate && // need to do validation\n !modalValidate() //validation return false\n ) {\n onModalError({\n name: 'Field Error',\n message: 'There are some field errors.',\n });\n return;\n }\n axiosResponse = onModalChangeLogo();\n break;\n // delete case: return a delte response with the modalDelete url\n // not sure what the modalFreshData stuff means.\n case 'Delete':\n axiosResponse = axios.delete(\n modalDelete,\n modalUpload(modalFreshData || modalData, modalState),\n modalUpload(modalFreshData || modalData, modalState)\n .config,\n );\n\n break;\n // add case: if validation happens and it false, dispatch error.\n // else return either modalAdd url, overrideModalAdd or onModalAdd\n case 'Add':\n if (\n modalValidate && // need to do validation\n !modalValidate() //validation return false\n ) {\n onModalError({\n name: 'Field Error',\n message: 'There are some field errors.',\n });\n return;\n }\n\n if (modalAdd) {\n axiosResponse = axios.post(\n modalAdd,\n modalUpload(\n modalFreshData || modalData,\n modalState,\n ),\n );\n } else if (onModalAdd) {\n axiosResponse = onModalAdd();\n } else {\n overrideModalAdd();\n return;\n }\n break;\n // approval case: return the modalApproval URl\n case 'Approval':\n axiosResponse = axios.put(\n modalApproval,\n modalUpload(modalFreshData || modalData, modalState),\n );\n break;\n // convert case: return the modalConvert URL\n case 'Convert':\n axiosResponse = axios.post(\n modalConvert,\n modalUpload(modalFreshData || modalData),\n );\n break;\n // edit case: if validation is requred and is false, dispatch a error\n // else return modalUpdate, onModalUpdate or overrideModalUpdate based on props\n case 'Edit':\n if (\n modalValidate && // need to do validation\n !modalValidate() //validation return false\n ) {\n onModalError({\n name: 'Field Error',\n message: 'There are some field errors.',\n });\n return;\n }\n if (modalUpdate) {\n axiosResponse = axios.put(\n modalUpdate,\n modalUpload(\n modalFreshData || modalData,\n modalState,\n ),\n modalUpload(modalFreshData || modalData, modalState)\n ?.config,\n );\n } else if (onModalUpdate) {\n axiosResponse = onModalUpdate();\n } else {\n overrideModalUpdate();\n return;\n }\n break;\n // copy case: if validation is required and its false then dispatch a error\n // else if return onModalCopy, else post with modalCopy\n case 'Copy':\n if (\n modalValidate && // need to do validation\n !modalValidate() //validation return false\n ) {\n onModalError({\n name: 'Field Error',\n message: 'There are some field errors.',\n });\n return;\n }\n if (onModalCopy) {\n onModalCopy();\n return;\n }\n\n // modal Copy Logic\n // not really sure what this is doing or why its neccessary for the app as redux actions are confusing\n axios\n .post(modalCopy)\n .then((copyResult) => {\n axios\n .put(modalUpdate, {\n ...copyResult.data,\n name: modalState?.copyName,\n })\n .then((renameResult) => {\n dispatch({\n type: 'OPEN_CHILD_TABLE',\n payload: {\n ...(renameResult?.data ?? {}),\n append: true,\n },\n });\n dispatch({\n type: 'CHANGE_BREADCRUMB_VIEW',\n payload:\n tableRowActions?.multiChildTable\n ?.to ?? 0,\n });\n return;\n })\n .catch((e2) => {\n dispatch({\n type: 'OPEN_CHILD_TABLE',\n payload: {\n ...(copyResult?.data ?? {}),\n append: true,\n },\n });\n dispatch({\n type: 'CHANGE_BREADCRUMB_VIEW',\n payload:\n tableRowActions?.multiChildTable\n ?.to ?? 0,\n });\n onModalError(e2);\n });\n })\n .catch((e) => {\n onModalError(e);\n });\n return;\n default:\n break;\n }\n\n /*\n * if there is a axios respoonse after all the above conditions, this executes it\n * the hash is changed using a dispatch\n * if onModalSuceed is inpt then it is called, else onSucceed is called\n * This block also has error handling\n */\n if (axiosResponse) {\n axiosResponse\n .then((res) => {\n dispatch({\n type: 'CHANGE_MODAL_HASH',\n });\n if (onModalSucceed) {\n onModalSucceed(res);\n return;\n }\n onSucceed(res);\n })\n .catch((e) => {\n if (overrideOnModalError) {\n overrideOnModalError(e);\n return;\n }\n onModalError(e);\n });\n }\n }\n }, [modalUploading]);\n\n //Memo that changes the columns the app renders when default columns changes\n const loadingColumns = useMemo(\n () => loadingColumnsConstructor(defaultColumns),\n [defaultColumns],\n );\n\n /*\n * The way the component renders all the data\n * If there is a error then the error compoent is returned\n * If the mode is either edit or add then the EditForm componet is rendered\n * else the Table and Modal is rendered\n */\n if (error) {\n return (\n <>\n \n >\n );\n }\n\n if (modalShow && newPage && (modalMode === 'Edit' || modalMode === 'Add')) {\n return ;\n }\n\n return (\n <>\n
\n \n >\n );\n}\n","import MultiSelect from './MultiselectSearchbox';\nimport { onModalError } from '../tables/TableAndModal';\n\n/*\n * A multiselect variant that remembers the input its hovered overed and then when clicking ->\n * Adds the option to the multiselect that is being focussed\n */\nconst FillOnClickMultiselect = ({\n staticEnum,\n activeTextareaID,\n activeTextareaField,\n setState,\n label,\n cursorPosition,\n setCursorPosition,\n ...rest\n}) => {\n function handleBtn(value) {\n const inputSelected = document.getElementById(activeTextareaID);\n if (inputSelected) {\n const textValue =\n inputSelected.value.substring(0, cursorPosition) +\n value +\n inputSelected.value.substring(\n cursorPosition,\n inputSelected.value.length,\n );\n setState({ [activeTextareaField]: textValue });\n inputSelected.value = textValue;\n inputSelected.focus();\n inputSelected.setSelectionRange(\n cursorPosition + value.length,\n cursorPosition + value.length,\n );\n setCursorPosition(inputSelected.selectionStart);\n }\n }\n\n return (\n {}}\n chip={{\n clickable: true,\n onClick: (e, option) => {\n handleBtn(option.id);\n },\n }}\n />\n );\n};\n\nexport default FillOnClickMultiselect;\n","import {useEffect, useState} from 'react';\n\nexport default function useDetectFileType(file) {\n const [fileType, setFileType] = useState(null);\n\n useEffect(() => {\n if (!file || !file.includes) return;\n const isPng = file.includes('.PNG') || file.includes('.png');\n const isSvg = file.includes('.SVG') || file.includes('.svg');\n const isBase64Svg = file.includes('data:image/svg');\n const isBase64Png = file.includes('data:image/png');\n\n if (isPng || isBase64Png) setFileType('png');\n if (isSvg || isBase64Svg) setFileType('svg');\n }, [file]);\n\n return fileType;\n}\n","import { useSelector } from 'react-redux';\nimport { Helmet } from 'react-helmet';\nimport useDetectFileType from 'hooks/useDetectFileType';\n\n/*\n * Header component to get favicon and company name from state\n */\nconst Header = () => {\n // const dispatch = useDispatch();\n\n const { partnerName, favIconPath } = useSelector((state) => {\n return { ...state.header };\n });\n\n const imgFileType = useDetectFileType(favIconPath);\n\n // useEffect(() => {\n // if (!partnerName || !favIconPath) {\n // axios.get(`/theme/${window.location.host}`).then((res) => {\n // const { data } = res;\n // dispatch({\n // type: 'SET_SBC_DOMAIN',\n // payload: data.sbcDomain,\n // });\n // dispatch({\n // type: 'CHANGE_IMAGE_PATH_LIGHT_MODE',\n // payload: data.lightLogo,\n // });\n // dispatch({\n // type: 'CHANGE_IMAGE_PATH_DARK_MODE',\n // payload: data.darkLogo,\n // });\n\n // dispatch({\n // type: 'HEADER_FAVICON_SUCCESS',\n // payload: data.favicon,\n // });\n // dispatch({\n // type: 'HEADER_TITLE_SUCCESS',\n // payload: data.titleName,\n // });\n // dispatch({\n // type: 'SET_SUPPORT_URL',\n // payload: data.extLinkSupport,\n // });\n // });\n // }\n // }, [partnerName, favIconPath]);\n\n //returns helmet with image and partner name\n return (\n \n {/**\n * @note CSP frame-ancestors\n * @see https://content-security-policy.com/frame-ancestors/\n */}\n \n \n {partnerName}\n \n );\n};\n\nexport default Header;\n","import React, { useState } from 'react';\nimport { useSelector } from 'react-redux';\nimport TextField from '@material-ui/core/TextField';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport { Spinner, Box } from '@chakra-ui/react';\nimport { ChevronDownIcon, QuestionOutlineIcon } from '@chakra-ui/icons';\n\n\nimport config from '../../config.json';\nimport ErrorBoundary from '../maintenance/ErrorBoundary';\nimport { customAutoCompleteStyle } from 'pages/navbar/constant';\nimport { InputAdornment, Tooltip } from '@material-ui/core';\n\nexport const findCurrentValue = ({\n options,\n displayField,\n dropDownValue,\n currentValue,\n noneFieldDisplay,\n onDisplayDropdown,\n}) => {\n if (!options || !displayField || !dropDownValue) {\n return null;\n }\n var res = options?.find((v) => {\n return v[dropDownValue] === currentValue;\n });\n\n if (!res) {\n return noneFieldDisplay || config.notAllocated.dropdown;\n }\n return (\n (onDisplayDropdown && onDisplayDropdown(res)) ||\n res[displayField] ||\n res ||\n 'ERROR:Not Found!!!!'\n );\n};\n\n// Specific for 'Company Managing' field on drop down\n// Labels company and partner for group by function of autocomplete\nexport const relabel = (companies) => {\n var res = [];\n let parentName = '';\n let parentID = '';\n for (const company of companies) {\n if (company.parent == null || company.parent.length === 0) {\n parentName = company.name;\n parentID = company.id;\n res.push({\n id: company.id,\n name: company.name,\n parentID: '',\n parentName: '',\n });\n } else {\n res.push({\n id: company.id,\n name: company.name,\n parentID,\n parentName,\n });\n }\n }\n return res;\n};\n\nexport const groupBy = (option) => {\n if (option.parentName.length === 0) {\n return option.name;\n }\n return option.parentName;\n};\n\nconst getOptionSelectedID = (option, v) => {\n return option.id === v.id;\n};\n\nexport const getOptionSelected = (option, value) => {\n if (typeof value === 'string') {\n return value === option.id;\n }\n return option.name === value.name;\n};\n\nexport const getOptionLabel = (option) => option.name || '';\n\n/*\n * SearchBox component used by multi selects, auto completes and drop downs that require search functionality\n */\nexport default function Asynchronous(props) {\n const { colorScheme } = useSelector((state) => state.settings);\n const [open, setOpen] = useState(false);\n const {\n placeholder,\n defaultValue,\n loading,\n onChange,\n message,\n onFocus,\n label,\n displayField,\n dropDownValue,\n onDisplayDropdown,\n options,\n noneFieldDisplay,\n helperText,\n errorText,\n groupByProps,\n endAdornment,\n renderOption,\n getOptionSelected: getOptionSelectedProps,\n getOptionLabel: getOptionLabelProps,\n dataWalkthroughid,\n isRequired = false,\n hasTooltip = false,\n tooltipLabel = 'Field is required.',\n } = props;\n\n const findCurrentName = () => {\n var res = options.find((v) => {\n return v.id === defaultValue;\n });\n var name = res?.name;\n if (res?.parentName) {\n name = res?.name + ' Under: ' + res?.parentName;\n }\n return name;\n };\n\n const [isHovered, setIsHovered] = useState(false);\n\n // For each option you pass in, it must not be null, hence the error boundary\n return (\n \n \n {\n //ASSUMPTION :ONLY USED WHEN THERE'S GROUP BY?\n if (value != null) {\n //CHANGE!\n const foundItem = options.filter(\n (company) =>\n company?.[dropDownValue ?? 'id'] ===\n value?.[dropDownValue ?? 'id'],\n );\n onChange(foundItem[0]);\n }\n }}\n onOpen={() => {\n setOpen(true);\n }}\n onClose={() => {\n setOpen(false);\n }}\n groupBy={groupByProps}\n getOptionSelected={\n getOptionSelectedProps || getOptionSelectedID\n }\n getOptionLabel={getOptionLabelProps || getOptionLabel}\n options={options}\n loading={loading}\n disableClearable\n renderInput={(params) => {\n return (\n setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n placeholder={\n placeholder ||\n findCurrentValue({\n options,\n displayField,\n dropDownValue,\n currentValue: defaultValue,\n message,\n onDisplayDropdown,\n noneFieldDisplay,\n }) ||\n findCurrentName()\n }\n variant=\"outlined\"\n size=\"small\"\n InputProps={{\n ...params.InputProps,\n endAdornment: (\n \n {loading ? (\n \n ) : null}\n {endAdornment}\n {params.InputProps.endAdornment}\n {isHovered && hasTooltip && (\n \n \n \n \n \n )}\n \n ),\n }}\n InputLabelProps={{ shrink: true }}\n />\n );\n }}\n popupIcon={}\n />\n \n \n );\n}\n","/* eslint-disable no-unused-vars */\nimport React, { useState, useEffect, forwardRef } from 'react';\nimport Skeleton from '@material-ui/lab/Skeleton';\nimport { MenuItem, FormControl, TextField } from '@material-ui/core';\nimport { useSelector } from 'react-redux';\nimport { Box } from '@chakra-ui/react';\nimport { ChevronDownIcon } from '@chakra-ui/icons';\n\nimport { axios } from '../../services/axios';\nimport Searchbox from '../presentational/Searchbox.jsx';\nimport config from '../../config.json';\nimport { customAutoCompleteStyle } from 'pages/navbar/constant';\n\n// eslint-disable-next-line react/display-name\nconst CustomChevronDownIcon = forwardRef((props, ref) => (\n \n));\n\n/*\n * Component used for drop down fields in the UI that require a series of options\n * those options can be gathered from a static list, fetched from the API when the component renders etc\n * This component also changes state so that modal forms can submit data using the value from the drop down\n */\nconst LoadingFieldDropdown = ({\n // this prop stops the component from fetching until another field/value has data\n dependency,\n // if there is no field display or we want a different default display then this value is shown\n noneFieldDisplay,\n // determines when the data will be fetched, if init is true it will be fetched when its loaded\n init,\n // function that triggers when the display drop down is shown\n onDisplayDropdown,\n // value behind the noneFieldDisplay as all values have a different display\n noneFieldValue,\n // prop to determine if its not a modal component\n notModalComponent,\n // instead of a api fetch the component can be fed a static list to use\n staticEnum,\n // the onChange function to be passed into the material component of this\n onChange,\n //\n noneField,\n // a function that can be passed in to represent a error, usually the onError from TableAndModal.jsx\n onError,\n // prop to pass through to sub componennts\n toggleLimit,\n // prop to pass through to sub componennts\n loadDependencies,\n // boolean to determine whether its searchable or not\n searchable,\n // the URL for fetching the data to populate the list\n fieldFetch,\n // label for the component as its a MUI textfield/searchbox\n fieldName,\n // used to determine the type of the value in the drop down, strint, int, bool etc\n fieldValue,\n // the value that is used for the state setting when selecting a value\n dropDownValue,\n // the field that is actually displayed in the drop down\n displayField,\n // props for the drop down list\n dropdownProps,\n // makes it so there is no empty option when the field first loads the drop down data\n noEmptyOption,\n // a function that triggers when the fetch is sucessful\n onFieldFetch,\n // determins if the component has dependencies\n hasDependency,\n // additional options for the static array that is passed into this component\n additional,\n // helper text is set inside the drop down\n helperText,\n // error text is what is displayed if there is a modalError\n errorText,\n // a bool that disalbes the drop down\n disabled,\n // a value to group the results of the api call or static enum by\n groupBy,\n // funciton that triggers when the funciton is focussed on\n onFocus,\n // if you want to render whats inside the wrapper as something that isnt a searchbox/textfield\n renderOption,\n // a filter for the options of the search box\n filter,\n // icon or any other sort of adornment that goes at the end of the field\n endAdornment,\n dataWalkthroughid, // used for the walkthrough\n isRequired, // show asterick beside label\n hasTooltip, // show tooltip on the right end\n tooltipLabel, // custom title for tooltip\n ...rest\n}) => {\n const [enumArray, setEnum] = useState(staticEnum || []);\n const [enumLoading, setEnumLoading] = useState(false);\n\n // state to detemine if the modal is showing\n const { show: modalShow } = useSelector((state) => {\n return { ...state.modal };\n });\n const { colorScheme } = useSelector((state) => state.settings);\n\n /*\n * Fetch function for the results based with onFieldFetch, fieldFetch props\n * if this is sucsessful the enum state is set to the result\n */\n const fetch = () => {\n setEnumLoading(true);\n if (onFieldFetch) {\n onFieldFetch()\n .then((res) => {\n setEnum(res.data);\n setEnumLoading(false);\n })\n .catch((e) => {\n onError(e);\n setEnumLoading(false);\n });\n return;\n }\n axios\n .get(fieldFetch)\n .then((res) => {\n setEnum(res.data);\n setEnumLoading(false);\n })\n .catch((e) => {\n onError(e);\n setEnumLoading(false);\n });\n };\n\n /*\n * Function to extract the field value\n * checks the type of this value and returns the fieldvalue\n */\n const extractFieldValue = () => {\n //set default case\n switch (typeof fieldValue) {\n case 'object':\n return fieldValue || '';\n case 'string':\n return fieldValue || '';\n case 'number':\n return fieldValue;\n default:\n return fieldValue;\n }\n };\n\n /*\n * calls a fetch based onFieldFetch or fieldFetch existing\n * also requires static enum and dependency to be false\n * also requires init or modalShow or notModalComponent to execuse fetch()\n */\n useEffect(() => {\n if (\n (onFieldFetch || fieldFetch) &&\n !staticEnum && //not static\n !hasDependency && // not depending on sth else\n (init || //do at first place\n modalShow)\n ) {\n fetch();\n }\n }, [modalShow, staticEnum]);\n\n /*\n * fetches based on the same factors as abovem doesnt accoutn for init or modalShow\n * could most likley be refacorted into a single useEffect()\n */\n useEffect(() => {\n if ((onFieldFetch || fieldFetch) && !staticEnum && hasDependency) {\n fetch();\n }\n }, [hasDependency, dependency, staticEnum]);\n\n /*\n * If the enumLoading state is true, returns a skeleton component\n */\n if (enumLoading) {\n return ;\n }\n\n /*\n * If the serachable prop is entered with a static enum of length > 0 then render a search box\n * many props are used for material ui requirements for SearchBox, documentation is online for those props\n */\n if (\n searchable &&\n !disabled &&\n (staticEnum || enumArray)?.concat(additional || []).length > 0\n ) {\n return (\n {\n onChange(v[dropDownValue]);\n }}\n noneFieldDisplay={noneFieldDisplay}\n options={(staticEnum || enumArray || [])\n .concat(additional || [])\n .concat(\n !noEmptyOption\n ? [\n {\n [dropDownValue]: null,\n [displayField]:\n noneFieldDisplay ||\n config.notAllocated.dropdown,\n },\n ]\n : [],\n )\n .sort((left, right) =>\n left && right\n ? groupBy\n ? groupBy(left)?.localeCompare(groupBy(right))\n : onDisplayDropdown\n ? onDisplayDropdown(left)?.localeCompare(\n onDisplayDropdown(right),\n )\n : left[displayField]?.localeCompare(\n right[displayField],\n )\n : 0,\n )\n .filter(\n filter ??\n function (v) {\n return true;\n },\n )}\n helperText={helperText}\n errorText={errorText}\n getOptionLabel={(v) => {\n if (typeof v === 'string') {\n if (v.length === 0) {\n return (\n noneFieldDisplay ?? config.notAllocated.dropdown\n );\n }\n\n const result = (staticEnum || enumArray || [])\n ?.concat(additional || [])\n ?.concat(\n !noEmptyOption\n ? [\n {\n [dropDownValue]: null,\n [displayField]:\n noneFieldDisplay ||\n config.notAllocated.dropdown,\n },\n ]\n : [],\n )\n .find((item) => item[dropDownValue] === v);\n if (result && onDisplayDropdown) {\n return (\n onDisplayDropdown(result) ??\n noneFieldDisplay ??\n config.notAllocated.dropdown\n );\n }\n return (\n result?.[displayField] ??\n noneFieldDisplay ??\n config.notAllocated.dropdown\n );\n }\n if (onDisplayDropdown) {\n return (\n onDisplayDropdown(v) ??\n noneFieldDisplay ??\n config.notAllocated.dropdown\n );\n }\n\n return (\n v[displayField] ??\n noneFieldDisplay ??\n config.notAllocated.dropdown\n );\n }}\n displayField={displayField}\n dropDownValue={dropDownValue}\n label={fieldName}\n //groupByProps={groupBy}\n onDisplayDropdown={onDisplayDropdown}\n renderOption={renderOption}\n getOptionSelected={(option, v) => {\n return option[dropDownValue] === v;\n }}\n isRequired={isRequired}\n hasTooltip={hasTooltip}\n tooltipLabel={tooltipLabel}\n {...dropdownProps}\n />\n );\n }\n\n /*\n * If the static enum or the array of possible choices has a length of less than 1\n * Render a textfield with a single option\n */\n if ((staticEnum || enumArray)?.concat(additional || []).length < 1) {\n return (\n \n );\n }\n\n /*\n * If there is no staticEnum input into the component then render this\n * mainly using props from material ui textfield some some aspects that I do not understand\n * This maps the dropDownValue and displayField to a list of MenuItems for the component to use\n */\n return (\n \n \n {\n onChange(e.target.value);\n }}\n helperText={errorText || helperText}\n error={Boolean(errorText)}\n variant={'outlined'}\n SelectProps={{\n IconComponent: CustomChevronDownIcon,\n }}\n {...dropdownProps}>\n {!noEmptyOption && (\n \n )}\n\n {dropDownValue && displayField\n ? (staticEnum || enumArray)\n ?.concat(additional || [])\n .map(\n (\n {\n [dropDownValue]: id,\n [displayField]: name,\n ...rest\n },\n idx,\n ) => {\n return (\n \n );\n },\n )\n : (staticEnum || enumArray)\n ?.concat(additional || [])\n .map((v, idx) => {\n return (\n \n );\n })}\n \n \n \n );\n};\n\nexport default LoadingFieldDropdown;\n","import React, { useState, useEffect } from 'react';\nimport { useSelector, useDispatch } from 'react-redux';\nimport Skeleton from '@material-ui/lab/Skeleton';\nimport { MenuItem, FormControl, TextField } from '@material-ui/core';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport { Box } from '@chakra-ui/react';\nimport { ChevronDownIcon } from '@chakra-ui/icons';\n\nimport ErrorBoundary from '@/components/maintenance/ErrorBoundary';\nimport { axios } from '@/services/axios';\nimport config from '@/config.json';\nimport { customAutoCompleteStyle } from 'pages/navbar/constant';\n\n// NOTE: copy of LoadingFieldDropdown component, otherwise TCAP will break\nconst disabledInputStyle = {\n '& input:disabled': {\n cursor: 'not-allowed',\n },\n};\n\nexport const findCurrentValue = ({\n options,\n displayField,\n dropDownValue,\n currentValue,\n noneFieldDisplay,\n onDisplayDropdown,\n}) => {\n if (!options || !displayField || !dropDownValue) {\n return null;\n }\n var res = options?.find((v) => {\n return v[dropDownValue] === currentValue;\n });\n\n if (!res) {\n return noneFieldDisplay || config.notAllocated.dropdown;\n }\n return (\n (onDisplayDropdown && onDisplayDropdown(res)) ||\n res[displayField] ||\n res ||\n 'ERROR:Not Found!!!!'\n );\n};\n\n// Specific for 'Company Managing' field on drop down\n// Labels company and partner for group by function of autocomplete\nexport const relabel = (companies) => {\n var res = [];\n let parentName = '';\n let parentID = '';\n for (const company of companies) {\n if (company.parent == null || company.parent.length === 0) {\n parentName = company.name;\n parentID = company.id;\n res.push({\n id: company.id,\n name: company.name,\n parentID: '',\n parentName: '',\n });\n } else {\n res.push({\n id: company.id,\n name: company.name,\n parentID,\n parentName,\n });\n }\n }\n return res;\n};\n\nexport const groupBy = (option) => {\n if (option.parentName.length === 0) {\n return option.name;\n }\n return option.parentName;\n};\n\nconst getOptionSelectedID = (option, v) => {\n return option.id === v.id;\n};\n\nexport const getOptionSelected = (option, value) => {\n if (typeof value === 'string') {\n return value === option.id;\n }\n return option.name === value.name;\n};\n\nexport const getOptionLabel = (option) => option.name;\n\n/*\n * SearchBox component used by multi selects, auto completes and drop downs that require search functionality\n */\nexport function SearchBox(props) {\n const [open, setOpen] = useState(false);\n const {\n placeholder,\n defaultValue,\n loading,\n onChange,\n message,\n onFocus,\n label,\n displayField,\n dropDownValue,\n onDisplayDropdown,\n options,\n noneFieldDisplay,\n helperText,\n errorText,\n groupByProps,\n endAdornment,\n renderOption,\n getOptionSelected: getOptionSelectedProps,\n getOptionLabel: getOptionLabelProps,\n dataWalkthroughid,\n inputValue,\n } = props;\n\n const { colorScheme } = useSelector((state) => state.settings);\n\n const findCurrentName = () => {\n var res = options.find((v) => {\n return v.id === defaultValue;\n });\n var name = res?.name;\n if (res?.parentName) {\n name = res?.name + ' Under: ' + res?.parentName;\n }\n return name;\n };\n\n // For each option you pass in, it must not be null, hence the error boundary\n return (\n \n \n {\n //ASSUMPTION :ONLY USED WHEN THERE'S GROUP BY?\n if (value != null) {\n //CHANGE!\n const foundItem = options.filter(\n (company) =>\n company?.[dropDownValue ?? 'id'] ===\n value?.[dropDownValue ?? 'id'],\n );\n onChange(foundItem[0]);\n }\n }}\n onOpen={() => {\n setOpen(true);\n }}\n onClose={() => {\n setOpen(false);\n }}\n groupBy={groupByProps}\n getOptionSelected={\n getOptionSelectedProps || getOptionSelectedID\n }\n getOptionLabel={getOptionLabelProps || getOptionLabel}\n options={options}\n loading={loading}\n disableClearable\n renderInput={(params) => {\n return (\n \n {loading ? (\n \n ) : null}\n {endAdornment}\n {params.InputProps.endAdornment}\n \n ),\n }}\n InputLabelProps={{ shrink: true }}\n />\n );\n }}\n popupIcon={}\n />\n \n \n );\n}\n\n/*\n * Component used for drop down fields in the UI that require a series of options\n * those options can be gathered from a static list, fetched from the API when the component renders etc\n * This component also changes state so that modal forms can submit data using the value from the drop down\n */\nconst LoadingFieldDropdownWithPlaceholder = ({\n // this prop stops the component from fetching until another field/value has data\n dependency,\n // if there is no field display or we want a different default display then this value is shown\n noneFieldDisplay,\n // determines when the data will be fetched, if init is true it will be fetched when its loaded\n init,\n // function that triggers when the display drop down is shown\n onDisplayDropdown,\n // value behind the noneFieldDisplay as all values have a different display\n noneFieldValue,\n // prop to determine if its not a modal component\n notModalComponent,\n // instead of a api fetch the component can be fed a static list to use\n staticEnum,\n // the onChange function to be passed into the material component of this\n onChange,\n //\n noneField,\n // a function that can be passed in to represent a error, usually the onError from TableAndModal.jsx\n onError,\n // prop to pass through to sub componennts\n toggleLimit,\n // prop to pass through to sub componennts\n loadDependencies,\n // boolean to determine whether its searchable or not\n searchable,\n // the URL for fetching the data to populate the list\n fieldFetch,\n // label for the component as its a MUI textfield/searchbox\n fieldName,\n // used to determine the type of the value in the drop down, strint, int, bool etc\n fieldValue,\n // the value that is used for the state setting when selecting a value\n dropDownValue,\n // the field that is actually displayed in the drop down\n displayField,\n // props for the drop down list\n dropdownProps,\n // makes it so there is no empty option when the field first loads the drop down data\n noEmptyOption,\n // a function that triggers when the fetch is sucessful\n onFieldFetch,\n // determins if the component has dependencies\n hasDependency,\n // additional options for the static array that is passed into this component\n additional,\n // helper text is set inside the drop down\n helperText,\n // error text is what is displayed if there is a modalError\n errorText,\n // a bool that disalbes the drop down\n disabled,\n // a value to group the results of the api call or static enum by\n groupBy,\n // funciton that triggers when the funciton is focussed on\n onFocus,\n // if you want to render whats inside the wrapper as something that isnt a searchbox/textfield\n renderOption,\n // a filter for the options of the search box\n filter,\n // icon or any other sort of adornment that goes at the end of the field\n endAdornment,\n dataWalkthroughid, // used for the walkthrough\n placeholder,\n inputValue,\n getOptionSelected: getOptionSelectedProps,\n ...rest\n}) => {\n const [enumArray, setEnum] = useState(staticEnum || []);\n const [enumLoading, setEnumLoading] = useState(false);\n\n // state to detemine if the modal is showing\n const { show: modalShow, state } = useSelector((state) => {\n return { ...state.modal };\n });\n\n const dispatch = useDispatch();\n\n /*\n * Fetch function for the results based with onFieldFetch, fieldFetch props\n * if this is sucsessful the enum state is set to the result\n */\n const fetch = () => {\n setEnumLoading(true);\n if (onFieldFetch) {\n onFieldFetch()\n .then((res) => {\n setEnum(res.data);\n setEnumLoading(false);\n })\n .catch((e) => {\n onError(e);\n setEnumLoading(false);\n });\n return;\n }\n axios\n .get(fieldFetch)\n .then((res) => {\n dispatch({\n type: 'CHANGE_MODAL_STATE',\n payload: {\n [fieldName]: res.data,\n },\n });\n setEnum(res.data);\n setEnumLoading(false);\n })\n .catch((e) => {\n onError(e);\n setEnumLoading(false);\n });\n };\n\n /*\n * Function to extract the field value\n * checks the type of this value and returns the fieldvalue\n */\n const extractFieldValue = () => {\n //set default case\n switch (typeof fieldValue) {\n case 'object':\n return fieldValue || '';\n case 'string':\n return fieldValue || '';\n case 'number':\n return fieldValue;\n default:\n return fieldValue;\n }\n };\n\n /*\n * calls a fetch based onFieldFetch or fieldFetch existing\n * also requires static enum and dependency to be false\n * also requires init or modalShow or notModalComponent to execuse fetch()\n */\n useEffect(() => {\n if (\n (onFieldFetch || fieldFetch) &&\n !staticEnum && //not static\n !hasDependency && // not depending on sth else\n (init || //do at first place\n modalShow ||\n notModalComponent)\n ) {\n fetch();\n }\n }, [\n // onFieldFetch, fieldFetch,\n modalShow,\n notModalComponent,\n staticEnum,\n ]);\n\n /*\n * fetches based on the same factors as abovem doesnt accoutn for init or modalShow\n * could most likley be refacorted into a single useEffect()\n */\n useEffect(() => {\n if ((onFieldFetch || fieldFetch) && !staticEnum && hasDependency) {\n fetch();\n }\n }, [onFieldFetch, fieldFetch, hasDependency, dependency, staticEnum]);\n\n /*\n * If the enumLoading state is true, returns a skeleton component\n */\n if (enumLoading) {\n return ;\n }\n\n /*\n * If the serachable prop is entered with a static enum of length > 0 then render a search box\n * many props are used for material ui requirements for SearchBox, documentation is online for those props\n */\n if (\n searchable &&\n !disabled &&\n (staticEnum || enumArray)?.concat(additional || []).length > 0\n ) {\n return (\n {\n onChange(v[dropDownValue]);\n }}\n noneFieldDisplay={noneFieldDisplay}\n options={(staticEnum || enumArray || [])\n .concat(additional || [])\n .concat(\n !noEmptyOption\n ? [\n {\n [dropDownValue]: null,\n [displayField]:\n noneFieldDisplay || placeholder,\n },\n ]\n : [],\n )\n .sort((left, right) =>\n left && right\n ? groupBy\n ? groupBy(left)?.localeCompare(groupBy(right))\n : onDisplayDropdown\n ? onDisplayDropdown(left)?.localeCompare(\n onDisplayDropdown(right),\n )\n : left[displayField]?.localeCompare(\n right[displayField],\n )\n : 0,\n )\n .filter(\n filter ??\n function (v) {\n return true;\n },\n )}\n helperText={helperText}\n errorText={errorText}\n getOptionLabel={(v) => {\n if (typeof v === 'string') {\n if (v.length === 0) {\n return noneFieldDisplay ?? placeholder;\n }\n\n const result = (staticEnum || enumArray || [])\n ?.concat(additional || [])\n ?.concat(\n !noEmptyOption\n ? [\n {\n [dropDownValue]: null,\n [displayField]:\n noneFieldDisplay ||\n placeholder,\n },\n ]\n : [],\n )\n .find((item) => item[dropDownValue] === v);\n if (result && onDisplayDropdown) {\n return (\n onDisplayDropdown(result) ??\n noneFieldDisplay ??\n placeholder\n );\n }\n return (\n result?.[displayField] ??\n noneFieldDisplay ??\n placeholder\n );\n }\n if (onDisplayDropdown) {\n return (\n onDisplayDropdown(v) ??\n noneFieldDisplay ??\n placeholder\n );\n }\n\n return v[displayField] ?? noneFieldDisplay ?? placeholder;\n }}\n displayField={displayField}\n dropDownValue={dropDownValue}\n label={fieldName}\n //groupByProps={groupBy}\n onDisplayDropdown={onDisplayDropdown}\n renderOption={renderOption}\n getOptionSelected={(option, v) => {\n return option[dropDownValue] === v;\n }}\n // {...dropdownProps}\n placeholder={placeholder}\n />\n );\n }\n\n /*\n * If the static enum or the array of possible choices has a length of less than 1\n * Render a textfield with a single option\n */\n if ((staticEnum || enumArray)?.concat(additional || []).length < 1) {\n return (\n \n \n \n );\n }\n\n /*\n * If there is no staticEnum input into the component then render this\n * mainly using props from material ui textfield some some aspects that I do not understand\n * This maps the dropDownValue and displayField to a list of MenuItems for the component to use\n */\n return (\n \n \n {\n onChange(e.target.value);\n }}\n helperText={errorText || helperText}\n error={Boolean(errorText)}\n variant={'outlined'}\n {...dropdownProps}>\n {!noEmptyOption && (\n \n )}\n\n {dropDownValue && displayField\n ? (staticEnum || enumArray)\n ?.concat(additional || [])\n .map(\n (\n {\n [dropDownValue]: id,\n [displayField]: name,\n ...rest\n },\n idx,\n ) => {\n return (\n \n );\n },\n )\n : (staticEnum || enumArray)\n ?.concat(additional || [])\n .map((v, idx) => {\n return (\n \n );\n })}\n \n \n \n );\n};\n\nexport default LoadingFieldDropdownWithPlaceholder;\n\nLoadingFieldDropdownWithPlaceholder.displayName = 'LoadingFieldDropdown2';\n","import { Button } from '@chakra-ui/react';\nimport { useSelector } from 'react-redux';\n\n/**\n * @typedef {Object} ChakraButtonProps\n * @property {import('react').ReactNode} children\n * @param {ChakraButtonProps & import('@chakra-ui/react').ButtonProps} props\n * @param {import('@chakra-ui/react').ButtonProps} props.rest\n * @returns\n */\nexport default function ChakraButton({ children, ...props }) {\n const { colorScheme } = useSelector((state) => state.settings);\n const isSecondary =\n props.className?.includes('secondary') || props.variant === 'outline';\n let bgColor;\n\n if (props && isSecondary) {\n bgColor = 'white';\n } else if (colorScheme === 'gray') {\n bgColor = 'gray.500';\n } else {\n bgColor = null;\n }\n return (\n \n );\n}\n","import { Input } from '@chakra-ui/react';\nimport { useSelector } from 'react-redux';\n\n/**\n * @typedef {Object} ChakraInputProps\n * @property {React.RefObject} customRef\n * @property {ChakraInputProps & import('@chakra-ui/react').InputProps} props\n * @param {ChakraInputProps} customRef\n * @param {import('@chakra-ui/react').InputProps} rest\n * @returns\n */\nexport default function ChakraInput({ customRef, ...rest }) {\n const { darkMode } = useSelector((state) => state.settings);\n return (\n \n );\n}\n","import {InputGroup} from '@chakra-ui/react';\n\nexport default function ChakraInputGroup({children, ...rest}) {\n return {children};\n}\n","import { Select } from '@chakra-ui/react';\nimport { useSelector } from 'react-redux';\n\n// react multi select uses label instead of name for the option text\n// instead of changing every instance of this component to use label instead of name\n// ill throw in a quick workaround so I dont need change anything else\n/**\n * @typedef {Object} ChakraSelectProps\n * @property {{label: string, value: string | number}[]} options\n * @param {ChakraSelectProps & import('@chakra-ui/react').SelectProps} props\n * @returns {JSX.Element}\n */\nexport default function ChakraSelect({ options, ...props }) {\n const { darkMode } = useSelector((state) => state.settings);\n return (\n \n );\n}\n","import {Checkbox} from '@chakra-ui/react';\nimport { useSelector } from 'react-redux';\n\nexport default function ChakraCheckbox({children, ...props}) {\n const {darkMode} = useSelector(state => state.settings)\n return {children};\n}\n","import { Heading } from '@chakra-ui/react';\n\nexport default function ChakraHeading({\n children,\n fontSize,\n fontWeight,\n mb,\n lineHeight,\n fontFamily,\n as,\n size,\n ...rest\n}) {\n return (\n \n {children}\n \n );\n}\n","export function classNames(...classes) {\n return classes.filter(Boolean).join(' ')\n}\n","import { Text } from '@chakra-ui/react';\nimport { useLocation } from 'react-router-dom';\nimport { useSelector } from 'react-redux';\n\nimport { classNames } from '@/utils/classNames';\n\n/**\n * @typedef {Object} ChakraTextProps\n * @property {import('react').ReactNode} children\n * @param {import('@chakra-ui/react').TextProps & ChakraTextProps} props\n * @returns\n */\nexport default function ChakraText({ children, ...rest }) {\n const location = useLocation();\n const { pathname } = location;\n const textColor = pathname.includes('services') ? 'black' : 'inherit';\n const { darkMode } = useSelector((state) => state.settings);\n\n return (\n \n {children}\n \n );\n}\n","import {Image, forwardRef} from '@chakra-ui/react';\n\nexport default forwardRef(function ChakraImage(props, ref) {\n return ;\n});\n","import { Box as ChakraBox, forwardRef } from '@chakra-ui/react';\nimport { useSelector } from 'react-redux';\n\nconst BoxWithBorder = forwardRef((props, ref) => {\n const { darkMode } = useSelector((state) => state.settings);\n return (\n \n );\n});\n\nexport { BoxWithBorder };\n","import { FormLabel, forwardRef } from '@chakra-ui/react';\nimport { useSelector } from 'react-redux';\n\n/**\n * @typedef {import('@chakra-ui/react').FormLabelProps} LabelProps\n * @type React.ForwardRefRenderFunction\n * @returns {JSX.Element}\n */\nexport default forwardRef(function ChakraInput(props, ref) {\n const { darkMode } = useSelector((state) => state.settings);\n const textColor = darkMode ? 'white' : 'black';\n return (\n \n {props.children}\n \n );\n});\n","import { FormControl } from '@chakra-ui/react';\n\n/**\n * @typedef {Object} ChakraFormControlProps\n * @property {import('react').ReactNode} children\n * @param {ChakraFormControlProps & import('@chakra-ui/react').FormControlProps} props\n * @param {import('@chakra-ui/react').FormControlProps} props.rest\n * @returns\n */\nexport default function ChakraFormControl({ children, ...rest }) {\n return {children};\n}\n","import { Alert } from '@chakra-ui/react';\nimport { useSelector } from 'react-redux';\n\nconst STATUSES = {\n info: { colorScheme: 'blue' },\n warning: { colorScheme: 'orange' },\n success: { colorScheme: 'green' },\n error: { colorScheme: 'red' },\n};\n\nconst variant = (status) => ({\n 'inline-accent': {\n borderRadius: 'md',\n borderInlineWidth: '3px',\n borderColor: `var(--chakra-colors-${STATUSES[status].colorScheme}-500)`,\n py: 2,\n minH: '40px',\n },\n});\n/**\n * @typedef {Object} ChakraAlertProps\n * @property {import('@chakra-ui/react').AlertProps} props\n * @property {import('react').ReactNode} props.children\n * @property {'left-accent' | 'inline-accent' | 'solid' | 'subtle'} props.variant\n */\n\n/**\n * @param {import('@chakra-ui/react').AlertProps & ChakraAlertProps} props\n */\nexport default function ChakraAlert({ children, ...props }) {\n const { darkMode } = useSelector((state) => state.settings);\n const setAlertStatusBg = (status) => {\n switch (status) {\n case 'error': {\n return darkMode ? 'rgba(254, 178, 178, 0.16)' : null;\n }\n\n case 'info': {\n return darkMode ? 'rgba(144, 205, 244, 0.16)' : null;\n }\n\n case 'success': {\n return darkMode ? 'rgba(154, 230, 180, 0.16)' : null;\n }\n\n case 'warning': {\n return darkMode ? 'rgba(251, 211, 141, 0.16)' : null;\n }\n\n default: {\n return null;\n }\n }\n };\n const alertBg = setAlertStatusBg(props.status);\n return (\n \n {children}\n \n );\n}\n","import {AlertDescription} from '@chakra-ui/react';\n\nexport default function ChakraAlertDescription({children, ...rest}) {\n return {children};\n}\n","import {AlertIcon} from '@chakra-ui/react';\n\nexport default function ChakraAlertIcon({...rest}) {\n return ;\n}\n","import { Modal } from '@chakra-ui/react';\n\nexport default function ChakraModal({\n children,\n closeOnOverlayClick = false,\n autoFocus = false,\n ...props\n}) {\n return (\n \n {children}\n \n );\n}\n","import { ModalOverlay } from '@chakra-ui/react';\n\nexport default function ChakraModalOverlay({ ...props }) {\n return ;\n}\n","import {ModalContent} from '@chakra-ui/react';\nimport {useSelector} from 'react-redux';\n\nexport default function ChakraModalContent({children, ...props}) {\n const {darkMode} = useSelector((state) => state.settings)\n const modalBg = darkMode ? 'dark.tcap' : 'white'\n return {children};\n}\n","import {ModalHeader} from '@chakra-ui/react';\nimport {useSelector} from 'react-redux';\n\nexport default function ChakraModalHeader({children, ...props}) {\n const {darkMode} =useSelector((state) => state.settings);\n return {children};\n}\n","import {ModalBody} from '@chakra-ui/react';\n\nexport default function ChakraModalBody({children, ...props}) {\n return {children};\n}\n","import { ModalFooter } from '@chakra-ui/react';\n\nexport default function ChakraModalFooter({ children, ...props }) {\n return {children};\n}\n","import {CircularProgress} from '@chakra-ui/react';\n\nexport default function LoadingIndicator(props) {\n return (\n \n );\n}\n","import { MenuItem } from '@chakra-ui/react';\nimport { useSelector } from 'react-redux';\n\n/**\n * @typedef {Object} ChakraMenuItemProps\n * @property {import('react').ReactNode} children\n * @param {import('@chakra-ui/react').MenuItemProps} props\n */\nexport default function ChakraMenuItem({ children, ...props }) {\n const { darkMode } = useSelector((state) => state.settings);\n return (\n \n );\n}\n","import { useSelector } from 'react-redux';\nimport { MenuList } from '@chakra-ui/react';\n\n/**\n * @typedef {Object} ChakraMenuItemProps\n * @property {import('react').ReactNode} children\n * @param {import('@chakra-ui/react').MenuListProps} props\n */\nconst ChakraMenuList = ({ children, ...props }) => {\n const { darkMode } = useSelector((state) => state.settings);\n\n const bgColorCondition = {\n bg: darkMode ? 'rgba(255, 255, 255, 0.16)' : 'gray.200',\n };\n\n const menuListStyle = {\n '& a': bgColorCondition,\n button: {\n '&:hover': bgColorCondition,\n },\n 'button[role=\"menuitem\"]:active': bgColorCondition,\n };\n\n return (\n \n {children}\n \n );\n};\n\nexport default ChakraMenuList;\n","import { motion } from 'framer-motion';\nimport { useLayoutContext } from 'context/LayoutContext';\n\nexport const AnimatedTextWord = ({ text }) => {\n const words = text.split(' ');\n const { isMenuCollapse } = useLayoutContext();\n\n const container = {\n hidden: { opacity: 0 },\n\n visible: (i = 1) => ({\n opacity: 1,\n transition: {\n staggerChildren: 0.36,\n delayChildren: 0.04 * i,\n },\n }),\n };\n\n const child = {\n visible: {\n opacity: 1,\n x: 0,\n transition: {\n type: 'spring',\n damping: 12,\n stiffness: 100,\n },\n },\n hidden: {\n opacity: 0,\n x: -20,\n transition: {\n type: 'spring',\n damping: 12,\n stiffness: 100,\n },\n },\n };\n\n return (\n \n {words.map((word, i) => (\n \n {word}\n \n ))}\n \n );\n};\n","export const _focus = '_focus';\nexport const _active = '_active';\nexport const _hover = '_hover';\n\nexport const colorMode = {\n [_focus]: {\n bg: 'whiteAlpha.300',\n },\n [_active]: {\n bg: 'whiteAlpha.300',\n },\n [_hover]: {\n bg: 'whiteAlpha.100',\n },\n};\nexport const accordionItemStyle = {\n '.chakra-stack .chakra-text': {\n marginInlineStart: 0,\n },\n\n '&': {\n marginBottom: 1,\n },\n '& .chakra-stack :where(.chakra-button)': {\n margin: 0,\n },\n};\n","import { useSelector } from 'react-redux';\nimport { deepmerge } from '@mui/utils';\nimport { createTheme } from '@mui/material/styles';\n\nimport chakratheme from '@/chakratheme';\n\n/**\n * @description Custom hook to merge chakra theme with mui theme\n * @returns {import('@mui/material/styles').Theme} theme\n */\nexport function useDeepMerge() {\n const { darkMode } = useSelector((state) => state.settings);\n const theme = createTheme(\n deepmerge(chakratheme, {\n palette: { mode: darkMode ? 'dark' : 'light' },\n shadows: Array(25).fill('none'),\n }),\n );\n\n return { theme, chakratheme };\n}\n","import { axios } from '@/services/axios';\n\nexport const getResourceAccounts = async (currentCompany) => {\n const res = await axios.get(`/ResourceAccounts/${currentCompany}`);\n return res.data;\n};\n","import classNames from 'classnames';\nimport {Box} from '@chakra-ui/react';\n\nexport default function Grid({\n // Grid\n rows,\n columns,\n gap,\n gapX,\n gapY,\n // Used to pass in gaps (for now)\n className,\n // Other\n children,\n ...rest\n}) {\n const _columns = {\n 1: 'grid-cols-1',\n 2: 'grid-cols-2',\n 3: 'grid-cols-3',\n 4: 'grid-cols-4',\n 5: 'grid-cols-5',\n 6: 'grid-cols-6',\n 7: 'grid-cols-7',\n 8: 'grid-cols-8',\n 9: 'grid-cols-9',\n 10: 'grid-cols-10',\n 11: 'grid-cols-11',\n 12: 'grid-cols-12',\n }[columns];\n\n const _rows = {\n 1: 'grid-rows-1',\n 2: 'grid-rows-2',\n 3: 'grid-rows-3',\n 4: 'grid-rows-4',\n 5: 'grid-rows-5',\n 6: 'grid-rows-6',\n 7: 'grid-rows-7',\n 8: 'grid-rows-8',\n 9: 'grid-rows-9',\n 10: 'grid-rows-10',\n 11: 'grid-rows-11',\n 12: 'grid-rows-12',\n }[rows];\n\n const _gap = {\n 0: 'gap-0',\n 1: 'gap-1',\n 2: 'gap-2',\n 3: 'gap-3',\n 4: 'gap-4',\n 5: 'gap-5',\n 6: 'gap-6',\n 7: 'gap-7',\n 8: 'gap-8',\n 9: 'gap-9',\n 10: 'gap-10',\n }[gap];\n\n const _gapX = {\n 0: 'gap-x-0',\n 1: 'gap-x-1',\n 2: 'gap-x-2',\n 3: 'gap-x-3',\n 4: 'gap-x-4',\n 5: 'gap-x-5',\n 6: 'gap-x-6',\n 7: 'gap-x-7',\n 8: 'gap-x-8',\n 9: 'gap-x-9',\n 10: 'gap-x-10',\n }[gapX];\n\n const _gapY = {\n 0: 'gap-y-0',\n 1: 'gap-y-1',\n 2: 'gap-y-2',\n 3: 'gap-y-3',\n 4: 'gap-y-4',\n 5: 'gap-y-5',\n 6: 'gap-y-6',\n 7: 'gap-y-7',\n 8: 'gap-y-8',\n 9: 'gap-y-9',\n 10: 'gap-y-10',\n }[gapY];\n\n const gridClasses = classNames(\n 'grid',\n className,\n _columns,\n _rows,\n _gap,\n _gapX,\n _gapY,\n );\n\n return (\n \n {children}\n \n );\n}\n","export default {\n modal: {\n ufModalProgress: 'modal/input/progress',\n ufModalCancelBtn: 'modal/button/cancel',\n },\n table: {\n ufAddActionBtn: 'table/button/addAction',\n ufDeleteActionBtn: 'table/button/deleteAction',\n ufEditActionBtn: 'table/button/editAction',\n }\n}","import React, { forwardRef } from 'react';\n\nimport AddBox from '@mui/icons-material/AddBox';\nimport ArrowDownward from '@mui/icons-material/ArrowDownward';\nimport Check from '@mui/icons-material/Check';\nimport ChevronLeft from '@mui/icons-material/ChevronLeft';\nimport ChevronRight from '@mui/icons-material/ChevronRight';\nimport ExpandLess from '@mui/icons-material/ExpandLess';\nimport ExpandMore from '@mui/icons-material/ExpandMore';\nimport Clear from '@mui/icons-material/Clear';\nimport DeleteOutline from '@mui/icons-material/DeleteOutline';\nimport Edit from '@mui/icons-material/Edit';\nimport FilterList from '@mui/icons-material/FilterList';\nimport FirstPage from '@mui/icons-material/FirstPage';\nimport LastPage from '@mui/icons-material/LastPage';\nimport Remove from '@mui/icons-material/Remove';\nimport SaveAlt from '@mui/icons-material/SaveAlt';\nimport Search from '@mui/icons-material/Search';\nimport ViewColumn from '@mui/icons-material/ViewColumn';\nimport Refresh from '@mui/icons-material/Refresh';\n\nimport walkthroughIds from './walkthroughIds';\n\nconst tableIcons = {\n Add: forwardRef((props, ref) => (\n \n )),\n Check: forwardRef((props, ref) => ),\n Clear: forwardRef((props, ref) => ),\n Delete: forwardRef((props, ref) => (\n \n )),\n DetailPanel: forwardRef((props, ref) => (\n \n )),\n MoveUp: forwardRef((props, ref) => ),\n MoveDown: forwardRef((props, ref) => ),\n Edit: forwardRef((props, ref) => (\n \n )),\n Export: forwardRef((props, ref) => ),\n Filter: forwardRef((props, ref) => ),\n FirstPage: forwardRef((props, ref) => ),\n LastPage: forwardRef((props, ref) => ),\n NextPage: forwardRef((props, ref) => ),\n PreviousPage: forwardRef((props, ref) => (\n \n )),\n ResetSearch: forwardRef((props, ref) => ),\n Search: forwardRef((props, ref) => ),\n SortArrow: forwardRef((props, ref) => (\n \n )),\n ThirdStateCheck: forwardRef((props, ref) => (\n \n )),\n ViewColumn: forwardRef((props, ref) => ),\n Refresh: forwardRef((props, ref) => ),\n};\n\nexport default tableIcons;\n","import { useSelector } from 'react-redux';\nimport {\n Box as ChakraBox,\n Button as ChakraButton,\n ChakraProvider,\n FormControl,\n ModalOverlay,\n Stack,\n Tooltip,\n} from '@chakra-ui/react';\nimport { Select } from 'chakra-react-select';\n\nimport {\n Modal,\n ModalContent,\n ModalBody,\n ModalHeader,\n ModalFooter,\n Input,\n FormLabel,\n Checkbox as ChakraCheckbox,\n} from '@/components/v4';\n\nimport chakratheme, {\n floatingLabelStyles as floatingStyle,\n} from '@/chakratheme';\n\nimport { chakraSelectDarkMode, defaultChakraSelectStyle } from '@/constants';\nexport default function BillingNotesModal({\n isOpen,\n onClose,\n modal,\n desc,\n setDesc,\n scopes,\n setScope,\n locations,\n location,\n setLocation,\n isActive,\n setIsActive,\n onSubmitHandler,\n}) {\n const { darkMode } = useSelector((state) => state.settings);\n const chakraSelectDark = chakraSelectDarkMode(darkMode);\n const floatingLabelStyles = floatingStyle(darkMode);\n\n const chakraStyles = {\n ...defaultChakraSelectStyle,\n ...chakraSelectDark,\n };\n return (\n \n \n \n\n \n Billing Note\n \n Please enter a billing note description\n \n \n \n \n \n );\n}\n","export const invoiceFormatList = [\n {\n title: 'CDR',\n contents: [\n {\n fields: {\n label: 'CDR Detail Fields',\n value: 'cdrDetailFields',\n },\n format: {\n label: 'CDR Detail Format',\n value: 'cdrDetailFormat',\n defaultValue: 'cdrDetailDefaultFormat',\n },\n },\n\n {\n fields: {\n label: 'CDR Summary Fields',\n value: 'cdrSummaryFields',\n },\n format: {\n label: 'CDR Summary Format',\n value: 'cdrSummaryFormat',\n defaultValue: 'cdrSummaryDefaultFormat',\n },\n },\n ],\n },\n {\n title: 'Number Block',\n contents: [\n {\n fields: {\n label: 'Number Block Detail Fields',\n value: 'numberBlockDetailFields',\n },\n format: {\n label: 'Number Block Detail Format',\n value: 'numberBlockDetailFormat',\n defaultValue: 'numberBlockDetailDefaultFormat',\n },\n },\n\n {\n fields: {\n label: 'Number Block Porting Detail Fields',\n value: 'numberBlockPortingDetailFields',\n },\n format: {\n label: 'Number Block Porting Detail Format',\n value: 'numberBlockPortingDetailFormat',\n defaultValue: 'numberBlockPortingDetailDefaultFormat',\n },\n },\n {\n fields: {\n label: 'Number Block Setup Detail Fields',\n value: 'numberBlockSetupDetailFields',\n },\n format: {\n label: 'Number Block Setup Detail Format',\n value: 'numberBlockSetupDetailFormat',\n defaultValue: 'numberBlockSetupDetailDefaultFormat',\n },\n },\n\n {\n fields: {\n label: 'Number Block Summary Fields',\n value: 'numberBlockSummaryFields',\n },\n format: {\n label: 'Number Block Summary Format',\n value: 'numberBlockSummaryFormat',\n defaultValue: 'numberBlockSummaryDefaultFormat',\n },\n },\n ],\n },\n {\n title: 'RGS',\n contents: [\n {\n fields: {\n label: 'RGS Detail Fields',\n value: 'rgsDetailFields',\n },\n format: {\n label: 'RGS Detail Format',\n value: 'rgsDetailFormat',\n defaultValue: 'rgsDetailDefaultFormat',\n },\n },\n\n {\n fields: {\n label: 'RGS Setup Detail Fields',\n value: 'rgsSetupDetailFields',\n },\n format: {\n label: 'RGS Setup Detail Format',\n value: 'rgsSetupDetailFormat',\n defaultValue: 'rgsSetupDetailDefaultFormat',\n },\n },\n\n {\n fields: {\n label: 'RGS Summary Fields',\n value: 'rgsSummaryFields',\n },\n format: {\n label: 'RGS Summary Format',\n value: 'rgsSummaryFormat',\n defaultValue: 'rgsSummaryDefaultFormat',\n },\n },\n ],\n },\n\n {\n title: 'User',\n contents: [\n {\n fields: {\n label: 'User Detail Fields',\n value: 'userDetailFields',\n },\n format: {\n label: 'User Detail Format',\n value: 'userDetailFormat',\n defaultValue: 'userDetailDefaultFormat',\n },\n },\n\n {\n fields: {\n label: 'User Setup Detail Fields',\n value: 'userSetupDetailFields',\n },\n format: {\n label: 'User Setup Detail Format',\n value: 'userSetupDetailFormat',\n defaultValue: 'userSetupDetailDefaultFormat',\n },\n },\n\n {\n fields: {\n label: 'User Summary Fields',\n value: 'userSummaryFields',\n },\n format: {\n label: 'User Summary Format',\n value: 'userSummaryFormat',\n defaultValue: 'userSummaryDefaultFormat',\n },\n },\n ],\n },\n];\n\nexport const customTablePaperStyle = (darkMode) => ({\n boxShadow: darkMode\n ? 'none'\n : '0px 5px 5px -3px rgba(0,0,0,0.2),0px 8px 10px 1px rgba(0,0,0,0.14),0px 3px 14px 2px rgba(0,0,0,0.12)',\n '&& .Mui-selected, &.Mui-focusVisible': {\n backgroundColor: darkMode\n ? 'rgba(255, 255, 255, 0.26)'\n : 'var(--chakra-colors-gray-100)',\n '&:hover': {\n backgroundColor: darkMode\n ? 'var(--chakra-colors-whiteAlpha-300)'\n : 'var(--chakra-colors-gray-200)',\n },\n },\n '& .MuiMenu-list': {\n li: {\n display: 'flex',\n padding: '6px 16px',\n '&:hover': {\n backgroundColor: darkMode\n ? 'var(--chakra-colors-whiteAlpha-300)'\n : 'var(--chakra-colors-gray-200)',\n },\n },\n },\n});\n","import {\n Box,\n MenuItem,\n Checkbox as MuiCheckbox,\n TextField as MuiTextField,\n Tooltip,\n} from '@mui/material';\n\nimport MaterialTable from 'material-table';\nimport { forwardRef, useEffect, useMemo, useState } from 'react';\nimport { useDispatch, useSelector } from 'react-redux';\nimport Edit from '@mui/icons-material/Edit';\nimport { useDisclosure } from '@chakra-ui/react';\n\nimport { createTheme, ThemeProvider } from '@material-ui/core/styles';\nimport tableIcons from '../../../utils/MaterialTableIcons';\nimport BillingNotesModal from './BillingNotesModal';\n\nimport store from '@/store/store';\nimport walkthroughIds from '../walkthroughIds';\nimport { customTablePaperStyle } from './constants';\n\nconst Checkbox = forwardRef((props, ref) => {\n return (\n \n );\n});\n\nCheckbox.displayName = 'Checkbox';\n\nconst TextField = forwardRef((props, ref) => {\n const { darkMode } = useSelector((state) => state.settings);\n return (\n \n );\n});\n\nTextField.displayName = 'TextField';\n\n// default columns for the table\nconst columns = [\n {\n field: 'description',\n title: ' Billing Note',\n width: 570,\n editComponent: (props) => {\n return (\n {\n props.onChange(e.target.value);\n }}\n />\n );\n },\n },\n {\n field: 'requiredScope',\n title: 'Scope',\n width: 125,\n editComponent: (props) => {\n return (\n props.onChange(e.target.value)}>\n {scopes.map((option) => (\n \n ))}\n \n );\n },\n },\n {\n field: 'isActive',\n title: 'Active',\n width: 120,\n type: 'boolean',\n render: (rowData) => {\n return (\n \n {\n store.dispatch({\n type: 'CHANGE_MODAL_STATE',\n payload: {\n rowClicked: rowData?.tableData?.id,\n },\n });\n }}\n onMouseLeave={() => {\n store.dispatch({\n type: 'CHANGE_MODAL_STATE',\n payload: {\n rowClicked: -1,\n },\n });\n }}\n checked={rowData.isActive}\n className=\"hover:cursor-not-allowed\"\n readOnly\n />\n \n );\n },\n editComponent: (props) => {\n return (\n props.onChange(e.target.checked)}\n />\n );\n },\n },\n {\n field: 'billingNoteLocation',\n title: 'Display Location',\n width: 220,\n render: (rowData) => {\n if (rowData.billingNoteLocation === 0) {\n return 'Top';\n }\n if (rowData.billingNoteLocation === 1) {\n return 'Bottom';\n } else {\n return 'Top';\n }\n },\n editComponent: (props) => {\n return (\n props.onChange(e.target.value)}>\n {locations.map((option) => (\n \n ))}\n \n );\n },\n },\n];\n// enums for inputs\nconst scopes = [\n { value: 20, label: 20 },\n { value: 40, label: 40 },\n { value: 60, label: 60 },\n { value: 80, label: 80 },\n];\nconst locations = [\n { value: 0, label: 'Top' },\n { value: 1, label: 'Bottom' },\n];\n\n/**\n * Table that is displayed in the billing note section of the company billing form\n */\nconst BillingNoteTable = (props) => {\n const muiTheme = useMemo(\n () =>\n createTheme({\n typography: {\n color: '#000000',\n },\n head: {\n backgroundColor: null,\n },\n overrides: {\n MuiToolbar: {\n root: {\n color: 'rgba(255,255,255, 0.7)',\n backgroundColor: '#424242',\n },\n },\n MuiTable: {\n root: {\n WebkitTextFillColor:\n 'rgba(255, 255, 255, 0.7) !important',\n backgroundColor: '#424242 !important',\n },\n },\n MuiTableHead: {\n root: {\n backgroundColor: '#424242 !important',\n },\n },\n MuiTableCell: {\n root: {\n borderBottom: null,\n borderTop: '1px solid rgba(224, 224, 224, 0.1)',\n },\n },\n MuiTablePagination: {\n root: {\n backgroundColor: 'white',\n },\n },\n MuiPaper: {\n root: {\n backgroundColor: null,\n },\n },\n MuiIconButton: {\n label: {\n color: 'rgba(255, 255, 255, 0.3)',\n },\n },\n },\n }),\n [],\n );\n\n const dispatch = useDispatch();\n const { setBillingState } = props;\n const [isActive, setIsActive] = useState(true);\n const [desc, setDesc] = useState();\n const [location, setLocation] = useState(0);\n const [scope, setScope] = useState(20);\n const [rows, setRows] = useState([]);\n const [loading] = useState(false);\n\n // state access\n const { state } = useSelector((state) => {\n return {\n ...state.modal,\n };\n });\n const { rowClicked } = state || -1;\n\n const { darkMode } = useSelector((state) => state.settings);\n\n const { isOpen, onOpen, onClose } = useDisclosure();\n\n const { modal } = walkthroughIds.companies.billing;\n\n // function for when the modal is submitted, ie a note is added\n const onSubmitHandler = () => {\n let tempNotes;\n if (state.companyBillingSettings) {\n tempNotes = [\n ...state.companyBillingSettings.billingNotes,\n {\n requiredScope: scope,\n billingNoteLocation: location,\n description: desc,\n isActive: isActive,\n billingSettingsID: state.companyBillingSettings.id,\n },\n ];\n } else {\n tempNotes = [\n {\n requiredScope: scope,\n billingNoteLocation: location,\n description: desc,\n isActive: isActive,\n billingSettingsID: state.companyBillingSettings.id,\n },\n ];\n }\n setBillingState({ billingNotes: tempNotes });\n onClose();\n };\n\n // append rows based on the state\n useEffect(() => {\n if (state?.companyBillingSettings?.billingNotes && loading === false) {\n let result = [];\n state.companyBillingSettings.billingNotes.forEach((v) => {\n const temp = {\n ...v,\n };\n result.push(temp);\n });\n setRows([...result]);\n }\n }, [state?.companyBillingSettings?.billingNotes, loading]);\n\n // sets array so dispatch can spread empty array for delete handling\n useEffect(() => {\n if (state.deletedNoteIDs === undefined) {\n dispatch({\n type: 'CHANGE_MODAL_STATE',\n payload: {\n deletedNoteIDs: [],\n },\n });\n }\n }, []);\n\n const billingNotesModalProps = {\n isOpen,\n onClose,\n modal,\n desc,\n setDesc,\n scopes,\n setScope,\n locations,\n location,\n setLocation,\n isActive,\n setIsActive,\n onSubmitHandler,\n };\n\n const foundRowClicked = rows.find(\n (row) => row?.tableData?.id === rowClicked,\n );\n\n // table that billing notes renders\n return (\n \n \n (\n \n ),\n }}\n columns={columns}\n data={rows}\n options={{\n actionsColumnIndex: -1,\n search: false,\n sorting: true,\n pageSize: 3,\n pageSizeOptions: [],\n draggable: false,\n }}\n actions={[\n {\n icon: tableIcons.Add,\n tooltip: 'Add',\n isFreeAction: true,\n onClick: onOpen,\n },\n ]}\n editable={{\n onRowDelete: (oldData) =>\n new Promise((resolve) => {\n setTimeout(() => {\n const dataDelete = [...rows];\n const index = oldData.tableData.id;\n dataDelete.splice(index, 1);\n setRows([...dataDelete]);\n dispatch({\n type: 'CHANGE_MODAL_STATE',\n payload: {\n deletedNoteIDs: [\n {\n id: oldData.id,\n },\n ...state.deletedNoteIDs,\n ],\n },\n });\n dispatch({\n type: 'CHANGE_MODAL_STATE',\n payload: {\n companyBillingSettings: {\n ...state.companyBillingSettings,\n billingNotes: dataDelete,\n },\n },\n });\n resolve();\n }, 1000);\n }),\n onRowUpdate: (newData, oldData) =>\n new Promise((resolve) => {\n setTimeout(() => {\n const dataUpdate = [...rows];\n const index = oldData.tableData.id;\n dataUpdate[index] = newData;\n setRows([...dataUpdate]);\n let result = [];\n state.companyBillingSettings.billingNotes.forEach(\n (v) => {\n if (\n v.description ===\n oldData.description\n ) {\n // if one state value matches the old data - update this value\n const temp = {\n ...newData,\n id: v.id,\n };\n result.push(temp);\n } else {\n // make sure to grab that host and keep it in state\n const temp = { ...v };\n result.push(temp);\n }\n },\n );\n setBillingState({\n billingNotes: result,\n });\n resolve();\n }, 1000);\n }),\n }}\n localization={{\n header: {\n actions: '',\n },\n body: {\n editRow: {\n deleteText:\n 'Are you sure you want to delete this note?',\n },\n },\n }}\n />\n \n\n {/* Diaglogue that opens when you add a billing note */}\n \n \n );\n};\n\nexport default BillingNoteTable;\n","import React from 'react';\nimport NumberFormat from 'react-number-format';\n\n/*\n * A series of number format methods\n */\nconst NumberFormatCustom = (props) => {\n const { inputRef, onChange, ...other } = props;\n\n return (\n {\n onChange &&\n onChange({\n target: {\n name: props.name,\n value: values.value,\n },\n });\n }}\n allowNegative={false}\n thousandSeparator\n isNumericString\n decimalScale={6}\n fixedDecimalScale={true}\n />\n );\n};\n\n/*\n * A series of number format methods\n */\nexport const NegativeSixDP = (props) => {\n const { inputRef, onChange, ...other } = props;\n\n return (\n {\n onChange &&\n onChange({\n target: {\n name: props.name,\n value: values.value,\n },\n });\n }}\n thousandSeparator\n isNumericString\n decimalScale={6}\n fixedDecimalScale={true}\n />\n );\n};\n\nexport const Dollar = (props) => {\n const { inputRef, onChange, ...other } = props;\n\n return (\n {\n onChange &&\n onChange({\n target: {\n name: props.name,\n value: values.value,\n },\n });\n }}\n allowNegative={false}\n thousandSeparator\n isNumericString\n prefix=\"$\"\n decimalScale={2}\n fixedDecimalScale={true}\n />\n );\n};\n\nexport const FloatAllowNegative = (props) => {\n const { inputRef, onChange, ...other } = props;\n\n return (\n {\n onChange &&\n onChange({\n target: {\n name: props.name,\n value: values.value,\n },\n });\n }}\n allowNegative={true}\n thousandSeparator\n isNumericString\n decimalScale={6}\n fixedDecimalScale={true}\n />\n );\n};\n\nexport const FloatSurchargePercentage = (props) => {\n const { inputRef, onChange, ...other } = props;\n return (\n {\n onChange &&\n onChange({\n target: {\n name: props.name,\n value: values.value,\n },\n });\n }}\n allowNegative={true}\n thousandSeparator\n isNumericString\n decimalScale={6}\n fixedDecimalScale={true}\n />\n );\n};\n\nexport const FloatSurcharge = (props) => {\n const { inputRef, onChange, ...other } = props;\n return (\n {\n onChange &&\n onChange({\n target: {\n name: props.name,\n value: values.value,\n },\n });\n }}\n allowNegative={true}\n thousandSeparator\n isNumericString\n decimalScale={6}\n fixedDecimalScale={true}\n />\n );\n};\nexport const NonNegativeInteger = (props) => {\n const { inputRef, onChange, ...other } = props;\n\n return (\n {\n onChange &&\n onChange({\n target: {\n name: props.name,\n value: values.value,\n },\n });\n }}\n allowNegative={false}\n thousandSeparator\n isNumericString\n decimalScale={0}\n fixedDecimalScale={true}\n />\n );\n};\n\nexport const PhoneNumber = (props) => {\n const { inputRef, onChange, ...other } = props;\n\n return (\n {\n onChange &&\n onChange({\n target: {\n name: props.name,\n value: values.value,\n },\n });\n }}\n allowNegative={false}\n isNumericString\n decimalScale={0}\n fixedDecimalScale={true}\n />\n );\n};\n\nexport default NumberFormatCustom;\n","import React from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Button from '@material-ui/core/Button';\nimport { Modal } from 'react-bootstrap';\nimport { classNames } from 'utils/classNames';\nimport { useSelector } from 'react-redux';\n\n// theme usage with material ui\nconst useStyles = makeStyles((theme) => ({\n root: {\n maxWidth: '100%',\n flexGrow: 1,\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n height: 50,\n paddingLeft: theme.spacing(4),\n backgroundColor: theme.palette.background.default,\n },\n img: {\n overflow: 'hidden',\n display: 'block',\n width: '100%',\n },\n content: {\n padding: '5%',\n },\n}));\n\n// Restore to default confirmation modal\nconst RestoreDefaultModal = ({ handleClose, show, handleSubmit, content }) => {\n const classes = useStyles();\n\n const { darkMode } = useSelector((state) => state.settings);\n\n return (\n \n \n Restore To Default \n \n \n