@layerfi/components 0.1.47 → 0.1.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/.idea/codeStyles/Project.xml +0 -61
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/layer-react.iml +0 -9
- package/.idea/misc.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/vcs.xml +0 -6
package/dist/esm/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/providers/LayerProvider/LayerProvider.tsx", "../../src/api/util.ts", "../../src/api/layer/authenticate.ts", "../../src/models/APIError.ts", "../../src/models/ErrorHandler.tsx", "../../src/api/layer/authenticated_http.ts", "../../src/api/layer/balance_sheet.ts", "../../src/api/layer/bankTransactions.ts", "../../src/api/layer/business.ts", "../../src/api/layer/categories.ts", "../../src/api/layer/chart_of_accounts.ts", "../../src/api/layer/journal.ts", "../../src/api/layer/linked_accounts.ts", "../../src/api/layer/profit_and_loss.ts", "../../src/api/layer/quickbooks.ts", "../../src/api/layer/statement-of-cash-flow.ts", "../../src/api/layer/tasks.ts", "../../src/api/layer.ts", "../../src/components/GlobalWidgets/GlobalWidgets.tsx", "../../src/contexts/DrawerContext/DrawerContext.tsx", "../../src/hooks/useWindowSize/useWindowSize.ts", "../../src/config/general.ts", "../../src/components/Drawer/Drawer.tsx", "../../src/components/Toast/Toast.tsx", "../../src/contexts/LayerContext/LayerContext.tsx", "../../src/hooks/useDataSync/useDataSync.tsx", "../../src/hooks/useDrawer/useDrawer.tsx", "../../src/providers/BankTransactionsProvider/BankTransactionsProvider.tsx", "../../src/contexts/BankTransactionsContext/BankTransactionsContext.tsx", "../../src/types/bank_transactions.ts", "../../src/types/categories.ts", "../../src/hooks/useBankTransactions/useBankTransactions.tsx", "../../src/components/BankTransactions/constants.ts", "../../src/components/BankTransactions/utils.ts", "../../src/hooks/useBankTransactions/utils.ts", "../../src/config/theme.ts", "../../src/utils/colors.ts", "../../src/components/Onboarding/Onboarding.tsx", "../../src/contexts/LinkedAccountsContext/LinkedAccountsContext.ts", "../../src/providers/LinkedAccountsProvider/LinkedAccountsProvider.tsx", "../../src/hooks/useLinkedAccounts/useLinkedAccounts.ts", "../../src/hooks/useLinkedAccounts/mockData.ts", "../../src/components/Container/Container.tsx", "../../src/components/Container/Header.tsx", "../../src/components/Onboarding/ConnectAccount.tsx", "../../src/icons/Bell.tsx", "../../src/icons/CreditCard.tsx", "../../src/icons/Folder.tsx", "../../src/icons/Link.tsx", "../../src/icons/PlaidIcon.tsx", "../../src/icons/Sunrise.tsx", "../../src/utils/bankTransactions.ts", "../../src/components/ActionableRow/ActionableRow.tsx", "../../src/icons/ChevronRight.tsx", "../../src/components/Button/Button.tsx", "../../src/components/Button/IconButton.tsx", "../../src/components/Button/RetryButton.tsx", "../../src/icons/RefreshCcw.tsx", "../../src/components/Button/SubmitButton.tsx", "../../src/icons/AlertCircle.tsx", "../../src/icons/CheckCircle.tsx", "../../src/icons/Loader.tsx", "../../src/icons/Save.tsx", "../../src/components/Tooltip/Tooltip.tsx", "../../src/components/Tooltip/useTooltip.ts", "../../src/components/Button/TextButton.tsx", "../../src/components/Button/BackButton.tsx", "../../src/icons/BackArrow.tsx", "../../src/components/Button/CloseButton.tsx", "../../src/icons/CloseIcon.tsx", "../../src/components/Button/ExpandButton.tsx", "../../src/components/Button/Link.tsx", "../../src/components/Typography/Text.tsx", "../../src/components/Typography/Heading.tsx", "../../src/components/Typography/ErrorText.tsx", "../../src/components/Badge/Badge.tsx", "../../src/components/DataState/DataState.tsx", "../../src/icons/AlertOctagon.tsx", "../../src/components/LinkedAccounts/LinkedAccounts.tsx", "../../src/components/Loader/Loader.tsx", "../../src/components/Loader/SmallLoader.tsx", "../../src/components/LinkedAccounts/LinkedAccountsContent.tsx", "../../src/icons/PlusIcon.tsx", "../../src/components/LinkedAccountOptions/LinkedAccountOptions.tsx", "../../src/icons/MoreVertical.tsx", "../../src/components/HoverMenu/HoverMenu.tsx", "../../src/components/LinkedAccountThumb/LinkedAccountThumb.tsx", "../../src/icons/InstitutionIcon.tsx", "../../src/models/Money.ts", "../../src/components/LinkedAccountPill/LinkedAccountPill.tsx", "../../src/components/Pill/Pill.tsx", "../../src/components/BankTransactions/BankTransactions.tsx", "../../src/hooks/useElementSize/useElementSize.ts", "../../src/utils/helpers.ts", "../../src/components/BankTransactionList/BankTransactionList.tsx", "../../src/components/BankTransactionList/BankTransactionListItem.tsx", "../../src/icons/ChevronDownFill.tsx", "../../src/components/BankTransactionRow/BankTransactionRow.tsx", "../../src/icons/Scissors.tsx", "../../src/components/CategorySelect/CategorySelect.tsx", "../../src/icons/Check.tsx", "../../src/icons/ChevronDown.tsx", "../../src/icons/MinimizeTwo.tsx", "../../src/components/CategorySelect/CategorySelectDrawer.tsx", "../../src/components/BankTransactionMobileList/BusinessCategories.tsx", "../../src/components/ActionableList/ActionableList.tsx", "../../src/components/BankTransactionMobileList/constants.ts", "../../src/components/BankTransactionMobileList/utils.ts", "../../src/components/ExpandedBankTransactionRow/ExpandedBankTransactionRow.tsx", "../../src/icons/ScissorsFullOpen.tsx", "../../src/icons/Trash.tsx", "../../src/components/Input/Input.tsx", "../../src/components/Input/InputGroup.tsx", "../../src/components/Input/FileInput.tsx", "../../src/icons/UploadCloud.tsx", "../../src/components/Input/Select.tsx", "../../src/components/Input/InputWithBadge.tsx", "../../src/components/MatchForm/MatchForm.tsx", "../../src/components/BankTransactionRow/MatchBadge.tsx", "../../src/components/MatchForm/MatchFormMobile.tsx", "../../src/components/Textarea/Textarea.tsx", "../../src/components/Toggle/Toggle.tsx", "../../src/components/ExpandedBankTransactionRow/APIErrorNotifications.tsx", "../../src/components/BankTransactionRow/SplitTooltipDetails.tsx", "../../src/components/BankTransactionList/Assignment.tsx", "../../src/components/BankTransactionMobileList/BankTransactionMobileList.tsx", "../../src/components/BankTransactionMobileList/BankTransactionMobileListItem.tsx", "../../src/components/BankTransactionMobileList/BankTransactionMobileForms.tsx", "../../src/components/BankTransactionMobileList/BusinessForm.tsx", "../../src/components/BankTransactionMobileList/PersonalForm.tsx", "../../src/components/BankTransactionMobileList/SplitAndMatchForm.tsx", "../../src/components/BankTransactionMobileList/MatchForm.tsx", "../../src/components/BankTransactionMobileList/SplitForm.tsx", "../../src/components/BankTransactionMobileList/TransactionToOpenContext.ts", "../../src/components/BankTransactionsTable/BankTransactionsTable.tsx", "../../src/components/BankTransactionsLoader/BankTransactionsLoader.tsx", "../../src/components/SkeletonTableLoader/SkeletonTableLoader.tsx", "../../src/components/SkeletonLoader/SkeletonLoader.tsx", "../../src/components/SyncingComponent/SyncingComponent.tsx", "../../src/components/ErrorBoundary/ErrorBoundary.tsx", "../../src/components/ErrorBoundary/ErrorBoundaryMessage.tsx", "../../src/components/Pagination/Pagination.tsx", "../../src/hooks/usePagination/usePagination.ts", "../../src/icons/ChevronLeft.tsx", "../../src/components/BankTransactions/BankTransactionsHeader.tsx", "../../src/icons/DownloadCloud.tsx", "../../src/utils/business.ts", "../../src/components/DatePicker/DatePicker.tsx", "../../src/components/DatePicker/DatePickerOptions.tsx", "../../src/components/BankTransactions/DataStates.tsx", "../../src/icons/Inbox.tsx", "../../src/components/Quickbooks/Quickbooks.tsx", "../../src/hooks/useQuickbooks/useQuickbooks.ts", "../../src/components/ProfitAndLoss/ProfitAndLoss.tsx", "../../src/hooks/useProfitAndLoss/useProfitAndLoss.tsx", "../../src/utils/profitAndLossUtils.ts", "../../src/hooks/useProfitAndLoss/useProfitAndLossQuery.tsx", "../../src/components/ProfitAndLossChart/ProfitAndLossChart.tsx", "../../src/hooks/useProfitAndLoss/useProfitAndLossLTM.tsx", "../../src/components/ProfitAndLossChart/Indicator.tsx", "../../src/components/ProfitAndLossDatePicker/ProfitAndLossDatePicker.tsx", "../../src/components/ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts.tsx", "../../src/icons/X.tsx", "../../src/components/ProfitAndLossDetailedCharts/DetailedChart.tsx", "../../src/utils/format.ts", "../../src/components/ProfitAndLossDetailedCharts/DetailedTable.tsx", "../../src/config/charts.ts", "../../src/icons/SortArrows.tsx", "../../src/components/ProfitAndLossDetailedCharts/Filters.tsx", "../../src/components/ProfitAndLossSummaries/ProfitAndLossSummaries.tsx", "../../src/components/ProfitAndLossSummaries/MiniChart.tsx", "../../src/components/ProfitAndLossTable/ProfitAndLossTable.tsx", "../../src/components/ProfitAndLossRow/ProfitAndLossRow.tsx", "../../src/icons/PieChart.tsx", "../../src/components/ProfitAndLossTable/empty_profit_and_loss_report.ts", "../../src/components/BalanceSheet/BalanceSheet.tsx", "../../src/contexts/BalanceSheetContext/BalanceSheetContext.tsx", "../../src/contexts/TableContext/TableContext.tsx", "../../src/hooks/useBalanceSheet/useBalanceSheet.tsx", "../../src/components/BalanceSheetDatePicker/BalanceSheetDatePicker.tsx", "../../src/components/BalanceSheetExpandAllButton/BalanceSheetExpandAllButton.tsx", "../../src/hooks/useTableExpandRow/useTableExpandRow.tsx", "../../src/components/BalanceSheetTable/BalanceSheetTable.tsx", "../../src/components/TableBody/TableBody.tsx", "../../src/components/TableCell/TableCell.tsx", "../../src/components/TableHead/TableHead.tsx", "../../src/components/TableRow/TableRow.tsx", "../../src/components/Table/Table.tsx", "../../src/components/View/View.tsx", "../../src/components/ViewHeader/ViewHeader.tsx", "../../src/components/Panel/Panel.tsx", "../../src/components/BalanceSheet/constants.ts", "../../src/components/StatementOfCashFlow/StatementOfCashFlow.tsx", "../../src/contexts/StatementOfCashContext/StatementOfCashFlowContext.tsx", "../../src/hooks/useStatementOfCashFlow/useStatementOfCashFlow.tsx", "../../src/components/StatementOfCashFlowTable/StatementOfCashFlowTable.tsx", "../../src/components/StatementOfCashFlow/constants.ts", "../../src/components/ChartOfAccounts/ChartOfAccounts.tsx", "../../src/contexts/ChartOfAccountsContext/ChartOfAccountsContext.tsx", "../../src/contexts/LedgerAccountsContext/LedgerAccountsContext.tsx", "../../src/hooks/useChartOfAccounts/useChartOfAccounts.tsx", "../../src/components/ChartOfAccountsForm/constants.ts", "../../src/hooks/useLedgerAccounts/useLedgerAccounts.tsx", "../../src/components/ChartOfAccountsTable/ChartOfAccountsTable.tsx", "../../src/components/ChartOfAccountsDatePicker/ChartOfAccountsDatePicker.tsx", "../../src/components/ChartOfAccountsRow/ChartOfAccountsRow.tsx", "../../src/icons/Edit2.tsx", "../../src/components/ChartOfAccountsSidebar/ChartOfAccountsSidebar.tsx", "../../src/components/ChartOfAccountsForm/ChartOfAccountsForm.tsx", "../../src/components/ChartOfAccountsForm/useParentOptions.ts", "../../src/components/LedgerAccount/LedgerAccountIndex.tsx", "../../src/components/LedgerAccountEntryDetails/LedgerAccountEntryDetails.tsx", "../../src/components/Card/Card.tsx", "../../src/components/DateTime/DateTime.tsx", "../../src/components/DetailsList/DetailsList.tsx", "../../src/components/DetailsList/DetailsListItem.tsx", "../../src/components/LedgerAccount/LedgerAccountRow.tsx", "../../src/components/Journal/Journal.tsx", "../../src/contexts/JournalContext/JournalContext.tsx", "../../src/hooks/useJournal/useJournal.tsx", "../../src/utils/journal.ts", "../../src/components/JournalTable/JournalTable.tsx", "../../src/components/JournalRow/JournalRow.tsx", "../../src/components/JournalSidebar/JournalSidebar.tsx", "../../src/components/JournalEntryDetails/JournalEntryDetails.tsx", "../../src/components/JournalForm/JournalForm.tsx", "../../src/components/JournalForm/JournalFormEntryLines.tsx", "../../src/components/Tasks/Tasks.tsx", "../../src/contexts/TasksContext/TasksContext.tsx", "../../src/hooks/useTasks/useTasks.tsx", "../../src/types/tasks.ts", "../../src/components/TasksHeader/TasksHeader.tsx", "../../src/icons/ProgressIcon.tsx", "../../src/components/TasksList/TasksList.tsx", "../../src/icons/SmileIcon.tsx", "../../src/components/TasksListItem/TasksListItem.tsx", "../../src/components/TasksPending/TasksPending.tsx", "../../src/components/UpsellBanner/BookkeepingUpsellBar.tsx", "../../src/icons/Coffee.tsx", "../../src/components/IconBox/IconBox.tsx", "../../src/views/BookkeepingOverview/BookkeepingOverview.tsx", "../../src/views/AccountingOverview/AccountingOverview.tsx", "../../src/components/TransactionToReviewCard/TransactionToReviewCard.tsx", "../../src/components/BadgeLoader/BadgeLoader.tsx", "../../src/components/NotificationCard/NotificationCard.tsx", "../../src/views/BankTransactionsWithLinkedAccounts/BankTransactionsWithLinkedAccounts.tsx", "../../src/views/GeneralLedger/GeneralLedger.tsx", "../../src/views/Reports/Reports.tsx", "../../src/components/ProfitAndLossView/ProfitAndLossView.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, { PropsWithChildren, useReducer, useEffect, Reducer } from 'react'\nimport { Layer } from '../../api/layer'\nimport { GlobalWidgets } from '../../components/GlobalWidgets'\nimport { ToastProps } from '../../components/Toast/Toast'\nimport { DrawerContext } from '../../contexts/DrawerContext'\nimport { LayerContext } from '../../contexts/LayerContext'\nimport { useDataSync } from '../../hooks/useDataSync'\nimport { useDrawer } from '../../hooks/useDrawer'\nimport { LayerError, errorHandler } from '../../models/ErrorHandler'\nimport { BankTransactionsProvider } from '../../providers/BankTransactionsProvider'\nimport {\n LayerContextValues,\n LayerContextAction,\n LayerContextActionName as Action,\n BankTransaction,\n} from '../../types'\nimport {\n ColorConfig,\n ColorsPaletteOption,\n LayerThemeConfig,\n OnboardingStep,\n} from '../../types/layer_context'\nimport { buildColorsPalette } from '../../utils/colors'\nimport { add, isBefore } from 'date-fns'\nimport useSWR, { SWRConfig } from 'swr'\n\nconst reducer: Reducer<LayerContextValues, LayerContextAction> = (\n state,\n action,\n) => {\n switch (action.type) {\n case Action.setAuth:\n case Action.setBusiness:\n case Action.setCategories:\n case Action.setTheme:\n case Action.setOnboardingStep:\n case Action.setColors:\n return { ...state, ...action.payload }\n case Action.setToast:\n return {\n ...state,\n toasts: [\n ...state.toasts,\n { ...action.payload.toast, isExiting: false },\n ],\n }\n case Action.setToastExit:\n return {\n ...state,\n toasts: state.toasts.map(toast =>\n toast.id === action.payload.toast.id\n ? { ...toast, isExiting: false }\n : toast,\n ),\n }\n case Action.removeToast:\n return {\n ...state,\n toasts: state.toasts.filter(t => t.id !== action.payload.toast.id),\n }\n default:\n return state\n }\n}\n\ntype LayerEnvironmentConfig = {\n url: string\n scope: string\n apiUrl: string\n}\n\nexport const LayerEnvironment: Record<string, LayerEnvironmentConfig> = {\n production: {\n url: 'https://auth.layerfi.com/oauth2/token',\n scope: 'https://api.layerfi.com/production',\n apiUrl: 'https://api.layerfi.com',\n },\n sandbox: {\n url: 'https://auth.layerfi.com/oauth2/token',\n scope: 'https://sandbox.layerfi.com/sandbox',\n apiUrl: 'https://sandbox.layerfi.com',\n },\n staging: {\n url: 'https://auth.layerfi.com/oauth2/token',\n scope: 'https://sandbox.layerfi.com/sandbox',\n apiUrl: 'https://sandbox.layerfi.com',\n },\n internalStaging: {\n url: 'https://auth.layerfi.com/oauth2/token',\n scope: 'https://sandbox.layerfi.com/sandbox',\n apiUrl: 'https://staging.layerfi.com',\n },\n}\n\nexport type EventCallbacks = {\n onTransactionCategorized?: (bankTransactionId: string) => void\n}\n\nexport type Props = {\n businessId: string\n appId?: string\n appSecret?: string\n businessAccessToken?: string\n environment?: keyof typeof LayerEnvironment\n theme?: LayerThemeConfig\n usePlaidSandbox?: boolean\n onError?: (error: LayerError) => void\n eventCallbacks?: EventCallbacks\n}\n\nexport const LayerProvider = ({\n appId,\n appSecret,\n businessId,\n children,\n businessAccessToken,\n environment = 'production',\n theme,\n usePlaidSandbox,\n onError,\n eventCallbacks,\n}: PropsWithChildren<Props>) => {\n const defaultSWRConfig = {\n revalidateInterval: 0,\n revalidateOnFocus: false,\n revalidateOnReconnect: false,\n revalidateIfStale: false,\n }\n\n errorHandler.setOnError(onError)\n\n const colors = buildColorsPalette(theme)\n\n const { url, scope, apiUrl } = LayerEnvironment[environment]\n const [state, dispatch] = useReducer(reducer, {\n auth: {\n access_token: '',\n token_type: '',\n expires_in: 0,\n expires_at: new Date(2000, 1, 1),\n },\n businessId,\n business: undefined,\n categories: [],\n apiUrl,\n theme,\n colors,\n usePlaidSandbox,\n onboardingStep: undefined,\n environment,\n toasts: [],\n eventCallbacks: {},\n })\n\n const { touch, syncTimestamps, read, readTimestamps, hasBeenTouched } =\n useDataSync()\n\n const { data: auth } =\n appId !== undefined && appSecret !== undefined\n ? useSWR(\n businessAccessToken === undefined &&\n appId !== undefined &&\n appSecret !== undefined &&\n isBefore(state.auth.expires_at, new Date()) &&\n 'authenticate',\n Layer.authenticate({\n appId,\n appSecret,\n authenticationUrl: url,\n scope,\n }),\n defaultSWRConfig,\n )\n : { data: undefined }\n\n useEffect(() => {\n if (businessAccessToken) {\n dispatch({\n type: Action.setAuth,\n payload: {\n auth: {\n access_token: businessAccessToken,\n token_type: 'Bearer',\n expires_in: 3600,\n expires_at: add(new Date(), { seconds: 3600.0 }),\n },\n },\n })\n } else if (auth?.access_token) {\n dispatch({\n type: Action.setAuth,\n payload: {\n auth: {\n ...auth,\n expires_at: add(new Date(), { seconds: auth.expires_in }),\n },\n },\n })\n }\n }, [businessAccessToken, auth?.access_token])\n\n const { data: categoriesData } = useSWR(\n businessId && state.auth?.access_token && `categories-${businessId}`,\n Layer.getCategories(apiUrl, state.auth?.access_token, {\n params: { businessId },\n }),\n {\n ...defaultSWRConfig,\n onSuccess: response => {\n if (response?.data?.categories?.length) {\n dispatch({\n type: Action.setCategories,\n payload: { categories: response.data.categories || [] },\n })\n }\n },\n },\n )\n useEffect(() => {\n if (categoriesData?.data?.categories?.length) {\n dispatch({\n type: Action.setCategories,\n payload: { categories: categoriesData.data.categories || [] },\n })\n }\n }, [categoriesData])\n\n const { data: businessData } = useSWR(\n businessId && state?.auth?.access_token && `business-${businessId}`,\n Layer.getBusiness(apiUrl, state?.auth?.access_token, {\n params: { businessId },\n }),\n {\n ...defaultSWRConfig,\n onSuccess: response => {\n if (response?.data) {\n dispatch({\n type: Action.setBusiness,\n payload: { business: response.data || [] },\n })\n }\n },\n },\n )\n useEffect(() => {\n if (businessData?.data) {\n dispatch({\n type: Action.setBusiness,\n payload: { business: businessData.data || [] },\n })\n }\n }, [businessData])\n\n const setTheme = (theme: LayerThemeConfig) => {\n dispatch({\n type: Action.setTheme,\n payload: { theme },\n })\n\n dispatch({\n type: Action.setColors,\n payload: { colors: buildColorsPalette(theme) },\n })\n }\n\n const setLightColor = (color?: ColorConfig) => {\n setTheme({\n ...(state.theme ?? {}),\n colors: {\n ...(state.theme?.colors ?? {}),\n light: color,\n },\n })\n }\n\n const setDarkColor = (color?: ColorConfig) => {\n setTheme({\n ...(state.theme ?? {}),\n colors: {\n ...(state.theme?.colors ?? {}),\n dark: color,\n },\n })\n }\n\n const setTextColor = (color?: ColorConfig) => {\n setTheme({\n ...(state.theme ?? {}),\n colors: {\n ...(state.theme?.colors ?? {}),\n text: color,\n },\n })\n }\n\n const setToast = (toast: ToastProps) => {\n dispatch({ type: Action.setToast, payload: { toast: toast } })\n }\n\n const removeToast = (toast: ToastProps) => {\n dispatch({ type: Action.removeToast, payload: { toast: toast } })\n }\n\n const setToastExit = (toast: ToastProps) => {\n dispatch({ type: Action.setToastExit, payload: { toast: toast } })\n }\n\n const addToast = (toast: ToastProps) => {\n const id = `${Date.now()}-${Math.random()}`\n const newToast = { id, isExiting: false, ...toast }\n\n setToast(newToast)\n\n setTimeout(() => {\n removeToast(newToast)\n setTimeout(() => {\n setToastExit(newToast)\n }, 1000)\n }, toast.duration || 2000)\n }\n\n const setColors = (colors?: { dark?: ColorConfig; light?: ColorConfig }) =>\n setTheme({\n ...(state.theme ?? {}),\n colors,\n })\n\n const getColor = (shade: number): ColorsPaletteOption | undefined => {\n if (state.colors && shade in state.colors) {\n return state.colors[shade]\n }\n\n return\n }\n\n const setOnboardingStep = (value: OnboardingStep) =>\n dispatch({\n type: Action.setOnboardingStep,\n payload: { onboardingStep: value },\n })\n\n const drawerContextData = useDrawer()\n\n return (\n <SWRConfig value={defaultSWRConfig}>\n <LayerContext.Provider\n value={{\n ...state,\n setTheme,\n getColor,\n setLightColor,\n setDarkColor,\n setTextColor,\n setColors,\n setOnboardingStep,\n addToast,\n removeToast,\n onError: errorHandler.onError,\n touch,\n read,\n syncTimestamps,\n readTimestamps,\n hasBeenTouched,\n eventCallbacks,\n }}\n >\n <BankTransactionsProvider>\n <DrawerContext.Provider value={drawerContextData}>\n {children}\n <GlobalWidgets />\n </DrawerContext.Provider>\n </BankTransactionsProvider>\n </LayerContext.Provider>\n </SWRConfig>\n )\n}\n", "export const formStringFromObject = (\n object: Record<string, string | number | boolean>,\n): string =>\n Object.entries(object)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&')\n", "import { OAuthResponse } from '../../types'\nimport { formStringFromObject } from '../util'\n\ntype AuthenticationArguments = {\n appId: string\n appSecret: string\n authenticationUrl?: string\n scope: string\n}\nexport const authenticate =\n ({\n appId,\n appSecret,\n authenticationUrl = 'https://auth.layerfi.com/oauth2/token',\n scope,\n }: AuthenticationArguments) =>\n (): Promise<OAuthResponse> =>\n fetch(authenticationUrl, {\n method: 'POST',\n headers: {\n Authorization: 'Basic ' + btoa(appId + ':' + appSecret),\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: formStringFromObject({\n grant_type: 'client_credentials',\n scope,\n client_id: appId,\n }),\n }).then(res => res.json() as Promise<OAuthResponse>)\n", "export interface APIErrorMessage {\n type?: string\n description?: string\n}\n\nexport class APIError extends Error {\n code?: number\n info?: string\n messages?: APIErrorMessage[]\n\n constructor(message: string, code?: number, messages?: APIErrorMessage[]) {\n super(message)\n this.name = 'APIError'\n this.code = code\n this.messages = messages\n\n Object.setPrototypeOf(this, APIError.prototype)\n }\n\n getMessage() {\n return this.message\n }\n\n getAllMessages() {\n return this.messages?.map(x => x.description)\n }\n}\n", "import { APIError } from './APIError'\n\ntype LayerErrorType = 'unauthenticated' | 'api' | 'render'\ntype LayerErrorScope = 'BankTransaction' | 'ChartOfAccounts'\n\nexport interface LayerError {\n type?: LayerErrorType\n scope?: LayerErrorScope\n payload: Error | APIError\n}\n\nclass ErrorHandlerClass {\n public onErrorCallback?: (err: LayerError) => void | undefined\n\n constructor() {\n this.onErrorCallback = undefined\n }\n\n public setOnError(errorFnc: ((err: LayerError) => void) | undefined) {\n this.onErrorCallback = errorFnc\n }\n\n public onError(err: LayerError) {\n if (this.onErrorCallback) {\n this.onErrorCallback(err)\n }\n }\n}\n\nexport const errorHandler = new ErrorHandlerClass()\n\nexport const reportError = (payload: LayerError) =>\n errorHandler.onError(payload)\n", "import { APIError } from '../../models/APIError'\nimport { reportError } from '../../models/ErrorHandler'\n\nexport type HTTPVerb = 'get' | 'put' | 'post' | 'patch' | 'options' | 'delete'\n\nexport const get =\n <\n Return extends Record<string, unknown> = Record<string, unknown>,\n Params extends Record<string, string | undefined> = Record<\n string,\n string | undefined\n >,\n >(\n url: (params: Params) => string,\n ) =>\n (\n baseUrl: string,\n accessToken: string | undefined,\n options?: { params?: Params },\n ) =>\n (): Promise<Return> =>\n fetch(`${baseUrl}${url(options?.params || ({} as Params))}`, {\n headers: {\n Authorization: 'Bearer ' + (accessToken || ''),\n 'Content-Type': 'application/json',\n },\n method: 'GET',\n })\n .then(res => handleResponse<Return>(res))\n .catch(error => handleException(error))\n\nexport const request =\n (verb: HTTPVerb) =>\n <\n Return extends Record<string, unknown> = Record<string, unknown>,\n Body extends Record<string, unknown> = Record<string, unknown>,\n Params extends Record<string, string | undefined> = Record<\n string,\n string | undefined\n >,\n >(\n url: (params: Params) => string,\n ) =>\n (\n baseUrl: string,\n accessToken: string | undefined,\n options?: {\n params?: Params\n body?: Body\n },\n ): Promise<Return> =>\n fetch(`${baseUrl}${url(options?.params || ({} as Params))}`, {\n headers: {\n Authorization: 'Bearer ' + (accessToken || ''),\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n },\n method: verb.toUpperCase(),\n body: JSON.stringify(options?.body),\n })\n .then(res => handleResponse<Return>(res))\n .catch(error => handleException(error))\n\nexport const post = request('post')\nexport const put = request('put')\nexport const deleteRequest = request('delete')\n\nexport const postWithFormData = <\n Return extends Record<string, unknown> = Record<string, unknown>,\n>(\n url: string,\n formData: FormData,\n baseUrl: string,\n accessToken: string | undefined,\n): Promise<Return> => {\n return fetch(`${baseUrl}${url}`, {\n method: 'POST',\n headers: {\n Authorization: 'Bearer ' + (accessToken || ''),\n },\n body: formData,\n })\n .then(res => handleResponse<Return>(res))\n .catch(error => handleException(error))\n}\n\nconst handleResponse = async <Return>(res: Response) => {\n if (!res.ok) {\n const errors = await tryToReadErrorsFromResponse(res)\n const apiError = new APIError(\n 'An error occurred while fetching the data from API.',\n res.status,\n errors,\n )\n throw apiError\n }\n\n const parsedResponse = await res.json()\n if (parsedResponse && 'errors' in parsedResponse) {\n const apiError = new APIError(\n 'Errors in the API response.',\n res.status,\n parsedResponse.errors ?? [],\n )\n throw apiError\n }\n\n return parsedResponse as Return\n}\n\nconst handleException = async (error: Error | APIError) => {\n if (error.name === 'APIError') {\n reportError({\n type: (error as APIError).code === 401 ? 'unauthenticated' : 'api',\n payload: error,\n })\n\n throw error\n }\n\n const apiError = new APIError(\n 'An error occurred while parsing the data from API.',\n undefined,\n [],\n )\n\n reportError({\n type: 'api',\n payload: apiError,\n })\n\n throw apiError\n}\n\nconst tryToReadErrorsFromResponse = async (res?: Response) => {\n try {\n const data = await res?.json()\n return data?.errors ?? []\n } catch (_err) {\n return []\n }\n}\n", "import { BalanceSheet } from '../../types'\nimport { get } from './authenticated_http'\n\nexport const getBalanceSheet = get<\n GetBalanceSheetReturn,\n GetBalanceSheetParams\n>(\n ({ businessId, effectiveDate }: GetBalanceSheetParams) =>\n `/v1/businesses/${businessId}/reports/balance-sheet?effective_date=${encodeURIComponent(\n effectiveDate,\n )}`,\n)\n\nexport type GetBalanceSheetReturn = {\n data?: BalanceSheet\n error?: unknown\n}\n\nexport interface GetBalanceSheetParams\n extends Record<string, string | undefined> {\n businessId: string\n effectiveDate: string\n}\n", "import { CategoryUpdate, BankTransaction, Metadata } from '../../types'\nimport {\n BankTransactionMatch,\n BankTransactionMatchType,\n BankTransactionMetadata,\n DocumentS3Urls,\n FileMetadata,\n} from '../../types/bank_transactions'\nimport { S3PresignedUrl } from '../../types/general'\nimport { get, put, post, postWithFormData } from './authenticated_http'\n\nexport type GetBankTransactionsReturn = {\n data?: BankTransaction[]\n meta?: Metadata\n error?: unknown\n}\n\nexport interface GetBankTransactionsParams\n extends Record<string, string | undefined> {\n businessId: string\n cursor?: string\n categorized?: string\n sortOrder?: 'ASC' | 'DESC'\n sortBy?: string\n}\nexport const getBankTransactions = get<\n GetBankTransactionsReturn,\n GetBankTransactionsParams\n>(\n ({\n businessId,\n cursor,\n categorized,\n sortBy = 'date',\n sortOrder = 'DESC',\n }: GetBankTransactionsParams) =>\n `/v1/businesses/${businessId}/bank-transactions?${\n cursor ? `cursor=${cursor}&` : ''\n }${\n categorized !== undefined && categorized !== '' ? `categorized=${categorized}&` : ''\n }sort_by=${sortBy}&sort_order=${sortOrder}&limit=200`,\n)\n\nexport const categorizeBankTransaction = put<\n { data: BankTransaction; errors: unknown },\n CategoryUpdate\n>(\n ({ businessId, bankTransactionId }) =>\n `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/categorize`,\n)\n\nexport const matchBankTransaction = put<\n { data: BankTransactionMatch; errors: unknown },\n { match_id: string; type: BankTransactionMatchType }\n>(\n ({ businessId, bankTransactionId }) =>\n `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/match`,\n)\n\nexport interface GetBankTransactionsCsvParams\n extends Record<string, string | undefined> {\n businessId: string\n startDate?: string\n endDate?: string\n categorized?: 'true' | 'false'\n category?: string\n month?: string\n year?: string\n}\n\nexport const getBankTransactionsCsv = get<{\n data?: S3PresignedUrl\n error?: unknown\n}>((params: Record<string, string | undefined>) => {\n const { businessId, startDate, endDate, categorized, category, month, year } =\n params as GetBankTransactionsCsvParams // Type assertion here for clarity\n return `/v1/businesses/${businessId}/reports/transactions/exports/csv?${\n startDate ? `start_date=${encodeURIComponent(startDate)}&` : ''\n }${endDate ? `end_date=${encodeURIComponent(endDate)}&` : ''}${\n month ? `month=${encodeURIComponent(month)}&` : ''\n }${year ? `year=${encodeURIComponent(year)}&` : ''}${\n categorized ? `categorized=${categorized}&` : ''\n }${category ? `category=${encodeURIComponent(category)}&` : ''}`\n})\n\nexport const getBankTransactionMetadata = get<{\n data: BankTransactionMetadata\n errors: unknown\n}>(\n ({ businessId, bankTransactionId }) =>\n `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/metadata`,\n)\n\nexport const updateBankTransactionMetadata = put<\n { data: BankTransactionMetadata; errors: unknown },\n { memo: string }\n>(\n ({ businessId, bankTransactionId }) =>\n `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/metadata`,\n)\n\nexport const listBankTransactionDocuments = get<{\n data: DocumentS3Urls\n errors: unknown\n}>(\n ({ businessId, bankTransactionId }) =>\n `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/documents`,\n)\n\nexport const uploadBankTransactionDocument =\n (baseUrl: string, accessToken: string) =>\n ({\n businessId,\n bankTransactionId,\n file,\n documentType,\n }: {\n businessId: string\n bankTransactionId: string\n file: File\n documentType: string\n }) => {\n const formData = new FormData()\n formData.append('file', file)\n formData.append('documentType', documentType)\n\n const endpoint = `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/documents`\n return postWithFormData<{ data: FileMetadata; errors: unknown }>(\n endpoint,\n formData,\n baseUrl,\n accessToken,\n )\n }\n", "import { Business } from '../../types'\nimport { get } from './authenticated_http'\n\nexport const getBusiness = get<{\n data: Business\n}>(({ businessId }) => `/v1/businesses/${businessId}`)\n", "import { Category } from '../../types'\nimport { get } from './authenticated_http'\n\nexport const getCategories = get<{\n data: {\n type: 'Category_List'\n categories: Category[]\n }\n}>(({ businessId }) => `/v1/businesses/${businessId}/categories`)\n", "import {\n Account,\n ChartOfAccounts,\n NewAccount,\n EditAccount,\n LedgerAccountsEntry,\n} from '../../types'\nimport { ChartWithBalances } from '../../types/chart_of_accounts'\nimport { LedgerAccountLineItems } from '../../types/ledger_accounts'\nimport { get, post, put } from './authenticated_http'\n\nexport const getChartOfAccounts = get<{ data: ChartOfAccounts }>(\n ({ businessId }) => `/v1/businesses/${businessId}/ledger/accounts`,\n)\n\nexport const getLedgerAccountBalances = get<{ data: ChartWithBalances }>(\n ({ businessId, startDate, endDate }) =>\n `/v1/businesses/${businessId}/ledger/balances?${\n startDate ? `&start_date=${encodeURIComponent(startDate)}` : ''\n }${endDate ? `&end_date=${encodeURIComponent(endDate)}` : ''}`,\n)\n\nexport const createAccount = post<{ data: Account }, NewAccount>(\n ({ businessId }) => `/v1/businesses/${businessId}/ledger/accounts`,\n)\n\nexport const updateAccount = put<{ data: Account }, EditAccount>(\n ({ businessId, accountId }) =>\n `/v1/businesses/${businessId}/ledger/accounts/${accountId}`,\n)\n\nexport const getLedgerAccountsLines = get<{ data: LedgerAccountLineItems }>(\n ({ businessId, accountId }) =>\n `/v1/businesses/${businessId}/ledger/accounts/${accountId}/lines`,\n)\n\nexport const getLedgerAccountsEntry = get<{ data: LedgerAccountsEntry }>(\n ({ businessId, entryId }) =>\n `/v1/businesses/${businessId}/ledger/entries/${entryId}`,\n)\n", "\nimport { JournalEntry } from '../../types/journal'\nimport { get, post } from './authenticated_http'\n\nexport const getJournal = get<{ data: JournalEntry[] }>(\n ({ businessId }) => `/v1/businesses/${businessId}/ledger/entries`,\n)\n\nexport const createJournalEntries = post<{ data: JournalEntry[] }>(\n ({ businessId }) => `/v1/businesses/${businessId}/ledger/manual-entries`,\n)\n", "import { LinkedAccounts, PublicToken } from '../../types/linked_accounts'\nimport { get, post } from './authenticated_http'\n\nexport const syncConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n }\n>(({ businessId }) => `/v1/businesses/${businessId}/sync`)\n\nexport const updateConnectionStatus = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n }\n>(\n ({ businessId }) =>\n `/v1/businesses/${businessId}/external-accounts/update-connection-status`,\n)\n\nexport const getLinkedAccounts = get<\n { data: LinkedAccounts },\n {\n businessId: string\n }\n>(({ businessId }) => `/v1/businesses/${businessId}/external-accounts`)\n\nexport const confirmConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n accountId: string\n }\n>(\n ({ businessId, accountId }) =>\n `/v1/businesses/${businessId}/external-accounts/${accountId}/confirm`,\n)\n\nexport const denyConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n accountId: string\n }\n>(\n ({ businessId, accountId }) =>\n `/v1/businesses/${businessId}/external-accounts/${accountId}/deny`,\n)\n\n// TODO: not implemented yet in backend\nexport const unlinkConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n connectionId: string\n }\n>(\n ({ businessId, connectionId }) =>\n `/v1/businesses/${businessId}/plaid/external-accounts/connection/${connectionId}/archive`,\n)\n\nexport const unlinkAccount = post<\n Record<string, unknown>,\n Record<string, unknown>,\n { businessId: string; accountId: string }\n>(\n ({ businessId, accountId }) =>\n `/v1/businesses/${businessId}/external-accounts/${accountId}/archive`,\n)\n\n/**********************\n * Plaid Specific API *\n **********************/\n\nexport const getPlaidLinkToken = post<\n {\n data: {\n type: 'Link_Token'\n link_token: string\n }\n },\n Record<string, unknown>,\n {\n businessId: string\n }\n>(({ businessId }) => `/v1/businesses/${businessId}/plaid/link`)\n\nexport const getPlaidUpdateModeLinkToken = post<\n {\n data: {\n type: 'Link_Token'\n link_token: string\n }\n },\n Record<string, unknown>,\n {\n businessId: string\n }\n>(({ businessId }) => `/v1/businesses/${businessId}/plaid/update-mode-link`)\n\nexport const exchangePlaidPublicToken = post<\n Record<string, unknown>,\n PublicToken,\n {\n businessId: string\n }\n>(({ businessId }) => `/v1/businesses/${businessId}/plaid/link/exchange`)\n\n// TODO: Delete once \"unlinkConnection\" is online. unlinkConnection is broader and would be able\n// to handle other providers like Stripe as well as Plaid\nexport const unlinkPlaidItem = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n plaidItemPlaidId: string\n }\n>(\n ({ businessId, plaidItemPlaidId }) =>\n `/v1/businesses/${businessId}/plaid/items/${plaidItemPlaidId}/unlink`,\n)\n\n// Only works in non-production environments\nexport const breakPlaidItemConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n plaidItemPlaidId: string\n }\n>(\n ({ businessId, plaidItemPlaidId }) =>\n `/v1/businesses/${businessId}/plaid/items/${plaidItemPlaidId}/sandbox-reset-item-login`,\n)\n\n// export const createAccount = post<{ data: LinkedAccount }, NewAccount>(\n// ({ businessId }) => `/v1/businesses/${businessId}/external-accounts`,\n// )\n", "import { ProfitAndLoss } from '../../types'\nimport { S3PresignedUrl } from '../../types/general'\nimport { ProfitAndLossSummaries } from '../../types/profit_and_loss'\nimport { get } from './authenticated_http'\n\nexport const getProfitAndLoss = get<{\n data?: ProfitAndLoss\n error?: unknown\n}>(\n ({ businessId, startDate, endDate, tagKey, tagValues, reportingBasis }) =>\n `/v1/businesses/${businessId}/reports/profit-and-loss?start_date=${\n startDate ? encodeURIComponent(startDate) : ''\n }&end_date=${endDate ? encodeURIComponent(endDate) : ''}${\n reportingBasis ? `&reporting_basis=${reportingBasis}` : ''\n }${tagKey ? `&tag_key=${tagKey}` : ''}${\n tagValues ? `&tag_values=${tagValues}` : ''\n }`,\n)\n\nexport const getProfitAndLossSummaries = get<{\n data?: ProfitAndLossSummaries\n error?: unknown\n}>(\n ({\n businessId,\n startYear,\n startMonth,\n endYear,\n endMonth,\n tagKey,\n tagValues,\n reportingBasis,\n }) =>\n `/v1/businesses/${businessId}/reports/profit-and-loss-summaries?start_year=${\n startYear ? encodeURIComponent(startYear) : ''\n }&start_month=${\n startMonth ? encodeURIComponent(startMonth) : ''\n }&end_year=${endYear ? encodeURIComponent(endYear) : ''}&end_month=${\n endMonth ? encodeURIComponent(endMonth) : ''\n }${reportingBasis ? `&reporting_basis=${reportingBasis}` : ''}${\n tagKey ? `&tag_key=${tagKey}` : ''\n }${tagValues ? `&tag_values=${tagValues}` : ''}`,\n)\n\nexport const getProfitAndLossCsv = get<{\n data?: S3PresignedUrl\n error?: unknown\n}>(\n ({\n businessId,\n startDate,\n endDate,\n month,\n year,\n tagKey,\n tagValues,\n reportingBasis,\n }) =>\n `/v1/businesses/${businessId}/reports/profit-and-loss/exports/csv?${\n startDate ? `start_date=${encodeURIComponent(startDate)}` : ''\n }${endDate ? `&end_date=${encodeURIComponent(endDate)}` : ''}${\n month ? `&month=${month}` : ''\n }${year ? `&year=${year}` : ''}${\n reportingBasis ? `&reporting_basis=${reportingBasis}` : ''\n }${tagKey ? `&tag_key=${tagKey}` : ''}${\n tagValues ? `&tag_values=${tagValues}` : ''\n }`,\n)\n", "import { StatusOfSyncFromQuickbooks } from \"../../types/quickbooks\";\nimport { get, post } from \"./authenticated_http\";\n\nexport const syncFromQuickbooks = post<\n Record<string, unknown>,\n Record<string, unknown>,\n { businessId: string }\n>(({ businessId }) => `/v1/businesses/${businessId}/quickbooks/sync-from`);\n\nexport const statusOfSyncFromQuickbooks = get<\n { data: StatusOfSyncFromQuickbooks },\n { businessId: string }\n>(\n ({ businessId }) => `/v1/businesses/${businessId}/quickbooks/sync-from/status`\n);\n\nexport const initQuickbooksOAuth = post<\n {\n data: {\n type: \"Quickbooks_Authorization_Params\";\n redirect_url: string;\n };\n },\n Record<string, unknown>,\n { businessId: string }\n>(({ businessId }) => `/v1/businesses/${businessId}/quickbooks/authorize`);\n\nexport const unlinkQuickbooksConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n { businessId: string }\n>(({ businessId }) => `/v1/businesses/${businessId}/quickbooks/unlink`);\n\n/**\n * Lets user know if there exists an active Quickbooks connection or not\n */\nexport const statusOfQuickbooksConnection = get<\n {\n data: {\n is_connected: boolean;\n };\n },\n { businessId: string }\n>(\n ({ businessId }) =>\n `/v1/businesses/${businessId}/quickbooks/connection-status`\n);\n", "import { StatementOfCashFlow } from '../../types'\nimport { get } from './authenticated_http'\n\nexport const getStatementOfCashFlow = get<\n GetStatementOfCashFlowReturn,\n GetStatementOfCashFlowParams\n>(\n ({ businessId, startDate, endDate }: GetStatementOfCashFlowParams) =>\n `/v1/businesses/${businessId}/reports/cashflow-statement?start_date=${encodeURIComponent(\n startDate,\n )}&end_date=${encodeURIComponent(endDate)}`,\n)\n\nexport type GetStatementOfCashFlowReturn = {\n data?: StatementOfCashFlow\n error?: unknown\n}\n\nexport interface GetStatementOfCashFlowParams\n extends Record<string, string | undefined> {\n businessId: string\n startDate: string\n endDate: string\n}\n", "import { TaskTypes } from '../../types/tasks'\nimport { get, post } from './authenticated_http'\n\nexport const getTasks = get<{ data: TaskTypes[] }>(\n ({ businessId }) => `/v1/businesses/${businessId}/tasks`,\n)\n\nexport const submitResponseToTask = post<{ data: TaskTypes }>(\n ({ businessId, taskId }) =>\n `/v1/businesses/${businessId}/tasks/${taskId}/user-response`,\n)\n\nexport const markTaskAsComplete = post<{ data: TaskTypes }>(\n ({ businessId, taskId }) =>\n `/v1/businesses/${businessId}/tasks/${taskId}/complete`,\n)\n", "import { authenticate } from './layer/authenticate'\nimport { getBalanceSheet } from './layer/balance_sheet'\nimport {\n getBankTransactions,\n categorizeBankTransaction,\n matchBankTransaction,\n getBankTransactionsCsv,\n getBankTransactionMetadata,\n updateBankTransactionMetadata,\n listBankTransactionDocuments,\n uploadBankTransactionDocument,\n} from './layer/bankTransactions'\nimport { getBusiness } from './layer/business'\nimport { getCategories } from './layer/categories'\nimport {\n getChartOfAccounts,\n getLedgerAccountBalances,\n createAccount,\n updateAccount,\n getLedgerAccountsLines,\n getLedgerAccountsEntry,\n} from './layer/chart_of_accounts'\nimport { getJournal, createJournalEntries } from './layer/journal'\nimport {\n getLinkedAccounts,\n getPlaidLinkToken,\n getPlaidUpdateModeLinkToken,\n exchangePlaidPublicToken,\n unlinkPlaidItem,\n unlinkAccount,\n confirmConnection,\n denyConnection,\n breakPlaidItemConnection,\n syncConnection,\n updateConnectionStatus,\n} from './layer/linked_accounts'\nimport {\n getProfitAndLoss,\n getProfitAndLossSummaries,\n getProfitAndLossCsv,\n} from './layer/profit_and_loss'\nimport {\n syncFromQuickbooks,\n statusOfSyncFromQuickbooks,\n initQuickbooksOAuth,\n statusOfQuickbooksConnection,\n unlinkQuickbooksConnection,\n} from './layer/quickbooks'\nimport { getStatementOfCashFlow } from './layer/statement-of-cash-flow'\nimport { getTasks, submitResponseToTask } from './layer/tasks'\n\nexport const Layer = {\n authenticate,\n getBusiness,\n categorizeBankTransaction,\n matchBankTransaction,\n createAccount,\n updateAccount,\n getBalanceSheet,\n getBankTransactions,\n getBankTransactionsCsv,\n getBankTransactionMetadata,\n listBankTransactionDocuments,\n updateBankTransactionMetadata,\n uploadBankTransactionDocument,\n getCategories,\n getChartOfAccounts,\n getLedgerAccountBalances,\n getLedgerAccountsLines,\n getLedgerAccountsEntry,\n getProfitAndLoss,\n getProfitAndLossSummaries,\n getProfitAndLossCsv,\n getLinkedAccounts,\n getJournal,\n createJournalEntries,\n getPlaidLinkToken,\n getPlaidUpdateModeLinkToken,\n exchangePlaidPublicToken,\n unlinkAccount,\n unlinkPlaidItem,\n confirmConnection,\n denyConnection,\n getTasks,\n submitResponseToTask,\n breakPlaidItemConnection,\n syncConnection,\n updateConnectionStatus,\n getStatementOfCashFlow,\n syncFromQuickbooks,\n statusOfSyncFromQuickbooks,\n statusOfQuickbooksConnection,\n initQuickbooksOAuth,\n unlinkQuickbooksConnection,\n}\n", "import React, { useContext, useEffect } from 'react'\nimport { DrawerContext } from '../../contexts/DrawerContext'\nimport { useSizeClass } from '../../hooks/useWindowSize'\nimport { Drawer } from '../Drawer'\nimport { ToastsContainer } from '../Toast/Toast'\n\nconst DrawerWidget = () => {\n const { content, close } = useContext(DrawerContext)\n\n const { isMobile, isTablet } = useSizeClass()\n\n useEffect(() => {\n if (!isMobile && !isTablet && content) {\n close()\n }\n }, [isMobile])\n\n return (\n <Drawer isOpen={Boolean(content)} onClose={close}>\n {content}\n </Drawer>\n )\n}\n\nexport const GlobalWidgets = () => {\n return (\n <>\n <ToastsContainer />\n <DrawerWidget />\n </>\n )\n}\n", "import { createContext } from 'react'\nimport { useDrawer } from '../../hooks/useDrawer'\n\nexport type DrawerContextType = ReturnType<typeof useDrawer>\nexport const DrawerContext = createContext<DrawerContextType>({\n content: undefined,\n setContent: () => undefined,\n close: () => undefined,\n isClosing: false,\n finishClosing: () => undefined,\n})\n", "import { useState, useLayoutEffect, useMemo } from 'react'\nimport { BREAKPOINTS } from '../../config/general'\n\nexport const useWindowSize = () => {\n const [size, setSize] = useState([0, 0])\n useLayoutEffect(() => {\n function updateSize() {\n setSize([window.innerWidth, window.innerHeight])\n }\n\n window.addEventListener('resize', updateSize)\n\n updateSize()\n\n return () => window.removeEventListener('resize', updateSize)\n }, [])\n return size\n}\n\nexport type SizeClass = 'mobile' | 'tablet' | 'desktop'\n\ninterface UseSizeClass {\n value: SizeClass\n isMobile: boolean\n isTablet: boolean\n isDesktop: boolean\n}\n\nexport function useSizeClass(): UseSizeClass {\n const [width] = useWindowSize()\n\n const sizeClass = useMemo((): SizeClass => {\n switch (true) {\n case width <= BREAKPOINTS.MOBILE:\n return 'mobile'\n case width <= BREAKPOINTS.TABLET:\n return 'tablet'\n default:\n return 'desktop'\n }\n }, [width])\n\n return {\n value: sizeClass,\n isMobile: sizeClass === 'mobile',\n isTablet: sizeClass === 'tablet',\n isDesktop: sizeClass === 'desktop',\n }\n}\n", "export const DATE_FORMAT = 'LLL d, yyyy'\nexport const MONTH_DAY_FORMAT = 'LLL d'\nexport const TIME_FORMAT = 'p'\n\nexport const BREAKPOINTS = {\n TABLET: 760,\n MOBILE: 500,\n}\n", "import React, { useContext } from 'react'\nimport { DrawerContext } from '../../contexts/DrawerContext'\n\nconst DrawerBackground = ({\n isOpen,\n isClosing,\n onClose,\n}: {\n isOpen: boolean\n isClosing: boolean\n onClose: () => void\n}) => (\n <div\n className={`Layer__drawer-background ${isClosing ? 'closing' : ''} ${\n isOpen ? 'open' : ''\n }`}\n onClick={onClose}\n ></div>\n)\n\nexport const Drawer = ({\n isOpen,\n onClose,\n children,\n}: {\n isOpen: boolean\n onClose: () => void\n children: React.ReactNode\n}) => {\n const { isClosing, finishClosing } = useContext(DrawerContext)\n\n return (\n <>\n <DrawerBackground\n isOpen={isOpen}\n onClose={onClose}\n isClosing={isClosing}\n />\n <div\n className={`Layer__drawer ${isClosing ? 'closing' : ''} ${\n isOpen ? 'open' : ''\n }`}\n onTransitionEnd={({ propertyName }) => {\n if (propertyName === 'bottom' && isClosing) {\n finishClosing()\n }\n }}\n onClick={e => e.stopPropagation()}\n >\n {children}\n </div>\n </>\n )\n}\n", "import React, { forwardRef } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport classNames from 'classnames'\n\nexport interface ToastProps {\n id?: string\n content: string\n duration?: number\n isExiting?: boolean\n}\n\nconst Toast = (props: ToastProps & { isExiting: boolean }) => {\n const { id, content, isExiting } = props\n const { removeToast } = useLayerContext()\n\n return (\n <div\n id={id}\n className={classNames('Layer__toast', {\n enter: !isExiting,\n exit: isExiting,\n })}\n onClick={() => removeToast(props)}\n >\n <p>{content}</p>\n </div>\n )\n}\n\nexport const ToastsContainer = forwardRef((_props, ref) => {\n const { toasts } = useLayerContext()\n\n return (\n <div className='Layer__toasts-container'>\n {toasts.map((toast, idx) => (\n <Toast key={`layer-toast-${idx}`} {...toast} />\n ))}\n </div>\n )\n})\n", "import { createContext, useContext } from 'react'\nimport { ToastProps } from '../../components/Toast/Toast'\nimport { LayerContextValues } from '../../types'\nimport {\n LayerContextHelpers,\n LayerThemeConfig,\n} from '../../types/layer_context'\n\nexport const LayerContext = createContext<\n LayerContextValues &\n LayerContextHelpers & { setTheme: (theme: LayerThemeConfig) => void }\n>({\n auth: {\n access_token: '',\n expires_at: new Date(2000, 1, 1),\n expires_in: -1,\n token_type: '',\n },\n businessId: '',\n business: undefined,\n categories: [],\n apiUrl: '',\n theme: undefined,\n colors: {},\n usePlaidSandbox: true,\n setTheme: () => undefined,\n getColor: _shade => undefined,\n setLightColor: () => undefined,\n setDarkColor: () => undefined,\n setTextColor: () => undefined,\n setColors: () => undefined,\n onboardingStep: undefined,\n setOnboardingStep: () => undefined,\n environment: '',\n toasts: [],\n addToast: (toast: ToastProps) => undefined,\n removeToast: () => undefined,\n onError: () => undefined,\n touch: () => undefined,\n read: () => undefined,\n syncTimestamps: {},\n readTimestamps: {},\n hasBeenTouched: () => false,\n eventCallbacks: {},\n})\n\nexport const useLayerContext = () => useContext(LayerContext)\n", "import React, { useState } from 'react'\nimport { DataModel } from '../../types/general'\n\ntype UseDataSync = () => {\n touch: (model: DataModel) => void\n read: (model: DataModel, cacheKey: string) => void\n syncTimestamps: Partial<Record<DataModel, number>>\n readTimestamps: Partial<Record<string, { t: number; m: DataModel }>>\n hasBeenTouched: (cacheKey: string) => boolean\n}\n\nconst ALL_TOUCHABLE = [\n DataModel.BUSINESS,\n DataModel.BANK_TRANSACTIONS,\n DataModel.LINKED_ACCOUNTS,\n DataModel.CHART_OF_ACCOUNTS,\n DataModel.JOURNAL,\n]\n\nconst DEPENDENCIES: Partial<Record<DataModel, DataModel[]>> = {\n [DataModel.BALANCE_SHEET]: ALL_TOUCHABLE,\n [DataModel.CHART_OF_ACCOUNTS]: ALL_TOUCHABLE,\n [DataModel.JOURNAL]: ALL_TOUCHABLE,\n [DataModel.LEDGER_ACCOUNTS]: ALL_TOUCHABLE,\n [DataModel.LINKED_ACCOUNTS]: ALL_TOUCHABLE,\n [DataModel.PROFIT_AND_LOSS]: ALL_TOUCHABLE,\n [DataModel.STATEMENT_OF_CASH_FLOWS]: ALL_TOUCHABLE,\n}\n\nlet readTimestampsG = {}\n\nexport const useDataSync: UseDataSync = () => {\n const initialTimestamp = Date.now()\n const [syncTimestamps, setSyncTimestamps] = useState<\n Partial<Record<DataModel, number>>\n >({\n [DataModel.BALANCE_SHEET]: initialTimestamp,\n [DataModel.CHART_OF_ACCOUNTS]: initialTimestamp,\n [DataModel.JOURNAL]: initialTimestamp,\n [DataModel.LEDGER_ACCOUNTS]: initialTimestamp,\n [DataModel.LINKED_ACCOUNTS]: initialTimestamp,\n [DataModel.PROFIT_AND_LOSS]: initialTimestamp,\n [DataModel.STATEMENT_OF_CASH_FLOWS]: initialTimestamp,\n })\n const [readTimestamps, setReadTimestamps] = useState<\n Partial<Record<string, { t: number; m: DataModel }>>\n >({})\n\n const touch = (model: DataModel) => {\n setSyncTimestamps({\n ...syncTimestamps,\n [model]: Date.now(),\n })\n }\n\n const read = (model: DataModel, cacheKey: string) => {\n readTimestampsG = {\n ...readTimestampsG,\n [cacheKey]: {\n t: Date.now(),\n m: model,\n },\n }\n setReadTimestamps({ ...readTimestampsG })\n }\n\n const hasBeenTouched = (cacheKey: string) => {\n const lastRead =\n cacheKey in readTimestamps ? readTimestamps[cacheKey] : undefined\n\n if (!lastRead || !lastRead?.m || !lastRead?.t) {\n return false\n }\n\n return Boolean(\n DEPENDENCIES[lastRead!.m]?.find(dep => {\n return (\n dep in syncTimestamps &&\n Boolean(syncTimestamps[dep]) &&\n (syncTimestamps[dep] as number) > (lastRead!.t as number)\n )\n }),\n )\n }\n\n return {\n touch,\n read,\n syncTimestamps,\n readTimestamps,\n hasBeenTouched,\n }\n}\n", "import React, { ReactNode, useState } from 'react'\n\ntype UseDrawer = () => {\n content?: ReactNode\n setContent: (content: ReactNode) => void\n finishClosing: () => void\n isClosing: boolean\n close: () => void\n}\n\nexport const useDrawer: UseDrawer = () => {\n const [content, setContent] = useState<ReactNode>(undefined)\n const [isClosing, setIsClosing] = useState(false)\n\n const close = () => {\n setIsClosing(true)\n }\n\n const finishClosing = () => {\n setContent(undefined)\n setIsClosing(false)\n }\n\n return {\n content,\n setContent,\n finishClosing,\n isClosing,\n close,\n }\n}\n", "import React, { ReactNode } from 'react'\nimport { BankTransactionsContext, useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { useBankTransactions } from '../../hooks/useBankTransactions'\n\ninterface BankTransactionsProviderProps {\n children: ReactNode\n}\n\nexport const BankTransactionsProvider = ({\n children,\n}: BankTransactionsProviderProps) => {\n const bankTransactionsContextData = useBankTransactions()\n return (\n <BankTransactionsContext.Provider value={bankTransactionsContextData}>\n {children}\n </BankTransactionsContext.Provider>\n )\n}\n", "import { createContext, useContext } from 'react'\nimport { useBankTransactions } from '../../hooks/useBankTransactions'\nimport { DisplayState } from '../../types'\n\nexport type BankTransactionsContextType = ReturnType<typeof useBankTransactions>\nexport const BankTransactionsContext =\n createContext<BankTransactionsContextType>({\n data: undefined,\n isLoading: false,\n loadingStatus: 'initial',\n isValidating: false,\n error: undefined,\n refetch: () => {},\n categorize: () => Promise.resolve(undefined),\n match: () => Promise.resolve(undefined),\n filters: undefined,\n setFilters: () => {},\n metadata: {\n pagination: undefined,\n },\n updateOneLocal: () => undefined,\n removeAfterCategorize: () => undefined,\n activate: () => undefined,\n display: DisplayState.review,\n fetchMore: () => {},\n hasMore: false,\n })\n\nexport const useBankTransactionsContext = () =>\n useContext(BankTransactionsContext)\n", "import { Categorization, CategorizationStatus, Category } from './categories'\nimport { S3PresignedUrl } from './general'\n\nexport enum Direction {\n CREDIT = 'CREDIT',\n DEBIT = 'DEBIT',\n}\n\nexport enum BankTransactionMatchType {\n CONFIRM_MATCH = 'Confirm_Match',\n}\n\nexport enum DisplayState {\n review = 'review',\n categorized = 'categorized',\n}\n\n// This isn't my favorite but BankTransaction contains much\n// more than we're using right now.\nexport interface BankTransaction extends Record<string, unknown> {\n type: 'Bank_Transaction'\n account_name?: string\n business_id: string\n recently_categorized?: boolean\n id: string\n date: string\n source: string\n source_transaction_id: string\n source_account_id: string\n imported_at: string\n description: string | null\n amount: number\n direction: Direction\n counterparty_name: string\n category: Category\n categorization_status: CategorizationStatus\n categorization_flow: Categorization | null\n categorization_method: string\n error?: string\n processing?: boolean\n suggested_matches?: SuggestedMatch[]\n match?: BankTransactionMatch\n}\n\nexport interface SuggestedMatch {\n id: string\n matchType: string\n details: {\n amount: number\n date: string\n description: string\n id: string\n type: string\n }\n}\n\nexport interface BankTransactionMatch {\n bank_transaction: BankTransaction\n id: string\n match_type?: string\n details: {\n amount: number\n date: string\n description: string\n id: string\n type: string\n }\n}\n\nexport interface BankTransactionMetadata {\n memo: string | null\n}\n\nexport interface DocumentS3Urls {\n type: 'Document_S3_Urls'\n documentUrls: S3PresignedUrl[]\n}\n\nexport interface FileMetadata {\n type: 'File_Metadata'\n id: string | null\n fileType: string\n fileName: string\n documentType: string\n}\n", "export enum CategorizationStatus {\n PENDING = 'PENDING',\n READY_FOR_INPUT = 'READY_FOR_INPUT',\n LAYER_REVIEW = 'LAYER_REVIEW',\n CATEGORIZED = 'CATEGORIZED',\n SPLIT = 'SPLIT',\n JOURNALING = 'JOURNALING',\n MATCHED = 'MATCHED',\n}\nexport interface CategoryEntry {\n amount?: number\n category: Category\n}\n\nexport interface Category {\n id: string\n type: string\n display_name: string\n category: string\n stable_name?: string\n subCategories?: Category[]\n entries?: CategoryEntry[]\n}\n\nexport enum CategorizationType {\n AUTO = 'AUTO',\n ASK_FROM_SUGGESTIONS = 'ASK_FROM_SUGGESTIONS',\n MEALS = 'MEALS',\n BUSINESS_TRAVEL_TRANSPORTATION = 'BUSINESS_TRAVEL_TRANSPORTATION',\n}\n\nexport interface AutoCategorization {\n type: CategorizationType.AUTO\n category: Category\n}\nexport interface SuggestedCategorization {\n type: CategorizationType\n suggestions: Category[]\n}\nexport type Categorization = AutoCategorization | SuggestedCategorization\n\nexport type AccountIdentifierPayloadObject =\n | {\n type: 'StableName'\n stable_name: string\n }\n | {\n type: 'AccountId'\n id: string\n }\n | {\n type: 'Exclusion'\n exclusion_type: string\n }\n\nexport type SingleCategoryUpdate = {\n type: 'Category'\n category: AccountIdentifierPayloadObject\n}\nexport type SplitCategoryUpdate = {\n type: 'Split'\n entries: {\n category: string | AccountIdentifierPayloadObject\n amount: number\n }[]\n}\nexport type CategoryUpdate = SingleCategoryUpdate | SplitCategoryUpdate\n\nexport function hasSuggestions(\n categorization: Categorization | null,\n): categorization is SuggestedCategorization {\n return (\n categorization != null &&\n (categorization as SuggestedCategorization).suggestions !== undefined &&\n (categorization as SuggestedCategorization).suggestions.length > 0\n )\n}\n", "import { useEffect, useMemo, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport {\n BankTransaction,\n CategorizationStatus,\n CategoryUpdate,\n} from '../../types'\nimport {\n BankTransactionMatchType,\n DisplayState,\n} from '../../types/bank_transactions'\nimport { DataModel, LoadedStatus } from '../../types/general'\nimport { BankTransactionFilters, UseBankTransactions } from './types'\nimport {\n applyAccountFilter,\n applyAmountFilter,\n applyCategorizationStatusFilter,\n applyDirectionFilter,\n appplyDateRangeFilter,\n collectAccounts,\n} from './utils'\nimport useSWRInfinite from 'swr/infinite'\n\nexport const useBankTransactions: UseBankTransactions = params => {\n const {\n auth,\n businessId,\n apiUrl,\n addToast,\n touch,\n read,\n syncTimestamps,\n hasBeenTouched,\n eventCallbacks,\n } = useLayerContext()\n const { scope = undefined } = params ?? {}\n const [filters, setTheFilters] = useState<BankTransactionFilters | undefined>(\n scope ? { categorizationStatus: scope } : undefined,\n )\n const display = useMemo(() => {\n if (filters?.categorizationStatus === DisplayState.review) {\n return DisplayState.review\n }\n\n return DisplayState.categorized\n }, [filters?.categorizationStatus])\n\n const [active, setActive] = useState(false)\n const [loadingStatus, setLoadingStatus] = useState<LoadedStatus>('initial')\n\n const getKey = (_index: number, prevData: any) => {\n if (!auth?.access_token || !active) {\n return [false, undefined]\n }\n\n if (!prevData?.meta?.pagination?.cursor) {\n return [\n businessId &&\n auth?.access_token &&\n `bank-transactions${\n filters?.categorizationStatus\n ? `-scope-${filters?.categorizationStatus}`\n : ''\n }-${businessId}`,\n undefined,\n ]\n }\n\n return [\n businessId &&\n auth?.access_token &&\n `bank-transactions${\n filters?.categorizationStatus\n ? `-scope-${filters?.categorizationStatus}`\n : ''\n }-${businessId}-${prevData.meta.pagination.cursor}`,\n prevData.meta.pagination.cursor,\n ]\n }\n\n const {\n data: rawResponseData,\n isLoading,\n isValidating,\n error: responseError,\n mutate,\n size,\n setSize,\n } = useSWRInfinite(\n getKey,\n async ([query, nextCursor]) => {\n if (auth?.access_token) {\n return Layer.getBankTransactions(apiUrl, auth?.access_token, {\n params: {\n businessId,\n cursor: nextCursor,\n categorized: filters?.categorizationStatus\n ? filters?.categorizationStatus === DisplayState.categorized\n ? 'true'\n : 'false'\n : '',\n },\n }).call(false)\n }\n\n return {}\n },\n {\n initialSize: 1,\n revalidateFirstPage: false,\n },\n )\n\n const data: BankTransaction[] | undefined = useMemo(() => {\n if (rawResponseData && rawResponseData.length > 0) {\n return rawResponseData\n ?.map(x => x?.data)\n .flat()\n .filter(x => !!x) as unknown as BankTransaction[]\n }\n\n return undefined\n }, [rawResponseData])\n\n const lastMetadata = useMemo(() => {\n if (rawResponseData && rawResponseData.length > 0) {\n return rawResponseData[rawResponseData.length - 1].meta\n }\n\n return undefined\n }, [rawResponseData])\n\n const hasMore = useMemo(() => {\n if (rawResponseData && rawResponseData.length > 0) {\n const lastElement = rawResponseData[rawResponseData.length - 1]\n return Boolean(\n lastElement.meta?.pagination?.cursor &&\n lastElement.meta?.pagination?.has_more,\n )\n }\n\n return false\n }, [rawResponseData])\n\n const accountsList = useMemo(\n () => (data ? collectAccounts(data) : []),\n [data],\n )\n\n useEffect(() => {\n if (isLoading && loadingStatus === 'initial') {\n setLoadingStatus('loading')\n return\n }\n\n if (!isLoading && loadingStatus === 'loading') {\n setLoadingStatus('complete')\n return\n }\n }, [isLoading])\n\n const activate = () => {\n setActive(true)\n }\n\n const setFilters = (value?: Partial<BankTransactionFilters>) => {\n setTheFilters({\n ...filters,\n ...(value ?? {}),\n })\n }\n\n const filteredData = useMemo(() => {\n let filtered = data\n\n if (!filtered) {\n return\n }\n\n if (filters?.amount?.min || filters?.amount?.max) {\n filtered = applyAmountFilter(filtered, filters.amount)\n }\n\n if (filters?.account) {\n filtered = applyAccountFilter(filtered, filters.account)\n }\n\n if (filters?.direction) {\n filtered = applyDirectionFilter(filtered, filters.direction)\n }\n\n if (filters?.categorizationStatus) {\n filtered = applyCategorizationStatusFilter(\n filtered,\n filters.categorizationStatus,\n )\n }\n\n if (filters?.dateRange?.startDate || filters?.dateRange?.endDate) {\n filtered = appplyDateRangeFilter(filtered, filters?.dateRange)\n }\n\n return filtered\n }, [filters, data])\n\n const categorize = (\n id: BankTransaction['id'],\n newCategory: CategoryUpdate,\n notify?: boolean,\n ) => {\n const foundBT = data?.find(x => x.business_id === businessId && x.id === id)\n if (foundBT) {\n updateOneLocal({ ...foundBT, processing: true, error: undefined })\n }\n\n return Layer.categorizeBankTransaction(apiUrl, auth.access_token, {\n params: { businessId, bankTransactionId: id },\n body: newCategory,\n })\n .then(({ data: newBT, errors }) => {\n if (newBT) {\n newBT.recently_categorized = true\n updateOneLocal(newBT)\n }\n if (errors) {\n console.error(errors)\n throw errors\n }\n if (newBT?.recently_categorized === true && notify) {\n addToast({ content: 'Transaction saved' })\n }\n })\n .catch(err => {\n const newBT = data?.find(\n x => x.business_id === businessId && x.id === id,\n )\n\n if (newBT) {\n updateOneLocal({\n ...newBT,\n error: err.message,\n processing: false,\n })\n }\n })\n .finally(() => {\n touch(DataModel.BANK_TRANSACTIONS)\n eventCallbacks?.onTransactionCategorized?.(id)\n })\n }\n\n const match = (\n id: BankTransaction['id'],\n matchId: BankTransaction['id'],\n notify?: boolean,\n ) => {\n const foundBT = data?.find(x => x.business_id === businessId && x.id === id)\n if (foundBT) {\n updateOneLocal({ ...foundBT, processing: true, error: undefined })\n }\n\n return Layer.matchBankTransaction(apiUrl, auth.access_token, {\n params: { businessId, bankTransactionId: id },\n body: { match_id: matchId, type: BankTransactionMatchType.CONFIRM_MATCH },\n })\n .then(({ data: bt, errors }) => {\n const newBT = data?.find(\n x => x.business_id === businessId && x.id === id,\n )\n\n if (newBT) {\n newBT.recently_categorized = true\n newBT.match = bt\n newBT.categorization_status = CategorizationStatus.MATCHED\n updateOneLocal(newBT)\n }\n if (errors) {\n console.error(errors)\n throw errors\n }\n\n if (newBT?.recently_categorized === true && notify) {\n addToast({ content: 'Transaction saved' })\n }\n })\n .catch(err => {\n const newBT = data?.find(\n x => x.business_id === businessId && x.id === id,\n )\n\n if (newBT) {\n updateOneLocal({\n ...newBT,\n error: err.message,\n processing: false,\n })\n }\n })\n .finally(() => {\n touch(DataModel.BANK_TRANSACTIONS)\n eventCallbacks?.onTransactionCategorized?.(id)\n })\n }\n\n const updateOneLocal = (newBankTransaction: BankTransaction) => {\n const updatedData = rawResponseData?.map(page => {\n return {\n ...page,\n data: page.data?.map(bt =>\n bt.id === newBankTransaction.id ? newBankTransaction : bt,\n ),\n }\n })\n mutate(updatedData, { revalidate: false })\n }\n\n const removeAfterCategorize = (bankTransaction: BankTransaction) => {\n const updatedData = rawResponseData?.map(page => {\n return {\n ...page,\n data: page.data?.filter(bt => bt.id !== bankTransaction.id),\n }\n })\n mutate(updatedData, { revalidate: false })\n }\n\n const refetch = () => {\n mutate()\n }\n\n const fetchMore = () => {\n if (hasMore) {\n setSize(size + 1)\n }\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (isLoading || isValidating) {\n read(DataModel.BANK_TRANSACTIONS, 'bank-transactions')\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (hasBeenTouched('bank-transactions')) {\n refetch()\n }\n }, [syncTimestamps])\n\n return {\n data: filteredData,\n metadata: lastMetadata,\n loadingStatus,\n isLoading,\n isValidating,\n refetch,\n error: responseError,\n categorize,\n match,\n updateOneLocal,\n removeAfterCategorize,\n filters,\n setFilters,\n accountsList,\n activate,\n display,\n fetchMore,\n hasMore,\n }\n}\n", "import { CategorizationStatus } from '../../types'\n\nexport type MobileComponentType = 'regularList' | 'mobileList'\n\nexport const CategorizedCategories = [\n CategorizationStatus.CATEGORIZED,\n CategorizationStatus.JOURNALING,\n CategorizationStatus.SPLIT,\n CategorizationStatus.MATCHED,\n]\n\nexport const ReviewCategories = [\n CategorizationStatus.READY_FOR_INPUT,\n CategorizationStatus.LAYER_REVIEW,\n]\n", "import { BankTransaction, DisplayState } from '../../types'\nimport { CategorizedCategories, ReviewCategories } from './constants'\n\nexport const filterVisibility = (\n scope: DisplayState,\n bankTransaction: BankTransaction,\n) => {\n const categorized = CategorizedCategories.includes(\n bankTransaction.categorization_status,\n )\n const inReview = ReviewCategories.includes(\n bankTransaction.categorization_status,\n )\n\n return (\n (scope === DisplayState.review && inReview) ||\n (scope === DisplayState.categorized && categorized)\n )\n}\n\nexport const isCategorized = (bankTransaction: BankTransaction) =>\n CategorizedCategories.includes(bankTransaction.categorization_status)\n", "import { filterVisibility } from '../../components/BankTransactions/utils'\nimport { BankTransaction, DateRange, Direction, DisplayState } from '../../types'\nimport { AccountItem, NumericRangeFilter } from './types'\nimport { parseISO } from 'date-fns'\n\nexport const collectAccounts = (transactions?: BankTransaction[]) => {\n const accounts: AccountItem[] = []\n if (!transactions) {\n return accounts\n }\n\n transactions.forEach(x => {\n if (!accounts.find(y => y.id === x.source_account_id)) {\n accounts.push({\n id: x.source_account_id,\n name: x.account_name || '',\n })\n }\n })\n\n return accounts.sort((a, b) => a.name.localeCompare(b.name))\n}\n\nexport const uniqAccountsList = (arr: AccountItem[], track = new Set()) =>\n arr.filter(({ id }) => (track.has(id) ? false : track.add(id)))\n\nexport const applyAmountFilter = (\n data?: BankTransaction[],\n filter?: NumericRangeFilter,\n) => {\n return data?.filter(x => {\n if (\n (filter?.min || filter?.min === 0) &&\n (filter?.max || filter?.max === 0)\n ) {\n return x.amount >= filter.min * 100 && x.amount <= filter.max * 100\n }\n\n if (filter?.min || filter?.min === 0) {\n return x.amount >= filter.min * 100\n }\n\n if (filter?.max || filter?.max === 0) {\n return x.amount <= filter.max * 100\n }\n })\n}\n\nexport const applyAccountFilter = (\n data?: BankTransaction[],\n filter?: string[],\n) => data?.filter(x => filter && filter.includes(x.source_account_id))\n\nexport const applyDirectionFilter = (\n data?: BankTransaction[],\n filter?: Direction[],\n) => {\n if (!filter) {\n return data\n }\n const normalizedFilter = filter.map(x => x.toLowerCase())\n\n return data?.filter(x =>\n normalizedFilter.includes(x.direction?.toLowerCase()),\n )\n}\n\nexport const applyCategorizationStatusFilter = (\n data?: BankTransaction[],\n filter?: DisplayState,\n) => {\n if (!filter) {\n return data\n }\n\n return data?.filter(\n tx =>\n filterVisibility(filter, tx) ||\n (filter === DisplayState.review && tx.recently_categorized) ||\n (filter === DisplayState.categorized && tx.recently_categorized),\n )\n}\n\nexport const appplyDateRangeFilter = (\n data?: BankTransaction[],\n filter?: Partial<DateRange>,\n) => {\n return data?.filter(x => {\n const txDate = parseISO(x.date)\n if (filter?.startDate && filter?.endDate) {\n return txDate >= filter.startDate && txDate <= filter.endDate\n }\n\n if (filter?.startDate) {\n return txDate >= filter.startDate\n }\n\n if (filter?.endDate) {\n return txDate <= filter.endDate\n }\n })\n}\n", "export const SHADES = {\n 50: { s: 1, l: 98 },\n 100: { s: 1, l: 96 },\n 200: { s: 1, l: 94 },\n 300: { s: 2, l: 92 },\n 500: { s: 5, l: 53 },\n 600: { s: 7, l: 40 },\n 700: { s: 9, l: 27 },\n 800: { s: 12, l: 20 },\n 1000: { s: 20, l: 7 },\n}\n\nexport const COLORS = {\n dark: {\n h: 0,\n s: 0,\n l: 7,\n },\n light: {\n h: 0,\n s: 0,\n l: 100,\n },\n}\n", "import { COLORS, SHADES } from '../config/theme'\nimport {\n LayerThemeConfig,\n ColorConfig,\n ColorRGBConfig,\n ColorRGBNumberConfig,\n ColorHSLNumberConfig,\n ColorsPalette,\n} from '../types/layer_context'\n\n/**\n * Convert `theme` config set in Provider into component styles.\n *\n * @param {LayerThemeConfig} theme - the theme set with provider\n */\nexport const parseStylesFromThemeConfig = (theme?: LayerThemeConfig) => {\n let styles = {}\n if (!theme) {\n return styles\n }\n\n if (theme.colors) {\n const darkColor = parseColorFromTheme('dark', theme.colors.dark)\n const lightColor = parseColorFromTheme('light', theme.colors.light)\n const textColor = parseTextColorFromTheme(theme.colors.text)\n styles = { ...styles, ...darkColor, ...lightColor, ...textColor }\n }\n\n return styles\n}\n\nconst parseTextColorFromTheme = (color?: ColorConfig) => {\n if (!color) {\n return {}\n }\n\n try {\n if ('hex' in color) {\n return { '--text-color-primary': color.hex }\n }\n\n return {}\n } catch (_err) {\n return {}\n }\n}\n\n/**\n * Parse the color from theme config into a CSS variables.\n * @param {string} colorName\n * @param {ColorConfig} color\n */\nconst parseColorFromTheme = (colorName: string, color?: ColorConfig) => {\n if (!color) {\n return {}\n }\n\n try {\n if ('h' in color && 's' in color && 'l' in color) {\n return {\n [`--color-${colorName}-h`]: color.h,\n [`--color-${colorName}-s`]: color.s,\n [`--color-${colorName}-l`]: color.l,\n }\n }\n\n if ('r' in color && 'g' in color && 'b' in color) {\n const { h, s, l } = rgbToHsl(color)\n return {\n [`--color-${colorName}-h`]: h,\n [`--color-${colorName}-s`]: `${s}%`,\n [`--color-${colorName}-l`]: `${l}%`,\n }\n }\n\n if ('hex' in color) {\n const rgb = hexToRgb(color.hex)\n if (!rgb) {\n return {}\n }\n const { h, s, l } = rgbToHsl({\n r: rgb.r.toString(),\n g: rgb.g.toString(),\n b: rgb.b.toString(),\n })\n return {\n [`--color-${colorName}-h`]: h,\n [`--color-${colorName}-s`]: `${s}%`,\n [`--color-${colorName}-l`]: `${l}%`,\n }\n }\n\n return {}\n } catch (_err) {\n return {}\n }\n}\n\n/**\n * Parse the color from theme config into a CSS variables.\n * @param {string} colorName\n * @param {ColorConfig} color\n */\nconst parseColorFromThemeToHsl = (\n color?: ColorConfig,\n): ColorHSLNumberConfig | undefined => {\n if (!color) {\n return\n }\n\n try {\n if ('h' in color && 's' in color && 'l' in color) {\n return {\n h: Number(color.h),\n s: Number(color.s),\n l: Number(color.l),\n }\n }\n\n if ('r' in color && 'g' in color && 'b' in color) {\n const { h, s, l } = rgbToHsl(color)\n return {\n h: h,\n s: s,\n l: l,\n }\n }\n\n if ('hex' in color) {\n const rgb = hexToRgb(color.hex)\n if (!rgb) {\n return undefined\n }\n const { h, s, l } = rgbToHsl({\n r: rgb.r.toString(),\n g: rgb.g.toString(),\n b: rgb.b.toString(),\n })\n return {\n h: h,\n s: s,\n l: l,\n }\n }\n\n return\n } catch (_err) {\n return\n }\n}\n\n/**\n * Convert RGB to HSL\n */\nconst rgbToHsl = (color: ColorRGBConfig) => {\n let r = Number(color.r)\n let g = Number(color.g)\n let b = Number(color.b)\n r /= 255\n g /= 255\n b /= 255\n const l = Math.max(r, g, b)\n const s = l - Math.min(r, g, b)\n const h = s\n ? l === r\n ? (g - b) / s\n : l === g\n ? 2 + (b - r) / s\n : 4 + (r - g) / s\n : 0\n return {\n h: 60 * h < 0 ? 60 * h + 360 : 60 * h,\n s: 100 * (s ? (l <= 0.5 ? s / (2 * l - s) : s / (2 - (2 * l - s))) : 0),\n l: (100 * (2 * l - s)) / 2,\n }\n}\n\n/**\n * Convert HEX to RGB\n */\nconst hexToRgb = (hex: string) => {\n const values = hex\n .replace(\n /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i,\n (m, r, g, b) => '#' + r + r + g + g + b + b,\n )\n .substring(1)\n .match(/.{2}/g)\n ?.map(x => parseInt(x, 16))\n\n if (!values) {\n return\n }\n\n return {\n r: values[0],\n g: values[1],\n b: values[2],\n }\n}\n\n/**\n * Build same color palette in RGB, HSL and HEX as CSS variables.\n */\nexport const buildColorsPalette = (theme?: LayerThemeConfig): ColorsPalette => {\n const darkColor = parseColorFromThemeToHsl(theme?.colors?.dark) ?? COLORS.dark\n const lightColor =\n parseColorFromThemeToHsl(theme?.colors?.light) ?? COLORS.light\n\n return {\n 50: buildColorShade(50, darkColor),\n 100: buildColorShade(100, darkColor),\n 200: buildColorShade(200, darkColor),\n 300: buildColorShade(300, darkColor),\n 400: {\n hsl: lightColor,\n rgb: hslToRgb(lightColor),\n hex: hslToHex(lightColor),\n },\n 500: buildColorShade(500, darkColor),\n 600: buildColorShade(600, darkColor),\n 700: buildColorShade(700, darkColor),\n 800: buildColorShade(800, darkColor),\n 900: {\n hsl: darkColor,\n rgb: hslToRgb(darkColor),\n hex: hslToHex(darkColor),\n },\n 1000: buildColorShade(1000, darkColor),\n }\n}\n\n/**\n * Build color shade based on the dark color (HSL)\n * and config values for S and L.\n */\nconst buildColorShade = (\n shade: keyof typeof SHADES,\n darkColorHsl: ColorHSLNumberConfig,\n) => {\n const hsl = { h: darkColorHsl.h, ...SHADES[shade] }\n const rgb = hslToRgb(hsl)\n const hex = hslToHex(hsl)\n\n return { hsl, rgb, hex }\n}\n/**\n * Convert Hue into RGB\n */\nconst hueToRgb = (p: number, q: number, t: number) => {\n if (t < 0) t += 1\n if (t > 1) t -= 1\n if (t < 1.0 / 6.0) return p + (q - p) * 6 * t\n if (t < 1.0 / 2.0) return q\n if (t < 2.0 / 3.0) return p + (q - p) * (2.0 / 3.0 - t) * 6\n return p\n}\n\n/**\n * Convert HSL to RGB\n */\nconst hslToRgb = (hsl: ColorHSLNumberConfig): ColorRGBNumberConfig => {\n let r, g, b\n let l = hsl.l / 100\n let s = hsl.s / 100\n\n if (hsl.s === 0) {\n r = g = b = l\n } else {\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s\n const p = 2 * l - q\n r = hueToRgb(p, q, hsl.h + 1.0 / 3.0)\n g = hueToRgb(p, q, hsl.h)\n b = hueToRgb(p, q, hsl.h - 1.0 / 3.0)\n }\n\n return {\n r: Math.round(r * 255),\n g: Math.round(g * 255),\n b: Math.round(b * 255),\n }\n}\n\n/**\n * Convert HSL to HEX\n */\nconst hslToHex = (hsl: ColorHSLNumberConfig): string => {\n const l = hsl.l / 100\n const s = hsl.s\n const a = (s * Math.min(l, 1 - l)) / 100\n const f = (n: number) => {\n const k = (n + hsl.h / 30) % 12\n const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)\n return Math.round(255 * color)\n .toString(16)\n .padStart(2, '0')\n }\n return `#${f(0)}${f(8)}${f(4)}`\n}\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { LinkedAccountsContext } from '../../contexts/LinkedAccountsContext'\nimport { LinkedAccountsProvider } from '../../providers/LinkedAccountsProvider'\nimport { Container } from '../Container'\nimport { ConnectAccount } from './ConnectAccount'\n\nconst COLLAPSED_STYLE = {\n maxHeight: 0,\n opacity: 0.2,\n transform: 'scale(0.96)',\n overflow: 'hidden',\n}\n\nconst EXPANDED_STYLE = {\n maxHeight: 1000,\n opacity: 1,\n transform: 'scale(1)',\n overflow: 'hidden',\n}\n\nexport interface OnboardingProps {\n onTransactionsToReviewClick?: () => void\n}\n\nexport const Onboarding = (props: OnboardingProps) => (\n <LinkedAccountsProvider>\n <OnboardingContent {...props} />\n </LinkedAccountsProvider>\n)\n\nexport const OnboardingContent = ({\n onTransactionsToReviewClick,\n}: OnboardingProps) => {\n const { onboardingStep, setOnboardingStep } = useLayerContext()\n\n const [style, setStyle] = useState(\n onboardingStep ? EXPANDED_STYLE : COLLAPSED_STYLE,\n )\n const { data, loadingStatus } = useContext(LinkedAccountsContext)\n\n useEffect(() => {\n if (\n data &&\n data?.length === 0 &&\n loadingStatus === 'complete' &&\n !onboardingStep\n ) {\n setOnboardingStep('connectAccount')\n return\n }\n\n if (\n data &&\n data.length > 0 &&\n loadingStatus === 'complete' &&\n onboardingStep === 'connectAccount'\n ) {\n setOnboardingStep('complete')\n }\n }, [data, loadingStatus])\n\n useEffect(() => {\n if (onboardingStep && style.maxHeight !== 1000) {\n setTimeout(() => {\n setStyle(EXPANDED_STYLE)\n }, 500)\n }\n }, [onboardingStep])\n\n if (!onboardingStep) {\n return null\n }\n\n return (\n <Container name='onboarding' style={style}>\n <div className='Layer__onboarding__content'>\n <ConnectAccount\n onboardingStep={onboardingStep}\n onTransactionsToReviewClick={onTransactionsToReviewClick}\n />\n </div>\n </Container>\n )\n}\n", "import { createContext } from 'react'\nimport { useLinkedAccounts } from '../../hooks/useLinkedAccounts'\n\nexport type LinkedAccountsContextType = ReturnType<typeof useLinkedAccounts>\nexport const LinkedAccountsContext = createContext<LinkedAccountsContextType>({\n data: undefined,\n isLoading: false,\n loadingStatus: 'initial',\n isValidating: false,\n error: undefined,\n updateConnectionStatus: () => {},\n addConnection: () => {},\n removeConnection: () => {},\n repairConnection: () => {},\n refetchAccounts: () => {},\n unlinkAccount: () => {},\n denyAccount: () => {},\n confirmAccount: () => {},\n breakConnection: () => {},\n syncAccounts: () => {},\n})\n", "import React, { ReactNode } from 'react'\nimport { LinkedAccountsContext } from '../../contexts/LinkedAccountsContext'\nimport { useLinkedAccounts } from '../../hooks/useLinkedAccounts'\n\ninterface LinkedAccountsProviderProps {\n children: ReactNode\n}\n\nexport const LinkedAccountsProvider = ({\n children,\n}: LinkedAccountsProviderProps) => {\n const linkedAccountsContextData = useLinkedAccounts()\n return (\n <LinkedAccountsContext.Provider value={linkedAccountsContextData}>\n {children}\n </LinkedAccountsContext.Provider>\n )\n}\n", "import { useEffect, useState } from 'react'\nimport { PlaidLinkOnSuccessMetadata, usePlaidLink } from 'react-plaid-link'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { DataModel, LoadedStatus } from '../../types/general'\nimport { LinkedAccount, Source } from '../../types/linked_accounts'\nimport { LINKED_ACCOUNTS_MOCK_DATA } from './mockData'\nimport useSWR from 'swr'\n\ntype UseLinkedAccounts = () => {\n data?: LinkedAccount[]\n isLoading: boolean\n loadingStatus: LoadedStatus\n isValidating: boolean\n error: unknown\n addConnection: (source: Source) => void\n removeConnection: (source: Source, sourceId: string) => void // means, \"unlink institution\"\n repairConnection: (source: Source, sourceId: string) => void\n updateConnectionStatus: () => void\n refetchAccounts: () => void\n syncAccounts: () => void\n unlinkAccount: (source: Source, accountId: string) => void\n confirmAccount: (source: Source, accountId: string) => void\n denyAccount: (source: Source, accountId: string) => void\n\n // Only works in non-production environments for test purposes\n breakConnection: (source: Source, connectionExternalId: string) => void\n}\n\nconst DEBUG = true\nconst USE_MOCK_RESPONSE_DATA = false\n\ntype LinkMode = 'update' | 'add'\n\nexport const useLinkedAccounts: UseLinkedAccounts = () => {\n const {\n auth,\n businessId,\n apiUrl,\n usePlaidSandbox,\n touch,\n read,\n syncTimestamps,\n hasBeenTouched,\n } = useLayerContext()\n const [linkToken, setLinkToken] = useState<string | null>(null)\n const [loadingStatus, setLoadingStatus] = useState<LoadedStatus>('initial')\n const USE_PLAID_SANDBOX = usePlaidSandbox ?? true\n const [linkMode, setLinkMode] = useState<LinkMode>('add')\n\n const queryKey =\n businessId && auth?.access_token && `linked-accounts-${businessId}`\n\n const {\n data: responseData,\n isLoading,\n isValidating,\n error: responseError,\n mutate,\n } = useSWR(\n queryKey,\n Layer.getLinkedAccounts(apiUrl, auth?.access_token, {\n params: { businessId },\n }),\n )\n\n useEffect(() => {\n if (!isLoading && responseData?.data.external_accounts) {\n setLoadingStatus('complete')\n return\n }\n\n if (isLoading && loadingStatus === 'initial') {\n setLoadingStatus('loading')\n return\n }\n\n if (!isLoading && loadingStatus === 'loading') {\n setLoadingStatus('complete')\n }\n }, [isLoading])\n\n /**\n * Initiates an add connection flow with Plaid\n */\n const fetchPlaidLinkToken = async () => {\n if (auth?.access_token) {\n const linkToken = (\n await Layer.getPlaidLinkToken(apiUrl, auth.access_token, {\n params: { businessId },\n })\n ).data.link_token\n setLinkMode('add')\n setLinkToken(linkToken)\n }\n }\n\n /**\n * Initiates a connection repair flow with Plaid\n */\n const fetchPlaidUpdateModeLinkToken = async (plaidItemPlaidId: string) => {\n if (auth?.access_token) {\n const linkToken = (\n await Layer.getPlaidUpdateModeLinkToken(apiUrl, auth.access_token, {\n params: { businessId },\n body: { plaid_item_id: plaidItemPlaidId },\n })\n ).data.link_token\n setLinkMode('update')\n setLinkToken(linkToken)\n }\n }\n\n /**\n * When the user has finished entering credentials, send the resulting\n * token to the backend where it will fetch and save the Plaid access token\n * and item id\n * */\n const exchangePlaidPublicToken = async (\n publicToken: string,\n metadata: PlaidLinkOnSuccessMetadata,\n ) => {\n await Layer.exchangePlaidPublicToken(apiUrl, auth?.access_token, {\n params: { businessId },\n body: { public_token: publicToken, institution: metadata.institution },\n })\n refetchAccounts()\n }\n\n const { open: plaidLinkStart, ready: plaidLinkReady } = usePlaidLink({\n token: linkToken,\n\n // If in update mode, we don't need to exchange the public token for an access token.\n // The existing access token will automatically become valid again\n onSuccess: async (\n publicToken: string,\n metadata: PlaidLinkOnSuccessMetadata,\n ) => {\n if (linkMode == 'add') {\n // Note: a sync is kicked off in the backend in this endpoint\n exchangePlaidPublicToken(publicToken, metadata)\n } else {\n // Refresh the account connections, which should remove the error\n // pills from any broken accounts\n await updateConnectionStatus()\n refetchAccounts()\n setLinkMode('add')\n touch(DataModel.LINKED_ACCOUNTS)\n }\n },\n onExit: () => setLinkMode('add'),\n env: USE_PLAID_SANDBOX ? 'sandbox' : undefined,\n })\n\n useEffect(() => {\n if (plaidLinkReady) {\n plaidLinkStart()\n }\n }, [plaidLinkStart, plaidLinkReady])\n\n const mockResponseData = {\n data: LINKED_ACCOUNTS_MOCK_DATA,\n meta: {},\n error: undefined,\n }\n\n const addConnection = (source: Source) => {\n if (source === 'PLAID') {\n fetchPlaidLinkToken()\n } else {\n console.error(\n `Adding a connection with source ${source} not yet supported`,\n )\n }\n }\n\n const repairConnection = async (\n source: Source,\n connectionExternalId: string,\n ) => {\n if (source === 'PLAID') {\n await fetchPlaidUpdateModeLinkToken(connectionExternalId)\n } else {\n console.error(\n `Repairing a connection with source ${source} not yet supported`,\n )\n }\n }\n\n const removeConnection = async (\n source: Source,\n connectionExternalId: string,\n ) => {\n if (source === 'PLAID') {\n await unlinkPlaidItem(connectionExternalId)\n await refetchAccounts()\n } else {\n console.error(\n `Removing a connection with source ${source} not yet supported`,\n )\n }\n }\n\n const unlinkAccount = async (source: Source, accountId: string) => {\n DEBUG && console.log('unlinking account')\n if (source === 'PLAID') {\n await Layer.unlinkAccount(apiUrl, auth?.access_token, {\n params: { businessId, accountId: accountId },\n })\n await refetchAccounts()\n touch(DataModel.LINKED_ACCOUNTS)\n } else {\n console.error(\n `Unlinking an account with source ${source} not yet supported`,\n )\n }\n }\n\n const confirmAccount = async (source: Source, accountId: string) => {\n DEBUG && console.log('confirming account')\n if (source === 'PLAID') {\n await Layer.confirmConnection(apiUrl, auth?.access_token, {\n params: {\n businessId,\n accountId,\n },\n })\n await refetchAccounts()\n touch(DataModel.LINKED_ACCOUNTS)\n } else {\n console.error(\n `Confirming an account with source ${source} not yet supported`,\n )\n }\n }\n\n const denyAccount = async (source: Source, accountId: string) => {\n DEBUG && console.log('confirming account')\n if (source === 'PLAID') {\n await Layer.denyConnection(apiUrl, auth?.access_token, {\n params: {\n businessId,\n accountId,\n },\n })\n await refetchAccounts()\n touch(DataModel.LINKED_ACCOUNTS)\n } else {\n console.error(\n `Denying an account with source ${source} not yet supported`,\n )\n }\n }\n\n /**\n * Test utility that puts a connection into a broken state. Only works in non-production environments.\n */\n const breakConnection = async (\n source: Source,\n connectionExternalId: string,\n ) => {\n DEBUG && console.log('Breaking sandbox plaid item connection')\n if (source === 'PLAID') {\n await Layer.breakPlaidItemConnection(apiUrl, auth?.access_token, {\n params: {\n businessId,\n plaidItemPlaidId: connectionExternalId,\n },\n })\n await refetchAccounts()\n touch(DataModel.LINKED_ACCOUNTS)\n } else {\n console.error(\n `Breaking a sandbox connection with source ${source} not yet supported`,\n )\n }\n }\n\n const refetchAccounts = async () => {\n DEBUG && console.log('refetching accounts...')\n await mutate()\n }\n\n const syncAccounts = async () => {\n DEBUG && console.log('resyncing accounts...')\n await Layer.syncConnection(apiUrl, auth?.access_token, {\n params: { businessId },\n })\n }\n\n const updateConnectionStatus = async () => {\n DEBUG && console.log('updating connection status...')\n await Layer.updateConnectionStatus(apiUrl, auth?.access_token, {\n params: { businessId },\n })\n }\n\n const unlinkPlaidItem = async (plaidItemPlaidId: string) => {\n DEBUG && console.log('unlinking plaid item')\n await Layer.unlinkPlaidItem(apiUrl, auth?.access_token, {\n params: { businessId, plaidItemPlaidId },\n })\n await refetchAccounts()\n touch(DataModel.LINKED_ACCOUNTS)\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.LINKED_ACCOUNTS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetchAccounts()\n }\n }, [syncTimestamps])\n\n return {\n data: USE_MOCK_RESPONSE_DATA\n ? mockResponseData.data\n : responseData?.data.external_accounts,\n isLoading,\n loadingStatus,\n isValidating,\n error: responseError,\n addConnection,\n removeConnection,\n repairConnection,\n refetchAccounts,\n unlinkAccount,\n confirmAccount,\n denyAccount,\n breakConnection,\n syncAccounts,\n updateConnectionStatus,\n }\n}\n", "import { LinkedAccount } from '../../types/linked_accounts'\n\nexport const LINKED_ACCOUNTS_MOCK_DATA: LinkedAccount[] = [\n {\n id: 'd800ada8-8075-4436-a712-08efabcbd51a',\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n external_account_name: 'Citi Double Cash\u00AE Card',\n mask: '1234',\n latest_balance_timestamp: {\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n balance: 435121,\n at: '2024-04-03T13:00:00Z',\n created_at: '2024-04-06T22:47:59.715458Z',\n },\n current_ledger_balance: 373717,\n institution: {\n name: 'Chase',\n logo: '',\n },\n connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n connection_external_id: '11111',\n connection_needs_repair_as_of: null,\n requires_user_confirmation_as_of: null,\n is_syncing: true,\n },\n {\n id: 'f98ec50a-c370-484d-a35b-d00207436075',\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n external_account_name: 'Citi Double Cash\u00AE Card',\n mask: '1234',\n latest_balance_timestamp: {\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n balance: 435121,\n at: '2024-04-03T13:00:00Z',\n created_at: '2024-04-06T16:44:35.715458Z',\n },\n current_ledger_balance: 373717,\n institution: {\n name: 'Chase',\n logo: '',\n },\n connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n connection_external_id: '11111',\n connection_needs_repair_as_of: null,\n requires_user_confirmation_as_of: null,\n is_syncing: false,\n },\n {\n id: '843f1748-fdaa-422d-a73d-2489a40c8dc7',\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n external_account_name: 'Citi Double Cash\u00AE Card',\n mask: '1234',\n latest_balance_timestamp: {\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n balance: 435121,\n at: '2024-04-03T13:00:00Z',\n created_at: '2024-04-06T16:44:35.715458Z',\n },\n current_ledger_balance: 373717,\n institution: {\n name: 'Chase',\n logo: '',\n },\n connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n connection_external_id: '11111',\n connection_needs_repair_as_of: '2024-03-06T16:44:35.715458Z',\n requires_user_confirmation_as_of: null,\n is_syncing: false,\n },\n {\n id: '8f430e29-e339-4d71-a08a-fce469c7a7c1',\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n external_account_name: 'Citi Double Cash\u00AE Card',\n mask: '1234',\n latest_balance_timestamp: {\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n balance: 435121,\n at: '2024-04-03T13:00:00Z',\n created_at: '2024-04-06T16:44:35.715458Z',\n },\n current_ledger_balance: 373717,\n institution: {\n name: 'Chase',\n logo: '',\n },\n connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n connection_external_id: '11111',\n connection_needs_repair_as_of: null,\n requires_user_confirmation_as_of: '2024-03-06T16:44:35.715458Z',\n is_syncing: false,\n },\n]\n", "import React, { CSSProperties, ReactNode, forwardRef } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { parseStylesFromThemeConfig } from '../../utils/colors'\nimport classNames from 'classnames'\n\nexport interface ContainerProps {\n name: string\n className?: string\n asWidget?: boolean\n elevated?: boolean\n transparentBg?: boolean\n children: ReactNode\n style?: CSSProperties\n}\n\nexport const Container = forwardRef<HTMLDivElement, ContainerProps>(\n (\n {\n name,\n className,\n children,\n asWidget,\n elevated = false,\n transparentBg = false,\n style,\n },\n ref,\n ) => {\n const baseClassName = classNames(\n 'Layer__component Layer__component-container',\n `Layer__${name}`,\n elevated && 'Layer__component--elevated',\n transparentBg && 'Layer__component--no-bg',\n asWidget && 'Layer__component--as-widget',\n className,\n )\n\n const { theme } = useLayerContext()\n\n const themeStyles = parseStylesFromThemeConfig(theme)\n\n return (\n <div\n ref={ref}\n className={baseClassName}\n style={{ ...themeStyles, ...style }}\n >\n {children}\n </div>\n )\n },\n)\n", "import React, { CSSProperties, ReactNode, forwardRef } from 'react'\nimport classNames from 'classnames'\n\nexport enum HeaderLayout {\n DEFAULT = 'default',\n NEXT_LINE_ACTIONS = 'next-line-actions',\n}\n\nexport interface HeaderProps {\n className?: string\n style?: CSSProperties\n children: ReactNode\n layout?: HeaderLayout\n}\n\nexport const Header = forwardRef<HTMLElement, HeaderProps>(\n ({ className, children, style, layout }, ref) => {\n const baseClassName = classNames(\n 'Layer__component-header',\n layout && `Layer__component-header--${layout}`,\n className,\n )\n\n return (\n <header ref={ref} className={baseClassName} style={style}>\n {children}\n </header>\n )\n },\n)\n", "import React, { useContext, useMemo } from 'react'\nimport { LinkedAccountsContext } from '../../contexts/LinkedAccountsContext'\nimport { useBankTransactions } from '../../hooks/useBankTransactions'\nimport BellIcon from '../../icons/Bell'\nimport CreditCardIcon from '../../icons/CreditCard'\nimport FolderIcon from '../../icons/Folder'\nimport LinkIcon from '../../icons/Link'\nimport PlaidIcon from '../../icons/PlaidIcon'\nimport SunriseIcon from '../../icons/Sunrise'\nimport { OnboardingStep } from '../../types/layer_context'\nimport { countTransactionsToReview } from '../../utils/bankTransactions'\nimport { ActionableRow } from '../ActionableRow'\nimport { Badge, BadgeVariant } from '../Badge'\nimport { BadgeSize } from '../Badge/Badge'\nimport { Button } from '../Button'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { Text } from '../Typography'\nimport { DisplayState } from '../../types'\n\nexport interface ConnectAccountProps {\n onboardingStep: OnboardingStep\n onTransactionsToReviewClick?: () => void\n currentMonthOnly?: boolean\n}\n\nexport const ConnectAccount = ({\n onboardingStep,\n onTransactionsToReviewClick,\n}: ConnectAccountProps) => {\n const { addConnection } = useContext(LinkedAccountsContext)\n const { data, isLoading } = useBankTransactions({\n scope: DisplayState.review,\n })\n\n const transactionsToReview = useMemo(\n () => countTransactionsToReview({ transactions: data }),\n [data, isLoading],\n )\n\n if (onboardingStep === 'connectAccount') {\n return (\n <>\n <DataState\n status={DataStateStatus.info}\n icon={<CreditCardIcon size={12} />}\n title='No accounts connected'\n description='Populate your accounting dashboard in 3 steps'\n />\n <ActionableRow\n iconBox={<PlaidIcon />}\n title='Connect accounts'\n description='Import data with one simple integration.'\n button={\n <Button\n onClick={() => addConnection('PLAID')}\n rightIcon={<LinkIcon size={12} />}\n >\n Connect\n </Button>\n }\n />\n </>\n )\n }\n\n return (\n <>\n <DataState\n status={DataStateStatus.success}\n icon={<SunriseIcon size={12} />}\n title='Account linked successfully'\n description='Your transactions are now available on the platform, to see all data on the charts, categorise transactions.'\n />\n {onTransactionsToReviewClick && transactionsToReview > 0 ? (\n <ActionableRow\n icon={<FolderIcon size={12} />}\n title={\n <Text>\n Categorise transactions{' '}\n <Badge\n variant={BadgeVariant.WARNING}\n size={BadgeSize.SMALL}\n icon={<BellIcon size={12} />}\n >\n {transactionsToReview} pending\n </Badge>\n </Text>\n }\n description='Once your data is on the platform categorize them in Bank Transactions tab'\n onClick={() => onTransactionsToReviewClick()}\n />\n ) : null}\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Bell = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M13.5 6C13.5 4.80653 13.0259 3.66193 12.182 2.81802C11.3381 1.97411 10.1935 1.5 9 1.5C7.80653 1.5 6.66193 1.97411 5.81802 2.81802C4.97411 3.66193 4.5 4.80653 4.5 6C4.5 11.25 2.25 12.75 2.25 12.75H15.75C15.75 12.75 13.5 11.25 13.5 6Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.2975 15.75C10.1656 15.9773 9.97638 16.166 9.74867 16.2971C9.52096 16.4283 9.26278 16.4973 9 16.4973C8.73721 16.4973 8.47904 16.4283 8.25133 16.2971C8.02362 16.166 7.83436 15.9773 7.7025 15.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Bell\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst CreditCard = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 12'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M10.5 2H1.5C0.947715 2 0.5 2.44772 0.5 3V9C0.5 9.55228 0.947715 10 1.5 10H10.5C11.0523 10 11.5 9.55228 11.5 9V3C11.5 2.44772 11.0523 2 10.5 2Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M0.5 5H11.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default CreditCard\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Folder = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 12'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M11 9.5C11 9.76522 10.8946 10.0196 10.7071 10.2071C10.5196 10.3946 10.2652 10.5 10 10.5H2C1.73478 10.5 1.48043 10.3946 1.29289 10.2071C1.10536 10.0196 1 9.76522 1 9.5V2.5C1 2.23478 1.10536 1.98043 1.29289 1.79289C1.48043 1.60536 1.73478 1.5 2 1.5H4.5L5.5 3H10C10.2652 3 10.5196 3.10536 10.7071 3.29289C10.8946 3.48043 11 3.73478 11 4V9.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Folder\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Link = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M7.5 9.75C7.82209 10.1806 8.23302 10.5369 8.70491 10.7947C9.17681 11.0525 9.69863 11.2058 10.235 11.2442C10.7713 11.2827 11.3097 11.2053 11.8135 11.0173C12.3173 10.8294 12.7748 10.5353 13.155 10.155L15.405 7.905C16.0881 7.19774 16.4661 6.25048 16.4575 5.26724C16.449 4.284 16.0546 3.34346 15.3593 2.64818C14.664 1.9529 13.7235 1.55851 12.7403 1.54997C11.757 1.54143 10.8098 1.9194 10.1025 2.6025L8.8125 3.885'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5 8.25C10.1779 7.8194 9.76698 7.46311 9.29508 7.2053C8.82319 6.94748 8.30137 6.79416 7.76501 6.75575C7.22865 6.71734 6.69031 6.79473 6.18649 6.98266C5.68267 7.1706 5.22516 7.4647 4.845 7.845L2.595 10.095C1.9119 10.8023 1.53393 11.7495 1.54247 12.7328C1.55101 13.716 1.9454 14.6565 2.64068 15.3518C3.33596 16.0471 4.2765 16.4415 5.25974 16.45C6.24298 16.4586 7.19024 16.0806 7.8975 15.3975L9.18 14.115'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Link\n", "import React from 'react'\n\nconst PlaidIcon = () => {\n return (\n <img\n src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAhCAYAAAC4JqlRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQDSURBVHgB7VbpK65bFP+9XJTMJGPGDIVIpjIln2S4SIr4AxSOIZFwPxA+HUf5rhAZb3xQylCUizKLD+I1ROYpZcq+e63u+9S5t573XN1z3nvr/or97GVba+3fmrYGf8DBwSHx/f09VH7a4DvD2Nj414uLi1X61tAvOzu7z0KIT/iB0Gg0bdfX12UaafyTNP4ZBoB0okxja2u7L789YRhoyQEBA8IIBsZ/0wF7e3tYWVkpe2tra8hQ4iP46VsOWVpaIiYmBrGxsYiKikJERASWl5eRnZ0NU1NT9PX1ISwsDCsrK5iZmcHi4iKmpqbw+vqqV7feJCwsLERbW5uyX19fx/7+PjIyMrC5uQkTExP4+/tjZGQEvr6+CA4OVs6Wlpaiq6sLqiAH1H4GBgaEDqmpqYq8qalJkdfX1yvyrKwscXd3x/L+/n6hT79eBnZ3d3F6egobGxtInUhPT8f9/T3fWHfb7e1tpKSk8JmxsTGWPT4+wsnJCV5eXqoEqCYhUSo7JXp6epCWlkadC5OTkxgaGmLjFRUVKC8vR2BgIEZHR9k4OUlnJXOcnO7u7vhwCKqqqpjKxMRE3tOqQ3Nzs3KutbWVZU9PT0IywbKEhASW1dbWqoZAlQHKbEJISAiXXnt7O+/Pz8+Rn58PDw8PeHp6Ii8vDzLuMDMzQ0tLC988Li6Oz/r5+X2cARcXF7G1tcU3OTk54bWyslJIx8Tx8bGQ00wcHR2Jw8NDERoaKsrKyviMzBleZcUIZ2dnVQb0VkF0dLR4fn5mhbLeFXlBQYESDsnAX6rm5eWF/1efflUHXF1d+RY6BuSDRRQXF/NtdTe/ubnhb5JVV1d/xYCsDuHm5vZxB2QTYUU1NTVCxprDQU6QUR3tFA5y4OzsTKHdx8dHyOrgfW9v78eTcGdnh9e5uTlOMukI3t7euN47OztxcHAArVaL7u5uODo68lnJEGRuYHWVX1zcntWgOguothsbG5GcnIyHhwd0dHRA3hS3t7eoq6vD5eUlzM3NIalnQ9R0qPVSs4qPj2cd09PTaib0zwLq+9QJLSwseE/KZQgwPj6OgIAAlm1sbPBsIGbIaWpGxJisIm5matA7jicmJtgQ1XZJSQlTTsplbJUzw8PDzAr9raioiLtfUFAQT0R90DuOZ2dnkZOTwyOZDK2trWFvbw+ZmZk8AygnGhoaIBMS3t7eX01Dyh19+KY3IY3cpKQkREZGQrZjZfbn5ubyzB8cHER4eDiWlpawsLDAhufn5zlv/hEH/gzdZKRQEIgdephcXV3h7+L/V/G/wgEtDAetkUymLzAQyLaxfMX8JtspPeqj8QMhn3dfZEf9RaMTyNIKNTIy+hnfGXKa3splVXbOGdr/DtMw0L76HoUPAAAAAElFTkSuQmCC'\n alt='Plaid'\n />\n )\n}\n\nexport default PlaidIcon\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Sunrise = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 12'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M8.5 9C8.5 8.33696 8.23661 7.70107 7.76777 7.23223C7.29893 6.76339 6.66304 6.5 6 6.5C5.33696 6.5 4.70107 6.76339 4.23223 7.23223C3.76339 7.70107 3.5 8.33696 3.5 9'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M6 3.3335V4.66683'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M2.11 5.10986L2.82 5.81986'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M0.5 9H1.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5 9H11.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9.17999 5.81986L9.88999 5.10986'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M11.5 11H0.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Sunrise\n", "import { filterVisibility } from '../components/BankTransactions/utils'\nimport { CategoryOption } from '../components/CategorySelect/CategorySelect'\nimport { BankTransaction, DateRange, Direction, DisplayState } from '../types'\nimport { isWithinInterval, parseISO } from 'date-fns'\n\nexport const hasMatch = (bankTransaction?: BankTransaction) => {\n return Boolean(\n (bankTransaction?.suggested_matches &&\n bankTransaction?.suggested_matches?.length > 0) ||\n bankTransaction?.match,\n )\n}\n\nexport const isCredit = ({ direction }: Pick<BankTransaction, 'direction'>) =>\n direction === Direction.CREDIT\n\nexport const isAlreadyMatched = (bankTransaction?: BankTransaction) => {\n if (bankTransaction?.match) {\n const foundMatch = bankTransaction.suggested_matches?.find(\n x => x.details.id === bankTransaction?.match?.details.id,\n )\n return foundMatch?.id\n }\n\n return undefined\n}\n\nexport const countTransactionsToReview = ({\n transactions,\n dateRange,\n}: {\n transactions?: BankTransaction[]\n dateRange?: DateRange\n}) => {\n if (transactions && transactions.length > 0) {\n if (dateRange) {\n const dateRangeInterval = {\n start: dateRange.startDate,\n end: dateRange.endDate,\n }\n return transactions.filter(tx => {\n try {\n return (\n filterVisibility(DisplayState.review, tx) &&\n isWithinInterval(parseISO(tx.date), dateRangeInterval)\n )\n } catch (_err) {\n return false\n }\n }).length\n }\n return transactions.filter(tx => filterVisibility(DisplayState.review, tx))\n .length\n }\n\n return 0\n}\n\nexport const getCategorizePayload = (category: CategoryOption) => {\n if (\n category?.payload &&\n 'id' in category.payload &&\n category.payload.type == 'ExclusionNested'\n ) {\n return {\n type: 'Exclusion' as 'Exclusion',\n exclusion_type: category.payload.id,\n }\n }\n\n if (category?.payload && 'id' in category.payload && category.payload.id) {\n return {\n type: 'AccountId' as 'AccountId',\n id: category.payload.id,\n }\n }\n\n return {\n type: 'StableName' as 'StableName',\n stable_name: category?.payload.stable_name || '',\n }\n}\n", "import React, { ReactNode } from 'react'\nimport ChevronRightIcon from '../../icons/ChevronRight'\nimport { IconButton } from '../Button'\nimport { Text } from '../Typography'\n\ninterface ActionableRowProps {\n icon?: ReactNode\n iconBox?: ReactNode\n title?: string | ReactNode\n description?: string | ReactNode\n button?: ReactNode\n onClick?: () => void\n}\n\nconst renderIcon = (icon?: ReactNode, iconBox?: ReactNode) => {\n if (iconBox) {\n return iconBox\n }\n\n if (icon) {\n return <span className='Layer__actionable_row__icon'>{icon}</span>\n }\n\n return\n}\n\nconst renderTitle = (title?: string | ReactNode) => {\n if (title && typeof title === 'string') {\n return <Text className='Layer__actionable_row__title'>{title}</Text>\n }\n\n if (title) {\n return title\n }\n\n return\n}\n\nconst renderDescription = (description?: string | ReactNode) => {\n if (description && typeof description === 'string') {\n return (\n <Text className='Layer__actionable_row__description'>{description}</Text>\n )\n }\n\n if (description) {\n return description\n }\n\n return\n}\n\nexport const ActionableRow = ({\n icon,\n iconBox,\n title,\n description,\n button,\n onClick,\n}: ActionableRowProps) => {\n return (\n <div className='Layer__actionable_row'>\n <div className='Layer__actionable_row__main'>\n {renderIcon(icon, iconBox)}\n <div className='Layer__actionable_row__main__text'>\n {renderTitle(title)}\n {renderDescription(description)}\n </div>\n </div>\n <div className='Layer__actionable_row__action'>\n {button && button}\n {!button && onClick ? (\n <IconButton\n onClick={onClick}\n icon={<ChevronRightIcon size={11} />}\n withBorder\n />\n ) : null}\n </div>\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ChevronRight = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n width='18'\n height='18'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n >\n <path\n d='M6.75 13.5L11.25 9L6.75 4.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\nexport default ChevronRight\n", "import React, { ButtonHTMLAttributes, ReactNode, useRef } from 'react'\nimport classNames from 'classnames'\n\nexport enum ButtonVariant {\n primary = 'primary',\n secondary = 'secondary',\n}\n\nexport type ButtonJustify = 'center' | 'space-between' | 'start'\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant\n leftIcon?: ReactNode\n rightIcon?: ReactNode\n iconOnly?: ReactNode\n iconAsPrimary?: boolean\n justify?: ButtonJustify\n fullWidth?: boolean\n}\n\nexport const Button = ({\n className,\n children,\n variant = ButtonVariant.primary,\n leftIcon,\n rightIcon,\n iconOnly,\n iconAsPrimary = false,\n justify = 'center',\n fullWidth,\n ...props\n}: ButtonProps) => {\n const buttonRef = useRef<HTMLButtonElement>(null)\n\n let justifyContent = 'center'\n if (justify) {\n justifyContent = justify\n } else if (leftIcon && rightIcon) {\n justifyContent = 'space-between'\n } else if (rightIcon) {\n justifyContent = 'space-between'\n } else if (leftIcon) {\n justifyContent = 'start'\n }\n\n const baseClassName = classNames(\n 'Layer__btn',\n `Layer__btn--${variant}`,\n iconOnly ? 'Layer__btn--icon-only' : '',\n iconAsPrimary && 'Layer__btn--with-primary-icon',\n fullWidth && 'Layer__btn--full-width',\n className,\n )\n\n const startAnimation = () =>\n buttonRef.current &&\n [...buttonRef.current.getElementsByClassName('animateOnHover')].forEach(\n el => (el as SVGAnimateElement).beginElement(),\n )\n\n const stopAnimation = () =>\n buttonRef.current &&\n [...buttonRef.current.getElementsByClassName('animateOnHover')].forEach(\n el => (el as SVGAnimateElement).endElement(),\n )\n\n return (\n <button\n {...props}\n className={baseClassName}\n onMouseEnter={startAnimation}\n onMouseLeave={stopAnimation}\n ref={buttonRef}\n >\n <span className={`Layer__btn-content Layer__justify--${justifyContent}`}>\n {leftIcon && (\n <span\n className={classNames(\n 'Layer__btn-icon Layer__btn-icon--left',\n iconAsPrimary && 'Layer__btn-icon--primary',\n )}\n >\n {leftIcon}\n </span>\n )}\n {!iconOnly && <span className='Layer__btn-text'>{children}</span>}\n {rightIcon && (\n <span\n className={classNames(\n 'Layer__btn-icon Layer__btn-icon--right',\n iconAsPrimary && 'Layer__btn-icon--primary',\n )}\n >\n {rightIcon}\n </span>\n )}\n </span>\n </button>\n )\n}\n", "import React, { ButtonHTMLAttributes, ReactNode, useRef } from 'react'\nimport classNames from 'classnames'\n\nexport interface IconButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n icon: ReactNode\n active?: boolean\n withBorder?: boolean\n}\n\nexport const IconButton = ({\n className,\n children,\n icon,\n active,\n withBorder = false,\n ...props\n}: IconButtonProps) => {\n const baseClassName = classNames(\n 'Layer__icon-btn',\n `Layer__icon-btn--${active ? 'active' : 'inactive'}`,\n withBorder && 'Layer__icon-btn--border',\n className,\n )\n\n return (\n <button {...props} className={baseClassName}>\n {icon}\n </button>\n )\n}\n", "import React, { ButtonHTMLAttributes } from 'react'\nimport RefreshCcw from '../../icons/RefreshCcw'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport { Button, ButtonVariant } from './Button'\nimport classNames from 'classnames'\n\nexport interface RetryButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n processing?: boolean\n disabled?: boolean\n error: string\n fullWidth?: boolean\n iconOnly?: boolean\n}\n\nexport const RetryButton = ({\n className,\n processing,\n disabled,\n error,\n children,\n ...props\n}: RetryButtonProps) => {\n const baseClassName = classNames(\n 'Layer__retry-btn',\n processing ? 'Layer__btn--processing' : '',\n className,\n )\n\n return (\n <Button\n {...props}\n className={baseClassName}\n variant={ButtonVariant.secondary}\n disabled={processing || disabled}\n rightIcon={<RefreshCcw size={12} />}\n justify='center'\n >\n {children}\n </Button>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst RefreshCcw = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M0.75 3V7.5H5.25'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M17.25 15V10.5H12.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M15.3675 6.75C14.9871 5.67508 14.3407 4.71405 13.4884 3.95656C12.6361 3.19907 11.6059 2.66982 10.4938 2.41819C9.38167 2.16656 8.22393 2.20075 7.12861 2.51758C6.03328 2.8344 5.03606 3.42353 4.23 4.23L0.75 7.5M17.25 10.5L13.77 13.77C12.9639 14.5765 11.9667 15.1656 10.8714 15.4824C9.77607 15.7992 8.61833 15.8334 7.50621 15.5818C6.3941 15.3302 5.36385 14.8009 4.5116 14.0434C3.65935 13.2859 3.01288 12.3249 2.6325 11.25'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default RefreshCcw\n", "import React, { ButtonHTMLAttributes } from 'react'\nimport AlertCircle from '../../icons/AlertCircle'\nimport CheckCircle from '../../icons/CheckCircle'\nimport Loader from '../../icons/Loader'\nimport Save from '../../icons/Save'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport { Button, ButtonVariant } from './Button'\nimport classNames from 'classnames'\n\nexport interface SubmitButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n processing?: boolean\n disabled?: boolean\n error?: boolean | string\n active?: boolean\n iconOnly?: boolean\n action?: SubmitAction\n noIcon?: boolean\n}\n\nexport enum SubmitAction {\n SAVE = 'save',\n UPDATE = 'update',\n}\n\nconst buildRightIcon = ({\n processing,\n error,\n action,\n noIcon,\n}: {\n processing?: boolean\n error?: boolean | string\n action: SubmitAction\n noIcon?: boolean\n}) => {\n if (noIcon) {\n return\n }\n\n if (processing) {\n return <Loader size={14} className='Layer__anim--rotating' />\n }\n\n if (error) {\n return (\n <Tooltip offset={12}>\n <TooltipTrigger>\n <AlertCircle size={14} />\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{error}</TooltipContent>\n </Tooltip>\n )\n }\n\n if (action === SubmitAction.UPDATE) {\n return (\n <span className='Layer__pt-2'>\n <CheckCircle size={14} />\n </span>\n )\n }\n\n return (\n <span>\n <Save size={14} style={{ paddingTop: 4 }} />\n </span>\n )\n}\n\nexport const SubmitButton = ({\n active,\n className,\n processing,\n disabled,\n error,\n children,\n action = SubmitAction.SAVE,\n noIcon,\n ...props\n}: SubmitButtonProps) => {\n const baseClassName = classNames(\n active ? 'Layer__btn--active' : '',\n className,\n )\n\n return (\n <Button\n {...props}\n className={baseClassName}\n variant={ButtonVariant.primary}\n disabled={processing || disabled}\n rightIcon={buildRightIcon({ processing, error, action, noIcon })}\n iconAsPrimary={true}\n >\n {children}\n </Button>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst AlertCircle = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 6V9'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 12H9.0075'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default AlertCircle\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst CheckCircle = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M16.5 8.30999V8.99999C16.4991 10.6173 15.9754 12.191 15.007 13.4864C14.0386 14.7817 12.6775 15.7293 11.1265 16.1879C9.57557 16.6465 7.91794 16.5914 6.40085 16.0309C4.88375 15.4704 3.58848 14.4346 2.70821 13.0778C1.82794 11.721 1.40984 10.116 1.51625 8.50223C1.62266 6.88841 2.2479 5.35223 3.2987 4.12279C4.34951 2.89335 5.76958 2.03653 7.34713 1.6801C8.92469 1.32367 10.5752 1.48674 12.0525 2.14499'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M16.5 3L9 10.5075L6.75 8.2575'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default CheckCircle\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Loader = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M9 1.5V4.5'\n stroke='#3E4044'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 13.5V16.5'\n stroke='#818388'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M3.6975 3.6975L5.82 5.82'\n stroke='#5F6166'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12.18 12.18L14.3025 14.3025'\n stroke='#2D2F33'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M1.5 9H4.5'\n stroke='#5F6166'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M13.5 9H16.5'\n stroke='#2D2F33'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M3.6975 14.3025L5.82 12.18'\n stroke='#818388'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12.18 5.82L14.3025 3.6975'\n stroke='#3E4044'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Loader\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Save = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M14.25 15.75H3.75C3.35218 15.75 2.97064 15.592 2.68934 15.3107C2.40804 15.0294 2.25 14.6478 2.25 14.25V3.75C2.25 3.35218 2.40804 2.97064 2.68934 2.68934C2.97064 2.40804 3.35218 2.25 3.75 2.25H12L15.75 6V14.25C15.75 14.6478 15.592 15.0294 15.3107 15.3107C15.0294 15.592 14.6478 15.75 14.25 15.75Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12.75 15.75V9.75H5.25V15.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M5.25 2.25V6H11.25'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Save\n", "import React, {\n ReactNode,\n forwardRef,\n HTMLProps,\n isValidElement,\n cloneElement,\n} from 'react'\nimport { TooltipContext, useTooltip, useTooltipContext } from './useTooltip'\nimport { useMergeRefs, FloatingPortal } from '@floating-ui/react'\nimport type { Placement } from '@floating-ui/react'\n\nexport interface TooltipOptions {\n initialOpen?: boolean\n placement?: Placement\n open?: boolean\n disabled?: boolean\n onOpenChange?: (open: boolean) => void\n offset?: number\n shift?: { padding?: number }\n}\n\nexport const Tooltip = ({\n children,\n ...options\n}: { children: ReactNode } & TooltipOptions) => {\n const tooltip = useTooltip(options)\n return (\n <TooltipContext.Provider value={tooltip}>\n {children}\n </TooltipContext.Provider>\n )\n}\n\nexport const TooltipTrigger = forwardRef<\n HTMLElement,\n HTMLProps<HTMLElement> & { asChild?: boolean }\n>(function TooltipTrigger({ children, asChild = false, ...props }, propRef) {\n const context = useTooltipContext()\n const childrenRef = (children as any).ref\n const ref = useMergeRefs([context.refs.setReference, propRef, childrenRef])\n\n if (asChild && isValidElement(children)) {\n return cloneElement(\n children,\n context.getReferenceProps({\n ref,\n ...props,\n ...children.props,\n 'data-state': context.open ? 'open' : 'closed',\n }),\n )\n }\n\n return (\n <span\n ref={ref}\n data-state={context.open ? 'open' : 'closed'}\n className={`Layer__tooltip-trigger Layer__tooltip-trigger--${\n context.open ? 'open' : 'closed'\n }`}\n {...context.getReferenceProps(props)}\n >\n {children}\n </span>\n )\n})\n\nexport const TooltipContent = forwardRef<\n HTMLDivElement,\n HTMLProps<HTMLDivElement>\n>(function TooltipContent({ style, className, ...props }, propRef) {\n const context = useTooltipContext()\n const ref = useMergeRefs([context.refs.setFloating, propRef])\n\n if (!context.open || context.disabled) return null\n\n return (\n <FloatingPortal>\n <div\n ref={ref}\n className={className}\n style={{\n ...context.floatingStyles,\n }}\n {...context.getFloatingProps(props)}\n >\n <div className='Layer__tooltip-content ' style={{ ...context.styles }}>\n {props.children}\n </div>\n </div>\n </FloatingPortal>\n )\n})\n", "import React, { useState } from 'react'\nimport { TooltipOptions } from './Tooltip'\nimport {\n useFloating,\n autoUpdate,\n offset,\n flip,\n shift,\n useHover,\n useFocus,\n useDismiss,\n useRole,\n useInteractions,\n useTransitionStyles,\n} from '@floating-ui/react'\n\nexport type ContextType = ReturnType<typeof useTooltip> | null\n\nexport const TooltipContext = React.createContext<ContextType>(null)\n\nexport const useTooltipContext = () => {\n const context = React.useContext(TooltipContext)\n\n if (context == null) {\n throw new Error('Tooltip components must be wrapped in <Tooltip />')\n }\n\n return context\n}\n\nexport const useTooltip = ({\n initialOpen = false,\n placement = 'top',\n open: controlledOpen,\n onOpenChange: setControlledOpen,\n disabled,\n offset: offsetProp = 5,\n shift: shiftProp = { padding: 5 },\n}: TooltipOptions = {}) => {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(initialOpen)\n\n const open = controlledOpen ?? uncontrolledOpen\n const setOpen = setControlledOpen ?? setUncontrolledOpen\n\n const data = useFloating({\n placement,\n open: disabled ? false : open,\n onOpenChange: setOpen,\n whileElementsMounted: autoUpdate,\n middleware: [\n offset(offsetProp),\n flip({\n crossAxis: placement.includes('-'),\n fallbackAxisSideDirection: 'start',\n padding: shiftProp?.padding ?? 5,\n }),\n shift(shiftProp),\n ],\n })\n\n const context = data.context\n\n const hover = useHover(context, {\n move: false,\n enabled: controlledOpen == null,\n })\n const focus = useFocus(context, {\n enabled: controlledOpen == null,\n })\n const dismiss = useDismiss(context)\n const role = useRole(context, { role: 'tooltip' })\n\n const interactions = useInteractions([hover, focus, dismiss, role])\n\n const { isMounted, styles } = useTransitionStyles(context, {\n initial: {\n opacity: 0,\n transform: 'scale(0.7)',\n color: 'transparent',\n },\n duration: 300,\n })\n\n return React.useMemo(\n () => ({\n open,\n setOpen,\n isMounted,\n styles,\n disabled,\n ...interactions,\n ...data,\n }),\n [open, setOpen, interactions, data, styles, disabled],\n )\n}\n", "import React, { ButtonHTMLAttributes, ReactNode, useRef } from 'react'\nimport classNames from 'classnames'\n\nexport type TextButtonProps = ButtonHTMLAttributes<HTMLButtonElement>\n\nexport const TextButton = ({\n className,\n children,\n ...props\n}: TextButtonProps) => {\n const baseClassName = classNames('Layer__text-btn', className)\n\n return (\n <button {...props} className={baseClassName}>\n {children}\n </button>\n )\n}\n", "import React, { ButtonHTMLAttributes, ReactNode } from 'react'\nimport BackArrow from '../../icons/BackArrow'\nimport classNames from 'classnames'\n\nexport interface BackButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n textOnly?: boolean\n}\n\nexport const BackButton = ({\n className,\n children,\n textOnly = false,\n ...props\n}: BackButtonProps) => {\n const baseClassName = classNames('Layer__btn', 'Layer__back-btn', className)\n\n return (\n <button {...props} className={baseClassName}>\n {textOnly ? 'Back' : <BackArrow size={16} />}\n </button>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst BackArrow = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 12 12'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M7.375 8.75L4.625 6L7.375 3.25'\n stroke='#1A130D'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default BackArrow\n", "import React, { ButtonHTMLAttributes } from 'react'\nimport CloseIcon from '../../icons/CloseIcon'\nimport classNames from 'classnames'\n\nexport interface CloseButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n textOnly?: boolean\n}\n\nexport const CloseButton = ({\n className,\n children,\n textOnly = false,\n ...props\n}: CloseButtonProps) => {\n const baseClassName = classNames('Layer__btn', 'Layer__back-btn', className)\n\n return (\n <button {...props} className={baseClassName}>\n {textOnly ? 'Back' : <CloseIcon size={16} />}\n </button>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst CloseIcon = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 12 12'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M8.75 3.25L3.25 8.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M3.25 3.25L8.75 8.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default CloseIcon\n", "import React, { ButtonHTMLAttributes, ReactNode } from 'react'\nimport BackArrow from '../../icons/BackArrow'\nimport classNames from 'classnames'\n\nexport interface ExpandButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n collapsed?: boolean\n}\n\nexport const ExpandButton = ({\n className,\n children,\n collapsed,\n ...props\n}: ExpandButtonProps) => {\n const baseClassName = classNames(\n 'Layer__btn',\n 'Layer__expand-btn',\n collapsed ? 'Layer__expand-btn--collapsed' : 'Layer__expand-btn--expanded',\n className,\n )\n\n return (\n <button {...props} className={baseClassName}>\n <BackArrow size={16} />\n </button>\n )\n}\n", "import React, {\n HTMLAttributeAnchorTarget,\n LinkHTMLAttributes,\n ReactNode,\n useRef,\n} from 'react'\nimport { ButtonVariant, ButtonJustify } from './Button'\nimport classNames from 'classnames'\n\nexport interface LinkProps extends LinkHTMLAttributes<HTMLAnchorElement> {\n variant?: ButtonVariant\n leftIcon?: ReactNode\n rightIcon?: ReactNode\n iconOnly?: ReactNode\n iconAsPrimary?: boolean\n justify?: ButtonJustify\n fullWidth?: boolean\n target: HTMLAttributeAnchorTarget\n}\n\nexport const Link = ({\n className,\n children,\n variant = ButtonVariant.primary,\n leftIcon,\n rightIcon,\n iconOnly,\n iconAsPrimary = false,\n justify = 'center',\n fullWidth,\n ...props\n}: LinkProps) => {\n const linkRef = useRef<HTMLAnchorElement>(null)\n\n let justifyContent = 'center'\n if (justify) {\n justifyContent = justify\n } else if (leftIcon && rightIcon) {\n justifyContent = 'space-between'\n } else if (rightIcon) {\n justifyContent = 'space-between'\n } else if (leftIcon) {\n justifyContent = 'start'\n }\n\n const baseClassName = classNames(\n 'Layer__btn',\n 'Layer__btn--as-link',\n `Layer__btn--${variant}`,\n iconOnly ? 'Layer__btn--icon-only' : '',\n iconAsPrimary && 'Layer__btn--with-primary-icon',\n fullWidth && 'Layer__btn--full-width',\n className,\n )\n\n const startAnimation = () =>\n linkRef.current &&\n [...linkRef.current.getElementsByClassName('animateOnHover')].forEach(el =>\n (el as SVGAnimateElement).beginElement(),\n )\n\n const stopAnimation = () =>\n linkRef.current &&\n [...linkRef.current.getElementsByClassName('animateOnHover')].forEach(el =>\n (el as SVGAnimateElement).endElement(),\n )\n\n return (\n <a\n {...props}\n className={baseClassName}\n onMouseEnter={startAnimation}\n onMouseLeave={stopAnimation}\n ref={linkRef}\n >\n <span className={`Layer__btn-content Layer__justify--${justifyContent}`}>\n {leftIcon && (\n <span\n className={classNames(\n 'Layer__btn-icon Layer__btn-icon--left',\n iconAsPrimary && 'Layer__btn-icon--primary',\n )}\n >\n {leftIcon}\n </span>\n )}\n {!iconOnly && <span className='Layer__btn-text'>{children}</span>}\n {rightIcon && (\n <span\n className={classNames(\n 'Layer__btn-icon Layer__btn-icon--right',\n iconAsPrimary && 'Layer__btn-icon--primary',\n )}\n >\n {rightIcon}\n </span>\n )}\n </span>\n </a>\n )\n}\n", "import React, { ReactNode, useRef, useState, useEffect } from 'react'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport enum TextSize {\n lg = 'lg',\n md = 'md',\n sm = 'sm',\n}\n\nexport enum TextWeight {\n normal = 'normal',\n bold = 'bold',\n}\n\nexport enum TextUseTooltip {\n whenTruncated = 'whenTruncated',\n always = 'always',\n}\n\nexport interface TextTooltipOptions {\n contentClassName?: string\n offset?: number\n shift?: { padding?: number }\n}\n\nexport interface TextProps {\n as?: React.ElementType\n className?: string\n children: ReactNode\n size?: TextSize\n weight?: TextWeight\n htmlFor?: string\n withTooltip?: TextUseTooltip\n tooltipOptions?: TextTooltipOptions\n}\n\nexport const Text = ({\n as: Component = 'p',\n className,\n children,\n size = TextSize.md,\n weight = TextWeight.normal,\n withTooltip,\n ...props\n}: TextProps) => {\n const baseClassName = classNames(\n `Layer__text Layer__text--${size} Layer__text--${weight}`,\n className,\n )\n\n if (withTooltip) {\n return (\n <TextWithTooltip\n as={Component}\n className={baseClassName}\n size={size}\n weight={weight}\n withTooltip={withTooltip}\n {...props}\n >\n {children}\n </TextWithTooltip>\n )\n }\n\n return (\n <Component {...props} className={baseClassName}>\n {children}\n </Component>\n )\n}\n\nexport const TextWithTooltip = ({\n as: Component = 'p',\n className,\n children,\n size = TextSize.md,\n weight = TextWeight.normal,\n withTooltip = TextUseTooltip.whenTruncated,\n tooltipOptions,\n ...props\n}: TextProps) => {\n const textElementRef = useRef<HTMLElement>()\n const compareSize = () => {\n if (textElementRef.current) {\n const compare =\n textElementRef.current.children[0].scrollWidth >\n textElementRef.current.children[0].clientWidth\n setHover(compare)\n }\n }\n\n useEffect(() => {\n compareSize()\n window.addEventListener('resize', compareSize)\n }, [])\n\n useEffect(\n () => () => {\n window.removeEventListener('resize', compareSize)\n },\n [],\n )\n\n const [hoverStatus, setHover] = useState(false)\n\n const contentClassName = classNames(\n 'Layer__tooltip',\n tooltipOptions?.contentClassName,\n )\n\n return (\n <Tooltip\n disabled={!hoverStatus}\n offset={tooltipOptions?.offset}\n shift={tooltipOptions?.shift}\n >\n <TooltipTrigger>\n <Component className={className} ref={textElementRef} {...props}>\n {children}\n </Component>\n </TooltipTrigger>\n <TooltipContent className={contentClassName}>{children}</TooltipContent>\n </Tooltip>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport classNames from 'classnames'\n\nexport enum HeadingSize {\n primary = 'primary',\n secondary = 'secondary',\n}\n\nexport interface HeadingProps {\n as?: React.ElementType\n className?: string\n children: ReactNode\n size?: HeadingSize\n}\n\nexport const Heading = ({\n as: Component = 'h2',\n className,\n children,\n size = HeadingSize.primary,\n}: HeadingProps) => {\n const baseClassName = classNames(\n `Layer__heading Layer__heading--${size}`,\n className,\n )\n\n return <Component className={baseClassName}>{children}</Component>\n}\n", "import React from 'react'\nimport { TextProps, Text } from './Text'\nimport classNames from 'classnames'\n\nexport type ErrorTextProps = TextProps\n\nexport const ErrorText = ({ className, ...props }: ErrorTextProps) => {\n const baseClassName = classNames('Layer__text--error', className)\n return <Text {...props} className={baseClassName} />\n}\n", "import React, { ReactNode } from 'react'\nimport { ButtonProps } from '../Button/Button'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport enum BadgeSize {\n SMALL = 'small',\n MEDIUM = 'medium',\n}\n\nexport enum BadgeVariant {\n DEFAULT = 'default',\n SUCCESS = 'success',\n WARNING = 'warning',\n ERROR = 'error',\n}\n\nexport interface BadgeProps {\n children: ReactNode\n icon?: ReactNode\n onClick?: ButtonProps['onClick']\n tooltip?: ReactNode\n size?: BadgeSize\n variant?: BadgeVariant\n hoverable?: boolean\n}\n\nexport const Badge = ({\n icon,\n onClick,\n children,\n tooltip,\n size = BadgeSize.MEDIUM,\n variant = BadgeVariant.DEFAULT,\n hoverable = false,\n}: BadgeProps) => {\n const baseProps = {\n className: classNames(\n 'Layer__badge',\n hoverable && !tooltip ? 'Layer__badge--with-hover' : '',\n onClick || tooltip ? 'Layer__badge--clickable' : '',\n `Layer__badge--${size}`,\n `Layer__badge--${variant}`,\n ),\n onClick,\n children,\n }\n\n let content = (\n <>\n {icon && <span className='Layer__badge__icon'>{icon}</span>}\n {children}\n </>\n )\n\n content = onClick ? (\n <button role='button' {...baseProps}>\n {content}\n </button>\n ) : (\n <span {...baseProps}>{content}</span>\n )\n\n if (tooltip) {\n return (\n <Tooltip offset={12}>\n <TooltipTrigger>{content}</TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{tooltip}</TooltipContent>\n </Tooltip>\n )\n }\n\n return content\n}\n", "import React, { ReactNode } from 'react'\nimport AlertOctagon from '../../icons/AlertOctagon'\nimport CheckCircle from '../../icons/CheckCircle'\nimport Loader from '../../icons/Loader'\nimport RefreshCcw from '../../icons/RefreshCcw'\nimport { Button, ButtonVariant } from '../Button'\nimport { Text, TextSize, TextWeight } from '../Typography'\n\nexport enum DataStateStatus {\n allDone = 'allDone',\n success = 'success',\n failed = 'failed',\n info = 'info',\n}\n\nexport interface DataStateProps {\n status: DataStateStatus\n title?: string\n icon?: ReactNode\n description?: string\n onRefresh?: () => void\n isLoading?: boolean\n}\n\nconst getIcon = (status: DataStateStatus, icon?: ReactNode) => {\n switch (status) {\n case DataStateStatus.failed:\n return (\n <span className='Layer__data-state__icon Layer__data-state__icon--error'>\n {icon ?? <AlertOctagon size={12} />}\n </span>\n )\n case DataStateStatus.info:\n return (\n <span className='Layer__data-state__icon Layer__data-state__icon--neutral'>\n {icon ?? <AlertOctagon size={12} />}\n </span>\n )\n case DataStateStatus.success:\n return (\n <span className='Layer__data-state__icon Layer__data-state__icon--success'>\n {icon ?? <AlertOctagon size={12} />}\n </span>\n )\n default:\n return (\n <span className='Layer__data-state__icon Layer__data-state__icon--neutral'>\n {icon ?? <CheckCircle size={12} />}\n </span>\n )\n }\n}\n\nexport const DataState = ({\n status,\n title,\n description,\n onRefresh,\n isLoading,\n icon,\n}: DataStateProps) => {\n return (\n <div className='Layer__data-state'>\n {getIcon(status, icon)}\n <Text\n as='span'\n size={TextSize.lg}\n weight={TextWeight.bold}\n className='Layer__data-state__title'\n >\n {title}\n </Text>\n <Text as='span' className='Layer__data-state__description'>\n {description}\n </Text>\n {onRefresh && (\n <span className='Layer__data-state__btn'>\n <Button\n variant={ButtonVariant.secondary}\n rightIcon={\n isLoading ? (\n <Loader size={14} className='Layer__anim--rotating' />\n ) : (\n <RefreshCcw size={12} />\n )\n }\n onClick={onRefresh}\n disabled={isLoading}\n >\n Refresh\n </Button>\n </span>\n )}\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst AlertOctagon = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M5.895 1.5H12.105L16.5 5.895V12.105L12.105 16.5H5.895L1.5 12.105V5.895L5.895 1.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 6V9'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 12H9.0075'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default AlertOctagon\n", "import React, { useContext } from 'react'\nimport { LinkedAccountsContext } from '../../contexts/LinkedAccountsContext'\nimport { LinkedAccountsProvider } from '../../providers/LinkedAccountsProvider'\nimport { Container, Header } from '../Container'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { Loader } from '../Loader'\nimport { Heading, HeadingSize } from '../Typography'\nimport { LinkedAccountsContent } from './LinkedAccountsContent'\n\nconst COMPONENT_NAME = 'linked-accounts'\n\nexport interface LinkedAccountsProps {\n asWidget?: boolean\n elevated?: boolean\n showLedgerBalance?: boolean\n showUnlinkItem?: boolean\n showBreakConnection?: boolean\n stringOverrides?: {\n title?: string\n }\n}\n\nexport const LinkedAccounts = (props: LinkedAccountsProps) => {\n return (\n <LinkedAccountsProvider>\n <LinkedAccountsComponent {...props} />\n </LinkedAccountsProvider>\n )\n}\n\nexport const LinkedAccountsComponent = ({\n asWidget,\n elevated,\n showLedgerBalance = true,\n showUnlinkItem = false,\n showBreakConnection = false,\n stringOverrides,\n}: LinkedAccountsProps) => {\n const { isLoading, error, isValidating, refetchAccounts } = useContext(\n LinkedAccountsContext,\n )\n\n return (\n <Container name={COMPONENT_NAME} elevated={elevated}>\n <Header className='Layer__linked-accounts__header'>\n <Heading\n className='Layer__linked-accounts__title'\n size={HeadingSize.secondary}\n >\n {stringOverrides?.title || \"Linked Accounts\"}\n </Heading>\n </Header>\n\n {isLoading && (\n <div className='Layer__linked-accounts__loader-container'>\n <Loader />\n </div>\n )}\n {error && !isLoading ? (\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={() => refetchAccounts()}\n isLoading={isValidating}\n />\n ) : null}\n {!error && !isLoading ? (\n <LinkedAccountsContent\n asWidget={asWidget}\n showLedgerBalance={showLedgerBalance}\n showUnlinkItem={showUnlinkItem}\n showBreakConnection={showBreakConnection}\n />\n ) : null}\n </Container>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport LoaderIcon from '../../icons/Loader'\n\nexport interface LoaderProps {\n children?: ReactNode\n size?: number\n}\n\nexport const Loader = ({ children, size = 28 }: LoaderProps) => {\n return (\n <span className='Layer__loader'>\n <LoaderIcon size={size} className='Layer__anim--rotating' />\n {children}\n </span>\n )\n}\n", "import React from 'react'\nimport LoaderIcon from '../../icons/Loader'\n\nexport interface SmallLoaderProps {\n size?: number\n}\n\nexport const SmallLoader = ({ size = 28 }: SmallLoaderProps) => {\n return (\n <span\n className='Layer__loader Layer__loader--with-bg'\n style={{ width: size, height: size, minWidth: size, minHeight: size }}\n >\n <LoaderIcon className='Layer__anim--rotating' size={size - 16} />\n </span>\n )\n}\n", "import React, { useContext } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { LinkedAccountsContext } from '../../contexts/LinkedAccountsContext'\nimport PlusIcon from '../../icons/PlusIcon'\nimport { LinkedAccountOptions } from '../LinkedAccountOptions'\nimport { LinkedAccountThumb } from '../LinkedAccountThumb'\nimport { Text, TextSize } from '../Typography'\nimport classNames from 'classnames'\n\ninterface LinkedAccountsDataProps {\n asWidget?: boolean\n showLedgerBalance?: boolean\n showUnlinkItem?: boolean\n showBreakConnection?: boolean\n}\n\nexport const LinkedAccountsContent = ({\n asWidget,\n showLedgerBalance,\n showUnlinkItem,\n showBreakConnection,\n}: LinkedAccountsDataProps) => {\n const {\n data,\n addConnection,\n unlinkAccount,\n removeConnection,\n repairConnection,\n confirmAccount,\n denyAccount,\n breakConnection,\n } = useContext(LinkedAccountsContext)\n const { environment } = useLayerContext()\n\n const linkedAccountsNewAccountClassName = classNames(\n 'Layer__linked-accounts__new-account',\n asWidget && '--as-widget',\n showLedgerBalance && '--show-ledger-balance',\n showUnlinkItem && '--show-unlink-item',\n showBreakConnection && '--show-break-connection',\n )\n\n return (\n <div className='Layer__linked-accounts__list'>\n {data?.map((account, index) => {\n let pillConfig\n if (account.requires_user_confirmation_as_of) {\n pillConfig = {\n text: 'Confirm account',\n config: [\n {\n name: 'Mark as a duplicate account',\n action: async () => {\n // TODO: trigger some sort of loading spinner here\n await denyAccount(account.external_account_source, account.id)\n // TODO: turn off loading spinner\n },\n },\n {\n name: 'Mark as not a duplicate account',\n action: async () => {\n // TODO: trigger some sort of loading spinner here\n await confirmAccount(\n account.external_account_source,\n account.id,\n )\n // TODO: turn off loading spinner\n },\n },\n ],\n }\n } else if (account.connection_needs_repair_as_of) {\n pillConfig = {\n text: 'Fix account',\n config: [\n {\n name: 'Repair connection',\n action: async () => {\n if (account.connection_external_id) {\n // TODO: trigger some sort of loading spinner here\n // An account is \"broken\" when its connection is broken\n await repairConnection(\n account.external_account_source,\n account.connection_external_id,\n )\n // TODO: turn off loading spinner\n }\n },\n },\n ],\n }\n }\n\n const additionalConfigs = [\n {\n name: 'Unlink account',\n action: async () => {\n // TODO: replace with better confirm dialog\n if (\n confirm(\n 'Please confirm you wish to remove this financial account',\n )\n ) {\n // TODO: trigger some sort of loading spinner here\n await unlinkAccount(account.external_account_source, account.id)\n }\n // TODO: turn off loading spinner\n },\n },\n ]\n\n if (showUnlinkItem) {\n additionalConfigs.push({\n name: `Unlink all accounts under this ${account.institution?.name} connection`,\n action: async () => {\n // TODO: replace with better confirm dialog\n if (\n account.connection_external_id &&\n confirm(\n `Please confirm you wish to remove all accounts belonging to ${\n account.institution?.name || 'this institution'\n }`,\n )\n ) {\n // TODO: trigger some sort of loading spinner here\n await removeConnection(\n account.external_account_source,\n account.connection_external_id,\n )\n // TODO: turn off loading spinner\n }\n },\n })\n }\n\n if (\n environment === 'staging' &&\n !account.connection_needs_repair_as_of &&\n account.external_account_source === 'PLAID' &&\n showBreakConnection\n ) {\n additionalConfigs.push({\n name: 'Break connection (test utility)',\n action: async () => {\n if (account.connection_external_id) {\n await breakConnection(\n account.external_account_source,\n account.connection_external_id,\n )\n } else {\n console.warn(\n \"Account doesn't have defined connection_external_id\",\n )\n }\n },\n })\n }\n\n return (\n <LinkedAccountOptions\n key={`linked-acc-${index}`}\n config={[\n ...additionalConfigs,\n ...(pillConfig ? pillConfig.config : []),\n ]}\n showLedgerBalance={showLedgerBalance}\n >\n <LinkedAccountThumb\n account={account}\n asWidget={asWidget}\n showLedgerBalance={showLedgerBalance}\n pillConfig={pillConfig}\n />\n </LinkedAccountOptions>\n )\n })}\n <div\n role='button'\n tabIndex={0}\n aria-label='new-account'\n onClick={() => addConnection('PLAID')}\n className={linkedAccountsNewAccountClassName}\n >\n <div className='Layer__linked-accounts__new-account-label'>\n <PlusIcon size={15} />\n <Text as='span' size={'sm' as TextSize}>\n Add Account\n </Text>\n </div>\n </div>\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst PlusIcon = ({ size = 14, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 16 16'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M14.6667 8.49996C14.6667 4.81806 11.6819 1.83329 8.00004 1.83329C4.31814 1.83329 1.33337 4.81806 1.33337 8.49996C1.33337 12.1819 4.31814 15.1666 8.00004 15.1666C11.6819 15.1666 14.6667 12.1819 14.6667 8.49996Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M5.33337 8.5L10.6667 8.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M8 11.1666L8 5.83329'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default PlusIcon\n", "import React from 'react'\nimport MoreVertical from '../../icons/MoreVertical'\nimport { HoverMenu, HoverMenuProps } from '../HoverMenu'\nimport classNames from 'classnames'\n\ninterface LinkedAccountOptionsProps extends HoverMenuProps {\n showLedgerBalance?: boolean\n}\n\nexport const LinkedAccountOptions = ({\n children,\n config,\n showLedgerBalance,\n}: LinkedAccountOptionsProps) => {\n const linkedAccountOptionsClassName = classNames(\n 'Layer__linked-accounts__options',\n showLedgerBalance == false && '--hide-ledger-balance',\n )\n return (\n <div className={linkedAccountOptionsClassName}>\n <div className='Layer__linked-accounts__options-overlay'>\n {config.length ? (\n <div className='Layer__linked-accounts__options-overlay-button'>\n <HoverMenu config={config}>\n <MoreVertical size={16} />\n </HoverMenu>\n </div>\n ) : null}\n </div>\n {children}\n </div>\n )\n}\n", "import React from 'react'\nimport { IconSvgProps } from './types'\n\nconst MoreVertical = ({ size = 18, ...props }: IconSvgProps) => {\n return (\n <svg\n viewBox='0 0 16 14'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M8.66659 8C8.66659 7.63181 8.36811 7.33333 7.99992 7.33333C7.63173 7.33333 7.33325 7.63181 7.33325 8C7.33325 8.36819 7.63173 8.66667 7.99992 8.66667C8.36811 8.66667 8.66659 8.36819 8.66659 8Z'\n fill='currentColor'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M8.66659 3.33333C8.66659 2.96514 8.36811 2.66667 7.99992 2.66667C7.63173 2.66667 7.33325 2.96514 7.33325 3.33333C7.33325 3.70152 7.63173 4 7.99992 4C8.36811 4 8.66659 3.70152 8.66659 3.33333Z'\n fill='currentColor'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M8.66659 12.6667C8.66659 12.2985 8.36811 12 7.99992 12C7.63173 12 7.33325 12.2985 7.33325 12.6667C7.33325 13.0349 7.63173 13.3333 7.99992 13.3333C8.36811 13.3333 8.66659 13.0349 8.66659 12.6667Z'\n fill='currentColor'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n )\n}\n\nexport default MoreVertical\n", "import React, { ReactNode, useEffect, useRef, useState } from 'react'\nimport classNames from 'classnames'\n\nexport interface HoverMenuProps {\n children: ReactNode\n config: {\n name: string\n action: () => void\n }[]\n}\n\nexport const HoverMenu = ({ children, config }: HoverMenuProps) => {\n const [openMenu, setOpenMenu] = useState(false)\n const hoverMenuRef = useRef<HTMLDivElement>(null)\n\n const hoverMenuClassName = classNames(\n 'Layer__hover-menu',\n openMenu && 'Layer__hover-menu--open',\n )\n\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (\n hoverMenuRef.current &&\n !hoverMenuRef.current.contains(event.target as Node)\n ) {\n setOpenMenu(false)\n }\n }\n\n document.addEventListener('click', handleClickOutside)\n return () => {\n document.removeEventListener('click', handleClickOutside)\n }\n }, [])\n\n return (\n <div\n className={hoverMenuClassName}\n ref={hoverMenuRef}\n onMouseLeave={() => setOpenMenu(false)}\n >\n <div\n className='Layer__hover-menu__children'\n role='button'\n onMouseEnter={() => setOpenMenu(true)}\n onClick={() => setOpenMenu(true)}\n >\n {children}\n </div>\n <div className='Layer__hover-menu__list-wrapper'>\n <ul className='Layer__hover-menu__list'>\n {config &&\n config.length > 0 &&\n config.map(item => (\n <li\n key={`hover-menu-${item.name}`}\n className='Layer__hover-menu__list-item'\n >\n <button\n className='Layer__hover-menu__list-item-button'\n onClick={item.action}\n >\n {item.name}\n </button>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n", "import React from 'react'\nimport InstitutionIcon from '../../icons/InstitutionIcon'\nimport LoaderIcon from '../../icons/Loader'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { LinkedAccount } from '../../types/linked_accounts'\nimport { LinkedAccountPill } from '../LinkedAccountPill'\nimport { Text, TextSize } from '../Typography'\nimport classNames from 'classnames'\n\nexport interface LinkedAccountThumbProps {\n account: LinkedAccount\n asWidget?: boolean\n showLedgerBalance?: boolean\n pillConfig?: {\n text: string\n config: { name: string; action: () => void }[]\n }\n}\n\nconst AccountNumber = ({ accountNumber }: { accountNumber: string }) => (\n <div className='account-number'>\n <Text size={'sm' as TextSize}>\u2022\u2022\u2022 {accountNumber}</Text>\n </div>\n)\n\nexport const LinkedAccountThumb = ({\n account,\n asWidget,\n showLedgerBalance,\n pillConfig,\n}: LinkedAccountThumbProps) => {\n const linkedAccountThumbClassName = classNames(\n 'Layer__linked-account-thumb',\n asWidget && '--as-widget',\n account.is_syncing && '--is-syncing',\n account.is_syncing && 'skeleton-loader',\n showLedgerBalance && '--show-ledger-balance',\n )\n\n const linkedAccountInfoClassName = classNames(\n 'topbar',\n account.is_syncing && '--is-syncing',\n !(showLedgerBalance || account.is_syncing) && '--hide-ledger-balance',\n )\n\n let bankBalance: React.ReactNode\n if (pillConfig) {\n bankBalance = (\n <LinkedAccountPill text={pillConfig.text} config={pillConfig.config} />\n )\n } else {\n bankBalance = (\n <Text as='span' className='account-balance'>\n {`${formatMoney(account.latest_balance_timestamp?.balance)}`}\n </Text>\n )\n }\n\n return (\n <div className={linkedAccountThumbClassName}>\n <div className={linkedAccountInfoClassName}>\n <div className='topbar-details'>\n <Text as='div' className='account-name'>\n {account.external_account_name}\n </Text>\n {!asWidget && account.mask && (\n <AccountNumber accountNumber={account.mask} />\n )}\n <Text\n as='span'\n className='account-institution'\n size={'sm' as TextSize}\n >\n {account.institution?.name\n ? account.institution?.name\n : account.external_account_name}\n </Text>\n </div>\n <div className='topbar-logo'>\n {account.institution?.logo != undefined ? (\n <img\n width={28}\n height={28}\n src={`data:image/png;base64,${account.institution.logo}`}\n alt={\n account.institution?.name\n ? account.institution?.name\n : account.external_account_name\n }\n />\n ) : (\n <InstitutionIcon />\n )}\n </div>\n </div>\n {account.is_syncing ? (\n <div className='loadingbar'>\n <div className='loading-text Layer__text--sm'>\n <div>Syncing account data</div>\n <div className='syncing-data-description'>\n This may take up to 5 minutes\n </div>\n </div>\n <div className='loading-wrapper'>\n <LoaderIcon size={11} className='Layer__anim--rotating' />\n </div>\n </div>\n ) : (\n <>\n {!asWidget && (\n <div className='middlebar'>\n <Text\n as='span'\n className={classNames(\n 'account-balance-text',\n !showLedgerBalance && '--hide-ledger-balance',\n )}\n size={'sm' as TextSize}\n >\n Bank balance\n </Text>\n {bankBalance}\n </div>\n )}\n {showLedgerBalance && (\n <div className='bottombar'>\n {asWidget && account.mask ? (\n <AccountNumber accountNumber={account.mask} />\n ) : (\n <Text\n as='span'\n className='account-balance-text'\n size={'sm' as TextSize}\n >\n Ledger balance\n </Text>\n )}\n <Text as='span' className='account-balance'>\n {`${formatMoney(account.current_ledger_balance)}`}\n </Text>\n </div>\n )}\n </>\n )}\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst InstitutionIcon = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 27 28'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <g filter='url(#filter0_i_2320_122784)'>\n <path\n d='M0 8.50225C0 8.13268 0.20383 7.79324 0.530047 7.61956L13.03 0.964441C13.3238 0.80803 13.6762 0.808029 13.97 0.964441L26.47 7.61956C26.7962 7.79324 27 8.13268 27 8.50225V9.71423C27 10.2665 26.5523 10.7142 26 10.7142H0.999999C0.447715 10.7142 0 10.2665 0 9.71423V8.50225Z'\n fill='currentColor'\n />\n </g>\n <g filter='url(#filter1_i_2320_122784)'>\n <path\n d='M3 13C3 12.4477 3.44772 12 4 12H7C7.55228 12 8 12.4477 8 13V20C8 20.5523 7.55228 21 7 21H4C3.44772 21 3 20.5523 3 20L3 13Z'\n fill='currentColor'\n />\n </g>\n <g filter='url(#filter2_i_2320_122784)'>\n <path\n d='M11 13C11 12.4477 11.4477 12 12 12H15C15.5523 12 16 12.4477 16 13V20C16 20.5523 15.5523 21 15 21H12C11.4477 21 11 20.5523 11 20L11 13Z'\n fill='currentColor'\n />\n </g>\n <g filter='url(#filter3_i_2320_122784)'>\n <path\n d='M19 13C19 12.4477 19.4477 12 20 12H23C23.5523 12 24 12.4477 24 13V20C24 20.5523 23.5523 21 23 21H20C19.4477 21 19 20.5523 19 20L19 13Z'\n fill='currentColor'\n />\n </g>\n <g filter='url(#filter4_i_2320_122784)'>\n <path\n d='M1 23.2856C1 22.7334 1.44772 22.2856 2 22.2856H25C25.5523 22.2856 26 22.7334 26 23.2856V26.2856C26 26.8379 25.5523 27.2856 25 27.2856H2C1.44772 27.2856 1 26.8379 1 26.2856L1 23.2856Z'\n fill='currentColor'\n />\n </g>\n <defs>\n <filter\n id='filter0_i_2320_122784'\n x='0'\n y='0.847168'\n width='27'\n height='9.86707'\n filterUnits='userSpaceOnUse'\n colorInterpolationFilters='sRGB'\n >\n <feFlood floodOpacity='0' result='BackgroundImageFix' />\n <feBlend\n mode='normal'\n in='SourceGraphic'\n in2='BackgroundImageFix'\n result='shape'\n />\n <feColorMatrix\n in='SourceAlpha'\n type='matrix'\n values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'\n result='hardAlpha'\n />\n <feOffset />\n <feGaussianBlur stdDeviation='0.5' />\n <feComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1' />\n <feColorMatrix\n type='matrix'\n values='0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.04 0'\n />\n <feBlend\n mode='normal'\n in2='shape'\n result='effect1_innerShadow_2320_122784'\n />\n </filter>\n <filter\n id='filter1_i_2320_122784'\n x='3'\n y='12'\n width='5'\n height='9'\n filterUnits='userSpaceOnUse'\n colorInterpolationFilters='sRGB'\n >\n <feFlood floodOpacity='0' result='BackgroundImageFix' />\n <feBlend\n mode='normal'\n in='SourceGraphic'\n in2='BackgroundImageFix'\n result='shape'\n />\n <feColorMatrix\n in='SourceAlpha'\n type='matrix'\n values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'\n result='hardAlpha'\n />\n <feOffset />\n <feGaussianBlur stdDeviation='0.5' />\n <feComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1' />\n <feColorMatrix\n type='matrix'\n values='0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.04 0'\n />\n <feBlend\n mode='normal'\n in2='shape'\n result='effect1_innerShadow_2320_122784'\n />\n </filter>\n <filter\n id='filter2_i_2320_122784'\n x='11'\n y='12'\n width='5'\n height='9'\n filterUnits='userSpaceOnUse'\n colorInterpolationFilters='sRGB'\n >\n <feFlood floodOpacity='0' result='BackgroundImageFix' />\n <feBlend\n mode='normal'\n in='SourceGraphic'\n in2='BackgroundImageFix'\n result='shape'\n />\n <feColorMatrix\n in='SourceAlpha'\n type='matrix'\n values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'\n result='hardAlpha'\n />\n <feOffset />\n <feGaussianBlur stdDeviation='0.5' />\n <feComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1' />\n <feColorMatrix\n type='matrix'\n values='0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.04 0'\n />\n <feBlend\n mode='normal'\n in2='shape'\n result='effect1_innerShadow_2320_122784'\n />\n </filter>\n <filter\n id='filter3_i_2320_122784'\n x='19'\n y='12'\n width='5'\n height='9'\n filterUnits='userSpaceOnUse'\n colorInterpolationFilters='sRGB'\n >\n <feFlood floodOpacity='0' result='BackgroundImageFix' />\n <feBlend\n mode='normal'\n in='SourceGraphic'\n in2='BackgroundImageFix'\n result='shape'\n />\n <feColorMatrix\n in='SourceAlpha'\n type='matrix'\n values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'\n result='hardAlpha'\n />\n <feOffset />\n <feGaussianBlur stdDeviation='0.5' />\n <feComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1' />\n <feColorMatrix\n type='matrix'\n values='0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.04 0'\n />\n <feBlend\n mode='normal'\n in2='shape'\n result='effect1_innerShadow_2320_122784'\n />\n </filter>\n <filter\n id='filter4_i_2320_122784'\n x='1'\n y='22.2856'\n width='25'\n height='5'\n filterUnits='userSpaceOnUse'\n colorInterpolationFilters='sRGB'\n >\n <feFlood floodOpacity='0' result='BackgroundImageFix' />\n <feBlend\n mode='normal'\n in='SourceGraphic'\n in2='BackgroundImageFix'\n result='shape'\n />\n <feColorMatrix\n in='SourceAlpha'\n type='matrix'\n values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'\n result='hardAlpha'\n />\n <feOffset />\n <feGaussianBlur stdDeviation='0.5' />\n <feComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1' />\n <feColorMatrix\n type='matrix'\n values='0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.04 0'\n />\n <feBlend\n mode='normal'\n in2='shape'\n result='effect1_innerShadow_2320_122784'\n />\n </filter>\n </defs>\n </svg>\n)\n\nexport default InstitutionIcon\n", "const formatter = new Intl.NumberFormat('en-US', {\n minimumIntegerDigits: 1,\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n})\n\nexport const centsToDollars = (cents: number = NaN): string =>\n isNaN(cents) ? '-.--' : formatter.format(cents / 100)\n\nexport const dollarsToCents = (dollars: string = ''): number =>\n Math.round(parseFloat(dollars) * 100)\n\nexport default {\n centsToDollars,\n dollarsToCents,\n}\n", "import React from 'react'\nimport AlertCircle from '../../icons/AlertCircle'\nimport MoreVertical from '../../icons/MoreVertical'\nimport { HoverMenu } from '../HoverMenu'\nimport { Pill } from '../Pill/Pill'\n\ntype Props = {\n text: string\n config: { name: string; action: () => void }[]\n}\n\nexport const LinkedAccountPill = ({ text, config }: Props) => {\n return (\n <>\n <Pill kind='error'>\n <AlertCircle size={14} /> {text}\n <div className='Layer__linked-accounts-pill__options-overlay'>\n <HoverMenu config={config}>\n <div className={'Layer__linked-accounts-pill__invisible-spacer'} />\n </HoverMenu>\n </div>\n </Pill>\n </>\n )\n}\n", "import React, { PropsWithChildren } from 'react'\n\ntype PillKind = 'default' | 'info' | 'success' | 'warning' | 'error'\n\ntype Props = PropsWithChildren & { kind?: PillKind; onHover?: () => void }\n\nexport const Pill = ({ children, kind = 'default', onHover }: Props) => (\n <span\n onMouseOver={onHover}\n className={`Layer__pill ${kind === 'error' ? 'Layer__pill--error' : ''}`}\n >\n {children}\n </span>\n)\n", "import React, { useState, useMemo, useEffect } from 'react'\nimport { BREAKPOINTS } from '../../config/general'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { BankTransactionFilters } from '../../hooks/useBankTransactions/types'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { useLinkedAccounts } from '../../hooks/useLinkedAccounts'\nimport { BankTransaction, DateRange, DisplayState } from '../../types'\nimport { debounce } from '../../utils/helpers'\nimport { BankTransactionList } from '../BankTransactionList'\nimport { BankTransactionMobileList } from '../BankTransactionMobileList'\nimport { BankTransactionsTable } from '../BankTransactionsTable'\nimport { BankTransactionsTableStringOverrides } from '../BankTransactionsTable/BankTransactionsTable'\nimport { Container } from '../Container'\nimport { ErrorBoundary } from '../ErrorBoundary'\nimport { Loader } from '../Loader'\nimport { Pagination } from '../Pagination'\nimport {\n BankTransactionsHeader,\n BankTransactionsHeaderStringOverrides,\n} from './BankTransactionsHeader'\nimport { DataStates } from './DataStates'\nimport { MobileComponentType } from './constants'\nimport { endOfMonth, parseISO, startOfMonth } from 'date-fns'\n\nconst COMPONENT_NAME = 'bank-transactions'\nconst TEST_EMPTY_STATE = false\nconst POLL_INTERVAL = 10000\n\nexport type BankTransactionsMode = 'bookkeeping-client' | 'self-serve'\n\nexport const categorizationEnabled: (\n mode: BankTransactionsMode,\n) => boolean = mode => {\n if (mode === 'bookkeeping-client') {\n return false\n }\n return true\n}\n\nexport interface BankTransactionsStringOverrides {\n bankTransactionCTAs?: BankTransactionCTAStringOverrides\n transactionsTable?: BankTransactionsTableStringOverrides\n bankTransactionsHeader?: BankTransactionsHeaderStringOverrides\n}\n\nexport interface BankTransactionCTAStringOverrides {\n approveButtonText?: string\n updateButtonText?: string\n}\n\nexport interface BankTransactionsProps {\n asWidget?: boolean\n pageSize?: number\n mode?: BankTransactionsMode\n showDescriptions?: boolean\n showReceiptUploads?: boolean\n monthlyView?: boolean\n categorizeView?: boolean\n mobileComponent?: MobileComponentType\n filters?: BankTransactionFilters\n hideHeader?: boolean\n stringOverrides?: BankTransactionsStringOverrides\n}\n\nexport interface BankTransactionsWithErrorProps extends BankTransactionsProps {\n onError?: (error: Error) => void\n}\n\nexport const BankTransactions = ({\n onError,\n ...props\n}: BankTransactionsWithErrorProps) => {\n return (\n <ErrorBoundary onError={onError}>\n <BankTransactionsContent {...props} />\n </ErrorBoundary>\n )\n}\n\nconst BankTransactionsContent = ({\n asWidget = false,\n pageSize = 20,\n mode = 'self-serve',\n showDescriptions = false,\n showReceiptUploads = false,\n monthlyView = false,\n mobileComponent,\n filters: inputFilters,\n hideHeader = false,\n stringOverrides,\n}: BankTransactionsProps) => {\n const [currentPage, setCurrentPage] = useState(1)\n const [initialLoad, setInitialLoad] = useState(true)\n const [dateRange, setDateRange] = useState<DateRange>({\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n })\n const categorizeView = categorizationEnabled(mode)\n\n const {\n activate,\n data,\n isLoading,\n loadingStatus,\n error,\n isValidating,\n refetch,\n setFilters,\n filters,\n display,\n hasMore,\n fetchMore,\n removeAfterCategorize,\n } = useBankTransactionsContext()\n\n const { data: linkedAccounts, refetchAccounts } = useLinkedAccounts()\n\n const isSyncing = useMemo(\n () => Boolean(linkedAccounts?.some(item => item.is_syncing)),\n [linkedAccounts],\n )\n\n const transactionsNotSynced = useMemo(\n () =>\n loadingStatus === 'complete' &&\n isSyncing &&\n (!data || data?.length === 0),\n [data, isSyncing, loadingStatus],\n )\n\n let intervalId: ReturnType<typeof setInterval> | undefined = undefined\n\n // calling `refetch()` directly in the `setInterval` didn't trigger actual request to API.\n // But it works when called from `useEffect`\n const [refreshTrigger, setRefreshTrigger] = useState(-1)\n useEffect(() => {\n if (refreshTrigger !== -1) {\n refetch()\n refetchAccounts()\n }\n }, [refreshTrigger])\n\n useEffect(() => {\n if (isSyncing) {\n intervalId = setInterval(() => {\n setRefreshTrigger(Math.random())\n }, POLL_INTERVAL)\n } else {\n if (intervalId) {\n clearInterval(intervalId)\n }\n }\n\n return () => {\n if (intervalId) {\n clearInterval(intervalId)\n }\n }\n }, [isSyncing, transactionsNotSynced])\n\n useEffect(() => {\n activate()\n }, [])\n\n useEffect(() => {\n if (JSON.stringify(inputFilters) !== JSON.stringify(filters)) {\n if (!filters?.categorizationStatus && categorizeView) {\n setFilters({\n ...filters,\n ...inputFilters,\n categorizationStatus: DisplayState.review,\n })\n } else if (\n !filters?.categorizationStatus &&\n !categorizationEnabled(mode)\n ) {\n setFilters({\n ...filters,\n ...inputFilters,\n categorizationStatus: DisplayState.categorized,\n })\n } else {\n setFilters({ ...filters, ...inputFilters })\n }\n } else if (!filters?.categorizationStatus && categorizeView) {\n setFilters({\n categorizationStatus: DisplayState.review,\n })\n } else if (!filters?.categorizationStatus && !categorizationEnabled(mode)) {\n setFilters({\n categorizationStatus: DisplayState.categorized,\n })\n }\n }, [inputFilters, categorizeView, mode])\n\n useEffect(() => {\n if (loadingStatus === 'complete') {\n const timeoutLoad = setTimeout(() => {\n setInitialLoad(false)\n }, 1000)\n return () => clearTimeout(timeoutLoad)\n }\n }, [loadingStatus])\n\n const bankTransactions = TEST_EMPTY_STATE\n ? []\n : useMemo(() => {\n if (monthlyView) {\n return data?.filter(\n x =>\n parseISO(x.date) >= dateRange.startDate &&\n parseISO(x.date) <= dateRange.endDate,\n )\n }\n\n const firstPageIndex = (currentPage - 1) * pageSize\n const lastPageIndex = firstPageIndex + pageSize\n return data?.slice(firstPageIndex, lastPageIndex)\n }, [currentPage, data, dateRange])\n\n const onCategorizationDisplayChange = (\n event: React.ChangeEvent<HTMLInputElement>,\n ) => {\n setFilters({\n categorizationStatus:\n event.target.value === DisplayState.categorized\n ? DisplayState.categorized\n : DisplayState.review,\n })\n setCurrentPage(1)\n }\n\n const [shiftStickyHeader, setShiftStickyHeader] = useState(0)\n const debounceShiftStickyHeader = debounce(setShiftStickyHeader, 500)\n const [listView, setListView] = useState(false)\n const [containerWidth, setContainerWidth] = useState(0)\n const debounceContainerWidth = debounce(setContainerWidth, 500)\n\n const removeTransaction = (bankTransaction: BankTransaction) =>\n removeAfterCategorize(bankTransaction)\n\n const containerRef = useElementSize<HTMLDivElement>((_el, _en, size) => {\n if (size?.height && size?.height >= 90) {\n const newShift = -Math.floor(size.height / 2) + 6\n if (newShift !== shiftStickyHeader) {\n debounceShiftStickyHeader(newShift)\n }\n } else if (size?.height > 0 && shiftStickyHeader !== 0) {\n debounceShiftStickyHeader(0)\n }\n\n if (size.width > BREAKPOINTS.TABLET && listView) {\n setListView(false)\n } else if (size.width <= BREAKPOINTS.TABLET && !listView) {\n setListView(true)\n }\n\n debounceContainerWidth(size?.width)\n })\n\n const editable = display === DisplayState.review\n\n const isLastPage =\n data &&\n !hasMore &&\n Math.ceil((data?.length || 0) / pageSize) === currentPage\n\n return (\n <Container\n className={\n display === DisplayState.review\n ? 'Layer__bank-transactions--to-review'\n : 'Layer__bank-transactions--categorized'\n }\n transparentBg={listView && mobileComponent === 'mobileList'}\n name={COMPONENT_NAME}\n asWidget={asWidget}\n ref={containerRef}\n >\n {!hideHeader && (\n <BankTransactionsHeader\n shiftStickyHeader={shiftStickyHeader}\n asWidget={asWidget}\n categorizedOnly={!categorizationEnabled(mode)}\n categorizeView={categorizeView}\n display={display}\n onCategorizationDisplayChange={onCategorizationDisplayChange}\n mobileComponent={mobileComponent}\n withDatePicker={monthlyView}\n listView={listView}\n dateRange={dateRange}\n setDateRange={v => setDateRange(v)}\n stringOverrides={stringOverrides?.bankTransactionsHeader}\n isDataLoading={isLoading}\n isSyncing={isSyncing}\n />\n )}\n\n {!listView && (\n <div className='Layer__bank-transactions__table-wrapper'>\n <BankTransactionsTable\n categorizeView={categorizeView}\n editable={editable}\n isLoading={isLoading}\n isSyncing={isSyncing}\n bankTransactions={bankTransactions}\n mode={mode}\n initialLoad={initialLoad}\n containerWidth={containerWidth}\n removeTransaction={removeTransaction}\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n page={currentPage}\n stringOverrides={stringOverrides}\n lastPage={isLastPage}\n onRefresh={refetch}\n />\n </div>\n )}\n\n {!isLoading && listView && mobileComponent !== 'mobileList' ? (\n <BankTransactionList\n mode={mode}\n bankTransactions={bankTransactions}\n editable={editable}\n removeTransaction={removeTransaction}\n containerWidth={containerWidth}\n stringOverrides={stringOverrides?.bankTransactionCTAs}\n />\n ) : null}\n\n {!isLoading && listView && mobileComponent === 'mobileList' ? (\n <BankTransactionMobileList\n bankTransactions={bankTransactions}\n editable={editable}\n mode={mode}\n removeTransaction={removeTransaction}\n initialLoad={initialLoad}\n />\n ) : null}\n\n {listView && isLoading ? (\n <div className='Layer__bank-transactions__list-loader'>\n <Loader />\n </div>\n ) : null}\n\n {!isSyncing || listView ? (\n <DataStates\n bankTransactions={bankTransactions}\n isLoading={isLoading}\n isValidating={isValidating}\n error={error}\n refetch={refetch}\n editable={editable}\n />\n ) : null}\n\n {!monthlyView && (\n <div className='Layer__bank-transactions__pagination'>\n <Pagination\n currentPage={currentPage}\n totalCount={data?.length || 0}\n pageSize={pageSize}\n onPageChange={page => setCurrentPage(page)}\n fetchMore={fetchMore}\n hasMore={hasMore}\n />\n </div>\n )}\n </Container>\n )\n}\n", "import { useLayoutEffect, useRef } from 'react'\n\nexport const useElementSize = <T extends HTMLElement>(\n callback: (\n target: T,\n entry: ResizeObserverEntry,\n size: {\n width: number\n height: number\n clientWidth: number\n clientHeight: number\n },\n ) => void,\n) => {\n const ref = useRef<T>(null)\n\n useLayoutEffect(() => {\n const element = ref?.current\n\n if (!element) {\n return\n }\n\n const observer = new ResizeObserver(entries => {\n callback(element, entries[0], {\n width: element.offsetWidth,\n height: element.offsetHeight,\n clientWidth: element.clientWidth,\n clientHeight: element.clientHeight,\n })\n })\n\n observer.observe(element)\n return () => {\n observer.disconnect()\n }\n }, [callback, ref])\n\n return ref\n}\n", "export const range = (start: number, end: number) => {\n let length = end - start + 1\n return Array.from({ length }, (_, idx) => idx + start)\n}\n\nexport const debounce = <F extends (...args: Parameters<F>) => ReturnType<F>>(\n fnc: F,\n timeout = 300,\n) => {\n let timer: ReturnType<typeof setTimeout>\n return (...args: Parameters<F>) => {\n clearTimeout(timer)\n timer = setTimeout(() => {\n fnc.apply(this, args)\n }, timeout)\n }\n}\n\nexport const sleep = (time: number) => {\n return new Promise(resolve => setTimeout(resolve, time))\n}\n\n/**\n * Convert the account name into stable_name\n */\nexport const convertToStableName = (name: string): string =>\n name\n .replace(/[`~!@#$%^&*()_|+\\-=?;:'\",.<>\\{\\}\\[\\]\\\\\\/]/gi, '')\n .replace(/\\W+/g, ' ')\n .split(/ |\\B(?=[A-Z])/)\n .map(word => word.toLowerCase())\n .join('_')\n", "import React from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport { BankTransaction } from '../../types'\nimport {\n BankTransactionCTAStringOverrides,\n BankTransactionsMode,\n} from '../BankTransactions/BankTransactions'\nimport { BankTransactionListItem } from './BankTransactionListItem'\n\ninterface BankTransactionListProps {\n bankTransactions?: BankTransaction[]\n editable: boolean\n mode: BankTransactionsMode\n containerWidth: number\n removeTransaction: (bt: BankTransaction) => void\n showDescriptions?: boolean\n showReceiptUploads?: boolean\n stringOverrides?: BankTransactionCTAStringOverrides\n}\n\nexport const BankTransactionList = ({\n bankTransactions,\n editable,\n removeTransaction,\n mode,\n containerWidth,\n showDescriptions = false,\n showReceiptUploads = false,\n stringOverrides,\n}: BankTransactionListProps) => {\n return (\n <ul className='Layer__bank-transactions__list'>\n {bankTransactions?.map(\n (bankTransaction: BankTransaction, index: number) => (\n <BankTransactionListItem\n index={index}\n key={bankTransaction.id}\n dateFormat={DATE_FORMAT}\n bankTransaction={bankTransaction}\n mode={mode}\n editable={editable}\n removeTransaction={removeTransaction}\n containerWidth={containerWidth}\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n stringOverrides={stringOverrides}\n />\n ),\n )}\n </ul>\n )\n}\n", "import React, { useEffect, useRef, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction } from '../../types'\nimport { getCategorizePayload, isCredit } from '../../utils/bankTransactions'\nimport { getDefaultSelectedCategory } from '../BankTransactionRow/BankTransactionRow'\nimport {\n BankTransactionCTAStringOverrides,\n BankTransactionsMode,\n} from '../BankTransactions/BankTransactions'\nimport { isCategorized } from '../BankTransactions/utils'\nimport { RetryButton, SubmitButton } from '../Button'\nimport { SubmitAction } from '../Button/SubmitButton'\nimport { CategorySelect } from '../CategorySelect'\nimport { ExpandedBankTransactionRow } from '../ExpandedBankTransactionRow'\nimport { SaveHandle } from '../ExpandedBankTransactionRow/ExpandedBankTransactionRow'\nimport { ErrorText, Text } from '../Typography'\nimport { TextUseTooltip } from '../Typography/Text'\nimport { Assignment } from './Assignment'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\ntype Props = {\n index: number\n dateFormat: string\n bankTransaction: BankTransaction\n editable: boolean\n mode: BankTransactionsMode\n showDescriptions: boolean\n showReceiptUploads: boolean\n removeTransaction: (bt: BankTransaction) => void\n containerWidth?: number\n stringOverrides?: BankTransactionCTAStringOverrides\n}\n\nexport const BankTransactionListItem = ({\n index = 0,\n dateFormat,\n bankTransaction,\n editable,\n mode,\n showDescriptions,\n showReceiptUploads,\n containerWidth,\n removeTransaction,\n stringOverrides,\n}: Props) => {\n const expandedRowRef = useRef<SaveHandle>(null)\n const [showRetry, setShowRetry] = useState(false)\n const { categorize: categorizeBankTransaction, match: matchBankTransaction } =\n useBankTransactionsContext()\n const [selectedCategory, setSelectedCategory] = useState(\n getDefaultSelectedCategory(bankTransaction),\n )\n\n const [open, setOpen] = useState(false)\n const toggleOpen = () => {\n setShowRetry(false)\n setOpen(!open)\n }\n\n const [showComponent, setShowComponent] = useState(false)\n\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, index * 80)\n\n return () => clearTimeout(timeoutId)\n }, [])\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n }\n }, [bankTransaction.error])\n\n useEffect(() => {\n if (editable && bankTransaction.recently_categorized) {\n setTimeout(() => {\n removeTransaction(bankTransaction)\n }, 300)\n }\n }, [bankTransaction.recently_categorized])\n\n const save = () => {\n // Save using form from expanded row when row is open:\n if (open && expandedRowRef?.current) {\n expandedRowRef?.current?.save()\n return\n }\n\n if (!selectedCategory) {\n return\n }\n\n if (selectedCategory.type === 'match') {\n matchBankTransaction(bankTransaction.id, selectedCategory.payload.id)\n return\n }\n\n categorizeBankTransaction(bankTransaction.id, {\n type: 'Category',\n category: getCategorizePayload(selectedCategory),\n })\n }\n\n const categorized = isCategorized(bankTransaction)\n\n const className = 'Layer__bank-transaction-list-item'\n const openClassName = open ? `${className}--expanded` : ''\n const rowClassName = classNames(\n className,\n bankTransaction.recently_categorized && editable\n ? 'Layer__bank-transaction-row--removing'\n : '',\n open ? openClassName : '',\n showComponent ? 'show' : '',\n )\n\n return (\n <li className={rowClassName}>\n <span className={`${className}__heading`}>\n <div className={`${className}__heading__main`}>\n <span className={`${className}__heading-date`}>\n {formatTime(parseISO(bankTransaction.date), dateFormat)}\n </span>\n <span className={`${className}__heading-separator`} />\n <span className={`${className}__heading-account-name`}>\n {bankTransaction.account_name ?? ''}\n </span>\n </div>\n <div\n onClick={toggleOpen}\n className='Layer__bank-transaction-row__expand-button'\n >\n <ChevronDownFill\n className={`Layer__chevron ${\n open ? 'Layer__chevron__up' : 'Layer__chevron__down'\n }`}\n />\n </div>\n </span>\n <span className={`${className}__body`}>\n <span className={`${className}__body__name`}>\n <Text as='span' withTooltip={TextUseTooltip.whenTruncated}>\n {bankTransaction.counterparty_name ?? bankTransaction.description}\n </Text>\n </span>\n <span\n className={`${className}__amount-${\n isCredit(bankTransaction) ? 'credit' : 'debit'\n }`}\n >\n {isCredit(bankTransaction) ? '+$' : ' $'}\n {formatMoney(bankTransaction.amount)}\n </span>\n </span>\n <span className={`${className}__expanded-row`}>\n <ExpandedBankTransactionRow\n ref={expandedRowRef}\n bankTransaction={bankTransaction}\n isOpen={open}\n mode={mode}\n close={() => setOpen(false)}\n categorized={categorized}\n asListItem={true}\n submitBtnText={\n categorized\n ? stringOverrides?.updateButtonText || 'Update'\n : stringOverrides?.approveButtonText || 'Approve'\n }\n containerWidth={containerWidth}\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n />\n </span>\n <span className={`${className}__base-row`}>\n {!categorized ? (\n <CategorySelect\n bankTransaction={bankTransaction}\n name={`category-${bankTransaction.id}`}\n value={selectedCategory}\n onChange={category => {\n setShowRetry(false)\n setSelectedCategory(category)\n }}\n disabled={bankTransaction.processing}\n />\n ) : null}\n {categorized ? <Assignment bankTransaction={bankTransaction} /> : null}\n {!categorized && !showRetry ? (\n <SubmitButton\n onClick={() => {\n if (!bankTransaction.processing) {\n save()\n }\n }}\n className='Layer__bank-transaction__submit-btn'\n processing={bankTransaction.processing}\n action={!categorized ? SubmitAction.SAVE : SubmitAction.UPDATE}\n >\n {!categorized\n ? stringOverrides?.approveButtonText || 'Approve'\n : stringOverrides?.updateButtonText || 'Update'}\n </SubmitButton>\n ) : null}\n {!categorized && showRetry ? (\n <RetryButton\n onClick={() => {\n if (!bankTransaction.processing) {\n save()\n }\n }}\n className='Layer__bank-transaction__retry-btn'\n processing={bankTransaction.processing}\n error={\n 'Approval failed. Check connection and retry in few seconds.'\n }\n >\n Retry\n </RetryButton>\n ) : null}\n </span>\n {bankTransaction.error && showRetry ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : null}\n </li>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ChevronDownFill = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path d='M4.5 6.75L9 11.25L13.5 6.75' fill='currentColor' />\n <path\n d='M4.5 6.75L9 11.25L13.5 6.75H4.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default ChevronDownFill\n", "import React, { useEffect, useRef, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport AlertCircle from '../../icons/AlertCircle'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport Scissors from '../../icons/Scissors'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction, CategorizationStatus, Category } from '../../types'\nimport { hasSuggestions } from '../../types/categories'\nimport { getCategorizePayload, isCredit } from '../../utils/bankTransactions'\nimport { Badge } from '../Badge'\nimport {\n BankTransactionCTAStringOverrides,\n BankTransactionsMode,\n categorizationEnabled,\n} from '../BankTransactions/BankTransactions'\nimport { isCategorized } from '../BankTransactions/utils'\nimport { SubmitButton, IconButton, RetryButton } from '../Button'\nimport { SubmitAction } from '../Button/SubmitButton'\nimport { CategorySelect } from '../CategorySelect'\nimport {\n mapCategoryToOption,\n mapSuggestedMatchToOption,\n} from '../CategorySelect/CategorySelect'\nimport { ExpandedBankTransactionRow } from '../ExpandedBankTransactionRow'\nimport { SaveHandle } from '../ExpandedBankTransactionRow/ExpandedBankTransactionRow'\nimport { Text } from '../Typography'\nimport { TextSize, TextUseTooltip } from '../Typography/Text'\nimport { MatchBadge } from './MatchBadge'\nimport { SplitTooltipDetails } from './SplitTooltipDetails'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\ntype Props = {\n index: number\n editable: boolean\n dateFormat: string\n bankTransaction: BankTransaction\n removeTransaction: (bt: BankTransaction) => void\n containerWidth?: number\n initialLoad?: boolean\n showDescriptions: boolean\n showReceiptUploads: boolean\n mode: BankTransactionsMode\n stringOverrides?: BankTransactionCTAStringOverrides\n}\n\nexport type LastSubmittedForm = 'simple' | 'match' | 'split' | undefined\n\nexport const extractDescriptionForSplit = (category: Category) => {\n if (!category.entries) {\n return ''\n }\n\n return category.entries.map(c => c.category.display_name).join(', ')\n}\n\nexport const getDefaultSelectedCategory = (\n bankTransaction: BankTransaction,\n) => {\n if (bankTransaction.suggested_matches?.[0]) {\n return mapSuggestedMatchToOption(bankTransaction.suggested_matches?.[0])\n }\n if (hasSuggestions(bankTransaction.categorization_flow)) {\n return mapCategoryToOption(\n bankTransaction.categorization_flow.suggestions[0],\n )\n }\n return undefined\n}\n\nlet clickTimer = Date.now()\n\nexport const BankTransactionRow = ({\n index = 0,\n editable,\n dateFormat,\n bankTransaction,\n mode,\n removeTransaction,\n containerWidth,\n initialLoad,\n showDescriptions,\n showReceiptUploads,\n stringOverrides,\n}: Props) => {\n const expandedRowRef = useRef<SaveHandle>(null)\n const [showRetry, setShowRetry] = useState(false)\n const {\n filters,\n categorize: categorizeBankTransaction,\n match: matchBankTransaction,\n } = useBankTransactionsContext()\n const [selectedCategory, setSelectedCategory] = useState(\n getDefaultSelectedCategory(bankTransaction),\n )\n const [open, setOpen] = useState(false)\n const toggleOpen = () => {\n setShowRetry(false)\n setOpen(!open)\n }\n\n const openRow = {\n onMouseDown: () => {\n clickTimer = Date.now()\n },\n onMouseUp: () => {\n if (Date.now() - clickTimer < 100 && !open) {\n setShowRetry(false)\n setOpen(true)\n }\n },\n }\n\n const [showComponent, setShowComponent] = useState(false)\n\n useEffect(() => {\n if (initialLoad) {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, index * 10)\n\n return () => clearTimeout(timeoutId)\n } else {\n setShowComponent(true)\n }\n }, [])\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n }\n }, [bankTransaction.error])\n\n useEffect(() => {\n if (editable && bankTransaction.recently_categorized) {\n setTimeout(() => {\n removeTransaction(bankTransaction)\n }, 300)\n }\n }, [bankTransaction.recently_categorized])\n\n const save = async () => {\n // Save using form from expanded row when row is open:\n if (open && expandedRowRef?.current) {\n expandedRowRef?.current?.save()\n return\n }\n\n if (!selectedCategory) {\n return\n }\n\n if (selectedCategory.type === 'match') {\n await matchBankTransaction(\n bankTransaction.id,\n selectedCategory.payload.id,\n )\n setOpen(false)\n return\n }\n\n await categorizeBankTransaction(bankTransaction.id, {\n type: 'Category',\n category: getCategorizePayload(selectedCategory),\n })\n setOpen(false)\n }\n\n const categorized = isCategorized(bankTransaction)\n\n const className = 'Layer__bank-transaction-row'\n const openClassName = open ? `${className}--expanded` : ''\n const rowClassName = classNames(\n className,\n bankTransaction.recently_categorized && editable\n ? 'Layer__bank-transaction-row--removing'\n : '',\n open ? openClassName : '',\n initialLoad ? 'initial-load' : '',\n showComponent ? 'show' : '',\n )\n\n return (\n <>\n <tr className={rowClassName}>\n <td\n className='Layer__table-cell Layer__bank-transaction-table__date-col'\n {...openRow}\n >\n <span className='Layer__table-cell-content'>\n {formatTime(parseISO(bankTransaction.date), dateFormat)}\n </span>\n </td>\n <td\n className='Layer__table-cell Layer__bank-transactions__tx-col'\n {...openRow}\n >\n <span className='Layer__table-cell-content'>\n <Text\n as='span'\n className='Layer__bank-transactions__tx-text'\n withTooltip={TextUseTooltip.whenTruncated}\n tooltipOptions={{\n contentClassName: 'Layer__bank-transactions__tx-tooltip',\n }}\n >\n {bankTransaction.counterparty_name ?? bankTransaction.description}\n </Text>\n </span>\n </td>\n <td\n className='Layer__table-cell Layer__bank-transactions__account-col'\n {...openRow}\n >\n <span className='Layer__table-cell-content'>\n <Text\n as='span'\n className='Layer__bank-transactions__account-text'\n withTooltip={TextUseTooltip.whenTruncated}\n >\n {bankTransaction.account_name ?? ''}\n </Text>\n </span>\n </td>\n <td\n className={`Layer__table-cell Layer__table-cell__amount-col Layer__bank-transactions__amount-col Layer__table-cell--amount ${className}__table-cell--amount-${\n isCredit(bankTransaction) ? 'credit' : 'debit'\n }`}\n {...openRow}\n >\n <span className='Layer__table-cell-content'>\n {isCredit(bankTransaction) ? '+$' : ' $'}\n {formatMoney(bankTransaction.amount)}\n </span>\n </td>\n <td\n className={classNames(\n 'Layer__table-cell',\n 'Layer__table-cell__category-col',\n `${className}__actions-cell`,\n `${className}__actions-cell--${open ? 'open' : 'close'}`,\n )}\n >\n <span\n className={`${className}__actions-container Layer__table-cell-content`}\n >\n {!categorized && !open ? (\n <CategorySelect\n bankTransaction={bankTransaction}\n name={`category-${bankTransaction.id}`}\n value={selectedCategory}\n onChange={category => {\n setSelectedCategory(category)\n setShowRetry(false)\n }}\n disabled={bankTransaction.processing}\n />\n ) : null}\n {categorized && !open ? (\n <Text as='span' className={`${className}__category-text`}>\n {bankTransaction.categorization_status ===\n CategorizationStatus.SPLIT && (\n <>\n <Badge\n icon={<Scissors size={11} />}\n tooltip={\n <SplitTooltipDetails\n classNamePrefix={className}\n category={bankTransaction.category}\n />\n }\n >\n Split\n </Badge>\n <span className={`${className}__category-text__text`}>\n {extractDescriptionForSplit(bankTransaction.category)}\n </span>\n </>\n )}\n {bankTransaction?.categorization_status ===\n CategorizationStatus.MATCHED &&\n bankTransaction?.match && (\n <>\n <MatchBadge\n classNamePrefix={className}\n bankTransaction={bankTransaction}\n dateFormat={dateFormat}\n />\n <span className={`${className}__category-text__text`}>\n {`${formatTime(\n parseISO(bankTransaction.match.bank_transaction.date),\n dateFormat,\n )}, ${bankTransaction.match?.details?.description}`}\n </span>\n </>\n )}\n {bankTransaction?.categorization_status !==\n CategorizationStatus.MATCHED &&\n bankTransaction?.categorization_status !==\n CategorizationStatus.SPLIT && (\n <span className={`${className}__category-text__text`}>\n {bankTransaction?.category?.display_name}\n </span>\n )}\n </Text>\n ) : null}\n {!categorized && !open && showRetry ? (\n <RetryButton\n onClick={() => {\n if (!bankTransaction.processing) {\n save()\n }\n }}\n className='Layer__bank-transaction__retry-btn'\n processing={bankTransaction.processing}\n error={\n 'Approval failed. Check connection and retry in few seconds.'\n }\n >\n Retry\n </RetryButton>\n ) : null}\n {open && bankTransaction.error ? (\n <Text\n as='span'\n size={TextSize.md}\n className='Layer__unsaved-info'\n >\n <span>Unsaved</span>\n <AlertCircle size={12} />\n </Text>\n ) : null}\n {(!categorized && (open || (!open && !showRetry))) ||\n (categorizationEnabled(mode) && categorized && open) ? (\n <SubmitButton\n onClick={() => {\n if (!bankTransaction.processing) {\n save()\n }\n }}\n className='Layer__bank-transaction__submit-btn'\n processing={bankTransaction.processing}\n active={open}\n action={categorized ? SubmitAction.SAVE : SubmitAction.UPDATE}\n >\n {categorized\n ? stringOverrides?.updateButtonText || 'Update'\n : stringOverrides?.approveButtonText || 'Approve'}\n </SubmitButton>\n ) : null}\n <IconButton\n onClick={toggleOpen}\n className='Layer__bank-transaction-row__expand-button'\n active={open}\n icon={\n <ChevronDownFill\n className={`Layer__chevron ${\n open ? 'Layer__chevron__up' : 'Layer__chevron__down'\n }`}\n />\n }\n />\n </span>\n </td>\n </tr>\n <tr>\n <td colSpan={5} className='Layer__bank-transaction-row__expanded-td'>\n <ExpandedBankTransactionRow\n ref={expandedRowRef}\n bankTransaction={bankTransaction}\n categorized={categorized}\n isOpen={open}\n mode={mode}\n close={() => setOpen(false)}\n containerWidth={containerWidth}\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n />\n </td>\n </tr>\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Scissors = ({ size = 11, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 11 11'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M2.75 4.125C3.50939 4.125 4.125 3.50939 4.125 2.75C4.125 1.99061 3.50939 1.375 2.75 1.375C1.99061 1.375 1.375 1.99061 1.375 2.75C1.375 3.50939 1.99061 4.125 2.75 4.125Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n >\n <animate\n attributeName='d'\n className='animateOnHover'\n values='M2.75 4.125C3.50939 4.125 4.125 3.50939 4.125 2.75C4.125 1.99061 3.50939 1.375 2.75 1.375C1.99061 1.375 1.375 1.99061 1.375 2.75C1.375 3.50939 1.99061 4.125 2.75 4.125Z;M2.50519 5.21436C3.20276 4.91424 3.52494 4.10544 3.22481 3.40788C2.92468 2.71031 2.11589 2.38813 1.41833 2.68826C0.720762 2.98839 0.398577 3.79718 0.698706 4.49474C0.998836 5.19231 1.80763 5.51449 2.50519 5.21436Z;M2.75 4.125C3.50939 4.125 4.125 3.50939 4.125 2.75C4.125 1.99061 3.50939 1.375 2.75 1.375C1.99061 1.375 1.375 1.99061 1.375 2.75C1.375 3.50939 1.99061 4.125 2.75 4.125Z'\n begin='indefinite'\n dur='400ms'\n repeatCount='1'\n fill='freeze'\n calcMode='linear'\n keyTimes='0;0.5;1'\n />\n </path>\n <path\n d='M2.75 9.625C3.50939 9.625 4.125 9.00939 4.125 8.25C4.125 7.49061 3.50939 6.875 2.75 6.875C1.99061 6.875 1.375 7.49061 1.375 8.25C1.375 9.00939 1.99061 9.625 2.75 9.625Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n >\n <animate\n attributeName='d'\n className='animateOnHover'\n values='M2.75 9.625C3.50939 9.625 4.125 9.00939 4.125 8.25C4.125 7.49061 3.50939 6.875 2.75 6.875C1.99061 6.875 1.375 7.49061 1.375 8.25C1.375 9.00939 1.99061 9.625 2.75 9.625Z;M1.43277 8.38576C2.13615 8.67201 2.9384 8.33386 3.22465 7.63049C3.5109 6.92711 3.17275 6.12486 2.46937 5.83861C1.766 5.55236 0.96375 5.89051 0.6775 6.59389C0.391251 7.29726 0.729398 8.09951 1.43277 8.38576Z;M2.75 9.625C3.50939 9.625 4.125 9.00939 4.125 8.25C4.125 7.49061 3.50939 6.875 2.75 6.875C1.99061 6.875 1.375 7.49061 1.375 8.25C1.375 9.00939 1.99061 9.625 2.75 9.625Z'\n begin='indefinite'\n dur='400ms'\n repeatCount='1'\n fill='freeze'\n calcMode='linear'\n keyTimes='0;0.5;1'\n />\n </path>\n <path\n d='M9.16668 1.83325L3.72168 7.27825'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n >\n <animate\n attributeName='d'\n className='animateOnHover'\n values='M9.16668 1.83325L3.72168 7.27825;M10.3129 3.58763L3.21706 6.57851;M9.16668 1.83325L3.72168 7.27825'\n begin='indefinite'\n dur='400ms'\n repeatCount='1'\n fill='freeze'\n calcMode='linear'\n keyTimes='0;0.5;1'\n />\n </path>\n <path\n d='M6.63232 6.63672L9.16691 9.16672'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n >\n <animate\n attributeName='d'\n className='animateOnHover'\n values='M6.63232 6.63672L9.16691 9.16672;M7.06396 5.9873L10.3921 7.3096;M6.63232 6.63672L9.16691 9.16672'\n begin='indefinite'\n dur='400ms'\n repeatCount='1'\n fill='freeze'\n calcMode='linear'\n keyTimes='0;0.5;1'\n />\n </path>\n <path\n d='M3.72168 3.72168L5.50001 5.50001'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n >\n <animate\n attributeName='d'\n className='animateOnHover'\n values='M3.72168 3.72168L5.50001 5.50001;M3.23828 4.45996L5.57467 5.39067;M3.72168 3.72168L5.50001 5.50001'\n begin='indefinite'\n dur='400ms'\n repeatCount='1'\n fill='freeze'\n calcMode='linear'\n keyTimes='0;0.5;1'\n />\n </path>\n </svg>\n)\n\nexport default Scissors\n", "import React from 'react'\nimport Select, {\n DropdownIndicatorProps,\n GroupHeadingProps,\n GroupBase,\n OptionProps,\n components,\n} from 'react-select'\nimport { DATE_FORMAT } from '../../config/general'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport Check from '../../icons/Check'\nimport ChevronDown from '../../icons/ChevronDown'\nimport MinimizeTwo from '../../icons/MinimizeTwo'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction, CategorizationType, Category } from '../../types'\nimport { SuggestedMatch } from '../../types/bank_transactions'\nimport { CategoryEntry } from '../../types/categories'\nimport { Badge } from '../Badge'\nimport { BadgeSize } from '../Badge/Badge'\nimport { CategorySelectDrawer } from './CategorySelectDrawer'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\ntype Props = {\n name?: string\n bankTransaction: BankTransaction\n value: CategoryOption | undefined\n onChange: (newValue: CategoryOption) => void\n disabled?: boolean\n className?: string\n excludeMatches?: boolean\n asDrawer?: boolean\n}\n\nexport enum OptionActionType {\n CATEGORY = 'category',\n MATCH = 'match',\n HIDDEN = 'hidden',\n}\n\nexport interface CategoryOptionPayload {\n id: string\n option_type: OptionActionType\n display_name: string\n date?: string\n amount?: number\n type?: string\n stable_name?: string\n entries?: CategoryEntry[]\n subCategories?: Category[]\n}\n\nexport interface CategoryOption {\n type: string\n disabled?: boolean\n payload: CategoryOptionPayload\n}\n\nexport const mapCategoryToOption = (category: Category): CategoryOption => {\n return {\n type: OptionActionType.CATEGORY,\n payload: {\n id: category.id,\n option_type: OptionActionType.CATEGORY,\n display_name: category.display_name,\n type: category.type,\n stable_name: category.stable_name,\n entries: category.entries,\n subCategories: category.subCategories,\n },\n }\n}\n\nexport const mapSuggestedMatchToOption = (\n record: SuggestedMatch,\n): CategoryOption => {\n return {\n type: OptionActionType.MATCH,\n payload: {\n id: record.id,\n option_type: OptionActionType.MATCH,\n display_name: record.details.description,\n amount: record.details.amount,\n },\n }\n}\n\nconst DropdownIndicator:\n | React.ComponentType<\n DropdownIndicatorProps<CategoryOption, false, GroupBase<CategoryOption>>\n >\n | null\n | undefined = props => {\n return (\n <components.DropdownIndicator {...props}>\n <ChevronDown />\n </components.DropdownIndicator>\n )\n}\n\nconst GroupHeading = (\n props: GroupHeadingProps<CategoryOption, false, GroupBase<CategoryOption>>,\n) => {\n return (\n <components.GroupHeading\n className={classNames(\n props.className,\n props.children === 'Match' || props.children === 'All categories'\n ? 'Layer__select__group-heading--main'\n : '',\n )}\n {...props}\n />\n )\n}\n\nconst Option = (\n props: OptionProps<CategoryOption, false, GroupBase<CategoryOption>>,\n) => {\n if (props.data.payload.option_type === 'hidden') {\n return\n }\n\n if (props.data.type === 'match') {\n return (\n <components.Option\n {...props}\n className={`${props.className} Layer__select__option-content__match`}\n >\n <div className='Layer__select__option-content__match__main-row'>\n <span className='Layer__select__option-content__match__date'>\n {props.data.payload.date &&\n formatTime(parseISO(props.data.payload.date), DATE_FORMAT)}\n </span>\n <span className='Layer__select__option-content__match__description'>\n {props.data.payload.display_name}\n </span>\n </div>\n <div className='Layer__select__option-content__match__amount-row'>\n <span className='Layer__select__option-content__match__amount'>\n ${formatMoney(props.data.payload.amount)}\n </span>\n </div>\n </components.Option>\n )\n }\n\n return (\n <components.Option\n {...props}\n className={`Layer__select__option-menu-content ${props.className}`}\n >\n <div>{props.data.payload.display_name}</div>\n {props.isSelected ? (\n <span className='Layer__select__option-menu-content-check'>\n <Check size={16} />\n </span>\n ) : null}\n </components.Option>\n )\n}\n\nconst allCategoriesDivider: GroupBase<CategoryOption>[] = [\n {\n label: 'All categories',\n options: [\n {\n type: 'All categories',\n disabled: true,\n payload: {\n id: 'all_categories',\n option_type: OptionActionType.HIDDEN,\n display_name: 'ALL CATEGORIES',\n },\n } satisfies CategoryOption,\n ],\n },\n]\n\nfunction flattenCategories(\n categories: Category[],\n): GroupBase<CategoryOption>[] {\n const categoryOptions = (categories || []).flatMap(category => {\n if (category?.subCategories && category?.subCategories?.length > 0) {\n if (category?.subCategories?.every(c => c.subCategories === undefined)) {\n return [\n {\n label: category.display_name,\n options: category.subCategories.map(x => mapCategoryToOption(x)),\n },\n ]\n }\n return flattenCategories(category.subCategories)\n }\n const resultOption = {\n label: category.display_name,\n options: [mapCategoryToOption(category)],\n } satisfies GroupBase<CategoryOption>\n return [resultOption]\n })\n return categoryOptions\n}\n\nexport const CategorySelect = ({\n bankTransaction,\n name,\n value,\n onChange,\n disabled,\n className,\n excludeMatches = false,\n asDrawer = false,\n}: Props) => {\n const { categories } = useLayerContext()\n\n const matchOptions =\n !excludeMatches && bankTransaction?.suggested_matches\n ? [\n {\n label: 'Match',\n options: bankTransaction.suggested_matches.map(x => {\n return {\n type: OptionActionType.MATCH,\n payload: {\n id: x.id,\n option_type: OptionActionType.MATCH,\n display_name: x.details.description,\n date: x.details.date,\n amount: x.details.amount,\n },\n } satisfies CategoryOption\n }),\n } satisfies GroupBase<CategoryOption>,\n ]\n : []\n\n const suggestedOptions =\n bankTransaction?.categorization_flow?.type ===\n CategorizationType.ASK_FROM_SUGGESTIONS\n ? [\n {\n label: 'Suggestions',\n options: bankTransaction.categorization_flow.suggestions.map(x =>\n mapCategoryToOption(x),\n ),\n } satisfies GroupBase<CategoryOption>,\n ]\n : []\n\n const categoryOptions = flattenCategories(categories)\n\n const options = [\n ...matchOptions,\n ...suggestedOptions,\n ...allCategoriesDivider,\n ...categoryOptions,\n ]\n\n const selected = value\n ? value\n : !excludeMatches &&\n matchOptions?.length === 1 &&\n matchOptions[0].options.length === 1\n ? matchOptions[0].options[0]\n : undefined\n\n const placeholder =\n matchOptions?.length === 1 && matchOptions[0].options.length > 1\n ? `${matchOptions[0].options.length} possible matches...`\n : 'Categorize or match...'\n\n if (asDrawer) {\n return <CategorySelectDrawer onSelect={onChange} selected={value} />\n }\n\n // The menu does not show in all cases unless the\n // menuPortalTarget and styles lines exist\n // See: https://stackoverflow.com/questions/55830799/how-to-change-zindex-in-react-select-drowpdown\n return (\n <Select<CategoryOption>\n name={name}\n className={`Layer__category-menu Layer__select ${className ?? ''}`}\n classNamePrefix='Layer__select'\n classNames={{\n menu: () => 'Layer__select__menu--lg',\n }}\n options={options}\n isSearchable={true}\n placeholder={placeholder}\n defaultValue={selected}\n formatOptionLabel={props => (\n <div className='Layer__select__option-label'>\n {props.type === 'match' && (\n <Badge size={BadgeSize.SMALL} icon={<MinimizeTwo size={11} />}>\n Match\n </Badge>\n )}\n <span>{props.payload.display_name}</span>\n </div>\n )}\n value={value}\n onChange={newValue => newValue && onChange(newValue)}\n getOptionLabel={category => category.payload.display_name}\n getOptionValue={category => category.payload.id}\n menuPortalTarget={document.body}\n styles={{\n menuPortal: base => ({ ...base, zIndex: 9999 }),\n }}\n components={{ DropdownIndicator, GroupHeading, Option }}\n isDisabled={disabled}\n isOptionDisabled={option => option.disabled ?? false}\n />\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Check = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M15 4.5L6.75 12.75L3 9'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Check\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ChevronDown = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M4.5 6.75L9 11.25L13.5 6.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default ChevronDown\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst MinimizeTwo = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M3 10.5H7.5V15'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M15 7.5H10.5V3'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5 7.5L15.75 2.25'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M2.25 15.75L7.5 10.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default MinimizeTwo\n", "import React, { useContext } from 'react'\nimport { DrawerContext } from '../../contexts/DrawerContext'\nimport ChevronDown from '../../icons/ChevronDown'\nimport { BusinessCategories } from '../BankTransactionMobileList/BusinessCategories'\nimport { CategoryOption, OptionActionType } from './CategorySelect'\nimport classNames from 'classnames'\n\ninterface CategorySelectDrawerProps {\n onSelect: (value: CategoryOption) => void\n selected?: CategoryOption\n}\n\nexport const CategorySelectDrawer = ({\n onSelect,\n selected,\n}: CategorySelectDrawerProps) => {\n const { setContent, close } = useContext(DrawerContext)\n\n const onDrawerCategorySelect = (value: CategoryOption) => {\n close()\n onSelect(value)\n }\n\n return (\n <button\n aria-label='Select category'\n className={classNames(\n 'Layer__category-menu__drawer-btn',\n selected && 'Layer__category-menu__drawer-btn--selected',\n )}\n onClick={() =>\n setContent(\n <CategorySelectDrawerContent onSelect={onDrawerCategorySelect} />,\n )\n }\n >\n {selected?.payload?.display_name ?? 'Select...'}\n <ChevronDown\n size={16}\n className='Layer__category-menu__drawer-btn__arrow'\n />\n </button>\n )\n}\n\nconst CategorySelectDrawerContent = ({\n onSelect,\n}: {\n onSelect: (value: CategoryOption) => void\n}) => (\n <BusinessCategories\n select={option => {\n option.value.payload &&\n onSelect({\n type: OptionActionType.CATEGORY,\n payload: {\n ...option.value.payload,\n },\n } satisfies CategoryOption)\n }}\n />\n)\n", "import React, { useState } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { ActionableList } from '../ActionableList'\nimport { Text, TextWeight } from '../Typography'\nimport { Option, flattenCategories } from './utils'\n\nexport interface BusinessCategoriesProps {\n select: (category: Option) => void\n}\n\nexport const BusinessCategories = ({ select }: BusinessCategoriesProps) => {\n const { categories } = useLayerContext()\n\n const categoryOptions = flattenCategories(categories)\n\n const [optionsToShow, setOptionsToShow] = useState(categoryOptions)\n const [selectedGroup, setSelectedGroup] = useState<string>()\n\n const onCategorySelect = (v: Option) => {\n if (v.value.type === 'GROUP' && v.value.items) {\n setOptionsToShow(v.value.items)\n setSelectedGroup(v.label)\n return\n }\n select(v)\n }\n\n return (\n <div className='Layer__bank-transaction-mobile-list-item__categories_list-container'>\n <Text\n weight={TextWeight.bold}\n className='Layer__bank-transaction-mobile-list-item__categories_list-title'\n >\n {selectedGroup ?? 'Select category'}\n </Text>\n <ActionableList<Option['value']>\n options={optionsToShow}\n onClick={onCategorySelect}\n />\n </div>\n )\n}\n", "import React from 'react'\nimport CheckIcon from '../../icons/Check'\nimport ChevronRight from '../../icons/ChevronRight'\nimport { Text } from '../Typography'\nimport classNames from 'classnames'\n\nexport interface ActionableListOption<T> {\n label: string\n id: string\n value: T\n asLink?: boolean\n secondary?: boolean\n}\n\ninterface ActionableListProps<T> {\n options: ActionableListOption<T>[]\n onClick: (item: ActionableListOption<T>) => void\n selected?: ActionableListOption<T>\n}\n\nexport const ActionableList = <T,>({\n options,\n onClick,\n selected,\n}: ActionableListProps<T>) => {\n return (\n <ul className='Layer__actionable-list'>\n {options.map((x, idx) => (\n <li\n role='button'\n onClick={() => onClick(x)}\n key={`actionable-list-item-${idx}`}\n className={classNames(\n x.secondary && 'Layer__actionable-list-item--secondary',\n x.asLink && 'Layer__actionable-list-item--as-link',\n )}\n >\n <Text>{x.label}</Text>\n {!x.asLink && selected && selected.id === x.id ? (\n <CheckIcon\n size={16}\n className='Layer__actionable-list__selected-icon'\n />\n ) : null}\n {x.asLink && (\n <ChevronRight\n size={16}\n className='Layer__actionable-list__link-icon'\n />\n )}\n </li>\n ))}\n </ul>\n )\n}\n", "export const PersonalCategories = ['PERSONAL_INCOME', 'PERSONAL_EXPENSES']\n", "import {\n BankTransaction,\n CategorizationStatus,\n Category,\n SuggestedCategorization,\n} from '../../types'\nimport { hasSuggestions } from '../../types/categories'\nimport {\n CategoryOptionPayload,\n OptionActionType,\n} from '../CategorySelect/CategorySelect'\nimport { PersonalCategories } from './constants'\n\nexport interface Option {\n label: string\n id: string\n value: {\n type: 'CATEGORY' | 'SELECT_CATEGORY' | 'GROUP'\n payload?: CategoryOptionPayload\n items?: Option[]\n }\n asLink?: boolean\n secondary?: boolean\n}\n\nexport const mapCategoryToOption = (category: Category): Option => ({\n label: category.display_name,\n id: category.id,\n value: {\n type: 'CATEGORY',\n payload: {\n id: category.id,\n option_type: OptionActionType.CATEGORY,\n display_name: category.display_name,\n type: category.type,\n stable_name: category.stable_name,\n entries: category.entries,\n subCategories: category.subCategories,\n },\n },\n})\n\nexport const flattenCategories = (categories: Category[]): Option[] => {\n const categoryOptions = (categories || []).flatMap(category => {\n if (category?.subCategories && category?.subCategories?.length > 0) {\n if (category?.subCategories?.every(c => c.subCategories === undefined)) {\n return [\n {\n label: category.display_name,\n id: category.id,\n value: {\n type: 'GROUP',\n items: category.subCategories.map(x => mapCategoryToOption(x)),\n },\n asLink: true,\n } satisfies Option,\n ]\n }\n return flattenCategories(category.subCategories)\n }\n\n const resultOption = mapCategoryToOption(category) satisfies Option\n return [resultOption]\n })\n\n return categoryOptions\n}\n\nexport const getAssignedValue = (\n bankTransaction: BankTransaction,\n): Option | undefined => {\n if (\n bankTransaction.categorization_status === CategorizationStatus.MATCHED ||\n bankTransaction?.categorization_status === CategorizationStatus.SPLIT\n ) {\n return\n }\n\n if (\n bankTransaction.category &&\n !PersonalCategories.includes(bankTransaction.category.display_name)\n ) {\n return mapCategoryToOption(bankTransaction.category)\n }\n\n if (hasSuggestions(bankTransaction.categorization_flow)) {\n const firstSuggestion = (\n bankTransaction.categorization_flow as SuggestedCategorization\n ).suggestions[0]\n return mapCategoryToOption(firstSuggestion)\n }\n\n return\n}\n", "import React, {\n forwardRef,\n useImperativeHandle,\n useState,\n useCallback,\n useEffect,\n useRef,\n TransitionEvent,\n} from 'react'\nimport { Layer } from '../../api/layer'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { useProfitAndLossLTM } from '../../hooks/useProfitAndLoss/useProfitAndLossLTM'\nimport AlertCircle from '../../icons/AlertCircle'\nimport Scissors from '../../icons/ScissorsFullOpen'\nimport Trash from '../../icons/Trash'\nimport {\n centsToDollars as formatMoney,\n dollarsToCents as parseMoney,\n} from '../../models/Money'\nimport {\n BankTransaction,\n SplitCategoryUpdate,\n SingleCategoryUpdate,\n} from '../../types'\nimport { hasSuggestions } from '../../types/categories'\nimport { getCategorizePayload, hasMatch } from '../../utils/bankTransactions'\nimport {\n BankTransactionsMode,\n categorizationEnabled,\n} from '../BankTransactions/BankTransactions'\nimport { Button, SubmitButton, ButtonVariant, TextButton } from '../Button'\nimport { SubmitAction } from '../Button/SubmitButton'\nimport { CategorySelect } from '../CategorySelect'\nimport {\n CategoryOption,\n mapCategoryToOption,\n} from '../CategorySelect/CategorySelect'\nimport { InputGroup, Input, FileInput } from '../Input'\nimport { MatchForm } from '../MatchForm'\nimport { Textarea } from '../Textarea'\nimport { Toggle } from '../Toggle'\nimport { ToggleSize } from '../Toggle/Toggle'\nimport { Text, ErrorText, TextSize } from '../Typography'\nimport { APIErrorNotifications } from './APIErrorNotifications'\nimport classNames from 'classnames'\n\ntype Props = {\n bankTransaction: BankTransaction\n isOpen?: boolean\n close: () => void\n asListItem?: boolean\n submitBtnText?: string\n mode: BankTransactionsMode\n containerWidth?: number\n categorized?: boolean\n showDescriptions: boolean\n showReceiptUploads: boolean\n}\n\ntype Split = {\n amount: number\n inputValue: string\n category: CategoryOption | undefined\n}\n\ntype RowState = {\n splits: Split[]\n description: string\n file: unknown\n}\n\nenum Purpose {\n categorize = 'categorize',\n match = 'match',\n}\n\nexport type SaveHandle = {\n save: () => void\n}\n\nconst isAlreadyMatched = (bankTransaction?: BankTransaction) => {\n if (bankTransaction?.match) {\n const foundMatch = bankTransaction.suggested_matches?.find(\n x => x.details.id === bankTransaction?.match?.details.id,\n )\n return foundMatch?.id\n }\n\n return undefined\n}\n\nconst validateSplit = (splitData: RowState) => {\n let valid = true\n\n splitData.splits.forEach(split => {\n if (split.amount <= 0) {\n valid = false\n } else if (!split.category) {\n valid = false\n }\n })\n\n return valid\n}\n\nexport const ExpandedBankTransactionRow = forwardRef<SaveHandle, Props>(\n (\n {\n bankTransaction,\n isOpen = false,\n close,\n categorized,\n asListItem = false,\n submitBtnText = 'Save',\n containerWidth,\n showDescriptions,\n mode,\n showReceiptUploads,\n },\n ref,\n ) => {\n const {\n categorize: categorizeBankTransaction,\n match: matchBankTransaction,\n } = useBankTransactionsContext()\n const [purpose, setPurpose] = useState<Purpose>(\n bankTransaction.category\n ? Purpose.categorize\n : hasMatch(bankTransaction)\n ? Purpose.match\n : Purpose.categorize,\n )\n const [selectedMatchId, setSelectedMatchId] = useState<string | undefined>(\n isAlreadyMatched(bankTransaction),\n )\n const [matchFormError, setMatchFormError] = useState<string | undefined>()\n const [splitFormError, setSplitFormError] = useState<string | undefined>()\n const [height, setHeight] = useState<string | number>(0)\n const [isOver, setOver] = useState(false)\n const bodyRef = useRef<HTMLSpanElement>(null)\n const [memoText, setMemoText] = useState<string | undefined>()\n const [receiptUrls, setReceiptUrls] = useState<string[]>([])\n const [isLoaded, setIsLoaded] = useState(false)\n\n const { auth, businessId, apiUrl } = useLayerContext()\n\n const defaultCategory =\n bankTransaction.category ||\n (hasSuggestions(bankTransaction.categorization_flow) &&\n bankTransaction.categorization_flow?.suggestions?.[0])\n\n const [rowState, updateRowState] = useState<RowState>({\n splits: bankTransaction.category?.entries\n ? bankTransaction.category?.entries.map(c => {\n return {\n amount: c.amount || 0,\n inputValue: formatMoney(c.amount),\n category: mapCategoryToOption(c.category),\n }\n })\n : [\n {\n amount: bankTransaction.amount,\n inputValue: formatMoney(bankTransaction.amount),\n category: mapCategoryToOption(defaultCategory),\n },\n ],\n description: '',\n file: undefined,\n })\n\n const addSplit = () => {\n updateRowState({\n ...rowState,\n splits: [\n ...rowState.splits,\n {\n amount: 0,\n inputValue: '0.00',\n category: mapCategoryToOption(defaultCategory),\n },\n ],\n })\n setSplitFormError(undefined)\n }\n\n const removeSplit = (index: number) => {\n const newSplits = rowState.splits.filter((_v, idx) => idx !== index)\n const splitTotal = newSplits.reduce((sum, split, index) => {\n const amount = index === 0 ? 0 : split.amount\n return sum + amount\n }, 0)\n const remaining = bankTransaction.amount - splitTotal\n newSplits[0].amount = remaining\n newSplits[0].inputValue = formatMoney(remaining)\n\n updateRowState({\n ...rowState,\n splits: newSplits,\n })\n setSplitFormError(undefined)\n }\n\n const sanitizeNumberInput = (input: string): string => {\n let sanitized = input.replace(/[^0-9.]/g, '')\n\n // Ensure there's at most one period\n const parts = sanitized.split('.')\n if (parts.length > 2) {\n sanitized = parts[0] + '.' + parts.slice(1).join('')\n }\n\n // Limit to two digits after the decimal point\n if (parts.length === 2) {\n sanitized = parts[0] + '.' + parts[1].slice(0, 2)\n }\n\n return sanitized\n }\n\n const updateAmounts =\n (rowNumber: number) => (event: React.ChangeEvent<HTMLInputElement>) => {\n const newDisplaying = sanitizeNumberInput(event.target.value)\n\n const newAmount = Number(newDisplaying) * 100 // cents\n const splitTotal = rowState.splits.reduce((sum, split, index) => {\n const amount =\n index === 0 ? 0 : index === rowNumber ? newAmount : split.amount\n return sum + amount\n }, 0)\n\n const remaining = bankTransaction.amount - splitTotal\n rowState.splits[rowNumber].amount = newAmount\n rowState.splits[rowNumber].inputValue = newDisplaying\n rowState.splits[0].amount = remaining\n rowState.splits[0].inputValue = formatMoney(remaining)\n updateRowState({ ...rowState })\n setSplitFormError(undefined)\n }\n\n const onBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (event.target.value === '') {\n const [_, index] = event.target.name.split('-')\n rowState.splits[parseInt(index)].inputValue = '0.00'\n updateRowState({ ...rowState })\n setSplitFormError(undefined)\n }\n }\n\n const onChangePurpose = (event: React.ChangeEvent<HTMLInputElement>) => {\n setPurpose(\n event.target.value === Purpose.match\n ? Purpose.match\n : Purpose.categorize,\n )\n setSplitFormError(undefined)\n setMatchFormError(undefined)\n }\n\n const changeCategory = (index: number, newValue: CategoryOption) => {\n rowState.splits[index].category = newValue\n updateRowState({ ...rowState })\n setSplitFormError(undefined)\n }\n\n const save = async () => {\n const endpoint = `/v1/businesses/${businessId}/bank-transactions/${bankTransaction.id}/metadata`\n\n if (showDescriptions && memoText != undefined) {\n const result = await Layer.updateBankTransactionMetadata(\n apiUrl,\n auth.access_token,\n {\n params: {\n businessId: businessId,\n bankTransactionId: bankTransaction.id,\n },\n body: {\n memo: memoText,\n },\n },\n )\n }\n\n if (purpose === Purpose.match) {\n if (!selectedMatchId) {\n setMatchFormError('Select an option to match the transaction')\n } else if (\n selectedMatchId &&\n selectedMatchId !== isAlreadyMatched(bankTransaction)\n ) {\n onMatchSubmit(selectedMatchId)\n }\n return\n }\n\n if (!validateSplit(rowState)) {\n if (rowState.splits.length > 1) {\n setSplitFormError(\n 'Use only positive amounts and select category for each entry',\n )\n } else {\n setSplitFormError('Category is required')\n }\n return\n }\n\n await categorizeBankTransaction(\n bankTransaction.id,\n rowState.splits.length === 1 && rowState?.splits[0].category\n ? ({\n type: 'Category',\n category: getCategorizePayload(rowState?.splits[0].category),\n } as SingleCategoryUpdate)\n : ({\n type: 'Split',\n entries: rowState.splits.map(split => ({\n category: split.category\n ? getCategorizePayload(split.category)\n : '',\n amount: split.amount,\n })),\n } as SplitCategoryUpdate),\n )\n close()\n }\n\n const fetchMetadata = async () => {\n const getBankTransactionMetadata = Layer.getBankTransactionMetadata(\n apiUrl,\n auth.access_token,\n {\n params: {\n businessId: businessId,\n bankTransactionId: bankTransaction.id,\n },\n },\n )\n const result = await getBankTransactionMetadata()\n if (result.data.memo) setMemoText(result.data.memo)\n }\n\n const fetchDocuments = async () => {\n const listBankTransactionDocuments = Layer.listBankTransactionDocuments(\n apiUrl,\n auth.access_token,\n {\n params: {\n businessId: businessId,\n bankTransactionId: bankTransaction.id,\n },\n },\n )\n const result = await listBankTransactionDocuments()\n const retrievedDocs = result.data.documentUrls.map(\n (docUrl: any) => docUrl.presignedUrl,\n )\n setReceiptUrls(retrievedDocs)\n }\n\n // Call this save action after clicking save in parent component:\n useImperativeHandle(ref, () => ({\n save,\n }))\n\n const onMatchSubmit = async (matchId: string) => {\n const foundMatch = bankTransaction.suggested_matches?.find(\n x => x.id === matchId,\n )\n if (!foundMatch) {\n return\n }\n\n await matchBankTransaction(bankTransaction.id, foundMatch.id)\n close()\n }\n\n const getDivHeight = useCallback(() => {\n const { height } = bodyRef.current\n ? bodyRef.current.getBoundingClientRect()\n : { height: undefined }\n\n return height || 0\n }, [])\n\n const handleTransitionEnd = useCallback(\n (e: TransitionEvent<HTMLSpanElement>) => {\n if (e.propertyName === 'height') {\n setHeight(isOpen ? 'auto' : 0)\n if (!isOpen) {\n setOver(true)\n }\n }\n },\n [isOpen],\n )\n\n useEffect(() => {\n if (!isLoaded) {\n return\n }\n\n setHeight(getDivHeight())\n setOver(false)\n\n if (!isOpen) {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => setHeight(0))\n })\n }\n }, [getDivHeight, isOpen])\n\n useEffect(() => {\n const loadDocumentsAndMetadata = async () => {\n if (showDescriptions) await fetchMetadata()\n if (showReceiptUploads) await fetchDocuments()\n setIsLoaded(true)\n setOver(true)\n }\n loadDocumentsAndMetadata()\n }, [])\n\n const className = 'Layer__expanded-bank-transaction-row'\n const shouldHide = !isOpen && isOver\n\n return (\n <span\n className={`${className} ${className}--${\n isOpen ? 'expanded' : 'collapsed'\n }`}\n style={{ height }}\n onTransitionEnd={handleTransitionEnd}\n >\n {shouldHide ? null : (\n <span className={`${className}__wrapper`} ref={bodyRef}>\n {categorizationEnabled(mode) ? (\n <div className={`${className}__content-toggle`}>\n <Toggle\n name={`purpose-${bankTransaction.id}${\n asListItem ? '-li' : ''\n }`}\n size={ToggleSize.small}\n options={[\n {\n value: 'categorize',\n label: 'Categorize',\n },\n {\n value: 'match',\n label: 'Match',\n disabled: !hasMatch(bankTransaction),\n disabledMessage:\n 'We could not find matching transactions',\n },\n ]}\n selected={purpose}\n onChange={onChangePurpose}\n />\n </div>\n ) : (\n <></>\n )}\n <div\n className={`${className}__content`}\n id={`expanded-${bankTransaction.id}`}\n >\n <div className={`${className}__content-panels`}>\n <div\n className={classNames(\n `${className}__match`,\n `${className}__content-panel`,\n purpose === Purpose.match\n ? `${className}__content-panel--active`\n : '',\n )}\n >\n <div className={`${className}__content-panel-container`}>\n <MatchForm\n classNamePrefix={className}\n bankTransaction={bankTransaction}\n selectedMatchId={selectedMatchId}\n readOnly={!categorizationEnabled(mode)}\n setSelectedMatchId={id => {\n setMatchFormError(undefined)\n setSelectedMatchId(id)\n }}\n matchFormError={matchFormError}\n />\n </div>\n </div>\n\n <div\n className={classNames(\n `${className}__splits`,\n `${className}__content-panel`,\n purpose === Purpose.categorize\n ? `${className}__content-panel--active`\n : '',\n )}\n >\n <div className={`${className}__content-panel-container`}>\n <div className={`${className}__splits-inputs`}>\n {rowState.splits.map((split, index) => (\n <div\n className={`${className}__table-cell--split-entry`}\n key={`split-${index}`}\n >\n <Input\n type='text'\n name={`split-${index}${asListItem ? '-li' : ''}`}\n disabled={\n index === 0 || !categorizationEnabled(mode)\n }\n onChange={updateAmounts(index)}\n value={split.inputValue}\n onBlur={onBlur}\n isInvalid={split.amount < 0}\n inputMode='numeric'\n errorMessage='Negative values are not allowed'\n />\n <div\n className={`${className}__table-cell--split-entry__right-col`}\n >\n <CategorySelect\n bankTransaction={bankTransaction}\n name={`category-${bankTransaction.id}`}\n value={split.category}\n onChange={value => changeCategory(index, value)}\n className='Layer__category-menu--full'\n disabled={\n bankTransaction.processing ||\n !categorizationEnabled(mode)\n }\n excludeMatches\n />\n {index > 0 && (\n <Button\n className={`${className}__table-cell--split-entry__merge-btn`}\n onClick={() => removeSplit(index)}\n rightIcon={<Trash size={18} />}\n variant={ButtonVariant.secondary}\n iconOnly={true}\n />\n )}\n </div>\n </div>\n ))}\n </div>\n {splitFormError && <ErrorText>{splitFormError}</ErrorText>}\n <div className={`${className}__total-and-btns`}>\n {rowState.splits.length > 1 && (\n <Input\n disabled={true}\n leftText='Total'\n inputMode='numeric'\n value={`$${formatMoney(\n rowState.splits.reduce(\n (x, { amount }) => x + amount,\n 0,\n ),\n )}`}\n />\n )}\n {categorizationEnabled(mode) ? (\n <div className={`${className}__splits-buttons`}>\n {rowState.splits.length > 1 ? (\n <TextButton\n onClick={addSplit}\n disabled={rowState.splits.length > 5}\n >\n Add new split\n </TextButton>\n ) : (\n <Button\n onClick={addSplit}\n rightIcon={<Scissors size={14} />}\n variant={ButtonVariant.secondary}\n disabled={rowState.splits.length > 5}\n >\n Split\n </Button>\n )}\n </div>\n ) : (\n <></>\n )}\n </div>\n </div>\n </div>\n </div>\n\n {showDescriptions && (\n <InputGroup\n className={`${className}__description`}\n name='description'\n >\n <Textarea\n name='description'\n placeholder='Add description'\n value={memoText}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>\n setMemoText(e.target.value)\n }\n />\n </InputGroup>\n )}\n\n {showReceiptUploads && (\n <div>\n <div className={`${className}__file-upload`}>\n <FileInput\n onUpload={async (file: File) => {\n const uploadDocument =\n Layer.uploadBankTransactionDocument(\n apiUrl,\n auth.access_token,\n )\n const result = await uploadDocument({\n businessId: businessId,\n bankTransactionId: bankTransaction.id,\n file: file,\n documentType: 'RECEIPT',\n })\n await fetchDocuments()\n }}\n text='Upload receipt'\n />\n\n {receiptUrls.length > 0 && 'Attached receipts:'}\n {receiptUrls.map((url, index) => (\n <a\n key={url}\n href={url}\n target='_blank'\n rel='noopener noreferrer'\n >\n Receipt {index + 1}\n </a>\n ))}\n </div>\n </div>\n )}\n\n {asListItem && categorizationEnabled(mode) ? (\n <div className={`${className}__submit-btn`}>\n {bankTransaction.error ? (\n <Text\n as='span'\n size={TextSize.md}\n className='Layer__unsaved-info'\n >\n <span>Unsaved</span>\n <AlertCircle size={12} />\n </Text>\n ) : null}\n <SubmitButton\n onClick={() => {\n if (!bankTransaction.processing) {\n save()\n }\n }}\n className='Layer__bank-transaction__submit-btn'\n processing={bankTransaction.processing}\n active={true}\n action={\n categorized ? SubmitAction.SAVE : SubmitAction.UPDATE\n }\n >\n {submitBtnText}\n </SubmitButton>\n </div>\n ) : null}\n </div>\n <APIErrorNotifications\n bankTransaction={bankTransaction}\n containerWidth={containerWidth}\n />\n </span>\n )}\n </span>\n )\n },\n)\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ScissorsFullOpen = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 12 12'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <g id='scissors'>\n <path\n id='Vector'\n d='M3 4.5C3.82843 4.5 4.5 3.82843 4.5 3C4.5 2.17157 3.82843 1.5 3 1.5C2.17157 1.5 1.5 2.17157 1.5 3C1.5 3.82843 2.17157 4.5 3 4.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n id='Vector_2'\n d='M3 10.5C3.82843 10.5 4.5 9.82843 4.5 9C4.5 8.17157 3.82843 7.5 3 7.5C2.17157 7.5 1.5 8.17157 1.5 9C1.5 9.82843 2.17157 10.5 3 10.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n id='Vector_3'\n d='M10 2L4.06 7.94'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n id='Vector_4'\n d='M7.235 7.23999L10 9.99999'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n id='Vector_5'\n d='M4.06 4.06006L6 6.00006'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </g>\n </svg>\n)\n\nexport default ScissorsFullOpen\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Trash = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M2.25 4.5H3.75H15.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M14.25 4.5V15C14.25 15.3978 14.092 15.7794 13.8107 16.0607C13.5294 16.342 13.1478 16.5 12.75 16.5H5.25C4.85218 16.5 4.47064 16.342 4.18934 16.0607C3.90804 15.7794 3.75 15.3978 3.75 15V4.5M6 4.5V3C6 2.60218 6.15804 2.22064 6.43934 1.93934C6.72064 1.65804 7.10218 1.5 7.5 1.5H10.5C10.8978 1.5 11.2794 1.65804 11.5607 1.93934C11.842 2.22064 12 2.60218 12 3V4.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M7.5 8.25V12.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5 8.25V12.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Trash\n", "import React, { HTMLProps } from 'react'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport interface InputProps extends HTMLProps<HTMLInputElement> {\n isInvalid?: boolean\n errorMessage?: string\n leftText?: string\n}\n\nexport const Input = ({\n className,\n isInvalid,\n errorMessage,\n leftText,\n ...props\n}: InputProps) => {\n const baseClassName = classNames(\n 'Layer__input',\n isInvalid ? 'Layer__input--error' : '',\n leftText ? 'Layer__input--with-left-text' : '',\n className,\n )\n\n return (\n <Tooltip disabled={!isInvalid || !errorMessage}>\n <TooltipTrigger className='Layer__input-tooltip'>\n <input {...props} className={baseClassName} />\n {leftText && <span className='Layer__input-left-text'>{leftText}</span>}\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{errorMessage}</TooltipContent>\n </Tooltip>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport { Text, TextSize } from '../Typography'\nimport classNames from 'classnames'\n\nexport interface InputGroupProps {\n label?: string\n name?: string\n className?: string\n children?: ReactNode\n inline?: boolean\n}\n\nexport const InputGroup = ({\n label,\n name,\n className,\n inline,\n children,\n}: InputGroupProps) => {\n const baseClassName = classNames(\n 'Layer__input-group',\n className,\n inline && 'Layer__input-group--inline',\n )\n return (\n <div className={baseClassName}>\n {label && (\n <Text\n as='label'\n size={TextSize.sm}\n className='Layer__input-label'\n htmlFor={name}\n >\n {label}\n </Text>\n )}\n {children}\n </div>\n )\n}\n", "import React, { useRef, ChangeEvent } from 'react'\nimport UploadCloud from '../../icons/UploadCloud'\nimport { Button } from '../Button'\nimport { ButtonVariant } from '../Button/Button'\n\nexport interface FileInputProps {\n text?: string\n onUpload?: (file: File) => void\n}\n\nexport const FileInput = ({ text = 'Upload', onUpload }: FileInputProps) => {\n const hiddenFileInput = useRef<HTMLInputElement>(null)\n\n const onClick = () => {\n if (hiddenFileInput.current) {\n hiddenFileInput.current.click()\n }\n }\n\n const onChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (event.target.files && event.target.files.length > 0 && onUpload) {\n const fileUploaded = event.target.files[0]\n onUpload(fileUploaded)\n }\n }\n\n return (\n <>\n <Button\n onClick={onClick}\n variant={ButtonVariant.secondary}\n rightIcon={<UploadCloud />}\n >\n {text}\n </Button>\n <input\n type='file'\n onChange={onChange}\n ref={hiddenFileInput}\n style={{ display: 'none' }}\n />\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst UploadCloud = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M12 12L9 9L6 12'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 9V15.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M15.2925 13.7925C16.024 13.3937 16.6019 12.7626 16.9349 11.999C17.2679 11.2353 17.3372 10.3824 17.1317 9.57501C16.9262 8.7676 16.4576 8.05162 15.8 7.54007C15.1424 7.02852 14.3332 6.75054 13.5 6.74999H12.555C12.328 5.87192 11.9049 5.05674 11.3175 4.36573C10.7301 3.67473 9.99364 3.12588 9.16358 2.76044C8.33352 2.39501 7.43141 2.22251 6.52509 2.2559C5.61876 2.28929 4.7318 2.52771 3.93088 2.95324C3.12997 3.37876 2.43593 3.98032 1.90097 4.71267C1.366 5.44503 1.00402 6.28914 0.842236 7.18153C0.680453 8.07393 0.72308 8.99139 0.966911 9.86493C1.21074 10.7385 1.64943 11.5454 2.25 12.225'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12 12L9 9L6 12'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default UploadCloud\n", "import React from 'react'\nimport ReactSelect, {\n DropdownIndicatorProps,\n GroupBase,\n OptionsOrGroups,\n components,\n} from 'react-select'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport interface SelectProps<T> {\n name?: string\n options?: OptionsOrGroups<T, GroupBase<T>>\n className?: string\n classNamePrefix?: string\n value?: T\n onChange: (selected: T) => void\n disabled?: boolean\n placeholder?: string\n isInvalid?: boolean\n errorMessage?: string\n}\n\nconst DropdownIndicator:\n | React.ComponentType<DropdownIndicatorProps<any, false, GroupBase<any>>>\n | null\n | undefined = props => {\n return (\n <components.DropdownIndicator {...props}>\n <ChevronDownFill />\n </components.DropdownIndicator>\n )\n}\n\nexport const Select = <T,>({\n name,\n options,\n className,\n classNamePrefix = 'Layer__select',\n value,\n onChange,\n disabled,\n placeholder,\n isInvalid,\n errorMessage,\n}: SelectProps<T>) => {\n const baseClassName = classNames(\n 'Layer__select',\n isInvalid ? 'Layer__select--error' : '',\n className,\n )\n return (\n <Tooltip disabled={!isInvalid || !errorMessage}>\n <TooltipTrigger className='Layer__input-tooltip'>\n <ReactSelect<T>\n name={name}\n className={baseClassName}\n classNamePrefix={classNamePrefix}\n placeholder={placeholder ?? 'Select...'}\n options={options}\n value={value}\n onChange={newValue => newValue && onChange(newValue)}\n menuPortalTarget={document.body}\n styles={{ menuPortal: base => ({ ...base, zIndex: 9999 }) }}\n components={{ DropdownIndicator }}\n isDisabled={disabled}\n />\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{errorMessage}</TooltipContent>\n </Tooltip>\n )\n}\n", "import React, { HTMLProps } from 'react'\nimport { Badge, BadgeVariant } from '../Badge'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport interface InputWithBadgeProps extends HTMLProps<HTMLInputElement> {\n isInvalid?: boolean\n errorMessage?: string\n leftText?: string\n variant?: BadgeVariant\n badge: React.ReactNode\n}\n\nexport const InputWithBadge = ({\n className,\n isInvalid,\n errorMessage,\n leftText,\n badge,\n variant = BadgeVariant.DEFAULT,\n ...props\n}: InputWithBadgeProps) => {\n const baseClassName = classNames(\n 'Layer__input',\n isInvalid ? 'Layer__input--error' : '',\n leftText ? 'Layer__input--with-left-text' : '',\n className,\n )\n\n return (\n <Tooltip disabled={!isInvalid || !errorMessage}>\n <TooltipTrigger className='Layer__input-tooltip'>\n <div className='Layer__input-with-badge'>\n <input {...props} className={baseClassName} />\n {badge && <Badge variant={variant}>{badge}</Badge>}\n </div>\n {leftText && <span className='Layer__input-left-text'>{leftText}</span>}\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{errorMessage}</TooltipContent>\n </Tooltip>\n )\n}\n", "import React from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction } from '../../types'\nimport { MatchBadge } from '../BankTransactionRow/MatchBadge'\nimport { Text, TextUseTooltip, ErrorText } from '../Typography'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface MatchFormProps {\n classNamePrefix: string\n bankTransaction: BankTransaction\n selectedMatchId?: string\n setSelectedMatchId: (val?: string) => void\n matchFormError?: string\n readOnly?: boolean\n}\n\nexport const MatchForm = ({\n classNamePrefix,\n bankTransaction,\n selectedMatchId,\n setSelectedMatchId,\n matchFormError,\n readOnly = false,\n}: MatchFormProps) => {\n return (\n <div className={`${classNamePrefix}__match-table`}>\n <div className={`${classNamePrefix}__match-table__header`}>\n <div className={`${classNamePrefix}__match-table__date`}>Date</div>\n <div className={`${classNamePrefix}__match-table__desc`}>\n Description\n </div>\n <div className={`${classNamePrefix}__match-table__amount`}>Amount</div>\n\n <div\n className={`${classNamePrefix}__match-table__status ${\n bankTransaction.match ? '' : 'no-match'\n }`}\n ></div>\n </div>\n\n {bankTransaction.suggested_matches?.map((match, idx) => {\n return (\n <div\n key={idx}\n className={classNames(\n `${classNamePrefix}__match-row`,\n match.id === selectedMatchId\n ? `${classNamePrefix}__match-row--selected`\n : '',\n )}\n onClick={() => {\n if (readOnly === true) {\n return\n }\n if (selectedMatchId === match.id) {\n setSelectedMatchId(undefined)\n return\n }\n setSelectedMatchId(match.id)\n }}\n >\n <div\n className={`Layer__nowrap ${classNamePrefix}__match-table__date`}\n >\n <span>\n {formatTime(parseISO(match.details.date), DATE_FORMAT)}\n </span>\n <span className='amount-next-to-date'>\n ${formatMoney(match.details.amount)}\n </span>\n </div>\n <div className={`${classNamePrefix}__match-table__desc`}>\n <Text\n className={`${classNamePrefix}__match-table__desc-tooltip`}\n withTooltip={TextUseTooltip.whenTruncated}\n as='span'\n >\n {match.details.description}\n </Text>\n {match.details.id === bankTransaction.match?.details.id && (\n <span className='match-badge'>\n <MatchBadge\n classNamePrefix={classNamePrefix}\n bankTransaction={bankTransaction}\n dateFormat={DATE_FORMAT}\n text='Matched'\n />\n </span>\n )}\n </div>\n <div className={`${classNamePrefix}__match-table__amount`}>\n ${formatMoney(match.details.amount)}\n </div>\n\n <div\n className={`${classNamePrefix}__match-table__status ${\n bankTransaction.match ? '' : 'no-match'\n }`}\n >\n {match.details.id === bankTransaction.match?.details.id && (\n <MatchBadge\n classNamePrefix={classNamePrefix}\n bankTransaction={bankTransaction}\n dateFormat={DATE_FORMAT}\n text='Matched'\n />\n )}\n </div>\n </div>\n )\n })}\n {matchFormError && <ErrorText>{matchFormError}</ErrorText>}\n </div>\n )\n}\n", "import React from 'react'\nimport MinimizeTwo from '../../icons/MinimizeTwo'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction, CategorizationStatus } from '../../types'\nimport { Badge } from '../Badge'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface MatchBadgeProps {\n bankTransaction: BankTransaction\n classNamePrefix: string\n dateFormat: string\n text?: string\n}\n\nexport const MatchBadge = ({\n bankTransaction,\n classNamePrefix,\n dateFormat,\n text = 'Match',\n}: MatchBadgeProps) => {\n if (\n bankTransaction.categorization_status === CategorizationStatus.MATCHED &&\n bankTransaction.match\n ) {\n const { date, amount } = bankTransaction.match.bank_transaction\n\n return (\n <Badge\n icon={<MinimizeTwo size={11} />}\n tooltip={\n <span className={`${classNamePrefix}__match-tooltip`}>\n <div className={`${classNamePrefix}__match-tooltip__date`}>\n {formatTime(parseISO(date), dateFormat)}\n </div>\n <div className={`${classNamePrefix}__match-tooltip__description`}>\n {bankTransaction.match?.details?.description ?? ''}\n </div>\n <div className={`${classNamePrefix}__match-tooltip__amount`}>\n ${formatMoney(amount)}\n </div>\n </span>\n }\n >\n {text}\n </Badge>\n )\n }\n\n return\n}\n", "import React from 'react'\nimport { MONTH_DAY_FORMAT } from '../../config/general'\nimport CheckIcon from '../../icons/Check'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { Text, ErrorText, TextSize } from '../Typography'\nimport { MatchFormProps } from './MatchForm'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport const MatchFormMobile = ({\n classNamePrefix,\n bankTransaction,\n selectedMatchId,\n setSelectedMatchId,\n matchFormError,\n}: MatchFormProps) => {\n return (\n <div className={`${classNamePrefix}__match-list`}>\n {bankTransaction.suggested_matches?.map((match, idx) => {\n return (\n <div\n key={idx}\n className={classNames(\n `${classNamePrefix}__match-item`,\n match.id === selectedMatchId\n ? `${classNamePrefix}__match-item--selected`\n : '',\n )}\n onClick={() => {\n if (selectedMatchId === match.id) {\n setSelectedMatchId(undefined)\n return\n }\n setSelectedMatchId(match.id)\n }}\n >\n <div className={`${classNamePrefix}__match-item__col-details`}>\n <div className={`${classNamePrefix}__match-item__heading`}>\n <Text\n className={`${classNamePrefix}__match-item__name`}\n as='span'\n >\n {match.details.description}\n </Text>\n <Text\n className={`${classNamePrefix}__match-item__amount`}\n as='span'\n >\n ${formatMoney(match.details.amount)}\n </Text>\n </div>\n <div className={`${classNamePrefix}__match-item__details`}>\n <Text\n className={`${classNamePrefix}__match-item__date`}\n size={TextSize.sm}\n as='span'\n >\n {formatTime(parseISO(match.details.date), MONTH_DAY_FORMAT)}\n </Text>\n </div>\n </div>\n\n <div className={`${classNamePrefix}__match-item__col-status`}>\n {selectedMatchId && selectedMatchId === match.id ? (\n <CheckIcon\n size={16}\n className={`${classNamePrefix}__match-item__selected-icon`}\n />\n ) : null}\n </div>\n </div>\n )\n })}\n {matchFormError && <ErrorText>{matchFormError}</ErrorText>}\n </div>\n )\n}\n", "import React, { HTMLProps } from 'react'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport interface TextareaProps extends HTMLProps<HTMLTextAreaElement> {\n isInvalid?: boolean\n errorMessage?: string\n}\n\nexport const Textarea = ({\n className,\n isInvalid,\n errorMessage,\n ...props\n}: TextareaProps) => {\n const baseClassName = classNames(\n 'Layer__textarea',\n isInvalid ? 'Layer__textarea--error' : '',\n className,\n )\n\n return (\n <Tooltip disabled={!isInvalid || !errorMessage}>\n <TooltipTrigger className='Layer__input-tooltip'>\n <textarea {...props} className={baseClassName} />\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{errorMessage}</TooltipContent>\n </Tooltip>\n )\n}\n", "import React, {\n CSSProperties,\n ChangeEvent,\n ReactNode,\n useEffect,\n useState,\n} from 'react'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport interface Option {\n label: string\n value: string\n disabled?: boolean\n disabledMessage?: string\n leftIcon?: ReactNode\n style?: CSSProperties\n}\n\nexport enum ToggleSize {\n medium = 'medium',\n small = 'small',\n xsmall = 'xsmall',\n}\n\nexport interface ToggleProps {\n name: string\n size?: ToggleSize\n options: Option[]\n selected?: Option['value']\n onChange: (event: ChangeEvent<HTMLInputElement>) => void\n}\n\ninterface ToggleOptionProps extends Option {\n checked: boolean\n label: string\n name: string\n size: ToggleSize\n onChange: (event: ChangeEvent<HTMLInputElement>) => void\n value: string\n disabled?: boolean\n disabledMessage?: string\n leftIcon?: ReactNode\n index: number\n}\n\nexport const Toggle = ({\n name,\n options,\n selected,\n onChange,\n size = ToggleSize.medium,\n}: ToggleProps) => {\n const [currentWidth, setCurrentWidth] = useState(0)\n const [thumbPos, setThumbPos] = useState({ left: 0, width: 0 })\n const [initialized, setInitialized] = useState(false)\n\n const toggleRef = useElementSize<HTMLDivElement>((a, b, c) => {\n if (c.width && c?.width !== currentWidth) {\n setCurrentWidth(c.width)\n }\n })\n\n const selectedValue = selected || options[0].value\n const baseClassName = classNames(\n 'Layer__toggle',\n `Layer__toggle--${size}`,\n initialized ? 'Layer__toggle--initialized' : '',\n )\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n updateThumbPosition(Number(e.target.getAttribute('data-idx') ?? 0))\n onChange(e)\n }\n\n const updateThumbPosition = (active: number) => {\n if (!toggleRef?.current) {\n return\n }\n\n const optionsNodes = [...toggleRef.current.children]\n .map(x => {\n if (\n x.className.includes('Layer__tooltip-trigger') &&\n x.children &&\n x.children.length > 0\n ) {\n return x.children[0]\n }\n\n return x\n })\n .filter(c => c.className.includes('Layer__toggle-option'))\n\n let shift = 0\n let width = thumbPos.width\n\n optionsNodes.forEach((c, i) => {\n if (i < active) {\n shift = shift + (c as HTMLElement).offsetWidth\n } else if (i === active) {\n width = (c as HTMLElement).offsetWidth\n }\n })\n\n shift = shift + (size === ToggleSize.medium ? 2 : 1.5)\n\n setThumbPos({ left: shift, width })\n }\n\n useEffect(() => {\n const selectedIndex = getSelectedIndex()\n updateThumbPosition(selectedIndex)\n\n setTimeout(() => {\n setInitialized(true)\n }, 400)\n }, [])\n\n useEffect(() => {\n const selectedIndex = getSelectedIndex()\n updateThumbPosition(selectedIndex)\n }, [currentWidth])\n\n const getSelectedIndex = () => {\n let selectedIndex = options.findIndex(\n option => option.value === selectedValue,\n )\n if (selectedIndex === -1) {\n return 0\n }\n\n return selectedIndex\n }\n\n return (\n <div className={baseClassName} ref={toggleRef}>\n {options.map((option, index) => (\n <ToggleOption\n {...option}\n size={size}\n key={option.value}\n name={name}\n checked={selectedValue === option.value}\n onChange={handleChange}\n disabled={option.disabled ?? false}\n disabledMessage={option.disabledMessage}\n index={index}\n />\n ))}\n <span className='Layer__toggle__thumb' style={{ ...thumbPos }} />\n </div>\n )\n}\n\nconst ToggleOption = ({\n checked,\n label,\n name,\n onChange,\n value,\n size,\n leftIcon,\n disabled,\n disabledMessage = 'Disabled',\n style,\n index,\n}: ToggleOptionProps) => {\n if (disabled) {\n return (\n <Tooltip>\n <TooltipTrigger>\n <label\n className={`Layer__toggle-option`}\n data-checked={checked}\n style={style}\n >\n <input\n type='radio'\n checked={checked}\n name={name}\n onChange={onChange}\n value={value}\n disabled={disabled ?? false}\n data-idx={index}\n />\n <span className='Layer__toggle-option-content'>\n {leftIcon && (\n <span className='Layer__toggle-option__icon'>{leftIcon}</span>\n )}\n <span>{label}</span>\n </span>\n </label>\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>\n {disabledMessage}\n </TooltipContent>\n </Tooltip>\n )\n }\n\n return (\n <label\n className={`Layer__toggle-option`}\n data-checked={checked}\n style={style}\n >\n <input\n type='radio'\n checked={checked}\n name={name}\n onChange={onChange}\n value={value}\n disabled={disabled ?? false}\n data-idx={index}\n />\n <span className='Layer__toggle-option-content'>\n {leftIcon && (\n <span className='Layer__toggle-option__icon'>{leftIcon}</span>\n )}\n <span>{label}</span>\n </span>\n </label>\n )\n}\n", "import React, { useEffect, useState } from 'react'\nimport AlertOctagon from '../../icons/AlertOctagon'\nimport { BankTransaction } from '../../types'\nimport { Text } from '../Typography'\n\ninterface APIErrorNotificationsProps {\n bankTransaction: BankTransaction\n containerWidth?: number\n}\n\ninterface Notification {\n bankTransactionId: string\n timestamp: number\n title: string\n message: string\n}\n\nconst ERROR_TITLE = 'Approval Failed'\nconst ERROR_MESSAGE = 'Something went wrong, try again later'\nconst NOTIFICATION_TIME = 4000\nconst FADE_OUT_TIME_WAIT = 1000\n\nlet notificationsCache: Notification[] = []\n\nexport const APIErrorNotifications = ({\n bankTransaction,\n containerWidth,\n}: APIErrorNotificationsProps) => {\n const [notifications, setNotifications] = useState<Notification[]>([])\n\n const pushNotification = (title: string, message: string) => {\n const timestamp = new Date().valueOf()\n if (\n notificationsCache.find(\n n =>\n n.timestamp === timestamp &&\n n.bankTransactionId !== bankTransaction.id,\n )\n ) {\n return\n }\n notificationsCache = notificationsCache.concat({\n bankTransactionId: bankTransaction.id,\n timestamp,\n title,\n message,\n })\n const ids = notificationsCache.map(\n ({ bankTransactionId }) => bankTransactionId,\n )\n const timestamps = notificationsCache.map(({ timestamp }) => timestamp)\n notificationsCache = notificationsCache.filter(\n ({ bankTransactionId, timestamp }, index) =>\n !ids.includes(bankTransactionId, index + 1) &&\n !timestamps.includes(timestamp, index + 1),\n )\n setNotifications(notificationsCache.concat())\n }\n\n const deleteNotification = (timestamp: number) => {\n notificationsCache = notificationsCache.filter(\n n => n.timestamp !== timestamp,\n )\n setNotifications(notificationsCache.concat())\n }\n\n useEffect(() => {\n if (bankTransaction.error) {\n pushNotification(ERROR_TITLE, ERROR_MESSAGE)\n }\n }, [bankTransaction.error])\n\n return (\n <div\n className='Layer__bank-transactions__notifications'\n style={containerWidth ? { left: containerWidth - 324 } : {}}\n >\n {notifications\n .filter(n => n.bankTransactionId === bankTransaction.id)\n .map(notification => (\n <Notification\n key={notification.timestamp}\n notification={notification}\n deleteNotification={deleteNotification}\n />\n ))}\n </div>\n )\n}\n\nconst Notification = ({\n notification,\n deleteNotification,\n}: {\n notification: Notification\n deleteNotification: (timestamp: number) => void\n}) => {\n const [visible, setVisible] = useState(false)\n\n useEffect(() => {\n setVisible(true)\n\n const timer = setTimeout(() => {\n hideNotification()\n }, NOTIFICATION_TIME)\n\n return () => clearTimeout(timer)\n }, [])\n\n const hideNotification = () => {\n setVisible(false)\n setTimeout(() => {\n deleteNotification(notification.timestamp)\n }, FADE_OUT_TIME_WAIT)\n }\n\n return (\n <div\n className={`Layer__bank-transactions__notification ${\n visible ? 'notification-enter' : 'notification-exit'\n }`}\n onClick={hideNotification}\n >\n <div className='Layer__bank-transactions__notification-content'>\n <div className='Layer__bank-transactions__notification-icon'>\n <AlertOctagon size={14} />\n </div>\n <div className='Layer__bank-transactions__notification-text'>\n <Text\n as='span'\n className='Layer__bank-transactions__notification-title'\n >\n {notification.title}\n </Text>\n <Text\n as='span'\n className='Layer__bank-transactions__notification-message'\n >\n {notification.message}\n </Text>\n </div>\n </div>\n </div>\n )\n}\n", "import React from 'react'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { Category } from '../../types'\n\nexport const SplitTooltipDetails = ({\n classNamePrefix,\n category,\n}: {\n classNamePrefix: string\n category: Category\n}) => {\n if (!category.entries) {\n return\n }\n\n return (\n <span className={`${classNamePrefix}__split-tooltip`}>\n <ul>\n {category.entries.map((entry, idx) => (\n <li key={idx}>\n <span className={`${classNamePrefix}__split-tooltip__label`}>\n {entry.category.display_name}\n </span>\n <span className={`${classNamePrefix}__split-tooltip__value`}>\n ${formatMoney(entry.amount)}\n </span>\n </li>\n ))}\n </ul>\n </span>\n )\n}\n", "import React from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport Scissors from '../../icons/Scissors'\nimport { BankTransaction, CategorizationStatus } from '../../types'\nimport { Badge } from '../Badge'\nimport { extractDescriptionForSplit } from '../BankTransactionRow/BankTransactionRow'\nimport { MatchBadge } from '../BankTransactionRow/MatchBadge'\nimport { SplitTooltipDetails } from '../BankTransactionRow/SplitTooltipDetails'\nimport { Text } from '../Typography'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface AssignmentProps {\n bankTransaction: BankTransaction\n}\n\nexport const Assignment = ({ bankTransaction }: AssignmentProps) => {\n if (\n bankTransaction.match &&\n bankTransaction.categorization_status === CategorizationStatus.MATCHED\n ) {\n return (\n <>\n <MatchBadge\n classNamePrefix='Layer__bank-transaction-list-item'\n bankTransaction={bankTransaction}\n dateFormat={DATE_FORMAT}\n text='Matched'\n />\n <Text className='Layer__bank-transaction-list-item__category-text__text'>\n {`${formatTime(\n parseISO(bankTransaction.match.bank_transaction.date),\n DATE_FORMAT,\n )}, ${bankTransaction.match.bank_transaction.description ?? bankTransaction.match?.details?.description}`}\n </Text>\n </>\n )\n }\n\n if (bankTransaction.categorization_status === CategorizationStatus.SPLIT) {\n return (\n <>\n <Badge\n icon={<Scissors size={11} />}\n tooltip={\n <SplitTooltipDetails\n classNamePrefix='Layer__bank-transaction-list-item'\n category={bankTransaction.category}\n />\n }\n >\n Split\n </Badge>\n <Text className='Layer__bank-transaction-list-item__category-text__text'>\n {extractDescriptionForSplit(bankTransaction.category)}\n </Text>\n </>\n )\n }\n\n return <Text>{bankTransaction?.category?.display_name}</Text>\n}\n", "import React from 'react'\nimport { BankTransaction } from '../../types'\nimport { BankTransactionsMode } from '../BankTransactions/BankTransactions'\nimport { BankTransactionMobileListItem } from './BankTransactionMobileListItem'\nimport {\n useTransactionToOpen,\n TransactionToOpenContext,\n} from './TransactionToOpenContext'\n\nexport interface BankTransactionMobileListProps {\n bankTransactions?: BankTransaction[]\n editable: boolean\n removeTransaction: (bt: BankTransaction) => void\n initialLoad?: boolean\n mode: BankTransactionsMode\n}\n\nexport const BankTransactionMobileList = ({\n bankTransactions,\n removeTransaction,\n editable,\n initialLoad,\n mode,\n}: BankTransactionMobileListProps) => {\n const transactionToOpenContextData = useTransactionToOpen()\n\n return (\n <TransactionToOpenContext.Provider value={transactionToOpenContextData}>\n <ul className='Layer__bank-transactions__mobile-list'>\n {bankTransactions?.map(\n (bankTransaction: BankTransaction, index: number) => (\n <BankTransactionMobileListItem\n index={index}\n mode={mode}\n key={bankTransaction.id}\n bankTransaction={bankTransaction}\n editable={editable}\n removeTransaction={removeTransaction}\n initialLoad={initialLoad}\n isFirstItem={index == 0}\n />\n ),\n )}\n </ul>\n </TransactionToOpenContext.Provider>\n )\n}\n", "import React, { useContext, useEffect, useRef, useState } from 'react'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction, CategorizationStatus } from '../../types'\nimport { hasMatch, isCredit } from '../../utils/bankTransactions'\nimport { extractDescriptionForSplit } from '../BankTransactionRow/BankTransactionRow'\nimport {\n BankTransactionsMode,\n categorizationEnabled,\n} from '../BankTransactions/BankTransactions'\nimport { isCategorized } from '../BankTransactions/utils'\nimport { CloseButton } from '../Button'\nimport { Toggle } from '../Toggle'\nimport { ToggleSize } from '../Toggle/Toggle'\nimport { Text } from '../Typography'\nimport { BankTransactionMobileForms } from './BankTransactionMobileForms'\nimport { TransactionToOpenContext } from './TransactionToOpenContext'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface BankTransactionMobileListItemProps {\n index: number\n bankTransaction: BankTransaction\n editable: boolean\n removeTransaction: (bt: BankTransaction) => void\n initialLoad?: boolean\n mode: BankTransactionsMode\n isFirstItem?: boolean\n}\n\nexport enum Purpose {\n business = 'business',\n personal = 'personal',\n more = 'more',\n}\n\nconst DATE_FORMAT = 'LLL d'\n\nconst getAssignedValue = (bankTransaction: BankTransaction) => {\n if (bankTransaction.categorization_status === CategorizationStatus.SPLIT) {\n return extractDescriptionForSplit(bankTransaction.category)\n }\n\n if (bankTransaction.categorization_status === CategorizationStatus.MATCHED) {\n return bankTransaction.match?.details?.description\n }\n\n return bankTransaction.category?.display_name\n}\n\nexport const BankTransactionMobileListItem = ({\n index = 0,\n bankTransaction,\n removeTransaction,\n editable,\n mode,\n initialLoad,\n isFirstItem = false,\n}: BankTransactionMobileListItemProps) => {\n const {\n transactionIdToOpen,\n setTransactionIdToOpen,\n clearTransactionIdToOpen,\n } = useContext(TransactionToOpenContext)\n const formRowRef = useElementSize<HTMLDivElement>((_a, _b, { height }) =>\n setHeight(height),\n )\n const headingRowRef = useElementSize<HTMLDivElement>((_a, _b, { height }) => {\n setHeadingHeight(height)\n })\n const itemRef = useRef<HTMLLIElement>(null)\n\n const [removeAnim, setRemoveAnim] = useState(false)\n const [purpose, setPurpose] = useState<Purpose>(\n bankTransaction.category\n ? bankTransaction.categorization_status === CategorizationStatus.SPLIT\n ? Purpose.more\n : Purpose.business\n : hasMatch(bankTransaction)\n ? Purpose.more\n : Purpose.business,\n )\n const [open, setOpen] = useState(isFirstItem)\n const [showComponent, setShowComponent] = useState(!initialLoad)\n const [height, setHeight] = useState(0)\n const [headingHeight, setHeadingHeight] = useState(63)\n\n const openNext = () => {\n if (editable && itemRef.current && itemRef.current.nextSibling) {\n const txId = (itemRef.current.nextSibling as HTMLLIElement).getAttribute(\n 'data-item',\n )\n\n if (txId) {\n setTransactionIdToOpen(txId)\n }\n }\n }\n\n useEffect(() => {\n if (transactionIdToOpen && transactionIdToOpen === bankTransaction.id) {\n setOpen(true)\n clearTransactionIdToOpen()\n }\n }, [transactionIdToOpen])\n\n useEffect(() => {\n if (!removeAnim && bankTransaction.recently_categorized) {\n if (editable) {\n setRemoveAnim(true)\n openNext()\n } else {\n close()\n }\n }\n }, [\n bankTransaction.recently_categorized,\n bankTransaction.category,\n bankTransaction.match,\n ])\n\n const toggleOpen = () => {\n if (open) {\n setHeight(0)\n }\n setOpen(!open)\n }\n\n const close = () => {\n setOpen(false)\n setHeight(0)\n }\n\n useEffect(() => {\n if (initialLoad) {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, index * 20)\n\n return () => clearTimeout(timeoutId)\n } else {\n setShowComponent(true)\n }\n }, [])\n\n useEffect(() => {\n if (editable && bankTransaction.recently_categorized) {\n setTimeout(() => {\n removeTransaction(bankTransaction)\n }, 300)\n }\n }, [bankTransaction.recently_categorized])\n\n const onChangePurpose = (event: React.ChangeEvent<HTMLInputElement>) =>\n setPurpose(event.target.value as Purpose)\n\n const categorized = isCategorized(bankTransaction)\n\n const className = 'Layer__bank-transaction-mobile-list-item'\n const openClassName = open ? `${className}--expanded` : ''\n const rowClassName = classNames(\n className,\n removeAnim ? 'Layer__bank-transaction-row--removing' : '',\n open ? openClassName : '',\n showComponent ? 'show' : '',\n )\n\n return (\n <li ref={itemRef} className={rowClassName} data-item={bankTransaction.id}>\n <span\n className={`${className}__heading`}\n onClick={toggleOpen}\n role='button'\n style={{ height: headingHeight }}\n >\n <div className={`${className}__heading__content`} ref={headingRowRef}>\n <div className={`${className}__heading__main`}>\n <Text as='span' className={`${className}__heading__tx-name`}>\n {bankTransaction.counterparty_name ?? bankTransaction.description}\n </Text>\n <Text as='span' className={`${className}__heading__account-name`}>\n {categorized && bankTransaction.categorization_status\n ? getAssignedValue(bankTransaction)\n : null}\n {!categorized && bankTransaction.account_name}\n </Text>\n {categorized && open && (\n <Text as='span' className={`${className}__categorized-name`}>\n {bankTransaction.account_name}\n </Text>\n )}\n </div>\n <div className={`${className}__heading__amount`}>\n <span\n className={`${className}__amount-${\n isCredit(bankTransaction) ? 'credit' : 'debit'\n }`}\n >\n {isCredit(bankTransaction) ? '+$' : ' $'}\n {formatMoney(bankTransaction.amount)}\n </span>\n <span className={`${className}__heading__date`}>\n {formatTime(parseISO(bankTransaction.date), DATE_FORMAT)}\n </span>\n </div>\n </div>\n </span>\n {categorizationEnabled(mode) ? (\n <div\n className={`${className}__expanded-row`}\n style={{ height: !open || removeAnim ? 0 : height }}\n >\n {open && (\n <div\n className={`${className}__expanded-row__content`}\n ref={formRowRef}\n >\n <div className={`${className}__toggle-row`}>\n <Toggle\n name={`purpose-${bankTransaction.id}`}\n size={ToggleSize.xsmall}\n options={[\n {\n value: 'business',\n label: 'Business',\n style: { minWidth: 84 },\n disabled: !categorizationEnabled(mode),\n },\n {\n value: 'personal',\n label: 'Personal',\n style: { minWidth: 84 },\n disabled: !categorizationEnabled(mode),\n },\n {\n value: 'more',\n label: 'More',\n style: { minWidth: 84 },\n disabled: !categorizationEnabled(mode),\n },\n ]}\n selected={purpose}\n onChange={onChangePurpose}\n />\n <CloseButton onClick={() => close()} />\n </div>\n <BankTransactionMobileForms\n purpose={purpose}\n bankTransaction={bankTransaction}\n />\n </div>\n )}\n </div>\n ) : (\n <></>\n )}\n </li>\n )\n}\n", "import React from 'react'\nimport { BankTransaction } from '../../types'\nimport { Purpose } from './BankTransactionMobileListItem'\nimport { BusinessForm } from './BusinessForm'\nimport { PersonalForm } from './PersonalForm'\nimport { SplitAndMatchForm } from './SplitAndMatchForm'\n\ninterface BankTransactionMobileFormsProps {\n purpose: Purpose\n bankTransaction: BankTransaction\n}\n\nexport const BankTransactionMobileForms = ({\n purpose,\n bankTransaction,\n}: BankTransactionMobileFormsProps) => {\n const getContent = () => {\n switch (purpose) {\n case 'business':\n return <BusinessForm bankTransaction={bankTransaction} />\n case 'personal':\n return <PersonalForm bankTransaction={bankTransaction} />\n case 'more':\n return <SplitAndMatchForm bankTransaction={bankTransaction} />\n default:\n return null\n }\n }\n\n return (\n <div className='Layer__bank-transaction-mobile-list-item__form-container'>\n {getContent()}\n </div>\n )\n}\n", "import React, { useContext, useEffect, useMemo, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { DrawerContext } from '../../contexts/DrawerContext'\nimport { BankTransaction, CategorizationType } from '../../types'\nimport { ActionableList } from '../ActionableList'\nimport { Button, ButtonVariant } from '../Button'\nimport { ErrorText } from '../Typography'\nimport { BusinessCategories } from './BusinessCategories'\nimport { Option, mapCategoryToOption, getAssignedValue } from './utils'\n\ninterface BusinessFormProps {\n bankTransaction: BankTransaction\n}\n\nexport const BusinessForm = ({ bankTransaction }: BusinessFormProps) => {\n const { setContent, close } = useContext(DrawerContext)\n const { categorize: categorizeBankTransaction, isLoading } =\n useBankTransactionsContext()\n const [selectedCategory, setSelectedCategory] = useState<Option | undefined>(\n getAssignedValue(bankTransaction),\n )\n const [showRetry, setShowRetry] = useState(false)\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n }\n }, [bankTransaction.error])\n\n const options = useMemo(() => {\n const options =\n bankTransaction?.categorization_flow?.type ===\n CategorizationType.ASK_FROM_SUGGESTIONS\n ? bankTransaction.categorization_flow.suggestions.map(x =>\n mapCategoryToOption(x),\n )\n : []\n\n if (selectedCategory && !options.find(x => x.id === selectedCategory?.id)) {\n options.unshift(selectedCategory)\n }\n\n if (options.length) {\n options.push({\n label: 'All categories',\n id: 'SELECT_CATEGORY',\n value: {\n type: 'SELECT_CATEGORY',\n },\n secondary: true,\n asLink: true,\n })\n }\n\n return options\n }, [bankTransaction, selectedCategory])\n\n const onDrawerCategorySelect = (value: Option) => {\n close()\n setSelectedCategory(value)\n }\n\n const openDrawer = () => {\n setContent(<BusinessCategories select={onDrawerCategorySelect} />)\n }\n\n const onCategorySelect = (category: Option) => {\n if (category.value.type === 'SELECT_CATEGORY') {\n openDrawer()\n } else {\n if (\n selectedCategory &&\n category.value.payload?.id === selectedCategory.value.payload?.id\n ) {\n setSelectedCategory(undefined)\n } else {\n setSelectedCategory(category)\n }\n }\n }\n\n const save = () => {\n if (!selectedCategory || !selectedCategory.value.payload) {\n return\n }\n\n const payload = selectedCategory?.value?.payload?.id\n ? {\n type: 'AccountId' as 'AccountId',\n id: selectedCategory.value.payload.id,\n }\n : {\n type: 'StableName' as 'StableName',\n stable_name: selectedCategory.value.payload?.stable_name || '',\n }\n\n categorizeBankTransaction(\n bankTransaction.id,\n {\n type: 'Category',\n category: payload,\n },\n true,\n )\n }\n\n return (\n <div className='Layer__bank-transaction-mobile-list-item__business-form'>\n <ActionableList<Option['value']>\n options={options}\n onClick={onCategorySelect}\n selected={selectedCategory}\n />\n {options.length === 0 ? (\n <Button\n onClick={openDrawer}\n fullWidth={true}\n variant={ButtonVariant.secondary}\n >\n Select category\n </Button>\n ) : null}\n {options.length > 0 ? (\n <Button\n onClick={save}\n disabled={\n !selectedCategory || isLoading || bankTransaction.processing\n }\n fullWidth={true}\n >\n {isLoading || bankTransaction.processing ? 'Saving...' : 'Save'}\n </Button>\n ) : null}\n {bankTransaction.error && showRetry ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : null}\n </div>\n )\n}\n", "import React, { useEffect, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { BankTransaction, CategorizationStatus } from '../../types'\nimport { isCredit } from '../../utils/bankTransactions'\nimport { Button } from '../Button'\nimport { ErrorText } from '../Typography'\nimport { PersonalCategories } from './constants'\n\ninterface PersonalFormProps {\n bankTransaction: BankTransaction\n}\n\nconst isAlreadyAssigned = (bankTransaction: BankTransaction) => {\n if (\n bankTransaction.categorization_status === CategorizationStatus.MATCHED ||\n bankTransaction?.categorization_status === CategorizationStatus.SPLIT\n ) {\n return false\n }\n\n return Boolean(\n bankTransaction.category &&\n PersonalCategories.includes(bankTransaction.category.display_name),\n )\n}\n\nexport const PersonalForm = ({ bankTransaction }: PersonalFormProps) => {\n const { categorize: categorizeBankTransaction, isLoading } =\n useBankTransactionsContext()\n const [showRetry, setShowRetry] = useState(false)\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n }\n }, [bankTransaction.error])\n\n const save = () => {\n categorizeBankTransaction(\n bankTransaction.id,\n {\n type: 'Category',\n category: {\n type: 'StableName',\n stable_name: isCredit(bankTransaction)\n ? 'PERSONAL_INCOME'\n : 'PERSONAL_EXPENSES',\n },\n },\n true,\n )\n }\n\n const alreadyAssigned = isAlreadyAssigned(bankTransaction)\n\n return (\n <div className='Layer__bank-transaction-mobile-list-item__personal-form'>\n <Button\n fullWidth={true}\n disabled={alreadyAssigned || isLoading || bankTransaction.processing}\n onClick={save}\n >\n {isLoading || bankTransaction.processing\n ? 'Saving...'\n : alreadyAssigned\n ? 'Saved as Personal'\n : 'Categorize as Personal'}\n </Button>\n {bankTransaction.error && showRetry ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : null}\n </div>\n )\n}\n", "import React, { useState } from 'react'\nimport { BankTransaction } from '../../types'\nimport { hasMatch } from '../../utils/bankTransactions'\nimport { TextButton } from '../Button'\nimport { MatchForm } from './MatchForm'\nimport { SplitForm } from './SplitForm'\n\ninterface SplitAndMatchFormProps {\n bankTransaction: BankTransaction\n}\n\nenum Purpose {\n categorize = 'categorize',\n match = 'match',\n}\n\nexport const SplitAndMatchForm = ({\n bankTransaction,\n}: SplitAndMatchFormProps) => {\n const anyMatch = hasMatch(bankTransaction)\n const [formType, setFormType] = useState(\n bankTransaction.category\n ? Purpose.categorize\n : anyMatch\n ? Purpose.match\n : Purpose.categorize,\n )\n\n return (\n <div className='Layer__bank-transaction-mobile-list-item__split-and-match-form'>\n {formType === Purpose.categorize && (\n <SplitForm bankTransaction={bankTransaction} />\n )}\n {formType === Purpose.match && (\n <MatchForm bankTransaction={bankTransaction} />\n )}\n {anyMatch && formType === Purpose.match ? (\n <div className='Layer__bank-transaction-mobile-list-item__switch-form-btns'>\n <TextButton onClick={() => setFormType(Purpose.categorize)}>\n or split transaction\n </TextButton>\n </div>\n ) : null}\n {anyMatch && formType === Purpose.categorize ? (\n <div className='Layer__bank-transaction-mobile-list-item__switch-form-btns'>\n <TextButton onClick={() => setFormType(Purpose.match)}>\n or find match\n </TextButton>\n </div>\n ) : null}\n </div>\n )\n}\n", "import React, { useEffect, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { BankTransaction } from '../../types'\nimport { isAlreadyMatched } from '../../utils/bankTransactions'\nimport { Button } from '../Button'\nimport { MatchFormMobile } from '../MatchForm'\nimport { ErrorText, Text, TextSize, TextWeight } from '../Typography'\n\nexport const MatchForm = ({\n bankTransaction,\n}: {\n bankTransaction: BankTransaction\n}) => {\n const { match: matchBankTransaction, isLoading } =\n useBankTransactionsContext()\n const [selectedMatchId, setSelectedMatchId] = useState<string | undefined>(\n isAlreadyMatched(bankTransaction) ??\n (bankTransaction.suggested_matches &&\n bankTransaction.suggested_matches?.length > 0\n ? bankTransaction.suggested_matches[0].id\n : undefined),\n )\n const [formError, setFormError] = useState<string | undefined>()\n const [showRetry, setShowRetry] = useState(false)\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n } else if (showRetry) {\n setShowRetry(false)\n }\n }, [bankTransaction.error])\n\n const onMatchSubmit = async (matchId: string) => {\n const foundMatch = bankTransaction.suggested_matches?.find(\n x => x.id === matchId,\n )\n if (!foundMatch) {\n return\n }\n\n await matchBankTransaction(bankTransaction.id, foundMatch.id, true)\n }\n\n const save = async () => {\n if (!selectedMatchId) {\n setFormError('Select an option to match the transaction')\n } else if (\n selectedMatchId &&\n selectedMatchId !== isAlreadyMatched(bankTransaction)\n ) {\n onMatchSubmit(selectedMatchId)\n }\n return\n }\n\n return (\n <div>\n <Text weight={TextWeight.bold} size={TextSize.sm}>\n Find match\n </Text>\n <MatchFormMobile\n classNamePrefix='Layer__bank-transaction-mobile-list-item'\n bankTransaction={bankTransaction}\n selectedMatchId={selectedMatchId}\n setSelectedMatchId={id => {\n setFormError(undefined)\n setSelectedMatchId(id)\n }}\n />\n <Button\n fullWidth={true}\n disabled={\n !selectedMatchId ||\n isLoading ||\n bankTransaction.processing ||\n selectedMatchId === isAlreadyMatched(bankTransaction)\n }\n onClick={save}\n >\n {isLoading || bankTransaction.processing\n ? 'Saving...'\n : 'Approve match'}\n </Button>\n {formError && <ErrorText>{formError}</ErrorText>}\n {bankTransaction.error && showRetry ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : null}\n </div>\n )\n}\n", "import React, { useEffect, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport Trash from '../../icons/Trash'\nimport {\n centsToDollars as formatMoney,\n dollarsToCents as parseMoney,\n} from '../../models/Money'\nimport { BankTransaction } from '../../types'\nimport {\n SingleCategoryUpdate,\n SplitCategoryUpdate,\n hasSuggestions,\n} from '../../types/categories'\nimport { getCategorizePayload } from '../../utils/bankTransactions'\nimport { Button, ButtonVariant, TextButton } from '../Button'\nimport { CategorySelect } from '../CategorySelect'\nimport {\n CategoryOption,\n mapCategoryToOption,\n} from '../CategorySelect/CategorySelect'\nimport { Input } from '../Input'\nimport { ErrorText, Text, TextSize, TextWeight } from '../Typography'\nimport classNames from 'classnames'\n\ntype Split = {\n amount: number\n inputValue: string\n category: CategoryOption | undefined\n}\n\ntype RowState = {\n splits: Split[]\n description: string\n file: unknown\n}\n\nexport const SplitForm = ({\n bankTransaction,\n}: {\n bankTransaction: BankTransaction\n}) => {\n const {\n categorize: categorizeBankTransaction,\n isLoading,\n error,\n } = useBankTransactionsContext()\n const defaultCategory =\n bankTransaction.category ||\n (hasSuggestions(bankTransaction.categorization_flow) &&\n bankTransaction.categorization_flow?.suggestions?.[0])\n\n const [rowState, updateRowState] = useState<RowState>({\n splits: bankTransaction.category?.entries\n ? bankTransaction.category?.entries.map(c => {\n return {\n amount: c.amount || 0,\n inputValue: formatMoney(c.amount),\n category: mapCategoryToOption(c.category),\n }\n })\n : [\n {\n amount: bankTransaction.amount,\n inputValue: formatMoney(bankTransaction.amount),\n category: defaultCategory\n ? mapCategoryToOption(defaultCategory)\n : undefined,\n },\n {\n amount: 0,\n inputValue: '0.00',\n category: defaultCategory\n ? mapCategoryToOption(defaultCategory)\n : undefined,\n },\n ],\n description: '',\n file: undefined,\n })\n const [formError, setFormError] = useState<string | undefined>()\n const [showRetry, setShowRetry] = useState(false)\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n }\n }, [bankTransaction.error])\n\n const removeSplit = (index: number) => {\n const newSplits = rowState.splits.filter((_v, idx) => idx !== index)\n const splitTotal = newSplits.reduce((sum, split, index) => {\n const amount = index === 0 ? 0 : split.amount\n return sum + amount\n }, 0)\n const remaining = bankTransaction.amount - splitTotal\n newSplits[0].amount = remaining\n newSplits[0].inputValue = formatMoney(remaining)\n\n updateRowState({\n ...rowState,\n splits: newSplits,\n })\n setFormError(undefined)\n }\n\n const updateAmounts =\n (rowNumber: number) => (event: React.ChangeEvent<HTMLInputElement>) => {\n const newAmount = parseMoney(event.target.value) || 0\n const newDisplaying = event.target.value\n const splitTotal = rowState.splits.reduce((sum, split, index) => {\n const amount =\n index === 0 ? 0 : index === rowNumber ? newAmount : split.amount\n return sum + amount\n }, 0)\n const remaining = bankTransaction.amount - splitTotal\n rowState.splits[rowNumber].amount = newAmount\n rowState.splits[rowNumber].inputValue = newDisplaying\n rowState.splits[0].amount = remaining\n rowState.splits[0].inputValue = formatMoney(remaining)\n updateRowState({ ...rowState })\n setFormError(undefined)\n }\n\n const onBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (event.target.value === '') {\n const [_, index] = event.target.name.split('-')\n rowState.splits[parseInt(index)].inputValue = '0.00'\n updateRowState({ ...rowState })\n setFormError(undefined)\n }\n }\n\n const changeCategory = (index: number, newValue: CategoryOption) => {\n rowState.splits[index].category = newValue\n updateRowState({ ...rowState })\n setFormError(undefined)\n }\n\n const addSplit = () => {\n updateRowState({\n ...rowState,\n splits: [\n ...rowState.splits,\n {\n amount: 0,\n inputValue: '0.00',\n category: defaultCategory\n ? mapCategoryToOption(defaultCategory)\n : undefined,\n },\n ],\n })\n setFormError(undefined)\n }\n\n const validateSplit = (splitData: RowState) => {\n let valid = true\n\n splitData.splits.forEach(split => {\n if (split.amount <= 0) {\n valid = false\n } else if (!split.category) {\n valid = false\n }\n })\n\n return valid\n }\n\n const save = async () => {\n if (!validateSplit(rowState)) {\n if (rowState.splits.length > 1) {\n setFormError(\n 'Use only positive amounts and select category for each entry',\n )\n } else {\n setFormError('Category is required')\n }\n return\n }\n\n await categorizeBankTransaction(\n bankTransaction.id,\n rowState.splits.length === 1 && rowState?.splits[0].category\n ? ({\n type: 'Category',\n category: getCategorizePayload(rowState?.splits[0].category),\n } as SingleCategoryUpdate)\n : ({\n type: 'Split',\n entries: rowState.splits.map(split => ({\n category: split.category\n ? getCategorizePayload(split.category)\n : '',\n amount: split.amount,\n })),\n } as SplitCategoryUpdate),\n true,\n )\n }\n\n return (\n <div>\n <Text weight={TextWeight.bold} size={TextSize.sm}>\n Split transaction\n </Text>\n <div className='Layer__bank-transactions__table-cell__header'>\n <Text size={TextSize.sm}>Category</Text>\n <Text size={TextSize.sm}>Amount</Text>\n </div>\n <div className='Layer__bank-transactions__splits-inputs'>\n {rowState.splits.map((split, index) => (\n <div\n className='Layer__bank-transactions__table-cell--split-entry'\n key={`split-${index}`}\n >\n <div className='Layer__bank-transactions__table-cell--split-entry__right-col'>\n <CategorySelect\n bankTransaction={bankTransaction}\n name={`category-${bankTransaction.id}`}\n value={split.category}\n onChange={value => changeCategory(index, value)}\n className='Layer__category-menu--full'\n disabled={bankTransaction.processing}\n excludeMatches\n asDrawer\n />\n </div>\n <Input\n type='text'\n name={`split-${index}`}\n className={classNames(\n 'Layer__split-amount-input',\n index === 0 && 'Layer__split-amount-input--first',\n )}\n disabled={index === 0}\n onChange={updateAmounts(index)}\n value={split.inputValue}\n onBlur={onBlur}\n isInvalid={split.amount < 0}\n errorMessage='Negative values are not allowed'\n inputMode='numeric'\n />\n {index > 0 && (\n <Button\n className='Layer__bank-transactions__table-cell--split-entry__merge-btn'\n onClick={() => removeSplit(index)}\n rightIcon={<Trash size={16} />}\n variant={ButtonVariant.secondary}\n iconOnly={true}\n />\n )}\n </div>\n ))}\n <TextButton\n onClick={addSplit}\n disabled={rowState.splits.length > 5 || isLoading}\n className='Layer__add-new-split'\n >\n Add new split\n </TextButton>\n </div>\n <Button\n fullWidth={true}\n onClick={save}\n disabled={isLoading || bankTransaction.processing}\n >\n {isLoading || bankTransaction.processing ? 'Saving...' : 'Save'}\n </Button>\n {formError && <ErrorText>{formError}</ErrorText>}\n {bankTransaction.error && showRetry ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : null}\n </div>\n )\n}\n", "import { createContext, useState } from 'react'\n\ntype UseTransactionToOpen = () => {\n transactionIdToOpen?: string\n setTransactionIdToOpen: (id: string) => void\n clearTransactionIdToOpen: () => void\n}\n\nexport const useTransactionToOpen: UseTransactionToOpen = () => {\n const [transactionIdToOpen, setTransactionIdToOpen] = useState<\n string | undefined\n >(undefined)\n\n const clearTransactionIdToOpen = () => setTransactionIdToOpen(undefined)\n\n return {\n transactionIdToOpen,\n setTransactionIdToOpen,\n clearTransactionIdToOpen,\n }\n}\n\nexport type TransactionToOpenContextType = ReturnType<\n typeof useTransactionToOpen\n>\nexport const TransactionToOpenContext =\n createContext<TransactionToOpenContextType>({\n transactionIdToOpen: undefined,\n setTransactionIdToOpen: () => undefined,\n clearTransactionIdToOpen: () => undefined,\n })\n", "import React from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport { BankTransaction } from '../../types'\nimport { BankTransactionRow } from '../BankTransactionRow'\nimport {\n BankTransactionsMode,\n BankTransactionsStringOverrides,\n} from '../BankTransactions/BankTransactions'\nimport { BankTransactionsLoader } from '../BankTransactionsLoader'\nimport { SyncingComponent } from '../SyncingComponent'\n\nexport interface BankTransactionsTableStringOverrides {\n dateColumnHeaderText?: string\n transactionColumnHeaderText?: string\n accountColumnHeaderText?: string\n amountColumnHeaderText?: string\n categorizeColumnHeaderText?: string\n categoryColumnHeaderText?: string\n}\n\ninterface BankTransactionsTableProps {\n bankTransactions?: BankTransaction[]\n editable: boolean\n categorizeView?: boolean\n mode: BankTransactionsMode\n isLoading?: boolean\n initialLoad?: boolean\n containerWidth: number\n removeTransaction: (bt: BankTransaction) => void\n showDescriptions?: boolean\n showReceiptUploads?: boolean\n stringOverrides?: BankTransactionsStringOverrides\n isSyncing?: boolean\n page?: number\n lastPage?: boolean\n onRefresh?: () => void\n}\n\nexport const BankTransactionsTable = ({\n categorizeView,\n editable,\n isLoading,\n bankTransactions,\n mode,\n initialLoad,\n containerWidth,\n removeTransaction,\n showDescriptions = false,\n showReceiptUploads = false,\n stringOverrides,\n isSyncing = false,\n page,\n lastPage,\n onRefresh,\n}: BankTransactionsTableProps) => {\n return (\n <table\n width='100%'\n className='Layer__table Layer__bank-transactions__table with-cell-separators'\n >\n <thead>\n <tr>\n <th className='Layer__table-header Layer__bank-transactions__date-col'>\n {stringOverrides?.transactionsTable?.dateColumnHeaderText || 'Date'}\n </th>\n <th className='Layer__table-header Layer__bank-transactions__tx-col'>\n {stringOverrides?.transactionsTable?.transactionColumnHeaderText ||\n 'Transaction'}\n </th>\n <th className='Layer__table-header Layer__bank-transactions__account-col'>\n {stringOverrides?.transactionsTable?.accountColumnHeaderText ||\n 'Account'}\n </th>\n <th className='Layer__table-header Layer__table-cell--amount Layer__table-cell__amount-col'>\n {stringOverrides?.transactionsTable?.amountColumnHeaderText ||\n 'Amount'}\n </th>\n {categorizeView && editable ? (\n <th className='Layer__table-header Layer__table-header--primary Layer__table-cell__category-col'>\n {stringOverrides?.transactionsTable?.categorizeColumnHeaderText ||\n 'Categorize'}\n </th>\n ) : (\n <th className='Layer__table-header Layer__table-cell__category-col'>\n {stringOverrides?.transactionsTable?.categoryColumnHeaderText ||\n 'Category'}\n </th>\n )}\n </tr>\n </thead>\n {isLoading && page && page === 1 ? (\n <BankTransactionsLoader isLoading={true} />\n ) : null}\n <tbody>\n {!isLoading &&\n bankTransactions?.map(\n (bankTransaction: BankTransaction, index: number) => (\n <BankTransactionRow\n initialLoad={initialLoad}\n index={index}\n editable={editable}\n mode={mode}\n key={bankTransaction.id}\n dateFormat={DATE_FORMAT}\n bankTransaction={bankTransaction}\n removeTransaction={removeTransaction}\n containerWidth={containerWidth}\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n stringOverrides={stringOverrides?.bankTransactionCTAs}\n />\n ),\n )}\n {isSyncing &&\n (lastPage ||\n ((!bankTransactions || bankTransactions.length === 0) &&\n page === 1)) ? (\n <tr>\n <td colSpan={3}>\n <SyncingComponent\n title='Syncing historical account data'\n onRefresh={() => onRefresh && onRefresh()}\n />\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n )\n}\n", "import React from 'react'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { BankTransaction } from '../../types'\nimport { IconButton, SubmitButton } from '../Button'\nimport { SubmitAction } from '../Button/SubmitButton'\nimport { CategorySelect } from '../CategorySelect'\nimport { SkeletonTableLoader } from '../SkeletonTableLoader'\n\nexport const BankTransactionsLoader = ({\n isLoading = true,\n}: {\n isLoading: boolean\n}) => {\n const inactiveBankTransactionsActions = (\n <div className='Layer__bank-transaction-row__actions-container Layer__bank-transaction-row__actions-disabled'>\n <CategorySelect\n name='category-bakn-transaction'\n bankTransaction={{} as BankTransaction}\n value={undefined}\n onChange={() => {}}\n disabled={true}\n />\n <SubmitButton\n onClick={() => {}}\n action={SubmitAction.UPDATE}\n className='Layer__bank-transaction__submit-btn'\n disabled={true}\n >\n Approve\n </SubmitButton>\n <IconButton\n disabled={true}\n onClick={() => {}}\n className='Layer__bank-transaction-row__expand-button'\n icon={\n <ChevronDownFill className='Layer__chevron Layer__chevron__down' />\n }\n />\n </div>\n )\n return (\n <SkeletonTableLoader\n rows={6}\n cols={\n isLoading\n ? [\n { colSpan: 4, trimLastXRows: 3 },\n { colSpan: 1, parts: 2 },\n ]\n : [\n { colSpan: 4 },\n { colSpan: 1, colComponent: inactiveBankTransactionsActions },\n ]\n }\n height={20}\n />\n )\n}\n", "import React from 'react'\nimport { SkeletonLoader } from '../SkeletonLoader'\n\ninterface SkeletonTableLoaderProps {\n rows: number\n cols: Array<{\n colSpan: number\n colComponent?: React.ReactNode\n trimLastXRows?: number\n parts?: number\n }>\n height?: number\n width?: number\n}\n\nexport const SkeletonTableLoader = ({\n rows,\n cols,\n height = 20,\n width = 100,\n}: SkeletonTableLoaderProps) => {\n return (\n <tbody className={'Layer__skeleton-table-body__loader'}>\n {Array.from({ length: rows }).map((_, rowIndex) => (\n <tr key={rowIndex}>\n {cols.map((col, colIndex) => {\n const trim: number =\n col.trimLastXRows && rowIndex >= col.trimLastXRows - 1\n ? (rowIndex - col.trimLastXRows + 1) * 10\n : 0\n return (\n <td\n key={colIndex}\n colSpan={col.colSpan}\n className='Layer__skeleton-loader__row'\n >\n {col.colComponent ? (\n col.colComponent\n ) : col.parts && col.parts > 1 ? (\n <span className='Layer__skeleton-loader__row__group'>\n {[...Array(col.parts)].map((_part, partIndex) => (\n <SkeletonLoader\n key={`part-${partIndex}`}\n width='100%'\n height={`${height}px`}\n />\n ))}\n </span>\n ) : (\n <SkeletonLoader\n width={`${width - trim}%`}\n height={`${height}px`}\n />\n )}\n </td>\n )\n })}\n </tr>\n ))}\n </tbody>\n )\n}\n", "import React from 'react'\nimport classNames from 'classnames'\n\nexport interface SkeletonLoaderProps {\n width?: string\n height?: string\n className?: string\n}\n\nexport const SkeletonLoader = ({\n height,\n width,\n className,\n}: SkeletonLoaderProps) => {\n const baseClassName = classNames(\n 'Layer__skeleton-loader Layer__anim--skeleton-loading',\n className,\n )\n return <div className={baseClassName} style={{ width, height }} />\n}\n", "import React from 'react'\nimport RefreshCcw from '../../icons/RefreshCcw'\nimport { IconButton } from '../Button'\nimport { SmallLoader } from '../Loader'\nimport classNames from 'classnames'\n\ninterface SyncingComponentProps {\n title?: string\n message?: string\n onRefresh?: () => void\n timeSync?: number\n inProgress?: boolean\n hideContent?: boolean\n}\n\n/**\n * SyncingComponent\n * @param title - Title of the component\n * @param message - Message of the component\n * @param onRefresh - Function to refresh the component\n * @param timeSync - Time to sync in minutes\n * @param inProgress - Show progress icon besides button\n * @param hideContent - Hide content of the component\n *\n * @example\n * <SyncingComponent\n * title='Syncing account data'\n * message='This may take up to'\n * onRefresh={() => console.log('refresh')}\n * timeSync={1440}\n * inProgress={false}\n * hideContent={false}\n * />\n */\nexport const SyncingComponent = ({\n title = 'Syncing account data',\n message = 'This may take up to',\n onRefresh,\n inProgress = false,\n timeSync = 1440,\n hideContent = false,\n}: SyncingComponentProps) => {\n const handleRefresh = () => {\n onRefresh && onRefresh()\n }\n\n const timeSyncInfo = () => {\n if (timeSync > 60) {\n return `${Math.floor(timeSync / 60)} hours`\n }\n return `${timeSync} minutes`\n }\n\n return (\n <div\n className={classNames(\n 'Layer__syncing-component',\n inProgress ? 'Layer__syncing-component--with-border' : '',\n )}\n >\n <div className='Layer__syncing-component__actions'>\n {inProgress ? (\n <SmallLoader />\n ) : (\n <IconButton icon={<RefreshCcw />} onClick={handleRefresh} />\n )}\n </div>\n {!hideContent && (\n <div className='Layer__syncing-component__content'>\n <div className='Layer__syncing-component__title'>{title}</div>\n <div className='Layer__syncing-component__message'>{`${message} ${timeSyncInfo()}`}</div>\n </div>\n )}\n </div>\n )\n}\n", "import React, { ErrorInfo, Component } from 'react'\nimport { LayerError, reportError } from '../../models/ErrorHandler'\nimport { ErrorBoundaryMessage } from './ErrorBoundaryMessage'\n\ninterface ErrorBoundaryProps {\n onError?: (error: Error) => void\n}\n\ninterface ErrorBoundaryState {\n hasError?: boolean\n}\n\nexport class ErrorBoundary extends Component<\n React.PropsWithChildren<ErrorBoundaryProps>,\n ErrorBoundaryState\n> {\n onError: (err: LayerError) => void\n\n constructor(props: any) {\n super(props)\n this.onError = props.onError\n this.state = { hasError: false }\n }\n\n static getDerivedStateFromError(_error: Error) {\n // Update state so the next render will show the fallback UI.\n return { hasError: true }\n }\n\n componentDidCatch(error: Error, _info: ErrorInfo) {\n if (this.onError) {\n this.onError({ type: 'render', payload: error })\n } else {\n reportError({ type: 'render', payload: error })\n }\n }\n\n render() {\n if (this.state.hasError) {\n return <ErrorBoundaryMessage />\n }\n return (this.props as { children: any }).children\n }\n}\n", "import React from 'react'\nimport { DataState, DataStateStatus } from '../DataState'\n\nexport const ErrorBoundaryMessage = () => {\n return (\n <div className='Layer__component Layer__component-container Layer__error-boundary'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='Try to refresh the page.'\n />\n </div>\n )\n}\n", "import React from 'react'\nimport { usePagination, DOTS } from '../../hooks/usePagination'\nimport ChevronLeft from '../../icons/ChevronLeft'\nimport ChevronRight from '../../icons/ChevronRight'\nimport classnames from 'classnames'\n\nexport interface PaginationProps {\n currentPage: number\n pageSize: number\n onPageChange: (page: number) => void\n totalCount: number\n siblingCount?: number\n hasMore?: boolean\n fetchMore?: () => void\n}\n\nexport const Pagination = ({\n onPageChange,\n totalCount,\n siblingCount = 1,\n currentPage,\n pageSize,\n hasMore,\n fetchMore\n}: PaginationProps) => {\n const paginationRange = usePagination({\n currentPage,\n totalCount,\n siblingCount,\n pageSize,\n })\n\n if (!paginationRange) {\n return\n }\n\n if (currentPage === 0 || paginationRange.length < 2) {\n return\n }\n\n let lastPage = paginationRange[paginationRange.length - 1]\n\n return (\n <ul className='Layer__pagination'>\n <li\n key={`page-prev`}\n className={classnames(\n 'Layer__pagination-item Layer__pagination-arrow Layer__pagination-arrow--previous',\n {\n disabled: currentPage === 1,\n },\n )}\n onClick={() => onPageChange(currentPage - 1)}\n >\n <ChevronLeft size={12} />\n </li>\n {paginationRange.map((pageNumber, idx) => {\n if (pageNumber === DOTS) {\n return (\n <li\n key={`${idx}-page-${pageNumber}`}\n className='Layer__pagination-item Layer__pagination-dots'\n >\n …\n </li>\n )\n }\n\n return (\n <li\n key={`page-${pageNumber}`}\n className={classnames('Layer__pagination-item', {\n selected: pageNumber === currentPage,\n })}\n onClick={() => {\n if (typeof pageNumber === 'number') {\n onPageChange(pageNumber)\n if (pageNumber === lastPage && hasMore && fetchMore) {\n fetchMore()\n }\n }\n }}\n >\n {pageNumber}\n </li>\n )\n })}\n {hasMore && fetchMore ?(\n <li\n key={`page-has-more`}\n className='Layer__pagination-item Layer__pagination-arrow Layer__pagination-arrow--next'\n onClick={fetchMore}\n >\n ...\n </li>\n ) : null}\n <li\n key={`page-last`}\n className={classnames(\n 'Layer__pagination-item Layer__pagination-arrow Layer__pagination-arrow--next',\n {\n disabled: currentPage === lastPage,\n },\n )}\n onClick={() => onPageChange(currentPage + 1)}\n >\n <ChevronRight size={12} />\n </li>\n </ul>\n )\n}\n", "import { useMemo } from 'react'\nimport { range } from '../../utils/helpers'\n\nexport const DOTS = '...'\n\nexport interface UsePaginationProps {\n totalCount: number\n pageSize: number\n siblingCount?: number\n currentPage: number\n}\n\nexport type UsePaginationReturn = (string | number)[] | undefined\n\nexport const usePagination = ({\n totalCount,\n pageSize,\n siblingCount = 1,\n currentPage,\n}: UsePaginationProps): UsePaginationReturn => {\n const paginationRange = useMemo(() => {\n const totalPageCount = Math.ceil(totalCount / pageSize)\n const totalPageNumbers = siblingCount + 5\n\n if (totalPageNumbers >= totalPageCount) {\n return range(1, totalPageCount)\n }\n\n const leftSiblingIndex = Math.max(currentPage - siblingCount, 1)\n const rightSiblingIndex = Math.min(\n currentPage + siblingCount,\n totalPageCount,\n )\n const shouldShowLeftDots = leftSiblingIndex > 2\n const shouldShowRightDots = rightSiblingIndex < totalPageCount - 2\n\n const firstPageIndex = 1\n const lastPageIndex = totalPageCount\n\n if (!shouldShowLeftDots && shouldShowRightDots) {\n let leftItemCount = 3 + 2 * siblingCount\n let leftRange = range(1, leftItemCount)\n\n return [...leftRange, DOTS, totalPageCount]\n }\n\n if (shouldShowLeftDots && !shouldShowRightDots) {\n let rightItemCount = 3 + 2 * siblingCount\n let rightRange = range(\n totalPageCount - rightItemCount + 1,\n totalPageCount,\n )\n return [firstPageIndex, DOTS, ...rightRange]\n }\n\n if (shouldShowLeftDots && shouldShowRightDots) {\n let middleRange = range(leftSiblingIndex, rightSiblingIndex)\n return [firstPageIndex, DOTS, ...middleRange, DOTS, lastPageIndex]\n }\n }, [totalCount, pageSize, siblingCount, currentPage])\n\n return paginationRange\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ChevronLeft = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n width='18'\n height='18'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n >\n <path\n d='M11.25 13.5L6.75 9L11.25 4.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\nexport default ChevronLeft\n", "import React, { ChangeEvent, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport DownloadCloud from '../../icons/DownloadCloud'\nimport { DateRange, DisplayState } from '../../types'\nimport { getEarliestDateToBrowse } from '../../utils/business'\nimport { Button, ButtonVariant, RetryButton } from '../Button'\nimport { Header } from '../Container'\nimport { DatePicker } from '../DatePicker'\nimport { SyncingComponent } from '../SyncingComponent'\nimport { Tabs } from '../Tabs'\nimport { Toggle } from '../Toggle'\nimport { ToggleSize } from '../Toggle/Toggle'\nimport { Heading, HeadingSize } from '../Typography'\nimport { MobileComponentType } from './constants'\nimport classNames from 'classnames'\nimport { endOfMonth, startOfMonth } from 'date-fns'\n\nexport interface BankTransactionsHeaderProps {\n shiftStickyHeader: number\n asWidget?: boolean\n categorizedOnly?: boolean\n categorizeView?: boolean\n display?: DisplayState\n onCategorizationDisplayChange: (event: ChangeEvent<HTMLInputElement>) => void\n mobileComponent?: MobileComponentType\n withDatePicker?: boolean\n listView?: boolean\n dateRange?: DateRange\n isDataLoading?: boolean\n isSyncing?: boolean\n setDateRange?: (value: DateRange) => void\n stringOverrides?: BankTransactionsHeaderStringOverrides\n}\n\nexport interface BankTransactionsHeaderStringOverrides {\n header?: string\n downloadButton?: string\n}\n\nconst DownloadButton = ({\n downloadButtonTextOverride,\n iconOnly,\n}: {\n downloadButtonTextOverride?: string\n iconOnly?: boolean\n}) => {\n const { auth, businessId, apiUrl } = useLayerContext()\n const [requestFailed, setRequestFailed] = useState(false)\n const [isDownloading, setIsDownloading] = useState(false)\n const handleClick = async () => {\n setIsDownloading(true)\n const currentYear = new Date().getFullYear().toString()\n const getBankTransactionsCsv = Layer.getBankTransactionsCsv(\n apiUrl,\n auth.access_token,\n {\n params: {\n businessId: businessId,\n year: currentYear,\n },\n },\n )\n try {\n const result = await getBankTransactionsCsv()\n if (result?.data?.presignedUrl) {\n window.location.href = result.data.presignedUrl\n setRequestFailed(false)\n } else {\n setRequestFailed(true)\n }\n } catch (e) {\n setRequestFailed(true)\n } finally {\n setIsDownloading(false)\n }\n }\n\n return requestFailed ? (\n <RetryButton\n onClick={handleClick}\n className='Layer__download-retry-btn'\n error={'Approval failed. Check connection and retry in few seconds.'}\n disabled={isDownloading}\n iconOnly={iconOnly}\n >\n Retry\n </RetryButton>\n ) : (\n <Button\n variant={ButtonVariant.secondary}\n rightIcon={<DownloadCloud size={12} />}\n onClick={handleClick}\n disabled={isDownloading}\n iconAsPrimary={iconOnly}\n iconOnly={iconOnly}\n >\n {downloadButtonTextOverride || 'Download'}\n </Button>\n )\n}\n\nexport const BankTransactionsHeader = ({\n shiftStickyHeader,\n asWidget,\n categorizedOnly,\n categorizeView = true,\n display,\n onCategorizationDisplayChange,\n mobileComponent,\n withDatePicker,\n listView,\n dateRange,\n setDateRange,\n stringOverrides,\n isSyncing,\n}: BankTransactionsHeaderProps) => {\n const { business } = useLayerContext()\n\n return (\n <Header\n className={classNames(\n 'Layer__bank-transactions__header',\n withDatePicker && 'Layer__bank-transactions__header--with-date-picker',\n mobileComponent && listView\n ? 'Layer__bank-transactions__header--mobile'\n : undefined,\n )}\n style={{ top: shiftStickyHeader }}\n >\n <div className='Layer__bank-transactions__header__content'>\n <div className='Layer__bank-transactions__header__content-title'>\n <Heading\n className='Layer__bank-transactions__title'\n size={asWidget ? HeadingSize.secondary : HeadingSize.secondary}\n >\n {stringOverrides?.header || 'Transactions'}\n </Heading>\n {isSyncing && (\n <SyncingComponent\n timeSync={5}\n inProgress={true}\n hideContent={listView}\n />\n )}\n </div>\n {withDatePicker && dateRange && setDateRange ? (\n <DatePicker\n mode='monthPicker'\n selected={dateRange.startDate}\n onChange={date => {\n if (!Array.isArray(date)) {\n setDateRange({\n startDate: startOfMonth(date),\n endDate: endOfMonth(date),\n })\n }\n }}\n minDate={getEarliestDateToBrowse(business)}\n />\n ) : null}\n </div>\n <div className='Layer__header__actions-wrapper'>\n <div className='Layer__header__actions Layer__justify--space-between'>\n {!categorizedOnly && categorizeView && (\n <Toggle\n name='bank-transaction-display'\n size={\n mobileComponent === 'mobileList'\n ? ToggleSize.small\n : ToggleSize.medium\n }\n options={[\n { label: 'To Review', value: DisplayState.review },\n { label: 'Categorized', value: DisplayState.categorized },\n ]}\n selected={display}\n onChange={onCategorizationDisplayChange}\n />\n )}\n\n <DownloadButton\n downloadButtonTextOverride={stringOverrides?.downloadButton}\n iconOnly={listView}\n />\n </div>\n </div>\n </Header>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst DownloadCloud = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M6 12.75L9 15.75L12 12.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 9V15.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M15.66 13.5675C16.3121 13.109 16.801 12.4546 17.056 11.6994C17.3109 10.9441 17.3186 10.1273 17.0778 9.36737C16.837 8.60748 16.3604 7.94407 15.7171 7.47342C15.0737 7.00278 14.2971 6.74938 13.5 6.75H12.555C12.3294 5.87091 11.9074 5.05444 11.3206 4.36206C10.7338 3.66969 9.99762 3.11945 9.16742 2.75277C8.33721 2.38609 7.43464 2.21252 6.52766 2.24514C5.62067 2.27776 4.7329 2.51571 3.93118 2.94107C3.12946 3.36644 2.43468 3.96814 1.89915 4.70087C1.36362 5.43361 1.0013 6.27829 0.839456 7.17132C0.677613 8.06434 0.720468 8.98245 0.964796 9.85652C1.20912 10.7306 1.64856 11.5378 2.25001 12.2175'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\nexport default DownloadCloud\n", "import { Business } from '../types'\nimport { differenceInCalendarMonths, parseISO, startOfMonth } from 'date-fns'\n\nexport const getActivationDate = (business?: Business) => {\n try {\n if (business && business.activation_at) {\n return parseISO(business.activation_at)\n }\n\n return\n } catch (_err) {\n return\n }\n}\n\nexport const getEarliestDateToBrowse = (business?: Business) => {\n const activationDate = getActivationDate(business)\n\n if (activationDate) {\n return startOfMonth(activationDate)\n }\n\n return\n}\n\nexport const isDateAllowedToBrowse = (date: Date, business?: Business) => {\n if (!business || !date) {\n return true\n }\n\n const activationDate = getEarliestDateToBrowse(business)\n\n if (!activationDate) {\n return true\n }\n\n return differenceInCalendarMonths(startOfMonth(date), activationDate) >= 0\n}\n", "import React, { useEffect, useRef, useState } from 'react'\nimport ReactDatePicker from 'react-datepicker'\nimport { BREAKPOINTS } from '../../config/general'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { useSizeClass } from '../../hooks/useWindowSize'\nimport ChevronLeft from '../../icons/ChevronLeft'\nimport ChevronRight from '../../icons/ChevronRight'\nimport { Button, ButtonVariant } from '../Button'\nimport { DatePickerOptions } from './DatePickerOptions'\nimport classNames from 'classnames'\n\ninterface DatePickerProps {\n mode:\n | 'dayPicker'\n | 'dayRangePicker'\n | 'monthPicker'\n | 'monthRangePicker'\n | 'timePicker'\n selected: Date | [Date | null, Date | null]\n onChange: (date: Date | [Date, Date | null]) => void\n dateFormat?: string\n timeIntervals?: number\n timeCaption?: string\n placeholderText?: string\n options?: string[]\n wrapperClassName?: string\n calendarClassName?: string\n popperClassName?: string\n currentDateOption?: boolean\n minDate?: Date\n maxDate?: Date\n navigateArrows?: boolean\n}\n\nconst getDefaultRangeDate = (\n date: 'start' | 'end',\n mode: DatePickerProps['mode'],\n selected: Date | [Date | null, Date | null],\n) => {\n try {\n if (isRangeMode(mode) && selected) {\n if (date === 'end') {\n return (selected as [Date | null, Date | null])[1]\n }\n return (selected as [Date | null, Date | null])[0]\n }\n\n return null\n } catch (_err) {\n return null\n }\n}\n\nconst isRangeMode = (mode: DatePickerProps['mode']) =>\n mode === 'dayRangePicker' || mode === 'monthRangePicker'\n\nexport const DatePicker = ({\n selected,\n onChange,\n mode = 'dayPicker',\n dateFormat = mode === 'monthPicker' || mode === 'monthRangePicker'\n ? 'MMM, yyyy'\n : mode === 'timePicker'\n ? 'h:mm aa'\n : 'MMM d, yyyy',\n timeIntervals = 15,\n timeCaption,\n placeholderText,\n options = [],\n wrapperClassName,\n calendarClassName,\n popperClassName,\n minDate,\n maxDate = new Date(),\n currentDateOption = true,\n navigateArrows = mode === 'monthPicker',\n ...props\n}: DatePickerProps) => {\n const pickerRef = useRef<ReactDatePicker>(null)\n const [updatePickerDate, setPickerDate] = useState<boolean>(false)\n const [selectedDates, setSelectedDates] = useState<\n Date | [Date | null, Date | null] | null\n >(selected)\n\n const { isDesktop } = useSizeClass()\n\n const [startDate, setStartDate] = useState<Date | null>(\n getDefaultRangeDate('start', mode, selected) ?? new Date(),\n )\n const [endDate, setEndDate] = useState<Date | null>(\n getDefaultRangeDate('end', mode, selected),\n )\n\n useEffect(() => {\n try {\n setPickerDate(true)\n if (\n !isRangeMode(mode) &&\n (selected as Date | null)?.getTime() !==\n (selectedDates as Date | null)?.getTime()\n ) {\n setSelectedDates(selected)\n return\n }\n\n if (isRangeMode(mode) && Array.isArray(selected)) {\n if ((startDate as Date | null)?.getTime() !== selected[0]?.getTime()) {\n setStartDate(selected[0])\n }\n if ((endDate as Date | null)?.getTime() !== selected[1]?.getTime()) {\n setEndDate(selected[1])\n }\n }\n } catch (_err) {\n return\n }\n }, [selected])\n\n useEffect(() => {\n if (\n onChange &&\n (!isRangeMode(mode) || (isRangeMode(mode) && !updatePickerDate))\n ) {\n onChange(selectedDates as Date | [Date, Date])\n } else {\n setPickerDate(false)\n }\n }, [selectedDates])\n\n useEffect(() => {\n if (isRangeMode(mode)) {\n setSelectedDates([startDate, endDate])\n }\n }, [startDate, endDate])\n\n const wrapperClassNames = classNames(\n 'Layer__datepicker__wrapper',\n mode === 'timePicker' && 'Layer__datepicker__time__wrapper',\n navigateArrows && 'Layer__datepicker__wrapper--arrows',\n )\n\n const datePickerWrapperClassNames = classNames(\n 'Layer__datepicker',\n mode === 'timePicker' && 'Layer__datepicker__time',\n wrapperClassName,\n )\n const calendarClassNames = classNames(\n 'Layer__datepicker__calendar',\n calendarClassName,\n )\n const popperClassNames = classNames(\n 'Layer__datepicker__popper',\n mode === 'timePicker' && 'Layer__datepicker__time__popper',\n popperClassName,\n )\n\n const handleDateChange = (date: Date | [Date | null, Date | null]) => {\n if (isRangeMode(mode)) {\n const [start, end] = date as [Date | null, Date | null]\n setStartDate(start)\n setEndDate(end)\n return\n }\n\n setSelectedDates(date)\n }\n\n const isCurrentDate = () => {\n const currentDate = new Date()\n if (mode === 'dayPicker') {\n return (\n selectedDates instanceof Date &&\n selectedDates.toDateString() === currentDate.toDateString()\n )\n } else if (mode === 'monthPicker') {\n return (\n selectedDates instanceof Date &&\n selectedDates.getMonth() === currentDate.getMonth() &&\n selectedDates.getFullYear() === currentDate.getFullYear()\n )\n }\n return false\n }\n\n const setCurrentDate = () => {\n const currentDate = new Date()\n if (mode === 'dayPicker') {\n setSelectedDates(currentDate)\n } else if (mode === 'monthPicker') {\n setSelectedDates(\n new Date(currentDate.getFullYear(), currentDate.getMonth(), 1),\n )\n }\n }\n\n const isTodayOrAfter = Boolean(\n selectedDates instanceof Date && selectedDates >= new Date(),\n )\n\n const isBeforeMinDate = Boolean(\n minDate && selectedDates instanceof Date && selectedDates <= minDate,\n )\n\n const changeDate = (value: number) => {\n if (mode === 'dayPicker') {\n setSelectedDates(\n new Date(\n (selectedDates as Date).setDate(\n (selectedDates as Date).getDate() + value,\n ),\n ),\n )\n } else if (mode === 'monthPicker') {\n setSelectedDates(\n new Date(\n (selectedDates as Date).setMonth(\n (selectedDates as Date).getMonth() + value,\n ),\n ),\n )\n }\n }\n\n return (\n <div className={wrapperClassNames}>\n <ReactDatePicker\n ref={pickerRef}\n wrapperClassName={datePickerWrapperClassNames}\n startDate={isRangeMode(mode) ? startDate : undefined}\n endDate={isRangeMode(mode) ? endDate : undefined}\n selected={\n mode !== 'dayRangePicker' && mode !== 'monthRangePicker'\n ? (selectedDates as Date)\n : undefined\n }\n onChange={handleDateChange}\n calendarClassName={calendarClassNames}\n popperClassName={popperClassNames}\n enableTabLoop={false}\n popperPlacement='bottom-start'\n selectsRange={isRangeMode(mode)}\n showMonthYearPicker={\n mode === 'monthPicker' || mode === 'monthRangePicker'\n }\n dateFormat={dateFormat}\n renderDayContents={day => (\n <span className='Layer__datepicker__day-contents'>{day}</span>\n )}\n timeIntervals={timeIntervals}\n timeCaption={timeCaption}\n timeFormat='h mm aa'\n showTimeSelect={mode === 'timePicker'}\n showTimeSelectOnly={mode === 'timePicker'}\n minDate={minDate}\n maxDate={maxDate}\n withPortal={!isDesktop}\n onCalendarOpen={() => {\n if (!isDesktop) {\n setTimeout(() => {\n document\n .getElementById('Layer__datepicker__portal')\n ?.classList.remove('Layer__datepicker__portal--closed')\n document\n .getElementById('Layer__datepicker__portal')\n ?.classList.add('Layer__datepicker__portal--opened')\n }, 10)\n }\n }}\n onCalendarClose={() => {\n if (!isDesktop) {\n document\n .getElementById('Layer__datepicker__portal')\n ?.classList.add('Layer__datepicker__portal--closed')\n document\n .getElementById('Layer__datepicker__portal')\n ?.classList.remove('Layer__datepicker__portal--opened')\n }\n }}\n portalId='Layer__datepicker__portal'\n onFocus={e => (e.target.readOnly = true)}\n onInputClick={() => {\n if (pickerRef.current && !isDesktop) {\n pickerRef.current.setOpen(!pickerRef.current.isCalendarOpen)\n }\n }}\n {...props}\n >\n {mode === 'dayRangePicker' && (\n <DatePickerOptions\n options={options}\n setSelectedDate={setSelectedDates}\n />\n )}\n </ReactDatePicker>\n {navigateArrows && !isDesktop && (\n <>\n <Button\n aria-label='Previous Date'\n className={classNames(\n 'Layer__datepicker__prev-button',\n isBeforeMinDate && 'Layer__datepicker__button--disabled',\n )}\n onClick={() => changeDate(-1)}\n variant={ButtonVariant.secondary}\n disabled={isBeforeMinDate}\n >\n <ChevronLeft className='Layer__datepicker__button-icon' size={16} />\n </Button>\n <Button\n aria-label='Next Date'\n variant={ButtonVariant.secondary}\n className={classNames(\n 'Layer__datepicker__next-button',\n isTodayOrAfter\n ? 'Layer__datepicker__button--disabled'\n : undefined,\n )}\n onClick={() => changeDate(1)}\n disabled={isTodayOrAfter}\n >\n <ChevronRight\n className='Layer__datepicker__button-icon'\n size={16}\n />\n </Button>\n </>\n )}\n {currentDateOption &&\n (mode === 'dayPicker' || mode === 'monthPicker') && (\n <Button\n className='Layer__datepicker__current-button'\n onClick={setCurrentDate}\n variant={ButtonVariant.secondary}\n disabled={isCurrentDate()}\n >\n {mode === 'dayPicker' ? 'Today' : 'Current'}\n </Button>\n )}\n </div>\n )\n}\n", "import React from 'react'\nimport { TextButton } from '../Button'\nimport {\n endOfMonth,\n endOfQuarter,\n endOfYear,\n startOfMonth,\n startOfQuarter,\n startOfYear,\n subMonths,\n subQuarters,\n subYears,\n} from 'date-fns'\n\nexport const DatePickerOptions = ({\n options,\n setSelectedDate,\n}: {\n options: string[]\n setSelectedDate: (dates: [Date | null, Date | null]) => void\n}) => {\n let optionsComponents: React.ReactNode[] = []\n\n const getOptionComponent = (option: string) => {\n switch (option) {\n case 'this-month':\n return (\n <TextButton\n key={option}\n onClick={() => {\n setSelectedDate([\n startOfMonth(new Date()),\n endOfMonth(new Date()),\n ])\n }}\n >\n This month\n </TextButton>\n )\n case 'last-month':\n return (\n <TextButton\n key={option}\n onClick={() => {\n setSelectedDate([\n startOfMonth(subMonths(new Date(), 1)),\n endOfMonth(subMonths(new Date(), 1)),\n ])\n }}\n >\n Last month\n </TextButton>\n )\n case 'this-quarter':\n return (\n <TextButton\n key={option}\n onClick={() => {\n setSelectedDate([\n startOfQuarter(new Date()),\n endOfQuarter(new Date()),\n ])\n }}\n >\n This quarter\n </TextButton>\n )\n case 'last-quarter':\n return (\n <TextButton\n key={option}\n onClick={() => {\n const lastQuarter = subQuarters(new Date(), 1)\n setSelectedDate([\n startOfQuarter(lastQuarter),\n endOfQuarter(lastQuarter),\n ])\n }}\n >\n Last quarter\n </TextButton>\n )\n case 'this-year':\n return (\n <TextButton\n key={option}\n onClick={() => {\n setSelectedDate([startOfYear(new Date()), endOfYear(new Date())])\n }}\n >\n This year\n </TextButton>\n )\n case 'last-year':\n return (\n <TextButton\n key={option}\n onClick={() => {\n const lastYear = subYears(new Date(), 1)\n setSelectedDate([startOfYear(lastYear), endOfYear(lastYear)])\n }}\n >\n Last year\n </TextButton>\n )\n }\n return <></>\n }\n\n if (options.length === 0) {\n const allOptions = [\n 'this-month',\n 'last-month',\n 'this-quarter',\n 'last-quarter',\n 'this-year',\n 'last-year',\n ]\n allOptions.forEach(option => {\n optionsComponents.push(getOptionComponent(option))\n })\n } else {\n options.forEach(option => {\n optionsComponents.push(getOptionComponent(option))\n })\n }\n\n if (optionsComponents.length === 0) {\n return <></>\n }\n\n return (\n <div className='Layer__datepicker__popper__custom-footer'>\n {optionsComponents}\n </div>\n )\n}\n", "import React from 'react'\nimport InboxIcon from '../../icons/Inbox'\nimport { BankTransaction } from '../../types'\nimport { DataState, DataStateStatus } from '../DataState'\n\ninterface DataStatesProps {\n bankTransactions?: BankTransaction[]\n isLoading?: boolean\n isValidating?: boolean\n error?: unknown\n refetch: () => void\n editable: boolean\n}\n\nexport const DataStates = ({\n bankTransactions,\n isLoading,\n isValidating,\n error,\n refetch,\n editable,\n}: DataStatesProps) => {\n let title = editable\n ? 'You are up to date with transactions!'\n : 'You have no categorized transactions'\n let description = editable\n ? 'All uncategorized transaction will be displayed here'\n : 'All transaction will be displayed here once reviewed'\n\n const showRefreshButton = bankTransactions?.length\n\n return (\n <>\n {!isLoading &&\n !error &&\n (bankTransactions === undefined ||\n (bankTransactions !== undefined && bankTransactions.length === 0)) ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={isLoading ? DataStateStatus.info : DataStateStatus.allDone}\n title={title}\n description={description}\n onRefresh={showRefreshButton ? refetch : undefined}\n isLoading={isValidating}\n icon={!editable ? <InboxIcon /> : undefined}\n />\n </div>\n ) : null}\n\n {!isLoading && error ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={refetch}\n isLoading={isValidating}\n />\n </div>\n ) : null}\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Inbox = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M16.5 9H12L10.5 11.25H7.5L6 9H1.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M4.0875 3.8325L1.5 9V13.5C1.5 13.8978 1.65804 14.2794 1.93934 14.5607C2.22064 14.842 2.60218 15 3 15H15C15.3978 15 15.7794 14.842 16.0607 14.5607C16.342 14.2794 16.5 13.8978 16.5 13.5V9L13.9125 3.8325C13.7883 3.58259 13.5969 3.37228 13.3597 3.22521C13.1226 3.07814 12.8491 3.00015 12.57 3H5.43C5.15094 3.00015 4.87745 3.07814 4.64028 3.22521C4.40312 3.37228 4.21168 3.58259 4.0875 3.8325Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Inbox\n", "import React from \"react\";\nimport { useQuickbooks } from \"../../hooks/useQuickbooks\";\n\nconst Quickbooks = () => {\n const {\n syncFromQuickbooks,\n isSyncingFromQuickbooks,\n quickbooksIsLinked,\n linkQuickbooks,\n unlinkQuickbooks,\n } = useQuickbooks();\n\n return (\n <div>\n <div>\n Quickbooks OAuth connection status:{\" \"}\n {quickbooksIsLinked === undefined\n ? \"\"\n : quickbooksIsLinked\n ? \"established\"\n : \"not connected\"}\n </div>\n <br />\n {quickbooksIsLinked === null && \"Loading...\"}\n {quickbooksIsLinked === false && (\n <button\n onClick={async () => {\n const authorizationUrl = await linkQuickbooks();\n window.location.href = authorizationUrl;\n }}\n >\n Link Quickbooks\n </button>\n )}\n {quickbooksIsLinked === true &&\n (isSyncingFromQuickbooks ? (\n \"Syncing data from Quickbooks...\"\n ) : (\n <div>\n <button onClick={syncFromQuickbooks}>Sync Quickbooks</button>\n <button onClick={unlinkQuickbooks}>Unlink Quickbooks</button>\n </div>\n ))}\n </div>\n );\n};\n\nexport { Quickbooks };\n", "import { useEffect, useRef, useState } from \"react\";\nimport { useLayerContext } from \"../../contexts/LayerContext\";\nimport { Layer } from \"../../api/layer\";\n\ntype UseQuickbooks = () => {\n linkQuickbooks: () => Promise<string>;\n unlinkQuickbooks: () => void;\n syncFromQuickbooks: () => void;\n isSyncingFromQuickbooks: boolean;\n quickbooksIsLinked: boolean | null;\n};\n\nconst DEBUG = true;\n\nexport const useQuickbooks: UseQuickbooks = () => {\n const { auth, businessId, apiUrl } = useLayerContext();\n const [isSyncingFromQuickbooks, setIsSyncingFromQuickbooks] =\n useState<boolean>(false);\n const [quickbooksIsLinked, setQuickbooksIsLinked] = useState<boolean | null>(\n null\n );\n const syncStatusIntervalRef = useRef<NodeJS.Timeout | null>(null);\n\n // Poll the server to determine when the Quickbooks sync is complete\n useEffect(() => {\n if (isSyncingFromQuickbooks && syncStatusIntervalRef.current === null) {\n const interval = setInterval(() => fetchIsSyncingFromQuickbooks(), 2000);\n syncStatusIntervalRef.current = interval;\n return () => clearInterval(interval);\n } else if (!isSyncingFromQuickbooks && syncStatusIntervalRef.current) {\n clearInterval(syncStatusIntervalRef.current);\n syncStatusIntervalRef.current = null;\n }\n }, [isSyncingFromQuickbooks]);\n\n // Determine whether there exists an active Quickbooks connection or not\n useEffect(() => {\n fetchQuickbooksConnectionStatus();\n }, []);\n\n const fetchQuickbooksConnectionStatus = async () => {\n const isConnected = (\n await Layer.statusOfQuickbooksConnection(apiUrl, auth.access_token, {\n params: { businessId },\n })()\n ).data.is_connected;\n setQuickbooksIsLinked(isConnected);\n };\n\n const syncFromQuickbooks = () => {\n DEBUG && console.log(\"Triggering sync from Quickbooks...\");\n setIsSyncingFromQuickbooks(true);\n try {\n Layer.syncFromQuickbooks(apiUrl, auth.access_token, {\n params: { businessId },\n });\n } catch {\n setIsSyncingFromQuickbooks(false);\n }\n };\n\n const fetchIsSyncingFromQuickbooks = async () => {\n DEBUG && console.log(\"Fetching status of sync from Quickbooks...\");\n const isSyncing = (\n await Layer.statusOfSyncFromQuickbooks(apiUrl, auth.access_token, {\n params: { businessId },\n })()\n ).data.is_syncing;\n setIsSyncingFromQuickbooks(isSyncing);\n };\n\n const linkQuickbooks = async () => {\n const res = await Layer.initQuickbooksOAuth(apiUrl, auth.access_token, {\n params: { businessId },\n });\n\n return res.data.redirect_url;\n };\n\n const unlinkQuickbooks = async () => {\n await Layer.unlinkQuickbooksConnection(apiUrl, auth.access_token, {\n params: { businessId },\n });\n fetchQuickbooksConnectionStatus();\n };\n\n return {\n isSyncingFromQuickbooks,\n syncFromQuickbooks,\n quickbooksIsLinked,\n linkQuickbooks,\n unlinkQuickbooks,\n };\n};\n", "import React, { PropsWithChildren, createContext } from 'react'\nimport { useProfitAndLoss } from '../../hooks/useProfitAndLoss'\nimport { ReportingBasis } from '../../types'\nimport { Container } from '../Container'\nimport { ProfitAndLossChart } from '../ProfitAndLossChart'\nimport { ProfitAndLossDatePicker } from '../ProfitAndLossDatePicker'\nimport { ProfitAndLossDetailedCharts } from '../ProfitAndLossDetailedCharts'\nimport { ProfitAndLossSummaries } from '../ProfitAndLossSummaries'\nimport { ProfitAndLossTable } from '../ProfitAndLossTable'\nimport { endOfMonth, startOfMonth } from 'date-fns'\n\ntype PNLContextType = ReturnType<typeof useProfitAndLoss>\nconst PNLContext = createContext<PNLContextType>({\n data: undefined,\n filteredDataRevenue: [],\n filteredTotalRevenue: undefined,\n filteredDataExpenses: [],\n filteredTotalExpenses: undefined,\n isLoading: true,\n isValidating: false,\n error: undefined,\n dateRange: {\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n },\n changeDateRange: () => {},\n refetch: () => {},\n sidebarScope: undefined,\n setSidebarScope: () => {},\n sortBy: () => {},\n setFilterTypes: () => {},\n filters: {\n expenses: undefined,\n revenue: undefined,\n },\n})\n\ntype Props = PropsWithChildren & {\n tagFilter?: {\n key: string\n values: string[]\n }\n reportingBasis?: ReportingBasis\n asContainer?: boolean\n}\n\nconst ProfitAndLoss = ({\n children,\n tagFilter,\n reportingBasis,\n asContainer = true,\n}: Props) => {\n const contextData = useProfitAndLoss({ tagFilter, reportingBasis })\n\n return (\n <PNLContext.Provider value={contextData}>\n {asContainer ? (\n <Container name='profit-and-loss'>{children}</Container>\n ) : (\n children\n )}\n </PNLContext.Provider>\n )\n}\n\nProfitAndLoss.Chart = ProfitAndLossChart\nProfitAndLoss.Context = PNLContext\nProfitAndLoss.DatePicker = ProfitAndLossDatePicker\nProfitAndLoss.Summaries = ProfitAndLossSummaries\nProfitAndLoss.Table = ProfitAndLossTable\nProfitAndLoss.DetailedCharts = ProfitAndLossDetailedCharts\nexport { ProfitAndLoss }\n", "import { useMemo, useState } from 'react'\nimport {\n ProfitAndLoss,\n DateRange,\n ReportingBasis,\n SortDirection,\n} from '../../types'\nimport { LineBaseItem } from '../../types/line_item'\nimport {\n collectExpensesItems,\n collectRevenueItems,\n applyShare,\n} from '../../utils/profitAndLossUtils'\nimport { useProfitAndLossQuery } from './useProfitAndLossQuery'\nimport { startOfMonth, endOfMonth } from 'date-fns'\n\nexport type Scope = 'expenses' | 'revenue'\n\nexport type SidebarScope = Scope | undefined\n\ntype Props = {\n startDate?: Date\n endDate?: Date\n tagFilter?: {\n key: string\n values: string[]\n }\n reportingBasis?: ReportingBasis\n}\n\ntype ProfitAndLossFilter = {\n sortBy?: string\n sortDirection?: SortDirection\n types?: string[]\n}\n\nexport type ProfitAndLossFilters = Record<\n Scope,\n ProfitAndLossFilter | undefined\n>\n\ntype UseProfitAndLoss = (props?: Props) => {\n data: ProfitAndLoss | undefined\n filteredDataRevenue: LineBaseItem[]\n filteredTotalRevenue?: number\n filteredDataExpenses: LineBaseItem[]\n filteredTotalExpenses?: number\n isLoading: boolean\n isValidating: boolean\n error: unknown\n dateRange: DateRange\n changeDateRange: (dateRange: Partial<DateRange>) => void\n refetch: () => void\n sidebarScope: SidebarScope\n setSidebarScope: (view: SidebarScope) => void\n filters: ProfitAndLossFilters\n sortBy: (scope: Scope, field: string, direction?: SortDirection) => void\n setFilterTypes: (scope: Scope, types: string[]) => void\n}\n\nexport const useProfitAndLoss: UseProfitAndLoss = (\n {\n startDate: initialStartDate,\n endDate: initialEndDate,\n tagFilter,\n reportingBasis,\n }: Props = {\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n },\n) => {\n const [startDate, setStartDate] = useState(\n initialStartDate || startOfMonth(Date.now()),\n )\n const [endDate, setEndDate] = useState(\n initialEndDate || endOfMonth(Date.now()),\n )\n const [filters, setFilters] = useState<ProfitAndLossFilters>({\n expenses: undefined,\n revenue: undefined,\n })\n\n const [sidebarScope, setSidebarScope] = useState<SidebarScope>(undefined)\n\n const { data, isLoading, isValidating, error, refetch } =\n useProfitAndLossQuery({\n startDate,\n endDate,\n tagFilter,\n reportingBasis,\n })\n\n const changeDateRange = ({\n startDate: newStartDate,\n endDate: newEndDate,\n }: Partial<DateRange>) => {\n newStartDate && setStartDate(newStartDate)\n newEndDate && setEndDate(newEndDate)\n }\n\n const sortBy = (scope: Scope, field: string, direction?: SortDirection) => {\n setFilters({\n ...filters,\n [scope]: {\n ...filters[scope],\n sortBy: field,\n sortDirection:\n direction ?? filters[scope]?.sortDirection === 'desc'\n ? 'asc'\n : 'desc',\n },\n })\n }\n\n const setFilterTypes = (scope: Scope, types: string[]) => {\n setFilters({\n ...filters,\n [scope]: {\n ...filters[scope],\n types,\n },\n })\n }\n\n const { filteredDataRevenue, filteredTotalRevenue } = useMemo(() => {\n if (!data) {\n return { filteredDataRevenue: [], filteredTotalRevenue: undefined }\n }\n const items = collectRevenueItems(data)\n const filtered = items.map(x => {\n if (\n filters['revenue']?.types &&\n filters['revenue']!.types!.length > 0 &&\n !filters['revenue']?.types?.includes(x.type)\n ) {\n return {\n ...x,\n hidden: true,\n }\n }\n\n return x\n })\n\n const sorted = filtered.sort((a, b) => {\n switch (filters['revenue']?.sortBy) {\n case 'category':\n if (filters['revenue']?.sortDirection === 'asc') {\n return a.display_name.localeCompare(b.display_name)\n }\n return b.display_name.localeCompare(a.display_name)\n\n case 'type':\n if (filters['revenue']?.sortDirection === 'asc') {\n return a.type.localeCompare(b.type)\n }\n return b.type.localeCompare(a.type)\n\n default:\n if (filters['revenue']?.sortDirection === 'asc') {\n return a.value - b.value\n }\n return b.value - a.value\n }\n })\n const total = sorted\n .filter(x => !x.hidden)\n .reduce((x, { value }) => x + value, 0)\n const withShare = applyShare(sorted, total)\n\n return { filteredDataRevenue: withShare, filteredTotalRevenue: total }\n }, [data, startDate, filters, sidebarScope])\n\n const { filteredDataExpenses, filteredTotalExpenses } = useMemo(() => {\n if (!data) {\n return { filteredDataExpenses: [], filteredTotalExpenses: undefined }\n }\n const items = collectExpensesItems(data)\n const filtered = items.map(x => {\n if (\n filters['expenses']?.types &&\n filters['expenses']!.types!.length > 0 &&\n !filters['expenses']?.types?.includes(x.type)\n ) {\n return {\n ...x,\n hidden: true,\n }\n }\n\n return x\n })\n const sorted = filtered.sort((a, b) => {\n switch (filters['expenses']?.sortBy) {\n case 'category':\n if (filters['expenses']?.sortDirection === 'asc') {\n return a.display_name.localeCompare(b.display_name)\n }\n return b.display_name.localeCompare(a.display_name)\n\n case 'type':\n if (filters['expenses']?.sortDirection === 'asc') {\n return a.type.localeCompare(b.type)\n }\n return b.type.localeCompare(a.type)\n\n default:\n if (filters['expenses']?.sortDirection === 'asc') {\n return a.value - b.value\n }\n return b.value - a.value\n }\n })\n const total = sorted\n .filter(x => !x.hidden)\n .reduce((x, { value }) => x + value, 0)\n const withShare = applyShare(sorted, total)\n\n return { filteredDataExpenses: withShare, filteredTotalExpenses: total }\n }, [data, startDate, filters, sidebarScope])\n\n return {\n data,\n filteredDataRevenue,\n filteredTotalRevenue,\n filteredDataExpenses,\n filteredTotalExpenses,\n isLoading,\n isValidating,\n error: error,\n dateRange: { startDate, endDate },\n refetch,\n changeDateRange,\n sidebarScope,\n setSidebarScope,\n sortBy,\n filters,\n setFilterTypes,\n }\n}\n", "import { SidebarScope } from '../hooks/useProfitAndLoss/useProfitAndLoss'\nimport { LineItem, LineBaseItem } from '../types/line_item'\nimport { ProfitAndLoss } from '../types/profit_and_loss'\n\nconst doesLineItemQualifies = (item: LineItem) => {\n return !(\n item.is_contra ||\n item.value === undefined ||\n item.value === null ||\n isNaN(item.value) ||\n item.value === -Infinity ||\n item.value === Infinity ||\n item.value < 0\n )\n}\n\nconst collectSubItems = (type: string, item?: LineItem | null) => {\n if (!item) {\n return []\n }\n\n const items: LineBaseItem[] = []\n\n item?.line_items?.forEach(item => {\n if (doesLineItemQualifies(item)) {\n items.push({\n name: item.name,\n display_name: item.display_name,\n value: item.value || 0,\n type,\n })\n }\n })\n\n return items\n}\n\nexport const collectExpensesItems = (data: ProfitAndLoss) => {\n const cogs = collectSubItems('Cost of Goods Sold', data.cost_of_goods_sold)\n const expenses = collectSubItems('Operating Expenses', data.expenses)\n const taxes = collectSubItems('Taxes & Licenses', data.taxes)\n\n return ([] as LineBaseItem[]).concat(cogs).concat(expenses).concat(taxes)\n}\n\nexport const collectRevenueItems = (data: ProfitAndLoss) => {\n const income = collectSubItems('Income', data.income)\n\n return ([] as LineBaseItem[]).concat(income)\n}\n\nexport const humanizeTitle = (sidebarView: SidebarScope) => {\n switch (sidebarView) {\n case 'expenses':\n return 'Expenses'\n case 'revenue':\n return 'Revenue'\n default:\n return 'Profit & Loss'\n }\n}\n\nexport const applyShare = (\n items: LineBaseItem[],\n total: number,\n): LineBaseItem[] => {\n return items.map(item => {\n if (total === 0) {\n return item\n }\n\n return {\n ...item,\n share: item.value / total,\n }\n })\n}\n", "import { useEffect } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { ProfitAndLoss, ReportingBasis } from '../../types'\nimport { DataModel } from '../../types/general'\nimport { startOfMonth, endOfMonth, formatISO } from 'date-fns'\nimport useSWR from 'swr'\n\ntype UseProfitAndLossQueryProps = {\n startDate: Date\n endDate: Date\n tagFilter?: {\n key: string\n values: string[]\n }\n reportingBasis?: ReportingBasis\n}\n\ntype UseProfitAndLossQueryReturn = (props?: UseProfitAndLossQueryProps) => {\n data?: ProfitAndLoss\n isLoading: boolean\n isValidating: boolean\n error: any\n refetch: () => void\n startDate: Date\n endDate: Date\n}\n\nexport const useProfitAndLossQuery: UseProfitAndLossQueryReturn = (\n {\n startDate,\n endDate,\n tagFilter,\n reportingBasis,\n }: UseProfitAndLossQueryProps = {\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n },\n) => {\n const { auth, businessId, apiUrl, syncTimestamps, read, hasBeenTouched } =\n useLayerContext()\n\n const queryKey =\n businessId &&\n startDate &&\n endDate &&\n auth?.access_token &&\n `profit-and-loss-${businessId}-${startDate.valueOf()}-${endDate.valueOf()}-${tagFilter?.key}-${tagFilter?.values?.join(\n ',',\n )}-${reportingBasis}`\n\n const {\n data: rawData,\n isLoading,\n isValidating,\n error: rawError,\n mutate,\n } = useSWR(\n queryKey,\n Layer.getProfitAndLoss(apiUrl, auth?.access_token, {\n params: {\n businessId,\n startDate: formatISO(startDate.valueOf()),\n endDate: formatISO(endDate.valueOf()),\n tagKey: tagFilter?.key,\n tagValues: tagFilter?.values?.join(','),\n reportingBasis,\n },\n }),\n )\n\n const refetch = () => {\n mutate()\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.PROFIT_AND_LOSS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps, startDate, endDate, tagFilter, reportingBasis])\n\n return {\n startDate,\n endDate,\n data: rawData?.data,\n isLoading,\n isValidating,\n error: rawError,\n refetch,\n }\n}\n", "import React, { useContext, useEffect, useMemo, useState } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport {\n ProfitAndLossSummaryData,\n useProfitAndLossLTM,\n} from '../../hooks/useProfitAndLoss/useProfitAndLossLTM'\nimport { centsToDollars } from '../../models/Money'\nimport { isDateAllowedToBrowse } from '../../utils/business'\nimport { ProfitAndLoss as PNL } from '../ProfitAndLoss'\nimport { Text } from '../Typography'\nimport { Indicator } from './Indicator'\nimport classNames from 'classnames'\nimport {\n add,\n differenceInMonths,\n endOfMonth,\n format,\n startOfMonth,\n sub,\n} from 'date-fns'\nimport {\n XAxis,\n Cell,\n Bar,\n LabelList,\n CartesianGrid,\n Legend,\n ResponsiveContainer,\n Tooltip,\n TooltipProps,\n Rectangle,\n YAxis,\n Line,\n ComposedChart,\n ReferenceLine,\n} from 'recharts'\nimport { CategoricalChartFunc } from 'recharts/types/chart/generateCategoricalChart'\nimport { Props as LegendProps } from 'recharts/types/component/DefaultLegendContent'\n\nconst getChartWindow = ({\n chartWindow,\n currentYear,\n currentMonth,\n}: {\n chartWindow: { start: Date; end: Date }\n currentYear: number\n currentMonth: number\n}) => {\n const today = startOfMonth(Date.now())\n const yearAgo = sub(today, { months: 11 })\n const current = startOfMonth(new Date(currentYear, currentMonth - 1, 1))\n\n if (\n differenceInMonths(startOfMonth(chartWindow.start), current) < 0 &&\n differenceInMonths(startOfMonth(chartWindow.end), current) > 1\n ) {\n return chartWindow\n }\n\n if (differenceInMonths(startOfMonth(chartWindow.start), current) === 0) {\n return {\n start: startOfMonth(sub(current, { months: 1 })),\n end: endOfMonth(add(current, { months: 11 })),\n }\n }\n\n if (\n differenceInMonths(endOfMonth(chartWindow.end), endOfMonth(current)) ===\n 1 &&\n differenceInMonths(today, current) >= 1\n ) {\n return {\n start: startOfMonth(sub(current, { months: 10 })),\n end: endOfMonth(add(current, { months: 2 })),\n }\n }\n\n if (\n differenceInMonths(current, startOfMonth(chartWindow.end)) === 0 &&\n differenceInMonths(current, startOfMonth(today)) > 0\n ) {\n return {\n start: startOfMonth(sub(current, { months: 11 })),\n end: endOfMonth(add(current, { months: 1 })),\n }\n }\n\n if (current >= yearAgo) {\n return {\n start: startOfMonth(yearAgo),\n end: endOfMonth(today),\n }\n }\n\n if (Number(current) > Number(chartWindow.end)) {\n return {\n start: startOfMonth(sub(current, { months: 12 })),\n end: endOfMonth(current),\n }\n }\n\n if (differenceInMonths(current, startOfMonth(chartWindow.start)) < 0) {\n return {\n start: startOfMonth(current),\n end: endOfMonth(add(current, { months: 11 })),\n }\n }\n\n return chartWindow\n}\n\nconst getLoadingValue = (data?: ProfitAndLossSummaryData[]) => {\n if (!data) {\n return 10000\n }\n\n let max = 0\n\n data.forEach(x => {\n const current = Math.max(\n Math.abs(x.income),\n Math.abs(Math.abs((x?.income || 0) - (x?.netProfit || 0))),\n )\n if (current > max) {\n max = current\n }\n })\n\n return max === 0 ? 10000 : max * 0.6\n}\n\nexport interface Props {\n forceRerenderOnDataChange?: boolean\n}\n\nexport const ProfitAndLossChart = ({\n forceRerenderOnDataChange = false,\n}: Props) => {\n const [compactView, setCompactView] = useState(false)\n const barSize = compactView ? 10 : 20\n\n const { getColor, business } = useLayerContext()\n const { changeDateRange, dateRange } = useContext(PNL.Context)\n const [localDateRange, setLocalDateRange] = useState(dateRange)\n const [customCursorSize, setCustomCursorSize] = useState({\n width: 0,\n height: 0,\n x: 0,\n })\n const [barAnimActive, setBarAnimActive] = useState(true)\n const [chartWindow, setChartWindow] = useState({\n start: startOfMonth(sub(Date.now(), { months: 11 })),\n end: endOfMonth(Date.now()),\n })\n\n const selectionMonth = useMemo(\n () => ({\n year: localDateRange.startDate.getFullYear(),\n month: localDateRange.startDate.getMonth(),\n }),\n [localDateRange],\n )\n\n useEffect(() => {\n if (\n Number(dateRange.startDate) !== Number(localDateRange.startDate) ||\n Number(dateRange.endDate) !== Number(localDateRange.endDate)\n ) {\n setLocalDateRange(dateRange)\n }\n }, [dateRange])\n\n const { data, loaded, pullData } = useProfitAndLossLTM({\n currentDate: startOfMonth(Date.now()),\n })\n\n const loadingValue = useMemo(() => getLoadingValue(data), [data])\n\n useEffect(() => {\n if (loaded === 'complete' && data) {\n const foundCurrent = data.find(\n x =>\n Number(startOfMonth(new Date(x.year, x.month - 1, 1))) >=\n Number(localDateRange.startDate) &&\n Number(startOfMonth(new Date(x.year, x.month - 1, 1))) <\n Number(localDateRange.endDate),\n )\n\n if (!foundCurrent) {\n const newDate = startOfMonth(localDateRange.startDate)\n pullData(newDate)\n return\n }\n\n const foundBefore = data.find(\n x =>\n Number(startOfMonth(new Date(x.year, x.month - 1, 1))) >=\n Number(sub(localDateRange.startDate, { months: 1 })) &&\n Number(startOfMonth(new Date(x.year, x.month - 1, 1))) <\n Number(sub(localDateRange.endDate, { months: 1 })),\n )\n\n if (!foundBefore) {\n const newDate = startOfMonth(\n sub(localDateRange.startDate, { months: 1 }),\n )\n pullData(newDate)\n }\n }\n }, [localDateRange])\n\n useEffect(() => {\n const newChartWindow = getChartWindow({\n chartWindow,\n currentYear: localDateRange.startDate.getFullYear(),\n currentMonth: localDateRange.startDate.getMonth() + 1,\n })\n\n if (\n Number(newChartWindow.start) !== Number(chartWindow.start) ||\n Number(newChartWindow.end) !== Number(chartWindow.end)\n ) {\n setChartWindow(newChartWindow)\n }\n }, [localDateRange])\n\n useEffect(() => {\n if (loaded === 'complete') {\n setTimeout(() => {\n setBarAnimActive(false)\n }, 2000)\n }\n }, [loaded])\n\n const getMonthName = (pnl: ProfitAndLossSummaryData | undefined) =>\n pnl\n ? format(\n new Date(pnl.year, pnl.month - 1, 1),\n compactView ? 'LLLLL' : 'LLL',\n )\n : ''\n\n const summarizePnL = (pnl: ProfitAndLossSummaryData | undefined) => ({\n name: getMonthName(pnl),\n revenue: pnl?.income || 0,\n revenueUncategorized: pnl?.uncategorizedInflows || 0,\n expenses: -(pnl?.totalExpenses || 0),\n expensesUncategorized: -(pnl?.uncategorizedOutflows || 0),\n totalExpensesInverse: pnl?.totalExpensesInverse || 0,\n uncategorizedOutflowsInverse: pnl?.uncategorizedOutflowsInverse || 0,\n netProfit: pnl?.netProfit || 0,\n selected:\n !!pnl &&\n pnl.month === selectionMonth.month + 1 &&\n pnl.year === selectionMonth.year,\n year: pnl?.year,\n month: pnl?.month,\n base: 0,\n loading: pnl?.isLoading ? loadingValue : 0,\n loadingExpenses: pnl?.isLoading ? -loadingValue : 0,\n })\n\n const theData = useMemo(() => {\n if (loaded !== 'complete') {\n const loadingData = []\n const today = Date.now()\n for (let i = 11; i >= 0; i--) {\n const currentDate = sub(today, { months: i })\n loadingData.push({\n name: format(currentDate, compactView ? 'LLLLL' : 'LLL'),\n revenue: 0,\n revenueUncategorized: 0,\n totalExpensesInverse: 0,\n uncategorizedOutflowsInverse: 0,\n expenses: 0,\n expensesUncategorized: 0,\n netProfit: 0,\n selected: false,\n year: currentDate.getFullYear(),\n month: currentDate.getMonth() + 1,\n loading: 1000 * Math.pow(-1, i + 1) * (((i + 1) % 12) + 1) + 90000,\n loadingExpenses:\n -1000 * Math.pow(-1, i + 1) * (((i + 1) % 2) + 1) - 90000,\n base: 0,\n })\n }\n return loadingData\n }\n\n return data\n ?.map(x => {\n const totalExpenses = x.totalExpenses || 0\n if (totalExpenses < 0 || x.uncategorizedOutflows < 0) {\n return {\n ...x,\n totalExpenses: totalExpenses < 0 ? 0 : totalExpenses,\n uncategorizedOutflows:\n x.uncategorizedOutflows < 0 ? 0 : x.uncategorizedOutflows,\n totalExpensesInverse: totalExpenses < 0 ? -totalExpenses : 0,\n uncategorizedOutflowsInverse:\n x.uncategorizedOutflows < 0 ? -x.uncategorizedOutflows : 0,\n }\n }\n\n return x\n })\n ?.filter(\n x =>\n differenceInMonths(\n startOfMonth(new Date(x.year, x.month - 1, 1)),\n chartWindow.start,\n ) >= 0 &&\n differenceInMonths(\n startOfMonth(new Date(x.year, x.month - 1, 1)),\n chartWindow.start,\n ) < 12 &&\n differenceInMonths(\n chartWindow.end,\n startOfMonth(new Date(x.year, x.month - 1, 1)),\n ) >= 0 &&\n differenceInMonths(\n chartWindow.end,\n startOfMonth(new Date(x.year, x.month - 1, 1)),\n ) <= 12,\n )\n .map(x => summarizePnL(x))\n }, [selectionMonth, chartWindow, data, loaded, compactView])\n\n const onClick: CategoricalChartFunc = ({ activePayload }) => {\n if (activePayload && activePayload.length > 0) {\n const { year, month } = activePayload[0].payload\n const isMonthAllowed = isDateAllowedToBrowse(\n new Date(year, month - 1, 1),\n business,\n )\n\n if (isMonthAllowed) {\n changeDateRange({\n startDate: new Date(year, month - 1, 1),\n endDate: endOfMonth(new Date(year, month - 1, 1)),\n })\n }\n }\n }\n\n const CustomTooltip = ({ active, payload }: TooltipProps<number, string>) => {\n if (active && payload && payload.length) {\n const netProfit = payload.find(x => x.dataKey === 'netProfit')?.value ?? 0\n const netProfitClass =\n netProfit > 0 ? 'positive' : netProfit < 0 ? 'negative' : ''\n const revenue = payload.find(x => x.dataKey === 'revenue')?.value ?? 0\n const expenses = payload.find(x => x.dataKey === 'expenses')?.value ?? 0\n\n return (\n <div className='Layer__chart__tooltip'>\n {loaded !== 'complete' ? (\n <Text>Loading...</Text>\n ) : (\n <ul className='Layer__chart__tooltip-list'>\n <li>\n <label className='Layer__chart__tooltip-label'>Revenue</label>\n <span className='Layer__chart__tooltip-value'>\n ${centsToDollars(revenue)}\n </span>\n </li>\n <li>\n <label className='Layer__chart__tooltip-label'>Expenses</label>\n <span className='Layer__chart__tooltip-value'>\n ${centsToDollars(Math.abs(expenses))}\n </span>\n </li>\n <li>\n <label className='Layer__chart__tooltip-label'>\n Net Profit\n </label>\n <span\n className={`Layer__chart__tooltip-value ${netProfitClass}`}\n >\n ${centsToDollars(netProfit)}\n </span>\n </li>\n </ul>\n )}\n </div>\n )\n }\n\n return null\n }\n\n const formatYAxisValue = (value?: string | number) => {\n if (!value) {\n return value\n }\n\n try {\n let suffix = ''\n const base = Number(value) / 100\n let val = base\n\n if (Math.abs(base) >= 1000000000) {\n suffix = 'B'\n val = base / 1000000000\n } else if (Math.abs(base) >= 1000000) {\n suffix = 'M'\n val = base / 1000000\n } else if (Math.abs(base) >= 1000) {\n suffix = 'k'\n val = base / 1000\n }\n return `${val}${suffix}`\n } catch (_err) {\n return value\n }\n }\n\n const renderLegend = (props: LegendProps) => {\n return (\n <ul className='Layer__chart-legend-list'>\n {props.payload?.map((entry, idx) => {\n if (entry.id === 'UncategorizedLegend') {\n return (\n <li\n key={`legend-item-${idx}`}\n className={`recharts-legend-item legend-item-${idx}`}\n >\n <svg\n className='recharts-surface'\n width='15'\n height='15'\n viewBox='0 0 15 15'\n style={{\n display: 'inline-block',\n verticalAlign: 'middle',\n marginRight: 4,\n }}\n >\n <circle\n cx='7'\n cy='7'\n r='7'\n fill='url(#layer-bar-stripe-pattern-dark)'\n />\n </svg>\n {entry.value}\n </li>\n )\n }\n return (\n <li\n key={`legend-item-${idx}`}\n className={`recharts-legend-item legend-item-${idx}`}\n >\n <svg\n className='recharts-surface'\n width='15'\n height='15'\n viewBox='0 0 15 15'\n style={{\n display: 'inline-block',\n verticalAlign: 'middle',\n marginRight: 4,\n }}\n >\n <circle cx='7' cy='7' r='7' />\n </svg>\n {entry.value}\n </li>\n )\n })}\n </ul>\n )\n }\n\n const CustomizedYTick = (props: any) => {\n return (\n <text {...props} className='Layer__chart_y-axis-tick'>\n <tspan dy='0.355em'>{formatYAxisValue(props.payload.value)}</tspan>\n </text>\n )\n }\n\n const CustomizedCursor = (props: any) => {\n const { points } = props\n const { width, height } = customCursorSize\n\n return (\n <Rectangle\n fill='#F7F8FA'\n stroke='none'\n x={points[0].x - width / 2}\n y={points[0].y}\n width={width}\n height={height}\n radius={6}\n className='Layer__chart__tooltip-cursor'\n />\n )\n }\n\n const [animateFrom, setAnimateFrom] = useState(-1)\n\n return (\n <ResponsiveContainer\n key={forceRerenderOnDataChange ? JSON.stringify(theData) : 'pnl-chart'}\n className={classNames(\n 'Layer__chart-container',\n loaded !== 'complete' && 'Layer__chart-container--loading',\n )}\n width='100%'\n height='100%'\n onResize={width => {\n if (width && width < 620 && !compactView) {\n setCompactView(true)\n return\n }\n\n if (width && width >= 620 && compactView) {\n setCompactView(false)\n return\n }\n }}\n >\n <ComposedChart\n margin={{ left: 12, right: 12, bottom: 12 }}\n data={theData}\n onClick={onClick}\n className='Layer__profit-and-loss-chart'\n >\n <defs>\n <pattern\n id='layer-bar-stripe-pattern'\n x='0'\n y='0'\n width='4'\n height='4'\n patternTransform='rotate(45)'\n patternUnits='userSpaceOnUse'\n >\n <rect width='4' height='4' opacity={0.16} />\n <line x1='0' y='0' x2='0' y2='4' strokeWidth='2' />\n </pattern>\n\n <pattern\n id='layer-bar-stripe-pattern-dark'\n x='0'\n y='0'\n width='4'\n height='4'\n patternTransform='rotate(45)'\n patternUnits='userSpaceOnUse'\n >\n <rect width='4' height='4' opacity={0.16} />\n <line x1='0' y='0' x2='0' y2='4' strokeWidth='2' />\n </pattern>\n </defs>\n <ReferenceLine\n y={0}\n stroke={getColor(300)?.hex ?? '#EBEDF0'}\n xAxisId='revenue'\n />\n <Tooltip\n wrapperClassName='Layer__chart__tooltip-wrapper'\n content={<CustomTooltip />}\n cursor={<CustomizedCursor />}\n animationDuration={100}\n animationEasing='ease-out'\n />\n <CartesianGrid\n vertical={false}\n stroke={getColor(200)?.hex ?? '#fff'}\n strokeDasharray='5 5'\n />\n <Legend\n verticalAlign='top'\n align='right'\n content={renderLegend}\n payload={[\n {\n value: 'Revenue',\n type: 'circle',\n id: 'IncomeLegend',\n },\n {\n value: 'Expenses',\n type: 'circle',\n id: 'ExpensesLegend',\n },\n {\n value: 'Uncategorized',\n type: 'circle',\n id: 'UncategorizedLegend',\n },\n ]}\n />\n <XAxis dataKey='name' xAxisId='revenue' tickLine={false} />\n <XAxis dataKey='name' xAxisId='expenses' tickLine={false} hide />\n <YAxis tick={<CustomizedYTick />} />\n <Bar\n dataKey='loading'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--loading'\n xAxisId='revenue'\n stackId='revenue'\n />\n <Bar\n dataKey='loadingExpenses'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--loading'\n xAxisId='expenses'\n stackId='expenses'\n />\n <Bar\n dataKey='totalExpensesInverse'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--expenses'\n xAxisId='revenue'\n stackId='revenue'\n >\n {theData?.map(entry => {\n return (\n <Cell\n key={entry.name}\n fill='url(#layer-bar-stripe-pattern-dark)'\n />\n )\n })}\n </Bar>\n <Bar\n dataKey='revenue'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n className='Layer__profit-and-loss-chart__bar--income'\n xAxisId='revenue'\n stackId='revenue'\n >\n <LabelList\n content={\n <Indicator\n setCustomCursorSize={(width, height, x) =>\n setCustomCursorSize({ width, height, x })\n }\n customCursorSize={customCursorSize}\n animateFrom={animateFrom}\n setAnimateFrom={setAnimateFrom}\n />\n }\n />\n {theData?.map(entry => {\n return (\n <Cell\n key={entry.name}\n className={\n entry.selected\n ? 'Layer__profit-and-loss-chart__cell--selected'\n : ''\n }\n />\n )\n })}\n </Bar>\n <Bar\n dataKey='uncategorizedOutflowsInverse'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--expenses-uncategorized'\n xAxisId='revenue'\n stackId='revenue'\n >\n {theData?.map(entry => {\n return (\n <Cell\n key={entry.name}\n fill='url(#layer-bar-stripe-pattern-dark)'\n />\n )\n })}\n </Bar>\n <Bar\n dataKey='revenueUncategorized'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--income-uncategorized'\n xAxisId='revenue'\n stackId='revenue'\n >\n {theData?.map(entry => {\n return (\n <Cell key={entry.name} fill='url(#layer-bar-stripe-pattern)' />\n )\n })}\n </Bar>\n <Bar\n dataKey='expenses'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n className='Layer__profit-and-loss-chart__bar--expenses'\n xAxisId='expenses'\n stackId='expenses'\n >\n {theData.map(entry => (\n <Cell\n key={entry.name}\n className={\n entry.selected\n ? 'Layer__profit-and-loss-chart__cell--selected'\n : ''\n }\n />\n ))}\n </Bar>\n <Bar\n dataKey='expensesUncategorized'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--expenses-uncategorized'\n xAxisId='expenses'\n stackId='expenses'\n >\n {theData?.map(entry => {\n return (\n <Cell\n key={entry.name}\n fill='url(#layer-bar-stripe-pattern-dark)'\n />\n )\n })}\n </Bar>\n <Line\n dot={true}\n strokeWidth={1}\n type='linear'\n dataKey='netProfit'\n stroke={getColor(1000)?.hex ?? '#000'}\n name='Net profit'\n xAxisId='revenue'\n animationDuration={20}\n />\n </ComposedChart>\n </ResponsiveContainer>\n )\n}\n", "import { useEffect, useMemo, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { ReportingBasis } from '../../types'\nimport { DataModel, LoadedStatus } from '../../types/general'\nimport { ProfitAndLossSummary } from '../../types/profit_and_loss'\nimport { startOfMonth, sub } from 'date-fns'\nimport useSWR from 'swr'\n\ntype UseProfitAndLossLTMProps = {\n currentDate: Date\n tagFilter?: {\n key: string\n values: string[]\n }\n reportingBasis?: ReportingBasis\n}\n\nexport interface ProfitAndLossSummaryData extends ProfitAndLossSummary {\n isLoading?: boolean\n}\n\ntype UseProfitAndLossLTMReturn = (props?: UseProfitAndLossLTMProps) => {\n data: ProfitAndLossSummaryData[]\n isLoading?: boolean\n loaded?: LoadedStatus\n error?: any\n pullData: (date: Date) => void\n refetch: () => void\n}\n\nconst buildDates = ({ currentDate }: { currentDate: Date }) => {\n return {\n startYear: startOfMonth(currentDate).getFullYear() - 1,\n startMonth: startOfMonth(currentDate).getMonth() + 1,\n endYear: startOfMonth(currentDate).getFullYear(),\n endMonth: startOfMonth(currentDate).getMonth() + 1,\n }\n}\n\nconst buildMonthsArray = (startDate: Date, endDate: Date) => {\n if (startDate >= endDate) {\n return []\n }\n\n var dates = []\n for (var d = startDate; d <= endDate; d.setMonth(d.getMonth() + 1)) {\n dates.push(new Date(d))\n }\n\n return dates\n}\n\n/**\n * Hooks fetch Last Twelve Months sending 12 requests (one for each month).\n * Implementation is not perfect, but we cannot use loops and arrays with hooks.\n */\nexport const useProfitAndLossLTM: UseProfitAndLossLTMReturn = (\n { currentDate, tagFilter, reportingBasis }: UseProfitAndLossLTMProps = {\n currentDate: startOfMonth(Date.now()),\n },\n) => {\n const {\n businessId,\n auth,\n apiUrl,\n syncTimestamps,\n read,\n readTimestamps,\n hasBeenTouched,\n } = useLayerContext()\n const [date, setDate] = useState(currentDate)\n const [loaded, setLoaded] = useState<LoadedStatus>('initial')\n const [data, setData] = useState<ProfitAndLossSummaryData[]>([])\n\n const { startYear, startMonth, endYear, endMonth } = useMemo(() => {\n return buildDates({ currentDate: date })\n }, [date, businessId, tagFilter, reportingBasis])\n\n const queryKey =\n businessId &&\n Boolean(startYear) &&\n Boolean(startMonth) &&\n Boolean(endYear) &&\n Boolean(endMonth) &&\n auth?.access_token &&\n `profit-and-loss-summaries-${businessId}-${startYear.toString()}-${startMonth.toString()}-${tagFilter?.key}-${tagFilter?.values?.join(\n ',',\n )}-${reportingBasis}`\n\n const {\n data: rawData,\n isLoading,\n isValidating,\n error,\n mutate,\n } = useSWR(\n queryKey,\n Layer.getProfitAndLossSummaries(apiUrl, auth?.access_token, {\n params: {\n businessId,\n startYear: startYear.toString(),\n startMonth: startMonth.toString(),\n endYear: endYear.toString(),\n endMonth: endMonth.toString(),\n tagKey: tagFilter?.key,\n tagValues: tagFilter?.values?.join(','),\n reportingBasis,\n },\n }),\n )\n\n useEffect(() => {\n // When new date range is set, populate 'data' with 'loading' items\n const newData = data.slice()\n\n const newPeriod = buildMonthsArray(sub(date, { years: 1 }), date)\n\n if (newData && newPeriod) {\n newPeriod.forEach(x => {\n if (\n !newData?.find(\n n => x.getMonth() + 1 === n.month && x.getFullYear() === n.year,\n )\n ) {\n newData.push({\n year: x.getFullYear(),\n month: x.getMonth() + 1,\n income: 0,\n costOfGoodsSold: 0,\n grossProfit: 0,\n operatingExpenses: 0,\n profitBeforeTaxes: 0,\n taxes: 0,\n netProfit: 0,\n fullyCategorized: false,\n totalExpenses: 0,\n uncategorizedInflows: 0,\n uncategorizedOutflows: 0,\n uncategorized_transactions: 0,\n isLoading: true,\n } satisfies ProfitAndLossSummaryData)\n }\n })\n }\n\n if (newData) {\n setData(\n newData.sort(\n (a, b) =>\n Number(new Date(a.year, a.month, 1)) -\n Number(new Date(b.year, b.month, 1)),\n ),\n )\n }\n }, [startYear, startMonth])\n\n useEffect(() => {\n const newData = rawData?.data?.months?.slice()\n\n if (data && newData) {\n data.forEach(x => {\n if (!newData?.find(n => x.month === n.month && x.year === n.year)) {\n newData.push({ ...x })\n }\n })\n }\n\n if (newData) {\n setData(\n newData.sort(\n (a, b) =>\n Number(new Date(a.year, a.month, 1)) -\n Number(new Date(b.year, b.month, 1)),\n ),\n )\n }\n }, [rawData])\n\n useEffect(() => {\n if (isLoading && loaded === 'initial') {\n setLoaded('loading')\n return\n }\n\n if (!isLoading && rawData) {\n setLoaded('complete')\n }\n }, [data, isLoading])\n\n const pullData = (date: Date) => setDate(date)\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.PROFIT_AND_LOSS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n mutate()\n }\n }, [\n syncTimestamps,\n startYear,\n startMonth,\n endYear,\n endMonth,\n tagFilter,\n reportingBasis,\n ])\n\n const refetch = () => {\n mutate()\n }\n\n return {\n data,\n isLoading,\n loaded,\n error,\n pullData,\n refetch,\n }\n}\n", "import React, { useEffect, useState } from 'react'\nimport { Props as BaseProps } from 'recharts/types/component/Label'\n\n// This component does not always exist. It gets recreated each time the\n// selected month changes on the chart. As a result, the coordinates are not\n// persistent and so resist CSS animation. That way we work around this is by\n// telling the parent component what its X value is. The parent renders using\n// that X as the \"animateFrom\" value. This then tells the paren its new X,\n// which becomes the new \"animateFrom\", set using useState setter, which causes\n// a render, which causes the new `animateFrom` to be passed in, which causes a\n// change in the X coordinate, which causes a transition to trigger.\n\ntype Props = BaseProps & {\n animateFrom: number\n setAnimateFrom: (x: number) => void\n customCursorSize: { width: number; height: number }\n setCustomCursorSize: (width: number, height: number, x: number) => void\n}\nconst emptyViewBox = { x: 0, y: 0, width: 0, height: 0 }\nexport const Indicator = ({\n className,\n animateFrom,\n setAnimateFrom,\n customCursorSize,\n setCustomCursorSize,\n viewBox = {},\n}: Props) => {\n if (!className?.match(/selected/)) {\n return null\n }\n\n const [opacityIndicator, setOpacityIndicator] = useState(0)\n\n const { x: animateTo = 0, width = 0 } =\n 'x' in viewBox ? viewBox : emptyViewBox\n const margin = width > 12 ? 12 : 6\n const boxWidth = width + margin\n const xOffset = boxWidth / 2\n const borderRadius = 6\n const rectWidth = `${boxWidth}px`\n const rectHeight = 'calc(100% - 38px)'\n\n // useEffect callbacks run after the browser paints\n useEffect(() => {\n if (Math.abs(animateTo - animateFrom) < 30) {\n setOpacityIndicator(0)\n }\n\n setAnimateFrom(animateTo)\n setTimeout(() => {\n setOpacityIndicator(1)\n }, 200)\n }, [animateTo])\n\n const rectRef = (ref: SVGRectElement | null) => {\n if (ref) {\n const refRectWidth = ref.getBoundingClientRect().width\n const refRectHeight = ref.getBoundingClientRect().height\n if (\n customCursorSize.width !== refRectWidth ||\n customCursorSize.height !== refRectHeight\n ) {\n setCustomCursorSize(refRectWidth, refRectHeight, actualX - xOffset)\n }\n }\n }\n\n const actualX = animateFrom === -1 ? animateTo : animateFrom\n return (\n <rect\n ref={rectRef}\n className='Layer__profit-and-loss-chart__selection-indicator'\n rx={borderRadius}\n ry={borderRadius}\n style={{\n width: rectWidth,\n // @ts-expect-error -- y is fine but x apparently isn't!\n x: actualX - xOffset / 2 + margin / 4,\n y: 22,\n height: rectHeight,\n opacity: opacityIndicator,\n }}\n />\n )\n}\n", "import React, { useContext, useEffect } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { getEarliestDateToBrowse } from '../../utils/business'\nimport { DatePicker } from '../DatePicker'\nimport { ProfitAndLoss } from '../ProfitAndLoss'\nimport { endOfMonth, startOfMonth } from 'date-fns'\n\nexport const ProfitAndLossDatePicker = () => {\n const { business } = useLayerContext()\n const { changeDateRange, dateRange } = useContext(ProfitAndLoss.Context)\n\n const minDate = getEarliestDateToBrowse(business)\n\n return (\n <DatePicker\n mode='monthPicker'\n selected={dateRange.startDate}\n onChange={date => {\n if (!Array.isArray(date)) {\n changeDateRange({\n startDate: startOfMonth(date),\n endDate: endOfMonth(date),\n })\n }\n }}\n minDate={minDate}\n />\n )\n}\n", "import React, { useContext, useState } from 'react'\nimport { SidebarScope } from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport XIcon from '../../icons/X'\nimport { humanizeTitle } from '../../utils/profitAndLossUtils'\nimport { Button, BackButton, ButtonVariant } from '../Button'\nimport { ProfitAndLoss as PNL } from '../ProfitAndLoss'\nimport { ProfitAndLossDatePicker } from '../ProfitAndLossDatePicker'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport { DetailedChart } from './DetailedChart'\nimport { DetailedTable, DetailedTableStringOverrides } from './DetailedTable'\nimport { Filters } from './Filters'\nimport { format } from 'date-fns'\n\nexport interface ProfitAndLossDetailedChartsStringOverrides {\n detailedTableStringOverrides?: DetailedTableStringOverrides\n}\n\nexport const ProfitAndLossDetailedCharts = ({\n scope,\n hideClose = false,\n showDatePicker = false,\n chartColorsList,\n stringOverrides,\n}: {\n scope?: SidebarScope\n hideClose?: boolean\n showDatePicker?: boolean\n chartColorsList?: string[]\n stringOverrides?: ProfitAndLossDetailedChartsStringOverrides\n}) => {\n const {\n filteredDataRevenue,\n filteredTotalRevenue,\n filteredDataExpenses,\n filteredTotalExpenses,\n sortBy,\n isLoading,\n filters,\n dateRange,\n sidebarScope,\n setSidebarScope,\n setFilterTypes,\n } = useContext(PNL.Context)\n\n const theScope = scope ? scope : sidebarScope\n const data =\n theScope === 'revenue' ? filteredDataRevenue : filteredDataExpenses\n const total =\n theScope === 'revenue' ? filteredTotalRevenue : filteredTotalExpenses\n\n const [hoveredItem, setHoveredItem] = useState<string | undefined>()\n\n return (\n <div className='Layer__profit-and-loss-detailed-charts'>\n <header className='Layer__profit-and-loss-detailed-charts__header'>\n <div className='Layer__profit-and-loss-detailed-charts__head'>\n <Text size={TextSize.lg} weight={TextWeight.bold} className='title'>\n {humanizeTitle(theScope)}\n </Text>\n <Text size={TextSize.sm} className='date'>\n {format(dateRange.startDate, 'LLLL, y')}\n </Text>\n {showDatePicker && <ProfitAndLossDatePicker />}\n </div>\n {!hideClose && (\n <Button\n rightIcon={<XIcon />}\n iconOnly={true}\n onClick={() => setSidebarScope(undefined)}\n variant={ButtonVariant.secondary}\n />\n )}\n </header>\n\n <header className='Layer__profit-and-loss-detailed-charts__header--tablet'>\n {!hideClose && (\n <BackButton onClick={() => setSidebarScope(undefined)} />\n )}\n <div className='Layer__profit-and-loss-detailed-charts__head'>\n <Text size={TextSize.lg} weight={TextWeight.bold} className='title'>\n {humanizeTitle(theScope)}\n </Text>\n <Text size={TextSize.sm} className='date'>\n {format(dateRange.startDate, 'LLLL, y')}\n </Text>\n </div>\n </header>\n\n <div className='Layer__profit-and-loss-detailed-charts__content'>\n <DetailedChart\n filteredData={data}\n filteredTotal={total}\n hoveredItem={hoveredItem}\n setHoveredItem={setHoveredItem}\n sidebarScope={theScope}\n date={dateRange.startDate}\n isLoading={isLoading}\n chartColorsList={chartColorsList}\n showDatePicker={showDatePicker}\n />\n\n <div className='Layer__profit-and-loss-detailed-charts__table-wrapper'>\n <Filters\n filteredData={data}\n sidebarScope={theScope}\n filters={filters}\n setFilterTypes={setFilterTypes}\n />\n\n <DetailedTable\n filteredData={data}\n sidebarScope={theScope}\n filters={filters}\n sortBy={sortBy}\n hoveredItem={hoveredItem}\n setHoveredItem={setHoveredItem}\n chartColorsList={chartColorsList}\n stringOverrides={stringOverrides?.detailedTableStringOverrides}\n />\n </div>\n </div>\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst X = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M13.5 4.5L4.5 13.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M4.5 4.5L13.5 13.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default X\n", "import React, { useMemo } from 'react'\nimport { SidebarScope } from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { LineBaseItem } from '../../types/line_item'\nimport { formatPercent } from '../../utils/format'\nimport { humanizeTitle } from '../../utils/profitAndLossUtils'\nimport { ProfitAndLossDatePicker } from '../ProfitAndLossDatePicker'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport { mapTypesToColors } from './DetailedTable'\nimport { format } from 'date-fns'\nimport {\n PieChart,\n Pie,\n Cell,\n ResponsiveContainer,\n Label,\n Text as ChartText,\n} from 'recharts'\nimport { PolarViewBox } from 'recharts/types/util/types'\n\ninterface DetailedChartProps {\n filteredData: LineBaseItem[]\n filteredTotal?: number\n hoveredItem?: string\n setHoveredItem: (name?: string) => void\n sidebarScope?: SidebarScope\n date: number | Date\n isLoading?: boolean\n showDatePicker?: boolean\n chartColorsList?: string[]\n}\n\nexport const DetailedChart = ({\n filteredData,\n filteredTotal,\n hoveredItem,\n setHoveredItem,\n sidebarScope,\n date,\n chartColorsList,\n isLoading,\n showDatePicker = true,\n}: DetailedChartProps) => {\n const chartData = useMemo(() => {\n if (!filteredData) {\n return []\n }\n return filteredData.map(x => {\n if (x.hidden) {\n return {\n name: x.display_name,\n value: 0,\n type: x.type,\n }\n }\n return {\n name: x.display_name,\n value: x.value,\n type: x.type,\n }\n })\n }, [filteredData, isLoading])\n\n const noValue = chartData.length === 0 || !chartData.find(x => x.value !== 0)\n\n const typeColorMapping = mapTypesToColors(chartData, chartColorsList)\n\n return (\n <div className='chart-field'>\n <div className='header--tablet'>\n {showDatePicker && <ProfitAndLossDatePicker />}\n </div>\n\n <div className='chart-container'>\n <ResponsiveContainer>\n <PieChart>\n {!isLoading && !noValue ? (\n <Pie\n data={chartData}\n dataKey='value'\n nameKey='name'\n cx='50%'\n cy='50%'\n innerRadius={'91%'}\n outerRadius={'100%'}\n paddingAngle={0.5}\n fill='#8884d8'\n animationDuration={200}\n animationEasing='ease-in-out'\n >\n {chartData.map((entry, index) => {\n let fill: string | undefined = typeColorMapping[index].color\n let active = true\n if (hoveredItem && entry.name !== hoveredItem) {\n active = false\n fill = undefined\n }\n\n return (\n <Cell\n key={`cell-${index}`}\n className={`Layer__profit-and-loss-detailed-charts__pie ${\n hoveredItem && active ? 'active' : 'inactive'\n }`}\n style={{ fill }}\n opacity={typeColorMapping[index].opacity}\n onMouseEnter={() => setHoveredItem(entry.name)}\n onMouseLeave={() => setHoveredItem(undefined)}\n />\n )\n })}\n <Label\n position='center'\n value='Total'\n className='pie-center-label-title'\n content={props => {\n const { cx, cy } = (props.viewBox as PolarViewBox) ?? {\n cx: 0,\n cy: 0,\n }\n const positioningProps = {\n x: cx,\n y: (cy || 0) - 15,\n textAnchor: 'middle' as\n | 'start'\n | 'middle'\n | 'end'\n | 'inherit',\n verticalAnchor: 'middle' as 'start' | 'middle' | 'end',\n }\n\n let text = 'Total'\n\n if (hoveredItem) {\n text = hoveredItem\n }\n\n return (\n <ChartText\n {...positioningProps}\n className='pie-center-label__title'\n >\n {text}\n </ChartText>\n )\n }}\n />\n\n <Label\n position='center'\n value='Total'\n className='pie-center-label-title'\n content={props => {\n const { cx, cy } = (props.viewBox as PolarViewBox) ?? {\n cx: 0,\n cy: 0,\n }\n const positioningProps = {\n x: cx,\n y: (cy || 0) + 5,\n textAnchor: 'middle' as\n | 'start'\n | 'middle'\n | 'end'\n | 'inherit',\n verticalAnchor: 'middle' as 'start' | 'middle' | 'end',\n }\n\n let value = filteredTotal\n if (hoveredItem) {\n value = filteredData.find(\n x => x.display_name === hoveredItem,\n )?.value\n }\n\n return (\n <ChartText\n {...positioningProps}\n className='pie-center-label__value'\n >\n {`$${formatMoney(value)}`}\n </ChartText>\n )\n }}\n />\n\n <Label\n position='center'\n value='Total'\n className='pie-center-label-title'\n content={props => {\n const { cx, cy } = (props.viewBox as PolarViewBox) ?? {\n cx: 0,\n cy: 0,\n }\n const positioningProps = {\n x: cx,\n y: (cy || 0) + 25,\n height: 20,\n textAnchor: 'middle' as\n | 'start'\n | 'middle'\n | 'end'\n | 'inherit',\n verticalAnchor: 'middle' as 'start' | 'middle' | 'end',\n }\n\n if (hoveredItem) {\n return (\n <ChartText\n {...positioningProps}\n className='pie-center-label__share'\n >\n {`${formatPercent(\n filteredData.find(\n x => x.display_name === hoveredItem,\n )?.share,\n )}%`}\n </ChartText>\n )\n }\n\n return\n }}\n />\n </Pie>\n ) : null}\n\n {!isLoading && noValue ? (\n <Pie\n data={[{ name: 'Total', value: 1 }]}\n dataKey='value'\n nameKey='name'\n cx='50%'\n cy='50%'\n innerRadius={'91%'}\n outerRadius={'100%'}\n paddingAngle={0}\n fill='#F8F8FA'\n animationDuration={200}\n animationEasing='ease-in-out'\n >\n <Label\n position='center'\n value='Total'\n className='pie-center-label-title'\n content={props => {\n const { cx, cy } = (props.viewBox as PolarViewBox) ?? {\n cx: 0,\n cy: 0,\n }\n const positioningProps = {\n x: cx,\n y: (cy || 0) - 15,\n textAnchor: 'middle' as\n | 'start'\n | 'middle'\n | 'end'\n | 'inherit',\n verticalAnchor: 'middle' as 'start' | 'middle' | 'end',\n }\n\n let text = 'Total'\n\n if (hoveredItem) {\n text = hoveredItem\n }\n\n return (\n <ChartText\n {...positioningProps}\n className='pie-center-label__title'\n >\n {text}\n </ChartText>\n )\n }}\n />\n\n <Label\n position='center'\n value='Total'\n className='pie-center-label-title'\n content={props => {\n const { cx, cy } = (props.viewBox as PolarViewBox) ?? {\n cx: 0,\n cy: 0,\n }\n const positioningProps = {\n x: cx,\n y: (cy || 0) + 5,\n textAnchor: 'middle' as\n | 'start'\n | 'middle'\n | 'end'\n | 'inherit',\n verticalAnchor: 'middle' as 'start' | 'middle' | 'end',\n }\n\n let value = filteredTotal\n if (hoveredItem) {\n value = filteredData.find(\n x => x.display_name === hoveredItem,\n )?.value\n }\n\n return (\n <ChartText\n {...positioningProps}\n className='pie-center-label__value'\n >\n {`$${formatMoney(value)}`}\n </ChartText>\n )\n }}\n />\n </Pie>\n ) : null}\n\n {isLoading ? (\n <Pie\n data={[{ name: 'loading...', value: 1 }]}\n dataKey='value'\n nameKey='name'\n cx='50%'\n cy='50%'\n innerRadius={'91%'}\n outerRadius={'100%'}\n paddingAngle={0}\n fill='#F8F8FA'\n animationDuration={200}\n animationEasing='ease-in-out'\n />\n ) : null}\n </PieChart>\n </ResponsiveContainer>\n </div>\n </div>\n )\n}\n", "/**\n * Capitalize first letter of the given text.\n */\nexport const capitalizeFirstLetter = (text: string) =>\n text.charAt(0).toUpperCase() + text.slice(1)\n\n/**\n * Convert number into percentage.\n *\n * @example\n * 0.112 -> 11%\n * 0.09843 -> 9.8%\n * 0.00123 -> 0.12%\n */\nexport const formatPercent = (\n value?: number,\n options?: Intl.NumberFormatOptions,\n) => {\n if (!value && value !== 0) {\n return\n }\n\n const val = value * 100\n\n let defaultOptions: Intl.NumberFormatOptions = {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n }\n\n if (Math.abs(val) < 10) {\n defaultOptions = {\n minimumFractionDigits: 1,\n maximumFractionDigits: 1,\n }\n }\n\n if (Math.abs(val) < 1) {\n defaultOptions = {\n minimumFractionDigits: 1,\n maximumFractionDigits: 1,\n }\n }\n\n if (val === 0) {\n defaultOptions = {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n }\n }\n\n return val.toLocaleString('en-US', {\n ...defaultOptions,\n ...options,\n })\n}\n\n/**\n * Convert Enum-like (upper snakecase) text into human friendly format.\n */\nexport const humanizeEnum = (text: string) => {\n return capitalizeFirstLetter(text.replace(/_/gi, ' ').toLowerCase())\n}\n\nexport const convertNumberToCurrency = (amount: number | undefined): string => {\n if (!amount) return ''\n\n let formattedValue = amount.toLocaleString('en-US')\n\n return formattedValue.length > 0 ? `$${formattedValue}` : ''\n}\n\nexport const convertCurrencyToNumber = (amount: string): number => {\n const inputValue = amount.replace(/[^0-9.]/g, '')\n\n return parseFloat(inputValue)\n}\n\nexport const CURRENCY_INPUT_PATTERN = '[0-9]+(.[0-9]+)?'\n", "import React from 'react'\nimport { DEFAULT_CHART_COLOR_TYPE } from '../../config/charts'\nimport {\n Scope,\n SidebarScope,\n ProfitAndLossFilters,\n} from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport SortArrows from '../../icons/SortArrows'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { SortDirection } from '../../types'\nimport { LineBaseItem } from '../../types/line_item'\nimport { formatPercent } from '../../utils/format'\nimport classNames from 'classnames'\n\nexport interface DetailedTableStringOverrides {\n categoryColumnHeader?: string\n typeColumnHeader?: string\n valueColumnHeader?: string\n}\n\nexport interface DetailedTableProps {\n filteredData: LineBaseItem[]\n hoveredItem?: string\n setHoveredItem: (name?: string) => void\n sidebarScope: SidebarScope\n filters: ProfitAndLossFilters\n sortBy: (scope: Scope, field: string, direction?: SortDirection) => void\n chartColorsList?: string[]\n stringOverrides?: DetailedTableStringOverrides\n}\n\nexport const mapTypesToColors = (\n data: any[],\n colorList: string[] = DEFAULT_CHART_COLOR_TYPE,\n) => {\n const typeToColor: any = {}\n const typeToLastOpacity: any = {}\n let colorIndex = 0\n\n return data.map(obj => {\n const type = obj.type\n\n if (!typeToColor[type]) {\n typeToColor[type] = colorList[colorIndex % colorList.length]\n colorIndex++\n typeToLastOpacity[type] = 1\n } else {\n typeToLastOpacity[type] -= 0.1\n }\n\n const opacity = typeToLastOpacity[type]\n\n return {\n color: typeToColor[type],\n opacity: opacity,\n }\n })\n}\n\nexport const DetailedTable = ({\n filteredData,\n sidebarScope,\n filters,\n sortBy,\n hoveredItem,\n setHoveredItem,\n chartColorsList,\n stringOverrides,\n}: DetailedTableProps) => {\n const buildColClass = (column: string) => {\n return classNames(\n 'Layer__sortable-col',\n sidebarScope && filters[sidebarScope]?.sortBy === column\n ? `sort--${\n (sidebarScope && filters[sidebarScope]?.sortDirection) ?? 'desc'\n }`\n : '',\n )\n }\n\n const typeColorMapping: any = mapTypesToColors(filteredData, chartColorsList)\n\n // Index to keep track of the next color to assign\n const colorIndex = 0\n\n return (\n <div className='details-container'>\n <div className='table'>\n <table>\n <thead>\n <tr>\n <th\n className={buildColClass('category')}\n onClick={() => sortBy(sidebarScope ?? 'expenses', 'category')}\n >\n {stringOverrides?.categoryColumnHeader || 'Category'}{' '}\n <SortArrows className='Layer__sort-arrows' />\n </th>\n <th\n className={buildColClass('type')}\n onClick={() => sortBy(sidebarScope ?? 'expenses', 'type')}\n >\n {stringOverrides?.typeColumnHeader || 'Type'}{' '}\n <SortArrows className='Layer__sort-arrows' />\n </th>\n <th></th>\n <th\n className={buildColClass('value')}\n onClick={() => sortBy(sidebarScope ?? 'expenses', 'value')}\n >\n {stringOverrides?.valueColumnHeader || 'Value'}{' '}\n <SortArrows className='Layer__sort-arrows' />\n </th>\n </tr>\n </thead>\n <tbody>\n {filteredData\n .filter(x => !x.hidden)\n .map((item, idx) => {\n return (\n <tr\n key={`pl-side-table-item-${idx}`}\n className={classNames(\n 'Layer__profit-and-loss-detailed-table__row',\n hoveredItem && hoveredItem === item.display_name\n ? 'active'\n : '',\n )}\n onMouseEnter={() => setHoveredItem(item.display_name)}\n onMouseLeave={() => setHoveredItem(undefined)}\n >\n <td className='category-col'>{item.display_name}</td>\n <td className='type-col'>{item.type}</td>\n <td className='value-col'>${formatMoney(item.value)}</td>\n <td className='share-col'>\n <span className='share-cell-content'>\n {formatPercent(item.share)}%\n <div\n className='share-icon'\n style={{\n background: typeColorMapping[idx].color,\n opacity: typeColorMapping[idx].opacity,\n }}\n />\n </span>\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n </div>\n )\n}\n", "export const INACTIVE_OPACITY_LEVELS = [\n 0.85, 0.7, 0.66, 0.55, 0.4, 0.33, 0.25, 0.15,\n]\n\nexport const DEFAULT_CHART_OPACITY = [1, 0.8, 0.6, 0.4, 0.2, 0.1]\n\nexport const DEFAULT_CHART_COLOR_TYPE = [\n '#008028',\n '#7417B3',\n '#006A80',\n '#8FB300',\n '#3D87CC',\n '#CC3DCC',\n '#3DCCB2',\n '#CCB129',\n '#2949CC',\n '#619900',\n '#6A52CC',\n '#71CC56',\n]\n\nexport const DEFAULT_MINICHART_COLORS = [\n {\n color: '#7417B3',\n opacity: 1,\n },\n {\n color: '#7417B3',\n opacity: 0.8,\n },\n {\n color: '#7417B3',\n opacity: 0.6,\n },\n {\n color: '#7417B3',\n opacity: 0.4,\n },\n {\n color: '#7417B3',\n opacity: 0.2,\n },\n {\n color: '#7417B3',\n opacity: 0.1,\n },\n {\n color: '#006A80',\n opacity: 1,\n },\n {\n color: '#006A80',\n opacity: 0.8,\n },\n {\n color: '#006A80',\n opacity: 0.6,\n },\n {\n color: '#006A80',\n opacity: 0.4,\n },\n {\n color: '#006A80',\n opacity: 0.2,\n },\n {\n color: '#006A80',\n opacity: 0.1,\n },\n {\n color: '#009930',\n opacity: 1,\n },\n {\n color: '#009930',\n opacity: 0.8,\n },\n {\n color: '#009930',\n opacity: 0.6,\n },\n {\n color: '#009930',\n opacity: 0.4,\n },\n {\n color: '#009930',\n opacity: 0.2,\n },\n {\n color: '#009930',\n opacity: 0.1,\n },\n]\n\nexport const TASKS_CHARTS_COLORS = {\n done: '#3B9C63',\n pending: '#DFA000',\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst SortArrows = ({ size = 13, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 13'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <g clipPath='url(#clip0_1758_75388)'>\n <path\n d='M1.33325 8.5L3.99992 11.1667L6.66659 8.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n className='desc-arrow'\n />\n <path\n d='M4 2.5L4 11.1667'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n className='desc-arrow'\n />\n <path\n d='M5.99988 5.16602L8.66654 2.49935L11.3332 5.16602'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n className='asc-arrow'\n />\n <path\n d='M8.66663 11.166L8.66663 2.49935'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n className='asc-arrow'\n />\n </g>\n <defs>\n <clipPath id='clip0_1758_75388'>\n <rect\n width='12'\n height='12'\n fill='white'\n transform='translate(0 0.5)'\n />\n </clipPath>\n </defs>\n </svg>\n)\n\nexport default SortArrows\n", "import React from 'react'\nimport Select, { components } from 'react-select'\nimport {\n Scope,\n SidebarScope,\n ProfitAndLossFilters,\n} from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport ChevronDown from '../../icons/ChevronDown'\nimport { LineBaseItem } from '../../types/line_item'\nimport { CategoryOption } from '../CategorySelect/CategorySelect'\nimport { Text, TextSize } from '../Typography'\n\nexport interface FiltersProps {\n filteredData: LineBaseItem[]\n sidebarScope: SidebarScope\n filters: ProfitAndLossFilters\n setFilterTypes: (scope: Scope, types: string[]) => void\n}\n\nexport const Filters = ({\n filteredData,\n sidebarScope,\n filters,\n setFilterTypes,\n}: FiltersProps) => {\n return (\n <div className='filters'>\n <Text size={TextSize.sm} className='Layer__label'>\n Filters\n </Text>\n <Select\n className='Layer__select type-select'\n classNamePrefix='Layer__select'\n value={\n sidebarScope && filters[sidebarScope]?.types\n ? sidebarScope &&\n filters[sidebarScope]?.types?.map(x => ({\n value: x,\n label: x,\n }))\n : []\n }\n isMulti\n isClearable={false}\n options={\n [...new Set(filteredData?.map(x => x.type))].map(x => ({\n label: x,\n value: x,\n })) as unknown as readonly { value: string; label: string }[]\n }\n onChange={selected => {\n setFilterTypes(\n sidebarScope ?? 'expenses',\n selected.map(x => x.value),\n )\n }}\n components={{\n DropdownIndicator: props => (\n <components.DropdownIndicator {...props}>\n <ChevronDown />\n </components.DropdownIndicator>\n ),\n Placeholder: props => (\n <components.Placeholder {...props}>\n <div className='Layer__select__multi-all-placeholder-badge'>\n All\n </div>\n </components.Placeholder>\n ),\n }}\n />\n </div>\n )\n}\n", "import React, { useContext, useMemo } from 'react'\nimport { Scope } from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { ProfitAndLoss } from '../../types'\nimport { LineBaseItem } from '../../types/line_item'\nimport {\n collectExpensesItems,\n collectRevenueItems,\n} from '../../utils/profitAndLossUtils'\nimport { ProfitAndLoss as PNL } from '../ProfitAndLoss'\nimport { SkeletonLoader } from '../SkeletonLoader'\nimport { MiniChart } from './MiniChart'\nimport classNames from 'classnames'\n\nexport interface ProfitAndLossSummariesStringOverrides {\n revenueLabel?: string\n expensesLabel?: string\n netProfitLabel?: string\n}\n\ntype Props = {\n vertical?: boolean\n actionable?: boolean\n revenueLabel?: string // deprecated\n stringOverrides?: ProfitAndLossSummariesStringOverrides\n}\n\nconst CHART_PLACEHOLDER = [\n {\n name: 'placeholder',\n display_name: 'placeholder',\n value: 1,\n type: 'placeholder',\n share: 1,\n },\n]\n\nconst buildMiniChartData = (scope: Scope, data?: ProfitAndLoss) => {\n if (!data) {\n return CHART_PLACEHOLDER\n }\n\n let items: LineBaseItem[] = []\n\n switch (scope) {\n case 'revenue':\n items = collectRevenueItems(data)\n break\n default:\n items = collectExpensesItems(data)\n }\n\n if (\n !items ||\n items.length === 0 ||\n !items.find(x => Math.abs(x.value) !== 0)\n ) {\n return CHART_PLACEHOLDER\n }\n\n return items.slice()\n}\n\nexport const ProfitAndLossSummaries = ({\n vertical,\n actionable = false,\n revenueLabel, // deprecated\n stringOverrides,\n}: Props) => {\n const {\n data: storedData,\n isLoading,\n setSidebarScope,\n sidebarScope,\n } = useContext(PNL.Context)\n\n const dataItem = Array.isArray(storedData)\n ? storedData[storedData.length - 1]\n : storedData\n\n const expensesChartData = useMemo(() => {\n return buildMiniChartData('expenses', dataItem)\n }, [storedData])\n\n const revenueChartData = useMemo(() => {\n return buildMiniChartData('revenue', dataItem)\n }, [storedData])\n\n const data = dataItem ? dataItem : { income: { value: NaN }, net_profit: NaN }\n\n const incomeDirectionClass =\n (data.income.value ?? NaN) < 0\n ? 'Layer__profit-and-loss-summaries__amount--negative'\n : 'Layer__profit-and-loss-summaries__amount--positive'\n\n const expensesDirectionClass =\n (data?.income?.value ?? NaN) - data.net_profit < 0\n ? 'Layer__profit-and-loss-summaries__amount--negative'\n : 'Layer__profit-and-loss-summaries__amount--positive'\n\n const netProfitDirectionClass =\n data.net_profit < 0\n ? 'Layer__profit-and-loss-summaries__amount--negative'\n : 'Layer__profit-and-loss-summaries__amount--positive'\n\n return (\n <div\n className={`Layer__profit-and-loss-summaries ${\n vertical ? 'flex-col' : ''\n }`}\n >\n <div\n className={classNames(\n 'Layer__profit-and-loss-summaries__summary',\n actionable && 'Layer__actionable',\n 'Layer__profit-and-loss-summaries__summary--income',\n sidebarScope === 'revenue' ? 'active' : '',\n )}\n onClick={() => {\n actionable && setSidebarScope('revenue')\n }}\n >\n <MiniChart data={revenueChartData} />\n <div className='Layer__profit-and-loss-summaries__text'>\n <span className='Layer__profit-and-loss-summaries__title'>\n {stringOverrides?.revenueLabel || revenueLabel || 'Revenue'}\n </span>\n {isLoading || storedData === undefined ? (\n <div className='Layer__profit-and-loss-summaries__loader'>\n <SkeletonLoader />\n </div>\n ) : (\n <span\n className={`Layer__profit-and-loss-summaries__amount ${incomeDirectionClass}`}\n >\n {formatMoney(Math.abs(data?.income?.value ?? NaN))}\n </span>\n )}\n </div>\n </div>\n <div\n className={classNames(\n 'Layer__profit-and-loss-summaries__summary',\n actionable && 'Layer__actionable',\n 'Layer__profit-and-loss-summaries__summary--expenses',\n sidebarScope === 'expenses' ? 'active' : '',\n )}\n onClick={() => {\n actionable && setSidebarScope('expenses')\n }}\n >\n <MiniChart data={expensesChartData} />\n <div className='Layer__profit-and-loss-summaries__text'>\n <span className='Layer__profit-and-loss-summaries__title'>\n {stringOverrides?.expensesLabel || 'Expenses'}\n </span>\n {isLoading || storedData === undefined ? (\n <div className='Layer__profit-and-loss-summaries__loader'>\n <SkeletonLoader className='Layer__profit-and-loss-summaries__loader' />\n </div>\n ) : (\n <span\n className={`Layer__profit-and-loss-summaries__amount ${expensesDirectionClass}`}\n >\n {formatMoney(\n Math.abs((data.income.value ?? 0) - data.net_profit),\n )}\n </span>\n )}\n </div>\n </div>\n <div\n className={classNames(\n 'Layer__profit-and-loss-summaries__summary net-profit Layer__profit-and-loss-summaries__summary--net-profit',\n actionable && 'Layer__actionable',\n )}\n >\n <div className='Layer__profit-and-loss-summaries__text'>\n <span className='Layer__profit-and-loss-summaries__title'>\n {stringOverrides?.netProfitLabel || 'Net Profit'}\n </span>\n {isLoading || storedData === undefined ? (\n <div className='Layer__profit-and-loss-summaries__loader'>\n <SkeletonLoader className='Layer__profit-and-loss-summaries__loader' />\n </div>\n ) : (\n <span\n className={`Layer__profit-and-loss-summaries__amount ${netProfitDirectionClass}`}\n >\n {formatMoney(Math.abs(data.net_profit))}\n </span>\n )}\n </div>\n </div>\n </div>\n )\n}\n", "import React from 'react'\nimport { DEFAULT_MINICHART_COLORS } from '../../config/charts'\nimport { LineBaseItem } from '../../types/line_item'\nimport { PieChart, Pie, Cell } from 'recharts'\n\nexport interface MiniChartProps {\n data: LineBaseItem[]\n}\n\nexport const MiniChart = ({ data }: MiniChartProps) => {\n return (\n <PieChart width={52} height={52} className='mini-chart'>\n <Pie\n data={data}\n dataKey='value'\n nameKey='name'\n cx='50%'\n cy='50%'\n innerRadius={10}\n outerRadius={16}\n paddingAngle={0.4}\n fill='#8884d8'\n width={24}\n height={24}\n animationDuration={250}\n animationEasing='ease-in-out'\n >\n {data.map((entry, index) => {\n const colorConfig =\n DEFAULT_MINICHART_COLORS[index % DEFAULT_MINICHART_COLORS.length]\n\n return (\n <Cell\n key={`cell-${index}`}\n className={`Layer__profit-and-loss-detailed-charts__pie`}\n fill={\n entry.name === 'placeholder' ? '#e6e6e6' : colorConfig.color\n }\n opacity={colorConfig.opacity}\n />\n )\n })}\n </Pie>\n </PieChart>\n )\n}\n", "import React, { useContext } from 'react'\nimport { Direction } from '../../types'\nimport { Loader } from '../Loader'\nimport { ProfitAndLoss } from '../ProfitAndLoss'\nimport { ProfitAndLossRow } from '../ProfitAndLossRow'\nimport emptyPNL from './empty_profit_and_loss_report'\nimport classNames from 'classnames'\n\nexport interface ProfitAndLossTableStringOverrides {\n grossProfitLabel?: string\n profitBeforeTaxesLabel?: string\n netProfitLabel?: string\n}\n\ntype Props = {\n lockExpanded?: boolean\n asContainer?: boolean\n stringOverrides?: ProfitAndLossTableStringOverrides\n}\n\nexport const ProfitAndLossTable = ({\n lockExpanded,\n asContainer,\n stringOverrides,\n}: Props) => {\n const {\n data: actualData,\n isLoading,\n setSidebarScope,\n } = useContext(ProfitAndLoss.Context)\n\n const currentData = Array.isArray(actualData)\n ? actualData[actualData.length - 1]\n : actualData\n const data = !currentData || isLoading ? emptyPNL : currentData\n\n if (isLoading || actualData === undefined) {\n return (\n <div\n className={classNames(\n 'Layer__profit-and-loss-table__loader-container',\n asContainer && 'Layer__component-container',\n )}\n >\n <Loader />\n </div>\n )\n }\n\n return (\n <>\n <div\n className={classNames(\n 'Layer__profit-and-loss-table Layer__profit-and-loss-table--main',\n asContainer && 'Layer__component-container',\n )}\n >\n <ProfitAndLossRow\n lineItem={data.income}\n direction={Direction.CREDIT}\n lockExpanded={lockExpanded}\n scope='revenue'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={data.cost_of_goods_sold}\n direction={Direction.DEBIT}\n lockExpanded={lockExpanded}\n scope='expenses'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={{\n value: data.gross_profit,\n display_name: stringOverrides?.grossProfitLabel || 'Gross Profit',\n }}\n variant='summation'\n direction={Direction.CREDIT}\n lockExpanded={lockExpanded}\n scope='revenue'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={data.expenses}\n direction={Direction.DEBIT}\n lockExpanded={lockExpanded}\n scope='expenses'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={{\n value: data.profit_before_taxes,\n display_name:\n stringOverrides?.profitBeforeTaxesLabel || 'Profit Before Taxes',\n }}\n variant='summation'\n direction={Direction.CREDIT}\n lockExpanded={lockExpanded}\n scope='revenue'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={data.taxes}\n direction={Direction.DEBIT}\n lockExpanded={lockExpanded}\n scope='expenses'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={{\n value: data.net_profit,\n display_name: stringOverrides?.netProfitLabel || 'Net Profit',\n }}\n variant='summation'\n direction={Direction.CREDIT}\n lockExpanded={lockExpanded}\n />\n </div>\n {data.other_outflows || data.personal_expenses ? (\n <div className='Layer__profit-and-loss-table Layer__profit-and-loss-table__outflows'>\n <ProfitAndLossRow\n lineItem={data.other_outflows}\n direction={Direction.DEBIT}\n lockExpanded={lockExpanded}\n />\n <ProfitAndLossRow\n lineItem={data.personal_expenses}\n direction={Direction.DEBIT}\n lockExpanded={lockExpanded}\n />\n </div>\n ) : null}\n </>\n )\n}\n", "import React, { useState } from 'react'\nimport { SidebarScope } from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport PieChart from '../../icons/PieChart'\nimport { centsToDollars } from '../../models/Money'\nimport { Direction, LineItem } from '../../types'\nimport { Text } from '../Typography'\n\ntype Props = {\n variant?: string\n depth?: number\n maxDepth?: number\n lineItem?: LineItem | null\n direction?: Direction\n scope?: SidebarScope\n setSidebarScope?: (name: SidebarScope) => void\n defaultExpanded?: boolean\n\n /* This removes the expand toggle and leaves everything in the expanded state */\n lockExpanded?: boolean\n}\n\nexport const ProfitAndLossRow = ({\n variant,\n lineItem,\n depth = 0,\n maxDepth = 8,\n direction = Direction.DEBIT,\n lockExpanded = false,\n scope,\n setSidebarScope,\n defaultExpanded = false,\n}: Props) => {\n if (!lineItem) {\n return null\n }\n const { value, display_name, line_items } = lineItem\n const [expanded, setExpanded] = useState(lockExpanded || defaultExpanded)\n const amount = value ?? 0\n const amountString = centsToDollars(Math.abs(amount))\n const labelClasses = [\n 'Layer__profit-and-loss-row',\n 'Layer__profit-and-loss-row__label',\n ]\n const valueClasses = [\n 'Layer__profit-and-loss-row',\n 'Layer__profit-and-loss-row__value',\n ]\n const positive =\n amount === 0 ||\n (direction === Direction.CREDIT && amount > 0) ||\n (direction === Direction.DEBIT && amount < 0)\n valueClasses.push(\n positive\n ? 'Layer__profit-and-loss-row__value--amount-positive'\n : 'Layer__profit-and-loss-row__value--amount-negative',\n )\n labelClasses.push(`Layer__profit-and-loss-row__label--depth-${depth}`)\n valueClasses.push(`Layer__profit-and-loss-row__value--depth-${depth}`)\n variant &&\n labelClasses.push(`Layer__profit-and-loss-row__label--variant-${variant}`)\n variant &&\n valueClasses.push(`Layer__profit-and-loss-row__value--variant-${variant}`)\n\n const toggleExpanded = () => setExpanded(!expanded)\n const canGoDeeper = depth < maxDepth\n const hasChildren = (line_items?.length ?? 0) > 0\n const displayChildren = hasChildren && canGoDeeper\n labelClasses.push(\n `Layer__profit-and-loss-row__label--display-children-${displayChildren}`,\n )\n valueClasses.push(\n `Layer__profit-and-loss-row__value--display-children-${displayChildren}`,\n )\n\n displayChildren &&\n expanded &&\n labelClasses.push('Layer__profit-and-loss-row__label--expanded')\n\n displayChildren &&\n expanded &&\n valueClasses.push('Layer__profit-and-loss-row__value--expanded')\n return (\n <>\n <div\n className={labelClasses.join(' ')}\n onClick={() => !lockExpanded && toggleExpanded()}\n style={{\n paddingLeft: depth === 0 && !hasChildren ? 28 : 16 * (depth + 1) + 2,\n }}\n >\n <span className='Layer__profit-and-loss-row__label__title'>\n {!lockExpanded && variant !== 'summation' ? (\n <ChevronDownFill\n size={16}\n className='Layer__profit-and-loss-row__label__chevron'\n />\n ) : null}\n <Text>{display_name}</Text>\n </span>\n {setSidebarScope && (\n <span\n className='Layer__profit-and-loss-row__detailed-chart-btn'\n onClick={e => {\n e.stopPropagation()\n setSidebarScope && setSidebarScope(scope ?? 'expenses')\n }}\n >\n <PieChart />\n </span>\n )}\n </div>\n <div className={valueClasses.join(' ')}>\n <Text>{amountString}</Text>\n </div>\n {canGoDeeper && hasChildren && (\n <div\n className={`Layer__profit-and-loss-row__children ${\n expanded && 'Layer__profit-and-loss-row__children--expanded'\n }`}\n >\n <div className='Layer__profit-and-loss-row__children--content'>\n {(line_items || []).map(line_item => (\n <ProfitAndLossRow\n key={line_item.display_name}\n lineItem={line_item}\n depth={depth + 1}\n maxDepth={maxDepth}\n direction={direction}\n />\n ))}\n </div>\n </div>\n )}\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst PieChart = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 12'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <g>\n <path\n d='M10.2213 7.78271C9.92969 8.47226 9.47363 9.07989 8.89297 9.55247C8.3123 10.0251 7.62471 10.3482 6.89031 10.4936C6.1559 10.6391 5.39705 10.6024 4.68009 10.3869C3.96313 10.1713 3.30989 9.78337 2.77749 9.25701C2.24509 8.73065 1.84973 8.08189 1.62598 7.36744C1.40223 6.65298 1.3569 5.8946 1.49396 5.15858C1.63102 4.42257 1.94629 3.73133 2.41221 3.14531C2.87813 2.55928 3.48051 2.09631 4.16669 1.79688'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5833 6.00033C10.5833 5.39843 10.4648 4.80244 10.2344 4.24636C10.0041 3.69028 9.66651 3.18502 9.24091 2.75942C8.8153 2.33382 8.31004 1.99621 7.75397 1.76588C7.19789 1.53554 6.60189 1.41699 6 1.41699V6.00033H10.5833Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </g>\n </svg>\n)\n\nexport default PieChart\n", "import { ProfitAndLoss } from '../../types'\n\nexport default {\n type: 'Profit_And_Loss',\n business_id: '',\n start_date: '',\n end_date: '',\n income: {\n name: 'INCOME',\n display_name: 'Income',\n value: NaN,\n line_items: null,\n },\n cost_of_goods_sold: {\n display_name: 'Cost of Goods Sold',\n name: 'COGS',\n value: NaN,\n line_items: null,\n },\n gross_profit: NaN,\n expenses: {\n name: 'EXPENSES',\n display_name: 'Expenses',\n value: NaN,\n line_items: null,\n },\n profit_before_taxes: NaN,\n taxes: {\n name: 'TAXES',\n display_name: 'Taxes',\n value: NaN,\n line_items: null,\n },\n net_profit: NaN,\n other_outflows: {\n name: 'OTHER_OUTFLOWS',\n display_name: 'Other outflows',\n value: NaN,\n line_items: null,\n },\n personal_expenses: {\n name: 'PERSONAL',\n display_name: 'Personal expenses',\n value: NaN,\n line_items: null,\n },\n fully_categorized: false,\n} as ProfitAndLoss\n", "import React, { PropsWithChildren, useEffect, useState } from 'react'\nimport { BalanceSheetContext } from '../../contexts/BalanceSheetContext'\nimport { TableProvider } from '../../contexts/TableContext'\nimport { useBalanceSheet } from '../../hooks/useBalanceSheet'\nimport { BalanceSheetDatePicker } from '../BalanceSheetDatePicker'\nimport { BalanceSheetExpandAllButton } from '../BalanceSheetExpandAllButton'\nimport { BalanceSheetTable } from '../BalanceSheetTable'\nimport { BalanceSheetTableStringOverrides } from '../BalanceSheetTable/BalanceSheetTable'\nimport { Container } from '../Container'\nimport { Loader } from '../Loader'\nimport { View } from '../View'\nimport { BALANCE_SHEET_ROWS } from './constants'\nimport { format, parse, startOfDay } from 'date-fns'\n\nexport interface BalanceSheetStringOverrides {\n balanceSheetTable?: BalanceSheetTableStringOverrides\n}\n\nexport type BalanceSheetViewProps = PropsWithChildren & {\n withExpandAllButton?: boolean\n asWidget?: boolean\n stringOverrides?: BalanceSheetStringOverrides\n}\n\nexport type BalanceSheetProps = PropsWithChildren & {\n effectiveDate?: Date\n asWidget?: boolean\n stringOverrides?: BalanceSheetStringOverrides\n}\n\nconst COMPONENT_NAME = 'balance-sheet'\n\nexport const BalanceSheet = (props: BalanceSheetProps) => {\n const balanceSheetContextData = useBalanceSheet(props.effectiveDate)\n return (\n <BalanceSheetContext.Provider value={balanceSheetContextData}>\n <BalanceSheetView\n asWidget={props.asWidget}\n stringOverrides={props.stringOverrides}\n {...props}\n />\n </BalanceSheetContext.Provider>\n )\n}\n\nconst BalanceSheetView = ({\n withExpandAllButton = true,\n asWidget = false,\n stringOverrides,\n}: BalanceSheetViewProps) => {\n const [effectiveDate, setEffectiveDate] = useState(startOfDay(new Date()))\n const { data, isLoading, refetch } = useBalanceSheet(effectiveDate)\n\n useEffect(() => {\n // Refetch only if selected effectiveDate and data's effectiveDate are different\n const d1 =\n effectiveDate &&\n format(startOfDay(effectiveDate), \"yyyy-MM-dd'T'HH:mm:ssXXX\")\n const d2 =\n data?.effective_date &&\n format(\n startOfDay(\n parse(data.effective_date, \"yyyy-MM-dd'T'HH:mm:ssXXX\", new Date()),\n ),\n \"yyyy-MM-dd'T'HH:mm:ssXXX\",\n )\n if (d1 && (!d2 || (d2 && d2 !== d1))) {\n refetch()\n }\n }, [effectiveDate])\n\n if (asWidget) {\n return (\n <TableProvider>\n <Container name={COMPONENT_NAME} asWidget={true}>\n <View\n type='panel'\n headerControls={\n <>\n <BalanceSheetDatePicker\n effectiveDate={effectiveDate}\n setEffectiveDate={setEffectiveDate}\n />\n {withExpandAllButton && <BalanceSheetExpandAllButton />}\n </>\n }\n >\n {!data || isLoading ? (\n <div className={`Layer__${COMPONENT_NAME}__loader-container`}>\n <Loader />\n </div>\n ) : (\n <BalanceSheetTable\n data={data}\n config={BALANCE_SHEET_ROWS}\n stringOverrides={stringOverrides?.balanceSheetTable}\n />\n )}\n </View>\n </Container>\n </TableProvider>\n )\n }\n\n return (\n <TableProvider>\n <View\n type='panel'\n headerControls={\n <>\n <BalanceSheetDatePicker\n effectiveDate={effectiveDate}\n setEffectiveDate={setEffectiveDate}\n />\n {withExpandAllButton && <BalanceSheetExpandAllButton />}\n </>\n }\n >\n {!data || isLoading ? (\n <div className={`Layer__${COMPONENT_NAME}__loader-container`}>\n <Loader />\n </div>\n ) : (\n <BalanceSheetTable\n data={data}\n config={BALANCE_SHEET_ROWS}\n stringOverrides={stringOverrides?.balanceSheetTable}\n />\n )}\n </View>\n </TableProvider>\n )\n}\n", "import { createContext } from 'react'\nimport { useBalanceSheet } from '../../hooks/useBalanceSheet'\n\nexport type BalanceSheetContextType = ReturnType<typeof useBalanceSheet>\nexport const BalanceSheetContext = createContext<BalanceSheetContextType>({\n data: undefined,\n isLoading: false,\n error: undefined,\n refetch: () => {},\n})\n", "import React, { createContext, useState, ReactNode } from 'react'\nimport { TableContextProps } from '../../types/table'\n\nconst defaultValue: TableContextProps = {\n expandedRows: [],\n setExpandedRows: () => {},\n expandAllRows: () => {},\n expandedAllRows: false,\n setExpandedAllRows: () => {},\n}\n\nexport const TableContext = createContext<TableContextProps>(defaultValue)\n\ninterface TableProviderProps {\n children: ReactNode\n}\n\nexport const TableProvider: React.FC<TableProviderProps> = ({ children }) => {\n const [expandedRows, setExpandedRowsState] = useState<string[]>([])\n const [expandedAllRows, setExpandedAllRows] = useState(false)\n\n const toggleRow = (rowKey: string) => {\n setExpandedRowsState(prevRows => {\n const rows = [...prevRows]\n if (rows.includes(rowKey)) {\n rows.splice(rows.indexOf(rowKey), 1)\n } else {\n rows.push(rowKey)\n }\n return rows\n })\n }\n\n const expandAllRows = (rowKeys: string[]) => {\n setExpandedRowsState(rowKeys)\n }\n\n const contextValue: TableContextProps = {\n expandedRows,\n setExpandedRows: toggleRow,\n expandAllRows,\n expandedAllRows,\n setExpandedAllRows,\n }\n\n return (\n <TableContext.Provider value={contextValue}>\n {children}\n </TableContext.Provider>\n )\n}\n", "import { useEffect } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { BalanceSheet } from '../../types'\nimport { DataModel } from '../../types/general'\nimport { format, startOfDay } from 'date-fns'\nimport useSWR from 'swr'\n\ntype UseBalanceSheet = (date?: Date) => {\n data: BalanceSheet | undefined\n isLoading: boolean\n error: unknown\n refetch: () => void\n}\n\nexport const useBalanceSheet: UseBalanceSheet = (date: Date = new Date()) => {\n const { auth, businessId, apiUrl, read, syncTimestamps, hasBeenTouched } =\n useLayerContext()\n const dateString = format(startOfDay(date), \"yyyy-MM-dd'T'HH:mm:ssXXX\")\n\n const queryKey =\n businessId &&\n dateString &&\n auth?.access_token &&\n `balance-sheet-${businessId}-${dateString}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getBalanceSheet(apiUrl, auth?.access_token, {\n params: {\n businessId,\n effectiveDate: dateString,\n },\n }),\n )\n\n const refetch = () => {\n mutate()\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.BALANCE_SHEET, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps, dateString])\n\n return { data: data?.data, isLoading, error, refetch }\n}\n", "import React from 'react'\nimport { DatePicker } from '../DatePicker'\n\nexport type BalanceSheetDatePickerProps = {\n effectiveDate: Date\n setEffectiveDate: (date: Date) => void\n}\n\nexport const BalanceSheetDatePicker = ({\n effectiveDate,\n setEffectiveDate,\n}: BalanceSheetDatePickerProps) => {\n return (\n <>\n <DatePicker\n selected={effectiveDate}\n onChange={date => date && setEffectiveDate(date as Date)}\n mode='dayPicker'\n />\n </>\n )\n}\n", "import React from 'react'\nimport { useTableExpandRow } from '../../hooks/useTableExpandRow'\nimport { Button, ButtonVariant } from '../Button'\n\nexport const BalanceSheetExpandAllButton = () => {\n const { expandedAllRows, toggleAllRows } = useTableExpandRow()\n return (\n <Button onClick={() => toggleAllRows()} variant={ButtonVariant.secondary}>\n {!expandedAllRows ? 'Expand all rows' : 'Collapse all rows'}\n </Button>\n )\n}\n", "import { useContext } from 'react'\nimport { TableContext } from '../../contexts/TableContext'\n\nexport const useTableExpandRow = () => {\n const {\n expandedAllRows,\n setExpandedAllRows,\n expandAllRows,\n expandedRows,\n setExpandedRows,\n } = useContext(TableContext)\n\n const toggleAllRows = () => {\n if (expandedAllRows) {\n setIsOpen([])\n return setExpandedAllRows(false)\n } else {\n return setExpandedAllRows(true)\n }\n }\n\n const setIsOpen = (\n rowKey: string | string[],\n withoutAllRowsUpdate?: boolean,\n ) => {\n if (!withoutAllRowsUpdate && expandedAllRows) {\n setExpandedAllRows(false)\n }\n if (Array.isArray(rowKey)) {\n return expandAllRows(rowKey)\n }\n return setExpandedRows(rowKey)\n }\n\n const isOpen = (rowKey: string) => expandedRows.includes(rowKey)\n\n return {\n isOpen,\n setIsOpen,\n expandedAllRows,\n toggleAllRows,\n }\n}\n", "import React, { useEffect } from 'react'\nimport { useTableExpandRow } from '../../hooks/useTableExpandRow'\nimport { BalanceSheet, LineItem } from '../../types'\nimport { Table, TableBody, TableCell, TableHead, TableRow } from '../Table'\n\nexport interface BalanceSheetTableStringOverrides {\n typeColumnHeader?: string\n totalColumnHeader?: string\n}\n\ntype BalanceSheetRowProps = {\n name: string\n displayName: string\n lineItem: string\n}\n\nexport const BalanceSheetTable = ({\n data,\n config,\n stringOverrides,\n}: {\n data: BalanceSheet\n config: BalanceSheetRowProps[]\n stringOverrides?: BalanceSheetTableStringOverrides\n}) => {\n const { isOpen, setIsOpen, expandedAllRows } = useTableExpandRow()\n const allRowKeys: string[] = []\n\n useEffect(() => {\n if (expandedAllRows) {\n setIsOpen(allRowKeys, true)\n }\n }, [expandedAllRows])\n\n useEffect(() => {\n setIsOpen(['assets'])\n }, [])\n\n const renderLineItem = (\n lineItem: LineItem,\n depth: number = 0,\n rowKey: string,\n rowIndex: number,\n ): React.ReactNode => {\n const expandable = !!lineItem.line_items && lineItem.line_items.length > 0\n\n const expanded = expandable ? isOpen(rowKey) : true\n\n const showChildren = expanded || expandedAllRows\n\n if (expandable) {\n allRowKeys.push(rowKey)\n }\n\n return (\n <React.Fragment key={rowKey + '-' + rowIndex}>\n <TableRow\n rowKey={rowKey + '-' + rowIndex}\n expandable={expandable}\n isExpanded={showChildren}\n handleExpand={() => setIsOpen(rowKey)}\n depth={depth}\n withDivider={depth === 0 && rowIndex > 0}\n >\n <TableCell withExpandIcon={expandable} primary={expandable}>\n {lineItem.display_name}\n </TableCell>\n <TableCell\n isCurrency={!expandable || (expandable && !expanded)}\n primary={expandable}\n >\n {(!expandable || (expandable && !expanded)) && lineItem.value}\n </TableCell>\n </TableRow>\n {showChildren &&\n lineItem.line_items &&\n lineItem.line_items.map((subItem, subIdx) =>\n renderLineItem(\n subItem,\n depth + 1,\n rowKey + ':' + subItem.name,\n subIdx,\n ),\n )}\n {showChildren && expandable && (\n <TableRow\n rowKey={rowKey + '-' + rowIndex + '--summation'}\n depth={depth + 1}\n variant='summation'\n >\n <TableCell primary>{`Total of ${lineItem.display_name}`}</TableCell>\n <TableCell primary isCurrency>\n {lineItem.value}\n </TableCell>\n </TableRow>\n )}\n </React.Fragment>\n )\n }\n\n return (\n <Table borderCollapse='collapse'>\n <TableHead>\n <TableRow isHeadRow rowKey='balance-sheet-head-row'>\n <TableCell isHeaderCell>{stringOverrides?.typeColumnHeader || \"Type\"}</TableCell>\n <TableCell isHeaderCell>{stringOverrides?.totalColumnHeader || \"Total\"}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {config.map((row, idx) => (\n <React.Fragment key={row.lineItem}>\n {data[row.lineItem as keyof BalanceSheet] &&\n renderLineItem(\n data[row.lineItem as keyof BalanceSheet] as LineItem,\n 0,\n row.lineItem,\n idx,\n )}\n </React.Fragment>\n ))}\n </TableBody>\n </Table>\n )\n}\n", "import React from 'react'\nimport { TableBodyProps } from '../../types/table'\n\nexport const TableBody = ({ children }: TableBodyProps) => {\n return <tbody className='Layer__table-body'>{children}</tbody>\n}\n", "import React from 'react'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { centsToDollars } from '../../models/Money'\nimport { TableCellProps } from '../../types/table'\nimport classNames from 'classnames'\n\nexport const TableCell = ({\n children,\n isHeaderCell,\n isCurrency,\n primary,\n withExpandIcon = false,\n}: TableCellProps) => {\n const amount = typeof children === 'number' ? children : 0\n const isPositive = amount >= 0\n const amountString = centsToDollars(Math.abs(amount))\n\n const cellClassNames = classNames(\n 'Layer__table-cell',\n (primary || isHeaderCell) && 'Layer__table-cell--primary',\n isCurrency && 'Layer__table-cell-amount',\n isCurrency && isPositive && 'Layer__table-cell-amount--positive',\n isCurrency && !isPositive && 'Layer__table-cell-amount--negative',\n )\n\n if (isHeaderCell) {\n return (\n <th className={cellClassNames}>\n <span className='Layer__table-cell-content'>{children}</span>\n </th>\n )\n }\n\n return (\n <td className={cellClassNames}>\n <span className='Layer__table-cell-content'>\n {withExpandIcon && (\n <ChevronDownFill\n className='Layer__table-row--expand-icon'\n size={16}\n />\n )}\n {isCurrency ? amountString : children}{' '}\n </span>\n </td>\n )\n}\n", "import React from 'react'\nimport { TableHeadProps } from '../../types/table'\n\nexport const TableHead = ({ children }: TableHeadProps) => {\n return <thead className='Layer__table-header'>{children}</thead>\n}\n", "import React from 'react'\nimport { TableRowProps } from '../../types/table'\nimport classNames from 'classnames'\n\nexport const TableRow: React.FC<TableRowProps> = ({\n rowKey,\n children,\n depth = 0,\n expandable = false,\n isExpanded = false,\n handleExpand,\n variant = expandable ? 'expandable' : 'default',\n withDivider,\n withDividerPosition = 'top',\n isHeadRow = false,\n}) => {\n const toggleExpanded = () => {\n if (variant === 'summation' || !expandable) return\n handleExpand && handleExpand()\n }\n\n const rowClassNames = classNames([\n 'Layer__table-row',\n !isHeadRow && `Layer__table-row--depth-${depth}`,\n !isHeadRow && `Layer__table-row--variant-${variant}`,\n !isHeadRow &&\n expandable &&\n (isExpanded\n ? 'Layer__table-row--expanded'\n : 'Layer__table-row--collapsed'),\n ])\n\n return (\n <>\n {withDivider && withDividerPosition === 'top' && (\n <tr className='Layer__table-empty-row'>\n <td colSpan={Array.isArray(children) ? children.length : 1} />\n </tr>\n )}\n\n <tr data-key={rowKey} className={rowClassNames} onClick={toggleExpanded}>\n {children}\n </tr>\n\n {withDivider && withDividerPosition === 'bottom' && (\n <tr className='Layer__table-empty-row'>\n <td colSpan={Array.isArray(children) ? children.length : 1} />\n </tr>\n )}\n </>\n )\n}\n", "import React, { useEffect, useRef } from 'react'\nimport { TableProps } from '../../types/table'\nimport classNames from 'classnames'\n\nexport const Table = ({\n componentName,\n children,\n borderCollapse = 'separate',\n bottomSpacing = true,\n}: TableProps) => {\n const tableRef = useRef<HTMLTableElement>(null)\n const prevChildrenRef = useRef<string[]>([])\n\n useEffect(() => {\n if (tableRef.current) {\n const tbody = tableRef.current.querySelector('tbody')\n const rows = tbody ? Array.from(tbody.querySelectorAll('tr')) : []\n\n const prevChildrenArray = prevChildrenRef.current\n const currentChildren = rows.map(\n child =>\n child.getAttribute('data-key') && {\n key: child.getAttribute('data-key'),\n child,\n },\n )\n const newChildrenKeys: string[] = []\n\n const newChildrenArray = currentChildren.filter(el => {\n if (el && el.key) {\n newChildrenKeys.push(el.key)\n }\n return el && el.key && !prevChildrenArray.includes(el.key)\n })\n\n newChildrenArray.forEach((row, index: number) => {\n const rowKey = row && row.key\n if (rowKey && !row.child.classList.contains('Layer__table-empty-row')) {\n row.child.classList.add('Layer__table-row--anim-starting-state')\n\n setTimeout(() => {\n row.child.classList.add('Layer__table-row--anim-complete-state')\n row.child.classList.remove('Layer__table-row--anim-starting-state')\n }, 15 * index)\n }\n })\n\n prevChildrenRef.current = newChildrenKeys as string[]\n }\n }, [children])\n\n const tableWrapperClassNames = classNames(\n 'Layer__table-wrapper',\n bottomSpacing && 'Layer__table-wrapper--bottom-spacing',\n )\n\n const tableClassNames = classNames(\n 'Layer__table',\n componentName && `Layer__${componentName}__table`,\n borderCollapse && `Layer__table__${borderCollapse}-rows`,\n )\n return (\n <div className={tableWrapperClassNames}>\n <table className={tableClassNames} ref={tableRef}>\n {children}\n </table>\n </div>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport { ViewHeader } from '../../components/ViewHeader'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { parseStylesFromThemeConfig } from '../../utils/colors'\nimport { Panel } from '../Panel'\nimport classNames from 'classnames'\n\nexport interface ViewProps {\n children: ReactNode\n title?: string\n headerControls?: ReactNode\n type?: 'default' | 'panel'\n withSidebar?: boolean\n sidebar?: ReactNode\n viewClassName?: string\n}\n\nexport const View = ({\n title,\n children,\n headerControls,\n type,\n withSidebar = false,\n sidebar,\n viewClassName,\n}: ViewProps) => {\n const { theme } = useLayerContext()\n const styles = parseStylesFromThemeConfig(theme)\n\n const viewClassNames = classNames(\n 'Layer__view',\n type === 'panel' && 'Layer__view--panel',\n viewClassName,\n )\n\n return (\n <div className={viewClassNames} style={{ ...styles }}>\n <ViewHeader title={title} controls={headerControls} />\n {withSidebar ? (\n <Panel sidebarIsOpen={true} sidebar={sidebar} defaultSidebarHeight>\n <div className='Layer__view-main'>{children}</div>\n </Panel>\n ) : (\n <div className='Layer__view-main'>{children}</div>\n )}\n </div>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport { Heading } from '../Typography'\n\nexport interface ViewHeaderProps {\n title?: string\n controls?: ReactNode\n}\n\nexport const ViewHeader = ({ title, controls }: ViewHeaderProps) => {\n return (\n <div className='Layer__view-header'>\n <div className='Layer__view-header__content'>\n {title && <Heading>{title}</Heading>}\n {controls && (\n <div className='Layer__view-header__controls'>{controls}</div>\n )}\n </div>\n </div>\n )\n}\n", "import React, { ReactNode, RefObject, useEffect, useState } from 'react'\nimport classNames from 'classnames'\n\nexport interface PanelProps {\n children: ReactNode\n className?: string\n sidebar?: ReactNode\n sidebarIsOpen?: boolean\n header?: ReactNode\n parentRef?: RefObject<HTMLDivElement>\n defaultSidebarHeight?: boolean\n}\n\nexport const Panel = ({\n children,\n className,\n sidebar,\n header,\n sidebarIsOpen,\n parentRef,\n defaultSidebarHeight = false,\n}: PanelProps) => {\n const [sidebarHeight, setSidebarHeight] = useState(0)\n\n useEffect(() => {\n if (parentRef?.current?.offsetHeight) {\n setSidebarHeight(parentRef?.current?.offsetHeight - 1)\n }\n }, [parentRef?.current?.offsetHeight, sidebarIsOpen])\n\n const sidebarClass = classNames(\n 'Layer__panel__sidebar',\n defaultSidebarHeight && 'Layer__panel__sidebar--default',\n )\n\n return (\n <div\n className={classNames(\n 'Layer__panel',\n className,\n sidebarIsOpen && 'Layer__panel--open',\n )}\n >\n <div className={'Layer__panel__content'}>\n {header}\n {children}\n </div>\n {sidebar && (\n <div\n className={sidebarClass}\n style={\n !defaultSidebarHeight\n ? {\n maxHeight:\n sidebarHeight > 0 && sidebarIsOpen ? sidebarHeight : 0,\n }\n : {}\n }\n >\n <div className='Layer__panel__sidebar-content'>{sidebar}</div>\n </div>\n )}\n </div>\n )\n}\n", "export const BALANCE_SHEET_ROWS = [\n {\n name: 'Assets',\n displayName: 'Assets',\n lineItem: 'assets',\n },\n {\n name: 'LiabilitiesAndEquity',\n displayName: 'Liabilities & Equity',\n lineItem: 'liabilities_and_equity',\n },\n]\n", "import React, { useState } from 'react'\nimport { StatementOfCashFlowContext } from '../../contexts/StatementOfCashContext'\nimport { TableProvider } from '../../contexts/TableContext'\nimport { useStatementOfCashFlow } from '../../hooks/useStatementOfCashFlow'\nimport { DatePicker } from '../DatePicker'\nimport { Loader } from '../Loader'\nimport { StatementOfCashFlowTable } from '../StatementOfCashFlowTable'\nimport { View } from '../View'\nimport { STATEMENT_OF_CASH_FLOW_ROWS } from './constants'\nimport { startOfDay, subWeeks } from 'date-fns'\nimport { StatementOfCashFlowTableStringOverrides } from '../StatementOfCashFlowTable/StatementOfCashFlowTable'\n\nconst COMPONENT_NAME = 'statement-of-cash-flow'\n\nexport interface StatementOfCashFlowStringOverrides {\n statementOfCashFlowTable?: StatementOfCashFlowTableStringOverrides\n}\n\nexport const StatementOfCashFlow = ({ stringOverrides }: { stringOverrides?: StatementOfCashFlowStringOverrides }) => {\n const cashContextData = useStatementOfCashFlow()\n return (\n <StatementOfCashFlowContext.Provider value={cashContextData}>\n <StatementOfCashFlowView stringOverrides={stringOverrides} />\n </StatementOfCashFlowContext.Provider>\n )\n}\n\nconst StatementOfCashFlowView = ( { stringOverrides }: {stringOverrides?: StatementOfCashFlowStringOverrides }) => {\n const [startDate, setStartDate] = useState(\n startOfDay(subWeeks(new Date(), 4)),\n )\n const [endDate, setEndDate] = useState(startOfDay(new Date()))\n const { data, isLoading, refetch } = useStatementOfCashFlow(\n startDate,\n endDate,\n )\n\n const handleDateChange = (dates: [Date | null, Date | null]) => {\n if (dates[0]) {\n setStartDate(startOfDay(dates[0]))\n }\n if (dates[1]) {\n setEndDate(startOfDay(dates[1]))\n }\n\n if (dates[0] && dates[1]) {\n refetch()\n }\n }\n\n return (\n <TableProvider>\n <View\n type='panel'\n headerControls={\n <>\n <DatePicker\n selected={[startDate, endDate]}\n onChange={dates =>\n handleDateChange(dates as [Date | null, Date | null])\n }\n dateFormat='MMM d'\n mode='dayRangePicker'\n />\n </>\n }\n >\n {!data || isLoading ? (\n <div className={`Layer__${COMPONENT_NAME}__loader-container`}>\n <Loader />\n </div>\n ) : (\n <StatementOfCashFlowTable\n data={data}\n config={STATEMENT_OF_CASH_FLOW_ROWS}\n stringOverrides={stringOverrides?.statementOfCashFlowTable}\n />\n )}\n </View>\n </TableProvider>\n )\n}\n", "import { createContext } from 'react'\nimport { useStatementOfCashFlow } from '../../hooks/useStatementOfCashFlow'\n\nexport type StatementOfCashFlowContextType = ReturnType<\n typeof useStatementOfCashFlow\n>\nexport const StatementOfCashFlowContext =\n createContext<StatementOfCashFlowContextType>({\n data: undefined,\n isLoading: false,\n error: undefined,\n refetch: () => {},\n })\n", "import { useEffect } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { StatementOfCashFlow } from '../../types'\nimport { DataModel } from '../../types/general'\nimport { format, startOfDay } from 'date-fns'\nimport useSWR from 'swr'\n\ntype UseStatementOfCashFlow = (\n startDate?: Date,\n endDate?: Date,\n) => {\n data: StatementOfCashFlow | undefined\n isLoading: boolean\n error: unknown\n refetch: () => void\n}\n\nexport const useStatementOfCashFlow: UseStatementOfCashFlow = (\n startDate: Date = new Date(),\n endDate: Date = new Date(),\n) => {\n const { auth, businessId, apiUrl, read, syncTimestamps, hasBeenTouched } =\n useLayerContext()\n const startDateString = format(\n startOfDay(startDate),\n \"yyyy-MM-dd'T'HH:mm:ssXXX\",\n )\n const endDateString = format(startOfDay(endDate), \"yyyy-MM-dd'T'HH:mm:ssXXX\")\n\n const queryKey =\n businessId &&\n startDateString &&\n endDateString &&\n auth?.access_token &&\n `statement-of-cash-${businessId}-${startDateString}-${endDateString}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getStatementOfCashFlow(apiUrl, auth?.access_token, {\n params: {\n businessId,\n startDate: startDateString,\n endDate: endDateString,\n },\n }),\n )\n\n const refetch = () => {\n mutate()\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.STATEMENT_OF_CASH_FLOWS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps, startDateString, endDateString])\n\n return { data: data?.data, isLoading, error, refetch }\n}\n", "import React from 'react'\nimport { useTableExpandRow } from '../../hooks/useTableExpandRow'\nimport { StatementOfCashFlow } from '../../types'\nimport { LineItem } from '../../types/line_item'\nimport { Table, TableHead, TableBody, TableRow, TableCell } from '../Table'\n\ntype StatementOfCashFlowRowProps = {\n name: string\n displayName: string\n lineItem: string | undefined\n summarize: boolean\n type: string\n}\n\nexport interface StatementOfCashFlowTableStringOverrides {\n typeColumnHeader?: string\n totalColumnHeader?: string\n}\n\nexport const StatementOfCashFlowTable = ({\n data,\n config,\n stringOverrides,\n}: {\n data: StatementOfCashFlow\n config: StatementOfCashFlowRowProps[]\n stringOverrides?: StatementOfCashFlowTableStringOverrides\n}) => {\n const { isOpen, setIsOpen } = useTableExpandRow()\n\n const renderLineItem = (\n lineItem: LineItem,\n depth: number = 0,\n rowKey: string,\n rowIndex: number,\n ): React.ReactNode => {\n const expandable = !!lineItem.line_items && lineItem.line_items.length > 0\n const expanded = expandable ? isOpen(rowKey) : true\n\n return (\n <React.Fragment key={rowKey + '-' + rowIndex}>\n <TableRow\n rowKey={rowKey + '-' + rowIndex}\n expandable={expandable}\n isExpanded={expanded}\n handleExpand={() => setIsOpen(rowKey)}\n depth={depth}\n >\n <TableCell withExpandIcon={expandable} primary={expandable}>\n {lineItem.display_name}\n </TableCell>\n <TableCell\n isCurrency={!expandable || (expandable && !expanded)}\n primary={expandable}\n >\n {(!expandable || (expandable && !expanded)) && lineItem.value}\n </TableCell>\n </TableRow>\n {expanded &&\n lineItem.line_items &&\n lineItem.line_items.map((subItem, subIdx) =>\n renderLineItem(\n subItem,\n depth + 1,\n rowKey + ':' + subItem.name,\n subIdx,\n ),\n )}\n {expanded && expandable && (\n <TableRow\n rowKey={rowKey + '-' + rowIndex + '--summation'}\n depth={depth + 1}\n variant='summation'\n >\n <TableCell primary>{`Total of ${lineItem.display_name}`}</TableCell>\n <TableCell primary isCurrency>\n {lineItem.value}\n </TableCell>\n </TableRow>\n )}\n </React.Fragment>\n )\n }\n\n return (\n <Table borderCollapse='collapse'>\n <TableHead>\n <TableRow rowKey='soc-flow-head-row' isHeadRow>\n <TableCell isHeaderCell>{stringOverrides?.typeColumnHeader || \"Type\"}</TableCell>\n <TableCell isHeaderCell>{stringOverrides?.totalColumnHeader || \"Total\"}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {config.map((row, idx) => {\n if (row.type === 'line_item') {\n return (\n <React.Fragment key={row.lineItem}>\n {data[row.lineItem as keyof StatementOfCashFlow] &&\n renderLineItem(\n data[row.lineItem as keyof StatementOfCashFlow] as LineItem,\n 0,\n row.lineItem ? row.lineItem : '',\n idx,\n )}\n </React.Fragment>\n )\n } else {\n return (\n <TableRow rowKey={row.name + '-' + idx} variant='default'>\n <TableCell primary>{row.displayName}</TableCell>\n <TableCell primary isCurrency>\n {row.lineItem}\n </TableCell>\n </TableRow>\n )\n }\n })}\n </TableBody>\n </Table>\n )\n}\n", "export const STATEMENT_OF_CASH_FLOW_ROWS = [\n {\n name: 'FinancingActivities',\n displayName: 'Financing Activities',\n lineItem: 'financing_activities',\n type: 'line_item',\n summarize: true,\n },\n {\n name: 'InvestingActivities',\n displayName: 'Investing Activities',\n lineItem: 'investing_activities',\n type: 'line_item',\n summarize: true,\n },\n {\n name: 'OperatingActivities',\n displayName: 'Operating Activities',\n lineItem: 'operating_activities',\n type: 'line_item',\n summarize: true,\n },\n {\n name: 'PeriodNetCashIncrease',\n displayName: 'Net Cash Increase For Period',\n lineItem: 'period_net_cash_increase',\n type: 'summary_value',\n summarize: false,\n },\n {\n name: 'CashAtEndOfPeriod',\n displayName: 'Cash at End of Period',\n lineItem: 'cash_at_end_of_period',\n type: 'summary_value',\n summarize: false,\n },\n]\n\nexport const ADJUSTMENTS_ROW_NAME = 'Adjustments to Net Income'\n", "import React, { useContext, useState } from 'react'\nimport { BREAKPOINTS } from '../../config/general'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { LedgerAccountsContext } from '../../contexts/LedgerAccountsContext'\nimport { useChartOfAccounts } from '../../hooks/useChartOfAccounts'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { useLedgerAccounts } from '../../hooks/useLedgerAccounts'\nimport { ChartOfAccountsTable } from '../ChartOfAccountsTable'\nimport { Container } from '../Container'\nimport { LedgerAccount } from '../LedgerAccount'\nimport { ChartOfAccountsTableStringOverrides } from '../ChartOfAccountsTable/ChartOfAccountsTable'\nimport { LedgerAccountStringOverrides } from '../LedgerAccount/LedgerAccountIndex'\n\nexport type View = 'mobile' | 'tablet' | 'desktop'\n\nexport interface ChartOfAccountsStringOverrides {\n chartOfAccountsTable?: ChartOfAccountsTableStringOverrides\n ledgerAccount?: LedgerAccountStringOverrides\n}\n\nexport interface ChartOfAccountsProps {\n asWidget?: boolean\n withDateControl?: boolean\n withExpandAllButton?: boolean\n stringOverrides?: ChartOfAccountsStringOverrides\n}\n\nexport const ChartOfAccounts = (props: ChartOfAccountsProps) => {\n const chartOfAccountsContextData = useChartOfAccounts({\n withDates: props.withDateControl,\n })\n const ledgerAccountsContextData = useLedgerAccounts()\n return (\n <ChartOfAccountsContext.Provider value={chartOfAccountsContextData}>\n <LedgerAccountsContext.Provider value={ledgerAccountsContextData}>\n <ChartOfAccountsContent {...props} />\n </LedgerAccountsContext.Provider>\n </ChartOfAccountsContext.Provider>\n )\n}\n\nconst ChartOfAccountsContent = ({\n asWidget,\n withDateControl,\n withExpandAllButton,\n stringOverrides,\n}: ChartOfAccountsProps) => {\n const { accountId } = useContext(LedgerAccountsContext)\n\n const [view, setView] = useState<View>('desktop')\n\n const containerRef = useElementSize<HTMLDivElement>((_a, _b, { width }) => {\n if (width) {\n if (width >= BREAKPOINTS.TABLET && view !== 'desktop') {\n setView('desktop')\n } else if (\n width <= BREAKPOINTS.TABLET &&\n width > BREAKPOINTS.MOBILE &&\n view !== 'tablet'\n ) {\n setView('tablet')\n } else if (width < BREAKPOINTS.MOBILE && view !== 'mobile') {\n setView('mobile')\n }\n }\n })\n\n return (\n <Container name='chart-of-accounts' ref={containerRef} asWidget={asWidget}>\n {accountId ? (\n <LedgerAccount view={view} containerRef={containerRef} stringOverrides={stringOverrides?.ledgerAccount}/>\n ) : (\n <ChartOfAccountsTable\n asWidget={asWidget}\n withDateControl={withDateControl}\n withExpandAllButton={withExpandAllButton}\n view={view}\n containerRef={containerRef}\n stringOverrides={stringOverrides?.chartOfAccountsTable}\n />\n )}\n </Container>\n )\n}\n", "import { createContext } from 'react'\nimport { useChartOfAccounts } from '../../hooks/useChartOfAccounts'\nimport { endOfMonth, startOfMonth } from 'date-fns'\n\nexport type ChartOfAccountsContextType = ReturnType<typeof useChartOfAccounts>\nexport const ChartOfAccountsContext = createContext<ChartOfAccountsContextType>(\n {\n data: undefined,\n isLoading: false,\n isValidating: false,\n error: undefined,\n refetch: () => Promise.resolve(undefined),\n create: () => Promise.resolve(undefined),\n form: undefined,\n sendingForm: false,\n apiError: undefined,\n addAccount: () => {},\n editAccount: () => {},\n cancelForm: () => {},\n changeFormData: () => {},\n submitForm: () => {},\n dateRange: {\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n },\n changeDateRange: () => {},\n },\n)\n", "import { createContext } from 'react'\nimport { useLedgerAccounts } from '../../hooks/useLedgerAccounts'\n\nexport type LedgerAccountsContextType = ReturnType<typeof useLedgerAccounts>\nexport const LedgerAccountsContext = createContext<LedgerAccountsContextType>({\n data: undefined,\n entryData: undefined,\n isLoading: false,\n isLoadingEntry: false,\n isValidating: false,\n isValidatingEntry: false,\n error: undefined,\n errorEntry: undefined,\n refetch: () => {},\n accountId: undefined,\n setAccountId: () => {},\n selectedEntryId: undefined,\n setSelectedEntryId: () => {},\n closeSelectedEntry: () => {},\n})\n", "import { useEffect, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { NORMALITY_OPTIONS } from '../../components/ChartOfAccountsForm/constants'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { FormError, DateRange, Direction, NewAccount } from '../../types'\nimport {\n ChartWithBalances,\n EditAccount,\n LedgerAccountBalance,\n} from '../../types/chart_of_accounts'\nimport { BaseSelectOption, DataModel } from '../../types/general'\nimport { endOfMonth, formatISO, startOfMonth } from 'date-fns'\nimport useSWR from 'swr'\n\nconst validate = (formData?: ChartOfAccountsForm) => {\n const errors: FormError[] = []\n\n const nameError = validateName(formData)\n if (nameError) {\n errors.push(nameError)\n }\n const normalityError = validateNormality(formData)\n if (normalityError) {\n errors.push(normalityError)\n }\n const typeError = validateType(formData)\n if (typeError) {\n errors.push(typeError)\n }\n\n return errors\n}\n\nconst revalidateField = (fieldName: string, formData?: ChartOfAccountsForm) => {\n switch (fieldName) {\n case 'name': {\n const nameError = validateName(formData)\n if (nameError) {\n return (formData?.errors || [])\n .filter(x => x.field !== fieldName)\n .concat([nameError])\n }\n\n return (formData?.errors || []).filter(x => x.field !== fieldName)\n }\n case 'normality': {\n const normalityError = validateNormality(formData)\n if (normalityError) {\n return (formData?.errors || [])\n .filter(x => x.field !== fieldName)\n .concat([normalityError])\n }\n\n return (formData?.errors || []).filter(x => x.field !== fieldName)\n }\n case 'type': {\n const typeError = validateType(formData)\n if (typeError) {\n return (formData?.errors || [])\n .filter(x => x.field !== fieldName)\n .concat([typeError])\n }\n\n return (formData?.errors || []).filter(x => x.field !== fieldName)\n }\n default:\n return formData?.errors\n }\n}\n\nconst validateType = (formData?: ChartOfAccountsForm) => {\n if (!formData?.data.type?.value) {\n return {\n field: 'type',\n message: 'Must be selected',\n }\n }\n\n return\n}\n\nconst validateNormality = (formData?: ChartOfAccountsForm) => {\n const stringValueNormality = formData?.data.normality?.value?.toString()\n if (stringValueNormality === undefined) {\n return {\n field: 'normality',\n message: 'Must be selected',\n }\n } else if (!['DEBIT', 'CREDIT'].includes(stringValueNormality)) {\n return {\n field: 'normality',\n message: 'Must be selected',\n }\n }\n\n return\n}\n\nconst validateName = (formData?: ChartOfAccountsForm) => {\n if (!formData?.data.name?.trim()) {\n return {\n field: 'name',\n message: 'Cannot be blank',\n }\n }\n\n return\n}\n\nexport interface ChartOfAccountsForm {\n action: 'new' | 'edit'\n accountId?: string\n data: {\n parent?: BaseSelectOption\n stable_name?: string\n name?: string\n type?: BaseSelectOption\n subType?: BaseSelectOption\n normality?: BaseSelectOption\n }\n errors?: FormError[]\n}\n\ntype Props = {\n startDate?: Date\n endDate?: Date\n withDates?: boolean\n}\n\ntype UseChartOfAccounts = () => {\n data: ChartWithBalances | undefined\n isLoading?: boolean\n isValidating?: boolean\n error?: unknown\n refetch: () => void\n create: (newAccount: NewAccount) => void\n form?: ChartOfAccountsForm\n sendingForm?: boolean\n apiError?: string\n addAccount: () => void\n editAccount: (id: string) => void\n cancelForm: () => void\n changeFormData: (\n name: string,\n value: string | BaseSelectOption | undefined,\n ) => void\n submitForm: () => void\n dateRange: DateRange\n changeDateRange: (dateRange: Partial<DateRange>) => void\n}\n\nexport const flattenAccounts = (\n accounts: LedgerAccountBalance[],\n): LedgerAccountBalance[] =>\n accounts\n .flatMap(a => [a, flattenAccounts(a.sub_accounts || [])])\n .flat()\n .filter(id => id)\n\nexport const useChartOfAccounts = (\n { withDates, startDate: initialStartDate, endDate: initialEndDate }: Props = {\n withDates: false,\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n },\n) => {\n const {\n auth,\n businessId,\n apiUrl,\n touch,\n read,\n syncTimestamps,\n hasBeenTouched,\n } = useLayerContext()\n\n const [form, setForm] = useState<ChartOfAccountsForm | undefined>()\n const [sendingForm, setSendingForm] = useState(false)\n const [apiError, setApiError] = useState<string | undefined>(undefined)\n const [startDate, setStartDate] = useState(\n initialStartDate ?? startOfMonth(Date.now()),\n )\n const [endDate, setEndDate] = useState(\n initialEndDate ?? endOfMonth(Date.now()),\n )\n\n const queryKey =\n businessId &&\n auth?.access_token &&\n `chart-of-accounts-${businessId}-${startDate?.valueOf()}-${endDate?.valueOf()}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getLedgerAccountBalances(apiUrl, auth?.access_token, {\n params: {\n businessId,\n startDate:\n withDates && startDate ? formatISO(startDate.valueOf()) : undefined,\n endDate:\n withDates && endDate ? formatISO(endDate.valueOf()) : undefined,\n },\n }),\n )\n\n const create = async (newAccount: NewAccount) => {\n setSendingForm(true)\n setApiError(undefined)\n\n try {\n await Layer.createAccount(apiUrl, auth?.access_token, {\n params: { businessId },\n body: newAccount,\n })\n await refetch()\n setForm(undefined)\n } catch (_err) {\n setApiError('Submit failed. Please, check your connection and try again.')\n } finally {\n setSendingForm(false)\n touch(DataModel.CHART_OF_ACCOUNTS)\n }\n }\n\n const update = async (accountData: EditAccount, accountId: string) => {\n setSendingForm(true)\n setApiError(undefined)\n\n const newAccountData = {\n ...accountData,\n }\n\n try {\n await Layer.updateAccount(apiUrl, auth?.access_token, {\n params: { businessId, accountId },\n body: newAccountData,\n })\n await refetch()\n setForm(undefined)\n } catch (_err) {\n setApiError('Submit failed. Please, check your connection and try again.')\n } finally {\n setSendingForm(false)\n touch(DataModel.CHART_OF_ACCOUNTS)\n }\n }\n\n const submitForm = () => {\n if (!form || !form.action) {\n return\n }\n\n const errors = validate(form)\n\n if (errors.length > 0) {\n setForm({\n ...form,\n errors,\n })\n\n return\n }\n\n const data = {\n name: form.data.name ?? '',\n stable_name: form.data.stable_name,\n parent_id: form.data.parent\n ? {\n type: 'AccountId' as const,\n id: form.data.parent.value as string,\n }\n : undefined,\n account_type: (form.data.type as BaseSelectOption).value.toString(),\n account_subtype: form.data.subType?.value.toString(),\n normality: form.data.normality?.value as Direction,\n }\n\n if (form.action === 'new') {\n create(data)\n return\n }\n\n if (form.action === 'edit' && form.accountId) {\n update(data, form.accountId)\n return\n }\n }\n\n const addAccount = () =>\n setForm({\n action: 'new',\n accountId: undefined,\n data: {\n parent: undefined,\n name: undefined,\n type: undefined,\n normality: undefined,\n subType: undefined,\n },\n })\n\n const editAccount = (id: string) => {\n const allAccounts = flattenAccounts(data?.data?.accounts || [])\n const found = allAccounts?.find(x => x.id === id)\n\n if (!found) {\n return\n }\n\n const parent = allAccounts.find(\n x => x.sub_accounts?.find(el => el.id === found.id),\n )\n\n setForm({\n action: 'edit',\n accountId: id,\n data: {\n parent: parent\n ? {\n value: parent.id,\n label: parent.name,\n }\n : undefined,\n stable_name: found.stable_name,\n name: found.name,\n type: {\n value: found.account_type.value,\n label: found.account_type.display_name,\n },\n\n subType: found.account_subtype\n ? {\n value: found.account_subtype?.value,\n label: found.account_subtype?.display_name,\n }\n : undefined,\n normality: NORMALITY_OPTIONS.find(\n normalityOption => normalityOption.value == found.normality,\n ),\n },\n })\n }\n\n const cancelForm = () => setForm(undefined)\n\n const changeFormData = (\n fieldName: string,\n value: string | BaseSelectOption | undefined,\n ) => {\n if (!form) {\n return\n }\n\n let newFormData = {\n ...form,\n data: {\n ...form.data,\n [fieldName]: value,\n },\n }\n\n /* When setting the parent field, automatically inherit the parent's type & normality fields */\n if (fieldName === 'parent') {\n const allAccounts = flattenAccounts(data?.data?.accounts || [])\n const foundParent = allAccounts?.find(\n x => x.id === (value as BaseSelectOption).value,\n )\n if (foundParent) {\n newFormData = {\n ...newFormData,\n data: {\n ...newFormData.data,\n /* Inherit the parent's type */\n type: {\n value: foundParent.account_type.value,\n label: foundParent.account_type.display_name,\n },\n\n /* If the parent has a subtype, inherit it */\n subType: foundParent.account_subtype\n ? {\n value: foundParent.account_subtype?.value,\n label: foundParent.account_subtype?.display_name,\n }\n : undefined,\n\n /* Inherit the parent's normality */\n normality: NORMALITY_OPTIONS.find(\n normalityOption => normalityOption.value == foundParent.normality,\n ),\n },\n }\n }\n }\n\n const errors = revalidateField(fieldName, newFormData)\n\n setForm({\n ...newFormData,\n errors,\n })\n }\n\n const changeDateRange = ({\n startDate: newStartDate,\n endDate: newEndDate,\n }: Partial<DateRange>) => {\n newStartDate && setStartDate(newStartDate)\n newEndDate && setEndDate(newEndDate)\n }\n\n const refetch = () => mutate()\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.CHART_OF_ACCOUNTS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps, startDate, endDate])\n\n return {\n data: data?.data,\n isLoading,\n isValidating,\n error,\n refetch,\n create,\n form,\n sendingForm,\n apiError,\n addAccount,\n editAccount,\n cancelForm,\n changeFormData,\n submitForm,\n dateRange: { startDate, endDate },\n changeDateRange,\n }\n}\n", "import { Direction } from '../../types'\nimport { BaseSelectOption } from '../../types/general'\n\nexport const LEDGER_ACCOUNT_TYPES: BaseSelectOption[] = [\n {\n value: 'ASSET',\n label: 'Assets',\n },\n {\n value: 'LIABILITY',\n label: 'Liabilities',\n },\n {\n value: 'EQUITY',\n label: 'Equities',\n },\n {\n value: 'REVENUE',\n label: 'Revenue',\n },\n {\n value: 'EXPENSE',\n label: 'Expenses',\n },\n]\n\nexport const DEFAULT_ACCOUNT_TYPE_DIRECTION: Record<string, Direction> = {\n ASSET: Direction.DEBIT,\n LIABILITY: Direction.CREDIT,\n EQUITY: Direction.CREDIT,\n REVENUE: Direction.CREDIT,\n EXPENSE: Direction.DEBIT,\n}\n\nexport const NORMALITY_OPTIONS: BaseSelectOption[] = [\n {\n value: Direction.DEBIT,\n label: 'Debit',\n },\n {\n value: Direction.CREDIT,\n label: 'Credit',\n },\n]\n\nexport const ASSET_LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n {\n value: 'BANK_ACCOUNTS',\n label: 'Bank Accounts',\n },\n {\n value: 'ACCOUNTS_RECEIVABLE',\n label: 'Accounts Receivable',\n },\n {\n value: 'INVENTORY',\n label: 'Inventory',\n },\n {\n value: 'PAYMENT_PROCESSOR_CLEARING_ACCOUNT',\n label: 'Payment Processor Clearing Accounts',\n },\n {\n value: 'FIXED_ASSET',\n label: 'Fixed Assets',\n },\n {\n value: 'CASH',\n label: 'Cash',\n },\n {\n value: 'UNDEPOSITED_FUNDS',\n label: 'Undeposited Funds',\n },\n]\n\nexport const LIABILITY_LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n {\n value: 'LIABILITY',\n label: 'Liabilities',\n },\n {\n value: 'ACCOUNTS_PAYABLE',\n label: 'Accounts Payable',\n },\n {\n value: 'CREDIT_CARD',\n label: 'Credit Cards',\n },\n {\n value: 'SHAREHOLDER_LOAN',\n label: 'Shareholder Loans',\n },\n {\n value: 'PAYROLL_LIABILITY',\n label: 'Payroll Liabilities',\n },\n {\n value: 'SALES_TAXES_PAYABLE',\n label: 'Sales Taxes Payable',\n },\n {\n value: 'LINE_OF_CREDIT',\n label: 'Lines of Credit',\n },\n {\n value: 'NOTES_PAYABLE',\n label: 'Notes Payable',\n },\n {\n value: 'TIPS',\n label: 'Tips',\n },\n {\n value: 'UNEARNED_REVENUE',\n label: 'Unearned Revenue',\n },\n {\n value: 'UNDEPOSITED_OUTFLOWS',\n label: 'Undeposited Outflows',\n },\n]\nexport const EQUITY_LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n {\n value: 'CONTRIBUTIONS',\n label: 'Contributions',\n },\n {\n value: 'DISTRIBUTIONS',\n label: 'Distributions',\n },\n {\n value: 'COMMON_STOCK',\n label: 'Common Stock',\n },\n {\n value: 'ADDITIONAL_PAID_IN_CAPITAL',\n label: 'Additional Paid In Capital',\n },\n {\n value: 'RETAINED_EARNINGS',\n label: 'Retained Earnings',\n },\n {\n value: 'ACCUMULATED_ADJUSTMENTS',\n label: 'Accumulated Adjustments',\n },\n {\n value: 'OPENING_BALANCE_EQUITY',\n label: 'Opening Balance Equity',\n },\n]\n\nexport const REVENUE_LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n {\n value: 'SALES',\n label: 'Sales',\n },\n {\n value: 'UNCATEGORIZED_REVENUE',\n label: 'Uncategorized Revenue',\n },\n {\n value: 'RETURNS_ALLOWANCES',\n label: 'Returns & Allowances',\n },\n]\n\nexport const EXPENSE_LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n {\n value: 'COGS',\n label: 'COGS',\n },\n {\n value: 'OPERATING_EXPENSES',\n label: 'Operating Expenses',\n },\n {\n value: 'PAYROLL',\n label: 'Payroll',\n },\n {\n value: 'TAXES_LICENSES',\n label: 'Taxes & Licenses',\n },\n {\n value: 'BAD_DEBT',\n label: 'Bad Debt',\n },\n {\n value: 'CHARITABLE_CONTRIBUTIONS',\n label: 'Charitable Contributions',\n },\n]\n\nexport const LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n ...ASSET_LEDGER_ACCOUNT_SUBTYPES,\n ...LIABILITY_LEDGER_ACCOUNT_SUBTYPES,\n ...EQUITY_LEDGER_ACCOUNT_SUBTYPES,\n ...REVENUE_LEDGER_ACCOUNT_SUBTYPES,\n ...EXPENSE_LEDGER_ACCOUNT_SUBTYPES,\n]\n\nexport const LEDGER_ACCOUNT_SUBTYPES_FOR_TYPE: Record<\n string,\n BaseSelectOption[]\n> = {\n ASSET: ASSET_LEDGER_ACCOUNT_SUBTYPES,\n LIABILITY: LIABILITY_LEDGER_ACCOUNT_SUBTYPES,\n EQUITY: EQUITY_LEDGER_ACCOUNT_SUBTYPES,\n REVENUE: REVENUE_LEDGER_ACCOUNT_SUBTYPES,\n EXPENSE: EXPENSE_LEDGER_ACCOUNT_SUBTYPES,\n}\n", "import { useEffect, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { LedgerAccounts, LedgerAccountsEntry } from '../../types'\nimport { DataModel } from '../../types/general'\nimport useSWR from 'swr'\n\ntype UseLedgerAccounts = () => {\n data?: LedgerAccounts\n entryData?: LedgerAccountsEntry\n isLoading?: boolean\n isLoadingEntry?: boolean\n isValidating?: boolean\n isValidatingEntry?: boolean\n error?: unknown\n errorEntry?: unknown\n refetch: () => void\n accountId?: string\n setAccountId: (id?: string) => void\n selectedEntryId?: string\n setSelectedEntryId: (id?: string) => void\n closeSelectedEntry: () => void\n}\n\nexport const useLedgerAccounts: UseLedgerAccounts = () => {\n const { auth, businessId, apiUrl, read, syncTimestamps, hasBeenTouched } =\n useLayerContext()\n\n const [accountId, setAccountId] = useState<string | undefined>()\n const [selectedEntryId, setSelectedEntryId] = useState<string | undefined>()\n\n const queryKey =\n businessId &&\n accountId &&\n auth?.access_token &&\n `ledger-accounts-lines-${businessId}-${accountId}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getLedgerAccountsLines(apiUrl, auth?.access_token, {\n params: { businessId, accountId },\n }),\n )\n\n const {\n data: entryData,\n mutate: mutateEntryData,\n isLoading: isLoadingEntry,\n isValidating: isValdiatingEntry,\n error: errorEntry,\n } = useSWR(\n businessId &&\n selectedEntryId &&\n auth?.access_token &&\n `ledger-accounts-entry-${businessId}-${selectedEntryId}}`,\n Layer.getLedgerAccountsEntry(apiUrl, auth?.access_token, {\n params: { businessId, entryId: selectedEntryId },\n }),\n )\n\n const refetch = () => mutate()\n\n const closeSelectedEntry = () => {\n setSelectedEntryId(undefined)\n mutateEntryData()\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.LEDGER_ACCOUNTS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps, accountId])\n\n return {\n data: data?.data,\n entryData: entryData?.data,\n isLoading,\n isLoadingEntry,\n isValidating,\n isValdiatingEntry,\n error,\n errorEntry,\n refetch,\n accountId,\n setAccountId,\n selectedEntryId,\n setSelectedEntryId,\n closeSelectedEntry,\n }\n}\n", "import React, { RefObject, useContext, useState } from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { Button, ButtonVariant } from '../Button'\nimport { View } from '../ChartOfAccounts/ChartOfAccounts'\nimport { ChartOfAccountsDatePicker } from '../ChartOfAccountsDatePicker'\nimport { ChartOfAccountsRow } from '../ChartOfAccountsRow'\nimport { ChartOfAccountsSidebar } from '../ChartOfAccountsSidebar'\nimport { Header } from '../Container'\nimport { HeaderLayout } from '../Container/Header'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { Loader } from '../Loader'\nimport { Panel } from '../Panel'\nimport { Heading, HeadingSize } from '../Typography'\nimport { ChartOfAccountsFormStringOverrides } from '../ChartOfAccountsForm/ChartOfAccountsForm'\n\nconst COMPONENT_NAME = 'chart-of-accounts'\nexport type ExpandActionState = undefined | 'expanded' | 'collapsed'\n\nexport interface ChartOfAccountsTableStringOverrides {\n headerText?: string\n addAccountButtonText?: string\n nameColumnHeader?: string\n typeColumnHeader?: string\n balanceColumnHeader?: string\n subtypeColumnHeader?: string\n chartOfAccountsForm?: ChartOfAccountsFormStringOverrides\n}\n\nexport const ChartOfAccountsTable = ({\n view,\n containerRef,\n asWidget = false,\n withDateControl = false,\n withExpandAllButton = false,\n stringOverrides,\n}: {\n view: View\n containerRef: RefObject<HTMLDivElement>\n asWidget?: boolean\n withDateControl?: boolean\n withExpandAllButton?: boolean\n stringOverrides?: ChartOfAccountsTableStringOverrides\n}) => {\n const { data, isLoading, addAccount, error, isValidating, refetch, form } =\n useContext(ChartOfAccountsContext)\n\n const [expandAll, setExpandAll] = useState<ExpandActionState>()\n\n let cumulativeIndex = 0\n const accountsLength = data?.accounts.length ?? 0\n\n return (\n <Panel\n sidebar={\n <ChartOfAccountsSidebar\n parentRef={containerRef}\n stringOverrides={stringOverrides?.chartOfAccountsForm}\n />}\n sidebarIsOpen={Boolean(form)}\n parentRef={containerRef}\n >\n <Header\n className={`Layer__${COMPONENT_NAME}__header`}\n layout={withDateControl ? HeaderLayout.NEXT_LINE_ACTIONS : undefined}\n >\n <Heading\n className={`Layer__${COMPONENT_NAME}__title`}\n size={asWidget ? HeadingSize.secondary : HeadingSize.primary}\n >\n {stringOverrides?.headerText || \"Chart of Accounts\"}\n </Heading>\n <div\n className={`Layer__${COMPONENT_NAME}__actions Layer__header__actions`}\n >\n {withDateControl || withExpandAllButton ? (\n <div className='Layer__header__actions-col'>\n {withDateControl && <ChartOfAccountsDatePicker />}\n {withExpandAllButton && (\n <Button\n variant={ButtonVariant.secondary}\n onClick={() =>\n setExpandAll(\n !expandAll || expandAll === 'collapsed'\n ? 'expanded'\n : 'collapsed',\n )\n }\n >\n {!expandAll || expandAll === 'collapsed'\n ? 'Expand all rows'\n : 'Collapse all rows'}\n </Button>\n )}\n </div>\n ) : null}\n <div className='Layer__header__actions-col'>\n <Button onClick={() => addAccount()} disabled={isLoading}>\n {stringOverrides?.addAccountButtonText || \"Add Account\"}\n </Button>\n </div>\n </div>\n </Header>\n\n <table className='Layer__chart-of-accounts__table'>\n <thead>\n <tr className='Layer__table-row--header'>\n <th className='Layer__table-header Layer__coa__name'>\n {stringOverrides?.nameColumnHeader || \"Name\"}\n </th>\n <th className='Layer__table-header Layer__coa__type'>\n {stringOverrides?.typeColumnHeader || \"Type\"}\n </th>\n <th className='Layer__table-header Layer__coa__subtype Layer__mobile--hidden'>\n {stringOverrides?.subtypeColumnHeader || \"Sub-Type\"}\n </th>\n <th className='Layer__table-header Layer__coa__balance'>\n {stringOverrides?.balanceColumnHeader || \"Balance\"}\n </th>\n <th className='Layer__table-header Layer__coa__actions' />\n </tr>\n </thead>\n\n <tbody>\n {!error &&\n data?.accounts.map((account, idx) => {\n const currentCumulativeIndex = cumulativeIndex\n cumulativeIndex =\n (account.sub_accounts?.length || 0) + cumulativeIndex + 1\n\n return (\n <ChartOfAccountsRow\n key={account.id}\n account={account}\n depth={0}\n index={idx}\n cumulativeIndex={currentCumulativeIndex}\n expanded={true}\n defaultOpen={true}\n acountsLength={accountsLength}\n view={view}\n expandAll={expandAll}\n />\n )\n })}\n </tbody>\n </table>\n\n {error ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={() => refetch()}\n isLoading={isValidating || isLoading}\n />\n </div>\n ) : null}\n\n {(!data || isLoading) && !error ? (\n <div className={`Layer__${COMPONENT_NAME}__loader-container`}>\n <Loader />\n </div>\n ) : null}\n\n {!isLoading && !error && data?.accounts.length === 0 ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.info}\n title='Accounts were not found'\n description='New account can be created with \"Add Account\".'\n onRefresh={() => refetch()}\n isLoading={isValidating}\n />\n </div>\n ) : null}\n </Panel>\n )\n}\n", "import React, { useContext } from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { DatePicker } from '../DatePicker'\nimport { endOfMonth, startOfMonth } from 'date-fns'\n\nexport const ChartOfAccountsDatePicker = () => {\n const { changeDateRange, dateRange } = useContext(ChartOfAccountsContext)\n\n return (\n <DatePicker\n mode='monthPicker'\n selected={dateRange.startDate}\n onChange={date => {\n if (!Array.isArray(date)) {\n changeDateRange({\n startDate: startOfMonth(date),\n endDate: endOfMonth(date),\n })\n }\n }}\n />\n )\n}\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { LedgerAccountsContext } from '../../contexts/LedgerAccountsContext'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport Edit2 from '../../icons/Edit2'\nimport { centsToDollars } from '../../models/Money'\nimport { LedgerAccountBalance } from '../../types/chart_of_accounts'\nimport { Button, ButtonVariant, TextButton } from '../Button'\nimport { View } from '../ChartOfAccounts/ChartOfAccounts'\nimport { ExpandActionState } from '../ChartOfAccountsTable/ChartOfAccountsTable'\nimport { Text, TextWeight } from '../Typography'\nimport classNames from 'classnames'\n\ntype ChartOfAccountsRowProps = {\n account: LedgerAccountBalance\n depth?: number\n index: number\n cumulativeIndex?: number\n expanded: boolean\n acountsLength: number\n defaultOpen?: boolean\n view?: View\n expandAll?: ExpandActionState\n}\n\nconst INDENTATION = 24\n\nconst EXPANDED_STYLE = {\n height: 52,\n paddingTop: 12,\n paddingBottom: 12,\n opacity: 1,\n}\n\nconst EXPANDED_MOBILE_STYLE = {\n height: 76,\n paddingTop: 12,\n paddingBottom: 12,\n opacity: 1,\n}\n\nconst COLLAPSED_STYLE = {\n height: 0,\n paddingTop: 0,\n paddingBottom: 0,\n opacity: 0.5,\n}\n\nexport const ChartOfAccountsRow = ({\n account,\n depth = 0,\n index,\n cumulativeIndex = 0,\n expanded = false,\n defaultOpen = false,\n acountsLength,\n view,\n expandAll,\n}: ChartOfAccountsRowProps) => {\n const { form, editAccount } = useContext(ChartOfAccountsContext)\n\n const { setAccountId } = useContext(LedgerAccountsContext)\n\n const baseStyle = view === 'desktop' ? EXPANDED_STYLE : EXPANDED_MOBILE_STYLE\n\n const [isOpen, setIsOpen] = useState(defaultOpen)\n const style = expanded\n ? {\n ...baseStyle,\n transitionDelay: `${15 * index}ms`,\n }\n : {\n ...COLLAPSED_STYLE,\n transitionDelay: `${acountsLength - 15 * index}ms`,\n }\n\n const [showComponent, setShowComponent] = useState(false)\n const [prevExpandedAll, setPrevExpandedAll] = useState(expandAll)\n\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, cumulativeIndex * 50)\n\n return () => clearTimeout(timeoutId)\n }, [])\n\n useEffect(() => {\n if (prevExpandedAll !== expandAll && expandAll) {\n setIsOpen(expandAll === 'collapsed' ? false : true)\n }\n }, [expandAll])\n\n const baseClass = classNames(\n 'Layer__table-row',\n isOpen ? 'Layer__table-row--expanded' : 'Layer__table-row--collapsed',\n !expanded && 'Layer__table-row--hidden',\n `Layer__table-row--depth-${depth}`,\n form?.accountId === account.id && 'Layer__table-row--active',\n !showComponent && 'Layer__table-row--anim-starting-state',\n )\n\n const desktopRowClass = classNames(\n baseClass,\n 'Layer__chart-of-accounts__row---desktop',\n )\n const mobileRowClass = classNames(\n baseClass,\n 'Layer__chart-of-accounts__row---mobile',\n )\n\n return (\n <>\n {view === 'desktop' && (\n <tr\n className={desktopRowClass}\n onClick={e => {\n e.preventDefault()\n e.stopPropagation()\n setAccountId(account.id)\n }}\n >\n <td className='Layer__table-cell Layer__coa__name'>\n <span className='Layer__table-cell-content' style={style}>\n <span\n className='Layer__table-cell-content-indentation'\n style={{\n paddingLeft: INDENTATION * depth + 16,\n }}\n >\n {account.sub_accounts && account.sub_accounts.length > 0 && (\n <ChevronDownFill\n size={16}\n className='Layer__table__expand-icon'\n onClick={e => {\n e.stopPropagation()\n setIsOpen(!isOpen)\n }}\n />\n )}\n <span className='Layer__coa__name__text'>{account.name}</span>\n </span>\n </span>\n </td>\n <td className='Layer__table-cell Layer__coa__type'>\n <span\n className='Layer__table-cell-content Layer__mobile--hidden'\n style={style}\n >\n {account.account_type?.display_name}\n </span>\n <span\n className='Layer__table-cell-content Layer__desktop--hidden'\n style={style}\n >\n <Text\n weight={TextWeight.bold}\n className='Layer__coa__type--mobile'\n >\n {account.normality}\n </Text>\n <Text className='Layer__coa__subtype--mobile'>\n {account.account_subtype?.display_name}\n </Text>\n </span>\n </td>\n <td className='Layer__table-cell Layer__coa__subtype Layer__mobile--hidden'>\n <span className='Layer__table-cell-content' style={style}>\n {account.account_subtype?.display_name}\n </span>\n </td>\n <td className='Layer__table-cell Layer__coa__balance'>\n <span\n className='Layer__table-cell-content Layer__table-cell--amount'\n style={style}\n >\n ${centsToDollars(Math.abs(account.balance || 0))}\n </span>\n </td>\n <td className='Layer__table-cell Layer__coa__actions'>\n <span className='Layer__table-cell-content' style={style}>\n <Button\n variant={ButtonVariant.secondary}\n rightIcon={<Edit2 size={12} />}\n iconOnly={true}\n onClick={e => {\n e.preventDefault()\n e.stopPropagation()\n editAccount(account.id)\n }}\n >\n Edit\n </Button>\n </span>\n </td>\n </tr>\n )}\n\n {view === 'mobile' || view === 'tablet' ? (\n <tr\n className={mobileRowClass}\n onClick={e => {\n e.preventDefault()\n e.stopPropagation()\n setAccountId(account.id)\n }}\n >\n <td className='Layer__table-cell' colSpan={5}>\n <span\n className='Layer__table-cell-content Layer__table-cell-content-indentation'\n style={{\n paddingLeft: INDENTATION * depth + 16,\n ...style,\n }}\n >\n {account.sub_accounts && account.sub_accounts.length > 0 && (\n <ChevronDownFill\n size={16}\n className='Layer__table__expand-icon'\n onClick={e => {\n e.stopPropagation()\n setIsOpen(!isOpen)\n }}\n />\n )}\n <div className='Layer__chart-of-accounts__mobile-row-content'>\n <div className='Layer__chart-of-accounts__mobile-row-content__top-row'>\n <Text\n as='span'\n className='Layer__chart-of-accounts__mobile-row-content__name'\n >\n {account.name}\n </Text>\n <TextButton\n onClick={e => {\n e.preventDefault()\n e.stopPropagation()\n editAccount(account.id)\n }}\n >\n Edit\n </TextButton>\n </div>\n <div className='Layer__chart-of-accounts__mobile-row-content__bottom-row'>\n <div className='Layer__chart-of-accounts__mobile-row-content__types'>\n <Text as='span'>{account.normality}</Text>\n <span className='Layer__chart-of-accounts__mobile-row-content__separator' />\n <Text as='span'>Sub-Type</Text>\n </div>\n <Text\n as='span'\n className='Layer__chart-of-accounts__mobile-row-content__balance'\n >\n ${centsToDollars(Math.abs(account.balance || 0))}\n </Text>\n </div>\n </div>\n </span>\n </td>\n </tr>\n ) : null}\n\n {(account.sub_accounts || []).map((subAccount, idx) => (\n <ChartOfAccountsRow\n key={subAccount.id}\n account={subAccount}\n depth={depth + 1}\n index={idx}\n expanded={isOpen && expanded}\n cumulativeIndex={cumulativeIndex + idx + 1}\n acountsLength={(account.sub_accounts ?? []).length}\n view={view}\n expandAll={expandAll}\n />\n ))}\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Edit2 = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M12.75 2.25C12.947 2.05301 13.1808 1.89676 13.4382 1.79015C13.6956 1.68355 13.9714 1.62868 14.25 1.62868C14.5286 1.62868 14.8044 1.68355 15.0618 1.79015C15.3192 1.89676 15.553 2.05301 15.75 2.25C15.947 2.44698 16.1032 2.68083 16.2098 2.9382C16.3165 3.19557 16.3713 3.47142 16.3713 3.75C16.3713 4.02857 16.3165 4.30442 16.2098 4.56179C16.1032 4.81916 15.947 5.05302 15.75 5.25L5.625 15.375L1.5 16.5L2.625 12.375L12.75 2.25Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\nexport default Edit2\n", "import React, { RefObject } from 'react'\nimport { ChartOfAccountsForm } from '../ChartOfAccountsForm'\nimport { ChartOfAccountsFormStringOverrides } from '../ChartOfAccountsForm/ChartOfAccountsForm'\n\nexport const ChartOfAccountsSidebar = ({\n parentRef: _parentRef,\n stringOverrides,\n}: {\n parentRef?: RefObject<HTMLDivElement>\n stringOverrides?: ChartOfAccountsFormStringOverrides\n}) => {\n return <ChartOfAccountsForm stringOverrides={stringOverrides} />\n}\n", "import React, { useContext, useMemo } from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { flattenAccounts } from '../../hooks/useChartOfAccounts/useChartOfAccounts'\nimport { centsToDollars } from '../../models/Money'\nimport { Button, ButtonVariant, RetryButton, SubmitButton } from '../Button'\nimport { Input, InputGroup, Select } from '../Input'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport {\n LEDGER_ACCOUNT_SUBTYPES,\n LEDGER_ACCOUNT_SUBTYPES_FOR_TYPE,\n LEDGER_ACCOUNT_TYPES,\n NORMALITY_OPTIONS,\n} from './constants'\nimport { useParentOptions } from './useParentOptions'\n\nexport interface ChartOfAccountsFormStringOverrides {\n editModeHeader?: string\n createModeHeader?: string\n cancelButton?: string\n retryButton?: string\n saveButton?: string\n parentLabel?: string\n nameLabel?: string\n typeLabel?: string\n subTypeLabel?: string\n normalityLabel?: string\n}\n\nexport const ChartOfAccountsForm = ({ stringOverrides } : {\n stringOverrides?: ChartOfAccountsFormStringOverrides\n}) => {\n const {\n form,\n data,\n changeFormData,\n cancelForm,\n submitForm,\n sendingForm,\n apiError,\n } = useContext(ChartOfAccountsContext)\n\n const parentOptions = useParentOptions(data)\n\n const entry = useMemo(() => {\n if (form?.action === 'edit' && form.accountId) {\n return flattenAccounts(data?.accounts || []).find(\n x => x.id === form.accountId,\n )\n }\n\n return\n }, [data, form?.accountId])\n\n if (!form) {\n return\n }\n\n return (\n <form\n className='Layer__form'\n onSubmit={e => {\n e.preventDefault()\n submitForm()\n }}\n >\n <div className='Layer__chart-of-accounts__sidebar__header'>\n <Text size={TextSize.lg} weight={TextWeight.bold} className='title'>\n {form?.action === 'edit'\n ? stringOverrides?.editModeHeader || 'Edit Account'\n : stringOverrides?.createModeHeader || 'Add New Account'}\n </Text>\n <div className='actions'>\n <Button\n type='button'\n onClick={cancelForm}\n variant={ButtonVariant.secondary}\n disabled={sendingForm}\n >\n {stringOverrides?.cancelButton || \"Cancel\"}\n </Button>\n {apiError && (\n <RetryButton\n type='submit'\n processing={sendingForm}\n error={'Check connection and retry in few seconds.'}\n disabled={sendingForm}\n >\n {stringOverrides?.retryButton || \"Retry\"}\n </RetryButton>\n )}\n {!apiError && (\n <SubmitButton\n type='submit'\n noIcon={true}\n active={true}\n disabled={sendingForm}\n >\n {stringOverrides?.saveButton || \"Save\"}\n </SubmitButton>\n )}\n </div>\n </div>\n\n {apiError && (\n <Text\n size={TextSize.sm}\n className='Layer__chart-of-accounts__form__error-message'\n >\n {apiError}\n </Text>\n )}\n\n {entry && (\n <div className='Layer__chart-of-accounts__form-edit-entry'>\n <Text weight={TextWeight.bold}>{entry.name}</Text>\n <Text weight={TextWeight.bold}>\n ${centsToDollars(entry.balance || 0)}\n </Text>\n </div>\n )}\n\n <div className='Layer__chart-of-accounts__form'>\n <InputGroup name='parent' label={stringOverrides?.parentLabel || 'Parent'} inline={true}>\n <Select\n options={parentOptions}\n value={form?.data.parent}\n onChange={sel => changeFormData('parent', sel)}\n disabled={sendingForm}\n />\n </InputGroup>\n <InputGroup name='name' label={stringOverrides?.nameLabel || 'Name'} inline={true}>\n <Input\n name='name'\n placeholder='Enter name...'\n value={form?.data.name}\n isInvalid={Boolean(form?.errors?.find(x => x.field === 'name'))}\n errorMessage={form?.errors?.find(x => x.field === 'name')?.message}\n disabled={sendingForm}\n onChange={e =>\n changeFormData('name', (e.target as HTMLInputElement).value)\n }\n />\n </InputGroup>\n <InputGroup name='type' label={stringOverrides?.typeLabel || 'Type'} inline={true}>\n <Select\n options={LEDGER_ACCOUNT_TYPES}\n value={form?.data.type}\n onChange={sel => changeFormData('type', sel)}\n isInvalid={Boolean(form?.errors?.find(x => x.field === 'type'))}\n errorMessage={form?.errors?.find(x => x.field === 'type')?.message}\n disabled={\n sendingForm ||\n form.action === 'edit' ||\n form.data.parent !== undefined\n }\n />\n </InputGroup>\n <InputGroup name='subType' label={stringOverrides?.subTypeLabel || 'Sub-Type'} inline={true}>\n <Select\n options={\n form?.data.type?.value !== undefined\n ? LEDGER_ACCOUNT_SUBTYPES_FOR_TYPE[form?.data.type?.value]\n : LEDGER_ACCOUNT_SUBTYPES\n }\n value={form?.data.subType}\n onChange={sel => changeFormData('subType', sel)}\n disabled={sendingForm}\n />\n </InputGroup>\n <InputGroup name='normality' label={stringOverrides?.normalityLabel || 'Normality'} inline={true}>\n <Select\n options={NORMALITY_OPTIONS}\n value={form?.data.normality}\n isInvalid={Boolean(\n form?.errors?.find(x => x.field === 'normality'),\n )}\n errorMessage={\n form?.errors?.find(x => x.field === 'normality')?.message\n }\n onChange={sel => changeFormData('normality', sel)}\n disabled={sendingForm}\n />\n </InputGroup>\n\n <div className='actions'>\n <Button\n type='button'\n onClick={cancelForm}\n variant={ButtonVariant.secondary}\n disabled={sendingForm}\n >\n {stringOverrides?.cancelButton || \"Cancel\"}\n </Button>\n {apiError && (\n <RetryButton\n type='submit'\n processing={sendingForm}\n error={'Check connection and retry in few seconds.'}\n disabled={sendingForm}\n >\n {stringOverrides?.retryButton || \"Retry\"}\n </RetryButton>\n )}\n {!apiError && (\n <SubmitButton\n type='submit'\n noIcon={true}\n active={true}\n disabled={sendingForm}\n >\n {stringOverrides?.saveButton || \"Save\"}\n </SubmitButton>\n )}\n </div>\n </div>\n </form>\n )\n}\n", "import React, { useMemo } from 'react'\nimport { flattenAccounts } from '../../hooks/useChartOfAccounts/useChartOfAccounts'\nimport { ChartWithBalances } from '../../types/chart_of_accounts'\nimport { BaseSelectOption } from '../../types/general'\n\nexport const useParentOptions = (\n data?: ChartWithBalances,\n): BaseSelectOption[] =>\n useMemo(\n () =>\n flattenAccounts(data?.accounts || [])\n .sort((a, b) => (a?.name && b?.name ? a.name.localeCompare(b.name) : 0))\n .map(x => {\n return {\n label: x.name,\n value: x.id,\n }\n }),\n [data?.accounts?.length],\n )\n", "import React, {\n RefObject,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { LedgerAccountsContext } from '../../contexts/LedgerAccountsContext'\nimport { flattenAccounts } from '../../hooks/useChartOfAccounts/useChartOfAccounts'\nimport { centsToDollars } from '../../models/Money'\nimport { BackButton } from '../Button'\nimport { View } from '../ChartOfAccounts/ChartOfAccounts'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { LedgerAccountEntryDetails } from '../LedgerAccountEntryDetails'\nimport { Loader } from '../Loader'\nimport { Pagination } from '../Pagination'\nimport { Panel } from '../Panel'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport { LedgerAccountRow } from './LedgerAccountRow'\nimport classNames from 'classnames'\nimport { LedgerAccountEntryDetailsStringOverrides } from '../LedgerAccountEntryDetails/LedgerAccountEntryDetails'\n\ninterface LedgerEntriesTableStringOverrides {\n dateColumnHeader?: string\n journalIdColumnHeader?: string\n sourceColumnHeader?: string\n debitColumnHeader?: string\n creditColumnHeader?: string\n runningBalanceColumnHeader?: string\n}\n\nexport interface LedgerAccountStringOverrides {\n ledgerEntryDetail?: LedgerAccountEntryDetailsStringOverrides\n ledgerEntriesTable?: LedgerEntriesTableStringOverrides\n}\n\nexport interface LedgerAccountProps {\n view: View\n containerRef: RefObject<HTMLDivElement>\n pageSize?: number\n stringOverrides?: LedgerAccountStringOverrides\n}\n\nexport const LedgerAccount = ({\n containerRef,\n pageSize = 15,\n view,\n stringOverrides,\n}: LedgerAccountProps) => {\n const [currentPage, setCurrentPage] = useState(1)\n const [initialLoad, setInitialLoad] = useState(true)\n\n const { data: accountData } = useContext(ChartOfAccountsContext)\n\n const {\n data: rawData,\n error,\n isLoading,\n isValidating,\n accountId,\n setAccountId,\n selectedEntryId,\n closeSelectedEntry,\n refetch,\n } = useContext(LedgerAccountsContext)\n\n useEffect(() => {\n if (!isLoading) {\n const timeoutLoad = setTimeout(() => {\n setInitialLoad(false)\n }, 1000)\n return () => clearTimeout(timeoutLoad)\n }\n }, [isLoading])\n\n const baseClassName = classNames(\n 'Layer__ledger-account__index',\n accountId && 'open',\n )\n\n const entry = useMemo(() => {\n return flattenAccounts(accountData?.accounts || []).find(\n x => x.id === accountId,\n )\n }, [accountId])\n\n const data = useMemo(() => {\n const firstPageIndex = (currentPage - 1) * pageSize\n const lastPageIndex = firstPageIndex + pageSize\n return rawData\n ?.sort((a, b) => Date.parse(b.date) - Date.parse(a.date))\n ?.slice(firstPageIndex, lastPageIndex)\n }, [rawData, currentPage])\n\n const close = () => {\n setAccountId(undefined)\n closeSelectedEntry()\n }\n\n return (\n <Panel\n sidebar={\n <LedgerAccountEntryDetails\n stringOverrides={stringOverrides?.ledgerEntryDetail}\n />}\n sidebarIsOpen={Boolean(selectedEntryId)}\n parentRef={containerRef}\n className='Layer__ledger-account__panel'\n >\n <div className={baseClassName}>\n <div className='Layer__ledger-account__header'>\n <BackButton onClick={close} />\n <div className='Layer__ledger-account__title-container'>\n <Text\n weight={TextWeight.bold}\n className='Layer__ledger-account__title'\n >\n {entry?.name ?? ''}\n </Text>\n <div className='Layer__ledger-account__balance-container'>\n <Text\n className='Layer__ledger-account__balance-label'\n size={TextSize.sm}\n >\n Current balance\n </Text>\n <Text\n className='Layer__ledger-account__balance-value'\n size={TextSize.sm}\n >\n ${centsToDollars(entry?.balance || 0)}\n </Text>\n </div>\n </div>\n </div>\n <table className='Layer__table Layer__table--hover-effect Layer__ledger-account-table'>\n <thead>\n <tr>\n {view !== 'desktop' && <th />}\n {view === 'desktop' && (\n <>\n <th className='Layer__table-header'>\n {stringOverrides?.ledgerEntriesTable?.dateColumnHeader || \"Date\"}\n </th>\n <th className='Layer__table-header'>\n {stringOverrides?.ledgerEntriesTable?.journalIdColumnHeader || \"Journal id #\"}\n </th>\n <th className='Layer__table-header'>\n {stringOverrides?.ledgerEntriesTable?.sourceColumnHeader || \"Source\"}\n </th>\n </>\n )}\n {view !== 'mobile' && (\n <>\n <th className='Layer__table-header Layer__table-cell--amount'>\n {stringOverrides?.ledgerEntriesTable?.debitColumnHeader || \"Debit\"}\n </th>\n <th className='Layer__table-header Layer__table-cell--amount'>\n {stringOverrides?.ledgerEntriesTable?.creditColumnHeader || \"Credit\"}\n </th>\n <th className='Layer__table-header Layer__table-cell--amount'>\n {stringOverrides?.ledgerEntriesTable?.runningBalanceColumnHeader || \"Running balance\"}\n </th>\n </>\n )}\n </tr>\n </thead>\n <tbody>\n {data?.map((x, index) => (\n <LedgerAccountRow\n key={x.id}\n row={x}\n index={index}\n initialLoad={initialLoad}\n view={view}\n />\n ))}\n </tbody>\n </table>\n\n {data && (\n <div className='Layer__ledger-account__pagination'>\n <Pagination\n currentPage={currentPage}\n totalCount={rawData?.length || 0}\n pageSize={pageSize}\n onPageChange={page => setCurrentPage(page)}\n />\n </div>\n )}\n\n {error ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={() => refetch()}\n isLoading={isValidating || isLoading}\n />\n </div>\n ) : null}\n\n {(!data || isLoading) && !error ? (\n <div className={`Layer__ledger-account__loader-container`}>\n <Loader />\n </div>\n ) : null}\n\n {!isLoading && !error && data?.length === 0 ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.info}\n title='No records found'\n onRefresh={() => refetch()}\n isLoading={isValidating}\n />\n </div>\n ) : null}\n </div>\n </Panel>\n )\n}\n", "import React, { useContext, useMemo } from 'react'\nimport { LedgerAccountsContext } from '../../contexts/LedgerAccountsContext'\nimport XIcon from '../../icons/X'\nimport { centsToDollars } from '../../models/Money'\nimport { Direction } from '../../types'\nimport {\n InvoiceLedgerEntrySource,\n InvoicePaymentLedgerEntrySource,\n LedgerEntrySource,\n ManualLedgerEntrySource,\n OpeningBalanceLedgerEntrySource,\n PayoutLedgerEntrySource,\n RefundPaymentLedgerEntrySource,\n TransactionLedgerEntrySource,\n} from '../../types/ledger_accounts'\nimport { humanizeEnum } from '../../utils/format'\nimport { Badge, BadgeVariant } from '../Badge'\nimport { BackButton, Button, ButtonVariant } from '../Button'\nimport { Card } from '../Card'\nimport { DateTime } from '../DateTime'\nimport { DetailsList, DetailsListItem } from '../DetailsList'\nimport { Table } from '../Table'\nimport { TableBody } from '../TableBody'\nimport { TableCell } from '../TableCell'\nimport { TableHead } from '../TableHead'\nimport { TableRow } from '../TableRow'\nimport { Text, TextWeight } from '../Typography'\n\ninterface SourceDetailStringOverrides {\n sourceLabel?: string\n accountNameLabel?: string\n dateLabel?: string\n amountLabel?: string\n directionLabel?: string\n counterpartyLabel?: string\n invoiceNumberLabel?: string\n recipientNameLabel?: string\n memoLabel?: string\n createdByLabel?: string\n processorLabel?: string\n}\n\n/*\n\n @SerialName(\"Transaction_Ledger_Entry_Source\")\n @SerialName(\"Invoice_Ledger_Entry_Source\")\n @SerialName(\"Manual_Ledger_Entry_Source\")\n @SerialName(\"Invoice_Payment_Ledger_Entry_Source\")\n @SerialName(\"Refund_Ledger_Entry_Source\")\n @SerialName(\"Opening_Balance_Ledger_Entry_Source\")\n @SerialName(\"Payout_Ledger_Entry_Source\")\n */\nexport const SourceDetailView = (\n { source, stringOverrides }: { source: LedgerEntrySource, stringOverrides?: SourceDetailStringOverrides }\n) => {\n switch (source.type) {\n case 'Transaction_Ledger_Entry_Source': {\n const transactionSource = source as TransactionLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.accountNameLabel || 'Account name'}>\n {transactionSource.account_name}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.dateLabel || 'Date'}>\n <DateTime value={transactionSource.date} />\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.amountLabel || 'Amount'}>\n {`$${centsToDollars(transactionSource.amount)}`}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.directionLabel || 'Direction'}>\n {transactionSource.direction}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.counterpartyLabel || 'Counterparty'}>\n {transactionSource.counterparty}\n </DetailsListItem>\n </>\n )\n }\n case 'Invoice_Ledger_Entry_Source': {\n const invoiceSource = source as InvoiceLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.invoiceNumberLabel || 'Invoice number'}>\n {invoiceSource.invoice_number}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.recipientNameLabel || 'Recipient name'}>\n {invoiceSource.recipient_name}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.dateLabel || 'Date'}>\n <DateTime value={invoiceSource.date} />\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.amountLabel || 'Amount'}>\n {`$${centsToDollars(invoiceSource.amount)}`}\n </DetailsListItem>\n </>\n )\n }\n case 'Manual_Ledger_Entry_Source': {\n const manualSource = source as ManualLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.memoLabel || 'Memo'}>{manualSource.memo}</DetailsListItem>\n <DetailsListItem label={stringOverrides?.createdByLabel || 'Created by'}>\n {manualSource.created_by}\n </DetailsListItem>\n </>\n )\n }\n case 'Invoice_Payment_Ledger_Entry_Source': {\n const invoicePaymentSource = source as InvoicePaymentLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.invoiceNumberLabel || 'Invoice number'}>\n {invoicePaymentSource.invoice_number}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.amountLabel || 'Amount'}>\n {`$${centsToDollars(invoicePaymentSource.amount)}`}\n </DetailsListItem>\n </>\n )\n }\n case 'Refund_Ledger_Entry_Source': {\n const refundSource = source as RefundPaymentLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.amountLabel || 'Amount'}>\n {`$${centsToDollars(refundSource.refunded_to_customer_amount)}`}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.recipientNameLabel || 'Recipient name'}>\n {refundSource.recipient_name}\n </DetailsListItem>\n </>\n )\n }\n case 'Opening_Balance_Ledger_Entry_Source': {\n const openingBalanceSource = source as OpeningBalanceLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.accountNameLabel || 'Account name'}>\n {openingBalanceSource.account_name}\n </DetailsListItem>\n </>\n )\n }\n case 'Payout_Ledger_Entry_Source': {\n const payoutSource = source as PayoutLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.amountLabel || 'Amount'}>\n {`$${centsToDollars(payoutSource.paid_out_amount)}`}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.processorLabel || 'Processor'}>\n {payoutSource.processor}\n </DetailsListItem>\n </>\n )\n }\n\n default:\n return null\n }\n}\n\ninterface JournalEntryDetailsStringOverrides {\n entryTypeLabel?: string\n dateLabel?: string\n creationDateLabel?: string\n reversalLabel?: string\n}\n\ninterface LineItemsTableStringOverrides {\n lineItemsColumnHeader?: string\n debitColumnHeader?: string\n creditColumnHeader?: string\n totalRowHeader?: string\n}\n\nexport interface LedgerAccountEntryDetailsStringOverrides {\n title?: string\n transactionSource?: {\n header?: string\n details?: SourceDetailStringOverrides\n }\n journalEntry?: {\n header?: (entryId?: string) => string\n details?: JournalEntryDetailsStringOverrides\n }\n lineItemsTable?: LineItemsTableStringOverrides\n}\n\nexport const LedgerAccountEntryDetails = ({ stringOverrides } : { stringOverrides?: LedgerAccountEntryDetailsStringOverrides }) => {\n const { entryData, isLoadingEntry, closeSelectedEntry, errorEntry } =\n useContext(LedgerAccountsContext)\n\n const { totalDebit, totalCredit } = useMemo(() => {\n let totalDebit = 0\n let totalCredit = 0\n entryData?.line_items?.forEach(item => {\n if (item.direction === Direction.CREDIT) {\n totalCredit += item.amount || 0\n } else if (item.direction === Direction.DEBIT) {\n totalDebit += item.amount || 0\n }\n })\n\n return { totalDebit, totalCredit }\n }, [entryData])\n\n return (\n <div className='Layer__ledger-account__entry-details'>\n <div className='Layer__ledger-account__entry-details__back-btn'>\n <BackButton onClick={() => closeSelectedEntry()} />\n <div className='Layer__ledger-account__entry-details__title-container'>\n <Text weight={TextWeight.bold}>{stringOverrides?.title || \"Transaction details\"}</Text>\n </div>\n </div>\n <DetailsList\n title={stringOverrides?.transactionSource?.header || 'Transaction source'}\n actions={\n <Button\n rightIcon={<XIcon />}\n iconOnly={true}\n onClick={closeSelectedEntry}\n variant={ButtonVariant.secondary}\n className='Layer__details-list__close-btn'\n />\n }\n >\n <DetailsListItem\n label={stringOverrides?.transactionSource?.details?.sourceLabel || 'Source'}\n isLoading={isLoadingEntry}\n >\n <Badge>{entryData?.source?.entity_name}</Badge>\n </DetailsListItem>\n {entryData?.source?.display_description && (\n <SourceDetailView source={entryData?.source} />\n )}\n </DetailsList>\n\n <DetailsList\n title={\n stringOverrides?.journalEntry?.header ?\n stringOverrides?.journalEntry?.header(entryData?.id.substring(0, 5)) :\n `Journal Entry ${entryData?.id.substring(0, 5)}`\n }\n className='Layer__border-top'\n >\n <DetailsListItem label={stringOverrides?.journalEntry?.details?.entryTypeLabel || 'Entry type'} isLoading={isLoadingEntry}>\n {humanizeEnum(entryData?.entry_type ?? '')}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.journalEntry?.details?.dateLabel || 'Date'} isLoading={isLoadingEntry}>\n {entryData?.entry_at && <DateTime value={entryData?.entry_at} />}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.journalEntry?.details?.creationDateLabel || 'Creation date'} isLoading={isLoadingEntry}>\n {entryData?.date && <DateTime value={entryData?.date} />}\n </DetailsListItem>\n {entryData?.reversal_id && (\n <DetailsListItem label={stringOverrides?.journalEntry?.details?.reversalLabel || 'Reversal'} isLoading={isLoadingEntry}>\n {entryData?.reversal_id.substring(0, 5)}\n </DetailsListItem>\n )}\n </DetailsList>\n\n {!isLoadingEntry && !errorEntry ? (\n <div className='Layer__ledger-account__entry-details__line-items'>\n <Card>\n <Table\n componentName='ledger-account__entry-details'\n borderCollapse='collapse'\n >\n <TableHead>\n <TableRow rowKey='soc-flow-head-row' isHeadRow>\n <TableCell>{stringOverrides?.lineItemsTable?.lineItemsColumnHeader || \"Line items\"}</TableCell>\n <TableCell>{stringOverrides?.lineItemsTable?.debitColumnHeader || \"Debit\"}</TableCell>\n <TableCell>{stringOverrides?.lineItemsTable?.creditColumnHeader || \"Credit\"}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {entryData?.line_items?.map((item, index) => (\n <TableRow\n key={`ledger-line-item-${index}`}\n rowKey={`ledger-line-item-${index}`}\n >\n <TableCell>{item.account?.name || ''}</TableCell>\n <TableCell>\n {item.direction === Direction.DEBIT && (\n <Badge variant={BadgeVariant.WARNING}>\n ${centsToDollars(item.amount || 0)}\n </Badge>\n )}\n </TableCell>\n <TableCell>\n {item.direction === Direction.CREDIT && (\n <Badge variant={BadgeVariant.SUCCESS}>\n ${centsToDollars(item.amount || 0)}\n </Badge>\n )}\n </TableCell>\n </TableRow>\n ))}\n <TableRow\n rowKey='ledger-line-item-summation'\n variant='summation'\n >\n <TableCell primary>{stringOverrides?.lineItemsTable?.totalRowHeader || \"Total\"}</TableCell>\n <TableCell isCurrency primary>\n {totalDebit || 0}\n </TableCell>\n <TableCell isCurrency primary>\n {totalCredit || 0}\n </TableCell>\n </TableRow>\n </TableBody>\n </Table>\n </Card>\n </div>\n ) : null}\n </div>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport classNames from 'classnames'\n\nexport interface CardProps {\n children: ReactNode\n className?: string\n}\n\nexport const Card = ({ children, className }: CardProps) => {\n return <div className={classNames('Layer__card', className)}>{children}</div>\n}\n", "import React from 'react'\nimport { DATE_FORMAT, TIME_FORMAT } from '../../config/general'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport { parseISO, format as formatTime } from 'date-fns'\n\ninterface DateTimeProps {\n value: string\n format?: string\n dateFormat?: string\n timeFormat?: string\n onlyDate?: boolean\n onlyTime?: boolean\n}\n\nexport const DateTime = ({\n value,\n format,\n dateFormat,\n timeFormat,\n onlyDate,\n onlyTime,\n}: DateTimeProps) => {\n if (format) {\n return (\n <Text className='Layer__datetime'>\n {formatTime(parseISO(value), format)}\n </Text>\n )\n }\n\n const date = formatTime(parseISO(value), dateFormat ?? DATE_FORMAT)\n const time = formatTime(parseISO(value), timeFormat ?? TIME_FORMAT)\n\n return (\n <Text className='Layer__datetime'>\n {!onlyTime && (\n <Text\n as='span'\n weight={TextWeight.bold}\n size={TextSize.sm}\n className='Layer__datetime__date'\n >\n {date}\n </Text>\n )}\n {!onlyDate && (\n <Text\n as='span'\n weight={TextWeight.bold}\n size={TextSize.sm}\n className='Layer__datetime__time'\n >\n {time}\n </Text>\n )}\n </Text>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport { Header } from '../Container'\nimport { Heading, HeadingSize } from '../Typography'\nimport classNames from 'classnames'\n\nexport interface DetailsListProps {\n title?: string\n className?: string\n children: ReactNode\n actions?: ReactNode\n}\n\nexport const DetailsList = ({\n title,\n children,\n className,\n actions,\n}: DetailsListProps) => {\n return (\n <div className={classNames('Layer__details-list', className)}>\n {title && (\n <Header>\n <Heading size={HeadingSize.secondary}>{title}</Heading>\n {actions && (\n <div className='Layer__details-list__actions'>{actions}</div>\n )}\n </Header>\n )}\n <ul className='Layer__details-list__list'>{children}</ul>\n </div>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport { SkeletonLoader } from '../SkeletonLoader'\nimport { Text, TextSize, TextWeight } from '../Typography'\n\nexport interface DetailsListItemProps {\n label: string\n children: ReactNode | string\n isLoading?: boolean\n}\n\nconst renderValue = (value: ReactNode | string) => {\n if (typeof value === 'string') {\n return (\n <Text weight={TextWeight.bold} size={TextSize.sm}>\n {value}\n </Text>\n )\n }\n\n return value\n}\n\nexport const DetailsListItem = ({\n label,\n children,\n isLoading,\n}: DetailsListItemProps) => {\n return (\n <li className='Layer__details-list-item'>\n <label className='Layer__details-list-item__label'>{label}</label>\n <span className='Layer__details-list-item__value'>\n {isLoading ? <SkeletonLoader /> : renderValue(children)}\n </span>\n </li>\n )\n}\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport { LedgerAccountsContext } from '../../contexts/LedgerAccountsContext'\nimport { centsToDollars } from '../../models/Money'\nimport { Direction, LedgerAccountLineItem } from '../../types'\nimport { View } from '../ChartOfAccounts/ChartOfAccounts'\nimport { Text, TextWeight } from '../Typography'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface LedgerAccountRowProps {\n row: LedgerAccountLineItem\n index: number\n initialLoad?: boolean\n view: View\n}\n\nexport const LedgerAccountRow = ({\n row,\n index,\n initialLoad,\n view,\n}: LedgerAccountRowProps) => {\n const { selectedEntryId, setSelectedEntryId, closeSelectedEntry } =\n useContext(LedgerAccountsContext)\n\n const [showComponent, setShowComponent] = useState(false)\n\n useEffect(() => {\n if (initialLoad) {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, index * 10)\n\n return () => clearTimeout(timeoutId)\n } else {\n setShowComponent(true)\n }\n }, [])\n\n if (view === 'tablet') {\n return (\n <tr\n className={classNames(\n 'Layer__table-row',\n row.entry_id === selectedEntryId && 'Layer__table-row--active',\n initialLoad && 'initial-load',\n 'Layer__table-row--with-show',\n showComponent ? 'show' : 'Layer__table-row--anim-starting-state',\n )}\n style={{ transitionDelay: `${15 * index}ms` }}\n onClick={() => {\n if (selectedEntryId === row.entry_id) {\n closeSelectedEntry()\n } else {\n setSelectedEntryId(row.entry_id)\n }\n }}\n >\n <td className='Layer__table-cell Layer__ledger-account-table__tablet-main-col'>\n <span className='Layer__table-cell-content'>\n <div className='Layer__ledger-account-table__tablet-main-col__date'>\n <Text>\n {row.date && formatTime(parseISO(row.date), DATE_FORMAT)}\n </Text>\n <Text\n weight={TextWeight.normal}\n className='Layer__ledger_account-table__journal-id'\n >\n {row.entry_id.substring(0, 5)}\n </Text>\n </div>\n <Text>{row.source?.display_description ?? ''}</Text>\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {row.direction === Direction.DEBIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {row.direction === Direction.CREDIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {`$${centsToDollars(row.running_balance)}`}\n </span>\n </td>\n </tr>\n )\n }\n\n if (view === 'mobile') {\n return (\n <tr\n className={classNames(\n 'Layer__table-row',\n row.entry_id === selectedEntryId && 'Layer__table-row--active',\n initialLoad && 'initial-load',\n 'Layer__table-row--with-show',\n showComponent ? 'show' : 'Layer__table-row--anim-starting-state',\n )}\n style={{ transitionDelay: `${15 * index}ms` }}\n onClick={() => {\n if (selectedEntryId === row.entry_id) {\n closeSelectedEntry()\n } else {\n setSelectedEntryId(row.entry_id)\n }\n }}\n >\n <td className='Layer__table-cell Layer__ledger-account-table__tablet-main-col'>\n <span className='Layer__table-cell-content'>\n <div className='Layer__ledger-account-table__tablet-main-col__date'>\n <Text>\n {row.date && formatTime(parseISO(row.date), DATE_FORMAT)}\n </Text>\n <Text\n weight={TextWeight.normal}\n className='Layer__ledger_account-table__journal-id'\n >\n {row.entry_id.substring(0, 5)}\n </Text>\n </div>\n <Text>{row.source?.display_description ?? ''}</Text>\n <div className='Layer__ledger_account-table__balances-mobile'>\n <div className='Layer__ledger_account-table__balance-item'>\n <span className='Layer__ledger_account-table__balances-mobile__label'>\n Debit\n </span>\n <span className='Layer__ledger_account-table__balances-mobile__value'>\n {' '}\n {row.direction === Direction.DEBIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </div>\n <div className='Layer__ledger_account-table__balance-item'>\n <span className='Layer__ledger_account-table__balances-mobile__label'>\n Credit\n </span>\n <span className='Layer__ledger_account-table__balances-mobile__value'>\n {row.direction === Direction.CREDIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </div>\n <div className='Layer__ledger_account-table__balance-item'>\n <span className='Layer__ledger_account-table__balances-mobile__label'>\n Running balance\n </span>\n <span className='Layer__ledger_account-table__balances-mobile__value'>\n {`$${centsToDollars(row.running_balance)}`}\n </span>\n </div>\n </div>\n </span>\n </td>\n </tr>\n )\n }\n\n return (\n <tr\n className={classNames(\n 'Layer__table-row',\n row.entry_id === selectedEntryId && 'Layer__table-row--active',\n initialLoad && 'initial-load',\n 'Layer__table-row--with-show',\n showComponent ? 'show' : 'Layer__table-row--anim-starting-state',\n )}\n style={{ transitionDelay: `${15 * index}ms` }}\n onClick={() => {\n if (selectedEntryId === row.entry_id) {\n closeSelectedEntry()\n } else {\n setSelectedEntryId(row.entry_id)\n }\n }}\n >\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {row.date && formatTime(parseISO(row.date), DATE_FORMAT)}\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {row.entry_id.substring(0, 5)}\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {row.source?.display_description ?? ''}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {row.direction === Direction.DEBIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {row.direction === Direction.CREDIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {`$${centsToDollars(row.running_balance)}`}\n </span>\n </td>\n </tr>\n )\n}\n", "import React, { useState } from 'react'\nimport { BREAKPOINTS } from '../../config/general'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport { TableProvider } from '../../contexts/TableContext'\nimport { useChartOfAccounts } from '../../hooks/useChartOfAccounts'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { useJournal } from '../../hooks/useJournal'\nimport { Container } from '../Container'\nimport { JournalTable } from '../JournalTable'\nimport { JournalTableStringOverrides } from '../JournalTable/JournalTable'\n\nexport type View = 'mobile' | 'tablet' | 'desktop'\n\nexport interface JournalConfig {\n form: {\n addEntryLinesLimit?: number\n }\n}\n\nexport interface JournalStringOverrides {\n journalTable?: JournalTableStringOverrides\n}\n\nexport interface JournalProps {\n asWidget?: boolean\n config?: JournalConfig\n stringOverrides?: JournalStringOverrides\n}\n\nexport const JOURNAL_CONFIG: JournalConfig = {\n form: {\n addEntryLinesLimit: 10,\n },\n}\n\nexport const Journal = (props: JournalProps) => {\n const JournalContextData = useJournal()\n const AccountsContextData = useChartOfAccounts()\n return (\n <ChartOfAccountsContext.Provider value={AccountsContextData}>\n <JournalContext.Provider value={JournalContextData}>\n <TableProvider>\n <JournalContent {...props} />\n </TableProvider>\n </JournalContext.Provider>\n </ChartOfAccountsContext.Provider>\n )\n}\n\nconst JournalContent = ({\n asWidget,\n config = JOURNAL_CONFIG,\n stringOverrides,\n}: JournalProps) => {\n const [view, setView] = useState<View>('desktop')\n\n const containerRef = useElementSize<HTMLDivElement>((_a, _b, { width }) => {\n if (width) {\n if (width >= BREAKPOINTS.TABLET && view !== 'desktop') {\n setView('desktop')\n } else if (\n width <= BREAKPOINTS.TABLET &&\n width > BREAKPOINTS.MOBILE &&\n view !== 'tablet'\n ) {\n setView('tablet')\n } else if (width < BREAKPOINTS.MOBILE && view !== 'mobile') {\n setView('mobile')\n }\n }\n })\n\n return (\n <Container name='journal' ref={containerRef} asWidget={asWidget}>\n <JournalTable\n view={view}\n containerRef={containerRef}\n config={config}\n stringOverrides={stringOverrides?.journalTable}\n />\n </Container>\n )\n}\n", "import { createContext } from 'react'\nimport { useJournal } from '../../hooks/useJournal'\n\nexport type JournalContextType = ReturnType<typeof useJournal>\nexport const JournalContext = createContext<JournalContextType>({\n data: undefined,\n isLoading: false,\n error: undefined,\n refetch: () => {},\n selectedEntryId: undefined,\n setSelectedEntryId: () => {},\n closeSelectedEntry: () => {},\n addEntry: () => {},\n addEntryLine: () => {},\n removeEntryLine: () => {},\n create: () => {},\n changeFormData: () => {},\n submitForm: () => {},\n cancelForm: () => {},\n form: undefined,\n setForm: () => {},\n sendingForm: false,\n apiError: undefined,\n})\n", "import { useEffect, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { get } from '../../api/layer/authenticated_http'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { Direction, FormError, FormErrorWithId } from '../../types'\nimport { LedgerAccountBalance } from '../../types/chart_of_accounts'\nimport { BaseSelectOption, DataModel } from '../../types/general'\nimport {\n JournalEntry,\n JournalEntryLineItem,\n NewApiJournalEntry,\n NewFormJournalEntry,\n} from '../../types/journal'\nimport { getAccountIdentifierPayload } from '../../utils/journal'\nimport { flattenAccounts } from '../useChartOfAccounts/useChartOfAccounts'\nimport useSWR from 'swr'\n\ntype UseJournal = () => {\n data?: JournalEntry[]\n isLoading?: boolean\n isLoadingEntry?: boolean\n isValidating?: boolean\n isValidatingEntry?: boolean\n error?: unknown\n errorEntry?: unknown\n refetch: () => void\n selectedEntryId?: string\n setSelectedEntryId: (id?: string) => void\n closeSelectedEntry: () => void\n create: (newJournalEntry: NewApiJournalEntry) => void\n changeFormData: (\n name: string,\n value: string | BaseSelectOption | undefined | number,\n lineItemIndex?: number,\n accounts?: LedgerAccountBalance[] | undefined,\n ) => void\n submitForm: () => void\n cancelForm: () => void\n addEntry: () => void\n sendingForm: boolean\n form?: JournalFormTypes\n apiError?: string\n setForm: (form?: JournalFormTypes) => void\n addEntryLine: (direction: Direction) => void\n removeEntryLine: (index: number) => void\n}\n\nexport interface JournalFormTypes {\n action: string\n data: NewFormJournalEntry\n errors?:\n | {\n entry: FormError[]\n lineItems: FormErrorWithId[]\n }\n | undefined\n}\n\nexport const useJournal: UseJournal = () => {\n const {\n auth,\n businessId,\n apiUrl,\n touch,\n read,\n syncTimestamps,\n hasBeenTouched,\n } = useLayerContext()\n\n const [selectedEntryId, setSelectedEntryId] = useState<string | undefined>()\n\n const [form, setForm] = useState<JournalFormTypes | undefined>()\n const [addingEntry, setAddingEntry] = useState(false)\n const [sendingForm, setSendingForm] = useState(false)\n const [apiError, setApiError] = useState<string | undefined>(undefined)\n\n const queryKey =\n businessId && auth?.access_token && `journal-lines-${businessId}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getJournal(apiUrl, auth?.access_token, {\n params: { businessId },\n }),\n )\n\n const refetch = () => mutate()\n\n const closeSelectedEntry = () => {\n setSelectedEntryId(undefined)\n }\n\n const create = async (newJournalEntry: NewApiJournalEntry) => {\n setSendingForm(true)\n setApiError(undefined)\n\n try {\n await Layer.createJournalEntries(apiUrl, auth?.access_token, {\n params: { businessId },\n body: newJournalEntry,\n })\n await refetch()\n closeSelectedEntry()\n setForm(undefined)\n } catch (_err) {\n setApiError('Submit failed. Please, check your connection and try again.')\n } finally {\n setSendingForm(false)\n touch(DataModel.BANK_TRANSACTIONS)\n }\n }\n\n const addEntry = () => {\n setSelectedEntryId('new')\n setForm({\n action: 'new',\n data: {\n entry_at: '',\n created_by: 'Test API Integration',\n memo: '',\n line_items: [\n {\n account_identifier: {\n type: '',\n stable_name: '',\n id: '',\n name: '',\n subType: undefined,\n },\n amount: 0,\n direction: Direction.CREDIT,\n },\n {\n account_identifier: {\n type: '',\n stable_name: '',\n id: '',\n name: '',\n subType: undefined,\n },\n amount: 0,\n direction: Direction.DEBIT,\n },\n ],\n },\n errors: undefined,\n })\n }\n\n const changeFormData = (\n fieldName: string,\n value: string | BaseSelectOption | undefined | number,\n lineItemIndex?: number,\n accounts?: LedgerAccountBalance[] | undefined,\n ) => {\n if (!form) {\n return\n }\n\n let newFormData = form\n\n if (lineItemIndex !== undefined) {\n const lineItems = form.data.line_items || []\n const lineItem = lineItems[lineItemIndex]\n\n if (!lineItem) {\n return\n }\n\n if (fieldName === 'parent' && accounts) {\n const allAccounts = flattenAccounts(accounts || [])\n const foundParent = allAccounts?.find(\n x => x.id === (value as BaseSelectOption).value,\n )\n\n if (foundParent) {\n const newLineItem = {\n ...lineItem,\n account_identifier: {\n id: foundParent.id,\n stable_name: foundParent.stable_name,\n type: foundParent.account_type.value,\n name: foundParent.name,\n subType: foundParent.account_subtype\n ? {\n value: foundParent.account_subtype.value,\n label: foundParent.account_subtype.display_name,\n }\n : undefined,\n },\n }\n lineItems[lineItemIndex] = newLineItem\n }\n } else {\n const newLineItem = {\n ...lineItem,\n [fieldName]: value,\n }\n\n lineItems[lineItemIndex] = newLineItem\n }\n\n newFormData = {\n ...form,\n data: {\n ...form.data,\n line_items: lineItems,\n },\n }\n } else {\n newFormData = {\n ...form,\n data: {\n ...form.data,\n [fieldName]: value,\n },\n }\n }\n\n setForm({\n ...newFormData,\n })\n }\n\n const validateLineItems = (lineItems?: JournalEntryLineItem[]) => {\n if (!lineItems) {\n return\n }\n const errors: FormErrorWithId[] = []\n\n lineItems.map((lineItem, idx) => {\n if (!lineItem.account_identifier.id) {\n errors.push({\n id: idx,\n field: 'account',\n message: 'Account is required',\n })\n }\n\n if (!lineItem.amount) {\n errors.push({\n id: idx,\n field: 'amount',\n message: 'Amount cannot be empty or zero',\n })\n }\n })\n return errors\n }\n\n const validate = (formData?: JournalFormTypes) => {\n let errors: {\n entry: FormError[]\n lineItems: FormErrorWithId[]\n } = {\n entry: [],\n lineItems: [],\n }\n\n const lineItems = validateLineItems(formData?.data.line_items)\n\n if (lineItems) {\n errors = {\n ...errors,\n lineItems,\n }\n }\n\n return errors\n }\n\n const submitForm = () => {\n if (!form || !form.action || addingEntry) {\n return\n }\n\n const errors = validate(form)\n\n if (errors.entry.length > 0 || errors.lineItems.length > 0) {\n setForm({\n ...form,\n errors,\n })\n\n return\n }\n\n if (form?.data) {\n create({\n ...form.data,\n line_items: form.data.line_items?.map(line => ({\n ...line,\n amount: line.amount * 100,\n account_identifier: getAccountIdentifierPayload(line),\n })),\n } as NewApiJournalEntry)\n }\n }\n\n const addEntryLine = (direction: Direction) => {\n if (!form) {\n return\n }\n\n setAddingEntry(true)\n\n const newEntryLine = {\n account_identifier: {\n type: '',\n stable_name: '',\n id: '',\n name: '',\n subType: undefined,\n },\n amount: 0,\n direction,\n }\n\n const entryLines = form?.data.line_items || []\n entryLines.push(newEntryLine)\n\n setForm({\n ...form,\n data: {\n ...form.data,\n line_items: entryLines,\n },\n })\n setTimeout(() => setAddingEntry(false), 100)\n }\n\n const removeEntryLine = (index: number) => {\n if (!form) {\n return\n }\n\n const entryLines = form.data.line_items || []\n entryLines.splice(index, 1)\n\n setForm({\n ...form,\n data: {\n ...form.data,\n line_items: entryLines,\n },\n })\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.JOURNAL, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps])\n\n return {\n data: data?.data,\n isLoading,\n isValidating,\n error,\n refetch,\n selectedEntryId,\n setSelectedEntryId,\n closeSelectedEntry,\n create,\n addEntry,\n changeFormData,\n submitForm,\n cancelForm: () => {\n setForm(undefined), setSelectedEntryId(undefined)\n },\n setForm,\n sendingForm,\n form,\n apiError,\n addEntryLine,\n removeEntryLine,\n }\n}\n", "import { AccountIdentifierPayloadObject } from '../types/categories'\nimport { JournalEntryLineItem } from '../types/journal'\n\nexport const getAccountIdentifierPayload = (\n journalLineItem: JournalEntryLineItem,\n): AccountIdentifierPayloadObject => {\n if (journalLineItem.account_identifier.id) {\n return {\n type: 'AccountId',\n id: journalLineItem.account_identifier.id,\n }\n }\n if (journalLineItem.account_identifier.stable_name) {\n return {\n type: 'StableName',\n stable_name: journalLineItem.account_identifier.stable_name,\n }\n }\n\n throw new Error('Invalid account identifier')\n}\n", "import React, { RefObject, useContext, useMemo, useState } from 'react'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport { Button, ButtonVariant } from '../Button'\nimport { Header } from '../Container'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { View } from '../Journal'\nimport { JournalConfig } from '../Journal/Journal'\nimport { JournalRow } from '../JournalRow'\nimport { JournalSidebar } from '../JournalSidebar'\nimport { Loader } from '../Loader'\nimport { Pagination } from '../Pagination'\nimport { Panel } from '../Panel'\nimport { Heading } from '../Typography'\nimport { JournalFormStringOverrides } from '../JournalForm/JournalForm'\n\nconst COMPONENT_NAME = 'journal'\n\nexport interface JournalTableStringOverrides {\n componentTitle?: string,\n addEntryButton?: string,\n idColumnHeader?: string,\n dateColumnHeader?: string,\n transactionColumnHeader?: string,\n accountColumnHeader?: string,\n debitColumnHeader?: string,\n creditColumnHeader?: string,\n journalForm?: JournalFormStringOverrides\n}\n\nexport const JournalTable = ({\n view,\n containerRef,\n pageSize = 15,\n config,\n stringOverrides,\n}: {\n view: View\n containerRef: RefObject<HTMLDivElement>\n pageSize?: number\n config: JournalConfig\n stringOverrides?: JournalTableStringOverrides\n}) => {\n const [currentPage, setCurrentPage] = useState(1)\n const {\n data: rawData,\n isLoading,\n error,\n isValidating,\n refetch,\n selectedEntryId,\n addEntry,\n } = useContext(JournalContext)\n\n const data = useMemo(() => {\n const firstPageIndex = (currentPage - 1) * pageSize\n const lastPageIndex = firstPageIndex + pageSize\n return rawData\n ?.sort((a, b) => Date.parse(b.date) - Date.parse(a.date))\n ?.slice(firstPageIndex, lastPageIndex)\n }, [rawData, currentPage])\n\n return (\n <Panel\n sidebar={<JournalSidebar parentRef={containerRef} config={config} stringOverrides={stringOverrides?.journalForm} />}\n sidebarIsOpen={Boolean(selectedEntryId)}\n parentRef={containerRef}\n >\n <Header className={`Layer__${COMPONENT_NAME}__header`}>\n <Heading className={`Layer__${COMPONENT_NAME}__title`}>{stringOverrides?.componentTitle || \"Journal\"}</Heading>\n <div className={`Layer__${COMPONENT_NAME}__actions`}>\n <Button onClick={() => addEntry()} disabled={isLoading}>\n {stringOverrides?.addEntryButton || \"Add Entry\"}\n </Button>\n </div>\n </Header>\n\n <table className='Layer__table Layer__table--hover-effect Layer__journal__table'>\n <thead>\n <tr>\n <th className='Layer__table-header' />\n <th className='Layer__table-header'>{stringOverrides?.idColumnHeader || \"Id\"}</th>\n <th className='Layer__table-header'>{stringOverrides?.dateColumnHeader || \"Date\"}</th>\n <th className='Layer__table-header'>{stringOverrides?.transactionColumnHeader || \"Transaction\"}</th>\n <th className='Layer__table-header'>{stringOverrides?.accountColumnHeader || \"Account\"}</th>\n <th className='Layer__table-header Layer__table-cell--amount'>\n {stringOverrides?.debitColumnHeader || \"Debit\"}\n </th>\n <th className='Layer__table-header Layer__table-cell--amount'>\n {stringOverrides?.creditColumnHeader || \"Credit\"}\n </th>\n </tr>\n </thead>\n\n <tbody>\n {!error &&\n data?.map((entry, idx) => {\n return (\n <JournalRow\n key={'journal-row-' + idx + entry.id}\n index={idx}\n view={view}\n row={entry}\n />\n )\n })}\n </tbody>\n </table>\n\n {data && (\n <div className='Layer__journal__pagination'>\n <Pagination\n currentPage={currentPage}\n totalCount={rawData?.length || 0}\n pageSize={pageSize}\n onPageChange={page => setCurrentPage(page)}\n />\n </div>\n )}\n\n {error ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={() => refetch()}\n isLoading={isValidating || isLoading}\n />\n </div>\n ) : null}\n\n {(!data || isLoading) && !error ? (\n <div className={`Layer__${COMPONENT_NAME}__loader-container`}>\n <Loader />\n </div>\n ) : null}\n </Panel>\n )\n}\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { centsToDollars } from '../../models/Money'\nimport {\n JournalEntry,\n JournalEntryLine,\n JournalEntryLineItem,\n} from '../../types'\nimport { humanizeEnum } from '../../utils/format'\nimport { View } from '../Journal'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface JournalRowProps {\n row: JournalEntry | JournalEntryLine | JournalEntryLineItem\n index: number\n initialLoad?: boolean\n view: View\n lineItemsLength?: number\n defaultOpen?: boolean\n expanded?: boolean\n depth?: number\n cumulativeIndex?: number\n selectedEntries?: boolean\n}\n\nconst INDENTATION = 24\n\nconst EXPANDED_STYLE = {\n height: '100%',\n opacity: 1,\n}\n\nconst COLLAPSED_STYLE = {\n height: 0,\n opacity: 0.5,\n paddingTop: 0,\n paddingBottom: 0,\n}\n\nconst rowId = (row: JournalEntry | JournalEntryLineItem | JournalEntryLine) => {\n if ('id' in row) {\n return row.id\n }\n\n return `${row.account_identifier.id}-${Math.random()}`\n}\n\nconst accountName = (row: JournalEntryLine | JournalEntryLineItem) => {\n if ('account' in row) {\n return row.account.name\n }\n\n return row.account_identifier.name\n}\n\nexport const JournalRow = ({\n row,\n index,\n initialLoad,\n view,\n lineItemsLength = 8,\n defaultOpen = false,\n expanded = false,\n depth = 0,\n cumulativeIndex = 0,\n selectedEntries = false,\n}: JournalRowProps) => {\n const { selectedEntryId, setSelectedEntryId, closeSelectedEntry } =\n useContext(JournalContext)\n\n const [isOpen, setIsOpen] = useState(index === 0 ? true : defaultOpen)\n\n const style = expanded\n ? {\n ...EXPANDED_STYLE,\n transitionDelay: `${15 * index}ms`,\n }\n : {\n ...COLLAPSED_STYLE,\n transitionDelay: `${lineItemsLength - 15 * index}ms`,\n }\n const [showComponent, setShowComponent] = useState(false)\n\n const baseClass = classNames(\n 'Layer__journal-table-row',\n rowId(row) === selectedEntryId && 'Layer__table-row--active',\n initialLoad && 'initial-load',\n 'Layer__table-row--with-show',\n showComponent ? 'show' : 'Layer__table-row--anim-starting-state',\n isOpen && 'Layer__journal__table-row--expanded',\n )\n\n const journalEntryLineClass = classNames(\n 'Layer__journal-entry-table-row',\n selectedEntries && 'Layer__table-row--active',\n initialLoad && 'initial-load',\n 'Layer__table-row--with-show',\n showComponent ? 'show' : 'Layer__table-row--anim-starting-state',\n 'Layer__journal-line__table-row',\n !expanded && 'Layer__table-row--hidden',\n )\n\n useEffect(() => {\n if (initialLoad) {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, index * 10)\n\n return () => clearTimeout(timeoutId)\n } else {\n setShowComponent(true)\n }\n }, [])\n\n if ('line_items' in row) {\n return (\n <>\n <tr\n className={baseClass}\n style={{ transitionDelay: `${15 * index}ms` }}\n onClick={e => {\n e.stopPropagation()\n\n if (selectedEntryId === row.id) {\n closeSelectedEntry()\n } else {\n setSelectedEntryId(row.id)\n }\n }}\n >\n <td className='Layer__table-cell Layer__journal__arrow'>\n <span className='Layer__table-cell-content'>\n <span\n className='Layer__table-cell-content-indentation'\n style={{\n paddingLeft: INDENTATION * depth + 16,\n }}\n onClick={e => {\n e.stopPropagation()\n e.preventDefault()\n\n setIsOpen(!isOpen)\n }}\n >\n {row.line_items && row.line_items.length > 0 && (\n <ChevronDownFill\n size={16}\n className='Layer__table__expand-icon'\n style={{\n transform: isOpen ? 'rotate(0deg)' : 'rotate(-90deg)',\n }}\n />\n )}\n </span>\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {row.id.substring(0, 5)}\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {row.date && formatTime(parseISO(row.date), DATE_FORMAT)}\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {humanizeEnum(row.entry_type)}\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>{`(${row.line_items.length})`}</span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n $\n {centsToDollars(\n Math.abs(\n row.line_items\n .filter(item => item.direction === 'DEBIT')\n .map(item => item.amount)\n .reduce((a, b) => a + b, 0),\n ),\n )}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n $\n {centsToDollars(\n Math.abs(\n row.line_items\n .filter(item => item.direction === 'CREDIT')\n .map(item => item.amount)\n .reduce((a, b) => a + b, 0),\n ),\n )}\n </span>\n </td>\n </tr>\n {(row.line_items || []).map((lineItem, idx) => (\n <JournalRow\n key={`${row.id}-${idx}`}\n row={lineItem}\n depth={depth + 1}\n index={idx}\n expanded={isOpen}\n cumulativeIndex={cumulativeIndex + idx + 1}\n lineItemsLength={(row.line_items ?? []).length}\n view={view}\n selectedEntries={row.id === selectedEntryId}\n />\n ))}\n </>\n )\n }\n\n return (\n <tr\n className={journalEntryLineClass}\n style={{ transitionDelay: `${15 * index}ms` }}\n >\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content' style={style} />\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content' style={style}>\n <span className='Layer__table-cell-hidden'>\n {rowId(row).substring(0, 5)}\n </span>\n </span>\n </td>\n <td className='Layer__table-cell' />\n <td className='Layer__table-cell' />\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content' style={style}>\n {accountName(row)}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n {row.direction === 'DEBIT' && (\n <span\n className='Layer__table-cell-content Layer__table-cell--amount'\n style={style}\n >\n ${centsToDollars(Math.abs(row.amount))}\n </span>\n )}\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n {row.direction === 'CREDIT' && (\n <span\n className='Layer__table-cell-content Layer__table-cell--amount'\n style={style}\n >\n ${centsToDollars(Math.abs(row.amount))}\n </span>\n )}\n </td>\n </tr>\n )\n}\n", "import React, { RefObject, useContext } from 'react'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport { JournalConfig } from '../Journal/Journal'\nimport { JournalEntryDetails } from '../JournalEntryDetails'\nimport { JournalForm } from '../JournalForm'\nimport { JournalFormStringOverrides } from '../JournalForm/JournalForm'\n\nexport const JournalSidebar = ({\n parentRef: _parentRef,\n config,\n stringOverrides,\n}: {\n parentRef?: RefObject<HTMLDivElement>\n config: JournalConfig\n stringOverrides?: JournalFormStringOverrides\n}) => {\n const { selectedEntryId } = useContext(JournalContext)\n if (selectedEntryId !== 'new') {\n return <JournalEntryDetails />\n }\n return <JournalForm config={config} stringOverrides={stringOverrides}/>\n}\n", "import React, { useContext, useMemo } from 'react'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport XIcon from '../../icons/X'\nimport { centsToDollars } from '../../models/Money'\nimport { Direction } from '../../types'\nimport { humanizeEnum } from '../../utils/format'\nimport { Badge, BadgeVariant } from '../Badge'\nimport { Button, ButtonVariant } from '../Button'\nimport { Card } from '../Card'\nimport { DateTime } from '../DateTime'\nimport { DetailsList, DetailsListItem } from '../DetailsList'\nimport { SourceDetailView } from '../LedgerAccountEntryDetails/LedgerAccountEntryDetails'\nimport { Table, TableBody, TableCell, TableHead, TableRow } from '../Table'\n\nexport const JournalEntryDetails = () => {\n const {\n data,\n isLoadingEntry,\n errorEntry,\n closeSelectedEntry,\n selectedEntryId,\n } = useContext(JournalContext)\n\n const entry = useMemo(() => {\n if (selectedEntryId && data) {\n return data.find(x => x.id === selectedEntryId)\n }\n\n return\n }, [data, selectedEntryId])\n\n return (\n <div className='Layer__journal__entry-details'>\n <DetailsList\n title='Transaction source'\n actions={\n <Button\n rightIcon={<XIcon />}\n iconOnly={true}\n onClick={closeSelectedEntry}\n className='Layer__details-list__close-btn'\n variant={ButtonVariant.secondary}\n />\n }\n >\n <DetailsListItem label='Source' isLoading={isLoadingEntry}>\n <Badge>{entry?.source?.entity_name}</Badge>\n </DetailsListItem>\n {entry?.source?.display_description && (\n <SourceDetailView source={entry?.source} />\n )}\n </DetailsList>\n <DetailsList\n title={`Journal Entry ${entry?.id.substring(0, 5)}`}\n className='Layer__border-top'\n >\n <DetailsListItem label='Entry type' isLoading={isLoadingEntry}>\n {humanizeEnum(entry?.entry_type ?? '')}\n </DetailsListItem>\n <DetailsListItem label='Date' isLoading={isLoadingEntry}>\n {entry?.entry_at && <DateTime value={entry?.entry_at} />}\n </DetailsListItem>\n <DetailsListItem label='Creation date' isLoading={isLoadingEntry}>\n {entry?.date && <DateTime value={entry?.date} />}\n </DetailsListItem>\n {entry?.reversal_id && (\n <DetailsListItem label='Reversal' isLoading={isLoadingEntry}>\n Journal Entry #{entry?.reversal_id}\n </DetailsListItem>\n )}\n </DetailsList>\n {!isLoadingEntry && !errorEntry ? (\n <div className='Layer__ledger-account__entry-details__line-items'>\n <Card>\n <Table\n componentName='ledger-account__entry-details'\n borderCollapse='collapse'\n >\n <TableHead>\n <TableRow rowKey='soc-flow-head-row' isHeadRow>\n <TableCell>Line items</TableCell>\n {[...Array(3)].map((_, index) => (\n <TableCell key={`ledger-empty-cell-${index}`} />\n ))}\n <TableCell>Debit</TableCell>\n <TableCell>Credit</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {entry?.line_items?.map((item, index) => (\n <TableRow\n key={`ledger-line-item-${index}`}\n rowKey={`ledger-line-item-${index}`}\n >\n <TableCell>{item.account_identifier?.name || ''}</TableCell>\n {[...Array(3)].map((_, index) => (\n <TableCell key={`ledger-empty-cell-${index}`} />\n ))}\n <TableCell>\n {item.direction === Direction.DEBIT && (\n <Badge variant={BadgeVariant.WARNING}>\n ${centsToDollars(item.amount || 0)}\n </Badge>\n )}\n </TableCell>\n <TableCell>\n {item.direction === Direction.CREDIT && (\n <Badge variant={BadgeVariant.SUCCESS}>\n ${centsToDollars(item.amount || 0)}\n </Badge>\n )}\n </TableCell>\n </TableRow>\n ))}\n <TableRow\n rowKey='ledger-line-item-summation'\n variant='summation'\n >\n <TableCell primary>Total</TableCell>\n {[...Array(3)].map((_, index) => (\n <TableCell key={`ledger-empty-cell-${index}`} />\n ))}\n <TableCell isCurrency primary>\n {entry?.line_items\n .filter(item => item.direction === 'DEBIT')\n .map(item => item.amount)\n .reduce((a, b) => a + b, 0) || 0}\n </TableCell>\n <TableCell isCurrency primary>\n {entry?.line_items\n .filter(item => item.direction === 'CREDIT')\n .map(item => item.amount)\n .reduce((a, b) => a + b, 0) || 0}\n </TableCell>\n </TableRow>\n </TableBody>\n </Table>\n </Card>\n </div>\n ) : null}\n </div>\n )\n}\n", "import React, { useContext } from 'react'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport { Button, ButtonVariant, RetryButton, SubmitButton } from '../Button'\nimport { DatePicker } from '../DatePicker'\nimport { InputGroup } from '../Input'\nimport { JournalConfig } from '../Journal/Journal'\nimport { Textarea } from '../Textarea/Textarea'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport { JournalFormEntryLines } from './JournalFormEntryLines'\n\nexport interface JournalFormStringOverrides {\n header?: string\n cancelButton?: string\n retryButton?: string\n saveButton?: string\n}\n\nexport const JournalForm = (\n { config, stringOverrides }: {\n config: JournalConfig,\n stringOverrides?: JournalFormStringOverrides\n }) => {\n const {\n form,\n cancelForm,\n submitForm,\n sendingForm,\n apiError,\n changeFormData,\n addEntryLine,\n removeEntryLine,\n } = useContext(JournalContext)\n\n return (\n <form\n className='Layer__form'\n onSubmit={e => {\n e.preventDefault()\n submitForm()\n }}\n >\n <div className='Layer__journal__sidebar__header'>\n <Text size={TextSize.lg} weight={TextWeight.bold} className='title'>\n {stringOverrides?.header && \"Add New Entry\"}\n </Text>\n <div className='actions'>\n <Button\n type='button'\n onClick={cancelForm}\n variant={ButtonVariant.secondary}\n disabled={sendingForm}\n >\n {stringOverrides?.cancelButton || \"Cancel\"}\n </Button>\n {apiError && (\n <RetryButton\n type='submit'\n processing={sendingForm}\n error={'Check connection and retry in few seconds.'}\n disabled={sendingForm}\n >\n {stringOverrides?.retryButton || \"Retry\"}\n </RetryButton>\n )}\n {!apiError && (\n <SubmitButton\n type='submit'\n noIcon={true}\n active={true}\n disabled={sendingForm}\n >\n {stringOverrides?.saveButton || \"Save\"}\n </SubmitButton>\n )}\n </div>\n </div>\n\n {apiError && (\n <Text\n size={TextSize.sm}\n className='Layer__journal__form__error-message'\n >\n {apiError}\n </Text>\n )}\n\n <div className='Layer__journal__form__input-group'>\n <InputGroup name='date' label='Date' inline={true}>\n <div className='Layer__journal__datepicker__wrapper'>\n <DatePicker\n selected={\n form?.data.entry_at ? new Date(form?.data.entry_at) : new Date()\n }\n onChange={date => {\n if (!Array.isArray(date)) {\n changeFormData('entry_at', date.toISOString())\n }\n }}\n mode='dayPicker'\n placeholderText='Select date'\n currentDateOption={false}\n />\n <DatePicker\n selected={\n form?.data.entry_at ? new Date(form?.data.entry_at) : new Date()\n }\n onChange={date => {\n if (!Array.isArray(date)) {\n changeFormData('entry_at', date.toISOString())\n }\n }}\n mode='timePicker'\n placeholderText='Select time'\n currentDateOption={false}\n />\n </div>\n </InputGroup>\n </div>\n <JournalFormEntryLines\n entrylineItems={form?.data.line_items || []}\n addEntryLine={addEntryLine}\n removeEntryLine={removeEntryLine}\n changeFormData={changeFormData}\n sendingForm={sendingForm}\n config={config}\n />\n <div className='Layer__journal__form__input-group Layer__journal__form__input-group__textarea'>\n <InputGroup name='memo' label='Notes'>\n <Textarea\n name='memo'\n placeholder='Add description'\n value={form?.data.memo}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>\n changeFormData('memo', e.target.value)\n }\n disabled={sendingForm}\n />\n </InputGroup>\n </div>\n <div className='Layer__journal__bottom-actions'>\n <Button\n type='button'\n onClick={cancelForm}\n variant={ButtonVariant.secondary}\n disabled={sendingForm}\n >\n {stringOverrides?.cancelButton || \"Cancel\"}\n </Button>\n {apiError && (\n <RetryButton\n type='submit'\n processing={sendingForm}\n error={'Check connection and retry in few seconds.'}\n disabled={sendingForm}\n >\n {stringOverrides?.retryButton || \"Retry\"}\n </RetryButton>\n )}\n {!apiError && (\n <SubmitButton\n type='submit'\n noIcon={true}\n active={true}\n disabled={sendingForm}\n >\n {stringOverrides?.saveButton || \"Save\"}\n </SubmitButton>\n )}\n </div>\n </form>\n )\n}\n", "import React, { useContext } from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport Trash from '../../icons/Trash'\nimport { Direction, JournalEntryLineItem } from '../../types'\nimport { LedgerAccountBalance } from '../../types/chart_of_accounts'\nimport { BaseSelectOption } from '../../types/general'\nimport {\n convertCurrencyToNumber,\n convertNumberToCurrency,\n humanizeEnum,\n} from '../../utils/format'\nimport { BadgeVariant } from '../Badge'\nimport { IconButton, TextButton } from '../Button'\nimport { useParentOptions } from '../ChartOfAccountsForm/useParentOptions'\nimport { InputWithBadge, InputGroup, Select } from '../Input'\nimport { JournalConfig } from '../Journal/Journal'\nimport { Text, TextSize } from '../Typography'\n\nexport const JournalFormEntryLines = ({\n entrylineItems,\n addEntryLine,\n removeEntryLine,\n changeFormData,\n sendingForm,\n config,\n}: {\n entrylineItems: JournalEntryLineItem[]\n addEntryLine: (direction: Direction) => void\n removeEntryLine: (index: number) => void\n changeFormData: (\n name: string,\n value: string | BaseSelectOption | number | undefined,\n lineItemIndex: number,\n accounts?: LedgerAccountBalance[] | undefined,\n ) => void\n sendingForm: boolean\n config: JournalConfig\n}) => {\n const { data: accountsData } = useContext(ChartOfAccountsContext)\n const { form } = useContext(JournalContext)\n\n const parentOptions = useParentOptions(accountsData)\n\n return (\n <>\n {Object.keys(Direction).map((direction, idx) => {\n return (\n <div\n key={'Layer__journal__form__input-group-' + idx}\n className='Layer__journal__form__input-group Layer__journal__form__input-group__border'\n >\n <Text\n className='Layer__journal__form__input-group__title'\n size={TextSize.lg}\n >\n Add {humanizeEnum(direction)} Account\n </Text>\n {entrylineItems?.map((item, idx) => {\n if (item.direction !== direction) {\n return null\n }\n return (\n <div\n className='Layer__journal__form__input-group__line-item'\n key={direction + '-' + idx}\n >\n <InputGroup name={direction} label='Amount' inline={true}>\n <InputWithBadge\n name={direction}\n placeholder='$0.00'\n value={convertNumberToCurrency(item.amount)}\n disabled={sendingForm}\n badge={humanizeEnum(direction)}\n variant={\n item.direction === 'CREDIT'\n ? BadgeVariant.SUCCESS\n : BadgeVariant.WARNING\n }\n onChange={e =>\n changeFormData(\n 'amount',\n convertCurrencyToNumber(\n (e.target as HTMLInputElement).value,\n ),\n idx,\n )\n }\n isInvalid={Boolean(\n form?.errors?.lineItems.find(\n x => x.id === idx && x.field === 'amount',\n ),\n )}\n errorMessage={\n form?.errors?.lineItems.find(\n x => x.id === idx && x.field === 'amount',\n )?.message\n }\n />\n </InputGroup>\n <InputGroup\n name='account-name'\n label='Account name'\n inline={true}\n >\n <Select\n options={parentOptions}\n value={{\n value: item.account_identifier.id,\n label: item.account_identifier.name,\n }}\n onChange={sel =>\n changeFormData(\n 'parent',\n sel,\n idx,\n accountsData?.accounts,\n )\n }\n isInvalid={Boolean(\n form?.errors?.lineItems.find(\n x => x.id === idx && x.field === 'account',\n ),\n )}\n errorMessage={\n form?.errors?.lineItems.find(\n x => x.id === idx && x.field === 'account',\n )?.message\n }\n />\n {idx >= 2 && (\n <IconButton\n className='Layer__remove__button'\n onClick={() => removeEntryLine(idx)}\n icon={<Trash />}\n />\n )}\n </InputGroup>\n </div>\n )\n })}\n {(config.form.addEntryLinesLimit === undefined ||\n config.form.addEntryLinesLimit > entrylineItems?.length) && (\n <TextButton\n className='Layer__journal__add-entry-line'\n onClick={() => addEntryLine(direction as Direction)}\n >\n Add next account\n </TextButton>\n )}\n </div>\n )\n })}\n </>\n )\n}\n", "import React, {\n createContext,\n ReactNode,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react'\nimport { TasksContext } from '../../contexts/TasksContext'\nimport { useTasks } from '../../hooks/useTasks'\nimport { isComplete } from '../../types/tasks'\nimport { Loader } from '../Loader'\nimport { TasksHeader } from '../TasksHeader'\nimport { TasksList } from '../TasksList'\nimport { TasksPending } from '../TasksPending'\nimport classNames from 'classnames'\n\nexport type UseTasksContextType = ReturnType<typeof useTasks>\nexport const UseTasksContext = createContext<UseTasksContextType>({\n data: undefined,\n isLoading: undefined,\n loadedStatus: 'initial',\n isValidating: undefined,\n error: undefined,\n refetch: () => {},\n submitResponseToTask: () => {},\n})\n\nexport const useTasksContext = () => useContext(UseTasksContext)\n\nexport interface TasksStringOverrides {\n header?: string\n}\n\nexport const Tasks = ({\n collapsable = false,\n defaultCollapsed = false,\n collapsedWhenComplete,\n tasksHeader, // deprecated\n stringOverrides,\n}: {\n tasksHeader?: string\n collapsable?: boolean\n defaultCollapsed?: boolean\n collapsedWhenComplete?: boolean\n stringOverrides?: TasksStringOverrides\n}) => {\n return (\n <TasksProvider>\n <TasksComponent\n collapsable={collapsable}\n defaultCollapsed={defaultCollapsed}\n collapsedWhenComplete={collapsedWhenComplete}\n tasksHeader={tasksHeader} // deprecated\n stringOverrides={stringOverrides}\n />\n </TasksProvider>\n )\n}\n\nexport const TasksProvider = ({ children }: { children: ReactNode }) => {\n const contextData = useTasks()\n\n return (\n <TasksContext.Provider value={contextData}>\n {children}\n </TasksContext.Provider>\n )\n}\n\nexport const TasksComponent = ({\n collapsable = false,\n defaultCollapsed = false,\n collapsedWhenComplete,\n tasksHeader, // deprecated\n stringOverrides,\n}: {\n tasksHeader?: string\n collapsable?: boolean\n defaultCollapsed?: boolean\n collapsedWhenComplete?: boolean\n stringOverrides?: TasksStringOverrides\n}) => {\n const { isLoading, loadedStatus, data } = useContext(TasksContext)\n const allComplete = useMemo(() => {\n if (!data) {\n return undefined\n }\n\n if (data && !isLoading) {\n return Boolean(data.every(x => isComplete(x.status)))\n }\n\n return false\n }, [data, isLoading])\n\n const [open, setOpen] = useState(\n defaultCollapsed || collapsedWhenComplete ? false : true,\n )\n\n useEffect(() => {\n if (\n allComplete &&\n open &&\n collapsedWhenComplete &&\n loadedStatus === 'complete'\n ) {\n setOpen(false)\n }\n }, [allComplete])\n\n return (\n <div className='Layer__tasks-component'>\n <TasksHeader\n tasksHeader={stringOverrides?.header || tasksHeader}\n collapsable={collapsable}\n open={open}\n toggleContent={() => setOpen(!open)}\n />\n <div\n className={classNames(\n 'Layer__tasks__content',\n !open && 'Layer__tasks__content--collapsed',\n )}\n >\n {isLoading || !data ? (\n <div className='Layer__tasks__loader-container'>\n <Loader />\n </div>\n ) : (\n <>\n {data.length > 0 && <TasksPending />}\n <TasksList />\n </>\n )}\n </div>\n </div>\n )\n}\n", "import { createContext } from 'react'\nimport { useTasks } from '../../hooks/useTasks'\n\nexport type TasksContextType = ReturnType<typeof useTasks>\nexport const TasksContext = createContext<TasksContextType>({\n data: undefined,\n isLoading: false,\n loadedStatus: 'initial',\n error: undefined,\n refetch: () => {},\n submitResponseToTask: () => {},\n})\n", "import { useEffect, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { LoadedStatus } from '../../types/general'\nimport { DataModel } from '../../types/general'\nimport { TaskTypes } from '../../types/tasks'\nimport useSWR from 'swr'\n\ntype UseTasks = () => {\n data?: TaskTypes[]\n isLoading?: boolean\n loadedStatus?: LoadedStatus\n isValidating?: boolean\n error?: unknown\n refetch: () => void\n submitResponseToTask: (taskId: string, userResponse: string) => void\n}\n\nexport const useTasks: UseTasks = () => {\n const [loadedStatus, setLoadedStatus] = useState<LoadedStatus>('initial')\n const { auth, businessId, apiUrl, read, syncTimestamps, hasBeenTouched } =\n useLayerContext()\n\n const queryKey = businessId && auth?.access_token && `tasks-${businessId}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getTasks(apiUrl, auth?.access_token, {\n params: { businessId },\n }),\n )\n\n useEffect(() => {\n if (isLoading && loadedStatus === 'initial') {\n setLoadedStatus('loading')\n } else if (!isLoading && loadedStatus === 'loading') {\n setLoadedStatus('complete')\n }\n }, [isLoading])\n\n const refetch = () => mutate()\n\n const submitResponseToTask = (taskId: string, userResponse: string) => {\n if (!taskId || !userResponse || userResponse.length === 0) return\n\n const data = {\n type: 'FreeResponse',\n user_response: userResponse,\n }\n\n Layer.submitResponseToTask(apiUrl, auth?.access_token, {\n params: { businessId, taskId },\n body: data,\n }).then(() => refetch())\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.TASKS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps])\n\n return {\n data: data?.data,\n isLoading,\n loadedStatus,\n isValidating,\n error,\n refetch,\n submitResponseToTask,\n }\n}\n", "export interface TaskTypes {\n id: string\n question: string\n status: TasksStatusType\n title: string\n transaction_id: string | null\n type: string\n user_marked_completed_at: string\n user_response: string\n user_response_type: TasksResponseType\n archived_at: string | null\n completed_at: string\n created_at: string\n updated_at: string\n}\n\nexport type TasksStatusType = 'COMPLETED' | 'TODO' | 'USER_MARKED_COMPLETED'\nexport type TasksResponseType = 'FREE_RESPONSE'\n\nconst COMPLETED_TASK_TYPES = ['COMPLETED', 'USER_MARKED_COMPLETED']\n\nexport function isComplete(taskType: TasksStatusType) {\n return COMPLETED_TASK_TYPES.includes(taskType)\n}\n", "import React, { useContext } from 'react'\nimport { TasksContext } from '../../contexts/TasksContext'\nimport AlertCircle from '../../icons/AlertCircle'\nimport Check from '../../icons/Check'\nimport ProgressIcon from '../../icons/ProgressIcon'\nimport RefreshCcw from '../../icons/RefreshCcw'\nimport { isComplete } from '../../types/tasks'\nimport { Badge, BadgeVariant } from '../Badge'\nimport { ExpandButton } from '../Button'\nimport { Text, TextSize } from '../Typography'\n\nconst ICONS = {\n loading: {\n icon: <ProgressIcon size={12} className='Layer__anim--rotating' />,\n text: 'Loading',\n badge: BadgeVariant.DEFAULT,\n },\n done: {\n icon: <Check size={12} />,\n text: 'Done',\n badge: BadgeVariant.SUCCESS,\n },\n pending: {\n icon: <AlertCircle size={12} />,\n text: 'In progress',\n badge: BadgeVariant.WARNING,\n },\n refresh: {\n icon: <RefreshCcw size={12} />,\n text: 'Refresh',\n badge: BadgeVariant.DEFAULT,\n },\n}\n\nexport const TasksHeader = ({\n tasksHeader = 'Bookkeeping Tasks',\n collapsable,\n open,\n toggleContent,\n}: {\n tasksHeader?: string\n collapsable?: boolean\n open?: boolean\n toggleContent: () => void\n}) => {\n const { data: tasks, loadedStatus, refetch, error } = useContext(TasksContext)\n\n const completedTasks = tasks?.filter(task => isComplete(task.status)).length\n\n const badgeVariant =\n completedTasks === tasks?.length ? ICONS.done : ICONS.pending\n\n return (\n <div className='Layer__tasks-header'>\n <div className='Layer__tasks-header__left-col'>\n <Text size={TextSize.lg}>{tasksHeader}</Text>\n {loadedStatus !== 'complete' && !open ? (\n <Badge variant={ICONS.loading.badge} icon={ICONS.loading.icon}>\n {ICONS.loading.text}\n </Badge>\n ) : loadedStatus === 'complete' && (!tasks || error) ? (\n <Badge\n onClick={() => refetch()}\n variant={ICONS.refresh.badge}\n icon={ICONS.refresh.icon}\n >\n {ICONS.refresh.text}\n </Badge>\n ) : loadedStatus === 'complete' ? (\n <Badge variant={badgeVariant.badge} icon={badgeVariant.icon}>\n {badgeVariant.text}\n </Badge>\n ) : open ? null : (\n <Badge variant={badgeVariant.badge} icon={badgeVariant.icon}>\n {badgeVariant.text}\n </Badge>\n )}\n </div>\n {collapsable && (\n <ExpandButton onClick={toggleContent} collapsed={!open} />\n )}\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ProgressIcon = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M9 1.5V4.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 13.5V16.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M3.6975 3.6975L5.82 5.82'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12.18 12.18L14.3025 14.3025'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M1.5 9H4.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M13.5 9H16.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M3.6975 14.3025L5.82 12.18'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12.18 5.82L14.3025 3.6975'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default ProgressIcon\n", "import React, { useContext, useEffect, useMemo, useState } from 'react'\nimport { TasksContext } from '../../contexts/TasksContext'\nimport SmileIcon from '../../icons/SmileIcon'\nimport { isComplete, TaskTypes } from '../../types/tasks'\nimport { Pagination } from '../Pagination'\nimport { TasksListItem } from '../TasksListItem'\nimport { ErrorText, Text, TextSize } from '../Typography'\n\nfunction paginateArray<T>(array: T[], chunkSize: number = 10): T[][] {\n const result: T[][] = []\n for (let i = 0; i < array.length; i += chunkSize) {\n const chunk = array.slice(i, i + chunkSize)\n result.push(chunk)\n }\n return result\n}\n\nconst TasksEmptyState = () => (\n <div className='Layer__tasks-empty-state'>\n <div className='Layer__tasks-icon'>\n <SmileIcon />\n </div>\n <Text size={TextSize.sm}>\n There are no pending tasks!\n <br /> Great job!\n </Text>\n </div>\n)\n\nexport const TasksList = ({ pageSize = 10 }: { pageSize?: number }) => {\n const { data: tasks, error } = useContext(TasksContext)\n\n const firstPageWithIincompleteTasks = paginateArray(\n tasks || [],\n pageSize,\n ).findIndex(page => page.some(task => !isComplete(task.status)))\n\n const [currentPage, setCurrentPage] = useState(\n firstPageWithIincompleteTasks === -1\n ? 1\n : firstPageWithIincompleteTasks + 1,\n )\n\n const sortedTasks = useMemo(() => {\n const firstPageIndex = (currentPage - 1) * pageSize\n const lastPageIndex = firstPageIndex + pageSize\n return tasks?.slice(firstPageIndex, lastPageIndex)\n }, [tasks, currentPage])\n\n const indexFirstIncomplete = sortedTasks?.findIndex(\n task => !isComplete(task.status),\n )\n\n const goToNextPage = (task: TaskTypes) => {\n const allComplete = sortedTasks\n ?.filter(taskInList => taskInList.id !== task.id)\n .every(task => isComplete(task.status))\n if (allComplete) {\n setCurrentPage(currentPage + 1)\n }\n }\n\n return (\n <div className='Layer__tasks-list'>\n {sortedTasks && sortedTasks.length > 0 ? (\n <>\n {sortedTasks.map((task, index) => (\n <TasksListItem\n key={task.id}\n task={task}\n goToNextPageIfAllComplete={goToNextPage}\n defaultOpen={index === indexFirstIncomplete}\n />\n ))}\n {tasks && tasks.length >= 10 && (\n <div className='Layer__tasks__pagination'>\n <Pagination\n currentPage={currentPage}\n totalCount={tasks?.length || 0}\n pageSize={pageSize}\n onPageChange={page => setCurrentPage(page)}\n />\n </div>\n )}\n </>\n ) : (\n <>\n {error ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : (\n <TasksEmptyState />\n )}\n </>\n )}\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst SmileIcon = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 12 12'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M6.5 11.5C9.26142 11.5 11.5 9.26142 11.5 6.5C11.5 3.73858 9.26142 1.5 6.5 1.5C3.73858 1.5 1.5 3.73858 1.5 6.5C1.5 9.26142 3.73858 11.5 6.5 11.5Z'\n stroke='#3B9C63'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M4.5 7.5C4.5 7.5 5.25 8.5 6.5 8.5C7.75 8.5 8.5 7.5 8.5 7.5'\n stroke='#3B9C63'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M5 5H5.005'\n stroke='#3B9C63'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M8 5H8.005'\n stroke='#3B9C63'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default SmileIcon\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { TasksContext } from '../../contexts/TasksContext'\nimport AlertCircle from '../../icons/AlertCircle'\nimport Check from '../../icons/Check'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { isComplete, TaskTypes } from '../../types/tasks'\nimport { Button, ButtonVariant } from '../Button'\nimport { Textarea } from '../Textarea'\nimport { Text, TextSize } from '../Typography'\nimport classNames from 'classnames'\nimport { set } from 'date-fns'\n\nexport const TasksListItem = ({\n task,\n goToNextPageIfAllComplete,\n defaultOpen,\n}: {\n task: TaskTypes\n goToNextPageIfAllComplete: (task: TaskTypes) => void\n defaultOpen: boolean\n}) => {\n const [isOpen, setIsOpen] = useState(defaultOpen)\n const [userResponse, setUserResponse] = useState(task.user_response || '')\n\n const { submitResponseToTask } = useContext(TasksContext)\n\n const taskBodyClassName = classNames(\n 'Layer__tasks-list-item__body',\n isOpen && 'Layer__tasks-list-item__body--expanded',\n isComplete(task.status) && 'Layer__tasks-list-item--completed',\n )\n\n const taskHeadClassName = classNames(\n 'Layer__tasks-list-item__head-info',\n isComplete(task.status)\n ? 'Layer__tasks-list-item--completed'\n : 'Layer__tasks-list-item--pending',\n )\n\n const taskItemClassName = classNames(\n 'Layer__tasks-list-item',\n isOpen && 'Layer__tasks-list-item__expanded',\n )\n\n useEffect(() => {\n setIsOpen(defaultOpen)\n }, [defaultOpen])\n\n return (\n <div className='Layer__tasks-list-item-wrapper'>\n <div className={taskItemClassName}>\n <div\n className='Layer__tasks-list-item__head'\n onClick={() => setIsOpen(!isOpen)}\n >\n <div className={taskHeadClassName}>\n <div className='Layer__tasks-list-item__head-info__status'>\n {isComplete(task.status) ? (\n <Check size={12} />\n ) : (\n <AlertCircle size={12} />\n )}\n </div>\n <Text size={TextSize.md}>{task.title}</Text>\n </div>\n <ChevronDownFill\n size={16}\n className='Layer__tasks__expand-icon'\n style={{\n transform: isOpen ? 'rotate(0deg)' : 'rotate(-180deg)',\n }}\n />\n </div>\n <div className={taskBodyClassName}>\n <div className='Layer__tasks-list-item__body-info'>\n <Text size={TextSize.sm}>{task.question}</Text>\n <Textarea\n value={userResponse}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>\n setUserResponse(e.target.value)\n }\n />\n <div className='Layer__tasks-list-item__actions'>\n <Button\n disabled={\n userResponse.length === 0 ||\n userResponse === task.user_response\n }\n variant={ButtonVariant.secondary}\n onClick={() => {\n submitResponseToTask(task.id, userResponse)\n setIsOpen(false)\n goToNextPageIfAllComplete(task)\n }}\n >\n {userResponse && userResponse.length === 0 ? 'Update' : 'Save'}\n </Button>\n </div>\n </div>\n </div>\n </div>\n </div>\n )\n}\n", "import React, { useContext } from 'react'\nimport { TASKS_CHARTS_COLORS } from '../../config/charts'\nimport { TasksContext } from '../../contexts/TasksContext'\nimport { isComplete } from '../../types/tasks'\nimport { Text, TextSize } from '../Typography'\nimport classNames from 'classnames'\nimport { format } from 'date-fns'\nimport { Cell, Pie, PieChart } from 'recharts'\n\nexport const TasksPending = () => {\n const { data } = useContext(TasksContext)\n const completedTasks = data?.filter(task => isComplete(task.status)).length\n\n const chartData = [\n {\n name: 'done',\n value: completedTasks,\n },\n {\n name: 'pending',\n value: data?.filter(task => !isComplete(task.status)).length,\n },\n ]\n\n const taskStatusClassName = classNames(\n completedTasks && completedTasks > 0\n ? 'Layer__tasks-pending-bar__status--done'\n : 'Layer__tasks-pending-bar__status--pending',\n )\n return (\n <div className='Layer__tasks-pending'>\n <Text size={TextSize.lg}>{format(Date.now(), 'MMMM')}</Text>\n <div className='Layer__tasks-pending-bar'>\n <Text size={TextSize.sm}>\n <span className={taskStatusClassName}>{completedTasks}</span>/\n {data?.length} done\n </Text>\n <PieChart width={24} height={24} className='mini-chart'>\n <Pie\n data={chartData}\n dataKey='value'\n nameKey='name'\n cx='50%'\n cy='50%'\n innerRadius={5}\n outerRadius={9}\n paddingAngle={0.2}\n fill={TASKS_CHARTS_COLORS.pending}\n width={16}\n height={16}\n animationDuration={250}\n animationEasing='ease-in-out'\n >\n {chartData.map((task, index) => {\n return (\n <Cell\n key={`cell-${index}`}\n className={'Layer__profit-and-loss-detailed-charts__pie'}\n fill={\n TASKS_CHARTS_COLORS[\n task.name as keyof typeof TASKS_CHARTS_COLORS\n ]\n }\n />\n )\n })}\n </Pie>\n </PieChart>\n </div>\n </div>\n )\n}\n", "import React from 'react'\nimport CoffeeIcon from '../../icons/Coffee'\nimport { Button, ButtonVariant, Link } from '../Button'\nimport { IconBox } from '../IconBox'\nimport { Text, TextSize, TextWeight } from '../Typography'\n\ninterface BookkeepingUpsellBarProps {\n onClick?: () => void\n href?: string\n}\n\nexport const BookkeepingUpsellBar = ({\n onClick,\n href,\n}: BookkeepingUpsellBarProps) => {\n return (\n <div className='Layer__bar-banner Layer__bar-banner--bookkeeping'>\n <div className='Layer__bar-banner__left-col'>\n <IconBox>\n <CoffeeIcon />\n </IconBox>\n <div className='Layer__bar-banner__text-container'>\n <Text size={TextSize.md} weight={TextWeight.bold}>\n Need help with your books?\n </Text>\n <Text\n size={TextSize.sm}\n className='Layer__bar-banner__text-container__desc'\n >\n Order bookkeeping service supported by real humans.\n </Text>\n </div>\n </div>\n {onClick ? (\n <Button variant={ButtonVariant.secondary} onClick={onClick}>\n Schedule a demo\n </Button>\n ) : href ? (\n <Link href={href} target='_blank' variant={ButtonVariant.secondary}>\n Schedule a demo\n </Link>\n ) : null}\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst CoffeeIcon = ({ size = 11, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 12'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <g clip-path='url(#clip0_5018_10141)'>\n <path\n d='M3.25 4.16666H2.79167C2.30544 4.16666 1.83912 4.35981 1.4953 4.70363C1.15149 5.04744 0.958333 5.51376 0.958333 5.99999C0.958333 6.48622 1.15149 6.95254 1.4953 7.29635C1.83912 7.64017 2.30544 7.83332 2.79167 7.83332H3.25'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5834 4.16666H3.25004V8.29166C3.25004 8.77789 3.4432 9.2442 3.78701 9.58802C4.13083 9.93184 4.59714 10.125 5.08337 10.125H8.75004C9.23627 10.125 9.70259 9.93184 10.0464 9.58802C10.3902 9.2442 10.5834 8.77789 10.5834 8.29166V4.16666Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M8.75 0.958344V2.33334'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M6.91663 0.958344V2.33334'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M5.08337 0.958344V2.33334'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </g>\n <defs>\n <clipPath id='clip0_5018_10141'>\n <rect\n width='11'\n height='11'\n fill='white'\n transform='matrix(-1 0 0 1 11.5 0.5)'\n />\n </clipPath>\n </defs>\n </svg>\n)\n\nexport default CoffeeIcon\n", "import React, { ReactNode } from 'react'\n\ninterface IconBoxProps {\n children: ReactNode\n}\n\nexport const IconBox = ({ children }: IconBoxProps) => {\n return <span className='Layer__icon-box'>{children}</span>\n}\n", "import React, { useState } from 'react'\nimport { Container, Header } from '../../components/Container'\nimport { ProfitAndLoss } from '../../components/ProfitAndLoss'\nimport { ProfitAndLossDetailedChartsStringOverrides } from '../../components/ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts'\nimport { ProfitAndLossSummariesStringOverrides } from '../../components/ProfitAndLossSummaries/ProfitAndLossSummaries'\nimport { TasksComponent, TasksProvider } from '../../components/Tasks'\nimport { TasksStringOverrides } from '../../components/Tasks/Tasks'\nimport { Toggle } from '../../components/Toggle'\nimport { Heading, HeadingSize } from '../../components/Typography'\nimport { View } from '../../components/View'\nimport { useWindowSize } from '../../hooks/useWindowSize'\nimport classNames from 'classnames'\n\nexport interface BookkeepingOverviewProps {\n title?: string // deprecated\n stringOverrides?: {\n title?: string\n tasks?: TasksStringOverrides\n profitAndLoss?: {\n header?: string\n detailedCharts?: ProfitAndLossDetailedChartsStringOverrides\n summaries?: ProfitAndLossSummariesStringOverrides\n }\n }\n}\n\ntype PnlToggleOption = 'revenue' | 'expenses'\n\nexport const BookkeepingOverview = ({\n title, // deprecated\n stringOverrides,\n}: BookkeepingOverviewProps) => {\n const [pnlToggle, setPnlToggle] = useState<PnlToggleOption>('expenses')\n const [width] = useWindowSize()\n\n return (\n <ProfitAndLoss asContainer={false}>\n <TasksProvider>\n <View\n viewClassName='Layer__bookkeeping-overview--view'\n title={stringOverrides?.title || title || 'Bookkeeping overview'}\n withSidebar={width > 1100}\n sidebar={<TasksComponent stringOverrides={stringOverrides?.tasks} />}\n >\n {width <= 1100 && (\n <TasksComponent\n collapsable\n collapsedWhenComplete\n stringOverrides={stringOverrides?.tasks}\n />\n )}\n <Container\n name='bookkeeping-overview-profit-and-loss'\n asWidget\n elevated={true}\n >\n <Header>\n <Heading size={HeadingSize.secondary}>\n {stringOverrides?.profitAndLoss?.header || 'Profit & Loss'}\n </Heading>\n <ProfitAndLoss.DatePicker />\n </Header>\n <div className='Layer__bookkeeping-overview__summaries-row'>\n <ProfitAndLoss.Summaries\n stringOverrides={stringOverrides?.profitAndLoss?.summaries}\n />\n </div>\n <ProfitAndLoss.Chart />\n </Container>\n <div className='Layer__bookkeeping-overview-profit-and-loss-charts'>\n <Toggle\n name='pnl-detailed-charts'\n options={[\n {\n value: 'revenue',\n label: 'Revenue',\n },\n {\n value: 'expenses',\n label: 'Expenses',\n },\n ]}\n selected={pnlToggle}\n onChange={e => setPnlToggle(e.target.value as PnlToggleOption)}\n />\n <Container\n name={classNames(\n 'bookkeeping-overview-profit-and-loss-chart',\n pnlToggle !== 'revenue' &&\n 'bookkeeping-overview-profit-and-loss-chart--hidden',\n )}\n >\n <ProfitAndLoss.DetailedCharts\n scope='revenue'\n hideClose={true}\n stringOverrides={stringOverrides?.profitAndLoss?.detailedCharts}\n />\n </Container>\n <Container\n name={classNames(\n 'bookkeeping-overview-profit-and-loss-chart',\n pnlToggle !== 'expenses' &&\n 'bookkeeping-overview-profit-and-loss-chart--hidden',\n )}\n >\n <ProfitAndLoss.DetailedCharts\n scope='expenses'\n hideClose={true}\n stringOverrides={stringOverrides?.profitAndLoss?.detailedCharts}\n />\n </Container>\n </div>\n </View>\n </TasksProvider>\n </ProfitAndLoss>\n )\n}\n", "import React, { ReactNode, useState } from 'react'\nimport { Container, Header } from '../../components/Container'\nimport { Onboarding } from '../../components/Onboarding'\nimport { ProfitAndLoss } from '../../components/ProfitAndLoss'\nimport { ProfitAndLossDetailedChartsStringOverrides } from '../../components/ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts'\nimport { ProfitAndLossSummariesStringOverrides } from '../../components/ProfitAndLossSummaries/ProfitAndLossSummaries'\nimport { Toggle } from '../../components/Toggle'\nimport { TransactionToReviewCard } from '../../components/TransactionToReviewCard'\nimport { Heading, HeadingSize } from '../../components/Typography'\nimport { View } from '../../components/View'\nimport classNames from 'classnames'\n\ninterface AccountingOverviewStringOverrides {\n header?: string\n profitAndLoss?: {\n detailedCharts?: ProfitAndLossDetailedChartsStringOverrides\n summaries?: ProfitAndLossSummariesStringOverrides\n }\n}\n\nexport interface AccountingOverviewProps {\n title?: string\n enableOnboarding?: boolean\n onTransactionsToReviewClick?: () => void\n middleBanner?: ReactNode\n chartColorsList?: string[]\n stringOverrides?: AccountingOverviewStringOverrides\n}\n\ntype PnlToggleOption = 'revenue' | 'expenses'\n\nexport const AccountingOverview = ({\n title = 'Accounting overview',\n enableOnboarding = false,\n onTransactionsToReviewClick,\n middleBanner,\n chartColorsList,\n stringOverrides,\n}: AccountingOverviewProps) => {\n const [pnlToggle, setPnlToggle] = useState<PnlToggleOption>('expenses')\n\n return (\n <ProfitAndLoss asContainer={false}>\n <View title={title} headerControls={<ProfitAndLoss.DatePicker />}>\n {enableOnboarding && (\n <Onboarding\n onTransactionsToReviewClick={onTransactionsToReviewClick}\n />\n )}\n <div className='Layer__accounting-overview__summaries-row'>\n <ProfitAndLoss.Summaries\n stringOverrides={stringOverrides?.profitAndLoss?.summaries}\n />\n <TransactionToReviewCard\n usePnlDateRange={true}\n onClick={onTransactionsToReviewClick}\n />\n </div>\n <Container\n name='accounting-overview-profit-and-loss'\n asWidget\n elevated={true}\n >\n <Header>\n <Heading size={HeadingSize.secondary}>\n {stringOverrides?.header || 'Profit & Loss'}\n </Heading>\n </Header>\n <ProfitAndLoss.Chart />\n </Container>\n {middleBanner && (\n <Container name='accounting-overview-middle-banner'>\n {middleBanner}\n </Container>\n )}\n <div className='Layer__accounting-overview-profit-and-loss-charts'>\n <Toggle\n name='pnl-detailed-charts'\n options={[\n {\n value: 'revenue',\n label: 'Revenue',\n },\n {\n value: 'expenses',\n label: 'Expenses',\n },\n ]}\n selected={pnlToggle}\n onChange={e => setPnlToggle(e.target.value as PnlToggleOption)}\n />\n <Container\n name={classNames(\n 'accounting-overview-profit-and-loss-chart',\n pnlToggle !== 'revenue' &&\n 'accounting-overview-profit-and-loss-chart--hidden',\n )}\n >\n <ProfitAndLoss.DetailedCharts\n scope='revenue'\n hideClose={true}\n stringOverrides={stringOverrides?.profitAndLoss?.detailedCharts}\n chartColorsList={chartColorsList}\n />\n </Container>\n <Container\n name={classNames(\n 'accounting-overview-profit-and-loss-chart',\n pnlToggle !== 'expenses' &&\n 'accounting-overview-profit-and-loss-chart--hidden',\n )}\n >\n <ProfitAndLoss.DetailedCharts\n scope='expenses'\n hideClose={true}\n stringOverrides={stringOverrides?.profitAndLoss?.detailedCharts}\n chartColorsList={chartColorsList}\n />\n </Container>\n </div>\n </View>\n </ProfitAndLoss>\n )\n}\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { Badge } from '../../components/Badge'\nimport { BadgeSize, BadgeVariant } from '../../components/Badge/Badge'\nimport { Text, TextSize } from '../../components/Typography'\nimport { useProfitAndLossLTM } from '../../hooks/useProfitAndLoss/useProfitAndLossLTM'\nimport BellIcon from '../../icons/Bell'\nimport CheckIcon from '../../icons/Check'\nimport RefreshCcw from '../../icons/RefreshCcw'\nimport { BadgeLoader } from '../BadgeLoader'\nimport { NotificationCard } from '../NotificationCard'\nimport { ProfitAndLoss } from '../ProfitAndLoss'\nimport { getMonth, getYear, startOfMonth } from 'date-fns'\n\nexport interface TransactionToReviewCardProps {\n onClick?: () => void\n usePnlDateRange?: boolean\n}\n\nexport const TransactionToReviewCard = ({\n onClick,\n usePnlDateRange,\n}: TransactionToReviewCardProps) => {\n const { dateRange: contextDateRange } = useContext(ProfitAndLoss.Context)\n const dateRange = usePnlDateRange ? contextDateRange : undefined\n\n const [toReview, setToReview] = useState(0)\n\n const { data, loaded, error, refetch } = useProfitAndLossLTM({\n currentDate: dateRange ? dateRange.startDate : startOfMonth(new Date()),\n })\n\n useEffect(() => {\n checkTransactionsToReview()\n }, [])\n\n useEffect(() => {\n checkTransactionsToReview()\n }, [dateRange, loaded])\n\n const checkTransactionsToReview = () => {\n if (data && dateRange) {\n const monthTx = data.filter(\n x =>\n x.month - 1 === getMonth(dateRange.startDate) &&\n x.year === getYear(dateRange.startDate),\n )\n if (monthTx.length > 0) {\n setToReview(monthTx[0].uncategorized_transactions)\n }\n }\n }\n\n return (\n <NotificationCard\n className='Layer__txs-to-review'\n onClick={() => onClick && onClick()}\n >\n <Text size={TextSize.sm}>Transactions to review</Text>\n {loaded === 'initial' || loaded === 'loading' ? <BadgeLoader /> : null}\n\n {loaded === 'complete' && error ? (\n <Badge\n variant={BadgeVariant.ERROR}\n size={BadgeSize.SMALL}\n icon={<RefreshCcw size={12} />}\n onClick={() => refetch()}\n >\n Refresh\n </Badge>\n ) : null}\n\n {loaded === 'complete' && !error && toReview > 0 ? (\n <Badge\n variant={BadgeVariant.WARNING}\n size={BadgeSize.SMALL}\n icon={<BellIcon size={12} />}\n >\n {toReview} pending\n </Badge>\n ) : null}\n\n {loaded === 'complete' && !error && toReview === 0 ? (\n <Badge\n variant={BadgeVariant.SUCCESS}\n size={BadgeSize.SMALL}\n icon={<CheckIcon size={12} />}\n >\n All done\n </Badge>\n ) : null}\n </NotificationCard>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport LoaderIcon from '../../icons/Loader'\n\nexport interface BadgeLoaderProps {\n children?: ReactNode\n size?: number\n}\n\nexport const BadgeLoader = ({ children }: BadgeLoaderProps) => {\n return (\n <span className='Layer__loader Layer__loader--as-badge'>\n <LoaderIcon size={11} className='Layer__anim--rotating' />\n {children}\n </span>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport ChevronRightIcon from '../../icons/ChevronRight'\nimport { IconButton } from '../Button'\nimport classNames from 'classnames'\n\nexport interface NotificationCardProps {\n onClick: () => void\n children: ReactNode\n className?: string\n}\n\nexport const NotificationCard = ({\n onClick,\n children,\n className,\n}: NotificationCardProps) => {\n return (\n <div className={classNames('Layer__notification-card', className)}>\n <div className='Layer__notification-card__main'>{children}</div>\n <IconButton\n icon={<ChevronRightIcon />}\n withBorder\n onClick={() => onClick()}\n />\n </div>\n )\n}\n", "import React from 'react'\nimport { BankTransactions } from '../../components/BankTransactions'\nimport {\n BankTransactionsMode,\n BankTransactionsStringOverrides,\n} from '../../components/BankTransactions/BankTransactions'\nimport { MobileComponentType } from '../../components/BankTransactions/constants'\nimport { LinkedAccounts } from '../../components/LinkedAccounts'\nimport { View } from '../../components/View'\n\ninterface BankTransactionsWithLinkedAccountsStringOverrides {\n title?: string\n linkedAccounts?: BankTransactionsWithLinkedAccountsStringOverrides\n bankTransactions?: BankTransactionsStringOverrides\n}\n\nexport interface BankTransactionsWithLinkedAccountsProps {\n title?: string // deprecated\n elevatedLinkedAccounts?: boolean\n showLedgerBalance?: boolean\n showUnlinkItem?: boolean\n showBreakConnection?: boolean\n showDescriptions?: boolean\n showReceiptUploads?: boolean\n mode?: BankTransactionsMode\n mobileComponent?: MobileComponentType\n stringOverrides?: BankTransactionsWithLinkedAccountsStringOverrides\n}\n\nexport const BankTransactionsWithLinkedAccounts = ({\n title, // deprecated\n elevatedLinkedAccounts = true,\n showLedgerBalance = true,\n showUnlinkItem = false,\n showBreakConnection = false,\n mode = 'self-serve',\n showDescriptions,\n showReceiptUploads,\n mobileComponent,\n stringOverrides,\n}: BankTransactionsWithLinkedAccountsProps) => {\n return (\n <View title={stringOverrides?.title || title || 'Bank transactions'}>\n <LinkedAccounts\n elevated={elevatedLinkedAccounts}\n showLedgerBalance={showLedgerBalance}\n showUnlinkItem={showUnlinkItem}\n showBreakConnection={showBreakConnection}\n stringOverrides={stringOverrides?.linkedAccounts}\n />\n <BankTransactions\n asWidget\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n mobileComponent={mobileComponent}\n mode={mode}\n stringOverrides={stringOverrides?.bankTransactions}\n />\n </View>\n )\n}\n", "import React, { useState } from 'react'\nimport { ChartOfAccounts } from '../../components/ChartOfAccounts'\nimport { ChartOfAccountsStringOverrides } from '../../components/ChartOfAccounts/ChartOfAccounts'\nimport { Container } from '../../components/Container'\nimport { Journal } from '../../components/Journal'\nimport { JournalStringOverrides } from '../../components/Journal/Journal'\nimport { ProfitAndLoss } from '../../components/ProfitAndLoss'\nimport { Toggle } from '../../components/Toggle'\nimport { View } from '../../components/View'\n\nexport interface GeneralLedgerStringOverrides {\n title?: string\n chartOfAccountsToggleOption?: string\n journalToggleOption?: string\n chartOfAccounts: ChartOfAccountsStringOverrides\n journal: JournalStringOverrides\n}\n\nexport interface GeneralLedgerProps {\n title?: string // deprecated\n stringOverrides?: GeneralLedgerStringOverrides\n}\n\nexport const GeneralLedgerView = ({\n title, // deprecated\n stringOverrides,\n}: GeneralLedgerProps) => {\n const [activeTab, setActiveTab] = useState('chartOfAccounts')\n\n return (\n <ProfitAndLoss asContainer={false}>\n <View title={stringOverrides?.title || title || 'General Ledger'}>\n <Toggle\n name='general-ledger-tabs'\n options={[\n {\n value: 'chartOfAccounts',\n label:\n stringOverrides?.chartOfAccountsToggleOption ||\n 'Chart of accounts',\n },\n {\n value: 'journal',\n label: stringOverrides?.journalToggleOption || 'Journal',\n },\n ]}\n selected={activeTab}\n onChange={opt => setActiveTab(opt.target.value)}\n />\n <Container name='generalLedger'>\n {activeTab === 'chartOfAccounts' ? (\n <ChartOfAccounts\n asWidget\n withExpandAllButton\n stringOverrides={stringOverrides?.chartOfAccounts}\n />\n ) : (\n <Journal stringOverrides={stringOverrides?.journal} />\n )}\n </Container>\n </View>\n </ProfitAndLoss>\n )\n}\n", "import React, { RefObject, useContext, useRef, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { BalanceSheet } from '../../components/BalanceSheet'\nimport { BalanceSheetStringOverrides } from '../../components/BalanceSheet/BalanceSheet'\nimport { Button, ButtonVariant, RetryButton } from '../../components/Button'\nimport { Container } from '../../components/Container'\nimport { Panel } from '../../components/Panel'\nimport { ProfitAndLoss } from '../../components/ProfitAndLoss'\nimport { ProfitAndLossDetailedChartsStringOverrides } from '../../components/ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts'\nimport { ProfitAndLossTableStringOverrides } from '../../components/ProfitAndLossTable/ProfitAndLossTable'\nimport { StatementOfCashFlow } from '../../components/StatementOfCashFlow'\nimport { StatementOfCashFlowStringOverrides } from '../../components/StatementOfCashFlow/StatementOfCashFlow'\nimport { Toggle } from '../../components/Toggle'\nimport { View } from '../../components/View'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport DownloadCloud from '../../icons/DownloadCloud'\n\ninterface ReportsStringOverrides {\n title?: string\n downloadButton?: DownloadButtonStringOverrides\n profitAndLoss?: {\n detailedCharts?: ProfitAndLossDetailedChartsStringOverrides\n table?: ProfitAndLossTableStringOverrides\n }\n balanceSheet?: BalanceSheetStringOverrides\n statementOfCashflow?: StatementOfCashFlowStringOverrides\n}\n\nexport interface ReportsProps {\n title?: string // deprecated\n stringOverrides?: ReportsStringOverrides\n enabledReports?: ReportType[]\n}\n\ntype ReportType = 'profitAndLoss' | 'balanceSheet' | 'statementOfCashFlow'\ntype ReportOption = { value: ReportType; label: string }\nexport interface ReportsPanelProps {\n containerRef: RefObject<HTMLDivElement>\n openReport: ReportType\n stringOverrides?: ReportsStringOverrides\n}\n\ninterface DownloadButtonStringOverrides {\n downloadButtonText?: string\n retryButtonText?: string\n}\n\nconst DownloadButton = ({\n stringOverrides,\n}: {\n stringOverrides?: DownloadButtonStringOverrides\n}) => {\n const { dateRange } = useContext(ProfitAndLoss.Context)\n const { auth, businessId, apiUrl } = useLayerContext()\n const [requestFailed, setRequestFailed] = useState(false)\n\n const handleClick = async () => {\n const month = (dateRange.startDate.getMonth() + 1).toString()\n const year = dateRange.startDate.getFullYear().toString()\n const getProfitAndLossCsv = Layer.getProfitAndLossCsv(\n apiUrl,\n auth.access_token,\n {\n params: {\n businessId: businessId,\n year: year,\n month: month,\n },\n },\n )\n try {\n const result = await getProfitAndLossCsv()\n if (result?.data?.presignedUrl) {\n window.location.href = result.data.presignedUrl\n setRequestFailed(false)\n } else {\n setRequestFailed(true)\n }\n } catch (e) {\n setRequestFailed(true)\n }\n }\n\n return requestFailed ? (\n <RetryButton\n onClick={handleClick}\n className='Layer__download-retry-btn'\n error={'Approval failed. Check connection and retry in few seconds.'}\n >\n {stringOverrides?.retryButtonText || 'Retry'}\n </RetryButton>\n ) : (\n <Button\n variant={ButtonVariant.secondary}\n rightIcon={<DownloadCloud size={12} />}\n onClick={handleClick}\n >\n {stringOverrides?.downloadButtonText || 'Download'}\n </Button>\n )\n}\n\nconst getOptions = (enabledReports: ReportType[]) => {\n return [\n enabledReports.includes('profitAndLoss')\n ? {\n value: 'profitAndLoss',\n label: 'Profit & Loss',\n }\n : null,\n enabledReports.includes('balanceSheet')\n ? {\n value: 'balanceSheet',\n label: 'Balance Sheet',\n }\n : null,\n enabledReports.includes('statementOfCashFlow')\n ? {\n value: 'statementOfCashFlow',\n label: 'Statement of Cash Flow',\n }\n : null,\n ].filter(o => !!o) as ReportOption[]\n}\n\nexport const Reports = ({\n title,\n stringOverrides,\n enabledReports = ['profitAndLoss', 'balanceSheet', 'statementOfCashFlow'],\n}: ReportsProps) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [activeTab, setActiveTab] = useState<ReportType>(enabledReports[0])\n\n const options = getOptions(enabledReports)\n const defaultTitle =\n enabledReports.length > 1\n ? 'Reports'\n : options.find(option => (option.value = enabledReports[0]))?.label\n\n return (\n <View title={stringOverrides?.title || title || defaultTitle}>\n {enabledReports.length > 1 && (\n <div className='Layer__component Layer__header__actions'>\n <Toggle\n name='reports-tabs'\n options={options}\n selected={activeTab}\n onChange={opt => setActiveTab(opt.target.value as ReportType)}\n />\n </div>\n )}\n <Container name='reports' ref={containerRef}>\n <ProfitAndLoss asContainer={false}>\n <ReportsPanel\n containerRef={containerRef}\n openReport={activeTab}\n stringOverrides={stringOverrides}\n />\n </ProfitAndLoss>\n </Container>\n </View>\n )\n}\n\nconst ReportsPanel = ({\n containerRef,\n openReport,\n stringOverrides,\n}: ReportsPanelProps) => {\n const { sidebarScope } = useContext(ProfitAndLoss.Context)\n return (\n <>\n {openReport === 'profitAndLoss' && (\n <View\n type='panel'\n headerControls={\n <>\n <ProfitAndLoss.DatePicker />\n <DownloadButton\n stringOverrides={stringOverrides?.downloadButton}\n />\n </>\n }\n >\n <Panel\n sidebar={\n <ProfitAndLoss.DetailedCharts\n showDatePicker={false}\n stringOverrides={stringOverrides?.profitAndLoss?.detailedCharts}\n />\n }\n sidebarIsOpen={Boolean(sidebarScope)}\n parentRef={containerRef}\n >\n <ProfitAndLoss.Table\n asContainer={false}\n stringOverrides={stringOverrides?.profitAndLoss?.table}\n />\n </Panel>\n </View>\n )}\n {openReport === 'balanceSheet' && (\n <BalanceSheet stringOverrides={stringOverrides?.balanceSheet} />\n )}\n {openReport === 'statementOfCashFlow' && (\n <StatementOfCashFlow\n stringOverrides={stringOverrides?.statementOfCashflow}\n />\n )}\n </>\n )\n}\n", "import React, { RefObject, useContext, useRef } from 'react'\nimport { Container, Header } from '../Container'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { Panel } from '../Panel'\nimport { ProfitAndLoss } from '../ProfitAndLoss'\nimport { ProfitAndLossDetailedCharts } from '../ProfitAndLossDetailedCharts'\nimport { ProfitAndLossDetailedChartsStringOverrides } from '../ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts'\nimport { ProfitAndLossSummariesStringOverrides } from '../ProfitAndLossSummaries/ProfitAndLossSummaries'\nimport { ProfitAndLossTableStringOverrides } from '../ProfitAndLossTable/ProfitAndLossTable'\nimport { Heading } from '../Typography'\n\nconst COMPONENT_NAME = 'profit-and-loss'\n\nexport interface ProfitAndLossViewProps {\n hideTable?: boolean\n hideChart?: boolean\n showDetailedCharts?: boolean\n stringOverrides?: {\n header?: string\n profitAndLossTable?: ProfitAndLossTableStringOverrides\n profitAndLossSummaries?: ProfitAndLossSummariesStringOverrides\n profitAndLossDetailedCharts?: ProfitAndLossDetailedChartsStringOverrides\n }\n}\n\nexport interface ProfitAndLossViewPanelProps extends ProfitAndLossViewProps {\n containerRef: RefObject<HTMLDivElement>\n}\n\nexport const ProfitAndLossView = (props: ProfitAndLossViewProps) => {\n const containerRef = useRef<HTMLDivElement>(null)\n\n return (\n <Container name={COMPONENT_NAME} ref={containerRef}>\n <ProfitAndLoss>\n <ProfitAndLossPanel containerRef={containerRef} {...props} />\n </ProfitAndLoss>\n </Container>\n )\n}\n\nconst ProfitAndLossPanel = ({\n containerRef,\n stringOverrides,\n ...props\n}: ProfitAndLossViewPanelProps) => {\n const { sidebarScope } = useContext(ProfitAndLoss.Context)\n\n return (\n <Panel\n sidebar={\n <ProfitAndLossDetailedCharts\n stringOverrides={stringOverrides?.profitAndLossDetailedCharts}\n />\n }\n sidebarIsOpen={Boolean(sidebarScope)}\n parentRef={containerRef}\n >\n <Header className={`Layer__${COMPONENT_NAME}__header`}>\n <Heading className='Layer__profit-and-loss__title'>\n {stringOverrides?.header || 'Profit & Loss'}\n </Heading>\n </Header>\n\n <Components stringOverrides={stringOverrides} {...props} />\n </Panel>\n )\n}\n\nconst Components = ({\n hideChart = false,\n hideTable = false,\n stringOverrides,\n}: ProfitAndLossViewProps) => {\n const { error, isLoading, isValidating, refetch } = useContext(\n ProfitAndLoss.Context,\n )\n\n if (!isLoading && error) {\n return (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={() => refetch()}\n isLoading={isValidating}\n />\n </div>\n )\n }\n\n return (\n <>\n {!hideChart && (\n <div className={`Layer__${COMPONENT_NAME}__chart_with_summaries`}>\n <div\n className={`Layer__${COMPONENT_NAME}__chart_with_summaries__summary-col`}\n >\n <ProfitAndLoss.DatePicker />\n <ProfitAndLoss.Summaries\n vertical={true}\n actionable\n stringOverrides={stringOverrides?.profitAndLossSummaries}\n />\n </div>\n <div\n className={`Layer__${COMPONENT_NAME}__chart_with_summaries__chart-col`}\n >\n <ProfitAndLoss.Chart />\n </div>\n </div>\n )}\n {!hideTable && (\n <ProfitAndLoss.Table\n stringOverrides={stringOverrides?.profitAndLossTable}\n />\n )}\n </>\n )\n}\n"],
|
|
4
|
+
"sourcesContent": ["import React, { PropsWithChildren, useReducer, useEffect, Reducer } from 'react'\nimport { Layer } from '../../api/layer'\nimport { GlobalWidgets } from '../../components/GlobalWidgets'\nimport { ToastProps } from '../../components/Toast/Toast'\nimport { DrawerContext } from '../../contexts/DrawerContext'\nimport { LayerContext } from '../../contexts/LayerContext'\nimport { useDataSync } from '../../hooks/useDataSync'\nimport { useDrawer } from '../../hooks/useDrawer'\nimport { LayerError, errorHandler } from '../../models/ErrorHandler'\nimport { BankTransactionsProvider } from '../../providers/BankTransactionsProvider'\nimport {\n LayerContextValues,\n LayerContextAction,\n LayerContextActionName as Action,\n BankTransaction,\n} from '../../types'\nimport {\n ColorConfig,\n ColorsPaletteOption,\n LayerThemeConfig,\n OnboardingStep,\n} from '../../types/layer_context'\nimport { buildColorsPalette } from '../../utils/colors'\nimport { add, isBefore } from 'date-fns'\nimport useSWR, { SWRConfig } from 'swr'\n\nconst reducer: Reducer<LayerContextValues, LayerContextAction> = (\n state,\n action,\n) => {\n switch (action.type) {\n case Action.setAuth:\n case Action.setBusiness:\n case Action.setCategories:\n case Action.setTheme:\n case Action.setOnboardingStep:\n case Action.setColors:\n return { ...state, ...action.payload }\n case Action.setToast:\n return {\n ...state,\n toasts: [\n ...state.toasts,\n { ...action.payload.toast, isExiting: false },\n ],\n }\n case Action.setToastExit:\n return {\n ...state,\n toasts: state.toasts.map(toast =>\n toast.id === action.payload.toast.id\n ? { ...toast, isExiting: false }\n : toast,\n ),\n }\n case Action.removeToast:\n return {\n ...state,\n toasts: state.toasts.filter(t => t.id !== action.payload.toast.id),\n }\n default:\n return state\n }\n}\n\ntype LayerEnvironmentConfig = {\n url: string\n scope: string\n apiUrl: string\n}\n\nexport const LayerEnvironment: Record<string, LayerEnvironmentConfig> = {\n production: {\n url: 'https://auth.layerfi.com/oauth2/token',\n scope: 'https://api.layerfi.com/production',\n apiUrl: 'https://api.layerfi.com',\n },\n sandbox: {\n url: 'https://auth.layerfi.com/oauth2/token',\n scope: 'https://sandbox.layerfi.com/sandbox',\n apiUrl: 'https://sandbox.layerfi.com',\n },\n staging: {\n url: 'https://auth.layerfi.com/oauth2/token',\n scope: 'https://sandbox.layerfi.com/sandbox',\n apiUrl: 'https://sandbox.layerfi.com',\n },\n internalStaging: {\n url: 'https://auth.layerfi.com/oauth2/token',\n scope: 'https://sandbox.layerfi.com/sandbox',\n apiUrl: 'https://staging.layerfi.com',\n },\n}\n\nexport type EventCallbacks = {\n onTransactionCategorized?: (bankTransactionId: string) => void\n}\n\nexport type Props = {\n businessId: string\n appId?: string\n appSecret?: string\n businessAccessToken?: string\n environment?: keyof typeof LayerEnvironment\n theme?: LayerThemeConfig\n usePlaidSandbox?: boolean\n onError?: (error: LayerError) => void\n eventCallbacks?: EventCallbacks\n}\n\nexport const LayerProvider = ({\n appId,\n appSecret,\n businessId,\n children,\n businessAccessToken,\n environment = 'production',\n theme,\n usePlaidSandbox,\n onError,\n eventCallbacks,\n}: PropsWithChildren<Props>) => {\n const defaultSWRConfig = {\n revalidateInterval: 0,\n revalidateOnFocus: false,\n revalidateOnReconnect: false,\n revalidateIfStale: false,\n }\n\n errorHandler.setOnError(onError)\n\n const colors = buildColorsPalette(theme)\n\n const { url, scope, apiUrl } = LayerEnvironment[environment]\n const [state, dispatch] = useReducer(reducer, {\n auth: {\n access_token: '',\n token_type: '',\n expires_in: 0,\n expires_at: new Date(2000, 1, 1),\n },\n businessId,\n business: undefined,\n categories: [],\n apiUrl,\n theme,\n colors,\n usePlaidSandbox,\n onboardingStep: undefined,\n environment,\n toasts: [],\n eventCallbacks: {},\n })\n\n const { touch, syncTimestamps, read, readTimestamps, hasBeenTouched } =\n useDataSync()\n\n const { data: auth } =\n appId !== undefined && appSecret !== undefined\n ? useSWR(\n businessAccessToken === undefined &&\n appId !== undefined &&\n appSecret !== undefined &&\n isBefore(state.auth.expires_at, new Date()) &&\n 'authenticate',\n Layer.authenticate({\n appId,\n appSecret,\n authenticationUrl: url,\n scope,\n }),\n defaultSWRConfig,\n )\n : { data: undefined }\n\n useEffect(() => {\n if (businessAccessToken) {\n dispatch({\n type: Action.setAuth,\n payload: {\n auth: {\n access_token: businessAccessToken,\n token_type: 'Bearer',\n expires_in: 3600,\n expires_at: add(new Date(), { seconds: 3600.0 }),\n },\n },\n })\n } else if (auth?.access_token) {\n dispatch({\n type: Action.setAuth,\n payload: {\n auth: {\n ...auth,\n expires_at: add(new Date(), { seconds: auth.expires_in }),\n },\n },\n })\n }\n }, [businessAccessToken, auth?.access_token])\n\n const { data: categoriesData } = useSWR(\n businessId && state.auth?.access_token && `categories-${businessId}`,\n Layer.getCategories(apiUrl, state.auth?.access_token, {\n params: { businessId },\n }),\n {\n ...defaultSWRConfig,\n onSuccess: response => {\n if (response?.data?.categories?.length) {\n dispatch({\n type: Action.setCategories,\n payload: { categories: response.data.categories || [] },\n })\n }\n },\n },\n )\n useEffect(() => {\n if (categoriesData?.data?.categories?.length) {\n dispatch({\n type: Action.setCategories,\n payload: { categories: categoriesData.data.categories || [] },\n })\n }\n }, [categoriesData])\n\n const { data: businessData } = useSWR(\n businessId && state?.auth?.access_token && `business-${businessId}`,\n Layer.getBusiness(apiUrl, state?.auth?.access_token, {\n params: { businessId },\n }),\n {\n ...defaultSWRConfig,\n onSuccess: response => {\n if (response?.data) {\n dispatch({\n type: Action.setBusiness,\n payload: { business: response.data || [] },\n })\n }\n },\n },\n )\n useEffect(() => {\n if (businessData?.data) {\n dispatch({\n type: Action.setBusiness,\n payload: { business: businessData.data || [] },\n })\n }\n }, [businessData])\n\n const setTheme = (theme: LayerThemeConfig) => {\n dispatch({\n type: Action.setTheme,\n payload: { theme },\n })\n\n dispatch({\n type: Action.setColors,\n payload: { colors: buildColorsPalette(theme) },\n })\n }\n\n const setLightColor = (color?: ColorConfig) => {\n setTheme({\n ...(state.theme ?? {}),\n colors: {\n ...(state.theme?.colors ?? {}),\n light: color,\n },\n })\n }\n\n const setDarkColor = (color?: ColorConfig) => {\n setTheme({\n ...(state.theme ?? {}),\n colors: {\n ...(state.theme?.colors ?? {}),\n dark: color,\n },\n })\n }\n\n const setTextColor = (color?: ColorConfig) => {\n setTheme({\n ...(state.theme ?? {}),\n colors: {\n ...(state.theme?.colors ?? {}),\n text: color,\n },\n })\n }\n\n const setToast = (toast: ToastProps) => {\n dispatch({ type: Action.setToast, payload: { toast: toast } })\n }\n\n const removeToast = (toast: ToastProps) => {\n dispatch({ type: Action.removeToast, payload: { toast: toast } })\n }\n\n const setToastExit = (toast: ToastProps) => {\n dispatch({ type: Action.setToastExit, payload: { toast: toast } })\n }\n\n const addToast = (toast: ToastProps) => {\n const id = `${Date.now()}-${Math.random()}`\n const newToast = { id, isExiting: false, ...toast }\n\n setToast(newToast)\n\n setTimeout(() => {\n removeToast(newToast)\n setTimeout(() => {\n setToastExit(newToast)\n }, 1000)\n }, toast.duration || 2000)\n }\n\n const setColors = (colors?: { dark?: ColorConfig; light?: ColorConfig }) =>\n setTheme({\n ...(state.theme ?? {}),\n colors,\n })\n\n const getColor = (shade: number): ColorsPaletteOption | undefined => {\n if (state.colors && shade in state.colors) {\n return state.colors[shade]\n }\n\n return\n }\n\n const setOnboardingStep = (value: OnboardingStep) =>\n dispatch({\n type: Action.setOnboardingStep,\n payload: { onboardingStep: value },\n })\n\n const drawerContextData = useDrawer()\n\n return (\n <SWRConfig value={defaultSWRConfig}>\n <LayerContext.Provider\n value={{\n ...state,\n setTheme,\n getColor,\n setLightColor,\n setDarkColor,\n setTextColor,\n setColors,\n setOnboardingStep,\n addToast,\n removeToast,\n onError: errorHandler.onError,\n touch,\n read,\n syncTimestamps,\n readTimestamps,\n hasBeenTouched,\n eventCallbacks,\n }}\n >\n <BankTransactionsProvider>\n <DrawerContext.Provider value={drawerContextData}>\n {children}\n <GlobalWidgets />\n </DrawerContext.Provider>\n </BankTransactionsProvider>\n </LayerContext.Provider>\n </SWRConfig>\n )\n}\n", "export const formStringFromObject = (\n object: Record<string, string | number | boolean>,\n): string =>\n Object.entries(object)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&')\n", "import { OAuthResponse } from '../../types'\nimport { formStringFromObject } from '../util'\n\ntype AuthenticationArguments = {\n appId: string\n appSecret: string\n authenticationUrl?: string\n scope: string\n}\nexport const authenticate =\n ({\n appId,\n appSecret,\n authenticationUrl = 'https://auth.layerfi.com/oauth2/token',\n scope,\n }: AuthenticationArguments) =>\n (): Promise<OAuthResponse> =>\n fetch(authenticationUrl, {\n method: 'POST',\n headers: {\n Authorization: 'Basic ' + btoa(appId + ':' + appSecret),\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: formStringFromObject({\n grant_type: 'client_credentials',\n scope,\n client_id: appId,\n }),\n }).then(res => res.json() as Promise<OAuthResponse>)\n", "export interface APIErrorMessage {\n type?: string\n description?: string\n}\n\nexport class APIError extends Error {\n code?: number\n info?: string\n messages?: APIErrorMessage[]\n\n constructor(message: string, code?: number, messages?: APIErrorMessage[]) {\n super(message)\n this.name = 'APIError'\n this.code = code\n this.messages = messages\n\n Object.setPrototypeOf(this, APIError.prototype)\n }\n\n getMessage() {\n return this.message\n }\n\n getAllMessages() {\n return this.messages?.map(x => x.description)\n }\n}\n", "import { APIError } from './APIError'\n\ntype LayerErrorType = 'unauthenticated' | 'api' | 'render'\ntype LayerErrorScope = 'BankTransaction' | 'ChartOfAccounts'\n\nexport interface LayerError {\n type?: LayerErrorType\n scope?: LayerErrorScope\n payload: Error | APIError\n}\n\nclass ErrorHandlerClass {\n public onErrorCallback?: (err: LayerError) => void | undefined\n\n constructor() {\n this.onErrorCallback = undefined\n }\n\n public setOnError(errorFnc: ((err: LayerError) => void) | undefined) {\n this.onErrorCallback = errorFnc\n }\n\n public onError(err: LayerError) {\n if (this.onErrorCallback) {\n this.onErrorCallback(err)\n }\n }\n}\n\nexport const errorHandler = new ErrorHandlerClass()\n\nexport const reportError = (payload: LayerError) =>\n errorHandler.onError(payload)\n", "import { APIError } from '../../models/APIError'\nimport { reportError } from '../../models/ErrorHandler'\n\nexport type HTTPVerb = 'get' | 'put' | 'post' | 'patch' | 'options' | 'delete'\n\nexport const get =\n <\n Return extends Record<string, unknown> = Record<string, unknown>,\n Params extends Record<string, string | undefined> = Record<\n string,\n string | undefined\n >,\n >(\n url: (params: Params) => string,\n ) =>\n (\n baseUrl: string,\n accessToken: string | undefined,\n options?: { params?: Params },\n ) =>\n (): Promise<Return> =>\n fetch(`${baseUrl}${url(options?.params || ({} as Params))}`, {\n headers: {\n Authorization: 'Bearer ' + (accessToken || ''),\n 'Content-Type': 'application/json',\n },\n method: 'GET',\n })\n .then(res => handleResponse<Return>(res))\n .catch(error => handleException(error))\n\nexport const request =\n (verb: HTTPVerb) =>\n <\n Return extends Record<string, unknown> = Record<string, unknown>,\n Body extends Record<string, unknown> = Record<string, unknown>,\n Params extends Record<string, string | undefined> = Record<\n string,\n string | undefined\n >,\n >(\n url: (params: Params) => string,\n ) =>\n (\n baseUrl: string,\n accessToken: string | undefined,\n options?: {\n params?: Params\n body?: Body\n },\n ): Promise<Return> =>\n fetch(`${baseUrl}${url(options?.params || ({} as Params))}`, {\n headers: {\n Authorization: 'Bearer ' + (accessToken || ''),\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n },\n method: verb.toUpperCase(),\n body: JSON.stringify(options?.body),\n })\n .then(res => handleResponse<Return>(res))\n .catch(error => handleException(error))\n\nexport const post = request('post')\nexport const put = request('put')\nexport const deleteRequest = request('delete')\n\nexport const postWithFormData = <\n Return extends Record<string, unknown> = Record<string, unknown>,\n>(\n url: string,\n formData: FormData,\n baseUrl: string,\n accessToken: string | undefined,\n): Promise<Return> => {\n return fetch(`${baseUrl}${url}`, {\n method: 'POST',\n headers: {\n Authorization: 'Bearer ' + (accessToken || ''),\n },\n body: formData,\n })\n .then(res => handleResponse<Return>(res))\n .catch(error => handleException(error))\n}\n\nconst handleResponse = async <Return>(res: Response) => {\n if (!res.ok) {\n const errors = await tryToReadErrorsFromResponse(res)\n const apiError = new APIError(\n 'An error occurred while fetching the data from API.',\n res.status,\n errors,\n )\n throw apiError\n }\n\n const parsedResponse = await res.json()\n if (parsedResponse && 'errors' in parsedResponse) {\n const apiError = new APIError(\n 'Errors in the API response.',\n res.status,\n parsedResponse.errors ?? [],\n )\n throw apiError\n }\n\n return parsedResponse as Return\n}\n\nconst handleException = async (error: Error | APIError) => {\n if (error.name === 'APIError') {\n reportError({\n type: (error as APIError).code === 401 ? 'unauthenticated' : 'api',\n payload: error,\n })\n\n throw error\n }\n\n const apiError = new APIError(\n 'An error occurred while parsing the data from API.',\n undefined,\n [],\n )\n\n reportError({\n type: 'api',\n payload: apiError,\n })\n\n throw apiError\n}\n\nconst tryToReadErrorsFromResponse = async (res?: Response) => {\n try {\n const data = await res?.json()\n return data?.errors ?? []\n } catch (_err) {\n return []\n }\n}\n", "import { BalanceSheet } from '../../types'\nimport { get } from './authenticated_http'\n\nexport const getBalanceSheet = get<\n GetBalanceSheetReturn,\n GetBalanceSheetParams\n>(\n ({ businessId, effectiveDate }: GetBalanceSheetParams) =>\n `/v1/businesses/${businessId}/reports/balance-sheet?effective_date=${encodeURIComponent(\n effectiveDate,\n )}`,\n)\n\nexport type GetBalanceSheetReturn = {\n data?: BalanceSheet\n error?: unknown\n}\n\nexport interface GetBalanceSheetParams\n extends Record<string, string | undefined> {\n businessId: string\n effectiveDate: string\n}\n", "import { CategoryUpdate, BankTransaction, Metadata } from '../../types'\nimport {\n BankTransactionMatch,\n BankTransactionMatchType,\n BankTransactionMetadata,\n DocumentS3Urls,\n FileMetadata,\n} from '../../types/bank_transactions'\nimport { S3PresignedUrl } from '../../types/general'\nimport { get, put, post, postWithFormData } from './authenticated_http'\n\nexport type GetBankTransactionsReturn = {\n data?: BankTransaction[]\n meta?: Metadata\n error?: unknown\n}\n\nexport interface GetBankTransactionsParams\n extends Record<string, string | undefined> {\n businessId: string\n cursor?: string\n categorized?: string\n sortOrder?: 'ASC' | 'DESC'\n sortBy?: string\n}\nexport const getBankTransactions = get<\n GetBankTransactionsReturn,\n GetBankTransactionsParams\n>(\n ({\n businessId,\n cursor,\n categorized,\n sortBy = 'date',\n sortOrder = 'DESC',\n }: GetBankTransactionsParams) =>\n `/v1/businesses/${businessId}/bank-transactions?${\n cursor ? `cursor=${cursor}&` : ''\n }${\n categorized !== undefined && categorized !== '' ? `categorized=${categorized}&` : ''\n }sort_by=${sortBy}&sort_order=${sortOrder}&limit=200`,\n)\n\nexport const categorizeBankTransaction = put<\n { data: BankTransaction; errors: unknown },\n CategoryUpdate\n>(\n ({ businessId, bankTransactionId }) =>\n `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/categorize`,\n)\n\nexport const matchBankTransaction = put<\n { data: BankTransactionMatch; errors: unknown },\n { match_id: string; type: BankTransactionMatchType }\n>(\n ({ businessId, bankTransactionId }) =>\n `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/match`,\n)\n\nexport interface GetBankTransactionsCsvParams\n extends Record<string, string | undefined> {\n businessId: string\n startDate?: string\n endDate?: string\n categorized?: 'true' | 'false'\n category?: string\n month?: string\n year?: string\n}\n\nexport const getBankTransactionsCsv = get<{\n data?: S3PresignedUrl\n error?: unknown\n}>((params: Record<string, string | undefined>) => {\n const { businessId, startDate, endDate, categorized, category, month, year } =\n params as GetBankTransactionsCsvParams // Type assertion here for clarity\n return `/v1/businesses/${businessId}/reports/transactions/exports/csv?${\n startDate ? `start_date=${encodeURIComponent(startDate)}&` : ''\n }${endDate ? `end_date=${encodeURIComponent(endDate)}&` : ''}${\n month ? `month=${encodeURIComponent(month)}&` : ''\n }${year ? `year=${encodeURIComponent(year)}&` : ''}${\n categorized ? `categorized=${categorized}&` : ''\n }${category ? `category=${encodeURIComponent(category)}&` : ''}`\n})\n\nexport const getBankTransactionMetadata = get<{\n data: BankTransactionMetadata\n errors: unknown\n}>(\n ({ businessId, bankTransactionId }) =>\n `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/metadata`,\n)\n\nexport const updateBankTransactionMetadata = put<\n { data: BankTransactionMetadata; errors: unknown },\n { memo: string }\n>(\n ({ businessId, bankTransactionId }) =>\n `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/metadata`,\n)\n\nexport const listBankTransactionDocuments = get<{\n data: DocumentS3Urls\n errors: unknown\n}>(\n ({ businessId, bankTransactionId }) =>\n `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/documents`,\n)\n\nexport const uploadBankTransactionDocument =\n (baseUrl: string, accessToken: string) =>\n ({\n businessId,\n bankTransactionId,\n file,\n documentType,\n }: {\n businessId: string\n bankTransactionId: string\n file: File\n documentType: string\n }) => {\n const formData = new FormData()\n formData.append('file', file)\n formData.append('documentType', documentType)\n\n const endpoint = `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/documents`\n return postWithFormData<{ data: FileMetadata; errors: unknown }>(\n endpoint,\n formData,\n baseUrl,\n accessToken,\n )\n }\n", "import { Business } from '../../types'\nimport { get } from './authenticated_http'\n\nexport const getBusiness = get<{\n data: Business\n}>(({ businessId }) => `/v1/businesses/${businessId}`)\n", "import { Category } from '../../types'\nimport { get } from './authenticated_http'\n\nexport const getCategories = get<{\n data: {\n type: 'Category_List'\n categories: Category[]\n }\n}>(({ businessId }) => `/v1/businesses/${businessId}/categories`)\n", "import {\n Account,\n ChartOfAccounts,\n NewAccount,\n EditAccount,\n LedgerAccountsEntry,\n} from '../../types'\nimport { ChartWithBalances } from '../../types/chart_of_accounts'\nimport { LedgerAccountLineItems } from '../../types/ledger_accounts'\nimport { get, post, put } from './authenticated_http'\n\nexport const getChartOfAccounts = get<{ data: ChartOfAccounts }>(\n ({ businessId }) => `/v1/businesses/${businessId}/ledger/accounts`,\n)\n\nexport const getLedgerAccountBalances = get<{ data: ChartWithBalances }>(\n ({ businessId, startDate, endDate }) =>\n `/v1/businesses/${businessId}/ledger/balances?${\n startDate ? `&start_date=${encodeURIComponent(startDate)}` : ''\n }${endDate ? `&end_date=${encodeURIComponent(endDate)}` : ''}`,\n)\n\nexport const createAccount = post<{ data: Account }, NewAccount>(\n ({ businessId }) => `/v1/businesses/${businessId}/ledger/accounts`,\n)\n\nexport const updateAccount = put<{ data: Account }, EditAccount>(\n ({ businessId, accountId }) =>\n `/v1/businesses/${businessId}/ledger/accounts/${accountId}`,\n)\n\nexport const getLedgerAccountsLines = get<{ data: LedgerAccountLineItems }>(\n ({ businessId, accountId }) =>\n `/v1/businesses/${businessId}/ledger/accounts/${accountId}/lines`,\n)\n\nexport const getLedgerAccountsEntry = get<{ data: LedgerAccountsEntry }>(\n ({ businessId, entryId }) =>\n `/v1/businesses/${businessId}/ledger/entries/${entryId}`,\n)\n", "\nimport { JournalEntry } from '../../types/journal'\nimport { get, post } from './authenticated_http'\n\nexport const getJournal = get<{ data: JournalEntry[] }>(\n ({ businessId }) => `/v1/businesses/${businessId}/ledger/entries`,\n)\n\nexport const createJournalEntries = post<{ data: JournalEntry[] }>(\n ({ businessId }) => `/v1/businesses/${businessId}/ledger/manual-entries`,\n)\n", "import { LinkedAccounts, PublicToken } from '../../types/linked_accounts'\nimport { get, post } from './authenticated_http'\n\nexport const syncConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n }\n>(({ businessId }) => `/v1/businesses/${businessId}/sync`)\n\nexport const updateConnectionStatus = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n }\n>(\n ({ businessId }) =>\n `/v1/businesses/${businessId}/external-accounts/update-connection-status`,\n)\n\nexport const getLinkedAccounts = get<\n { data: LinkedAccounts },\n {\n businessId: string\n }\n>(({ businessId }) => `/v1/businesses/${businessId}/external-accounts`)\n\nexport const confirmConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n accountId: string\n }\n>(\n ({ businessId, accountId }) =>\n `/v1/businesses/${businessId}/external-accounts/${accountId}/confirm`,\n)\n\nexport const denyConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n accountId: string\n }\n>(\n ({ businessId, accountId }) =>\n `/v1/businesses/${businessId}/external-accounts/${accountId}/deny`,\n)\n\n// TODO: not implemented yet in backend\nexport const unlinkConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n connectionId: string\n }\n>(\n ({ businessId, connectionId }) =>\n `/v1/businesses/${businessId}/plaid/external-accounts/connection/${connectionId}/archive`,\n)\n\nexport const unlinkAccount = post<\n Record<string, unknown>,\n Record<string, unknown>,\n { businessId: string; accountId: string }\n>(\n ({ businessId, accountId }) =>\n `/v1/businesses/${businessId}/external-accounts/${accountId}/archive`,\n)\n\n/**********************\n * Plaid Specific API *\n **********************/\n\nexport const getPlaidLinkToken = post<\n {\n data: {\n type: 'Link_Token'\n link_token: string\n }\n },\n Record<string, unknown>,\n {\n businessId: string\n }\n>(({ businessId }) => `/v1/businesses/${businessId}/plaid/link`)\n\nexport const getPlaidUpdateModeLinkToken = post<\n {\n data: {\n type: 'Link_Token'\n link_token: string\n }\n },\n Record<string, unknown>,\n {\n businessId: string\n }\n>(({ businessId }) => `/v1/businesses/${businessId}/plaid/update-mode-link`)\n\nexport const exchangePlaidPublicToken = post<\n Record<string, unknown>,\n PublicToken,\n {\n businessId: string\n }\n>(({ businessId }) => `/v1/businesses/${businessId}/plaid/link/exchange`)\n\n// TODO: Delete once \"unlinkConnection\" is online. unlinkConnection is broader and would be able\n// to handle other providers like Stripe as well as Plaid\nexport const unlinkPlaidItem = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n plaidItemPlaidId: string\n }\n>(\n ({ businessId, plaidItemPlaidId }) =>\n `/v1/businesses/${businessId}/plaid/items/${plaidItemPlaidId}/unlink`,\n)\n\n// Only works in non-production environments\nexport const breakPlaidItemConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n {\n businessId: string\n plaidItemPlaidId: string\n }\n>(\n ({ businessId, plaidItemPlaidId }) =>\n `/v1/businesses/${businessId}/plaid/items/${plaidItemPlaidId}/sandbox-reset-item-login`,\n)\n\n// export const createAccount = post<{ data: LinkedAccount }, NewAccount>(\n// ({ businessId }) => `/v1/businesses/${businessId}/external-accounts`,\n// )\n", "import { ProfitAndLoss } from '../../types'\nimport { S3PresignedUrl } from '../../types/general'\nimport { ProfitAndLossSummaries } from '../../types/profit_and_loss'\nimport { get } from './authenticated_http'\n\nexport const getProfitAndLoss = get<{\n data?: ProfitAndLoss\n error?: unknown\n}>(\n ({ businessId, startDate, endDate, tagKey, tagValues, reportingBasis }) =>\n `/v1/businesses/${businessId}/reports/profit-and-loss?start_date=${\n startDate ? encodeURIComponent(startDate) : ''\n }&end_date=${endDate ? encodeURIComponent(endDate) : ''}${\n reportingBasis ? `&reporting_basis=${reportingBasis}` : ''\n }${tagKey ? `&tag_key=${tagKey}` : ''}${\n tagValues ? `&tag_values=${tagValues}` : ''\n }`,\n)\n\nexport const getProfitAndLossSummaries = get<{\n data?: ProfitAndLossSummaries\n error?: unknown\n}>(\n ({\n businessId,\n startYear,\n startMonth,\n endYear,\n endMonth,\n tagKey,\n tagValues,\n reportingBasis,\n }) =>\n `/v1/businesses/${businessId}/reports/profit-and-loss-summaries?start_year=${\n startYear ? encodeURIComponent(startYear) : ''\n }&start_month=${\n startMonth ? encodeURIComponent(startMonth) : ''\n }&end_year=${endYear ? encodeURIComponent(endYear) : ''}&end_month=${\n endMonth ? encodeURIComponent(endMonth) : ''\n }${reportingBasis ? `&reporting_basis=${reportingBasis}` : ''}${\n tagKey ? `&tag_key=${tagKey}` : ''\n }${tagValues ? `&tag_values=${tagValues}` : ''}`,\n)\n\nexport const getProfitAndLossCsv = get<{\n data?: S3PresignedUrl\n error?: unknown\n}>(\n ({\n businessId,\n startDate,\n endDate,\n month,\n year,\n tagKey,\n tagValues,\n reportingBasis,\n }) =>\n `/v1/businesses/${businessId}/reports/profit-and-loss/exports/csv?${\n startDate ? `start_date=${encodeURIComponent(startDate)}` : ''\n }${endDate ? `&end_date=${encodeURIComponent(endDate)}` : ''}${\n month ? `&month=${month}` : ''\n }${year ? `&year=${year}` : ''}${\n reportingBasis ? `&reporting_basis=${reportingBasis}` : ''\n }${tagKey ? `&tag_key=${tagKey}` : ''}${\n tagValues ? `&tag_values=${tagValues}` : ''\n }`,\n)\n", "import { StatusOfSyncFromQuickbooks } from \"../../types/quickbooks\";\nimport { get, post } from \"./authenticated_http\";\n\nexport const syncFromQuickbooks = post<\n Record<string, unknown>,\n Record<string, unknown>,\n { businessId: string }\n>(({ businessId }) => `/v1/businesses/${businessId}/quickbooks/sync-from`);\n\nexport const statusOfSyncFromQuickbooks = get<\n { data: StatusOfSyncFromQuickbooks },\n { businessId: string }\n>(\n ({ businessId }) => `/v1/businesses/${businessId}/quickbooks/sync-from/status`\n);\n\nexport const initQuickbooksOAuth = post<\n {\n data: {\n type: \"Quickbooks_Authorization_Params\";\n redirect_url: string;\n };\n },\n Record<string, unknown>,\n { businessId: string }\n>(({ businessId }) => `/v1/businesses/${businessId}/quickbooks/authorize`);\n\nexport const unlinkQuickbooksConnection = post<\n Record<string, unknown>,\n Record<string, unknown>,\n { businessId: string }\n>(({ businessId }) => `/v1/businesses/${businessId}/quickbooks/unlink`);\n\n/**\n * Lets user know if there exists an active Quickbooks connection or not\n */\nexport const statusOfQuickbooksConnection = get<\n {\n data: {\n is_connected: boolean;\n };\n },\n { businessId: string }\n>(\n ({ businessId }) =>\n `/v1/businesses/${businessId}/quickbooks/connection-status`\n);\n", "import { StatementOfCashFlow } from '../../types'\nimport { get } from './authenticated_http'\n\nexport const getStatementOfCashFlow = get<\n GetStatementOfCashFlowReturn,\n GetStatementOfCashFlowParams\n>(\n ({ businessId, startDate, endDate }: GetStatementOfCashFlowParams) =>\n `/v1/businesses/${businessId}/reports/cashflow-statement?start_date=${encodeURIComponent(\n startDate,\n )}&end_date=${encodeURIComponent(endDate)}`,\n)\n\nexport type GetStatementOfCashFlowReturn = {\n data?: StatementOfCashFlow\n error?: unknown\n}\n\nexport interface GetStatementOfCashFlowParams\n extends Record<string, string | undefined> {\n businessId: string\n startDate: string\n endDate: string\n}\n", "import { TaskTypes } from '../../types/tasks'\nimport { get, post } from './authenticated_http'\n\nexport const getTasks = get<{ data: TaskTypes[] }>(\n ({ businessId }) => `/v1/businesses/${businessId}/tasks`,\n)\n\nexport const submitResponseToTask = post<{ data: TaskTypes }>(\n ({ businessId, taskId }) =>\n `/v1/businesses/${businessId}/tasks/${taskId}/user-response`,\n)\n\nexport const markTaskAsComplete = post<{ data: TaskTypes }>(\n ({ businessId, taskId }) =>\n `/v1/businesses/${businessId}/tasks/${taskId}/complete`,\n)\n", "import { authenticate } from './layer/authenticate'\nimport { getBalanceSheet } from './layer/balance_sheet'\nimport {\n getBankTransactions,\n categorizeBankTransaction,\n matchBankTransaction,\n getBankTransactionsCsv,\n getBankTransactionMetadata,\n updateBankTransactionMetadata,\n listBankTransactionDocuments,\n uploadBankTransactionDocument,\n} from './layer/bankTransactions'\nimport { getBusiness } from './layer/business'\nimport { getCategories } from './layer/categories'\nimport {\n getChartOfAccounts,\n getLedgerAccountBalances,\n createAccount,\n updateAccount,\n getLedgerAccountsLines,\n getLedgerAccountsEntry,\n} from './layer/chart_of_accounts'\nimport { getJournal, createJournalEntries } from './layer/journal'\nimport {\n getLinkedAccounts,\n getPlaidLinkToken,\n getPlaidUpdateModeLinkToken,\n exchangePlaidPublicToken,\n unlinkPlaidItem,\n unlinkAccount,\n confirmConnection,\n denyConnection,\n breakPlaidItemConnection,\n syncConnection,\n updateConnectionStatus,\n} from './layer/linked_accounts'\nimport {\n getProfitAndLoss,\n getProfitAndLossSummaries,\n getProfitAndLossCsv,\n} from './layer/profit_and_loss'\nimport {\n syncFromQuickbooks,\n statusOfSyncFromQuickbooks,\n initQuickbooksOAuth,\n statusOfQuickbooksConnection,\n unlinkQuickbooksConnection,\n} from './layer/quickbooks'\nimport { getStatementOfCashFlow } from './layer/statement-of-cash-flow'\nimport { getTasks, submitResponseToTask } from './layer/tasks'\n\nexport const Layer = {\n authenticate,\n getBusiness,\n categorizeBankTransaction,\n matchBankTransaction,\n createAccount,\n updateAccount,\n getBalanceSheet,\n getBankTransactions,\n getBankTransactionsCsv,\n getBankTransactionMetadata,\n listBankTransactionDocuments,\n updateBankTransactionMetadata,\n uploadBankTransactionDocument,\n getCategories,\n getChartOfAccounts,\n getLedgerAccountBalances,\n getLedgerAccountsLines,\n getLedgerAccountsEntry,\n getProfitAndLoss,\n getProfitAndLossSummaries,\n getProfitAndLossCsv,\n getLinkedAccounts,\n getJournal,\n createJournalEntries,\n getPlaidLinkToken,\n getPlaidUpdateModeLinkToken,\n exchangePlaidPublicToken,\n unlinkAccount,\n unlinkPlaidItem,\n confirmConnection,\n denyConnection,\n getTasks,\n submitResponseToTask,\n breakPlaidItemConnection,\n syncConnection,\n updateConnectionStatus,\n getStatementOfCashFlow,\n syncFromQuickbooks,\n statusOfSyncFromQuickbooks,\n statusOfQuickbooksConnection,\n initQuickbooksOAuth,\n unlinkQuickbooksConnection,\n}\n", "import React, { useContext, useEffect } from 'react'\nimport { DrawerContext } from '../../contexts/DrawerContext'\nimport { useSizeClass } from '../../hooks/useWindowSize'\nimport { Drawer } from '../Drawer'\nimport { ToastsContainer } from '../Toast/Toast'\n\nconst DrawerWidget = () => {\n const { content, close } = useContext(DrawerContext)\n\n const { isMobile, isTablet } = useSizeClass()\n\n useEffect(() => {\n if (!isMobile && !isTablet && content) {\n close()\n }\n }, [isMobile])\n\n return (\n <Drawer isOpen={Boolean(content)} onClose={close}>\n {content}\n </Drawer>\n )\n}\n\nexport const GlobalWidgets = () => {\n return (\n <>\n <ToastsContainer />\n <DrawerWidget />\n </>\n )\n}\n", "import { createContext } from 'react'\nimport { useDrawer } from '../../hooks/useDrawer'\n\nexport type DrawerContextType = ReturnType<typeof useDrawer>\nexport const DrawerContext = createContext<DrawerContextType>({\n content: undefined,\n setContent: () => undefined,\n close: () => undefined,\n isClosing: false,\n finishClosing: () => undefined,\n})\n", "import { useState, useLayoutEffect, useMemo } from 'react'\nimport { BREAKPOINTS } from '../../config/general'\n\nexport const useWindowSize = () => {\n const [size, setSize] = useState([0, 0])\n useLayoutEffect(() => {\n function updateSize() {\n setSize([window.innerWidth, window.innerHeight])\n }\n\n window.addEventListener('resize', updateSize)\n\n updateSize()\n\n return () => window.removeEventListener('resize', updateSize)\n }, [])\n return size\n}\n\nexport type SizeClass = 'mobile' | 'tablet' | 'desktop'\n\ninterface UseSizeClass {\n value: SizeClass\n isMobile: boolean\n isTablet: boolean\n isDesktop: boolean\n}\n\nexport function useSizeClass(): UseSizeClass {\n const [width] = useWindowSize()\n\n const sizeClass = useMemo((): SizeClass => {\n switch (true) {\n case width <= BREAKPOINTS.MOBILE:\n return 'mobile'\n case width <= BREAKPOINTS.TABLET:\n return 'tablet'\n default:\n return 'desktop'\n }\n }, [width])\n\n return {\n value: sizeClass,\n isMobile: sizeClass === 'mobile',\n isTablet: sizeClass === 'tablet',\n isDesktop: sizeClass === 'desktop',\n }\n}\n", "export const DATE_FORMAT = 'LLL d, yyyy'\nexport const MONTH_DAY_FORMAT = 'LLL d'\nexport const TIME_FORMAT = 'p'\n\nexport const BREAKPOINTS = {\n TABLET: 760,\n MOBILE: 500,\n}\n", "import React, { useContext } from 'react'\nimport { DrawerContext } from '../../contexts/DrawerContext'\n\nconst DrawerBackground = ({\n isOpen,\n isClosing,\n onClose,\n}: {\n isOpen: boolean\n isClosing: boolean\n onClose: () => void\n}) => (\n <div\n className={`Layer__drawer-background ${isClosing ? 'closing' : ''} ${\n isOpen ? 'open' : ''\n }`}\n onClick={onClose}\n ></div>\n)\n\nexport const Drawer = ({\n isOpen,\n onClose,\n children,\n}: {\n isOpen: boolean\n onClose: () => void\n children: React.ReactNode\n}) => {\n const { isClosing, finishClosing } = useContext(DrawerContext)\n\n return (\n <>\n <DrawerBackground\n isOpen={isOpen}\n onClose={onClose}\n isClosing={isClosing}\n />\n <div\n className={`Layer__drawer ${isClosing ? 'closing' : ''} ${\n isOpen ? 'open' : ''\n }`}\n onTransitionEnd={({ propertyName }) => {\n if (propertyName === 'bottom' && isClosing) {\n finishClosing()\n }\n }}\n onClick={e => e.stopPropagation()}\n >\n {children}\n </div>\n </>\n )\n}\n", "import React, { forwardRef } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport classNames from 'classnames'\n\nexport interface ToastProps {\n id?: string\n content: string\n duration?: number\n isExiting?: boolean\n}\n\nconst Toast = (props: ToastProps & { isExiting: boolean }) => {\n const { id, content, isExiting } = props\n const { removeToast } = useLayerContext()\n\n return (\n <div\n id={id}\n className={classNames('Layer__toast', {\n enter: !isExiting,\n exit: isExiting,\n })}\n onClick={() => removeToast(props)}\n >\n <p>{content}</p>\n </div>\n )\n}\n\nexport const ToastsContainer = forwardRef((_props, ref) => {\n const { toasts } = useLayerContext()\n\n return (\n <div className='Layer__toasts-container'>\n {toasts.map((toast, idx) => (\n <Toast key={`layer-toast-${idx}`} {...toast} />\n ))}\n </div>\n )\n})\n", "import { createContext, useContext } from 'react'\nimport { ToastProps } from '../../components/Toast/Toast'\nimport { LayerContextValues } from '../../types'\nimport {\n LayerContextHelpers,\n LayerThemeConfig,\n} from '../../types/layer_context'\n\nexport const LayerContext = createContext<\n LayerContextValues &\n LayerContextHelpers & { setTheme: (theme: LayerThemeConfig) => void }\n>({\n auth: {\n access_token: '',\n expires_at: new Date(2000, 1, 1),\n expires_in: -1,\n token_type: '',\n },\n businessId: '',\n business: undefined,\n categories: [],\n apiUrl: '',\n theme: undefined,\n colors: {},\n usePlaidSandbox: true,\n setTheme: () => undefined,\n getColor: _shade => undefined,\n setLightColor: () => undefined,\n setDarkColor: () => undefined,\n setTextColor: () => undefined,\n setColors: () => undefined,\n onboardingStep: undefined,\n setOnboardingStep: () => undefined,\n environment: '',\n toasts: [],\n addToast: (toast: ToastProps) => undefined,\n removeToast: () => undefined,\n onError: () => undefined,\n touch: () => undefined,\n read: () => undefined,\n syncTimestamps: {},\n readTimestamps: {},\n hasBeenTouched: () => false,\n eventCallbacks: {},\n})\n\nexport const useLayerContext = () => useContext(LayerContext)\n", "import React, { useState } from 'react'\nimport { DataModel } from '../../types/general'\n\ntype UseDataSync = () => {\n touch: (model: DataModel) => void\n read: (model: DataModel, cacheKey: string) => void\n syncTimestamps: Partial<Record<DataModel, number>>\n readTimestamps: Partial<Record<string, { t: number; m: DataModel }>>\n hasBeenTouched: (cacheKey: string) => boolean\n}\n\nconst ALL_TOUCHABLE = [\n DataModel.BUSINESS,\n DataModel.BANK_TRANSACTIONS,\n DataModel.LINKED_ACCOUNTS,\n DataModel.CHART_OF_ACCOUNTS,\n DataModel.JOURNAL,\n]\n\nconst DEPENDENCIES: Partial<Record<DataModel, DataModel[]>> = {\n [DataModel.BALANCE_SHEET]: ALL_TOUCHABLE,\n [DataModel.CHART_OF_ACCOUNTS]: ALL_TOUCHABLE,\n [DataModel.JOURNAL]: ALL_TOUCHABLE,\n [DataModel.LEDGER_ACCOUNTS]: ALL_TOUCHABLE,\n [DataModel.LINKED_ACCOUNTS]: ALL_TOUCHABLE,\n [DataModel.PROFIT_AND_LOSS]: ALL_TOUCHABLE,\n [DataModel.STATEMENT_OF_CASH_FLOWS]: ALL_TOUCHABLE,\n}\n\nlet readTimestampsG = {}\n\nexport const useDataSync: UseDataSync = () => {\n const initialTimestamp = Date.now()\n const [syncTimestamps, setSyncTimestamps] = useState<\n Partial<Record<DataModel, number>>\n >({\n [DataModel.BALANCE_SHEET]: initialTimestamp,\n [DataModel.CHART_OF_ACCOUNTS]: initialTimestamp,\n [DataModel.JOURNAL]: initialTimestamp,\n [DataModel.LEDGER_ACCOUNTS]: initialTimestamp,\n [DataModel.LINKED_ACCOUNTS]: initialTimestamp,\n [DataModel.PROFIT_AND_LOSS]: initialTimestamp,\n [DataModel.STATEMENT_OF_CASH_FLOWS]: initialTimestamp,\n })\n const [readTimestamps, setReadTimestamps] = useState<\n Partial<Record<string, { t: number; m: DataModel }>>\n >({})\n\n const touch = (model: DataModel) => {\n setSyncTimestamps({\n ...syncTimestamps,\n [model]: Date.now(),\n })\n }\n\n const read = (model: DataModel, cacheKey: string) => {\n readTimestampsG = {\n ...readTimestampsG,\n [cacheKey]: {\n t: Date.now(),\n m: model,\n },\n }\n setReadTimestamps({ ...readTimestampsG })\n }\n\n const hasBeenTouched = (cacheKey: string) => {\n const lastRead =\n cacheKey in readTimestamps ? readTimestamps[cacheKey] : undefined\n\n if (!lastRead || !lastRead?.m || !lastRead?.t) {\n return false\n }\n\n return Boolean(\n DEPENDENCIES[lastRead!.m]?.find(dep => {\n return (\n dep in syncTimestamps &&\n Boolean(syncTimestamps[dep]) &&\n (syncTimestamps[dep] as number) > (lastRead!.t as number)\n )\n }),\n )\n }\n\n return {\n touch,\n read,\n syncTimestamps,\n readTimestamps,\n hasBeenTouched,\n }\n}\n", "import React, { ReactNode, useState } from 'react'\n\ntype UseDrawer = () => {\n content?: ReactNode\n setContent: (content: ReactNode) => void\n finishClosing: () => void\n isClosing: boolean\n close: () => void\n}\n\nexport const useDrawer: UseDrawer = () => {\n const [content, setContent] = useState<ReactNode>(undefined)\n const [isClosing, setIsClosing] = useState(false)\n\n const close = () => {\n setIsClosing(true)\n }\n\n const finishClosing = () => {\n setContent(undefined)\n setIsClosing(false)\n }\n\n return {\n content,\n setContent,\n finishClosing,\n isClosing,\n close,\n }\n}\n", "import React, { ReactNode } from 'react'\nimport { BankTransactionsContext, useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { useBankTransactions } from '../../hooks/useBankTransactions'\n\ninterface BankTransactionsProviderProps {\n children: ReactNode\n}\n\nexport const BankTransactionsProvider = ({\n children,\n}: BankTransactionsProviderProps) => {\n const bankTransactionsContextData = useBankTransactions()\n return (\n <BankTransactionsContext.Provider value={bankTransactionsContextData}>\n {children}\n </BankTransactionsContext.Provider>\n )\n}\n", "import { createContext, useContext } from 'react'\nimport { useBankTransactions } from '../../hooks/useBankTransactions'\nimport { DisplayState } from '../../types'\n\nexport type BankTransactionsContextType = ReturnType<typeof useBankTransactions>\nexport const BankTransactionsContext =\n createContext<BankTransactionsContextType>({\n data: undefined,\n isLoading: false,\n loadingStatus: 'initial',\n isValidating: false,\n error: undefined,\n refetch: () => {},\n categorize: () => Promise.resolve(undefined),\n match: () => Promise.resolve(undefined),\n filters: undefined,\n setFilters: () => {},\n metadata: {\n pagination: undefined,\n },\n updateOneLocal: () => undefined,\n removeAfterCategorize: () => undefined,\n activate: () => undefined,\n display: DisplayState.review,\n fetchMore: () => {},\n hasMore: false,\n })\n\nexport const useBankTransactionsContext = () =>\n useContext(BankTransactionsContext)\n", "import { Categorization, CategorizationStatus, Category } from './categories'\nimport { S3PresignedUrl } from './general'\n\nexport enum Direction {\n CREDIT = 'CREDIT',\n DEBIT = 'DEBIT',\n}\n\nexport enum BankTransactionMatchType {\n CONFIRM_MATCH = 'Confirm_Match',\n}\n\nexport enum DisplayState {\n review = 'review',\n categorized = 'categorized',\n}\n\n// This isn't my favorite but BankTransaction contains much\n// more than we're using right now.\nexport interface BankTransaction extends Record<string, unknown> {\n type: 'Bank_Transaction'\n account_name?: string\n business_id: string\n recently_categorized?: boolean\n id: string\n date: string\n source: string\n source_transaction_id: string\n source_account_id: string\n imported_at: string\n description: string | null\n amount: number\n direction: Direction\n counterparty_name: string\n category: Category\n categorization_status: CategorizationStatus\n categorization_flow: Categorization | null\n categorization_method: string\n error?: string\n processing?: boolean\n suggested_matches?: SuggestedMatch[]\n match?: BankTransactionMatch\n}\n\nexport interface SuggestedMatch {\n id: string\n matchType: string\n details: {\n amount: number\n date: string\n description: string\n id: string\n type: string\n }\n}\n\nexport interface BankTransactionMatch {\n bank_transaction: BankTransaction\n id: string\n match_type?: string\n details: {\n amount: number\n date: string\n description: string\n id: string\n type: string\n }\n}\n\nexport interface BankTransactionMetadata {\n memo: string | null\n}\n\nexport interface DocumentS3Urls {\n type: 'Document_S3_Urls'\n documentUrls: S3PresignedUrl[]\n}\n\nexport interface FileMetadata {\n type: 'File_Metadata'\n id: string | null\n fileType: string\n fileName: string\n documentType: string\n}\n", "export enum CategorizationStatus {\n PENDING = 'PENDING',\n READY_FOR_INPUT = 'READY_FOR_INPUT',\n LAYER_REVIEW = 'LAYER_REVIEW',\n CATEGORIZED = 'CATEGORIZED',\n SPLIT = 'SPLIT',\n JOURNALING = 'JOURNALING',\n MATCHED = 'MATCHED',\n}\nexport interface CategoryEntry {\n amount?: number\n category: Category\n}\n\nexport interface Category {\n id: string\n type: string\n display_name: string\n category: string\n stable_name?: string\n subCategories?: Category[]\n entries?: CategoryEntry[]\n}\n\nexport enum CategorizationType {\n AUTO = 'AUTO',\n ASK_FROM_SUGGESTIONS = 'ASK_FROM_SUGGESTIONS',\n MEALS = 'MEALS',\n BUSINESS_TRAVEL_TRANSPORTATION = 'BUSINESS_TRAVEL_TRANSPORTATION',\n}\n\nexport interface AutoCategorization {\n type: CategorizationType.AUTO\n category: Category\n}\nexport interface SuggestedCategorization {\n type: CategorizationType\n suggestions: Category[]\n}\nexport type Categorization = AutoCategorization | SuggestedCategorization\n\nexport type AccountIdentifierPayloadObject =\n | {\n type: 'StableName'\n stable_name: string\n }\n | {\n type: 'AccountId'\n id: string\n }\n | {\n type: 'Exclusion'\n exclusion_type: string\n }\n\nexport type SingleCategoryUpdate = {\n type: 'Category'\n category: AccountIdentifierPayloadObject\n}\nexport type SplitCategoryUpdate = {\n type: 'Split'\n entries: {\n category: string | AccountIdentifierPayloadObject\n amount: number\n }[]\n}\nexport type CategoryUpdate = SingleCategoryUpdate | SplitCategoryUpdate\n\nexport function hasSuggestions(\n categorization: Categorization | null,\n): categorization is SuggestedCategorization {\n return (\n categorization != null &&\n (categorization as SuggestedCategorization).suggestions !== undefined &&\n (categorization as SuggestedCategorization).suggestions.length > 0\n )\n}\n", "import { useEffect, useMemo, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport {\n BankTransaction,\n CategorizationStatus,\n CategoryUpdate,\n} from '../../types'\nimport {\n BankTransactionMatchType,\n DisplayState,\n} from '../../types/bank_transactions'\nimport { DataModel, LoadedStatus } from '../../types/general'\nimport { BankTransactionFilters, UseBankTransactions } from './types'\nimport {\n applyAccountFilter,\n applyAmountFilter,\n applyCategorizationStatusFilter,\n applyDirectionFilter,\n appplyDateRangeFilter,\n collectAccounts,\n} from './utils'\nimport useSWRInfinite from 'swr/infinite'\n\nexport const useBankTransactions: UseBankTransactions = params => {\n const {\n auth,\n businessId,\n apiUrl,\n addToast,\n touch,\n read,\n syncTimestamps,\n hasBeenTouched,\n eventCallbacks,\n } = useLayerContext()\n const { scope = undefined } = params ?? {}\n const [filters, setTheFilters] = useState<BankTransactionFilters | undefined>(\n scope ? { categorizationStatus: scope } : undefined,\n )\n const display = useMemo(() => {\n if (filters?.categorizationStatus === DisplayState.review) {\n return DisplayState.review\n }\n\n return DisplayState.categorized\n }, [filters?.categorizationStatus])\n\n const [active, setActive] = useState(false)\n const [loadingStatus, setLoadingStatus] = useState<LoadedStatus>('initial')\n\n const getKey = (_index: number, prevData: any) => {\n if (!auth?.access_token || !active) {\n return [false, undefined]\n }\n\n if (!prevData?.meta?.pagination?.cursor) {\n return [\n businessId &&\n auth?.access_token &&\n `bank-transactions${\n filters?.categorizationStatus\n ? `-scope-${filters?.categorizationStatus}`\n : ''\n }-${businessId}`,\n undefined,\n ]\n }\n\n return [\n businessId &&\n auth?.access_token &&\n `bank-transactions${\n filters?.categorizationStatus\n ? `-scope-${filters?.categorizationStatus}`\n : ''\n }-${businessId}-${prevData.meta.pagination.cursor}`,\n prevData.meta.pagination.cursor,\n ]\n }\n\n const {\n data: rawResponseData,\n isLoading,\n isValidating,\n error: responseError,\n mutate,\n size,\n setSize,\n } = useSWRInfinite(\n getKey,\n async ([query, nextCursor]) => {\n if (auth?.access_token) {\n return Layer.getBankTransactions(apiUrl, auth?.access_token, {\n params: {\n businessId,\n cursor: nextCursor,\n categorized: filters?.categorizationStatus\n ? filters?.categorizationStatus === DisplayState.categorized\n ? 'true'\n : 'false'\n : '',\n },\n }).call(false)\n }\n\n return {}\n },\n {\n initialSize: 1,\n revalidateFirstPage: false,\n },\n )\n\n const data: BankTransaction[] | undefined = useMemo(() => {\n if (rawResponseData && rawResponseData.length > 0) {\n return rawResponseData\n ?.map(x => x?.data)\n .flat()\n .filter(x => !!x) as unknown as BankTransaction[]\n }\n\n return undefined\n }, [rawResponseData])\n\n const lastMetadata = useMemo(() => {\n if (rawResponseData && rawResponseData.length > 0) {\n return rawResponseData[rawResponseData.length - 1].meta\n }\n\n return undefined\n }, [rawResponseData])\n\n const hasMore = useMemo(() => {\n if (rawResponseData && rawResponseData.length > 0) {\n const lastElement = rawResponseData[rawResponseData.length - 1]\n return Boolean(\n lastElement.meta?.pagination?.cursor &&\n lastElement.meta?.pagination?.has_more,\n )\n }\n\n return false\n }, [rawResponseData])\n\n const accountsList = useMemo(\n () => (data ? collectAccounts(data) : []),\n [data],\n )\n\n useEffect(() => {\n if (isLoading && loadingStatus === 'initial') {\n setLoadingStatus('loading')\n return\n }\n\n if (!isLoading && loadingStatus === 'loading') {\n setLoadingStatus('complete')\n return\n }\n }, [isLoading])\n\n const activate = () => {\n setActive(true)\n }\n\n const setFilters = (value?: Partial<BankTransactionFilters>) => {\n setTheFilters({\n ...filters,\n ...(value ?? {}),\n })\n }\n\n const filteredData = useMemo(() => {\n let filtered = data\n\n if (!filtered) {\n return\n }\n\n if (filters?.amount?.min || filters?.amount?.max) {\n filtered = applyAmountFilter(filtered, filters.amount)\n }\n\n if (filters?.account) {\n filtered = applyAccountFilter(filtered, filters.account)\n }\n\n if (filters?.direction) {\n filtered = applyDirectionFilter(filtered, filters.direction)\n }\n\n if (filters?.categorizationStatus) {\n filtered = applyCategorizationStatusFilter(\n filtered,\n filters.categorizationStatus,\n )\n }\n\n if (filters?.dateRange?.startDate || filters?.dateRange?.endDate) {\n filtered = appplyDateRangeFilter(filtered, filters?.dateRange)\n }\n\n return filtered\n }, [filters, data])\n\n const categorize = (\n id: BankTransaction['id'],\n newCategory: CategoryUpdate,\n notify?: boolean,\n ) => {\n const foundBT = data?.find(x => x.business_id === businessId && x.id === id)\n if (foundBT) {\n updateOneLocal({ ...foundBT, processing: true, error: undefined })\n }\n\n return Layer.categorizeBankTransaction(apiUrl, auth.access_token, {\n params: { businessId, bankTransactionId: id },\n body: newCategory,\n })\n .then(({ data: newBT, errors }) => {\n if (newBT) {\n newBT.recently_categorized = true\n updateOneLocal(newBT)\n }\n if (errors) {\n console.error(errors)\n throw errors\n }\n if (newBT?.recently_categorized === true && notify) {\n addToast({ content: 'Transaction saved' })\n }\n })\n .catch(err => {\n const newBT = data?.find(\n x => x.business_id === businessId && x.id === id,\n )\n\n if (newBT) {\n updateOneLocal({\n ...newBT,\n error: err.message,\n processing: false,\n })\n }\n })\n .finally(() => {\n touch(DataModel.BANK_TRANSACTIONS)\n eventCallbacks?.onTransactionCategorized?.(id)\n })\n }\n\n const match = (\n id: BankTransaction['id'],\n matchId: BankTransaction['id'],\n notify?: boolean,\n ) => {\n const foundBT = data?.find(x => x.business_id === businessId && x.id === id)\n if (foundBT) {\n updateOneLocal({ ...foundBT, processing: true, error: undefined })\n }\n\n return Layer.matchBankTransaction(apiUrl, auth.access_token, {\n params: { businessId, bankTransactionId: id },\n body: { match_id: matchId, type: BankTransactionMatchType.CONFIRM_MATCH },\n })\n .then(({ data: bt, errors }) => {\n const newBT = data?.find(\n x => x.business_id === businessId && x.id === id,\n )\n\n if (newBT) {\n newBT.recently_categorized = true\n newBT.match = bt\n newBT.categorization_status = CategorizationStatus.MATCHED\n updateOneLocal(newBT)\n }\n if (errors) {\n console.error(errors)\n throw errors\n }\n\n if (newBT?.recently_categorized === true && notify) {\n addToast({ content: 'Transaction saved' })\n }\n })\n .catch(err => {\n const newBT = data?.find(\n x => x.business_id === businessId && x.id === id,\n )\n\n if (newBT) {\n updateOneLocal({\n ...newBT,\n error: err.message,\n processing: false,\n })\n }\n })\n .finally(() => {\n touch(DataModel.BANK_TRANSACTIONS)\n eventCallbacks?.onTransactionCategorized?.(id)\n })\n }\n\n const updateOneLocal = (newBankTransaction: BankTransaction) => {\n const updatedData = rawResponseData?.map(page => {\n return {\n ...page,\n data: page.data?.map(bt =>\n bt.id === newBankTransaction.id ? newBankTransaction : bt,\n ),\n }\n })\n mutate(updatedData, { revalidate: false })\n }\n\n const removeAfterCategorize = (bankTransaction: BankTransaction) => {\n const updatedData = rawResponseData?.map(page => {\n return {\n ...page,\n data: page.data?.filter(bt => bt.id !== bankTransaction.id),\n }\n })\n mutate(updatedData, { revalidate: false })\n }\n\n const refetch = () => {\n mutate()\n }\n\n const fetchMore = () => {\n if (hasMore) {\n setSize(size + 1)\n }\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (isLoading || isValidating) {\n read(DataModel.BANK_TRANSACTIONS, 'bank-transactions')\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (hasBeenTouched('bank-transactions')) {\n refetch()\n }\n }, [syncTimestamps])\n\n return {\n data: filteredData,\n metadata: lastMetadata,\n loadingStatus,\n isLoading,\n isValidating,\n refetch,\n error: responseError,\n categorize,\n match,\n updateOneLocal,\n removeAfterCategorize,\n filters,\n setFilters,\n accountsList,\n activate,\n display,\n fetchMore,\n hasMore,\n }\n}\n", "import { CategorizationStatus } from '../../types'\n\nexport type MobileComponentType = 'regularList' | 'mobileList'\n\nexport const CategorizedCategories = [\n CategorizationStatus.CATEGORIZED,\n CategorizationStatus.JOURNALING,\n CategorizationStatus.SPLIT,\n CategorizationStatus.MATCHED,\n]\n\nexport const ReviewCategories = [\n CategorizationStatus.READY_FOR_INPUT,\n CategorizationStatus.LAYER_REVIEW,\n]\n", "import { BankTransaction, DisplayState } from '../../types'\nimport { CategorizedCategories, ReviewCategories } from './constants'\n\nexport const filterVisibility = (\n scope: DisplayState,\n bankTransaction: BankTransaction,\n) => {\n const categorized = CategorizedCategories.includes(\n bankTransaction.categorization_status,\n )\n const inReview = ReviewCategories.includes(\n bankTransaction.categorization_status,\n )\n\n return (\n (scope === DisplayState.review && inReview) ||\n (scope === DisplayState.categorized && categorized)\n )\n}\n\nexport const isCategorized = (bankTransaction: BankTransaction) =>\n CategorizedCategories.includes(bankTransaction.categorization_status)\n", "import { filterVisibility } from '../../components/BankTransactions/utils'\nimport { BankTransaction, DateRange, Direction, DisplayState } from '../../types'\nimport { AccountItem, NumericRangeFilter } from './types'\nimport { parseISO } from 'date-fns'\n\nexport const collectAccounts = (transactions?: BankTransaction[]) => {\n const accounts: AccountItem[] = []\n if (!transactions) {\n return accounts\n }\n\n transactions.forEach(x => {\n if (!accounts.find(y => y.id === x.source_account_id)) {\n accounts.push({\n id: x.source_account_id,\n name: x.account_name || '',\n })\n }\n })\n\n return accounts.sort((a, b) => a.name.localeCompare(b.name))\n}\n\nexport const uniqAccountsList = (arr: AccountItem[], track = new Set()) =>\n arr.filter(({ id }) => (track.has(id) ? false : track.add(id)))\n\nexport const applyAmountFilter = (\n data?: BankTransaction[],\n filter?: NumericRangeFilter,\n) => {\n return data?.filter(x => {\n if (\n (filter?.min || filter?.min === 0) &&\n (filter?.max || filter?.max === 0)\n ) {\n return x.amount >= filter.min * 100 && x.amount <= filter.max * 100\n }\n\n if (filter?.min || filter?.min === 0) {\n return x.amount >= filter.min * 100\n }\n\n if (filter?.max || filter?.max === 0) {\n return x.amount <= filter.max * 100\n }\n })\n}\n\nexport const applyAccountFilter = (\n data?: BankTransaction[],\n filter?: string[],\n) => data?.filter(x => filter && filter.includes(x.source_account_id))\n\nexport const applyDirectionFilter = (\n data?: BankTransaction[],\n filter?: Direction[],\n) => {\n if (!filter) {\n return data\n }\n const normalizedFilter = filter.map(x => x.toLowerCase())\n\n return data?.filter(x =>\n normalizedFilter.includes(x.direction?.toLowerCase()),\n )\n}\n\nexport const applyCategorizationStatusFilter = (\n data?: BankTransaction[],\n filter?: DisplayState,\n) => {\n if (!filter) {\n return data\n }\n\n return data?.filter(\n tx =>\n filterVisibility(filter, tx) ||\n (filter === DisplayState.review && tx.recently_categorized) ||\n (filter === DisplayState.categorized && tx.recently_categorized),\n )\n}\n\nexport const appplyDateRangeFilter = (\n data?: BankTransaction[],\n filter?: Partial<DateRange>,\n) => {\n return data?.filter(x => {\n const txDate = parseISO(x.date)\n if (filter?.startDate && filter?.endDate) {\n return txDate >= filter.startDate && txDate <= filter.endDate\n }\n\n if (filter?.startDate) {\n return txDate >= filter.startDate\n }\n\n if (filter?.endDate) {\n return txDate <= filter.endDate\n }\n })\n}\n", "export const SHADES = {\n 50: { s: 1, l: 98 },\n 100: { s: 1, l: 96 },\n 200: { s: 1, l: 94 },\n 300: { s: 2, l: 92 },\n 500: { s: 5, l: 53 },\n 600: { s: 7, l: 40 },\n 700: { s: 9, l: 27 },\n 800: { s: 12, l: 20 },\n 1000: { s: 20, l: 7 },\n}\n\nexport const COLORS = {\n dark: {\n h: 0,\n s: 0,\n l: 7,\n },\n light: {\n h: 0,\n s: 0,\n l: 100,\n },\n}\n", "import { COLORS, SHADES } from '../config/theme'\nimport {\n LayerThemeConfig,\n ColorConfig,\n ColorRGBConfig,\n ColorRGBNumberConfig,\n ColorHSLNumberConfig,\n ColorsPalette,\n} from '../types/layer_context'\n\n/**\n * Convert `theme` config set in Provider into component styles.\n *\n * @param {LayerThemeConfig} theme - the theme set with provider\n */\nexport const parseStylesFromThemeConfig = (theme?: LayerThemeConfig) => {\n let styles = {}\n if (!theme) {\n return styles\n }\n\n if (theme.colors) {\n const darkColor = parseColorFromTheme('dark', theme.colors.dark)\n const lightColor = parseColorFromTheme('light', theme.colors.light)\n const textColor = parseTextColorFromTheme(theme.colors.text)\n styles = { ...styles, ...darkColor, ...lightColor, ...textColor }\n }\n\n return styles\n}\n\nconst parseTextColorFromTheme = (color?: ColorConfig) => {\n if (!color) {\n return {}\n }\n\n try {\n if ('hex' in color) {\n return { '--text-color-primary': color.hex }\n }\n\n return {}\n } catch (_err) {\n return {}\n }\n}\n\n/**\n * Parse the color from theme config into a CSS variables.\n * @param {string} colorName\n * @param {ColorConfig} color\n */\nconst parseColorFromTheme = (colorName: string, color?: ColorConfig) => {\n if (!color) {\n return {}\n }\n\n try {\n if ('h' in color && 's' in color && 'l' in color) {\n return {\n [`--color-${colorName}-h`]: color.h,\n [`--color-${colorName}-s`]: color.s,\n [`--color-${colorName}-l`]: color.l,\n }\n }\n\n if ('r' in color && 'g' in color && 'b' in color) {\n const { h, s, l } = rgbToHsl(color)\n return {\n [`--color-${colorName}-h`]: h,\n [`--color-${colorName}-s`]: `${s}%`,\n [`--color-${colorName}-l`]: `${l}%`,\n }\n }\n\n if ('hex' in color) {\n const rgb = hexToRgb(color.hex)\n if (!rgb) {\n return {}\n }\n const { h, s, l } = rgbToHsl({\n r: rgb.r.toString(),\n g: rgb.g.toString(),\n b: rgb.b.toString(),\n })\n return {\n [`--color-${colorName}-h`]: h,\n [`--color-${colorName}-s`]: `${s}%`,\n [`--color-${colorName}-l`]: `${l}%`,\n }\n }\n\n return {}\n } catch (_err) {\n return {}\n }\n}\n\n/**\n * Parse the color from theme config into a CSS variables.\n * @param {string} colorName\n * @param {ColorConfig} color\n */\nconst parseColorFromThemeToHsl = (\n color?: ColorConfig,\n): ColorHSLNumberConfig | undefined => {\n if (!color) {\n return\n }\n\n try {\n if ('h' in color && 's' in color && 'l' in color) {\n return {\n h: Number(color.h),\n s: Number(color.s),\n l: Number(color.l),\n }\n }\n\n if ('r' in color && 'g' in color && 'b' in color) {\n const { h, s, l } = rgbToHsl(color)\n return {\n h: h,\n s: s,\n l: l,\n }\n }\n\n if ('hex' in color) {\n const rgb = hexToRgb(color.hex)\n if (!rgb) {\n return undefined\n }\n const { h, s, l } = rgbToHsl({\n r: rgb.r.toString(),\n g: rgb.g.toString(),\n b: rgb.b.toString(),\n })\n return {\n h: h,\n s: s,\n l: l,\n }\n }\n\n return\n } catch (_err) {\n return\n }\n}\n\n/**\n * Convert RGB to HSL\n */\nconst rgbToHsl = (color: ColorRGBConfig) => {\n let r = Number(color.r)\n let g = Number(color.g)\n let b = Number(color.b)\n r /= 255\n g /= 255\n b /= 255\n const l = Math.max(r, g, b)\n const s = l - Math.min(r, g, b)\n const h = s\n ? l === r\n ? (g - b) / s\n : l === g\n ? 2 + (b - r) / s\n : 4 + (r - g) / s\n : 0\n return {\n h: 60 * h < 0 ? 60 * h + 360 : 60 * h,\n s: 100 * (s ? (l <= 0.5 ? s / (2 * l - s) : s / (2 - (2 * l - s))) : 0),\n l: (100 * (2 * l - s)) / 2,\n }\n}\n\n/**\n * Convert HEX to RGB\n */\nconst hexToRgb = (hex: string) => {\n const values = hex\n .replace(\n /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i,\n (m, r, g, b) => '#' + r + r + g + g + b + b,\n )\n .substring(1)\n .match(/.{2}/g)\n ?.map(x => parseInt(x, 16))\n\n if (!values) {\n return\n }\n\n return {\n r: values[0],\n g: values[1],\n b: values[2],\n }\n}\n\n/**\n * Build same color palette in RGB, HSL and HEX as CSS variables.\n */\nexport const buildColorsPalette = (theme?: LayerThemeConfig): ColorsPalette => {\n const darkColor = parseColorFromThemeToHsl(theme?.colors?.dark) ?? COLORS.dark\n const lightColor =\n parseColorFromThemeToHsl(theme?.colors?.light) ?? COLORS.light\n\n return {\n 50: buildColorShade(50, darkColor),\n 100: buildColorShade(100, darkColor),\n 200: buildColorShade(200, darkColor),\n 300: buildColorShade(300, darkColor),\n 400: {\n hsl: lightColor,\n rgb: hslToRgb(lightColor),\n hex: hslToHex(lightColor),\n },\n 500: buildColorShade(500, darkColor),\n 600: buildColorShade(600, darkColor),\n 700: buildColorShade(700, darkColor),\n 800: buildColorShade(800, darkColor),\n 900: {\n hsl: darkColor,\n rgb: hslToRgb(darkColor),\n hex: hslToHex(darkColor),\n },\n 1000: buildColorShade(1000, darkColor),\n }\n}\n\n/**\n * Build color shade based on the dark color (HSL)\n * and config values for S and L.\n */\nconst buildColorShade = (\n shade: keyof typeof SHADES,\n darkColorHsl: ColorHSLNumberConfig,\n) => {\n const hsl = { h: darkColorHsl.h, ...SHADES[shade] }\n const rgb = hslToRgb(hsl)\n const hex = hslToHex(hsl)\n\n return { hsl, rgb, hex }\n}\n/**\n * Convert Hue into RGB\n */\nconst hueToRgb = (p: number, q: number, t: number) => {\n if (t < 0) t += 1\n if (t > 1) t -= 1\n if (t < 1.0 / 6.0) return p + (q - p) * 6 * t\n if (t < 1.0 / 2.0) return q\n if (t < 2.0 / 3.0) return p + (q - p) * (2.0 / 3.0 - t) * 6\n return p\n}\n\n/**\n * Convert HSL to RGB\n */\nconst hslToRgb = (hsl: ColorHSLNumberConfig): ColorRGBNumberConfig => {\n let r, g, b\n let l = hsl.l / 100\n let s = hsl.s / 100\n\n if (hsl.s === 0) {\n r = g = b = l\n } else {\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s\n const p = 2 * l - q\n r = hueToRgb(p, q, hsl.h + 1.0 / 3.0)\n g = hueToRgb(p, q, hsl.h)\n b = hueToRgb(p, q, hsl.h - 1.0 / 3.0)\n }\n\n return {\n r: Math.round(r * 255),\n g: Math.round(g * 255),\n b: Math.round(b * 255),\n }\n}\n\n/**\n * Convert HSL to HEX\n */\nconst hslToHex = (hsl: ColorHSLNumberConfig): string => {\n const l = hsl.l / 100\n const s = hsl.s\n const a = (s * Math.min(l, 1 - l)) / 100\n const f = (n: number) => {\n const k = (n + hsl.h / 30) % 12\n const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)\n return Math.round(255 * color)\n .toString(16)\n .padStart(2, '0')\n }\n return `#${f(0)}${f(8)}${f(4)}`\n}\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { LinkedAccountsContext } from '../../contexts/LinkedAccountsContext'\nimport { LinkedAccountsProvider } from '../../providers/LinkedAccountsProvider'\nimport { Container } from '../Container'\nimport { ConnectAccount } from './ConnectAccount'\n\nconst COLLAPSED_STYLE = {\n maxHeight: 0,\n opacity: 0.2,\n transform: 'scale(0.96)',\n overflow: 'hidden',\n}\n\nconst EXPANDED_STYLE = {\n maxHeight: 1000,\n opacity: 1,\n transform: 'scale(1)',\n overflow: 'hidden',\n}\n\nexport interface OnboardingProps {\n onTransactionsToReviewClick?: () => void\n}\n\nexport const Onboarding = (props: OnboardingProps) => (\n <LinkedAccountsProvider>\n <OnboardingContent {...props} />\n </LinkedAccountsProvider>\n)\n\nexport const OnboardingContent = ({\n onTransactionsToReviewClick,\n}: OnboardingProps) => {\n const { onboardingStep, setOnboardingStep } = useLayerContext()\n\n const [style, setStyle] = useState(\n onboardingStep ? EXPANDED_STYLE : COLLAPSED_STYLE,\n )\n const { data, loadingStatus } = useContext(LinkedAccountsContext)\n\n useEffect(() => {\n if (\n data &&\n data?.length === 0 &&\n loadingStatus === 'complete' &&\n !onboardingStep\n ) {\n setOnboardingStep('connectAccount')\n return\n }\n\n if (\n data &&\n data.length > 0 &&\n loadingStatus === 'complete' &&\n onboardingStep === 'connectAccount'\n ) {\n setOnboardingStep('complete')\n }\n }, [data, loadingStatus])\n\n useEffect(() => {\n if (onboardingStep && style.maxHeight !== 1000) {\n setTimeout(() => {\n setStyle(EXPANDED_STYLE)\n }, 500)\n }\n }, [onboardingStep])\n\n if (!onboardingStep) {\n return null\n }\n\n return (\n <Container name='onboarding' style={style}>\n <div className='Layer__onboarding__content'>\n <ConnectAccount\n onboardingStep={onboardingStep}\n onTransactionsToReviewClick={onTransactionsToReviewClick}\n />\n </div>\n </Container>\n )\n}\n", "import { createContext } from 'react'\nimport { useLinkedAccounts } from '../../hooks/useLinkedAccounts'\n\nexport type LinkedAccountsContextType = ReturnType<typeof useLinkedAccounts>\nexport const LinkedAccountsContext = createContext<LinkedAccountsContextType>({\n data: undefined,\n isLoading: false,\n loadingStatus: 'initial',\n isValidating: false,\n error: undefined,\n updateConnectionStatus: () => {},\n addConnection: () => {},\n removeConnection: () => {},\n repairConnection: () => {},\n refetchAccounts: () => {},\n unlinkAccount: () => {},\n denyAccount: () => {},\n confirmAccount: () => {},\n breakConnection: () => {},\n syncAccounts: () => {},\n})\n", "import React, { ReactNode } from 'react'\nimport { LinkedAccountsContext } from '../../contexts/LinkedAccountsContext'\nimport { useLinkedAccounts } from '../../hooks/useLinkedAccounts'\n\ninterface LinkedAccountsProviderProps {\n children: ReactNode\n}\n\nexport const LinkedAccountsProvider = ({\n children,\n}: LinkedAccountsProviderProps) => {\n const linkedAccountsContextData = useLinkedAccounts()\n return (\n <LinkedAccountsContext.Provider value={linkedAccountsContextData}>\n {children}\n </LinkedAccountsContext.Provider>\n )\n}\n", "import { useEffect, useState } from 'react'\nimport { PlaidLinkOnSuccessMetadata, usePlaidLink } from 'react-plaid-link'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { DataModel, LoadedStatus } from '../../types/general'\nimport { LinkedAccount, Source } from '../../types/linked_accounts'\nimport { LINKED_ACCOUNTS_MOCK_DATA } from './mockData'\nimport useSWR from 'swr'\n\ntype UseLinkedAccounts = () => {\n data?: LinkedAccount[]\n isLoading: boolean\n loadingStatus: LoadedStatus\n isValidating: boolean\n error: unknown\n addConnection: (source: Source) => void\n removeConnection: (source: Source, sourceId: string) => void // means, \"unlink institution\"\n repairConnection: (source: Source, sourceId: string) => void\n updateConnectionStatus: () => void\n refetchAccounts: () => void\n syncAccounts: () => void\n unlinkAccount: (source: Source, accountId: string) => void\n confirmAccount: (source: Source, accountId: string) => void\n denyAccount: (source: Source, accountId: string) => void\n\n // Only works in non-production environments for test purposes\n breakConnection: (source: Source, connectionExternalId: string) => void\n}\n\nconst DEBUG = true\nconst USE_MOCK_RESPONSE_DATA = false\n\ntype LinkMode = 'update' | 'add'\n\nexport const useLinkedAccounts: UseLinkedAccounts = () => {\n const {\n auth,\n businessId,\n apiUrl,\n usePlaidSandbox,\n touch,\n read,\n syncTimestamps,\n hasBeenTouched,\n } = useLayerContext()\n const [linkToken, setLinkToken] = useState<string | null>(null)\n const [loadingStatus, setLoadingStatus] = useState<LoadedStatus>('initial')\n const USE_PLAID_SANDBOX = usePlaidSandbox ?? true\n const [linkMode, setLinkMode] = useState<LinkMode>('add')\n\n const queryKey =\n businessId && auth?.access_token && `linked-accounts-${businessId}`\n\n const {\n data: responseData,\n isLoading,\n isValidating,\n error: responseError,\n mutate,\n } = useSWR(\n queryKey,\n Layer.getLinkedAccounts(apiUrl, auth?.access_token, {\n params: { businessId },\n }),\n )\n\n useEffect(() => {\n if (!isLoading && responseData?.data.external_accounts) {\n setLoadingStatus('complete')\n return\n }\n\n if (isLoading && loadingStatus === 'initial') {\n setLoadingStatus('loading')\n return\n }\n\n if (!isLoading && loadingStatus === 'loading') {\n setLoadingStatus('complete')\n }\n }, [isLoading])\n\n /**\n * Initiates an add connection flow with Plaid\n */\n const fetchPlaidLinkToken = async () => {\n if (auth?.access_token) {\n const linkToken = (\n await Layer.getPlaidLinkToken(apiUrl, auth.access_token, {\n params: { businessId },\n })\n ).data.link_token\n setLinkMode('add')\n setLinkToken(linkToken)\n }\n }\n\n /**\n * Initiates a connection repair flow with Plaid\n */\n const fetchPlaidUpdateModeLinkToken = async (plaidItemPlaidId: string) => {\n if (auth?.access_token) {\n const linkToken = (\n await Layer.getPlaidUpdateModeLinkToken(apiUrl, auth.access_token, {\n params: { businessId },\n body: { plaid_item_id: plaidItemPlaidId },\n })\n ).data.link_token\n setLinkMode('update')\n setLinkToken(linkToken)\n }\n }\n\n /**\n * When the user has finished entering credentials, send the resulting\n * token to the backend where it will fetch and save the Plaid access token\n * and item id\n * */\n const exchangePlaidPublicToken = async (\n publicToken: string,\n metadata: PlaidLinkOnSuccessMetadata,\n ) => {\n await Layer.exchangePlaidPublicToken(apiUrl, auth?.access_token, {\n params: { businessId },\n body: { public_token: publicToken, institution: metadata.institution },\n })\n refetchAccounts()\n }\n\n const { open: plaidLinkStart, ready: plaidLinkReady } = usePlaidLink({\n token: linkToken,\n\n // If in update mode, we don't need to exchange the public token for an access token.\n // The existing access token will automatically become valid again\n onSuccess: async (\n publicToken: string,\n metadata: PlaidLinkOnSuccessMetadata,\n ) => {\n if (linkMode == 'add') {\n // Note: a sync is kicked off in the backend in this endpoint\n exchangePlaidPublicToken(publicToken, metadata)\n } else {\n // Refresh the account connections, which should remove the error\n // pills from any broken accounts\n await updateConnectionStatus()\n refetchAccounts()\n setLinkMode('add')\n touch(DataModel.LINKED_ACCOUNTS)\n }\n },\n onExit: () => setLinkMode('add'),\n env: USE_PLAID_SANDBOX ? 'sandbox' : undefined,\n })\n\n useEffect(() => {\n if (plaidLinkReady) {\n plaidLinkStart()\n }\n }, [plaidLinkStart, plaidLinkReady])\n\n const mockResponseData = {\n data: LINKED_ACCOUNTS_MOCK_DATA,\n meta: {},\n error: undefined,\n }\n\n const addConnection = (source: Source) => {\n if (source === 'PLAID') {\n fetchPlaidLinkToken()\n } else {\n console.error(\n `Adding a connection with source ${source} not yet supported`,\n )\n }\n }\n\n const repairConnection = async (\n source: Source,\n connectionExternalId: string,\n ) => {\n if (source === 'PLAID') {\n await fetchPlaidUpdateModeLinkToken(connectionExternalId)\n } else {\n console.error(\n `Repairing a connection with source ${source} not yet supported`,\n )\n }\n }\n\n const removeConnection = async (\n source: Source,\n connectionExternalId: string,\n ) => {\n if (source === 'PLAID') {\n await unlinkPlaidItem(connectionExternalId)\n await refetchAccounts()\n } else {\n console.error(\n `Removing a connection with source ${source} not yet supported`,\n )\n }\n }\n\n const unlinkAccount = async (source: Source, accountId: string) => {\n DEBUG && console.log('unlinking account')\n if (source === 'PLAID') {\n await Layer.unlinkAccount(apiUrl, auth?.access_token, {\n params: { businessId, accountId: accountId },\n })\n await refetchAccounts()\n touch(DataModel.LINKED_ACCOUNTS)\n } else {\n console.error(\n `Unlinking an account with source ${source} not yet supported`,\n )\n }\n }\n\n const confirmAccount = async (source: Source, accountId: string) => {\n DEBUG && console.log('confirming account')\n if (source === 'PLAID') {\n await Layer.confirmConnection(apiUrl, auth?.access_token, {\n params: {\n businessId,\n accountId,\n },\n })\n await refetchAccounts()\n touch(DataModel.LINKED_ACCOUNTS)\n } else {\n console.error(\n `Confirming an account with source ${source} not yet supported`,\n )\n }\n }\n\n const denyAccount = async (source: Source, accountId: string) => {\n DEBUG && console.log('confirming account')\n if (source === 'PLAID') {\n await Layer.denyConnection(apiUrl, auth?.access_token, {\n params: {\n businessId,\n accountId,\n },\n })\n await refetchAccounts()\n touch(DataModel.LINKED_ACCOUNTS)\n } else {\n console.error(\n `Denying an account with source ${source} not yet supported`,\n )\n }\n }\n\n /**\n * Test utility that puts a connection into a broken state. Only works in non-production environments.\n */\n const breakConnection = async (\n source: Source,\n connectionExternalId: string,\n ) => {\n DEBUG && console.log('Breaking sandbox plaid item connection')\n if (source === 'PLAID') {\n await Layer.breakPlaidItemConnection(apiUrl, auth?.access_token, {\n params: {\n businessId,\n plaidItemPlaidId: connectionExternalId,\n },\n })\n await refetchAccounts()\n touch(DataModel.LINKED_ACCOUNTS)\n } else {\n console.error(\n `Breaking a sandbox connection with source ${source} not yet supported`,\n )\n }\n }\n\n const refetchAccounts = async () => {\n DEBUG && console.log('refetching accounts...')\n await mutate()\n }\n\n const syncAccounts = async () => {\n DEBUG && console.log('resyncing accounts...')\n await Layer.syncConnection(apiUrl, auth?.access_token, {\n params: { businessId },\n })\n }\n\n const updateConnectionStatus = async () => {\n DEBUG && console.log('updating connection status...')\n await Layer.updateConnectionStatus(apiUrl, auth?.access_token, {\n params: { businessId },\n })\n }\n\n const unlinkPlaidItem = async (plaidItemPlaidId: string) => {\n DEBUG && console.log('unlinking plaid item')\n await Layer.unlinkPlaidItem(apiUrl, auth?.access_token, {\n params: { businessId, plaidItemPlaidId },\n })\n await refetchAccounts()\n touch(DataModel.LINKED_ACCOUNTS)\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.LINKED_ACCOUNTS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetchAccounts()\n }\n }, [syncTimestamps])\n\n return {\n data: USE_MOCK_RESPONSE_DATA\n ? mockResponseData.data\n : responseData?.data.external_accounts,\n isLoading,\n loadingStatus,\n isValidating,\n error: responseError,\n addConnection,\n removeConnection,\n repairConnection,\n refetchAccounts,\n unlinkAccount,\n confirmAccount,\n denyAccount,\n breakConnection,\n syncAccounts,\n updateConnectionStatus,\n }\n}\n", "import { LinkedAccount } from '../../types/linked_accounts'\n\nexport const LINKED_ACCOUNTS_MOCK_DATA: LinkedAccount[] = [\n {\n id: 'd800ada8-8075-4436-a712-08efabcbd51a',\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n external_account_name: 'Citi Double Cash\u00AE Card',\n mask: '1234',\n latest_balance_timestamp: {\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n balance: 435121,\n at: '2024-04-03T13:00:00Z',\n created_at: '2024-04-06T22:47:59.715458Z',\n },\n current_ledger_balance: 373717,\n institution: {\n name: 'Chase',\n logo: '',\n },\n connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n connection_external_id: '11111',\n connection_needs_repair_as_of: null,\n requires_user_confirmation_as_of: null,\n is_syncing: true,\n },\n {\n id: 'f98ec50a-c370-484d-a35b-d00207436075',\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n external_account_name: 'Citi Double Cash\u00AE Card',\n mask: '1234',\n latest_balance_timestamp: {\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n balance: 435121,\n at: '2024-04-03T13:00:00Z',\n created_at: '2024-04-06T16:44:35.715458Z',\n },\n current_ledger_balance: 373717,\n institution: {\n name: 'Chase',\n logo: '',\n },\n connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n connection_external_id: '11111',\n connection_needs_repair_as_of: null,\n requires_user_confirmation_as_of: null,\n is_syncing: false,\n },\n {\n id: '843f1748-fdaa-422d-a73d-2489a40c8dc7',\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n external_account_name: 'Citi Double Cash\u00AE Card',\n mask: '1234',\n latest_balance_timestamp: {\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n balance: 435121,\n at: '2024-04-03T13:00:00Z',\n created_at: '2024-04-06T16:44:35.715458Z',\n },\n current_ledger_balance: 373717,\n institution: {\n name: 'Chase',\n logo: '',\n },\n connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n connection_external_id: '11111',\n connection_needs_repair_as_of: '2024-03-06T16:44:35.715458Z',\n requires_user_confirmation_as_of: null,\n is_syncing: false,\n },\n {\n id: '8f430e29-e339-4d71-a08a-fce469c7a7c1',\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n external_account_name: 'Citi Double Cash\u00AE Card',\n mask: '1234',\n latest_balance_timestamp: {\n external_account_external_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n external_account_source: 'PLAID',\n balance: 435121,\n at: '2024-04-03T13:00:00Z',\n created_at: '2024-04-06T16:44:35.715458Z',\n },\n current_ledger_balance: 373717,\n institution: {\n name: 'Chase',\n logo: '',\n },\n connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',\n connection_external_id: '11111',\n connection_needs_repair_as_of: null,\n requires_user_confirmation_as_of: '2024-03-06T16:44:35.715458Z',\n is_syncing: false,\n },\n]\n", "import React, { CSSProperties, ReactNode, forwardRef } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { parseStylesFromThemeConfig } from '../../utils/colors'\nimport classNames from 'classnames'\n\nexport interface ContainerProps {\n name: string\n className?: string\n asWidget?: boolean\n elevated?: boolean\n transparentBg?: boolean\n children: ReactNode\n style?: CSSProperties\n}\n\nexport const Container = forwardRef<HTMLDivElement, ContainerProps>(\n (\n {\n name,\n className,\n children,\n asWidget,\n elevated = false,\n transparentBg = false,\n style,\n },\n ref,\n ) => {\n const baseClassName = classNames(\n 'Layer__component Layer__component-container',\n `Layer__${name}`,\n elevated && 'Layer__component--elevated',\n transparentBg && 'Layer__component--no-bg',\n asWidget && 'Layer__component--as-widget',\n className,\n )\n\n const { theme } = useLayerContext()\n\n const themeStyles = parseStylesFromThemeConfig(theme)\n\n return (\n <div\n ref={ref}\n className={baseClassName}\n style={{ ...themeStyles, ...style }}\n >\n {children}\n </div>\n )\n },\n)\n", "import React, { CSSProperties, ReactNode, forwardRef } from 'react'\nimport classNames from 'classnames'\n\nexport enum HeaderLayout {\n DEFAULT = 'default',\n NEXT_LINE_ACTIONS = 'next-line-actions',\n}\n\nexport interface HeaderProps {\n className?: string\n style?: CSSProperties\n children: ReactNode\n layout?: HeaderLayout\n}\n\nexport const Header = forwardRef<HTMLElement, HeaderProps>(\n ({ className, children, style, layout }, ref) => {\n const baseClassName = classNames(\n 'Layer__component-header',\n layout && `Layer__component-header--${layout}`,\n className,\n )\n\n return (\n <header ref={ref} className={baseClassName} style={style}>\n {children}\n </header>\n )\n },\n)\n", "import React, { useContext, useMemo } from 'react'\nimport { LinkedAccountsContext } from '../../contexts/LinkedAccountsContext'\nimport { useBankTransactions } from '../../hooks/useBankTransactions'\nimport BellIcon from '../../icons/Bell'\nimport CreditCardIcon from '../../icons/CreditCard'\nimport FolderIcon from '../../icons/Folder'\nimport LinkIcon from '../../icons/Link'\nimport PlaidIcon from '../../icons/PlaidIcon'\nimport SunriseIcon from '../../icons/Sunrise'\nimport { OnboardingStep } from '../../types/layer_context'\nimport { countTransactionsToReview } from '../../utils/bankTransactions'\nimport { ActionableRow } from '../ActionableRow'\nimport { Badge, BadgeVariant } from '../Badge'\nimport { BadgeSize } from '../Badge/Badge'\nimport { Button } from '../Button'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { Text } from '../Typography'\nimport { DisplayState } from '../../types'\n\nexport interface ConnectAccountProps {\n onboardingStep: OnboardingStep\n onTransactionsToReviewClick?: () => void\n currentMonthOnly?: boolean\n}\n\nexport const ConnectAccount = ({\n onboardingStep,\n onTransactionsToReviewClick,\n}: ConnectAccountProps) => {\n const { addConnection } = useContext(LinkedAccountsContext)\n const { data, isLoading } = useBankTransactions({\n scope: DisplayState.review,\n })\n\n const transactionsToReview = useMemo(\n () => countTransactionsToReview({ transactions: data }),\n [data, isLoading],\n )\n\n if (onboardingStep === 'connectAccount') {\n return (\n <>\n <DataState\n status={DataStateStatus.info}\n icon={<CreditCardIcon size={12} />}\n title='No accounts connected'\n description='Populate your accounting dashboard in 3 steps'\n />\n <ActionableRow\n iconBox={<PlaidIcon />}\n title='Connect accounts'\n description='Import data with one simple integration.'\n button={\n <Button\n onClick={() => addConnection('PLAID')}\n rightIcon={<LinkIcon size={12} />}\n >\n Connect\n </Button>\n }\n />\n </>\n )\n }\n\n return (\n <>\n <DataState\n status={DataStateStatus.success}\n icon={<SunriseIcon size={12} />}\n title='Account linked successfully'\n description='Your transactions are now available on the platform, to see all data on the charts, categorise transactions.'\n />\n {onTransactionsToReviewClick && transactionsToReview > 0 ? (\n <ActionableRow\n icon={<FolderIcon size={12} />}\n title={\n <Text>\n Categorise transactions{' '}\n <Badge\n variant={BadgeVariant.WARNING}\n size={BadgeSize.SMALL}\n icon={<BellIcon size={12} />}\n >\n {transactionsToReview} pending\n </Badge>\n </Text>\n }\n description='Once your data is on the platform categorize them in Bank Transactions tab'\n onClick={() => onTransactionsToReviewClick()}\n />\n ) : null}\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Bell = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M13.5 6C13.5 4.80653 13.0259 3.66193 12.182 2.81802C11.3381 1.97411 10.1935 1.5 9 1.5C7.80653 1.5 6.66193 1.97411 5.81802 2.81802C4.97411 3.66193 4.5 4.80653 4.5 6C4.5 11.25 2.25 12.75 2.25 12.75H15.75C15.75 12.75 13.5 11.25 13.5 6Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.2975 15.75C10.1656 15.9773 9.97638 16.166 9.74867 16.2971C9.52096 16.4283 9.26278 16.4973 9 16.4973C8.73721 16.4973 8.47904 16.4283 8.25133 16.2971C8.02362 16.166 7.83436 15.9773 7.7025 15.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Bell\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst CreditCard = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 12'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M10.5 2H1.5C0.947715 2 0.5 2.44772 0.5 3V9C0.5 9.55228 0.947715 10 1.5 10H10.5C11.0523 10 11.5 9.55228 11.5 9V3C11.5 2.44772 11.0523 2 10.5 2Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M0.5 5H11.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default CreditCard\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Folder = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 12'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M11 9.5C11 9.76522 10.8946 10.0196 10.7071 10.2071C10.5196 10.3946 10.2652 10.5 10 10.5H2C1.73478 10.5 1.48043 10.3946 1.29289 10.2071C1.10536 10.0196 1 9.76522 1 9.5V2.5C1 2.23478 1.10536 1.98043 1.29289 1.79289C1.48043 1.60536 1.73478 1.5 2 1.5H4.5L5.5 3H10C10.2652 3 10.5196 3.10536 10.7071 3.29289C10.8946 3.48043 11 3.73478 11 4V9.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Folder\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Link = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M7.5 9.75C7.82209 10.1806 8.23302 10.5369 8.70491 10.7947C9.17681 11.0525 9.69863 11.2058 10.235 11.2442C10.7713 11.2827 11.3097 11.2053 11.8135 11.0173C12.3173 10.8294 12.7748 10.5353 13.155 10.155L15.405 7.905C16.0881 7.19774 16.4661 6.25048 16.4575 5.26724C16.449 4.284 16.0546 3.34346 15.3593 2.64818C14.664 1.9529 13.7235 1.55851 12.7403 1.54997C11.757 1.54143 10.8098 1.9194 10.1025 2.6025L8.8125 3.885'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5 8.25C10.1779 7.8194 9.76698 7.46311 9.29508 7.2053C8.82319 6.94748 8.30137 6.79416 7.76501 6.75575C7.22865 6.71734 6.69031 6.79473 6.18649 6.98266C5.68267 7.1706 5.22516 7.4647 4.845 7.845L2.595 10.095C1.9119 10.8023 1.53393 11.7495 1.54247 12.7328C1.55101 13.716 1.9454 14.6565 2.64068 15.3518C3.33596 16.0471 4.2765 16.4415 5.25974 16.45C6.24298 16.4586 7.19024 16.0806 7.8975 15.3975L9.18 14.115'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Link\n", "import React from 'react'\n\nconst PlaidIcon = () => {\n return (\n <img\n src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAhCAYAAAC4JqlRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQDSURBVHgB7VbpK65bFP+9XJTMJGPGDIVIpjIln2S4SIr4AxSOIZFwPxA+HUf5rhAZb3xQylCUizKLD+I1ROYpZcq+e63u+9S5t573XN1z3nvr/or97GVba+3fmrYGf8DBwSHx/f09VH7a4DvD2Nj414uLi1X61tAvOzu7z0KIT/iB0Gg0bdfX12UaafyTNP4ZBoB0okxja2u7L789YRhoyQEBA8IIBsZ/0wF7e3tYWVkpe2tra8hQ4iP46VsOWVpaIiYmBrGxsYiKikJERASWl5eRnZ0NU1NT9PX1ISwsDCsrK5iZmcHi4iKmpqbw+vqqV7feJCwsLERbW5uyX19fx/7+PjIyMrC5uQkTExP4+/tjZGQEvr6+CA4OVs6Wlpaiq6sLqiAH1H4GBgaEDqmpqYq8qalJkdfX1yvyrKwscXd3x/L+/n6hT79eBnZ3d3F6egobGxtInUhPT8f9/T3fWHfb7e1tpKSk8JmxsTGWPT4+wsnJCV5eXqoEqCYhUSo7JXp6epCWlkadC5OTkxgaGmLjFRUVKC8vR2BgIEZHR9k4OUlnJXOcnO7u7vhwCKqqqpjKxMRE3tOqQ3Nzs3KutbWVZU9PT0IywbKEhASW1dbWqoZAlQHKbEJISAiXXnt7O+/Pz8+Rn58PDw8PeHp6Ii8vDzLuMDMzQ0tLC988Li6Oz/r5+X2cARcXF7G1tcU3OTk54bWyslJIx8Tx8bGQ00wcHR2Jw8NDERoaKsrKyviMzBleZcUIZ2dnVQb0VkF0dLR4fn5mhbLeFXlBQYESDsnAX6rm5eWF/1efflUHXF1d+RY6BuSDRRQXF/NtdTe/ubnhb5JVV1d/xYCsDuHm5vZxB2QTYUU1NTVCxprDQU6QUR3tFA5y4OzsTKHdx8dHyOrgfW9v78eTcGdnh9e5uTlOMukI3t7euN47OztxcHAArVaL7u5uODo68lnJEGRuYHWVX1zcntWgOguothsbG5GcnIyHhwd0dHRA3hS3t7eoq6vD5eUlzM3NIalnQ9R0qPVSs4qPj2cd09PTaib0zwLq+9QJLSwseE/KZQgwPj6OgIAAlm1sbPBsIGbIaWpGxJisIm5matA7jicmJtgQ1XZJSQlTTsplbJUzw8PDzAr9raioiLtfUFAQT0R90DuOZ2dnkZOTwyOZDK2trWFvbw+ZmZk8AygnGhoaIBMS3t7eX01Dyh19+KY3IY3cpKQkREZGQrZjZfbn5ubyzB8cHER4eDiWlpawsLDAhufn5zlv/hEH/gzdZKRQEIgdephcXV3h7+L/V/G/wgEtDAetkUymLzAQyLaxfMX8JtspPeqj8QMhn3dfZEf9RaMTyNIKNTIy+hnfGXKa3splVXbOGdr/DtMw0L76HoUPAAAAAElFTkSuQmCC'\n alt='Plaid'\n />\n )\n}\n\nexport default PlaidIcon\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Sunrise = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 12'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M8.5 9C8.5 8.33696 8.23661 7.70107 7.76777 7.23223C7.29893 6.76339 6.66304 6.5 6 6.5C5.33696 6.5 4.70107 6.76339 4.23223 7.23223C3.76339 7.70107 3.5 8.33696 3.5 9'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M6 3.3335V4.66683'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M2.11 5.10986L2.82 5.81986'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M0.5 9H1.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5 9H11.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9.17999 5.81986L9.88999 5.10986'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M11.5 11H0.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Sunrise\n", "import { filterVisibility } from '../components/BankTransactions/utils'\nimport { CategoryOption } from '../components/CategorySelect/CategorySelect'\nimport { BankTransaction, DateRange, Direction, DisplayState } from '../types'\nimport { isWithinInterval, parseISO } from 'date-fns'\n\nexport const hasMatch = (bankTransaction?: BankTransaction) => {\n return Boolean(\n (bankTransaction?.suggested_matches &&\n bankTransaction?.suggested_matches?.length > 0) ||\n bankTransaction?.match,\n )\n}\n\nexport const isCredit = ({ direction }: Pick<BankTransaction, 'direction'>) =>\n direction === Direction.CREDIT\n\nexport const isAlreadyMatched = (bankTransaction?: BankTransaction) => {\n if (bankTransaction?.match) {\n const foundMatch = bankTransaction.suggested_matches?.find(\n x => x.details.id === bankTransaction?.match?.details.id,\n )\n return foundMatch?.id\n }\n\n return undefined\n}\n\nexport const countTransactionsToReview = ({\n transactions,\n dateRange,\n}: {\n transactions?: BankTransaction[]\n dateRange?: DateRange\n}) => {\n if (transactions && transactions.length > 0) {\n if (dateRange) {\n const dateRangeInterval = {\n start: dateRange.startDate,\n end: dateRange.endDate,\n }\n return transactions.filter(tx => {\n try {\n return (\n filterVisibility(DisplayState.review, tx) &&\n isWithinInterval(parseISO(tx.date), dateRangeInterval)\n )\n } catch (_err) {\n return false\n }\n }).length\n }\n return transactions.filter(tx => filterVisibility(DisplayState.review, tx))\n .length\n }\n\n return 0\n}\n\nexport const getCategorizePayload = (category: CategoryOption) => {\n if (\n category?.payload &&\n 'id' in category.payload &&\n category.payload.type == 'ExclusionNested'\n ) {\n return {\n type: 'Exclusion' as 'Exclusion',\n exclusion_type: category.payload.id,\n }\n }\n\n if (category?.payload && 'id' in category.payload && category.payload.id) {\n return {\n type: 'AccountId' as 'AccountId',\n id: category.payload.id,\n }\n }\n\n return {\n type: 'StableName' as 'StableName',\n stable_name: category?.payload.stable_name || '',\n }\n}\n", "import React, { ReactNode } from 'react'\nimport ChevronRightIcon from '../../icons/ChevronRight'\nimport { IconButton } from '../Button'\nimport { Text } from '../Typography'\n\ninterface ActionableRowProps {\n icon?: ReactNode\n iconBox?: ReactNode\n title?: string | ReactNode\n description?: string | ReactNode\n button?: ReactNode\n onClick?: () => void\n}\n\nconst renderIcon = (icon?: ReactNode, iconBox?: ReactNode) => {\n if (iconBox) {\n return iconBox\n }\n\n if (icon) {\n return <span className='Layer__actionable_row__icon'>{icon}</span>\n }\n\n return\n}\n\nconst renderTitle = (title?: string | ReactNode) => {\n if (title && typeof title === 'string') {\n return <Text className='Layer__actionable_row__title'>{title}</Text>\n }\n\n if (title) {\n return title\n }\n\n return\n}\n\nconst renderDescription = (description?: string | ReactNode) => {\n if (description && typeof description === 'string') {\n return (\n <Text className='Layer__actionable_row__description'>{description}</Text>\n )\n }\n\n if (description) {\n return description\n }\n\n return\n}\n\nexport const ActionableRow = ({\n icon,\n iconBox,\n title,\n description,\n button,\n onClick,\n}: ActionableRowProps) => {\n return (\n <div className='Layer__actionable_row'>\n <div className='Layer__actionable_row__main'>\n {renderIcon(icon, iconBox)}\n <div className='Layer__actionable_row__main__text'>\n {renderTitle(title)}\n {renderDescription(description)}\n </div>\n </div>\n <div className='Layer__actionable_row__action'>\n {button && button}\n {!button && onClick ? (\n <IconButton\n onClick={onClick}\n icon={<ChevronRightIcon size={11} />}\n withBorder\n />\n ) : null}\n </div>\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ChevronRight = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n width='18'\n height='18'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n >\n <path\n d='M6.75 13.5L11.25 9L6.75 4.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\nexport default ChevronRight\n", "import React, { ButtonHTMLAttributes, ReactNode, useRef } from 'react'\nimport classNames from 'classnames'\n\nexport enum ButtonVariant {\n primary = 'primary',\n secondary = 'secondary',\n}\n\nexport type ButtonJustify = 'center' | 'space-between' | 'start'\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant\n leftIcon?: ReactNode\n rightIcon?: ReactNode\n iconOnly?: ReactNode\n iconAsPrimary?: boolean\n justify?: ButtonJustify\n fullWidth?: boolean\n}\n\nexport const Button = ({\n className,\n children,\n variant = ButtonVariant.primary,\n leftIcon,\n rightIcon,\n iconOnly,\n iconAsPrimary = false,\n justify = 'center',\n fullWidth,\n ...props\n}: ButtonProps) => {\n const buttonRef = useRef<HTMLButtonElement>(null)\n\n let justifyContent = 'center'\n if (justify) {\n justifyContent = justify\n } else if (leftIcon && rightIcon) {\n justifyContent = 'space-between'\n } else if (rightIcon) {\n justifyContent = 'space-between'\n } else if (leftIcon) {\n justifyContent = 'start'\n }\n\n const baseClassName = classNames(\n 'Layer__btn',\n `Layer__btn--${variant}`,\n iconOnly ? 'Layer__btn--icon-only' : '',\n iconAsPrimary && 'Layer__btn--with-primary-icon',\n fullWidth && 'Layer__btn--full-width',\n className,\n )\n\n const startAnimation = () =>\n buttonRef.current &&\n [...buttonRef.current.getElementsByClassName('animateOnHover')].forEach(\n el => (el as SVGAnimateElement).beginElement(),\n )\n\n const stopAnimation = () =>\n buttonRef.current &&\n [...buttonRef.current.getElementsByClassName('animateOnHover')].forEach(\n el => (el as SVGAnimateElement).endElement(),\n )\n\n return (\n <button\n {...props}\n className={baseClassName}\n onMouseEnter={startAnimation}\n onMouseLeave={stopAnimation}\n ref={buttonRef}\n >\n <span className={`Layer__btn-content Layer__justify--${justifyContent}`}>\n {leftIcon && (\n <span\n className={classNames(\n 'Layer__btn-icon Layer__btn-icon--left',\n iconAsPrimary && 'Layer__btn-icon--primary',\n )}\n >\n {leftIcon}\n </span>\n )}\n {!iconOnly && <span className='Layer__btn-text'>{children}</span>}\n {rightIcon && (\n <span\n className={classNames(\n 'Layer__btn-icon Layer__btn-icon--right',\n iconAsPrimary && 'Layer__btn-icon--primary',\n )}\n >\n {rightIcon}\n </span>\n )}\n </span>\n </button>\n )\n}\n", "import React, { ButtonHTMLAttributes, ReactNode, useRef } from 'react'\nimport classNames from 'classnames'\n\nexport interface IconButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n icon: ReactNode\n active?: boolean\n withBorder?: boolean\n}\n\nexport const IconButton = ({\n className,\n children,\n icon,\n active,\n withBorder = false,\n ...props\n}: IconButtonProps) => {\n const baseClassName = classNames(\n 'Layer__icon-btn',\n `Layer__icon-btn--${active ? 'active' : 'inactive'}`,\n withBorder && 'Layer__icon-btn--border',\n className,\n )\n\n return (\n <button {...props} className={baseClassName}>\n {icon}\n </button>\n )\n}\n", "import React, { ButtonHTMLAttributes } from 'react'\nimport RefreshCcw from '../../icons/RefreshCcw'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport { Button, ButtonVariant } from './Button'\nimport classNames from 'classnames'\n\nexport interface RetryButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n processing?: boolean\n disabled?: boolean\n error: string\n fullWidth?: boolean\n iconOnly?: boolean\n}\n\nexport const RetryButton = ({\n className,\n processing,\n disabled,\n error,\n children,\n ...props\n}: RetryButtonProps) => {\n const baseClassName = classNames(\n 'Layer__retry-btn',\n processing ? 'Layer__btn--processing' : '',\n className,\n )\n\n return (\n <Button\n {...props}\n className={baseClassName}\n variant={ButtonVariant.secondary}\n disabled={processing || disabled}\n rightIcon={<RefreshCcw size={12} />}\n justify='center'\n >\n {children}\n </Button>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst RefreshCcw = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M0.75 3V7.5H5.25'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M17.25 15V10.5H12.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M15.3675 6.75C14.9871 5.67508 14.3407 4.71405 13.4884 3.95656C12.6361 3.19907 11.6059 2.66982 10.4938 2.41819C9.38167 2.16656 8.22393 2.20075 7.12861 2.51758C6.03328 2.8344 5.03606 3.42353 4.23 4.23L0.75 7.5M17.25 10.5L13.77 13.77C12.9639 14.5765 11.9667 15.1656 10.8714 15.4824C9.77607 15.7992 8.61833 15.8334 7.50621 15.5818C6.3941 15.3302 5.36385 14.8009 4.5116 14.0434C3.65935 13.2859 3.01288 12.3249 2.6325 11.25'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default RefreshCcw\n", "import React, { ButtonHTMLAttributes } from 'react'\nimport AlertCircle from '../../icons/AlertCircle'\nimport CheckCircle from '../../icons/CheckCircle'\nimport Loader from '../../icons/Loader'\nimport Save from '../../icons/Save'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport { Button, ButtonVariant } from './Button'\nimport classNames from 'classnames'\n\nexport interface SubmitButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n processing?: boolean\n disabled?: boolean\n error?: boolean | string\n active?: boolean\n iconOnly?: boolean\n action?: SubmitAction\n noIcon?: boolean\n}\n\nexport enum SubmitAction {\n SAVE = 'save',\n UPDATE = 'update',\n}\n\nconst buildRightIcon = ({\n processing,\n error,\n action,\n noIcon,\n}: {\n processing?: boolean\n error?: boolean | string\n action: SubmitAction\n noIcon?: boolean\n}) => {\n if (noIcon) {\n return\n }\n\n if (processing) {\n return <Loader size={14} className='Layer__anim--rotating' />\n }\n\n if (error) {\n return (\n <Tooltip offset={12}>\n <TooltipTrigger>\n <AlertCircle size={14} />\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{error}</TooltipContent>\n </Tooltip>\n )\n }\n\n if (action === SubmitAction.UPDATE) {\n return (\n <span className='Layer__pt-2'>\n <CheckCircle size={14} />\n </span>\n )\n }\n\n return (\n <span>\n <Save size={14} style={{ paddingTop: 4 }} />\n </span>\n )\n}\n\nexport const SubmitButton = ({\n active,\n className,\n processing,\n disabled,\n error,\n children,\n action = SubmitAction.SAVE,\n noIcon,\n ...props\n}: SubmitButtonProps) => {\n const baseClassName = classNames(\n active ? 'Layer__btn--active' : '',\n className,\n )\n\n return (\n <Button\n {...props}\n className={baseClassName}\n variant={ButtonVariant.primary}\n disabled={processing || disabled}\n rightIcon={buildRightIcon({ processing, error, action, noIcon })}\n iconAsPrimary={true}\n >\n {children}\n </Button>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst AlertCircle = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 6V9'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 12H9.0075'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default AlertCircle\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst CheckCircle = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M16.5 8.30999V8.99999C16.4991 10.6173 15.9754 12.191 15.007 13.4864C14.0386 14.7817 12.6775 15.7293 11.1265 16.1879C9.57557 16.6465 7.91794 16.5914 6.40085 16.0309C4.88375 15.4704 3.58848 14.4346 2.70821 13.0778C1.82794 11.721 1.40984 10.116 1.51625 8.50223C1.62266 6.88841 2.2479 5.35223 3.2987 4.12279C4.34951 2.89335 5.76958 2.03653 7.34713 1.6801C8.92469 1.32367 10.5752 1.48674 12.0525 2.14499'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M16.5 3L9 10.5075L6.75 8.2575'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default CheckCircle\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Loader = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M9 1.5V4.5'\n stroke='#3E4044'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 13.5V16.5'\n stroke='#818388'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M3.6975 3.6975L5.82 5.82'\n stroke='#5F6166'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12.18 12.18L14.3025 14.3025'\n stroke='#2D2F33'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M1.5 9H4.5'\n stroke='#5F6166'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M13.5 9H16.5'\n stroke='#2D2F33'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M3.6975 14.3025L5.82 12.18'\n stroke='#818388'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12.18 5.82L14.3025 3.6975'\n stroke='#3E4044'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Loader\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Save = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M14.25 15.75H3.75C3.35218 15.75 2.97064 15.592 2.68934 15.3107C2.40804 15.0294 2.25 14.6478 2.25 14.25V3.75C2.25 3.35218 2.40804 2.97064 2.68934 2.68934C2.97064 2.40804 3.35218 2.25 3.75 2.25H12L15.75 6V14.25C15.75 14.6478 15.592 15.0294 15.3107 15.3107C15.0294 15.592 14.6478 15.75 14.25 15.75Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12.75 15.75V9.75H5.25V15.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M5.25 2.25V6H11.25'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Save\n", "import React, {\n ReactNode,\n forwardRef,\n HTMLProps,\n isValidElement,\n cloneElement,\n} from 'react'\nimport { TooltipContext, useTooltip, useTooltipContext } from './useTooltip'\nimport { useMergeRefs, FloatingPortal } from '@floating-ui/react'\nimport type { Placement } from '@floating-ui/react'\n\nexport interface TooltipOptions {\n initialOpen?: boolean\n placement?: Placement\n open?: boolean\n disabled?: boolean\n onOpenChange?: (open: boolean) => void\n offset?: number\n shift?: { padding?: number }\n}\n\nexport const Tooltip = ({\n children,\n ...options\n}: { children: ReactNode } & TooltipOptions) => {\n const tooltip = useTooltip(options)\n return (\n <TooltipContext.Provider value={tooltip}>\n {children}\n </TooltipContext.Provider>\n )\n}\n\nexport const TooltipTrigger = forwardRef<\n HTMLElement,\n HTMLProps<HTMLElement> & { asChild?: boolean }\n>(function TooltipTrigger({ children, asChild = false, ...props }, propRef) {\n const context = useTooltipContext()\n const childrenRef = (children as any).ref\n const ref = useMergeRefs([context.refs.setReference, propRef, childrenRef])\n\n if (asChild && isValidElement(children)) {\n return cloneElement(\n children,\n context.getReferenceProps({\n ref,\n ...props,\n ...children.props,\n 'data-state': context.open ? 'open' : 'closed',\n }),\n )\n }\n\n return (\n <span\n ref={ref}\n data-state={context.open ? 'open' : 'closed'}\n className={`Layer__tooltip-trigger Layer__tooltip-trigger--${\n context.open ? 'open' : 'closed'\n }`}\n {...context.getReferenceProps(props)}\n >\n {children}\n </span>\n )\n})\n\nexport const TooltipContent = forwardRef<\n HTMLDivElement,\n HTMLProps<HTMLDivElement>\n>(function TooltipContent({ style, className, ...props }, propRef) {\n const context = useTooltipContext()\n const ref = useMergeRefs([context.refs.setFloating, propRef])\n\n if (!context.open || context.disabled) return null\n\n return (\n <FloatingPortal>\n <div\n ref={ref}\n className={className}\n style={{\n ...context.floatingStyles,\n }}\n {...context.getFloatingProps(props)}\n >\n <div className='Layer__tooltip-content ' style={{ ...context.styles }}>\n {props.children}\n </div>\n </div>\n </FloatingPortal>\n )\n})\n", "import React, { useState } from 'react'\nimport { TooltipOptions } from './Tooltip'\nimport {\n useFloating,\n autoUpdate,\n offset,\n flip,\n shift,\n useHover,\n useFocus,\n useDismiss,\n useRole,\n useInteractions,\n useTransitionStyles,\n} from '@floating-ui/react'\n\nexport type ContextType = ReturnType<typeof useTooltip> | null\n\nexport const TooltipContext = React.createContext<ContextType>(null)\n\nexport const useTooltipContext = () => {\n const context = React.useContext(TooltipContext)\n\n if (context == null) {\n throw new Error('Tooltip components must be wrapped in <Tooltip />')\n }\n\n return context\n}\n\nexport const useTooltip = ({\n initialOpen = false,\n placement = 'top',\n open: controlledOpen,\n onOpenChange: setControlledOpen,\n disabled,\n offset: offsetProp = 5,\n shift: shiftProp = { padding: 5 },\n}: TooltipOptions = {}) => {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(initialOpen)\n\n const open = controlledOpen ?? uncontrolledOpen\n const setOpen = setControlledOpen ?? setUncontrolledOpen\n\n const data = useFloating({\n placement,\n open: disabled ? false : open,\n onOpenChange: setOpen,\n whileElementsMounted: autoUpdate,\n middleware: [\n offset(offsetProp),\n flip({\n crossAxis: placement.includes('-'),\n fallbackAxisSideDirection: 'start',\n padding: shiftProp?.padding ?? 5,\n }),\n shift(shiftProp),\n ],\n })\n\n const context = data.context\n\n const hover = useHover(context, {\n move: false,\n enabled: controlledOpen == null,\n })\n const focus = useFocus(context, {\n enabled: controlledOpen == null,\n })\n const dismiss = useDismiss(context)\n const role = useRole(context, { role: 'tooltip' })\n\n const interactions = useInteractions([hover, focus, dismiss, role])\n\n const { isMounted, styles } = useTransitionStyles(context, {\n initial: {\n opacity: 0,\n transform: 'scale(0.7)',\n color: 'transparent',\n },\n duration: 300,\n })\n\n return React.useMemo(\n () => ({\n open,\n setOpen,\n isMounted,\n styles,\n disabled,\n ...interactions,\n ...data,\n }),\n [open, setOpen, interactions, data, styles, disabled],\n )\n}\n", "import React, { ButtonHTMLAttributes, ReactNode, useRef } from 'react'\nimport classNames from 'classnames'\n\nexport type TextButtonProps = ButtonHTMLAttributes<HTMLButtonElement>\n\nexport const TextButton = ({\n className,\n children,\n ...props\n}: TextButtonProps) => {\n const baseClassName = classNames('Layer__text-btn', className)\n\n return (\n <button {...props} className={baseClassName}>\n {children}\n </button>\n )\n}\n", "import React, { ButtonHTMLAttributes, ReactNode } from 'react'\nimport BackArrow from '../../icons/BackArrow'\nimport classNames from 'classnames'\n\nexport interface BackButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n textOnly?: boolean\n}\n\nexport const BackButton = ({\n className,\n children,\n textOnly = false,\n ...props\n}: BackButtonProps) => {\n const baseClassName = classNames('Layer__btn', 'Layer__back-btn', className)\n\n return (\n <button {...props} className={baseClassName}>\n {textOnly ? 'Back' : <BackArrow size={16} />}\n </button>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst BackArrow = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 12 12'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M7.375 8.75L4.625 6L7.375 3.25'\n stroke='#1A130D'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default BackArrow\n", "import React, { ButtonHTMLAttributes } from 'react'\nimport CloseIcon from '../../icons/CloseIcon'\nimport classNames from 'classnames'\n\nexport interface CloseButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n textOnly?: boolean\n}\n\nexport const CloseButton = ({\n className,\n children,\n textOnly = false,\n ...props\n}: CloseButtonProps) => {\n const baseClassName = classNames('Layer__btn', 'Layer__back-btn', className)\n\n return (\n <button {...props} className={baseClassName}>\n {textOnly ? 'Back' : <CloseIcon size={16} />}\n </button>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst CloseIcon = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 12 12'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M8.75 3.25L3.25 8.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M3.25 3.25L8.75 8.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default CloseIcon\n", "import React, { ButtonHTMLAttributes, ReactNode } from 'react'\nimport BackArrow from '../../icons/BackArrow'\nimport classNames from 'classnames'\n\nexport interface ExpandButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement> {\n collapsed?: boolean\n}\n\nexport const ExpandButton = ({\n className,\n children,\n collapsed,\n ...props\n}: ExpandButtonProps) => {\n const baseClassName = classNames(\n 'Layer__btn',\n 'Layer__expand-btn',\n collapsed ? 'Layer__expand-btn--collapsed' : 'Layer__expand-btn--expanded',\n className,\n )\n\n return (\n <button {...props} className={baseClassName}>\n <BackArrow size={16} />\n </button>\n )\n}\n", "import React, {\n HTMLAttributeAnchorTarget,\n LinkHTMLAttributes,\n ReactNode,\n useRef,\n} from 'react'\nimport { ButtonVariant, ButtonJustify } from './Button'\nimport classNames from 'classnames'\n\nexport interface LinkProps extends LinkHTMLAttributes<HTMLAnchorElement> {\n variant?: ButtonVariant\n leftIcon?: ReactNode\n rightIcon?: ReactNode\n iconOnly?: ReactNode\n iconAsPrimary?: boolean\n justify?: ButtonJustify\n fullWidth?: boolean\n target: HTMLAttributeAnchorTarget\n}\n\nexport const Link = ({\n className,\n children,\n variant = ButtonVariant.primary,\n leftIcon,\n rightIcon,\n iconOnly,\n iconAsPrimary = false,\n justify = 'center',\n fullWidth,\n ...props\n}: LinkProps) => {\n const linkRef = useRef<HTMLAnchorElement>(null)\n\n let justifyContent = 'center'\n if (justify) {\n justifyContent = justify\n } else if (leftIcon && rightIcon) {\n justifyContent = 'space-between'\n } else if (rightIcon) {\n justifyContent = 'space-between'\n } else if (leftIcon) {\n justifyContent = 'start'\n }\n\n const baseClassName = classNames(\n 'Layer__btn',\n 'Layer__btn--as-link',\n `Layer__btn--${variant}`,\n iconOnly ? 'Layer__btn--icon-only' : '',\n iconAsPrimary && 'Layer__btn--with-primary-icon',\n fullWidth && 'Layer__btn--full-width',\n className,\n )\n\n const startAnimation = () =>\n linkRef.current &&\n [...linkRef.current.getElementsByClassName('animateOnHover')].forEach(el =>\n (el as SVGAnimateElement).beginElement(),\n )\n\n const stopAnimation = () =>\n linkRef.current &&\n [...linkRef.current.getElementsByClassName('animateOnHover')].forEach(el =>\n (el as SVGAnimateElement).endElement(),\n )\n\n return (\n <a\n {...props}\n className={baseClassName}\n onMouseEnter={startAnimation}\n onMouseLeave={stopAnimation}\n ref={linkRef}\n >\n <span className={`Layer__btn-content Layer__justify--${justifyContent}`}>\n {leftIcon && (\n <span\n className={classNames(\n 'Layer__btn-icon Layer__btn-icon--left',\n iconAsPrimary && 'Layer__btn-icon--primary',\n )}\n >\n {leftIcon}\n </span>\n )}\n {!iconOnly && <span className='Layer__btn-text'>{children}</span>}\n {rightIcon && (\n <span\n className={classNames(\n 'Layer__btn-icon Layer__btn-icon--right',\n iconAsPrimary && 'Layer__btn-icon--primary',\n )}\n >\n {rightIcon}\n </span>\n )}\n </span>\n </a>\n )\n}\n", "import React, { ReactNode, useRef, useState, useEffect } from 'react'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport enum TextSize {\n lg = 'lg',\n md = 'md',\n sm = 'sm',\n}\n\nexport enum TextWeight {\n normal = 'normal',\n bold = 'bold',\n}\n\nexport enum TextUseTooltip {\n whenTruncated = 'whenTruncated',\n always = 'always',\n}\n\nexport interface TextTooltipOptions {\n contentClassName?: string\n offset?: number\n shift?: { padding?: number }\n}\n\nexport interface TextProps {\n as?: React.ElementType\n className?: string\n children: ReactNode\n size?: TextSize\n weight?: TextWeight\n htmlFor?: string\n withTooltip?: TextUseTooltip\n tooltipOptions?: TextTooltipOptions\n}\n\nexport const Text = ({\n as: Component = 'p',\n className,\n children,\n size = TextSize.md,\n weight = TextWeight.normal,\n withTooltip,\n ...props\n}: TextProps) => {\n const baseClassName = classNames(\n `Layer__text Layer__text--${size} Layer__text--${weight}`,\n className,\n )\n\n if (withTooltip) {\n return (\n <TextWithTooltip\n as={Component}\n className={baseClassName}\n size={size}\n weight={weight}\n withTooltip={withTooltip}\n {...props}\n >\n {children}\n </TextWithTooltip>\n )\n }\n\n return (\n <Component {...props} className={baseClassName}>\n {children}\n </Component>\n )\n}\n\nexport const TextWithTooltip = ({\n as: Component = 'p',\n className,\n children,\n size = TextSize.md,\n weight = TextWeight.normal,\n withTooltip = TextUseTooltip.whenTruncated,\n tooltipOptions,\n ...props\n}: TextProps) => {\n const textElementRef = useRef<HTMLElement>()\n const compareSize = () => {\n if (textElementRef.current) {\n const compare =\n textElementRef.current.children[0].scrollWidth >\n textElementRef.current.children[0].clientWidth\n setHover(compare)\n }\n }\n\n useEffect(() => {\n compareSize()\n window.addEventListener('resize', compareSize)\n }, [])\n\n useEffect(\n () => () => {\n window.removeEventListener('resize', compareSize)\n },\n [],\n )\n\n const [hoverStatus, setHover] = useState(false)\n\n const contentClassName = classNames(\n 'Layer__tooltip',\n tooltipOptions?.contentClassName,\n )\n\n return (\n <Tooltip\n disabled={!hoverStatus}\n offset={tooltipOptions?.offset}\n shift={tooltipOptions?.shift}\n >\n <TooltipTrigger>\n <Component className={className} ref={textElementRef} {...props}>\n {children}\n </Component>\n </TooltipTrigger>\n <TooltipContent className={contentClassName}>{children}</TooltipContent>\n </Tooltip>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport classNames from 'classnames'\n\nexport enum HeadingSize {\n primary = 'primary',\n secondary = 'secondary',\n}\n\nexport interface HeadingProps {\n as?: React.ElementType\n className?: string\n children: ReactNode\n size?: HeadingSize\n}\n\nexport const Heading = ({\n as: Component = 'h2',\n className,\n children,\n size = HeadingSize.primary,\n}: HeadingProps) => {\n const baseClassName = classNames(\n `Layer__heading Layer__heading--${size}`,\n className,\n )\n\n return <Component className={baseClassName}>{children}</Component>\n}\n", "import React from 'react'\nimport { TextProps, Text } from './Text'\nimport classNames from 'classnames'\n\nexport type ErrorTextProps = TextProps\n\nexport const ErrorText = ({ className, ...props }: ErrorTextProps) => {\n const baseClassName = classNames('Layer__text--error', className)\n return <Text {...props} className={baseClassName} />\n}\n", "import React, { ReactNode } from 'react'\nimport { ButtonProps } from '../Button/Button'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport enum BadgeSize {\n SMALL = 'small',\n MEDIUM = 'medium',\n}\n\nexport enum BadgeVariant {\n DEFAULT = 'default',\n SUCCESS = 'success',\n WARNING = 'warning',\n ERROR = 'error',\n}\n\nexport interface BadgeProps {\n children: ReactNode\n icon?: ReactNode\n onClick?: ButtonProps['onClick']\n tooltip?: ReactNode\n size?: BadgeSize\n variant?: BadgeVariant\n hoverable?: boolean\n}\n\nexport const Badge = ({\n icon,\n onClick,\n children,\n tooltip,\n size = BadgeSize.MEDIUM,\n variant = BadgeVariant.DEFAULT,\n hoverable = false,\n}: BadgeProps) => {\n const baseProps = {\n className: classNames(\n 'Layer__badge',\n hoverable && !tooltip ? 'Layer__badge--with-hover' : '',\n onClick || tooltip ? 'Layer__badge--clickable' : '',\n `Layer__badge--${size}`,\n `Layer__badge--${variant}`,\n ),\n onClick,\n children,\n }\n\n let content = (\n <>\n {icon && <span className='Layer__badge__icon'>{icon}</span>}\n {children}\n </>\n )\n\n content = onClick ? (\n <button role='button' {...baseProps}>\n {content}\n </button>\n ) : (\n <span {...baseProps}>{content}</span>\n )\n\n if (tooltip) {\n return (\n <Tooltip offset={12}>\n <TooltipTrigger>{content}</TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{tooltip}</TooltipContent>\n </Tooltip>\n )\n }\n\n return content\n}\n", "import React, { ReactNode } from 'react'\nimport AlertOctagon from '../../icons/AlertOctagon'\nimport CheckCircle from '../../icons/CheckCircle'\nimport Loader from '../../icons/Loader'\nimport RefreshCcw from '../../icons/RefreshCcw'\nimport { Button, ButtonVariant } from '../Button'\nimport { Text, TextSize, TextWeight } from '../Typography'\n\nexport enum DataStateStatus {\n allDone = 'allDone',\n success = 'success',\n failed = 'failed',\n info = 'info',\n}\n\nexport interface DataStateProps {\n status: DataStateStatus\n title?: string\n icon?: ReactNode\n description?: string\n onRefresh?: () => void\n isLoading?: boolean\n}\n\nconst getIcon = (status: DataStateStatus, icon?: ReactNode) => {\n switch (status) {\n case DataStateStatus.failed:\n return (\n <span className='Layer__data-state__icon Layer__data-state__icon--error'>\n {icon ?? <AlertOctagon size={12} />}\n </span>\n )\n case DataStateStatus.info:\n return (\n <span className='Layer__data-state__icon Layer__data-state__icon--neutral'>\n {icon ?? <AlertOctagon size={12} />}\n </span>\n )\n case DataStateStatus.success:\n return (\n <span className='Layer__data-state__icon Layer__data-state__icon--success'>\n {icon ?? <AlertOctagon size={12} />}\n </span>\n )\n default:\n return (\n <span className='Layer__data-state__icon Layer__data-state__icon--neutral'>\n {icon ?? <CheckCircle size={12} />}\n </span>\n )\n }\n}\n\nexport const DataState = ({\n status,\n title,\n description,\n onRefresh,\n isLoading,\n icon,\n}: DataStateProps) => {\n return (\n <div className='Layer__data-state'>\n {getIcon(status, icon)}\n <Text\n as='span'\n size={TextSize.lg}\n weight={TextWeight.bold}\n className='Layer__data-state__title'\n >\n {title}\n </Text>\n <Text as='span' className='Layer__data-state__description'>\n {description}\n </Text>\n {onRefresh && (\n <span className='Layer__data-state__btn'>\n <Button\n variant={ButtonVariant.secondary}\n rightIcon={\n isLoading ? (\n <Loader size={14} className='Layer__anim--rotating' />\n ) : (\n <RefreshCcw size={12} />\n )\n }\n onClick={onRefresh}\n disabled={isLoading}\n >\n Refresh\n </Button>\n </span>\n )}\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst AlertOctagon = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M5.895 1.5H12.105L16.5 5.895V12.105L12.105 16.5H5.895L1.5 12.105V5.895L5.895 1.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 6V9'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 12H9.0075'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default AlertOctagon\n", "import React, { useContext } from 'react'\nimport { LinkedAccountsContext } from '../../contexts/LinkedAccountsContext'\nimport { LinkedAccountsProvider } from '../../providers/LinkedAccountsProvider'\nimport { Container, Header } from '../Container'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { Loader } from '../Loader'\nimport { Heading, HeadingSize } from '../Typography'\nimport { LinkedAccountsContent } from './LinkedAccountsContent'\n\nconst COMPONENT_NAME = 'linked-accounts'\n\nexport interface LinkedAccountsProps {\n asWidget?: boolean\n elevated?: boolean\n showLedgerBalance?: boolean\n showUnlinkItem?: boolean\n showBreakConnection?: boolean\n stringOverrides?: {\n title?: string\n }\n}\n\nexport const LinkedAccounts = (props: LinkedAccountsProps) => {\n return (\n <LinkedAccountsProvider>\n <LinkedAccountsComponent {...props} />\n </LinkedAccountsProvider>\n )\n}\n\nexport const LinkedAccountsComponent = ({\n asWidget,\n elevated,\n showLedgerBalance = true,\n showUnlinkItem = false,\n showBreakConnection = false,\n stringOverrides,\n}: LinkedAccountsProps) => {\n const { isLoading, error, isValidating, refetchAccounts } = useContext(\n LinkedAccountsContext,\n )\n\n return (\n <Container name={COMPONENT_NAME} elevated={elevated}>\n <Header className='Layer__linked-accounts__header'>\n <Heading\n className='Layer__linked-accounts__title'\n size={HeadingSize.secondary}\n >\n {stringOverrides?.title || \"Linked Accounts\"}\n </Heading>\n </Header>\n\n {isLoading && (\n <div className='Layer__linked-accounts__loader-container'>\n <Loader />\n </div>\n )}\n {error && !isLoading ? (\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={() => refetchAccounts()}\n isLoading={isValidating}\n />\n ) : null}\n {!error && !isLoading ? (\n <LinkedAccountsContent\n asWidget={asWidget}\n showLedgerBalance={showLedgerBalance}\n showUnlinkItem={showUnlinkItem}\n showBreakConnection={showBreakConnection}\n />\n ) : null}\n </Container>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport LoaderIcon from '../../icons/Loader'\n\nexport interface LoaderProps {\n children?: ReactNode\n size?: number\n}\n\nexport const Loader = ({ children, size = 28 }: LoaderProps) => {\n return (\n <span className='Layer__loader'>\n <LoaderIcon size={size} className='Layer__anim--rotating' />\n {children}\n </span>\n )\n}\n", "import React from 'react'\nimport LoaderIcon from '../../icons/Loader'\n\nexport interface SmallLoaderProps {\n size?: number\n}\n\nexport const SmallLoader = ({ size = 28 }: SmallLoaderProps) => {\n return (\n <span\n className='Layer__loader Layer__loader--with-bg'\n style={{ width: size, height: size, minWidth: size, minHeight: size }}\n >\n <LoaderIcon className='Layer__anim--rotating' size={size - 16} />\n </span>\n )\n}\n", "import React, { useContext } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { LinkedAccountsContext } from '../../contexts/LinkedAccountsContext'\nimport PlusIcon from '../../icons/PlusIcon'\nimport { LinkedAccountOptions } from '../LinkedAccountOptions'\nimport { LinkedAccountThumb } from '../LinkedAccountThumb'\nimport { Text, TextSize } from '../Typography'\nimport classNames from 'classnames'\n\ninterface LinkedAccountsDataProps {\n asWidget?: boolean\n showLedgerBalance?: boolean\n showUnlinkItem?: boolean\n showBreakConnection?: boolean\n}\n\nexport const LinkedAccountsContent = ({\n asWidget,\n showLedgerBalance,\n showUnlinkItem,\n showBreakConnection,\n}: LinkedAccountsDataProps) => {\n const {\n data,\n addConnection,\n unlinkAccount,\n removeConnection,\n repairConnection,\n confirmAccount,\n denyAccount,\n breakConnection,\n } = useContext(LinkedAccountsContext)\n const { environment } = useLayerContext()\n\n const linkedAccountsNewAccountClassName = classNames(\n 'Layer__linked-accounts__new-account',\n asWidget && '--as-widget',\n showLedgerBalance && '--show-ledger-balance',\n showUnlinkItem && '--show-unlink-item',\n showBreakConnection && '--show-break-connection',\n )\n\n return (\n <div className='Layer__linked-accounts__list'>\n {data?.map((account, index) => {\n let pillConfig\n if (account.requires_user_confirmation_as_of) {\n pillConfig = {\n text: 'Confirm account',\n config: [\n {\n name: 'Mark as a duplicate account',\n action: async () => {\n // TODO: trigger some sort of loading spinner here\n await denyAccount(account.external_account_source, account.id)\n // TODO: turn off loading spinner\n },\n },\n {\n name: 'Mark as not a duplicate account',\n action: async () => {\n // TODO: trigger some sort of loading spinner here\n await confirmAccount(\n account.external_account_source,\n account.id,\n )\n // TODO: turn off loading spinner\n },\n },\n ],\n }\n } else if (account.connection_needs_repair_as_of) {\n pillConfig = {\n text: 'Fix account',\n config: [\n {\n name: 'Repair connection',\n action: async () => {\n if (account.connection_external_id) {\n // TODO: trigger some sort of loading spinner here\n // An account is \"broken\" when its connection is broken\n await repairConnection(\n account.external_account_source,\n account.connection_external_id,\n )\n // TODO: turn off loading spinner\n }\n },\n },\n ],\n }\n }\n\n const additionalConfigs = [\n {\n name: 'Unlink account',\n action: async () => {\n // TODO: replace with better confirm dialog\n if (\n confirm(\n 'Please confirm you wish to remove this financial account',\n )\n ) {\n // TODO: trigger some sort of loading spinner here\n await unlinkAccount(account.external_account_source, account.id)\n }\n // TODO: turn off loading spinner\n },\n },\n ]\n\n if (showUnlinkItem) {\n additionalConfigs.push({\n name: `Unlink all accounts under this ${account.institution?.name} connection`,\n action: async () => {\n // TODO: replace with better confirm dialog\n if (\n account.connection_external_id &&\n confirm(\n `Please confirm you wish to remove all accounts belonging to ${\n account.institution?.name || 'this institution'\n }`,\n )\n ) {\n // TODO: trigger some sort of loading spinner here\n await removeConnection(\n account.external_account_source,\n account.connection_external_id,\n )\n // TODO: turn off loading spinner\n }\n },\n })\n }\n\n if (\n environment === 'staging' &&\n !account.connection_needs_repair_as_of &&\n account.external_account_source === 'PLAID' &&\n showBreakConnection\n ) {\n additionalConfigs.push({\n name: 'Break connection (test utility)',\n action: async () => {\n if (account.connection_external_id) {\n await breakConnection(\n account.external_account_source,\n account.connection_external_id,\n )\n } else {\n console.warn(\n \"Account doesn't have defined connection_external_id\",\n )\n }\n },\n })\n }\n\n return (\n <LinkedAccountOptions\n key={`linked-acc-${index}`}\n config={[\n ...additionalConfigs,\n ...(pillConfig ? pillConfig.config : []),\n ]}\n showLedgerBalance={showLedgerBalance}\n >\n <LinkedAccountThumb\n account={account}\n asWidget={asWidget}\n showLedgerBalance={showLedgerBalance}\n pillConfig={pillConfig}\n />\n </LinkedAccountOptions>\n )\n })}\n <div\n role='button'\n tabIndex={0}\n aria-label='new-account'\n onClick={() => addConnection('PLAID')}\n className={linkedAccountsNewAccountClassName}\n >\n <div className='Layer__linked-accounts__new-account-label'>\n <PlusIcon size={15} />\n <Text as='span' size={'sm' as TextSize}>\n Add Account\n </Text>\n </div>\n </div>\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst PlusIcon = ({ size = 14, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 16 16'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M14.6667 8.49996C14.6667 4.81806 11.6819 1.83329 8.00004 1.83329C4.31814 1.83329 1.33337 4.81806 1.33337 8.49996C1.33337 12.1819 4.31814 15.1666 8.00004 15.1666C11.6819 15.1666 14.6667 12.1819 14.6667 8.49996Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M5.33337 8.5L10.6667 8.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M8 11.1666L8 5.83329'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default PlusIcon\n", "import React from 'react'\nimport MoreVertical from '../../icons/MoreVertical'\nimport { HoverMenu, HoverMenuProps } from '../HoverMenu'\nimport classNames from 'classnames'\n\ninterface LinkedAccountOptionsProps extends HoverMenuProps {\n showLedgerBalance?: boolean\n}\n\nexport const LinkedAccountOptions = ({\n children,\n config,\n showLedgerBalance,\n}: LinkedAccountOptionsProps) => {\n const linkedAccountOptionsClassName = classNames(\n 'Layer__linked-accounts__options',\n showLedgerBalance == false && '--hide-ledger-balance',\n )\n return (\n <div className={linkedAccountOptionsClassName}>\n <div className='Layer__linked-accounts__options-overlay'>\n {config.length ? (\n <div className='Layer__linked-accounts__options-overlay-button'>\n <HoverMenu config={config}>\n <MoreVertical size={16} />\n </HoverMenu>\n </div>\n ) : null}\n </div>\n {children}\n </div>\n )\n}\n", "import React from 'react'\nimport { IconSvgProps } from './types'\n\nconst MoreVertical = ({ size = 18, ...props }: IconSvgProps) => {\n return (\n <svg\n viewBox='0 0 16 14'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M8.66659 8C8.66659 7.63181 8.36811 7.33333 7.99992 7.33333C7.63173 7.33333 7.33325 7.63181 7.33325 8C7.33325 8.36819 7.63173 8.66667 7.99992 8.66667C8.36811 8.66667 8.66659 8.36819 8.66659 8Z'\n fill='currentColor'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M8.66659 3.33333C8.66659 2.96514 8.36811 2.66667 7.99992 2.66667C7.63173 2.66667 7.33325 2.96514 7.33325 3.33333C7.33325 3.70152 7.63173 4 7.99992 4C8.36811 4 8.66659 3.70152 8.66659 3.33333Z'\n fill='currentColor'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M8.66659 12.6667C8.66659 12.2985 8.36811 12 7.99992 12C7.63173 12 7.33325 12.2985 7.33325 12.6667C7.33325 13.0349 7.63173 13.3333 7.99992 13.3333C8.36811 13.3333 8.66659 13.0349 8.66659 12.6667Z'\n fill='currentColor'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n )\n}\n\nexport default MoreVertical\n", "import React, { ReactNode, useEffect, useRef, useState } from 'react'\nimport classNames from 'classnames'\n\nexport interface HoverMenuProps {\n children: ReactNode\n config: {\n name: string\n action: () => void\n }[]\n}\n\nexport const HoverMenu = ({ children, config }: HoverMenuProps) => {\n const [openMenu, setOpenMenu] = useState(false)\n const hoverMenuRef = useRef<HTMLDivElement>(null)\n\n const hoverMenuClassName = classNames(\n 'Layer__hover-menu',\n openMenu && 'Layer__hover-menu--open',\n )\n\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (\n hoverMenuRef.current &&\n !hoverMenuRef.current.contains(event.target as Node)\n ) {\n setOpenMenu(false)\n }\n }\n\n document.addEventListener('click', handleClickOutside)\n return () => {\n document.removeEventListener('click', handleClickOutside)\n }\n }, [])\n\n return (\n <div\n className={hoverMenuClassName}\n ref={hoverMenuRef}\n onMouseLeave={() => setOpenMenu(false)}\n >\n <div\n className='Layer__hover-menu__children'\n role='button'\n onMouseEnter={() => setOpenMenu(true)}\n onClick={() => setOpenMenu(true)}\n >\n {children}\n </div>\n <div className='Layer__hover-menu__list-wrapper'>\n <ul className='Layer__hover-menu__list'>\n {config &&\n config.length > 0 &&\n config.map(item => (\n <li\n key={`hover-menu-${item.name}`}\n className='Layer__hover-menu__list-item'\n >\n <button\n className='Layer__hover-menu__list-item-button'\n onClick={item.action}\n >\n {item.name}\n </button>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n", "import React from 'react'\nimport InstitutionIcon from '../../icons/InstitutionIcon'\nimport LoaderIcon from '../../icons/Loader'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { LinkedAccount } from '../../types/linked_accounts'\nimport { LinkedAccountPill } from '../LinkedAccountPill'\nimport { Text, TextSize } from '../Typography'\nimport classNames from 'classnames'\n\nexport interface LinkedAccountThumbProps {\n account: LinkedAccount\n asWidget?: boolean\n showLedgerBalance?: boolean\n pillConfig?: {\n text: string\n config: { name: string; action: () => void }[]\n }\n}\n\nconst AccountNumber = ({ accountNumber }: { accountNumber: string }) => (\n <div className='account-number'>\n <Text size={'sm' as TextSize}>\u2022\u2022\u2022 {accountNumber}</Text>\n </div>\n)\n\nexport const LinkedAccountThumb = ({\n account,\n asWidget,\n showLedgerBalance,\n pillConfig,\n}: LinkedAccountThumbProps) => {\n const linkedAccountThumbClassName = classNames(\n 'Layer__linked-account-thumb',\n asWidget && '--as-widget',\n account.is_syncing && '--is-syncing',\n account.is_syncing && 'skeleton-loader',\n showLedgerBalance && '--show-ledger-balance',\n )\n\n const linkedAccountInfoClassName = classNames(\n 'topbar',\n account.is_syncing && '--is-syncing',\n !(showLedgerBalance || account.is_syncing) && '--hide-ledger-balance',\n )\n\n let bankBalance: React.ReactNode\n if (pillConfig) {\n bankBalance = (\n <LinkedAccountPill text={pillConfig.text} config={pillConfig.config} />\n )\n } else {\n bankBalance = (\n <Text as='span' className='account-balance'>\n {`${formatMoney(account.latest_balance_timestamp?.balance)}`}\n </Text>\n )\n }\n\n return (\n <div className={linkedAccountThumbClassName}>\n <div className={linkedAccountInfoClassName}>\n <div className='topbar-details'>\n <Text as='div' className='account-name'>\n {account.external_account_name}\n </Text>\n {!asWidget && account.mask && (\n <AccountNumber accountNumber={account.mask} />\n )}\n <Text\n as='span'\n className='account-institution'\n size={'sm' as TextSize}\n >\n {account.institution?.name\n ? account.institution?.name\n : account.external_account_name}\n </Text>\n </div>\n <div className='topbar-logo'>\n {account.institution?.logo != undefined ? (\n <img\n width={28}\n height={28}\n src={`data:image/png;base64,${account.institution.logo}`}\n alt={\n account.institution?.name\n ? account.institution?.name\n : account.external_account_name\n }\n />\n ) : (\n <InstitutionIcon />\n )}\n </div>\n </div>\n {account.is_syncing ? (\n <div className='loadingbar'>\n <div className='loading-text Layer__text--sm'>\n <div>Syncing account data</div>\n <div className='syncing-data-description'>\n This may take up to 5 minutes\n </div>\n </div>\n <div className='loading-wrapper'>\n <LoaderIcon size={11} className='Layer__anim--rotating' />\n </div>\n </div>\n ) : (\n <>\n {!asWidget && (\n <div className='middlebar'>\n <Text\n as='span'\n className={classNames(\n 'account-balance-text',\n !showLedgerBalance && '--hide-ledger-balance',\n )}\n size={'sm' as TextSize}\n >\n Bank balance\n </Text>\n {bankBalance}\n </div>\n )}\n {showLedgerBalance && (\n <div className='bottombar'>\n {asWidget && account.mask ? (\n <AccountNumber accountNumber={account.mask} />\n ) : (\n <Text\n as='span'\n className='account-balance-text'\n size={'sm' as TextSize}\n >\n Ledger balance\n </Text>\n )}\n <Text as='span' className='account-balance'>\n {`${formatMoney(account.current_ledger_balance)}`}\n </Text>\n </div>\n )}\n </>\n )}\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst InstitutionIcon = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 27 28'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <g filter='url(#filter0_i_2320_122784)'>\n <path\n d='M0 8.50225C0 8.13268 0.20383 7.79324 0.530047 7.61956L13.03 0.964441C13.3238 0.80803 13.6762 0.808029 13.97 0.964441L26.47 7.61956C26.7962 7.79324 27 8.13268 27 8.50225V9.71423C27 10.2665 26.5523 10.7142 26 10.7142H0.999999C0.447715 10.7142 0 10.2665 0 9.71423V8.50225Z'\n fill='currentColor'\n />\n </g>\n <g filter='url(#filter1_i_2320_122784)'>\n <path\n d='M3 13C3 12.4477 3.44772 12 4 12H7C7.55228 12 8 12.4477 8 13V20C8 20.5523 7.55228 21 7 21H4C3.44772 21 3 20.5523 3 20L3 13Z'\n fill='currentColor'\n />\n </g>\n <g filter='url(#filter2_i_2320_122784)'>\n <path\n d='M11 13C11 12.4477 11.4477 12 12 12H15C15.5523 12 16 12.4477 16 13V20C16 20.5523 15.5523 21 15 21H12C11.4477 21 11 20.5523 11 20L11 13Z'\n fill='currentColor'\n />\n </g>\n <g filter='url(#filter3_i_2320_122784)'>\n <path\n d='M19 13C19 12.4477 19.4477 12 20 12H23C23.5523 12 24 12.4477 24 13V20C24 20.5523 23.5523 21 23 21H20C19.4477 21 19 20.5523 19 20L19 13Z'\n fill='currentColor'\n />\n </g>\n <g filter='url(#filter4_i_2320_122784)'>\n <path\n d='M1 23.2856C1 22.7334 1.44772 22.2856 2 22.2856H25C25.5523 22.2856 26 22.7334 26 23.2856V26.2856C26 26.8379 25.5523 27.2856 25 27.2856H2C1.44772 27.2856 1 26.8379 1 26.2856L1 23.2856Z'\n fill='currentColor'\n />\n </g>\n <defs>\n <filter\n id='filter0_i_2320_122784'\n x='0'\n y='0.847168'\n width='27'\n height='9.86707'\n filterUnits='userSpaceOnUse'\n colorInterpolationFilters='sRGB'\n >\n <feFlood floodOpacity='0' result='BackgroundImageFix' />\n <feBlend\n mode='normal'\n in='SourceGraphic'\n in2='BackgroundImageFix'\n result='shape'\n />\n <feColorMatrix\n in='SourceAlpha'\n type='matrix'\n values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'\n result='hardAlpha'\n />\n <feOffset />\n <feGaussianBlur stdDeviation='0.5' />\n <feComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1' />\n <feColorMatrix\n type='matrix'\n values='0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.04 0'\n />\n <feBlend\n mode='normal'\n in2='shape'\n result='effect1_innerShadow_2320_122784'\n />\n </filter>\n <filter\n id='filter1_i_2320_122784'\n x='3'\n y='12'\n width='5'\n height='9'\n filterUnits='userSpaceOnUse'\n colorInterpolationFilters='sRGB'\n >\n <feFlood floodOpacity='0' result='BackgroundImageFix' />\n <feBlend\n mode='normal'\n in='SourceGraphic'\n in2='BackgroundImageFix'\n result='shape'\n />\n <feColorMatrix\n in='SourceAlpha'\n type='matrix'\n values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'\n result='hardAlpha'\n />\n <feOffset />\n <feGaussianBlur stdDeviation='0.5' />\n <feComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1' />\n <feColorMatrix\n type='matrix'\n values='0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.04 0'\n />\n <feBlend\n mode='normal'\n in2='shape'\n result='effect1_innerShadow_2320_122784'\n />\n </filter>\n <filter\n id='filter2_i_2320_122784'\n x='11'\n y='12'\n width='5'\n height='9'\n filterUnits='userSpaceOnUse'\n colorInterpolationFilters='sRGB'\n >\n <feFlood floodOpacity='0' result='BackgroundImageFix' />\n <feBlend\n mode='normal'\n in='SourceGraphic'\n in2='BackgroundImageFix'\n result='shape'\n />\n <feColorMatrix\n in='SourceAlpha'\n type='matrix'\n values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'\n result='hardAlpha'\n />\n <feOffset />\n <feGaussianBlur stdDeviation='0.5' />\n <feComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1' />\n <feColorMatrix\n type='matrix'\n values='0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.04 0'\n />\n <feBlend\n mode='normal'\n in2='shape'\n result='effect1_innerShadow_2320_122784'\n />\n </filter>\n <filter\n id='filter3_i_2320_122784'\n x='19'\n y='12'\n width='5'\n height='9'\n filterUnits='userSpaceOnUse'\n colorInterpolationFilters='sRGB'\n >\n <feFlood floodOpacity='0' result='BackgroundImageFix' />\n <feBlend\n mode='normal'\n in='SourceGraphic'\n in2='BackgroundImageFix'\n result='shape'\n />\n <feColorMatrix\n in='SourceAlpha'\n type='matrix'\n values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'\n result='hardAlpha'\n />\n <feOffset />\n <feGaussianBlur stdDeviation='0.5' />\n <feComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1' />\n <feColorMatrix\n type='matrix'\n values='0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.04 0'\n />\n <feBlend\n mode='normal'\n in2='shape'\n result='effect1_innerShadow_2320_122784'\n />\n </filter>\n <filter\n id='filter4_i_2320_122784'\n x='1'\n y='22.2856'\n width='25'\n height='5'\n filterUnits='userSpaceOnUse'\n colorInterpolationFilters='sRGB'\n >\n <feFlood floodOpacity='0' result='BackgroundImageFix' />\n <feBlend\n mode='normal'\n in='SourceGraphic'\n in2='BackgroundImageFix'\n result='shape'\n />\n <feColorMatrix\n in='SourceAlpha'\n type='matrix'\n values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'\n result='hardAlpha'\n />\n <feOffset />\n <feGaussianBlur stdDeviation='0.5' />\n <feComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1' />\n <feColorMatrix\n type='matrix'\n values='0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.04 0'\n />\n <feBlend\n mode='normal'\n in2='shape'\n result='effect1_innerShadow_2320_122784'\n />\n </filter>\n </defs>\n </svg>\n)\n\nexport default InstitutionIcon\n", "const formatter = new Intl.NumberFormat('en-US', {\n minimumIntegerDigits: 1,\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n})\n\nexport const centsToDollars = (cents: number = NaN): string =>\n isNaN(cents) ? '-.--' : formatter.format(cents / 100)\n\nexport const dollarsToCents = (dollars: string = ''): number =>\n Math.round(parseFloat(dollars) * 100)\n\nexport default {\n centsToDollars,\n dollarsToCents,\n}\n", "import React from 'react'\nimport AlertCircle from '../../icons/AlertCircle'\nimport MoreVertical from '../../icons/MoreVertical'\nimport { HoverMenu } from '../HoverMenu'\nimport { Pill } from '../Pill/Pill'\n\ntype Props = {\n text: string\n config: { name: string; action: () => void }[]\n}\n\nexport const LinkedAccountPill = ({ text, config }: Props) => {\n return (\n <>\n <Pill kind='error'>\n <AlertCircle size={14} /> {text}\n <div className='Layer__linked-accounts-pill__options-overlay'>\n <HoverMenu config={config}>\n <div className={'Layer__linked-accounts-pill__invisible-spacer'} />\n </HoverMenu>\n </div>\n </Pill>\n </>\n )\n}\n", "import React, { PropsWithChildren } from 'react'\n\ntype PillKind = 'default' | 'info' | 'success' | 'warning' | 'error'\n\ntype Props = PropsWithChildren & { kind?: PillKind; onHover?: () => void }\n\nexport const Pill = ({ children, kind = 'default', onHover }: Props) => (\n <span\n onMouseOver={onHover}\n className={`Layer__pill ${kind === 'error' ? 'Layer__pill--error' : ''}`}\n >\n {children}\n </span>\n)\n", "import React, { useState, useMemo, useEffect } from 'react'\nimport { BREAKPOINTS } from '../../config/general'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { BankTransactionFilters } from '../../hooks/useBankTransactions/types'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { useLinkedAccounts } from '../../hooks/useLinkedAccounts'\nimport { BankTransaction, DateRange, DisplayState } from '../../types'\nimport { debounce } from '../../utils/helpers'\nimport { BankTransactionList } from '../BankTransactionList'\nimport { BankTransactionMobileList } from '../BankTransactionMobileList'\nimport { BankTransactionsTable } from '../BankTransactionsTable'\nimport { BankTransactionsTableStringOverrides } from '../BankTransactionsTable/BankTransactionsTable'\nimport { Container } from '../Container'\nimport { ErrorBoundary } from '../ErrorBoundary'\nimport { Loader } from '../Loader'\nimport { Pagination } from '../Pagination'\nimport {\n BankTransactionsHeader,\n BankTransactionsHeaderStringOverrides,\n} from './BankTransactionsHeader'\nimport { DataStates } from './DataStates'\nimport { MobileComponentType } from './constants'\nimport { endOfMonth, parseISO, startOfMonth } from 'date-fns'\n\nconst COMPONENT_NAME = 'bank-transactions'\nconst TEST_EMPTY_STATE = false\nconst POLL_INTERVAL = 1000\n\nexport type BankTransactionsMode = 'bookkeeping-client' | 'self-serve'\n\nexport const categorizationEnabled: (\n mode: BankTransactionsMode,\n) => boolean = mode => {\n if (mode === 'bookkeeping-client') {\n return false\n }\n return true\n}\n\nexport interface BankTransactionsStringOverrides {\n bankTransactionCTAs?: BankTransactionCTAStringOverrides\n transactionsTable?: BankTransactionsTableStringOverrides\n bankTransactionsHeader?: BankTransactionsHeaderStringOverrides\n}\n\nexport interface BankTransactionCTAStringOverrides {\n approveButtonText?: string\n updateButtonText?: string\n}\n\nexport interface BankTransactionsProps {\n asWidget?: boolean\n pageSize?: number\n mode?: BankTransactionsMode\n showDescriptions?: boolean\n showReceiptUploads?: boolean\n monthlyView?: boolean\n categorizeView?: boolean\n mobileComponent?: MobileComponentType\n filters?: BankTransactionFilters\n hideHeader?: boolean\n stringOverrides?: BankTransactionsStringOverrides\n}\n\nexport interface BankTransactionsWithErrorProps extends BankTransactionsProps {\n onError?: (error: Error) => void\n}\n\nexport const BankTransactions = ({\n onError,\n ...props\n}: BankTransactionsWithErrorProps) => {\n return (\n <ErrorBoundary onError={onError}>\n <BankTransactionsContent {...props} />\n </ErrorBoundary>\n )\n}\n\nconst BankTransactionsContent = ({\n asWidget = false,\n pageSize = 20,\n mode = 'self-serve',\n showDescriptions = false,\n showReceiptUploads = false,\n monthlyView = false,\n mobileComponent,\n filters: inputFilters,\n hideHeader = false,\n stringOverrides,\n}: BankTransactionsProps) => {\n const [currentPage, setCurrentPage] = useState(1)\n const [initialLoad, setInitialLoad] = useState(true)\n const [dateRange, setDateRange] = useState<DateRange>({\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n })\n const categorizeView = categorizationEnabled(mode)\n\n const {\n activate,\n data,\n isLoading,\n loadingStatus,\n error,\n isValidating,\n refetch,\n setFilters,\n filters,\n display,\n hasMore,\n fetchMore,\n removeAfterCategorize,\n } = useBankTransactionsContext()\n\n const { data: linkedAccounts, refetchAccounts } = useLinkedAccounts()\n\n const isSyncing = useMemo(\n () => Boolean(linkedAccounts?.some(item => item.is_syncing)),\n [linkedAccounts],\n )\n\n const transactionsNotSynced = useMemo(\n () =>\n loadingStatus === 'complete' &&\n isSyncing &&\n (!data || data?.length === 0),\n [data, isSyncing, loadingStatus],\n )\n\n let intervalId: ReturnType<typeof setInterval> | undefined = undefined\n\n // calling `refetch()` directly in the `setInterval` didn't trigger actual request to API.\n // But it works when called from `useEffect`\n const [refreshTrigger, setRefreshTrigger] = useState(-1)\n useEffect(() => {\n if (refreshTrigger !== -1) {\n refetch()\n refetchAccounts()\n }\n }, [refreshTrigger])\n\n useEffect(() => {\n if (isSyncing) {\n intervalId = setInterval(() => {\n setRefreshTrigger(Math.random())\n }, POLL_INTERVAL)\n } else {\n if (intervalId) {\n clearInterval(intervalId)\n }\n }\n\n return () => {\n if (intervalId) {\n clearInterval(intervalId)\n }\n }\n }, [isSyncing, transactionsNotSynced])\n\n useEffect(() => {\n activate()\n }, [])\n\n useEffect(() => {\n if (JSON.stringify(inputFilters) !== JSON.stringify(filters)) {\n if (!filters?.categorizationStatus && categorizeView) {\n setFilters({\n ...filters,\n ...inputFilters,\n categorizationStatus: DisplayState.review,\n })\n } else if (\n !filters?.categorizationStatus &&\n !categorizationEnabled(mode)\n ) {\n setFilters({\n ...filters,\n ...inputFilters,\n categorizationStatus: DisplayState.categorized,\n })\n } else {\n setFilters({ ...filters, ...inputFilters })\n }\n } else if (!filters?.categorizationStatus && categorizeView) {\n setFilters({\n categorizationStatus: DisplayState.review,\n })\n } else if (!filters?.categorizationStatus && !categorizationEnabled(mode)) {\n setFilters({\n categorizationStatus: DisplayState.categorized,\n })\n }\n }, [inputFilters, categorizeView, mode])\n\n useEffect(() => {\n if (loadingStatus === 'complete') {\n const timeoutLoad = setTimeout(() => {\n setInitialLoad(false)\n }, 1000)\n return () => clearTimeout(timeoutLoad)\n }\n }, [loadingStatus])\n\n const bankTransactions = TEST_EMPTY_STATE\n ? []\n : useMemo(() => {\n if (monthlyView) {\n return data?.filter(\n x =>\n parseISO(x.date) >= dateRange.startDate &&\n parseISO(x.date) <= dateRange.endDate,\n )\n }\n\n const firstPageIndex = (currentPage - 1) * pageSize\n const lastPageIndex = firstPageIndex + pageSize\n return data?.slice(firstPageIndex, lastPageIndex)\n }, [currentPage, data, dateRange])\n\n const onCategorizationDisplayChange = (\n event: React.ChangeEvent<HTMLInputElement>,\n ) => {\n setFilters({\n categorizationStatus:\n event.target.value === DisplayState.categorized\n ? DisplayState.categorized\n : DisplayState.review,\n })\n setCurrentPage(1)\n }\n\n const [shiftStickyHeader, setShiftStickyHeader] = useState(0)\n const debounceShiftStickyHeader = debounce(setShiftStickyHeader, 500)\n const [listView, setListView] = useState(false)\n const [containerWidth, setContainerWidth] = useState(0)\n const debounceContainerWidth = debounce(setContainerWidth, 500)\n\n const removeTransaction = (bankTransaction: BankTransaction) =>\n removeAfterCategorize(bankTransaction)\n\n const containerRef = useElementSize<HTMLDivElement>((_el, _en, size) => {\n if (size?.height && size?.height >= 90) {\n const newShift = -Math.floor(size.height / 2) + 6\n if (newShift !== shiftStickyHeader) {\n debounceShiftStickyHeader(newShift)\n }\n } else if (size?.height > 0 && shiftStickyHeader !== 0) {\n debounceShiftStickyHeader(0)\n }\n\n if (size.width > BREAKPOINTS.TABLET && listView) {\n setListView(false)\n } else if (size.width <= BREAKPOINTS.TABLET && !listView) {\n setListView(true)\n }\n\n debounceContainerWidth(size?.width)\n })\n\n const editable = display === DisplayState.review\n\n const isLastPage =\n data &&\n !hasMore &&\n Math.ceil((data?.length || 0) / pageSize) === currentPage\n\n return (\n <Container\n className={\n display === DisplayState.review\n ? 'Layer__bank-transactions--to-review'\n : 'Layer__bank-transactions--categorized'\n }\n transparentBg={listView && mobileComponent === 'mobileList'}\n name={COMPONENT_NAME}\n asWidget={asWidget}\n ref={containerRef}\n >\n {!hideHeader && (\n <BankTransactionsHeader\n shiftStickyHeader={shiftStickyHeader}\n asWidget={asWidget}\n categorizedOnly={!categorizationEnabled(mode)}\n categorizeView={categorizeView}\n display={display}\n onCategorizationDisplayChange={onCategorizationDisplayChange}\n mobileComponent={mobileComponent}\n withDatePicker={monthlyView}\n listView={listView}\n dateRange={dateRange}\n setDateRange={v => setDateRange(v)}\n stringOverrides={stringOverrides?.bankTransactionsHeader}\n isDataLoading={isLoading}\n isSyncing={isSyncing}\n />\n )}\n\n {!listView && (\n <div className='Layer__bank-transactions__table-wrapper'>\n <BankTransactionsTable\n categorizeView={categorizeView}\n editable={editable}\n isLoading={isLoading}\n isSyncing={isSyncing}\n bankTransactions={bankTransactions}\n mode={mode}\n initialLoad={initialLoad}\n containerWidth={containerWidth}\n removeTransaction={removeTransaction}\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n page={currentPage}\n stringOverrides={stringOverrides}\n lastPage={isLastPage}\n onRefresh={refetch}\n />\n </div>\n )}\n\n {!isLoading && listView && mobileComponent !== 'mobileList' ? (\n <BankTransactionList\n mode={mode}\n bankTransactions={bankTransactions}\n editable={editable}\n removeTransaction={removeTransaction}\n containerWidth={containerWidth}\n stringOverrides={stringOverrides?.bankTransactionCTAs}\n />\n ) : null}\n\n {!isLoading && listView && mobileComponent === 'mobileList' ? (\n <BankTransactionMobileList\n bankTransactions={bankTransactions}\n editable={editable}\n mode={mode}\n removeTransaction={removeTransaction}\n initialLoad={initialLoad}\n />\n ) : null}\n\n {listView && isLoading ? (\n <div className='Layer__bank-transactions__list-loader'>\n <Loader />\n </div>\n ) : null}\n\n {!isSyncing || listView ? (\n <DataStates\n bankTransactions={bankTransactions}\n isLoading={isLoading}\n isValidating={isValidating}\n error={error}\n refetch={refetch}\n editable={editable}\n />\n ) : null}\n\n {!monthlyView && (\n <div className='Layer__bank-transactions__pagination'>\n <Pagination\n currentPage={currentPage}\n totalCount={data?.length || 0}\n pageSize={pageSize}\n onPageChange={page => setCurrentPage(page)}\n fetchMore={fetchMore}\n hasMore={hasMore}\n />\n </div>\n )}\n </Container>\n )\n}\n", "import { useLayoutEffect, useRef } from 'react'\n\nexport const useElementSize = <T extends HTMLElement>(\n callback: (\n target: T,\n entry: ResizeObserverEntry,\n size: {\n width: number\n height: number\n clientWidth: number\n clientHeight: number\n },\n ) => void,\n) => {\n const ref = useRef<T>(null)\n\n useLayoutEffect(() => {\n const element = ref?.current\n\n if (!element) {\n return\n }\n\n const observer = new ResizeObserver(entries => {\n callback(element, entries[0], {\n width: element.offsetWidth,\n height: element.offsetHeight,\n clientWidth: element.clientWidth,\n clientHeight: element.clientHeight,\n })\n })\n\n observer.observe(element)\n return () => {\n observer.disconnect()\n }\n }, [callback, ref])\n\n return ref\n}\n", "export const range = (start: number, end: number) => {\n let length = end - start + 1\n return Array.from({ length }, (_, idx) => idx + start)\n}\n\nexport const debounce = <F extends (...args: Parameters<F>) => ReturnType<F>>(\n fnc: F,\n timeout = 300,\n) => {\n let timer: ReturnType<typeof setTimeout>\n return (...args: Parameters<F>) => {\n clearTimeout(timer)\n timer = setTimeout(() => {\n fnc.apply(this, args)\n }, timeout)\n }\n}\n\nexport const sleep = (time: number) => {\n return new Promise(resolve => setTimeout(resolve, time))\n}\n\n/**\n * Convert the account name into stable_name\n */\nexport const convertToStableName = (name: string): string =>\n name\n .replace(/[`~!@#$%^&*()_|+\\-=?;:'\",.<>\\{\\}\\[\\]\\\\\\/]/gi, '')\n .replace(/\\W+/g, ' ')\n .split(/ |\\B(?=[A-Z])/)\n .map(word => word.toLowerCase())\n .join('_')\n", "import React from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport { BankTransaction } from '../../types'\nimport {\n BankTransactionCTAStringOverrides,\n BankTransactionsMode,\n} from '../BankTransactions/BankTransactions'\nimport { BankTransactionListItem } from './BankTransactionListItem'\n\ninterface BankTransactionListProps {\n bankTransactions?: BankTransaction[]\n editable: boolean\n mode: BankTransactionsMode\n containerWidth: number\n removeTransaction: (bt: BankTransaction) => void\n showDescriptions?: boolean\n showReceiptUploads?: boolean\n stringOverrides?: BankTransactionCTAStringOverrides\n}\n\nexport const BankTransactionList = ({\n bankTransactions,\n editable,\n removeTransaction,\n mode,\n containerWidth,\n showDescriptions = false,\n showReceiptUploads = false,\n stringOverrides,\n}: BankTransactionListProps) => {\n return (\n <ul className='Layer__bank-transactions__list'>\n {bankTransactions?.map(\n (bankTransaction: BankTransaction, index: number) => (\n <BankTransactionListItem\n index={index}\n key={bankTransaction.id}\n dateFormat={DATE_FORMAT}\n bankTransaction={bankTransaction}\n mode={mode}\n editable={editable}\n removeTransaction={removeTransaction}\n containerWidth={containerWidth}\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n stringOverrides={stringOverrides}\n />\n ),\n )}\n </ul>\n )\n}\n", "import React, { useEffect, useRef, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction } from '../../types'\nimport { getCategorizePayload, isCredit } from '../../utils/bankTransactions'\nimport { getDefaultSelectedCategory } from '../BankTransactionRow/BankTransactionRow'\nimport {\n BankTransactionCTAStringOverrides,\n BankTransactionsMode,\n} from '../BankTransactions/BankTransactions'\nimport { isCategorized } from '../BankTransactions/utils'\nimport { RetryButton, SubmitButton } from '../Button'\nimport { SubmitAction } from '../Button/SubmitButton'\nimport { CategorySelect } from '../CategorySelect'\nimport { ExpandedBankTransactionRow } from '../ExpandedBankTransactionRow'\nimport { SaveHandle } from '../ExpandedBankTransactionRow/ExpandedBankTransactionRow'\nimport { ErrorText, Text } from '../Typography'\nimport { TextUseTooltip } from '../Typography/Text'\nimport { Assignment } from './Assignment'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\ntype Props = {\n index: number\n dateFormat: string\n bankTransaction: BankTransaction\n editable: boolean\n mode: BankTransactionsMode\n showDescriptions: boolean\n showReceiptUploads: boolean\n removeTransaction: (bt: BankTransaction) => void\n containerWidth?: number\n stringOverrides?: BankTransactionCTAStringOverrides\n}\n\nexport const BankTransactionListItem = ({\n index = 0,\n dateFormat,\n bankTransaction,\n editable,\n mode,\n showDescriptions,\n showReceiptUploads,\n containerWidth,\n removeTransaction,\n stringOverrides,\n}: Props) => {\n const expandedRowRef = useRef<SaveHandle>(null)\n const [showRetry, setShowRetry] = useState(false)\n const { categorize: categorizeBankTransaction, match: matchBankTransaction } =\n useBankTransactionsContext()\n const [selectedCategory, setSelectedCategory] = useState(\n getDefaultSelectedCategory(bankTransaction),\n )\n\n const [open, setOpen] = useState(false)\n const toggleOpen = () => {\n setShowRetry(false)\n setOpen(!open)\n }\n\n const [showComponent, setShowComponent] = useState(false)\n\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, index * 80)\n\n return () => clearTimeout(timeoutId)\n }, [])\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n }\n }, [bankTransaction.error])\n\n useEffect(() => {\n if (editable && bankTransaction.recently_categorized) {\n setTimeout(() => {\n removeTransaction(bankTransaction)\n }, 300)\n }\n }, [bankTransaction.recently_categorized])\n\n const save = () => {\n // Save using form from expanded row when row is open:\n if (open && expandedRowRef?.current) {\n expandedRowRef?.current?.save()\n return\n }\n\n if (!selectedCategory) {\n return\n }\n\n if (selectedCategory.type === 'match') {\n matchBankTransaction(bankTransaction.id, selectedCategory.payload.id)\n return\n }\n\n categorizeBankTransaction(bankTransaction.id, {\n type: 'Category',\n category: getCategorizePayload(selectedCategory),\n })\n }\n\n const categorized = isCategorized(bankTransaction)\n\n const className = 'Layer__bank-transaction-list-item'\n const openClassName = open ? `${className}--expanded` : ''\n const rowClassName = classNames(\n className,\n bankTransaction.recently_categorized && editable\n ? 'Layer__bank-transaction-row--removing'\n : '',\n open ? openClassName : '',\n showComponent ? 'show' : '',\n )\n\n return (\n <li className={rowClassName}>\n <span className={`${className}__heading`}>\n <div className={`${className}__heading__main`}>\n <span className={`${className}__heading-date`}>\n {formatTime(parseISO(bankTransaction.date), dateFormat)}\n </span>\n <span className={`${className}__heading-separator`} />\n <span className={`${className}__heading-account-name`}>\n {bankTransaction.account_name ?? ''}\n </span>\n </div>\n <div\n onClick={toggleOpen}\n className='Layer__bank-transaction-row__expand-button'\n >\n <ChevronDownFill\n className={`Layer__chevron ${\n open ? 'Layer__chevron__up' : 'Layer__chevron__down'\n }`}\n />\n </div>\n </span>\n <span className={`${className}__body`}>\n <span className={`${className}__body__name`}>\n <Text as='span' withTooltip={TextUseTooltip.whenTruncated}>\n {bankTransaction.counterparty_name ?? bankTransaction.description}\n </Text>\n </span>\n <span\n className={`${className}__amount-${\n isCredit(bankTransaction) ? 'credit' : 'debit'\n }`}\n >\n {isCredit(bankTransaction) ? '+$' : ' $'}\n {formatMoney(bankTransaction.amount)}\n </span>\n </span>\n <span className={`${className}__expanded-row`}>\n <ExpandedBankTransactionRow\n ref={expandedRowRef}\n bankTransaction={bankTransaction}\n isOpen={open}\n mode={mode}\n close={() => setOpen(false)}\n categorized={categorized}\n asListItem={true}\n submitBtnText={\n categorized\n ? stringOverrides?.updateButtonText || 'Update'\n : stringOverrides?.approveButtonText || 'Approve'\n }\n containerWidth={containerWidth}\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n />\n </span>\n <span className={`${className}__base-row`}>\n {!categorized ? (\n <CategorySelect\n bankTransaction={bankTransaction}\n name={`category-${bankTransaction.id}`}\n value={selectedCategory}\n onChange={category => {\n setShowRetry(false)\n setSelectedCategory(category)\n }}\n disabled={bankTransaction.processing}\n />\n ) : null}\n {categorized ? <Assignment bankTransaction={bankTransaction} /> : null}\n {!categorized && !showRetry ? (\n <SubmitButton\n onClick={() => {\n if (!bankTransaction.processing) {\n save()\n }\n }}\n className='Layer__bank-transaction__submit-btn'\n processing={bankTransaction.processing}\n action={!categorized ? SubmitAction.SAVE : SubmitAction.UPDATE}\n >\n {!categorized\n ? stringOverrides?.approveButtonText || 'Approve'\n : stringOverrides?.updateButtonText || 'Update'}\n </SubmitButton>\n ) : null}\n {!categorized && showRetry ? (\n <RetryButton\n onClick={() => {\n if (!bankTransaction.processing) {\n save()\n }\n }}\n className='Layer__bank-transaction__retry-btn'\n processing={bankTransaction.processing}\n error={\n 'Approval failed. Check connection and retry in few seconds.'\n }\n >\n Retry\n </RetryButton>\n ) : null}\n </span>\n {bankTransaction.error && showRetry ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : null}\n </li>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ChevronDownFill = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path d='M4.5 6.75L9 11.25L13.5 6.75' fill='currentColor' />\n <path\n d='M4.5 6.75L9 11.25L13.5 6.75H4.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default ChevronDownFill\n", "import React, { useEffect, useRef, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport AlertCircle from '../../icons/AlertCircle'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport Scissors from '../../icons/Scissors'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction, CategorizationStatus, Category } from '../../types'\nimport { hasSuggestions } from '../../types/categories'\nimport { getCategorizePayload, isCredit } from '../../utils/bankTransactions'\nimport { Badge } from '../Badge'\nimport {\n BankTransactionCTAStringOverrides,\n BankTransactionsMode,\n categorizationEnabled,\n} from '../BankTransactions/BankTransactions'\nimport { isCategorized } from '../BankTransactions/utils'\nimport { SubmitButton, IconButton, RetryButton } from '../Button'\nimport { SubmitAction } from '../Button/SubmitButton'\nimport { CategorySelect } from '../CategorySelect'\nimport {\n mapCategoryToOption,\n mapSuggestedMatchToOption,\n} from '../CategorySelect/CategorySelect'\nimport { ExpandedBankTransactionRow } from '../ExpandedBankTransactionRow'\nimport { SaveHandle } from '../ExpandedBankTransactionRow/ExpandedBankTransactionRow'\nimport { Text } from '../Typography'\nimport { TextSize, TextUseTooltip } from '../Typography/Text'\nimport { MatchBadge } from './MatchBadge'\nimport { SplitTooltipDetails } from './SplitTooltipDetails'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\ntype Props = {\n index: number\n editable: boolean\n dateFormat: string\n bankTransaction: BankTransaction\n removeTransaction: (bt: BankTransaction) => void\n containerWidth?: number\n initialLoad?: boolean\n showDescriptions: boolean\n showReceiptUploads: boolean\n mode: BankTransactionsMode\n stringOverrides?: BankTransactionCTAStringOverrides\n}\n\nexport type LastSubmittedForm = 'simple' | 'match' | 'split' | undefined\n\nexport const extractDescriptionForSplit = (category: Category) => {\n if (!category.entries) {\n return ''\n }\n\n return category.entries.map(c => c.category.display_name).join(', ')\n}\n\nexport const getDefaultSelectedCategory = (\n bankTransaction: BankTransaction,\n) => {\n if (bankTransaction.suggested_matches?.[0]) {\n return mapSuggestedMatchToOption(bankTransaction.suggested_matches?.[0])\n }\n if (hasSuggestions(bankTransaction.categorization_flow)) {\n return mapCategoryToOption(\n bankTransaction.categorization_flow.suggestions[0],\n )\n }\n return undefined\n}\n\nlet clickTimer = Date.now()\n\nexport const BankTransactionRow = ({\n index = 0,\n editable,\n dateFormat,\n bankTransaction,\n mode,\n removeTransaction,\n containerWidth,\n initialLoad,\n showDescriptions,\n showReceiptUploads,\n stringOverrides,\n}: Props) => {\n const expandedRowRef = useRef<SaveHandle>(null)\n const [showRetry, setShowRetry] = useState(false)\n const {\n filters,\n categorize: categorizeBankTransaction,\n match: matchBankTransaction,\n } = useBankTransactionsContext()\n const [selectedCategory, setSelectedCategory] = useState(\n getDefaultSelectedCategory(bankTransaction),\n )\n const [open, setOpen] = useState(false)\n const toggleOpen = () => {\n setShowRetry(false)\n setOpen(!open)\n }\n\n const openRow = {\n onMouseDown: () => {\n clickTimer = Date.now()\n },\n onMouseUp: () => {\n if (Date.now() - clickTimer < 100 && !open) {\n setShowRetry(false)\n setOpen(true)\n }\n },\n }\n\n const [showComponent, setShowComponent] = useState(false)\n\n useEffect(() => {\n if (initialLoad) {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, index * 10)\n\n return () => clearTimeout(timeoutId)\n } else {\n setShowComponent(true)\n }\n }, [])\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n }\n }, [bankTransaction.error])\n\n useEffect(() => {\n if (editable && bankTransaction.recently_categorized) {\n setTimeout(() => {\n removeTransaction(bankTransaction)\n }, 300)\n }\n }, [bankTransaction.recently_categorized])\n\n const save = async () => {\n // Save using form from expanded row when row is open:\n if (open && expandedRowRef?.current) {\n expandedRowRef?.current?.save()\n return\n }\n\n if (!selectedCategory) {\n return\n }\n\n if (selectedCategory.type === 'match') {\n await matchBankTransaction(\n bankTransaction.id,\n selectedCategory.payload.id,\n )\n setOpen(false)\n return\n }\n\n await categorizeBankTransaction(bankTransaction.id, {\n type: 'Category',\n category: getCategorizePayload(selectedCategory),\n })\n setOpen(false)\n }\n\n const categorized = isCategorized(bankTransaction)\n\n const className = 'Layer__bank-transaction-row'\n const openClassName = open ? `${className}--expanded` : ''\n const rowClassName = classNames(\n className,\n bankTransaction.recently_categorized && editable\n ? 'Layer__bank-transaction-row--removing'\n : '',\n open ? openClassName : '',\n initialLoad ? 'initial-load' : '',\n showComponent ? 'show' : '',\n )\n\n return (\n <>\n <tr className={rowClassName}>\n <td\n className='Layer__table-cell Layer__bank-transaction-table__date-col'\n {...openRow}\n >\n <span className='Layer__table-cell-content'>\n {formatTime(parseISO(bankTransaction.date), dateFormat)}\n </span>\n </td>\n <td\n className='Layer__table-cell Layer__bank-transactions__tx-col'\n {...openRow}\n >\n <span className='Layer__table-cell-content'>\n <Text\n as='span'\n className='Layer__bank-transactions__tx-text'\n withTooltip={TextUseTooltip.whenTruncated}\n tooltipOptions={{\n contentClassName: 'Layer__bank-transactions__tx-tooltip',\n }}\n >\n {bankTransaction.counterparty_name ?? bankTransaction.description}\n </Text>\n </span>\n </td>\n <td\n className='Layer__table-cell Layer__bank-transactions__account-col'\n {...openRow}\n >\n <span className='Layer__table-cell-content'>\n <Text\n as='span'\n className='Layer__bank-transactions__account-text'\n withTooltip={TextUseTooltip.whenTruncated}\n >\n {bankTransaction.account_name ?? ''}\n </Text>\n </span>\n </td>\n <td\n className={`Layer__table-cell Layer__table-cell__amount-col Layer__bank-transactions__amount-col Layer__table-cell--amount ${className}__table-cell--amount-${\n isCredit(bankTransaction) ? 'credit' : 'debit'\n }`}\n {...openRow}\n >\n <span className='Layer__table-cell-content'>\n {isCredit(bankTransaction) ? '+$' : ' $'}\n {formatMoney(bankTransaction.amount)}\n </span>\n </td>\n <td\n className={classNames(\n 'Layer__table-cell',\n 'Layer__table-cell__category-col',\n `${className}__actions-cell`,\n `${className}__actions-cell--${open ? 'open' : 'close'}`,\n )}\n >\n <span\n className={`${className}__actions-container Layer__table-cell-content`}\n >\n {!categorized && !open ? (\n <CategorySelect\n bankTransaction={bankTransaction}\n name={`category-${bankTransaction.id}`}\n value={selectedCategory}\n onChange={category => {\n setSelectedCategory(category)\n setShowRetry(false)\n }}\n disabled={bankTransaction.processing}\n />\n ) : null}\n {categorized && !open ? (\n <Text as='span' className={`${className}__category-text`}>\n {bankTransaction.categorization_status ===\n CategorizationStatus.SPLIT && (\n <>\n <Badge\n icon={<Scissors size={11} />}\n tooltip={\n <SplitTooltipDetails\n classNamePrefix={className}\n category={bankTransaction.category}\n />\n }\n >\n Split\n </Badge>\n <span className={`${className}__category-text__text`}>\n {extractDescriptionForSplit(bankTransaction.category)}\n </span>\n </>\n )}\n {bankTransaction?.categorization_status ===\n CategorizationStatus.MATCHED &&\n bankTransaction?.match && (\n <>\n <MatchBadge\n classNamePrefix={className}\n bankTransaction={bankTransaction}\n dateFormat={dateFormat}\n />\n <span className={`${className}__category-text__text`}>\n {`${formatTime(\n parseISO(bankTransaction.match.bank_transaction.date),\n dateFormat,\n )}, ${bankTransaction.match?.details?.description}`}\n </span>\n </>\n )}\n {bankTransaction?.categorization_status !==\n CategorizationStatus.MATCHED &&\n bankTransaction?.categorization_status !==\n CategorizationStatus.SPLIT && (\n <span className={`${className}__category-text__text`}>\n {bankTransaction?.category?.display_name}\n </span>\n )}\n </Text>\n ) : null}\n {!categorized && !open && showRetry ? (\n <RetryButton\n onClick={() => {\n if (!bankTransaction.processing) {\n save()\n }\n }}\n className='Layer__bank-transaction__retry-btn'\n processing={bankTransaction.processing}\n error={\n 'Approval failed. Check connection and retry in few seconds.'\n }\n >\n Retry\n </RetryButton>\n ) : null}\n {open && bankTransaction.error ? (\n <Text\n as='span'\n size={TextSize.md}\n className='Layer__unsaved-info'\n >\n <span>Unsaved</span>\n <AlertCircle size={12} />\n </Text>\n ) : null}\n {(!categorized && (open || (!open && !showRetry))) ||\n (categorizationEnabled(mode) && categorized && open) ? (\n <SubmitButton\n onClick={() => {\n if (!bankTransaction.processing) {\n save()\n }\n }}\n className='Layer__bank-transaction__submit-btn'\n processing={bankTransaction.processing}\n active={open}\n action={categorized ? SubmitAction.SAVE : SubmitAction.UPDATE}\n >\n {categorized\n ? stringOverrides?.updateButtonText || 'Update'\n : stringOverrides?.approveButtonText || 'Approve'}\n </SubmitButton>\n ) : null}\n <IconButton\n onClick={toggleOpen}\n className='Layer__bank-transaction-row__expand-button'\n active={open}\n icon={\n <ChevronDownFill\n className={`Layer__chevron ${\n open ? 'Layer__chevron__up' : 'Layer__chevron__down'\n }`}\n />\n }\n />\n </span>\n </td>\n </tr>\n <tr>\n <td colSpan={5} className='Layer__bank-transaction-row__expanded-td'>\n <ExpandedBankTransactionRow\n ref={expandedRowRef}\n bankTransaction={bankTransaction}\n categorized={categorized}\n isOpen={open}\n mode={mode}\n close={() => setOpen(false)}\n containerWidth={containerWidth}\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n />\n </td>\n </tr>\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Scissors = ({ size = 11, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 11 11'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M2.75 4.125C3.50939 4.125 4.125 3.50939 4.125 2.75C4.125 1.99061 3.50939 1.375 2.75 1.375C1.99061 1.375 1.375 1.99061 1.375 2.75C1.375 3.50939 1.99061 4.125 2.75 4.125Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n >\n <animate\n attributeName='d'\n className='animateOnHover'\n values='M2.75 4.125C3.50939 4.125 4.125 3.50939 4.125 2.75C4.125 1.99061 3.50939 1.375 2.75 1.375C1.99061 1.375 1.375 1.99061 1.375 2.75C1.375 3.50939 1.99061 4.125 2.75 4.125Z;M2.50519 5.21436C3.20276 4.91424 3.52494 4.10544 3.22481 3.40788C2.92468 2.71031 2.11589 2.38813 1.41833 2.68826C0.720762 2.98839 0.398577 3.79718 0.698706 4.49474C0.998836 5.19231 1.80763 5.51449 2.50519 5.21436Z;M2.75 4.125C3.50939 4.125 4.125 3.50939 4.125 2.75C4.125 1.99061 3.50939 1.375 2.75 1.375C1.99061 1.375 1.375 1.99061 1.375 2.75C1.375 3.50939 1.99061 4.125 2.75 4.125Z'\n begin='indefinite'\n dur='400ms'\n repeatCount='1'\n fill='freeze'\n calcMode='linear'\n keyTimes='0;0.5;1'\n />\n </path>\n <path\n d='M2.75 9.625C3.50939 9.625 4.125 9.00939 4.125 8.25C4.125 7.49061 3.50939 6.875 2.75 6.875C1.99061 6.875 1.375 7.49061 1.375 8.25C1.375 9.00939 1.99061 9.625 2.75 9.625Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n >\n <animate\n attributeName='d'\n className='animateOnHover'\n values='M2.75 9.625C3.50939 9.625 4.125 9.00939 4.125 8.25C4.125 7.49061 3.50939 6.875 2.75 6.875C1.99061 6.875 1.375 7.49061 1.375 8.25C1.375 9.00939 1.99061 9.625 2.75 9.625Z;M1.43277 8.38576C2.13615 8.67201 2.9384 8.33386 3.22465 7.63049C3.5109 6.92711 3.17275 6.12486 2.46937 5.83861C1.766 5.55236 0.96375 5.89051 0.6775 6.59389C0.391251 7.29726 0.729398 8.09951 1.43277 8.38576Z;M2.75 9.625C3.50939 9.625 4.125 9.00939 4.125 8.25C4.125 7.49061 3.50939 6.875 2.75 6.875C1.99061 6.875 1.375 7.49061 1.375 8.25C1.375 9.00939 1.99061 9.625 2.75 9.625Z'\n begin='indefinite'\n dur='400ms'\n repeatCount='1'\n fill='freeze'\n calcMode='linear'\n keyTimes='0;0.5;1'\n />\n </path>\n <path\n d='M9.16668 1.83325L3.72168 7.27825'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n >\n <animate\n attributeName='d'\n className='animateOnHover'\n values='M9.16668 1.83325L3.72168 7.27825;M10.3129 3.58763L3.21706 6.57851;M9.16668 1.83325L3.72168 7.27825'\n begin='indefinite'\n dur='400ms'\n repeatCount='1'\n fill='freeze'\n calcMode='linear'\n keyTimes='0;0.5;1'\n />\n </path>\n <path\n d='M6.63232 6.63672L9.16691 9.16672'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n >\n <animate\n attributeName='d'\n className='animateOnHover'\n values='M6.63232 6.63672L9.16691 9.16672;M7.06396 5.9873L10.3921 7.3096;M6.63232 6.63672L9.16691 9.16672'\n begin='indefinite'\n dur='400ms'\n repeatCount='1'\n fill='freeze'\n calcMode='linear'\n keyTimes='0;0.5;1'\n />\n </path>\n <path\n d='M3.72168 3.72168L5.50001 5.50001'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n >\n <animate\n attributeName='d'\n className='animateOnHover'\n values='M3.72168 3.72168L5.50001 5.50001;M3.23828 4.45996L5.57467 5.39067;M3.72168 3.72168L5.50001 5.50001'\n begin='indefinite'\n dur='400ms'\n repeatCount='1'\n fill='freeze'\n calcMode='linear'\n keyTimes='0;0.5;1'\n />\n </path>\n </svg>\n)\n\nexport default Scissors\n", "import React from 'react'\nimport Select, {\n DropdownIndicatorProps,\n GroupHeadingProps,\n GroupBase,\n OptionProps,\n components,\n} from 'react-select'\nimport { DATE_FORMAT } from '../../config/general'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport Check from '../../icons/Check'\nimport ChevronDown from '../../icons/ChevronDown'\nimport MinimizeTwo from '../../icons/MinimizeTwo'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction, CategorizationType, Category } from '../../types'\nimport { SuggestedMatch } from '../../types/bank_transactions'\nimport { CategoryEntry } from '../../types/categories'\nimport { Badge } from '../Badge'\nimport { BadgeSize } from '../Badge/Badge'\nimport { CategorySelectDrawer } from './CategorySelectDrawer'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\ntype Props = {\n name?: string\n bankTransaction: BankTransaction\n value: CategoryOption | undefined\n onChange: (newValue: CategoryOption) => void\n disabled?: boolean\n className?: string\n excludeMatches?: boolean\n asDrawer?: boolean\n}\n\nexport enum OptionActionType {\n CATEGORY = 'category',\n MATCH = 'match',\n HIDDEN = 'hidden',\n}\n\nexport interface CategoryOptionPayload {\n id: string\n option_type: OptionActionType\n display_name: string\n date?: string\n amount?: number\n type?: string\n stable_name?: string\n entries?: CategoryEntry[]\n subCategories?: Category[]\n}\n\nexport interface CategoryOption {\n type: string\n disabled?: boolean\n payload: CategoryOptionPayload\n}\n\nexport const mapCategoryToOption = (category: Category): CategoryOption => {\n return {\n type: OptionActionType.CATEGORY,\n payload: {\n id: category.id,\n option_type: OptionActionType.CATEGORY,\n display_name: category.display_name,\n type: category.type,\n stable_name: category.stable_name,\n entries: category.entries,\n subCategories: category.subCategories,\n },\n }\n}\n\nexport const mapSuggestedMatchToOption = (\n record: SuggestedMatch,\n): CategoryOption => {\n return {\n type: OptionActionType.MATCH,\n payload: {\n id: record.id,\n option_type: OptionActionType.MATCH,\n display_name: record.details.description,\n amount: record.details.amount,\n },\n }\n}\n\nconst DropdownIndicator:\n | React.ComponentType<\n DropdownIndicatorProps<CategoryOption, false, GroupBase<CategoryOption>>\n >\n | null\n | undefined = props => {\n return (\n <components.DropdownIndicator {...props}>\n <ChevronDown />\n </components.DropdownIndicator>\n )\n}\n\nconst GroupHeading = (\n props: GroupHeadingProps<CategoryOption, false, GroupBase<CategoryOption>>,\n) => {\n return (\n <components.GroupHeading\n className={classNames(\n props.className,\n props.children === 'Match' || props.children === 'All categories'\n ? 'Layer__select__group-heading--main'\n : '',\n )}\n {...props}\n />\n )\n}\n\nconst Option = (\n props: OptionProps<CategoryOption, false, GroupBase<CategoryOption>>,\n) => {\n if (props.data.payload.option_type === 'hidden') {\n return\n }\n\n if (props.data.type === 'match') {\n return (\n <components.Option\n {...props}\n className={`${props.className} Layer__select__option-content__match`}\n >\n <div className='Layer__select__option-content__match__main-row'>\n <span className='Layer__select__option-content__match__date'>\n {props.data.payload.date &&\n formatTime(parseISO(props.data.payload.date), DATE_FORMAT)}\n </span>\n <span className='Layer__select__option-content__match__description'>\n {props.data.payload.display_name}\n </span>\n </div>\n <div className='Layer__select__option-content__match__amount-row'>\n <span className='Layer__select__option-content__match__amount'>\n ${formatMoney(props.data.payload.amount)}\n </span>\n </div>\n </components.Option>\n )\n }\n\n return (\n <components.Option\n {...props}\n className={`Layer__select__option-menu-content ${props.className}`}\n >\n <div>{props.data.payload.display_name}</div>\n {props.isSelected ? (\n <span className='Layer__select__option-menu-content-check'>\n <Check size={16} />\n </span>\n ) : null}\n </components.Option>\n )\n}\n\nconst allCategoriesDivider: GroupBase<CategoryOption>[] = [\n {\n label: 'All categories',\n options: [\n {\n type: 'All categories',\n disabled: true,\n payload: {\n id: 'all_categories',\n option_type: OptionActionType.HIDDEN,\n display_name: 'ALL CATEGORIES',\n },\n } satisfies CategoryOption,\n ],\n },\n]\n\nfunction flattenCategories(\n categories: Category[],\n): GroupBase<CategoryOption>[] {\n const categoryOptions = (categories || []).flatMap(category => {\n if (category?.subCategories && category?.subCategories?.length > 0) {\n if (category?.subCategories?.every(c => c.subCategories === undefined)) {\n return [\n {\n label: category.display_name,\n options: category.subCategories.map(x => mapCategoryToOption(x)),\n },\n ]\n }\n return flattenCategories(category.subCategories)\n }\n const resultOption = {\n label: category.display_name,\n options: [mapCategoryToOption(category)],\n } satisfies GroupBase<CategoryOption>\n return [resultOption]\n })\n return categoryOptions\n}\n\nexport const CategorySelect = ({\n bankTransaction,\n name,\n value,\n onChange,\n disabled,\n className,\n excludeMatches = false,\n asDrawer = false,\n}: Props) => {\n const { categories } = useLayerContext()\n\n const matchOptions =\n !excludeMatches && bankTransaction?.suggested_matches\n ? [\n {\n label: 'Match',\n options: bankTransaction.suggested_matches.map(x => {\n return {\n type: OptionActionType.MATCH,\n payload: {\n id: x.id,\n option_type: OptionActionType.MATCH,\n display_name: x.details.description,\n date: x.details.date,\n amount: x.details.amount,\n },\n } satisfies CategoryOption\n }),\n } satisfies GroupBase<CategoryOption>,\n ]\n : []\n\n const suggestedOptions =\n bankTransaction?.categorization_flow?.type ===\n CategorizationType.ASK_FROM_SUGGESTIONS\n ? [\n {\n label: 'Suggestions',\n options: bankTransaction.categorization_flow.suggestions.map(x =>\n mapCategoryToOption(x),\n ),\n } satisfies GroupBase<CategoryOption>,\n ]\n : []\n\n const categoryOptions = flattenCategories(categories)\n\n const options = [\n ...matchOptions,\n ...suggestedOptions,\n ...allCategoriesDivider,\n ...categoryOptions,\n ]\n\n const selected = value\n ? value\n : !excludeMatches &&\n matchOptions?.length === 1 &&\n matchOptions[0].options.length === 1\n ? matchOptions[0].options[0]\n : undefined\n\n const placeholder =\n matchOptions?.length === 1 && matchOptions[0].options.length > 1\n ? `${matchOptions[0].options.length} possible matches...`\n : 'Categorize or match...'\n\n if (asDrawer) {\n return <CategorySelectDrawer onSelect={onChange} selected={value} />\n }\n\n // The menu does not show in all cases unless the\n // menuPortalTarget and styles lines exist\n // See: https://stackoverflow.com/questions/55830799/how-to-change-zindex-in-react-select-drowpdown\n return (\n <Select<CategoryOption>\n name={name}\n className={`Layer__category-menu Layer__select ${className ?? ''}`}\n classNamePrefix='Layer__select'\n classNames={{\n menu: () => 'Layer__select__menu--lg',\n }}\n options={options}\n isSearchable={true}\n placeholder={placeholder}\n defaultValue={selected}\n formatOptionLabel={props => (\n <div className='Layer__select__option-label'>\n {props.type === 'match' && (\n <Badge size={BadgeSize.SMALL} icon={<MinimizeTwo size={11} />}>\n Match\n </Badge>\n )}\n <span>{props.payload.display_name}</span>\n </div>\n )}\n value={value}\n onChange={newValue => newValue && onChange(newValue)}\n getOptionLabel={category => category.payload.display_name}\n getOptionValue={category => category.payload.id}\n menuPortalTarget={document.body}\n styles={{\n menuPortal: base => ({ ...base, zIndex: 9999 }),\n }}\n components={{ DropdownIndicator, GroupHeading, Option }}\n isDisabled={disabled}\n isOptionDisabled={option => option.disabled ?? false}\n />\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Check = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M15 4.5L6.75 12.75L3 9'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Check\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ChevronDown = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M4.5 6.75L9 11.25L13.5 6.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default ChevronDown\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst MinimizeTwo = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M3 10.5H7.5V15'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M15 7.5H10.5V3'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5 7.5L15.75 2.25'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M2.25 15.75L7.5 10.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default MinimizeTwo\n", "import React, { useContext } from 'react'\nimport { DrawerContext } from '../../contexts/DrawerContext'\nimport ChevronDown from '../../icons/ChevronDown'\nimport { BusinessCategories } from '../BankTransactionMobileList/BusinessCategories'\nimport { CategoryOption, OptionActionType } from './CategorySelect'\nimport classNames from 'classnames'\n\ninterface CategorySelectDrawerProps {\n onSelect: (value: CategoryOption) => void\n selected?: CategoryOption\n}\n\nexport const CategorySelectDrawer = ({\n onSelect,\n selected,\n}: CategorySelectDrawerProps) => {\n const { setContent, close } = useContext(DrawerContext)\n\n const onDrawerCategorySelect = (value: CategoryOption) => {\n close()\n onSelect(value)\n }\n\n return (\n <button\n aria-label='Select category'\n className={classNames(\n 'Layer__category-menu__drawer-btn',\n selected && 'Layer__category-menu__drawer-btn--selected',\n )}\n onClick={() =>\n setContent(\n <CategorySelectDrawerContent onSelect={onDrawerCategorySelect} />,\n )\n }\n >\n {selected?.payload?.display_name ?? 'Select...'}\n <ChevronDown\n size={16}\n className='Layer__category-menu__drawer-btn__arrow'\n />\n </button>\n )\n}\n\nconst CategorySelectDrawerContent = ({\n onSelect,\n}: {\n onSelect: (value: CategoryOption) => void\n}) => (\n <BusinessCategories\n select={option => {\n option.value.payload &&\n onSelect({\n type: OptionActionType.CATEGORY,\n payload: {\n ...option.value.payload,\n },\n } satisfies CategoryOption)\n }}\n />\n)\n", "import React, { useState } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { ActionableList } from '../ActionableList'\nimport { Text, TextWeight } from '../Typography'\nimport { Option, flattenCategories } from './utils'\n\nexport interface BusinessCategoriesProps {\n select: (category: Option) => void\n}\n\nexport const BusinessCategories = ({ select }: BusinessCategoriesProps) => {\n const { categories } = useLayerContext()\n\n const categoryOptions = flattenCategories(categories)\n\n const [optionsToShow, setOptionsToShow] = useState(categoryOptions)\n const [selectedGroup, setSelectedGroup] = useState<string>()\n\n const onCategorySelect = (v: Option) => {\n if (v.value.type === 'GROUP' && v.value.items) {\n setOptionsToShow(v.value.items)\n setSelectedGroup(v.label)\n return\n }\n select(v)\n }\n\n return (\n <div className='Layer__bank-transaction-mobile-list-item__categories_list-container'>\n <Text\n weight={TextWeight.bold}\n className='Layer__bank-transaction-mobile-list-item__categories_list-title'\n >\n {selectedGroup ?? 'Select category'}\n </Text>\n <ActionableList<Option['value']>\n options={optionsToShow}\n onClick={onCategorySelect}\n />\n </div>\n )\n}\n", "import React from 'react'\nimport CheckIcon from '../../icons/Check'\nimport ChevronRight from '../../icons/ChevronRight'\nimport { Text } from '../Typography'\nimport classNames from 'classnames'\n\nexport interface ActionableListOption<T> {\n label: string\n id: string\n value: T\n asLink?: boolean\n secondary?: boolean\n}\n\ninterface ActionableListProps<T> {\n options: ActionableListOption<T>[]\n onClick: (item: ActionableListOption<T>) => void\n selected?: ActionableListOption<T>\n}\n\nexport const ActionableList = <T,>({\n options,\n onClick,\n selected,\n}: ActionableListProps<T>) => {\n return (\n <ul className='Layer__actionable-list'>\n {options.map((x, idx) => (\n <li\n role='button'\n onClick={() => onClick(x)}\n key={`actionable-list-item-${idx}`}\n className={classNames(\n x.secondary && 'Layer__actionable-list-item--secondary',\n x.asLink && 'Layer__actionable-list-item--as-link',\n )}\n >\n <Text>{x.label}</Text>\n {!x.asLink && selected && selected.id === x.id ? (\n <CheckIcon\n size={16}\n className='Layer__actionable-list__selected-icon'\n />\n ) : null}\n {x.asLink && (\n <ChevronRight\n size={16}\n className='Layer__actionable-list__link-icon'\n />\n )}\n </li>\n ))}\n </ul>\n )\n}\n", "export const PersonalCategories = ['PERSONAL_INCOME', 'PERSONAL_EXPENSES']\n", "import {\n BankTransaction,\n CategorizationStatus,\n Category,\n SuggestedCategorization,\n} from '../../types'\nimport { hasSuggestions } from '../../types/categories'\nimport {\n CategoryOptionPayload,\n OptionActionType,\n} from '../CategorySelect/CategorySelect'\nimport { PersonalCategories } from './constants'\n\nexport interface Option {\n label: string\n id: string\n value: {\n type: 'CATEGORY' | 'SELECT_CATEGORY' | 'GROUP'\n payload?: CategoryOptionPayload\n items?: Option[]\n }\n asLink?: boolean\n secondary?: boolean\n}\n\nexport const mapCategoryToOption = (category: Category): Option => ({\n label: category.display_name,\n id: category.id,\n value: {\n type: 'CATEGORY',\n payload: {\n id: category.id,\n option_type: OptionActionType.CATEGORY,\n display_name: category.display_name,\n type: category.type,\n stable_name: category.stable_name,\n entries: category.entries,\n subCategories: category.subCategories,\n },\n },\n})\n\nexport const flattenCategories = (categories: Category[]): Option[] => {\n const categoryOptions = (categories || []).flatMap(category => {\n if (category?.subCategories && category?.subCategories?.length > 0) {\n if (category?.subCategories?.every(c => c.subCategories === undefined)) {\n return [\n {\n label: category.display_name,\n id: category.id,\n value: {\n type: 'GROUP',\n items: category.subCategories.map(x => mapCategoryToOption(x)),\n },\n asLink: true,\n } satisfies Option,\n ]\n }\n return flattenCategories(category.subCategories)\n }\n\n const resultOption = mapCategoryToOption(category) satisfies Option\n return [resultOption]\n })\n\n return categoryOptions\n}\n\nexport const getAssignedValue = (\n bankTransaction: BankTransaction,\n): Option | undefined => {\n if (\n bankTransaction.categorization_status === CategorizationStatus.MATCHED ||\n bankTransaction?.categorization_status === CategorizationStatus.SPLIT\n ) {\n return\n }\n\n if (\n bankTransaction.category &&\n !PersonalCategories.includes(bankTransaction.category.display_name)\n ) {\n return mapCategoryToOption(bankTransaction.category)\n }\n\n if (hasSuggestions(bankTransaction.categorization_flow)) {\n const firstSuggestion = (\n bankTransaction.categorization_flow as SuggestedCategorization\n ).suggestions[0]\n return mapCategoryToOption(firstSuggestion)\n }\n\n return\n}\n", "import React, {\n forwardRef,\n useImperativeHandle,\n useState,\n useCallback,\n useEffect,\n useRef,\n TransitionEvent,\n} from 'react'\nimport { Layer } from '../../api/layer'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { useProfitAndLossLTM } from '../../hooks/useProfitAndLoss/useProfitAndLossLTM'\nimport AlertCircle from '../../icons/AlertCircle'\nimport Scissors from '../../icons/ScissorsFullOpen'\nimport Trash from '../../icons/Trash'\nimport {\n centsToDollars as formatMoney,\n dollarsToCents as parseMoney,\n} from '../../models/Money'\nimport {\n BankTransaction,\n SplitCategoryUpdate,\n SingleCategoryUpdate,\n} from '../../types'\nimport { hasSuggestions } from '../../types/categories'\nimport { getCategorizePayload, hasMatch } from '../../utils/bankTransactions'\nimport {\n BankTransactionsMode,\n categorizationEnabled,\n} from '../BankTransactions/BankTransactions'\nimport { Button, SubmitButton, ButtonVariant, TextButton } from '../Button'\nimport { SubmitAction } from '../Button/SubmitButton'\nimport { CategorySelect } from '../CategorySelect'\nimport {\n CategoryOption,\n mapCategoryToOption,\n} from '../CategorySelect/CategorySelect'\nimport { InputGroup, Input, FileInput } from '../Input'\nimport { MatchForm } from '../MatchForm'\nimport { Textarea } from '../Textarea'\nimport { Toggle } from '../Toggle'\nimport { ToggleSize } from '../Toggle/Toggle'\nimport { Text, ErrorText, TextSize } from '../Typography'\nimport { APIErrorNotifications } from './APIErrorNotifications'\nimport classNames from 'classnames'\n\ntype Props = {\n bankTransaction: BankTransaction\n isOpen?: boolean\n close: () => void\n asListItem?: boolean\n submitBtnText?: string\n mode: BankTransactionsMode\n containerWidth?: number\n categorized?: boolean\n showDescriptions: boolean\n showReceiptUploads: boolean\n}\n\ntype Split = {\n amount: number\n inputValue: string\n category: CategoryOption | undefined\n}\n\ntype RowState = {\n splits: Split[]\n description: string\n file: unknown\n}\n\nenum Purpose {\n categorize = 'categorize',\n match = 'match',\n}\n\nexport type SaveHandle = {\n save: () => void\n}\n\nconst isAlreadyMatched = (bankTransaction?: BankTransaction) => {\n if (bankTransaction?.match) {\n const foundMatch = bankTransaction.suggested_matches?.find(\n x => x.details.id === bankTransaction?.match?.details.id,\n )\n return foundMatch?.id\n }\n\n return undefined\n}\n\nconst validateSplit = (splitData: RowState) => {\n let valid = true\n\n splitData.splits.forEach(split => {\n if (split.amount <= 0) {\n valid = false\n } else if (!split.category) {\n valid = false\n }\n })\n\n return valid\n}\n\nexport const ExpandedBankTransactionRow = forwardRef<SaveHandle, Props>(\n (\n {\n bankTransaction,\n isOpen = false,\n close,\n categorized,\n asListItem = false,\n submitBtnText = 'Save',\n containerWidth,\n showDescriptions,\n mode,\n showReceiptUploads,\n },\n ref,\n ) => {\n const {\n categorize: categorizeBankTransaction,\n match: matchBankTransaction,\n } = useBankTransactionsContext()\n const [purpose, setPurpose] = useState<Purpose>(\n bankTransaction.category\n ? Purpose.categorize\n : hasMatch(bankTransaction)\n ? Purpose.match\n : Purpose.categorize,\n )\n const [selectedMatchId, setSelectedMatchId] = useState<string | undefined>(\n isAlreadyMatched(bankTransaction),\n )\n const [matchFormError, setMatchFormError] = useState<string | undefined>()\n const [splitFormError, setSplitFormError] = useState<string | undefined>()\n const [height, setHeight] = useState<string | number>(0)\n const [isOver, setOver] = useState(false)\n const bodyRef = useRef<HTMLSpanElement>(null)\n const [memoText, setMemoText] = useState<string | undefined>()\n const [receiptUrls, setReceiptUrls] = useState<string[]>([])\n const [isLoaded, setIsLoaded] = useState(false)\n\n const { auth, businessId, apiUrl } = useLayerContext()\n\n const defaultCategory =\n bankTransaction.category ||\n (hasSuggestions(bankTransaction.categorization_flow) &&\n bankTransaction.categorization_flow?.suggestions?.[0])\n\n const [rowState, updateRowState] = useState<RowState>({\n splits: bankTransaction.category?.entries\n ? bankTransaction.category?.entries.map(c => {\n return {\n amount: c.amount || 0,\n inputValue: formatMoney(c.amount),\n category: mapCategoryToOption(c.category),\n }\n })\n : [\n {\n amount: bankTransaction.amount,\n inputValue: formatMoney(bankTransaction.amount),\n category: mapCategoryToOption(defaultCategory),\n },\n ],\n description: '',\n file: undefined,\n })\n\n const addSplit = () => {\n updateRowState({\n ...rowState,\n splits: [\n ...rowState.splits,\n {\n amount: 0,\n inputValue: '0.00',\n category: mapCategoryToOption(defaultCategory),\n },\n ],\n })\n setSplitFormError(undefined)\n }\n\n const removeSplit = (index: number) => {\n const newSplits = rowState.splits.filter((_v, idx) => idx !== index)\n const splitTotal = newSplits.reduce((sum, split, index) => {\n const amount = index === 0 ? 0 : split.amount\n return sum + amount\n }, 0)\n const remaining = bankTransaction.amount - splitTotal\n newSplits[0].amount = remaining\n newSplits[0].inputValue = formatMoney(remaining)\n\n updateRowState({\n ...rowState,\n splits: newSplits,\n })\n setSplitFormError(undefined)\n }\n\n const sanitizeNumberInput = (input: string): string => {\n let sanitized = input.replace(/[^0-9.]/g, '')\n\n // Ensure there's at most one period\n const parts = sanitized.split('.')\n if (parts.length > 2) {\n sanitized = parts[0] + '.' + parts.slice(1).join('')\n }\n\n // Limit to two digits after the decimal point\n if (parts.length === 2) {\n sanitized = parts[0] + '.' + parts[1].slice(0, 2)\n }\n\n return sanitized\n }\n\n const updateAmounts =\n (rowNumber: number) => (event: React.ChangeEvent<HTMLInputElement>) => {\n const newDisplaying = sanitizeNumberInput(event.target.value)\n\n const newAmount = Number(newDisplaying) * 100 // cents\n const splitTotal = rowState.splits.reduce((sum, split, index) => {\n const amount =\n index === 0 ? 0 : index === rowNumber ? newAmount : split.amount\n return sum + amount\n }, 0)\n\n const remaining = bankTransaction.amount - splitTotal\n rowState.splits[rowNumber].amount = newAmount\n rowState.splits[rowNumber].inputValue = newDisplaying\n rowState.splits[0].amount = remaining\n rowState.splits[0].inputValue = formatMoney(remaining)\n updateRowState({ ...rowState })\n setSplitFormError(undefined)\n }\n\n const onBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (event.target.value === '') {\n const [_, index] = event.target.name.split('-')\n rowState.splits[parseInt(index)].inputValue = '0.00'\n updateRowState({ ...rowState })\n setSplitFormError(undefined)\n }\n }\n\n const onChangePurpose = (event: React.ChangeEvent<HTMLInputElement>) => {\n setPurpose(\n event.target.value === Purpose.match\n ? Purpose.match\n : Purpose.categorize,\n )\n setSplitFormError(undefined)\n setMatchFormError(undefined)\n }\n\n const changeCategory = (index: number, newValue: CategoryOption) => {\n rowState.splits[index].category = newValue\n updateRowState({ ...rowState })\n setSplitFormError(undefined)\n }\n\n const save = async () => {\n const endpoint = `/v1/businesses/${businessId}/bank-transactions/${bankTransaction.id}/metadata`\n\n if (showDescriptions && memoText != undefined) {\n const result = await Layer.updateBankTransactionMetadata(\n apiUrl,\n auth.access_token,\n {\n params: {\n businessId: businessId,\n bankTransactionId: bankTransaction.id,\n },\n body: {\n memo: memoText,\n },\n },\n )\n }\n\n if (purpose === Purpose.match) {\n if (!selectedMatchId) {\n setMatchFormError('Select an option to match the transaction')\n } else if (\n selectedMatchId &&\n selectedMatchId !== isAlreadyMatched(bankTransaction)\n ) {\n onMatchSubmit(selectedMatchId)\n }\n return\n }\n\n if (!validateSplit(rowState)) {\n if (rowState.splits.length > 1) {\n setSplitFormError(\n 'Use only positive amounts and select category for each entry',\n )\n } else {\n setSplitFormError('Category is required')\n }\n return\n }\n\n await categorizeBankTransaction(\n bankTransaction.id,\n rowState.splits.length === 1 && rowState?.splits[0].category\n ? ({\n type: 'Category',\n category: getCategorizePayload(rowState?.splits[0].category),\n } as SingleCategoryUpdate)\n : ({\n type: 'Split',\n entries: rowState.splits.map(split => ({\n category: split.category\n ? getCategorizePayload(split.category)\n : '',\n amount: split.amount,\n })),\n } as SplitCategoryUpdate),\n )\n close()\n }\n\n const fetchMetadata = async () => {\n const getBankTransactionMetadata = Layer.getBankTransactionMetadata(\n apiUrl,\n auth.access_token,\n {\n params: {\n businessId: businessId,\n bankTransactionId: bankTransaction.id,\n },\n },\n )\n const result = await getBankTransactionMetadata()\n if (result.data.memo) setMemoText(result.data.memo)\n }\n\n const fetchDocuments = async () => {\n const listBankTransactionDocuments = Layer.listBankTransactionDocuments(\n apiUrl,\n auth.access_token,\n {\n params: {\n businessId: businessId,\n bankTransactionId: bankTransaction.id,\n },\n },\n )\n const result = await listBankTransactionDocuments()\n const retrievedDocs = result.data.documentUrls.map(\n (docUrl: any) => docUrl.presignedUrl,\n )\n setReceiptUrls(retrievedDocs)\n }\n\n // Call this save action after clicking save in parent component:\n useImperativeHandle(ref, () => ({\n save,\n }))\n\n const onMatchSubmit = async (matchId: string) => {\n const foundMatch = bankTransaction.suggested_matches?.find(\n x => x.id === matchId,\n )\n if (!foundMatch) {\n return\n }\n\n await matchBankTransaction(bankTransaction.id, foundMatch.id)\n close()\n }\n\n const getDivHeight = useCallback(() => {\n const { height } = bodyRef.current\n ? bodyRef.current.getBoundingClientRect()\n : { height: undefined }\n\n return height || 0\n }, [])\n\n const handleTransitionEnd = useCallback(\n (e: TransitionEvent<HTMLSpanElement>) => {\n if (e.propertyName === 'height') {\n setHeight(isOpen ? 'auto' : 0)\n if (!isOpen) {\n setOver(true)\n }\n }\n },\n [isOpen],\n )\n\n useEffect(() => {\n if (!isLoaded) {\n return\n }\n\n setHeight(getDivHeight())\n setOver(false)\n\n if (!isOpen) {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => setHeight(0))\n })\n }\n }, [getDivHeight, isOpen])\n\n useEffect(() => {\n const loadDocumentsAndMetadata = async () => {\n if (showDescriptions) await fetchMetadata()\n if (showReceiptUploads) await fetchDocuments()\n setIsLoaded(true)\n setOver(true)\n }\n loadDocumentsAndMetadata()\n }, [])\n\n const className = 'Layer__expanded-bank-transaction-row'\n const shouldHide = !isOpen && isOver\n\n return (\n <span\n className={`${className} ${className}--${\n isOpen ? 'expanded' : 'collapsed'\n }`}\n style={{ height }}\n onTransitionEnd={handleTransitionEnd}\n >\n {shouldHide ? null : (\n <span className={`${className}__wrapper`} ref={bodyRef}>\n {categorizationEnabled(mode) ? (\n <div className={`${className}__content-toggle`}>\n <Toggle\n name={`purpose-${bankTransaction.id}${\n asListItem ? '-li' : ''\n }`}\n size={ToggleSize.small}\n options={[\n {\n value: 'categorize',\n label: 'Categorize',\n },\n {\n value: 'match',\n label: 'Match',\n disabled: !hasMatch(bankTransaction),\n disabledMessage:\n 'We could not find matching transactions',\n },\n ]}\n selected={purpose}\n onChange={onChangePurpose}\n />\n </div>\n ) : (\n <></>\n )}\n <div\n className={`${className}__content`}\n id={`expanded-${bankTransaction.id}`}\n >\n <div className={`${className}__content-panels`}>\n <div\n className={classNames(\n `${className}__match`,\n `${className}__content-panel`,\n purpose === Purpose.match\n ? `${className}__content-panel--active`\n : '',\n )}\n >\n <div className={`${className}__content-panel-container`}>\n <MatchForm\n classNamePrefix={className}\n bankTransaction={bankTransaction}\n selectedMatchId={selectedMatchId}\n readOnly={!categorizationEnabled(mode)}\n setSelectedMatchId={id => {\n setMatchFormError(undefined)\n setSelectedMatchId(id)\n }}\n matchFormError={matchFormError}\n />\n </div>\n </div>\n\n <div\n className={classNames(\n `${className}__splits`,\n `${className}__content-panel`,\n purpose === Purpose.categorize\n ? `${className}__content-panel--active`\n : '',\n )}\n >\n <div className={`${className}__content-panel-container`}>\n <div className={`${className}__splits-inputs`}>\n {rowState.splits.map((split, index) => (\n <div\n className={`${className}__table-cell--split-entry`}\n key={`split-${index}`}\n >\n <Input\n type='text'\n name={`split-${index}${asListItem ? '-li' : ''}`}\n disabled={\n index === 0 || !categorizationEnabled(mode)\n }\n onChange={updateAmounts(index)}\n value={split.inputValue}\n onBlur={onBlur}\n isInvalid={split.amount < 0}\n inputMode='numeric'\n errorMessage='Negative values are not allowed'\n />\n <div\n className={`${className}__table-cell--split-entry__right-col`}\n >\n <CategorySelect\n bankTransaction={bankTransaction}\n name={`category-${bankTransaction.id}`}\n value={split.category}\n onChange={value => changeCategory(index, value)}\n className='Layer__category-menu--full'\n disabled={\n bankTransaction.processing ||\n !categorizationEnabled(mode)\n }\n excludeMatches\n />\n {index > 0 && (\n <Button\n className={`${className}__table-cell--split-entry__merge-btn`}\n onClick={() => removeSplit(index)}\n rightIcon={<Trash size={18} />}\n variant={ButtonVariant.secondary}\n iconOnly={true}\n />\n )}\n </div>\n </div>\n ))}\n </div>\n {splitFormError && <ErrorText>{splitFormError}</ErrorText>}\n <div className={`${className}__total-and-btns`}>\n {rowState.splits.length > 1 && (\n <Input\n disabled={true}\n leftText='Total'\n inputMode='numeric'\n value={`$${formatMoney(\n rowState.splits.reduce(\n (x, { amount }) => x + amount,\n 0,\n ),\n )}`}\n />\n )}\n {categorizationEnabled(mode) ? (\n <div className={`${className}__splits-buttons`}>\n {rowState.splits.length > 1 ? (\n <TextButton\n onClick={addSplit}\n disabled={rowState.splits.length > 5}\n >\n Add new split\n </TextButton>\n ) : (\n <Button\n onClick={addSplit}\n rightIcon={<Scissors size={14} />}\n variant={ButtonVariant.secondary}\n disabled={rowState.splits.length > 5}\n >\n Split\n </Button>\n )}\n </div>\n ) : (\n <></>\n )}\n </div>\n </div>\n </div>\n </div>\n\n {showDescriptions && (\n <InputGroup\n className={`${className}__description`}\n name='description'\n >\n <Textarea\n name='description'\n placeholder='Add description'\n value={memoText}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>\n setMemoText(e.target.value)\n }\n />\n </InputGroup>\n )}\n\n {showReceiptUploads && (\n <div>\n <div className={`${className}__file-upload`}>\n <FileInput\n onUpload={async (file: File) => {\n const uploadDocument =\n Layer.uploadBankTransactionDocument(\n apiUrl,\n auth.access_token,\n )\n const result = await uploadDocument({\n businessId: businessId,\n bankTransactionId: bankTransaction.id,\n file: file,\n documentType: 'RECEIPT',\n })\n await fetchDocuments()\n }}\n text='Upload receipt'\n />\n\n {receiptUrls.length > 0 && 'Attached receipts:'}\n {receiptUrls.map((url, index) => (\n <a\n key={url}\n href={url}\n target='_blank'\n rel='noopener noreferrer'\n >\n Receipt {index + 1}\n </a>\n ))}\n </div>\n </div>\n )}\n\n {asListItem && categorizationEnabled(mode) ? (\n <div className={`${className}__submit-btn`}>\n {bankTransaction.error ? (\n <Text\n as='span'\n size={TextSize.md}\n className='Layer__unsaved-info'\n >\n <span>Unsaved</span>\n <AlertCircle size={12} />\n </Text>\n ) : null}\n <SubmitButton\n onClick={() => {\n if (!bankTransaction.processing) {\n save()\n }\n }}\n className='Layer__bank-transaction__submit-btn'\n processing={bankTransaction.processing}\n active={true}\n action={\n categorized ? SubmitAction.SAVE : SubmitAction.UPDATE\n }\n >\n {submitBtnText}\n </SubmitButton>\n </div>\n ) : null}\n </div>\n <APIErrorNotifications\n bankTransaction={bankTransaction}\n containerWidth={containerWidth}\n />\n </span>\n )}\n </span>\n )\n },\n)\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ScissorsFullOpen = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 12 12'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <g id='scissors'>\n <path\n id='Vector'\n d='M3 4.5C3.82843 4.5 4.5 3.82843 4.5 3C4.5 2.17157 3.82843 1.5 3 1.5C2.17157 1.5 1.5 2.17157 1.5 3C1.5 3.82843 2.17157 4.5 3 4.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n id='Vector_2'\n d='M3 10.5C3.82843 10.5 4.5 9.82843 4.5 9C4.5 8.17157 3.82843 7.5 3 7.5C2.17157 7.5 1.5 8.17157 1.5 9C1.5 9.82843 2.17157 10.5 3 10.5Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n id='Vector_3'\n d='M10 2L4.06 7.94'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n id='Vector_4'\n d='M7.235 7.23999L10 9.99999'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n id='Vector_5'\n d='M4.06 4.06006L6 6.00006'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </g>\n </svg>\n)\n\nexport default ScissorsFullOpen\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Trash = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M2.25 4.5H3.75H15.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M14.25 4.5V15C14.25 15.3978 14.092 15.7794 13.8107 16.0607C13.5294 16.342 13.1478 16.5 12.75 16.5H5.25C4.85218 16.5 4.47064 16.342 4.18934 16.0607C3.90804 15.7794 3.75 15.3978 3.75 15V4.5M6 4.5V3C6 2.60218 6.15804 2.22064 6.43934 1.93934C6.72064 1.65804 7.10218 1.5 7.5 1.5H10.5C10.8978 1.5 11.2794 1.65804 11.5607 1.93934C11.842 2.22064 12 2.60218 12 3V4.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M7.5 8.25V12.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5 8.25V12.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Trash\n", "import React, { HTMLProps } from 'react'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport interface InputProps extends HTMLProps<HTMLInputElement> {\n isInvalid?: boolean\n errorMessage?: string\n leftText?: string\n}\n\nexport const Input = ({\n className,\n isInvalid,\n errorMessage,\n leftText,\n ...props\n}: InputProps) => {\n const baseClassName = classNames(\n 'Layer__input',\n isInvalid ? 'Layer__input--error' : '',\n leftText ? 'Layer__input--with-left-text' : '',\n className,\n )\n\n return (\n <Tooltip disabled={!isInvalid || !errorMessage}>\n <TooltipTrigger className='Layer__input-tooltip'>\n <input {...props} className={baseClassName} />\n {leftText && <span className='Layer__input-left-text'>{leftText}</span>}\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{errorMessage}</TooltipContent>\n </Tooltip>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport { Text, TextSize } from '../Typography'\nimport classNames from 'classnames'\n\nexport interface InputGroupProps {\n label?: string\n name?: string\n className?: string\n children?: ReactNode\n inline?: boolean\n}\n\nexport const InputGroup = ({\n label,\n name,\n className,\n inline,\n children,\n}: InputGroupProps) => {\n const baseClassName = classNames(\n 'Layer__input-group',\n className,\n inline && 'Layer__input-group--inline',\n )\n return (\n <div className={baseClassName}>\n {label && (\n <Text\n as='label'\n size={TextSize.sm}\n className='Layer__input-label'\n htmlFor={name}\n >\n {label}\n </Text>\n )}\n {children}\n </div>\n )\n}\n", "import React, { useRef, ChangeEvent } from 'react'\nimport UploadCloud from '../../icons/UploadCloud'\nimport { Button } from '../Button'\nimport { ButtonVariant } from '../Button/Button'\n\nexport interface FileInputProps {\n text?: string\n onUpload?: (file: File) => void\n}\n\nexport const FileInput = ({ text = 'Upload', onUpload }: FileInputProps) => {\n const hiddenFileInput = useRef<HTMLInputElement>(null)\n\n const onClick = () => {\n if (hiddenFileInput.current) {\n hiddenFileInput.current.click()\n }\n }\n\n const onChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (event.target.files && event.target.files.length > 0 && onUpload) {\n const fileUploaded = event.target.files[0]\n onUpload(fileUploaded)\n }\n }\n\n return (\n <>\n <Button\n onClick={onClick}\n variant={ButtonVariant.secondary}\n rightIcon={<UploadCloud />}\n >\n {text}\n </Button>\n <input\n type='file'\n onChange={onChange}\n ref={hiddenFileInput}\n style={{ display: 'none' }}\n />\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst UploadCloud = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 18 18'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M12 12L9 9L6 12'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 9V15.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M15.2925 13.7925C16.024 13.3937 16.6019 12.7626 16.9349 11.999C17.2679 11.2353 17.3372 10.3824 17.1317 9.57501C16.9262 8.7676 16.4576 8.05162 15.8 7.54007C15.1424 7.02852 14.3332 6.75054 13.5 6.74999H12.555C12.328 5.87192 11.9049 5.05674 11.3175 4.36573C10.7301 3.67473 9.99364 3.12588 9.16358 2.76044C8.33352 2.39501 7.43141 2.22251 6.52509 2.2559C5.61876 2.28929 4.7318 2.52771 3.93088 2.95324C3.12997 3.37876 2.43593 3.98032 1.90097 4.71267C1.366 5.44503 1.00402 6.28914 0.842236 7.18153C0.680453 8.07393 0.72308 8.99139 0.966911 9.86493C1.21074 10.7385 1.64943 11.5454 2.25 12.225'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12 12L9 9L6 12'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default UploadCloud\n", "import React from 'react'\nimport ReactSelect, {\n DropdownIndicatorProps,\n GroupBase,\n OptionsOrGroups,\n components,\n} from 'react-select'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport interface SelectProps<T> {\n name?: string\n options?: OptionsOrGroups<T, GroupBase<T>>\n className?: string\n classNamePrefix?: string\n value?: T\n onChange: (selected: T) => void\n disabled?: boolean\n placeholder?: string\n isInvalid?: boolean\n errorMessage?: string\n}\n\nconst DropdownIndicator:\n | React.ComponentType<DropdownIndicatorProps<any, false, GroupBase<any>>>\n | null\n | undefined = props => {\n return (\n <components.DropdownIndicator {...props}>\n <ChevronDownFill />\n </components.DropdownIndicator>\n )\n}\n\nexport const Select = <T,>({\n name,\n options,\n className,\n classNamePrefix = 'Layer__select',\n value,\n onChange,\n disabled,\n placeholder,\n isInvalid,\n errorMessage,\n}: SelectProps<T>) => {\n const baseClassName = classNames(\n 'Layer__select',\n isInvalid ? 'Layer__select--error' : '',\n className,\n )\n return (\n <Tooltip disabled={!isInvalid || !errorMessage}>\n <TooltipTrigger className='Layer__input-tooltip'>\n <ReactSelect<T>\n name={name}\n className={baseClassName}\n classNamePrefix={classNamePrefix}\n placeholder={placeholder ?? 'Select...'}\n options={options}\n value={value}\n onChange={newValue => newValue && onChange(newValue)}\n menuPortalTarget={document.body}\n styles={{ menuPortal: base => ({ ...base, zIndex: 9999 }) }}\n components={{ DropdownIndicator }}\n isDisabled={disabled}\n />\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{errorMessage}</TooltipContent>\n </Tooltip>\n )\n}\n", "import React, { HTMLProps } from 'react'\nimport { Badge, BadgeVariant } from '../Badge'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport interface InputWithBadgeProps extends HTMLProps<HTMLInputElement> {\n isInvalid?: boolean\n errorMessage?: string\n leftText?: string\n variant?: BadgeVariant\n badge: React.ReactNode\n}\n\nexport const InputWithBadge = ({\n className,\n isInvalid,\n errorMessage,\n leftText,\n badge,\n variant = BadgeVariant.DEFAULT,\n ...props\n}: InputWithBadgeProps) => {\n const baseClassName = classNames(\n 'Layer__input',\n isInvalid ? 'Layer__input--error' : '',\n leftText ? 'Layer__input--with-left-text' : '',\n className,\n )\n\n return (\n <Tooltip disabled={!isInvalid || !errorMessage}>\n <TooltipTrigger className='Layer__input-tooltip'>\n <div className='Layer__input-with-badge'>\n <input {...props} className={baseClassName} />\n {badge && <Badge variant={variant}>{badge}</Badge>}\n </div>\n {leftText && <span className='Layer__input-left-text'>{leftText}</span>}\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{errorMessage}</TooltipContent>\n </Tooltip>\n )\n}\n", "import React from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction } from '../../types'\nimport { MatchBadge } from '../BankTransactionRow/MatchBadge'\nimport { Text, TextUseTooltip, ErrorText } from '../Typography'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface MatchFormProps {\n classNamePrefix: string\n bankTransaction: BankTransaction\n selectedMatchId?: string\n setSelectedMatchId: (val?: string) => void\n matchFormError?: string\n readOnly?: boolean\n}\n\nexport const MatchForm = ({\n classNamePrefix,\n bankTransaction,\n selectedMatchId,\n setSelectedMatchId,\n matchFormError,\n readOnly = false,\n}: MatchFormProps) => {\n return (\n <div className={`${classNamePrefix}__match-table`}>\n <div className={`${classNamePrefix}__match-table__header`}>\n <div className={`${classNamePrefix}__match-table__date`}>Date</div>\n <div className={`${classNamePrefix}__match-table__desc`}>\n Description\n </div>\n <div className={`${classNamePrefix}__match-table__amount`}>Amount</div>\n\n <div\n className={`${classNamePrefix}__match-table__status ${\n bankTransaction.match ? '' : 'no-match'\n }`}\n ></div>\n </div>\n\n {bankTransaction.suggested_matches?.map((match, idx) => {\n return (\n <div\n key={idx}\n className={classNames(\n `${classNamePrefix}__match-row`,\n match.id === selectedMatchId\n ? `${classNamePrefix}__match-row--selected`\n : '',\n )}\n onClick={() => {\n if (readOnly === true) {\n return\n }\n if (selectedMatchId === match.id) {\n setSelectedMatchId(undefined)\n return\n }\n setSelectedMatchId(match.id)\n }}\n >\n <div\n className={`Layer__nowrap ${classNamePrefix}__match-table__date`}\n >\n <span>\n {formatTime(parseISO(match.details.date), DATE_FORMAT)}\n </span>\n <span className='amount-next-to-date'>\n ${formatMoney(match.details.amount)}\n </span>\n </div>\n <div className={`${classNamePrefix}__match-table__desc`}>\n <Text\n className={`${classNamePrefix}__match-table__desc-tooltip`}\n withTooltip={TextUseTooltip.whenTruncated}\n as='span'\n >\n {match.details.description}\n </Text>\n {match.details.id === bankTransaction.match?.details.id && (\n <span className='match-badge'>\n <MatchBadge\n classNamePrefix={classNamePrefix}\n bankTransaction={bankTransaction}\n dateFormat={DATE_FORMAT}\n text='Matched'\n />\n </span>\n )}\n </div>\n <div className={`${classNamePrefix}__match-table__amount`}>\n ${formatMoney(match.details.amount)}\n </div>\n\n <div\n className={`${classNamePrefix}__match-table__status ${\n bankTransaction.match ? '' : 'no-match'\n }`}\n >\n {match.details.id === bankTransaction.match?.details.id && (\n <MatchBadge\n classNamePrefix={classNamePrefix}\n bankTransaction={bankTransaction}\n dateFormat={DATE_FORMAT}\n text='Matched'\n />\n )}\n </div>\n </div>\n )\n })}\n {matchFormError && <ErrorText>{matchFormError}</ErrorText>}\n </div>\n )\n}\n", "import React from 'react'\nimport MinimizeTwo from '../../icons/MinimizeTwo'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction, CategorizationStatus } from '../../types'\nimport { Badge } from '../Badge'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface MatchBadgeProps {\n bankTransaction: BankTransaction\n classNamePrefix: string\n dateFormat: string\n text?: string\n}\n\nexport const MatchBadge = ({\n bankTransaction,\n classNamePrefix,\n dateFormat,\n text = 'Match',\n}: MatchBadgeProps) => {\n if (\n bankTransaction.categorization_status === CategorizationStatus.MATCHED &&\n bankTransaction.match\n ) {\n const { date, amount } = bankTransaction.match.bank_transaction\n\n return (\n <Badge\n icon={<MinimizeTwo size={11} />}\n tooltip={\n <span className={`${classNamePrefix}__match-tooltip`}>\n <div className={`${classNamePrefix}__match-tooltip__date`}>\n {formatTime(parseISO(date), dateFormat)}\n </div>\n <div className={`${classNamePrefix}__match-tooltip__description`}>\n {bankTransaction.match?.details?.description ?? ''}\n </div>\n <div className={`${classNamePrefix}__match-tooltip__amount`}>\n ${formatMoney(amount)}\n </div>\n </span>\n }\n >\n {text}\n </Badge>\n )\n }\n\n return\n}\n", "import React from 'react'\nimport { MONTH_DAY_FORMAT } from '../../config/general'\nimport CheckIcon from '../../icons/Check'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { Text, ErrorText, TextSize } from '../Typography'\nimport { MatchFormProps } from './MatchForm'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport const MatchFormMobile = ({\n classNamePrefix,\n bankTransaction,\n selectedMatchId,\n setSelectedMatchId,\n matchFormError,\n}: MatchFormProps) => {\n return (\n <div className={`${classNamePrefix}__match-list`}>\n {bankTransaction.suggested_matches?.map((match, idx) => {\n return (\n <div\n key={idx}\n className={classNames(\n `${classNamePrefix}__match-item`,\n match.id === selectedMatchId\n ? `${classNamePrefix}__match-item--selected`\n : '',\n )}\n onClick={() => {\n if (selectedMatchId === match.id) {\n setSelectedMatchId(undefined)\n return\n }\n setSelectedMatchId(match.id)\n }}\n >\n <div className={`${classNamePrefix}__match-item__col-details`}>\n <div className={`${classNamePrefix}__match-item__heading`}>\n <Text\n className={`${classNamePrefix}__match-item__name`}\n as='span'\n >\n {match.details.description}\n </Text>\n <Text\n className={`${classNamePrefix}__match-item__amount`}\n as='span'\n >\n ${formatMoney(match.details.amount)}\n </Text>\n </div>\n <div className={`${classNamePrefix}__match-item__details`}>\n <Text\n className={`${classNamePrefix}__match-item__date`}\n size={TextSize.sm}\n as='span'\n >\n {formatTime(parseISO(match.details.date), MONTH_DAY_FORMAT)}\n </Text>\n </div>\n </div>\n\n <div className={`${classNamePrefix}__match-item__col-status`}>\n {selectedMatchId && selectedMatchId === match.id ? (\n <CheckIcon\n size={16}\n className={`${classNamePrefix}__match-item__selected-icon`}\n />\n ) : null}\n </div>\n </div>\n )\n })}\n {matchFormError && <ErrorText>{matchFormError}</ErrorText>}\n </div>\n )\n}\n", "import React, { HTMLProps } from 'react'\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport interface TextareaProps extends HTMLProps<HTMLTextAreaElement> {\n isInvalid?: boolean\n errorMessage?: string\n}\n\nexport const Textarea = ({\n className,\n isInvalid,\n errorMessage,\n ...props\n}: TextareaProps) => {\n const baseClassName = classNames(\n 'Layer__textarea',\n isInvalid ? 'Layer__textarea--error' : '',\n className,\n )\n\n return (\n <Tooltip disabled={!isInvalid || !errorMessage}>\n <TooltipTrigger className='Layer__input-tooltip'>\n <textarea {...props} className={baseClassName} />\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>{errorMessage}</TooltipContent>\n </Tooltip>\n )\n}\n", "import React, {\n CSSProperties,\n ChangeEvent,\n ReactNode,\n useEffect,\n useState,\n} from 'react'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../Tooltip'\nimport classNames from 'classnames'\n\nexport interface Option {\n label: string\n value: string\n disabled?: boolean\n disabledMessage?: string\n leftIcon?: ReactNode\n style?: CSSProperties\n}\n\nexport enum ToggleSize {\n medium = 'medium',\n small = 'small',\n xsmall = 'xsmall',\n}\n\nexport interface ToggleProps {\n name: string\n size?: ToggleSize\n options: Option[]\n selected?: Option['value']\n onChange: (event: ChangeEvent<HTMLInputElement>) => void\n}\n\ninterface ToggleOptionProps extends Option {\n checked: boolean\n label: string\n name: string\n size: ToggleSize\n onChange: (event: ChangeEvent<HTMLInputElement>) => void\n value: string\n disabled?: boolean\n disabledMessage?: string\n leftIcon?: ReactNode\n index: number\n}\n\nexport const Toggle = ({\n name,\n options,\n selected,\n onChange,\n size = ToggleSize.medium,\n}: ToggleProps) => {\n const [currentWidth, setCurrentWidth] = useState(0)\n const [thumbPos, setThumbPos] = useState({ left: 0, width: 0 })\n const [initialized, setInitialized] = useState(false)\n\n const toggleRef = useElementSize<HTMLDivElement>((a, b, c) => {\n if (c.width && c?.width !== currentWidth) {\n setCurrentWidth(c.width)\n }\n })\n\n const selectedValue = selected || options[0].value\n const baseClassName = classNames(\n 'Layer__toggle',\n `Layer__toggle--${size}`,\n initialized ? 'Layer__toggle--initialized' : '',\n )\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n updateThumbPosition(Number(e.target.getAttribute('data-idx') ?? 0))\n onChange(e)\n }\n\n const updateThumbPosition = (active: number) => {\n if (!toggleRef?.current) {\n return\n }\n\n const optionsNodes = [...toggleRef.current.children]\n .map(x => {\n if (\n x.className.includes('Layer__tooltip-trigger') &&\n x.children &&\n x.children.length > 0\n ) {\n return x.children[0]\n }\n\n return x\n })\n .filter(c => c.className.includes('Layer__toggle-option'))\n\n let shift = 0\n let width = thumbPos.width\n\n optionsNodes.forEach((c, i) => {\n if (i < active) {\n shift = shift + (c as HTMLElement).offsetWidth\n } else if (i === active) {\n width = (c as HTMLElement).offsetWidth\n }\n })\n\n shift = shift + (size === ToggleSize.medium ? 2 : 1.5)\n\n setThumbPos({ left: shift, width })\n }\n\n useEffect(() => {\n const selectedIndex = getSelectedIndex()\n updateThumbPosition(selectedIndex)\n\n setTimeout(() => {\n setInitialized(true)\n }, 400)\n }, [])\n\n useEffect(() => {\n const selectedIndex = getSelectedIndex()\n updateThumbPosition(selectedIndex)\n }, [currentWidth])\n\n const getSelectedIndex = () => {\n let selectedIndex = options.findIndex(\n option => option.value === selectedValue,\n )\n if (selectedIndex === -1) {\n return 0\n }\n\n return selectedIndex\n }\n\n return (\n <div className={baseClassName} ref={toggleRef}>\n {options.map((option, index) => (\n <ToggleOption\n {...option}\n size={size}\n key={option.value}\n name={name}\n checked={selectedValue === option.value}\n onChange={handleChange}\n disabled={option.disabled ?? false}\n disabledMessage={option.disabledMessage}\n index={index}\n />\n ))}\n <span className='Layer__toggle__thumb' style={{ ...thumbPos }} />\n </div>\n )\n}\n\nconst ToggleOption = ({\n checked,\n label,\n name,\n onChange,\n value,\n size,\n leftIcon,\n disabled,\n disabledMessage = 'Disabled',\n style,\n index,\n}: ToggleOptionProps) => {\n if (disabled) {\n return (\n <Tooltip>\n <TooltipTrigger>\n <label\n className={`Layer__toggle-option`}\n data-checked={checked}\n style={style}\n >\n <input\n type='radio'\n checked={checked}\n name={name}\n onChange={onChange}\n value={value}\n disabled={disabled ?? false}\n data-idx={index}\n />\n <span className='Layer__toggle-option-content'>\n {leftIcon && (\n <span className='Layer__toggle-option__icon'>{leftIcon}</span>\n )}\n <span>{label}</span>\n </span>\n </label>\n </TooltipTrigger>\n <TooltipContent className='Layer__tooltip'>\n {disabledMessage}\n </TooltipContent>\n </Tooltip>\n )\n }\n\n return (\n <label\n className={`Layer__toggle-option`}\n data-checked={checked}\n style={style}\n >\n <input\n type='radio'\n checked={checked}\n name={name}\n onChange={onChange}\n value={value}\n disabled={disabled ?? false}\n data-idx={index}\n />\n <span className='Layer__toggle-option-content'>\n {leftIcon && (\n <span className='Layer__toggle-option__icon'>{leftIcon}</span>\n )}\n <span>{label}</span>\n </span>\n </label>\n )\n}\n", "import React, { useEffect, useState } from 'react'\nimport AlertOctagon from '../../icons/AlertOctagon'\nimport { BankTransaction } from '../../types'\nimport { Text } from '../Typography'\n\ninterface APIErrorNotificationsProps {\n bankTransaction: BankTransaction\n containerWidth?: number\n}\n\ninterface Notification {\n bankTransactionId: string\n timestamp: number\n title: string\n message: string\n}\n\nconst ERROR_TITLE = 'Approval Failed'\nconst ERROR_MESSAGE = 'Something went wrong, try again later'\nconst NOTIFICATION_TIME = 4000\nconst FADE_OUT_TIME_WAIT = 1000\n\nlet notificationsCache: Notification[] = []\n\nexport const APIErrorNotifications = ({\n bankTransaction,\n containerWidth,\n}: APIErrorNotificationsProps) => {\n const [notifications, setNotifications] = useState<Notification[]>([])\n\n const pushNotification = (title: string, message: string) => {\n const timestamp = new Date().valueOf()\n if (\n notificationsCache.find(\n n =>\n n.timestamp === timestamp &&\n n.bankTransactionId !== bankTransaction.id,\n )\n ) {\n return\n }\n notificationsCache = notificationsCache.concat({\n bankTransactionId: bankTransaction.id,\n timestamp,\n title,\n message,\n })\n const ids = notificationsCache.map(\n ({ bankTransactionId }) => bankTransactionId,\n )\n const timestamps = notificationsCache.map(({ timestamp }) => timestamp)\n notificationsCache = notificationsCache.filter(\n ({ bankTransactionId, timestamp }, index) =>\n !ids.includes(bankTransactionId, index + 1) &&\n !timestamps.includes(timestamp, index + 1),\n )\n setNotifications(notificationsCache.concat())\n }\n\n const deleteNotification = (timestamp: number) => {\n notificationsCache = notificationsCache.filter(\n n => n.timestamp !== timestamp,\n )\n setNotifications(notificationsCache.concat())\n }\n\n useEffect(() => {\n if (bankTransaction.error) {\n pushNotification(ERROR_TITLE, ERROR_MESSAGE)\n }\n }, [bankTransaction.error])\n\n return (\n <div\n className='Layer__bank-transactions__notifications'\n style={containerWidth ? { left: containerWidth - 324 } : {}}\n >\n {notifications\n .filter(n => n.bankTransactionId === bankTransaction.id)\n .map(notification => (\n <Notification\n key={notification.timestamp}\n notification={notification}\n deleteNotification={deleteNotification}\n />\n ))}\n </div>\n )\n}\n\nconst Notification = ({\n notification,\n deleteNotification,\n}: {\n notification: Notification\n deleteNotification: (timestamp: number) => void\n}) => {\n const [visible, setVisible] = useState(false)\n\n useEffect(() => {\n setVisible(true)\n\n const timer = setTimeout(() => {\n hideNotification()\n }, NOTIFICATION_TIME)\n\n return () => clearTimeout(timer)\n }, [])\n\n const hideNotification = () => {\n setVisible(false)\n setTimeout(() => {\n deleteNotification(notification.timestamp)\n }, FADE_OUT_TIME_WAIT)\n }\n\n return (\n <div\n className={`Layer__bank-transactions__notification ${\n visible ? 'notification-enter' : 'notification-exit'\n }`}\n onClick={hideNotification}\n >\n <div className='Layer__bank-transactions__notification-content'>\n <div className='Layer__bank-transactions__notification-icon'>\n <AlertOctagon size={14} />\n </div>\n <div className='Layer__bank-transactions__notification-text'>\n <Text\n as='span'\n className='Layer__bank-transactions__notification-title'\n >\n {notification.title}\n </Text>\n <Text\n as='span'\n className='Layer__bank-transactions__notification-message'\n >\n {notification.message}\n </Text>\n </div>\n </div>\n </div>\n )\n}\n", "import React from 'react'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { Category } from '../../types'\n\nexport const SplitTooltipDetails = ({\n classNamePrefix,\n category,\n}: {\n classNamePrefix: string\n category: Category\n}) => {\n if (!category.entries) {\n return\n }\n\n return (\n <span className={`${classNamePrefix}__split-tooltip`}>\n <ul>\n {category.entries.map((entry, idx) => (\n <li key={idx}>\n <span className={`${classNamePrefix}__split-tooltip__label`}>\n {entry.category.display_name}\n </span>\n <span className={`${classNamePrefix}__split-tooltip__value`}>\n ${formatMoney(entry.amount)}\n </span>\n </li>\n ))}\n </ul>\n </span>\n )\n}\n", "import React from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport Scissors from '../../icons/Scissors'\nimport { BankTransaction, CategorizationStatus } from '../../types'\nimport { Badge } from '../Badge'\nimport { extractDescriptionForSplit } from '../BankTransactionRow/BankTransactionRow'\nimport { MatchBadge } from '../BankTransactionRow/MatchBadge'\nimport { SplitTooltipDetails } from '../BankTransactionRow/SplitTooltipDetails'\nimport { Text } from '../Typography'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface AssignmentProps {\n bankTransaction: BankTransaction\n}\n\nexport const Assignment = ({ bankTransaction }: AssignmentProps) => {\n if (\n bankTransaction.match &&\n bankTransaction.categorization_status === CategorizationStatus.MATCHED\n ) {\n return (\n <>\n <MatchBadge\n classNamePrefix='Layer__bank-transaction-list-item'\n bankTransaction={bankTransaction}\n dateFormat={DATE_FORMAT}\n text='Matched'\n />\n <Text className='Layer__bank-transaction-list-item__category-text__text'>\n {`${formatTime(\n parseISO(bankTransaction.match.bank_transaction.date),\n DATE_FORMAT,\n )}, ${bankTransaction.match.bank_transaction.description ?? bankTransaction.match?.details?.description}`}\n </Text>\n </>\n )\n }\n\n if (bankTransaction.categorization_status === CategorizationStatus.SPLIT) {\n return (\n <>\n <Badge\n icon={<Scissors size={11} />}\n tooltip={\n <SplitTooltipDetails\n classNamePrefix='Layer__bank-transaction-list-item'\n category={bankTransaction.category}\n />\n }\n >\n Split\n </Badge>\n <Text className='Layer__bank-transaction-list-item__category-text__text'>\n {extractDescriptionForSplit(bankTransaction.category)}\n </Text>\n </>\n )\n }\n\n return <Text>{bankTransaction?.category?.display_name}</Text>\n}\n", "import React from 'react'\nimport { BankTransaction } from '../../types'\nimport { BankTransactionsMode } from '../BankTransactions/BankTransactions'\nimport { BankTransactionMobileListItem } from './BankTransactionMobileListItem'\nimport {\n useTransactionToOpen,\n TransactionToOpenContext,\n} from './TransactionToOpenContext'\n\nexport interface BankTransactionMobileListProps {\n bankTransactions?: BankTransaction[]\n editable: boolean\n removeTransaction: (bt: BankTransaction) => void\n initialLoad?: boolean\n mode: BankTransactionsMode\n}\n\nexport const BankTransactionMobileList = ({\n bankTransactions,\n removeTransaction,\n editable,\n initialLoad,\n mode,\n}: BankTransactionMobileListProps) => {\n const transactionToOpenContextData = useTransactionToOpen()\n\n return (\n <TransactionToOpenContext.Provider value={transactionToOpenContextData}>\n <ul className='Layer__bank-transactions__mobile-list'>\n {bankTransactions?.map(\n (bankTransaction: BankTransaction, index: number) => (\n <BankTransactionMobileListItem\n index={index}\n mode={mode}\n key={bankTransaction.id}\n bankTransaction={bankTransaction}\n editable={editable}\n removeTransaction={removeTransaction}\n initialLoad={initialLoad}\n isFirstItem={index == 0}\n />\n ),\n )}\n </ul>\n </TransactionToOpenContext.Provider>\n )\n}\n", "import React, { useContext, useEffect, useRef, useState } from 'react'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { BankTransaction, CategorizationStatus } from '../../types'\nimport { hasMatch, isCredit } from '../../utils/bankTransactions'\nimport { extractDescriptionForSplit } from '../BankTransactionRow/BankTransactionRow'\nimport {\n BankTransactionsMode,\n categorizationEnabled,\n} from '../BankTransactions/BankTransactions'\nimport { isCategorized } from '../BankTransactions/utils'\nimport { CloseButton } from '../Button'\nimport { Toggle } from '../Toggle'\nimport { ToggleSize } from '../Toggle/Toggle'\nimport { Text } from '../Typography'\nimport { BankTransactionMobileForms } from './BankTransactionMobileForms'\nimport { TransactionToOpenContext } from './TransactionToOpenContext'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface BankTransactionMobileListItemProps {\n index: number\n bankTransaction: BankTransaction\n editable: boolean\n removeTransaction: (bt: BankTransaction) => void\n initialLoad?: boolean\n mode: BankTransactionsMode\n isFirstItem?: boolean\n}\n\nexport enum Purpose {\n business = 'business',\n personal = 'personal',\n more = 'more',\n}\n\nconst DATE_FORMAT = 'LLL d'\n\nconst getAssignedValue = (bankTransaction: BankTransaction) => {\n if (bankTransaction.categorization_status === CategorizationStatus.SPLIT) {\n return extractDescriptionForSplit(bankTransaction.category)\n }\n\n if (bankTransaction.categorization_status === CategorizationStatus.MATCHED) {\n return bankTransaction.match?.details?.description\n }\n\n return bankTransaction.category?.display_name\n}\n\nexport const BankTransactionMobileListItem = ({\n index = 0,\n bankTransaction,\n removeTransaction,\n editable,\n mode,\n initialLoad,\n isFirstItem = false,\n}: BankTransactionMobileListItemProps) => {\n const {\n transactionIdToOpen,\n setTransactionIdToOpen,\n clearTransactionIdToOpen,\n } = useContext(TransactionToOpenContext)\n const formRowRef = useElementSize<HTMLDivElement>((_a, _b, { height }) =>\n setHeight(height),\n )\n const headingRowRef = useElementSize<HTMLDivElement>((_a, _b, { height }) => {\n setHeadingHeight(height)\n })\n const itemRef = useRef<HTMLLIElement>(null)\n\n const [removeAnim, setRemoveAnim] = useState(false)\n const [purpose, setPurpose] = useState<Purpose>(\n bankTransaction.category\n ? bankTransaction.categorization_status === CategorizationStatus.SPLIT\n ? Purpose.more\n : Purpose.business\n : hasMatch(bankTransaction)\n ? Purpose.more\n : Purpose.business,\n )\n const [open, setOpen] = useState(isFirstItem)\n const [showComponent, setShowComponent] = useState(!initialLoad)\n const [height, setHeight] = useState(0)\n const [headingHeight, setHeadingHeight] = useState(63)\n\n const openNext = () => {\n if (editable && itemRef.current && itemRef.current.nextSibling) {\n const txId = (itemRef.current.nextSibling as HTMLLIElement).getAttribute(\n 'data-item',\n )\n\n if (txId) {\n setTransactionIdToOpen(txId)\n }\n }\n }\n\n useEffect(() => {\n if (transactionIdToOpen && transactionIdToOpen === bankTransaction.id) {\n setOpen(true)\n clearTransactionIdToOpen()\n }\n }, [transactionIdToOpen])\n\n useEffect(() => {\n if (!removeAnim && bankTransaction.recently_categorized) {\n if (editable) {\n setRemoveAnim(true)\n openNext()\n } else {\n close()\n }\n }\n }, [\n bankTransaction.recently_categorized,\n bankTransaction.category,\n bankTransaction.match,\n ])\n\n const toggleOpen = () => {\n if (open) {\n setHeight(0)\n }\n setOpen(!open)\n }\n\n const close = () => {\n setOpen(false)\n setHeight(0)\n }\n\n useEffect(() => {\n if (initialLoad) {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, index * 20)\n\n return () => clearTimeout(timeoutId)\n } else {\n setShowComponent(true)\n }\n }, [])\n\n useEffect(() => {\n if (editable && bankTransaction.recently_categorized) {\n setTimeout(() => {\n removeTransaction(bankTransaction)\n }, 300)\n }\n }, [bankTransaction.recently_categorized])\n\n const onChangePurpose = (event: React.ChangeEvent<HTMLInputElement>) =>\n setPurpose(event.target.value as Purpose)\n\n const categorized = isCategorized(bankTransaction)\n\n const className = 'Layer__bank-transaction-mobile-list-item'\n const openClassName = open ? `${className}--expanded` : ''\n const rowClassName = classNames(\n className,\n removeAnim ? 'Layer__bank-transaction-row--removing' : '',\n open ? openClassName : '',\n showComponent ? 'show' : '',\n )\n\n return (\n <li ref={itemRef} className={rowClassName} data-item={bankTransaction.id}>\n <span\n className={`${className}__heading`}\n onClick={toggleOpen}\n role='button'\n style={{ height: headingHeight }}\n >\n <div className={`${className}__heading__content`} ref={headingRowRef}>\n <div className={`${className}__heading__main`}>\n <Text as='span' className={`${className}__heading__tx-name`}>\n {bankTransaction.counterparty_name ?? bankTransaction.description}\n </Text>\n <Text as='span' className={`${className}__heading__account-name`}>\n {categorized && bankTransaction.categorization_status\n ? getAssignedValue(bankTransaction)\n : null}\n {!categorized && bankTransaction.account_name}\n </Text>\n {categorized && open && (\n <Text as='span' className={`${className}__categorized-name`}>\n {bankTransaction.account_name}\n </Text>\n )}\n </div>\n <div className={`${className}__heading__amount`}>\n <span\n className={`${className}__amount-${\n isCredit(bankTransaction) ? 'credit' : 'debit'\n }`}\n >\n {isCredit(bankTransaction) ? '+$' : ' $'}\n {formatMoney(bankTransaction.amount)}\n </span>\n <span className={`${className}__heading__date`}>\n {formatTime(parseISO(bankTransaction.date), DATE_FORMAT)}\n </span>\n </div>\n </div>\n </span>\n {categorizationEnabled(mode) ? (\n <div\n className={`${className}__expanded-row`}\n style={{ height: !open || removeAnim ? 0 : height }}\n >\n {open && (\n <div\n className={`${className}__expanded-row__content`}\n ref={formRowRef}\n >\n <div className={`${className}__toggle-row`}>\n <Toggle\n name={`purpose-${bankTransaction.id}`}\n size={ToggleSize.xsmall}\n options={[\n {\n value: 'business',\n label: 'Business',\n style: { minWidth: 84 },\n disabled: !categorizationEnabled(mode),\n },\n {\n value: 'personal',\n label: 'Personal',\n style: { minWidth: 84 },\n disabled: !categorizationEnabled(mode),\n },\n {\n value: 'more',\n label: 'More',\n style: { minWidth: 84 },\n disabled: !categorizationEnabled(mode),\n },\n ]}\n selected={purpose}\n onChange={onChangePurpose}\n />\n <CloseButton onClick={() => close()} />\n </div>\n <BankTransactionMobileForms\n purpose={purpose}\n bankTransaction={bankTransaction}\n />\n </div>\n )}\n </div>\n ) : (\n <></>\n )}\n </li>\n )\n}\n", "import React from 'react'\nimport { BankTransaction } from '../../types'\nimport { Purpose } from './BankTransactionMobileListItem'\nimport { BusinessForm } from './BusinessForm'\nimport { PersonalForm } from './PersonalForm'\nimport { SplitAndMatchForm } from './SplitAndMatchForm'\n\ninterface BankTransactionMobileFormsProps {\n purpose: Purpose\n bankTransaction: BankTransaction\n}\n\nexport const BankTransactionMobileForms = ({\n purpose,\n bankTransaction,\n}: BankTransactionMobileFormsProps) => {\n const getContent = () => {\n switch (purpose) {\n case 'business':\n return <BusinessForm bankTransaction={bankTransaction} />\n case 'personal':\n return <PersonalForm bankTransaction={bankTransaction} />\n case 'more':\n return <SplitAndMatchForm bankTransaction={bankTransaction} />\n default:\n return null\n }\n }\n\n return (\n <div className='Layer__bank-transaction-mobile-list-item__form-container'>\n {getContent()}\n </div>\n )\n}\n", "import React, { useContext, useEffect, useMemo, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { DrawerContext } from '../../contexts/DrawerContext'\nimport { BankTransaction, CategorizationType } from '../../types'\nimport { ActionableList } from '../ActionableList'\nimport { Button, ButtonVariant } from '../Button'\nimport { ErrorText } from '../Typography'\nimport { BusinessCategories } from './BusinessCategories'\nimport { Option, mapCategoryToOption, getAssignedValue } from './utils'\n\ninterface BusinessFormProps {\n bankTransaction: BankTransaction\n}\n\nexport const BusinessForm = ({ bankTransaction }: BusinessFormProps) => {\n const { setContent, close } = useContext(DrawerContext)\n const { categorize: categorizeBankTransaction, isLoading } =\n useBankTransactionsContext()\n const [selectedCategory, setSelectedCategory] = useState<Option | undefined>(\n getAssignedValue(bankTransaction),\n )\n const [showRetry, setShowRetry] = useState(false)\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n }\n }, [bankTransaction.error])\n\n const options = useMemo(() => {\n const options =\n bankTransaction?.categorization_flow?.type ===\n CategorizationType.ASK_FROM_SUGGESTIONS\n ? bankTransaction.categorization_flow.suggestions.map(x =>\n mapCategoryToOption(x),\n )\n : []\n\n if (selectedCategory && !options.find(x => x.id === selectedCategory?.id)) {\n options.unshift(selectedCategory)\n }\n\n if (options.length) {\n options.push({\n label: 'All categories',\n id: 'SELECT_CATEGORY',\n value: {\n type: 'SELECT_CATEGORY',\n },\n secondary: true,\n asLink: true,\n })\n }\n\n return options\n }, [bankTransaction, selectedCategory])\n\n const onDrawerCategorySelect = (value: Option) => {\n close()\n setSelectedCategory(value)\n }\n\n const openDrawer = () => {\n setContent(<BusinessCategories select={onDrawerCategorySelect} />)\n }\n\n const onCategorySelect = (category: Option) => {\n if (category.value.type === 'SELECT_CATEGORY') {\n openDrawer()\n } else {\n if (\n selectedCategory &&\n category.value.payload?.id === selectedCategory.value.payload?.id\n ) {\n setSelectedCategory(undefined)\n } else {\n setSelectedCategory(category)\n }\n }\n }\n\n const save = () => {\n if (!selectedCategory || !selectedCategory.value.payload) {\n return\n }\n\n const payload = selectedCategory?.value?.payload?.id\n ? {\n type: 'AccountId' as 'AccountId',\n id: selectedCategory.value.payload.id,\n }\n : {\n type: 'StableName' as 'StableName',\n stable_name: selectedCategory.value.payload?.stable_name || '',\n }\n\n categorizeBankTransaction(\n bankTransaction.id,\n {\n type: 'Category',\n category: payload,\n },\n true,\n )\n }\n\n return (\n <div className='Layer__bank-transaction-mobile-list-item__business-form'>\n <ActionableList<Option['value']>\n options={options}\n onClick={onCategorySelect}\n selected={selectedCategory}\n />\n {options.length === 0 ? (\n <Button\n onClick={openDrawer}\n fullWidth={true}\n variant={ButtonVariant.secondary}\n >\n Select category\n </Button>\n ) : null}\n {options.length > 0 ? (\n <Button\n onClick={save}\n disabled={\n !selectedCategory || isLoading || bankTransaction.processing\n }\n fullWidth={true}\n >\n {isLoading || bankTransaction.processing ? 'Saving...' : 'Save'}\n </Button>\n ) : null}\n {bankTransaction.error && showRetry ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : null}\n </div>\n )\n}\n", "import React, { useEffect, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { BankTransaction, CategorizationStatus } from '../../types'\nimport { isCredit } from '../../utils/bankTransactions'\nimport { Button } from '../Button'\nimport { ErrorText } from '../Typography'\nimport { PersonalCategories } from './constants'\n\ninterface PersonalFormProps {\n bankTransaction: BankTransaction\n}\n\nconst isAlreadyAssigned = (bankTransaction: BankTransaction) => {\n if (\n bankTransaction.categorization_status === CategorizationStatus.MATCHED ||\n bankTransaction?.categorization_status === CategorizationStatus.SPLIT\n ) {\n return false\n }\n\n return Boolean(\n bankTransaction.category &&\n PersonalCategories.includes(bankTransaction.category.display_name),\n )\n}\n\nexport const PersonalForm = ({ bankTransaction }: PersonalFormProps) => {\n const { categorize: categorizeBankTransaction, isLoading } =\n useBankTransactionsContext()\n const [showRetry, setShowRetry] = useState(false)\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n }\n }, [bankTransaction.error])\n\n const save = () => {\n categorizeBankTransaction(\n bankTransaction.id,\n {\n type: 'Category',\n category: {\n type: 'StableName',\n stable_name: isCredit(bankTransaction)\n ? 'PERSONAL_INCOME'\n : 'PERSONAL_EXPENSES',\n },\n },\n true,\n )\n }\n\n const alreadyAssigned = isAlreadyAssigned(bankTransaction)\n\n return (\n <div className='Layer__bank-transaction-mobile-list-item__personal-form'>\n <Button\n fullWidth={true}\n disabled={alreadyAssigned || isLoading || bankTransaction.processing}\n onClick={save}\n >\n {isLoading || bankTransaction.processing\n ? 'Saving...'\n : alreadyAssigned\n ? 'Saved as Personal'\n : 'Categorize as Personal'}\n </Button>\n {bankTransaction.error && showRetry ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : null}\n </div>\n )\n}\n", "import React, { useState } from 'react'\nimport { BankTransaction } from '../../types'\nimport { hasMatch } from '../../utils/bankTransactions'\nimport { TextButton } from '../Button'\nimport { MatchForm } from './MatchForm'\nimport { SplitForm } from './SplitForm'\n\ninterface SplitAndMatchFormProps {\n bankTransaction: BankTransaction\n}\n\nenum Purpose {\n categorize = 'categorize',\n match = 'match',\n}\n\nexport const SplitAndMatchForm = ({\n bankTransaction,\n}: SplitAndMatchFormProps) => {\n const anyMatch = hasMatch(bankTransaction)\n const [formType, setFormType] = useState(\n bankTransaction.category\n ? Purpose.categorize\n : anyMatch\n ? Purpose.match\n : Purpose.categorize,\n )\n\n return (\n <div className='Layer__bank-transaction-mobile-list-item__split-and-match-form'>\n {formType === Purpose.categorize && (\n <SplitForm bankTransaction={bankTransaction} />\n )}\n {formType === Purpose.match && (\n <MatchForm bankTransaction={bankTransaction} />\n )}\n {anyMatch && formType === Purpose.match ? (\n <div className='Layer__bank-transaction-mobile-list-item__switch-form-btns'>\n <TextButton onClick={() => setFormType(Purpose.categorize)}>\n or split transaction\n </TextButton>\n </div>\n ) : null}\n {anyMatch && formType === Purpose.categorize ? (\n <div className='Layer__bank-transaction-mobile-list-item__switch-form-btns'>\n <TextButton onClick={() => setFormType(Purpose.match)}>\n or find match\n </TextButton>\n </div>\n ) : null}\n </div>\n )\n}\n", "import React, { useEffect, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport { BankTransaction } from '../../types'\nimport { isAlreadyMatched } from '../../utils/bankTransactions'\nimport { Button } from '../Button'\nimport { MatchFormMobile } from '../MatchForm'\nimport { ErrorText, Text, TextSize, TextWeight } from '../Typography'\n\nexport const MatchForm = ({\n bankTransaction,\n}: {\n bankTransaction: BankTransaction\n}) => {\n const { match: matchBankTransaction, isLoading } =\n useBankTransactionsContext()\n const [selectedMatchId, setSelectedMatchId] = useState<string | undefined>(\n isAlreadyMatched(bankTransaction) ??\n (bankTransaction.suggested_matches &&\n bankTransaction.suggested_matches?.length > 0\n ? bankTransaction.suggested_matches[0].id\n : undefined),\n )\n const [formError, setFormError] = useState<string | undefined>()\n const [showRetry, setShowRetry] = useState(false)\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n } else if (showRetry) {\n setShowRetry(false)\n }\n }, [bankTransaction.error])\n\n const onMatchSubmit = async (matchId: string) => {\n const foundMatch = bankTransaction.suggested_matches?.find(\n x => x.id === matchId,\n )\n if (!foundMatch) {\n return\n }\n\n await matchBankTransaction(bankTransaction.id, foundMatch.id, true)\n }\n\n const save = async () => {\n if (!selectedMatchId) {\n setFormError('Select an option to match the transaction')\n } else if (\n selectedMatchId &&\n selectedMatchId !== isAlreadyMatched(bankTransaction)\n ) {\n onMatchSubmit(selectedMatchId)\n }\n return\n }\n\n return (\n <div>\n <Text weight={TextWeight.bold} size={TextSize.sm}>\n Find match\n </Text>\n <MatchFormMobile\n classNamePrefix='Layer__bank-transaction-mobile-list-item'\n bankTransaction={bankTransaction}\n selectedMatchId={selectedMatchId}\n setSelectedMatchId={id => {\n setFormError(undefined)\n setSelectedMatchId(id)\n }}\n />\n <Button\n fullWidth={true}\n disabled={\n !selectedMatchId ||\n isLoading ||\n bankTransaction.processing ||\n selectedMatchId === isAlreadyMatched(bankTransaction)\n }\n onClick={save}\n >\n {isLoading || bankTransaction.processing\n ? 'Saving...'\n : 'Approve match'}\n </Button>\n {formError && <ErrorText>{formError}</ErrorText>}\n {bankTransaction.error && showRetry ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : null}\n </div>\n )\n}\n", "import React, { useEffect, useState } from 'react'\nimport { useBankTransactionsContext } from '../../contexts/BankTransactionsContext'\nimport Trash from '../../icons/Trash'\nimport {\n centsToDollars as formatMoney,\n dollarsToCents as parseMoney,\n} from '../../models/Money'\nimport { BankTransaction } from '../../types'\nimport {\n SingleCategoryUpdate,\n SplitCategoryUpdate,\n hasSuggestions,\n} from '../../types/categories'\nimport { getCategorizePayload } from '../../utils/bankTransactions'\nimport { Button, ButtonVariant, TextButton } from '../Button'\nimport { CategorySelect } from '../CategorySelect'\nimport {\n CategoryOption,\n mapCategoryToOption,\n} from '../CategorySelect/CategorySelect'\nimport { Input } from '../Input'\nimport { ErrorText, Text, TextSize, TextWeight } from '../Typography'\nimport classNames from 'classnames'\n\ntype Split = {\n amount: number\n inputValue: string\n category: CategoryOption | undefined\n}\n\ntype RowState = {\n splits: Split[]\n description: string\n file: unknown\n}\n\nexport const SplitForm = ({\n bankTransaction,\n}: {\n bankTransaction: BankTransaction\n}) => {\n const {\n categorize: categorizeBankTransaction,\n isLoading,\n error,\n } = useBankTransactionsContext()\n const defaultCategory =\n bankTransaction.category ||\n (hasSuggestions(bankTransaction.categorization_flow) &&\n bankTransaction.categorization_flow?.suggestions?.[0])\n\n const [rowState, updateRowState] = useState<RowState>({\n splits: bankTransaction.category?.entries\n ? bankTransaction.category?.entries.map(c => {\n return {\n amount: c.amount || 0,\n inputValue: formatMoney(c.amount),\n category: mapCategoryToOption(c.category),\n }\n })\n : [\n {\n amount: bankTransaction.amount,\n inputValue: formatMoney(bankTransaction.amount),\n category: defaultCategory\n ? mapCategoryToOption(defaultCategory)\n : undefined,\n },\n {\n amount: 0,\n inputValue: '0.00',\n category: defaultCategory\n ? mapCategoryToOption(defaultCategory)\n : undefined,\n },\n ],\n description: '',\n file: undefined,\n })\n const [formError, setFormError] = useState<string | undefined>()\n const [showRetry, setShowRetry] = useState(false)\n\n useEffect(() => {\n if (bankTransaction.error) {\n setShowRetry(true)\n }\n }, [bankTransaction.error])\n\n const removeSplit = (index: number) => {\n const newSplits = rowState.splits.filter((_v, idx) => idx !== index)\n const splitTotal = newSplits.reduce((sum, split, index) => {\n const amount = index === 0 ? 0 : split.amount\n return sum + amount\n }, 0)\n const remaining = bankTransaction.amount - splitTotal\n newSplits[0].amount = remaining\n newSplits[0].inputValue = formatMoney(remaining)\n\n updateRowState({\n ...rowState,\n splits: newSplits,\n })\n setFormError(undefined)\n }\n\n const updateAmounts =\n (rowNumber: number) => (event: React.ChangeEvent<HTMLInputElement>) => {\n const newAmount = parseMoney(event.target.value) || 0\n const newDisplaying = event.target.value\n const splitTotal = rowState.splits.reduce((sum, split, index) => {\n const amount =\n index === 0 ? 0 : index === rowNumber ? newAmount : split.amount\n return sum + amount\n }, 0)\n const remaining = bankTransaction.amount - splitTotal\n rowState.splits[rowNumber].amount = newAmount\n rowState.splits[rowNumber].inputValue = newDisplaying\n rowState.splits[0].amount = remaining\n rowState.splits[0].inputValue = formatMoney(remaining)\n updateRowState({ ...rowState })\n setFormError(undefined)\n }\n\n const onBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (event.target.value === '') {\n const [_, index] = event.target.name.split('-')\n rowState.splits[parseInt(index)].inputValue = '0.00'\n updateRowState({ ...rowState })\n setFormError(undefined)\n }\n }\n\n const changeCategory = (index: number, newValue: CategoryOption) => {\n rowState.splits[index].category = newValue\n updateRowState({ ...rowState })\n setFormError(undefined)\n }\n\n const addSplit = () => {\n updateRowState({\n ...rowState,\n splits: [\n ...rowState.splits,\n {\n amount: 0,\n inputValue: '0.00',\n category: defaultCategory\n ? mapCategoryToOption(defaultCategory)\n : undefined,\n },\n ],\n })\n setFormError(undefined)\n }\n\n const validateSplit = (splitData: RowState) => {\n let valid = true\n\n splitData.splits.forEach(split => {\n if (split.amount <= 0) {\n valid = false\n } else if (!split.category) {\n valid = false\n }\n })\n\n return valid\n }\n\n const save = async () => {\n if (!validateSplit(rowState)) {\n if (rowState.splits.length > 1) {\n setFormError(\n 'Use only positive amounts and select category for each entry',\n )\n } else {\n setFormError('Category is required')\n }\n return\n }\n\n await categorizeBankTransaction(\n bankTransaction.id,\n rowState.splits.length === 1 && rowState?.splits[0].category\n ? ({\n type: 'Category',\n category: getCategorizePayload(rowState?.splits[0].category),\n } as SingleCategoryUpdate)\n : ({\n type: 'Split',\n entries: rowState.splits.map(split => ({\n category: split.category\n ? getCategorizePayload(split.category)\n : '',\n amount: split.amount,\n })),\n } as SplitCategoryUpdate),\n true,\n )\n }\n\n return (\n <div>\n <Text weight={TextWeight.bold} size={TextSize.sm}>\n Split transaction\n </Text>\n <div className='Layer__bank-transactions__table-cell__header'>\n <Text size={TextSize.sm}>Category</Text>\n <Text size={TextSize.sm}>Amount</Text>\n </div>\n <div className='Layer__bank-transactions__splits-inputs'>\n {rowState.splits.map((split, index) => (\n <div\n className='Layer__bank-transactions__table-cell--split-entry'\n key={`split-${index}`}\n >\n <div className='Layer__bank-transactions__table-cell--split-entry__right-col'>\n <CategorySelect\n bankTransaction={bankTransaction}\n name={`category-${bankTransaction.id}`}\n value={split.category}\n onChange={value => changeCategory(index, value)}\n className='Layer__category-menu--full'\n disabled={bankTransaction.processing}\n excludeMatches\n asDrawer\n />\n </div>\n <Input\n type='text'\n name={`split-${index}`}\n className={classNames(\n 'Layer__split-amount-input',\n index === 0 && 'Layer__split-amount-input--first',\n )}\n disabled={index === 0}\n onChange={updateAmounts(index)}\n value={split.inputValue}\n onBlur={onBlur}\n isInvalid={split.amount < 0}\n errorMessage='Negative values are not allowed'\n inputMode='numeric'\n />\n {index > 0 && (\n <Button\n className='Layer__bank-transactions__table-cell--split-entry__merge-btn'\n onClick={() => removeSplit(index)}\n rightIcon={<Trash size={16} />}\n variant={ButtonVariant.secondary}\n iconOnly={true}\n />\n )}\n </div>\n ))}\n <TextButton\n onClick={addSplit}\n disabled={rowState.splits.length > 5 || isLoading}\n className='Layer__add-new-split'\n >\n Add new split\n </TextButton>\n </div>\n <Button\n fullWidth={true}\n onClick={save}\n disabled={isLoading || bankTransaction.processing}\n >\n {isLoading || bankTransaction.processing ? 'Saving...' : 'Save'}\n </Button>\n {formError && <ErrorText>{formError}</ErrorText>}\n {bankTransaction.error && showRetry ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : null}\n </div>\n )\n}\n", "import { createContext, useState } from 'react'\n\ntype UseTransactionToOpen = () => {\n transactionIdToOpen?: string\n setTransactionIdToOpen: (id: string) => void\n clearTransactionIdToOpen: () => void\n}\n\nexport const useTransactionToOpen: UseTransactionToOpen = () => {\n const [transactionIdToOpen, setTransactionIdToOpen] = useState<\n string | undefined\n >(undefined)\n\n const clearTransactionIdToOpen = () => setTransactionIdToOpen(undefined)\n\n return {\n transactionIdToOpen,\n setTransactionIdToOpen,\n clearTransactionIdToOpen,\n }\n}\n\nexport type TransactionToOpenContextType = ReturnType<\n typeof useTransactionToOpen\n>\nexport const TransactionToOpenContext =\n createContext<TransactionToOpenContextType>({\n transactionIdToOpen: undefined,\n setTransactionIdToOpen: () => undefined,\n clearTransactionIdToOpen: () => undefined,\n })\n", "import React from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport { BankTransaction } from '../../types'\nimport { BankTransactionRow } from '../BankTransactionRow'\nimport {\n BankTransactionsMode,\n BankTransactionsStringOverrides,\n} from '../BankTransactions/BankTransactions'\nimport { BankTransactionsLoader } from '../BankTransactionsLoader'\nimport { SyncingComponent } from '../SyncingComponent'\n\nexport interface BankTransactionsTableStringOverrides {\n dateColumnHeaderText?: string\n transactionColumnHeaderText?: string\n accountColumnHeaderText?: string\n amountColumnHeaderText?: string\n categorizeColumnHeaderText?: string\n categoryColumnHeaderText?: string\n}\n\ninterface BankTransactionsTableProps {\n bankTransactions?: BankTransaction[]\n editable: boolean\n categorizeView?: boolean\n mode: BankTransactionsMode\n isLoading?: boolean\n initialLoad?: boolean\n containerWidth: number\n removeTransaction: (bt: BankTransaction) => void\n showDescriptions?: boolean\n showReceiptUploads?: boolean\n stringOverrides?: BankTransactionsStringOverrides\n isSyncing?: boolean\n page?: number\n lastPage?: boolean\n onRefresh?: () => void\n}\n\nexport const BankTransactionsTable = ({\n categorizeView,\n editable,\n isLoading,\n bankTransactions,\n mode,\n initialLoad,\n containerWidth,\n removeTransaction,\n showDescriptions = false,\n showReceiptUploads = false,\n stringOverrides,\n isSyncing = false,\n page,\n lastPage,\n onRefresh,\n}: BankTransactionsTableProps) => {\n return (\n <table\n width='100%'\n className='Layer__table Layer__bank-transactions__table with-cell-separators'\n >\n <thead>\n <tr>\n <th className='Layer__table-header Layer__bank-transactions__date-col'>\n {stringOverrides?.transactionsTable?.dateColumnHeaderText || 'Date'}\n </th>\n <th className='Layer__table-header Layer__bank-transactions__tx-col'>\n {stringOverrides?.transactionsTable?.transactionColumnHeaderText ||\n 'Transaction'}\n </th>\n <th className='Layer__table-header Layer__bank-transactions__account-col'>\n {stringOverrides?.transactionsTable?.accountColumnHeaderText ||\n 'Account'}\n </th>\n <th className='Layer__table-header Layer__table-cell--amount Layer__table-cell__amount-col'>\n {stringOverrides?.transactionsTable?.amountColumnHeaderText ||\n 'Amount'}\n </th>\n {categorizeView && editable ? (\n <th className='Layer__table-header Layer__table-header--primary Layer__table-cell__category-col'>\n {stringOverrides?.transactionsTable?.categorizeColumnHeaderText ||\n 'Categorize'}\n </th>\n ) : (\n <th className='Layer__table-header Layer__table-cell__category-col'>\n {stringOverrides?.transactionsTable?.categoryColumnHeaderText ||\n 'Category'}\n </th>\n )}\n </tr>\n </thead>\n {isLoading && page && page === 1 ? (\n <BankTransactionsLoader isLoading={true} />\n ) : null}\n <tbody>\n {!isLoading &&\n bankTransactions?.map(\n (bankTransaction: BankTransaction, index: number) => (\n <BankTransactionRow\n initialLoad={initialLoad}\n index={index}\n editable={editable}\n mode={mode}\n key={bankTransaction.id}\n dateFormat={DATE_FORMAT}\n bankTransaction={bankTransaction}\n removeTransaction={removeTransaction}\n containerWidth={containerWidth}\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n stringOverrides={stringOverrides?.bankTransactionCTAs}\n />\n ),\n )}\n {isSyncing &&\n (lastPage ||\n ((!bankTransactions || bankTransactions.length === 0) &&\n page === 1)) ? (\n <tr>\n <td colSpan={3}>\n <SyncingComponent\n title='Syncing historical account data'\n onRefresh={() => onRefresh && onRefresh()}\n />\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n )\n}\n", "import React from 'react'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { BankTransaction } from '../../types'\nimport { IconButton, SubmitButton } from '../Button'\nimport { SubmitAction } from '../Button/SubmitButton'\nimport { CategorySelect } from '../CategorySelect'\nimport { SkeletonTableLoader } from '../SkeletonTableLoader'\n\nexport const BankTransactionsLoader = ({\n isLoading = true,\n}: {\n isLoading: boolean\n}) => {\n const inactiveBankTransactionsActions = (\n <div className='Layer__bank-transaction-row__actions-container Layer__bank-transaction-row__actions-disabled'>\n <CategorySelect\n name='category-bakn-transaction'\n bankTransaction={{} as BankTransaction}\n value={undefined}\n onChange={() => {}}\n disabled={true}\n />\n <SubmitButton\n onClick={() => {}}\n action={SubmitAction.UPDATE}\n className='Layer__bank-transaction__submit-btn'\n disabled={true}\n >\n Approve\n </SubmitButton>\n <IconButton\n disabled={true}\n onClick={() => {}}\n className='Layer__bank-transaction-row__expand-button'\n icon={\n <ChevronDownFill className='Layer__chevron Layer__chevron__down' />\n }\n />\n </div>\n )\n return (\n <SkeletonTableLoader\n rows={6}\n cols={\n isLoading\n ? [\n { colSpan: 4, trimLastXRows: 3 },\n { colSpan: 1, parts: 2 },\n ]\n : [\n { colSpan: 4 },\n { colSpan: 1, colComponent: inactiveBankTransactionsActions },\n ]\n }\n height={20}\n />\n )\n}\n", "import React from 'react'\nimport { SkeletonLoader } from '../SkeletonLoader'\n\ninterface SkeletonTableLoaderProps {\n rows: number\n cols: Array<{\n colSpan: number\n colComponent?: React.ReactNode\n trimLastXRows?: number\n parts?: number\n }>\n height?: number\n width?: number\n}\n\nexport const SkeletonTableLoader = ({\n rows,\n cols,\n height = 20,\n width = 100,\n}: SkeletonTableLoaderProps) => {\n return (\n <tbody className={'Layer__skeleton-table-body__loader'}>\n {Array.from({ length: rows }).map((_, rowIndex) => (\n <tr key={rowIndex}>\n {cols.map((col, colIndex) => {\n const trim: number =\n col.trimLastXRows && rowIndex >= col.trimLastXRows - 1\n ? (rowIndex - col.trimLastXRows + 1) * 10\n : 0\n return (\n <td\n key={colIndex}\n colSpan={col.colSpan}\n className='Layer__skeleton-loader__row'\n >\n {col.colComponent ? (\n col.colComponent\n ) : col.parts && col.parts > 1 ? (\n <span className='Layer__skeleton-loader__row__group'>\n {[...Array(col.parts)].map((_part, partIndex) => (\n <SkeletonLoader\n key={`part-${partIndex}`}\n width='100%'\n height={`${height}px`}\n />\n ))}\n </span>\n ) : (\n <SkeletonLoader\n width={`${width - trim}%`}\n height={`${height}px`}\n />\n )}\n </td>\n )\n })}\n </tr>\n ))}\n </tbody>\n )\n}\n", "import React from 'react'\nimport classNames from 'classnames'\n\nexport interface SkeletonLoaderProps {\n width?: string\n height?: string\n className?: string\n}\n\nexport const SkeletonLoader = ({\n height,\n width,\n className,\n}: SkeletonLoaderProps) => {\n const baseClassName = classNames(\n 'Layer__skeleton-loader Layer__anim--skeleton-loading',\n className,\n )\n return <div className={baseClassName} style={{ width, height }} />\n}\n", "import React from 'react'\nimport RefreshCcw from '../../icons/RefreshCcw'\nimport { IconButton } from '../Button'\nimport { SmallLoader } from '../Loader'\nimport classNames from 'classnames'\n\ninterface SyncingComponentProps {\n title?: string\n message?: string\n onRefresh?: () => void\n timeSync?: number\n inProgress?: boolean\n hideContent?: boolean\n}\n\n/**\n * SyncingComponent\n * @param title - Title of the component\n * @param message - Message of the component\n * @param onRefresh - Function to refresh the component\n * @param timeSync - Time to sync in minutes\n * @param inProgress - Show progress icon besides button\n * @param hideContent - Hide content of the component\n *\n * @example\n * <SyncingComponent\n * title='Syncing account data'\n * message='This may take up to'\n * onRefresh={() => console.log('refresh')}\n * timeSync={1440}\n * inProgress={false}\n * hideContent={false}\n * />\n */\nexport const SyncingComponent = ({\n title = 'Syncing account data',\n message = 'This may take up to',\n onRefresh,\n inProgress = false,\n timeSync = 1440,\n hideContent = false,\n}: SyncingComponentProps) => {\n const handleRefresh = () => {\n onRefresh && onRefresh()\n }\n\n const timeSyncInfo = () => {\n if (timeSync > 60) {\n return `${Math.floor(timeSync / 60)} hours`\n }\n return `${timeSync} minutes`\n }\n\n return (\n <div\n className={classNames(\n 'Layer__syncing-component',\n inProgress ? 'Layer__syncing-component--with-border' : '',\n )}\n >\n <div className='Layer__syncing-component__actions'>\n {inProgress ? (\n <SmallLoader />\n ) : (\n <IconButton icon={<RefreshCcw />} onClick={handleRefresh} />\n )}\n </div>\n {!hideContent && (\n <div className='Layer__syncing-component__content'>\n <div className='Layer__syncing-component__title'>{title}</div>\n <div className='Layer__syncing-component__message'>{`${message} ${timeSyncInfo()}`}</div>\n </div>\n )}\n </div>\n )\n}\n", "import React, { ErrorInfo, Component } from 'react'\nimport { LayerError, reportError } from '../../models/ErrorHandler'\nimport { ErrorBoundaryMessage } from './ErrorBoundaryMessage'\n\ninterface ErrorBoundaryProps {\n onError?: (error: Error) => void\n}\n\ninterface ErrorBoundaryState {\n hasError?: boolean\n}\n\nexport class ErrorBoundary extends Component<\n React.PropsWithChildren<ErrorBoundaryProps>,\n ErrorBoundaryState\n> {\n onError: (err: LayerError) => void\n\n constructor(props: any) {\n super(props)\n this.onError = props.onError\n this.state = { hasError: false }\n }\n\n static getDerivedStateFromError(_error: Error) {\n // Update state so the next render will show the fallback UI.\n return { hasError: true }\n }\n\n componentDidCatch(error: Error, _info: ErrorInfo) {\n if (this.onError) {\n this.onError({ type: 'render', payload: error })\n } else {\n reportError({ type: 'render', payload: error })\n }\n }\n\n render() {\n if (this.state.hasError) {\n return <ErrorBoundaryMessage />\n }\n return (this.props as { children: any }).children\n }\n}\n", "import React from 'react'\nimport { DataState, DataStateStatus } from '../DataState'\n\nexport const ErrorBoundaryMessage = () => {\n return (\n <div className='Layer__component Layer__component-container Layer__error-boundary'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='Try to refresh the page.'\n />\n </div>\n )\n}\n", "import React from 'react'\nimport { usePagination, DOTS } from '../../hooks/usePagination'\nimport ChevronLeft from '../../icons/ChevronLeft'\nimport ChevronRight from '../../icons/ChevronRight'\nimport classnames from 'classnames'\n\nexport interface PaginationProps {\n currentPage: number\n pageSize: number\n onPageChange: (page: number) => void\n totalCount: number\n siblingCount?: number\n hasMore?: boolean\n fetchMore?: () => void\n}\n\nexport const Pagination = ({\n onPageChange,\n totalCount,\n siblingCount = 1,\n currentPage,\n pageSize,\n hasMore,\n fetchMore\n}: PaginationProps) => {\n const paginationRange = usePagination({\n currentPage,\n totalCount,\n siblingCount,\n pageSize,\n })\n\n if (!paginationRange) {\n return\n }\n\n if (currentPage === 0 || paginationRange.length < 2) {\n return\n }\n\n let lastPage = paginationRange[paginationRange.length - 1]\n\n return (\n <ul className='Layer__pagination'>\n <li\n key={`page-prev`}\n className={classnames(\n 'Layer__pagination-item Layer__pagination-arrow Layer__pagination-arrow--previous',\n {\n disabled: currentPage === 1,\n },\n )}\n onClick={() => onPageChange(currentPage - 1)}\n >\n <ChevronLeft size={12} />\n </li>\n {paginationRange.map((pageNumber, idx) => {\n if (pageNumber === DOTS) {\n return (\n <li\n key={`${idx}-page-${pageNumber}`}\n className='Layer__pagination-item Layer__pagination-dots'\n >\n …\n </li>\n )\n }\n\n return (\n <li\n key={`page-${pageNumber}`}\n className={classnames('Layer__pagination-item', {\n selected: pageNumber === currentPage,\n })}\n onClick={() => {\n if (typeof pageNumber === 'number') {\n onPageChange(pageNumber)\n if (pageNumber === lastPage && hasMore && fetchMore) {\n fetchMore()\n }\n }\n }}\n >\n {pageNumber}\n </li>\n )\n })}\n {hasMore && fetchMore ?(\n <li\n key={`page-has-more`}\n className='Layer__pagination-item Layer__pagination-arrow Layer__pagination-arrow--next'\n onClick={fetchMore}\n >\n ...\n </li>\n ) : null}\n <li\n key={`page-last`}\n className={classnames(\n 'Layer__pagination-item Layer__pagination-arrow Layer__pagination-arrow--next',\n {\n disabled: currentPage === lastPage,\n },\n )}\n onClick={() => onPageChange(currentPage + 1)}\n >\n <ChevronRight size={12} />\n </li>\n </ul>\n )\n}\n", "import { useMemo } from 'react'\nimport { range } from '../../utils/helpers'\n\nexport const DOTS = '...'\n\nexport interface UsePaginationProps {\n totalCount: number\n pageSize: number\n siblingCount?: number\n currentPage: number\n}\n\nexport type UsePaginationReturn = (string | number)[] | undefined\n\nexport const usePagination = ({\n totalCount,\n pageSize,\n siblingCount = 1,\n currentPage,\n}: UsePaginationProps): UsePaginationReturn => {\n const paginationRange = useMemo(() => {\n const totalPageCount = Math.ceil(totalCount / pageSize)\n const totalPageNumbers = siblingCount + 5\n\n if (totalPageNumbers >= totalPageCount) {\n return range(1, totalPageCount)\n }\n\n const leftSiblingIndex = Math.max(currentPage - siblingCount, 1)\n const rightSiblingIndex = Math.min(\n currentPage + siblingCount,\n totalPageCount,\n )\n const shouldShowLeftDots = leftSiblingIndex > 2\n const shouldShowRightDots = rightSiblingIndex < totalPageCount - 2\n\n const firstPageIndex = 1\n const lastPageIndex = totalPageCount\n\n if (!shouldShowLeftDots && shouldShowRightDots) {\n let leftItemCount = 3 + 2 * siblingCount\n let leftRange = range(1, leftItemCount)\n\n return [...leftRange, DOTS, totalPageCount]\n }\n\n if (shouldShowLeftDots && !shouldShowRightDots) {\n let rightItemCount = 3 + 2 * siblingCount\n let rightRange = range(\n totalPageCount - rightItemCount + 1,\n totalPageCount,\n )\n return [firstPageIndex, DOTS, ...rightRange]\n }\n\n if (shouldShowLeftDots && shouldShowRightDots) {\n let middleRange = range(leftSiblingIndex, rightSiblingIndex)\n return [firstPageIndex, DOTS, ...middleRange, DOTS, lastPageIndex]\n }\n }, [totalCount, pageSize, siblingCount, currentPage])\n\n return paginationRange\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ChevronLeft = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n width='18'\n height='18'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n >\n <path\n d='M11.25 13.5L6.75 9L11.25 4.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\nexport default ChevronLeft\n", "import React, { ChangeEvent, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport DownloadCloud from '../../icons/DownloadCloud'\nimport { DateRange, DisplayState } from '../../types'\nimport { getEarliestDateToBrowse } from '../../utils/business'\nimport { Button, ButtonVariant, RetryButton } from '../Button'\nimport { Header } from '../Container'\nimport { DatePicker } from '../DatePicker'\nimport { SyncingComponent } from '../SyncingComponent'\nimport { Tabs } from '../Tabs'\nimport { Toggle } from '../Toggle'\nimport { ToggleSize } from '../Toggle/Toggle'\nimport { Heading, HeadingSize } from '../Typography'\nimport { MobileComponentType } from './constants'\nimport classNames from 'classnames'\nimport { endOfMonth, startOfMonth } from 'date-fns'\n\nexport interface BankTransactionsHeaderProps {\n shiftStickyHeader: number\n asWidget?: boolean\n categorizedOnly?: boolean\n categorizeView?: boolean\n display?: DisplayState\n onCategorizationDisplayChange: (event: ChangeEvent<HTMLInputElement>) => void\n mobileComponent?: MobileComponentType\n withDatePicker?: boolean\n listView?: boolean\n dateRange?: DateRange\n isDataLoading?: boolean\n isSyncing?: boolean\n setDateRange?: (value: DateRange) => void\n stringOverrides?: BankTransactionsHeaderStringOverrides\n}\n\nexport interface BankTransactionsHeaderStringOverrides {\n header?: string\n downloadButton?: string\n}\n\nconst DownloadButton = ({\n downloadButtonTextOverride,\n iconOnly,\n}: {\n downloadButtonTextOverride?: string\n iconOnly?: boolean\n}) => {\n const { auth, businessId, apiUrl } = useLayerContext()\n const [requestFailed, setRequestFailed] = useState(false)\n const [isDownloading, setIsDownloading] = useState(false)\n const handleClick = async () => {\n setIsDownloading(true)\n const currentYear = new Date().getFullYear().toString()\n const getBankTransactionsCsv = Layer.getBankTransactionsCsv(\n apiUrl,\n auth.access_token,\n {\n params: {\n businessId: businessId,\n year: currentYear,\n },\n },\n )\n try {\n const result = await getBankTransactionsCsv()\n if (result?.data?.presignedUrl) {\n window.location.href = result.data.presignedUrl\n setRequestFailed(false)\n } else {\n setRequestFailed(true)\n }\n } catch (e) {\n setRequestFailed(true)\n } finally {\n setIsDownloading(false)\n }\n }\n\n return requestFailed ? (\n <RetryButton\n onClick={handleClick}\n className='Layer__download-retry-btn'\n error={'Approval failed. Check connection and retry in few seconds.'}\n disabled={isDownloading}\n iconOnly={iconOnly}\n >\n Retry\n </RetryButton>\n ) : (\n <Button\n variant={ButtonVariant.secondary}\n rightIcon={<DownloadCloud size={12} />}\n onClick={handleClick}\n disabled={isDownloading}\n iconAsPrimary={iconOnly}\n iconOnly={iconOnly}\n >\n {downloadButtonTextOverride || 'Download'}\n </Button>\n )\n}\n\nexport const BankTransactionsHeader = ({\n shiftStickyHeader,\n asWidget,\n categorizedOnly,\n categorizeView = true,\n display,\n onCategorizationDisplayChange,\n mobileComponent,\n withDatePicker,\n listView,\n dateRange,\n setDateRange,\n stringOverrides,\n isSyncing,\n}: BankTransactionsHeaderProps) => {\n const { business } = useLayerContext()\n\n return (\n <Header\n className={classNames(\n 'Layer__bank-transactions__header',\n withDatePicker && 'Layer__bank-transactions__header--with-date-picker',\n mobileComponent && listView\n ? 'Layer__bank-transactions__header--mobile'\n : undefined,\n )}\n style={{ top: shiftStickyHeader }}\n >\n <div className='Layer__bank-transactions__header__content'>\n <div className='Layer__bank-transactions__header__content-title'>\n <Heading\n className='Layer__bank-transactions__title'\n size={asWidget ? HeadingSize.secondary : HeadingSize.secondary}\n >\n {stringOverrides?.header || 'Transactions'}\n </Heading>\n {isSyncing && (\n <SyncingComponent\n timeSync={5}\n inProgress={true}\n hideContent={listView}\n />\n )}\n </div>\n {withDatePicker && dateRange && setDateRange ? (\n <DatePicker\n mode='monthPicker'\n selected={dateRange.startDate}\n onChange={date => {\n if (!Array.isArray(date)) {\n setDateRange({\n startDate: startOfMonth(date),\n endDate: endOfMonth(date),\n })\n }\n }}\n minDate={getEarliestDateToBrowse(business)}\n />\n ) : null}\n </div>\n <div className='Layer__header__actions-wrapper'>\n <div className='Layer__header__actions Layer__justify--space-between'>\n {!categorizedOnly && categorizeView && (\n <Toggle\n name='bank-transaction-display'\n size={\n mobileComponent === 'mobileList'\n ? ToggleSize.small\n : ToggleSize.medium\n }\n options={[\n { label: 'To Review', value: DisplayState.review },\n { label: 'Categorized', value: DisplayState.categorized },\n ]}\n selected={display}\n onChange={onCategorizationDisplayChange}\n />\n )}\n\n <DownloadButton\n downloadButtonTextOverride={stringOverrides?.downloadButton}\n iconOnly={listView}\n />\n </div>\n </div>\n </Header>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst DownloadCloud = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M6 12.75L9 15.75L12 12.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 9V15.75'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M15.66 13.5675C16.3121 13.109 16.801 12.4546 17.056 11.6994C17.3109 10.9441 17.3186 10.1273 17.0778 9.36737C16.837 8.60748 16.3604 7.94407 15.7171 7.47342C15.0737 7.00278 14.2971 6.74938 13.5 6.75H12.555C12.3294 5.87091 11.9074 5.05444 11.3206 4.36206C10.7338 3.66969 9.99762 3.11945 9.16742 2.75277C8.33721 2.38609 7.43464 2.21252 6.52766 2.24514C5.62067 2.27776 4.7329 2.51571 3.93118 2.94107C3.12946 3.36644 2.43468 3.96814 1.89915 4.70087C1.36362 5.43361 1.0013 6.27829 0.839456 7.17132C0.677613 8.06434 0.720468 8.98245 0.964796 9.85652C1.20912 10.7306 1.64856 11.5378 2.25001 12.2175'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\nexport default DownloadCloud\n", "import { Business } from '../types'\nimport { differenceInCalendarMonths, parseISO, startOfMonth } from 'date-fns'\n\nexport const getActivationDate = (business?: Business) => {\n try {\n if (business && business.activation_at) {\n return parseISO(business.activation_at)\n }\n\n return\n } catch (_err) {\n return\n }\n}\n\nexport const getEarliestDateToBrowse = (business?: Business) => {\n const activationDate = getActivationDate(business)\n\n if (activationDate) {\n return startOfMonth(activationDate)\n }\n\n return\n}\n\nexport const isDateAllowedToBrowse = (date: Date, business?: Business) => {\n if (!business || !date) {\n return true\n }\n\n const activationDate = getEarliestDateToBrowse(business)\n\n if (!activationDate) {\n return true\n }\n\n return differenceInCalendarMonths(startOfMonth(date), activationDate) >= 0\n}\n", "import React, { useEffect, useRef, useState } from 'react'\nimport ReactDatePicker from 'react-datepicker'\nimport { BREAKPOINTS } from '../../config/general'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { useSizeClass } from '../../hooks/useWindowSize'\nimport ChevronLeft from '../../icons/ChevronLeft'\nimport ChevronRight from '../../icons/ChevronRight'\nimport { Button, ButtonVariant } from '../Button'\nimport { DatePickerOptions } from './DatePickerOptions'\nimport classNames from 'classnames'\n\ninterface DatePickerProps {\n mode:\n | 'dayPicker'\n | 'dayRangePicker'\n | 'monthPicker'\n | 'monthRangePicker'\n | 'timePicker'\n selected: Date | [Date | null, Date | null]\n onChange: (date: Date | [Date, Date | null]) => void\n dateFormat?: string\n timeIntervals?: number\n timeCaption?: string\n placeholderText?: string\n options?: string[]\n wrapperClassName?: string\n calendarClassName?: string\n popperClassName?: string\n currentDateOption?: boolean\n minDate?: Date\n maxDate?: Date\n navigateArrows?: boolean\n}\n\nconst getDefaultRangeDate = (\n date: 'start' | 'end',\n mode: DatePickerProps['mode'],\n selected: Date | [Date | null, Date | null],\n) => {\n try {\n if (isRangeMode(mode) && selected) {\n if (date === 'end') {\n return (selected as [Date | null, Date | null])[1]\n }\n return (selected as [Date | null, Date | null])[0]\n }\n\n return null\n } catch (_err) {\n return null\n }\n}\n\nconst isRangeMode = (mode: DatePickerProps['mode']) =>\n mode === 'dayRangePicker' || mode === 'monthRangePicker'\n\nexport const DatePicker = ({\n selected,\n onChange,\n mode = 'dayPicker',\n dateFormat = mode === 'monthPicker' || mode === 'monthRangePicker'\n ? 'MMM, yyyy'\n : mode === 'timePicker'\n ? 'h:mm aa'\n : 'MMM d, yyyy',\n timeIntervals = 15,\n timeCaption,\n placeholderText,\n options = [],\n wrapperClassName,\n calendarClassName,\n popperClassName,\n minDate,\n maxDate = new Date(),\n currentDateOption = true,\n navigateArrows = mode === 'monthPicker',\n ...props\n}: DatePickerProps) => {\n const pickerRef = useRef<ReactDatePicker>(null)\n const [updatePickerDate, setPickerDate] = useState<boolean>(false)\n const [selectedDates, setSelectedDates] = useState<\n Date | [Date | null, Date | null] | null\n >(selected)\n\n const { isDesktop } = useSizeClass()\n\n const [startDate, setStartDate] = useState<Date | null>(\n getDefaultRangeDate('start', mode, selected) ?? new Date(),\n )\n const [endDate, setEndDate] = useState<Date | null>(\n getDefaultRangeDate('end', mode, selected),\n )\n\n useEffect(() => {\n try {\n setPickerDate(true)\n if (\n !isRangeMode(mode) &&\n (selected as Date | null)?.getTime() !==\n (selectedDates as Date | null)?.getTime()\n ) {\n setSelectedDates(selected)\n return\n }\n\n if (isRangeMode(mode) && Array.isArray(selected)) {\n if ((startDate as Date | null)?.getTime() !== selected[0]?.getTime()) {\n setStartDate(selected[0])\n }\n if ((endDate as Date | null)?.getTime() !== selected[1]?.getTime()) {\n setEndDate(selected[1])\n }\n }\n } catch (_err) {\n return\n }\n }, [selected])\n\n useEffect(() => {\n if (\n onChange &&\n (!isRangeMode(mode) || (isRangeMode(mode) && !updatePickerDate))\n ) {\n onChange(selectedDates as Date | [Date, Date])\n } else {\n setPickerDate(false)\n }\n }, [selectedDates])\n\n useEffect(() => {\n if (isRangeMode(mode)) {\n setSelectedDates([startDate, endDate])\n }\n }, [startDate, endDate])\n\n const wrapperClassNames = classNames(\n 'Layer__datepicker__wrapper',\n mode === 'timePicker' && 'Layer__datepicker__time__wrapper',\n navigateArrows && 'Layer__datepicker__wrapper--arrows',\n )\n\n const datePickerWrapperClassNames = classNames(\n 'Layer__datepicker',\n mode === 'timePicker' && 'Layer__datepicker__time',\n wrapperClassName,\n )\n const calendarClassNames = classNames(\n 'Layer__datepicker__calendar',\n calendarClassName,\n )\n const popperClassNames = classNames(\n 'Layer__datepicker__popper',\n mode === 'timePicker' && 'Layer__datepicker__time__popper',\n popperClassName,\n )\n\n const handleDateChange = (date: Date | [Date | null, Date | null]) => {\n if (isRangeMode(mode)) {\n const [start, end] = date as [Date | null, Date | null]\n setStartDate(start)\n setEndDate(end)\n return\n }\n\n setSelectedDates(date)\n }\n\n const isCurrentDate = () => {\n const currentDate = new Date()\n if (mode === 'dayPicker') {\n return (\n selectedDates instanceof Date &&\n selectedDates.toDateString() === currentDate.toDateString()\n )\n } else if (mode === 'monthPicker') {\n return (\n selectedDates instanceof Date &&\n selectedDates.getMonth() === currentDate.getMonth() &&\n selectedDates.getFullYear() === currentDate.getFullYear()\n )\n }\n return false\n }\n\n const setCurrentDate = () => {\n const currentDate = new Date()\n if (mode === 'dayPicker') {\n setSelectedDates(currentDate)\n } else if (mode === 'monthPicker') {\n setSelectedDates(\n new Date(currentDate.getFullYear(), currentDate.getMonth(), 1),\n )\n }\n }\n\n const isTodayOrAfter = Boolean(\n selectedDates instanceof Date && selectedDates >= new Date(),\n )\n\n const isBeforeMinDate = Boolean(\n minDate && selectedDates instanceof Date && selectedDates <= minDate,\n )\n\n const changeDate = (value: number) => {\n if (mode === 'dayPicker') {\n setSelectedDates(\n new Date(\n (selectedDates as Date).setDate(\n (selectedDates as Date).getDate() + value,\n ),\n ),\n )\n } else if (mode === 'monthPicker') {\n setSelectedDates(\n new Date(\n (selectedDates as Date).setMonth(\n (selectedDates as Date).getMonth() + value,\n ),\n ),\n )\n }\n }\n\n return (\n <div className={wrapperClassNames}>\n <ReactDatePicker\n ref={pickerRef}\n wrapperClassName={datePickerWrapperClassNames}\n startDate={isRangeMode(mode) ? startDate : undefined}\n endDate={isRangeMode(mode) ? endDate : undefined}\n selected={\n mode !== 'dayRangePicker' && mode !== 'monthRangePicker'\n ? (selectedDates as Date)\n : undefined\n }\n onChange={handleDateChange}\n calendarClassName={calendarClassNames}\n popperClassName={popperClassNames}\n enableTabLoop={false}\n popperPlacement='bottom-start'\n selectsRange={isRangeMode(mode)}\n showMonthYearPicker={\n mode === 'monthPicker' || mode === 'monthRangePicker'\n }\n dateFormat={dateFormat}\n renderDayContents={day => (\n <span className='Layer__datepicker__day-contents'>{day}</span>\n )}\n timeIntervals={timeIntervals}\n timeCaption={timeCaption}\n timeFormat='h mm aa'\n showTimeSelect={mode === 'timePicker'}\n showTimeSelectOnly={mode === 'timePicker'}\n minDate={minDate}\n maxDate={maxDate}\n withPortal={!isDesktop}\n onCalendarOpen={() => {\n if (!isDesktop) {\n setTimeout(() => {\n document\n .getElementById('Layer__datepicker__portal')\n ?.classList.remove('Layer__datepicker__portal--closed')\n document\n .getElementById('Layer__datepicker__portal')\n ?.classList.add('Layer__datepicker__portal--opened')\n }, 10)\n }\n }}\n onCalendarClose={() => {\n if (!isDesktop) {\n document\n .getElementById('Layer__datepicker__portal')\n ?.classList.add('Layer__datepicker__portal--closed')\n document\n .getElementById('Layer__datepicker__portal')\n ?.classList.remove('Layer__datepicker__portal--opened')\n }\n }}\n portalId='Layer__datepicker__portal'\n onFocus={e => (e.target.readOnly = true)}\n onInputClick={() => {\n if (pickerRef.current && !isDesktop) {\n pickerRef.current.setOpen(!pickerRef.current.isCalendarOpen)\n }\n }}\n {...props}\n >\n {mode === 'dayRangePicker' && (\n <DatePickerOptions\n options={options}\n setSelectedDate={setSelectedDates}\n />\n )}\n </ReactDatePicker>\n {navigateArrows && !isDesktop && (\n <>\n <Button\n aria-label='Previous Date'\n className={classNames(\n 'Layer__datepicker__prev-button',\n isBeforeMinDate && 'Layer__datepicker__button--disabled',\n )}\n onClick={() => changeDate(-1)}\n variant={ButtonVariant.secondary}\n disabled={isBeforeMinDate}\n >\n <ChevronLeft className='Layer__datepicker__button-icon' size={16} />\n </Button>\n <Button\n aria-label='Next Date'\n variant={ButtonVariant.secondary}\n className={classNames(\n 'Layer__datepicker__next-button',\n isTodayOrAfter\n ? 'Layer__datepicker__button--disabled'\n : undefined,\n )}\n onClick={() => changeDate(1)}\n disabled={isTodayOrAfter}\n >\n <ChevronRight\n className='Layer__datepicker__button-icon'\n size={16}\n />\n </Button>\n </>\n )}\n {currentDateOption &&\n (mode === 'dayPicker' || mode === 'monthPicker') && (\n <Button\n className='Layer__datepicker__current-button'\n onClick={setCurrentDate}\n variant={ButtonVariant.secondary}\n disabled={isCurrentDate()}\n >\n {mode === 'dayPicker' ? 'Today' : 'Current'}\n </Button>\n )}\n </div>\n )\n}\n", "import React from 'react'\nimport { TextButton } from '../Button'\nimport {\n endOfMonth,\n endOfQuarter,\n endOfYear,\n startOfMonth,\n startOfQuarter,\n startOfYear,\n subMonths,\n subQuarters,\n subYears,\n} from 'date-fns'\n\nexport const DatePickerOptions = ({\n options,\n setSelectedDate,\n}: {\n options: string[]\n setSelectedDate: (dates: [Date | null, Date | null]) => void\n}) => {\n let optionsComponents: React.ReactNode[] = []\n\n const getOptionComponent = (option: string) => {\n switch (option) {\n case 'this-month':\n return (\n <TextButton\n key={option}\n onClick={() => {\n setSelectedDate([\n startOfMonth(new Date()),\n endOfMonth(new Date()),\n ])\n }}\n >\n This month\n </TextButton>\n )\n case 'last-month':\n return (\n <TextButton\n key={option}\n onClick={() => {\n setSelectedDate([\n startOfMonth(subMonths(new Date(), 1)),\n endOfMonth(subMonths(new Date(), 1)),\n ])\n }}\n >\n Last month\n </TextButton>\n )\n case 'this-quarter':\n return (\n <TextButton\n key={option}\n onClick={() => {\n setSelectedDate([\n startOfQuarter(new Date()),\n endOfQuarter(new Date()),\n ])\n }}\n >\n This quarter\n </TextButton>\n )\n case 'last-quarter':\n return (\n <TextButton\n key={option}\n onClick={() => {\n const lastQuarter = subQuarters(new Date(), 1)\n setSelectedDate([\n startOfQuarter(lastQuarter),\n endOfQuarter(lastQuarter),\n ])\n }}\n >\n Last quarter\n </TextButton>\n )\n case 'this-year':\n return (\n <TextButton\n key={option}\n onClick={() => {\n setSelectedDate([startOfYear(new Date()), endOfYear(new Date())])\n }}\n >\n This year\n </TextButton>\n )\n case 'last-year':\n return (\n <TextButton\n key={option}\n onClick={() => {\n const lastYear = subYears(new Date(), 1)\n setSelectedDate([startOfYear(lastYear), endOfYear(lastYear)])\n }}\n >\n Last year\n </TextButton>\n )\n }\n return <></>\n }\n\n if (options.length === 0) {\n const allOptions = [\n 'this-month',\n 'last-month',\n 'this-quarter',\n 'last-quarter',\n 'this-year',\n 'last-year',\n ]\n allOptions.forEach(option => {\n optionsComponents.push(getOptionComponent(option))\n })\n } else {\n options.forEach(option => {\n optionsComponents.push(getOptionComponent(option))\n })\n }\n\n if (optionsComponents.length === 0) {\n return <></>\n }\n\n return (\n <div className='Layer__datepicker__popper__custom-footer'>\n {optionsComponents}\n </div>\n )\n}\n", "import React from 'react'\nimport InboxIcon from '../../icons/Inbox'\nimport { BankTransaction } from '../../types'\nimport { DataState, DataStateStatus } from '../DataState'\n\ninterface DataStatesProps {\n bankTransactions?: BankTransaction[]\n isLoading?: boolean\n isValidating?: boolean\n error?: unknown\n refetch: () => void\n editable: boolean\n}\n\nexport const DataStates = ({\n bankTransactions,\n isLoading,\n isValidating,\n error,\n refetch,\n editable,\n}: DataStatesProps) => {\n let title = editable\n ? 'You are up to date with transactions!'\n : 'You have no categorized transactions'\n let description = editable\n ? 'All uncategorized transaction will be displayed here'\n : 'All transaction will be displayed here once reviewed'\n\n const showRefreshButton = bankTransactions?.length\n\n return (\n <>\n {!isLoading &&\n !error &&\n (bankTransactions === undefined ||\n (bankTransactions !== undefined && bankTransactions.length === 0)) ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={isLoading ? DataStateStatus.info : DataStateStatus.allDone}\n title={title}\n description={description}\n onRefresh={showRefreshButton ? refetch : undefined}\n isLoading={isValidating}\n icon={!editable ? <InboxIcon /> : undefined}\n />\n </div>\n ) : null}\n\n {!isLoading && error ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={refetch}\n isLoading={isValidating}\n />\n </div>\n ) : null}\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Inbox = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M16.5 9H12L10.5 11.25H7.5L6 9H1.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M4.0875 3.8325L1.5 9V13.5C1.5 13.8978 1.65804 14.2794 1.93934 14.5607C2.22064 14.842 2.60218 15 3 15H15C15.3978 15 15.7794 14.842 16.0607 14.5607C16.342 14.2794 16.5 13.8978 16.5 13.5V9L13.9125 3.8325C13.7883 3.58259 13.5969 3.37228 13.3597 3.22521C13.1226 3.07814 12.8491 3.00015 12.57 3H5.43C5.15094 3.00015 4.87745 3.07814 4.64028 3.22521C4.40312 3.37228 4.21168 3.58259 4.0875 3.8325Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default Inbox\n", "import React from \"react\";\nimport { useQuickbooks } from \"../../hooks/useQuickbooks\";\n\nconst Quickbooks = () => {\n const {\n syncFromQuickbooks,\n isSyncingFromQuickbooks,\n quickbooksIsLinked,\n linkQuickbooks,\n unlinkQuickbooks,\n } = useQuickbooks();\n\n return (\n <div>\n <div>\n Quickbooks OAuth connection status:{\" \"}\n {quickbooksIsLinked === undefined\n ? \"\"\n : quickbooksIsLinked\n ? \"established\"\n : \"not connected\"}\n </div>\n <br />\n {quickbooksIsLinked === null && \"Loading...\"}\n {quickbooksIsLinked === false && (\n <button\n onClick={async () => {\n const authorizationUrl = await linkQuickbooks();\n window.location.href = authorizationUrl;\n }}\n >\n Link Quickbooks\n </button>\n )}\n {quickbooksIsLinked === true &&\n (isSyncingFromQuickbooks ? (\n \"Syncing data from Quickbooks...\"\n ) : (\n <div>\n <button onClick={syncFromQuickbooks}>Sync Quickbooks</button>\n <button onClick={unlinkQuickbooks}>Unlink Quickbooks</button>\n </div>\n ))}\n </div>\n );\n};\n\nexport { Quickbooks };\n", "import { useEffect, useRef, useState } from \"react\";\nimport { useLayerContext } from \"../../contexts/LayerContext\";\nimport { Layer } from \"../../api/layer\";\n\ntype UseQuickbooks = () => {\n linkQuickbooks: () => Promise<string>;\n unlinkQuickbooks: () => void;\n syncFromQuickbooks: () => void;\n isSyncingFromQuickbooks: boolean;\n quickbooksIsLinked: boolean | null;\n};\n\nconst DEBUG = true;\n\nexport const useQuickbooks: UseQuickbooks = () => {\n const { auth, businessId, apiUrl } = useLayerContext();\n const [isSyncingFromQuickbooks, setIsSyncingFromQuickbooks] =\n useState<boolean>(false);\n const [quickbooksIsLinked, setQuickbooksIsLinked] = useState<boolean | null>(\n null\n );\n const syncStatusIntervalRef = useRef<NodeJS.Timeout | null>(null);\n\n // Poll the server to determine when the Quickbooks sync is complete\n useEffect(() => {\n if (isSyncingFromQuickbooks && syncStatusIntervalRef.current === null) {\n const interval = setInterval(() => fetchIsSyncingFromQuickbooks(), 2000);\n syncStatusIntervalRef.current = interval;\n return () => clearInterval(interval);\n } else if (!isSyncingFromQuickbooks && syncStatusIntervalRef.current) {\n clearInterval(syncStatusIntervalRef.current);\n syncStatusIntervalRef.current = null;\n }\n }, [isSyncingFromQuickbooks]);\n\n // Determine whether there exists an active Quickbooks connection or not\n useEffect(() => {\n fetchQuickbooksConnectionStatus();\n }, []);\n\n const fetchQuickbooksConnectionStatus = async () => {\n const isConnected = (\n await Layer.statusOfQuickbooksConnection(apiUrl, auth.access_token, {\n params: { businessId },\n })()\n ).data.is_connected;\n setQuickbooksIsLinked(isConnected);\n };\n\n const syncFromQuickbooks = () => {\n DEBUG && console.log(\"Triggering sync from Quickbooks...\");\n setIsSyncingFromQuickbooks(true);\n try {\n Layer.syncFromQuickbooks(apiUrl, auth.access_token, {\n params: { businessId },\n });\n } catch {\n setIsSyncingFromQuickbooks(false);\n }\n };\n\n const fetchIsSyncingFromQuickbooks = async () => {\n DEBUG && console.log(\"Fetching status of sync from Quickbooks...\");\n const isSyncing = (\n await Layer.statusOfSyncFromQuickbooks(apiUrl, auth.access_token, {\n params: { businessId },\n })()\n ).data.is_syncing;\n setIsSyncingFromQuickbooks(isSyncing);\n };\n\n const linkQuickbooks = async () => {\n const res = await Layer.initQuickbooksOAuth(apiUrl, auth.access_token, {\n params: { businessId },\n });\n\n return res.data.redirect_url;\n };\n\n const unlinkQuickbooks = async () => {\n await Layer.unlinkQuickbooksConnection(apiUrl, auth.access_token, {\n params: { businessId },\n });\n fetchQuickbooksConnectionStatus();\n };\n\n return {\n isSyncingFromQuickbooks,\n syncFromQuickbooks,\n quickbooksIsLinked,\n linkQuickbooks,\n unlinkQuickbooks,\n };\n};\n", "import React, { PropsWithChildren, createContext } from 'react'\nimport { useProfitAndLoss } from '../../hooks/useProfitAndLoss'\nimport { ReportingBasis } from '../../types'\nimport { Container } from '../Container'\nimport { ProfitAndLossChart } from '../ProfitAndLossChart'\nimport { ProfitAndLossDatePicker } from '../ProfitAndLossDatePicker'\nimport { ProfitAndLossDetailedCharts } from '../ProfitAndLossDetailedCharts'\nimport { ProfitAndLossSummaries } from '../ProfitAndLossSummaries'\nimport { ProfitAndLossTable } from '../ProfitAndLossTable'\nimport { endOfMonth, startOfMonth } from 'date-fns'\n\ntype PNLContextType = ReturnType<typeof useProfitAndLoss>\nconst PNLContext = createContext<PNLContextType>({\n data: undefined,\n filteredDataRevenue: [],\n filteredTotalRevenue: undefined,\n filteredDataExpenses: [],\n filteredTotalExpenses: undefined,\n isLoading: true,\n isValidating: false,\n error: undefined,\n dateRange: {\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n },\n changeDateRange: () => {},\n refetch: () => {},\n sidebarScope: undefined,\n setSidebarScope: () => {},\n sortBy: () => {},\n setFilterTypes: () => {},\n filters: {\n expenses: undefined,\n revenue: undefined,\n },\n})\n\ntype Props = PropsWithChildren & {\n tagFilter?: {\n key: string\n values: string[]\n }\n reportingBasis?: ReportingBasis\n asContainer?: boolean\n}\n\nconst ProfitAndLoss = ({\n children,\n tagFilter,\n reportingBasis,\n asContainer = true,\n}: Props) => {\n const contextData = useProfitAndLoss({ tagFilter, reportingBasis })\n\n return (\n <PNLContext.Provider value={contextData}>\n {asContainer ? (\n <Container name='profit-and-loss'>{children}</Container>\n ) : (\n children\n )}\n </PNLContext.Provider>\n )\n}\n\nProfitAndLoss.Chart = ProfitAndLossChart\nProfitAndLoss.Context = PNLContext\nProfitAndLoss.DatePicker = ProfitAndLossDatePicker\nProfitAndLoss.Summaries = ProfitAndLossSummaries\nProfitAndLoss.Table = ProfitAndLossTable\nProfitAndLoss.DetailedCharts = ProfitAndLossDetailedCharts\nexport { ProfitAndLoss }\n", "import { useMemo, useState } from 'react'\nimport {\n ProfitAndLoss,\n DateRange,\n ReportingBasis,\n SortDirection,\n} from '../../types'\nimport { LineBaseItem } from '../../types/line_item'\nimport {\n collectExpensesItems,\n collectRevenueItems,\n applyShare,\n} from '../../utils/profitAndLossUtils'\nimport { useProfitAndLossQuery } from './useProfitAndLossQuery'\nimport { startOfMonth, endOfMonth } from 'date-fns'\n\nexport type Scope = 'expenses' | 'revenue'\n\nexport type SidebarScope = Scope | undefined\n\ntype Props = {\n startDate?: Date\n endDate?: Date\n tagFilter?: {\n key: string\n values: string[]\n }\n reportingBasis?: ReportingBasis\n}\n\ntype ProfitAndLossFilter = {\n sortBy?: string\n sortDirection?: SortDirection\n types?: string[]\n}\n\nexport type ProfitAndLossFilters = Record<\n Scope,\n ProfitAndLossFilter | undefined\n>\n\ntype UseProfitAndLoss = (props?: Props) => {\n data: ProfitAndLoss | undefined\n filteredDataRevenue: LineBaseItem[]\n filteredTotalRevenue?: number\n filteredDataExpenses: LineBaseItem[]\n filteredTotalExpenses?: number\n isLoading: boolean\n isValidating: boolean\n error: unknown\n dateRange: DateRange\n changeDateRange: (dateRange: Partial<DateRange>) => void\n refetch: () => void\n sidebarScope: SidebarScope\n setSidebarScope: (view: SidebarScope) => void\n filters: ProfitAndLossFilters\n sortBy: (scope: Scope, field: string, direction?: SortDirection) => void\n setFilterTypes: (scope: Scope, types: string[]) => void\n}\n\nexport const useProfitAndLoss: UseProfitAndLoss = (\n {\n startDate: initialStartDate,\n endDate: initialEndDate,\n tagFilter,\n reportingBasis,\n }: Props = {\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n },\n) => {\n const [startDate, setStartDate] = useState(\n initialStartDate || startOfMonth(Date.now()),\n )\n const [endDate, setEndDate] = useState(\n initialEndDate || endOfMonth(Date.now()),\n )\n const [filters, setFilters] = useState<ProfitAndLossFilters>({\n expenses: undefined,\n revenue: undefined,\n })\n\n const [sidebarScope, setSidebarScope] = useState<SidebarScope>(undefined)\n\n const { data, isLoading, isValidating, error, refetch } =\n useProfitAndLossQuery({\n startDate,\n endDate,\n tagFilter,\n reportingBasis,\n })\n\n const changeDateRange = ({\n startDate: newStartDate,\n endDate: newEndDate,\n }: Partial<DateRange>) => {\n newStartDate && setStartDate(newStartDate)\n newEndDate && setEndDate(newEndDate)\n }\n\n const sortBy = (scope: Scope, field: string, direction?: SortDirection) => {\n setFilters({\n ...filters,\n [scope]: {\n ...filters[scope],\n sortBy: field,\n sortDirection:\n direction ?? filters[scope]?.sortDirection === 'desc'\n ? 'asc'\n : 'desc',\n },\n })\n }\n\n const setFilterTypes = (scope: Scope, types: string[]) => {\n setFilters({\n ...filters,\n [scope]: {\n ...filters[scope],\n types,\n },\n })\n }\n\n const { filteredDataRevenue, filteredTotalRevenue } = useMemo(() => {\n if (!data) {\n return { filteredDataRevenue: [], filteredTotalRevenue: undefined }\n }\n const items = collectRevenueItems(data)\n const filtered = items.map(x => {\n if (\n filters['revenue']?.types &&\n filters['revenue']!.types!.length > 0 &&\n !filters['revenue']?.types?.includes(x.type)\n ) {\n return {\n ...x,\n hidden: true,\n }\n }\n\n return x\n })\n\n const sorted = filtered.sort((a, b) => {\n switch (filters['revenue']?.sortBy) {\n case 'category':\n if (filters['revenue']?.sortDirection === 'asc') {\n return a.display_name.localeCompare(b.display_name)\n }\n return b.display_name.localeCompare(a.display_name)\n\n case 'type':\n if (filters['revenue']?.sortDirection === 'asc') {\n return a.type.localeCompare(b.type)\n }\n return b.type.localeCompare(a.type)\n\n default:\n if (filters['revenue']?.sortDirection === 'asc') {\n return a.value - b.value\n }\n return b.value - a.value\n }\n })\n const total = sorted\n .filter(x => !x.hidden)\n .reduce((x, { value }) => x + value, 0)\n const withShare = applyShare(sorted, total)\n\n return { filteredDataRevenue: withShare, filteredTotalRevenue: total }\n }, [data, startDate, filters, sidebarScope])\n\n const { filteredDataExpenses, filteredTotalExpenses } = useMemo(() => {\n if (!data) {\n return { filteredDataExpenses: [], filteredTotalExpenses: undefined }\n }\n const items = collectExpensesItems(data)\n const filtered = items.map(x => {\n if (\n filters['expenses']?.types &&\n filters['expenses']!.types!.length > 0 &&\n !filters['expenses']?.types?.includes(x.type)\n ) {\n return {\n ...x,\n hidden: true,\n }\n }\n\n return x\n })\n const sorted = filtered.sort((a, b) => {\n switch (filters['expenses']?.sortBy) {\n case 'category':\n if (filters['expenses']?.sortDirection === 'asc') {\n return a.display_name.localeCompare(b.display_name)\n }\n return b.display_name.localeCompare(a.display_name)\n\n case 'type':\n if (filters['expenses']?.sortDirection === 'asc') {\n return a.type.localeCompare(b.type)\n }\n return b.type.localeCompare(a.type)\n\n default:\n if (filters['expenses']?.sortDirection === 'asc') {\n return a.value - b.value\n }\n return b.value - a.value\n }\n })\n const total = sorted\n .filter(x => !x.hidden)\n .reduce((x, { value }) => x + value, 0)\n const withShare = applyShare(sorted, total)\n\n return { filteredDataExpenses: withShare, filteredTotalExpenses: total }\n }, [data, startDate, filters, sidebarScope])\n\n return {\n data,\n filteredDataRevenue,\n filteredTotalRevenue,\n filteredDataExpenses,\n filteredTotalExpenses,\n isLoading,\n isValidating,\n error: error,\n dateRange: { startDate, endDate },\n refetch,\n changeDateRange,\n sidebarScope,\n setSidebarScope,\n sortBy,\n filters,\n setFilterTypes,\n }\n}\n", "import { SidebarScope } from '../hooks/useProfitAndLoss/useProfitAndLoss'\nimport { LineItem, LineBaseItem } from '../types/line_item'\nimport { ProfitAndLoss } from '../types/profit_and_loss'\n\nconst doesLineItemQualifies = (item: LineItem) => {\n return !(\n item.is_contra ||\n item.value === undefined ||\n item.value === null ||\n isNaN(item.value) ||\n item.value === -Infinity ||\n item.value === Infinity ||\n item.value < 0\n )\n}\n\nconst collectSubItems = (type: string, item?: LineItem | null) => {\n if (!item) {\n return []\n }\n\n const items: LineBaseItem[] = []\n\n item?.line_items?.forEach(item => {\n if (doesLineItemQualifies(item)) {\n items.push({\n name: item.name,\n display_name: item.display_name,\n value: item.value || 0,\n type,\n })\n }\n })\n\n return items\n}\n\nexport const collectExpensesItems = (data: ProfitAndLoss) => {\n const cogs = collectSubItems('Cost of Goods Sold', data.cost_of_goods_sold)\n const expenses = collectSubItems('Operating Expenses', data.expenses)\n const taxes = collectSubItems('Taxes & Licenses', data.taxes)\n\n return ([] as LineBaseItem[]).concat(cogs).concat(expenses).concat(taxes)\n}\n\nexport const collectRevenueItems = (data: ProfitAndLoss) => {\n const income = collectSubItems('Income', data.income)\n\n return ([] as LineBaseItem[]).concat(income)\n}\n\nexport const humanizeTitle = (sidebarView: SidebarScope) => {\n switch (sidebarView) {\n case 'expenses':\n return 'Expenses'\n case 'revenue':\n return 'Revenue'\n default:\n return 'Profit & Loss'\n }\n}\n\nexport const applyShare = (\n items: LineBaseItem[],\n total: number,\n): LineBaseItem[] => {\n return items.map(item => {\n if (total === 0) {\n return item\n }\n\n return {\n ...item,\n share: item.value / total,\n }\n })\n}\n", "import { useEffect } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { ProfitAndLoss, ReportingBasis } from '../../types'\nimport { DataModel } from '../../types/general'\nimport { startOfMonth, endOfMonth, formatISO } from 'date-fns'\nimport useSWR from 'swr'\n\ntype UseProfitAndLossQueryProps = {\n startDate: Date\n endDate: Date\n tagFilter?: {\n key: string\n values: string[]\n }\n reportingBasis?: ReportingBasis\n}\n\ntype UseProfitAndLossQueryReturn = (props?: UseProfitAndLossQueryProps) => {\n data?: ProfitAndLoss\n isLoading: boolean\n isValidating: boolean\n error: any\n refetch: () => void\n startDate: Date\n endDate: Date\n}\n\nexport const useProfitAndLossQuery: UseProfitAndLossQueryReturn = (\n {\n startDate,\n endDate,\n tagFilter,\n reportingBasis,\n }: UseProfitAndLossQueryProps = {\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n },\n) => {\n const { auth, businessId, apiUrl, syncTimestamps, read, hasBeenTouched } =\n useLayerContext()\n\n const queryKey =\n businessId &&\n startDate &&\n endDate &&\n auth?.access_token &&\n `profit-and-loss-${businessId}-${startDate.valueOf()}-${endDate.valueOf()}-${tagFilter?.key}-${tagFilter?.values?.join(\n ',',\n )}-${reportingBasis}`\n\n const {\n data: rawData,\n isLoading,\n isValidating,\n error: rawError,\n mutate,\n } = useSWR(\n queryKey,\n Layer.getProfitAndLoss(apiUrl, auth?.access_token, {\n params: {\n businessId,\n startDate: formatISO(startDate.valueOf()),\n endDate: formatISO(endDate.valueOf()),\n tagKey: tagFilter?.key,\n tagValues: tagFilter?.values?.join(','),\n reportingBasis,\n },\n }),\n )\n\n const refetch = () => {\n mutate()\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.PROFIT_AND_LOSS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps, startDate, endDate, tagFilter, reportingBasis])\n\n return {\n startDate,\n endDate,\n data: rawData?.data,\n isLoading,\n isValidating,\n error: rawError,\n refetch,\n }\n}\n", "import React, { useContext, useEffect, useMemo, useState } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport {\n ProfitAndLossSummaryData,\n useProfitAndLossLTM,\n} from '../../hooks/useProfitAndLoss/useProfitAndLossLTM'\nimport { centsToDollars } from '../../models/Money'\nimport { isDateAllowedToBrowse } from '../../utils/business'\nimport { ProfitAndLoss as PNL } from '../ProfitAndLoss'\nimport { Text } from '../Typography'\nimport { Indicator } from './Indicator'\nimport classNames from 'classnames'\nimport {\n add,\n differenceInMonths,\n endOfMonth,\n format,\n startOfMonth,\n sub,\n} from 'date-fns'\nimport {\n XAxis,\n Cell,\n Bar,\n LabelList,\n CartesianGrid,\n Legend,\n ResponsiveContainer,\n Tooltip,\n TooltipProps,\n Rectangle,\n YAxis,\n Line,\n ComposedChart,\n ReferenceLine,\n} from 'recharts'\nimport { CategoricalChartFunc } from 'recharts/types/chart/generateCategoricalChart'\nimport { Props as LegendProps } from 'recharts/types/component/DefaultLegendContent'\n\nconst getChartWindow = ({\n chartWindow,\n currentYear,\n currentMonth,\n}: {\n chartWindow: { start: Date; end: Date }\n currentYear: number\n currentMonth: number\n}) => {\n const today = startOfMonth(Date.now())\n const yearAgo = sub(today, { months: 11 })\n const current = startOfMonth(new Date(currentYear, currentMonth - 1, 1))\n\n if (\n differenceInMonths(startOfMonth(chartWindow.start), current) < 0 &&\n differenceInMonths(startOfMonth(chartWindow.end), current) > 1\n ) {\n return chartWindow\n }\n\n if (differenceInMonths(startOfMonth(chartWindow.start), current) === 0) {\n return {\n start: startOfMonth(sub(current, { months: 1 })),\n end: endOfMonth(add(current, { months: 11 })),\n }\n }\n\n if (\n differenceInMonths(endOfMonth(chartWindow.end), endOfMonth(current)) ===\n 1 &&\n differenceInMonths(today, current) >= 1\n ) {\n return {\n start: startOfMonth(sub(current, { months: 10 })),\n end: endOfMonth(add(current, { months: 2 })),\n }\n }\n\n if (\n differenceInMonths(current, startOfMonth(chartWindow.end)) === 0 &&\n differenceInMonths(current, startOfMonth(today)) > 0\n ) {\n return {\n start: startOfMonth(sub(current, { months: 11 })),\n end: endOfMonth(add(current, { months: 1 })),\n }\n }\n\n if (current >= yearAgo) {\n return {\n start: startOfMonth(yearAgo),\n end: endOfMonth(today),\n }\n }\n\n if (Number(current) > Number(chartWindow.end)) {\n return {\n start: startOfMonth(sub(current, { months: 12 })),\n end: endOfMonth(current),\n }\n }\n\n if (differenceInMonths(current, startOfMonth(chartWindow.start)) < 0) {\n return {\n start: startOfMonth(current),\n end: endOfMonth(add(current, { months: 11 })),\n }\n }\n\n return chartWindow\n}\n\nconst getLoadingValue = (data?: ProfitAndLossSummaryData[]) => {\n if (!data) {\n return 10000\n }\n\n let max = 0\n\n data.forEach(x => {\n const current = Math.max(\n Math.abs(x.income),\n Math.abs(Math.abs((x?.income || 0) - (x?.netProfit || 0))),\n )\n if (current > max) {\n max = current\n }\n })\n\n return max === 0 ? 10000 : max * 0.6\n}\n\nexport interface Props {\n forceRerenderOnDataChange?: boolean\n}\n\nexport const ProfitAndLossChart = ({\n forceRerenderOnDataChange = false,\n}: Props) => {\n const [compactView, setCompactView] = useState(false)\n const barSize = compactView ? 10 : 20\n\n const { getColor, business } = useLayerContext()\n const { changeDateRange, dateRange } = useContext(PNL.Context)\n const [localDateRange, setLocalDateRange] = useState(dateRange)\n const [customCursorSize, setCustomCursorSize] = useState({\n width: 0,\n height: 0,\n x: 0,\n })\n const [barAnimActive, setBarAnimActive] = useState(true)\n const [chartWindow, setChartWindow] = useState({\n start: startOfMonth(sub(Date.now(), { months: 11 })),\n end: endOfMonth(Date.now()),\n })\n\n const selectionMonth = useMemo(\n () => ({\n year: localDateRange.startDate.getFullYear(),\n month: localDateRange.startDate.getMonth(),\n }),\n [localDateRange],\n )\n\n useEffect(() => {\n if (\n Number(dateRange.startDate) !== Number(localDateRange.startDate) ||\n Number(dateRange.endDate) !== Number(localDateRange.endDate)\n ) {\n setLocalDateRange(dateRange)\n }\n }, [dateRange])\n\n const { data, loaded, pullData } = useProfitAndLossLTM({\n currentDate: startOfMonth(Date.now()),\n })\n\n const loadingValue = useMemo(() => getLoadingValue(data), [data])\n\n useEffect(() => {\n if (loaded === 'complete' && data) {\n const foundCurrent = data.find(\n x =>\n Number(startOfMonth(new Date(x.year, x.month - 1, 1))) >=\n Number(localDateRange.startDate) &&\n Number(startOfMonth(new Date(x.year, x.month - 1, 1))) <\n Number(localDateRange.endDate),\n )\n\n if (!foundCurrent) {\n const newDate = startOfMonth(localDateRange.startDate)\n pullData(newDate)\n return\n }\n\n const foundBefore = data.find(\n x =>\n Number(startOfMonth(new Date(x.year, x.month - 1, 1))) >=\n Number(sub(localDateRange.startDate, { months: 1 })) &&\n Number(startOfMonth(new Date(x.year, x.month - 1, 1))) <\n Number(sub(localDateRange.endDate, { months: 1 })),\n )\n\n if (!foundBefore) {\n const newDate = startOfMonth(\n sub(localDateRange.startDate, { months: 1 }),\n )\n pullData(newDate)\n }\n }\n }, [localDateRange])\n\n useEffect(() => {\n const newChartWindow = getChartWindow({\n chartWindow,\n currentYear: localDateRange.startDate.getFullYear(),\n currentMonth: localDateRange.startDate.getMonth() + 1,\n })\n\n if (\n Number(newChartWindow.start) !== Number(chartWindow.start) ||\n Number(newChartWindow.end) !== Number(chartWindow.end)\n ) {\n setChartWindow(newChartWindow)\n }\n }, [localDateRange])\n\n useEffect(() => {\n if (loaded === 'complete') {\n setTimeout(() => {\n setBarAnimActive(false)\n }, 2000)\n }\n }, [loaded])\n\n const getMonthName = (pnl: ProfitAndLossSummaryData | undefined) =>\n pnl\n ? format(\n new Date(pnl.year, pnl.month - 1, 1),\n compactView ? 'LLLLL' : 'LLL',\n )\n : ''\n\n const summarizePnL = (pnl: ProfitAndLossSummaryData | undefined) => ({\n name: getMonthName(pnl),\n revenue: pnl?.income || 0,\n revenueUncategorized: pnl?.uncategorizedInflows || 0,\n expenses: -(pnl?.totalExpenses || 0),\n expensesUncategorized: -(pnl?.uncategorizedOutflows || 0),\n totalExpensesInverse: pnl?.totalExpensesInverse || 0,\n uncategorizedOutflowsInverse: pnl?.uncategorizedOutflowsInverse || 0,\n netProfit: pnl?.netProfit || 0,\n selected:\n !!pnl &&\n pnl.month === selectionMonth.month + 1 &&\n pnl.year === selectionMonth.year,\n year: pnl?.year,\n month: pnl?.month,\n base: 0,\n loading: pnl?.isLoading ? loadingValue : 0,\n loadingExpenses: pnl?.isLoading ? -loadingValue : 0,\n })\n\n const theData = useMemo(() => {\n if (loaded !== 'complete') {\n const loadingData = []\n const today = Date.now()\n for (let i = 11; i >= 0; i--) {\n const currentDate = sub(today, { months: i })\n loadingData.push({\n name: format(currentDate, compactView ? 'LLLLL' : 'LLL'),\n revenue: 0,\n revenueUncategorized: 0,\n totalExpensesInverse: 0,\n uncategorizedOutflowsInverse: 0,\n expenses: 0,\n expensesUncategorized: 0,\n netProfit: 0,\n selected: false,\n year: currentDate.getFullYear(),\n month: currentDate.getMonth() + 1,\n loading: 1000 * Math.pow(-1, i + 1) * (((i + 1) % 12) + 1) + 90000,\n loadingExpenses:\n -1000 * Math.pow(-1, i + 1) * (((i + 1) % 2) + 1) - 90000,\n base: 0,\n })\n }\n return loadingData\n }\n\n return data\n ?.map(x => {\n const totalExpenses = x.totalExpenses || 0\n if (totalExpenses < 0 || x.uncategorizedOutflows < 0) {\n return {\n ...x,\n totalExpenses: totalExpenses < 0 ? 0 : totalExpenses,\n uncategorizedOutflows:\n x.uncategorizedOutflows < 0 ? 0 : x.uncategorizedOutflows,\n totalExpensesInverse: totalExpenses < 0 ? -totalExpenses : 0,\n uncategorizedOutflowsInverse:\n x.uncategorizedOutflows < 0 ? -x.uncategorizedOutflows : 0,\n }\n }\n\n return x\n })\n ?.filter(\n x =>\n differenceInMonths(\n startOfMonth(new Date(x.year, x.month - 1, 1)),\n chartWindow.start,\n ) >= 0 &&\n differenceInMonths(\n startOfMonth(new Date(x.year, x.month - 1, 1)),\n chartWindow.start,\n ) < 12 &&\n differenceInMonths(\n chartWindow.end,\n startOfMonth(new Date(x.year, x.month - 1, 1)),\n ) >= 0 &&\n differenceInMonths(\n chartWindow.end,\n startOfMonth(new Date(x.year, x.month - 1, 1)),\n ) <= 12,\n )\n .map(x => summarizePnL(x))\n }, [selectionMonth, chartWindow, data, loaded, compactView])\n\n const onClick: CategoricalChartFunc = ({ activePayload }) => {\n if (activePayload && activePayload.length > 0) {\n const { year, month } = activePayload[0].payload\n const isMonthAllowed = isDateAllowedToBrowse(\n new Date(year, month - 1, 1),\n business,\n )\n\n if (isMonthAllowed) {\n changeDateRange({\n startDate: new Date(year, month - 1, 1),\n endDate: endOfMonth(new Date(year, month - 1, 1)),\n })\n }\n }\n }\n\n const CustomTooltip = ({ active, payload }: TooltipProps<number, string>) => {\n if (active && payload && payload.length) {\n const netProfit = payload.find(x => x.dataKey === 'netProfit')?.value ?? 0\n const netProfitClass =\n netProfit > 0 ? 'positive' : netProfit < 0 ? 'negative' : ''\n const revenue = payload.find(x => x.dataKey === 'revenue')?.value ?? 0\n const expenses = payload.find(x => x.dataKey === 'expenses')?.value ?? 0\n\n return (\n <div className='Layer__chart__tooltip'>\n {loaded !== 'complete' ? (\n <Text>Loading...</Text>\n ) : (\n <ul className='Layer__chart__tooltip-list'>\n <li>\n <label className='Layer__chart__tooltip-label'>Revenue</label>\n <span className='Layer__chart__tooltip-value'>\n ${centsToDollars(revenue)}\n </span>\n </li>\n <li>\n <label className='Layer__chart__tooltip-label'>Expenses</label>\n <span className='Layer__chart__tooltip-value'>\n ${centsToDollars(Math.abs(expenses))}\n </span>\n </li>\n <li>\n <label className='Layer__chart__tooltip-label'>\n Net Profit\n </label>\n <span\n className={`Layer__chart__tooltip-value ${netProfitClass}`}\n >\n ${centsToDollars(netProfit)}\n </span>\n </li>\n </ul>\n )}\n </div>\n )\n }\n\n return null\n }\n\n const formatYAxisValue = (value?: string | number) => {\n if (!value) {\n return value\n }\n\n try {\n let suffix = ''\n const base = Number(value) / 100\n let val = base\n\n if (Math.abs(base) >= 1000000000) {\n suffix = 'B'\n val = base / 1000000000\n } else if (Math.abs(base) >= 1000000) {\n suffix = 'M'\n val = base / 1000000\n } else if (Math.abs(base) >= 1000) {\n suffix = 'k'\n val = base / 1000\n }\n return `${val}${suffix}`\n } catch (_err) {\n return value\n }\n }\n\n const renderLegend = (props: LegendProps) => {\n return (\n <ul className='Layer__chart-legend-list'>\n {props.payload?.map((entry, idx) => {\n if (entry.id === 'UncategorizedLegend') {\n return (\n <li\n key={`legend-item-${idx}`}\n className={`recharts-legend-item legend-item-${idx}`}\n >\n <svg\n className='recharts-surface'\n width='15'\n height='15'\n viewBox='0 0 15 15'\n style={{\n display: 'inline-block',\n verticalAlign: 'middle',\n marginRight: 4,\n }}\n >\n <circle\n cx='7'\n cy='7'\n r='7'\n fill='url(#layer-bar-stripe-pattern-dark)'\n />\n </svg>\n {entry.value}\n </li>\n )\n }\n return (\n <li\n key={`legend-item-${idx}`}\n className={`recharts-legend-item legend-item-${idx}`}\n >\n <svg\n className='recharts-surface'\n width='15'\n height='15'\n viewBox='0 0 15 15'\n style={{\n display: 'inline-block',\n verticalAlign: 'middle',\n marginRight: 4,\n }}\n >\n <circle cx='7' cy='7' r='7' />\n </svg>\n {entry.value}\n </li>\n )\n })}\n </ul>\n )\n }\n\n const CustomizedYTick = (props: any) => {\n return (\n <text {...props} className='Layer__chart_y-axis-tick'>\n <tspan dy='0.355em'>{formatYAxisValue(props.payload.value)}</tspan>\n </text>\n )\n }\n\n const CustomizedCursor = (props: any) => {\n const { points } = props\n const { width, height } = customCursorSize\n\n return (\n <Rectangle\n fill='#F7F8FA'\n stroke='none'\n x={points[0].x - width / 2}\n y={points[0].y}\n width={width}\n height={height}\n radius={6}\n className='Layer__chart__tooltip-cursor'\n />\n )\n }\n\n const [animateFrom, setAnimateFrom] = useState(-1)\n\n return (\n <ResponsiveContainer\n key={forceRerenderOnDataChange ? JSON.stringify(theData) : 'pnl-chart'}\n className={classNames(\n 'Layer__chart-container',\n loaded !== 'complete' && 'Layer__chart-container--loading',\n )}\n width='100%'\n height='100%'\n onResize={width => {\n if (width && width < 620 && !compactView) {\n setCompactView(true)\n return\n }\n\n if (width && width >= 620 && compactView) {\n setCompactView(false)\n return\n }\n }}\n >\n <ComposedChart\n margin={{ left: 12, right: 12, bottom: 12 }}\n data={theData}\n onClick={onClick}\n className='Layer__profit-and-loss-chart'\n >\n <defs>\n <pattern\n id='layer-bar-stripe-pattern'\n x='0'\n y='0'\n width='4'\n height='4'\n patternTransform='rotate(45)'\n patternUnits='userSpaceOnUse'\n >\n <rect width='4' height='4' opacity={0.16} />\n <line x1='0' y='0' x2='0' y2='4' strokeWidth='2' />\n </pattern>\n\n <pattern\n id='layer-bar-stripe-pattern-dark'\n x='0'\n y='0'\n width='4'\n height='4'\n patternTransform='rotate(45)'\n patternUnits='userSpaceOnUse'\n >\n <rect width='4' height='4' opacity={0.16} />\n <line x1='0' y='0' x2='0' y2='4' strokeWidth='2' />\n </pattern>\n </defs>\n <ReferenceLine\n y={0}\n stroke={getColor(300)?.hex ?? '#EBEDF0'}\n xAxisId='revenue'\n />\n <Tooltip\n wrapperClassName='Layer__chart__tooltip-wrapper'\n content={<CustomTooltip />}\n cursor={<CustomizedCursor />}\n animationDuration={100}\n animationEasing='ease-out'\n />\n <CartesianGrid\n vertical={false}\n stroke={getColor(200)?.hex ?? '#fff'}\n strokeDasharray='5 5'\n />\n <Legend\n verticalAlign='top'\n align='right'\n content={renderLegend}\n payload={[\n {\n value: 'Revenue',\n type: 'circle',\n id: 'IncomeLegend',\n },\n {\n value: 'Expenses',\n type: 'circle',\n id: 'ExpensesLegend',\n },\n {\n value: 'Uncategorized',\n type: 'circle',\n id: 'UncategorizedLegend',\n },\n ]}\n />\n <XAxis dataKey='name' xAxisId='revenue' tickLine={false} />\n <XAxis dataKey='name' xAxisId='expenses' tickLine={false} hide />\n <YAxis tick={<CustomizedYTick />} />\n <Bar\n dataKey='loading'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--loading'\n xAxisId='revenue'\n stackId='revenue'\n />\n <Bar\n dataKey='loadingExpenses'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--loading'\n xAxisId='expenses'\n stackId='expenses'\n />\n <Bar\n dataKey='totalExpensesInverse'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--expenses'\n xAxisId='revenue'\n stackId='revenue'\n >\n {theData?.map(entry => {\n return (\n <Cell\n key={entry.name}\n fill='url(#layer-bar-stripe-pattern-dark)'\n />\n )\n })}\n </Bar>\n <Bar\n dataKey='revenue'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n className='Layer__profit-and-loss-chart__bar--income'\n xAxisId='revenue'\n stackId='revenue'\n >\n <LabelList\n content={\n <Indicator\n setCustomCursorSize={(width, height, x) =>\n setCustomCursorSize({ width, height, x })\n }\n customCursorSize={customCursorSize}\n animateFrom={animateFrom}\n setAnimateFrom={setAnimateFrom}\n />\n }\n />\n {theData?.map(entry => {\n return (\n <Cell\n key={entry.name}\n className={\n entry.selected\n ? 'Layer__profit-and-loss-chart__cell--selected'\n : ''\n }\n />\n )\n })}\n </Bar>\n <Bar\n dataKey='uncategorizedOutflowsInverse'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--expenses-uncategorized'\n xAxisId='revenue'\n stackId='revenue'\n >\n {theData?.map(entry => {\n return (\n <Cell\n key={entry.name}\n fill='url(#layer-bar-stripe-pattern-dark)'\n />\n )\n })}\n </Bar>\n <Bar\n dataKey='revenueUncategorized'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--income-uncategorized'\n xAxisId='revenue'\n stackId='revenue'\n >\n {theData?.map(entry => {\n return (\n <Cell key={entry.name} fill='url(#layer-bar-stripe-pattern)' />\n )\n })}\n </Bar>\n <Bar\n dataKey='expenses'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n className='Layer__profit-and-loss-chart__bar--expenses'\n xAxisId='expenses'\n stackId='expenses'\n >\n {theData.map(entry => (\n <Cell\n key={entry.name}\n className={\n entry.selected\n ? 'Layer__profit-and-loss-chart__cell--selected'\n : ''\n }\n />\n ))}\n </Bar>\n <Bar\n dataKey='expensesUncategorized'\n barSize={barSize}\n isAnimationActive={barAnimActive}\n animationDuration={100}\n radius={[2, 2, 0, 0]}\n className='Layer__profit-and-loss-chart__bar--expenses-uncategorized'\n xAxisId='expenses'\n stackId='expenses'\n >\n {theData?.map(entry => {\n return (\n <Cell\n key={entry.name}\n fill='url(#layer-bar-stripe-pattern-dark)'\n />\n )\n })}\n </Bar>\n <Line\n dot={true}\n strokeWidth={1}\n type='linear'\n dataKey='netProfit'\n stroke={getColor(1000)?.hex ?? '#000'}\n name='Net profit'\n xAxisId='revenue'\n animationDuration={20}\n />\n </ComposedChart>\n </ResponsiveContainer>\n )\n}\n", "import { useEffect, useMemo, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { ReportingBasis } from '../../types'\nimport { DataModel, LoadedStatus } from '../../types/general'\nimport { ProfitAndLossSummary } from '../../types/profit_and_loss'\nimport { startOfMonth, sub } from 'date-fns'\nimport useSWR from 'swr'\n\ntype UseProfitAndLossLTMProps = {\n currentDate: Date\n tagFilter?: {\n key: string\n values: string[]\n }\n reportingBasis?: ReportingBasis\n}\n\nexport interface ProfitAndLossSummaryData extends ProfitAndLossSummary {\n isLoading?: boolean\n}\n\ntype UseProfitAndLossLTMReturn = (props?: UseProfitAndLossLTMProps) => {\n data: ProfitAndLossSummaryData[]\n isLoading?: boolean\n loaded?: LoadedStatus\n error?: any\n pullData: (date: Date) => void\n refetch: () => void\n}\n\nconst buildDates = ({ currentDate }: { currentDate: Date }) => {\n return {\n startYear: startOfMonth(currentDate).getFullYear() - 1,\n startMonth: startOfMonth(currentDate).getMonth() + 1,\n endYear: startOfMonth(currentDate).getFullYear(),\n endMonth: startOfMonth(currentDate).getMonth() + 1,\n }\n}\n\nconst buildMonthsArray = (startDate: Date, endDate: Date) => {\n if (startDate >= endDate) {\n return []\n }\n\n var dates = []\n for (var d = startDate; d <= endDate; d.setMonth(d.getMonth() + 1)) {\n dates.push(new Date(d))\n }\n\n return dates\n}\n\n/**\n * Hooks fetch Last Twelve Months sending 12 requests (one for each month).\n * Implementation is not perfect, but we cannot use loops and arrays with hooks.\n */\nexport const useProfitAndLossLTM: UseProfitAndLossLTMReturn = (\n { currentDate, tagFilter, reportingBasis }: UseProfitAndLossLTMProps = {\n currentDate: startOfMonth(Date.now()),\n },\n) => {\n const {\n businessId,\n auth,\n apiUrl,\n syncTimestamps,\n read,\n readTimestamps,\n hasBeenTouched,\n } = useLayerContext()\n const [date, setDate] = useState(currentDate)\n const [loaded, setLoaded] = useState<LoadedStatus>('initial')\n const [data, setData] = useState<ProfitAndLossSummaryData[]>([])\n\n const { startYear, startMonth, endYear, endMonth } = useMemo(() => {\n return buildDates({ currentDate: date })\n }, [date, businessId, tagFilter, reportingBasis])\n\n const queryKey =\n businessId &&\n Boolean(startYear) &&\n Boolean(startMonth) &&\n Boolean(endYear) &&\n Boolean(endMonth) &&\n auth?.access_token &&\n `profit-and-loss-summaries-${businessId}-${startYear.toString()}-${startMonth.toString()}-${tagFilter?.key}-${tagFilter?.values?.join(\n ',',\n )}-${reportingBasis}`\n\n const {\n data: rawData,\n isLoading,\n isValidating,\n error,\n mutate,\n } = useSWR(\n queryKey,\n Layer.getProfitAndLossSummaries(apiUrl, auth?.access_token, {\n params: {\n businessId,\n startYear: startYear.toString(),\n startMonth: startMonth.toString(),\n endYear: endYear.toString(),\n endMonth: endMonth.toString(),\n tagKey: tagFilter?.key,\n tagValues: tagFilter?.values?.join(','),\n reportingBasis,\n },\n }),\n )\n\n useEffect(() => {\n // When new date range is set, populate 'data' with 'loading' items\n const newData = data.slice()\n\n const newPeriod = buildMonthsArray(sub(date, { years: 1 }), date)\n\n if (newData && newPeriod) {\n newPeriod.forEach(x => {\n if (\n !newData?.find(\n n => x.getMonth() + 1 === n.month && x.getFullYear() === n.year,\n )\n ) {\n newData.push({\n year: x.getFullYear(),\n month: x.getMonth() + 1,\n income: 0,\n costOfGoodsSold: 0,\n grossProfit: 0,\n operatingExpenses: 0,\n profitBeforeTaxes: 0,\n taxes: 0,\n netProfit: 0,\n fullyCategorized: false,\n totalExpenses: 0,\n uncategorizedInflows: 0,\n uncategorizedOutflows: 0,\n uncategorized_transactions: 0,\n isLoading: true,\n } satisfies ProfitAndLossSummaryData)\n }\n })\n }\n\n if (newData) {\n setData(\n newData.sort(\n (a, b) =>\n Number(new Date(a.year, a.month, 1)) -\n Number(new Date(b.year, b.month, 1)),\n ),\n )\n }\n }, [startYear, startMonth])\n\n useEffect(() => {\n const newData = rawData?.data?.months?.slice()\n\n if (data && newData) {\n data.forEach(x => {\n if (!newData?.find(n => x.month === n.month && x.year === n.year)) {\n newData.push({ ...x })\n }\n })\n }\n\n if (newData) {\n setData(\n newData.sort(\n (a, b) =>\n Number(new Date(a.year, a.month, 1)) -\n Number(new Date(b.year, b.month, 1)),\n ),\n )\n }\n }, [rawData])\n\n useEffect(() => {\n if (isLoading && loaded === 'initial') {\n setLoaded('loading')\n return\n }\n\n if (!isLoading && rawData) {\n setLoaded('complete')\n }\n }, [data, isLoading])\n\n const pullData = (date: Date) => setDate(date)\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.PROFIT_AND_LOSS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n mutate()\n }\n }, [\n syncTimestamps,\n startYear,\n startMonth,\n endYear,\n endMonth,\n tagFilter,\n reportingBasis,\n ])\n\n const refetch = () => {\n mutate()\n }\n\n return {\n data,\n isLoading,\n loaded,\n error,\n pullData,\n refetch,\n }\n}\n", "import React, { useEffect, useState } from 'react'\nimport { Props as BaseProps } from 'recharts/types/component/Label'\n\n// This component does not always exist. It gets recreated each time the\n// selected month changes on the chart. As a result, the coordinates are not\n// persistent and so resist CSS animation. That way we work around this is by\n// telling the parent component what its X value is. The parent renders using\n// that X as the \"animateFrom\" value. This then tells the paren its new X,\n// which becomes the new \"animateFrom\", set using useState setter, which causes\n// a render, which causes the new `animateFrom` to be passed in, which causes a\n// change in the X coordinate, which causes a transition to trigger.\n\ntype Props = BaseProps & {\n animateFrom: number\n setAnimateFrom: (x: number) => void\n customCursorSize: { width: number; height: number }\n setCustomCursorSize: (width: number, height: number, x: number) => void\n}\nconst emptyViewBox = { x: 0, y: 0, width: 0, height: 0 }\nexport const Indicator = ({\n className,\n animateFrom,\n setAnimateFrom,\n customCursorSize,\n setCustomCursorSize,\n viewBox = {},\n}: Props) => {\n if (!className?.match(/selected/)) {\n return null\n }\n\n const [opacityIndicator, setOpacityIndicator] = useState(0)\n\n const { x: animateTo = 0, width = 0 } =\n 'x' in viewBox ? viewBox : emptyViewBox\n const margin = width > 12 ? 12 : 6\n const boxWidth = width + margin\n const xOffset = boxWidth / 2\n const borderRadius = 6\n const rectWidth = `${boxWidth}px`\n const rectHeight = 'calc(100% - 38px)'\n\n // useEffect callbacks run after the browser paints\n useEffect(() => {\n if (Math.abs(animateTo - animateFrom) < 30) {\n setOpacityIndicator(0)\n }\n\n setAnimateFrom(animateTo)\n setTimeout(() => {\n setOpacityIndicator(1)\n }, 200)\n }, [animateTo])\n\n const rectRef = (ref: SVGRectElement | null) => {\n if (ref) {\n const refRectWidth = ref.getBoundingClientRect().width\n const refRectHeight = ref.getBoundingClientRect().height\n if (\n customCursorSize.width !== refRectWidth ||\n customCursorSize.height !== refRectHeight\n ) {\n setCustomCursorSize(refRectWidth, refRectHeight, actualX - xOffset)\n }\n }\n }\n\n const actualX = animateFrom === -1 ? animateTo : animateFrom\n return (\n <rect\n ref={rectRef}\n className='Layer__profit-and-loss-chart__selection-indicator'\n rx={borderRadius}\n ry={borderRadius}\n style={{\n width: rectWidth,\n // @ts-expect-error -- y is fine but x apparently isn't!\n x: actualX - xOffset / 2 + margin / 4,\n y: 22,\n height: rectHeight,\n opacity: opacityIndicator,\n }}\n />\n )\n}\n", "import React, { useContext, useEffect } from 'react'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { getEarliestDateToBrowse } from '../../utils/business'\nimport { DatePicker } from '../DatePicker'\nimport { ProfitAndLoss } from '../ProfitAndLoss'\nimport { endOfMonth, startOfMonth } from 'date-fns'\n\nexport const ProfitAndLossDatePicker = () => {\n const { business } = useLayerContext()\n const { changeDateRange, dateRange } = useContext(ProfitAndLoss.Context)\n\n const minDate = getEarliestDateToBrowse(business)\n\n return (\n <DatePicker\n mode='monthPicker'\n selected={dateRange.startDate}\n onChange={date => {\n if (!Array.isArray(date)) {\n changeDateRange({\n startDate: startOfMonth(date),\n endDate: endOfMonth(date),\n })\n }\n }}\n minDate={minDate}\n />\n )\n}\n", "import React, { useContext, useState } from 'react'\nimport { SidebarScope } from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport XIcon from '../../icons/X'\nimport { humanizeTitle } from '../../utils/profitAndLossUtils'\nimport { Button, BackButton, ButtonVariant } from '../Button'\nimport { ProfitAndLoss as PNL } from '../ProfitAndLoss'\nimport { ProfitAndLossDatePicker } from '../ProfitAndLossDatePicker'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport { DetailedChart } from './DetailedChart'\nimport { DetailedTable, DetailedTableStringOverrides } from './DetailedTable'\nimport { Filters } from './Filters'\nimport { format } from 'date-fns'\n\nexport interface ProfitAndLossDetailedChartsStringOverrides {\n detailedTableStringOverrides?: DetailedTableStringOverrides\n}\n\nexport const ProfitAndLossDetailedCharts = ({\n scope,\n hideClose = false,\n showDatePicker = false,\n chartColorsList,\n stringOverrides,\n}: {\n scope?: SidebarScope\n hideClose?: boolean\n showDatePicker?: boolean\n chartColorsList?: string[]\n stringOverrides?: ProfitAndLossDetailedChartsStringOverrides\n}) => {\n const {\n filteredDataRevenue,\n filteredTotalRevenue,\n filteredDataExpenses,\n filteredTotalExpenses,\n sortBy,\n isLoading,\n filters,\n dateRange,\n sidebarScope,\n setSidebarScope,\n setFilterTypes,\n } = useContext(PNL.Context)\n\n const theScope = scope ? scope : sidebarScope\n const data =\n theScope === 'revenue' ? filteredDataRevenue : filteredDataExpenses\n const total =\n theScope === 'revenue' ? filteredTotalRevenue : filteredTotalExpenses\n\n const [hoveredItem, setHoveredItem] = useState<string | undefined>()\n\n return (\n <div className='Layer__profit-and-loss-detailed-charts'>\n <header className='Layer__profit-and-loss-detailed-charts__header'>\n <div className='Layer__profit-and-loss-detailed-charts__head'>\n <Text size={TextSize.lg} weight={TextWeight.bold} className='title'>\n {humanizeTitle(theScope)}\n </Text>\n <Text size={TextSize.sm} className='date'>\n {format(dateRange.startDate, 'LLLL, y')}\n </Text>\n {showDatePicker && <ProfitAndLossDatePicker />}\n </div>\n {!hideClose && (\n <Button\n rightIcon={<XIcon />}\n iconOnly={true}\n onClick={() => setSidebarScope(undefined)}\n variant={ButtonVariant.secondary}\n />\n )}\n </header>\n\n <header className='Layer__profit-and-loss-detailed-charts__header--tablet'>\n {!hideClose && (\n <BackButton onClick={() => setSidebarScope(undefined)} />\n )}\n <div className='Layer__profit-and-loss-detailed-charts__head'>\n <Text size={TextSize.lg} weight={TextWeight.bold} className='title'>\n {humanizeTitle(theScope)}\n </Text>\n <Text size={TextSize.sm} className='date'>\n {format(dateRange.startDate, 'LLLL, y')}\n </Text>\n </div>\n </header>\n\n <div className='Layer__profit-and-loss-detailed-charts__content'>\n <DetailedChart\n filteredData={data}\n filteredTotal={total}\n hoveredItem={hoveredItem}\n setHoveredItem={setHoveredItem}\n sidebarScope={theScope}\n date={dateRange.startDate}\n isLoading={isLoading}\n chartColorsList={chartColorsList}\n showDatePicker={showDatePicker}\n />\n\n <div className='Layer__profit-and-loss-detailed-charts__table-wrapper'>\n <Filters\n filteredData={data}\n sidebarScope={theScope}\n filters={filters}\n setFilterTypes={setFilterTypes}\n />\n\n <DetailedTable\n filteredData={data}\n sidebarScope={theScope}\n filters={filters}\n sortBy={sortBy}\n hoveredItem={hoveredItem}\n setHoveredItem={setHoveredItem}\n chartColorsList={chartColorsList}\n stringOverrides={stringOverrides?.detailedTableStringOverrides}\n />\n </div>\n </div>\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst X = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M13.5 4.5L4.5 13.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M4.5 4.5L13.5 13.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default X\n", "import React, { useMemo } from 'react'\nimport { SidebarScope } from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { LineBaseItem } from '../../types/line_item'\nimport { formatPercent } from '../../utils/format'\nimport { humanizeTitle } from '../../utils/profitAndLossUtils'\nimport { ProfitAndLossDatePicker } from '../ProfitAndLossDatePicker'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport { mapTypesToColors } from './DetailedTable'\nimport { format } from 'date-fns'\nimport {\n PieChart,\n Pie,\n Cell,\n ResponsiveContainer,\n Label,\n Text as ChartText,\n} from 'recharts'\nimport { PolarViewBox } from 'recharts/types/util/types'\n\ninterface DetailedChartProps {\n filteredData: LineBaseItem[]\n filteredTotal?: number\n hoveredItem?: string\n setHoveredItem: (name?: string) => void\n sidebarScope?: SidebarScope\n date: number | Date\n isLoading?: boolean\n showDatePicker?: boolean\n chartColorsList?: string[]\n}\n\nexport const DetailedChart = ({\n filteredData,\n filteredTotal,\n hoveredItem,\n setHoveredItem,\n sidebarScope,\n date,\n chartColorsList,\n isLoading,\n showDatePicker = true,\n}: DetailedChartProps) => {\n const chartData = useMemo(() => {\n if (!filteredData) {\n return []\n }\n return filteredData.map(x => {\n if (x.hidden) {\n return {\n name: x.display_name,\n value: 0,\n type: x.type,\n }\n }\n return {\n name: x.display_name,\n value: x.value,\n type: x.type,\n }\n })\n }, [filteredData, isLoading])\n\n const noValue = chartData.length === 0 || !chartData.find(x => x.value !== 0)\n\n const typeColorMapping = mapTypesToColors(chartData, chartColorsList)\n\n return (\n <div className='chart-field'>\n <div className='header--tablet'>\n {showDatePicker && <ProfitAndLossDatePicker />}\n </div>\n\n <div className='chart-container'>\n <ResponsiveContainer>\n <PieChart>\n {!isLoading && !noValue ? (\n <Pie\n data={chartData}\n dataKey='value'\n nameKey='name'\n cx='50%'\n cy='50%'\n innerRadius={'91%'}\n outerRadius={'100%'}\n paddingAngle={0.5}\n fill='#8884d8'\n animationDuration={200}\n animationEasing='ease-in-out'\n >\n {chartData.map((entry, index) => {\n let fill: string | undefined = typeColorMapping[index].color\n let active = true\n if (hoveredItem && entry.name !== hoveredItem) {\n active = false\n fill = undefined\n }\n\n return (\n <Cell\n key={`cell-${index}`}\n className={`Layer__profit-and-loss-detailed-charts__pie ${\n hoveredItem && active ? 'active' : 'inactive'\n }`}\n style={{ fill }}\n opacity={typeColorMapping[index].opacity}\n onMouseEnter={() => setHoveredItem(entry.name)}\n onMouseLeave={() => setHoveredItem(undefined)}\n />\n )\n })}\n <Label\n position='center'\n value='Total'\n className='pie-center-label-title'\n content={props => {\n const { cx, cy } = (props.viewBox as PolarViewBox) ?? {\n cx: 0,\n cy: 0,\n }\n const positioningProps = {\n x: cx,\n y: (cy || 0) - 15,\n textAnchor: 'middle' as\n | 'start'\n | 'middle'\n | 'end'\n | 'inherit',\n verticalAnchor: 'middle' as 'start' | 'middle' | 'end',\n }\n\n let text = 'Total'\n\n if (hoveredItem) {\n text = hoveredItem\n }\n\n return (\n <ChartText\n {...positioningProps}\n className='pie-center-label__title'\n >\n {text}\n </ChartText>\n )\n }}\n />\n\n <Label\n position='center'\n value='Total'\n className='pie-center-label-title'\n content={props => {\n const { cx, cy } = (props.viewBox as PolarViewBox) ?? {\n cx: 0,\n cy: 0,\n }\n const positioningProps = {\n x: cx,\n y: (cy || 0) + 5,\n textAnchor: 'middle' as\n | 'start'\n | 'middle'\n | 'end'\n | 'inherit',\n verticalAnchor: 'middle' as 'start' | 'middle' | 'end',\n }\n\n let value = filteredTotal\n if (hoveredItem) {\n value = filteredData.find(\n x => x.display_name === hoveredItem,\n )?.value\n }\n\n return (\n <ChartText\n {...positioningProps}\n className='pie-center-label__value'\n >\n {`$${formatMoney(value)}`}\n </ChartText>\n )\n }}\n />\n\n <Label\n position='center'\n value='Total'\n className='pie-center-label-title'\n content={props => {\n const { cx, cy } = (props.viewBox as PolarViewBox) ?? {\n cx: 0,\n cy: 0,\n }\n const positioningProps = {\n x: cx,\n y: (cy || 0) + 25,\n height: 20,\n textAnchor: 'middle' as\n | 'start'\n | 'middle'\n | 'end'\n | 'inherit',\n verticalAnchor: 'middle' as 'start' | 'middle' | 'end',\n }\n\n if (hoveredItem) {\n return (\n <ChartText\n {...positioningProps}\n className='pie-center-label__share'\n >\n {`${formatPercent(\n filteredData.find(\n x => x.display_name === hoveredItem,\n )?.share,\n )}%`}\n </ChartText>\n )\n }\n\n return\n }}\n />\n </Pie>\n ) : null}\n\n {!isLoading && noValue ? (\n <Pie\n data={[{ name: 'Total', value: 1 }]}\n dataKey='value'\n nameKey='name'\n cx='50%'\n cy='50%'\n innerRadius={'91%'}\n outerRadius={'100%'}\n paddingAngle={0}\n fill='#F8F8FA'\n animationDuration={200}\n animationEasing='ease-in-out'\n >\n <Label\n position='center'\n value='Total'\n className='pie-center-label-title'\n content={props => {\n const { cx, cy } = (props.viewBox as PolarViewBox) ?? {\n cx: 0,\n cy: 0,\n }\n const positioningProps = {\n x: cx,\n y: (cy || 0) - 15,\n textAnchor: 'middle' as\n | 'start'\n | 'middle'\n | 'end'\n | 'inherit',\n verticalAnchor: 'middle' as 'start' | 'middle' | 'end',\n }\n\n let text = 'Total'\n\n if (hoveredItem) {\n text = hoveredItem\n }\n\n return (\n <ChartText\n {...positioningProps}\n className='pie-center-label__title'\n >\n {text}\n </ChartText>\n )\n }}\n />\n\n <Label\n position='center'\n value='Total'\n className='pie-center-label-title'\n content={props => {\n const { cx, cy } = (props.viewBox as PolarViewBox) ?? {\n cx: 0,\n cy: 0,\n }\n const positioningProps = {\n x: cx,\n y: (cy || 0) + 5,\n textAnchor: 'middle' as\n | 'start'\n | 'middle'\n | 'end'\n | 'inherit',\n verticalAnchor: 'middle' as 'start' | 'middle' | 'end',\n }\n\n let value = filteredTotal\n if (hoveredItem) {\n value = filteredData.find(\n x => x.display_name === hoveredItem,\n )?.value\n }\n\n return (\n <ChartText\n {...positioningProps}\n className='pie-center-label__value'\n >\n {`$${formatMoney(value)}`}\n </ChartText>\n )\n }}\n />\n </Pie>\n ) : null}\n\n {isLoading ? (\n <Pie\n data={[{ name: 'loading...', value: 1 }]}\n dataKey='value'\n nameKey='name'\n cx='50%'\n cy='50%'\n innerRadius={'91%'}\n outerRadius={'100%'}\n paddingAngle={0}\n fill='#F8F8FA'\n animationDuration={200}\n animationEasing='ease-in-out'\n />\n ) : null}\n </PieChart>\n </ResponsiveContainer>\n </div>\n </div>\n )\n}\n", "/**\n * Capitalize first letter of the given text.\n */\nexport const capitalizeFirstLetter = (text: string) =>\n text.charAt(0).toUpperCase() + text.slice(1)\n\n/**\n * Convert number into percentage.\n *\n * @example\n * 0.112 -> 11%\n * 0.09843 -> 9.8%\n * 0.00123 -> 0.12%\n */\nexport const formatPercent = (\n value?: number,\n options?: Intl.NumberFormatOptions,\n) => {\n if (!value && value !== 0) {\n return\n }\n\n const val = value * 100\n\n let defaultOptions: Intl.NumberFormatOptions = {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n }\n\n if (Math.abs(val) < 10) {\n defaultOptions = {\n minimumFractionDigits: 1,\n maximumFractionDigits: 1,\n }\n }\n\n if (Math.abs(val) < 1) {\n defaultOptions = {\n minimumFractionDigits: 1,\n maximumFractionDigits: 1,\n }\n }\n\n if (val === 0) {\n defaultOptions = {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n }\n }\n\n return val.toLocaleString('en-US', {\n ...defaultOptions,\n ...options,\n })\n}\n\n/**\n * Convert Enum-like (upper snakecase) text into human friendly format.\n */\nexport const humanizeEnum = (text: string) => {\n return capitalizeFirstLetter(text.replace(/_/gi, ' ').toLowerCase())\n}\n\nexport const convertNumberToCurrency = (amount: number | undefined): string => {\n if (!amount) return ''\n\n let formattedValue = amount.toLocaleString('en-US')\n\n return formattedValue.length > 0 ? `$${formattedValue}` : ''\n}\n\nexport const convertCurrencyToNumber = (amount: string): number => {\n const inputValue = amount.replace(/[^0-9.]/g, '')\n\n return parseFloat(inputValue)\n}\n\nexport const CURRENCY_INPUT_PATTERN = '[0-9]+(.[0-9]+)?'\n", "import React from 'react'\nimport { DEFAULT_CHART_COLOR_TYPE } from '../../config/charts'\nimport {\n Scope,\n SidebarScope,\n ProfitAndLossFilters,\n} from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport SortArrows from '../../icons/SortArrows'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { SortDirection } from '../../types'\nimport { LineBaseItem } from '../../types/line_item'\nimport { formatPercent } from '../../utils/format'\nimport classNames from 'classnames'\n\nexport interface DetailedTableStringOverrides {\n categoryColumnHeader?: string\n typeColumnHeader?: string\n valueColumnHeader?: string\n}\n\nexport interface DetailedTableProps {\n filteredData: LineBaseItem[]\n hoveredItem?: string\n setHoveredItem: (name?: string) => void\n sidebarScope: SidebarScope\n filters: ProfitAndLossFilters\n sortBy: (scope: Scope, field: string, direction?: SortDirection) => void\n chartColorsList?: string[]\n stringOverrides?: DetailedTableStringOverrides\n}\n\nexport const mapTypesToColors = (\n data: any[],\n colorList: string[] = DEFAULT_CHART_COLOR_TYPE,\n) => {\n const typeToColor: any = {}\n const typeToLastOpacity: any = {}\n let colorIndex = 0\n\n return data.map(obj => {\n const type = obj.type\n\n if (!typeToColor[type]) {\n typeToColor[type] = colorList[colorIndex % colorList.length]\n colorIndex++\n typeToLastOpacity[type] = 1\n } else {\n typeToLastOpacity[type] -= 0.1\n }\n\n const opacity = typeToLastOpacity[type]\n\n return {\n color: typeToColor[type],\n opacity: opacity,\n }\n })\n}\n\nexport const DetailedTable = ({\n filteredData,\n sidebarScope,\n filters,\n sortBy,\n hoveredItem,\n setHoveredItem,\n chartColorsList,\n stringOverrides,\n}: DetailedTableProps) => {\n const buildColClass = (column: string) => {\n return classNames(\n 'Layer__sortable-col',\n sidebarScope && filters[sidebarScope]?.sortBy === column\n ? `sort--${\n (sidebarScope && filters[sidebarScope]?.sortDirection) ?? 'desc'\n }`\n : '',\n )\n }\n\n const typeColorMapping: any = mapTypesToColors(filteredData, chartColorsList)\n\n // Index to keep track of the next color to assign\n const colorIndex = 0\n\n return (\n <div className='details-container'>\n <div className='table'>\n <table>\n <thead>\n <tr>\n <th\n className={buildColClass('category')}\n onClick={() => sortBy(sidebarScope ?? 'expenses', 'category')}\n >\n {stringOverrides?.categoryColumnHeader || 'Category'}{' '}\n <SortArrows className='Layer__sort-arrows' />\n </th>\n <th\n className={buildColClass('type')}\n onClick={() => sortBy(sidebarScope ?? 'expenses', 'type')}\n >\n {stringOverrides?.typeColumnHeader || 'Type'}{' '}\n <SortArrows className='Layer__sort-arrows' />\n </th>\n <th></th>\n <th\n className={buildColClass('value')}\n onClick={() => sortBy(sidebarScope ?? 'expenses', 'value')}\n >\n {stringOverrides?.valueColumnHeader || 'Value'}{' '}\n <SortArrows className='Layer__sort-arrows' />\n </th>\n </tr>\n </thead>\n <tbody>\n {filteredData\n .filter(x => !x.hidden)\n .map((item, idx) => {\n return (\n <tr\n key={`pl-side-table-item-${idx}`}\n className={classNames(\n 'Layer__profit-and-loss-detailed-table__row',\n hoveredItem && hoveredItem === item.display_name\n ? 'active'\n : '',\n )}\n onMouseEnter={() => setHoveredItem(item.display_name)}\n onMouseLeave={() => setHoveredItem(undefined)}\n >\n <td className='category-col'>{item.display_name}</td>\n <td className='type-col'>{item.type}</td>\n <td className='value-col'>${formatMoney(item.value)}</td>\n <td className='share-col'>\n <span className='share-cell-content'>\n {formatPercent(item.share)}%\n <div\n className='share-icon'\n style={{\n background: typeColorMapping[idx].color,\n opacity: typeColorMapping[idx].opacity,\n }}\n />\n </span>\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n </div>\n )\n}\n", "export const INACTIVE_OPACITY_LEVELS = [\n 0.85, 0.7, 0.66, 0.55, 0.4, 0.33, 0.25, 0.15,\n]\n\nexport const DEFAULT_CHART_OPACITY = [1, 0.8, 0.6, 0.4, 0.2, 0.1]\n\nexport const DEFAULT_CHART_COLOR_TYPE = [\n '#008028',\n '#7417B3',\n '#006A80',\n '#8FB300',\n '#3D87CC',\n '#CC3DCC',\n '#3DCCB2',\n '#CCB129',\n '#2949CC',\n '#619900',\n '#6A52CC',\n '#71CC56',\n]\n\nexport const DEFAULT_MINICHART_COLORS = [\n {\n color: '#7417B3',\n opacity: 1,\n },\n {\n color: '#7417B3',\n opacity: 0.8,\n },\n {\n color: '#7417B3',\n opacity: 0.6,\n },\n {\n color: '#7417B3',\n opacity: 0.4,\n },\n {\n color: '#7417B3',\n opacity: 0.2,\n },\n {\n color: '#7417B3',\n opacity: 0.1,\n },\n {\n color: '#006A80',\n opacity: 1,\n },\n {\n color: '#006A80',\n opacity: 0.8,\n },\n {\n color: '#006A80',\n opacity: 0.6,\n },\n {\n color: '#006A80',\n opacity: 0.4,\n },\n {\n color: '#006A80',\n opacity: 0.2,\n },\n {\n color: '#006A80',\n opacity: 0.1,\n },\n {\n color: '#009930',\n opacity: 1,\n },\n {\n color: '#009930',\n opacity: 0.8,\n },\n {\n color: '#009930',\n opacity: 0.6,\n },\n {\n color: '#009930',\n opacity: 0.4,\n },\n {\n color: '#009930',\n opacity: 0.2,\n },\n {\n color: '#009930',\n opacity: 0.1,\n },\n]\n\nexport const TASKS_CHARTS_COLORS = {\n done: '#3B9C63',\n pending: '#DFA000',\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst SortArrows = ({ size = 13, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 13'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <g clipPath='url(#clip0_1758_75388)'>\n <path\n d='M1.33325 8.5L3.99992 11.1667L6.66659 8.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n className='desc-arrow'\n />\n <path\n d='M4 2.5L4 11.1667'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n className='desc-arrow'\n />\n <path\n d='M5.99988 5.16602L8.66654 2.49935L11.3332 5.16602'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n className='asc-arrow'\n />\n <path\n d='M8.66663 11.166L8.66663 2.49935'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n className='asc-arrow'\n />\n </g>\n <defs>\n <clipPath id='clip0_1758_75388'>\n <rect\n width='12'\n height='12'\n fill='white'\n transform='translate(0 0.5)'\n />\n </clipPath>\n </defs>\n </svg>\n)\n\nexport default SortArrows\n", "import React from 'react'\nimport Select, { components } from 'react-select'\nimport {\n Scope,\n SidebarScope,\n ProfitAndLossFilters,\n} from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport ChevronDown from '../../icons/ChevronDown'\nimport { LineBaseItem } from '../../types/line_item'\nimport { CategoryOption } from '../CategorySelect/CategorySelect'\nimport { Text, TextSize } from '../Typography'\n\nexport interface FiltersProps {\n filteredData: LineBaseItem[]\n sidebarScope: SidebarScope\n filters: ProfitAndLossFilters\n setFilterTypes: (scope: Scope, types: string[]) => void\n}\n\nexport const Filters = ({\n filteredData,\n sidebarScope,\n filters,\n setFilterTypes,\n}: FiltersProps) => {\n return (\n <div className='filters'>\n <Text size={TextSize.sm} className='Layer__label'>\n Filters\n </Text>\n <Select\n className='Layer__select type-select'\n classNamePrefix='Layer__select'\n value={\n sidebarScope && filters[sidebarScope]?.types\n ? sidebarScope &&\n filters[sidebarScope]?.types?.map(x => ({\n value: x,\n label: x,\n }))\n : []\n }\n isMulti\n isClearable={false}\n options={\n [...new Set(filteredData?.map(x => x.type))].map(x => ({\n label: x,\n value: x,\n })) as unknown as readonly { value: string; label: string }[]\n }\n onChange={selected => {\n setFilterTypes(\n sidebarScope ?? 'expenses',\n selected.map(x => x.value),\n )\n }}\n components={{\n DropdownIndicator: props => (\n <components.DropdownIndicator {...props}>\n <ChevronDown />\n </components.DropdownIndicator>\n ),\n Placeholder: props => (\n <components.Placeholder {...props}>\n <div className='Layer__select__multi-all-placeholder-badge'>\n All\n </div>\n </components.Placeholder>\n ),\n }}\n />\n </div>\n )\n}\n", "import React, { useContext, useMemo } from 'react'\nimport { Scope } from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport { centsToDollars as formatMoney } from '../../models/Money'\nimport { ProfitAndLoss } from '../../types'\nimport { LineBaseItem } from '../../types/line_item'\nimport {\n collectExpensesItems,\n collectRevenueItems,\n} from '../../utils/profitAndLossUtils'\nimport { ProfitAndLoss as PNL } from '../ProfitAndLoss'\nimport { SkeletonLoader } from '../SkeletonLoader'\nimport { MiniChart } from './MiniChart'\nimport classNames from 'classnames'\n\nexport interface ProfitAndLossSummariesStringOverrides {\n revenueLabel?: string\n expensesLabel?: string\n netProfitLabel?: string\n}\n\ntype Props = {\n vertical?: boolean\n actionable?: boolean\n revenueLabel?: string // deprecated\n stringOverrides?: ProfitAndLossSummariesStringOverrides\n}\n\nconst CHART_PLACEHOLDER = [\n {\n name: 'placeholder',\n display_name: 'placeholder',\n value: 1,\n type: 'placeholder',\n share: 1,\n },\n]\n\nconst buildMiniChartData = (scope: Scope, data?: ProfitAndLoss) => {\n if (!data) {\n return CHART_PLACEHOLDER\n }\n\n let items: LineBaseItem[] = []\n\n switch (scope) {\n case 'revenue':\n items = collectRevenueItems(data)\n break\n default:\n items = collectExpensesItems(data)\n }\n\n if (\n !items ||\n items.length === 0 ||\n !items.find(x => Math.abs(x.value) !== 0)\n ) {\n return CHART_PLACEHOLDER\n }\n\n return items.slice()\n}\n\nexport const ProfitAndLossSummaries = ({\n vertical,\n actionable = false,\n revenueLabel, // deprecated\n stringOverrides,\n}: Props) => {\n const {\n data: storedData,\n isLoading,\n setSidebarScope,\n sidebarScope,\n } = useContext(PNL.Context)\n\n const dataItem = Array.isArray(storedData)\n ? storedData[storedData.length - 1]\n : storedData\n\n const expensesChartData = useMemo(() => {\n return buildMiniChartData('expenses', dataItem)\n }, [storedData])\n\n const revenueChartData = useMemo(() => {\n return buildMiniChartData('revenue', dataItem)\n }, [storedData])\n\n const data = dataItem ? dataItem : { income: { value: NaN }, net_profit: NaN }\n\n const incomeDirectionClass =\n (data.income.value ?? NaN) < 0\n ? 'Layer__profit-and-loss-summaries__amount--negative'\n : 'Layer__profit-and-loss-summaries__amount--positive'\n\n const expensesDirectionClass =\n (data?.income?.value ?? NaN) - data.net_profit < 0\n ? 'Layer__profit-and-loss-summaries__amount--negative'\n : 'Layer__profit-and-loss-summaries__amount--positive'\n\n const netProfitDirectionClass =\n data.net_profit < 0\n ? 'Layer__profit-and-loss-summaries__amount--negative'\n : 'Layer__profit-and-loss-summaries__amount--positive'\n\n return (\n <div\n className={`Layer__profit-and-loss-summaries ${\n vertical ? 'flex-col' : ''\n }`}\n >\n <div\n className={classNames(\n 'Layer__profit-and-loss-summaries__summary',\n actionable && 'Layer__actionable',\n 'Layer__profit-and-loss-summaries__summary--income',\n sidebarScope === 'revenue' ? 'active' : '',\n )}\n onClick={() => {\n actionable && setSidebarScope('revenue')\n }}\n >\n <MiniChart data={revenueChartData} />\n <div className='Layer__profit-and-loss-summaries__text'>\n <span className='Layer__profit-and-loss-summaries__title'>\n {stringOverrides?.revenueLabel || revenueLabel || 'Revenue'}\n </span>\n {isLoading || storedData === undefined ? (\n <div className='Layer__profit-and-loss-summaries__loader'>\n <SkeletonLoader />\n </div>\n ) : (\n <span\n className={`Layer__profit-and-loss-summaries__amount ${incomeDirectionClass}`}\n >\n {formatMoney(Math.abs(data?.income?.value ?? NaN))}\n </span>\n )}\n </div>\n </div>\n <div\n className={classNames(\n 'Layer__profit-and-loss-summaries__summary',\n actionable && 'Layer__actionable',\n 'Layer__profit-and-loss-summaries__summary--expenses',\n sidebarScope === 'expenses' ? 'active' : '',\n )}\n onClick={() => {\n actionable && setSidebarScope('expenses')\n }}\n >\n <MiniChart data={expensesChartData} />\n <div className='Layer__profit-and-loss-summaries__text'>\n <span className='Layer__profit-and-loss-summaries__title'>\n {stringOverrides?.expensesLabel || 'Expenses'}\n </span>\n {isLoading || storedData === undefined ? (\n <div className='Layer__profit-and-loss-summaries__loader'>\n <SkeletonLoader className='Layer__profit-and-loss-summaries__loader' />\n </div>\n ) : (\n <span\n className={`Layer__profit-and-loss-summaries__amount ${expensesDirectionClass}`}\n >\n {formatMoney(\n Math.abs((data.income.value ?? 0) - data.net_profit),\n )}\n </span>\n )}\n </div>\n </div>\n <div\n className={classNames(\n 'Layer__profit-and-loss-summaries__summary net-profit Layer__profit-and-loss-summaries__summary--net-profit',\n actionable && 'Layer__actionable',\n )}\n >\n <div className='Layer__profit-and-loss-summaries__text'>\n <span className='Layer__profit-and-loss-summaries__title'>\n {stringOverrides?.netProfitLabel || 'Net Profit'}\n </span>\n {isLoading || storedData === undefined ? (\n <div className='Layer__profit-and-loss-summaries__loader'>\n <SkeletonLoader className='Layer__profit-and-loss-summaries__loader' />\n </div>\n ) : (\n <span\n className={`Layer__profit-and-loss-summaries__amount ${netProfitDirectionClass}`}\n >\n {formatMoney(Math.abs(data.net_profit))}\n </span>\n )}\n </div>\n </div>\n </div>\n )\n}\n", "import React from 'react'\nimport { DEFAULT_MINICHART_COLORS } from '../../config/charts'\nimport { LineBaseItem } from '../../types/line_item'\nimport { PieChart, Pie, Cell } from 'recharts'\n\nexport interface MiniChartProps {\n data: LineBaseItem[]\n}\n\nexport const MiniChart = ({ data }: MiniChartProps) => {\n return (\n <PieChart width={52} height={52} className='mini-chart'>\n <Pie\n data={data}\n dataKey='value'\n nameKey='name'\n cx='50%'\n cy='50%'\n innerRadius={10}\n outerRadius={16}\n paddingAngle={0.4}\n fill='#8884d8'\n width={24}\n height={24}\n animationDuration={250}\n animationEasing='ease-in-out'\n >\n {data.map((entry, index) => {\n const colorConfig =\n DEFAULT_MINICHART_COLORS[index % DEFAULT_MINICHART_COLORS.length]\n\n return (\n <Cell\n key={`cell-${index}`}\n className={`Layer__profit-and-loss-detailed-charts__pie`}\n fill={\n entry.name === 'placeholder' ? '#e6e6e6' : colorConfig.color\n }\n opacity={colorConfig.opacity}\n />\n )\n })}\n </Pie>\n </PieChart>\n )\n}\n", "import React, { useContext } from 'react'\nimport { Direction } from '../../types'\nimport { Loader } from '../Loader'\nimport { ProfitAndLoss } from '../ProfitAndLoss'\nimport { ProfitAndLossRow } from '../ProfitAndLossRow'\nimport emptyPNL from './empty_profit_and_loss_report'\nimport classNames from 'classnames'\n\nexport interface ProfitAndLossTableStringOverrides {\n grossProfitLabel?: string\n profitBeforeTaxesLabel?: string\n netProfitLabel?: string\n}\n\ntype Props = {\n lockExpanded?: boolean\n asContainer?: boolean\n stringOverrides?: ProfitAndLossTableStringOverrides\n}\n\nexport const ProfitAndLossTable = ({\n lockExpanded,\n asContainer,\n stringOverrides,\n}: Props) => {\n const {\n data: actualData,\n isLoading,\n setSidebarScope,\n } = useContext(ProfitAndLoss.Context)\n\n const currentData = Array.isArray(actualData)\n ? actualData[actualData.length - 1]\n : actualData\n const data = !currentData || isLoading ? emptyPNL : currentData\n\n if (isLoading || actualData === undefined) {\n return (\n <div\n className={classNames(\n 'Layer__profit-and-loss-table__loader-container',\n asContainer && 'Layer__component-container',\n )}\n >\n <Loader />\n </div>\n )\n }\n\n return (\n <>\n <div\n className={classNames(\n 'Layer__profit-and-loss-table Layer__profit-and-loss-table--main',\n asContainer && 'Layer__component-container',\n )}\n >\n <ProfitAndLossRow\n lineItem={data.income}\n direction={Direction.CREDIT}\n lockExpanded={lockExpanded}\n scope='revenue'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={data.cost_of_goods_sold}\n direction={Direction.DEBIT}\n lockExpanded={lockExpanded}\n scope='expenses'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={{\n value: data.gross_profit,\n display_name: stringOverrides?.grossProfitLabel || 'Gross Profit',\n }}\n variant='summation'\n direction={Direction.CREDIT}\n lockExpanded={lockExpanded}\n scope='revenue'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={data.expenses}\n direction={Direction.DEBIT}\n lockExpanded={lockExpanded}\n scope='expenses'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={{\n value: data.profit_before_taxes,\n display_name:\n stringOverrides?.profitBeforeTaxesLabel || 'Profit Before Taxes',\n }}\n variant='summation'\n direction={Direction.CREDIT}\n lockExpanded={lockExpanded}\n scope='revenue'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={data.taxes}\n direction={Direction.DEBIT}\n lockExpanded={lockExpanded}\n scope='expenses'\n setSidebarScope={setSidebarScope}\n defaultExpanded\n />\n <ProfitAndLossRow\n lineItem={{\n value: data.net_profit,\n display_name: stringOverrides?.netProfitLabel || 'Net Profit',\n }}\n variant='summation'\n direction={Direction.CREDIT}\n lockExpanded={lockExpanded}\n />\n </div>\n {data.other_outflows || data.personal_expenses ? (\n <div className='Layer__profit-and-loss-table Layer__profit-and-loss-table__outflows'>\n <ProfitAndLossRow\n lineItem={data.other_outflows}\n direction={Direction.DEBIT}\n lockExpanded={lockExpanded}\n />\n <ProfitAndLossRow\n lineItem={data.personal_expenses}\n direction={Direction.DEBIT}\n lockExpanded={lockExpanded}\n />\n </div>\n ) : null}\n </>\n )\n}\n", "import React, { useState } from 'react'\nimport { SidebarScope } from '../../hooks/useProfitAndLoss/useProfitAndLoss'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport PieChart from '../../icons/PieChart'\nimport { centsToDollars } from '../../models/Money'\nimport { Direction, LineItem } from '../../types'\nimport { Text } from '../Typography'\n\ntype Props = {\n variant?: string\n depth?: number\n maxDepth?: number\n lineItem?: LineItem | null\n direction?: Direction\n scope?: SidebarScope\n setSidebarScope?: (name: SidebarScope) => void\n defaultExpanded?: boolean\n\n /* This removes the expand toggle and leaves everything in the expanded state */\n lockExpanded?: boolean\n}\n\nexport const ProfitAndLossRow = ({\n variant,\n lineItem,\n depth = 0,\n maxDepth = 8,\n direction = Direction.DEBIT,\n lockExpanded = false,\n scope,\n setSidebarScope,\n defaultExpanded = false,\n}: Props) => {\n if (!lineItem) {\n return null\n }\n const { value, display_name, line_items } = lineItem\n const [expanded, setExpanded] = useState(lockExpanded || defaultExpanded)\n const amount = value ?? 0\n const amountString = centsToDollars(Math.abs(amount))\n const labelClasses = [\n 'Layer__profit-and-loss-row',\n 'Layer__profit-and-loss-row__label',\n ]\n const valueClasses = [\n 'Layer__profit-and-loss-row',\n 'Layer__profit-and-loss-row__value',\n ]\n const positive =\n amount === 0 ||\n (direction === Direction.CREDIT && amount > 0) ||\n (direction === Direction.DEBIT && amount < 0)\n valueClasses.push(\n positive\n ? 'Layer__profit-and-loss-row__value--amount-positive'\n : 'Layer__profit-and-loss-row__value--amount-negative',\n )\n labelClasses.push(`Layer__profit-and-loss-row__label--depth-${depth}`)\n valueClasses.push(`Layer__profit-and-loss-row__value--depth-${depth}`)\n variant &&\n labelClasses.push(`Layer__profit-and-loss-row__label--variant-${variant}`)\n variant &&\n valueClasses.push(`Layer__profit-and-loss-row__value--variant-${variant}`)\n\n const toggleExpanded = () => setExpanded(!expanded)\n const canGoDeeper = depth < maxDepth\n const hasChildren = (line_items?.length ?? 0) > 0\n const displayChildren = hasChildren && canGoDeeper\n labelClasses.push(\n `Layer__profit-and-loss-row__label--display-children-${displayChildren}`,\n )\n valueClasses.push(\n `Layer__profit-and-loss-row__value--display-children-${displayChildren}`,\n )\n\n displayChildren &&\n expanded &&\n labelClasses.push('Layer__profit-and-loss-row__label--expanded')\n\n displayChildren &&\n expanded &&\n valueClasses.push('Layer__profit-and-loss-row__value--expanded')\n return (\n <>\n <div\n className={labelClasses.join(' ')}\n onClick={() => !lockExpanded && toggleExpanded()}\n style={{\n paddingLeft: depth === 0 && !hasChildren ? 28 : 16 * (depth + 1) + 2,\n }}\n >\n <span className='Layer__profit-and-loss-row__label__title'>\n {!lockExpanded && variant !== 'summation' ? (\n <ChevronDownFill\n size={16}\n className='Layer__profit-and-loss-row__label__chevron'\n />\n ) : null}\n <Text>{display_name}</Text>\n </span>\n {setSidebarScope && (\n <span\n className='Layer__profit-and-loss-row__detailed-chart-btn'\n onClick={e => {\n e.stopPropagation()\n setSidebarScope && setSidebarScope(scope ?? 'expenses')\n }}\n >\n <PieChart />\n </span>\n )}\n </div>\n <div className={valueClasses.join(' ')}>\n <Text>{amountString}</Text>\n </div>\n {canGoDeeper && hasChildren && (\n <div\n className={`Layer__profit-and-loss-row__children ${\n expanded && 'Layer__profit-and-loss-row__children--expanded'\n }`}\n >\n <div className='Layer__profit-and-loss-row__children--content'>\n {(line_items || []).map(line_item => (\n <ProfitAndLossRow\n key={line_item.display_name}\n lineItem={line_item}\n depth={depth + 1}\n maxDepth={maxDepth}\n direction={direction}\n />\n ))}\n </div>\n </div>\n )}\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst PieChart = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 12'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <g>\n <path\n d='M10.2213 7.78271C9.92969 8.47226 9.47363 9.07989 8.89297 9.55247C8.3123 10.0251 7.62471 10.3482 6.89031 10.4936C6.1559 10.6391 5.39705 10.6024 4.68009 10.3869C3.96313 10.1713 3.30989 9.78337 2.77749 9.25701C2.24509 8.73065 1.84973 8.08189 1.62598 7.36744C1.40223 6.65298 1.3569 5.8946 1.49396 5.15858C1.63102 4.42257 1.94629 3.73133 2.41221 3.14531C2.87813 2.55928 3.48051 2.09631 4.16669 1.79688'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5833 6.00033C10.5833 5.39843 10.4648 4.80244 10.2344 4.24636C10.0041 3.69028 9.66651 3.18502 9.24091 2.75942C8.8153 2.33382 8.31004 1.99621 7.75397 1.76588C7.19789 1.53554 6.60189 1.41699 6 1.41699V6.00033H10.5833Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </g>\n </svg>\n)\n\nexport default PieChart\n", "import { ProfitAndLoss } from '../../types'\n\nexport default {\n type: 'Profit_And_Loss',\n business_id: '',\n start_date: '',\n end_date: '',\n income: {\n name: 'INCOME',\n display_name: 'Income',\n value: NaN,\n line_items: null,\n },\n cost_of_goods_sold: {\n display_name: 'Cost of Goods Sold',\n name: 'COGS',\n value: NaN,\n line_items: null,\n },\n gross_profit: NaN,\n expenses: {\n name: 'EXPENSES',\n display_name: 'Expenses',\n value: NaN,\n line_items: null,\n },\n profit_before_taxes: NaN,\n taxes: {\n name: 'TAXES',\n display_name: 'Taxes',\n value: NaN,\n line_items: null,\n },\n net_profit: NaN,\n other_outflows: {\n name: 'OTHER_OUTFLOWS',\n display_name: 'Other outflows',\n value: NaN,\n line_items: null,\n },\n personal_expenses: {\n name: 'PERSONAL',\n display_name: 'Personal expenses',\n value: NaN,\n line_items: null,\n },\n fully_categorized: false,\n} as ProfitAndLoss\n", "import React, { PropsWithChildren, useEffect, useState } from 'react'\nimport { BalanceSheetContext } from '../../contexts/BalanceSheetContext'\nimport { TableProvider } from '../../contexts/TableContext'\nimport { useBalanceSheet } from '../../hooks/useBalanceSheet'\nimport { BalanceSheetDatePicker } from '../BalanceSheetDatePicker'\nimport { BalanceSheetExpandAllButton } from '../BalanceSheetExpandAllButton'\nimport { BalanceSheetTable } from '../BalanceSheetTable'\nimport { BalanceSheetTableStringOverrides } from '../BalanceSheetTable/BalanceSheetTable'\nimport { Container } from '../Container'\nimport { Loader } from '../Loader'\nimport { View } from '../View'\nimport { BALANCE_SHEET_ROWS } from './constants'\nimport { format, parse, startOfDay } from 'date-fns'\n\nexport interface BalanceSheetStringOverrides {\n balanceSheetTable?: BalanceSheetTableStringOverrides\n}\n\nexport type BalanceSheetViewProps = PropsWithChildren & {\n withExpandAllButton?: boolean\n asWidget?: boolean\n stringOverrides?: BalanceSheetStringOverrides\n}\n\nexport type BalanceSheetProps = PropsWithChildren & {\n effectiveDate?: Date\n asWidget?: boolean\n stringOverrides?: BalanceSheetStringOverrides\n}\n\nconst COMPONENT_NAME = 'balance-sheet'\n\nexport const BalanceSheet = (props: BalanceSheetProps) => {\n const balanceSheetContextData = useBalanceSheet(props.effectiveDate)\n return (\n <BalanceSheetContext.Provider value={balanceSheetContextData}>\n <BalanceSheetView\n asWidget={props.asWidget}\n stringOverrides={props.stringOverrides}\n {...props}\n />\n </BalanceSheetContext.Provider>\n )\n}\n\nconst BalanceSheetView = ({\n withExpandAllButton = true,\n asWidget = false,\n stringOverrides,\n}: BalanceSheetViewProps) => {\n const [effectiveDate, setEffectiveDate] = useState(startOfDay(new Date()))\n const { data, isLoading, refetch } = useBalanceSheet(effectiveDate)\n\n useEffect(() => {\n // Refetch only if selected effectiveDate and data's effectiveDate are different\n const d1 =\n effectiveDate &&\n format(startOfDay(effectiveDate), \"yyyy-MM-dd'T'HH:mm:ssXXX\")\n const d2 =\n data?.effective_date &&\n format(\n startOfDay(\n parse(data.effective_date, \"yyyy-MM-dd'T'HH:mm:ssXXX\", new Date()),\n ),\n \"yyyy-MM-dd'T'HH:mm:ssXXX\",\n )\n if (d1 && (!d2 || (d2 && d2 !== d1))) {\n refetch()\n }\n }, [effectiveDate])\n\n if (asWidget) {\n return (\n <TableProvider>\n <Container name={COMPONENT_NAME} asWidget={true}>\n <View\n type='panel'\n headerControls={\n <>\n <BalanceSheetDatePicker\n effectiveDate={effectiveDate}\n setEffectiveDate={setEffectiveDate}\n />\n {withExpandAllButton && <BalanceSheetExpandAllButton />}\n </>\n }\n >\n {!data || isLoading ? (\n <div className={`Layer__${COMPONENT_NAME}__loader-container`}>\n <Loader />\n </div>\n ) : (\n <BalanceSheetTable\n data={data}\n config={BALANCE_SHEET_ROWS}\n stringOverrides={stringOverrides?.balanceSheetTable}\n />\n )}\n </View>\n </Container>\n </TableProvider>\n )\n }\n\n return (\n <TableProvider>\n <View\n type='panel'\n headerControls={\n <>\n <BalanceSheetDatePicker\n effectiveDate={effectiveDate}\n setEffectiveDate={setEffectiveDate}\n />\n {withExpandAllButton && <BalanceSheetExpandAllButton />}\n </>\n }\n >\n {!data || isLoading ? (\n <div className={`Layer__${COMPONENT_NAME}__loader-container`}>\n <Loader />\n </div>\n ) : (\n <BalanceSheetTable\n data={data}\n config={BALANCE_SHEET_ROWS}\n stringOverrides={stringOverrides?.balanceSheetTable}\n />\n )}\n </View>\n </TableProvider>\n )\n}\n", "import { createContext } from 'react'\nimport { useBalanceSheet } from '../../hooks/useBalanceSheet'\n\nexport type BalanceSheetContextType = ReturnType<typeof useBalanceSheet>\nexport const BalanceSheetContext = createContext<BalanceSheetContextType>({\n data: undefined,\n isLoading: false,\n error: undefined,\n refetch: () => {},\n})\n", "import React, { createContext, useState, ReactNode } from 'react'\nimport { TableContextProps } from '../../types/table'\n\nconst defaultValue: TableContextProps = {\n expandedRows: [],\n setExpandedRows: () => {},\n expandAllRows: () => {},\n expandedAllRows: false,\n setExpandedAllRows: () => {},\n}\n\nexport const TableContext = createContext<TableContextProps>(defaultValue)\n\ninterface TableProviderProps {\n children: ReactNode\n}\n\nexport const TableProvider: React.FC<TableProviderProps> = ({ children }) => {\n const [expandedRows, setExpandedRowsState] = useState<string[]>([])\n const [expandedAllRows, setExpandedAllRows] = useState(false)\n\n const toggleRow = (rowKey: string) => {\n setExpandedRowsState(prevRows => {\n const rows = [...prevRows]\n if (rows.includes(rowKey)) {\n rows.splice(rows.indexOf(rowKey), 1)\n } else {\n rows.push(rowKey)\n }\n return rows\n })\n }\n\n const expandAllRows = (rowKeys: string[]) => {\n setExpandedRowsState(rowKeys)\n }\n\n const contextValue: TableContextProps = {\n expandedRows,\n setExpandedRows: toggleRow,\n expandAllRows,\n expandedAllRows,\n setExpandedAllRows,\n }\n\n return (\n <TableContext.Provider value={contextValue}>\n {children}\n </TableContext.Provider>\n )\n}\n", "import { useEffect } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { BalanceSheet } from '../../types'\nimport { DataModel } from '../../types/general'\nimport { format, startOfDay } from 'date-fns'\nimport useSWR from 'swr'\n\ntype UseBalanceSheet = (date?: Date) => {\n data: BalanceSheet | undefined\n isLoading: boolean\n error: unknown\n refetch: () => void\n}\n\nexport const useBalanceSheet: UseBalanceSheet = (date: Date = new Date()) => {\n const { auth, businessId, apiUrl, read, syncTimestamps, hasBeenTouched } =\n useLayerContext()\n const dateString = format(startOfDay(date), \"yyyy-MM-dd'T'HH:mm:ssXXX\")\n\n const queryKey =\n businessId &&\n dateString &&\n auth?.access_token &&\n `balance-sheet-${businessId}-${dateString}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getBalanceSheet(apiUrl, auth?.access_token, {\n params: {\n businessId,\n effectiveDate: dateString,\n },\n }),\n )\n\n const refetch = () => {\n mutate()\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.BALANCE_SHEET, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps, dateString])\n\n return { data: data?.data, isLoading, error, refetch }\n}\n", "import React from 'react'\nimport { DatePicker } from '../DatePicker'\n\nexport type BalanceSheetDatePickerProps = {\n effectiveDate: Date\n setEffectiveDate: (date: Date) => void\n}\n\nexport const BalanceSheetDatePicker = ({\n effectiveDate,\n setEffectiveDate,\n}: BalanceSheetDatePickerProps) => {\n return (\n <>\n <DatePicker\n selected={effectiveDate}\n onChange={date => date && setEffectiveDate(date as Date)}\n mode='dayPicker'\n />\n </>\n )\n}\n", "import React from 'react'\nimport { useTableExpandRow } from '../../hooks/useTableExpandRow'\nimport { Button, ButtonVariant } from '../Button'\n\nexport const BalanceSheetExpandAllButton = () => {\n const { expandedAllRows, toggleAllRows } = useTableExpandRow()\n return (\n <Button onClick={() => toggleAllRows()} variant={ButtonVariant.secondary}>\n {!expandedAllRows ? 'Expand all rows' : 'Collapse all rows'}\n </Button>\n )\n}\n", "import { useContext } from 'react'\nimport { TableContext } from '../../contexts/TableContext'\n\nexport const useTableExpandRow = () => {\n const {\n expandedAllRows,\n setExpandedAllRows,\n expandAllRows,\n expandedRows,\n setExpandedRows,\n } = useContext(TableContext)\n\n const toggleAllRows = () => {\n if (expandedAllRows) {\n setIsOpen([])\n return setExpandedAllRows(false)\n } else {\n return setExpandedAllRows(true)\n }\n }\n\n const setIsOpen = (\n rowKey: string | string[],\n withoutAllRowsUpdate?: boolean,\n ) => {\n if (!withoutAllRowsUpdate && expandedAllRows) {\n setExpandedAllRows(false)\n }\n if (Array.isArray(rowKey)) {\n return expandAllRows(rowKey)\n }\n return setExpandedRows(rowKey)\n }\n\n const isOpen = (rowKey: string) => expandedRows.includes(rowKey)\n\n return {\n isOpen,\n setIsOpen,\n expandedAllRows,\n toggleAllRows,\n }\n}\n", "import React, { useEffect } from 'react'\nimport { useTableExpandRow } from '../../hooks/useTableExpandRow'\nimport { BalanceSheet, LineItem } from '../../types'\nimport { Table, TableBody, TableCell, TableHead, TableRow } from '../Table'\n\nexport interface BalanceSheetTableStringOverrides {\n typeColumnHeader?: string\n totalColumnHeader?: string\n}\n\ntype BalanceSheetRowProps = {\n name: string\n displayName: string\n lineItem: string\n}\n\nexport const BalanceSheetTable = ({\n data,\n config,\n stringOverrides,\n}: {\n data: BalanceSheet\n config: BalanceSheetRowProps[]\n stringOverrides?: BalanceSheetTableStringOverrides\n}) => {\n const { isOpen, setIsOpen, expandedAllRows } = useTableExpandRow()\n const allRowKeys: string[] = []\n\n useEffect(() => {\n if (expandedAllRows) {\n setIsOpen(allRowKeys, true)\n }\n }, [expandedAllRows])\n\n useEffect(() => {\n setIsOpen(['assets'])\n }, [])\n\n const renderLineItem = (\n lineItem: LineItem,\n depth: number = 0,\n rowKey: string,\n rowIndex: number,\n ): React.ReactNode => {\n const expandable = !!lineItem.line_items && lineItem.line_items.length > 0\n\n const expanded = expandable ? isOpen(rowKey) : true\n\n const showChildren = expanded || expandedAllRows\n\n if (expandable) {\n allRowKeys.push(rowKey)\n }\n\n return (\n <React.Fragment key={rowKey + '-' + rowIndex}>\n <TableRow\n rowKey={rowKey + '-' + rowIndex}\n expandable={expandable}\n isExpanded={showChildren}\n handleExpand={() => setIsOpen(rowKey)}\n depth={depth}\n withDivider={depth === 0 && rowIndex > 0}\n >\n <TableCell withExpandIcon={expandable} primary={expandable}>\n {lineItem.display_name}\n </TableCell>\n <TableCell\n isCurrency={!expandable || (expandable && !expanded)}\n primary={expandable}\n >\n {(!expandable || (expandable && !expanded)) && lineItem.value}\n </TableCell>\n </TableRow>\n {showChildren &&\n lineItem.line_items &&\n lineItem.line_items.map((subItem, subIdx) =>\n renderLineItem(\n subItem,\n depth + 1,\n rowKey + ':' + subItem.name,\n subIdx,\n ),\n )}\n {showChildren && expandable && (\n <TableRow\n rowKey={rowKey + '-' + rowIndex + '--summation'}\n depth={depth + 1}\n variant='summation'\n >\n <TableCell primary>{`Total of ${lineItem.display_name}`}</TableCell>\n <TableCell primary isCurrency>\n {lineItem.value}\n </TableCell>\n </TableRow>\n )}\n </React.Fragment>\n )\n }\n\n return (\n <Table borderCollapse='collapse'>\n <TableHead>\n <TableRow isHeadRow rowKey='balance-sheet-head-row'>\n <TableCell isHeaderCell>{stringOverrides?.typeColumnHeader || \"Type\"}</TableCell>\n <TableCell isHeaderCell>{stringOverrides?.totalColumnHeader || \"Total\"}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {config.map((row, idx) => (\n <React.Fragment key={row.lineItem}>\n {data[row.lineItem as keyof BalanceSheet] &&\n renderLineItem(\n data[row.lineItem as keyof BalanceSheet] as LineItem,\n 0,\n row.lineItem,\n idx,\n )}\n </React.Fragment>\n ))}\n </TableBody>\n </Table>\n )\n}\n", "import React from 'react'\nimport { TableBodyProps } from '../../types/table'\n\nexport const TableBody = ({ children }: TableBodyProps) => {\n return <tbody className='Layer__table-body'>{children}</tbody>\n}\n", "import React from 'react'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { centsToDollars } from '../../models/Money'\nimport { TableCellProps } from '../../types/table'\nimport classNames from 'classnames'\n\nexport const TableCell = ({\n children,\n isHeaderCell,\n isCurrency,\n primary,\n withExpandIcon = false,\n}: TableCellProps) => {\n const amount = typeof children === 'number' ? children : 0\n const isPositive = amount >= 0\n const amountString = centsToDollars(Math.abs(amount))\n\n const cellClassNames = classNames(\n 'Layer__table-cell',\n (primary || isHeaderCell) && 'Layer__table-cell--primary',\n isCurrency && 'Layer__table-cell-amount',\n isCurrency && isPositive && 'Layer__table-cell-amount--positive',\n isCurrency && !isPositive && 'Layer__table-cell-amount--negative',\n )\n\n if (isHeaderCell) {\n return (\n <th className={cellClassNames}>\n <span className='Layer__table-cell-content'>{children}</span>\n </th>\n )\n }\n\n return (\n <td className={cellClassNames}>\n <span className='Layer__table-cell-content'>\n {withExpandIcon && (\n <ChevronDownFill\n className='Layer__table-row--expand-icon'\n size={16}\n />\n )}\n {isCurrency ? amountString : children}{' '}\n </span>\n </td>\n )\n}\n", "import React from 'react'\nimport { TableHeadProps } from '../../types/table'\n\nexport const TableHead = ({ children }: TableHeadProps) => {\n return <thead className='Layer__table-header'>{children}</thead>\n}\n", "import React from 'react'\nimport { TableRowProps } from '../../types/table'\nimport classNames from 'classnames'\n\nexport const TableRow: React.FC<TableRowProps> = ({\n rowKey,\n children,\n depth = 0,\n expandable = false,\n isExpanded = false,\n handleExpand,\n variant = expandable ? 'expandable' : 'default',\n withDivider,\n withDividerPosition = 'top',\n isHeadRow = false,\n}) => {\n const toggleExpanded = () => {\n if (variant === 'summation' || !expandable) return\n handleExpand && handleExpand()\n }\n\n const rowClassNames = classNames([\n 'Layer__table-row',\n !isHeadRow && `Layer__table-row--depth-${depth}`,\n !isHeadRow && `Layer__table-row--variant-${variant}`,\n !isHeadRow &&\n expandable &&\n (isExpanded\n ? 'Layer__table-row--expanded'\n : 'Layer__table-row--collapsed'),\n ])\n\n return (\n <>\n {withDivider && withDividerPosition === 'top' && (\n <tr className='Layer__table-empty-row'>\n <td colSpan={Array.isArray(children) ? children.length : 1} />\n </tr>\n )}\n\n <tr data-key={rowKey} className={rowClassNames} onClick={toggleExpanded}>\n {children}\n </tr>\n\n {withDivider && withDividerPosition === 'bottom' && (\n <tr className='Layer__table-empty-row'>\n <td colSpan={Array.isArray(children) ? children.length : 1} />\n </tr>\n )}\n </>\n )\n}\n", "import React, { useEffect, useRef } from 'react'\nimport { TableProps } from '../../types/table'\nimport classNames from 'classnames'\n\nexport const Table = ({\n componentName,\n children,\n borderCollapse = 'separate',\n bottomSpacing = true,\n}: TableProps) => {\n const tableRef = useRef<HTMLTableElement>(null)\n const prevChildrenRef = useRef<string[]>([])\n\n useEffect(() => {\n if (tableRef.current) {\n const tbody = tableRef.current.querySelector('tbody')\n const rows = tbody ? Array.from(tbody.querySelectorAll('tr')) : []\n\n const prevChildrenArray = prevChildrenRef.current\n const currentChildren = rows.map(\n child =>\n child.getAttribute('data-key') && {\n key: child.getAttribute('data-key'),\n child,\n },\n )\n const newChildrenKeys: string[] = []\n\n const newChildrenArray = currentChildren.filter(el => {\n if (el && el.key) {\n newChildrenKeys.push(el.key)\n }\n return el && el.key && !prevChildrenArray.includes(el.key)\n })\n\n newChildrenArray.forEach((row, index: number) => {\n const rowKey = row && row.key\n if (rowKey && !row.child.classList.contains('Layer__table-empty-row')) {\n row.child.classList.add('Layer__table-row--anim-starting-state')\n\n setTimeout(() => {\n row.child.classList.add('Layer__table-row--anim-complete-state')\n row.child.classList.remove('Layer__table-row--anim-starting-state')\n }, 15 * index)\n }\n })\n\n prevChildrenRef.current = newChildrenKeys as string[]\n }\n }, [children])\n\n const tableWrapperClassNames = classNames(\n 'Layer__table-wrapper',\n bottomSpacing && 'Layer__table-wrapper--bottom-spacing',\n )\n\n const tableClassNames = classNames(\n 'Layer__table',\n componentName && `Layer__${componentName}__table`,\n borderCollapse && `Layer__table__${borderCollapse}-rows`,\n )\n return (\n <div className={tableWrapperClassNames}>\n <table className={tableClassNames} ref={tableRef}>\n {children}\n </table>\n </div>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport { ViewHeader } from '../../components/ViewHeader'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { parseStylesFromThemeConfig } from '../../utils/colors'\nimport { Panel } from '../Panel'\nimport classNames from 'classnames'\n\nexport interface ViewProps {\n children: ReactNode\n title?: string\n headerControls?: ReactNode\n type?: 'default' | 'panel'\n withSidebar?: boolean\n sidebar?: ReactNode\n viewClassName?: string\n}\n\nexport const View = ({\n title,\n children,\n headerControls,\n type,\n withSidebar = false,\n sidebar,\n viewClassName,\n}: ViewProps) => {\n const { theme } = useLayerContext()\n const styles = parseStylesFromThemeConfig(theme)\n\n const viewClassNames = classNames(\n 'Layer__view',\n type === 'panel' && 'Layer__view--panel',\n viewClassName,\n )\n\n return (\n <div className={viewClassNames} style={{ ...styles }}>\n <ViewHeader title={title} controls={headerControls} />\n {withSidebar ? (\n <Panel sidebarIsOpen={true} sidebar={sidebar} defaultSidebarHeight>\n <div className='Layer__view-main'>{children}</div>\n </Panel>\n ) : (\n <div className='Layer__view-main'>{children}</div>\n )}\n </div>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport { Heading } from '../Typography'\n\nexport interface ViewHeaderProps {\n title?: string\n controls?: ReactNode\n}\n\nexport const ViewHeader = ({ title, controls }: ViewHeaderProps) => {\n return (\n <div className='Layer__view-header'>\n <div className='Layer__view-header__content'>\n {title && <Heading>{title}</Heading>}\n {controls && (\n <div className='Layer__view-header__controls'>{controls}</div>\n )}\n </div>\n </div>\n )\n}\n", "import React, { ReactNode, RefObject, useEffect, useState } from 'react'\nimport classNames from 'classnames'\n\nexport interface PanelProps {\n children: ReactNode\n className?: string\n sidebar?: ReactNode\n sidebarIsOpen?: boolean\n header?: ReactNode\n parentRef?: RefObject<HTMLDivElement>\n defaultSidebarHeight?: boolean\n}\n\nexport const Panel = ({\n children,\n className,\n sidebar,\n header,\n sidebarIsOpen,\n parentRef,\n defaultSidebarHeight = false,\n}: PanelProps) => {\n const [sidebarHeight, setSidebarHeight] = useState(0)\n\n useEffect(() => {\n if (parentRef?.current?.offsetHeight) {\n setSidebarHeight(parentRef?.current?.offsetHeight - 1)\n }\n }, [parentRef?.current?.offsetHeight, sidebarIsOpen])\n\n const sidebarClass = classNames(\n 'Layer__panel__sidebar',\n defaultSidebarHeight && 'Layer__panel__sidebar--default',\n )\n\n return (\n <div\n className={classNames(\n 'Layer__panel',\n className,\n sidebarIsOpen && 'Layer__panel--open',\n )}\n >\n <div className={'Layer__panel__content'}>\n {header}\n {children}\n </div>\n {sidebar && (\n <div\n className={sidebarClass}\n style={\n !defaultSidebarHeight\n ? {\n maxHeight:\n sidebarHeight > 0 && sidebarIsOpen ? sidebarHeight : 0,\n }\n : {}\n }\n >\n <div className='Layer__panel__sidebar-content'>{sidebar}</div>\n </div>\n )}\n </div>\n )\n}\n", "export const BALANCE_SHEET_ROWS = [\n {\n name: 'Assets',\n displayName: 'Assets',\n lineItem: 'assets',\n },\n {\n name: 'LiabilitiesAndEquity',\n displayName: 'Liabilities & Equity',\n lineItem: 'liabilities_and_equity',\n },\n]\n", "import React, { useState } from 'react'\nimport { StatementOfCashFlowContext } from '../../contexts/StatementOfCashContext'\nimport { TableProvider } from '../../contexts/TableContext'\nimport { useStatementOfCashFlow } from '../../hooks/useStatementOfCashFlow'\nimport { DatePicker } from '../DatePicker'\nimport { Loader } from '../Loader'\nimport { StatementOfCashFlowTable } from '../StatementOfCashFlowTable'\nimport { View } from '../View'\nimport { STATEMENT_OF_CASH_FLOW_ROWS } from './constants'\nimport { startOfDay, subWeeks } from 'date-fns'\nimport { StatementOfCashFlowTableStringOverrides } from '../StatementOfCashFlowTable/StatementOfCashFlowTable'\n\nconst COMPONENT_NAME = 'statement-of-cash-flow'\n\nexport interface StatementOfCashFlowStringOverrides {\n statementOfCashFlowTable?: StatementOfCashFlowTableStringOverrides\n}\n\nexport const StatementOfCashFlow = ({ stringOverrides }: { stringOverrides?: StatementOfCashFlowStringOverrides }) => {\n const cashContextData = useStatementOfCashFlow()\n return (\n <StatementOfCashFlowContext.Provider value={cashContextData}>\n <StatementOfCashFlowView stringOverrides={stringOverrides} />\n </StatementOfCashFlowContext.Provider>\n )\n}\n\nconst StatementOfCashFlowView = ( { stringOverrides }: {stringOverrides?: StatementOfCashFlowStringOverrides }) => {\n const [startDate, setStartDate] = useState(\n startOfDay(subWeeks(new Date(), 4)),\n )\n const [endDate, setEndDate] = useState(startOfDay(new Date()))\n const { data, isLoading, refetch } = useStatementOfCashFlow(\n startDate,\n endDate,\n )\n\n const handleDateChange = (dates: [Date | null, Date | null]) => {\n if (dates[0]) {\n setStartDate(startOfDay(dates[0]))\n }\n if (dates[1]) {\n setEndDate(startOfDay(dates[1]))\n }\n\n if (dates[0] && dates[1]) {\n refetch()\n }\n }\n\n return (\n <TableProvider>\n <View\n type='panel'\n headerControls={\n <>\n <DatePicker\n selected={[startDate, endDate]}\n onChange={dates =>\n handleDateChange(dates as [Date | null, Date | null])\n }\n dateFormat='MMM d'\n mode='dayRangePicker'\n />\n </>\n }\n >\n {!data || isLoading ? (\n <div className={`Layer__${COMPONENT_NAME}__loader-container`}>\n <Loader />\n </div>\n ) : (\n <StatementOfCashFlowTable\n data={data}\n config={STATEMENT_OF_CASH_FLOW_ROWS}\n stringOverrides={stringOverrides?.statementOfCashFlowTable}\n />\n )}\n </View>\n </TableProvider>\n )\n}\n", "import { createContext } from 'react'\nimport { useStatementOfCashFlow } from '../../hooks/useStatementOfCashFlow'\n\nexport type StatementOfCashFlowContextType = ReturnType<\n typeof useStatementOfCashFlow\n>\nexport const StatementOfCashFlowContext =\n createContext<StatementOfCashFlowContextType>({\n data: undefined,\n isLoading: false,\n error: undefined,\n refetch: () => {},\n })\n", "import { useEffect } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { StatementOfCashFlow } from '../../types'\nimport { DataModel } from '../../types/general'\nimport { format, startOfDay } from 'date-fns'\nimport useSWR from 'swr'\n\ntype UseStatementOfCashFlow = (\n startDate?: Date,\n endDate?: Date,\n) => {\n data: StatementOfCashFlow | undefined\n isLoading: boolean\n error: unknown\n refetch: () => void\n}\n\nexport const useStatementOfCashFlow: UseStatementOfCashFlow = (\n startDate: Date = new Date(),\n endDate: Date = new Date(),\n) => {\n const { auth, businessId, apiUrl, read, syncTimestamps, hasBeenTouched } =\n useLayerContext()\n const startDateString = format(\n startOfDay(startDate),\n \"yyyy-MM-dd'T'HH:mm:ssXXX\",\n )\n const endDateString = format(startOfDay(endDate), \"yyyy-MM-dd'T'HH:mm:ssXXX\")\n\n const queryKey =\n businessId &&\n startDateString &&\n endDateString &&\n auth?.access_token &&\n `statement-of-cash-${businessId}-${startDateString}-${endDateString}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getStatementOfCashFlow(apiUrl, auth?.access_token, {\n params: {\n businessId,\n startDate: startDateString,\n endDate: endDateString,\n },\n }),\n )\n\n const refetch = () => {\n mutate()\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.STATEMENT_OF_CASH_FLOWS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps, startDateString, endDateString])\n\n return { data: data?.data, isLoading, error, refetch }\n}\n", "import React from 'react'\nimport { useTableExpandRow } from '../../hooks/useTableExpandRow'\nimport { StatementOfCashFlow } from '../../types'\nimport { LineItem } from '../../types/line_item'\nimport { Table, TableHead, TableBody, TableRow, TableCell } from '../Table'\n\ntype StatementOfCashFlowRowProps = {\n name: string\n displayName: string\n lineItem: string | undefined\n summarize: boolean\n type: string\n}\n\nexport interface StatementOfCashFlowTableStringOverrides {\n typeColumnHeader?: string\n totalColumnHeader?: string\n}\n\nexport const StatementOfCashFlowTable = ({\n data,\n config,\n stringOverrides,\n}: {\n data: StatementOfCashFlow\n config: StatementOfCashFlowRowProps[]\n stringOverrides?: StatementOfCashFlowTableStringOverrides\n}) => {\n const { isOpen, setIsOpen } = useTableExpandRow()\n\n const renderLineItem = (\n lineItem: LineItem,\n depth: number = 0,\n rowKey: string,\n rowIndex: number,\n ): React.ReactNode => {\n const expandable = !!lineItem.line_items && lineItem.line_items.length > 0\n const expanded = expandable ? isOpen(rowKey) : true\n\n return (\n <React.Fragment key={rowKey + '-' + rowIndex}>\n <TableRow\n rowKey={rowKey + '-' + rowIndex}\n expandable={expandable}\n isExpanded={expanded}\n handleExpand={() => setIsOpen(rowKey)}\n depth={depth}\n >\n <TableCell withExpandIcon={expandable} primary={expandable}>\n {lineItem.display_name}\n </TableCell>\n <TableCell\n isCurrency={!expandable || (expandable && !expanded)}\n primary={expandable}\n >\n {(!expandable || (expandable && !expanded)) && lineItem.value}\n </TableCell>\n </TableRow>\n {expanded &&\n lineItem.line_items &&\n lineItem.line_items.map((subItem, subIdx) =>\n renderLineItem(\n subItem,\n depth + 1,\n rowKey + ':' + subItem.name,\n subIdx,\n ),\n )}\n {expanded && expandable && (\n <TableRow\n rowKey={rowKey + '-' + rowIndex + '--summation'}\n depth={depth + 1}\n variant='summation'\n >\n <TableCell primary>{`Total of ${lineItem.display_name}`}</TableCell>\n <TableCell primary isCurrency>\n {lineItem.value}\n </TableCell>\n </TableRow>\n )}\n </React.Fragment>\n )\n }\n\n return (\n <Table borderCollapse='collapse'>\n <TableHead>\n <TableRow rowKey='soc-flow-head-row' isHeadRow>\n <TableCell isHeaderCell>{stringOverrides?.typeColumnHeader || \"Type\"}</TableCell>\n <TableCell isHeaderCell>{stringOverrides?.totalColumnHeader || \"Total\"}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {config.map((row, idx) => {\n if (row.type === 'line_item') {\n return (\n <React.Fragment key={row.lineItem}>\n {data[row.lineItem as keyof StatementOfCashFlow] &&\n renderLineItem(\n data[row.lineItem as keyof StatementOfCashFlow] as LineItem,\n 0,\n row.lineItem ? row.lineItem : '',\n idx,\n )}\n </React.Fragment>\n )\n } else {\n return (\n <TableRow rowKey={row.name + '-' + idx} variant='default'>\n <TableCell primary>{row.displayName}</TableCell>\n <TableCell primary isCurrency>\n {row.lineItem}\n </TableCell>\n </TableRow>\n )\n }\n })}\n </TableBody>\n </Table>\n )\n}\n", "export const STATEMENT_OF_CASH_FLOW_ROWS = [\n {\n name: 'FinancingActivities',\n displayName: 'Financing Activities',\n lineItem: 'financing_activities',\n type: 'line_item',\n summarize: true,\n },\n {\n name: 'InvestingActivities',\n displayName: 'Investing Activities',\n lineItem: 'investing_activities',\n type: 'line_item',\n summarize: true,\n },\n {\n name: 'OperatingActivities',\n displayName: 'Operating Activities',\n lineItem: 'operating_activities',\n type: 'line_item',\n summarize: true,\n },\n {\n name: 'PeriodNetCashIncrease',\n displayName: 'Net Cash Increase For Period',\n lineItem: 'period_net_cash_increase',\n type: 'summary_value',\n summarize: false,\n },\n {\n name: 'CashAtEndOfPeriod',\n displayName: 'Cash at End of Period',\n lineItem: 'cash_at_end_of_period',\n type: 'summary_value',\n summarize: false,\n },\n]\n\nexport const ADJUSTMENTS_ROW_NAME = 'Adjustments to Net Income'\n", "import React, { useContext, useState } from 'react'\nimport { BREAKPOINTS } from '../../config/general'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { LedgerAccountsContext } from '../../contexts/LedgerAccountsContext'\nimport { useChartOfAccounts } from '../../hooks/useChartOfAccounts'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { useLedgerAccounts } from '../../hooks/useLedgerAccounts'\nimport { ChartOfAccountsTable } from '../ChartOfAccountsTable'\nimport { Container } from '../Container'\nimport { LedgerAccount } from '../LedgerAccount'\nimport { ChartOfAccountsTableStringOverrides } from '../ChartOfAccountsTable/ChartOfAccountsTable'\nimport { LedgerAccountStringOverrides } from '../LedgerAccount/LedgerAccountIndex'\n\nexport type View = 'mobile' | 'tablet' | 'desktop'\n\nexport interface ChartOfAccountsStringOverrides {\n chartOfAccountsTable?: ChartOfAccountsTableStringOverrides\n ledgerAccount?: LedgerAccountStringOverrides\n}\n\nexport interface ChartOfAccountsProps {\n asWidget?: boolean\n withDateControl?: boolean\n withExpandAllButton?: boolean\n stringOverrides?: ChartOfAccountsStringOverrides\n}\n\nexport const ChartOfAccounts = (props: ChartOfAccountsProps) => {\n const chartOfAccountsContextData = useChartOfAccounts({\n withDates: props.withDateControl,\n })\n const ledgerAccountsContextData = useLedgerAccounts()\n return (\n <ChartOfAccountsContext.Provider value={chartOfAccountsContextData}>\n <LedgerAccountsContext.Provider value={ledgerAccountsContextData}>\n <ChartOfAccountsContent {...props} />\n </LedgerAccountsContext.Provider>\n </ChartOfAccountsContext.Provider>\n )\n}\n\nconst ChartOfAccountsContent = ({\n asWidget,\n withDateControl,\n withExpandAllButton,\n stringOverrides,\n}: ChartOfAccountsProps) => {\n const { accountId } = useContext(LedgerAccountsContext)\n\n const [view, setView] = useState<View>('desktop')\n\n const containerRef = useElementSize<HTMLDivElement>((_a, _b, { width }) => {\n if (width) {\n if (width >= BREAKPOINTS.TABLET && view !== 'desktop') {\n setView('desktop')\n } else if (\n width <= BREAKPOINTS.TABLET &&\n width > BREAKPOINTS.MOBILE &&\n view !== 'tablet'\n ) {\n setView('tablet')\n } else if (width < BREAKPOINTS.MOBILE && view !== 'mobile') {\n setView('mobile')\n }\n }\n })\n\n return (\n <Container name='chart-of-accounts' ref={containerRef} asWidget={asWidget}>\n {accountId ? (\n <LedgerAccount view={view} containerRef={containerRef} stringOverrides={stringOverrides?.ledgerAccount}/>\n ) : (\n <ChartOfAccountsTable\n asWidget={asWidget}\n withDateControl={withDateControl}\n withExpandAllButton={withExpandAllButton}\n view={view}\n containerRef={containerRef}\n stringOverrides={stringOverrides?.chartOfAccountsTable}\n />\n )}\n </Container>\n )\n}\n", "import { createContext } from 'react'\nimport { useChartOfAccounts } from '../../hooks/useChartOfAccounts'\nimport { endOfMonth, startOfMonth } from 'date-fns'\n\nexport type ChartOfAccountsContextType = ReturnType<typeof useChartOfAccounts>\nexport const ChartOfAccountsContext = createContext<ChartOfAccountsContextType>(\n {\n data: undefined,\n isLoading: false,\n isValidating: false,\n error: undefined,\n refetch: () => Promise.resolve(undefined),\n create: () => Promise.resolve(undefined),\n form: undefined,\n sendingForm: false,\n apiError: undefined,\n addAccount: () => {},\n editAccount: () => {},\n cancelForm: () => {},\n changeFormData: () => {},\n submitForm: () => {},\n dateRange: {\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n },\n changeDateRange: () => {},\n },\n)\n", "import { createContext } from 'react'\nimport { useLedgerAccounts } from '../../hooks/useLedgerAccounts'\n\nexport type LedgerAccountsContextType = ReturnType<typeof useLedgerAccounts>\nexport const LedgerAccountsContext = createContext<LedgerAccountsContextType>({\n data: undefined,\n entryData: undefined,\n isLoading: false,\n isLoadingEntry: false,\n isValidating: false,\n isValidatingEntry: false,\n error: undefined,\n errorEntry: undefined,\n refetch: () => {},\n accountId: undefined,\n setAccountId: () => {},\n selectedEntryId: undefined,\n setSelectedEntryId: () => {},\n closeSelectedEntry: () => {},\n})\n", "import { useEffect, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { NORMALITY_OPTIONS } from '../../components/ChartOfAccountsForm/constants'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { FormError, DateRange, Direction, NewAccount } from '../../types'\nimport {\n ChartWithBalances,\n EditAccount,\n LedgerAccountBalance,\n} from '../../types/chart_of_accounts'\nimport { BaseSelectOption, DataModel } from '../../types/general'\nimport { endOfMonth, formatISO, startOfMonth } from 'date-fns'\nimport useSWR from 'swr'\n\nconst validate = (formData?: ChartOfAccountsForm) => {\n const errors: FormError[] = []\n\n const nameError = validateName(formData)\n if (nameError) {\n errors.push(nameError)\n }\n const normalityError = validateNormality(formData)\n if (normalityError) {\n errors.push(normalityError)\n }\n const typeError = validateType(formData)\n if (typeError) {\n errors.push(typeError)\n }\n\n return errors\n}\n\nconst revalidateField = (fieldName: string, formData?: ChartOfAccountsForm) => {\n switch (fieldName) {\n case 'name': {\n const nameError = validateName(formData)\n if (nameError) {\n return (formData?.errors || [])\n .filter(x => x.field !== fieldName)\n .concat([nameError])\n }\n\n return (formData?.errors || []).filter(x => x.field !== fieldName)\n }\n case 'normality': {\n const normalityError = validateNormality(formData)\n if (normalityError) {\n return (formData?.errors || [])\n .filter(x => x.field !== fieldName)\n .concat([normalityError])\n }\n\n return (formData?.errors || []).filter(x => x.field !== fieldName)\n }\n case 'type': {\n const typeError = validateType(formData)\n if (typeError) {\n return (formData?.errors || [])\n .filter(x => x.field !== fieldName)\n .concat([typeError])\n }\n\n return (formData?.errors || []).filter(x => x.field !== fieldName)\n }\n default:\n return formData?.errors\n }\n}\n\nconst validateType = (formData?: ChartOfAccountsForm) => {\n if (!formData?.data.type?.value) {\n return {\n field: 'type',\n message: 'Must be selected',\n }\n }\n\n return\n}\n\nconst validateNormality = (formData?: ChartOfAccountsForm) => {\n const stringValueNormality = formData?.data.normality?.value?.toString()\n if (stringValueNormality === undefined) {\n return {\n field: 'normality',\n message: 'Must be selected',\n }\n } else if (!['DEBIT', 'CREDIT'].includes(stringValueNormality)) {\n return {\n field: 'normality',\n message: 'Must be selected',\n }\n }\n\n return\n}\n\nconst validateName = (formData?: ChartOfAccountsForm) => {\n if (!formData?.data.name?.trim()) {\n return {\n field: 'name',\n message: 'Cannot be blank',\n }\n }\n\n return\n}\n\nexport interface ChartOfAccountsForm {\n action: 'new' | 'edit'\n accountId?: string\n data: {\n parent?: BaseSelectOption\n stable_name?: string\n name?: string\n type?: BaseSelectOption\n subType?: BaseSelectOption\n normality?: BaseSelectOption\n }\n errors?: FormError[]\n}\n\ntype Props = {\n startDate?: Date\n endDate?: Date\n withDates?: boolean\n}\n\ntype UseChartOfAccounts = () => {\n data: ChartWithBalances | undefined\n isLoading?: boolean\n isValidating?: boolean\n error?: unknown\n refetch: () => void\n create: (newAccount: NewAccount) => void\n form?: ChartOfAccountsForm\n sendingForm?: boolean\n apiError?: string\n addAccount: () => void\n editAccount: (id: string) => void\n cancelForm: () => void\n changeFormData: (\n name: string,\n value: string | BaseSelectOption | undefined,\n ) => void\n submitForm: () => void\n dateRange: DateRange\n changeDateRange: (dateRange: Partial<DateRange>) => void\n}\n\nexport const flattenAccounts = (\n accounts: LedgerAccountBalance[],\n): LedgerAccountBalance[] =>\n accounts\n .flatMap(a => [a, flattenAccounts(a.sub_accounts || [])])\n .flat()\n .filter(id => id)\n\nexport const useChartOfAccounts = (\n { withDates, startDate: initialStartDate, endDate: initialEndDate }: Props = {\n withDates: false,\n startDate: startOfMonth(new Date()),\n endDate: endOfMonth(new Date()),\n },\n) => {\n const {\n auth,\n businessId,\n apiUrl,\n touch,\n read,\n syncTimestamps,\n hasBeenTouched,\n } = useLayerContext()\n\n const [form, setForm] = useState<ChartOfAccountsForm | undefined>()\n const [sendingForm, setSendingForm] = useState(false)\n const [apiError, setApiError] = useState<string | undefined>(undefined)\n const [startDate, setStartDate] = useState(\n initialStartDate ?? startOfMonth(Date.now()),\n )\n const [endDate, setEndDate] = useState(\n initialEndDate ?? endOfMonth(Date.now()),\n )\n\n const queryKey =\n businessId &&\n auth?.access_token &&\n `chart-of-accounts-${businessId}-${startDate?.valueOf()}-${endDate?.valueOf()}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getLedgerAccountBalances(apiUrl, auth?.access_token, {\n params: {\n businessId,\n startDate:\n withDates && startDate ? formatISO(startDate.valueOf()) : undefined,\n endDate:\n withDates && endDate ? formatISO(endDate.valueOf()) : undefined,\n },\n }),\n )\n\n const create = async (newAccount: NewAccount) => {\n setSendingForm(true)\n setApiError(undefined)\n\n try {\n await Layer.createAccount(apiUrl, auth?.access_token, {\n params: { businessId },\n body: newAccount,\n })\n await refetch()\n setForm(undefined)\n } catch (_err) {\n setApiError('Submit failed. Please, check your connection and try again.')\n } finally {\n setSendingForm(false)\n touch(DataModel.CHART_OF_ACCOUNTS)\n }\n }\n\n const update = async (accountData: EditAccount, accountId: string) => {\n setSendingForm(true)\n setApiError(undefined)\n\n const newAccountData = {\n ...accountData,\n }\n\n try {\n await Layer.updateAccount(apiUrl, auth?.access_token, {\n params: { businessId, accountId },\n body: newAccountData,\n })\n await refetch()\n setForm(undefined)\n } catch (_err) {\n setApiError('Submit failed. Please, check your connection and try again.')\n } finally {\n setSendingForm(false)\n touch(DataModel.CHART_OF_ACCOUNTS)\n }\n }\n\n const submitForm = () => {\n if (!form || !form.action) {\n return\n }\n\n const errors = validate(form)\n\n if (errors.length > 0) {\n setForm({\n ...form,\n errors,\n })\n\n return\n }\n\n const data = {\n name: form.data.name ?? '',\n stable_name: form.data.stable_name,\n parent_id: form.data.parent\n ? {\n type: 'AccountId' as const,\n id: form.data.parent.value as string,\n }\n : undefined,\n account_type: (form.data.type as BaseSelectOption).value.toString(),\n account_subtype: form.data.subType?.value.toString(),\n normality: form.data.normality?.value as Direction,\n }\n\n if (form.action === 'new') {\n create(data)\n return\n }\n\n if (form.action === 'edit' && form.accountId) {\n update(data, form.accountId)\n return\n }\n }\n\n const addAccount = () =>\n setForm({\n action: 'new',\n accountId: undefined,\n data: {\n parent: undefined,\n name: undefined,\n type: undefined,\n normality: undefined,\n subType: undefined,\n },\n })\n\n const editAccount = (id: string) => {\n const allAccounts = flattenAccounts(data?.data?.accounts || [])\n const found = allAccounts?.find(x => x.id === id)\n\n if (!found) {\n return\n }\n\n const parent = allAccounts.find(\n x => x.sub_accounts?.find(el => el.id === found.id),\n )\n\n setForm({\n action: 'edit',\n accountId: id,\n data: {\n parent: parent\n ? {\n value: parent.id,\n label: parent.name,\n }\n : undefined,\n stable_name: found.stable_name,\n name: found.name,\n type: {\n value: found.account_type.value,\n label: found.account_type.display_name,\n },\n\n subType: found.account_subtype\n ? {\n value: found.account_subtype?.value,\n label: found.account_subtype?.display_name,\n }\n : undefined,\n normality: NORMALITY_OPTIONS.find(\n normalityOption => normalityOption.value == found.normality,\n ),\n },\n })\n }\n\n const cancelForm = () => setForm(undefined)\n\n const changeFormData = (\n fieldName: string,\n value: string | BaseSelectOption | undefined,\n ) => {\n if (!form) {\n return\n }\n\n let newFormData = {\n ...form,\n data: {\n ...form.data,\n [fieldName]: value,\n },\n }\n\n /* When setting the parent field, automatically inherit the parent's type & normality fields */\n if (fieldName === 'parent') {\n const allAccounts = flattenAccounts(data?.data?.accounts || [])\n const foundParent = allAccounts?.find(\n x => x.id === (value as BaseSelectOption).value,\n )\n if (foundParent) {\n newFormData = {\n ...newFormData,\n data: {\n ...newFormData.data,\n /* Inherit the parent's type */\n type: {\n value: foundParent.account_type.value,\n label: foundParent.account_type.display_name,\n },\n\n /* If the parent has a subtype, inherit it */\n subType: foundParent.account_subtype\n ? {\n value: foundParent.account_subtype?.value,\n label: foundParent.account_subtype?.display_name,\n }\n : undefined,\n\n /* Inherit the parent's normality */\n normality: NORMALITY_OPTIONS.find(\n normalityOption => normalityOption.value == foundParent.normality,\n ),\n },\n }\n }\n }\n\n const errors = revalidateField(fieldName, newFormData)\n\n setForm({\n ...newFormData,\n errors,\n })\n }\n\n const changeDateRange = ({\n startDate: newStartDate,\n endDate: newEndDate,\n }: Partial<DateRange>) => {\n newStartDate && setStartDate(newStartDate)\n newEndDate && setEndDate(newEndDate)\n }\n\n const refetch = () => mutate()\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.CHART_OF_ACCOUNTS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps, startDate, endDate])\n\n return {\n data: data?.data,\n isLoading,\n isValidating,\n error,\n refetch,\n create,\n form,\n sendingForm,\n apiError,\n addAccount,\n editAccount,\n cancelForm,\n changeFormData,\n submitForm,\n dateRange: { startDate, endDate },\n changeDateRange,\n }\n}\n", "import { Direction } from '../../types'\nimport { BaseSelectOption } from '../../types/general'\n\nexport const LEDGER_ACCOUNT_TYPES: BaseSelectOption[] = [\n {\n value: 'ASSET',\n label: 'Assets',\n },\n {\n value: 'LIABILITY',\n label: 'Liabilities',\n },\n {\n value: 'EQUITY',\n label: 'Equities',\n },\n {\n value: 'REVENUE',\n label: 'Revenue',\n },\n {\n value: 'EXPENSE',\n label: 'Expenses',\n },\n]\n\nexport const DEFAULT_ACCOUNT_TYPE_DIRECTION: Record<string, Direction> = {\n ASSET: Direction.DEBIT,\n LIABILITY: Direction.CREDIT,\n EQUITY: Direction.CREDIT,\n REVENUE: Direction.CREDIT,\n EXPENSE: Direction.DEBIT,\n}\n\nexport const NORMALITY_OPTIONS: BaseSelectOption[] = [\n {\n value: Direction.DEBIT,\n label: 'Debit',\n },\n {\n value: Direction.CREDIT,\n label: 'Credit',\n },\n]\n\nexport const ASSET_LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n {\n value: 'BANK_ACCOUNTS',\n label: 'Bank Accounts',\n },\n {\n value: 'ACCOUNTS_RECEIVABLE',\n label: 'Accounts Receivable',\n },\n {\n value: 'INVENTORY',\n label: 'Inventory',\n },\n {\n value: 'PAYMENT_PROCESSOR_CLEARING_ACCOUNT',\n label: 'Payment Processor Clearing Accounts',\n },\n {\n value: 'FIXED_ASSET',\n label: 'Fixed Assets',\n },\n {\n value: 'CASH',\n label: 'Cash',\n },\n {\n value: 'UNDEPOSITED_FUNDS',\n label: 'Undeposited Funds',\n },\n]\n\nexport const LIABILITY_LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n {\n value: 'LIABILITY',\n label: 'Liabilities',\n },\n {\n value: 'ACCOUNTS_PAYABLE',\n label: 'Accounts Payable',\n },\n {\n value: 'CREDIT_CARD',\n label: 'Credit Cards',\n },\n {\n value: 'SHAREHOLDER_LOAN',\n label: 'Shareholder Loans',\n },\n {\n value: 'PAYROLL_LIABILITY',\n label: 'Payroll Liabilities',\n },\n {\n value: 'SALES_TAXES_PAYABLE',\n label: 'Sales Taxes Payable',\n },\n {\n value: 'LINE_OF_CREDIT',\n label: 'Lines of Credit',\n },\n {\n value: 'NOTES_PAYABLE',\n label: 'Notes Payable',\n },\n {\n value: 'TIPS',\n label: 'Tips',\n },\n {\n value: 'UNEARNED_REVENUE',\n label: 'Unearned Revenue',\n },\n {\n value: 'UNDEPOSITED_OUTFLOWS',\n label: 'Undeposited Outflows',\n },\n]\nexport const EQUITY_LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n {\n value: 'CONTRIBUTIONS',\n label: 'Contributions',\n },\n {\n value: 'DISTRIBUTIONS',\n label: 'Distributions',\n },\n {\n value: 'COMMON_STOCK',\n label: 'Common Stock',\n },\n {\n value: 'ADDITIONAL_PAID_IN_CAPITAL',\n label: 'Additional Paid In Capital',\n },\n {\n value: 'RETAINED_EARNINGS',\n label: 'Retained Earnings',\n },\n {\n value: 'ACCUMULATED_ADJUSTMENTS',\n label: 'Accumulated Adjustments',\n },\n {\n value: 'OPENING_BALANCE_EQUITY',\n label: 'Opening Balance Equity',\n },\n]\n\nexport const REVENUE_LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n {\n value: 'SALES',\n label: 'Sales',\n },\n {\n value: 'UNCATEGORIZED_REVENUE',\n label: 'Uncategorized Revenue',\n },\n {\n value: 'RETURNS_ALLOWANCES',\n label: 'Returns & Allowances',\n },\n]\n\nexport const EXPENSE_LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n {\n value: 'COGS',\n label: 'COGS',\n },\n {\n value: 'OPERATING_EXPENSES',\n label: 'Operating Expenses',\n },\n {\n value: 'PAYROLL',\n label: 'Payroll',\n },\n {\n value: 'TAXES_LICENSES',\n label: 'Taxes & Licenses',\n },\n {\n value: 'BAD_DEBT',\n label: 'Bad Debt',\n },\n {\n value: 'CHARITABLE_CONTRIBUTIONS',\n label: 'Charitable Contributions',\n },\n]\n\nexport const LEDGER_ACCOUNT_SUBTYPES: BaseSelectOption[] = [\n ...ASSET_LEDGER_ACCOUNT_SUBTYPES,\n ...LIABILITY_LEDGER_ACCOUNT_SUBTYPES,\n ...EQUITY_LEDGER_ACCOUNT_SUBTYPES,\n ...REVENUE_LEDGER_ACCOUNT_SUBTYPES,\n ...EXPENSE_LEDGER_ACCOUNT_SUBTYPES,\n]\n\nexport const LEDGER_ACCOUNT_SUBTYPES_FOR_TYPE: Record<\n string,\n BaseSelectOption[]\n> = {\n ASSET: ASSET_LEDGER_ACCOUNT_SUBTYPES,\n LIABILITY: LIABILITY_LEDGER_ACCOUNT_SUBTYPES,\n EQUITY: EQUITY_LEDGER_ACCOUNT_SUBTYPES,\n REVENUE: REVENUE_LEDGER_ACCOUNT_SUBTYPES,\n EXPENSE: EXPENSE_LEDGER_ACCOUNT_SUBTYPES,\n}\n", "import { useEffect, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { LedgerAccounts, LedgerAccountsEntry } from '../../types'\nimport { DataModel } from '../../types/general'\nimport useSWR from 'swr'\n\ntype UseLedgerAccounts = () => {\n data?: LedgerAccounts\n entryData?: LedgerAccountsEntry\n isLoading?: boolean\n isLoadingEntry?: boolean\n isValidating?: boolean\n isValidatingEntry?: boolean\n error?: unknown\n errorEntry?: unknown\n refetch: () => void\n accountId?: string\n setAccountId: (id?: string) => void\n selectedEntryId?: string\n setSelectedEntryId: (id?: string) => void\n closeSelectedEntry: () => void\n}\n\nexport const useLedgerAccounts: UseLedgerAccounts = () => {\n const { auth, businessId, apiUrl, read, syncTimestamps, hasBeenTouched } =\n useLayerContext()\n\n const [accountId, setAccountId] = useState<string | undefined>()\n const [selectedEntryId, setSelectedEntryId] = useState<string | undefined>()\n\n const queryKey =\n businessId &&\n accountId &&\n auth?.access_token &&\n `ledger-accounts-lines-${businessId}-${accountId}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getLedgerAccountsLines(apiUrl, auth?.access_token, {\n params: { businessId, accountId },\n }),\n )\n\n const {\n data: entryData,\n mutate: mutateEntryData,\n isLoading: isLoadingEntry,\n isValidating: isValdiatingEntry,\n error: errorEntry,\n } = useSWR(\n businessId &&\n selectedEntryId &&\n auth?.access_token &&\n `ledger-accounts-entry-${businessId}-${selectedEntryId}}`,\n Layer.getLedgerAccountsEntry(apiUrl, auth?.access_token, {\n params: { businessId, entryId: selectedEntryId },\n }),\n )\n\n const refetch = () => mutate()\n\n const closeSelectedEntry = () => {\n setSelectedEntryId(undefined)\n mutateEntryData()\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.LEDGER_ACCOUNTS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps, accountId])\n\n return {\n data: data?.data,\n entryData: entryData?.data,\n isLoading,\n isLoadingEntry,\n isValidating,\n isValdiatingEntry,\n error,\n errorEntry,\n refetch,\n accountId,\n setAccountId,\n selectedEntryId,\n setSelectedEntryId,\n closeSelectedEntry,\n }\n}\n", "import React, { RefObject, useContext, useState } from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { Button, ButtonVariant } from '../Button'\nimport { View } from '../ChartOfAccounts/ChartOfAccounts'\nimport { ChartOfAccountsDatePicker } from '../ChartOfAccountsDatePicker'\nimport { ChartOfAccountsRow } from '../ChartOfAccountsRow'\nimport { ChartOfAccountsSidebar } from '../ChartOfAccountsSidebar'\nimport { Header } from '../Container'\nimport { HeaderLayout } from '../Container/Header'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { Loader } from '../Loader'\nimport { Panel } from '../Panel'\nimport { Heading, HeadingSize } from '../Typography'\nimport { ChartOfAccountsFormStringOverrides } from '../ChartOfAccountsForm/ChartOfAccountsForm'\n\nconst COMPONENT_NAME = 'chart-of-accounts'\nexport type ExpandActionState = undefined | 'expanded' | 'collapsed'\n\nexport interface ChartOfAccountsTableStringOverrides {\n headerText?: string\n addAccountButtonText?: string\n nameColumnHeader?: string\n typeColumnHeader?: string\n balanceColumnHeader?: string\n subtypeColumnHeader?: string\n chartOfAccountsForm?: ChartOfAccountsFormStringOverrides\n}\n\nexport const ChartOfAccountsTable = ({\n view,\n containerRef,\n asWidget = false,\n withDateControl = false,\n withExpandAllButton = false,\n stringOverrides,\n}: {\n view: View\n containerRef: RefObject<HTMLDivElement>\n asWidget?: boolean\n withDateControl?: boolean\n withExpandAllButton?: boolean\n stringOverrides?: ChartOfAccountsTableStringOverrides\n}) => {\n const { data, isLoading, addAccount, error, isValidating, refetch, form } =\n useContext(ChartOfAccountsContext)\n\n const [expandAll, setExpandAll] = useState<ExpandActionState>()\n\n let cumulativeIndex = 0\n const accountsLength = data?.accounts.length ?? 0\n\n return (\n <Panel\n sidebar={\n <ChartOfAccountsSidebar\n parentRef={containerRef}\n stringOverrides={stringOverrides?.chartOfAccountsForm}\n />}\n sidebarIsOpen={Boolean(form)}\n parentRef={containerRef}\n >\n <Header\n className={`Layer__${COMPONENT_NAME}__header`}\n layout={withDateControl ? HeaderLayout.NEXT_LINE_ACTIONS : undefined}\n >\n <Heading\n className={`Layer__${COMPONENT_NAME}__title`}\n size={asWidget ? HeadingSize.secondary : HeadingSize.primary}\n >\n {stringOverrides?.headerText || \"Chart of Accounts\"}\n </Heading>\n <div\n className={`Layer__${COMPONENT_NAME}__actions Layer__header__actions`}\n >\n {withDateControl || withExpandAllButton ? (\n <div className='Layer__header__actions-col'>\n {withDateControl && <ChartOfAccountsDatePicker />}\n {withExpandAllButton && (\n <Button\n variant={ButtonVariant.secondary}\n onClick={() =>\n setExpandAll(\n !expandAll || expandAll === 'collapsed'\n ? 'expanded'\n : 'collapsed',\n )\n }\n >\n {!expandAll || expandAll === 'collapsed'\n ? 'Expand all rows'\n : 'Collapse all rows'}\n </Button>\n )}\n </div>\n ) : null}\n <div className='Layer__header__actions-col'>\n <Button onClick={() => addAccount()} disabled={isLoading}>\n {stringOverrides?.addAccountButtonText || \"Add Account\"}\n </Button>\n </div>\n </div>\n </Header>\n\n <table className='Layer__chart-of-accounts__table'>\n <thead>\n <tr className='Layer__table-row--header'>\n <th className='Layer__table-header Layer__coa__name'>\n {stringOverrides?.nameColumnHeader || \"Name\"}\n </th>\n <th className='Layer__table-header Layer__coa__type'>\n {stringOverrides?.typeColumnHeader || \"Type\"}\n </th>\n <th className='Layer__table-header Layer__coa__subtype Layer__mobile--hidden'>\n {stringOverrides?.subtypeColumnHeader || \"Sub-Type\"}\n </th>\n <th className='Layer__table-header Layer__coa__balance'>\n {stringOverrides?.balanceColumnHeader || \"Balance\"}\n </th>\n <th className='Layer__table-header Layer__coa__actions' />\n </tr>\n </thead>\n\n <tbody>\n {!error &&\n data?.accounts.map((account, idx) => {\n const currentCumulativeIndex = cumulativeIndex\n cumulativeIndex =\n (account.sub_accounts?.length || 0) + cumulativeIndex + 1\n\n return (\n <ChartOfAccountsRow\n key={account.id}\n account={account}\n depth={0}\n index={idx}\n cumulativeIndex={currentCumulativeIndex}\n expanded={true}\n defaultOpen={true}\n acountsLength={accountsLength}\n view={view}\n expandAll={expandAll}\n />\n )\n })}\n </tbody>\n </table>\n\n {error ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={() => refetch()}\n isLoading={isValidating || isLoading}\n />\n </div>\n ) : null}\n\n {(!data || isLoading) && !error ? (\n <div className={`Layer__${COMPONENT_NAME}__loader-container`}>\n <Loader />\n </div>\n ) : null}\n\n {!isLoading && !error && data?.accounts.length === 0 ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.info}\n title='Accounts were not found'\n description='New account can be created with \"Add Account\".'\n onRefresh={() => refetch()}\n isLoading={isValidating}\n />\n </div>\n ) : null}\n </Panel>\n )\n}\n", "import React, { useContext } from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { DatePicker } from '../DatePicker'\nimport { endOfMonth, startOfMonth } from 'date-fns'\n\nexport const ChartOfAccountsDatePicker = () => {\n const { changeDateRange, dateRange } = useContext(ChartOfAccountsContext)\n\n return (\n <DatePicker\n mode='monthPicker'\n selected={dateRange.startDate}\n onChange={date => {\n if (!Array.isArray(date)) {\n changeDateRange({\n startDate: startOfMonth(date),\n endDate: endOfMonth(date),\n })\n }\n }}\n />\n )\n}\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { LedgerAccountsContext } from '../../contexts/LedgerAccountsContext'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport Edit2 from '../../icons/Edit2'\nimport { centsToDollars } from '../../models/Money'\nimport { LedgerAccountBalance } from '../../types/chart_of_accounts'\nimport { Button, ButtonVariant, TextButton } from '../Button'\nimport { View } from '../ChartOfAccounts/ChartOfAccounts'\nimport { ExpandActionState } from '../ChartOfAccountsTable/ChartOfAccountsTable'\nimport { Text, TextWeight } from '../Typography'\nimport classNames from 'classnames'\n\ntype ChartOfAccountsRowProps = {\n account: LedgerAccountBalance\n depth?: number\n index: number\n cumulativeIndex?: number\n expanded: boolean\n acountsLength: number\n defaultOpen?: boolean\n view?: View\n expandAll?: ExpandActionState\n}\n\nconst INDENTATION = 24\n\nconst EXPANDED_STYLE = {\n height: 52,\n paddingTop: 12,\n paddingBottom: 12,\n opacity: 1,\n}\n\nconst EXPANDED_MOBILE_STYLE = {\n height: 76,\n paddingTop: 12,\n paddingBottom: 12,\n opacity: 1,\n}\n\nconst COLLAPSED_STYLE = {\n height: 0,\n paddingTop: 0,\n paddingBottom: 0,\n opacity: 0.5,\n}\n\nexport const ChartOfAccountsRow = ({\n account,\n depth = 0,\n index,\n cumulativeIndex = 0,\n expanded = false,\n defaultOpen = false,\n acountsLength,\n view,\n expandAll,\n}: ChartOfAccountsRowProps) => {\n const { form, editAccount } = useContext(ChartOfAccountsContext)\n\n const { setAccountId } = useContext(LedgerAccountsContext)\n\n const baseStyle = view === 'desktop' ? EXPANDED_STYLE : EXPANDED_MOBILE_STYLE\n\n const [isOpen, setIsOpen] = useState(defaultOpen)\n const style = expanded\n ? {\n ...baseStyle,\n transitionDelay: `${15 * index}ms`,\n }\n : {\n ...COLLAPSED_STYLE,\n transitionDelay: `${acountsLength - 15 * index}ms`,\n }\n\n const [showComponent, setShowComponent] = useState(false)\n const [prevExpandedAll, setPrevExpandedAll] = useState(expandAll)\n\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, cumulativeIndex * 50)\n\n return () => clearTimeout(timeoutId)\n }, [])\n\n useEffect(() => {\n if (prevExpandedAll !== expandAll && expandAll) {\n setIsOpen(expandAll === 'collapsed' ? false : true)\n }\n }, [expandAll])\n\n const baseClass = classNames(\n 'Layer__table-row',\n isOpen ? 'Layer__table-row--expanded' : 'Layer__table-row--collapsed',\n !expanded && 'Layer__table-row--hidden',\n `Layer__table-row--depth-${depth}`,\n form?.accountId === account.id && 'Layer__table-row--active',\n !showComponent && 'Layer__table-row--anim-starting-state',\n )\n\n const desktopRowClass = classNames(\n baseClass,\n 'Layer__chart-of-accounts__row---desktop',\n )\n const mobileRowClass = classNames(\n baseClass,\n 'Layer__chart-of-accounts__row---mobile',\n )\n\n return (\n <>\n {view === 'desktop' && (\n <tr\n className={desktopRowClass}\n onClick={e => {\n e.preventDefault()\n e.stopPropagation()\n setAccountId(account.id)\n }}\n >\n <td className='Layer__table-cell Layer__coa__name'>\n <span className='Layer__table-cell-content' style={style}>\n <span\n className='Layer__table-cell-content-indentation'\n style={{\n paddingLeft: INDENTATION * depth + 16,\n }}\n >\n {account.sub_accounts && account.sub_accounts.length > 0 && (\n <ChevronDownFill\n size={16}\n className='Layer__table__expand-icon'\n onClick={e => {\n e.stopPropagation()\n setIsOpen(!isOpen)\n }}\n />\n )}\n <span className='Layer__coa__name__text'>{account.name}</span>\n </span>\n </span>\n </td>\n <td className='Layer__table-cell Layer__coa__type'>\n <span\n className='Layer__table-cell-content Layer__mobile--hidden'\n style={style}\n >\n {account.account_type?.display_name}\n </span>\n <span\n className='Layer__table-cell-content Layer__desktop--hidden'\n style={style}\n >\n <Text\n weight={TextWeight.bold}\n className='Layer__coa__type--mobile'\n >\n {account.normality}\n </Text>\n <Text className='Layer__coa__subtype--mobile'>\n {account.account_subtype?.display_name}\n </Text>\n </span>\n </td>\n <td className='Layer__table-cell Layer__coa__subtype Layer__mobile--hidden'>\n <span className='Layer__table-cell-content' style={style}>\n {account.account_subtype?.display_name}\n </span>\n </td>\n <td className='Layer__table-cell Layer__coa__balance'>\n <span\n className='Layer__table-cell-content Layer__table-cell--amount'\n style={style}\n >\n ${centsToDollars(Math.abs(account.balance || 0))}\n </span>\n </td>\n <td className='Layer__table-cell Layer__coa__actions'>\n <span className='Layer__table-cell-content' style={style}>\n <Button\n variant={ButtonVariant.secondary}\n rightIcon={<Edit2 size={12} />}\n iconOnly={true}\n onClick={e => {\n e.preventDefault()\n e.stopPropagation()\n editAccount(account.id)\n }}\n >\n Edit\n </Button>\n </span>\n </td>\n </tr>\n )}\n\n {view === 'mobile' || view === 'tablet' ? (\n <tr\n className={mobileRowClass}\n onClick={e => {\n e.preventDefault()\n e.stopPropagation()\n setAccountId(account.id)\n }}\n >\n <td className='Layer__table-cell' colSpan={5}>\n <span\n className='Layer__table-cell-content Layer__table-cell-content-indentation'\n style={{\n paddingLeft: INDENTATION * depth + 16,\n ...style,\n }}\n >\n {account.sub_accounts && account.sub_accounts.length > 0 && (\n <ChevronDownFill\n size={16}\n className='Layer__table__expand-icon'\n onClick={e => {\n e.stopPropagation()\n setIsOpen(!isOpen)\n }}\n />\n )}\n <div className='Layer__chart-of-accounts__mobile-row-content'>\n <div className='Layer__chart-of-accounts__mobile-row-content__top-row'>\n <Text\n as='span'\n className='Layer__chart-of-accounts__mobile-row-content__name'\n >\n {account.name}\n </Text>\n <TextButton\n onClick={e => {\n e.preventDefault()\n e.stopPropagation()\n editAccount(account.id)\n }}\n >\n Edit\n </TextButton>\n </div>\n <div className='Layer__chart-of-accounts__mobile-row-content__bottom-row'>\n <div className='Layer__chart-of-accounts__mobile-row-content__types'>\n <Text as='span'>{account.normality}</Text>\n <span className='Layer__chart-of-accounts__mobile-row-content__separator' />\n <Text as='span'>Sub-Type</Text>\n </div>\n <Text\n as='span'\n className='Layer__chart-of-accounts__mobile-row-content__balance'\n >\n ${centsToDollars(Math.abs(account.balance || 0))}\n </Text>\n </div>\n </div>\n </span>\n </td>\n </tr>\n ) : null}\n\n {(account.sub_accounts || []).map((subAccount, idx) => (\n <ChartOfAccountsRow\n key={subAccount.id}\n account={subAccount}\n depth={depth + 1}\n index={idx}\n expanded={isOpen && expanded}\n cumulativeIndex={cumulativeIndex + idx + 1}\n acountsLength={(account.sub_accounts ?? []).length}\n view={view}\n expandAll={expandAll}\n />\n ))}\n </>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst Edit2 = ({ size = 18, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M12.75 2.25C12.947 2.05301 13.1808 1.89676 13.4382 1.79015C13.6956 1.68355 13.9714 1.62868 14.25 1.62868C14.5286 1.62868 14.8044 1.68355 15.0618 1.79015C15.3192 1.89676 15.553 2.05301 15.75 2.25C15.947 2.44698 16.1032 2.68083 16.2098 2.9382C16.3165 3.19557 16.3713 3.47142 16.3713 3.75C16.3713 4.02857 16.3165 4.30442 16.2098 4.56179C16.1032 4.81916 15.947 5.05302 15.75 5.25L5.625 15.375L1.5 16.5L2.625 12.375L12.75 2.25Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\nexport default Edit2\n", "import React, { RefObject } from 'react'\nimport { ChartOfAccountsForm } from '../ChartOfAccountsForm'\nimport { ChartOfAccountsFormStringOverrides } from '../ChartOfAccountsForm/ChartOfAccountsForm'\n\nexport const ChartOfAccountsSidebar = ({\n parentRef: _parentRef,\n stringOverrides,\n}: {\n parentRef?: RefObject<HTMLDivElement>\n stringOverrides?: ChartOfAccountsFormStringOverrides\n}) => {\n return <ChartOfAccountsForm stringOverrides={stringOverrides} />\n}\n", "import React, { useContext, useMemo } from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { flattenAccounts } from '../../hooks/useChartOfAccounts/useChartOfAccounts'\nimport { centsToDollars } from '../../models/Money'\nimport { Button, ButtonVariant, RetryButton, SubmitButton } from '../Button'\nimport { Input, InputGroup, Select } from '../Input'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport {\n LEDGER_ACCOUNT_SUBTYPES,\n LEDGER_ACCOUNT_SUBTYPES_FOR_TYPE,\n LEDGER_ACCOUNT_TYPES,\n NORMALITY_OPTIONS,\n} from './constants'\nimport { useParentOptions } from './useParentOptions'\n\nexport interface ChartOfAccountsFormStringOverrides {\n editModeHeader?: string\n createModeHeader?: string\n cancelButton?: string\n retryButton?: string\n saveButton?: string\n parentLabel?: string\n nameLabel?: string\n typeLabel?: string\n subTypeLabel?: string\n normalityLabel?: string\n}\n\nexport const ChartOfAccountsForm = ({ stringOverrides } : {\n stringOverrides?: ChartOfAccountsFormStringOverrides\n}) => {\n const {\n form,\n data,\n changeFormData,\n cancelForm,\n submitForm,\n sendingForm,\n apiError,\n } = useContext(ChartOfAccountsContext)\n\n const parentOptions = useParentOptions(data)\n\n const entry = useMemo(() => {\n if (form?.action === 'edit' && form.accountId) {\n return flattenAccounts(data?.accounts || []).find(\n x => x.id === form.accountId,\n )\n }\n\n return\n }, [data, form?.accountId])\n\n if (!form) {\n return\n }\n\n return (\n <form\n className='Layer__form'\n onSubmit={e => {\n e.preventDefault()\n submitForm()\n }}\n >\n <div className='Layer__chart-of-accounts__sidebar__header'>\n <Text size={TextSize.lg} weight={TextWeight.bold} className='title'>\n {form?.action === 'edit'\n ? stringOverrides?.editModeHeader || 'Edit Account'\n : stringOverrides?.createModeHeader || 'Add New Account'}\n </Text>\n <div className='actions'>\n <Button\n type='button'\n onClick={cancelForm}\n variant={ButtonVariant.secondary}\n disabled={sendingForm}\n >\n {stringOverrides?.cancelButton || \"Cancel\"}\n </Button>\n {apiError && (\n <RetryButton\n type='submit'\n processing={sendingForm}\n error={'Check connection and retry in few seconds.'}\n disabled={sendingForm}\n >\n {stringOverrides?.retryButton || \"Retry\"}\n </RetryButton>\n )}\n {!apiError && (\n <SubmitButton\n type='submit'\n noIcon={true}\n active={true}\n disabled={sendingForm}\n >\n {stringOverrides?.saveButton || \"Save\"}\n </SubmitButton>\n )}\n </div>\n </div>\n\n {apiError && (\n <Text\n size={TextSize.sm}\n className='Layer__chart-of-accounts__form__error-message'\n >\n {apiError}\n </Text>\n )}\n\n {entry && (\n <div className='Layer__chart-of-accounts__form-edit-entry'>\n <Text weight={TextWeight.bold}>{entry.name}</Text>\n <Text weight={TextWeight.bold}>\n ${centsToDollars(entry.balance || 0)}\n </Text>\n </div>\n )}\n\n <div className='Layer__chart-of-accounts__form'>\n <InputGroup name='parent' label={stringOverrides?.parentLabel || 'Parent'} inline={true}>\n <Select\n options={parentOptions}\n value={form?.data.parent}\n onChange={sel => changeFormData('parent', sel)}\n disabled={sendingForm}\n />\n </InputGroup>\n <InputGroup name='name' label={stringOverrides?.nameLabel || 'Name'} inline={true}>\n <Input\n name='name'\n placeholder='Enter name...'\n value={form?.data.name}\n isInvalid={Boolean(form?.errors?.find(x => x.field === 'name'))}\n errorMessage={form?.errors?.find(x => x.field === 'name')?.message}\n disabled={sendingForm}\n onChange={e =>\n changeFormData('name', (e.target as HTMLInputElement).value)\n }\n />\n </InputGroup>\n <InputGroup name='type' label={stringOverrides?.typeLabel || 'Type'} inline={true}>\n <Select\n options={LEDGER_ACCOUNT_TYPES}\n value={form?.data.type}\n onChange={sel => changeFormData('type', sel)}\n isInvalid={Boolean(form?.errors?.find(x => x.field === 'type'))}\n errorMessage={form?.errors?.find(x => x.field === 'type')?.message}\n disabled={\n sendingForm ||\n form.action === 'edit' ||\n form.data.parent !== undefined\n }\n />\n </InputGroup>\n <InputGroup name='subType' label={stringOverrides?.subTypeLabel || 'Sub-Type'} inline={true}>\n <Select\n options={\n form?.data.type?.value !== undefined\n ? LEDGER_ACCOUNT_SUBTYPES_FOR_TYPE[form?.data.type?.value]\n : LEDGER_ACCOUNT_SUBTYPES\n }\n value={form?.data.subType}\n onChange={sel => changeFormData('subType', sel)}\n disabled={sendingForm}\n />\n </InputGroup>\n <InputGroup name='normality' label={stringOverrides?.normalityLabel || 'Normality'} inline={true}>\n <Select\n options={NORMALITY_OPTIONS}\n value={form?.data.normality}\n isInvalid={Boolean(\n form?.errors?.find(x => x.field === 'normality'),\n )}\n errorMessage={\n form?.errors?.find(x => x.field === 'normality')?.message\n }\n onChange={sel => changeFormData('normality', sel)}\n disabled={sendingForm}\n />\n </InputGroup>\n\n <div className='actions'>\n <Button\n type='button'\n onClick={cancelForm}\n variant={ButtonVariant.secondary}\n disabled={sendingForm}\n >\n {stringOverrides?.cancelButton || \"Cancel\"}\n </Button>\n {apiError && (\n <RetryButton\n type='submit'\n processing={sendingForm}\n error={'Check connection and retry in few seconds.'}\n disabled={sendingForm}\n >\n {stringOverrides?.retryButton || \"Retry\"}\n </RetryButton>\n )}\n {!apiError && (\n <SubmitButton\n type='submit'\n noIcon={true}\n active={true}\n disabled={sendingForm}\n >\n {stringOverrides?.saveButton || \"Save\"}\n </SubmitButton>\n )}\n </div>\n </div>\n </form>\n )\n}\n", "import React, { useMemo } from 'react'\nimport { flattenAccounts } from '../../hooks/useChartOfAccounts/useChartOfAccounts'\nimport { ChartWithBalances } from '../../types/chart_of_accounts'\nimport { BaseSelectOption } from '../../types/general'\n\nexport const useParentOptions = (\n data?: ChartWithBalances,\n): BaseSelectOption[] =>\n useMemo(\n () =>\n flattenAccounts(data?.accounts || [])\n .sort((a, b) => (a?.name && b?.name ? a.name.localeCompare(b.name) : 0))\n .map(x => {\n return {\n label: x.name,\n value: x.id,\n }\n }),\n [data?.accounts?.length],\n )\n", "import React, {\n RefObject,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { LedgerAccountsContext } from '../../contexts/LedgerAccountsContext'\nimport { flattenAccounts } from '../../hooks/useChartOfAccounts/useChartOfAccounts'\nimport { centsToDollars } from '../../models/Money'\nimport { BackButton } from '../Button'\nimport { View } from '../ChartOfAccounts/ChartOfAccounts'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { LedgerAccountEntryDetails } from '../LedgerAccountEntryDetails'\nimport { Loader } from '../Loader'\nimport { Pagination } from '../Pagination'\nimport { Panel } from '../Panel'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport { LedgerAccountRow } from './LedgerAccountRow'\nimport classNames from 'classnames'\nimport { LedgerAccountEntryDetailsStringOverrides } from '../LedgerAccountEntryDetails/LedgerAccountEntryDetails'\n\ninterface LedgerEntriesTableStringOverrides {\n dateColumnHeader?: string\n journalIdColumnHeader?: string\n sourceColumnHeader?: string\n debitColumnHeader?: string\n creditColumnHeader?: string\n runningBalanceColumnHeader?: string\n}\n\nexport interface LedgerAccountStringOverrides {\n ledgerEntryDetail?: LedgerAccountEntryDetailsStringOverrides\n ledgerEntriesTable?: LedgerEntriesTableStringOverrides\n}\n\nexport interface LedgerAccountProps {\n view: View\n containerRef: RefObject<HTMLDivElement>\n pageSize?: number\n stringOverrides?: LedgerAccountStringOverrides\n}\n\nexport const LedgerAccount = ({\n containerRef,\n pageSize = 15,\n view,\n stringOverrides,\n}: LedgerAccountProps) => {\n const [currentPage, setCurrentPage] = useState(1)\n const [initialLoad, setInitialLoad] = useState(true)\n\n const { data: accountData } = useContext(ChartOfAccountsContext)\n\n const {\n data: rawData,\n error,\n isLoading,\n isValidating,\n accountId,\n setAccountId,\n selectedEntryId,\n closeSelectedEntry,\n refetch,\n } = useContext(LedgerAccountsContext)\n\n useEffect(() => {\n if (!isLoading) {\n const timeoutLoad = setTimeout(() => {\n setInitialLoad(false)\n }, 1000)\n return () => clearTimeout(timeoutLoad)\n }\n }, [isLoading])\n\n const baseClassName = classNames(\n 'Layer__ledger-account__index',\n accountId && 'open',\n )\n\n const entry = useMemo(() => {\n return flattenAccounts(accountData?.accounts || []).find(\n x => x.id === accountId,\n )\n }, [accountId])\n\n const data = useMemo(() => {\n const firstPageIndex = (currentPage - 1) * pageSize\n const lastPageIndex = firstPageIndex + pageSize\n return rawData\n ?.sort((a, b) => Date.parse(b.date) - Date.parse(a.date))\n ?.slice(firstPageIndex, lastPageIndex)\n }, [rawData, currentPage])\n\n const close = () => {\n setAccountId(undefined)\n closeSelectedEntry()\n }\n\n return (\n <Panel\n sidebar={\n <LedgerAccountEntryDetails\n stringOverrides={stringOverrides?.ledgerEntryDetail}\n />}\n sidebarIsOpen={Boolean(selectedEntryId)}\n parentRef={containerRef}\n className='Layer__ledger-account__panel'\n >\n <div className={baseClassName}>\n <div className='Layer__ledger-account__header'>\n <BackButton onClick={close} />\n <div className='Layer__ledger-account__title-container'>\n <Text\n weight={TextWeight.bold}\n className='Layer__ledger-account__title'\n >\n {entry?.name ?? ''}\n </Text>\n <div className='Layer__ledger-account__balance-container'>\n <Text\n className='Layer__ledger-account__balance-label'\n size={TextSize.sm}\n >\n Current balance\n </Text>\n <Text\n className='Layer__ledger-account__balance-value'\n size={TextSize.sm}\n >\n ${centsToDollars(entry?.balance || 0)}\n </Text>\n </div>\n </div>\n </div>\n <table className='Layer__table Layer__table--hover-effect Layer__ledger-account-table'>\n <thead>\n <tr>\n {view !== 'desktop' && <th />}\n {view === 'desktop' && (\n <>\n <th className='Layer__table-header'>\n {stringOverrides?.ledgerEntriesTable?.dateColumnHeader || \"Date\"}\n </th>\n <th className='Layer__table-header'>\n {stringOverrides?.ledgerEntriesTable?.journalIdColumnHeader || \"Journal id #\"}\n </th>\n <th className='Layer__table-header'>\n {stringOverrides?.ledgerEntriesTable?.sourceColumnHeader || \"Source\"}\n </th>\n </>\n )}\n {view !== 'mobile' && (\n <>\n <th className='Layer__table-header Layer__table-cell--amount'>\n {stringOverrides?.ledgerEntriesTable?.debitColumnHeader || \"Debit\"}\n </th>\n <th className='Layer__table-header Layer__table-cell--amount'>\n {stringOverrides?.ledgerEntriesTable?.creditColumnHeader || \"Credit\"}\n </th>\n <th className='Layer__table-header Layer__table-cell--amount'>\n {stringOverrides?.ledgerEntriesTable?.runningBalanceColumnHeader || \"Running balance\"}\n </th>\n </>\n )}\n </tr>\n </thead>\n <tbody>\n {data?.map((x, index) => (\n <LedgerAccountRow\n key={x.id}\n row={x}\n index={index}\n initialLoad={initialLoad}\n view={view}\n />\n ))}\n </tbody>\n </table>\n\n {data && (\n <div className='Layer__ledger-account__pagination'>\n <Pagination\n currentPage={currentPage}\n totalCount={rawData?.length || 0}\n pageSize={pageSize}\n onPageChange={page => setCurrentPage(page)}\n />\n </div>\n )}\n\n {error ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={() => refetch()}\n isLoading={isValidating || isLoading}\n />\n </div>\n ) : null}\n\n {(!data || isLoading) && !error ? (\n <div className={`Layer__ledger-account__loader-container`}>\n <Loader />\n </div>\n ) : null}\n\n {!isLoading && !error && data?.length === 0 ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.info}\n title='No records found'\n onRefresh={() => refetch()}\n isLoading={isValidating}\n />\n </div>\n ) : null}\n </div>\n </Panel>\n )\n}\n", "import React, { useContext, useMemo } from 'react'\nimport { LedgerAccountsContext } from '../../contexts/LedgerAccountsContext'\nimport XIcon from '../../icons/X'\nimport { centsToDollars } from '../../models/Money'\nimport { Direction } from '../../types'\nimport {\n InvoiceLedgerEntrySource,\n InvoicePaymentLedgerEntrySource,\n LedgerEntrySource,\n ManualLedgerEntrySource,\n OpeningBalanceLedgerEntrySource,\n PayoutLedgerEntrySource,\n RefundPaymentLedgerEntrySource,\n TransactionLedgerEntrySource,\n} from '../../types/ledger_accounts'\nimport { humanizeEnum } from '../../utils/format'\nimport { Badge, BadgeVariant } from '../Badge'\nimport { BackButton, Button, ButtonVariant } from '../Button'\nimport { Card } from '../Card'\nimport { DateTime } from '../DateTime'\nimport { DetailsList, DetailsListItem } from '../DetailsList'\nimport { Table } from '../Table'\nimport { TableBody } from '../TableBody'\nimport { TableCell } from '../TableCell'\nimport { TableHead } from '../TableHead'\nimport { TableRow } from '../TableRow'\nimport { Text, TextWeight } from '../Typography'\n\ninterface SourceDetailStringOverrides {\n sourceLabel?: string\n accountNameLabel?: string\n dateLabel?: string\n amountLabel?: string\n directionLabel?: string\n counterpartyLabel?: string\n invoiceNumberLabel?: string\n recipientNameLabel?: string\n memoLabel?: string\n createdByLabel?: string\n processorLabel?: string\n}\n\n/*\n\n @SerialName(\"Transaction_Ledger_Entry_Source\")\n @SerialName(\"Invoice_Ledger_Entry_Source\")\n @SerialName(\"Manual_Ledger_Entry_Source\")\n @SerialName(\"Invoice_Payment_Ledger_Entry_Source\")\n @SerialName(\"Refund_Ledger_Entry_Source\")\n @SerialName(\"Opening_Balance_Ledger_Entry_Source\")\n @SerialName(\"Payout_Ledger_Entry_Source\")\n */\nexport const SourceDetailView = (\n { source, stringOverrides }: { source: LedgerEntrySource, stringOverrides?: SourceDetailStringOverrides }\n) => {\n switch (source.type) {\n case 'Transaction_Ledger_Entry_Source': {\n const transactionSource = source as TransactionLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.accountNameLabel || 'Account name'}>\n {transactionSource.account_name}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.dateLabel || 'Date'}>\n <DateTime value={transactionSource.date} />\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.amountLabel || 'Amount'}>\n {`$${centsToDollars(transactionSource.amount)}`}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.directionLabel || 'Direction'}>\n {transactionSource.direction}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.counterpartyLabel || 'Counterparty'}>\n {transactionSource.counterparty}\n </DetailsListItem>\n </>\n )\n }\n case 'Invoice_Ledger_Entry_Source': {\n const invoiceSource = source as InvoiceLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.invoiceNumberLabel || 'Invoice number'}>\n {invoiceSource.invoice_number}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.recipientNameLabel || 'Recipient name'}>\n {invoiceSource.recipient_name}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.dateLabel || 'Date'}>\n <DateTime value={invoiceSource.date} />\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.amountLabel || 'Amount'}>\n {`$${centsToDollars(invoiceSource.amount)}`}\n </DetailsListItem>\n </>\n )\n }\n case 'Manual_Ledger_Entry_Source': {\n const manualSource = source as ManualLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.memoLabel || 'Memo'}>{manualSource.memo}</DetailsListItem>\n <DetailsListItem label={stringOverrides?.createdByLabel || 'Created by'}>\n {manualSource.created_by}\n </DetailsListItem>\n </>\n )\n }\n case 'Invoice_Payment_Ledger_Entry_Source': {\n const invoicePaymentSource = source as InvoicePaymentLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.invoiceNumberLabel || 'Invoice number'}>\n {invoicePaymentSource.invoice_number}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.amountLabel || 'Amount'}>\n {`$${centsToDollars(invoicePaymentSource.amount)}`}\n </DetailsListItem>\n </>\n )\n }\n case 'Refund_Ledger_Entry_Source': {\n const refundSource = source as RefundPaymentLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.amountLabel || 'Amount'}>\n {`$${centsToDollars(refundSource.refunded_to_customer_amount)}`}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.recipientNameLabel || 'Recipient name'}>\n {refundSource.recipient_name}\n </DetailsListItem>\n </>\n )\n }\n case 'Opening_Balance_Ledger_Entry_Source': {\n const openingBalanceSource = source as OpeningBalanceLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.accountNameLabel || 'Account name'}>\n {openingBalanceSource.account_name}\n </DetailsListItem>\n </>\n )\n }\n case 'Payout_Ledger_Entry_Source': {\n const payoutSource = source as PayoutLedgerEntrySource\n return (\n <>\n <DetailsListItem label={stringOverrides?.amountLabel || 'Amount'}>\n {`$${centsToDollars(payoutSource.paid_out_amount)}`}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.processorLabel || 'Processor'}>\n {payoutSource.processor}\n </DetailsListItem>\n </>\n )\n }\n\n default:\n return null\n }\n}\n\ninterface JournalEntryDetailsStringOverrides {\n entryTypeLabel?: string\n dateLabel?: string\n creationDateLabel?: string\n reversalLabel?: string\n}\n\ninterface LineItemsTableStringOverrides {\n lineItemsColumnHeader?: string\n debitColumnHeader?: string\n creditColumnHeader?: string\n totalRowHeader?: string\n}\n\nexport interface LedgerAccountEntryDetailsStringOverrides {\n title?: string\n transactionSource?: {\n header?: string\n details?: SourceDetailStringOverrides\n }\n journalEntry?: {\n header?: (entryId?: string) => string\n details?: JournalEntryDetailsStringOverrides\n }\n lineItemsTable?: LineItemsTableStringOverrides\n}\n\nexport const LedgerAccountEntryDetails = ({ stringOverrides } : { stringOverrides?: LedgerAccountEntryDetailsStringOverrides }) => {\n const { entryData, isLoadingEntry, closeSelectedEntry, errorEntry } =\n useContext(LedgerAccountsContext)\n\n const { totalDebit, totalCredit } = useMemo(() => {\n let totalDebit = 0\n let totalCredit = 0\n entryData?.line_items?.forEach(item => {\n if (item.direction === Direction.CREDIT) {\n totalCredit += item.amount || 0\n } else if (item.direction === Direction.DEBIT) {\n totalDebit += item.amount || 0\n }\n })\n\n return { totalDebit, totalCredit }\n }, [entryData])\n\n return (\n <div className='Layer__ledger-account__entry-details'>\n <div className='Layer__ledger-account__entry-details__back-btn'>\n <BackButton onClick={() => closeSelectedEntry()} />\n <div className='Layer__ledger-account__entry-details__title-container'>\n <Text weight={TextWeight.bold}>{stringOverrides?.title || \"Transaction details\"}</Text>\n </div>\n </div>\n <DetailsList\n title={stringOverrides?.transactionSource?.header || 'Transaction source'}\n actions={\n <Button\n rightIcon={<XIcon />}\n iconOnly={true}\n onClick={closeSelectedEntry}\n variant={ButtonVariant.secondary}\n className='Layer__details-list__close-btn'\n />\n }\n >\n <DetailsListItem\n label={stringOverrides?.transactionSource?.details?.sourceLabel || 'Source'}\n isLoading={isLoadingEntry}\n >\n <Badge>{entryData?.source?.entity_name}</Badge>\n </DetailsListItem>\n {entryData?.source?.display_description && (\n <SourceDetailView source={entryData?.source} />\n )}\n </DetailsList>\n\n <DetailsList\n title={\n stringOverrides?.journalEntry?.header ?\n stringOverrides?.journalEntry?.header(entryData?.id.substring(0, 5)) :\n `Journal Entry ${entryData?.id.substring(0, 5)}`\n }\n className='Layer__border-top'\n >\n <DetailsListItem label={stringOverrides?.journalEntry?.details?.entryTypeLabel || 'Entry type'} isLoading={isLoadingEntry}>\n {humanizeEnum(entryData?.entry_type ?? '')}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.journalEntry?.details?.dateLabel || 'Date'} isLoading={isLoadingEntry}>\n {entryData?.entry_at && <DateTime value={entryData?.entry_at} />}\n </DetailsListItem>\n <DetailsListItem label={stringOverrides?.journalEntry?.details?.creationDateLabel || 'Creation date'} isLoading={isLoadingEntry}>\n {entryData?.date && <DateTime value={entryData?.date} />}\n </DetailsListItem>\n {entryData?.reversal_id && (\n <DetailsListItem label={stringOverrides?.journalEntry?.details?.reversalLabel || 'Reversal'} isLoading={isLoadingEntry}>\n {entryData?.reversal_id.substring(0, 5)}\n </DetailsListItem>\n )}\n </DetailsList>\n\n {!isLoadingEntry && !errorEntry ? (\n <div className='Layer__ledger-account__entry-details__line-items'>\n <Card>\n <Table\n componentName='ledger-account__entry-details'\n borderCollapse='collapse'\n >\n <TableHead>\n <TableRow rowKey='soc-flow-head-row' isHeadRow>\n <TableCell>{stringOverrides?.lineItemsTable?.lineItemsColumnHeader || \"Line items\"}</TableCell>\n <TableCell>{stringOverrides?.lineItemsTable?.debitColumnHeader || \"Debit\"}</TableCell>\n <TableCell>{stringOverrides?.lineItemsTable?.creditColumnHeader || \"Credit\"}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {entryData?.line_items?.map((item, index) => (\n <TableRow\n key={`ledger-line-item-${index}`}\n rowKey={`ledger-line-item-${index}`}\n >\n <TableCell>{item.account?.name || ''}</TableCell>\n <TableCell>\n {item.direction === Direction.DEBIT && (\n <Badge variant={BadgeVariant.WARNING}>\n ${centsToDollars(item.amount || 0)}\n </Badge>\n )}\n </TableCell>\n <TableCell>\n {item.direction === Direction.CREDIT && (\n <Badge variant={BadgeVariant.SUCCESS}>\n ${centsToDollars(item.amount || 0)}\n </Badge>\n )}\n </TableCell>\n </TableRow>\n ))}\n <TableRow\n rowKey='ledger-line-item-summation'\n variant='summation'\n >\n <TableCell primary>{stringOverrides?.lineItemsTable?.totalRowHeader || \"Total\"}</TableCell>\n <TableCell isCurrency primary>\n {totalDebit || 0}\n </TableCell>\n <TableCell isCurrency primary>\n {totalCredit || 0}\n </TableCell>\n </TableRow>\n </TableBody>\n </Table>\n </Card>\n </div>\n ) : null}\n </div>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport classNames from 'classnames'\n\nexport interface CardProps {\n children: ReactNode\n className?: string\n}\n\nexport const Card = ({ children, className }: CardProps) => {\n return <div className={classNames('Layer__card', className)}>{children}</div>\n}\n", "import React from 'react'\nimport { DATE_FORMAT, TIME_FORMAT } from '../../config/general'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport { parseISO, format as formatTime } from 'date-fns'\n\ninterface DateTimeProps {\n value: string\n format?: string\n dateFormat?: string\n timeFormat?: string\n onlyDate?: boolean\n onlyTime?: boolean\n}\n\nexport const DateTime = ({\n value,\n format,\n dateFormat,\n timeFormat,\n onlyDate,\n onlyTime,\n}: DateTimeProps) => {\n if (format) {\n return (\n <Text className='Layer__datetime'>\n {formatTime(parseISO(value), format)}\n </Text>\n )\n }\n\n const date = formatTime(parseISO(value), dateFormat ?? DATE_FORMAT)\n const time = formatTime(parseISO(value), timeFormat ?? TIME_FORMAT)\n\n return (\n <Text className='Layer__datetime'>\n {!onlyTime && (\n <Text\n as='span'\n weight={TextWeight.bold}\n size={TextSize.sm}\n className='Layer__datetime__date'\n >\n {date}\n </Text>\n )}\n {!onlyDate && (\n <Text\n as='span'\n weight={TextWeight.bold}\n size={TextSize.sm}\n className='Layer__datetime__time'\n >\n {time}\n </Text>\n )}\n </Text>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport { Header } from '../Container'\nimport { Heading, HeadingSize } from '../Typography'\nimport classNames from 'classnames'\n\nexport interface DetailsListProps {\n title?: string\n className?: string\n children: ReactNode\n actions?: ReactNode\n}\n\nexport const DetailsList = ({\n title,\n children,\n className,\n actions,\n}: DetailsListProps) => {\n return (\n <div className={classNames('Layer__details-list', className)}>\n {title && (\n <Header>\n <Heading size={HeadingSize.secondary}>{title}</Heading>\n {actions && (\n <div className='Layer__details-list__actions'>{actions}</div>\n )}\n </Header>\n )}\n <ul className='Layer__details-list__list'>{children}</ul>\n </div>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport { SkeletonLoader } from '../SkeletonLoader'\nimport { Text, TextSize, TextWeight } from '../Typography'\n\nexport interface DetailsListItemProps {\n label: string\n children: ReactNode | string\n isLoading?: boolean\n}\n\nconst renderValue = (value: ReactNode | string) => {\n if (typeof value === 'string') {\n return (\n <Text weight={TextWeight.bold} size={TextSize.sm}>\n {value}\n </Text>\n )\n }\n\n return value\n}\n\nexport const DetailsListItem = ({\n label,\n children,\n isLoading,\n}: DetailsListItemProps) => {\n return (\n <li className='Layer__details-list-item'>\n <label className='Layer__details-list-item__label'>{label}</label>\n <span className='Layer__details-list-item__value'>\n {isLoading ? <SkeletonLoader /> : renderValue(children)}\n </span>\n </li>\n )\n}\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport { LedgerAccountsContext } from '../../contexts/LedgerAccountsContext'\nimport { centsToDollars } from '../../models/Money'\nimport { Direction, LedgerAccountLineItem } from '../../types'\nimport { View } from '../ChartOfAccounts/ChartOfAccounts'\nimport { Text, TextWeight } from '../Typography'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface LedgerAccountRowProps {\n row: LedgerAccountLineItem\n index: number\n initialLoad?: boolean\n view: View\n}\n\nexport const LedgerAccountRow = ({\n row,\n index,\n initialLoad,\n view,\n}: LedgerAccountRowProps) => {\n const { selectedEntryId, setSelectedEntryId, closeSelectedEntry } =\n useContext(LedgerAccountsContext)\n\n const [showComponent, setShowComponent] = useState(false)\n\n useEffect(() => {\n if (initialLoad) {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, index * 10)\n\n return () => clearTimeout(timeoutId)\n } else {\n setShowComponent(true)\n }\n }, [])\n\n if (view === 'tablet') {\n return (\n <tr\n className={classNames(\n 'Layer__table-row',\n row.entry_id === selectedEntryId && 'Layer__table-row--active',\n initialLoad && 'initial-load',\n 'Layer__table-row--with-show',\n showComponent ? 'show' : 'Layer__table-row--anim-starting-state',\n )}\n style={{ transitionDelay: `${15 * index}ms` }}\n onClick={() => {\n if (selectedEntryId === row.entry_id) {\n closeSelectedEntry()\n } else {\n setSelectedEntryId(row.entry_id)\n }\n }}\n >\n <td className='Layer__table-cell Layer__ledger-account-table__tablet-main-col'>\n <span className='Layer__table-cell-content'>\n <div className='Layer__ledger-account-table__tablet-main-col__date'>\n <Text>\n {row.date && formatTime(parseISO(row.date), DATE_FORMAT)}\n </Text>\n <Text\n weight={TextWeight.normal}\n className='Layer__ledger_account-table__journal-id'\n >\n {row.entry_id.substring(0, 5)}\n </Text>\n </div>\n <Text>{row.source?.display_description ?? ''}</Text>\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {row.direction === Direction.DEBIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {row.direction === Direction.CREDIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {`$${centsToDollars(row.running_balance)}`}\n </span>\n </td>\n </tr>\n )\n }\n\n if (view === 'mobile') {\n return (\n <tr\n className={classNames(\n 'Layer__table-row',\n row.entry_id === selectedEntryId && 'Layer__table-row--active',\n initialLoad && 'initial-load',\n 'Layer__table-row--with-show',\n showComponent ? 'show' : 'Layer__table-row--anim-starting-state',\n )}\n style={{ transitionDelay: `${15 * index}ms` }}\n onClick={() => {\n if (selectedEntryId === row.entry_id) {\n closeSelectedEntry()\n } else {\n setSelectedEntryId(row.entry_id)\n }\n }}\n >\n <td className='Layer__table-cell Layer__ledger-account-table__tablet-main-col'>\n <span className='Layer__table-cell-content'>\n <div className='Layer__ledger-account-table__tablet-main-col__date'>\n <Text>\n {row.date && formatTime(parseISO(row.date), DATE_FORMAT)}\n </Text>\n <Text\n weight={TextWeight.normal}\n className='Layer__ledger_account-table__journal-id'\n >\n {row.entry_id.substring(0, 5)}\n </Text>\n </div>\n <Text>{row.source?.display_description ?? ''}</Text>\n <div className='Layer__ledger_account-table__balances-mobile'>\n <div className='Layer__ledger_account-table__balance-item'>\n <span className='Layer__ledger_account-table__balances-mobile__label'>\n Debit\n </span>\n <span className='Layer__ledger_account-table__balances-mobile__value'>\n {' '}\n {row.direction === Direction.DEBIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </div>\n <div className='Layer__ledger_account-table__balance-item'>\n <span className='Layer__ledger_account-table__balances-mobile__label'>\n Credit\n </span>\n <span className='Layer__ledger_account-table__balances-mobile__value'>\n {row.direction === Direction.CREDIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </div>\n <div className='Layer__ledger_account-table__balance-item'>\n <span className='Layer__ledger_account-table__balances-mobile__label'>\n Running balance\n </span>\n <span className='Layer__ledger_account-table__balances-mobile__value'>\n {`$${centsToDollars(row.running_balance)}`}\n </span>\n </div>\n </div>\n </span>\n </td>\n </tr>\n )\n }\n\n return (\n <tr\n className={classNames(\n 'Layer__table-row',\n row.entry_id === selectedEntryId && 'Layer__table-row--active',\n initialLoad && 'initial-load',\n 'Layer__table-row--with-show',\n showComponent ? 'show' : 'Layer__table-row--anim-starting-state',\n )}\n style={{ transitionDelay: `${15 * index}ms` }}\n onClick={() => {\n if (selectedEntryId === row.entry_id) {\n closeSelectedEntry()\n } else {\n setSelectedEntryId(row.entry_id)\n }\n }}\n >\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {row.date && formatTime(parseISO(row.date), DATE_FORMAT)}\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {row.entry_id.substring(0, 5)}\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {row.source?.display_description ?? ''}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {row.direction === Direction.DEBIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {row.direction === Direction.CREDIT &&\n `$${centsToDollars(row?.amount || 0)}`}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n {`$${centsToDollars(row.running_balance)}`}\n </span>\n </td>\n </tr>\n )\n}\n", "import React, { useState } from 'react'\nimport { BREAKPOINTS } from '../../config/general'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport { TableProvider } from '../../contexts/TableContext'\nimport { useChartOfAccounts } from '../../hooks/useChartOfAccounts'\nimport { useElementSize } from '../../hooks/useElementSize'\nimport { useJournal } from '../../hooks/useJournal'\nimport { Container } from '../Container'\nimport { JournalTable } from '../JournalTable'\nimport { JournalTableStringOverrides } from '../JournalTable/JournalTable'\n\nexport type View = 'mobile' | 'tablet' | 'desktop'\n\nexport interface JournalConfig {\n form: {\n addEntryLinesLimit?: number\n }\n}\n\nexport interface JournalStringOverrides {\n journalTable?: JournalTableStringOverrides\n}\n\nexport interface JournalProps {\n asWidget?: boolean\n config?: JournalConfig\n stringOverrides?: JournalStringOverrides\n}\n\nexport const JOURNAL_CONFIG: JournalConfig = {\n form: {\n addEntryLinesLimit: 10,\n },\n}\n\nexport const Journal = (props: JournalProps) => {\n const JournalContextData = useJournal()\n const AccountsContextData = useChartOfAccounts()\n return (\n <ChartOfAccountsContext.Provider value={AccountsContextData}>\n <JournalContext.Provider value={JournalContextData}>\n <TableProvider>\n <JournalContent {...props} />\n </TableProvider>\n </JournalContext.Provider>\n </ChartOfAccountsContext.Provider>\n )\n}\n\nconst JournalContent = ({\n asWidget,\n config = JOURNAL_CONFIG,\n stringOverrides,\n}: JournalProps) => {\n const [view, setView] = useState<View>('desktop')\n\n const containerRef = useElementSize<HTMLDivElement>((_a, _b, { width }) => {\n if (width) {\n if (width >= BREAKPOINTS.TABLET && view !== 'desktop') {\n setView('desktop')\n } else if (\n width <= BREAKPOINTS.TABLET &&\n width > BREAKPOINTS.MOBILE &&\n view !== 'tablet'\n ) {\n setView('tablet')\n } else if (width < BREAKPOINTS.MOBILE && view !== 'mobile') {\n setView('mobile')\n }\n }\n })\n\n return (\n <Container name='journal' ref={containerRef} asWidget={asWidget}>\n <JournalTable\n view={view}\n containerRef={containerRef}\n config={config}\n stringOverrides={stringOverrides?.journalTable}\n />\n </Container>\n )\n}\n", "import { createContext } from 'react'\nimport { useJournal } from '../../hooks/useJournal'\n\nexport type JournalContextType = ReturnType<typeof useJournal>\nexport const JournalContext = createContext<JournalContextType>({\n data: undefined,\n isLoading: false,\n error: undefined,\n refetch: () => {},\n selectedEntryId: undefined,\n setSelectedEntryId: () => {},\n closeSelectedEntry: () => {},\n addEntry: () => {},\n addEntryLine: () => {},\n removeEntryLine: () => {},\n create: () => {},\n changeFormData: () => {},\n submitForm: () => {},\n cancelForm: () => {},\n form: undefined,\n setForm: () => {},\n sendingForm: false,\n apiError: undefined,\n})\n", "import { useEffect, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { get } from '../../api/layer/authenticated_http'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { Direction, FormError, FormErrorWithId } from '../../types'\nimport { LedgerAccountBalance } from '../../types/chart_of_accounts'\nimport { BaseSelectOption, DataModel } from '../../types/general'\nimport {\n JournalEntry,\n JournalEntryLineItem,\n NewApiJournalEntry,\n NewFormJournalEntry,\n} from '../../types/journal'\nimport { getAccountIdentifierPayload } from '../../utils/journal'\nimport { flattenAccounts } from '../useChartOfAccounts/useChartOfAccounts'\nimport useSWR from 'swr'\n\ntype UseJournal = () => {\n data?: JournalEntry[]\n isLoading?: boolean\n isLoadingEntry?: boolean\n isValidating?: boolean\n isValidatingEntry?: boolean\n error?: unknown\n errorEntry?: unknown\n refetch: () => void\n selectedEntryId?: string\n setSelectedEntryId: (id?: string) => void\n closeSelectedEntry: () => void\n create: (newJournalEntry: NewApiJournalEntry) => void\n changeFormData: (\n name: string,\n value: string | BaseSelectOption | undefined | number,\n lineItemIndex?: number,\n accounts?: LedgerAccountBalance[] | undefined,\n ) => void\n submitForm: () => void\n cancelForm: () => void\n addEntry: () => void\n sendingForm: boolean\n form?: JournalFormTypes\n apiError?: string\n setForm: (form?: JournalFormTypes) => void\n addEntryLine: (direction: Direction) => void\n removeEntryLine: (index: number) => void\n}\n\nexport interface JournalFormTypes {\n action: string\n data: NewFormJournalEntry\n errors?:\n | {\n entry: FormError[]\n lineItems: FormErrorWithId[]\n }\n | undefined\n}\n\nexport const useJournal: UseJournal = () => {\n const {\n auth,\n businessId,\n apiUrl,\n touch,\n read,\n syncTimestamps,\n hasBeenTouched,\n } = useLayerContext()\n\n const [selectedEntryId, setSelectedEntryId] = useState<string | undefined>()\n\n const [form, setForm] = useState<JournalFormTypes | undefined>()\n const [addingEntry, setAddingEntry] = useState(false)\n const [sendingForm, setSendingForm] = useState(false)\n const [apiError, setApiError] = useState<string | undefined>(undefined)\n\n const queryKey =\n businessId && auth?.access_token && `journal-lines-${businessId}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getJournal(apiUrl, auth?.access_token, {\n params: { businessId },\n }),\n )\n\n const refetch = () => mutate()\n\n const closeSelectedEntry = () => {\n setSelectedEntryId(undefined)\n }\n\n const create = async (newJournalEntry: NewApiJournalEntry) => {\n setSendingForm(true)\n setApiError(undefined)\n\n try {\n await Layer.createJournalEntries(apiUrl, auth?.access_token, {\n params: { businessId },\n body: newJournalEntry,\n })\n await refetch()\n closeSelectedEntry()\n setForm(undefined)\n } catch (_err) {\n setApiError('Submit failed. Please, check your connection and try again.')\n } finally {\n setSendingForm(false)\n touch(DataModel.BANK_TRANSACTIONS)\n }\n }\n\n const addEntry = () => {\n setSelectedEntryId('new')\n setForm({\n action: 'new',\n data: {\n entry_at: '',\n created_by: 'Test API Integration',\n memo: '',\n line_items: [\n {\n account_identifier: {\n type: '',\n stable_name: '',\n id: '',\n name: '',\n subType: undefined,\n },\n amount: 0,\n direction: Direction.CREDIT,\n },\n {\n account_identifier: {\n type: '',\n stable_name: '',\n id: '',\n name: '',\n subType: undefined,\n },\n amount: 0,\n direction: Direction.DEBIT,\n },\n ],\n },\n errors: undefined,\n })\n }\n\n const changeFormData = (\n fieldName: string,\n value: string | BaseSelectOption | undefined | number,\n lineItemIndex?: number,\n accounts?: LedgerAccountBalance[] | undefined,\n ) => {\n if (!form) {\n return\n }\n\n let newFormData = form\n\n if (lineItemIndex !== undefined) {\n const lineItems = form.data.line_items || []\n const lineItem = lineItems[lineItemIndex]\n\n if (!lineItem) {\n return\n }\n\n if (fieldName === 'parent' && accounts) {\n const allAccounts = flattenAccounts(accounts || [])\n const foundParent = allAccounts?.find(\n x => x.id === (value as BaseSelectOption).value,\n )\n\n if (foundParent) {\n const newLineItem = {\n ...lineItem,\n account_identifier: {\n id: foundParent.id,\n stable_name: foundParent.stable_name,\n type: foundParent.account_type.value,\n name: foundParent.name,\n subType: foundParent.account_subtype\n ? {\n value: foundParent.account_subtype.value,\n label: foundParent.account_subtype.display_name,\n }\n : undefined,\n },\n }\n lineItems[lineItemIndex] = newLineItem\n }\n } else {\n const newLineItem = {\n ...lineItem,\n [fieldName]: value,\n }\n\n lineItems[lineItemIndex] = newLineItem\n }\n\n newFormData = {\n ...form,\n data: {\n ...form.data,\n line_items: lineItems,\n },\n }\n } else {\n newFormData = {\n ...form,\n data: {\n ...form.data,\n [fieldName]: value,\n },\n }\n }\n\n setForm({\n ...newFormData,\n })\n }\n\n const validateLineItems = (lineItems?: JournalEntryLineItem[]) => {\n if (!lineItems) {\n return\n }\n const errors: FormErrorWithId[] = []\n\n lineItems.map((lineItem, idx) => {\n if (!lineItem.account_identifier.id) {\n errors.push({\n id: idx,\n field: 'account',\n message: 'Account is required',\n })\n }\n\n if (!lineItem.amount) {\n errors.push({\n id: idx,\n field: 'amount',\n message: 'Amount cannot be empty or zero',\n })\n }\n })\n return errors\n }\n\n const validate = (formData?: JournalFormTypes) => {\n let errors: {\n entry: FormError[]\n lineItems: FormErrorWithId[]\n } = {\n entry: [],\n lineItems: [],\n }\n\n const lineItems = validateLineItems(formData?.data.line_items)\n\n if (lineItems) {\n errors = {\n ...errors,\n lineItems,\n }\n }\n\n return errors\n }\n\n const submitForm = () => {\n if (!form || !form.action || addingEntry) {\n return\n }\n\n const errors = validate(form)\n\n if (errors.entry.length > 0 || errors.lineItems.length > 0) {\n setForm({\n ...form,\n errors,\n })\n\n return\n }\n\n if (form?.data) {\n create({\n ...form.data,\n line_items: form.data.line_items?.map(line => ({\n ...line,\n amount: line.amount * 100,\n account_identifier: getAccountIdentifierPayload(line),\n })),\n } as NewApiJournalEntry)\n }\n }\n\n const addEntryLine = (direction: Direction) => {\n if (!form) {\n return\n }\n\n setAddingEntry(true)\n\n const newEntryLine = {\n account_identifier: {\n type: '',\n stable_name: '',\n id: '',\n name: '',\n subType: undefined,\n },\n amount: 0,\n direction,\n }\n\n const entryLines = form?.data.line_items || []\n entryLines.push(newEntryLine)\n\n setForm({\n ...form,\n data: {\n ...form.data,\n line_items: entryLines,\n },\n })\n setTimeout(() => setAddingEntry(false), 100)\n }\n\n const removeEntryLine = (index: number) => {\n if (!form) {\n return\n }\n\n const entryLines = form.data.line_items || []\n entryLines.splice(index, 1)\n\n setForm({\n ...form,\n data: {\n ...form.data,\n line_items: entryLines,\n },\n })\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.JOURNAL, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps])\n\n return {\n data: data?.data,\n isLoading,\n isValidating,\n error,\n refetch,\n selectedEntryId,\n setSelectedEntryId,\n closeSelectedEntry,\n create,\n addEntry,\n changeFormData,\n submitForm,\n cancelForm: () => {\n setForm(undefined), setSelectedEntryId(undefined)\n },\n setForm,\n sendingForm,\n form,\n apiError,\n addEntryLine,\n removeEntryLine,\n }\n}\n", "import { AccountIdentifierPayloadObject } from '../types/categories'\nimport { JournalEntryLineItem } from '../types/journal'\n\nexport const getAccountIdentifierPayload = (\n journalLineItem: JournalEntryLineItem,\n): AccountIdentifierPayloadObject => {\n if (journalLineItem.account_identifier.id) {\n return {\n type: 'AccountId',\n id: journalLineItem.account_identifier.id,\n }\n }\n if (journalLineItem.account_identifier.stable_name) {\n return {\n type: 'StableName',\n stable_name: journalLineItem.account_identifier.stable_name,\n }\n }\n\n throw new Error('Invalid account identifier')\n}\n", "import React, { RefObject, useContext, useMemo, useState } from 'react'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport { Button, ButtonVariant } from '../Button'\nimport { Header } from '../Container'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { View } from '../Journal'\nimport { JournalConfig } from '../Journal/Journal'\nimport { JournalRow } from '../JournalRow'\nimport { JournalSidebar } from '../JournalSidebar'\nimport { Loader } from '../Loader'\nimport { Pagination } from '../Pagination'\nimport { Panel } from '../Panel'\nimport { Heading } from '../Typography'\nimport { JournalFormStringOverrides } from '../JournalForm/JournalForm'\n\nconst COMPONENT_NAME = 'journal'\n\nexport interface JournalTableStringOverrides {\n componentTitle?: string,\n addEntryButton?: string,\n idColumnHeader?: string,\n dateColumnHeader?: string,\n transactionColumnHeader?: string,\n accountColumnHeader?: string,\n debitColumnHeader?: string,\n creditColumnHeader?: string,\n journalForm?: JournalFormStringOverrides\n}\n\nexport const JournalTable = ({\n view,\n containerRef,\n pageSize = 15,\n config,\n stringOverrides,\n}: {\n view: View\n containerRef: RefObject<HTMLDivElement>\n pageSize?: number\n config: JournalConfig\n stringOverrides?: JournalTableStringOverrides\n}) => {\n const [currentPage, setCurrentPage] = useState(1)\n const {\n data: rawData,\n isLoading,\n error,\n isValidating,\n refetch,\n selectedEntryId,\n addEntry,\n } = useContext(JournalContext)\n\n const data = useMemo(() => {\n const firstPageIndex = (currentPage - 1) * pageSize\n const lastPageIndex = firstPageIndex + pageSize\n return rawData\n ?.sort((a, b) => Date.parse(b.date) - Date.parse(a.date))\n ?.slice(firstPageIndex, lastPageIndex)\n }, [rawData, currentPage])\n\n return (\n <Panel\n sidebar={<JournalSidebar parentRef={containerRef} config={config} stringOverrides={stringOverrides?.journalForm} />}\n sidebarIsOpen={Boolean(selectedEntryId)}\n parentRef={containerRef}\n >\n <Header className={`Layer__${COMPONENT_NAME}__header`}>\n <Heading className={`Layer__${COMPONENT_NAME}__title`}>{stringOverrides?.componentTitle || \"Journal\"}</Heading>\n <div className={`Layer__${COMPONENT_NAME}__actions`}>\n <Button onClick={() => addEntry()} disabled={isLoading}>\n {stringOverrides?.addEntryButton || \"Add Entry\"}\n </Button>\n </div>\n </Header>\n\n <table className='Layer__table Layer__table--hover-effect Layer__journal__table'>\n <thead>\n <tr>\n <th className='Layer__table-header' />\n <th className='Layer__table-header'>{stringOverrides?.idColumnHeader || \"Id\"}</th>\n <th className='Layer__table-header'>{stringOverrides?.dateColumnHeader || \"Date\"}</th>\n <th className='Layer__table-header'>{stringOverrides?.transactionColumnHeader || \"Transaction\"}</th>\n <th className='Layer__table-header'>{stringOverrides?.accountColumnHeader || \"Account\"}</th>\n <th className='Layer__table-header Layer__table-cell--amount'>\n {stringOverrides?.debitColumnHeader || \"Debit\"}\n </th>\n <th className='Layer__table-header Layer__table-cell--amount'>\n {stringOverrides?.creditColumnHeader || \"Credit\"}\n </th>\n </tr>\n </thead>\n\n <tbody>\n {!error &&\n data?.map((entry, idx) => {\n return (\n <JournalRow\n key={'journal-row-' + idx + entry.id}\n index={idx}\n view={view}\n row={entry}\n />\n )\n })}\n </tbody>\n </table>\n\n {data && (\n <div className='Layer__journal__pagination'>\n <Pagination\n currentPage={currentPage}\n totalCount={rawData?.length || 0}\n pageSize={pageSize}\n onPageChange={page => setCurrentPage(page)}\n />\n </div>\n )}\n\n {error ? (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={() => refetch()}\n isLoading={isValidating || isLoading}\n />\n </div>\n ) : null}\n\n {(!data || isLoading) && !error ? (\n <div className={`Layer__${COMPONENT_NAME}__loader-container`}>\n <Loader />\n </div>\n ) : null}\n </Panel>\n )\n}\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { DATE_FORMAT } from '../../config/general'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { centsToDollars } from '../../models/Money'\nimport {\n JournalEntry,\n JournalEntryLine,\n JournalEntryLineItem,\n} from '../../types'\nimport { humanizeEnum } from '../../utils/format'\nimport { View } from '../Journal'\nimport classNames from 'classnames'\nimport { parseISO, format as formatTime } from 'date-fns'\n\nexport interface JournalRowProps {\n row: JournalEntry | JournalEntryLine | JournalEntryLineItem\n index: number\n initialLoad?: boolean\n view: View\n lineItemsLength?: number\n defaultOpen?: boolean\n expanded?: boolean\n depth?: number\n cumulativeIndex?: number\n selectedEntries?: boolean\n}\n\nconst INDENTATION = 24\n\nconst EXPANDED_STYLE = {\n height: '100%',\n opacity: 1,\n}\n\nconst COLLAPSED_STYLE = {\n height: 0,\n opacity: 0.5,\n paddingTop: 0,\n paddingBottom: 0,\n}\n\nconst rowId = (row: JournalEntry | JournalEntryLineItem | JournalEntryLine) => {\n if ('id' in row) {\n return row.id\n }\n\n return `${row.account_identifier.id}-${Math.random()}`\n}\n\nconst accountName = (row: JournalEntryLine | JournalEntryLineItem) => {\n if ('account' in row) {\n return row.account.name\n }\n\n return row.account_identifier.name\n}\n\nexport const JournalRow = ({\n row,\n index,\n initialLoad,\n view,\n lineItemsLength = 8,\n defaultOpen = false,\n expanded = false,\n depth = 0,\n cumulativeIndex = 0,\n selectedEntries = false,\n}: JournalRowProps) => {\n const { selectedEntryId, setSelectedEntryId, closeSelectedEntry } =\n useContext(JournalContext)\n\n const [isOpen, setIsOpen] = useState(index === 0 ? true : defaultOpen)\n\n const style = expanded\n ? {\n ...EXPANDED_STYLE,\n transitionDelay: `${15 * index}ms`,\n }\n : {\n ...COLLAPSED_STYLE,\n transitionDelay: `${lineItemsLength - 15 * index}ms`,\n }\n const [showComponent, setShowComponent] = useState(false)\n\n const baseClass = classNames(\n 'Layer__journal-table-row',\n rowId(row) === selectedEntryId && 'Layer__table-row--active',\n initialLoad && 'initial-load',\n 'Layer__table-row--with-show',\n showComponent ? 'show' : 'Layer__table-row--anim-starting-state',\n isOpen && 'Layer__journal__table-row--expanded',\n )\n\n const journalEntryLineClass = classNames(\n 'Layer__journal-entry-table-row',\n selectedEntries && 'Layer__table-row--active',\n initialLoad && 'initial-load',\n 'Layer__table-row--with-show',\n showComponent ? 'show' : 'Layer__table-row--anim-starting-state',\n 'Layer__journal-line__table-row',\n !expanded && 'Layer__table-row--hidden',\n )\n\n useEffect(() => {\n if (initialLoad) {\n const timeoutId = setTimeout(() => {\n setShowComponent(true)\n }, index * 10)\n\n return () => clearTimeout(timeoutId)\n } else {\n setShowComponent(true)\n }\n }, [])\n\n if ('line_items' in row) {\n return (\n <>\n <tr\n className={baseClass}\n style={{ transitionDelay: `${15 * index}ms` }}\n onClick={e => {\n e.stopPropagation()\n\n if (selectedEntryId === row.id) {\n closeSelectedEntry()\n } else {\n setSelectedEntryId(row.id)\n }\n }}\n >\n <td className='Layer__table-cell Layer__journal__arrow'>\n <span className='Layer__table-cell-content'>\n <span\n className='Layer__table-cell-content-indentation'\n style={{\n paddingLeft: INDENTATION * depth + 16,\n }}\n onClick={e => {\n e.stopPropagation()\n e.preventDefault()\n\n setIsOpen(!isOpen)\n }}\n >\n {row.line_items && row.line_items.length > 0 && (\n <ChevronDownFill\n size={16}\n className='Layer__table__expand-icon'\n style={{\n transform: isOpen ? 'rotate(0deg)' : 'rotate(-90deg)',\n }}\n />\n )}\n </span>\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {row.id.substring(0, 5)}\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {row.date && formatTime(parseISO(row.date), DATE_FORMAT)}\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>\n {humanizeEnum(row.entry_type)}\n </span>\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content'>{`(${row.line_items.length})`}</span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n $\n {centsToDollars(\n Math.abs(\n row.line_items\n .filter(item => item.direction === 'DEBIT')\n .map(item => item.amount)\n .reduce((a, b) => a + b, 0),\n ),\n )}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n <span className='Layer__table-cell-content Layer__table-cell--amount'>\n $\n {centsToDollars(\n Math.abs(\n row.line_items\n .filter(item => item.direction === 'CREDIT')\n .map(item => item.amount)\n .reduce((a, b) => a + b, 0),\n ),\n )}\n </span>\n </td>\n </tr>\n {(row.line_items || []).map((lineItem, idx) => (\n <JournalRow\n key={`${row.id}-${idx}`}\n row={lineItem}\n depth={depth + 1}\n index={idx}\n expanded={isOpen}\n cumulativeIndex={cumulativeIndex + idx + 1}\n lineItemsLength={(row.line_items ?? []).length}\n view={view}\n selectedEntries={row.id === selectedEntryId}\n />\n ))}\n </>\n )\n }\n\n return (\n <tr\n className={journalEntryLineClass}\n style={{ transitionDelay: `${15 * index}ms` }}\n >\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content' style={style} />\n </td>\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content' style={style}>\n <span className='Layer__table-cell-hidden'>\n {rowId(row).substring(0, 5)}\n </span>\n </span>\n </td>\n <td className='Layer__table-cell' />\n <td className='Layer__table-cell' />\n <td className='Layer__table-cell'>\n <span className='Layer__table-cell-content' style={style}>\n {accountName(row)}\n </span>\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n {row.direction === 'DEBIT' && (\n <span\n className='Layer__table-cell-content Layer__table-cell--amount'\n style={style}\n >\n ${centsToDollars(Math.abs(row.amount))}\n </span>\n )}\n </td>\n <td className='Layer__table-cell Layer__table-cell--primary'>\n {row.direction === 'CREDIT' && (\n <span\n className='Layer__table-cell-content Layer__table-cell--amount'\n style={style}\n >\n ${centsToDollars(Math.abs(row.amount))}\n </span>\n )}\n </td>\n </tr>\n )\n}\n", "import React, { RefObject, useContext } from 'react'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport { JournalConfig } from '../Journal/Journal'\nimport { JournalEntryDetails } from '../JournalEntryDetails'\nimport { JournalForm } from '../JournalForm'\nimport { JournalFormStringOverrides } from '../JournalForm/JournalForm'\n\nexport const JournalSidebar = ({\n parentRef: _parentRef,\n config,\n stringOverrides,\n}: {\n parentRef?: RefObject<HTMLDivElement>\n config: JournalConfig\n stringOverrides?: JournalFormStringOverrides\n}) => {\n const { selectedEntryId } = useContext(JournalContext)\n if (selectedEntryId !== 'new') {\n return <JournalEntryDetails />\n }\n return <JournalForm config={config} stringOverrides={stringOverrides}/>\n}\n", "import React, { useContext, useMemo } from 'react'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport XIcon from '../../icons/X'\nimport { centsToDollars } from '../../models/Money'\nimport { Direction } from '../../types'\nimport { humanizeEnum } from '../../utils/format'\nimport { Badge, BadgeVariant } from '../Badge'\nimport { Button, ButtonVariant } from '../Button'\nimport { Card } from '../Card'\nimport { DateTime } from '../DateTime'\nimport { DetailsList, DetailsListItem } from '../DetailsList'\nimport { SourceDetailView } from '../LedgerAccountEntryDetails/LedgerAccountEntryDetails'\nimport { Table, TableBody, TableCell, TableHead, TableRow } from '../Table'\n\nexport const JournalEntryDetails = () => {\n const {\n data,\n isLoadingEntry,\n errorEntry,\n closeSelectedEntry,\n selectedEntryId,\n } = useContext(JournalContext)\n\n const entry = useMemo(() => {\n if (selectedEntryId && data) {\n return data.find(x => x.id === selectedEntryId)\n }\n\n return\n }, [data, selectedEntryId])\n\n return (\n <div className='Layer__journal__entry-details'>\n <DetailsList\n title='Transaction source'\n actions={\n <Button\n rightIcon={<XIcon />}\n iconOnly={true}\n onClick={closeSelectedEntry}\n className='Layer__details-list__close-btn'\n variant={ButtonVariant.secondary}\n />\n }\n >\n <DetailsListItem label='Source' isLoading={isLoadingEntry}>\n <Badge>{entry?.source?.entity_name}</Badge>\n </DetailsListItem>\n {entry?.source?.display_description && (\n <SourceDetailView source={entry?.source} />\n )}\n </DetailsList>\n <DetailsList\n title={`Journal Entry ${entry?.id.substring(0, 5)}`}\n className='Layer__border-top'\n >\n <DetailsListItem label='Entry type' isLoading={isLoadingEntry}>\n {humanizeEnum(entry?.entry_type ?? '')}\n </DetailsListItem>\n <DetailsListItem label='Date' isLoading={isLoadingEntry}>\n {entry?.entry_at && <DateTime value={entry?.entry_at} />}\n </DetailsListItem>\n <DetailsListItem label='Creation date' isLoading={isLoadingEntry}>\n {entry?.date && <DateTime value={entry?.date} />}\n </DetailsListItem>\n {entry?.reversal_id && (\n <DetailsListItem label='Reversal' isLoading={isLoadingEntry}>\n Journal Entry #{entry?.reversal_id}\n </DetailsListItem>\n )}\n </DetailsList>\n {!isLoadingEntry && !errorEntry ? (\n <div className='Layer__ledger-account__entry-details__line-items'>\n <Card>\n <Table\n componentName='ledger-account__entry-details'\n borderCollapse='collapse'\n >\n <TableHead>\n <TableRow rowKey='soc-flow-head-row' isHeadRow>\n <TableCell>Line items</TableCell>\n {[...Array(3)].map((_, index) => (\n <TableCell key={`ledger-empty-cell-${index}`} />\n ))}\n <TableCell>Debit</TableCell>\n <TableCell>Credit</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {entry?.line_items?.map((item, index) => (\n <TableRow\n key={`ledger-line-item-${index}`}\n rowKey={`ledger-line-item-${index}`}\n >\n <TableCell>{item.account_identifier?.name || ''}</TableCell>\n {[...Array(3)].map((_, index) => (\n <TableCell key={`ledger-empty-cell-${index}`} />\n ))}\n <TableCell>\n {item.direction === Direction.DEBIT && (\n <Badge variant={BadgeVariant.WARNING}>\n ${centsToDollars(item.amount || 0)}\n </Badge>\n )}\n </TableCell>\n <TableCell>\n {item.direction === Direction.CREDIT && (\n <Badge variant={BadgeVariant.SUCCESS}>\n ${centsToDollars(item.amount || 0)}\n </Badge>\n )}\n </TableCell>\n </TableRow>\n ))}\n <TableRow\n rowKey='ledger-line-item-summation'\n variant='summation'\n >\n <TableCell primary>Total</TableCell>\n {[...Array(3)].map((_, index) => (\n <TableCell key={`ledger-empty-cell-${index}`} />\n ))}\n <TableCell isCurrency primary>\n {entry?.line_items\n .filter(item => item.direction === 'DEBIT')\n .map(item => item.amount)\n .reduce((a, b) => a + b, 0) || 0}\n </TableCell>\n <TableCell isCurrency primary>\n {entry?.line_items\n .filter(item => item.direction === 'CREDIT')\n .map(item => item.amount)\n .reduce((a, b) => a + b, 0) || 0}\n </TableCell>\n </TableRow>\n </TableBody>\n </Table>\n </Card>\n </div>\n ) : null}\n </div>\n )\n}\n", "import React, { useContext } from 'react'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport { Button, ButtonVariant, RetryButton, SubmitButton } from '../Button'\nimport { DatePicker } from '../DatePicker'\nimport { InputGroup } from '../Input'\nimport { JournalConfig } from '../Journal/Journal'\nimport { Textarea } from '../Textarea/Textarea'\nimport { Text, TextSize, TextWeight } from '../Typography'\nimport { JournalFormEntryLines } from './JournalFormEntryLines'\n\nexport interface JournalFormStringOverrides {\n header?: string\n cancelButton?: string\n retryButton?: string\n saveButton?: string\n}\n\nexport const JournalForm = (\n { config, stringOverrides }: {\n config: JournalConfig,\n stringOverrides?: JournalFormStringOverrides\n }) => {\n const {\n form,\n cancelForm,\n submitForm,\n sendingForm,\n apiError,\n changeFormData,\n addEntryLine,\n removeEntryLine,\n } = useContext(JournalContext)\n\n return (\n <form\n className='Layer__form'\n onSubmit={e => {\n e.preventDefault()\n submitForm()\n }}\n >\n <div className='Layer__journal__sidebar__header'>\n <Text size={TextSize.lg} weight={TextWeight.bold} className='title'>\n {stringOverrides?.header && \"Add New Entry\"}\n </Text>\n <div className='actions'>\n <Button\n type='button'\n onClick={cancelForm}\n variant={ButtonVariant.secondary}\n disabled={sendingForm}\n >\n {stringOverrides?.cancelButton || \"Cancel\"}\n </Button>\n {apiError && (\n <RetryButton\n type='submit'\n processing={sendingForm}\n error={'Check connection and retry in few seconds.'}\n disabled={sendingForm}\n >\n {stringOverrides?.retryButton || \"Retry\"}\n </RetryButton>\n )}\n {!apiError && (\n <SubmitButton\n type='submit'\n noIcon={true}\n active={true}\n disabled={sendingForm}\n >\n {stringOverrides?.saveButton || \"Save\"}\n </SubmitButton>\n )}\n </div>\n </div>\n\n {apiError && (\n <Text\n size={TextSize.sm}\n className='Layer__journal__form__error-message'\n >\n {apiError}\n </Text>\n )}\n\n <div className='Layer__journal__form__input-group'>\n <InputGroup name='date' label='Date' inline={true}>\n <div className='Layer__journal__datepicker__wrapper'>\n <DatePicker\n selected={\n form?.data.entry_at ? new Date(form?.data.entry_at) : new Date()\n }\n onChange={date => {\n if (!Array.isArray(date)) {\n changeFormData('entry_at', date.toISOString())\n }\n }}\n mode='dayPicker'\n placeholderText='Select date'\n currentDateOption={false}\n />\n <DatePicker\n selected={\n form?.data.entry_at ? new Date(form?.data.entry_at) : new Date()\n }\n onChange={date => {\n if (!Array.isArray(date)) {\n changeFormData('entry_at', date.toISOString())\n }\n }}\n mode='timePicker'\n placeholderText='Select time'\n currentDateOption={false}\n />\n </div>\n </InputGroup>\n </div>\n <JournalFormEntryLines\n entrylineItems={form?.data.line_items || []}\n addEntryLine={addEntryLine}\n removeEntryLine={removeEntryLine}\n changeFormData={changeFormData}\n sendingForm={sendingForm}\n config={config}\n />\n <div className='Layer__journal__form__input-group Layer__journal__form__input-group__textarea'>\n <InputGroup name='memo' label='Notes'>\n <Textarea\n name='memo'\n placeholder='Add description'\n value={form?.data.memo}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>\n changeFormData('memo', e.target.value)\n }\n disabled={sendingForm}\n />\n </InputGroup>\n </div>\n <div className='Layer__journal__bottom-actions'>\n <Button\n type='button'\n onClick={cancelForm}\n variant={ButtonVariant.secondary}\n disabled={sendingForm}\n >\n {stringOverrides?.cancelButton || \"Cancel\"}\n </Button>\n {apiError && (\n <RetryButton\n type='submit'\n processing={sendingForm}\n error={'Check connection and retry in few seconds.'}\n disabled={sendingForm}\n >\n {stringOverrides?.retryButton || \"Retry\"}\n </RetryButton>\n )}\n {!apiError && (\n <SubmitButton\n type='submit'\n noIcon={true}\n active={true}\n disabled={sendingForm}\n >\n {stringOverrides?.saveButton || \"Save\"}\n </SubmitButton>\n )}\n </div>\n </form>\n )\n}\n", "import React, { useContext } from 'react'\nimport { ChartOfAccountsContext } from '../../contexts/ChartOfAccountsContext'\nimport { JournalContext } from '../../contexts/JournalContext'\nimport Trash from '../../icons/Trash'\nimport { Direction, JournalEntryLineItem } from '../../types'\nimport { LedgerAccountBalance } from '../../types/chart_of_accounts'\nimport { BaseSelectOption } from '../../types/general'\nimport {\n convertCurrencyToNumber,\n convertNumberToCurrency,\n humanizeEnum,\n} from '../../utils/format'\nimport { BadgeVariant } from '../Badge'\nimport { IconButton, TextButton } from '../Button'\nimport { useParentOptions } from '../ChartOfAccountsForm/useParentOptions'\nimport { InputWithBadge, InputGroup, Select } from '../Input'\nimport { JournalConfig } from '../Journal/Journal'\nimport { Text, TextSize } from '../Typography'\n\nexport const JournalFormEntryLines = ({\n entrylineItems,\n addEntryLine,\n removeEntryLine,\n changeFormData,\n sendingForm,\n config,\n}: {\n entrylineItems: JournalEntryLineItem[]\n addEntryLine: (direction: Direction) => void\n removeEntryLine: (index: number) => void\n changeFormData: (\n name: string,\n value: string | BaseSelectOption | number | undefined,\n lineItemIndex: number,\n accounts?: LedgerAccountBalance[] | undefined,\n ) => void\n sendingForm: boolean\n config: JournalConfig\n}) => {\n const { data: accountsData } = useContext(ChartOfAccountsContext)\n const { form } = useContext(JournalContext)\n\n const parentOptions = useParentOptions(accountsData)\n\n return (\n <>\n {Object.keys(Direction).map((direction, idx) => {\n return (\n <div\n key={'Layer__journal__form__input-group-' + idx}\n className='Layer__journal__form__input-group Layer__journal__form__input-group__border'\n >\n <Text\n className='Layer__journal__form__input-group__title'\n size={TextSize.lg}\n >\n Add {humanizeEnum(direction)} Account\n </Text>\n {entrylineItems?.map((item, idx) => {\n if (item.direction !== direction) {\n return null\n }\n return (\n <div\n className='Layer__journal__form__input-group__line-item'\n key={direction + '-' + idx}\n >\n <InputGroup name={direction} label='Amount' inline={true}>\n <InputWithBadge\n name={direction}\n placeholder='$0.00'\n value={convertNumberToCurrency(item.amount)}\n disabled={sendingForm}\n badge={humanizeEnum(direction)}\n variant={\n item.direction === 'CREDIT'\n ? BadgeVariant.SUCCESS\n : BadgeVariant.WARNING\n }\n onChange={e =>\n changeFormData(\n 'amount',\n convertCurrencyToNumber(\n (e.target as HTMLInputElement).value,\n ),\n idx,\n )\n }\n isInvalid={Boolean(\n form?.errors?.lineItems.find(\n x => x.id === idx && x.field === 'amount',\n ),\n )}\n errorMessage={\n form?.errors?.lineItems.find(\n x => x.id === idx && x.field === 'amount',\n )?.message\n }\n />\n </InputGroup>\n <InputGroup\n name='account-name'\n label='Account name'\n inline={true}\n >\n <Select\n options={parentOptions}\n value={{\n value: item.account_identifier.id,\n label: item.account_identifier.name,\n }}\n onChange={sel =>\n changeFormData(\n 'parent',\n sel,\n idx,\n accountsData?.accounts,\n )\n }\n isInvalid={Boolean(\n form?.errors?.lineItems.find(\n x => x.id === idx && x.field === 'account',\n ),\n )}\n errorMessage={\n form?.errors?.lineItems.find(\n x => x.id === idx && x.field === 'account',\n )?.message\n }\n />\n {idx >= 2 && (\n <IconButton\n className='Layer__remove__button'\n onClick={() => removeEntryLine(idx)}\n icon={<Trash />}\n />\n )}\n </InputGroup>\n </div>\n )\n })}\n {(config.form.addEntryLinesLimit === undefined ||\n config.form.addEntryLinesLimit > entrylineItems?.length) && (\n <TextButton\n className='Layer__journal__add-entry-line'\n onClick={() => addEntryLine(direction as Direction)}\n >\n Add next account\n </TextButton>\n )}\n </div>\n )\n })}\n </>\n )\n}\n", "import React, {\n createContext,\n ReactNode,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react'\nimport { TasksContext } from '../../contexts/TasksContext'\nimport { useTasks } from '../../hooks/useTasks'\nimport { isComplete } from '../../types/tasks'\nimport { Loader } from '../Loader'\nimport { TasksHeader } from '../TasksHeader'\nimport { TasksList } from '../TasksList'\nimport { TasksPending } from '../TasksPending'\nimport classNames from 'classnames'\n\nexport type UseTasksContextType = ReturnType<typeof useTasks>\nexport const UseTasksContext = createContext<UseTasksContextType>({\n data: undefined,\n isLoading: undefined,\n loadedStatus: 'initial',\n isValidating: undefined,\n error: undefined,\n refetch: () => {},\n submitResponseToTask: () => {},\n})\n\nexport const useTasksContext = () => useContext(UseTasksContext)\n\nexport interface TasksStringOverrides {\n header?: string\n}\n\nexport const Tasks = ({\n collapsable = false,\n defaultCollapsed = false,\n collapsedWhenComplete,\n tasksHeader, // deprecated\n stringOverrides,\n}: {\n tasksHeader?: string\n collapsable?: boolean\n defaultCollapsed?: boolean\n collapsedWhenComplete?: boolean\n stringOverrides?: TasksStringOverrides\n}) => {\n return (\n <TasksProvider>\n <TasksComponent\n collapsable={collapsable}\n defaultCollapsed={defaultCollapsed}\n collapsedWhenComplete={collapsedWhenComplete}\n tasksHeader={tasksHeader} // deprecated\n stringOverrides={stringOverrides}\n />\n </TasksProvider>\n )\n}\n\nexport const TasksProvider = ({ children }: { children: ReactNode }) => {\n const contextData = useTasks()\n\n return (\n <TasksContext.Provider value={contextData}>\n {children}\n </TasksContext.Provider>\n )\n}\n\nexport const TasksComponent = ({\n collapsable = false,\n defaultCollapsed = false,\n collapsedWhenComplete,\n tasksHeader, // deprecated\n stringOverrides,\n}: {\n tasksHeader?: string\n collapsable?: boolean\n defaultCollapsed?: boolean\n collapsedWhenComplete?: boolean\n stringOverrides?: TasksStringOverrides\n}) => {\n const { isLoading, loadedStatus, data } = useContext(TasksContext)\n const allComplete = useMemo(() => {\n if (!data) {\n return undefined\n }\n\n if (data && !isLoading) {\n return Boolean(data.every(x => isComplete(x.status)))\n }\n\n return false\n }, [data, isLoading])\n\n const [open, setOpen] = useState(\n defaultCollapsed || collapsedWhenComplete ? false : true,\n )\n\n useEffect(() => {\n if (\n allComplete &&\n open &&\n collapsedWhenComplete &&\n loadedStatus === 'complete'\n ) {\n setOpen(false)\n }\n }, [allComplete])\n\n return (\n <div className='Layer__tasks-component'>\n <TasksHeader\n tasksHeader={stringOverrides?.header || tasksHeader}\n collapsable={collapsable}\n open={open}\n toggleContent={() => setOpen(!open)}\n />\n <div\n className={classNames(\n 'Layer__tasks__content',\n !open && 'Layer__tasks__content--collapsed',\n )}\n >\n {isLoading || !data ? (\n <div className='Layer__tasks__loader-container'>\n <Loader />\n </div>\n ) : (\n <>\n {data.length > 0 && <TasksPending />}\n <TasksList />\n </>\n )}\n </div>\n </div>\n )\n}\n", "import { createContext } from 'react'\nimport { useTasks } from '../../hooks/useTasks'\n\nexport type TasksContextType = ReturnType<typeof useTasks>\nexport const TasksContext = createContext<TasksContextType>({\n data: undefined,\n isLoading: false,\n loadedStatus: 'initial',\n error: undefined,\n refetch: () => {},\n submitResponseToTask: () => {},\n})\n", "import { useEffect, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport { LoadedStatus } from '../../types/general'\nimport { DataModel } from '../../types/general'\nimport { TaskTypes } from '../../types/tasks'\nimport useSWR from 'swr'\n\ntype UseTasks = () => {\n data?: TaskTypes[]\n isLoading?: boolean\n loadedStatus?: LoadedStatus\n isValidating?: boolean\n error?: unknown\n refetch: () => void\n submitResponseToTask: (taskId: string, userResponse: string) => void\n}\n\nexport const useTasks: UseTasks = () => {\n const [loadedStatus, setLoadedStatus] = useState<LoadedStatus>('initial')\n const { auth, businessId, apiUrl, read, syncTimestamps, hasBeenTouched } =\n useLayerContext()\n\n const queryKey = businessId && auth?.access_token && `tasks-${businessId}`\n\n const { data, isLoading, isValidating, error, mutate } = useSWR(\n queryKey,\n Layer.getTasks(apiUrl, auth?.access_token, {\n params: { businessId },\n }),\n )\n\n useEffect(() => {\n if (isLoading && loadedStatus === 'initial') {\n setLoadedStatus('loading')\n } else if (!isLoading && loadedStatus === 'loading') {\n setLoadedStatus('complete')\n }\n }, [isLoading])\n\n const refetch = () => mutate()\n\n const submitResponseToTask = (taskId: string, userResponse: string) => {\n if (!taskId || !userResponse || userResponse.length === 0) return\n\n const data = {\n type: 'FreeResponse',\n user_response: userResponse,\n }\n\n Layer.submitResponseToTask(apiUrl, auth?.access_token, {\n params: { businessId, taskId },\n body: data,\n }).then(() => refetch())\n }\n\n // Refetch data if related models has been changed since last fetch\n useEffect(() => {\n if (queryKey && (isLoading || isValidating)) {\n read(DataModel.TASKS, queryKey)\n }\n }, [isLoading, isValidating])\n\n useEffect(() => {\n if (queryKey && hasBeenTouched(queryKey)) {\n refetch()\n }\n }, [syncTimestamps])\n\n return {\n data: data?.data,\n isLoading,\n loadedStatus,\n isValidating,\n error,\n refetch,\n submitResponseToTask,\n }\n}\n", "export interface TaskTypes {\n id: string\n question: string\n status: TasksStatusType\n title: string\n transaction_id: string | null\n type: string\n user_marked_completed_at: string\n user_response: string\n user_response_type: TasksResponseType\n archived_at: string | null\n completed_at: string\n created_at: string\n updated_at: string\n}\n\nexport type TasksStatusType = 'COMPLETED' | 'TODO' | 'USER_MARKED_COMPLETED'\nexport type TasksResponseType = 'FREE_RESPONSE'\n\nconst COMPLETED_TASK_TYPES = ['COMPLETED', 'USER_MARKED_COMPLETED']\n\nexport function isComplete(taskType: TasksStatusType) {\n return COMPLETED_TASK_TYPES.includes(taskType)\n}\n", "import React, { useContext } from 'react'\nimport { TasksContext } from '../../contexts/TasksContext'\nimport AlertCircle from '../../icons/AlertCircle'\nimport Check from '../../icons/Check'\nimport ProgressIcon from '../../icons/ProgressIcon'\nimport RefreshCcw from '../../icons/RefreshCcw'\nimport { isComplete } from '../../types/tasks'\nimport { Badge, BadgeVariant } from '../Badge'\nimport { ExpandButton } from '../Button'\nimport { Text, TextSize } from '../Typography'\n\nconst ICONS = {\n loading: {\n icon: <ProgressIcon size={12} className='Layer__anim--rotating' />,\n text: 'Loading',\n badge: BadgeVariant.DEFAULT,\n },\n done: {\n icon: <Check size={12} />,\n text: 'Done',\n badge: BadgeVariant.SUCCESS,\n },\n pending: {\n icon: <AlertCircle size={12} />,\n text: 'In progress',\n badge: BadgeVariant.WARNING,\n },\n refresh: {\n icon: <RefreshCcw size={12} />,\n text: 'Refresh',\n badge: BadgeVariant.DEFAULT,\n },\n}\n\nexport const TasksHeader = ({\n tasksHeader = 'Bookkeeping Tasks',\n collapsable,\n open,\n toggleContent,\n}: {\n tasksHeader?: string\n collapsable?: boolean\n open?: boolean\n toggleContent: () => void\n}) => {\n const { data: tasks, loadedStatus, refetch, error } = useContext(TasksContext)\n\n const completedTasks = tasks?.filter(task => isComplete(task.status)).length\n\n const badgeVariant =\n completedTasks === tasks?.length ? ICONS.done : ICONS.pending\n\n return (\n <div className='Layer__tasks-header'>\n <div className='Layer__tasks-header__left-col'>\n <Text size={TextSize.lg}>{tasksHeader}</Text>\n {loadedStatus !== 'complete' && !open ? (\n <Badge variant={ICONS.loading.badge} icon={ICONS.loading.icon}>\n {ICONS.loading.text}\n </Badge>\n ) : loadedStatus === 'complete' && (!tasks || error) ? (\n <Badge\n onClick={() => refetch()}\n variant={ICONS.refresh.badge}\n icon={ICONS.refresh.icon}\n >\n {ICONS.refresh.text}\n </Badge>\n ) : loadedStatus === 'complete' ? (\n <Badge variant={badgeVariant.badge} icon={badgeVariant.icon}>\n {badgeVariant.text}\n </Badge>\n ) : open ? null : (\n <Badge variant={badgeVariant.badge} icon={badgeVariant.icon}>\n {badgeVariant.text}\n </Badge>\n )}\n </div>\n {collapsable && (\n <ExpandButton onClick={toggleContent} collapsed={!open} />\n )}\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst ProgressIcon = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 18 18'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M9 1.5V4.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M9 13.5V16.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M3.6975 3.6975L5.82 5.82'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12.18 12.18L14.3025 14.3025'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M1.5 9H4.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M13.5 9H16.5'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M3.6975 14.3025L5.82 12.18'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M12.18 5.82L14.3025 3.6975'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default ProgressIcon\n", "import React, { useContext, useEffect, useMemo, useState } from 'react'\nimport { TasksContext } from '../../contexts/TasksContext'\nimport SmileIcon from '../../icons/SmileIcon'\nimport { isComplete, TaskTypes } from '../../types/tasks'\nimport { Pagination } from '../Pagination'\nimport { TasksListItem } from '../TasksListItem'\nimport { ErrorText, Text, TextSize } from '../Typography'\n\nfunction paginateArray<T>(array: T[], chunkSize: number = 10): T[][] {\n const result: T[][] = []\n for (let i = 0; i < array.length; i += chunkSize) {\n const chunk = array.slice(i, i + chunkSize)\n result.push(chunk)\n }\n return result\n}\n\nconst TasksEmptyState = () => (\n <div className='Layer__tasks-empty-state'>\n <div className='Layer__tasks-icon'>\n <SmileIcon />\n </div>\n <Text size={TextSize.sm}>\n There are no pending tasks!\n <br /> Great job!\n </Text>\n </div>\n)\n\nexport const TasksList = ({ pageSize = 10 }: { pageSize?: number }) => {\n const { data: tasks, error } = useContext(TasksContext)\n\n const firstPageWithIincompleteTasks = paginateArray(\n tasks || [],\n pageSize,\n ).findIndex(page => page.some(task => !isComplete(task.status)))\n\n const [currentPage, setCurrentPage] = useState(\n firstPageWithIincompleteTasks === -1\n ? 1\n : firstPageWithIincompleteTasks + 1,\n )\n\n const sortedTasks = useMemo(() => {\n const firstPageIndex = (currentPage - 1) * pageSize\n const lastPageIndex = firstPageIndex + pageSize\n return tasks?.slice(firstPageIndex, lastPageIndex)\n }, [tasks, currentPage])\n\n const indexFirstIncomplete = sortedTasks?.findIndex(\n task => !isComplete(task.status),\n )\n\n const goToNextPage = (task: TaskTypes) => {\n const allComplete = sortedTasks\n ?.filter(taskInList => taskInList.id !== task.id)\n .every(task => isComplete(task.status))\n if (allComplete) {\n setCurrentPage(currentPage + 1)\n }\n }\n\n return (\n <div className='Layer__tasks-list'>\n {sortedTasks && sortedTasks.length > 0 ? (\n <>\n {sortedTasks.map((task, index) => (\n <TasksListItem\n key={task.id}\n task={task}\n goToNextPageIfAllComplete={goToNextPage}\n defaultOpen={index === indexFirstIncomplete}\n />\n ))}\n {tasks && tasks.length >= 10 && (\n <div className='Layer__tasks__pagination'>\n <Pagination\n currentPage={currentPage}\n totalCount={tasks?.length || 0}\n pageSize={pageSize}\n onPageChange={page => setCurrentPage(page)}\n />\n </div>\n )}\n </>\n ) : (\n <>\n {error ? (\n <ErrorText>\n Approval failed. Check connection and retry in few seconds.\n </ErrorText>\n ) : (\n <TasksEmptyState />\n )}\n </>\n )}\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst SmileIcon = ({ size = 12, ...props }: IconSvgProps) => (\n <svg\n viewBox='0 0 12 12'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n width={size}\n height={size}\n >\n <path\n d='M6.5 11.5C9.26142 11.5 11.5 9.26142 11.5 6.5C11.5 3.73858 9.26142 1.5 6.5 1.5C3.73858 1.5 1.5 3.73858 1.5 6.5C1.5 9.26142 3.73858 11.5 6.5 11.5Z'\n stroke='#3B9C63'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M4.5 7.5C4.5 7.5 5.25 8.5 6.5 8.5C7.75 8.5 8.5 7.5 8.5 7.5'\n stroke='#3B9C63'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M5 5H5.005'\n stroke='#3B9C63'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M8 5H8.005'\n stroke='#3B9C63'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n)\n\nexport default SmileIcon\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { TasksContext } from '../../contexts/TasksContext'\nimport AlertCircle from '../../icons/AlertCircle'\nimport Check from '../../icons/Check'\nimport ChevronDownFill from '../../icons/ChevronDownFill'\nimport { isComplete, TaskTypes } from '../../types/tasks'\nimport { Button, ButtonVariant } from '../Button'\nimport { Textarea } from '../Textarea'\nimport { Text, TextSize } from '../Typography'\nimport classNames from 'classnames'\nimport { set } from 'date-fns'\n\nexport const TasksListItem = ({\n task,\n goToNextPageIfAllComplete,\n defaultOpen,\n}: {\n task: TaskTypes\n goToNextPageIfAllComplete: (task: TaskTypes) => void\n defaultOpen: boolean\n}) => {\n const [isOpen, setIsOpen] = useState(defaultOpen)\n const [userResponse, setUserResponse] = useState(task.user_response || '')\n\n const { submitResponseToTask } = useContext(TasksContext)\n\n const taskBodyClassName = classNames(\n 'Layer__tasks-list-item__body',\n isOpen && 'Layer__tasks-list-item__body--expanded',\n isComplete(task.status) && 'Layer__tasks-list-item--completed',\n )\n\n const taskHeadClassName = classNames(\n 'Layer__tasks-list-item__head-info',\n isComplete(task.status)\n ? 'Layer__tasks-list-item--completed'\n : 'Layer__tasks-list-item--pending',\n )\n\n const taskItemClassName = classNames(\n 'Layer__tasks-list-item',\n isOpen && 'Layer__tasks-list-item__expanded',\n )\n\n useEffect(() => {\n setIsOpen(defaultOpen)\n }, [defaultOpen])\n\n return (\n <div className='Layer__tasks-list-item-wrapper'>\n <div className={taskItemClassName}>\n <div\n className='Layer__tasks-list-item__head'\n onClick={() => setIsOpen(!isOpen)}\n >\n <div className={taskHeadClassName}>\n <div className='Layer__tasks-list-item__head-info__status'>\n {isComplete(task.status) ? (\n <Check size={12} />\n ) : (\n <AlertCircle size={12} />\n )}\n </div>\n <Text size={TextSize.md}>{task.title}</Text>\n </div>\n <ChevronDownFill\n size={16}\n className='Layer__tasks__expand-icon'\n style={{\n transform: isOpen ? 'rotate(0deg)' : 'rotate(-180deg)',\n }}\n />\n </div>\n <div className={taskBodyClassName}>\n <div className='Layer__tasks-list-item__body-info'>\n <Text size={TextSize.sm}>{task.question}</Text>\n <Textarea\n value={userResponse}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>\n setUserResponse(e.target.value)\n }\n />\n <div className='Layer__tasks-list-item__actions'>\n <Button\n disabled={\n userResponse.length === 0 ||\n userResponse === task.user_response\n }\n variant={ButtonVariant.secondary}\n onClick={() => {\n submitResponseToTask(task.id, userResponse)\n setIsOpen(false)\n goToNextPageIfAllComplete(task)\n }}\n >\n {userResponse && userResponse.length === 0 ? 'Update' : 'Save'}\n </Button>\n </div>\n </div>\n </div>\n </div>\n </div>\n )\n}\n", "import React, { useContext } from 'react'\nimport { TASKS_CHARTS_COLORS } from '../../config/charts'\nimport { TasksContext } from '../../contexts/TasksContext'\nimport { isComplete } from '../../types/tasks'\nimport { Text, TextSize } from '../Typography'\nimport classNames from 'classnames'\nimport { format } from 'date-fns'\nimport { Cell, Pie, PieChart } from 'recharts'\n\nexport const TasksPending = () => {\n const { data } = useContext(TasksContext)\n const completedTasks = data?.filter(task => isComplete(task.status)).length\n\n const chartData = [\n {\n name: 'done',\n value: completedTasks,\n },\n {\n name: 'pending',\n value: data?.filter(task => !isComplete(task.status)).length,\n },\n ]\n\n const taskStatusClassName = classNames(\n completedTasks && completedTasks > 0\n ? 'Layer__tasks-pending-bar__status--done'\n : 'Layer__tasks-pending-bar__status--pending',\n )\n return (\n <div className='Layer__tasks-pending'>\n <Text size={TextSize.lg}>{format(Date.now(), 'MMMM')}</Text>\n <div className='Layer__tasks-pending-bar'>\n <Text size={TextSize.sm}>\n <span className={taskStatusClassName}>{completedTasks}</span>/\n {data?.length} done\n </Text>\n <PieChart width={24} height={24} className='mini-chart'>\n <Pie\n data={chartData}\n dataKey='value'\n nameKey='name'\n cx='50%'\n cy='50%'\n innerRadius={5}\n outerRadius={9}\n paddingAngle={0.2}\n fill={TASKS_CHARTS_COLORS.pending}\n width={16}\n height={16}\n animationDuration={250}\n animationEasing='ease-in-out'\n >\n {chartData.map((task, index) => {\n return (\n <Cell\n key={`cell-${index}`}\n className={'Layer__profit-and-loss-detailed-charts__pie'}\n fill={\n TASKS_CHARTS_COLORS[\n task.name as keyof typeof TASKS_CHARTS_COLORS\n ]\n }\n />\n )\n })}\n </Pie>\n </PieChart>\n </div>\n </div>\n )\n}\n", "import React from 'react'\nimport CoffeeIcon from '../../icons/Coffee'\nimport { Button, ButtonVariant, Link } from '../Button'\nimport { IconBox } from '../IconBox'\nimport { Text, TextSize, TextWeight } from '../Typography'\n\ninterface BookkeepingUpsellBarProps {\n onClick?: () => void\n href?: string\n}\n\nexport const BookkeepingUpsellBar = ({\n onClick,\n href,\n}: BookkeepingUpsellBarProps) => {\n return (\n <div className='Layer__bar-banner Layer__bar-banner--bookkeeping'>\n <div className='Layer__bar-banner__left-col'>\n <IconBox>\n <CoffeeIcon />\n </IconBox>\n <div className='Layer__bar-banner__text-container'>\n <Text size={TextSize.md} weight={TextWeight.bold}>\n Need help with your books?\n </Text>\n <Text\n size={TextSize.sm}\n className='Layer__bar-banner__text-container__desc'\n >\n Order bookkeeping service supported by real humans.\n </Text>\n </div>\n </div>\n {onClick ? (\n <Button variant={ButtonVariant.secondary} onClick={onClick}>\n Schedule a demo\n </Button>\n ) : href ? (\n <Link href={href} target='_blank' variant={ButtonVariant.secondary}>\n Schedule a demo\n </Link>\n ) : null}\n </div>\n )\n}\n", "import * as React from 'react'\nimport { IconSvgProps } from './types'\n\nconst CoffeeIcon = ({ size = 11, ...props }: IconSvgProps) => (\n <svg\n xmlns='http://www.w3.org/2000/svg'\n viewBox='0 0 12 12'\n fill='none'\n {...props}\n width={size}\n height={size}\n >\n <g clip-path='url(#clip0_5018_10141)'>\n <path\n d='M3.25 4.16666H2.79167C2.30544 4.16666 1.83912 4.35981 1.4953 4.70363C1.15149 5.04744 0.958333 5.51376 0.958333 5.99999C0.958333 6.48622 1.15149 6.95254 1.4953 7.29635C1.83912 7.64017 2.30544 7.83332 2.79167 7.83332H3.25'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M10.5834 4.16666H3.25004V8.29166C3.25004 8.77789 3.4432 9.2442 3.78701 9.58802C4.13083 9.93184 4.59714 10.125 5.08337 10.125H8.75004C9.23627 10.125 9.70259 9.93184 10.0464 9.58802C10.3902 9.2442 10.5834 8.77789 10.5834 8.29166V4.16666Z'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M8.75 0.958344V2.33334'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M6.91663 0.958344V2.33334'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n <path\n d='M5.08337 0.958344V2.33334'\n stroke='currentColor'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </g>\n <defs>\n <clipPath id='clip0_5018_10141'>\n <rect\n width='11'\n height='11'\n fill='white'\n transform='matrix(-1 0 0 1 11.5 0.5)'\n />\n </clipPath>\n </defs>\n </svg>\n)\n\nexport default CoffeeIcon\n", "import React, { ReactNode } from 'react'\n\ninterface IconBoxProps {\n children: ReactNode\n}\n\nexport const IconBox = ({ children }: IconBoxProps) => {\n return <span className='Layer__icon-box'>{children}</span>\n}\n", "import React, { useState } from 'react'\nimport { Container, Header } from '../../components/Container'\nimport { ProfitAndLoss } from '../../components/ProfitAndLoss'\nimport { ProfitAndLossDetailedChartsStringOverrides } from '../../components/ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts'\nimport { ProfitAndLossSummariesStringOverrides } from '../../components/ProfitAndLossSummaries/ProfitAndLossSummaries'\nimport { TasksComponent, TasksProvider } from '../../components/Tasks'\nimport { TasksStringOverrides } from '../../components/Tasks/Tasks'\nimport { Toggle } from '../../components/Toggle'\nimport { Heading, HeadingSize } from '../../components/Typography'\nimport { View } from '../../components/View'\nimport { useWindowSize } from '../../hooks/useWindowSize'\nimport classNames from 'classnames'\n\nexport interface BookkeepingOverviewProps {\n title?: string // deprecated\n stringOverrides?: {\n title?: string\n tasks?: TasksStringOverrides\n profitAndLoss?: {\n header?: string\n detailedCharts?: ProfitAndLossDetailedChartsStringOverrides\n summaries?: ProfitAndLossSummariesStringOverrides\n }\n }\n}\n\ntype PnlToggleOption = 'revenue' | 'expenses'\n\nexport const BookkeepingOverview = ({\n title, // deprecated\n stringOverrides,\n}: BookkeepingOverviewProps) => {\n const [pnlToggle, setPnlToggle] = useState<PnlToggleOption>('expenses')\n const [width] = useWindowSize()\n\n return (\n <ProfitAndLoss asContainer={false}>\n <TasksProvider>\n <View\n viewClassName='Layer__bookkeeping-overview--view'\n title={stringOverrides?.title || title || 'Bookkeeping overview'}\n withSidebar={width > 1100}\n sidebar={<TasksComponent stringOverrides={stringOverrides?.tasks} />}\n >\n {width <= 1100 && (\n <TasksComponent\n collapsable\n collapsedWhenComplete\n stringOverrides={stringOverrides?.tasks}\n />\n )}\n <Container\n name='bookkeeping-overview-profit-and-loss'\n asWidget\n elevated={true}\n >\n <Header>\n <Heading size={HeadingSize.secondary}>\n {stringOverrides?.profitAndLoss?.header || 'Profit & Loss'}\n </Heading>\n <ProfitAndLoss.DatePicker />\n </Header>\n <div className='Layer__bookkeeping-overview__summaries-row'>\n <ProfitAndLoss.Summaries\n stringOverrides={stringOverrides?.profitAndLoss?.summaries}\n />\n </div>\n <ProfitAndLoss.Chart />\n </Container>\n <div className='Layer__bookkeeping-overview-profit-and-loss-charts'>\n <Toggle\n name='pnl-detailed-charts'\n options={[\n {\n value: 'revenue',\n label: 'Revenue',\n },\n {\n value: 'expenses',\n label: 'Expenses',\n },\n ]}\n selected={pnlToggle}\n onChange={e => setPnlToggle(e.target.value as PnlToggleOption)}\n />\n <Container\n name={classNames(\n 'bookkeeping-overview-profit-and-loss-chart',\n pnlToggle !== 'revenue' &&\n 'bookkeeping-overview-profit-and-loss-chart--hidden',\n )}\n >\n <ProfitAndLoss.DetailedCharts\n scope='revenue'\n hideClose={true}\n stringOverrides={stringOverrides?.profitAndLoss?.detailedCharts}\n />\n </Container>\n <Container\n name={classNames(\n 'bookkeeping-overview-profit-and-loss-chart',\n pnlToggle !== 'expenses' &&\n 'bookkeeping-overview-profit-and-loss-chart--hidden',\n )}\n >\n <ProfitAndLoss.DetailedCharts\n scope='expenses'\n hideClose={true}\n stringOverrides={stringOverrides?.profitAndLoss?.detailedCharts}\n />\n </Container>\n </div>\n </View>\n </TasksProvider>\n </ProfitAndLoss>\n )\n}\n", "import React, { ReactNode, useState } from 'react'\nimport { Container, Header } from '../../components/Container'\nimport { Onboarding } from '../../components/Onboarding'\nimport { ProfitAndLoss } from '../../components/ProfitAndLoss'\nimport { ProfitAndLossDetailedChartsStringOverrides } from '../../components/ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts'\nimport { ProfitAndLossSummariesStringOverrides } from '../../components/ProfitAndLossSummaries/ProfitAndLossSummaries'\nimport { Toggle } from '../../components/Toggle'\nimport { TransactionToReviewCard } from '../../components/TransactionToReviewCard'\nimport { Heading, HeadingSize } from '../../components/Typography'\nimport { View } from '../../components/View'\nimport classNames from 'classnames'\n\ninterface AccountingOverviewStringOverrides {\n header?: string\n profitAndLoss?: {\n detailedCharts?: ProfitAndLossDetailedChartsStringOverrides\n summaries?: ProfitAndLossSummariesStringOverrides\n }\n}\n\nexport interface AccountingOverviewProps {\n title?: string\n enableOnboarding?: boolean\n onTransactionsToReviewClick?: () => void\n middleBanner?: ReactNode\n chartColorsList?: string[]\n stringOverrides?: AccountingOverviewStringOverrides\n}\n\ntype PnlToggleOption = 'revenue' | 'expenses'\n\nexport const AccountingOverview = ({\n title = 'Accounting overview',\n enableOnboarding = false,\n onTransactionsToReviewClick,\n middleBanner,\n chartColorsList,\n stringOverrides,\n}: AccountingOverviewProps) => {\n const [pnlToggle, setPnlToggle] = useState<PnlToggleOption>('expenses')\n\n return (\n <ProfitAndLoss asContainer={false}>\n <View title={title} headerControls={<ProfitAndLoss.DatePicker />}>\n {enableOnboarding && (\n <Onboarding\n onTransactionsToReviewClick={onTransactionsToReviewClick}\n />\n )}\n <div className='Layer__accounting-overview__summaries-row'>\n <ProfitAndLoss.Summaries\n stringOverrides={stringOverrides?.profitAndLoss?.summaries}\n />\n <TransactionToReviewCard\n usePnlDateRange={true}\n onClick={onTransactionsToReviewClick}\n />\n </div>\n <Container\n name='accounting-overview-profit-and-loss'\n asWidget\n elevated={true}\n >\n <Header>\n <Heading size={HeadingSize.secondary}>\n {stringOverrides?.header || 'Profit & Loss'}\n </Heading>\n </Header>\n <ProfitAndLoss.Chart />\n </Container>\n {middleBanner && (\n <Container name='accounting-overview-middle-banner'>\n {middleBanner}\n </Container>\n )}\n <div className='Layer__accounting-overview-profit-and-loss-charts'>\n <Toggle\n name='pnl-detailed-charts'\n options={[\n {\n value: 'revenue',\n label: 'Revenue',\n },\n {\n value: 'expenses',\n label: 'Expenses',\n },\n ]}\n selected={pnlToggle}\n onChange={e => setPnlToggle(e.target.value as PnlToggleOption)}\n />\n <Container\n name={classNames(\n 'accounting-overview-profit-and-loss-chart',\n pnlToggle !== 'revenue' &&\n 'accounting-overview-profit-and-loss-chart--hidden',\n )}\n >\n <ProfitAndLoss.DetailedCharts\n scope='revenue'\n hideClose={true}\n stringOverrides={stringOverrides?.profitAndLoss?.detailedCharts}\n chartColorsList={chartColorsList}\n />\n </Container>\n <Container\n name={classNames(\n 'accounting-overview-profit-and-loss-chart',\n pnlToggle !== 'expenses' &&\n 'accounting-overview-profit-and-loss-chart--hidden',\n )}\n >\n <ProfitAndLoss.DetailedCharts\n scope='expenses'\n hideClose={true}\n stringOverrides={stringOverrides?.profitAndLoss?.detailedCharts}\n chartColorsList={chartColorsList}\n />\n </Container>\n </div>\n </View>\n </ProfitAndLoss>\n )\n}\n", "import React, { useContext, useEffect, useState } from 'react'\nimport { Badge } from '../../components/Badge'\nimport { BadgeSize, BadgeVariant } from '../../components/Badge/Badge'\nimport { Text, TextSize } from '../../components/Typography'\nimport { useProfitAndLossLTM } from '../../hooks/useProfitAndLoss/useProfitAndLossLTM'\nimport BellIcon from '../../icons/Bell'\nimport CheckIcon from '../../icons/Check'\nimport RefreshCcw from '../../icons/RefreshCcw'\nimport { BadgeLoader } from '../BadgeLoader'\nimport { NotificationCard } from '../NotificationCard'\nimport { ProfitAndLoss } from '../ProfitAndLoss'\nimport { getMonth, getYear, startOfMonth } from 'date-fns'\n\nexport interface TransactionToReviewCardProps {\n onClick?: () => void\n usePnlDateRange?: boolean\n}\n\nexport const TransactionToReviewCard = ({\n onClick,\n usePnlDateRange,\n}: TransactionToReviewCardProps) => {\n const { dateRange: contextDateRange } = useContext(ProfitAndLoss.Context)\n const dateRange = usePnlDateRange ? contextDateRange : undefined\n\n const [toReview, setToReview] = useState(0)\n\n const { data, loaded, error, refetch } = useProfitAndLossLTM({\n currentDate: dateRange ? dateRange.startDate : startOfMonth(new Date()),\n })\n\n useEffect(() => {\n checkTransactionsToReview()\n }, [])\n\n useEffect(() => {\n checkTransactionsToReview()\n }, [dateRange, loaded])\n\n const checkTransactionsToReview = () => {\n if (data && dateRange) {\n const monthTx = data.filter(\n x =>\n x.month - 1 === getMonth(dateRange.startDate) &&\n x.year === getYear(dateRange.startDate),\n )\n if (monthTx.length > 0) {\n setToReview(monthTx[0].uncategorized_transactions)\n }\n }\n }\n\n return (\n <NotificationCard\n className='Layer__txs-to-review'\n onClick={() => onClick && onClick()}\n >\n <Text size={TextSize.sm}>Transactions to review</Text>\n {loaded === 'initial' || loaded === 'loading' ? <BadgeLoader /> : null}\n\n {loaded === 'complete' && error ? (\n <Badge\n variant={BadgeVariant.ERROR}\n size={BadgeSize.SMALL}\n icon={<RefreshCcw size={12} />}\n onClick={() => refetch()}\n >\n Refresh\n </Badge>\n ) : null}\n\n {loaded === 'complete' && !error && toReview > 0 ? (\n <Badge\n variant={BadgeVariant.WARNING}\n size={BadgeSize.SMALL}\n icon={<BellIcon size={12} />}\n >\n {toReview} pending\n </Badge>\n ) : null}\n\n {loaded === 'complete' && !error && toReview === 0 ? (\n <Badge\n variant={BadgeVariant.SUCCESS}\n size={BadgeSize.SMALL}\n icon={<CheckIcon size={12} />}\n >\n All done\n </Badge>\n ) : null}\n </NotificationCard>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport LoaderIcon from '../../icons/Loader'\n\nexport interface BadgeLoaderProps {\n children?: ReactNode\n size?: number\n}\n\nexport const BadgeLoader = ({ children }: BadgeLoaderProps) => {\n return (\n <span className='Layer__loader Layer__loader--as-badge'>\n <LoaderIcon size={11} className='Layer__anim--rotating' />\n {children}\n </span>\n )\n}\n", "import React, { ReactNode } from 'react'\nimport ChevronRightIcon from '../../icons/ChevronRight'\nimport { IconButton } from '../Button'\nimport classNames from 'classnames'\n\nexport interface NotificationCardProps {\n onClick: () => void\n children: ReactNode\n className?: string\n}\n\nexport const NotificationCard = ({\n onClick,\n children,\n className,\n}: NotificationCardProps) => {\n return (\n <div className={classNames('Layer__notification-card', className)}>\n <div className='Layer__notification-card__main'>{children}</div>\n <IconButton\n icon={<ChevronRightIcon />}\n withBorder\n onClick={() => onClick()}\n />\n </div>\n )\n}\n", "import React from 'react'\nimport { BankTransactions } from '../../components/BankTransactions'\nimport {\n BankTransactionsMode,\n BankTransactionsStringOverrides,\n} from '../../components/BankTransactions/BankTransactions'\nimport { MobileComponentType } from '../../components/BankTransactions/constants'\nimport { LinkedAccounts } from '../../components/LinkedAccounts'\nimport { View } from '../../components/View'\n\ninterface BankTransactionsWithLinkedAccountsStringOverrides {\n title?: string\n linkedAccounts?: BankTransactionsWithLinkedAccountsStringOverrides\n bankTransactions?: BankTransactionsStringOverrides\n}\n\nexport interface BankTransactionsWithLinkedAccountsProps {\n title?: string // deprecated\n elevatedLinkedAccounts?: boolean\n showLedgerBalance?: boolean\n showUnlinkItem?: boolean\n showBreakConnection?: boolean\n showDescriptions?: boolean\n showReceiptUploads?: boolean\n mode?: BankTransactionsMode\n mobileComponent?: MobileComponentType\n stringOverrides?: BankTransactionsWithLinkedAccountsStringOverrides\n}\n\nexport const BankTransactionsWithLinkedAccounts = ({\n title, // deprecated\n elevatedLinkedAccounts = true,\n showLedgerBalance = true,\n showUnlinkItem = false,\n showBreakConnection = false,\n mode = 'self-serve',\n showDescriptions,\n showReceiptUploads,\n mobileComponent,\n stringOverrides,\n}: BankTransactionsWithLinkedAccountsProps) => {\n return (\n <View title={stringOverrides?.title || title || 'Bank transactions'}>\n <LinkedAccounts\n elevated={elevatedLinkedAccounts}\n showLedgerBalance={showLedgerBalance}\n showUnlinkItem={showUnlinkItem}\n showBreakConnection={showBreakConnection}\n stringOverrides={stringOverrides?.linkedAccounts}\n />\n <BankTransactions\n asWidget\n showDescriptions={showDescriptions}\n showReceiptUploads={showReceiptUploads}\n mobileComponent={mobileComponent}\n mode={mode}\n stringOverrides={stringOverrides?.bankTransactions}\n />\n </View>\n )\n}\n", "import React, { useState } from 'react'\nimport { ChartOfAccounts } from '../../components/ChartOfAccounts'\nimport { ChartOfAccountsStringOverrides } from '../../components/ChartOfAccounts/ChartOfAccounts'\nimport { Container } from '../../components/Container'\nimport { Journal } from '../../components/Journal'\nimport { JournalStringOverrides } from '../../components/Journal/Journal'\nimport { ProfitAndLoss } from '../../components/ProfitAndLoss'\nimport { Toggle } from '../../components/Toggle'\nimport { View } from '../../components/View'\n\nexport interface GeneralLedgerStringOverrides {\n title?: string\n chartOfAccountsToggleOption?: string\n journalToggleOption?: string\n chartOfAccounts: ChartOfAccountsStringOverrides\n journal: JournalStringOverrides\n}\n\nexport interface GeneralLedgerProps {\n title?: string // deprecated\n stringOverrides?: GeneralLedgerStringOverrides\n}\n\nexport const GeneralLedgerView = ({\n title, // deprecated\n stringOverrides,\n}: GeneralLedgerProps) => {\n const [activeTab, setActiveTab] = useState('chartOfAccounts')\n\n return (\n <ProfitAndLoss asContainer={false}>\n <View title={stringOverrides?.title || title || 'General Ledger'}>\n <Toggle\n name='general-ledger-tabs'\n options={[\n {\n value: 'chartOfAccounts',\n label:\n stringOverrides?.chartOfAccountsToggleOption ||\n 'Chart of accounts',\n },\n {\n value: 'journal',\n label: stringOverrides?.journalToggleOption || 'Journal',\n },\n ]}\n selected={activeTab}\n onChange={opt => setActiveTab(opt.target.value)}\n />\n <Container name='generalLedger'>\n {activeTab === 'chartOfAccounts' ? (\n <ChartOfAccounts\n asWidget\n withExpandAllButton\n stringOverrides={stringOverrides?.chartOfAccounts}\n />\n ) : (\n <Journal stringOverrides={stringOverrides?.journal} />\n )}\n </Container>\n </View>\n </ProfitAndLoss>\n )\n}\n", "import React, { RefObject, useContext, useRef, useState } from 'react'\nimport { Layer } from '../../api/layer'\nimport { BalanceSheet } from '../../components/BalanceSheet'\nimport { BalanceSheetStringOverrides } from '../../components/BalanceSheet/BalanceSheet'\nimport { Button, ButtonVariant, RetryButton } from '../../components/Button'\nimport { Container } from '../../components/Container'\nimport { Panel } from '../../components/Panel'\nimport { ProfitAndLoss } from '../../components/ProfitAndLoss'\nimport { ProfitAndLossDetailedChartsStringOverrides } from '../../components/ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts'\nimport { ProfitAndLossTableStringOverrides } from '../../components/ProfitAndLossTable/ProfitAndLossTable'\nimport { StatementOfCashFlow } from '../../components/StatementOfCashFlow'\nimport { StatementOfCashFlowStringOverrides } from '../../components/StatementOfCashFlow/StatementOfCashFlow'\nimport { Toggle } from '../../components/Toggle'\nimport { View } from '../../components/View'\nimport { useLayerContext } from '../../contexts/LayerContext'\nimport DownloadCloud from '../../icons/DownloadCloud'\n\ninterface ReportsStringOverrides {\n title?: string\n downloadButton?: DownloadButtonStringOverrides\n profitAndLoss?: {\n detailedCharts?: ProfitAndLossDetailedChartsStringOverrides\n table?: ProfitAndLossTableStringOverrides\n }\n balanceSheet?: BalanceSheetStringOverrides\n statementOfCashflow?: StatementOfCashFlowStringOverrides\n}\n\nexport interface ReportsProps {\n title?: string // deprecated\n stringOverrides?: ReportsStringOverrides\n enabledReports?: ReportType[]\n}\n\ntype ReportType = 'profitAndLoss' | 'balanceSheet' | 'statementOfCashFlow'\ntype ReportOption = { value: ReportType; label: string }\nexport interface ReportsPanelProps {\n containerRef: RefObject<HTMLDivElement>\n openReport: ReportType\n stringOverrides?: ReportsStringOverrides\n}\n\ninterface DownloadButtonStringOverrides {\n downloadButtonText?: string\n retryButtonText?: string\n}\n\nconst DownloadButton = ({\n stringOverrides,\n}: {\n stringOverrides?: DownloadButtonStringOverrides\n}) => {\n const { dateRange } = useContext(ProfitAndLoss.Context)\n const { auth, businessId, apiUrl } = useLayerContext()\n const [requestFailed, setRequestFailed] = useState(false)\n\n const handleClick = async () => {\n const month = (dateRange.startDate.getMonth() + 1).toString()\n const year = dateRange.startDate.getFullYear().toString()\n const getProfitAndLossCsv = Layer.getProfitAndLossCsv(\n apiUrl,\n auth.access_token,\n {\n params: {\n businessId: businessId,\n year: year,\n month: month,\n },\n },\n )\n try {\n const result = await getProfitAndLossCsv()\n if (result?.data?.presignedUrl) {\n window.location.href = result.data.presignedUrl\n setRequestFailed(false)\n } else {\n setRequestFailed(true)\n }\n } catch (e) {\n setRequestFailed(true)\n }\n }\n\n return requestFailed ? (\n <RetryButton\n onClick={handleClick}\n className='Layer__download-retry-btn'\n error={'Approval failed. Check connection and retry in few seconds.'}\n >\n {stringOverrides?.retryButtonText || 'Retry'}\n </RetryButton>\n ) : (\n <Button\n variant={ButtonVariant.secondary}\n rightIcon={<DownloadCloud size={12} />}\n onClick={handleClick}\n >\n {stringOverrides?.downloadButtonText || 'Download'}\n </Button>\n )\n}\n\nconst getOptions = (enabledReports: ReportType[]) => {\n return [\n enabledReports.includes('profitAndLoss')\n ? {\n value: 'profitAndLoss',\n label: 'Profit & Loss',\n }\n : null,\n enabledReports.includes('balanceSheet')\n ? {\n value: 'balanceSheet',\n label: 'Balance Sheet',\n }\n : null,\n enabledReports.includes('statementOfCashFlow')\n ? {\n value: 'statementOfCashFlow',\n label: 'Statement of Cash Flow',\n }\n : null,\n ].filter(o => !!o) as ReportOption[]\n}\n\nexport const Reports = ({\n title,\n stringOverrides,\n enabledReports = ['profitAndLoss', 'balanceSheet', 'statementOfCashFlow'],\n}: ReportsProps) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [activeTab, setActiveTab] = useState<ReportType>(enabledReports[0])\n\n const options = getOptions(enabledReports)\n const defaultTitle =\n enabledReports.length > 1\n ? 'Reports'\n : options.find(option => (option.value = enabledReports[0]))?.label\n\n return (\n <View title={stringOverrides?.title || title || defaultTitle}>\n {enabledReports.length > 1 && (\n <div className='Layer__component Layer__header__actions'>\n <Toggle\n name='reports-tabs'\n options={options}\n selected={activeTab}\n onChange={opt => setActiveTab(opt.target.value as ReportType)}\n />\n </div>\n )}\n <Container name='reports' ref={containerRef}>\n <ProfitAndLoss asContainer={false}>\n <ReportsPanel\n containerRef={containerRef}\n openReport={activeTab}\n stringOverrides={stringOverrides}\n />\n </ProfitAndLoss>\n </Container>\n </View>\n )\n}\n\nconst ReportsPanel = ({\n containerRef,\n openReport,\n stringOverrides,\n}: ReportsPanelProps) => {\n const { sidebarScope } = useContext(ProfitAndLoss.Context)\n return (\n <>\n {openReport === 'profitAndLoss' && (\n <View\n type='panel'\n headerControls={\n <>\n <ProfitAndLoss.DatePicker />\n <DownloadButton\n stringOverrides={stringOverrides?.downloadButton}\n />\n </>\n }\n >\n <Panel\n sidebar={\n <ProfitAndLoss.DetailedCharts\n showDatePicker={false}\n stringOverrides={stringOverrides?.profitAndLoss?.detailedCharts}\n />\n }\n sidebarIsOpen={Boolean(sidebarScope)}\n parentRef={containerRef}\n >\n <ProfitAndLoss.Table\n asContainer={false}\n stringOverrides={stringOverrides?.profitAndLoss?.table}\n />\n </Panel>\n </View>\n )}\n {openReport === 'balanceSheet' && (\n <BalanceSheet stringOverrides={stringOverrides?.balanceSheet} />\n )}\n {openReport === 'statementOfCashFlow' && (\n <StatementOfCashFlow\n stringOverrides={stringOverrides?.statementOfCashflow}\n />\n )}\n </>\n )\n}\n", "import React, { RefObject, useContext, useRef } from 'react'\nimport { Container, Header } from '../Container'\nimport { DataState, DataStateStatus } from '../DataState'\nimport { Panel } from '../Panel'\nimport { ProfitAndLoss } from '../ProfitAndLoss'\nimport { ProfitAndLossDetailedCharts } from '../ProfitAndLossDetailedCharts'\nimport { ProfitAndLossDetailedChartsStringOverrides } from '../ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts'\nimport { ProfitAndLossSummariesStringOverrides } from '../ProfitAndLossSummaries/ProfitAndLossSummaries'\nimport { ProfitAndLossTableStringOverrides } from '../ProfitAndLossTable/ProfitAndLossTable'\nimport { Heading } from '../Typography'\n\nconst COMPONENT_NAME = 'profit-and-loss'\n\nexport interface ProfitAndLossViewProps {\n hideTable?: boolean\n hideChart?: boolean\n showDetailedCharts?: boolean\n stringOverrides?: {\n header?: string\n profitAndLossTable?: ProfitAndLossTableStringOverrides\n profitAndLossSummaries?: ProfitAndLossSummariesStringOverrides\n profitAndLossDetailedCharts?: ProfitAndLossDetailedChartsStringOverrides\n }\n}\n\nexport interface ProfitAndLossViewPanelProps extends ProfitAndLossViewProps {\n containerRef: RefObject<HTMLDivElement>\n}\n\nexport const ProfitAndLossView = (props: ProfitAndLossViewProps) => {\n const containerRef = useRef<HTMLDivElement>(null)\n\n return (\n <Container name={COMPONENT_NAME} ref={containerRef}>\n <ProfitAndLoss>\n <ProfitAndLossPanel containerRef={containerRef} {...props} />\n </ProfitAndLoss>\n </Container>\n )\n}\n\nconst ProfitAndLossPanel = ({\n containerRef,\n stringOverrides,\n ...props\n}: ProfitAndLossViewPanelProps) => {\n const { sidebarScope } = useContext(ProfitAndLoss.Context)\n\n return (\n <Panel\n sidebar={\n <ProfitAndLossDetailedCharts\n stringOverrides={stringOverrides?.profitAndLossDetailedCharts}\n />\n }\n sidebarIsOpen={Boolean(sidebarScope)}\n parentRef={containerRef}\n >\n <Header className={`Layer__${COMPONENT_NAME}__header`}>\n <Heading className='Layer__profit-and-loss__title'>\n {stringOverrides?.header || 'Profit & Loss'}\n </Heading>\n </Header>\n\n <Components stringOverrides={stringOverrides} {...props} />\n </Panel>\n )\n}\n\nconst Components = ({\n hideChart = false,\n hideTable = false,\n stringOverrides,\n}: ProfitAndLossViewProps) => {\n const { error, isLoading, isValidating, refetch } = useContext(\n ProfitAndLoss.Context,\n )\n\n if (!isLoading && error) {\n return (\n <div className='Layer__table-state-container'>\n <DataState\n status={DataStateStatus.failed}\n title='Something went wrong'\n description='We couldn\u2019t load your data.'\n onRefresh={() => refetch()}\n isLoading={isValidating}\n />\n </div>\n )\n }\n\n return (\n <>\n {!hideChart && (\n <div className={`Layer__${COMPONENT_NAME}__chart_with_summaries`}>\n <div\n className={`Layer__${COMPONENT_NAME}__chart_with_summaries__summary-col`}\n >\n <ProfitAndLoss.DatePicker />\n <ProfitAndLoss.Summaries\n vertical={true}\n actionable\n stringOverrides={stringOverrides?.profitAndLossSummaries}\n />\n </div>\n <div\n className={`Layer__${COMPONENT_NAME}__chart_with_summaries__chart-col`}\n >\n <ProfitAndLoss.Chart />\n </div>\n </div>\n )}\n {!hideTable && (\n <ProfitAndLoss.Table\n stringOverrides={stringOverrides?.profitAndLossTable}\n />\n )}\n </>\n )\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["React", "useEffect", "React", "useContext", "React", "createContext", "useContext", "React", "useContext", "React", "useState", "useState", "useState", "React", "createContext", "useContext", "Direction", "DisplayState", "createContext", "useContext", "useEffect", "useMemo", "useState", "useState", "useMemo", "useEffect", "React", "useEffect", "theme", "colors", "React", "React", "useContext", "useEffect", "useState", "createContext", "React", "useEffect", "useState", "useSWR", "useState", "useEffect", "linkToken", "exchangePlaidPublicToken", "updateConnectionStatus", "unlinkPlaidItem", "unlinkAccount", "React", "React", "forwardRef", "classNames", "forwardRef", "React", "React", "forwardRef", "classNames", "forwardRef", "classNames", "React", "React", "useContext", "useMemo", "React", "React", "React", "React", "React", "React", "parseISO", "React", "React", "React", "classNames", "classNames", "React", "React", "classNames", "React", "React", "classNames", "React", "React", "React", "React", "React", "React", "React", "forwardRef", "React", "useState", "React", "forwardRef", "TooltipTrigger", "TooltipContent", "classNames", "React", "classNames", "React", "classNames", "React", "React", "classNames", "React", "React", "React", "classNames", "React", "React", "classNames", "React", "React", "useRef", "classNames", "Link", "useRef", "React", "React", "useRef", "useState", "useEffect", "classNames", "Component", "classNames", "React", "useRef", "useEffect", "useState", "React", "classNames", "Component", "classNames", "React", "React", "classNames", "React", "React", "React", "classNames", "classNames", "React", "React", "React", "React", "useContext", "useMemo", "React", "React", "useState", "useContext", "useEffect", "React", "useContext", "React", "Loader", "React", "React", "React", "React", "useContext", "React", "React", "React", "React", "useEffect", "useRef", "useState", "classNames", "classNames", "React", "React", "React", "React", "React", "React", "classNames", "React", "classNames", "unlinkAccount", "useContext", "React", "React", "useContext", "Loader", "React", "useState", "useMemo", "useEffect", "useLayoutEffect", "useRef", "React", "React", "useEffect", "useRef", "useState", "React", "React", "useEffect", "useRef", "useState", "React", "React", "React", "React", "React", "React", "useContext", "React", "useState", "React", "classNames", "React", "useState", "React", "classNames", "useContext", "React", "classNames", "parseISO", "mapCategoryToOption", "React", "classNames", "Option", "parseISO", "flattenCategories", "React", "forwardRef", "useState", "useEffect", "useRef", "React", "React", "React", "classNames", "React", "React", "classNames", "React", "React", "useRef", "React", "useRef", "React", "React", "components", "classNames", "DropdownIndicator", "React", "components", "Select", "React", "classNames", "React", "React", "React", "parseISO", "formatTime", "React", "classNames", "parseISO", "formatTime", "React", "React", "classNames", "parseISO", "formatTime", "React", "React", "classNames", "React", "React", "useEffect", "useState", "classNames", "useState", "classNames", "shift", "useEffect", "React", "React", "useEffect", "useState", "useState", "timestamp", "useEffect", "React", "classNames", "isAlreadyMatched", "forwardRef", "categorizeBankTransaction", "matchBankTransaction", "useState", "useRef", "mapCategoryToOption", "index", "getBankTransactionMetadata", "listBankTransactionDocuments", "height", "useEffect", "React", "classNames", "React", "React", "classNames", "parseISO", "formatTime", "mapCategoryToOption", "useRef", "useState", "categorizeBankTransaction", "matchBankTransaction", "useEffect", "React", "React", "parseISO", "formatTime", "React", "classNames", "parseISO", "formatTime", "useRef", "useState", "categorizeBankTransaction", "matchBankTransaction", "useEffect", "React", "React", "React", "React", "useContext", "useEffect", "useRef", "useState", "React", "React", "useContext", "useEffect", "useMemo", "useState", "useContext", "categorizeBankTransaction", "useState", "useEffect", "useMemo", "options", "React", "React", "useEffect", "useState", "categorizeBankTransaction", "useState", "useEffect", "React", "React", "useState", "React", "useEffect", "useState", "MatchForm", "matchBankTransaction", "useState", "useEffect", "React", "React", "useEffect", "useState", "classNames", "categorizeBankTransaction", "useState", "mapCategoryToOption", "useEffect", "index", "validateSplit", "React", "useState", "React", "MatchForm", "React", "createContext", "useState", "classNames", "parseISO", "formatTime", "DATE_FORMAT", "getAssignedValue", "useContext", "height", "useRef", "useState", "useEffect", "classNames", "React", "formatTime", "parseISO", "React", "React", "React", "React", "React", "classNames", "React", "React", "React", "classNames", "React", "React", "React", "React", "React", "React", "React", "useMemo", "useMemo", "React", "React", "React", "useState", "React", "parseISO", "React", "useEffect", "useRef", "useState", "React", "startOfMonth", "React", "classNames", "useRef", "useState", "useEffect", "React", "classNames", "endOfMonth", "startOfMonth", "useState", "getBankTransactionsCsv", "React", "React", "React", "React", "endOfMonth", "parseISO", "startOfMonth", "COMPONENT_NAME", "React", "useState", "useMemo", "useEffect", "Loader", "React", "useEffect", "useRef", "useState", "DEBUG", "useState", "useRef", "useEffect", "syncFromQuickbooks", "syncFromQuickbooks", "React", "React", "createContext", "useMemo", "useState", "item", "useEffect", "startOfMonth", "endOfMonth", "useSWR", "useEffect", "startOfMonth", "endOfMonth", "useState", "useMemo", "React", "useContext", "useEffect", "useMemo", "useState", "useEffect", "useMemo", "useState", "startOfMonth", "useSWR", "useState", "useMemo", "useEffect", "date", "React", "useEffect", "useState", "classNames", "add", "endOfMonth", "startOfMonth", "sub", "Tooltip", "useState", "useContext", "useMemo", "useEffect", "React", "React", "useContext", "endOfMonth", "startOfMonth", "useContext", "React", "React", "useContext", "useState", "React", "React", "useMemo", "React", "React", "classNames", "React", "Cell", "ResponsiveContainer", "useMemo", "React", "React", "Select", "components", "React", "Select", "components", "format", "useContext", "useState", "React", "React", "useContext", "useMemo", "React", "PieChart", "Pie", "Cell", "React", "classNames", "useContext", "useMemo", "React", "React", "useContext", "React", "useState", "React", "PieChart", "useState", "React", "classNames", "useContext", "React", "Loader", "endOfMonth", "startOfMonth", "createContext", "React", "React", "useEffect", "useState", "createContext", "React", "createContext", "useState", "useEffect", "format", "useSWR", "useEffect", "React", "React", "React", "useContext", "useContext", "React", "React", "useEffect", "React", "React", "classNames", "React", "React", "React", "classNames", "React", "useEffect", "useRef", "classNames", "useEffect", "React", "React", "React", "React", "React", "useEffect", "useState", "classNames", "classNames", "React", "format", "startOfDay", "COMPONENT_NAME", "React", "useState", "useEffect", "Loader", "React", "useState", "createContext", "useEffect", "format", "startOfDay", "useSWR", "useEffect", "React", "React", "startOfDay", "COMPONENT_NAME", "React", "useState", "Loader", "React", "useContext", "useState", "createContext", "endOfMonth", "startOfMonth", "createContext", "useEffect", "useState", "endOfMonth", "formatISO", "startOfMonth", "useSWR", "useState", "data", "useEffect", "useEffect", "useState", "useSWR", "useState", "useEffect", "React", "useContext", "useState", "React", "useContext", "endOfMonth", "startOfMonth", "useContext", "React", "React", "useContext", "useEffect", "useState", "React", "classNames", "EXPANDED_STYLE", "COLLAPSED_STYLE", "useContext", "useState", "useEffect", "React", "React", "React", "useContext", "useMemo", "useMemo", "useMemo", "useContext", "useMemo", "React", "Select", "React", "COMPONENT_NAME", "useContext", "useState", "React", "Loader", "React", "useContext", "useEffect", "useMemo", "useState", "React", "useContext", "useMemo", "React", "classNames", "React", "parseISO", "formatTime", "format", "React", "React", "classNames", "React", "React", "React", "React", "useContext", "useMemo", "totalDebit", "totalCredit", "React", "useContext", "useEffect", "useState", "classNames", "parseISO", "formatTime", "useContext", "useState", "useEffect", "React", "classNames", "useState", "useContext", "useEffect", "useMemo", "React", "Loader", "React", "useContext", "useState", "React", "useState", "createContext", "useEffect", "useState", "useSWR", "useState", "validate", "useEffect", "React", "useContext", "useMemo", "useState", "React", "useContext", "useEffect", "useState", "classNames", "parseISO", "formatTime", "INDENTATION", "EXPANDED_STYLE", "COLLAPSED_STYLE", "useContext", "useState", "useEffect", "React", "React", "useContext", "React", "useContext", "useMemo", "useContext", "useMemo", "React", "index", "React", "useContext", "React", "useContext", "useContext", "React", "idx", "Select", "useContext", "React", "useContext", "React", "COMPONENT_NAME", "useState", "useContext", "useMemo", "React", "Loader", "React", "useState", "React", "createContext", "useContext", "useEffect", "useMemo", "useState", "createContext", "useEffect", "useState", "useSWR", "useState", "useEffect", "submitResponseToTask", "data", "React", "useContext", "React", "React", "useContext", "React", "useContext", "useMemo", "useState", "React", "React", "useContext", "useEffect", "useState", "classNames", "useState", "submitResponseToTask", "useContext", "useEffect", "React", "React", "useContext", "useState", "useMemo", "task", "React", "useContext", "classNames", "format", "Cell", "Pie", "PieChart", "useContext", "React", "classNames", "createContext", "React", "useContext", "useMemo", "useState", "useEffect", "classNames", "Loader", "React", "React", "React", "React", "Link", "React", "useState", "classNames", "useState", "React", "React", "useState", "React", "useContext", "useEffect", "useState", "React", "React", "React", "classNames", "React", "startOfMonth", "useContext", "useState", "useEffect", "React", "classNames", "useState", "React", "React", "React", "React", "useState", "useState", "React", "React", "useContext", "useRef", "useState", "DownloadButton", "useContext", "useState", "getProfitAndLossCsv", "React", "useRef", "React", "useContext", "useRef", "COMPONENT_NAME", "useRef", "React", "useContext"]
|
|
7
7
|
}
|