Skip to content

Commit

Permalink
Add settings Dialog (#194)
Browse files Browse the repository at this point in the history
Adds settings dialog with balance, id status, account and disconnect
action.
  • Loading branch information
luistorres authored Apr 9, 2024
1 parent 5e391cd commit 24e0138
Show file tree
Hide file tree
Showing 21 changed files with 675 additions and 183 deletions.
22 changes: 22 additions & 0 deletions packages/web-app/app/_ui/components/avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useKyc } from '@/app/_providers/kyc/context';
import { DefaultAvatar, LockedAvatar, PendingAvatar } from './svg/avatars';
import { idOSCredentialStatus } from '@/app/_types/idos';

const avatarMap = {
pending: PendingAvatar,
contacted: PendingAvatar,
approved: DefaultAvatar,
rejected: LockedAvatar,
expired: LockedAvatar,
};

const getAvatar = (status: idOSCredentialStatus | undefined) => {
return (status && avatarMap[status]) || LockedAvatar;
};

export const Avatar = () => {
const { status } = useKyc();
const Avatar = getAvatar(status);

return <Avatar />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { Dialog, Transition } from '@headlessui/react';
import { Fragment } from 'react';
import { Close } from '../svg/close';

type TDialogWrapperProps = {
show: boolean;
Expand Down Expand Up @@ -37,6 +38,9 @@ export function DialogWrapper({ show, close, children }: TDialogWrapperProps) {
>
<Dialog.Panel className="relative transform overflow-hidden rounded-md border border-mono-50 bg-white px-4 pb-4 pt-5 text-mono-900 shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6">
{children}
<div className="absolute right-4 top-5 md:right-6 md:top-6">
<Close onClick={close} />
</div>
</Dialog.Panel>
</Transition.Child>
</div>
Expand Down
102 changes: 0 additions & 102 deletions packages/web-app/app/_ui/components/dialogs/settings-dialog.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use client';

import { useIdOS } from '@/app/_providers/idos';
import { useCopyToClipboard } from '@/app/_ui/hooks/useCopyToClipboard';
import { formatAddress } from '@/app/_ui/utils/formatAddress';
import { useCallback, useMemo } from 'react';
import { Button } from '../../button';
import { Check } from '../../svg/check';
import { Clipboard } from '../../svg/clipboard';

export const Address = () => {
const [copiedText, copy] = useCopyToClipboard();
const { address } = useIdOS();
const displayAddress = useMemo(() => {
if (!address) return;

return formatAddress(address);
}, [address]);

const handleClick = useCallback(() => {
if (!address) return;

copy(address);
}, [address, copy]);

if (!address) return null;

return (
<div>
<label htmlFor="address" className="sr-only">
Account Address
</label>
<Button
variant="secondary"
onClick={handleClick}
className="content-center items-center gap-1 pb-0 pl-0 pr-0 pt-0 font-normal text-mono-950 hover:text-blue-400"
>
<div>{displayAddress}</div>
{copiedText ? <Check /> : <Clipboard />}
</Button>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client';

import { useAccount, useBalance } from 'wagmi';
import { Wallet } from '../../svg/wallet';
import { formatEther } from 'viem';

export const Balance = () => {
const { address } = useAccount();
const balance = useBalance({
address: address,
blockTag: 'latest',
});

return (
<>
<Wallet />
<div className="flex flex-col items-start gap-2">
<h3 className="text-sm text-mono-800">Balance</h3>
<p className="font-medium">
{balance?.data?.formatted ? formatEther(balance?.data.value) : null}{' '}
{balance.data?.symbol}
</p>
</div>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use client';

import { Button } from '../..';
import { useDisconnect } from 'wagmi';
import { Disconnect as DisconnectIcon } from '../../svg/disconnect';
import { useDialog } from '@/app/_providers/dialog/context';

export const DisconnectMenu = () => {
const { disconnect } = useDisconnect();
const { close } = useDialog();

return (
<>
<DisconnectIcon />
<Button
variant="secondary"
className="pb-0 pl-0 pr-0 pt-0 font-normal text-mono-950 hover:text-blue-400"
onClick={() => {
disconnect();
close();
}}
>
Disconnect
</Button>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use client';

import { Dialog } from '@headlessui/react';
import { Avatar } from '../../avatar';
import { Address } from './address';
import { Balance } from './balance';
import { IdStatus } from './status';
import { DisconnectMenu } from './disconnect';

export function SettingsDialog() {
return (
<>
<Dialog.Title
as="h4"
className="relative flex w-full justify-center pb-6 text-mono-950"
>
<div className="">Settings</div>
</Dialog.Title>
<div className="flex flex-col divide-y divide-mono-300">
<div className="flex items-center gap-3 pb-6">
<Avatar />
<Address />
</div>
<div className="flex gap-2 py-6">
<Balance />
</div>
<div className="relative flex gap-2 py-6">
<IdStatus />
</div>
<div className="flex gap-2 pt-6">
<DisconnectMenu />
</div>
</div>
</>
);
}

SettingsDialog.displayName = 'settingsDialog';
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
'use client';

import { useKyc } from '@/app/_providers/kyc/context';
import { ID } from '../../svg/id';
import { useIdOS } from '@/app/_providers/idos';
import Link from 'next/link';
import { Check } from '../../svg/check';
import { idOSCredentialStatus } from '@/app/_types/idos';

const getNotVerifiedMessage = (status: idOSCredentialStatus | undefined) => {
if (status === 'expired') return 'KYC expired';
if (status === 'rejected') return 'KYC rejected';
return 'Not verified';
};

const Status = () => {
const { getProviderUrl, address } = useIdOS();
const { status, error, isSuccess, isLoading } = useKyc();

if (!address) return 'wallet not connected';
if (isLoading) return 'Loading...';
if (error || !isSuccess) return 'Something went wrong';

const providerUrl = getProviderUrl(address);

if (status === 'pending' || status === 'contacted') {
return (
<>
<div className="absolute right-0 top-7 h-3 w-3 rounded-full bg-yellow-500"></div>
<h4>Verification in progress</h4>
<p className="text-start">
Your information is currently being verified.
</p>
<Link
href={providerUrl}
className="select-none rounded-md text-xs text-blue-500 hover:text-blue-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mono-400"
>
Manage my ID
</Link>
</>
);
}

if (status === 'approved') {
return (
<>
<div className="flex items-center gap-2">
<h4>Verified</h4>
<Check />
</div>
<Link
href={providerUrl}
className="select-none rounded-md text-xs text-blue-500 hover:text-blue-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mono-400"
>
Manage my ID
</Link>
</>
);
}

return (
<>
<div className="absolute right-0 top-7 h-3 w-3 rounded-full bg-red-700"></div>
<h4>{getNotVerifiedMessage(status)}</h4>
<p className="text-start">
To be able to contribute to this project, you must complete ID Plus
verification.
</p>
<Link
href={providerUrl}
className="select-none rounded-md text-xs text-blue-500 hover:text-blue-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mono-400"
>
Verify my ID
</Link>
</>
);
};

export const IdStatus = () => (
<>
<div className="min-w-6">
<ID />
</div>
<div className="flex flex-col items-start gap-2">
<h3 className="text-sm text-mono-800">Id Status</h3>
<Status />
</div>
</>
);
Loading

0 comments on commit 24e0138

Please sign in to comment.