diff --git a/CHANGELOG.md b/CHANGELOG.md index 66cf900..94944ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,40 @@ -# v4.2.2 (Tue Sep 12 2023) +# v4.4.1 (Wed Sep 27 2023) + +#### 🚀 Enhancement + +- Remove Universal option from prompts (it remains available in flags) + +# v4.4.0 (Wed Sep 27 2023) + +#### 🚀 Enhancement + +- Updates the UI design of the templates + +#### Authors: 2 + +- James ([@jamesrp13](https://github.com/jamesrp13)) +- Aditya Kulkarni ([@AdityaKulkarni](https://github.com/AdityaKulkarni)) + +--- + +# v4.3.1 (Fri Sep 15 2023) #### 🚀 Enhancement +- Enables anonymous usage tracking with a command to opt out +- Updates Quickstart to use Dedicated Wallet + +#### Authors: 2 + +- James ([@jamesrp13](https://github.com/jamesrp13)) +- Aditya Kulkarni ([@AdityaKulkarni](https://github.com/AdityaKulkarni)) + +--- + +# v4.2.2 (Tue Sep 12 2023) + +#### 🐛 Bug Fix + - Fix bug where network isn't always added into template configuration #### Authors: 2 @@ -9,6 +42,8 @@ - James ([@jamesrp13](https://github.com/jamesrp13)) - Aditya Kulkarni ([@AdityaKulkarni](https://github.com/AdityaKulkarni)) +--- + # v4.2.0 (Mon Sep 11 2023) #### 🚀 Enhancement diff --git a/core/cli.ts b/core/cli.ts index ebb5b54..316968b 100644 --- a/core/cli.ts +++ b/core/cli.ts @@ -45,7 +45,7 @@ export const ConsoleMessages = { startCmd && chalk` {rgb(0,255,255) ${startCmd}}`, ].filter(Boolean); - msg.join('\n'); + return msg.join('\n'); }, }; diff --git a/core/create-app.tsx b/core/create-app.tsx index 6f770e5..3d2b5f4 100644 --- a/core/create-app.tsx +++ b/core/create-app.tsx @@ -89,8 +89,6 @@ export async function createApp(config: CreateMagicAppConfig) { })), }; - console.log('config', JSON.stringify(config, null, 2)); - const templateFlags: any = await parseFlags(mapTemplateToFlags(config.template as string), config?.data); const repoUrl = new URL(`${DEFAULT_CREATE_MAGIC_APP_REPO}/tree/${config.branch}`, GITHUB_BASE_URL); const repoInfo = await getRepoInfo(repoUrl, getRelativeTemplatePath(config.template as string)); diff --git a/core/utils/renderScaffold.ts b/core/utils/renderScaffold.ts index cb57519..44d00c3 100644 --- a/core/utils/renderScaffold.ts +++ b/core/utils/renderScaffold.ts @@ -7,16 +7,17 @@ import fs from 'fs'; // TODO - update templateData type to be more specific export const renderScaffold = async (cwd: string, scaffold: BaseScaffold, templateData: any) => { const basePath = resolveToRoot('scaffolds', scaffold.templateName, 'template'); - const allDirFilePaths = []; + const allDirFilePaths: string[] = []; // typeof scaffold.source being a string means it's a directory and we should copy all files if (typeof scaffold.source == 'string') { - readTemplateDirs(basePath, (err, filePaths) => { + readTemplateDirs(basePath, async (err, filePaths) => { if (err) { console.log(err); } for (const filePath of filePaths) { allDirFilePaths.push(filePath); } + await copyFilesAndRenameEnv(allDirFilePaths, basePath, cwd, templateData); }); // Otherwise it's an array and we should copy all the files in the array } else { @@ -37,13 +38,15 @@ export const renderScaffold = async (cwd: string, scaffold: BaseScaffold, templa allDirFilePaths.push(resolvedPath); } } + await copyFilesAndRenameEnv(allDirFilePaths, basePath, cwd, templateData); } +}; +async function copyFilesAndRenameEnv(allDirFilePaths: string[], basePath: string, cwd: string, templateData: any) { for (const filePath of allDirFilePaths) { await copyFileWithEjsData(filePath, path.join(cwd, filePath.replace(basePath, '')), templateData); } - if (fs.existsSync(path.join(cwd, '.env.example'))) { fs.renameSync(path.join(cwd, '.env.example'), path.join(cwd, '.env')); } -}; +} diff --git a/package.json b/package.json index d679913..049c460 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "make-magic", - "version": "4.2.2", + "version": "4.4.1", "description": "A tool for quickly scaffolding an app with Magic authentication baked-in!", "repository": "magiclabs/create-magic-app", "license": "MIT", diff --git a/scaffolds/nextjs-dedicated-wallet/scaffold.tsx b/scaffolds/nextjs-dedicated-wallet/scaffold.tsx index b8eca4c..236ae6e 100644 --- a/scaffolds/nextjs-dedicated-wallet/scaffold.tsx +++ b/scaffolds/nextjs-dedicated-wallet/scaffold.tsx @@ -21,10 +21,13 @@ export default class DedicatedScaffold extends BaseScaffold { public installationCommand: string[] = ['npm', 'install']; public startCommand: string[] = ['npm', 'run', 'dev']; public source: string | string[] = [ - './public/background.svg', './public/favicon.ico', - './public/magic_color_white.svg', + './public/logo.svg', + './public/info.svg', './public/link.svg', + './public/link_white.svg', + './public/redirect_bg.png', + './public/login_bg.png', './.env.example', './.eslintrc.json', './.gitignore', diff --git a/scaffolds/nextjs-dedicated-wallet/template/public/background.svg b/scaffolds/nextjs-dedicated-wallet/template/public/background.svg deleted file mode 100644 index c611daa..0000000 --- a/scaffolds/nextjs-dedicated-wallet/template/public/background.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/scaffolds/nextjs-dedicated-wallet/template/public/info.svg b/scaffolds/nextjs-dedicated-wallet/template/public/info.svg new file mode 100644 index 0000000..df6edb9 --- /dev/null +++ b/scaffolds/nextjs-dedicated-wallet/template/public/info.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-dedicated-wallet/template/public/link_white.svg b/scaffolds/nextjs-dedicated-wallet/template/public/link_white.svg new file mode 100644 index 0000000..c87852b --- /dev/null +++ b/scaffolds/nextjs-dedicated-wallet/template/public/link_white.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-dedicated-wallet/template/public/login_bg.png b/scaffolds/nextjs-dedicated-wallet/template/public/login_bg.png new file mode 100644 index 0000000..a4021c4 Binary files /dev/null and b/scaffolds/nextjs-dedicated-wallet/template/public/login_bg.png differ diff --git a/scaffolds/nextjs-dedicated-wallet/template/public/logo.svg b/scaffolds/nextjs-dedicated-wallet/template/public/logo.svg new file mode 100644 index 0000000..e13da68 --- /dev/null +++ b/scaffolds/nextjs-dedicated-wallet/template/public/logo.svg @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-dedicated-wallet/template/public/magic_color_white.svg b/scaffolds/nextjs-dedicated-wallet/template/public/magic_color_white.svg deleted file mode 100644 index 3267c05..0000000 --- a/scaffolds/nextjs-dedicated-wallet/template/public/magic_color_white.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - diff --git a/scaffolds/nextjs-dedicated-wallet/template/public/redirect_bg.png b/scaffolds/nextjs-dedicated-wallet/template/public/redirect_bg.png new file mode 100644 index 0000000..aa322ee Binary files /dev/null and b/scaffolds/nextjs-dedicated-wallet/template/public/redirect_bg.png differ diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Dashboard.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Dashboard.tsx index c690b9b..4e02d36 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Dashboard.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Dashboard.tsx @@ -11,13 +11,11 @@ export default function Dashboard({ token, setToken }: LoginProps) { return (
- -
- - + +
diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Header.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Header.tsx index ebe7cfc..a6e4012 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Header.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Header.tsx @@ -1,11 +1,17 @@ import Image from 'next/image'; -import MagicColorWhite from 'public/magic_color_white.svg'; +import Logo from 'public/logo.svg'; import DevLinks from './DevLinks'; const Header = () => { return (
- logo +
+ logo +
Magic
+
+ Demo +
+
); diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Login.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Login.tsx index 2516d62..9cac8d6 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Login.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Login.tsx @@ -8,7 +8,7 @@ const Login = ({ token, setToken }: LoginProps) => { return (
-
+
grid-flow-row auto-rows-fr gap-5 p-4 mt-8`}> <% loginMethods.forEach(authType => { %> <% if (authType !== "Social Logins") { %> <%-`<${authType.replaceAll(' ', '')} token={token} setToken={setToken} />`-%> diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx index 2225998..4c2cbed 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx @@ -1,6 +1,9 @@ import React, { useCallback } from 'react'; -import Spacer from '../ui/Spacer'; import DevLinks from './DevLinks'; +import Image from 'next/image'; +import Info from 'public/info.svg'; +import Link from 'public/link_white.svg'; +import Logo from 'public/logo.svg'; const MagicDashboardRedirect = () => { const onClick = useCallback(() => { @@ -9,18 +12,27 @@ const MagicDashboardRedirect = () => { return (
- - -
-

- Please set your NEXT_PUBLIC_MAGIC_API_KEY environment variable in .env. You can get - your Magic API key from the Magic Dashboard. -

+
+ logo +
Magic
+
+ Demo +
- -
-
diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Discord.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Discord.tsx index 489fafb..763aed7 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Discord.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Discord.tsx @@ -55,18 +55,16 @@ const Discord = ({ token, setToken }: LoginProps) => { ) : (
-
0 ? 'cursor-default' : 'cursor-pointer', - )} +
+ Discord +
Continue with Discord
+
)} diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx index f1bae1c..662e77c 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx @@ -68,7 +68,7 @@ const EmailOTP = ({ token, setToken }: LoginProps) => { disabled={isLoginInProgress || (token.length > 0 ? false : email.length == 0)} onClick={() => handleLogin()} > - {isLoginInProgress ? : 'Login'} + {isLoginInProgress ? : 'Log in / Sign up'}
diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx index 4e9f1c0..17bd3a1 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx @@ -55,18 +55,16 @@ const Facebook = ({ token, setToken }: LoginProps) => { ) : (
-
0 ? 'cursor-default' : 'cursor-pointer', - )} +
+ Facebook +
Continue with Facebook
+
)} diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Github.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Github.tsx index e527a3e..8004de7 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Github.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Github.tsx @@ -55,18 +55,16 @@ const Github = ({ token, setToken }: LoginProps) => { ) : (
-
0 ? 'cursor-default' : 'cursor-pointer', - )} +
+ Github +
Continue with Github
+
)} diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Google.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Google.tsx index 324e347..4dc8087 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Google.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Google.tsx @@ -55,18 +55,16 @@ const Google = ({ token, setToken }: LoginProps) => { ) : (
-
0 ? 'cursor-default' : 'cursor-pointer', - )} +
+ Google +
Continue with Google
+
)} diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx index 68adc0c..2b3e474 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx @@ -74,7 +74,7 @@ const SMSOTP = ({ token, setToken }: LoginProps) => { disabled={isLoginInProgress || (token.length > 0 ? false : phone.length == 0)} onClick={() => handleLogin()} > - {isLoginInProgress ? : 'Login'} + {isLoginInProgress ? : 'Log in / Sign up'}
diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx index fe7af2c..8986ba7 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx @@ -55,18 +55,16 @@ const Twitch = ({ token, setToken }: LoginProps) => { ) : (
-
0 ? 'cursor-default' : 'cursor-pointer', - )} +
+ Twitch +
Continue with Twitch
+
)} diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx index a7c12e3..f90a7a2 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx @@ -55,18 +55,16 @@ const Twitter = ({ token, setToken }: LoginProps) => { ) : (
-
0 ? 'cursor-default' : 'cursor-pointer', - )} +
+ Twitter +
Continue with Twitter
+
)} diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/styles/globals.css b/scaffolds/nextjs-dedicated-wallet/template/src/styles/globals.css index 83bde73..7222af2 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/styles/globals.css +++ b/scaffolds/nextjs-dedicated-wallet/template/src/styles/globals.css @@ -47,7 +47,7 @@ ul { } .nft-name { - @apply text-black font-semibold; + @apply font-semibold text-black; font-family: 'Inter'; } @@ -60,7 +60,7 @@ ul { } .cards-container { - @apply mt-[-250px] relative; + @apply relative top-[30px] md:top-[-60px] lg:top-[-60px]; } @media only screen and (max-width: 767px) { @@ -70,7 +70,7 @@ ul { } .network-dropdown { - @apply w-fit m-auto rounded-xl; + @apply m-auto w-fit rounded-xl; } .active-network { @@ -116,7 +116,7 @@ ul { @apply flex flex-col items-center min-h-screen bg-gray-300; } .login-method-grid { - @apply w-[100%] grid grid-cols-4 gap-5 p-4; + @apply max-w-[100%] grid-rows-3 gap-5 p-4 mt-8; } .login-method-grid-item-container { @@ -125,7 +125,7 @@ ul { .login-button { @apply w-full h-12 text-white font-semibold text-base leading-6 transition-[0.1s] text-center transition-[0.1s] m-auto px-2 py-3 rounded-[300px] border-[none]; - background: #a799ff; + background: #8271f3; } .login-button:disabled { @@ -142,7 +142,7 @@ ul { } .links { - @apply flex justify-center text-white font-semibold mt-5 mb-3 mx-auto; + @apply flex justify-center mx-auto mt-5 text-sm mb-3 font-semibold text-white; } .link { @apply transition-[0.1s] px-[30px] py-0; @@ -163,7 +163,7 @@ ul { @apply cursor-pointer; } .link-divider { - @apply h-5 w-px; + @apply w-px h-5; } .footer-links { @@ -221,7 +221,7 @@ ul { @apply w-[50px] text-center flex items-center justify-center cursor-default; } .loading { - @apply animate-spin cursor-default; + @apply cursor-default animate-spin; } @keyframes rotation { @@ -234,18 +234,18 @@ ul { } .card { - @apply w-[300px] flex flex-col shadow-[0px_4px_24px_rgba(49,49,49,0.1)] mt-0 mb-[27px] mx-auto px-6 py-8 rounded-2xl bg-[#ffffff]; + @apply w-[344px] flex flex-col shadow-[0px_4px_24px_rgba(49,49,49,0.1)] mt-0 mb-[27px] mx-auto px-6 py-8 rounded-2xl bg-[#ffffff]; } .card-header { @apply text-xl font-semibold text-left mt-0 mb-[25px]; } .card-label-container { - @apply flex justify-between items-center mb-3; + @apply flex items-center justify-between mb-3; } .card-label { - @apply text-sm font-medium cursor-pointer; + @apply text-sm font-medium cursor-pointer; } .toast { @apply fixed w-fit text-white font-medium shadow-[4px_8px_20px_rgba(0,0,0,0.15)] mx-auto my-0 px-4 py-2 rounded-[10px] top-[30px] inset-x-0 bg-[#00875f]; @@ -291,10 +291,35 @@ a { } .app-header-container { - @apply block pt-4 w-full drop-shadow-[0_35px_35px_rgba(0,0,0,0.25)] min-h-[30vh] flex flex-col items-center bg-magic block; + @apply block w-full drop-shadow-[0_35px_35px_rgba(0,0,0,0.25)] min-h-[40%] flex-col gap-2.5 p-8 items-center bg-[url('/login_bg.png')] bg-cover bg-no-repeat pb-20; text-align: -webkit-center; } .redirect-container { - @apply flex flex-col items-center min-h-screen bg-[length:100%_auto] bg-[url('/background.svg')]; + @apply flex flex-col items-center h-screen bg-center bg-cover bg-no-repeat bg-[url('/redirect_bg.png')]; +} + +.redirect-card { + @apply bg-[#F8F8FA] rounded-[10px] shadow-[0px_4px_24px_rgba(49,49,49,0.1)] p-2 m-12; +} + +.social-login-button { + @apply flex flex-row min-w-[296px] h-12 text-[#3C4043] transition-[0.1s] px-6 py-3 rounded-[300px] bg-[#ffffff] border-2 border-[#DADCE0] relative top-16; +} + +.social-login-button:disabled { + @apply opacity-50; +} + +.social-login-button:hover:enabled { + @apply cursor-pointer; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #ffffff; +} +.social-login-button:active:enabled { + @apply opacity-50 scale-[0.99]; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #ffffff; +} + +.api-button { + @apply bg-[#6844bc] text-[#FFFFFF] flex w-[280px] justify-center items-center h-12 font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none]; } diff --git a/scaffolds/nextjs-dedicated-wallet/template/tailwind.config.js b/scaffolds/nextjs-dedicated-wallet/template/tailwind.config.js index 1da1a7e..0fc0404 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/tailwind.config.js +++ b/scaffolds/nextjs-dedicated-wallet/template/tailwind.config.js @@ -1,19 +1,17 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: [ - './src/pages/**/*.{js,ts,jsx,tsx,mdx}', - './src/components/**/*.{js,ts,jsx,tsx,mdx}', - './src/app/**/*.{js,ts,jsx,tsx,mdx}', - ], - theme: { - extend: { - backgroundImage: { - magic: "url('../../public//background.svg')", - 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', - 'gradient-conic': - 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', - }, - }, - }, - plugins: [], -} + content: [ + './src/pages/**/*.{js,ts,jsx,tsx,mdx}', + './src/components/**/*.{js,ts,jsx,tsx,mdx}', + './src/app/**/*.{js,ts,jsx,tsx,mdx}', + ], + theme: { + extend: { + backgroundImage: { + 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', + 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', + }, + }, + }, + plugins: [], +}; diff --git a/scaffolds/nextjs-flow-dedicated-wallet/scaffold.tsx b/scaffolds/nextjs-flow-dedicated-wallet/scaffold.tsx index 24a724c..8f1886e 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/scaffold.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/scaffold.tsx @@ -1,6 +1,6 @@ import { Flags } from 'core/flags'; import BaseScaffold from 'core/types/BaseScaffold'; -import { AuthTypePrompt, BlockchainNetworkPrompt, NpmClientPrompt, PublishableApiKeyPrompt } from 'scaffolds/prompts'; +import { AuthTypePrompt, NpmClientPrompt, PublishableApiKeyPrompt } from 'scaffolds/prompts'; export type Data = NpmClientPrompt.Data & PublishableApiKeyPrompt.Data & AuthTypePrompt.Data; @@ -21,10 +21,13 @@ export default class FlowDedicatedScaffold extends BaseScaffold { public installationCommand: string[] = ['npm', 'install']; public startCommand: string[] = ['npm', 'run', 'dev']; public source: string | string[] = [ - './public/background.svg', './public/favicon.ico', - './public/magic_color_white.svg', + './public/logo.svg', + './public/info.svg', './public/link.svg', + './public/link_white.svg', + './public/redirect_bg.png', + './public/login_bg.png', './.env.example', './.eslintrc.json', './.gitignore', diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/public/background.svg b/scaffolds/nextjs-flow-dedicated-wallet/template/public/background.svg deleted file mode 100644 index c611daa..0000000 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/public/background.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/public/info.svg b/scaffolds/nextjs-flow-dedicated-wallet/template/public/info.svg new file mode 100644 index 0000000..df6edb9 --- /dev/null +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/public/info.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/public/link_white.svg b/scaffolds/nextjs-flow-dedicated-wallet/template/public/link_white.svg new file mode 100644 index 0000000..c87852b --- /dev/null +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/public/link_white.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/public/login_bg.png b/scaffolds/nextjs-flow-dedicated-wallet/template/public/login_bg.png new file mode 100644 index 0000000..a4021c4 Binary files /dev/null and b/scaffolds/nextjs-flow-dedicated-wallet/template/public/login_bg.png differ diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/public/logo.svg b/scaffolds/nextjs-flow-dedicated-wallet/template/public/logo.svg new file mode 100644 index 0000000..e13da68 --- /dev/null +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/public/logo.svg @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/public/magic_color_white.svg b/scaffolds/nextjs-flow-dedicated-wallet/template/public/magic_color_white.svg deleted file mode 100644 index 3267c05..0000000 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/public/magic_color_white.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/public/redirect_bg.png b/scaffolds/nextjs-flow-dedicated-wallet/template/public/redirect_bg.png new file mode 100644 index 0000000..aa322ee Binary files /dev/null and b/scaffolds/nextjs-flow-dedicated-wallet/template/public/redirect_bg.png differ diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Dashboard.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Dashboard.tsx index 25a067a..4e02d36 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Dashboard.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Dashboard.tsx @@ -1,27 +1,25 @@ -import React from 'react' -import WalletMethods from './cards/WalletMethodsCard' -import SendTransaction from './cards/SendTransactionCard' -import Spacer from '@/components/ui/Spacer' -import {LoginProps} from '@/utils/types' -import UserInfo from './cards/UserInfoCard' -import DevLinks from './DevLinks' -import Header from './Header' +import React from 'react'; +import WalletMethods from './cards/WalletMethodsCard'; +import SendTransaction from './cards/SendTransactionCard'; +import Spacer from '@/components/ui/Spacer'; +import { LoginProps } from '@/utils/types'; +import UserInfo from './cards/UserInfoCard'; +import DevLinks from './DevLinks'; +import Header from './Header'; -export default function Dashboard({token, setToken}: LoginProps) { - return ( -
-
- - -
- - - - - - -
- -
- ) +export default function Dashboard({ token, setToken }: LoginProps) { + return ( +
+
+
+ + + + + + +
+ +
+ ); } diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Header.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Header.tsx index b997a10..b02dbb1 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Header.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Header.tsx @@ -1,19 +1,16 @@ -import Image from 'next/image' -import MagicColorWhite from 'public/magic_color_white.svg' -import {Dispatch, SetStateAction} from 'react' -import DevLinks from './DevLinks' +import Image from 'next/image'; +import MagicLogo from 'public/logo.svg'; +import DevLinks from './DevLinks'; const Header = () => { - return ( -
- logo - -
- ) -} + return ( +
+ magic-logo +
Magic
+

Demo

+ +
+ ); +}; -export default Header +export default Header; diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Login.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Login.tsx index a2ba0ba..9cac8d6 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Login.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/Login.tsx @@ -1,22 +1,22 @@ -import {LoginProps} from '@/utils/types' +import { LoginProps } from '@/utils/types' import Header from './Header' <% loginMethods.forEach(authType => { %> <%-`import ${authType.replaceAll(' ', '')} from './auth/${authType.replaceAll(' ', '')}';`-%> <% }) %> -const Login = ({token, setToken}: LoginProps) => { - return ( -
-
-
- <% loginMethods.forEach(authType => { %> - <% if (authType !== "Social Logins") { %> - <%-`<${authType.replaceAll(' ', '')} token={token} setToken={setToken} />`-%> - <% } %> - <% }) %> -
-
- ) +const Login = ({ token, setToken }: LoginProps) => { + return ( +
+
+
grid-flow-row auto-rows-fr gap-5 p-4 mt-8`}> + <% loginMethods.forEach(authType => { %> + <% if (authType !== "Social Logins") { %> + <%-`<${authType.replaceAll(' ', '')} token={token} setToken={setToken} />`-%> + <% } %> + <% }) %> +
+
+ ) } export default Login diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx index 3c0eb04..4c2cbed 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx @@ -1,35 +1,43 @@ -import React, {useCallback} from 'react' -import Spacer from '../ui/Spacer' -import Header from './Header' -import DevLinks from './DevLinks' +import React, { useCallback } from 'react'; +import DevLinks from './DevLinks'; +import Image from 'next/image'; +import Info from 'public/info.svg'; +import Link from 'public/link_white.svg'; +import Logo from 'public/logo.svg'; const MagicDashboardRedirect = () => { - const onClick = useCallback(() => { - window.open('https://dashboard.magic.link/signup', '_blank') - }, []) + const onClick = useCallback(() => { + window.open('https://dashboard.magic.link/signup', '_blank'); + }, []); - return ( -
- - -
-

- Please set your NEXT_PUBLIC_MAGIC_API_KEY{' '} - environment variable in .env. You can get your - Magic API key from the Magic Dashboard. -

-
- -
- -
- -
- ) -} + return ( +
+
+ logo +
Magic
+
+ Demo +
+
+
+
+
+ logo +

+ Please set your NEXT_PUBLIC_MAGIC_API_KEY environment variable in .env. You can + get your Magic API key from the Magic Dashboard. +

+
+
-export default MagicDashboardRedirect + +
+ +
+ ); +}; + +export default MagicDashboardRedirect; diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Discord.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Discord.tsx index d05c653..763aed7 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Discord.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Discord.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '@/components/ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import discord from 'public/social/Discord.svg' -import Card from '@/components/ui/Card' -import CardHeader from '@/components/ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '@/components/ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import discord from 'public/social/Discord.svg'; +import Card from '@/components/ui/Card'; +import CardHeader from '@/components/ui/CardHeader'; -const Discord = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Discord = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'discord', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'discord', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Discord Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Discord -
Discord
-
-
- )} -
- ) -} -export default Discord + return ( + + Discord Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Discord; diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx index 3327f6b..662e77c 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx @@ -1,90 +1,78 @@ -import {useMagic} from '../MagicProvider' -import showToast from '@/utils/showToast' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import {RPCError, RPCErrorCode} from 'magic-sdk' -import {LoginProps} from '@/utils/types' -import {saveToken} from '@/utils/common' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' -import {useState} from 'react' -import FormInput from '@/components/ui/FormInput' +import { useMagic } from '../MagicProvider'; +import showToast from '@/utils/showToast'; +import Spinner from '../../ui/Spinner'; +import { RPCError, RPCErrorCode } from 'magic-sdk'; +import { LoginProps } from '@/utils/types'; +import { saveToken } from '@/utils/common'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; +import { useState } from 'react'; +import FormInput from '@/components/ui/FormInput'; -const EmailOTP = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [email, setEmail] = useState('') - const [emailError, setEmailError] = useState(false) - const [isLoginInProgress, setLoginInProgress] = useState(false) +const EmailOTP = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [email, setEmail] = useState(''); + const [emailError, setEmailError] = useState(false); + const [isLoginInProgress, setLoginInProgress] = useState(false); - const handleLogin = async () => { - if ( - !email.match( - /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/ - ) - ) { - setEmailError(true) - } else { - try { - setLoginInProgress(true) - setEmailError(false) - const account = await magic?.auth.loginWithEmailOTP({email}) - if (account) { - saveToken(account, setToken, 'EMAIL') - setEmail('') - } - } catch (e) { - console.log('login error: ' + JSON.stringify(e)) - if (e instanceof RPCError) { - switch (e.code) { - case RPCErrorCode.MagicLinkFailedVerification: - case RPCErrorCode.MagicLinkExpired: - case RPCErrorCode.MagicLinkRateLimited: - case RPCErrorCode.UserAlreadyLoggedIn: - showToast({message: e.message, type: 'error'}) - break - default: - showToast({ - message: - 'Something went wrong. Please try again', - type: 'error', - }) - } - } - } finally { - setLoginInProgress(false) - } - } - } + const handleLogin = async () => { + if (!email.match(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)) { + setEmailError(true); + } else { + try { + setLoginInProgress(true); + setEmailError(false); + const account = await magic?.auth.loginWithEmailOTP({ email }); + if (account) { + saveToken(account, setToken, 'EMAIL'); + setEmail(''); + } + } catch (e) { + console.log('login error: ' + JSON.stringify(e)); + if (e instanceof RPCError) { + switch (e.code) { + case RPCErrorCode.MagicLinkFailedVerification: + case RPCErrorCode.MagicLinkExpired: + case RPCErrorCode.MagicLinkRateLimited: + case RPCErrorCode.UserAlreadyLoggedIn: + showToast({ message: e.message, type: 'error' }); + break; + default: + showToast({ + message: 'Something went wrong. Please try again', + type: 'error', + }); + } + } + } finally { + setLoginInProgress(false); + } + } + }; - return ( - - Email OTP Login -
- { - if (emailError) setEmailError(false) - setEmail(e.target.value) - }} - placeholder={ - token.length > 0 ? 'Already logged in' : 'Email' - } - value={email} - /> - {emailError && ( - Enter a valid email - )} - -
-
- ) -} + return ( + + Email OTP Login +
+ { + if (emailError) setEmailError(false); + setEmail(e.target.value); + }} + placeholder={token.length > 0 ? 'Already logged in' : 'Email'} + value={email} + /> + {emailError && Enter a valid email} + +
+
+ ); +}; -export default EmailOTP +export default EmailOTP; diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx index 107761a..17bd3a1 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import facebook from 'public/social/Facebook.svg' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '../../ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import facebook from 'public/social/Facebook.svg'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; -const Facebook = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Facebook = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'facebook', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'facebook', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Facebook Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Google -
Facebook
-
-
- )} -
- ) -} -export default Facebook + return ( + + Facebook Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Facebook; diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Github.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Github.tsx index 431fd34..8004de7 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Github.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Github.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import github from 'public/social/Github.svg' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '../../ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import github from 'public/social/Github.svg'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; -const Github = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Github = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'github', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'github', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Github Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Google -
Github
-
-
- )} -
- ) -} -export default Github + return ( + + Github Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Github; diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Google.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Google.tsx index 29ab572..4dc8087 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Google.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Google.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import google from 'public/social/Google.svg' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '../../ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import google from 'public/social/Google.svg'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; -const Google = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Google = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'google', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'google', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Google Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Google -
Google
-
-
- )} -
- ) -} -export default Google + return ( + + Google Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Google; diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/LoginForm.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/LoginForm.tsx deleted file mode 100644 index 80a53f2..0000000 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/LoginForm.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import {LoginProps} from '@/utils/types' -import {useEffect, useMemo, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import {useRouter} from 'next/router' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' - -const setScriptAttributesAndAddScript = (src: string) => { - const script = document.createElement('script') - script.src = src - script.setAttribute( - 'data-magic-publishable-api-key', - process.env.NEXT_PUBLIC_MAGIC_API_KEY! - ) - script.setAttribute('data-redirect-uri', '/') - script.async = true - - document.body.appendChild(script) -} - -const LoginForm = ({token, setToken}: LoginProps) => { - const router = useRouter() - const [isLoginInProgress, setLoginInProgress] = useState(false) - - useMemo(async () => { - if (token.length == 0 && router.query) { - if (router.query.didt) { - await saveToken(router.query.didt as string, setToken, 'FORM') - router.replace('/', undefined, {shallow: true}) - } - if (router.query.magic_credential) { - await saveToken( - router.query.magic_credential as string, - setToken, - 'FORM' - ) - router.replace('/', undefined, {shallow: true}) - } - } - }, [router, setToken, token.length]) - - useEffect(() => { - if (token.length > 0 && !isLoginInProgress) { - setLoginInProgress(false) - } - }, [token, setLoginInProgress, isLoginInProgress]) - - const handleLogin = () => { - setLoginInProgress(true) - setScriptAttributesAndAddScript('https://auth.magic.link/pnp/login') - } - - return ( - - Login Form - - - Please wait a few seconds after clicking login as this button is - executing a magic script - - - ) -} - -export default LoginForm diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx index 239e4ac..2b3e474 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx @@ -1,90 +1,84 @@ -import {useState} from 'react' -import {useMagic} from '../MagicProvider' -import showToast from '@/utils/showToast' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import {RPCError, RPCErrorCode} from 'magic-sdk' -import {LoginProps} from '@/utils/types' -import {saveToken} from '@/utils/common' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' -import FormInput from '@/components/ui/FormInput' +import { useState } from 'react'; +import { useMagic } from '../MagicProvider'; +import showToast from '@/utils/showToast'; +import Spinner from '../../ui/Spinner'; +import { RPCError, RPCErrorCode } from 'magic-sdk'; +import { LoginProps } from '@/utils/types'; +import { saveToken } from '@/utils/common'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; +import FormInput from '@/components/ui/FormInput'; -const SMSOTP = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [phone, setPhone] = useState('') - const [phoneError, setPhoneError] = useState(false) - const [isLoginInProgress, setLoginInProgress] = useState(false) +const SMSOTP = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [phone, setPhone] = useState(''); + const [phoneError, setPhoneError] = useState(false); + const [isLoginInProgress, setLoginInProgress] = useState(false); - const handleLogin = async () => { - if (!phone.match(/^\+?\d{10,14}$/)) { - setPhoneError(true) - } else { - try { - setLoginInProgress(true) - setPhoneError(false) - const account = await magic?.auth.loginWithSMS({ - phoneNumber: phone, - }) - if (account) { - saveToken(account, setToken, 'SMS') - setPhone('') - } - } catch (e) { - console.log('login error: ' + JSON.stringify(e)) - if (e instanceof RPCError) { - switch (e.code) { - case RPCErrorCode.MagicLinkFailedVerification: - case RPCErrorCode.MagicLinkExpired: - case RPCErrorCode.MagicLinkRateLimited: - case RPCErrorCode.UserAlreadyLoggedIn: - showToast({message: e.message, type: 'error'}) - break - default: - showToast({ - message: - 'Something went wrong. Please try again', - type: 'error', - }) - } - } - } finally { - setLoginInProgress(false) - } - } - } + const handleLogin = async () => { + if (!phone.match(/^\+?\d{10,14}$/)) { + setPhoneError(true); + } else { + try { + setLoginInProgress(true); + setPhoneError(false); + const account = await magic?.auth.loginWithSMS({ + phoneNumber: phone, + }); + if (account) { + saveToken(account, setToken, 'SMS'); + setPhone(''); + } + } catch (e) { + console.log('login error: ' + JSON.stringify(e)); + if (e instanceof RPCError) { + switch (e.code) { + case RPCErrorCode.MagicLinkFailedVerification: + case RPCErrorCode.MagicLinkExpired: + case RPCErrorCode.MagicLinkRateLimited: + case RPCErrorCode.UserAlreadyLoggedIn: + showToast({ message: e.message, type: 'error' }); + break; + default: + showToast({ + message: 'Something went wrong. Please try again', + type: 'error', + }); + } + } + } finally { + setLoginInProgress(false); + } + } + }; - return ( - - SMS Login -
- { - if (phoneError) setPhoneError(false) - setPhone(e.target.value) - }} - placeholder={ - token.length > 0 ? 'Already logged in' : '+11234567890' - } - value={phone} - /> - {phoneError && ( - - Enter a valid phone number - - )} - -
-
- ) -} + return ( + + SMS Login +
+ { + if (phoneError) setPhoneError(false); + setPhone(e.target.value); + }} + placeholder={token.length > 0 ? 'Already logged in' : '+11234567890'} + value={phone} + /> + {phoneError && ( + + Enter a valid phone number + + )} + +
+
+ ); +}; -export default SMSOTP +export default SMSOTP; diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx index 3f03e01..8986ba7 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import twitch from 'public/social/Twitch.svg' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '../../ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import twitch from 'public/social/Twitch.svg'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; -const Twitch = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Twitch = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'twitch', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'twitch', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Twitch Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Twitch -
Twitch
-
-
- )} -
- ) -} -export default Twitch + return ( + + Twitch Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Twitch; diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx index d60db9e..f90a7a2 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import twitter from 'public/social/Twitter.svg' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '../../ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import twitter from 'public/social/Twitter.svg'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; -const Twitter = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Twitter = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'twitter', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'twitter', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Twitter Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Twitter -
Twitter
-
-
- )} -
- ) -} -export default Twitter + return ( + + Twitter Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Twitter; diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/src/styles/globals.css b/scaffolds/nextjs-flow-dedicated-wallet/template/src/styles/globals.css index aba4039..7222af2 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/src/styles/globals.css +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/src/styles/globals.css @@ -5,301 +5,321 @@ @tailwind utilities; :root { - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 214, 219, 220; + --background-end-rgb: 255, 255, 255; } @media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; - } + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + } } html, body { - @apply m-0 p-0 bg-[#f8f8fa] scroll-pt-12; - font-family: 'Inter', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + @apply m-0 p-0 bg-[#f8f8fa] scroll-pt-12; + font-family: 'Inter', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } nav > ul > li { - @apply text-left list-none text-[#777679] cursor-pointer mb-[15px]; + @apply text-left list-none text-[#777679] cursor-pointer mb-[15px]; } ul { - @apply w-fit m-0 pl-[30px] pr-0 py-0; + @apply w-fit m-0 pl-[30px] pr-0 py-0; } .active { - @apply text-[#6851ff] font-semibold; + @apply text-[#6851ff] font-semibold; } .active::before { - @apply content-['\2022'] text-[#6851ff] font-[bold] inline-block w-[1em] ml-[-1em]; + @apply content-['\2022'] text-[#6851ff] font-[bold] inline-block w-[1em] ml-[-1em]; } .nft { - @apply text-[#777679]; + @apply text-[#777679]; } .nft-name { - @apply text-black font-semibold; - font-family: 'Inter'; + @apply font-semibold text-black; + font-family: 'Inter'; } .nft-list { - @apply overflow-auto max-h-[270px]; + @apply overflow-auto max-h-[270px]; } .nft:not(:last-child) { - @apply mb-2.5; + @apply mb-2.5; } .cards-container { - @apply mt-[-250px] relative; + @apply relative top-[30px] md:top-[-60px] lg:top-[-60px]; } @media only screen and (max-width: 767px) { - .cards-container { - @apply mt-[-89px]; - } + .cards-container { + @apply mt-[-89px]; + } } .network-dropdown { - @apply w-fit m-auto rounded-xl; + @apply m-auto w-fit rounded-xl; } .active-network { - @apply border w-[264px] flex items-center cursor-pointer justify-between m-auto px-4 py-3 rounded-xl border-solid border-[#dddbe0] bg-[#fff]; + @apply border w-[264px] flex items-center cursor-pointer justify-between m-auto px-4 py-3 rounded-xl border-solid border-[#dddbe0] bg-[#fff]; } .active-network::selection { - @apply bg-transparent; + @apply bg-transparent; } .rotate { - @apply rotate-180; + @apply rotate-180; } .network-options { - @apply overflow-hidden w-fit border mx-auto my-[5px] px-0 py-[5px] rounded-xl border-solid border-[#dddbe0] bg-[#fff]; + @apply overflow-hidden w-fit border mx-auto my-[5px] px-0 py-[5px] rounded-xl border-solid border-[#dddbe0] bg-[#fff]; } .network-dropdown-option { - @apply w-[264px] flex items-center justify-start transition-[0.1s] m-auto px-4 py-3 bg-[#fff]; + @apply w-[264px] flex items-center justify-start transition-[0.1s] m-auto px-4 py-3 bg-[#fff]; } .network-dropdown-option:hover { - @apply text-white cursor-pointer bg-[#6851ff]; + @apply text-white cursor-pointer bg-[#6851ff]; } .network-dropdown-option:active { - @apply opacity-50; + @apply opacity-50; } .magic-logo { - @apply mt-10 mb-[15px] mx-0 text-center; + @apply mb-[15px] mx-0 text-center; } .demo-sub-header { - @apply text-[rgba(255,255,255,0.5)] text-xl font-normal m-0; - font-family: monospace; + @apply text-[rgba(255,255,255,0.5)] text-xl font-normal m-0; + font-family: monospace; } .home-page { - @apply flex flex-col justify-center items-center min-h-screen relative; + @apply flex flex-col justify-center items-center min-h-screen relative bg-[length:100vw_320px] bg-no-repeat bg-[url('/main.svg')]; } .login-page { - @apply flex flex-col items-center min-h-screen bg-gray-300; + @apply flex flex-col items-center min-h-screen bg-gray-300; } .login-method-grid { - @apply w-[100%] grid grid-cols-4 gap-5 p-4; + @apply max-w-[100%] grid-rows-3 gap-5 p-4 mt-8; } .login-method-grid-item-container { - @apply flex flex-col items-center justify-center; + @apply flex flex-col items-center justify-center; } .login-button { - @apply w-full h-12 text-white font-semibold text-base leading-6 transition-[0.1s] text-center transition-[0.1s] m-auto px-2 py-3 rounded-[300px] border-[none]; - background: #a799ff; + @apply w-full h-12 text-white font-semibold text-base leading-6 transition-[0.1s] text-center transition-[0.1s] m-auto px-2 py-3 rounded-[300px] border-[none]; + background: #8271f3; } .login-button:disabled { - background: #a799ff; + background: #a799ff; } .login-button:hover:enabled { - @apply cursor-pointer; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), - #a799ff; + @apply cursor-pointer; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #a799ff; } .login-button:active:enabled { - @apply opacity-50 cursor-pointer scale-[0.99]; - background: #a799ff; + @apply opacity-50 cursor-pointer scale-[0.99]; + background: #a799ff; } .links { - @apply flex justify-center text-white font-semibold mt-5 mb-3 mx-auto; + @apply flex justify-center mx-auto mt-5 text-sm mb-3 font-semibold text-white; } .link { - @apply transition-[0.1s] px-[30px] py-0; + @apply transition-[0.1s] px-[30px] py-0; } @media only screen and (max-width: 420px) { - .link { - @apply px-[15px] py-0; - } + .link { + @apply px-[15px] py-0; + } } @media only screen and (max-width: 320px) { - .link { - @apply px-[5px] py-0; - } + .link { + @apply px-[5px] py-0; + } } .link > a { - @apply cursor-pointer; + @apply cursor-pointer; } .link-divider { - @apply h-5 w-px; + @apply w-px h-5; } .footer-links { - @apply flex items-center absolute w-full mt-[30px] mb-0 mx-auto bottom-10; + @apply flex items-center absolute w-full mt-[30px] mb-0 mx-auto bottom-10; } .wallet-method-container { - @apply text-left; + @apply text-left; } .wallet-method { - @apply w-fit text-[#522fd4] bg-[#edebff] text-base cursor-pointer font-medium transition-[0.1s] h-8 px-3 py-1.5 rounded-[32px] border-[none]; - font-family: monospace; + @apply w-fit text-[#522fd4] bg-[#edebff] text-base cursor-pointer font-medium transition-[0.1s] h-8 px-3 py-1.5 rounded-[32px] border-[none]; + font-family: monospace; } .wallet-method:hover:enabled { - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), - #edebff; - background-blend-mode: color-burn, normal; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; + background-blend-mode: color-burn, normal; } .wallet-method:active:enabled { - @apply opacity-50 scale-[0.99]; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), - #edebff; + @apply opacity-50 scale-[0.99]; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; } .wallet-method-desc { - @apply text-[#77767a] text-left text-sm mt-2.5; + @apply text-[#77767a] text-left text-sm mt-2.5; } .form-input { - @apply box-border flex flex-row items-center w-full h-12 border text-base leading-6 text-[#18171a] mb-[15px] px-4 py-3 rounded-[10px] border-solid border-[#dddbe0]; - background: #ffffff; + @apply box-border flex flex-row items-center w-full h-12 border text-base leading-6 text-[#18171a] mb-[15px] px-4 py-3 rounded-[10px] border-solid border-[#dddbe0]; + background: #ffffff; } .form-input::placeholder { - color: #77767a; + color: #77767a; } .form-button { - @apply flex flex-row justify-center items-center w-full h-12 text-[#522fd4] font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none] bg-[#edebff]; + @apply flex flex-row justify-center items-center w-full h-12 text-[#522fd4] font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none] bg-[#edebff]; } .form-button:disabled { - @apply opacity-50; + @apply opacity-50; } .form-button:hover:enabled { - @apply cursor-pointer; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), - #edebff; + @apply cursor-pointer; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; } .form-button:active:enabled { - @apply opacity-50 scale-[0.99]; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), - #edebff; + @apply opacity-50 scale-[0.99]; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; } .loading-container { - @apply w-[50px] text-center flex items-center justify-center cursor-default; + @apply w-[50px] text-center flex items-center justify-center cursor-default; } .loading { - @apply animate-spin cursor-default; + @apply cursor-default animate-spin; } @keyframes rotation { - 0% { - transform: rotate(0); - } - 100% { - transform: rotate(360deg); - } + 0% { + transform: rotate(0); + } + 100% { + transform: rotate(360deg); + } } .card { - @apply w-[300px] flex flex-col shadow-[0px_4px_24px_rgba(49,49,49,0.1)] mt-0 mb-[27px] mx-auto px-6 py-8 rounded-2xl bg-[#ffffff]; + @apply w-[344px] flex flex-col shadow-[0px_4px_24px_rgba(49,49,49,0.1)] mt-0 mb-[27px] mx-auto px-6 py-8 rounded-2xl bg-[#ffffff]; } .card-header { - @apply text-xl font-semibold text-left mt-0 mb-[25px]; + @apply text-xl font-semibold text-left mt-0 mb-[25px]; } .card-label-container { - @apply flex justify-between items-center mb-3; + @apply flex items-center justify-between mb-3; } .card-label { - @apply text-sm font-medium cursor-pointer; + @apply text-sm font-medium cursor-pointer; } .toast { - @apply fixed w-fit text-white font-medium shadow-[4px_8px_20px_rgba(0,0,0,0.15)] mx-auto my-0 px-4 py-2 rounded-[10px] top-[30px] inset-x-0 bg-[#00875f]; + @apply fixed w-fit text-white font-medium shadow-[4px_8px_20px_rgba(0,0,0,0.15)] mx-auto my-0 px-4 py-2 rounded-[10px] top-[30px] inset-x-0 bg-[#00875f]; } .action-button { - @apply font-semibold text-[#6851ff] cursor-pointer transition-[0.1s]; + @apply font-semibold text-[#6851ff] cursor-pointer transition-[0.1s]; } .disconnect-button { - @apply font-semibold text-[#d43100] cursor-pointer transition-[0.1s]; + @apply font-semibold text-[#d43100] cursor-pointer transition-[0.1s]; } .action-button:hover, .disconnect-button:hover { - @apply opacity-70; + @apply opacity-70; } .action-button:active, .disconnect-button:active { - @apply scale-[0.98]; + @apply scale-[0.98]; } .code { - @apply text-base text-left p-2.5 rounded-[10px]; - font-family: monospace; - background: #f8f8fa; - word-wrap: break-word; + @apply text-base text-left p-2.5 rounded-[10px]; + font-family: monospace; + background: #f8f8fa; + word-wrap: break-word; } .error { - @apply self-start text-xs font-semibold text-red-700 justify-self-start; + @apply self-start text-xs font-semibold text-red-700 justify-self-start; } .divider { - @apply mx-0 my-[15px] border-b-[#ededf3] border-b border-solid; + @apply mx-0 my-[15px] border-b-[#ededf3] border-b border-solid; } .flex-row { - @apply flex items-center; + @apply flex items-center; } .green-dot { - @apply h-1.5 w-1.5 bg-[#00cc8f] mr-2.5 rounded-[50%]; + @apply h-1.5 w-1.5 bg-[#00cc8f] mr-2.5 rounded-[50%]; } .connected { - @apply text-base mx-0 my-[5px]; + @apply text-base mx-0 my-[5px]; } a { - all: unset; + all: unset; } .app-header-container { - @apply block w-full drop-shadow-[0_35px_35px_rgba(0,0,0,0.25)] min-h-[30vh] flex flex-col items-center bg-magic block; - text-align: -webkit-center; + @apply block w-full drop-shadow-[0_35px_35px_rgba(0,0,0,0.25)] min-h-[40%] flex-col gap-2.5 p-8 items-center bg-[url('/login_bg.png')] bg-cover bg-no-repeat pb-20; + text-align: -webkit-center; } .redirect-container { - @apply flex flex-col items-center min-h-screen bg-[length:100%_auto] bg-[url('/background.svg')]; + @apply flex flex-col items-center h-screen bg-center bg-cover bg-no-repeat bg-[url('/redirect_bg.png')]; +} + +.redirect-card { + @apply bg-[#F8F8FA] rounded-[10px] shadow-[0px_4px_24px_rgba(49,49,49,0.1)] p-2 m-12; +} + +.social-login-button { + @apply flex flex-row min-w-[296px] h-12 text-[#3C4043] transition-[0.1s] px-6 py-3 rounded-[300px] bg-[#ffffff] border-2 border-[#DADCE0] relative top-16; +} + +.social-login-button:disabled { + @apply opacity-50; +} + +.social-login-button:hover:enabled { + @apply cursor-pointer; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #ffffff; +} +.social-login-button:active:enabled { + @apply opacity-50 scale-[0.99]; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #ffffff; +} + +.api-button { + @apply bg-[#6844bc] text-[#FFFFFF] flex w-[280px] justify-center items-center h-12 font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none]; } diff --git a/scaffolds/nextjs-flow-dedicated-wallet/template/tailwind.config.js b/scaffolds/nextjs-flow-dedicated-wallet/template/tailwind.config.js index 1da1a7e..0fc0404 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/template/tailwind.config.js +++ b/scaffolds/nextjs-flow-dedicated-wallet/template/tailwind.config.js @@ -1,19 +1,17 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: [ - './src/pages/**/*.{js,ts,jsx,tsx,mdx}', - './src/components/**/*.{js,ts,jsx,tsx,mdx}', - './src/app/**/*.{js,ts,jsx,tsx,mdx}', - ], - theme: { - extend: { - backgroundImage: { - magic: "url('../../public//background.svg')", - 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', - 'gradient-conic': - 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', - }, - }, - }, - plugins: [], -} + content: [ + './src/pages/**/*.{js,ts,jsx,tsx,mdx}', + './src/components/**/*.{js,ts,jsx,tsx,mdx}', + './src/app/**/*.{js,ts,jsx,tsx,mdx}', + ], + theme: { + extend: { + backgroundImage: { + 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', + 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', + }, + }, + }, + plugins: [], +}; diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/info.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/info.svg new file mode 100644 index 0000000..df6edb9 --- /dev/null +++ b/scaffolds/nextjs-flow-universal-wallet/template/public/info.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/link_white.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/link_white.svg new file mode 100644 index 0000000..c87852b --- /dev/null +++ b/scaffolds/nextjs-flow-universal-wallet/template/public/link_white.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/login_bg.png b/scaffolds/nextjs-flow-universal-wallet/template/public/login_bg.png new file mode 100644 index 0000000..a4021c4 Binary files /dev/null and b/scaffolds/nextjs-flow-universal-wallet/template/public/login_bg.png differ diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/logo.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/logo.svg new file mode 100644 index 0000000..e13da68 --- /dev/null +++ b/scaffolds/nextjs-flow-universal-wallet/template/public/logo.svg @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/redirect_bg.png b/scaffolds/nextjs-flow-universal-wallet/template/public/redirect_bg.png new file mode 100644 index 0000000..aa322ee Binary files /dev/null and b/scaffolds/nextjs-flow-universal-wallet/template/public/redirect_bg.png differ diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Links.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/DevLinks.tsx similarity index 100% rename from scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Links.tsx rename to scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/DevLinks.tsx diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Home.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Home.tsx index 15cfe85..a1d58de 100644 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Home.tsx +++ b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Home.tsx @@ -1,32 +1,32 @@ -import React from 'react' -import TableOfContents from '../ui/TableOfContents' -import AppHeader from '../ui/AppHeader' -import Wallet from './cards/UserInfoCard' -import WalletMethods from './cards/WalletMethodsCard' -import SendTransaction from './cards/SendTransactionsCard' -import Links from './Links' -import Spacer from '../ui/Spacer' +import React from 'react'; +import TableOfContents from '../ui/TableOfContents'; +import AppHeader from '../ui/AppHeader'; +import Wallet from './cards/UserInfoCard'; +import WalletMethods from './cards/WalletMethodsCard'; +import SendTransaction from './cards/SendTransactionsCard'; +import Links from './DevLinks'; +import Spacer from '../ui/Spacer'; interface Props { - setAccount: React.Dispatch> + setAccount: React.Dispatch>; } -export default function Home({setAccount}: Props) { - return ( -
- - - - - -
- - - - - - -
-
- ) +export default function Home({ setAccount }: Props) { + return ( +
+ + + + + +
+ + + + + + +
+
+ ); } diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Login.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Login.tsx index 5c66b6d..0055c1b 100644 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Login.tsx +++ b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Login.tsx @@ -1,42 +1,42 @@ -import React, {useState, useCallback} from 'react' -import AppHeader from '../ui/AppHeader' -import Links from './Links' -import ConnectButton from '../ui/ConnectButton' -import Spacer from '../ui/Spacer' -import {useMagicContext} from '@/components/magic/MagicProvider' +import React, { useState, useCallback } from 'react'; +import AppHeader from '../ui/AppHeader'; +import Links from './DevLinks'; +import ConnectButton from '../ui/ConnectButton'; +import Spacer from '../ui/Spacer'; +import { useMagicContext } from '@/components/magic/MagicProvider'; interface Props { - setAccount: React.Dispatch> + setAccount: React.Dispatch>; } -const Login = ({setAccount}: Props) => { - const [disabled, setDisabled] = useState(false) - const {magic} = useMagicContext() +const Login = ({ setAccount }: Props) => { + const [disabled, setDisabled] = useState(false); + const { magic } = useMagicContext(); - const connect = useCallback(async () => { - if (!magic) return - try { - setDisabled(true) - const account = await magic.flow.getAccount() - setDisabled(false) - console.log('Logged in user:', account) - localStorage.setItem('user', account) - setAccount(account) - } catch (error) { - setDisabled(false) - console.error(error) - } - }, [magic, setAccount]) + const connect = useCallback(async () => { + if (!magic) return; + try { + setDisabled(true); + const account = await magic.flow.getAccount(); + setDisabled(false); + console.log('Logged in user:', account); + localStorage.setItem('user', account); + setAccount(account); + } catch (error) { + setDisabled(false); + console.error(error); + } + }, [magic, setAccount]); - return ( -
- - - - - -
- ) -} + return ( +
+ + + + + +
+ ); +}; -export default Login +export default Login; diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx index 97aeede..2478f09 100644 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx +++ b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx @@ -1,34 +1,43 @@ -import React, {useCallback} from 'react' -import AppHeader from '../ui/AppHeader' -import Links from './Links' -import Spacer from '../ui/Spacer' +import React, { useCallback } from 'react'; +import Image from 'next/image'; +import Info from 'public/info.svg'; +import Link from 'public/link_white.svg'; +import Logo from 'public/logo.svg'; +import DevLinks from './DevLinks'; const MagicDashboardRedirect = () => { - const onClick = useCallback(() => { - window.open('https://dashboard.magic.link/signup', '_blank') - }, []) + const onClick = useCallback(() => { + window.open('https://dashboard.magic.link/signup', '_blank'); + }, []); - return ( -
- - - -
-

- Please set your NEXT_PUBLIC_MAGIC_API_KEY{' '} - environment variable in .env. You can get your - Magic API key from the Magic Dashboard. -

-
- -
- -
- -
- ) -} + return ( +
+
+ logo +
Magic
+
+ Demo +
+
+
+
+
+ logo +

+ Please set your NEXT_PUBLIC_MAGIC_API_KEY environment variable in .env. You can + get your Magic API key from the Magic Dashboard. +

+
+
-export default MagicDashboardRedirect + +
+ +
+ ); +}; + +export default MagicDashboardRedirect; diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/styles/globals.css b/scaffolds/nextjs-flow-universal-wallet/template/src/styles/globals.css index f78df5d..aed673d 100644 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/styles/globals.css +++ b/scaffolds/nextjs-flow-universal-wallet/template/src/styles/globals.css @@ -5,282 +5,285 @@ html, body { - @apply m-0 p-0 bg-[#f8f8fa] scroll-pt-12; - font-family: 'Inter', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + @apply m-0 p-0 bg-[#f8f8fa] scroll-pt-12; + font-family: 'Inter', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } .table-of-contents { - @apply w-[220px] min-w-[220px] self-start sticky max-h-[calc(100vh_-_70px)] overflow-auto mt-0 px-0 py-6 top-0; - position: -webkit-sticky; + @apply w-[220px] min-w-[220px] self-start sticky max-h-[calc(100vh_-_70px)] overflow-auto mt-0 px-0 py-6 top-0; + position: -webkit-sticky; } nav > ul > li { - @apply text-left list-none text-[#777679] cursor-pointer mb-[15px]; + @apply text-left list-none text-[#777679] cursor-pointer mb-[15px]; } ul { - @apply w-fit m-0 pl-[30px] pr-0 py-0; + @apply w-fit m-0 pl-[30px] pr-0 py-0; } .active { - @apply text-[#6851ff] font-semibold; + @apply text-[#6851ff] font-semibold; } .active::before { - @apply content-['\2022'] text-[#6851ff] font-[bold] inline-block w-[1em] ml-[-1em]; + @apply content-['\2022'] text-[#6851ff] font-[bold] inline-block w-[1em] ml-[-1em]; } .nft { - @apply text-[#777679]; + @apply text-[#777679]; } .nft-name { - @apply text-black font-semibold; - font-family: 'Inter'; + @apply text-black font-semibold; + font-family: 'Inter'; } .nft-list { - @apply overflow-auto max-h-[270px]; + @apply overflow-auto max-h-[270px]; } .nft:not(:last-child) { - @apply mb-2.5; + @apply mb-2.5; } .cards-container { - @apply mt-[-260px]; + @apply mt-[-260px]; } @media only screen and (max-width: 767px) { - .table-of-contents { - @apply hidden; - } - .cards-container { - @apply mt-[-89px]; - } + .table-of-contents { + @apply hidden; + } + .cards-container { + @apply mt-[-89px]; + } } .network-dropdown { - @apply w-fit m-auto rounded-xl; + @apply w-fit m-auto rounded-xl; } .active-network { - @apply border w-[264px] flex items-center cursor-pointer justify-between m-auto px-4 py-3 rounded-xl border-solid border-[#dddbe0] bg-[#fff]; + @apply border w-[264px] flex items-center cursor-pointer justify-between m-auto px-4 py-3 rounded-xl border-solid border-[#dddbe0] bg-[#fff]; } .active-network::selection { - @apply bg-transparent; + @apply bg-transparent; } .rotate { - @apply rotate-180; + @apply rotate-180; } .network-options { - @apply overflow-hidden w-fit border mx-auto my-[5px] px-0 py-[5px] rounded-xl border-solid border-[#dddbe0] bg-[#fff]; + @apply overflow-hidden w-fit border mx-auto my-[5px] px-0 py-[5px] rounded-xl border-solid border-[#dddbe0] bg-[#fff]; } .network-dropdown-option { - @apply w-[264px] flex items-center justify-start transition-[0.1s] m-auto px-4 py-3 bg-[#fff]; + @apply w-[264px] flex items-center justify-start transition-[0.1s] m-auto px-4 py-3 bg-[#fff]; } .network-dropdown-option:hover { - @apply text-white cursor-pointer bg-[#6851ff]; + @apply text-white cursor-pointer bg-[#6851ff]; } .network-dropdown-option:active { - @apply opacity-50; + @apply opacity-50; } .magic-logo { - @apply mb-[15px] mx-0 text-center; + @apply mb-[15px] mx-0 text-center; } .demo-sub-header { - @apply text-[rgba(255,255,255,0.5)] text-xl font-normal m-0; - font-family: monospace; + @apply text-[rgba(255,255,255,0.5)] text-xl font-normal m-0; + font-family: monospace; } .home-page { - @apply flex flex-col justify-center items-center min-h-screen relative bg-[length:100vw_320px] bg-no-repeat bg-[url('/main.svg')]; + @apply flex flex-col justify-center items-center min-h-screen relative bg-[length:100vw_320px] bg-no-repeat bg-[url('/main.svg')]; } .login-page { - @apply min-h-screen bg-[length:100%_auto] bg-[url('/login.svg')]; + @apply min-h-screen bg-[length:100%_auto] bg-[url('/login.svg')]; } .connect-button { - @apply w-[296px] h-12 text-white font-semibold text-base leading-6 transition-[0.1s] text-center transition-[0.1s] m-auto px-6 py-3 rounded-[300px] border-[none]; - background: rgba(255, 255, 255, 0.1); + @apply w-[296px] h-12 text-white font-semibold text-base leading-6 transition-[0.1s] text-center transition-[0.1s] m-auto px-6 py-3 rounded-[300px] border-[none]; + background: rgba(255, 255, 255, 0.1); } .connect-button:hover:enabled { - @apply cursor-pointer; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), - rgba(255, 255, 255, 0.1); + @apply cursor-pointer; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), rgba(255, 255, 255, 0.1); } .connect-button:active:enabled { - @apply opacity-50 cursor-pointer scale-[0.99]; - background: rgba(255, 255, 255, 0.1); + @apply opacity-50 cursor-pointer scale-[0.99]; + background: rgba(255, 255, 255, 0.1); } .links { - @apply flex justify-center text-white font-semibold mt-5 mb-3 mx-auto; + @apply flex justify-center text-white font-semibold mt-5 mb-3 mx-auto; } .link { - @apply transition-[0.1s] px-[30px] py-0; + @apply transition-[0.1s] px-[30px] py-0; } @media only screen and (max-width: 420px) { - .link { - @apply px-[15px] py-0; - } + .link { + @apply px-[15px] py-0; + } } @media only screen and (max-width: 320px) { - .link { - @apply px-[5px] py-0; - } + .link { + @apply px-[5px] py-0; + } } .link > a { - @apply cursor-pointer; + @apply cursor-pointer; } .link-divider { - @apply h-5 w-px; + @apply h-5 w-px; } .footer-links { - @apply flex items-center absolute w-full mt-[30px] mb-0 mx-auto bottom-10; + @apply flex items-center absolute w-full mt-[30px] mb-0 mx-auto bottom-10; } .wallet-method-container { - @apply text-left; + @apply text-left; } .wallet-method { - @apply w-fit text-[#522fd4] bg-[#edebff] text-base cursor-pointer font-medium transition-[0.1s] h-8 px-3 py-1.5 rounded-[32px] border-[none]; - font-family: monospace; + @apply w-fit text-[#522fd4] bg-[#edebff] text-base cursor-pointer font-medium transition-[0.1s] h-8 px-3 py-1.5 rounded-[32px] border-[none]; + font-family: monospace; } .wallet-method:hover:enabled { - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), - #edebff; - background-blend-mode: color-burn, normal; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; + background-blend-mode: color-burn, normal; } .wallet-method:active:enabled { - @apply opacity-50 scale-[0.99]; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), - #edebff; + @apply opacity-50 scale-[0.99]; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; } .wallet-method-desc { - @apply text-[#77767a] text-left text-sm mt-2.5; + @apply text-[#77767a] text-left text-sm mt-2.5; } .form-input { - @apply box-border flex flex-row items-center w-full h-12 border text-base leading-6 text-[#18171a] mb-[15px] px-4 py-3 rounded-[10px] border-solid border-[#dddbe0]; - background: #ffffff; + @apply box-border flex flex-row items-center w-full h-12 border text-base leading-6 text-[#18171a] mb-[15px] px-4 py-3 rounded-[10px] border-solid border-[#dddbe0]; + background: #ffffff; } .form-input::placeholder { - color: #77767a; + color: #77767a; } .form-button { - @apply flex flex-row justify-center items-center w-full h-12 text-[#522fd4] font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none] bg-[#edebff]; + @apply flex flex-row justify-center items-center w-full h-12 text-[#522fd4] font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none] bg-[#edebff]; } .form-button:disabled { - @apply opacity-50; + @apply opacity-50; } .form-button:hover:enabled { - @apply cursor-pointer; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), - #edebff; + @apply cursor-pointer; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; } .form-button:active:enabled { - @apply opacity-50 scale-[0.99]; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), - #edebff; + @apply opacity-50 scale-[0.99]; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; } .loading-container { - @apply w-[50px] text-center flex items-center justify-center cursor-default; + @apply w-[50px] text-center flex items-center justify-center cursor-default; } .loading { - @apply animate-spin cursor-default; + @apply animate-spin cursor-default; } @keyframes rotation { - 0% { - transform: rotate(0); - } - 100% { - transform: rotate(360deg); - } + 0% { + transform: rotate(0); + } + 100% { + transform: rotate(360deg); + } } .card { - @apply w-[300px] flex flex-col shadow-[0px_4px_24px_rgba(49,49,49,0.1)] mt-0 mb-[27px] mx-auto px-6 py-8 rounded-2xl bg-[#ffffff]; + @apply w-[300px] flex flex-col shadow-[0px_4px_24px_rgba(49,49,49,0.1)] mt-0 mb-[27px] mx-auto px-6 py-8 rounded-2xl bg-[#ffffff]; } .card-header { - @apply text-xl font-semibold text-left mt-0 mb-[25px]; + @apply text-xl font-semibold text-left mt-0 mb-[25px]; } .card-label-container { - @apply flex justify-between items-center mb-3; + @apply flex justify-between items-center mb-3; } .card-label { - @apply text-sm font-medium cursor-pointer; + @apply text-sm font-medium cursor-pointer; } .toast { - @apply fixed w-fit text-white font-medium shadow-[4px_8px_20px_rgba(0,0,0,0.15)] mx-auto my-0 px-4 py-2 rounded-[10px] top-[30px] inset-x-0 bg-[#00875f]; + @apply fixed w-fit text-white font-medium shadow-[4px_8px_20px_rgba(0,0,0,0.15)] mx-auto my-0 px-4 py-2 rounded-[10px] top-[30px] inset-x-0 bg-[#00875f]; } .action-button { - @apply font-semibold text-[#6851ff] cursor-pointer transition-[0.1s]; + @apply font-semibold text-[#6851ff] cursor-pointer transition-[0.1s]; } .disconnect-button { - @apply font-semibold text-[#d43100] cursor-pointer transition-[0.1s]; + @apply font-semibold text-[#d43100] cursor-pointer transition-[0.1s]; } .action-button:hover, .disconnect-button:hover { - @apply opacity-70; + @apply opacity-70; } .action-button:active, .disconnect-button:active { - @apply scale-[0.98]; + @apply scale-[0.98]; } .code { - @apply text-base text-left p-2.5 rounded-[10px]; - font-family: monospace; - background: #f8f8fa; - word-wrap: break-word; + @apply text-base text-left p-2.5 rounded-[10px]; + font-family: monospace; + background: #f8f8fa; + word-wrap: break-word; } .error { - @apply text-[#d43100] text-xs text-left -mt-2.5 mb-2.5 mx-0; + @apply text-[#d43100] text-xs text-left -mt-2.5 mb-2.5 mx-0; } .divider { - @apply mx-0 my-[15px] border-b-[#ededf3] border-b border-solid; + @apply mx-0 my-[15px] border-b-[#ededf3] border-b border-solid; } .flex-row { - @apply flex items-center; + @apply flex items-center; } .green-dot { - @apply h-1.5 w-1.5 bg-[#00cc8f] mr-2.5 rounded-[50%]; + @apply h-1.5 w-1.5 bg-[#00cc8f] mr-2.5 rounded-[50%]; } .connected { - @apply text-base mx-0 my-[5px]; + @apply text-base mx-0 my-[5px]; } a { - all: unset; + all: unset; } .app-header-container { - @apply block pt-4; - text-align: -webkit-center; + @apply block pt-4; + text-align: -webkit-center; } .redirect-container { - @apply flex flex-col items-center min-h-screen bg-['100%_auto'] bg-[url('/login.svg')]; + @apply flex flex-col items-center min-h-screen bg-['100%_auto'] bg-[url('/login.svg')]; +} + +.redirect-card { + @apply bg-[#F8F8FA] rounded-[10px] shadow-[0px_4px_24px_rgba(49,49,49,0.1)] p-2 m-12; +} + +.api-button { + @apply bg-[#6844bc] text-[#FFFFFF] flex w-[280px] justify-center items-center h-12 font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none]; } diff --git a/scaffolds/nextjs-solana-dedicated-wallet/scaffold.tsx b/scaffolds/nextjs-solana-dedicated-wallet/scaffold.tsx index 8df6050..aa54317 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/scaffold.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/scaffold.tsx @@ -1,6 +1,6 @@ import { Flags } from 'core/flags'; import BaseScaffold from 'core/types/BaseScaffold'; -import { AuthTypePrompt, BlockchainNetworkPrompt, NpmClientPrompt, PublishableApiKeyPrompt } from 'scaffolds/prompts'; +import { AuthTypePrompt, NpmClientPrompt, PublishableApiKeyPrompt } from 'scaffolds/prompts'; export type Data = NpmClientPrompt.Data & PublishableApiKeyPrompt.Data & AuthTypePrompt.Data; @@ -21,10 +21,13 @@ export default class SolanaDedicatedScaffold extends BaseScaffold { public installationCommand: string[] = ['npm', 'install']; public startCommand: string[] = ['npm', 'run', 'dev']; public source: string | string[] = [ - './public/background.svg', './public/favicon.ico', - './public/magic_color_white.svg', + './public/logo.svg', + './public/info.svg', './public/link.svg', + './public/link_white.svg', + './public/redirect_bg.png', + './public/login_bg.png', './.env.example', './.eslintrc.json', './.gitignore', diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/public/background.svg b/scaffolds/nextjs-solana-dedicated-wallet/template/public/background.svg deleted file mode 100644 index c611daa..0000000 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/public/background.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/public/info.svg b/scaffolds/nextjs-solana-dedicated-wallet/template/public/info.svg new file mode 100644 index 0000000..df6edb9 --- /dev/null +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/public/info.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/public/link_white.svg b/scaffolds/nextjs-solana-dedicated-wallet/template/public/link_white.svg new file mode 100644 index 0000000..c87852b --- /dev/null +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/public/link_white.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/public/login_bg.png b/scaffolds/nextjs-solana-dedicated-wallet/template/public/login_bg.png new file mode 100644 index 0000000..a4021c4 Binary files /dev/null and b/scaffolds/nextjs-solana-dedicated-wallet/template/public/login_bg.png differ diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/public/logo.svg b/scaffolds/nextjs-solana-dedicated-wallet/template/public/logo.svg new file mode 100644 index 0000000..e13da68 --- /dev/null +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/public/logo.svg @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/public/magic_color_white.svg b/scaffolds/nextjs-solana-dedicated-wallet/template/public/magic_color_white.svg deleted file mode 100644 index 3267c05..0000000 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/public/magic_color_white.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/public/redirect_bg.png b/scaffolds/nextjs-solana-dedicated-wallet/template/public/redirect_bg.png new file mode 100644 index 0000000..aa322ee Binary files /dev/null and b/scaffolds/nextjs-solana-dedicated-wallet/template/public/redirect_bg.png differ diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Dashboard.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Dashboard.tsx index 25a067a..4e02d36 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Dashboard.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Dashboard.tsx @@ -1,27 +1,25 @@ -import React from 'react' -import WalletMethods from './cards/WalletMethodsCard' -import SendTransaction from './cards/SendTransactionCard' -import Spacer from '@/components/ui/Spacer' -import {LoginProps} from '@/utils/types' -import UserInfo from './cards/UserInfoCard' -import DevLinks from './DevLinks' -import Header from './Header' +import React from 'react'; +import WalletMethods from './cards/WalletMethodsCard'; +import SendTransaction from './cards/SendTransactionCard'; +import Spacer from '@/components/ui/Spacer'; +import { LoginProps } from '@/utils/types'; +import UserInfo from './cards/UserInfoCard'; +import DevLinks from './DevLinks'; +import Header from './Header'; -export default function Dashboard({token, setToken}: LoginProps) { - return ( -
-
- - -
- - - - - - -
- -
- ) +export default function Dashboard({ token, setToken }: LoginProps) { + return ( +
+
+
+ + + + + + +
+ +
+ ); } diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Header.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Header.tsx index b997a10..a6e4012 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Header.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Header.tsx @@ -1,19 +1,20 @@ -import Image from 'next/image' -import MagicColorWhite from 'public/magic_color_white.svg' -import {Dispatch, SetStateAction} from 'react' -import DevLinks from './DevLinks' +import Image from 'next/image'; +import Logo from 'public/logo.svg'; +import DevLinks from './DevLinks'; const Header = () => { - return ( -
- logo - -
- ) -} + return ( +
+
+ logo +
Magic
+
+ Demo +
+
+ +
+ ); +}; -export default Header +export default Header; diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Login.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Login.tsx index 185ed38..9cac8d6 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Login.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/Login.tsx @@ -1,22 +1,22 @@ -import {LoginProps} from '@/utils/types' +import { LoginProps } from '@/utils/types' import Header from './Header' <% loginMethods.forEach(authType => { %> <%-`import ${authType.replaceAll(' ', '')} from './auth/${authType.replaceAll(' ', '')}';`-%> <% }) %> -const Login = ({token, setToken}: LoginProps) => { - return ( -
-
-
- <% loginMethods.forEach(authType => { %> - <% if (authType !== "Social Logins") { %> - <%-`<${authType.replaceAll(' ', '')} token={token} setToken={setToken} />`-%> - <% } %> - <% }) %> -
-
- ) +const Login = ({ token, setToken }: LoginProps) => { + return ( +
+
+
grid-flow-row auto-rows-fr gap-5 p-4 mt-8`}> + <% loginMethods.forEach(authType => { %> + <% if (authType !== "Social Logins") { %> + <%-`<${authType.replaceAll(' ', '')} token={token} setToken={setToken} />`-%> + <% } %> + <% }) %> +
+
+ ) } export default Login diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx index 6083206..4c2cbed 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx @@ -1,7 +1,9 @@ import React, { useCallback } from 'react'; -import Spacer from '../ui/Spacer'; -import Header from './Header'; import DevLinks from './DevLinks'; +import Image from 'next/image'; +import Info from 'public/info.svg'; +import Link from 'public/link_white.svg'; +import Logo from 'public/logo.svg'; const MagicDashboardRedirect = () => { const onClick = useCallback(() => { @@ -10,18 +12,27 @@ const MagicDashboardRedirect = () => { return (
- - -
-

- Please set your NEXT_PUBLIC_MAGIC_API_KEY environment variable in .env. You can get - your Magic API key from the Magic Dashboard. -

+
+ logo +
Magic
+
+ Demo +
- -
-
diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Discord.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Discord.tsx index d05c653..763aed7 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Discord.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Discord.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '@/components/ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import discord from 'public/social/Discord.svg' -import Card from '@/components/ui/Card' -import CardHeader from '@/components/ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '@/components/ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import discord from 'public/social/Discord.svg'; +import Card from '@/components/ui/Card'; +import CardHeader from '@/components/ui/CardHeader'; -const Discord = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Discord = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'discord', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'discord', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Discord Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Discord -
Discord
-
-
- )} -
- ) -} -export default Discord + return ( + + Discord Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Discord; diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx index 3327f6b..662e77c 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx @@ -1,90 +1,78 @@ -import {useMagic} from '../MagicProvider' -import showToast from '@/utils/showToast' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import {RPCError, RPCErrorCode} from 'magic-sdk' -import {LoginProps} from '@/utils/types' -import {saveToken} from '@/utils/common' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' -import {useState} from 'react' -import FormInput from '@/components/ui/FormInput' +import { useMagic } from '../MagicProvider'; +import showToast from '@/utils/showToast'; +import Spinner from '../../ui/Spinner'; +import { RPCError, RPCErrorCode } from 'magic-sdk'; +import { LoginProps } from '@/utils/types'; +import { saveToken } from '@/utils/common'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; +import { useState } from 'react'; +import FormInput from '@/components/ui/FormInput'; -const EmailOTP = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [email, setEmail] = useState('') - const [emailError, setEmailError] = useState(false) - const [isLoginInProgress, setLoginInProgress] = useState(false) +const EmailOTP = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [email, setEmail] = useState(''); + const [emailError, setEmailError] = useState(false); + const [isLoginInProgress, setLoginInProgress] = useState(false); - const handleLogin = async () => { - if ( - !email.match( - /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/ - ) - ) { - setEmailError(true) - } else { - try { - setLoginInProgress(true) - setEmailError(false) - const account = await magic?.auth.loginWithEmailOTP({email}) - if (account) { - saveToken(account, setToken, 'EMAIL') - setEmail('') - } - } catch (e) { - console.log('login error: ' + JSON.stringify(e)) - if (e instanceof RPCError) { - switch (e.code) { - case RPCErrorCode.MagicLinkFailedVerification: - case RPCErrorCode.MagicLinkExpired: - case RPCErrorCode.MagicLinkRateLimited: - case RPCErrorCode.UserAlreadyLoggedIn: - showToast({message: e.message, type: 'error'}) - break - default: - showToast({ - message: - 'Something went wrong. Please try again', - type: 'error', - }) - } - } - } finally { - setLoginInProgress(false) - } - } - } + const handleLogin = async () => { + if (!email.match(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)) { + setEmailError(true); + } else { + try { + setLoginInProgress(true); + setEmailError(false); + const account = await magic?.auth.loginWithEmailOTP({ email }); + if (account) { + saveToken(account, setToken, 'EMAIL'); + setEmail(''); + } + } catch (e) { + console.log('login error: ' + JSON.stringify(e)); + if (e instanceof RPCError) { + switch (e.code) { + case RPCErrorCode.MagicLinkFailedVerification: + case RPCErrorCode.MagicLinkExpired: + case RPCErrorCode.MagicLinkRateLimited: + case RPCErrorCode.UserAlreadyLoggedIn: + showToast({ message: e.message, type: 'error' }); + break; + default: + showToast({ + message: 'Something went wrong. Please try again', + type: 'error', + }); + } + } + } finally { + setLoginInProgress(false); + } + } + }; - return ( - - Email OTP Login -
- { - if (emailError) setEmailError(false) - setEmail(e.target.value) - }} - placeholder={ - token.length > 0 ? 'Already logged in' : 'Email' - } - value={email} - /> - {emailError && ( - Enter a valid email - )} - -
-
- ) -} + return ( + + Email OTP Login +
+ { + if (emailError) setEmailError(false); + setEmail(e.target.value); + }} + placeholder={token.length > 0 ? 'Already logged in' : 'Email'} + value={email} + /> + {emailError && Enter a valid email} + +
+
+ ); +}; -export default EmailOTP +export default EmailOTP; diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx index 107761a..17bd3a1 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import facebook from 'public/social/Facebook.svg' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '../../ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import facebook from 'public/social/Facebook.svg'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; -const Facebook = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Facebook = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'facebook', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'facebook', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Facebook Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Google -
Facebook
-
-
- )} -
- ) -} -export default Facebook + return ( + + Facebook Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Facebook; diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Github.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Github.tsx index 431fd34..8004de7 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Github.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Github.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import github from 'public/social/Github.svg' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '../../ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import github from 'public/social/Github.svg'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; -const Github = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Github = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'github', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'github', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Github Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Google -
Github
-
-
- )} -
- ) -} -export default Github + return ( + + Github Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Github; diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Google.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Google.tsx index 29ab572..4dc8087 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Google.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Google.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import google from 'public/social/Google.svg' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '../../ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import google from 'public/social/Google.svg'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; -const Google = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Google = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'google', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'google', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Google Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Google -
Google
-
-
- )} -
- ) -} -export default Google + return ( + + Google Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Google; diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/LoginForm.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/LoginForm.tsx deleted file mode 100644 index 80a53f2..0000000 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/LoginForm.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import {LoginProps} from '@/utils/types' -import {useEffect, useMemo, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import {useRouter} from 'next/router' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' - -const setScriptAttributesAndAddScript = (src: string) => { - const script = document.createElement('script') - script.src = src - script.setAttribute( - 'data-magic-publishable-api-key', - process.env.NEXT_PUBLIC_MAGIC_API_KEY! - ) - script.setAttribute('data-redirect-uri', '/') - script.async = true - - document.body.appendChild(script) -} - -const LoginForm = ({token, setToken}: LoginProps) => { - const router = useRouter() - const [isLoginInProgress, setLoginInProgress] = useState(false) - - useMemo(async () => { - if (token.length == 0 && router.query) { - if (router.query.didt) { - await saveToken(router.query.didt as string, setToken, 'FORM') - router.replace('/', undefined, {shallow: true}) - } - if (router.query.magic_credential) { - await saveToken( - router.query.magic_credential as string, - setToken, - 'FORM' - ) - router.replace('/', undefined, {shallow: true}) - } - } - }, [router, setToken, token.length]) - - useEffect(() => { - if (token.length > 0 && !isLoginInProgress) { - setLoginInProgress(false) - } - }, [token, setLoginInProgress, isLoginInProgress]) - - const handleLogin = () => { - setLoginInProgress(true) - setScriptAttributesAndAddScript('https://auth.magic.link/pnp/login') - } - - return ( - - Login Form - - - Please wait a few seconds after clicking login as this button is - executing a magic script - - - ) -} - -export default LoginForm diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx index 239e4ac..2b3e474 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx @@ -1,90 +1,84 @@ -import {useState} from 'react' -import {useMagic} from '../MagicProvider' -import showToast from '@/utils/showToast' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import {RPCError, RPCErrorCode} from 'magic-sdk' -import {LoginProps} from '@/utils/types' -import {saveToken} from '@/utils/common' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' -import FormInput from '@/components/ui/FormInput' +import { useState } from 'react'; +import { useMagic } from '../MagicProvider'; +import showToast from '@/utils/showToast'; +import Spinner from '../../ui/Spinner'; +import { RPCError, RPCErrorCode } from 'magic-sdk'; +import { LoginProps } from '@/utils/types'; +import { saveToken } from '@/utils/common'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; +import FormInput from '@/components/ui/FormInput'; -const SMSOTP = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [phone, setPhone] = useState('') - const [phoneError, setPhoneError] = useState(false) - const [isLoginInProgress, setLoginInProgress] = useState(false) +const SMSOTP = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [phone, setPhone] = useState(''); + const [phoneError, setPhoneError] = useState(false); + const [isLoginInProgress, setLoginInProgress] = useState(false); - const handleLogin = async () => { - if (!phone.match(/^\+?\d{10,14}$/)) { - setPhoneError(true) - } else { - try { - setLoginInProgress(true) - setPhoneError(false) - const account = await magic?.auth.loginWithSMS({ - phoneNumber: phone, - }) - if (account) { - saveToken(account, setToken, 'SMS') - setPhone('') - } - } catch (e) { - console.log('login error: ' + JSON.stringify(e)) - if (e instanceof RPCError) { - switch (e.code) { - case RPCErrorCode.MagicLinkFailedVerification: - case RPCErrorCode.MagicLinkExpired: - case RPCErrorCode.MagicLinkRateLimited: - case RPCErrorCode.UserAlreadyLoggedIn: - showToast({message: e.message, type: 'error'}) - break - default: - showToast({ - message: - 'Something went wrong. Please try again', - type: 'error', - }) - } - } - } finally { - setLoginInProgress(false) - } - } - } + const handleLogin = async () => { + if (!phone.match(/^\+?\d{10,14}$/)) { + setPhoneError(true); + } else { + try { + setLoginInProgress(true); + setPhoneError(false); + const account = await magic?.auth.loginWithSMS({ + phoneNumber: phone, + }); + if (account) { + saveToken(account, setToken, 'SMS'); + setPhone(''); + } + } catch (e) { + console.log('login error: ' + JSON.stringify(e)); + if (e instanceof RPCError) { + switch (e.code) { + case RPCErrorCode.MagicLinkFailedVerification: + case RPCErrorCode.MagicLinkExpired: + case RPCErrorCode.MagicLinkRateLimited: + case RPCErrorCode.UserAlreadyLoggedIn: + showToast({ message: e.message, type: 'error' }); + break; + default: + showToast({ + message: 'Something went wrong. Please try again', + type: 'error', + }); + } + } + } finally { + setLoginInProgress(false); + } + } + }; - return ( - - SMS Login -
- { - if (phoneError) setPhoneError(false) - setPhone(e.target.value) - }} - placeholder={ - token.length > 0 ? 'Already logged in' : '+11234567890' - } - value={phone} - /> - {phoneError && ( - - Enter a valid phone number - - )} - -
-
- ) -} + return ( + + SMS Login +
+ { + if (phoneError) setPhoneError(false); + setPhone(e.target.value); + }} + placeholder={token.length > 0 ? 'Already logged in' : '+11234567890'} + value={phone} + /> + {phoneError && ( + + Enter a valid phone number + + )} + +
+
+ ); +}; -export default SMSOTP +export default SMSOTP; diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx index 3f03e01..8986ba7 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import twitch from 'public/social/Twitch.svg' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '../../ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import twitch from 'public/social/Twitch.svg'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; -const Twitch = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Twitch = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'twitch', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'twitch', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Twitch Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Twitch -
Twitch
-
-
- )} -
- ) -} -export default Twitch + return ( + + Twitch Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Twitch; diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx index d60db9e..f90a7a2 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx @@ -1,81 +1,73 @@ -import {LoginProps} from '@/utils/types' -import {useMagic} from '../MagicProvider' -import {useEffect, useState} from 'react' -import {saveToken} from '@/utils/common' -import Spinner from '../../ui/Spinner' -import classNames from 'classnames' -import Image from 'next/image' -import twitter from 'public/social/Twitter.svg' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' +import { LoginProps } from '@/utils/types'; +import { useMagic } from '../MagicProvider'; +import { useEffect, useState } from 'react'; +import { saveToken } from '@/utils/common'; +import Spinner from '../../ui/Spinner'; +import classNames from 'classnames'; +import Image from 'next/image'; +import twitter from 'public/social/Twitter.svg'; +import Card from '../../ui/Card'; +import CardHeader from '../../ui/CardHeader'; -const Twitter = ({token, setToken}: LoginProps) => { - const {magic} = useMagic() - const [isAuthLoading, setIsAuthLoading] = useState(null) +const Twitter = ({ token, setToken }: LoginProps) => { + const { magic } = useMagic(); + const [isAuthLoading, setIsAuthLoading] = useState(null); - useEffect(() => { - setIsAuthLoading(localStorage.getItem('isAuthLoading')) - }, []) + useEffect(() => { + setIsAuthLoading(localStorage.getItem('isAuthLoading')); + }, []); - useEffect(() => { - const checkLogin = async () => { - try { - if (magic) { - const result = await magic?.oauth.getRedirectResult() - //do stuff with user profile data - saveToken(result.magic.idToken, setToken, 'SOCIAL') - setLoadingFlag('false') - } - } catch (e) { - console.log('social login error: ' + e) - setLoadingFlag('false') - } - } + useEffect(() => { + const checkLogin = async () => { + try { + if (magic) { + const result = await magic?.oauth.getRedirectResult(); + //do stuff with user profile data + saveToken(result.magic.idToken, setToken, 'SOCIAL'); + setLoadingFlag('false'); + } + } catch (e) { + console.log('social login error: ' + e); + setLoadingFlag('false'); + } + }; - checkLogin() - }, [magic, setToken]) + checkLogin(); + }, [magic, setToken]); - const login = async () => { - setLoadingFlag('true') - await magic?.oauth.loginWithRedirect({ - provider: 'twitter', - redirectURI: window.location.origin, - }) - } + const login = async () => { + setLoadingFlag('true'); + await magic?.oauth.loginWithRedirect({ + provider: 'twitter', + redirectURI: window.location.origin, + }); + }; - const setLoadingFlag = (loading: string) => { - localStorage.setItem('isAuthLoading', loading) - setIsAuthLoading(loading) - } + const setLoadingFlag = (loading: string) => { + localStorage.setItem('isAuthLoading', loading); + setIsAuthLoading(loading); + }; - return ( - - Twitter Login - {isAuthLoading && isAuthLoading !== 'false' ? ( - - ) : ( -
-
0 - ? 'cursor-default' - : 'cursor-pointer' - )} - onClick={() => { - if (token.length == 0) login() - }}> - Twitter -
Twitter
-
-
- )} -
- ) -} -export default Twitter + return ( + + Twitter Login + {isAuthLoading && isAuthLoading !== 'false' ? ( + + ) : ( +
+ +
+ )} +
+ ); +}; +export default Twitter; diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/src/styles/globals.css b/scaffolds/nextjs-solana-dedicated-wallet/template/src/styles/globals.css index 83bde73..7222af2 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/src/styles/globals.css +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/src/styles/globals.css @@ -47,7 +47,7 @@ ul { } .nft-name { - @apply text-black font-semibold; + @apply font-semibold text-black; font-family: 'Inter'; } @@ -60,7 +60,7 @@ ul { } .cards-container { - @apply mt-[-250px] relative; + @apply relative top-[30px] md:top-[-60px] lg:top-[-60px]; } @media only screen and (max-width: 767px) { @@ -70,7 +70,7 @@ ul { } .network-dropdown { - @apply w-fit m-auto rounded-xl; + @apply m-auto w-fit rounded-xl; } .active-network { @@ -116,7 +116,7 @@ ul { @apply flex flex-col items-center min-h-screen bg-gray-300; } .login-method-grid { - @apply w-[100%] grid grid-cols-4 gap-5 p-4; + @apply max-w-[100%] grid-rows-3 gap-5 p-4 mt-8; } .login-method-grid-item-container { @@ -125,7 +125,7 @@ ul { .login-button { @apply w-full h-12 text-white font-semibold text-base leading-6 transition-[0.1s] text-center transition-[0.1s] m-auto px-2 py-3 rounded-[300px] border-[none]; - background: #a799ff; + background: #8271f3; } .login-button:disabled { @@ -142,7 +142,7 @@ ul { } .links { - @apply flex justify-center text-white font-semibold mt-5 mb-3 mx-auto; + @apply flex justify-center mx-auto mt-5 text-sm mb-3 font-semibold text-white; } .link { @apply transition-[0.1s] px-[30px] py-0; @@ -163,7 +163,7 @@ ul { @apply cursor-pointer; } .link-divider { - @apply h-5 w-px; + @apply w-px h-5; } .footer-links { @@ -221,7 +221,7 @@ ul { @apply w-[50px] text-center flex items-center justify-center cursor-default; } .loading { - @apply animate-spin cursor-default; + @apply cursor-default animate-spin; } @keyframes rotation { @@ -234,18 +234,18 @@ ul { } .card { - @apply w-[300px] flex flex-col shadow-[0px_4px_24px_rgba(49,49,49,0.1)] mt-0 mb-[27px] mx-auto px-6 py-8 rounded-2xl bg-[#ffffff]; + @apply w-[344px] flex flex-col shadow-[0px_4px_24px_rgba(49,49,49,0.1)] mt-0 mb-[27px] mx-auto px-6 py-8 rounded-2xl bg-[#ffffff]; } .card-header { @apply text-xl font-semibold text-left mt-0 mb-[25px]; } .card-label-container { - @apply flex justify-between items-center mb-3; + @apply flex items-center justify-between mb-3; } .card-label { - @apply text-sm font-medium cursor-pointer; + @apply text-sm font-medium cursor-pointer; } .toast { @apply fixed w-fit text-white font-medium shadow-[4px_8px_20px_rgba(0,0,0,0.15)] mx-auto my-0 px-4 py-2 rounded-[10px] top-[30px] inset-x-0 bg-[#00875f]; @@ -291,10 +291,35 @@ a { } .app-header-container { - @apply block pt-4 w-full drop-shadow-[0_35px_35px_rgba(0,0,0,0.25)] min-h-[30vh] flex flex-col items-center bg-magic block; + @apply block w-full drop-shadow-[0_35px_35px_rgba(0,0,0,0.25)] min-h-[40%] flex-col gap-2.5 p-8 items-center bg-[url('/login_bg.png')] bg-cover bg-no-repeat pb-20; text-align: -webkit-center; } .redirect-container { - @apply flex flex-col items-center min-h-screen bg-[length:100%_auto] bg-[url('/background.svg')]; + @apply flex flex-col items-center h-screen bg-center bg-cover bg-no-repeat bg-[url('/redirect_bg.png')]; +} + +.redirect-card { + @apply bg-[#F8F8FA] rounded-[10px] shadow-[0px_4px_24px_rgba(49,49,49,0.1)] p-2 m-12; +} + +.social-login-button { + @apply flex flex-row min-w-[296px] h-12 text-[#3C4043] transition-[0.1s] px-6 py-3 rounded-[300px] bg-[#ffffff] border-2 border-[#DADCE0] relative top-16; +} + +.social-login-button:disabled { + @apply opacity-50; +} + +.social-login-button:hover:enabled { + @apply cursor-pointer; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #ffffff; +} +.social-login-button:active:enabled { + @apply opacity-50 scale-[0.99]; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #ffffff; +} + +.api-button { + @apply bg-[#6844bc] text-[#FFFFFF] flex w-[280px] justify-center items-center h-12 font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none]; } diff --git a/scaffolds/nextjs-solana-dedicated-wallet/template/tailwind.config.js b/scaffolds/nextjs-solana-dedicated-wallet/template/tailwind.config.js index 1da1a7e..0fc0404 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/template/tailwind.config.js +++ b/scaffolds/nextjs-solana-dedicated-wallet/template/tailwind.config.js @@ -1,19 +1,17 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: [ - './src/pages/**/*.{js,ts,jsx,tsx,mdx}', - './src/components/**/*.{js,ts,jsx,tsx,mdx}', - './src/app/**/*.{js,ts,jsx,tsx,mdx}', - ], - theme: { - extend: { - backgroundImage: { - magic: "url('../../public//background.svg')", - 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', - 'gradient-conic': - 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', - }, - }, - }, - plugins: [], -} + content: [ + './src/pages/**/*.{js,ts,jsx,tsx,mdx}', + './src/components/**/*.{js,ts,jsx,tsx,mdx}', + './src/app/**/*.{js,ts,jsx,tsx,mdx}', + ], + theme: { + extend: { + backgroundImage: { + 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', + 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', + }, + }, + }, + plugins: [], +}; diff --git a/scaffolds/nextjs-universal-wallet/scaffold.ts b/scaffolds/nextjs-universal-wallet/scaffold.ts index 8559db2..6d4e582 100644 --- a/scaffolds/nextjs-universal-wallet/scaffold.ts +++ b/scaffolds/nextjs-universal-wallet/scaffold.ts @@ -2,7 +2,6 @@ import { Flags } from 'core/flags'; import BaseScaffold from 'core/types/BaseScaffold'; import { Prompt } from 'enquirer'; import { BlockchainNetworkPrompt, PublishableApiKeyPrompt } from 'scaffolds/prompts'; -import * as fs from 'fs'; export type Data = BlockchainNetworkPrompt.Data & PublishableApiKeyPrompt.Data; diff --git a/scaffolds/nextjs-universal-wallet/template/.env.example b/scaffolds/nextjs-universal-wallet/template/.env.example new file mode 100644 index 0000000..4b4c3b1 --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/.env.example @@ -0,0 +1,2 @@ +NEXT_PUBLIC_BLOCKCHAIN_NETWORK=<%= network %> +NEXT_PUBLIC_MAGIC_API_KEY=<%= publishableApiKey %> \ No newline at end of file diff --git a/scaffolds/nextjs-universal-wallet/template/.eslintrc.json b/scaffolds/nextjs-universal-wallet/template/.eslintrc.json new file mode 100644 index 0000000..bffb357 --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/scaffolds/nextjs-universal-wallet/template/.gitignore b/scaffolds/nextjs-universal-wallet/template/.gitignore new file mode 100644 index 0000000..c98ad77 --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/.gitignore @@ -0,0 +1,39 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +#environment +.env \ No newline at end of file diff --git a/scaffolds/nextjs-universal-wallet/template/README.md b/scaffolds/nextjs-universal-wallet/template/README.md new file mode 100644 index 0000000..68281ea --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/README.md @@ -0,0 +1,44 @@ +This scaffold is meant to help you bootstrap your own projects with Magic's [Universal Wallet](https://magic.link/docs/connect/overview). Magic is a developer SDK that integrates with your application to enable passwordless Web3 onboarding. + +The folder structure of this scaffold is designed to encapsulate all things Magic into one place so you can easily add or remove components and functionality. For example, all Magic-specific components are in the `src/components/magic` directory while generic UI components are in the `src/components/ui` directory. + +## Next.js + +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. + +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. + +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. + +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/scaffolds/nextjs-universal-wallet/template/next.config.js b/scaffolds/nextjs-universal-wallet/template/next.config.js new file mode 100644 index 0000000..91ef62f --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/next.config.js @@ -0,0 +1,6 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, +}; + +module.exports = nextConfig; diff --git a/scaffolds/nextjs-universal-wallet/template/package.json b/scaffolds/nextjs-universal-wallet/template/package.json new file mode 100644 index 0000000..4702fc9 --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/package.json @@ -0,0 +1,29 @@ +{ + "name": "<%= projectName %>", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint --fix" + }, + "dependencies": { + "@types/node": "18.15.11", + "@types/react": "18.0.35", + "@types/react-dom": "18.0.11", + "eslint-config-next": "13.3.0", + "magic-sdk": "^16.2.0", + "next": "13.3.0", + "react": "18.2.0", + "react-dom": "18.2.0", + "typescript": "5.0.4", + "web3": "^1.9.0" + }, + "devDependencies": { + "autoprefixer": "^10.4.15", + "eslint": "^8.45.0", + "postcss": "^8.4.28", + "tailwindcss": "^3.3.3" + } +} diff --git a/scaffolds/nextjs-universal-wallet/template/postcss.config.js b/scaffolds/nextjs-universal-wallet/template/postcss.config.js new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/scaffolds/nextjs-universal-wallet/template/public/info.svg b/scaffolds/nextjs-universal-wallet/template/public/info.svg new file mode 100644 index 0000000..df6edb9 --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/public/info.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-universal-wallet/template/public/link_white.svg b/scaffolds/nextjs-universal-wallet/template/public/link_white.svg new file mode 100644 index 0000000..c87852b --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/public/link_white.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-universal-wallet/template/public/login_bg.png b/scaffolds/nextjs-universal-wallet/template/public/login_bg.png new file mode 100644 index 0000000..a4021c4 Binary files /dev/null and b/scaffolds/nextjs-universal-wallet/template/public/login_bg.png differ diff --git a/scaffolds/nextjs-universal-wallet/template/public/logo.svg b/scaffolds/nextjs-universal-wallet/template/public/logo.svg new file mode 100644 index 0000000..e13da68 --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/public/logo.svg @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/scaffolds/nextjs-universal-wallet/template/public/redirect_bg.png b/scaffolds/nextjs-universal-wallet/template/public/redirect_bg.png new file mode 100644 index 0000000..aa322ee Binary files /dev/null and b/scaffolds/nextjs-universal-wallet/template/public/redirect_bg.png differ diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/Links.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/DevLinks.tsx similarity index 100% rename from scaffolds/nextjs-universal-wallet/template/src/components/magic/Links.tsx rename to scaffolds/nextjs-universal-wallet/template/src/components/magic/DevLinks.tsx diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/Home.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/Home.tsx index acb16e4..c36d8a1 100644 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/Home.tsx +++ b/scaffolds/nextjs-universal-wallet/template/src/components/magic/Home.tsx @@ -4,7 +4,7 @@ import AppHeader from '../ui/AppHeader'; import Wallet from './cards/UserInfoCard'; import WalletMethods from './cards/WalletMethodsCard'; import SendTransaction from './cards/SendTransactionsCard'; -import Links from './Links'; +import Links from './DevLinks'; import Spacer from '../ui/Spacer'; import HomePageBackground from 'public/main.svg'; interface Props { diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/Login.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/Login.tsx index 07e5642..ad9f7bc 100644 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/Login.tsx +++ b/scaffolds/nextjs-universal-wallet/template/src/components/magic/Login.tsx @@ -1,6 +1,6 @@ import React, { useState, useCallback } from 'react'; import AppHeader from '../ui/AppHeader'; -import Links from './Links'; +import Links from './DevLinks'; import ConnectButton from '../ui/ConnectButton'; import Spacer from '../ui/Spacer'; import LoginPageBackground from 'public/login.svg'; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx index 69f173b..2478f09 100644 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx +++ b/scaffolds/nextjs-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx @@ -1,32 +1,41 @@ import React, { useCallback } from 'react'; -import AppHeader from '../ui/AppHeader'; -import Links from './Links'; -import Spacer from '../ui/Spacer'; -import LoginPageBackground from 'public/login.svg'; +import Image from 'next/image'; +import Info from 'public/info.svg'; +import Link from 'public/link_white.svg'; +import Logo from 'public/logo.svg'; +import DevLinks from './DevLinks'; const MagicDashboardRedirect = () => { const onClick = useCallback(() => { - window.open('https://dashboard.magic.link', '_blank'); + window.open('https://dashboard.magic.link/signup', '_blank'); }, []); return (
- - - -
-

- Please set your NEXT_PUBLIC_MAGIC_API_KEY environment variable in .env. You can get - your Magic API key from the Magic Dashboard. -

+
+ logo +
Magic
+
+ Demo +
- -
-
- +
); }; diff --git a/scaffolds/nextjs-universal-wallet/template/src/styles/globals.css b/scaffolds/nextjs-universal-wallet/template/src/styles/globals.css index 46e0d2f..e926d58 100644 --- a/scaffolds/nextjs-universal-wallet/template/src/styles/globals.css +++ b/scaffolds/nextjs-universal-wallet/template/src/styles/globals.css @@ -280,3 +280,11 @@ a { .redirect-container { @apply flex flex-col items-center min-h-screen bg-['100%_auto'] bg-[url('/login.svg')]; } + +.redirect-card { + @apply bg-[#F8F8FA] rounded-[10px] shadow-[0px_4px_24px_rgba(49,49,49,0.1)] p-2 m-12; +} + +.api-button { + @apply bg-[#6844bc] text-[#FFFFFF] flex w-[280px] justify-center items-center h-12 font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none]; +} diff --git a/scaffolds/nextjs-universal-wallet/template/tailwind.config.js b/scaffolds/nextjs-universal-wallet/template/tailwind.config.js new file mode 100644 index 0000000..84ecf21 --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/tailwind.config.js @@ -0,0 +1,15 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + './app/**/*.{js,ts,jsx,tsx,mdx}', + './pages/**/*.{js,ts,jsx,tsx,mdx}', + './components/**/*.{js,ts,jsx,tsx,mdx}', + + // Or if using `src` directory: + './src/**/*.{js,ts,jsx,tsx,mdx}', + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/scaffolds/nextjs-universal-wallet/template/tsconfig.json b/scaffolds/nextjs-universal-wallet/template/tsconfig.json new file mode 100644 index 0000000..61c19ab --- /dev/null +++ b/scaffolds/nextjs-universal-wallet/template/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +}