Untitled

 avatar
unknown
plain_text
a year ago
19 kB
3
Indexable
/* eslint-disable @typescript-eslint/ban-ts-comment */
import React, { useState } from 'react'
import { Card } from '@abyss/web/ui/Card'
import { Layout } from '@abyss/web/ui/Layout'
import { Grid } from '@abyss/web/ui/Grid'
import { DateInputRange } from '@abyss/web/ui/DateInputRange'
import { SelectInput } from '@abyss/web/ui/SelectInput'
import { Button } from '@abyss/web/ui/Button'
import { dayjs } from '@abyss/web/tools/dayjs'
import { useForm } from '@abyss/web/hooks/useForm'
import { FormProvider } from '@abyss/web/ui/FormProvider'
import { CollapseProvider } from '@abyss/web/ui/CollapseProvider'
import SubmittedFilesTiles from './SubmittedFilesTiles/SubmittedFilesTiles'
import { LoadingOverlay } from '@abyss/web/ui/LoadingOverlay'
import { RadioGroup } from '@abyss/web/ui/RadioGroup'
import { SubmittedTileDataType } from './SubmittedFilesDataModel'
import { useToast } from '@abyss/web/hooks/useToast'
import { HeaderWrapper, HeaderWrapperDiv1, HeaderWrapperDiv2, ClearCriteriaBtn } from './SubmittedFiles.styled'

import { getTenantOrPartnerData, fetchCountForTiles } from './SubmittedFilesTiles/submittedFilesService'
import { getHeaderName, apiResponseMapperObj, apisFor835Partner, apisForAllOtherTrn, apisFor275Partner, apisFor275Tenant } from './SubmittedFilesTiles/TileAPIMappings'

const initialTileState = {
  'Submitted Files': '-',
  'Processed Checks': '-',
  'Invalid Files': '-',
  'Duplicate Files': '-',
  'ENR Checks': '-',
  'Inbound Failed Files': '-',
  'Outbound Failed Files': '-',
  'Resubmissions Audit Tile': '-',
  'Outbound Processed Files': '-',
  "Missing 275's 999 Files": '-',
  "Rejected 275's 999 Files": '-',
  'Rejected Attachments': '-',
  'Total Individual Attachments': '-'
}

interface SubmittedFilesFormDataType {
  submissionDate: { from: string; to: string }
  selectedTransactionTypes837: []
  idType: string
  selectedTenant: string
  selectedPartner: string
}

export const buildReqBodyForEDI = (submittedData) => {
  const reqBody = {
    tenantId: submittedData.idType === 'TenantId' ? submittedData.selectedTenant : submittedData.selectedPartner,
    startDate: submittedData.submissionDate.from.replaceAll('/', '-'),
    endDate: submittedData.submissionDate.to.replaceAll('/', '-'),
    transactionType: submittedData.selectedTransactionTypes837,
    submissionTimeRange: 'DR',
    submitterType: submittedData.idType
  }
  return reqBody
}

const SubmittedFiles = () => {
  const minStartDate = new Date()
  const CurDate = new Date()
  minStartDate.setMonth(CurDate.getMonth() - 13, 0)
  const defaultEndDate = dayjs(CurDate).format('MM/DD/YYYY')
  const yesterdayDate = new Date()
  yesterdayDate.setDate(yesterdayDate.getDate() - 1)
  const defaultStartDate = dayjs(yesterdayDate).format('MM/DD/YYYY')
  const form = useForm({
    defaultValues: {
      submissionDate: { from: defaultStartDate, to: defaultEndDate },
      selectedTransactionTypes837: [],
      idType: '',
      selectedTenant: '',
      selectedPartner: ''
    }
  })
  const { toast } = useToast()
  const idTypeLength = form.getValues('idType').length
  const submissionDatefromfilled = form.getValues('submissionDate.from') != ''
  const submissionDatetofilled = form.getValues('submissionDate.to') != ''
  const selectTranslength = form.getValues('selectedTransactionTypes837').length
  const selectTenantLength = form.getValues('selectedTenant').length
  const selectPartnerLength = form.getValues('selectedPartner').length
  const formidType = form.getValues('idType')

  const valididType = (formidType) => {
    if ((formidType === 'TenantId' && selectTenantLength > 0) || (formidType === 'PartnerId' && selectPartnerLength > 0)) {
      return true
    } else {
      return false
    }
  }

  const formvalid = idTypeLength > 0 && submissionDatefromfilled && submissionDatetofilled && selectTranslength > 0 && valididType(formidType)
  const [value, setValue] = useState({ from: '', to: '' })
  const [showTiles, setShowTiles] = useState(false)
  const [isLoading, setIsLoading] = useState(false)
  const [tilesData, setTilesData] = useState<SubmittedTileDataType>(initialTileState)
  const [transactiontype, setTransactiontype] = useState('')
  const [data, setData] = useState<SubmittedFilesFormDataType>({
    submissionDate: { from: '', to: '' },
    selectedTransactionTypes837: [],
    idType: '',
    selectedTenant: '',
    selectedPartner: ''
  })
  const [idType, setIdType] = useState('')
  const [submit, setSubmit] = useState(false)
  const [tenantsOrPartners, setTenantsOrPartners] = useState([])
  const [tenantId, setTenantId] = useState('')
  const [startDate, setStartDate] = useState('')
  const [endDate, setEndDate] = useState('')
  const [submitterIdType, setSubmitterIdType] = useState('')
  const [filtercollapsed, setFiltercollapsed] = useState(false)
  const trancString = JSON.stringify(data?.selectedTransactionTypes837)
  const filterCollapseBtn: HTMLElement = document.getElementsByClassName('abyss-card-collapse-button')[0] as HTMLElement
  filterCollapseBtn && filterCollapseBtn.addEventListener('click', () => setFiltercollapsed(!filtercollapsed))

  const onReset = () => {
    form.reset()
    setData({ submissionDate: { from: '', to: '' }, selectedTransactionTypes837: [], idType: '', selectedTenant: '', selectedPartner: '' })
    setIdType('')
    setSubmitterIdType('')
    setSubmit(false)
    setShowTiles(false)
    if (filtercollapsed) {
      filterCollapseBtn.click()
    }
  }

  const HeaderEDI = (
    <HeaderWrapper>
      <HeaderWrapperDiv1>Filters</HeaderWrapperDiv1>
      {submit && (
        <>
          <HeaderWrapperDiv2>
            {data.submissionDate && (
              <span>
                Submission Date Range: {data.submissionDate.from} - {data.submissionDate.to}
              </span>
            )}
            <span>Transaction Type: {trancString}</span>
            {data.idType === 'TenantId' && <span>Tenant ID: {data.selectedTenant}</span>}
            {data.idType === 'PartnerId' && <span>Partner ID: {data.selectedPartner}</span>}
          </HeaderWrapperDiv2>
          <ClearCriteriaBtn id="clear-criteria" onClick={onReset}>
            Clear Criteria
          </ClearCriteriaBtn>
        </>
      )}
    </HeaderWrapper>
  )

  // Further additions can be made here to include other transaction types
  const transactionEDIOpts = [
    { value: 'All', label: 'All' },
    { value: '835', label: '835' },
    { value: '275', label: '275' }
  ]

  const onSubmit = (data) => {
    setData(data)
    setSubmit(true)
    setSubmitterIdType(idType)
    showTiles && setIsLoading(true)
    setTransactiontype(data.selectedTransactionTypes837)
    setTenantId('TenantId' === idType ? data.selectedTenant : data.selectedPartner)
    setStartDate(data.submissionDate.from.replaceAll('/', '-'))
    setEndDate(data.submissionDate.to.replaceAll('/', '-'))
    fetchDataForEDI(data)
    filterCollapseBtn.click()
    setFiltercollapsed(true)
  }

  const handleIDChange = (e) => {
    e.stopPropagation()
    setIdType(e.target.value)
    setIsLoading(true)
    getTenantOrPartnerList(e.target.value)
  }

  const getTenantOrPartnerList = (submitter) => {
    return getTenantOrPartnerData(submitter)
      .then((response) => {
        const res = response.data.map((d) => ({
          label: d,
          value: d
        }))
        setIsLoading(false)
        setTenantsOrPartners(res)
      })
      .catch(() => {
        setIsLoading(false)
        setTenantsOrPartners([])
        return toast.show({
          title: 'Internal Server Error',
          message: 'This request could not be completed currently due to some internal server error. Please try again later.',
          autoClose: false
        })
      })
  }

  const fetchDataForEDI = (submittedData) => {
    prepareTilesToShow(submittedData.selectedTransactionTypes837, buildReqBodyForEDI(submittedData))
  }

  // For introducing APIs for new tiles, go to TileAPIMappings.ts and add the respective APIs that need to be called
  // add additional condition in below method to include that transaction type
  const getAPIListForTrnType = (transactionType) => {
    let apiList
    if (transactionType === '835' && idType === 'PartnerId') {
      apiList = apisFor835Partner
    } else if (transactionType === '275' && idType === 'PartnerId') {
      apiList = apisFor275Partner
    } else if (transactionType === '275' && idType === 'TenantId') {
      apiList = apisFor275Tenant
    } else {
      apiList = apisForAllOtherTrn
    }
    return apiList
  }

  const buildTilesData = (transactionType, apiName, data, tileData, idType) => {
    const header = getHeaderName(transactionType, apiName, idType)
    if ('100' === data['statusCode']) {
      tileData[header] = data[apiResponseMapperObj[apiName]]
    } else if ('400' === data['statusCode']) {
      tileData[header] = 'Failed to fetch data due to internal server error'
    }
    return { ...tileData }
  }

  const prepareTilesToShow = (transactionType, reqBody) => {
    let apiListForTrnType: string[] = []
    let tileData = initialTileState

    apiListForTrnType = getAPIListForTrnType(transactionType)

    apiListForTrnType.forEach((apiName) => {
      setIsLoading(true)
      fetchCountForTiles(apiName, reqBody)
        .then((response) => {
          tileData = buildTilesData(transactionType, apiName, response.data, tileData, idType)
          setTilesData(tileData)
          setIsLoading(false)
        })
        .catch(() => {
          setIsLoading(false)
          tileData = buildTilesData(transactionType, apiName, { statusCode: '400' }, tileData, idType)
          setTilesData(tileData)
        })
    })
    setShowTiles(true)
  }

  return (
    <LoadingOverlay
      loadingTitle="Please Wait"
      loadingMessage="Retrieving Information."
      isDismissable
      ariaLoadingLabel="Loading"
      isLoading={isLoading}
      width="20%"
    >
      <CollapseProvider defaultIsOpen={true}>
        <Card>
          <div className="filters">
            <Card header={HeaderEDI} size="small" collapse>
              <Card.Section>
                <FormProvider state={form} onSubmit={onSubmit}>
                  <Layout.Stack alignItems="left" grow>
                    <Grid>
                      <Grid.Col span={3}>
                        <DateInputRange
                          label="Submission Start Date"
                          model="submissionDate"
                          values={value}
                          // @ts-expect-error
                          onChange={setValue}
                          startDateLabel="Start Date"
                          endDateLabel="End Date"
                          minimumDate={minStartDate}
                          maximumDate={CurDate}
                          validators={{
                            required: true,
                            validate: {
                              isBefore: (v) => {
                                return (
                                  dayjs(v.from, 'MM/DD/YYYY').isBefore(dayjs(new Date(), 'MM/DD/YYYY')) ||
                                    toast.show({
                                      title: 'Date input validation error',
                                      message: 'Start Date should not be a future date'
                                    }),
                                  dayjs(v.from, 'MM/DD/YYYY').isBefore(dayjs(new Date(), 'MM/DD/YYYY')) || 'Start Date should not be a future date',
                                  dayjs(v.to, 'MM/DD/YYYY').isBefore(dayjs(new Date(), 'MM/DD/YYYY')) ||
                                    toast.show({
                                      title: 'Date input validation error',
                                      message: 'End date should not be a future date'
                                    }),
                                  dayjs(v.to, 'MM/DD/YYYY').isBefore(dayjs(new Date(), 'MM/DD/YYYY')) || 'End date should not be a future date'
                                )
                              },

                              isAfter: (v) => {
                                const beforestartDate = new Date(v.from)
                                beforestartDate.setDate(beforestartDate.getDate() - 1)

                                return (
                                  dayjs(v.to, 'MM/DD/YYYY').isAfter(dayjs(beforestartDate, 'MM/DD/YYYY')) ||
                                    toast.show({
                                      title: 'Date input validation error',
                                      message: 'End date should be after Start Date'
                                    }),
                                  dayjs(v.to, 'MM/DD/YYYY').isAfter(dayjs(beforestartDate, 'MM/DD/YYYY')) || 'End date should be after start date'
                                )
                              },

                              isBetween: (v) => {
                                const validatedefaultStartDate = new Date()
                                const validatedefaultMessageStartDate = new Date()
                                validatedefaultStartDate.setMonth(validatedefaultStartDate.getMonth() - 13, 0)
                                validatedefaultMessageStartDate.setMonth(validatedefaultMessageStartDate.getMonth() - 13, 1)
                                const validateToday = new Date()

                                return (
                                  dayjs(v.from, 'MM/DD/YYYY').isBetween(dayjs(validatedefaultStartDate, 'MM/DD/YYYY', validateToday, 'MM/DD/YYYY')) ||
                                    toast.show({
                                      title: 'Date range validation error',
                                      message:
                                        'Date range should be between ' +
                                        validatedefaultMessageStartDate.toLocaleDateString() +
                                        '--' +
                                        validateToday.toLocaleDateString()
                                    }),
                                  dayjs(v.from, 'MM/DD/YYYY').isBetween(
                                    dayjs(validatedefaultStartDate.toLocaleDateString(), 'MM/DD/YYYY', validateToday, 'MM/DD/YYYY')
                                  ) ||
                                    'Date range should be between ' +
                                      validatedefaultMessageStartDate.toLocaleDateString() +
                                      '--' +
                                      validateToday.toLocaleDateString()
                                )
                              }
                            }
                          }}
                        />
                      </Grid.Col>

                      <Grid.Col span={3}>
                        <SelectInput
                          label="Transaction Type"
                          model="selectedTransactionTypes837"
                          options={transactionEDIOpts}
                          placeholder={'Please select transaction type'}
                          validators={{ required: true }}
                          css={{ 'abyss-select-input-root': { padding: '0.35em' } }}
                        />
                      </Grid.Col>

                      <Grid.Col span={2}>
                        <RadioGroup
                          label="Select ID Type"
                          model="idType"
                          onChange={(e) => handleIDChange(e)}
                          value={idType}
                          display="column"
                          validators={{ required: true }}
                        >
                          <RadioGroup.Radio label="Tenant ID" value="TenantId" />
                          <RadioGroup.Radio label="Partner ID" value="PartnerId" />
                        </RadioGroup>
                      </Grid.Col>
                      {idType === 'TenantId' && (
                        <Grid.Col span={3}>
                          <SelectInput
                            label="Tenant ID"
                            model="selectedTenant"
                            options={tenantsOrPartners}
                            placeholder={'Please select Tenant ID'}
                            isSearchable
                            virtual
                            validators={{ required: true }}
                          />
                        </Grid.Col>
                      )}
                      {idType === 'PartnerId' && (
                        <Grid.Col span={3}>
                          <SelectInput
                            label="Partner ID"
                            model="selectedPartner"
                            options={tenantsOrPartners}
                            placeholder={'Please select Partner ID'}
                            isSearchable
                            virtual
                            validators={{ required: true }}
                          />
                        </Grid.Col>
                      )}
                    </Grid>
                    <Grid>
                      <Grid.Col span={2}>
                        <Button type="submit" disabled={!formvalid}>
                          Apply Filters
                        </Button>
                      </Grid.Col>
                    </Grid>
                  </Layout.Stack>
                </FormProvider>
              </Card.Section>
            </Card>
          </div>
          {showTiles && (
            <Card.Section id="submittedFilesTiles">
              <SubmittedFilesTiles
                tilesData={tilesData}
                transactionType={transactiontype}
                submitterType={submitterIdType}
                tenantId={tenantId}
                startDate={startDate}
                endDate={endDate}
                fetchDataForEDI={() => fetchDataForEDI(data)}
              />
            </Card.Section>
          )}
        </Card>
      </CollapseProvider>
    </LoadingOverlay>
  )
}

export default SubmittedFiles
Editor is loading...
Leave a Comment