@redneckz/wildless-cms-uni-blocks 0.14.745 → 0.14.746
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/bundle/blocks.schema.json +1 -1
- package/bundle/bundle.umd.js +81 -8
- package/bundle/bundle.umd.min.js +1 -1
- package/bundle/components/CardTransfer/CardTransferContent.d.ts +2 -1
- package/bundle/components/CardTransfer/SubmitFailedDialog.d.ts +6 -0
- package/bundle/components/CardTransfer/submitCardTransfer.d.ts +16 -0
- package/bundle/components/CardTransfer/useSubmitCardTransfer.d.ts +11 -0
- package/dist/components/CardTransfer/CardTransfer.js +9 -7
- package/dist/components/CardTransfer/CardTransfer.js.map +1 -1
- package/dist/components/CardTransfer/CardTransferContent.d.ts +2 -1
- package/dist/components/CardTransfer/SubmitFailedDialog.d.ts +6 -0
- package/dist/components/CardTransfer/SubmitFailedDialog.js +13 -0
- package/dist/components/CardTransfer/SubmitFailedDialog.js.map +1 -0
- package/dist/components/CardTransfer/submitCardTransfer.d.ts +16 -0
- package/dist/components/CardTransfer/submitCardTransfer.js +44 -0
- package/dist/components/CardTransfer/submitCardTransfer.js.map +1 -0
- package/dist/components/CardTransfer/useSubmitCardTransfer.d.ts +11 -0
- package/dist/components/CardTransfer/useSubmitCardTransfer.js +33 -0
- package/dist/components/CardTransfer/useSubmitCardTransfer.js.map +1 -0
- package/lib/common.css +1 -1
- package/lib/components/CardTransfer/CardTransfer.fixture.d.ts +2 -1
- package/lib/components/CardTransfer/CardTransfer.fixture.mobile.d.ts +2 -1
- package/lib/components/CardTransfer/CardTransfer.js +10 -8
- package/lib/components/CardTransfer/CardTransfer.js.map +1 -1
- package/lib/components/CardTransfer/CardTransferContent.d.ts +2 -1
- package/lib/components/CardTransfer/SubmitFailedDialog.d.ts +6 -0
- package/lib/components/CardTransfer/SubmitFailedDialog.js +10 -0
- package/lib/components/CardTransfer/SubmitFailedDialog.js.map +1 -0
- package/lib/components/CardTransfer/submitCardTransfer.d.ts +16 -0
- package/lib/components/CardTransfer/submitCardTransfer.js +39 -0
- package/lib/components/CardTransfer/submitCardTransfer.js.map +1 -0
- package/lib/components/CardTransfer/useSubmitCardTransfer.d.ts +11 -0
- package/lib/components/CardTransfer/useSubmitCardTransfer.js +30 -0
- package/lib/components/CardTransfer/useSubmitCardTransfer.js.map +1 -0
- package/mobile/bundle/bundle.umd.js +81 -8
- package/mobile/bundle/bundle.umd.min.js +1 -1
- package/mobile/bundle/components/CardTransfer/CardTransferContent.d.ts +2 -1
- package/mobile/bundle/components/CardTransfer/SubmitFailedDialog.d.ts +6 -0
- package/mobile/bundle/components/CardTransfer/submitCardTransfer.d.ts +16 -0
- package/mobile/bundle/components/CardTransfer/useSubmitCardTransfer.d.ts +11 -0
- package/mobile/dist/components/CardTransfer/CardTransfer.js +9 -7
- package/mobile/dist/components/CardTransfer/CardTransfer.js.map +1 -1
- package/mobile/dist/components/CardTransfer/CardTransferContent.d.ts +2 -1
- package/mobile/dist/components/CardTransfer/SubmitFailedDialog.d.ts +6 -0
- package/mobile/dist/components/CardTransfer/SubmitFailedDialog.js +13 -0
- package/mobile/dist/components/CardTransfer/SubmitFailedDialog.js.map +1 -0
- package/mobile/dist/components/CardTransfer/submitCardTransfer.d.ts +16 -0
- package/mobile/dist/components/CardTransfer/submitCardTransfer.js +44 -0
- package/mobile/dist/components/CardTransfer/submitCardTransfer.js.map +1 -0
- package/mobile/dist/components/CardTransfer/useSubmitCardTransfer.d.ts +11 -0
- package/mobile/dist/components/CardTransfer/useSubmitCardTransfer.js +33 -0
- package/mobile/dist/components/CardTransfer/useSubmitCardTransfer.js.map +1 -0
- package/mobile/lib/common.css +1 -1
- package/mobile/lib/components/CardTransfer/CardTransfer.js +10 -8
- package/mobile/lib/components/CardTransfer/CardTransfer.js.map +1 -1
- package/mobile/lib/components/CardTransfer/CardTransferContent.d.ts +2 -1
- package/mobile/lib/components/CardTransfer/SubmitFailedDialog.d.ts +6 -0
- package/mobile/lib/components/CardTransfer/SubmitFailedDialog.js +10 -0
- package/mobile/lib/components/CardTransfer/SubmitFailedDialog.js.map +1 -0
- package/mobile/lib/components/CardTransfer/submitCardTransfer.d.ts +16 -0
- package/mobile/lib/components/CardTransfer/submitCardTransfer.js +39 -0
- package/mobile/lib/components/CardTransfer/submitCardTransfer.js.map +1 -0
- package/mobile/lib/components/CardTransfer/useSubmitCardTransfer.d.ts +11 -0
- package/mobile/lib/components/CardTransfer/useSubmitCardTransfer.js +30 -0
- package/mobile/lib/components/CardTransfer/useSubmitCardTransfer.js.map +1 -0
- package/mobile/src/components/CardTransfer/CardTransfer.tsx +12 -9
- package/mobile/src/components/CardTransfer/CardTransferContent.ts +3 -1
- package/mobile/src/components/CardTransfer/SubmitFailedDialog.tsx +42 -0
- package/mobile/src/components/CardTransfer/submitCardTransfer.ts +72 -0
- package/mobile/src/components/CardTransfer/useSubmitCardTransfer.tsx +47 -0
- package/package.json +1 -1
- package/src/components/CardTransfer/CardTransfer.fixture.mobile.tsx +11 -3
- package/src/components/CardTransfer/CardTransfer.fixture.tsx +13 -1
- package/src/components/CardTransfer/CardTransfer.tsx +12 -9
- package/src/components/CardTransfer/CardTransferContent.ts +3 -1
- package/src/components/CardTransfer/SubmitFailedDialog.tsx +42 -0
- package/src/components/CardTransfer/submitCardTransfer.ts +72 -0
- package/src/components/CardTransfer/useSubmitCardTransfer.tsx +47 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type CardTransferFormType } from './CardTransferContent';
|
|
2
|
+
export declare type CardTransferResponse = Partial<{
|
|
3
|
+
errorCode: number;
|
|
4
|
+
errorMessage: string;
|
|
5
|
+
orderId: string;
|
|
6
|
+
formUrl: string;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const submitCardTransfer: (typeForm: CardTransferFormType, amount: number) => Promise<CardTransferResponse | null>;
|
|
9
|
+
export declare const isSuccessResponse: (response: CardTransferResponse | null) => response is {
|
|
10
|
+
orderId: string;
|
|
11
|
+
formUrl: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const isErrorInResponse: (response: CardTransferResponse | null) => response is {
|
|
14
|
+
errorCode: number;
|
|
15
|
+
errorMessage: string;
|
|
16
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { API_BASE_URI } from '../../api/apiBaseUrl.js';
|
|
2
|
+
import { locationNavigator } from '../../external/locationNavigator.js';
|
|
3
|
+
const paymentURLMap = {
|
|
4
|
+
private: 'p2p/registerP2P',
|
|
5
|
+
business: 'b2c/registerB2C',
|
|
6
|
+
};
|
|
7
|
+
const SUCCESS_URL = '/p2p/success';
|
|
8
|
+
const FAIL_URL = '/p2p/success';
|
|
9
|
+
const CURRENCY_CODE = '643';
|
|
10
|
+
const LANGUAGE = 'ru';
|
|
11
|
+
export const submitCardTransfer = async (typeForm, amount) => {
|
|
12
|
+
const navigator = locationNavigator();
|
|
13
|
+
const submitBody = {
|
|
14
|
+
amount: String(amount),
|
|
15
|
+
currency: CURRENCY_CODE,
|
|
16
|
+
returnUrl: `${navigator.origin}${SUCCESS_URL}`,
|
|
17
|
+
failUrl: `${navigator.origin}${FAIL_URL}`,
|
|
18
|
+
language: LANGUAGE,
|
|
19
|
+
};
|
|
20
|
+
const url = `${API_BASE_URI}/payment/${paymentURLMap[typeForm]}`;
|
|
21
|
+
try {
|
|
22
|
+
const res = await fetch(url, {
|
|
23
|
+
method: 'POST',
|
|
24
|
+
headers: { 'Content-Type': 'application/json' },
|
|
25
|
+
mode: 'cors',
|
|
26
|
+
body: JSON.stringify(submitBody),
|
|
27
|
+
});
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return await res.json();
|
|
32
|
+
}
|
|
33
|
+
catch (ex) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
export const isSuccessResponse = (response) => Boolean(response?.formUrl) && Boolean(response?.orderId);
|
|
38
|
+
export const isErrorInResponse = (response) => Boolean(response?.errorMessage) && response?.errorCode !== 0;
|
|
39
|
+
//# sourceMappingURL=submitCardTransfer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submitCardTransfer.js","sourceRoot":"","sources":["../../../src/components/CardTransfer/submitCardTransfer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAkBrE,MAAM,aAAa,GAAyC;IAC1D,OAAO,EAAE,iBAAiB;IAC1B,QAAQ,EAAE,iBAAiB;CAC5B,CAAC;AAEF,MAAM,WAAW,GAAG,cAAc,CAAC;AACnC,MAAM,QAAQ,GAAG,cAAc,CAAC;AAChC,MAAM,aAAa,GAAG,KAAK,CAAC;AAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC;AAEtB,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EACrC,QAA8B,EAC9B,MAAc,EACwB,EAAE;IACxC,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;IAEtC,MAAM,UAAU,GAA2B;QACzC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;QACtB,QAAQ,EAAE,aAAa;QACvB,SAAS,EAAE,GAAG,SAAS,CAAC,MAAM,GAAG,WAAW,EAAE;QAC9C,OAAO,EAAE,GAAG,SAAS,CAAC,MAAM,GAAG,QAAQ,EAAE;QACzC,QAAQ,EAAE,QAAQ;KACnB,CAAC;IAEF,MAAM,GAAG,GAAG,GAAG,YAAY,YAAY,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;IAEjE,IAAI;QACF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;SACjC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;YACX,OAAO,IAAI,CAAC;SACb;QAED,OAAO,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;KACzB;IAAC,OAAO,EAAE,EAAE;QACX,OAAO,IAAI,CAAC;KACb;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,QAAqC,EACa,EAAE,CACpD,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAE3D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,QAAqC,EACoB,EAAE,CAC3D,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,QAAQ,EAAE,SAAS,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type CardTransferFormType } from './CardTransferContent';
|
|
2
|
+
export interface TransactionStore {
|
|
3
|
+
transaction: {
|
|
4
|
+
orderId: string;
|
|
5
|
+
type: 'p2p' | 'b2c';
|
|
6
|
+
url: string;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export declare const useSubmitCardTransfer: (formType: CardTransferFormType) => ({ amount }: {
|
|
10
|
+
amount: number;
|
|
11
|
+
}) => Promise<void>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useCallback } from '@redneckz/uni-jsx/lib/hooks';
|
|
2
|
+
import { useSessionStore } from '@redneckz/uni-jsx/lib/Store/useSessionStore';
|
|
3
|
+
import { locationNavigator } from '../../external/locationNavigator.js';
|
|
4
|
+
import { useDialog } from '../../ui-kit/DialogManager/useDialog.js';
|
|
5
|
+
import { isErrorInResponse, isSuccessResponse, submitCardTransfer } from './submitCardTransfer.js';
|
|
6
|
+
import { SubmitFailedDialog } from './SubmitFailedDialog.js';
|
|
7
|
+
export const useSubmitCardTransfer = (formType) => {
|
|
8
|
+
const responseTypeDialog = useDialog(SubmitFailedDialog);
|
|
9
|
+
const sessionStore = useSessionStore();
|
|
10
|
+
const navigator = locationNavigator();
|
|
11
|
+
const adjustedTypeForm = formType === 'private' ? 'p2p' : 'b2c';
|
|
12
|
+
return useCallback(async ({ amount }) => {
|
|
13
|
+
const response = await submitCardTransfer(formType, amount);
|
|
14
|
+
if (isSuccessResponse(response)) {
|
|
15
|
+
sessionStore.transaction = {
|
|
16
|
+
orderId: response.orderId,
|
|
17
|
+
type: adjustedTypeForm,
|
|
18
|
+
url: navigator.href,
|
|
19
|
+
};
|
|
20
|
+
navigator.assign(`${adjustedTypeForm}/?formUrl=${encodeURIComponent(response.formUrl)}`);
|
|
21
|
+
}
|
|
22
|
+
if (isErrorInResponse(response)) {
|
|
23
|
+
responseTypeDialog.open({
|
|
24
|
+
errorCode: response.errorCode,
|
|
25
|
+
errorMessage: response.errorMessage,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}, [formType]);
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=useSubmitCardTransfer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSubmitCardTransfer.js","sourceRoot":"","sources":["../../../src/components/CardTransfer/useSubmitCardTransfer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AAEjE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAU1D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,QAA8B,EAAE,EAAE;IACtE,MAAM,kBAAkB,GAAG,SAAS,CAAC,kBAAkB,CAAC,CAAC;IACzD,MAAM,YAAY,GAAG,eAAe,EAAoB,CAAC;IACzD,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;IAEtC,MAAM,gBAAgB,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IAEhE,OAAO,WAAW,CAChB,KAAK,EAAE,EAAE,MAAM,EAAsB,EAAE,EAAE;QACvC,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAE5D,IAAI,iBAAiB,CAAC,QAAQ,CAAC,EAAE;YAC/B,YAAY,CAAC,WAAW,GAAG;gBACzB,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,IAAI,EAAE,gBAAgB;gBACtB,GAAG,EAAE,SAAS,CAAC,IAAI;aACpB,CAAC;YAEF,SAAS,CAAC,MAAM,CAAC,GAAG,gBAAgB,aAAa,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;SAC1F;QAED,IAAI,iBAAiB,CAAC,QAAQ,CAAC,EAAE;YAC/B,kBAAkB,CAAC,IAAI,CAAC;gBACtB,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,YAAY,EAAE,QAAQ,CAAC,YAAY;aACpC,CAAC,CAAC;SACJ;IACH,CAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { JSX } from '@redneckz/uni-jsx';
|
|
2
|
-
import { useEffect
|
|
2
|
+
import { useEffect } from '@redneckz/uni-jsx/lib/hooks';
|
|
3
|
+
import { useBool } from '@redneckz/uni-jsx/lib/hooks/useBool';
|
|
3
4
|
import { useForm } from '../../hooks/useForm/useForm';
|
|
4
5
|
import { BlockWrapper } from '../../ui-kit/BlockWrapper';
|
|
5
6
|
import { Button } from '../../ui-kit/Button/Button';
|
|
@@ -8,17 +9,13 @@ import { Heading } from '../../ui-kit/Heading/Heading';
|
|
|
8
9
|
import { type UniBlockProps } from '../../UniBlock/UniBlockProps';
|
|
9
10
|
import { style } from '../../utils/style';
|
|
10
11
|
import { type CardTransferContent } from './CardTransferContent';
|
|
12
|
+
import { useSubmitCardTransfer } from './useSubmitCardTransfer';
|
|
11
13
|
|
|
12
14
|
const DEFAULT_TITLE = 'Укажите сумму перевода';
|
|
13
15
|
const DEFAULT_LABEL = 'Сумма перевода';
|
|
14
16
|
const MAX_AMOUNT = 300000;
|
|
15
17
|
const MIN_AMOUNT = 1;
|
|
16
18
|
|
|
17
|
-
const FORM_URL_MAP = {
|
|
18
|
-
private: 'https://old.rshb.ru/p2p/',
|
|
19
|
-
business: 'https://old.rshb.ru/smallbusiness/p2p/',
|
|
20
|
-
};
|
|
21
|
-
|
|
22
19
|
const INITIAL_FORM_STATE = {
|
|
23
20
|
amount: 1500,
|
|
24
21
|
};
|
|
@@ -34,9 +31,15 @@ export const CardTransfer = JSX<CardTransferProps>(
|
|
|
34
31
|
formType = 'private',
|
|
35
32
|
...rest
|
|
36
33
|
}) => {
|
|
37
|
-
const [
|
|
38
|
-
|
|
34
|
+
const [isDisabled, { setValue: setDisabled }] = useBool(false);
|
|
35
|
+
|
|
36
|
+
const handleSubmit = useSubmitCardTransfer(formType);
|
|
37
|
+
|
|
38
|
+
const [{ amount }, { field, onSubmit }] = useForm(INITIAL_FORM_STATE, {
|
|
39
|
+
onSubmit: handleSubmit,
|
|
40
|
+
});
|
|
39
41
|
|
|
42
|
+
// TODO: dont set state in useEffect
|
|
40
43
|
useEffect(() => {
|
|
41
44
|
setDisabled(amount <= 0);
|
|
42
45
|
}, [amount]);
|
|
@@ -54,7 +57,7 @@ export const CardTransfer = JSX<CardTransferProps>(
|
|
|
54
57
|
title={title}
|
|
55
58
|
/>
|
|
56
59
|
) : null}
|
|
57
|
-
<form className="w-full xl:max-w-[468px]" method="POST"
|
|
60
|
+
<form className="w-full xl:max-w-[468px]" method="POST" onSubmit={onSubmit}>
|
|
58
61
|
<CurrencyInput
|
|
59
62
|
valid={!isDisabled}
|
|
60
63
|
label={label}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type LabelProps, type TextProps, type TitleProps } from '../../model/HeadlineType';
|
|
2
2
|
import { type UniBlockContent } from '../../UniBlock/UniBlockProps';
|
|
3
3
|
|
|
4
|
+
export type CardTransferFormType = 'private' | 'business';
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* @title Перевод с карты на карту
|
|
6
8
|
*/
|
|
@@ -13,5 +15,5 @@ export type CardTransferContent = UniBlockContent &
|
|
|
13
15
|
* @title Тип формы
|
|
14
16
|
* @enumNames ['Частные клиенты', 'Бизнес-клиенты']
|
|
15
17
|
*/
|
|
16
|
-
formType?:
|
|
18
|
+
formType?: CardTransferFormType;
|
|
17
19
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Dialog } from '../../ui-kit/DialogManager/Dialog';
|
|
2
|
+
import { Img } from '../../ui-kit/Img/Img';
|
|
3
|
+
import { Headline } from '../Headline/Headline';
|
|
4
|
+
|
|
5
|
+
export interface FormResponseDialogProps {
|
|
6
|
+
onClose?: () => void;
|
|
7
|
+
errorCode?: number;
|
|
8
|
+
errorMessage?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const FAILED_TITLE = 'Ошибка перевода';
|
|
12
|
+
|
|
13
|
+
export const SubmitFailedDialog = ({
|
|
14
|
+
onClose,
|
|
15
|
+
errorCode,
|
|
16
|
+
errorMessage,
|
|
17
|
+
}: FormResponseDialogProps) => {
|
|
18
|
+
const description = errorCode ? `Код ошибки - ${errorCode}` : 'Пожалуйста, повторите позднее';
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Dialog className="my-6xl max-w-lg w-full min-h-fit mx-auto" onClose={onClose}>
|
|
22
|
+
<div className="flex flex-col gap-lg items-center rounded-md space-x-m">
|
|
23
|
+
<Img image={{ icon: 'ResponseFailIcon', iconVersion: 'normal' }} width="136" height="136" />
|
|
24
|
+
<Headline
|
|
25
|
+
className="w-full"
|
|
26
|
+
title={FAILED_TITLE}
|
|
27
|
+
description={description}
|
|
28
|
+
headlineVersion="XS"
|
|
29
|
+
isEmbedded={true}
|
|
30
|
+
/>
|
|
31
|
+
{errorMessage ? (
|
|
32
|
+
<div className="bg-secondary-dark rounded-xl px-4 pt-4 pb-8 grid gap-4 grid-cols-12">
|
|
33
|
+
<div className="col-span-8"> {errorMessage}</div>
|
|
34
|
+
<div className="col-span-4">
|
|
35
|
+
<Img image={{ icon: 'ResponseFailIcon', iconVersion: 'normal' }} />
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
) : null}
|
|
39
|
+
</div>
|
|
40
|
+
</Dialog>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { API_BASE_URI } from '../../api/apiBaseUrl';
|
|
2
|
+
import { locationNavigator } from '../../external/locationNavigator';
|
|
3
|
+
import { type CardTransferFormType } from './CardTransferContent';
|
|
4
|
+
|
|
5
|
+
type CardTransferSubmitBody = {
|
|
6
|
+
amount: string;
|
|
7
|
+
currency: string;
|
|
8
|
+
returnUrl: string;
|
|
9
|
+
failUrl: string;
|
|
10
|
+
language: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type CardTransferResponse = Partial<{
|
|
14
|
+
errorCode: number;
|
|
15
|
+
errorMessage: string;
|
|
16
|
+
orderId: string;
|
|
17
|
+
formUrl: string;
|
|
18
|
+
}>;
|
|
19
|
+
|
|
20
|
+
const paymentURLMap: Record<CardTransferFormType, string> = {
|
|
21
|
+
private: 'p2p/registerP2P',
|
|
22
|
+
business: 'b2c/registerB2C',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const SUCCESS_URL = '/p2p/success';
|
|
26
|
+
const FAIL_URL = '/p2p/success';
|
|
27
|
+
const CURRENCY_CODE = '643';
|
|
28
|
+
const LANGUAGE = 'ru';
|
|
29
|
+
|
|
30
|
+
export const submitCardTransfer = async (
|
|
31
|
+
typeForm: CardTransferFormType,
|
|
32
|
+
amount: number,
|
|
33
|
+
): Promise<CardTransferResponse | null> => {
|
|
34
|
+
const navigator = locationNavigator();
|
|
35
|
+
|
|
36
|
+
const submitBody: CardTransferSubmitBody = {
|
|
37
|
+
amount: String(amount),
|
|
38
|
+
currency: CURRENCY_CODE,
|
|
39
|
+
returnUrl: `${navigator.origin}${SUCCESS_URL}`,
|
|
40
|
+
failUrl: `${navigator.origin}${FAIL_URL}`,
|
|
41
|
+
language: LANGUAGE,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const url = `${API_BASE_URI}/payment/${paymentURLMap[typeForm]}`;
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const res = await fetch(url, {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
headers: { 'Content-Type': 'application/json' },
|
|
50
|
+
mode: 'cors',
|
|
51
|
+
body: JSON.stringify(submitBody),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (!res.ok) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return await res.json();
|
|
59
|
+
} catch (ex) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const isSuccessResponse = (
|
|
65
|
+
response: CardTransferResponse | null,
|
|
66
|
+
): response is { orderId: string; formUrl: string } =>
|
|
67
|
+
Boolean(response?.formUrl) && Boolean(response?.orderId);
|
|
68
|
+
|
|
69
|
+
export const isErrorInResponse = (
|
|
70
|
+
response: CardTransferResponse | null,
|
|
71
|
+
): response is { errorCode: number; errorMessage: string } =>
|
|
72
|
+
Boolean(response?.errorMessage) && response?.errorCode !== 0;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useCallback } from '@redneckz/uni-jsx/lib/hooks';
|
|
2
|
+
import { useSessionStore } from '@redneckz/uni-jsx/lib/Store/useSessionStore';
|
|
3
|
+
import { locationNavigator } from '../../external/locationNavigator';
|
|
4
|
+
import { useDialog } from '../../ui-kit/DialogManager/useDialog';
|
|
5
|
+
import { type CardTransferFormType } from './CardTransferContent';
|
|
6
|
+
import { isErrorInResponse, isSuccessResponse, submitCardTransfer } from './submitCardTransfer';
|
|
7
|
+
import { SubmitFailedDialog } from './SubmitFailedDialog';
|
|
8
|
+
|
|
9
|
+
export interface TransactionStore {
|
|
10
|
+
transaction: {
|
|
11
|
+
orderId: string;
|
|
12
|
+
type: 'p2p' | 'b2c';
|
|
13
|
+
url: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const useSubmitCardTransfer = (formType: CardTransferFormType) => {
|
|
18
|
+
const responseTypeDialog = useDialog(SubmitFailedDialog);
|
|
19
|
+
const sessionStore = useSessionStore<TransactionStore>();
|
|
20
|
+
const navigator = locationNavigator();
|
|
21
|
+
|
|
22
|
+
const adjustedTypeForm = formType === 'private' ? 'p2p' : 'b2c';
|
|
23
|
+
|
|
24
|
+
return useCallback(
|
|
25
|
+
async ({ amount }: { amount: number }) => {
|
|
26
|
+
const response = await submitCardTransfer(formType, amount);
|
|
27
|
+
|
|
28
|
+
if (isSuccessResponse(response)) {
|
|
29
|
+
sessionStore.transaction = {
|
|
30
|
+
orderId: response.orderId,
|
|
31
|
+
type: adjustedTypeForm,
|
|
32
|
+
url: navigator.href,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
navigator.assign(`${adjustedTypeForm}/?formUrl=${encodeURIComponent(response.formUrl)}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (isErrorInResponse(response)) {
|
|
39
|
+
responseTypeDialog.open({
|
|
40
|
+
errorCode: response.errorCode,
|
|
41
|
+
errorMessage: response.errorMessage,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
[formType],
|
|
46
|
+
);
|
|
47
|
+
};
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import '../../setup-fixture';
|
|
2
|
+
import { DialogManager } from '../../ui-kit/DialogManager/DialogManager';
|
|
2
3
|
import { type LinkButtonProps } from '../../ui-kit/LinkButton/LinkButtonProps';
|
|
3
4
|
import { CardTransfer } from './CardTransfer';
|
|
4
5
|
|
|
@@ -8,9 +9,16 @@ const button: LinkButtonProps = {
|
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
export default {
|
|
11
|
-
|
|
12
|
-
<div
|
|
13
|
-
<CardTransfer
|
|
12
|
+
private: (
|
|
13
|
+
<div>
|
|
14
|
+
<CardTransfer button={button} formType="private" />
|
|
15
|
+
<DialogManager />
|
|
16
|
+
</div>
|
|
17
|
+
),
|
|
18
|
+
business: (
|
|
19
|
+
<div>
|
|
20
|
+
<CardTransfer button={button} formType="business" />
|
|
21
|
+
<DialogManager />
|
|
14
22
|
</div>
|
|
15
23
|
),
|
|
16
24
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '../../setup-fixture';
|
|
2
2
|
|
|
3
|
+
import { DialogManager } from '../../ui-kit/DialogManager/DialogManager';
|
|
3
4
|
import { type LinkButtonProps } from '../../ui-kit/LinkButton/LinkButtonProps';
|
|
4
5
|
import { CardTransfer } from './CardTransfer';
|
|
5
6
|
|
|
@@ -9,5 +10,16 @@ const button: LinkButtonProps = {
|
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export default {
|
|
12
|
-
|
|
13
|
+
private: (
|
|
14
|
+
<div>
|
|
15
|
+
<CardTransfer button={button} formType="private" />
|
|
16
|
+
<DialogManager />
|
|
17
|
+
</div>
|
|
18
|
+
),
|
|
19
|
+
business: (
|
|
20
|
+
<div>
|
|
21
|
+
<CardTransfer button={button} formType="business" />
|
|
22
|
+
<DialogManager />
|
|
23
|
+
</div>
|
|
24
|
+
),
|
|
13
25
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { JSX } from '@redneckz/uni-jsx';
|
|
2
|
-
import { useEffect
|
|
2
|
+
import { useEffect } from '@redneckz/uni-jsx/lib/hooks';
|
|
3
|
+
import { useBool } from '@redneckz/uni-jsx/lib/hooks/useBool';
|
|
3
4
|
import { useForm } from '../../hooks/useForm/useForm';
|
|
4
5
|
import { BlockWrapper } from '../../ui-kit/BlockWrapper';
|
|
5
6
|
import { Button } from '../../ui-kit/Button/Button';
|
|
@@ -8,17 +9,13 @@ import { Heading } from '../../ui-kit/Heading/Heading';
|
|
|
8
9
|
import { type UniBlockProps } from '../../UniBlock/UniBlockProps';
|
|
9
10
|
import { style } from '../../utils/style';
|
|
10
11
|
import { type CardTransferContent } from './CardTransferContent';
|
|
12
|
+
import { useSubmitCardTransfer } from './useSubmitCardTransfer';
|
|
11
13
|
|
|
12
14
|
const DEFAULT_TITLE = 'Укажите сумму перевода';
|
|
13
15
|
const DEFAULT_LABEL = 'Сумма перевода';
|
|
14
16
|
const MAX_AMOUNT = 300000;
|
|
15
17
|
const MIN_AMOUNT = 1;
|
|
16
18
|
|
|
17
|
-
const FORM_URL_MAP = {
|
|
18
|
-
private: 'https://old.rshb.ru/p2p/',
|
|
19
|
-
business: 'https://old.rshb.ru/smallbusiness/p2p/',
|
|
20
|
-
};
|
|
21
|
-
|
|
22
19
|
const INITIAL_FORM_STATE = {
|
|
23
20
|
amount: 1500,
|
|
24
21
|
};
|
|
@@ -34,9 +31,15 @@ export const CardTransfer = JSX<CardTransferProps>(
|
|
|
34
31
|
formType = 'private',
|
|
35
32
|
...rest
|
|
36
33
|
}) => {
|
|
37
|
-
const [
|
|
38
|
-
|
|
34
|
+
const [isDisabled, { setValue: setDisabled }] = useBool(false);
|
|
35
|
+
|
|
36
|
+
const handleSubmit = useSubmitCardTransfer(formType);
|
|
37
|
+
|
|
38
|
+
const [{ amount }, { field, onSubmit }] = useForm(INITIAL_FORM_STATE, {
|
|
39
|
+
onSubmit: handleSubmit,
|
|
40
|
+
});
|
|
39
41
|
|
|
42
|
+
// TODO: dont set state in useEffect
|
|
40
43
|
useEffect(() => {
|
|
41
44
|
setDisabled(amount <= 0);
|
|
42
45
|
}, [amount]);
|
|
@@ -54,7 +57,7 @@ export const CardTransfer = JSX<CardTransferProps>(
|
|
|
54
57
|
title={title}
|
|
55
58
|
/>
|
|
56
59
|
) : null}
|
|
57
|
-
<form className="w-full xl:max-w-[468px]" method="POST"
|
|
60
|
+
<form className="w-full xl:max-w-[468px]" method="POST" onSubmit={onSubmit}>
|
|
58
61
|
<CurrencyInput
|
|
59
62
|
valid={!isDisabled}
|
|
60
63
|
label={label}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type LabelProps, type TextProps, type TitleProps } from '../../model/HeadlineType';
|
|
2
2
|
import { type UniBlockContent } from '../../UniBlock/UniBlockProps';
|
|
3
3
|
|
|
4
|
+
export type CardTransferFormType = 'private' | 'business';
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* @title Перевод с карты на карту
|
|
6
8
|
*/
|
|
@@ -13,5 +15,5 @@ export type CardTransferContent = UniBlockContent &
|
|
|
13
15
|
* @title Тип формы
|
|
14
16
|
* @enumNames ['Частные клиенты', 'Бизнес-клиенты']
|
|
15
17
|
*/
|
|
16
|
-
formType?:
|
|
18
|
+
formType?: CardTransferFormType;
|
|
17
19
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Dialog } from '../../ui-kit/DialogManager/Dialog';
|
|
2
|
+
import { Img } from '../../ui-kit/Img/Img';
|
|
3
|
+
import { Headline } from '../Headline/Headline';
|
|
4
|
+
|
|
5
|
+
export interface FormResponseDialogProps {
|
|
6
|
+
onClose?: () => void;
|
|
7
|
+
errorCode?: number;
|
|
8
|
+
errorMessage?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const FAILED_TITLE = 'Ошибка перевода';
|
|
12
|
+
|
|
13
|
+
export const SubmitFailedDialog = ({
|
|
14
|
+
onClose,
|
|
15
|
+
errorCode,
|
|
16
|
+
errorMessage,
|
|
17
|
+
}: FormResponseDialogProps) => {
|
|
18
|
+
const description = errorCode ? `Код ошибки - ${errorCode}` : 'Пожалуйста, повторите позднее';
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Dialog className="my-6xl max-w-lg w-full min-h-fit mx-auto" onClose={onClose}>
|
|
22
|
+
<div className="flex flex-col gap-lg items-center rounded-md space-x-m">
|
|
23
|
+
<Img image={{ icon: 'ResponseFailIcon', iconVersion: 'normal' }} width="136" height="136" />
|
|
24
|
+
<Headline
|
|
25
|
+
className="w-full"
|
|
26
|
+
title={FAILED_TITLE}
|
|
27
|
+
description={description}
|
|
28
|
+
headlineVersion="XS"
|
|
29
|
+
isEmbedded={true}
|
|
30
|
+
/>
|
|
31
|
+
{errorMessage ? (
|
|
32
|
+
<div className="bg-secondary-dark rounded-xl px-4 pt-4 pb-8 grid gap-4 grid-cols-12">
|
|
33
|
+
<div className="col-span-8"> {errorMessage}</div>
|
|
34
|
+
<div className="col-span-4">
|
|
35
|
+
<Img image={{ icon: 'ResponseFailIcon', iconVersion: 'normal' }} />
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
) : null}
|
|
39
|
+
</div>
|
|
40
|
+
</Dialog>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { API_BASE_URI } from '../../api/apiBaseUrl';
|
|
2
|
+
import { locationNavigator } from '../../external/locationNavigator';
|
|
3
|
+
import { type CardTransferFormType } from './CardTransferContent';
|
|
4
|
+
|
|
5
|
+
type CardTransferSubmitBody = {
|
|
6
|
+
amount: string;
|
|
7
|
+
currency: string;
|
|
8
|
+
returnUrl: string;
|
|
9
|
+
failUrl: string;
|
|
10
|
+
language: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type CardTransferResponse = Partial<{
|
|
14
|
+
errorCode: number;
|
|
15
|
+
errorMessage: string;
|
|
16
|
+
orderId: string;
|
|
17
|
+
formUrl: string;
|
|
18
|
+
}>;
|
|
19
|
+
|
|
20
|
+
const paymentURLMap: Record<CardTransferFormType, string> = {
|
|
21
|
+
private: 'p2p/registerP2P',
|
|
22
|
+
business: 'b2c/registerB2C',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const SUCCESS_URL = '/p2p/success';
|
|
26
|
+
const FAIL_URL = '/p2p/success';
|
|
27
|
+
const CURRENCY_CODE = '643';
|
|
28
|
+
const LANGUAGE = 'ru';
|
|
29
|
+
|
|
30
|
+
export const submitCardTransfer = async (
|
|
31
|
+
typeForm: CardTransferFormType,
|
|
32
|
+
amount: number,
|
|
33
|
+
): Promise<CardTransferResponse | null> => {
|
|
34
|
+
const navigator = locationNavigator();
|
|
35
|
+
|
|
36
|
+
const submitBody: CardTransferSubmitBody = {
|
|
37
|
+
amount: String(amount),
|
|
38
|
+
currency: CURRENCY_CODE,
|
|
39
|
+
returnUrl: `${navigator.origin}${SUCCESS_URL}`,
|
|
40
|
+
failUrl: `${navigator.origin}${FAIL_URL}`,
|
|
41
|
+
language: LANGUAGE,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const url = `${API_BASE_URI}/payment/${paymentURLMap[typeForm]}`;
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const res = await fetch(url, {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
headers: { 'Content-Type': 'application/json' },
|
|
50
|
+
mode: 'cors',
|
|
51
|
+
body: JSON.stringify(submitBody),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (!res.ok) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return await res.json();
|
|
59
|
+
} catch (ex) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const isSuccessResponse = (
|
|
65
|
+
response: CardTransferResponse | null,
|
|
66
|
+
): response is { orderId: string; formUrl: string } =>
|
|
67
|
+
Boolean(response?.formUrl) && Boolean(response?.orderId);
|
|
68
|
+
|
|
69
|
+
export const isErrorInResponse = (
|
|
70
|
+
response: CardTransferResponse | null,
|
|
71
|
+
): response is { errorCode: number; errorMessage: string } =>
|
|
72
|
+
Boolean(response?.errorMessage) && response?.errorCode !== 0;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useCallback } from '@redneckz/uni-jsx/lib/hooks';
|
|
2
|
+
import { useSessionStore } from '@redneckz/uni-jsx/lib/Store/useSessionStore';
|
|
3
|
+
import { locationNavigator } from '../../external/locationNavigator';
|
|
4
|
+
import { useDialog } from '../../ui-kit/DialogManager/useDialog';
|
|
5
|
+
import { type CardTransferFormType } from './CardTransferContent';
|
|
6
|
+
import { isErrorInResponse, isSuccessResponse, submitCardTransfer } from './submitCardTransfer';
|
|
7
|
+
import { SubmitFailedDialog } from './SubmitFailedDialog';
|
|
8
|
+
|
|
9
|
+
export interface TransactionStore {
|
|
10
|
+
transaction: {
|
|
11
|
+
orderId: string;
|
|
12
|
+
type: 'p2p' | 'b2c';
|
|
13
|
+
url: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const useSubmitCardTransfer = (formType: CardTransferFormType) => {
|
|
18
|
+
const responseTypeDialog = useDialog(SubmitFailedDialog);
|
|
19
|
+
const sessionStore = useSessionStore<TransactionStore>();
|
|
20
|
+
const navigator = locationNavigator();
|
|
21
|
+
|
|
22
|
+
const adjustedTypeForm = formType === 'private' ? 'p2p' : 'b2c';
|
|
23
|
+
|
|
24
|
+
return useCallback(
|
|
25
|
+
async ({ amount }: { amount: number }) => {
|
|
26
|
+
const response = await submitCardTransfer(formType, amount);
|
|
27
|
+
|
|
28
|
+
if (isSuccessResponse(response)) {
|
|
29
|
+
sessionStore.transaction = {
|
|
30
|
+
orderId: response.orderId,
|
|
31
|
+
type: adjustedTypeForm,
|
|
32
|
+
url: navigator.href,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
navigator.assign(`${adjustedTypeForm}/?formUrl=${encodeURIComponent(response.formUrl)}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (isErrorInResponse(response)) {
|
|
39
|
+
responseTypeDialog.open({
|
|
40
|
+
errorCode: response.errorCode,
|
|
41
|
+
errorMessage: response.errorMessage,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
[formType],
|
|
46
|
+
);
|
|
47
|
+
};
|