Skip to content

Commit

Permalink
feat(transfer-alerts): list and detail pages (#485)
Browse files Browse the repository at this point in the history
* feat(transfer): add sender_account_type to transfer data

* feat(transfer-alerts): list and detail pages
  • Loading branch information
balzdur authored Jul 1, 2024
1 parent aa611a5 commit 332dadc
Show file tree
Hide file tree
Showing 22 changed files with 543 additions and 39 deletions.
3 changes: 2 additions & 1 deletion packages/app-builder/public/locales/en/navigation.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
"settings.case_manager": "Case Manager",
"settings.inboxes": "Inboxes",
"settings.tags": "Tags",
"transfercheck.transfers": "Transfers"
"transfercheck.transfers": "Transfers",
"transfercheck.alerts": "Alerts"
}
22 changes: 21 additions & 1 deletion packages/app-builder/public/locales/en/transfercheck.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@
"transfer_detail.status.suspected_fraud": "Suspected fraud",
"transfer_detail.status.confirmed_fraud": "Confirmed fraud",
"transfer_detail.title": "Transfer details",
"transfer_detail.transfer_status.title": "Transfer status",
"transfer_detail.transfer_data.title": "Transfer data",
"transfer_detail.transfer_data.description": "Here is the transfer id associated to the source information system <TransferIdLabel>transfer_id</TransferIdLabel>: <TransferIdValue>{{transferId}}</TransferIdValue>"
"transfer_detail.transfer_data.description": "Here is the transfer id associated to the source information system <TransferIdLabel>transfer_id</TransferIdLabel>: <TransferIdValue>{{transferId}}</TransferIdValue>",
"transfer_detail.transfer_data.sender": "Sender",
"transfer_detail.transfer_data.beneficiary": "Beneficiary",
"transfer_detail.transfer_data.label": "Label",
"transfer_detail.transfer_data.currency": "Currency",
"transfer_detail.transfer_data.value": "Value",
"transfer_detail.transfer_data.requested_at": "Requested at",
"transfer_detail.transfer_data.created_at": "Created at",
"transfer_detail.transfer_data.updated_at": "Updated at",
"transfer_detail.transfer_data.account_id": "Account id",
"transfer_detail.transfer_data.account_type": "Account type",
"transfer_detail.transfer_data.bic": "BIC",
"transfer_detail.transfer_data.device": "Device",
"transfer_detail.transfer_data.ip": "IP",
"transfer_detail.transfer_data.name": "Name",
"alerts.empty": "You have no alerts",
"alerts.search.empty": "No alert found",
"alert_detail.title": "Alert details",
"alert_detail.alert_data.title": "Alert data",
"alert_detail.alert_data.transfer_id": "Here is the transfer id associated to this alert <TransferIdLabel>transfer_id</TransferIdLabel>: <TransferIdValue>{{transferId}}</TransferIdValue>"
}
2 changes: 1 addition & 1 deletion packages/app-builder/src/components/HelpCenter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export function useMarbleCoreResources() {
return t('navigation:scenarios');
if (location.pathname.startsWith(getRoute('/lists/')))
return t('navigation:lists');
if (location.pathname.startsWith(getRoute('/workflows/')))
if (location.pathname.startsWith(getRoute('/workflows')))
return t('navigation:workflows');
if (location.pathname.startsWith(getRoute('/data')))
return t('navigation:data');
Expand Down
1 change: 1 addition & 0 deletions packages/app-builder/src/components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { type IconProps } from 'packages/ui-icons/src/Icon';
import * as React from 'react';
import { useTranslation } from 'react-i18next';

//TODO(split apps): refactor this to be translation agnostic: directly pass the translated string (it will help separate the navigation.json file per "app")
export const navigationI18n = ['navigation'] satisfies Namespace;

export interface SidebarLinkProps {
Expand Down
148 changes: 148 additions & 0 deletions packages/app-builder/src/components/TransferAlerts/AlertData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { type TransferAlert } from '@app-builder/models/transfer-alert';
import {
formatDateRelative,
formatDateTime,
useFormatLanguage,
} from '@app-builder/utils/format';
import { useGetCopyToClipboard } from '@app-builder/utils/use-get-copy-to-clipboard';
import { Trans, useTranslation } from 'react-i18next';
import { Tooltip } from 'ui-design-system';

import { Callout } from '../Callout';
import { alertsI18n } from './alerts-i18n';

interface AlertDataProps {
alert: TransferAlert;
}

export function AlertData({ alert }: AlertDataProps) {
const { t } = useTranslation(alertsI18n);
const language = useFormatLanguage();
const getCopyToClipboardProps = useGetCopyToClipboard();

return (
<div className="grid grid-cols-2 gap-8">
<Callout className="col-span-2" variant="outlined" color="red">
<div className="flex flex-col gap-2">
<Tooltip.Default
content={
<span className="text-grey-100 text-s">
{formatDateTime(alert.createdAt, {
language,
})}
</span>
}
>
<span className="text-grey-50 text-s w-fit first-letter:capitalize">
{formatDateRelative(alert.createdAt, {
language,
})}
</span>
</Tooltip.Default>

<span className="whitespace-pre-wrap">{alert.message}</span>
</div>
</Callout>

<table className="border-grey-10 h-fit w-full table-auto border-separate border-spacing-0 overflow-hidden rounded-lg border">
<thead>
<tr>
<th className="bg-grey-02 h-12 px-4" colSpan={2}>
Sender
</th>
</tr>
</thead>
<tbody>
<tr>
<td className="text-grey-50 text-s border-grey-10 border-t p-4">
IBAN
</td>
<td className="text-grey-100 text-s border-grey-10 border-t p-4">
{alert.beneficiaryIban}
</td>
</tr>
</tbody>
</table>

<table className="border-grey-10 h-fit w-full table-auto border-separate border-spacing-0 overflow-hidden rounded-lg border">
<thead>
<tr>
<th className="bg-grey-02 h-12 px-4" colSpan={2}>
Beneficiary
</th>
</tr>
</thead>
<tbody>
<tr>
<td className="text-grey-50 text-s border-grey-10 border-t p-4">
IBAN
</td>
<td className="text-grey-100 text-s border-grey-10 border-t p-4">
{alert.beneficiaryIban}
</td>
</tr>
</tbody>
</table>

<p className="col-span-2 whitespace-pre-wrap">
<Trans
t={t}
i18nKey="transfercheck:alert_detail.alert_data.transfer_id"
components={{
TransferIdLabel: <code className="select-none" />,
TransferIdValue: (
<code
className="border-grey-10 cursor-pointer select-none rounded-sm border px-1"
{...getCopyToClipboardProps(alert.transferEndToEndId)}
/>
),
}}
values={{
transferId: alert.transferEndToEndId,
}}
/>
</p>
</div>
);
}

export function AlertData2({ alert }: AlertDataProps) {
const language = useFormatLanguage();

return (
<div className="flex flex-col gap-8">
<Callout variant="outlined" color="red">
<div className="flex flex-col gap-2">
<Tooltip.Default
content={
<span className="text-grey-100 text-s">
{formatDateTime(alert.createdAt, {
language,
})}
</span>
}
>
<span className="text-grey-50 text-s w-fit first-letter:capitalize">
{formatDateRelative(alert.createdAt, {
language,
})}
</span>
</Tooltip.Default>

<span className="whitespace-pre-wrap">{alert.message}</span>
</div>
</Callout>

<div className="grid w-full grid-cols-[max-content_1fr] gap-x-8 gap-y-2">
<span className="text-grey-50 text-s">Transfer ID</span>
<span className="text-grey-100 text-s">{alert.transferEndToEndId}</span>

<span className="text-grey-50 text-s">Sender IBAN</span>
<span className="text-grey-100 text-s">{alert.senderIban}</span>

<span className="text-grey-50 text-s">Beneficiary IBAN</span>
<span className="text-grey-100 text-s">{alert.beneficiaryIban}</span>
</div>
</div>
);
}
105 changes: 105 additions & 0 deletions packages/app-builder/src/components/TransferAlerts/AlertsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { type TransferAlert } from '@app-builder/models/transfer-alert';
import { formatDateTime, useFormatLanguage } from '@app-builder/utils/format';
import { getRoute } from '@app-builder/utils/routes';
import { fromUUID } from '@app-builder/utils/short-uuid';
import { Link } from '@remix-run/react';
import { createColumnHelper, getCoreRowModel } from '@tanstack/react-table';
import clsx from 'clsx';
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { Table, useTable } from 'ui-design-system';

import { alertsI18n } from './alerts-i18n';

interface AlertsListProps {
alerts: TransferAlert[];
}

const columnHelper = createColumnHelper<TransferAlert>();

export function AlertsList({ alerts }: AlertsListProps) {
const { t } = useTranslation(alertsI18n);
const language = useFormatLanguage();

const columns = React.useMemo(
() => [
columnHelper.accessor((row) => row.status, {
id: 'status',
header: 'Status',
size: 50,
}),
columnHelper.accessor((row) => row.message, {
id: 'message',
header: 'Message',
size: 200,
cell: ({ getValue }) => {
const message = getValue();
return <div className="py-2">{message}</div>;
},
}),
columnHelper.accessor((row) => row.createdAt, {
id: 'createdAt',
header: 'Created At',
size: 100,
cell: ({ getValue }) => {
const dateTime = getValue();
return (
<time dateTime={dateTime}>
{formatDateTime(dateTime, { language, timeStyle: undefined })}
</time>
);
},
}),
],
[language],
);

const { rows, table, getBodyProps, getContainerProps } = useTable({
data: alerts,
columns,
columnResizeMode: 'onChange',
getCoreRowModel: getCoreRowModel(),
rowLink: (alert) => (
<Link
to={getRoute('/transfercheck/alerts/:alertId', {
alertId: fromUUID(alert.id),
})}
/>
),
});

if (rows.length === 0 || alerts.length === 0) {
const emptyMessage =
alerts.length === 0
? t('transfercheck:alerts.empty')
: t('transfercheck:alerts.search.empty');
return (
<div className="bg-grey-00 border-grey-10 flex h-28 max-w-3xl flex-col items-center justify-center rounded-lg border border-solid p-4">
<p className="text-s font-medium">{emptyMessage}</p>
</div>
);
}

return (
<Table.Container {...getContainerProps()}>
<Table.Header headerGroups={table.getHeaderGroups()} />
<Table.Body {...getBodyProps()}>
{rows.map((row) => {
const bgClassName =
row.original.status === 'unread' ? 'bg-grey-00' : 'transparent';
return (
<Table.Row
key={row.id}
tabIndex={0}
className={clsx(
'hover:bg-grey-02 relative cursor-pointer',
bgClassName,
)}
row={row}
/>
);
})}
</Table.Body>
</Table.Container>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { type Namespace } from 'i18next';

export const alertsI18n = ['common', 'transfercheck'] satisfies Namespace;
Loading

0 comments on commit 332dadc

Please sign in to comment.