{"results":{"result":{"added-files":{"code-health":9.571164024061876,"old-code-health":0.0,"files":[{"file":"src/components/Reports/HealthIndicatorReport/HealthIndicatorWidget/HealthIndicatorWidget.tsx","loc":140,"code-health":9.608927141875917},{"file":"src/components/Reports/HealthIndicatorReport/HealthIndicatorWidget/HealthIndicatorWidget.test.tsx","loc":115,"code-health":9.387218218812514},{"file":"src/components/Reports/HealthIndicatorReport/HealthIndicatorWidget/WidgetStat/WidgetStat.tsx","loc":37,"code-health":10.0}]},"external-review-url":"https://github.com/CruGlobal/mpdx-react/pull/1229","old-code-health":9.60616681807373,"modified-files":{"code-health":9.525675152771905,"old-code-health":9.60616681807373,"files":[{"file":"src/components/Dashboard/Dashboard.tsx","loc":74,"old-loc":74,"code-health":10.0,"old-code-health":10.0},{"file":"src/components/Dashboard/MonthlyGoal/MonthlyGoal.tsx","loc":291,"old-loc":245,"code-health":8.7579534928254,"old-code-health":8.977641209366904},{"file":"src/components/StyledProgress/StyledProgress.tsx","loc":121,"old-loc":107,"code-health":10.0,"old-code-health":10.0},{"file":"src/components/Dashboard/MonthlyGoal/MonthlyGoal.test.tsx","loc":229,"old-loc":174,"code-health":10.0,"old-code-health":10.0},{"file":"src/components/StyledProgress/StyledProgress.test.tsx","loc":47,"old-loc":36,"code-health":10.0,"old-code-health":10.0}]},"removed-files":{"code-health":0.0,"old-code-health":0.0,"files":[]},"external-review-id":"1229","analysis-time":"2024-12-16T19:58:47Z","negative-impact-count":3,"suppressions":{"number-of-types":0,"number-of-files-touched":0,"findings":[]},"affected-hotspots":0,"commits":["fd88993f0494b130a6b0f65149975520712d2980","4fd1765cce36349150918b72ef0e204961bd70bd","00f42501b5dc9a7a941096458589d27cc5d139ca","17d45113ea2f2798211a80c9bdd50f41f60b1513","22ca6cabab56b4b91cd1121167149985f72b2455","b4015ca12fe76eed4742f8623e63bced864d47a2","33c9b3dbbf9badaf55d1b00645c9549480e82ec5","d32225fbf2e8b032d625ce66c09ae2ef5b33d983","8764489d094c4a981aa49679ca62258c49b9a27b"],"is-negative-review":true,"negative-findings":{"number-of-types":2,"number-of-files-touched":3,"findings":[{"method":"HealthIndicatorWidget:React.FC<HealthIndicatorWidgetProps>","why-it-occurs":"A Complex Method has a high cyclomatic complexity. The recommended threshold for the React language is a cyclomatic complexity lower than 10.","name":"Complex Method","file":"src/components/Reports/HealthIndicatorReport/HealthIndicatorWidget/HealthIndicatorWidget.tsx","refactoring-examples":[{"architectural-component-id":null,"author-name":"Caleb Cox","training-data":{"loc-added":"3","loc-deleted":"3","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"1.35","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"canac@users.noreply.github.com","commit-full-message":"","commit-date":"2025-08-22T20:09:43Z","current-rev":"ca8f2ca29","filename":"mpdx-react/src/components/Helpjuice/Helpjuice.tsx","previous-rev":"04561eb59","commit-title":"Use CSS selector","language":"React","id":"6c93798585f2bb2ec87d5c50d0b52d7b6449a168","model-score":0.96,"author-id":null,"project-id":53436,"delta-file-score":0.568307,"diff":"diff --git a/src/components/Helpjuice/Helpjuice.tsx b/src/components/Helpjuice/Helpjuice.tsx\nindex a7b200c1a..a54cbb05a 100644\n--- a/src/components/Helpjuice/Helpjuice.tsx\n+++ b/src/components/Helpjuice/Helpjuice.tsx\n@@ -63,7 +63,7 @@ export const Helpjuice: React.FC = () => {\n       // We need to turn them into absolute URLs so that they open correctly\n-      for (const link of document.querySelectorAll('#article-content-body a')) {\n+      for (const link of document.querySelectorAll(\n+        '#article-content-body a[href^=\"/\"]',\n+      )) {\n         const href = link.getAttribute('href');\n-        if (href?.startsWith('/')) {\n-          link.setAttribute('href', `${helpJuiceOrigin}${href}`);\n-        }\n+        link.setAttribute('href', `${helpJuiceOrigin}${href}`);\n       }\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Daniel Bisgrove","training-data":{"loc-added":"3","loc-deleted":"1","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"5.382","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"daniel@bizz-websites.com","commit-full-message":"","commit-date":"2024-10-17T14:59:21Z","current-rev":"b4989f844","filename":"mpdx-react/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.tsx","previous-rev":"5894a893f","commit-title":"fixup! Fix routing issue after switching account","language":"React","id":"584c52e9e432999ea473cfb396e1aa9c502822cd","model-score":0.75,"author-id":null,"project-id":53436,"delta-file-score":1.555564,"diff":"diff --git a/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.tsx b/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.tsx\nindex a1e149d28..1f91bda3c 100644\n--- a/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.tsx\n+++ b/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.tsx\n@@ -197,3 +197,5 @@ const ProfileMenu = (): ReactElement => {\n       router.pathname ===\n-      '/accountLists/[accountListId]/reports/financialAccounts/[[...financialAccount]]'\n+        '/accountLists/[accountListId]/reports/financialAccounts/[financialAccountId]/entries' ||\n+      router.pathname ===\n+        '/accountLists/[accountListId]/reports/financialAccounts/[financialAccountId]'\n     ) {\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Daniel Bisgrove","training-data":{"loc-added":"11","loc-deleted":"4","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"6.318","delta-n-functions":"0","current-file-score":"9.842730062691357"},"author-email":"daniel@bizz-websites.com","commit-full-message":"","commit-date":"2024-06-12T15:32:50Z","current-rev":"e6289830e","filename":"mpdx-react/src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/EditContactAddressModal.tsx","previous-rev":"a9d552f51","commit-title":"Adding the ability to allow custom cache updates after mutation.","language":"React","id":"f22174b78d624b68491e49f4f04f0b1e4aec4edb","model-score":0.7,"author-id":null,"project-id":53436,"delta-file-score":1.6399608,"diff":"diff --git a/src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/EditContactAddressModal.tsx b/src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/EditContactAddressModal.tsx\nindex 9b6af14a0..8f9925d99 100644\n--- a/src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/EditContactAddressModal.tsx\n+++ b/src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/EditContactAddressModal.tsx\n@@ -1,2 +1,3 @@\n import React, { ReactElement } from 'react';\n+import { ApolloCache } from '@apollo/client';\n import {\n@@ -70,3 +71,3 @@ interface EditContactAddressModalProps {\n   contactId: string;\n-  handleClose: (deletedAddress: boolean) => void;\n+  handleUpdateCacheOnDelete?: (cache: ApolloCache<unknown>, object) => void;\n }\n@@ -80,2 +81,3 @@ export const EditContactAddressModal: React.FC<\n   handleClose,\n+  handleUpdateCacheOnDelete,\n }): ReactElement<EditContactAddressModalProps> => {\n@@ -127,4 +129,7 @@ export const EditContactAddressModal: React.FC<\n         },\n-        update: (cache, { data: deletedContactAddress }) => {\n-          const deletedAddressId = deletedContactAddress?.deleteAddress?.id;\n+        update: (cache) => {\n+          const deletedAddressId = address.id;\n+          if (handleUpdateCacheOnDelete) {\n+            handleUpdateCacheOnDelete(cache, { deletedAddressId });\n+          } else {\n           const query = {\n@@ -137,3 +142,4 @@ export const EditContactAddressModal: React.FC<\n \n-          const dataFromCache = cache.readQuery<ContactDetailsTabQuery>(query);\n+            const dataFromCache =\n+              cache.readQuery<ContactDetailsTabQuery>(query);\n \n@@ -153,2 +159,3 @@ export const EditContactAddressModal: React.FC<\n             cache.writeQuery({ ...query, data });\n+            }\n           }\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Bizz (Daniel Bisgrove)","training-data":{"loc-added":"27","loc-deleted":"2","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"6.048","delta-n-functions":"0","current-file-score":"9.842730062691357"},"author-email":"56281168+dr-bizz@users.noreply.github.com","commit-full-message":"* Add more warning messages when dragging contact to different columns.","commit-date":"2024-09-12T14:53:23Z","current-rev":"556abc41a","filename":"mpdx-react/src/components/Tool/Appeal/Modals/PledgeModal/PledgeModal.tsx","previous-rev":"3cde16b8e","commit-title":"MPDX-8187 + MPDX-8188 Add more warning messages when dragging contact to different columns. (#1056)","language":"React","id":"106116e788da85247f60c309cc55586685450747","model-score":0.7,"author-id":null,"project-id":53436,"delta-file-score":1.5710658,"diff":"diff --git a/src/components/Tool/Appeal/Modals/PledgeModal/PledgeModal.tsx b/src/components/Tool/Appeal/Modals/PledgeModal/PledgeModal.tsx\nindex a7217c8d6..3f655858e 100644\n--- a/src/components/Tool/Appeal/Modals/PledgeModal/PledgeModal.tsx\n+++ b/src/components/Tool/Appeal/Modals/PledgeModal/PledgeModal.tsx\n@@ -35,2 +35,3 @@ import i18n from 'src/lib/i18n';\n import {\n+  AppealStatusEnum,\n   AppealsContext,\n@@ -39,2 +40,3 @@ import {\n import { AppealContactInfoFragment } from '../../AppealsContext/contacts.generated';\n+import handleReceivedSnackBarNotifications from '../../Shared/handleReceivedSnackBarNotifications/handleReceivedSnackBarNotifications';\n import {\n@@ -51,2 +53,3 @@ interface PledgeModalProps {\n   pledge?: AppealContactInfoFragment['pledges'][0];\n+  selectedAppealStatus?: AppealStatusEnum | null;\n }\n@@ -79,2 +82,3 @@ export const PledgeModal: React.FC<PledgeModalProps> = ({\n   handleClose,\n+  selectedAppealStatus,\n }) => {\n@@ -116,3 +120,13 @@ export const PledgeModal: React.FC<PledgeModalProps> = ({\n         refetchQueries: ['Contacts', 'Appeal'],\n-        onCompleted: () => {\n+        onCompleted: ({ createAccountListPledge }) => {\n+          const newStatus = createAccountListPledge?.pledge.status;\n+          if (selectedAppealStatus) {\n+            handleReceivedSnackBarNotifications({\n+              dbStatus: newStatus,\n+              selectedAppealStatus,\n+              t,\n+              enqueueSnackbar,\n+            });\n+          }\n+\n           enqueueSnackbar(t('Successfully added commitment to appeal'), {\n@@ -145,3 +159,14 @@ export const PledgeModal: React.FC<PledgeModalProps> = ({\n         refetchQueries: ['Contacts', 'Appeal'],\n-        onCompleted: () => {\n+        onCompleted: ({ updateAccountListPledge }) => {\n+          const newStatus = updateAccountListPledge?.pledge.status;\n+\n+          if (selectedAppealStatus) {\n+            handleReceivedSnackBarNotifications({\n+              dbStatus: newStatus,\n+              selectedAppealStatus,\n+              t,\n+              enqueueSnackbar,\n+            });\n+          }\n+\n           enqueueSnackbar(t('Successfully edited commitment'), {\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Caleb Cox","training-data":{"loc-added":"28","loc-deleted":"12","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"3.294","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"canac@users.noreply.github.com","commit-full-message":"","commit-date":"2024-09-11T20:30:58Z","current-rev":"5e0f11d70","filename":"mpdx-react/src/components/Tool/Appeal/Modals/UpdateDonationsModal/DonationTable/DonationTable.tsx","previous-rev":"3cde16b8e","commit-title":"Cross out donations that will be removed from the appeal","language":"React","id":"2b776d0649fadc98ac0439811d1bba93e1303c17","model-score":0.59,"author-id":null,"project-id":53436,"delta-file-score":0.98683935,"diff":"diff --git a/src/components/Tool/Appeal/Modals/UpdateDonationsModal/DonationTable/DonationTable.tsx b/src/components/Tool/Appeal/Modals/UpdateDonationsModal/DonationTable/DonationTable.tsx\nindex dd4312d05..ce79ea35e 100644\n--- a/src/components/Tool/Appeal/Modals/UpdateDonationsModal/DonationTable/DonationTable.tsx\n+++ b/src/components/Tool/Appeal/Modals/UpdateDonationsModal/DonationTable/DonationTable.tsx\n@@ -87,2 +87,9 @@ export const DonationTable: React.FC<DonationTableProps> = ({\n   const { data, error, loading, fetchMore } = donationTableQueryResult;\n+  const preselectedDonations = useMemo(\n+    () =>\n+      data?.donations.nodes\n+        .filter((donation) => donation.appeal?.id === appealId)\n+        .map(createDonationRow) ?? [],\n+    [data],\n+  );\n \n@@ -96,12 +103,6 @@ export const DonationTable: React.FC<DonationTableProps> = ({\n   useEffect(() => {\n-    if (!data?.donations.nodes.length) {\n-      return;\n+    if (preselectedDonations?.length) {\n+      setSelectedDonations(preselectedDonations);\n     }\n-\n-    const preselectedDonations = data.donations.nodes\n-      .filter((donation) => donation.appeal?.id === appealId)\n-      .map(createDonationRow);\n-\n-    setSelectedDonations(preselectedDonations);\n-  }, [data]);\n+  }, [preselectedDonations]);\n \n@@ -111,2 +112,7 @@ export const DonationTable: React.FC<DonationTableProps> = ({\n \n+  const isPreselectedDonation = (donation: DonationRow) =>\n+    preselectedDonations.some((donationRow) => donationRow.id === donation.id);\n+  const isDonationChecked = (donation: DonationRow) =>\n+    selectedDonations.some((donationRow) => donationRow.id === donation.id);\n+\n   const date: RenderCell = ({ row }) => dateFormatShort(row.date, locale);\n@@ -125,3 +131,14 @@ export const DonationTable: React.FC<DonationTableProps> = ({\n \n-  const appeal: RenderCell = ({ row: donation }) => donation.appealName;\n+  const appeal: RenderCell = ({ row: donation }) => (\n+    <span\n+      style={{\n+        textDecoration:\n+          isPreselectedDonation(donation) && !isDonationChecked(donation)\n+            ? 'line-through'\n+            : undefined,\n+      }}\n+    >\n+      {donation.appealName}\n+    </span>\n+  );\n \n@@ -144,4 +161,3 @@ export const DonationTable: React.FC<DonationTableProps> = ({\n   };\n-  const isDonationChecked = (donation: DonationRow) =>\n-    selectedDonations.some((donationRow) => donationRow.id === donation.id);\n+\n   const select: RenderCell = ({ row: donation }) => (\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Daniel Bisgrove","training-data":{"loc-added":"67","loc-deleted":"0","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"3.816","delta-n-functions":"0","current-file-score":"9.842730062691357"},"author-email":"daniel@bizz-websites.com","commit-full-message":"","commit-date":"2024-06-25T14:55:28Z","current-rev":"945772dc6","filename":"mpdx-react/src/components/Tool/FixMailingAddresses/FixMailingAddresses.tsx","previous-rev":"eb907de17","commit-title":"Confirm single contact's addresses","language":"React","id":"f789b68cc8d82a89d390a756ba271bb953316cf5","model-score":0.55,"author-id":null,"project-id":53436,"delta-file-score":0.97569954,"diff":"diff --git a/src/components/Tool/FixMailingAddresses/FixMailingAddresses.tsx b/src/components/Tool/FixMailingAddresses/FixMailingAddresses.tsx\nindex 086bc13ea..4dbb7857d 100644\n--- a/src/components/Tool/FixMailingAddresses/FixMailingAddresses.tsx\n+++ b/src/components/Tool/FixMailingAddresses/FixMailingAddresses.tsx\n@@ -15,2 +15,3 @@ import {\n } from '@mui/material';\n+import { useSnackbar } from 'notistack';\n import { Trans, useTranslation } from 'react-i18next';\n@@ -28,4 +29,12 @@ import {\n   useInvalidAddressesQuery,\n+  useUpdateContactAddressMutation,\n } from './GetInvalidAddresses.generated';\n \n+export type HandleSingleConfirmProps = {\n+  addresses: ContactAddressFragment[];\n+  id: string;\n+  name: string;\n+  onlyErrorOnce?: boolean;\n+};\n+\n const useStyles = makeStyles()(() => ({\n@@ -136,2 +145,59 @@ const FixSendNewsletter: React.FC<Props> = ({\n   });\n+  const [updateAddress] = useUpdateContactAddressMutation();\n+  const { enqueueSnackbar } = useSnackbar();\n+\n+  const handleSingleConfirm = async ({\n+    addresses,\n+    id,\n+    name,\n+    onlyErrorOnce = false,\n+  }: HandleSingleConfirmProps) => {\n+    const errors: string[] = [];\n+\n+    for (let idx = 0; idx < addresses.length; idx++) {\n+      const address = addresses[idx];\n+\n+      await updateAddress({\n+        variables: {\n+          accountListId,\n+          attributes: {\n+            id: address.id,\n+            validValues: true,\n+            // TODO: Fix the Graph QL Input\n+            // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n+            // @ts-ignore\n+            primaryMailingAddress: address.primaryMailingAddress,\n+          },\n+        },\n+        update(cache) {\n+          if (idx === addresses.length - 1 && !errors.length) {\n+            cache.evict({ id: `Contact:${id}` });\n+          }\n+        },\n+        onError(error) {\n+          errors.push(\n+            `${name} - ${t('Error while saving addresses.')} ${error.cause}`,\n+          );\n+        },\n+      });\n+    }\n+\n+    if (errors.length) {\n+      if (onlyErrorOnce) {\n+        enqueueSnackbar(t(`Error updating contact ${name}`), {\n+          variant: 'error',\n+          autoHideDuration: 7000,\n+        });\n+      } else {\n+        errors.forEach((error) => {\n+          enqueueSnackbar(error, { variant: 'error' });\n+        });\n+      }\n+      return { success: false };\n+    } else {\n+      enqueueSnackbar(t(`Updated contact ${name}`), { variant: 'success' });\n+      return { success: true };\n+    }\n+  };\n+\n \n@@ -305,2 +371,3 @@ const FixSendNewsletter: React.FC<Props> = ({\n                         setContactFocus={setContactFocus}\n+                        handleSingleConfirm={handleSingleConfirm}\n                       />\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Will James","training-data":{"loc-added":"13","loc-deleted":"22","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"4.734","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"william.james@cru.org","commit-full-message":"","commit-date":"2025-07-14T17:18:44Z","current-rev":"0bda3723a","filename":"mpdx-react/src/components/Settings/integrations/Organization/ConnectOrganization.tsx","previous-rev":"ae4398dda","commit-title":"Updates components to use OrganizationAutocomplete and new location of DonorAccountAutocomplete.","language":"React","id":"69d809f40ed2a58a216204dcb06d76f74bac23db","model-score":0.54,"author-id":null,"project-id":53436,"delta-file-score":1.3835225,"diff":"diff --git a/src/components/Settings/integrations/Organization/ConnectOrganization.tsx b/src/components/Settings/integrations/Organization/ConnectOrganization.tsx\nindex 2f47f930b..d5713c142 100644\n--- a/src/components/Settings/integrations/Organization/ConnectOrganization.tsx\n+++ b/src/components/Settings/integrations/Organization/ConnectOrganization.tsx\n@@ -9,3 +9,2 @@ import { useApolloClient } from '@apollo/client';\n import {\n-  Autocomplete,\n   Box,\n@@ -23,2 +22,4 @@ import { useTranslation } from 'react-i18next';\n import { FieldWrapper } from 'src/components/Shared/Forms/FieldWrapper';\n+import { OrganizationAutocomplete } from 'src/components/common/Autocomplete/OrganizationAutocomplete/OrganizationAutocomplete';\n+import { Organization } from 'src/graphql/types.generated';\n import useGetAppSettings from 'src/hooks/useGetAppSettings';\n@@ -175,32 +176,22 @@ export const ConnectOrganization: React.FC<ConnectOrganizationProps> = ({\n           <ContentContainer>\n-            <Autocomplete\n+            <OrganizationAutocomplete\n               disabled={isSubmitting}\n               autoHighlight\n+              fullWidth\n               loading={loading}\n               value={selectedOrganization}\n+              organizations={\n+                organizations?.organizations?.filter(\n+                  (organization) => !organization?.disableNewUsers,\n+                ) ?? []\n+              }\n               onChange={(_, value) => {\n+                const org = value as Organization;\n                 setOrganizationType(\n-                  getOrganizationType(value?.apiClass, value?.oauth),\n+                  getOrganizationType(org?.apiClass, org?.oauth),\n                 );\n-                setSelectedOrg(value?.name ?? '');\n+                setSelectedOrg(org?.name ?? '');\n                 setFieldValue('selectedOrganization', value);\n               }}\n-              options={\n-                organizations?.organizations?.filter(\n-                  (organization) => !organization?.disableNewUsers,\n-                ) || []\n-              }\n-              getOptionLabel={(option) =>\n-                organizations?.organizations?.find(\n-                  ({ id }) => String(id) === String(option.id),\n-                )?.name ?? ''\n-              }\n-              fullWidth\n-              renderInput={(params) => (\n-                <TextField\n-                  {...params}\n-                  label={t('Organization')}\n-                  inputRef={focusOnOrganization}\n-                />\n-              )}\n+              textFieldFocusRef={focusOnOrganization}\n             />\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Daniel Bisgrove","training-data":{"loc-added":"36","loc-deleted":"11","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"3.114","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"daniel@bizz-websites.com","commit-full-message":"","commit-date":"2024-09-09T14:15:22Z","current-rev":"c4ef64282","filename":"mpdx-react/src/components/Tool/Appeal/Flow/ContactFlowColumn/ContactFlowColumn.tsx","previous-rev":"d2f225d28","commit-title":"Adding select all and deselect all onto each column","language":"React","id":"71c7067d34e931c166b2b014f7cb1e52c43ff71e","model-score":0.48,"author-id":null,"project-id":53436,"delta-file-score":0.93582284,"diff":"diff --git a/src/components/Tool/Appeal/Flow/ContactFlowColumn/ContactFlowColumn.tsx b/src/components/Tool/Appeal/Flow/ContactFlowColumn/ContactFlowColumn.tsx\nindex 3c24bc0f8..14c0029d0 100644\n--- a/src/components/Tool/Appeal/Flow/ContactFlowColumn/ContactFlowColumn.tsx\n+++ b/src/components/Tool/Appeal/Flow/ContactFlowColumn/ContactFlowColumn.tsx\n@@ -1,2 +1,2 @@\n-import React, { useRef, useState } from 'react';\n+import React, { useMemo, useRef, useState } from 'react';\n import MoreVertIcon from '@mui/icons-material/MoreVert';\n@@ -30,2 +30,3 @@ import {\n } from 'src/components/Tool/Appeal/AppealsContext/AppealsContext';\n+import { useGetIdsForMassSelectionQuery } from 'src/hooks/GetIdsForMassSelection.generated';\n import { appealHeaderInfoHeight } from '../../AppealDetails/AppealHeaderInfo/AppealHeaderInfo';\n@@ -70,5 +71,9 @@ export const ContactFlowColumn: React.FC<Props> = ({\n }) => {\n-  const { appealId, sanitizedFilters, starredFilter } = React.useContext(\n-    AppealsContext,\n-  ) as AppealsType;\n+  const {\n+    appealId,\n+    sanitizedFilters,\n+    starredFilter,\n+    selectMultipleIds,\n+    deselectMultipleIds,\n+  } = React.useContext(AppealsContext) as AppealsType;\n   const { t } = useTranslation();\n@@ -79,2 +84,13 @@ export const ContactFlowColumn: React.FC<Props> = ({\n \n+  const contactsFilters = useMemo(\n+    () => ({\n+      ...sanitizedFilters,\n+      ...starredFilter,\n+      appeal: [appealId ?? ''],\n+      appealStatus,\n+      wildcardSearch: searchTerm as string,\n+    }),\n+    [sanitizedFilters, starredFilter, searchTerm, appealId],\n+  );\n+\n   const { data, loading, fetchMore } = useContactsQuery({\n@@ -82,9 +98,3 @@ export const ContactFlowColumn: React.FC<Props> = ({\n       accountListId: accountListId ?? '',\n-      contactsFilters: {\n-        ...sanitizedFilters,\n-        ...starredFilter,\n-        appeal: [appealId ?? ''],\n-        appealStatus,\n-        wildcardSearch: searchTerm as string,\n-      },\n+      contactsFilters,\n     },\n@@ -93,2 +103,17 @@ export const ContactFlowColumn: React.FC<Props> = ({\n \n+  const contactCount = data?.contacts.totalCount ?? 0;\n+  const { data: allContacts } = useGetIdsForMassSelectionQuery({\n+    variables: {\n+      accountListId,\n+      first: contactCount,\n+      contactsFilters,\n+    },\n+    skip: contactCount === 0,\n+  });\n+\n+  const allContactIds = useMemo(\n+    () => allContacts?.contacts.nodes.map((contact) => contact.id) ?? [],\n+    [allContacts],\n+  );\n+\n   const { data: excludedContacts } = useExcludedAppealContactsQuery({\n@@ -118,4 +143,4 @@ export const ContactFlowColumn: React.FC<Props> = ({\n   const handleSelectAll = () => {\n+    selectMultipleIds(allContactIds);\n     setAnchorEl(null);\n-    // TODO implement select all\n   };\n@@ -123,4 +148,4 @@ export const ContactFlowColumn: React.FC<Props> = ({\n   const handleDeselectAll = () => {\n+    deselectMultipleIds(allContactIds);\n     setAnchorEl(null);\n-    // TODO implement deselect all\n   };\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Bizz (Daniel Bisgrove)","training-data":{"loc-added":"11","loc-deleted":"35","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"1.89","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"56281168+dr-bizz@users.noreply.github.com","commit-full-message":"* Add more warning messages when dragging contact to different columns.","commit-date":"2024-09-12T14:53:23Z","current-rev":"556abc41a","filename":"mpdx-react/src/components/Tool/Appeal/Flow/ContactFlow.tsx","previous-rev":"3cde16b8e","commit-title":"MPDX-8187 + MPDX-8188 Add more warning messages when dragging contact to different columns. (#1056)","language":"React","id":"cc97c2e44cba84629f9011bdb93cbabefafca6ba","model-score":0.45,"author-id":null,"project-id":53436,"delta-file-score":1.0139161,"diff":"diff --git a/src/components/Tool/Appeal/Flow/ContactFlow.tsx b/src/components/Tool/Appeal/Flow/ContactFlow.tsx\nindex 0c0c95f5d..10319643a 100644\n--- a/src/components/Tool/Appeal/Flow/ContactFlow.tsx\n+++ b/src/components/Tool/Appeal/Flow/ContactFlow.tsx\n@@ -19,2 +19,3 @@ import { DynamicPledgeModal } from '../Modals/PledgeModal/DynamicPledgeModal';\n import { DynamicUpdateDonationsModal } from '../Modals/UpdateDonationsModal/DynamicUpdateDonationsModal';\n+import handleReceivedSnackBarNotifications from '../Shared/handleReceivedSnackBarNotifications/handleReceivedSnackBarNotifications';\n import { ContactFlowColumn } from './ContactFlowColumn/ContactFlowColumn';\n@@ -102,2 +103,4 @@ export const ContactFlow: React.FC<ContactFlowProps> = ({\n   const [contact, setContact] = useState<DraggedContact | null>(null);\n+  const [selectedAppealStatus, setSelectedAppealStatus] =\n+    useState<AppealStatusEnum | null>(null);\n \n@@ -126,2 +129,3 @@ export const ContactFlow: React.FC<ContactFlowProps> = ({\n     setContact(contact);\n+    setSelectedAppealStatus(newAppealStatus);\n \n@@ -168,37 +172,8 @@ export const ContactFlow: React.FC<ContactFlowProps> = ({\n \n-              if (\n-                newStatus === PledgeStatusEnum.NotReceived &&\n-                newAppealStatus === AppealStatusEnum.ReceivedNotProcessed\n-              ) {\n-                enqueueSnackbar(\n-                  t(\n-                    'Unable to move contact here as gift has not been received by Cru.',\n-                  ),\n-                  {\n-                    variant: 'warning',\n-                  },\n-                );\n-              } else if (\n-                newStatus === PledgeStatusEnum.Processed &&\n-                (newAppealStatus === AppealStatusEnum.ReceivedNotProcessed ||\n-                  newAppealStatus === AppealStatusEnum.NotReceived)\n-              ) {\n-                enqueueSnackbar(\n-                  t(\n-                    'Unable to move contact here as this gift is already processed.',\n-                  ),\n-                  {\n-                    variant: 'warning',\n-                  },\n-                );\n-              } else {\n-                enqueueSnackbar(\n-                  t(\n-                    'Unable to move contact to Committed as part of the pledge has been Received.',\n-                  ),\n-                  {\n-                    variant: 'warning',\n-                  },\n-                );\n-              }\n+              handleReceivedSnackBarNotifications({\n+                dbStatus: newStatus,\n+                selectedAppealStatus: newAppealStatus,\n+                t,\n+                enqueueSnackbar,\n+              });\n             },\n@@ -277,2 +252,3 @@ export const ContactFlow: React.FC<ContactFlowProps> = ({\n           pledge={contact.pledge}\n+          selectedAppealStatus={selectedAppealStatus}\n           handleClose={() => setPledgeModalOpen(false)}\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Katelyn Grimes","training-data":{"loc-added":"6","loc-deleted":"47","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"2.214","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"katelyn.grimes@cru.org","commit-full-message":"","commit-date":"2025-07-07T18:07:18Z","current-rev":"752983e07","filename":"mpdx-react/src/components/Contacts/MassActions/AddToAppeal/MassActionsAddToAppealModal.tsx","previous-rev":"5e9623b38","commit-title":"Combined appeal autocompletes into a shared component","language":"React","id":"63eb6ef0a32d566f136c346702dc5d4ff42a4b18","model-score":0.44,"author-id":null,"project-id":53436,"delta-file-score":0.67582667,"diff":"diff --git a/src/components/Contacts/MassActions/AddToAppeal/MassActionsAddToAppealModal.tsx b/src/components/Contacts/MassActions/AddToAppeal/MassActionsAddToAppealModal.tsx\nindex 70d596bcf..4d03b262c 100644\n--- a/src/components/Contacts/MassActions/AddToAppeal/MassActionsAddToAppealModal.tsx\n+++ b/src/components/Contacts/MassActions/AddToAppeal/MassActionsAddToAppealModal.tsx\n@@ -2,3 +2,2 @@ import React, { ReactElement } from 'react';\n import {\n-  Autocomplete,\n   CircularProgress,\n@@ -7,3 +6,2 @@ import {\n   FormControl,\n-  TextField,\n } from '@mui/material';\n@@ -14,2 +12,3 @@ import * as yup from 'yup';\n import { ContactsDocument } from 'pages/accountLists/[accountListId]/contacts/Contacts.generated';\n+import { AppealAutocomplete } from 'src/common/Autocompletes/AppealAutocomplete';\n import {\n@@ -18,3 +17,2 @@ import {\n } from 'src/components/common/Modal/ActionButtons/ActionButtons';\n-import { useFetchAllPages } from 'src/hooks/useFetchAllPages';\n import Modal from '../../../common/Modal/Modal';\n@@ -67,7 +65,3 @@ export const MassActionsAddToAppealModal: React.FC<\n \n-  const {\n-    data: appeals,\n-    error,\n-    fetchMore,\n-  } = useGetAppealsForMassActionQuery({\n+  const { data: appeals } = useGetAppealsForMassActionQuery({\n     variables: {\n@@ -76,7 +70,2 @@ export const MassActionsAddToAppealModal: React.FC<\n   });\n-  const { loading: loadingAppeals } = useFetchAllPages({\n-    fetchMore,\n-    error,\n-    pageInfo: appeals?.appeals.pageInfo,\n-  });\n \n@@ -105,18 +94,5 @@ export const MassActionsAddToAppealModal: React.FC<\n               <FormControl fullWidth>\n-                <Autocomplete\n+                <AppealAutocomplete\n                   id=\"appeal\"\n                   value={appeal}\n-                  autoSelect\n-                  autoHighlight\n-                  options={\n-                    (appeals?.appeals.nodes &&\n-                      appeals?.appeals.nodes.map((appeal) => appeal.id)) ||\n-                    []\n-                  }\n-                  getOptionLabel={(appealId): string => {\n-                    const currentAppeal = appeals?.appeals?.nodes.find(\n-                      (appeal) => appeal.id === appealId,\n-                    )?.name;\n-                    return currentAppeal ?? '';\n-                  }}\n                   onChange={(_, appealId): void =>\n@@ -124,23 +100,6 @@ export const MassActionsAddToAppealModal: React.FC<\n                   }\n-                  isOptionEqualToValue={(option, value): boolean =>\n-                    option === value\n-                  }\n-                  renderInput={(params): ReactElement => (\n-                    <TextField\n-                      {...params}\n-                      label={t('Appeal')}\n-                      data-testid=\"appealTextInput\"\n-                      InputProps={{\n-                        ...params.InputProps,\n-                        endAdornment: (\n-                          <>\n-                            {loadingAppeals && (\n-                              <CircularProgress color=\"primary\" size={20} />\n-                            )}\n-                            {params.InputProps.endAdornment}\n-                          </>\n-                        ),\n-                      }}\n-                    />\n-                  )}\n+                  accountListId={accountListId}\n+                  TextFieldProps={{\n+                    label: t('Appeal'),\n+                  }}\n                 />\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Will James","training-data":{"loc-added":"42","loc-deleted":"7","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"1.35","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"william.james@cru.org","commit-full-message":"* Create \"Simple\"/\"Default\" version of the PDS Goal Calculator","commit-date":"2026-05-12T19:40:00Z","current-rev":"9e1a327a9","filename":"mpdx-react/src/components/HrTools/PdsGoalCalculator/GoalsList/PdsGoalsList.tsx","previous-rev":"ab6e4572a","commit-title":"[MPDX-9475] - Add Default and Simple view to PDS Goal Calculator (#1765)","language":"React","id":"938fac7a4d8fc5523a0700b41822bd6fe16fe37e","model-score":0.44,"author-id":null,"project-id":53436,"delta-file-score":0.41834745,"diff":"diff --git a/src/components/HrTools/PdsGoalCalculator/GoalsList/PdsGoalsList.tsx b/src/components/HrTools/PdsGoalCalculator/GoalsList/PdsGoalsList.tsx\nindex 32b908c74..ccab9c1c4 100644\n--- a/src/components/HrTools/PdsGoalCalculator/GoalsList/PdsGoalsList.tsx\n+++ b/src/components/HrTools/PdsGoalCalculator/GoalsList/PdsGoalsList.tsx\n@@ -1,6 +1,8 @@\n import { useRouter } from 'next/router';\n-import React from 'react';\n+import React, { useState } from 'react';\n import { Box, Button, CircularProgress, Stack, styled } from '@mui/material';\n+import { useSnackbar } from 'notistack';\n import { useTranslation } from 'react-i18next';\n import { useGetUserQuery } from 'src/components/User/GetUser.generated';\n+import { DesignationSupportFormType } from 'src/graphql/types.generated';\n import { useAccountListId } from 'src/hooks/useAccountListId';\n@@ -10,2 +12,3 @@ import illustration6graybg from 'src/images/drawkit/grape/drawkit-grape-pack-ill\n import { PdsGoalCard } from '../GoalCard/PdsGoalCard';\n+import { CreateGoalDialog } from './CreateGoalDialog';\n import {\n@@ -28,2 +31,3 @@ export const PdsGoalsList: React.FC = () => {\n   const router = useRouter();\n+  const { enqueueSnackbar } = useSnackbar();\n   const accountListId = useAccountListId() ?? '';\n@@ -44,5 +48,30 @@ export const PdsGoalsList: React.FC = () => {\n \n+  const [dialogOpen, setDialogOpen] = useState(false);\n+\n   const goals = data?.designationSupportCalculations.nodes;\n \n-  const handleCreateGoal = async () => {\n+  const handleCreateGoal = async (formType: DesignationSupportFormType) => {\n+    const isDetailed = formType === DesignationSupportFormType.Detailed;\n+    let detailedDefaults: {\n+      ministryCellPhone: number;\n+      ministryInternet: number;\n+    } | null = null;\n+    if (isDetailed) {\n+      const reimbursements = goalMiscConstants.REIMBURSEMENTS_WITH_MAXIMUM;\n+      const phoneFee = reimbursements?.PHONE?.fee;\n+      const internetFee = reimbursements?.INTERNET?.fee;\n+      if (phoneFee === undefined || internetFee === undefined) {\n+        enqueueSnackbar(\n+          t(\n+            'Could not load required defaults. Please try again or pick Simple.',\n+          ),\n+          { variant: 'error' },\n+        );\n+        return;\n+      }\n+      detailedDefaults = {\n+        ministryCellPhone: phoneFee,\n+        ministryInternet: internetFee,\n+      };\n+    }\n     const { data } = await createPdsGoalCalculation({\n@@ -50,8 +79,7 @@ export const PdsGoalsList: React.FC = () => {\n         attributes: {\n-          ministryCellPhone:\n-            goalMiscConstants.REIMBURSEMENTS_WITH_MAXIMUM?.PHONE?.fee,\n-          ministryInternet:\n-            goalMiscConstants.REIMBURSEMENTS_WITH_MAXIMUM?.INTERNET?.fee,\n+          formType,\n+          ...(detailedDefaults ?? {}),\n         },\n       },\n+      refetchQueries: ['PdsGoalCalculations'],\n     });\n@@ -61,2 +89,3 @@ export const PdsGoalsList: React.FC = () => {\n     if (calculation) {\n+      setDialogOpen(false);\n       router.push(\n@@ -73,3 +102,3 @@ export const PdsGoalsList: React.FC = () => {\n           variant=\"contained\"\n-          onClick={handleCreateGoal}\n+          onClick={() => setDialogOpen(true)}\n           disabled={constantsLoading}\n@@ -80,2 +109,8 @@ export const PdsGoalsList: React.FC = () => {\n \n+      <CreateGoalDialog\n+        open={dialogOpen}\n+        onClose={() => setDialogOpen(false)}\n+        onCreate={handleCreateGoal}\n+      />\n+\n       {loading ? (\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Will James","training-data":{"loc-added":"6","loc-deleted":"58","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"1.0","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"william.james@cru.org","commit-full-message":"* PDS Calc Summary Report","commit-date":"2026-05-01T17:40:25Z","current-rev":"5a123162c","filename":"mpdx-react/src/components/HrTools/PdsGoalCalculator/SupportItem/OtherSection.tsx","previous-rev":"edfa70868","commit-title":"[MPDX-9450] - PDS Calc Summary Report (#1753)","language":"React","id":"d710b962e1649b58a2b06e1410af4911bfbff6cc","model-score":0.42,"author-id":null,"project-id":53436,"delta-file-score":1.044829,"diff":"diff --git a/src/components/HrTools/PdsGoalCalculator/SupportItem/OtherSection.tsx b/src/components/HrTools/PdsGoalCalculator/SupportItem/OtherSection.tsx\nindex 1f44f34b2..b7bb8663a 100644\n--- a/src/components/HrTools/PdsGoalCalculator/SupportItem/OtherSection.tsx\n+++ b/src/components/HrTools/PdsGoalCalculator/SupportItem/OtherSection.tsx\n@@ -3,3 +3,2 @@ import { Divider, Typography } from '@mui/material';\n import { useTranslation } from 'react-i18next';\n-import { useGoalCalculatorConstants } from 'src/hooks/useGoalCalculatorConstants';\n import { useLocale } from 'src/hooks/useLocale';\n@@ -7,5 +6,2 @@ import { useDataGridLocaleText } from 'src/hooks/useMuiLocaleText';\n import { usePdsGoalCalculator } from '../Shared/PdsGoalCalculatorContext';\n-import { OtherExpensesConstants } from '../calculations/OtherExpenses';\n-import { calculateReimbursableTotals } from '../calculations/reimbursableExpenses';\n-import { calculateSalaryTotals } from '../calculations/salaryCalculation';\n import {\n@@ -20,22 +16,6 @@ export const OtherSection: React.FC = () => {\n   const localeText = useDataGridLocaleText();\n-  const { calculation, hcmUser } = usePdsGoalCalculator();\n-  const { goalMiscConstants, goalGeographicConstantMap } =\n-    useGoalCalculatorConstants();\n-\n-  const additionalRates = goalMiscConstants.ADDITIONAL_RATES;\n-  const employerFicaRate = additionalRates?.EMPLOYER_FICA_RATE?.fee;\n-  const workCompPercentage = additionalRates?.PART_TIME_WORK_COMPENSATION?.fee;\n-  const attritionRate = goalMiscConstants.RATES?.ATTRITION_RATE?.fee;\n-  const creditCardFeeRate = additionalRates?.CREDIT_CARD_FEE_RATE?.fee;\n-  const adminRate = goalMiscConstants.RATES?.ADMIN_RATE?.fee;\n+  const { calculation, summaryData } = usePdsGoalCalculator();\n \n   const rows = useMemo(() => {\n-    if (\n-      !calculation ||\n-      employerFicaRate === undefined ||\n-      workCompPercentage === undefined ||\n-      attritionRate === undefined ||\n-      creditCardFeeRate === undefined ||\n-      adminRate === undefined\n-    ) {\n+    if (!calculation || !summaryData) {\n       return [];\n@@ -43,41 +23,9 @@ export const OtherSection: React.FC = () => {\n \n-    const geographicMultiplier =\n-      goalGeographicConstantMap.get(calculation.geographicLocation ?? '') ?? 0;\n-\n-    const salaryTotals = calculateSalaryTotals(calculation, {\n-      geographicMultiplier,\n-      employerFicaRate,\n-    });\n-    const reimbursableTotals = calculateReimbursableTotals(calculation);\n-\n-    const taxDeferredPct =\n-      (hcmUser?.fourOThreeB?.currentTaxDeferredContributionPercentage ?? 0) /\n-      100;\n-    const rothPct =\n-      (hcmUser?.fourOThreeB?.currentRothContributionPercentage ?? 0) / 100;\n-\n-    const constants: OtherExpensesConstants = {\n-      reimbursableTotal: reimbursableTotals.total,\n-      salarySubtotal: salaryTotals.subtotal,\n-      fourOThreeBPercentage: taxDeferredPct + rothPct,\n-      grossMonthlyPay: salaryTotals.grossMonthlyPay,\n-      workCompPercentage,\n-      attritionRate,\n-      creditCardFeeRate,\n-      adminRate,\n-    };\n-\n-    return buildOtherBreakdownRows(calculation, constants, locale, t);\n-  }, [\n-    calculation,\n-    hcmUser,\n-    employerFicaRate,\n-    workCompPercentage,\n-    attritionRate,\n-    creditCardFeeRate,\n-    adminRate,\n-    goalGeographicConstantMap,\n-    locale,\n-    t,\n-  ]);\n+    return buildOtherBreakdownRows(\n+      calculation,\n+      summaryData.otherConstants,\n+      locale,\n+      t,\n+    );\n+  }, [calculation, summaryData, locale, t]);\n \n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Katelyn Grimes","training-data":{"loc-added":"39","loc-deleted":"80","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"2.628","delta-n-functions":"0","current-file-score":"9.40379462694782"},"author-email":"katelyn.grimes@cru.org","commit-full-message":"","commit-date":"2025-08-14T18:36:54Z","current-rev":"df8a86fe4","filename":"mpdx-react/src/components/Reports/MPGAIncomeExpensesReport/MPGAIncomeExpensesReport.tsx","previous-rev":"a0f7d4e19","commit-title":"Review changes based on suggestions","language":"React","id":"8c1286de7c828b8ddbab5d7b790c1714f573f9e7","model-score":0.18,"author-id":null,"project-id":53436,"delta-file-score":0.20024464,"diff":"diff --git a/src/components/Reports/MPGAIncomeExpensesReport/MPGAIncomeExpensesReport.tsx b/src/components/Reports/MPGAIncomeExpensesReport/MPGAIncomeExpensesReport.tsx\nindex 1787c3ba2..403927576 100644\n--- a/src/components/Reports/MPGAIncomeExpensesReport/MPGAIncomeExpensesReport.tsx\n+++ b/src/components/Reports/MPGAIncomeExpensesReport/MPGAIncomeExpensesReport.tsx\n@@ -14,13 +14,15 @@ import {\n } from 'src/components/Shared/MultiPageLayout/MultiPageHeader';\n-import { PrintOnlyReport } from './DisplayModes/PrintOnlyReport';\n-import { ScreenOnlyReport } from './DisplayModes/ScreenOnlyReport';\n-import { getLast12Months } from './Helper/getLastTwelveMonths';\n-import { mockData } from './mockData';\n+import { useGetLastTwelveMonths } from 'src/hooks/useGetLastTwelveMonths';\n+import { useLocale } from 'src/hooks/useLocale';\n+import { useReportsStaffExpensesQuery } from '../ReportsStaffExpenses.generated';\n import {\n-  PrintOnly,\n-  ScreenOnly,\n   SimplePrintOnly,\n-  StyledHeaderBox,\n+  SimpleScreenOnly,\n   StyledPrintButton,\n-} from './styledComponents';\n+} from '../styledComponents';\n+import { PrintOnlyReport } from './DisplayModes/PrintOnlyReport';\n+import { ScreenOnlyReport } from './DisplayModes/ScreenOnlyReport';\n+import { TotalsProvider } from './TotalsContext/TotalsContext';\n+import { mockData } from './mockData';\n+import { PrintOnly, StyledHeaderBox } from './styledComponents';\n \n@@ -35,4 +37,9 @@ export const MPGAIncomeExpensesReport: React.FC<\n   MPGAIncomeExpensesReportProps\n-> = ({ title, isNavListOpen, onNavListToggle }) => {\n+> = ({ accountListId, title, isNavListOpen, onNavListToggle }) => {\n   const { t } = useTranslation();\n+  const locale = useLocale();\n+\n+  const { data: staffExpensesData } = useReportsStaffExpensesQuery({\n+    variables: { accountListId: accountListId },\n+  });\n \n@@ -42,45 +49,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n \n-  const last12Months = useMemo(() => getLast12Months(), []);\n-\n-  const incomeTotal = useMemo(\n-    () => mockData.income?.data.reduce((sum, data) => sum + data.total, 0),\n-    [mockData.income?.data],\n-  );\n-\n-  const ministryTotal = useMemo(\n-    () =>\n-      mockData.ministryExpenses?.data.reduce(\n-        (sum, data) => sum + data.total,\n-        0,\n-      ),\n-    [mockData.ministryExpenses?.data],\n-  );\n-\n-  const healthcareTotal = useMemo(\n-    () =>\n-      mockData.healthcareExpenses?.data.reduce(\n-        (sum, data) => sum + data.total,\n-        0,\n-      ),\n-    [mockData.healthcareExpenses?.data],\n-  );\n-\n-  const miscTotal = useMemo(\n-    () => mockData.misc?.data.reduce((sum, data) => sum + data.total, 0),\n-    [mockData.misc?.data],\n-  );\n-\n-  const otherTotal = useMemo(\n-    () => mockData.other?.data.reduce((sum, data) => sum + data.total, 0),\n-    [mockData.other?.data],\n-  );\n-\n-  const expensesTotal = useMemo(\n-    () =>\n-      (ministryTotal ?? 0) +\n-      (healthcareTotal ?? 0) +\n-      (miscTotal ?? 0) +\n-      (otherTotal ?? 0),\n-    [ministryTotal, healthcareTotal, miscTotal, otherTotal],\n-  );\n+  const last12Months = useGetLastTwelveMonths(locale, true);\n \n@@ -88,12 +53,12 @@ export const MPGAIncomeExpensesReport: React.FC<\n     () => [\n-      ...(mockData.ministryExpenses?.data ?? []),\n-      ...(mockData.healthcareExpenses?.data ?? []),\n-      ...(mockData.misc?.data ?? []),\n-      ...(mockData.other?.data ?? []),\n+      ...(mockData.ministryExpenses ?? []),\n+      ...(mockData.healthcareExpenses ?? []),\n+      ...(mockData.misc ?? []),\n+      ...(mockData.other ?? []),\n     ],\n     [\n-      mockData.ministryExpenses?.data,\n-      mockData.healthcareExpenses?.data,\n-      mockData.misc?.data,\n-      mockData.other?.data,\n+      mockData.ministryExpenses,\n+      mockData.healthcareExpenses,\n+      mockData.misc,\n+      mockData.other,\n     ],\n@@ -119,3 +84,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n       <Box>\n-        <ScreenOnly>\n+        <SimpleScreenOnly>\n           <MultiPageHeader\n@@ -126,3 +91,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n           />\n-        </ScreenOnly>\n+        </SimpleScreenOnly>\n         <Box mt={2}>\n@@ -130,3 +95,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n             <StyledHeaderBox>\n-              <ScreenOnly>\n+              <SimpleScreenOnly>\n                 <Typography variant=\"h4\">\n@@ -134,3 +99,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n                 </Typography>\n-              </ScreenOnly>\n+              </SimpleScreenOnly>\n               <SimplePrintOnly>\n@@ -140,3 +105,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n               </SimplePrintOnly>\n-              <ScreenOnly>\n+              <SimpleScreenOnly>\n                 <StyledPrintButton\n@@ -151,3 +116,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n                 </StyledPrintButton>\n-              </ScreenOnly>\n+              </SimpleScreenOnly>\n             </StyledHeaderBox>\n@@ -159,27 +124,21 @@ export const MPGAIncomeExpensesReport: React.FC<\n         </Box>\n-        <ScreenOnly>\n-          <ScreenOnlyReport\n-            data={mockData}\n-            incomeTotal={incomeTotal}\n-            expensesTotal={expensesTotal}\n-            ministryTotal={ministryTotal}\n-            healthcareTotal={healthcareTotal}\n-            miscTotal={miscTotal}\n-            otherTotal={otherTotal}\n-            last12Months={last12Months}\n-            expenseData={expenseData}\n-          />\n-        </ScreenOnly>\n+        <SimpleScreenOnly>\n+          <TotalsProvider data={mockData}>\n+            <ScreenOnlyReport\n+              data={mockData}\n+              last12Months={last12Months}\n+              expenseData={expenseData}\n+              currency={staffExpensesData?.accountList.currency || 'USD'}\n+            />\n+          </TotalsProvider>\n+        </SimpleScreenOnly>\n         <PrintOnly>\n-          <PrintOnlyReport\n-            data={mockData}\n-            incomeTotal={incomeTotal}\n-            expensesTotal={expensesTotal}\n-            ministryTotal={ministryTotal}\n-            healthcareTotal={healthcareTotal}\n-            miscTotal={miscTotal}\n-            otherTotal={otherTotal}\n-            last12Months={last12Months}\n-            expenseData={expenseData}\n-          />\n+          <TotalsProvider data={mockData}>\n+            <PrintOnlyReport\n+              data={mockData}\n+              last12Months={last12Months}\n+              expenseData={expenseData}\n+              currency={staffExpensesData?.accountList.currency || 'USD'}\n+            />\n+          </TotalsProvider>\n         </PrintOnly>\n","improvement-type":"Complex Method"}],"change-level":"warning","is-hotspot?":false,"line":42,"what-changed":"HealthIndicatorWidget:React.FC<HealthIndicatorWidgetProps> has a cyclomatic complexity of 14, threshold = 10","how-to-fix":"There are many reasons for Complex Method. Sometimes, another design approach is beneficial such as a) modeling state using an explicit state machine rather than conditionals, or b) using table lookup rather than long chains of logic. In other scenarios, the function can be split using [EXTRACT FUNCTION](https://refactoring.com/catalog/extractFunction.html). Just make sure you extract natural and cohesive functions. Complex Methods can also be addressed by identifying complex conditional expressions and then using the [DECOMPOSE CONDITIONAL](https://refactoring.com/catalog/decomposeConditional.html) refactoring.","change-type":"introduced"},{"method":"MonthlyGoal","why-it-occurs":"A Complex Method has a high cyclomatic complexity. The recommended threshold for the React language is a cyclomatic complexity lower than 10.","name":"Complex Method","file":"src/components/Dashboard/MonthlyGoal/MonthlyGoal.tsx","refactoring-examples":[{"architectural-component-id":null,"author-name":"Caleb Cox","training-data":{"loc-added":"3","loc-deleted":"3","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"1.35","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"canac@users.noreply.github.com","commit-full-message":"","commit-date":"2025-08-22T20:09:43Z","current-rev":"ca8f2ca29","filename":"mpdx-react/src/components/Helpjuice/Helpjuice.tsx","previous-rev":"04561eb59","commit-title":"Use CSS selector","language":"React","id":"6c93798585f2bb2ec87d5c50d0b52d7b6449a168","model-score":0.96,"author-id":null,"project-id":53436,"delta-file-score":0.568307,"diff":"diff --git a/src/components/Helpjuice/Helpjuice.tsx b/src/components/Helpjuice/Helpjuice.tsx\nindex a7b200c1a..a54cbb05a 100644\n--- a/src/components/Helpjuice/Helpjuice.tsx\n+++ b/src/components/Helpjuice/Helpjuice.tsx\n@@ -63,7 +63,7 @@ export const Helpjuice: React.FC = () => {\n       // We need to turn them into absolute URLs so that they open correctly\n-      for (const link of document.querySelectorAll('#article-content-body a')) {\n+      for (const link of document.querySelectorAll(\n+        '#article-content-body a[href^=\"/\"]',\n+      )) {\n         const href = link.getAttribute('href');\n-        if (href?.startsWith('/')) {\n-          link.setAttribute('href', `${helpJuiceOrigin}${href}`);\n-        }\n+        link.setAttribute('href', `${helpJuiceOrigin}${href}`);\n       }\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Daniel Bisgrove","training-data":{"loc-added":"3","loc-deleted":"1","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"5.382","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"daniel@bizz-websites.com","commit-full-message":"","commit-date":"2024-10-17T14:59:21Z","current-rev":"b4989f844","filename":"mpdx-react/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.tsx","previous-rev":"5894a893f","commit-title":"fixup! Fix routing issue after switching account","language":"React","id":"584c52e9e432999ea473cfb396e1aa9c502822cd","model-score":0.75,"author-id":null,"project-id":53436,"delta-file-score":1.555564,"diff":"diff --git a/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.tsx b/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.tsx\nindex a1e149d28..1f91bda3c 100644\n--- a/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.tsx\n+++ b/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.tsx\n@@ -197,3 +197,5 @@ const ProfileMenu = (): ReactElement => {\n       router.pathname ===\n-      '/accountLists/[accountListId]/reports/financialAccounts/[[...financialAccount]]'\n+        '/accountLists/[accountListId]/reports/financialAccounts/[financialAccountId]/entries' ||\n+      router.pathname ===\n+        '/accountLists/[accountListId]/reports/financialAccounts/[financialAccountId]'\n     ) {\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Daniel Bisgrove","training-data":{"loc-added":"11","loc-deleted":"4","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"6.318","delta-n-functions":"0","current-file-score":"9.842730062691357"},"author-email":"daniel@bizz-websites.com","commit-full-message":"","commit-date":"2024-06-12T15:32:50Z","current-rev":"e6289830e","filename":"mpdx-react/src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/EditContactAddressModal.tsx","previous-rev":"a9d552f51","commit-title":"Adding the ability to allow custom cache updates after mutation.","language":"React","id":"f22174b78d624b68491e49f4f04f0b1e4aec4edb","model-score":0.7,"author-id":null,"project-id":53436,"delta-file-score":1.6399608,"diff":"diff --git a/src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/EditContactAddressModal.tsx b/src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/EditContactAddressModal.tsx\nindex 9b6af14a0..8f9925d99 100644\n--- a/src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/EditContactAddressModal.tsx\n+++ b/src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/EditContactAddressModal.tsx\n@@ -1,2 +1,3 @@\n import React, { ReactElement } from 'react';\n+import { ApolloCache } from '@apollo/client';\n import {\n@@ -70,3 +71,3 @@ interface EditContactAddressModalProps {\n   contactId: string;\n-  handleClose: (deletedAddress: boolean) => void;\n+  handleUpdateCacheOnDelete?: (cache: ApolloCache<unknown>, object) => void;\n }\n@@ -80,2 +81,3 @@ export const EditContactAddressModal: React.FC<\n   handleClose,\n+  handleUpdateCacheOnDelete,\n }): ReactElement<EditContactAddressModalProps> => {\n@@ -127,4 +129,7 @@ export const EditContactAddressModal: React.FC<\n         },\n-        update: (cache, { data: deletedContactAddress }) => {\n-          const deletedAddressId = deletedContactAddress?.deleteAddress?.id;\n+        update: (cache) => {\n+          const deletedAddressId = address.id;\n+          if (handleUpdateCacheOnDelete) {\n+            handleUpdateCacheOnDelete(cache, { deletedAddressId });\n+          } else {\n           const query = {\n@@ -137,3 +142,4 @@ export const EditContactAddressModal: React.FC<\n \n-          const dataFromCache = cache.readQuery<ContactDetailsTabQuery>(query);\n+            const dataFromCache =\n+              cache.readQuery<ContactDetailsTabQuery>(query);\n \n@@ -153,2 +159,3 @@ export const EditContactAddressModal: React.FC<\n             cache.writeQuery({ ...query, data });\n+            }\n           }\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Bizz (Daniel Bisgrove)","training-data":{"loc-added":"27","loc-deleted":"2","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"6.048","delta-n-functions":"0","current-file-score":"9.842730062691357"},"author-email":"56281168+dr-bizz@users.noreply.github.com","commit-full-message":"* Add more warning messages when dragging contact to different columns.","commit-date":"2024-09-12T14:53:23Z","current-rev":"556abc41a","filename":"mpdx-react/src/components/Tool/Appeal/Modals/PledgeModal/PledgeModal.tsx","previous-rev":"3cde16b8e","commit-title":"MPDX-8187 + MPDX-8188 Add more warning messages when dragging contact to different columns. (#1056)","language":"React","id":"106116e788da85247f60c309cc55586685450747","model-score":0.7,"author-id":null,"project-id":53436,"delta-file-score":1.5710658,"diff":"diff --git a/src/components/Tool/Appeal/Modals/PledgeModal/PledgeModal.tsx b/src/components/Tool/Appeal/Modals/PledgeModal/PledgeModal.tsx\nindex a7217c8d6..3f655858e 100644\n--- a/src/components/Tool/Appeal/Modals/PledgeModal/PledgeModal.tsx\n+++ b/src/components/Tool/Appeal/Modals/PledgeModal/PledgeModal.tsx\n@@ -35,2 +35,3 @@ import i18n from 'src/lib/i18n';\n import {\n+  AppealStatusEnum,\n   AppealsContext,\n@@ -39,2 +40,3 @@ import {\n import { AppealContactInfoFragment } from '../../AppealsContext/contacts.generated';\n+import handleReceivedSnackBarNotifications from '../../Shared/handleReceivedSnackBarNotifications/handleReceivedSnackBarNotifications';\n import {\n@@ -51,2 +53,3 @@ interface PledgeModalProps {\n   pledge?: AppealContactInfoFragment['pledges'][0];\n+  selectedAppealStatus?: AppealStatusEnum | null;\n }\n@@ -79,2 +82,3 @@ export const PledgeModal: React.FC<PledgeModalProps> = ({\n   handleClose,\n+  selectedAppealStatus,\n }) => {\n@@ -116,3 +120,13 @@ export const PledgeModal: React.FC<PledgeModalProps> = ({\n         refetchQueries: ['Contacts', 'Appeal'],\n-        onCompleted: () => {\n+        onCompleted: ({ createAccountListPledge }) => {\n+          const newStatus = createAccountListPledge?.pledge.status;\n+          if (selectedAppealStatus) {\n+            handleReceivedSnackBarNotifications({\n+              dbStatus: newStatus,\n+              selectedAppealStatus,\n+              t,\n+              enqueueSnackbar,\n+            });\n+          }\n+\n           enqueueSnackbar(t('Successfully added commitment to appeal'), {\n@@ -145,3 +159,14 @@ export const PledgeModal: React.FC<PledgeModalProps> = ({\n         refetchQueries: ['Contacts', 'Appeal'],\n-        onCompleted: () => {\n+        onCompleted: ({ updateAccountListPledge }) => {\n+          const newStatus = updateAccountListPledge?.pledge.status;\n+\n+          if (selectedAppealStatus) {\n+            handleReceivedSnackBarNotifications({\n+              dbStatus: newStatus,\n+              selectedAppealStatus,\n+              t,\n+              enqueueSnackbar,\n+            });\n+          }\n+\n           enqueueSnackbar(t('Successfully edited commitment'), {\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Caleb Cox","training-data":{"loc-added":"28","loc-deleted":"12","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"3.294","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"canac@users.noreply.github.com","commit-full-message":"","commit-date":"2024-09-11T20:30:58Z","current-rev":"5e0f11d70","filename":"mpdx-react/src/components/Tool/Appeal/Modals/UpdateDonationsModal/DonationTable/DonationTable.tsx","previous-rev":"3cde16b8e","commit-title":"Cross out donations that will be removed from the appeal","language":"React","id":"2b776d0649fadc98ac0439811d1bba93e1303c17","model-score":0.59,"author-id":null,"project-id":53436,"delta-file-score":0.98683935,"diff":"diff --git a/src/components/Tool/Appeal/Modals/UpdateDonationsModal/DonationTable/DonationTable.tsx b/src/components/Tool/Appeal/Modals/UpdateDonationsModal/DonationTable/DonationTable.tsx\nindex dd4312d05..ce79ea35e 100644\n--- a/src/components/Tool/Appeal/Modals/UpdateDonationsModal/DonationTable/DonationTable.tsx\n+++ b/src/components/Tool/Appeal/Modals/UpdateDonationsModal/DonationTable/DonationTable.tsx\n@@ -87,2 +87,9 @@ export const DonationTable: React.FC<DonationTableProps> = ({\n   const { data, error, loading, fetchMore } = donationTableQueryResult;\n+  const preselectedDonations = useMemo(\n+    () =>\n+      data?.donations.nodes\n+        .filter((donation) => donation.appeal?.id === appealId)\n+        .map(createDonationRow) ?? [],\n+    [data],\n+  );\n \n@@ -96,12 +103,6 @@ export const DonationTable: React.FC<DonationTableProps> = ({\n   useEffect(() => {\n-    if (!data?.donations.nodes.length) {\n-      return;\n+    if (preselectedDonations?.length) {\n+      setSelectedDonations(preselectedDonations);\n     }\n-\n-    const preselectedDonations = data.donations.nodes\n-      .filter((donation) => donation.appeal?.id === appealId)\n-      .map(createDonationRow);\n-\n-    setSelectedDonations(preselectedDonations);\n-  }, [data]);\n+  }, [preselectedDonations]);\n \n@@ -111,2 +112,7 @@ export const DonationTable: React.FC<DonationTableProps> = ({\n \n+  const isPreselectedDonation = (donation: DonationRow) =>\n+    preselectedDonations.some((donationRow) => donationRow.id === donation.id);\n+  const isDonationChecked = (donation: DonationRow) =>\n+    selectedDonations.some((donationRow) => donationRow.id === donation.id);\n+\n   const date: RenderCell = ({ row }) => dateFormatShort(row.date, locale);\n@@ -125,3 +131,14 @@ export const DonationTable: React.FC<DonationTableProps> = ({\n \n-  const appeal: RenderCell = ({ row: donation }) => donation.appealName;\n+  const appeal: RenderCell = ({ row: donation }) => (\n+    <span\n+      style={{\n+        textDecoration:\n+          isPreselectedDonation(donation) && !isDonationChecked(donation)\n+            ? 'line-through'\n+            : undefined,\n+      }}\n+    >\n+      {donation.appealName}\n+    </span>\n+  );\n \n@@ -144,4 +161,3 @@ export const DonationTable: React.FC<DonationTableProps> = ({\n   };\n-  const isDonationChecked = (donation: DonationRow) =>\n-    selectedDonations.some((donationRow) => donationRow.id === donation.id);\n+\n   const select: RenderCell = ({ row: donation }) => (\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Daniel Bisgrove","training-data":{"loc-added":"67","loc-deleted":"0","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"3.816","delta-n-functions":"0","current-file-score":"9.842730062691357"},"author-email":"daniel@bizz-websites.com","commit-full-message":"","commit-date":"2024-06-25T14:55:28Z","current-rev":"945772dc6","filename":"mpdx-react/src/components/Tool/FixMailingAddresses/FixMailingAddresses.tsx","previous-rev":"eb907de17","commit-title":"Confirm single contact's addresses","language":"React","id":"f789b68cc8d82a89d390a756ba271bb953316cf5","model-score":0.55,"author-id":null,"project-id":53436,"delta-file-score":0.97569954,"diff":"diff --git a/src/components/Tool/FixMailingAddresses/FixMailingAddresses.tsx b/src/components/Tool/FixMailingAddresses/FixMailingAddresses.tsx\nindex 086bc13ea..4dbb7857d 100644\n--- a/src/components/Tool/FixMailingAddresses/FixMailingAddresses.tsx\n+++ b/src/components/Tool/FixMailingAddresses/FixMailingAddresses.tsx\n@@ -15,2 +15,3 @@ import {\n } from '@mui/material';\n+import { useSnackbar } from 'notistack';\n import { Trans, useTranslation } from 'react-i18next';\n@@ -28,4 +29,12 @@ import {\n   useInvalidAddressesQuery,\n+  useUpdateContactAddressMutation,\n } from './GetInvalidAddresses.generated';\n \n+export type HandleSingleConfirmProps = {\n+  addresses: ContactAddressFragment[];\n+  id: string;\n+  name: string;\n+  onlyErrorOnce?: boolean;\n+};\n+\n const useStyles = makeStyles()(() => ({\n@@ -136,2 +145,59 @@ const FixSendNewsletter: React.FC<Props> = ({\n   });\n+  const [updateAddress] = useUpdateContactAddressMutation();\n+  const { enqueueSnackbar } = useSnackbar();\n+\n+  const handleSingleConfirm = async ({\n+    addresses,\n+    id,\n+    name,\n+    onlyErrorOnce = false,\n+  }: HandleSingleConfirmProps) => {\n+    const errors: string[] = [];\n+\n+    for (let idx = 0; idx < addresses.length; idx++) {\n+      const address = addresses[idx];\n+\n+      await updateAddress({\n+        variables: {\n+          accountListId,\n+          attributes: {\n+            id: address.id,\n+            validValues: true,\n+            // TODO: Fix the Graph QL Input\n+            // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n+            // @ts-ignore\n+            primaryMailingAddress: address.primaryMailingAddress,\n+          },\n+        },\n+        update(cache) {\n+          if (idx === addresses.length - 1 && !errors.length) {\n+            cache.evict({ id: `Contact:${id}` });\n+          }\n+        },\n+        onError(error) {\n+          errors.push(\n+            `${name} - ${t('Error while saving addresses.')} ${error.cause}`,\n+          );\n+        },\n+      });\n+    }\n+\n+    if (errors.length) {\n+      if (onlyErrorOnce) {\n+        enqueueSnackbar(t(`Error updating contact ${name}`), {\n+          variant: 'error',\n+          autoHideDuration: 7000,\n+        });\n+      } else {\n+        errors.forEach((error) => {\n+          enqueueSnackbar(error, { variant: 'error' });\n+        });\n+      }\n+      return { success: false };\n+    } else {\n+      enqueueSnackbar(t(`Updated contact ${name}`), { variant: 'success' });\n+      return { success: true };\n+    }\n+  };\n+\n \n@@ -305,2 +371,3 @@ const FixSendNewsletter: React.FC<Props> = ({\n                         setContactFocus={setContactFocus}\n+                        handleSingleConfirm={handleSingleConfirm}\n                       />\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Will James","training-data":{"loc-added":"13","loc-deleted":"22","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"4.734","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"william.james@cru.org","commit-full-message":"","commit-date":"2025-07-14T17:18:44Z","current-rev":"0bda3723a","filename":"mpdx-react/src/components/Settings/integrations/Organization/ConnectOrganization.tsx","previous-rev":"ae4398dda","commit-title":"Updates components to use OrganizationAutocomplete and new location of DonorAccountAutocomplete.","language":"React","id":"69d809f40ed2a58a216204dcb06d76f74bac23db","model-score":0.54,"author-id":null,"project-id":53436,"delta-file-score":1.3835225,"diff":"diff --git a/src/components/Settings/integrations/Organization/ConnectOrganization.tsx b/src/components/Settings/integrations/Organization/ConnectOrganization.tsx\nindex 2f47f930b..d5713c142 100644\n--- a/src/components/Settings/integrations/Organization/ConnectOrganization.tsx\n+++ b/src/components/Settings/integrations/Organization/ConnectOrganization.tsx\n@@ -9,3 +9,2 @@ import { useApolloClient } from '@apollo/client';\n import {\n-  Autocomplete,\n   Box,\n@@ -23,2 +22,4 @@ import { useTranslation } from 'react-i18next';\n import { FieldWrapper } from 'src/components/Shared/Forms/FieldWrapper';\n+import { OrganizationAutocomplete } from 'src/components/common/Autocomplete/OrganizationAutocomplete/OrganizationAutocomplete';\n+import { Organization } from 'src/graphql/types.generated';\n import useGetAppSettings from 'src/hooks/useGetAppSettings';\n@@ -175,32 +176,22 @@ export const ConnectOrganization: React.FC<ConnectOrganizationProps> = ({\n           <ContentContainer>\n-            <Autocomplete\n+            <OrganizationAutocomplete\n               disabled={isSubmitting}\n               autoHighlight\n+              fullWidth\n               loading={loading}\n               value={selectedOrganization}\n+              organizations={\n+                organizations?.organizations?.filter(\n+                  (organization) => !organization?.disableNewUsers,\n+                ) ?? []\n+              }\n               onChange={(_, value) => {\n+                const org = value as Organization;\n                 setOrganizationType(\n-                  getOrganizationType(value?.apiClass, value?.oauth),\n+                  getOrganizationType(org?.apiClass, org?.oauth),\n                 );\n-                setSelectedOrg(value?.name ?? '');\n+                setSelectedOrg(org?.name ?? '');\n                 setFieldValue('selectedOrganization', value);\n               }}\n-              options={\n-                organizations?.organizations?.filter(\n-                  (organization) => !organization?.disableNewUsers,\n-                ) || []\n-              }\n-              getOptionLabel={(option) =>\n-                organizations?.organizations?.find(\n-                  ({ id }) => String(id) === String(option.id),\n-                )?.name ?? ''\n-              }\n-              fullWidth\n-              renderInput={(params) => (\n-                <TextField\n-                  {...params}\n-                  label={t('Organization')}\n-                  inputRef={focusOnOrganization}\n-                />\n-              )}\n+              textFieldFocusRef={focusOnOrganization}\n             />\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Daniel Bisgrove","training-data":{"loc-added":"36","loc-deleted":"11","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"3.114","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"daniel@bizz-websites.com","commit-full-message":"","commit-date":"2024-09-09T14:15:22Z","current-rev":"c4ef64282","filename":"mpdx-react/src/components/Tool/Appeal/Flow/ContactFlowColumn/ContactFlowColumn.tsx","previous-rev":"d2f225d28","commit-title":"Adding select all and deselect all onto each column","language":"React","id":"71c7067d34e931c166b2b014f7cb1e52c43ff71e","model-score":0.48,"author-id":null,"project-id":53436,"delta-file-score":0.93582284,"diff":"diff --git a/src/components/Tool/Appeal/Flow/ContactFlowColumn/ContactFlowColumn.tsx b/src/components/Tool/Appeal/Flow/ContactFlowColumn/ContactFlowColumn.tsx\nindex 3c24bc0f8..14c0029d0 100644\n--- a/src/components/Tool/Appeal/Flow/ContactFlowColumn/ContactFlowColumn.tsx\n+++ b/src/components/Tool/Appeal/Flow/ContactFlowColumn/ContactFlowColumn.tsx\n@@ -1,2 +1,2 @@\n-import React, { useRef, useState } from 'react';\n+import React, { useMemo, useRef, useState } from 'react';\n import MoreVertIcon from '@mui/icons-material/MoreVert';\n@@ -30,2 +30,3 @@ import {\n } from 'src/components/Tool/Appeal/AppealsContext/AppealsContext';\n+import { useGetIdsForMassSelectionQuery } from 'src/hooks/GetIdsForMassSelection.generated';\n import { appealHeaderInfoHeight } from '../../AppealDetails/AppealHeaderInfo/AppealHeaderInfo';\n@@ -70,5 +71,9 @@ export const ContactFlowColumn: React.FC<Props> = ({\n }) => {\n-  const { appealId, sanitizedFilters, starredFilter } = React.useContext(\n-    AppealsContext,\n-  ) as AppealsType;\n+  const {\n+    appealId,\n+    sanitizedFilters,\n+    starredFilter,\n+    selectMultipleIds,\n+    deselectMultipleIds,\n+  } = React.useContext(AppealsContext) as AppealsType;\n   const { t } = useTranslation();\n@@ -79,2 +84,13 @@ export const ContactFlowColumn: React.FC<Props> = ({\n \n+  const contactsFilters = useMemo(\n+    () => ({\n+      ...sanitizedFilters,\n+      ...starredFilter,\n+      appeal: [appealId ?? ''],\n+      appealStatus,\n+      wildcardSearch: searchTerm as string,\n+    }),\n+    [sanitizedFilters, starredFilter, searchTerm, appealId],\n+  );\n+\n   const { data, loading, fetchMore } = useContactsQuery({\n@@ -82,9 +98,3 @@ export const ContactFlowColumn: React.FC<Props> = ({\n       accountListId: accountListId ?? '',\n-      contactsFilters: {\n-        ...sanitizedFilters,\n-        ...starredFilter,\n-        appeal: [appealId ?? ''],\n-        appealStatus,\n-        wildcardSearch: searchTerm as string,\n-      },\n+      contactsFilters,\n     },\n@@ -93,2 +103,17 @@ export const ContactFlowColumn: React.FC<Props> = ({\n \n+  const contactCount = data?.contacts.totalCount ?? 0;\n+  const { data: allContacts } = useGetIdsForMassSelectionQuery({\n+    variables: {\n+      accountListId,\n+      first: contactCount,\n+      contactsFilters,\n+    },\n+    skip: contactCount === 0,\n+  });\n+\n+  const allContactIds = useMemo(\n+    () => allContacts?.contacts.nodes.map((contact) => contact.id) ?? [],\n+    [allContacts],\n+  );\n+\n   const { data: excludedContacts } = useExcludedAppealContactsQuery({\n@@ -118,4 +143,4 @@ export const ContactFlowColumn: React.FC<Props> = ({\n   const handleSelectAll = () => {\n+    selectMultipleIds(allContactIds);\n     setAnchorEl(null);\n-    // TODO implement select all\n   };\n@@ -123,4 +148,4 @@ export const ContactFlowColumn: React.FC<Props> = ({\n   const handleDeselectAll = () => {\n+    deselectMultipleIds(allContactIds);\n     setAnchorEl(null);\n-    // TODO implement deselect all\n   };\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Bizz (Daniel Bisgrove)","training-data":{"loc-added":"11","loc-deleted":"35","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"1.89","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"56281168+dr-bizz@users.noreply.github.com","commit-full-message":"* Add more warning messages when dragging contact to different columns.","commit-date":"2024-09-12T14:53:23Z","current-rev":"556abc41a","filename":"mpdx-react/src/components/Tool/Appeal/Flow/ContactFlow.tsx","previous-rev":"3cde16b8e","commit-title":"MPDX-8187 + MPDX-8188 Add more warning messages when dragging contact to different columns. (#1056)","language":"React","id":"cc97c2e44cba84629f9011bdb93cbabefafca6ba","model-score":0.45,"author-id":null,"project-id":53436,"delta-file-score":1.0139161,"diff":"diff --git a/src/components/Tool/Appeal/Flow/ContactFlow.tsx b/src/components/Tool/Appeal/Flow/ContactFlow.tsx\nindex 0c0c95f5d..10319643a 100644\n--- a/src/components/Tool/Appeal/Flow/ContactFlow.tsx\n+++ b/src/components/Tool/Appeal/Flow/ContactFlow.tsx\n@@ -19,2 +19,3 @@ import { DynamicPledgeModal } from '../Modals/PledgeModal/DynamicPledgeModal';\n import { DynamicUpdateDonationsModal } from '../Modals/UpdateDonationsModal/DynamicUpdateDonationsModal';\n+import handleReceivedSnackBarNotifications from '../Shared/handleReceivedSnackBarNotifications/handleReceivedSnackBarNotifications';\n import { ContactFlowColumn } from './ContactFlowColumn/ContactFlowColumn';\n@@ -102,2 +103,4 @@ export const ContactFlow: React.FC<ContactFlowProps> = ({\n   const [contact, setContact] = useState<DraggedContact | null>(null);\n+  const [selectedAppealStatus, setSelectedAppealStatus] =\n+    useState<AppealStatusEnum | null>(null);\n \n@@ -126,2 +129,3 @@ export const ContactFlow: React.FC<ContactFlowProps> = ({\n     setContact(contact);\n+    setSelectedAppealStatus(newAppealStatus);\n \n@@ -168,37 +172,8 @@ export const ContactFlow: React.FC<ContactFlowProps> = ({\n \n-              if (\n-                newStatus === PledgeStatusEnum.NotReceived &&\n-                newAppealStatus === AppealStatusEnum.ReceivedNotProcessed\n-              ) {\n-                enqueueSnackbar(\n-                  t(\n-                    'Unable to move contact here as gift has not been received by Cru.',\n-                  ),\n-                  {\n-                    variant: 'warning',\n-                  },\n-                );\n-              } else if (\n-                newStatus === PledgeStatusEnum.Processed &&\n-                (newAppealStatus === AppealStatusEnum.ReceivedNotProcessed ||\n-                  newAppealStatus === AppealStatusEnum.NotReceived)\n-              ) {\n-                enqueueSnackbar(\n-                  t(\n-                    'Unable to move contact here as this gift is already processed.',\n-                  ),\n-                  {\n-                    variant: 'warning',\n-                  },\n-                );\n-              } else {\n-                enqueueSnackbar(\n-                  t(\n-                    'Unable to move contact to Committed as part of the pledge has been Received.',\n-                  ),\n-                  {\n-                    variant: 'warning',\n-                  },\n-                );\n-              }\n+              handleReceivedSnackBarNotifications({\n+                dbStatus: newStatus,\n+                selectedAppealStatus: newAppealStatus,\n+                t,\n+                enqueueSnackbar,\n+              });\n             },\n@@ -277,2 +252,3 @@ export const ContactFlow: React.FC<ContactFlowProps> = ({\n           pledge={contact.pledge}\n+          selectedAppealStatus={selectedAppealStatus}\n           handleClose={() => setPledgeModalOpen(false)}\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Katelyn Grimes","training-data":{"loc-added":"6","loc-deleted":"47","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"2.214","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"katelyn.grimes@cru.org","commit-full-message":"","commit-date":"2025-07-07T18:07:18Z","current-rev":"752983e07","filename":"mpdx-react/src/components/Contacts/MassActions/AddToAppeal/MassActionsAddToAppealModal.tsx","previous-rev":"5e9623b38","commit-title":"Combined appeal autocompletes into a shared component","language":"React","id":"63eb6ef0a32d566f136c346702dc5d4ff42a4b18","model-score":0.44,"author-id":null,"project-id":53436,"delta-file-score":0.67582667,"diff":"diff --git a/src/components/Contacts/MassActions/AddToAppeal/MassActionsAddToAppealModal.tsx b/src/components/Contacts/MassActions/AddToAppeal/MassActionsAddToAppealModal.tsx\nindex 70d596bcf..4d03b262c 100644\n--- a/src/components/Contacts/MassActions/AddToAppeal/MassActionsAddToAppealModal.tsx\n+++ b/src/components/Contacts/MassActions/AddToAppeal/MassActionsAddToAppealModal.tsx\n@@ -2,3 +2,2 @@ import React, { ReactElement } from 'react';\n import {\n-  Autocomplete,\n   CircularProgress,\n@@ -7,3 +6,2 @@ import {\n   FormControl,\n-  TextField,\n } from '@mui/material';\n@@ -14,2 +12,3 @@ import * as yup from 'yup';\n import { ContactsDocument } from 'pages/accountLists/[accountListId]/contacts/Contacts.generated';\n+import { AppealAutocomplete } from 'src/common/Autocompletes/AppealAutocomplete';\n import {\n@@ -18,3 +17,2 @@ import {\n } from 'src/components/common/Modal/ActionButtons/ActionButtons';\n-import { useFetchAllPages } from 'src/hooks/useFetchAllPages';\n import Modal from '../../../common/Modal/Modal';\n@@ -67,7 +65,3 @@ export const MassActionsAddToAppealModal: React.FC<\n \n-  const {\n-    data: appeals,\n-    error,\n-    fetchMore,\n-  } = useGetAppealsForMassActionQuery({\n+  const { data: appeals } = useGetAppealsForMassActionQuery({\n     variables: {\n@@ -76,7 +70,2 @@ export const MassActionsAddToAppealModal: React.FC<\n   });\n-  const { loading: loadingAppeals } = useFetchAllPages({\n-    fetchMore,\n-    error,\n-    pageInfo: appeals?.appeals.pageInfo,\n-  });\n \n@@ -105,18 +94,5 @@ export const MassActionsAddToAppealModal: React.FC<\n               <FormControl fullWidth>\n-                <Autocomplete\n+                <AppealAutocomplete\n                   id=\"appeal\"\n                   value={appeal}\n-                  autoSelect\n-                  autoHighlight\n-                  options={\n-                    (appeals?.appeals.nodes &&\n-                      appeals?.appeals.nodes.map((appeal) => appeal.id)) ||\n-                    []\n-                  }\n-                  getOptionLabel={(appealId): string => {\n-                    const currentAppeal = appeals?.appeals?.nodes.find(\n-                      (appeal) => appeal.id === appealId,\n-                    )?.name;\n-                    return currentAppeal ?? '';\n-                  }}\n                   onChange={(_, appealId): void =>\n@@ -124,23 +100,6 @@ export const MassActionsAddToAppealModal: React.FC<\n                   }\n-                  isOptionEqualToValue={(option, value): boolean =>\n-                    option === value\n-                  }\n-                  renderInput={(params): ReactElement => (\n-                    <TextField\n-                      {...params}\n-                      label={t('Appeal')}\n-                      data-testid=\"appealTextInput\"\n-                      InputProps={{\n-                        ...params.InputProps,\n-                        endAdornment: (\n-                          <>\n-                            {loadingAppeals && (\n-                              <CircularProgress color=\"primary\" size={20} />\n-                            )}\n-                            {params.InputProps.endAdornment}\n-                          </>\n-                        ),\n-                      }}\n-                    />\n-                  )}\n+                  accountListId={accountListId}\n+                  TextFieldProps={{\n+                    label: t('Appeal'),\n+                  }}\n                 />\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Will James","training-data":{"loc-added":"42","loc-deleted":"7","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"1.35","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"william.james@cru.org","commit-full-message":"* Create \"Simple\"/\"Default\" version of the PDS Goal Calculator","commit-date":"2026-05-12T19:40:00Z","current-rev":"9e1a327a9","filename":"mpdx-react/src/components/HrTools/PdsGoalCalculator/GoalsList/PdsGoalsList.tsx","previous-rev":"ab6e4572a","commit-title":"[MPDX-9475] - Add Default and Simple view to PDS Goal Calculator (#1765)","language":"React","id":"938fac7a4d8fc5523a0700b41822bd6fe16fe37e","model-score":0.44,"author-id":null,"project-id":53436,"delta-file-score":0.41834745,"diff":"diff --git a/src/components/HrTools/PdsGoalCalculator/GoalsList/PdsGoalsList.tsx b/src/components/HrTools/PdsGoalCalculator/GoalsList/PdsGoalsList.tsx\nindex 32b908c74..ccab9c1c4 100644\n--- a/src/components/HrTools/PdsGoalCalculator/GoalsList/PdsGoalsList.tsx\n+++ b/src/components/HrTools/PdsGoalCalculator/GoalsList/PdsGoalsList.tsx\n@@ -1,6 +1,8 @@\n import { useRouter } from 'next/router';\n-import React from 'react';\n+import React, { useState } from 'react';\n import { Box, Button, CircularProgress, Stack, styled } from '@mui/material';\n+import { useSnackbar } from 'notistack';\n import { useTranslation } from 'react-i18next';\n import { useGetUserQuery } from 'src/components/User/GetUser.generated';\n+import { DesignationSupportFormType } from 'src/graphql/types.generated';\n import { useAccountListId } from 'src/hooks/useAccountListId';\n@@ -10,2 +12,3 @@ import illustration6graybg from 'src/images/drawkit/grape/drawkit-grape-pack-ill\n import { PdsGoalCard } from '../GoalCard/PdsGoalCard';\n+import { CreateGoalDialog } from './CreateGoalDialog';\n import {\n@@ -28,2 +31,3 @@ export const PdsGoalsList: React.FC = () => {\n   const router = useRouter();\n+  const { enqueueSnackbar } = useSnackbar();\n   const accountListId = useAccountListId() ?? '';\n@@ -44,5 +48,30 @@ export const PdsGoalsList: React.FC = () => {\n \n+  const [dialogOpen, setDialogOpen] = useState(false);\n+\n   const goals = data?.designationSupportCalculations.nodes;\n \n-  const handleCreateGoal = async () => {\n+  const handleCreateGoal = async (formType: DesignationSupportFormType) => {\n+    const isDetailed = formType === DesignationSupportFormType.Detailed;\n+    let detailedDefaults: {\n+      ministryCellPhone: number;\n+      ministryInternet: number;\n+    } | null = null;\n+    if (isDetailed) {\n+      const reimbursements = goalMiscConstants.REIMBURSEMENTS_WITH_MAXIMUM;\n+      const phoneFee = reimbursements?.PHONE?.fee;\n+      const internetFee = reimbursements?.INTERNET?.fee;\n+      if (phoneFee === undefined || internetFee === undefined) {\n+        enqueueSnackbar(\n+          t(\n+            'Could not load required defaults. Please try again or pick Simple.',\n+          ),\n+          { variant: 'error' },\n+        );\n+        return;\n+      }\n+      detailedDefaults = {\n+        ministryCellPhone: phoneFee,\n+        ministryInternet: internetFee,\n+      };\n+    }\n     const { data } = await createPdsGoalCalculation({\n@@ -50,8 +79,7 @@ export const PdsGoalsList: React.FC = () => {\n         attributes: {\n-          ministryCellPhone:\n-            goalMiscConstants.REIMBURSEMENTS_WITH_MAXIMUM?.PHONE?.fee,\n-          ministryInternet:\n-            goalMiscConstants.REIMBURSEMENTS_WITH_MAXIMUM?.INTERNET?.fee,\n+          formType,\n+          ...(detailedDefaults ?? {}),\n         },\n       },\n+      refetchQueries: ['PdsGoalCalculations'],\n     });\n@@ -61,2 +89,3 @@ export const PdsGoalsList: React.FC = () => {\n     if (calculation) {\n+      setDialogOpen(false);\n       router.push(\n@@ -73,3 +102,3 @@ export const PdsGoalsList: React.FC = () => {\n           variant=\"contained\"\n-          onClick={handleCreateGoal}\n+          onClick={() => setDialogOpen(true)}\n           disabled={constantsLoading}\n@@ -80,2 +109,8 @@ export const PdsGoalsList: React.FC = () => {\n \n+      <CreateGoalDialog\n+        open={dialogOpen}\n+        onClose={() => setDialogOpen(false)}\n+        onCreate={handleCreateGoal}\n+      />\n+\n       {loading ? (\n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Will James","training-data":{"loc-added":"6","loc-deleted":"58","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"1.0","delta-n-functions":"0","current-file-score":"10.0"},"author-email":"william.james@cru.org","commit-full-message":"* PDS Calc Summary Report","commit-date":"2026-05-01T17:40:25Z","current-rev":"5a123162c","filename":"mpdx-react/src/components/HrTools/PdsGoalCalculator/SupportItem/OtherSection.tsx","previous-rev":"edfa70868","commit-title":"[MPDX-9450] - PDS Calc Summary Report (#1753)","language":"React","id":"d710b962e1649b58a2b06e1410af4911bfbff6cc","model-score":0.42,"author-id":null,"project-id":53436,"delta-file-score":1.044829,"diff":"diff --git a/src/components/HrTools/PdsGoalCalculator/SupportItem/OtherSection.tsx b/src/components/HrTools/PdsGoalCalculator/SupportItem/OtherSection.tsx\nindex 1f44f34b2..b7bb8663a 100644\n--- a/src/components/HrTools/PdsGoalCalculator/SupportItem/OtherSection.tsx\n+++ b/src/components/HrTools/PdsGoalCalculator/SupportItem/OtherSection.tsx\n@@ -3,3 +3,2 @@ import { Divider, Typography } from '@mui/material';\n import { useTranslation } from 'react-i18next';\n-import { useGoalCalculatorConstants } from 'src/hooks/useGoalCalculatorConstants';\n import { useLocale } from 'src/hooks/useLocale';\n@@ -7,5 +6,2 @@ import { useDataGridLocaleText } from 'src/hooks/useMuiLocaleText';\n import { usePdsGoalCalculator } from '../Shared/PdsGoalCalculatorContext';\n-import { OtherExpensesConstants } from '../calculations/OtherExpenses';\n-import { calculateReimbursableTotals } from '../calculations/reimbursableExpenses';\n-import { calculateSalaryTotals } from '../calculations/salaryCalculation';\n import {\n@@ -20,22 +16,6 @@ export const OtherSection: React.FC = () => {\n   const localeText = useDataGridLocaleText();\n-  const { calculation, hcmUser } = usePdsGoalCalculator();\n-  const { goalMiscConstants, goalGeographicConstantMap } =\n-    useGoalCalculatorConstants();\n-\n-  const additionalRates = goalMiscConstants.ADDITIONAL_RATES;\n-  const employerFicaRate = additionalRates?.EMPLOYER_FICA_RATE?.fee;\n-  const workCompPercentage = additionalRates?.PART_TIME_WORK_COMPENSATION?.fee;\n-  const attritionRate = goalMiscConstants.RATES?.ATTRITION_RATE?.fee;\n-  const creditCardFeeRate = additionalRates?.CREDIT_CARD_FEE_RATE?.fee;\n-  const adminRate = goalMiscConstants.RATES?.ADMIN_RATE?.fee;\n+  const { calculation, summaryData } = usePdsGoalCalculator();\n \n   const rows = useMemo(() => {\n-    if (\n-      !calculation ||\n-      employerFicaRate === undefined ||\n-      workCompPercentage === undefined ||\n-      attritionRate === undefined ||\n-      creditCardFeeRate === undefined ||\n-      adminRate === undefined\n-    ) {\n+    if (!calculation || !summaryData) {\n       return [];\n@@ -43,41 +23,9 @@ export const OtherSection: React.FC = () => {\n \n-    const geographicMultiplier =\n-      goalGeographicConstantMap.get(calculation.geographicLocation ?? '') ?? 0;\n-\n-    const salaryTotals = calculateSalaryTotals(calculation, {\n-      geographicMultiplier,\n-      employerFicaRate,\n-    });\n-    const reimbursableTotals = calculateReimbursableTotals(calculation);\n-\n-    const taxDeferredPct =\n-      (hcmUser?.fourOThreeB?.currentTaxDeferredContributionPercentage ?? 0) /\n-      100;\n-    const rothPct =\n-      (hcmUser?.fourOThreeB?.currentRothContributionPercentage ?? 0) / 100;\n-\n-    const constants: OtherExpensesConstants = {\n-      reimbursableTotal: reimbursableTotals.total,\n-      salarySubtotal: salaryTotals.subtotal,\n-      fourOThreeBPercentage: taxDeferredPct + rothPct,\n-      grossMonthlyPay: salaryTotals.grossMonthlyPay,\n-      workCompPercentage,\n-      attritionRate,\n-      creditCardFeeRate,\n-      adminRate,\n-    };\n-\n-    return buildOtherBreakdownRows(calculation, constants, locale, t);\n-  }, [\n-    calculation,\n-    hcmUser,\n-    employerFicaRate,\n-    workCompPercentage,\n-    attritionRate,\n-    creditCardFeeRate,\n-    adminRate,\n-    goalGeographicConstantMap,\n-    locale,\n-    t,\n-  ]);\n+    return buildOtherBreakdownRows(\n+      calculation,\n+      summaryData.otherConstants,\n+      locale,\n+      t,\n+    );\n+  }, [calculation, summaryData, locale, t]);\n \n","improvement-type":"Complex Method"},{"architectural-component-id":null,"author-name":"Katelyn Grimes","training-data":{"loc-added":"39","loc-deleted":"80","delta-cc-mean":"0.0","delta-cc-total":"0","delta-penalties":"2.628","delta-n-functions":"0","current-file-score":"9.40379462694782"},"author-email":"katelyn.grimes@cru.org","commit-full-message":"","commit-date":"2025-08-14T18:36:54Z","current-rev":"df8a86fe4","filename":"mpdx-react/src/components/Reports/MPGAIncomeExpensesReport/MPGAIncomeExpensesReport.tsx","previous-rev":"a0f7d4e19","commit-title":"Review changes based on suggestions","language":"React","id":"8c1286de7c828b8ddbab5d7b790c1714f573f9e7","model-score":0.18,"author-id":null,"project-id":53436,"delta-file-score":0.20024464,"diff":"diff --git a/src/components/Reports/MPGAIncomeExpensesReport/MPGAIncomeExpensesReport.tsx b/src/components/Reports/MPGAIncomeExpensesReport/MPGAIncomeExpensesReport.tsx\nindex 1787c3ba2..403927576 100644\n--- a/src/components/Reports/MPGAIncomeExpensesReport/MPGAIncomeExpensesReport.tsx\n+++ b/src/components/Reports/MPGAIncomeExpensesReport/MPGAIncomeExpensesReport.tsx\n@@ -14,13 +14,15 @@ import {\n } from 'src/components/Shared/MultiPageLayout/MultiPageHeader';\n-import { PrintOnlyReport } from './DisplayModes/PrintOnlyReport';\n-import { ScreenOnlyReport } from './DisplayModes/ScreenOnlyReport';\n-import { getLast12Months } from './Helper/getLastTwelveMonths';\n-import { mockData } from './mockData';\n+import { useGetLastTwelveMonths } from 'src/hooks/useGetLastTwelveMonths';\n+import { useLocale } from 'src/hooks/useLocale';\n+import { useReportsStaffExpensesQuery } from '../ReportsStaffExpenses.generated';\n import {\n-  PrintOnly,\n-  ScreenOnly,\n   SimplePrintOnly,\n-  StyledHeaderBox,\n+  SimpleScreenOnly,\n   StyledPrintButton,\n-} from './styledComponents';\n+} from '../styledComponents';\n+import { PrintOnlyReport } from './DisplayModes/PrintOnlyReport';\n+import { ScreenOnlyReport } from './DisplayModes/ScreenOnlyReport';\n+import { TotalsProvider } from './TotalsContext/TotalsContext';\n+import { mockData } from './mockData';\n+import { PrintOnly, StyledHeaderBox } from './styledComponents';\n \n@@ -35,4 +37,9 @@ export const MPGAIncomeExpensesReport: React.FC<\n   MPGAIncomeExpensesReportProps\n-> = ({ title, isNavListOpen, onNavListToggle }) => {\n+> = ({ accountListId, title, isNavListOpen, onNavListToggle }) => {\n   const { t } = useTranslation();\n+  const locale = useLocale();\n+\n+  const { data: staffExpensesData } = useReportsStaffExpensesQuery({\n+    variables: { accountListId: accountListId },\n+  });\n \n@@ -42,45 +49,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n \n-  const last12Months = useMemo(() => getLast12Months(), []);\n-\n-  const incomeTotal = useMemo(\n-    () => mockData.income?.data.reduce((sum, data) => sum + data.total, 0),\n-    [mockData.income?.data],\n-  );\n-\n-  const ministryTotal = useMemo(\n-    () =>\n-      mockData.ministryExpenses?.data.reduce(\n-        (sum, data) => sum + data.total,\n-        0,\n-      ),\n-    [mockData.ministryExpenses?.data],\n-  );\n-\n-  const healthcareTotal = useMemo(\n-    () =>\n-      mockData.healthcareExpenses?.data.reduce(\n-        (sum, data) => sum + data.total,\n-        0,\n-      ),\n-    [mockData.healthcareExpenses?.data],\n-  );\n-\n-  const miscTotal = useMemo(\n-    () => mockData.misc?.data.reduce((sum, data) => sum + data.total, 0),\n-    [mockData.misc?.data],\n-  );\n-\n-  const otherTotal = useMemo(\n-    () => mockData.other?.data.reduce((sum, data) => sum + data.total, 0),\n-    [mockData.other?.data],\n-  );\n-\n-  const expensesTotal = useMemo(\n-    () =>\n-      (ministryTotal ?? 0) +\n-      (healthcareTotal ?? 0) +\n-      (miscTotal ?? 0) +\n-      (otherTotal ?? 0),\n-    [ministryTotal, healthcareTotal, miscTotal, otherTotal],\n-  );\n+  const last12Months = useGetLastTwelveMonths(locale, true);\n \n@@ -88,12 +53,12 @@ export const MPGAIncomeExpensesReport: React.FC<\n     () => [\n-      ...(mockData.ministryExpenses?.data ?? []),\n-      ...(mockData.healthcareExpenses?.data ?? []),\n-      ...(mockData.misc?.data ?? []),\n-      ...(mockData.other?.data ?? []),\n+      ...(mockData.ministryExpenses ?? []),\n+      ...(mockData.healthcareExpenses ?? []),\n+      ...(mockData.misc ?? []),\n+      ...(mockData.other ?? []),\n     ],\n     [\n-      mockData.ministryExpenses?.data,\n-      mockData.healthcareExpenses?.data,\n-      mockData.misc?.data,\n-      mockData.other?.data,\n+      mockData.ministryExpenses,\n+      mockData.healthcareExpenses,\n+      mockData.misc,\n+      mockData.other,\n     ],\n@@ -119,3 +84,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n       <Box>\n-        <ScreenOnly>\n+        <SimpleScreenOnly>\n           <MultiPageHeader\n@@ -126,3 +91,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n           />\n-        </ScreenOnly>\n+        </SimpleScreenOnly>\n         <Box mt={2}>\n@@ -130,3 +95,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n             <StyledHeaderBox>\n-              <ScreenOnly>\n+              <SimpleScreenOnly>\n                 <Typography variant=\"h4\">\n@@ -134,3 +99,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n                 </Typography>\n-              </ScreenOnly>\n+              </SimpleScreenOnly>\n               <SimplePrintOnly>\n@@ -140,3 +105,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n               </SimplePrintOnly>\n-              <ScreenOnly>\n+              <SimpleScreenOnly>\n                 <StyledPrintButton\n@@ -151,3 +116,3 @@ export const MPGAIncomeExpensesReport: React.FC<\n                 </StyledPrintButton>\n-              </ScreenOnly>\n+              </SimpleScreenOnly>\n             </StyledHeaderBox>\n@@ -159,27 +124,21 @@ export const MPGAIncomeExpensesReport: React.FC<\n         </Box>\n-        <ScreenOnly>\n-          <ScreenOnlyReport\n-            data={mockData}\n-            incomeTotal={incomeTotal}\n-            expensesTotal={expensesTotal}\n-            ministryTotal={ministryTotal}\n-            healthcareTotal={healthcareTotal}\n-            miscTotal={miscTotal}\n-            otherTotal={otherTotal}\n-            last12Months={last12Months}\n-            expenseData={expenseData}\n-          />\n-        </ScreenOnly>\n+        <SimpleScreenOnly>\n+          <TotalsProvider data={mockData}>\n+            <ScreenOnlyReport\n+              data={mockData}\n+              last12Months={last12Months}\n+              expenseData={expenseData}\n+              currency={staffExpensesData?.accountList.currency || 'USD'}\n+            />\n+          </TotalsProvider>\n+        </SimpleScreenOnly>\n         <PrintOnly>\n-          <PrintOnlyReport\n-            data={mockData}\n-            incomeTotal={incomeTotal}\n-            expensesTotal={expensesTotal}\n-            ministryTotal={ministryTotal}\n-            healthcareTotal={healthcareTotal}\n-            miscTotal={miscTotal}\n-            otherTotal={otherTotal}\n-            last12Months={last12Months}\n-            expenseData={expenseData}\n-          />\n+          <TotalsProvider data={mockData}>\n+            <PrintOnlyReport\n+              data={mockData}\n+              last12Months={last12Months}\n+              expenseData={expenseData}\n+              currency={staffExpensesData?.accountList.currency || 'USD'}\n+            />\n+          </TotalsProvider>\n         </PrintOnly>\n","improvement-type":"Complex Method"}],"change-level":"warning","is-hotspot?":false,"line":60,"what-changed":"MonthlyGoal increases in cyclomatic complexity from 14 to 19, threshold = 10","how-to-fix":"There are many reasons for Complex Method. Sometimes, another design approach is beneficial such as a) modeling state using an explicit state machine rather than conditionals, or b) using table lookup rather than long chains of logic. In other scenarios, the function can be split using [EXTRACT FUNCTION](https://refactoring.com/catalog/extractFunction.html). Just make sure you extract natural and cohesive functions. Complex Methods can also be addressed by identifying complex conditional expressions and then using the [DECOMPOSE CONDITIONAL](https://refactoring.com/catalog/decomposeConditional.html) refactoring.","change-type":"degraded"},{"why-it-occurs":"Duplicated code often leads to code that's harder to change since the same logical change has to be done in multiple functions. More duplication gives lower code health.","name":"Code Duplication","file":"src/components/Reports/HealthIndicatorReport/HealthIndicatorWidget/HealthIndicatorWidget.test.tsx","refactoring-examples":null,"change-level":"warning","is-hotspot?":false,"line":103,"what-changed":"The module contains 3 functions with similar structure: 'should set to FALSE as machine goal is different than the monthly goal','should set to FALSE as machine goal is not defined','should set to TRUE as machine goal is defined and the same as the monthly goal'","how-to-fix":"A certain degree of duplicated code might be acceptable. The problems start when it is the same behavior that is duplicated across the functions in the module, ie. a violation of the Don't Repeat Yourself (DRY) principle. DRY violations lead to code that is changed together in predictable patterns, which is both expensive and risky. DRY violations can be identified using CodeScene's X-Ray analysis to detect clusters of change coupled functions with high code similarity. [Read More](https://codescene.com/blog/software-revolution-part3/)\n\nOnce you have identified the similarities across functions, look to extract and encapsulate the concept that varies into its own function(s). These shared abstractions can then be re-used, which minimizes the amount of duplication and simplifies change.","change-type":"introduced"}]},"positive-impact-count":0,"repo":"mpdx-react","code-health":9.538277382768747,"version":"3.0","authors":["Daniel Bisgrove"],"directives":{"added":[],"removed":[]},"positive-findings":{"number-of-types":0,"number-of-files-touched":0,"findings":[]},"notices":{"number-of-types":0,"number-of-files-touched":0,"findings":[]},"external-review-provider":"GitHub"},"analysistime":"2024-12-16T19:58:47.000Z","project-name":"mpdx-react","repository":"https://github.com/CruGlobal/mpdx-react.git"}}