Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .env

This file was deleted.

2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
NEXT_PUBLIC_NETWORK=NETWORK
NEXT_PUBLIC_AUTH_URL=AUTH_ENDPOINT
20 changes: 18 additions & 2 deletions components/profile/menu-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { Div } from '@stylin.js/elements';
import { not } from 'ramda';
import { FC, useState } from 'react';

import { MEMEZ_FUN_TOKEN_AUTH } from '@/constants';
import { useCookie } from '@/hooks/use-cookie';

import {
DocIDSVG,
ExplorerSVG,
Expand All @@ -20,9 +23,22 @@ import RPCCollapseMenuInfo from './rpc-collapse-info';
const MenuList: FC = () => {
const [isActiveNSFE, setIsActiveNSFE] = useState(false);
const [isRPCMenuOpen, setIsRPCMenuOpen] = useState(false);
const { mutate: disconnectWallet } = useDisconnectWallet();
const { cookie: bearerToken } = useCookie(MEMEZ_FUN_TOKEN_AUTH);
const [isAccountMenuOpen, setIsAccountMenuOpen] = useState(false);
const [isExplorerMenuOpen, setIsExplorerMenuOpen] = useState(false);
const { mutate: disconnectWallet } = useDisconnectWallet();

const handleDisconnectWallet = () => {
fetch(`${process.env.NEXT_PUBLIC_AUTH_URL}/sign-out`, {
method: 'DELETE',
mode: 'cors',
headers: {
Authorization: `Bearer ${bearerToken}`,
},
}).then((res) => {
res.ok && disconnectWallet();
});
};

return (
<Div>
Expand Down Expand Up @@ -58,7 +74,7 @@ const MenuList: FC = () => {
Icon={LogoutSVG}
title="Disconnect"
color="#E85965"
onClick={() => disconnectWallet()}
onClick={handleDisconnectWallet}
/>
</Div>
);
Expand Down
2 changes: 2 additions & 0 deletions constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ export * from './math';
export * from './network';
export * from './routes';
export const DROPDOWN_DATA = ['Days', 'Weeks', 'Months'];

export const MEMEZ_FUN_TOKEN_AUTH = 'MEMEZ_FUN_TOKEN_AUTH';
34 changes: 34 additions & 0 deletions hooks/use-cookie/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useState } from 'react';
const setCookie = (name: string, value: string, days: number) => {
const expires = new Date();
expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000);
document.cookie = `${name}=${value}; expires=${expires.toUTCString()}; path=/`;
};

const getCookie = (name: string): string | null => {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop()?.split(';').shift() || null;
return null;
};

const deleteCookie = (name: string) => {
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;
};
export const useCookie = (name: string) => {
const [cookie, setCookieState] = useState<string | null>(() =>
getCookie(name)
);

const set = (value: string, days: number = 365) => {
setCookie(name, value, days);
setCookieState(value);
};

const remove = () => {
deleteCookie(name);
setCookieState(null);
};

return { cookie, set, remove } as const;
};
7 changes: 6 additions & 1 deletion pages/_document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { Head, Html, Main, NextScript } from 'next/document';

const Document = () => (
<Html lang="en">
<Head />
<Head>
<meta
httpEquiv="Content-Security-Policy"
content="upgrade-insecure-requests"
/>
</Head>
<body>
<Main />
<NextScript />
Expand Down
6 changes: 4 additions & 2 deletions views/sign-in/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ const SignIn: FC = () => {
</P>
</Div>
<Div>
<SignInForm />
<SignInButtons />
<form>
<SignInForm />
<SignInButtons />
</form>
<Div
mt="3rem"
gap="0.5rem"
Expand Down
184 changes: 105 additions & 79 deletions views/sign-in/sign-in-button.tsx
Original file line number Diff line number Diff line change
@@ -1,114 +1,140 @@
import { useDisconnectWallet } from '@mysten/dapp-kit';
import { Button, Div } from '@stylin.js/elements';
import { useRouter } from 'next/router';
import { FC } from 'react';
import { useFormContext } from 'react-hook-form';

import DialogCountdown from '@/components/dialog/dialog-countdown';
import { LoaderSVG } from '@/components/svg';
import { useConnectModal } from '@/components/wallet-button/wallet-button.hook';
import { MEMEZ_FUN_TOKEN_AUTH, RoutesEnum } from '@/constants';
import { useCookie } from '@/hooks/use-cookie';
import { useDialog } from '@/hooks/use-dialog';

import { SignInFormProps } from './sign-in.types';

const SignInButton: FC = () => {
const { setValue, trigger } = useFormContext<SignInFormProps>();
const { dialog, handleClose } = useDialog();
const handleOpenConnectModal = useConnectModal();
const { mutate: disconnectWallet } = useDisconnectWallet();
const { set: setCookie } = useCookie(MEMEZ_FUN_TOKEN_AUTH);
const { getValues, handleSubmit } = useFormContext<SignInFormProps>();
const { push } = useRouter();

const handleCreateProfile = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const isSuccess = Math.random() > 0.5;
if (isSuccess) {
setValue('success', true);
resolve('success');
return;
}
reject('Error');
}, 1000);
});
};
const scheduleTimeToDisconnect = () => {
const oneHour = 60 * 60 * 1000;
const disconnectTimer = setTimeout(() => {
disconnectWallet();
push(RoutesEnum.SignIn);
}, oneHour);

const handleSignIn = async () => {
let fieldsToValidate: (keyof SignInFormProps)[] = [];
return disconnectTimer;
};

fieldsToValidate = ['username', 'password'];
const isValid = await trigger(fieldsToValidate);
const onSignIn = async () => {
const { username, password } = getValues();
const body = JSON.stringify({
username,
password,
});
return await fetch(`${process.env.NEXT_PUBLIC_AUTH_URL}/sign-in`, {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
},
body,
}).then(async (res) => {
const response = await res.json();
scheduleTimeToDisconnect();
if (!res.ok) {
throw new Error(`${response.error}: ${response.message}`);
}
setCookie(response.accessToken);
return;
});
};

if (isValid) {
await dialog.promise(handleCreateProfile(), {
success: () => ({
title: 'Sign-in successful',
button: (
<Button
all="unset"
py="1rem"
px="1.5rem"
flex="2"
bg="#F5B722"
color="#000000"
cursor="pointer"
textAlign="center"
borderRadius="1rem"
>
You will&apos;be redirect to connect your wallet in{' '}
<DialogCountdown
timeout={5000}
onComplete={handleOpenConnectModal}
/>{' '}
sec
</Button>
),
ghostButton: (
<Button
all="unset"
color="#F5B722"
cursor="pointer"
textAlign="center"
fontSize="0.825rem"
onClick={handleOpenConnectModal}
nHover={{ textDecoration: 'underline' }}
>
Connect your wallet now
</Button>
),
message: 'Now connect your wallet do see all the function',
}),
loading: () => ({
Icon: <LoaderSVG />,
title: 'Signing...',
message: 'Please wait...',
}),
error: (e) => ({
title: 'Oops! You can not sign in!',
button: { label: 'Try again', onClick: handleClose },
message: (
e.message ||
'Make sure you fill every field correctly and try again.'
).replace('Invariant failed: ', ''),
ghostButton: {
label: 'Do not want to try again!',
onClick: handleClose,
},
}),
});
}
if (!isValid) return;
const handleSignIn = () => {
dialog.promise(onSignIn(), {
success: () => ({
title: 'Sign-in successful',
button: (
<Button
all="unset"
py="1rem"
px="1.5rem"
flex="2"
bg="#F5B722"
color="#000000"
cursor="pointer"
textAlign="center"
borderRadius="1rem"
>
You will&apos;be redirect to connect your wallet in{' '}
<DialogCountdown
timeout={5000}
onComplete={handleOpenConnectModal}
/>{' '}
sec
</Button>
),
ghostButton: (
<Button
all="unset"
color="#F5B722"
cursor="pointer"
textAlign="center"
fontSize="0.825rem"
onClick={handleOpenConnectModal}
nHover={{ textDecoration: 'underline' }}
>
Connect your wallet now
</Button>
),
message: 'Now connect your wallet do see all the function',
}),
loading: () => ({
Icon: <LoaderSVG />,
title: 'Signing...',
message: 'Please wait...',
}),
error: (e) => ({
title: 'Oops! You can not sign in!',
button: { label: 'Try again', onClick: handleClose },
message: (
e.message || 'Make sure you fill every field correctly and try again.'
).replace('Invariant failed: ', ''),
ghostButton: {
label: 'Do not want to try again!',
onClick: handleClose,
},
}),
});
};

return (
<Div mt="2.5rem" display="flex" gap="0.5rem" justifyContent="center">
<Div
mt="2.5rem"
display="flex"
gap="0.5rem"
alignItems="center"
flexDirection="column"
justifyContent="center"
>
<Button
all="unset"
py="0.4rem"
bg="#F6C853"
display="flex"
width="7.5rem"
cursor="pointer"
type="submit"
borderRadius="100px"
transition="all .3s"
justifyContent="center"
border="1px solid #F6C853"
onClick={async () => await handleSignIn()}
onClick={handleSubmit(handleSignIn)}
nHover={{
transform: 'scale(1.05)',
}}
Expand Down
2 changes: 1 addition & 1 deletion views/sign-in/sign-in-validations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const SignInValidationSchema = yup.object({
password: yup
.string()
.required('Password is required')
.min(8, 'Must be at least 8 characters')
.min(6, 'Must be at least 8 characters')
.matches(/[A-Z]/, 'Must contain an uppercase letter')
.matches(/[0-9]/, 'Must contain a number'),
});