story(TEAMMSBMOB-19638): фиксы по странице "Счета"

This commit is contained in:
nizhegorodtsevav
2025-11-14 12:53:04 +03:00
parent 347e6942bd
commit 6fbf04fde8
9 changed files with 101 additions and 77 deletions
+1
View File
@@ -31,6 +31,7 @@ const PATHS_DEPOSITS = {
EARLY_REFUND: `${PATHS.DEPOSITS}/products/early-refund`,
ACCOUNTS: `${PATHS.DEPOSITS}/accounts`,
ACCOUNTS_CREATE_INTERNAL: `${PATHS.DEPOSITS}/accounts/create/internal`,
ACCOUNTS_CREATE_EXTERNAL: `${PATHS.DEPOSITS}/accounts/create/external`,
OPEN_PRODUCT: `${PATHS.DEPOSITS}/`,
} as const;
@@ -16,8 +16,15 @@ const TabsWrapper = styled.div(({ theme }) => ({
}));
const OrgWrapper = styled.div(() => ({
position: 'relative',
height: '100%',
}));
export { Container, TabsWrapper, OrgWrapper };
const ContentWrapper = styled.div(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
height: '100%',
gap: theme.space[8],
position: 'relative',
}));
export { Container, TabsWrapper, OrgWrapper, ContentWrapper };
@@ -13,11 +13,12 @@ import { AccountsFilterForm } from '@/widgets/AccountsFiltersForm';
const defaultFilters: AccountFilter = { organizations: [], accountUsage: [], currencies: [], accountName: '' };
const AccountsPageContent = () => {
const { userAuthorities } = useAppContext();
const AccountsPageContent = ({ hasRights }: { hasRights: boolean }) => {
const { userInfoUnionData } = useUserInfoUnion();
const formRef = useRef<any>(null);
const goBack = useRedirect('b');
const [filtersState, setFiltersState] = useState<AccountFilter>(defaultFilters);
const setOrganization = (id: string) => formRef.current?.change('organizations', [id]);
@@ -26,9 +27,13 @@ const AccountsPageContent = () => {
setFiltersState(defaultFilters);
}, []);
const hasRights = checkHaveUserPermissions(userAuthorities?.data.authorities, necessaryUserAuthorities);
const [activeTab, setActiveTab] = useState<string | undefined>(localization.INTERNAL_TAB_VALUE);
const createAccountLink = useMemo(
() => (activeTab === localization.INTERNAL_TAB_VALUE ? PATHS.ACCOUNTS_CREATE_INTERNAL.PATH : PATHS.ACCOUNTS_CREATE_EXTERNAL.PATH),
[activeTab]
);
const tabHandleChange = (value: string | undefined) => setActiveTab(value);
const organizationIds = useMemo(
@@ -40,24 +45,6 @@ const AccountsPageContent = () => {
[filtersState, userInfoUnionData]
);
if (organizationIds.length === 0) {
return (
<SystemResponseWrapper>
<SystemResponse
description={localization.SYSTEM_RESPONSE_RIGHTS.DESCRIPTION}
mainButtonProps={{
dataAction: 'select',
variant: 'primary',
children: localization.SYSTEM_RESPONSE_ADD_NEW.BUTTON_TEXT,
}}
size="M"
statusIcon="addNew"
text={localization.SYSTEM_RESPONSE_ADD_NEW.TEXT}
/>
</SystemResponseWrapper>
);
}
if (!hasRights)
return (
<SystemResponseWrapper>
@@ -67,6 +54,7 @@ const AccountsPageContent = () => {
dataAction: 'click',
variant: 'secondary',
children: localization.SYSTEM_RESPONSE_BUTTON_TEXT,
onClick: goBack,
}}
size="M"
statusIcon="error"
@@ -80,30 +68,37 @@ const AccountsPageContent = () => {
<S.TabsWrapper>
<Tabs activeTab={activeTab} options={tabOptions} onTabChange={tabHandleChange} />
</S.TabsWrapper>
<AccountsFilterForm formRef={formRef} setFiltersState={setFiltersState} />
<S.OrgWrapper>
{organizationIds.length > 1 ? (
<SeveralOrganizations
accountType={activeTab}
filterState={filtersState}
organizationIds={organizationIds}
resetFilters={resetFilters}
setOrganization={setOrganization}
/>
) : (
<SingleOrganization
accountType={activeTab}
filterState={filtersState}
organizationId={organizationIds[0]}
resetFilters={resetFilters}
/>
)}
</S.OrgWrapper>
<S.ContentWrapper>
<AccountsFilterForm formRef={formRef} setFiltersState={setFiltersState} />
<S.OrgWrapper>
{organizationIds.length > 1 ? (
<SeveralOrganizations
accountType={activeTab}
createAccountLink={createAccountLink}
filterState={filtersState}
organizationIds={organizationIds}
resetFilters={resetFilters}
setOrganization={setOrganization}
/>
) : (
<SingleOrganization
accountType={activeTab}
createAccountLink={createAccountLink}
filterState={filtersState}
organizationId={organizationIds[0]}
resetFilters={resetFilters}
/>
)}
</S.OrgWrapper>
</S.ContentWrapper>
</>
);
};
const AccountsPage = () => {
const { userAuthorities } = useAppContext();
const hasRights = checkHaveUserPermissions(userAuthorities?.data.authorities, necessaryUserAuthorities);
const toEcoAccounts = useRedirect(ECO_SERVICES_PATHS.WEB_DEALING_ACCOUNTS);
const { isEnabled: isAccountsEnabled } = useFeatureToggles(FEATURE_TOGGLE_NAMES.DEPOSIT_ACCOUNTS);
@@ -114,8 +109,8 @@ const AccountsPage = () => {
return (
<S.Container>
<PageHeader contextMenuButtonsVisible title={PATHS.ACCOUNTS.TITLE} />
<AccountsPageContent />
<PageHeader contextMenuButtonsVisible={hasRights} title={PATHS.ACCOUNTS.TITLE} />
<AccountsPageContent hasRights={hasRights} />
</S.Container>
);
};
@@ -9,6 +9,7 @@ const PATHS = {
EARLY_REFUND: { PATH: PATHS_DEPOSITS.EARLY_REFUND, TITLE: 'Досрочное закрытие' },
ACCOUNTS: { PATH: PATHS_DEPOSITS.ACCOUNTS, TITLE: 'Счета' },
ACCOUNTS_CREATE_INTERNAL: { PATH: PATHS_DEPOSITS.ACCOUNTS_CREATE_INTERNAL, TITLE: 'Добавить внутренний счёт' },
ACCOUNTS_CREATE_EXTERNAL: { PATH: PATHS_DEPOSITS.ACCOUNTS_CREATE_EXTERNAL, TITLE: 'Добавить внешний счёт' },
} as const;
export { PATHS };
@@ -1,13 +1,14 @@
import styled from '@emotion/styled';
const StyledSystemResponse = styled.div`
const StyledSystemResponse = styled.div<{ $absolute?: boolean }>`
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
position: ${props => (props.$absolute ? 'absolute' : 'static')};
top: ${props => props.$absolute && 0};
background-color: ${props => props.theme.colors.bg.primary};
`;
const StyledSystemResponseWithLoading = styled(StyledSystemResponse)<{ $loading: boolean }>``;
export { StyledSystemResponseWithLoading, StyledSystemResponse };
export { StyledSystemResponse };
@@ -2,8 +2,11 @@ import * as S from './SystemResponseWrapper.styles';
interface SystemResponseWrapperProps {
children: React.ReactNode;
absolute?: boolean;
}
const SystemResponseWrapper = ({ children }: SystemResponseWrapperProps) => <S.StyledSystemResponse>{children}</S.StyledSystemResponse>;
const SystemResponseWrapper = ({ children, absolute }: SystemResponseWrapperProps) => (
<S.StyledSystemResponse $absolute={absolute}>{children}</S.StyledSystemResponse>
);
export { SystemResponseWrapper };
@@ -9,7 +9,6 @@ const localization = {
TEXT: 'Что-то не сработало',
},
SYSTEM_RESPONSE_ADD_NEW: {
DESCRIPTION: 'Обратитесь к владельцу организации',
BUTTON_TEXT: 'Добавить счёт',
TEXT: 'Здесь будут ваши счета для расчётов по депозитам и МНО',
},
@@ -17,7 +16,7 @@ const localization = {
TEXT_BANNED: 'Заблокирован',
INTERNAL_TITLE: 'Счёт',
EXTERNAL_TITLE: 'Внешний',
SHOW_MORE_TITLE: 'Показать ещё',
SHOW_MORE_TITLE: 'Показать все',
};
export { localization };
@@ -2,6 +2,7 @@ import { useMemo } from 'react';
import { Spinner } from '@fractal-ui/core';
import { SystemResponse } from '@fractal-ui/extended';
import { Text } from '@fractal-ui/styling';
import { useRedirect } from '@msb/shared';
import { localization } from '../constants';
import { AccountList } from './AccountsList';
import * as S from './SingleOrganization.styles';
@@ -14,11 +15,20 @@ interface Props {
filterState: AccountFilter;
setOrganization(id: string): void;
resetFilters(): void;
createAccountLink: string;
}
const SeveralOrganizations = ({ organizationIds, accountType = '', filterState, setOrganization, resetFilters }: Props) => {
const SeveralOrganizations = ({
organizationIds,
accountType = '',
filterState,
setOrganization,
resetFilters,
createAccountLink,
}: Props) => {
const { data, isLoading, isError } = useGetSeveralOrganizations(organizationIds, accountType, filterState);
const goToCreate = useRedirect(createAccountLink);
const goBack = useRedirect('b');
const commonTotalResult: number = useMemo(
() =>
data.reduce((acc: number, value): number => {
@@ -37,6 +47,25 @@ const SeveralOrganizations = ({ organizationIds, accountType = '', filterState,
);
}
if (isError) {
return (
<SystemResponseWrapper absolute>
<SystemResponse
description={localization.SYSTEM_RESPONSE_ERROR.DESCRIPTION}
mainButtonProps={{
dataAction: 'click',
variant: 'secondary',
children: localization.SYSTEM_RESPONSE_BUTTON_TEXT,
onClick: goBack,
}}
size="M"
statusIcon="error"
text={localization.SYSTEM_RESPONSE_ERROR.TEXT}
/>
</SystemResponseWrapper>
);
}
if (!isLoading && filterState.organizations.length > 0 && commonTotalResult === 0) {
return (
<SystemResponseWrapper>
@@ -58,13 +87,13 @@ const SeveralOrganizations = ({ organizationIds, accountType = '', filterState,
if (!isLoading && commonTotalResult === 0) {
return (
<SystemResponseWrapper>
<SystemResponseWrapper absolute>
<SystemResponse
description={localization.SYSTEM_RESPONSE_ADD_NEW.DESCRIPTION}
mainButtonProps={{
dataAction: 'select',
variant: 'primary',
children: localization.SYSTEM_RESPONSE_ADD_NEW.BUTTON_TEXT,
onClick: goToCreate,
}}
size="M"
statusIcon="addNew"
@@ -74,24 +103,6 @@ const SeveralOrganizations = ({ organizationIds, accountType = '', filterState,
);
}
if (isError) {
return (
<SystemResponseWrapper>
<SystemResponse
description={localization.SYSTEM_RESPONSE_ERROR.DESCRIPTION}
mainButtonProps={{
dataAction: 'click',
variant: 'secondary',
children: localization.SYSTEM_RESPONSE_BUTTON_TEXT,
}}
size="M"
statusIcon="error"
text={localization.SYSTEM_RESPONSE_ERROR.TEXT}
/>
</SystemResponseWrapper>
);
}
return (
<>
{data.map((account, index) => {
@@ -1,6 +1,7 @@
import { useEffect, useRef, useCallback } from 'react';
import { Spinner } from '@fractal-ui/core';
import { SystemResponse } from '@fractal-ui/extended';
import { useRedirect } from '@msb/shared';
import { localization } from '../constants';
import { AccountItem } from './AccountsList';
import * as S from './SingleOrganization.styles';
@@ -12,15 +13,19 @@ interface Props {
accountType: string | undefined;
filterState: AccountFilter;
resetFilters(): void;
createAccountLink: string;
}
const SingleOrganization = ({ organizationId, accountType, filterState, resetFilters }: Props) => {
const SingleOrganization = ({ organizationId, accountType, filterState, resetFilters, createAccountLink }: Props) => {
const { data, isLoading, isFetching, isError, hasNextPage, fetchNextPage } = useGetInfinityQueryForAccount(
organizationId,
accountType!,
filterState
);
const goToCreate = useRedirect(createAccountLink);
const goBack = useRedirect('b');
const loaderRef = useRef<HTMLDivElement>(null);
const observerRef = useRef<IntersectionObserver>();
@@ -72,13 +77,14 @@ const SingleOrganization = ({ organizationId, accountType, filterState, resetFil
if (isError) {
return (
<SystemResponseWrapper>
<SystemResponseWrapper absolute>
<SystemResponse
description={localization.SYSTEM_RESPONSE_ERROR.DESCRIPTION}
mainButtonProps={{
dataAction: 'click',
variant: 'secondary',
children: localization.SYSTEM_RESPONSE_BUTTON_TEXT,
onClick: goBack,
}}
size="M"
statusIcon="error"
@@ -111,11 +117,11 @@ const SingleOrganization = ({ organizationId, accountType, filterState, resetFil
return (
<SystemResponseWrapper>
<SystemResponse
description={localization.SYSTEM_RESPONSE_ADD_NEW.DESCRIPTION}
mainButtonProps={{
dataAction: 'select',
variant: 'primary',
children: localization.SYSTEM_RESPONSE_ADD_NEW.BUTTON_TEXT,
onClick: goToCreate,
}}
size="M"
statusIcon="addNew"