@swan-io/shared-business 13.1.8 → 13.1.10
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swan-io/shared-business",
|
|
3
|
-
"version": "13.1.
|
|
3
|
+
"version": "13.1.10",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": "^22.12.0"
|
|
6
6
|
},
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
],
|
|
26
26
|
"license": "MIT",
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@swan-io/lake": "13.1.
|
|
28
|
+
"@swan-io/lake": "13.1.10"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@formatjs/intl": "^3.1.6",
|
|
@@ -50,6 +50,6 @@
|
|
|
50
50
|
"@types/react-dom": "^19.1.7",
|
|
51
51
|
"@types/react-native": "^0.72.8",
|
|
52
52
|
"type-fest": "^4.41.0",
|
|
53
|
-
"@swan-io/lake": "13.1.
|
|
53
|
+
"@swan-io/lake": "13.1.10"
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -39,8 +39,9 @@ type CreditStatementV1Props = {
|
|
|
39
39
|
issuerName: string;
|
|
40
40
|
siret: string;
|
|
41
41
|
repaymentDate: string;
|
|
42
|
+
closingBalance: Amount;
|
|
42
43
|
};
|
|
43
|
-
export declare const CreditStatementV1: ({ partnerLogoUrl, accountHolderType, accountHolderName, accountHolderAddress, iban, bic, openingDate, closingDate, transactions, issueDate, issuerName, siret, repaymentDate, }: CreditStatementV1Props) => import("react/jsx-runtime").JSX.Element;
|
|
44
|
+
export declare const CreditStatementV1: ({ partnerLogoUrl, accountHolderType, accountHolderName, accountHolderAddress, iban, bic, openingDate, closingDate, transactions, issueDate, issuerName, siret, repaymentDate, closingBalance, }: CreditStatementV1Props) => import("react/jsx-runtime").JSX.Element;
|
|
44
45
|
export type CreditStatementProps = CreditStatementV1Props;
|
|
45
46
|
export declare const CreditStatement: (props: CreditStatementProps) => import("react/jsx-runtime").JSX.Element;
|
|
46
47
|
export {};
|
|
@@ -11,7 +11,7 @@ import { printFormat } from "iban";
|
|
|
11
11
|
import { StyleSheet } from "react-native";
|
|
12
12
|
import { match } from "ts-pattern";
|
|
13
13
|
import { getCountryName } from "../constants/countries";
|
|
14
|
-
import { formatNestedMessage, locale, t } from "../utils/i18n";
|
|
14
|
+
import { formatCurrencySymbol, formatNestedMessage, locale, t } from "../utils/i18n";
|
|
15
15
|
const LOGO_MAX_HEIGHT = 24;
|
|
16
16
|
const LOGO_MAX_WIDTH = 150;
|
|
17
17
|
const styles = StyleSheet.create({
|
|
@@ -33,6 +33,14 @@ const styles = StyleSheet.create({
|
|
|
33
33
|
fontSize: 18,
|
|
34
34
|
fontWeight: "400",
|
|
35
35
|
},
|
|
36
|
+
closingBalanceLabel: {
|
|
37
|
+
fontSize: 15,
|
|
38
|
+
fontWeight: "500",
|
|
39
|
+
},
|
|
40
|
+
closingBalanceAmount: {
|
|
41
|
+
fontSize: 15,
|
|
42
|
+
fontWeight: "400",
|
|
43
|
+
},
|
|
36
44
|
pageTitle: {
|
|
37
45
|
fontSize: 20,
|
|
38
46
|
color: colors.swan[500],
|
|
@@ -88,7 +96,7 @@ const logoStyle = {
|
|
|
88
96
|
objectPosition: "left",
|
|
89
97
|
};
|
|
90
98
|
const formatMaskedPan = (value) => `••${value.slice(-4)}`;
|
|
91
|
-
export const CreditStatementV1 = ({ partnerLogoUrl, accountHolderType, accountHolderName, accountHolderAddress, iban, bic, openingDate, closingDate, transactions, issueDate, issuerName, siret, repaymentDate, }) => {
|
|
99
|
+
export const CreditStatementV1 = ({ partnerLogoUrl, accountHolderType, accountHolderName, accountHolderAddress, iban, bic, openingDate, closingDate, transactions, issueDate, issuerName, siret, repaymentDate, closingBalance, }) => {
|
|
92
100
|
return (_jsxs(Box, { style: styles.container, direction: "column", justifyContent: "spaceBetween", children: [_jsxs(Box, { direction: "row", justifyContent: "spaceBetween", alignItems: "start", children: [_jsxs(Box, { direction: "row", alignItems: "center", children: [isNotNullishOrEmpty(partnerLogoUrl) ? (_jsx("img", { src: partnerLogoUrl, style: logoStyle })) : (_jsx(SwanLogo, { style: styles.defaultLogo })), _jsx(Separator, { horizontal: true, space: 8 }), _jsx(LakeText, { style: styles.mediumText, children: t("accountStatement.partnership") }), _jsx(Space, { width: 4 }), _jsx(SwanLogo, { color: colors.gray[900], style: styles.swanLogo })] }), _jsxs(Box, { children: [_jsx(LakeText, { style: styles.pageTitle, children: t("creditStatement.titleDocument") }), _jsx(LakeText, { style: styles.text, color: colors.gray[700], children: accountHolderType === "Company"
|
|
93
101
|
? t("accountStatement.titleDocument.companyDescription")
|
|
94
102
|
: t("accountStatement.titleDocument.individualDescription") }), _jsx(LakeText, { align: "right", style: styles.smallText, children: t("creditStatement.issueDate", {
|
|
@@ -101,7 +109,7 @@ export const CreditStatementV1 = ({ partnerLogoUrl, accountHolderType, accountHo
|
|
|
101
109
|
}) }), _jsx(Space, { height: 24 }), _jsx(Box, { direction: "row", justifyContent: "spaceBetween", children: _jsx(Box, { direction: "column", justifyContent: "end", children: _jsx(LakeText, { style: styles.subtitle, color: colors.gray[900], children: t("accountStatement.date", {
|
|
102
110
|
openingDate: dayjs(openingDate).format(locale.dateFormat),
|
|
103
111
|
closingDate: dayjs(closingDate).format(locale.dateFormat),
|
|
104
|
-
}) }) }) }), _jsx(Space, { height: 16 }), _jsxs(_Fragment, { children: [_jsxs(Box, { direction: "row", children: [_jsx(LakeText, { style: [styles.titleColumn, { width: "15%" }], color: colors.gray[700], children: t("accountStatement.column.date") }), _jsx(LakeText, { style: [styles.titleColumn, { width: "55%" }], color: colors.gray[700], children: t("accountStatement.column.description") }), _jsx(LakeText, { style: [styles.titleColumn, { width: "15%", textAlign: "right" }], color: colors.gray[700], children: t("creditStatement.column.debit") }), _jsx(LakeText, { style: [styles.titleColumn, { width: "15%", textAlign: "right" }], color: colors.gray[700], children: t("creditStatement.column.credit") })] }), _jsx(Space, { height: 12 }),
|
|
112
|
+
}) }) }) }), _jsx(Space, { height: 16 }), _jsxs(_Fragment, { children: [_jsxs(Box, { direction: "row", children: [_jsx(LakeText, { style: [styles.titleColumn, { width: "15%" }], color: colors.gray[700], children: t("accountStatement.column.date") }), _jsx(LakeText, { style: [styles.titleColumn, { width: "55%" }], color: colors.gray[700], children: t("accountStatement.column.description") }), _jsx(LakeText, { style: [styles.titleColumn, { width: "15%", textAlign: "right" }], color: colors.gray[700], children: t("creditStatement.column.debit") }), _jsx(LakeText, { style: [styles.titleColumn, { width: "15%", textAlign: "right" }], color: colors.gray[700], children: t("creditStatement.column.credit") })] }), _jsx(Space, { height: 12 }), _jsxs(Box, { direction: "column", children: [transactions.map(({ transactionAmount, transactionDate, transactionLabel, transactionSide, transactionType, transactionId, counterparty, maskedPan, }) => (_jsxs(_Fragment, { children: [_jsxs(Box, { direction: "row", children: [_jsx(LakeText, { style: [styles.smallText, { width: "15%" }], color: colors.gray[700], children: dayjs(transactionDate).format(locale.dateFormat) }), _jsxs(Box, { direction: "column", style: { width: "55%" }, children: [_jsx(LakeText, { style: styles.smallText, color: colors.gray[700], children: `${translateTransaction(transactionType)} ${transactionLabel}` }), _jsx(LakeText, { style: styles.smallText, color: colors.gray[500], children: `${counterparty} ${maskedPan ? formatMaskedPan(maskedPan) : ""}` })] }), _jsx(LakeText, { color: colors.gray[700], style: [styles.smallText, styles.rightColumnContent], children: transactionSide === "Debit" ? `- ${transactionAmount.value}` : "" }), _jsx(LakeText, { color: colors.gray[700], style: [styles.smallText, styles.rightColumnContent], children: transactionSide === "Credit" ? transactionAmount.value : "" })] }, transactionId), _jsx(Space, { height: 8 })] }))), _jsx(Box, { direction: "row", justifyContent: "end", children: _jsxs(Box, { direction: "row", justifyContent: "spaceBetween", alignItems: "center", style: { width: "50%" }, children: [_jsx(LakeText, { style: styles.closingBalanceLabel, color: colors.gray[900], children: t("accountStatement.closingBalance") }), _jsx(LakeText, { color: colors.gray[900], style: styles.closingBalanceAmount, children: formatCurrencySymbol(Number(closingBalance.value), closingBalance.currency) })] }) })] })] }), _jsx(Space, { height: 24 })] }));
|
|
105
113
|
};
|
|
106
114
|
export const CreditStatement = (props) => match(props)
|
|
107
115
|
.with({ version: "v1" }, props => _jsx(CreditStatementV1, { ...props }))
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Array, Option } from "@swan-io/boxed";
|
|
3
|
+
import { Box } from "@swan-io/lake/src/components/Box";
|
|
3
4
|
import { Form } from "@swan-io/lake/src/components/Form";
|
|
4
5
|
import { LakeButton, LakeButtonGroup } from "@swan-io/lake/src/components/LakeButton";
|
|
5
6
|
import { LakeCopyButton } from "@swan-io/lake/src/components/LakeCopyButton";
|
|
@@ -10,7 +11,7 @@ import { ReadOnlyFieldList } from "@swan-io/lake/src/components/ReadOnlyFieldLis
|
|
|
10
11
|
import { Space } from "@swan-io/lake/src/components/Space";
|
|
11
12
|
import { colors } from "@swan-io/lake/src/constants/design";
|
|
12
13
|
import { isNotNullish } from "@swan-io/lake/src/utils/nullish";
|
|
13
|
-
import {
|
|
14
|
+
import { badStatusToError, Request } from "@swan-io/request";
|
|
14
15
|
import { Fragment, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
|
15
16
|
import { StyleSheet } from "react-native";
|
|
16
17
|
import { match } from "ts-pattern";
|
|
@@ -30,10 +31,17 @@ const Help = (props) => {
|
|
|
30
31
|
})
|
|
31
32
|
.with({ type: "button" }, ({ label, onPress }) => {
|
|
32
33
|
var _a;
|
|
33
|
-
return (_jsx(LakeButton, { mode: "
|
|
34
|
+
return (_jsx(LakeButton, { mode: "secondary", size: "small", color: "gray", icon: (_a = props.icon) !== null && _a !== void 0 ? _a : "question-circle-regular", onPress: onPress, style: styles.button, ariaLabel: t("supportingDocuments.help.whatIsThis"), children: label }));
|
|
34
35
|
})
|
|
35
36
|
.exhaustive();
|
|
36
37
|
};
|
|
38
|
+
const getSupportLink = (language) => match(language)
|
|
39
|
+
.with("fr", () => "https://support.swan.io/hc/en-150/articles/22502977563933--Proof-of-registration-for-French-companies")
|
|
40
|
+
.with("it", () => "https://support.swan.io/hc/en-150/articles/22537604831005--Proof-of-registration-for-Italian-companies")
|
|
41
|
+
.with("de", () => "https://support.swan.io/hc/en-150/articles/22535023588509--Proof-of-registration-for-German-companies")
|
|
42
|
+
.with("es", () => "https://support.swan.io/hc/en-150/articles/22544703221021--Proof-of-registration-for-Spanish-companies")
|
|
43
|
+
.with("nl", () => "https://support.swan.io/hc/en-150/articles/22543228421277--Proof-of-registration-for-Dutch-companies")
|
|
44
|
+
.otherwise(() => "https://support.swan.io/hc/en-150/articles/22620756787869-Proof-of-company-registration");
|
|
37
45
|
export const getSupportingDocumentPurposeLabel = (purpose) => {
|
|
38
46
|
const key = `supportingDocuments.purpose.${purpose}`;
|
|
39
47
|
return isTranslationKey(key) ? t(key) : purpose;
|
|
@@ -124,37 +132,41 @@ export const SupportingDocumentCollection = ({ ref, documents, generateUpload, u
|
|
|
124
132
|
var _a, _b;
|
|
125
133
|
const metadata = getPurposeMetadata === null || getPurposeMetadata === void 0 ? void 0 : getPurposeMetadata(purpose);
|
|
126
134
|
const label = (_a = purposeDescriptionLabelOverrides === null || purposeDescriptionLabelOverrides === void 0 ? void 0 : purposeDescriptionLabelOverrides[purpose]) !== null && _a !== void 0 ? _a : getSupportingDocumentPurposeDescriptionLabel(purpose);
|
|
127
|
-
return (_jsxs(Fragment, { children: [_jsx(LakeLabel, { label: (_b = purposeLabelOverrides === null || purposeLabelOverrides === void 0 ? void 0 : purposeLabelOverrides[purpose]) !== null && _b !== void 0 ? _b : getSupportingDocumentPurposeLabel(purpose), description: label, help: isNotNullish(metadata) ? (_jsx(Help, { type: "button", label: metadata.title, onPress: () => setCurrentMetadata(metadata) })) : (match(purpose)
|
|
135
|
+
return (_jsxs(Fragment, { children: [_jsx(LakeLabel, { label: (_b = purposeLabelOverrides === null || purposeLabelOverrides === void 0 ? void 0 : purposeLabelOverrides[purpose]) !== null && _b !== void 0 ? _b : getSupportingDocumentPurposeLabel(purpose), description: label, help: isNotNullish(metadata) ? (purpose === "CompanyRegistration" ? (_jsx(LakeButton, { size: "small", mode: "tertiary", icon: "question-circle-regular", onPress: () => window.open(getSupportLink(locale.language)), ariaLabel: t("supportingDocuments.help.howToSendAGoodDocument"), children: t("supportingDocuments.help.howToSendAGoodDocument") })) : (_jsx(Help, { type: "button", label: metadata.title, onPress: () => setCurrentMetadata(metadata) }))) : (match(purpose)
|
|
128
136
|
.with("PowerOfAttorney", () => (_jsx(Help, { type: "button", icon: "arrow-down-filled", label: t("supportingDocuments.help.downloadTemplate"), onPress: () => setShowPowerOfAttorneyModal(true) })))
|
|
129
137
|
.with("SwornStatement", () => (_jsx(Help, { type: "button", icon: "arrow-down-filled", label: t("supportingDocuments.help.downloadTemplate"), onPress: () => setShowSwornStatementModal(true) })))
|
|
130
|
-
.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
138
|
+
.with("CompanyRegistration", () => (_jsx(LakeButton, { size: "small", mode: "tertiary", icon: "question-circle-regular", onPress: () => window.open(getSupportLink(locale.language)), ariaLabel: t("supportingDocuments.help.howToSendAGoodDocument"), children: t("supportingDocuments.help.howToSendAGoodDocument") })))
|
|
139
|
+
.otherwise(() => null)), render: () => (_jsxs(_Fragment, { children: [_jsx(Box, { direction: "row", children: match(purpose)
|
|
140
|
+
.with("PowerOfAttorney", () => (_jsx(Help, { type: "button", icon: "arrow-down-filled", label: t("supportingDocuments.help.downloadTemplate"), onPress: () => setShowPowerOfAttorneyModal(true) })))
|
|
141
|
+
.with("SwornStatement", () => (_jsx(Help, { type: "button", icon: "arrow-down-filled", label: t("supportingDocuments.help.downloadTemplate"), onPress: () => setShowSwornStatementModal(true) })))
|
|
142
|
+
.otherwise(() => null) }), _jsx(Space, { height: 16 }), _jsx(FilesUploader, { ref: ref => {
|
|
143
|
+
filesUploaderRefByPurpose.current[purpose] = ref;
|
|
144
|
+
},
|
|
145
|
+
// Only allow uploading is the Supporting Document Collection awaits for docs
|
|
146
|
+
// and that the specific purpose isn't already fully validated
|
|
147
|
+
canUpload: !readonlyDocumentPurposes.includes(purpose) &&
|
|
148
|
+
!readOnly &&
|
|
149
|
+
status === "WaitingForDocument" &&
|
|
150
|
+
!areAllDocumentsValidated, accept: ACCEPTED_FORMATS, maxSize: 20000000, icon: "document-regular", initialFiles: files, generateUpload: generateUpload, getUploadConfig: file => ({ fileName: file.name, purpose }), uploadFile: isNotNullish(uploadFile)
|
|
151
|
+
? uploadFile
|
|
152
|
+
: ({ upload, file, onProgress }) => {
|
|
153
|
+
const body = new FormData();
|
|
154
|
+
upload.fields.forEach(({ key, value }) => body.append(key, value));
|
|
155
|
+
body.append("file", file);
|
|
156
|
+
setTimeout(() => onProgress(0.8), 100);
|
|
157
|
+
return Request.make({
|
|
158
|
+
url: upload.url,
|
|
159
|
+
method: "POST",
|
|
160
|
+
body,
|
|
161
|
+
type: "text",
|
|
162
|
+
}).mapOkToResult(badStatusToError);
|
|
163
|
+
}, formatAndSizeDescription: t("supportingDocuments.documentTypes", {
|
|
164
|
+
maxSizeMB: 20000000 / 1000000,
|
|
165
|
+
}), onRemoveFile: readOnly ? undefined : onRemoveFile, onChange: files => {
|
|
166
|
+
if (isRequired) {
|
|
167
|
+
filesByRequiredPurpose.current.set(purpose, files);
|
|
168
|
+
}
|
|
169
|
+
}, showIds: showIds })] })) }), _jsx(Space, { height: 24 })] }, purpose));
|
|
158
170
|
}), showableDocumentPurposes.length === 0 ? (_jsxs(_Fragment, { children: [_jsx(Space, { height: 24 }), _jsx(LakeText, { align: "center", children: t("supportingDocuments.noDocuments") }), _jsx(Space, { height: 24 })] })) : null, _jsxs(LakeModal, { visible: showPowerOfAttorneyModal, title: t("supportingDocuments.powerOfAttorneyModal.title"), icon: "document-regular", onPressClose: () => setShowPowerOfAttorneyModal(false), children: [_jsx(LakeText, { children: t("supportingDocuments.powerOfAttorneyModal.description") }), _jsx(Space, { height: 16 }), _jsx(LakeButtonGroup, { paddingBottom: 0, children: _jsx(LakeButton, { grow: true, color: "current", onPress: () => window.open(`/power-of-attorney-template/${match(templateLanguage)
|
|
159
171
|
.with("fr", () => "fr")
|
|
160
172
|
.with("de", () => "de")
|
package/src/locales/en.json
CHANGED
|
@@ -298,6 +298,7 @@
|
|
|
298
298
|
"supportingDocuments.help.whatIsThis": "What is this?",
|
|
299
299
|
"supportingDocuments.informations": "Document details",
|
|
300
300
|
"supportingDocuments.noDocuments": "No documents.",
|
|
301
|
+
"supportingDocuments.help.howToSendAGoodDocument": "How to send a good document?",
|
|
301
302
|
"supportingDocuments.powerOfAttorneyModal.description": "A signed and dated document authorizing an individual to represent or act on behalf of a company's legal representative.",
|
|
302
303
|
"supportingDocuments.powerOfAttorneyModal.title": "Power of attorney signed by the legal representative",
|
|
303
304
|
"supportingDocuments.purpose.AdministratorDecisionOfAppointment": "Administrator appointment letter",
|