Skip to content

Commit

Permalink
Merge pull request #92 from Portkey-Wallet/feature/approve-detial
Browse files Browse the repository at this point in the history
Feature/approve detial
  • Loading branch information
FrankFeng1116 authored Aug 21, 2024
2 parents 35bf535 + 6610428 commit c1e9a98
Show file tree
Hide file tree
Showing 14 changed files with 554 additions and 37 deletions.
21 changes: 21 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"jsxBracketSameLine": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 120,
"endOfLine": "lf",
"overrides": [
{
"files": "*.css",
"options": {
"parser": "css"
}
},
{
"files": "*.less",
"options": {
"parser": "less"
}
}
]
}
5 changes: 5 additions & 0 deletions public/error.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions public/portkeyLogoBlack.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 20 additions & 24 deletions src/app/recaptcha/page.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,50 @@
"use client";
import React, { useEffect, useMemo } from "react";
import GoogleReCaptcha from "src/components/GoogleReCaptcha";
import { BaseReCaptcha } from "src/components/GoogleReCaptcha/types";
import { useSendMessageByIframe } from "src/hooks/iframe";
import { TSearch } from "src/types";
import "./index.css";
'use client';
import React, { useEffect, useMemo } from 'react';
import GoogleReCaptcha from 'src/components/GoogleReCaptcha';
import { BaseReCaptcha } from 'src/components/GoogleReCaptcha/types';
import { useSendMessageByIframe } from 'src/hooks/iframe';
import { TSearch } from 'src/types';
import './index.css';

export default function Recaptcha({
searchParams = {},
}: {
searchParams: TSearch;
}) {
export default function Recaptcha({ searchParams = {} }: { searchParams: TSearch }) {
const { onSuccess } = useSendMessageByIframe({
target: "@portkey/ui-did-react:ReCaptcha",
target: '@portkey/ui-did-react:ReCaptcha',
});

const {
theme = "light",
siteKey,
size = "normal",
theme = 'light',
siteKey = '6LfR_bElAAAAAJSOBuxle4dCFaciuu9zfxRQfQC0',
size = 'normal',
} = useMemo(() => {
return searchParams as Omit<BaseReCaptcha, "customReCaptchaHandler">;
return searchParams as Omit<BaseReCaptcha, 'customReCaptchaHandler'>;
}, [searchParams]);

useEffect(() => {
document.body.classList.add("recaptcha-body");
document.body.classList.add('recaptcha-body');
}, []);

return (
<div className="h-screen flex justify-center items-center">
{siteKey ? (
<GoogleReCaptcha
theme={theme || "light"}
size={size || "normal"}
theme={theme || 'light'}
size={size || 'normal'}
siteKey={siteKey}
onSuccess={(res) => {
onSuccess({
type: "PortkeyReCaptchaOnSuccess",
type: 'PortkeyReCaptchaOnSuccess',
data: res,
});
}}
onError={(res) => {
console.log(res, "onError");
console.log(res, 'onError');
}}
onExpire={(err) => {
console.log(err, "onExpire");
console.log(err, 'onExpire');
}}
/>
) : (
"Invalid siteKey"
'Invalid siteKey'
)}
</div>
);
Expand Down
31 changes: 19 additions & 12 deletions src/app/social-start/page.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
"use client";
import React, { useMemo } from "react";
import { useSearchParams } from "next/navigation";
import { base64toJSON } from "src/utils";
import { OPENLOGIN_ACTIONS } from "src/constants/social";
import SocialAuth from "src/pages-components/social-auth";
import { OpenLoginParamConfig } from "src/types/auth";
'use client';
import React, { useCallback, useMemo, useState } from 'react';
import { useSearchParams } from 'next/navigation';
import { base64toJSON } from 'src/utils';
import { OPENLOGIN_ACTIONS } from 'src/constants/social';
import SocialAuth from 'src/pages-components/social-auth';
import { OpenLoginParamConfig } from 'src/types/auth';
import JumpEntry from 'src/pages-components/entry';

export default function SocialStart() {
const searchParams = useSearchParams();
const b64Params = searchParams.get("b64Params") || "";
const b64Params = searchParams.get('b64Params') || '';

const params = useMemo(() => {
try {
const data = base64toJSON(b64Params);
console.log(data, "b64Params===");
console.log(data, 'b64Params===');
return data as any;
} catch (error) {
return {};
}
}, [b64Params]);
const [showAgree, setShowAggree] = useState<boolean>(true);
const onApprove = useCallback(() => {
setShowAggree(false);
}, []);

if (params?.actionType !== OPENLOGIN_ACTIONS.LOGIN) return <>`actionType` No Support</>;
return (
<div>
{params?.actionType === OPENLOGIN_ACTIONS.LOGIN ? (
<SocialAuth authInfo={params as OpenLoginParamConfig} />
{params.approveDetail && showAgree ? (
<JumpEntry authInfo={params as OpenLoginParamConfig} onApprove={onApprove} />
) : (
<>`actionType` No Support</>
<SocialAuth authInfo={params as OpenLoginParamConfig} />
)}
</div>
);
Expand Down
11 changes: 11 additions & 0 deletions src/components/CommonImage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import clsx from 'clsx';
import Image, { ImageProps } from 'next/image';
import styles from './styles.module.css';

export default function CommonImage({ className, style, layout = 'fill', alt = 'img', ...props }: ImageProps) {
return (
<div className={clsx(styles['common-img'], className)} style={style}>
<Image {...props} layout={layout} alt={alt} />
</div>
);
}
3 changes: 3 additions & 0 deletions src/components/CommonImage/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.common-img {
position: relative;
}
14 changes: 14 additions & 0 deletions src/constants/entry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const entryPageData = {
logo: {
src: '/portkeyLogoBlack.svg',
width: 230,
height: 78,
alt: 'Portkey Logo',
},
errorIcon: {
src: '/error.svg',
width: 16,
height: 16,
alt: 'Error Icon',
},
};
98 changes: 98 additions & 0 deletions src/pages-components/entry/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import pcStyle from './pc-styles.module.css';
import mobileStyle from './mobile-styles.module.css';
import { Button, ConfigProvider } from 'antd';
import { useCallback, useEffect, useState } from 'react';
import { getCountry, translateOperationEnumToStr } from 'src/utils/model';

import CommonImage from 'src/components/CommonImage';
import { entryPageData } from 'src/constants/entry';
import { useStyleProvider } from 'src/utils/mobile';
import { OpenLoginParamConfig } from 'src/types/auth';

export default function JumpEntry({ onApprove, authInfo }: { onApprove?: () => void; authInfo: OpenLoginParamConfig }) {
const { logo, errorIcon } = entryPageData;
const styles = useStyleProvider<Record<string, string>>({
pcStyle,
mobileStyle,
});
const [consumedData, setConsumedData] = useState<{ [x: string]: string | number | boolean } | undefined>({});
const [ip, setIp] = useState<string | undefined>('--');

const checkUserIp = useCallback(async (serviceUrl: string) => {
try {
const country = await getCountry(serviceUrl);
setIp(country);
// eslint-disable-next-line no-empty
} catch (ignored) {}
}, []);

useEffect(() => {
try {
if (!authInfo) throw new Error('invalid data');
console.log(authInfo, 'entryPrams===');
const { approveDetail, serviceURI } = authInfo;
if (!approveDetail) return onApprove?.();
const { symbol, amount, originChainId, targetChainId, operationType, guardian } = approveDetail;
const { guardianType, identifier, thirdPartyEmail } = guardian;
if (!serviceURI || !guardianType) {
throw new Error('invalid data');
}
const raw: any = {};
raw['Operation Type'] = translateOperationEnumToStr(operationType);
symbol && (raw['Token'] = symbol);
(amount || typeof amount === 'number') && (raw['Amount'] = amount);
const realChainId = targetChainId || originChainId;
raw['Chain'] = realChainId === `AELF` ? `MainChain ${realChainId}` : `SideChain ${realChainId}`;
raw['Guardian Type'] = guardianType;
const guardianAccount = thirdPartyEmail || identifier;
raw['Guardian Account'] = guardianAccount;
raw['Time'] = new Date().toLocaleString();
raw['IP'] = ip;
setConsumedData(raw);
checkUserIp(serviceURI);
} catch (e) {
console.error(e);
setConsumedData(undefined);
}
}, [authInfo, checkUserIp, ip, onApprove]);

return (
<ConfigProvider>
<div className={styles.container}>
<div className={styles.wrapper}>
<CommonImage src={logo.src} style={{ width: logo.width, height: logo.height }} alt={logo.alt} priority />
<div className={styles.introductionText}>
{'Verification details are as follows. Proceed only if all data matches:'}
</div>
<div className={styles.dashboard}>
{consumedData ? (
Object.entries(consumedData).map(([key, value]) => {
return (
<div className={styles.infoLine} key={key}>
<div className={styles.infoTitle}>{key}</div>
<div className={styles.infoContent}>{value}</div>
</div>
);
})
) : (
<div className={styles.infoLine}>
<CommonImage
src={errorIcon.src}
style={{ width: errorIcon.width, height: errorIcon.height }}
alt={errorIcon.alt}
priority
/>
<div className={styles.errorText}>Invalid parameter.</div>
</div>
)}
</div>
{!!consumedData && (
<Button type="primary" className={styles.jumpBtn} onClick={onApprove}>
<div className={styles.jumpBtnText}>Agree</div>
</Button>
)}
</div>
</div>
</ConfigProvider>
);
}
Loading

0 comments on commit c1e9a98

Please sign in to comment.