feat(webapp): Dialog to choose the bank service provider

This commit is contained in:
Ahmed Bouhuolia
2024-03-01 17:22:28 +02:00
parent 0833baabda
commit daf87a8ec7
7 changed files with 222 additions and 24 deletions

View File

@@ -110,12 +110,12 @@ function CashFlowAccountsActionsBar({
</NavbarGroup>
<NavbarGroup align={Alignment.RIGHT}>
{/* <Button
<Button
className={Classes.MINIMAL}
text={'Connect to Bank / Credit Card'}
onClick={handleConnectToBank}
/>
<NavbarDivider /> */}
<NavbarDivider />
<Button
className={Classes.MINIMAL}
icon={<Icon icon="refresh-16" iconSize={14} />}

View File

@@ -26,6 +26,7 @@ function ConnectBankDialogBodyRoot({
const { mutateAsync: getPlaidLinkToken } = useGetPlaidLinkToken();
const setPlaidId = useSetBankingPlaidToken();
// Handles the form submitting.
const handleSubmit = (
values: ConnectBankDialogForm,
{ setSubmitting }: FormikHelpers<ConnectBankDialogForm>,

View File

@@ -1,30 +1,51 @@
import { Button } from '@blueprintjs/core';
import { FFormGroup, FSelect } from '@/components';
import { useFormikContext } from 'formik';
// @ts-nocheck
import styled from 'styled-components';
import { Stack } from '@/components';
import { TellerIcon } from '../Icons/TellerIcon';
import { YodleeIcon } from '../Icons/YodleeIcon';
import { PlaidIcon } from '../Icons/PlaidIcon';
import { BankServiceCard } from './ConnectBankServiceCard';
const TopDesc = styled('p')`
margin-bottom: 20px;
color: #5f6b7c;
`;
export function ConnectBankDialogContent() {
const { isSubmitting } = useFormikContext();
return (
<div>
<FFormGroup
label={'Banking Syncing Service Provider'}
name={'serviceProvider'}
>
<FSelect
name={'serviceProvider'}
valueAccessor={'key'}
textAccessor={'label'}
popoverProps={{ minimal: true }}
items={BankFeedsServiceProviders}
/>
</FFormGroup>
<TopDesc>
Contrary to popular belief, Lorem Ipsum is not simply random text. It
has roots in a piece of classical Latin literature
</TopDesc>
<Button type={'submit'} loading={isSubmitting}>
Connect
</Button>
<Stack>
<BankServiceCard
title={'Plaid (US, UK & Austrial)'}
icon={<PlaidIcon />}
>
Contrary to popular belief, Lorem Ipsum is not simply random text. It
has roots in a piece of classical Latin literature.
</BankServiceCard>
<BankServiceCard
title={'Teller (US, UK & Austrial) — Soon'}
icon={<TellerIcon />}
disabled
>
Contrary to popular belief, Lorem Ipsum is not simply random text. It
has roots in a piece of classical Latin literature.
</BankServiceCard>
<BankServiceCard
title={'Yodlee (US, UK & Austrial) — Soon'}
icon={<YodleeIcon />}
disabled
>
Contrary to popular belief, Lorem Ipsum is not simply random text. It
has roots in a piece of classical Latin literature.
</BankServiceCard>
</Stack>
</div>
);
}
export const BankFeedsServiceProviders = [{ label: 'Plaid', key: 'plaid' }];

View File

@@ -0,0 +1,72 @@
import styled from 'styled-components';
import { Group } from '@/components';
const BankServiceIcon = styled('div')`
height: 40px;
width: 40px;
border: 1px solid #c8cad0;
border-radius: 3px;
display: flex;
svg {
margin: auto;
}
`;
const BankServiceContent = styled(`div`)`
flex: 1 0;
`;
const BankServiceCardRoot = styled('button')`
border-radius: 3px;
border: 1px solid #c8cad0;
transition: all 0.1s ease-in-out;
background: transparent;
text-align: inherit;
padding: 14px;
&:not(:disabled) {
cursor: pointer;
}
&:hover:not(:disabled) {
border-color: #0153cc;
}
&:disabled {
background: #f9fdff;
}
`;
const BankServiceTitle = styled(`h3`)`
font-weight: 600;
font-size: 14px;
color: #2d333d;
`;
const BankServiceDesc = styled('p')`
margin-top: 4px;
margin-bottom: 6px;
font-size: 13px;
color: #738091;
`;
interface BankServiceCardProps {
title: string;
children: React.ReactNode;
disabled?: boolean;
icon: React.ReactNode;
}
export function BankServiceCard({
title,
children,
icon,
disabled,
}: BankServiceCardProps) {
return (
<BankServiceCardRoot disabled={disabled}>
<Group>
<BankServiceIcon>{icon}</BankServiceIcon>
<BankServiceContent>
<BankServiceTitle>{title}</BankServiceTitle>
<BankServiceDesc>{children}</BankServiceDesc>
</BankServiceContent>
</Group>
</BankServiceCardRoot>
);
}

View File

@@ -0,0 +1,17 @@
export const PlaidIcon = (props: any) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={30}
height={30}
viewBox={'0 0 48 48'}
{...props}
>
<path
fill="#111"
fillRule="evenodd"
d="M18.637 0 4.09 3.81.081 18.439l5.014 5.148L0 28.65l3.773 14.693 14.484 4.047 5.096-5.064 5.014 5.147 14.547-3.81 4.008-14.63-5.013-5.146 5.095-5.063L43.231 4.13 28.745.083l-5.094 5.063zM9.71 6.624l7.663-2.008 3.351 3.44-4.887 4.856zm16.822 1.478 3.405-3.383 7.63 2.132-6.227 6.187zM4.672 17.238l2.111-7.705 6.125 6.288-4.886 4.856zm29.547-1.243 6.227-6.189 1.986 7.74-3.404 3.384zm-15.502-.127 4.887-4.856 4.807 4.936-4.886 4.856zm-7.814 7.765 4.886-4.856 4.81 4.936-4.888 4.856zm15.503.127 4.886-4.856L36.1 23.84l-4.887 4.856zM4.57 29.927l3.406-3.385 4.807 4.937-6.225 6.186zm14.021 1.598 4.887-4.856 4.808 4.936-4.886 4.856zm15.502.128 4.887-4.856 3.351 3.439-2.11 7.705zm-24.656 8.97 6.226-6.189 4.81 4.936-3.406 3.385zm16.843-1.206 4.886-4.856 6.126 6.289-7.662 2.007z"
mask="url(#a)"
/>
</svg>
);

View File

@@ -0,0 +1,42 @@
export const TellerIcon = () => (
<svg
height={30}
width={30}
viewBox="0 0 789 789"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0_4283_1925)">
<path
d="M433.606 360.544C351.138 278.075 351.138 144.366 433.606 61.8977C516.075 -20.5711 649.784 -20.5711 732.252 61.8977C814.721 144.366 814.721 278.075 732.252 360.544C649.784 443.012 516.075 443.012 433.606 360.544Z"
fill="#FF5833"
></path>
<path
d="M639.444 578.592C639.444 599.543 622.46 616.527 601.509 616.527H215.57C194.62 616.527 177.636 599.543 177.636 578.592V192.654C177.636 171.703 194.62 154.719 215.57 154.719H601.509C622.46 154.719 639.444 171.703 639.444 192.654V578.592Z"
fill="#0057FF"
></path>
<path
d="M379.425 154.717L601.501 154.717C622.452 154.717 639.436 171.701 639.436 192.651V414.731C568.518 434.347 489.361 416.283 433.616 360.538C377.871 304.793 359.807 225.635 379.425 154.717Z"
fill="#FF77FA"
></path>
<path
d="M383.842 410.314C466.311 492.783 466.311 626.492 383.842 708.961L334.294 758.508C294.899 797.904 231.025 797.904 191.63 758.509L35.647 602.526C-3.74884 563.13 -3.74887 499.257 35.647 459.861L85.1942 410.314C167.663 327.845 301.372 327.845 383.842 410.314Z"
fill="#3CE475"
></path>
<path
d="M437.917 616.525H215.576C194.626 616.525 177.642 599.541 177.642 578.59L177.642 356.224C248.655 336.442 327.991 354.472 383.833 410.314C439.68 466.161 457.708 545.507 437.917 616.525Z"
fill="#00FFFF"
></path>
</g>
<defs>
<clipPath id="clip0_4283_1925">
<rect
width="2427.58"
height="788.009"
fill="white"
transform="translate(0.55127 0.0461426)"
></rect>
</clipPath>
</defs>
</svg>
);

View File

@@ -0,0 +1,45 @@
export const YodleeIcon = (props: any) => (
<svg
xmlns="http://www.w3.org/2000/svg"
xmlSpace="preserve"
id="Layer_1"
x={0}
y={0}
style={{
width: 28,
height: 28,
}}
viewBox="0 0 30 57.5"
{...props}
>
<style>{'.st0{fill:#343741}.st1{fill:#0084d4}.st3{fill:#8bd3e6}'}</style>
<path
d="m15.1 30.2 4.4-1.4-4.4-1.4-4.4 1.4z"
style={{
fill: 'none',
}}
/>
<path
d="M0 0v9.8l19.5 6.3 15-4.9zM0 12.7v9.8l15.1-4.9zM19.5 28.8l15-4.9-4.3-1.4-15.1 4.9zM19.5 41.4l15-4.9-4.3-1.4L15.1 40zM10.7 28.8 0 32.3v2.8l15.1-4.9z"
className="st3"
/>
<path
d="M0 35.1v9.8L15.1 40zM15.1 30.2l15.1 4.9 4.3-1.4-15-4.9z"
className="st0"
/>
<path
d="M34.5 33.7v-9.8l-15 4.9zM0 35.1 15.1 40l15.1-4.9-15.1-4.9z"
className="st1"
/>
<path d="M0 47.7v9.8l34.5-11.2-15-4.9z" className="st0" />
<path d="M34.5 46.3v-9.8l-15 4.9z" className="st1" />
<path
d="m15.1 17.6 15.1 4.9 4.3-1.5-15-4.9zM15.1 27.4 0 22.5v2.8l10.7 3.5z"
className="st0"
/>
<path
d="M34.5 21v-9.8l-15 4.9zM0 22.5l15.1 4.9 15.1-4.9-15.1-4.9zM0 25.3v7l10.7-3.5z"
className="st1"
/>
</svg>
);