diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..be1ad0f9d --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,10 @@ +module.exports = { + root: true, + // This tells ESLint to load the config from the package `config` + // extends: ["custom"], + settings: { + next: { + rootDir: ["apps/*/"], + }, + }, +}; diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index bffb357a7..000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/apps/app/.eslintrc.js b/apps/app/.eslintrc.js new file mode 100644 index 000000000..64b6ff36b --- /dev/null +++ b/apps/app/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require("config/.eslintrc"); diff --git a/apps/app/Dockerfile.web b/apps/app/Dockerfile.web index 8b3bc4656..be8abf5fa 100644 --- a/apps/app/Dockerfile.web +++ b/apps/app/Dockerfile.web @@ -14,7 +14,7 @@ ENV PATH="${PATH}:./pnpm" COPY ./apps ./apps COPY ./package.json ./package.json -COPY ./.eslintrc.json ./.eslintrc.json +COPY ./.eslintrc.js ./.eslintrc.js COPY ./turbo.json ./turbo.json COPY ./pnpm-workspace.yaml ./pnpm-workspace.yaml COPY ./pnpm-lock.yaml ./pnpm-lock.yaml diff --git a/apps/app/components/forms/EmailCodeForm.tsx b/apps/app/components/account/email-code-form.tsx similarity index 84% rename from apps/app/components/forms/EmailCodeForm.tsx rename to apps/app/components/account/email-code-form.tsx index 6c3ef8f86..ff5f8632d 100644 --- a/apps/app/components/forms/EmailCodeForm.tsx +++ b/apps/app/components/account/email-code-form.tsx @@ -1,28 +1,28 @@ import React, { useState } from "react"; -// react hook form import { useForm } from "react-hook-form"; // ui -import { Button, Input } from "ui"; -import authenticationService from "lib/services/authentication.service"; -// icons import { CheckCircleIcon } from "@heroicons/react/20/solid"; +import { Button, Input } from "components/ui"; +// services +import authenticationService from "services/authentication.service"; +// icons // types -type SignIn = { +type EmailCodeFormValues = { email: string; key?: string; token?: string; }; -const EmailCodeForm = ({ onSuccess }: any) => { +export const EmailCodeForm = ({ onSuccess }: any) => { const [codeSent, setCodeSent] = useState(false); const { register, handleSubmit, setError, setValue, - formState: { errors, isSubmitting, dirtyFields, isValid, isDirty }, - } = useForm({ + formState: { errors, isSubmitting, isValid, isDirty }, + } = useForm({ defaultValues: { email: "", key: "", @@ -32,9 +32,8 @@ const EmailCodeForm = ({ onSuccess }: any) => { reValidateMode: "onChange", }); - const onSubmit = ({ email }: SignIn) => { + const onSubmit = ({ email }: EmailCodeFormValues) => { console.log(email); - authenticationService .emailCode({ email }) .then((res) => { @@ -46,15 +45,15 @@ const EmailCodeForm = ({ onSuccess }: any) => { }); }; - const handleSignin = (formData: SignIn) => { + const handleSignin = (formData: EmailCodeFormValues) => { authenticationService .magicSignIn(formData) - .then(async (response) => { - await onSuccess(response); + .then((response) => { + onSuccess(response); }) .catch((error) => { console.log(error); - setError("token" as keyof SignIn, { + setError("token" as keyof EmailCodeFormValues, { type: "manual", message: error.error, }); @@ -127,5 +126,3 @@ const EmailCodeForm = ({ onSuccess }: any) => { ); }; - -export default EmailCodeForm; diff --git a/apps/app/components/forms/EmailPasswordForm.tsx b/apps/app/components/account/email-password-form.tsx similarity index 79% rename from apps/app/components/forms/EmailPasswordForm.tsx rename to apps/app/components/account/email-password-form.tsx index 384b77598..029485b8b 100644 --- a/apps/app/components/forms/EmailPasswordForm.tsx +++ b/apps/app/components/account/email-password-form.tsx @@ -1,29 +1,26 @@ import React from "react"; // next import Link from "next/link"; -import { useRouter } from "next/router"; // react hook form import { useForm } from "react-hook-form"; // ui -import { Button, Input } from "ui"; -import authenticationService from "lib/services/authentication.service"; +import { Button, Input } from "components/ui"; +import authenticationService from "services/authentication.service"; // types -type SignIn = { +type EmailPasswordFormValues = { email: string; password?: string; medium?: string; }; -const EmailPasswordForm = ({ onSuccess }: any) => { +export const EmailPasswordForm = ({ onSuccess }: any) => { const { register, handleSubmit, setError, - setValue, - getValues, - formState: { errors, isSubmitting, dirtyFields, isValid, isDirty }, - } = useForm({ + formState: { errors, isSubmitting, isValid, isDirty }, + } = useForm({ defaultValues: { email: "", password: "", @@ -33,11 +30,11 @@ const EmailPasswordForm = ({ onSuccess }: any) => { reValidateMode: "onChange", }); - const onSubmit = (formData: SignIn) => { + const onSubmit = (formData: EmailPasswordFormValues) => { authenticationService .emailLogin(formData) - .then(async (response) => { - await onSuccess(response); + .then((response) => { + onSuccess(response); }) .catch((error) => { console.log(error); @@ -45,7 +42,7 @@ const EmailPasswordForm = ({ onSuccess }: any) => { Object.keys(error.response.data).forEach((key) => { const err = error.response.data[key]; console.log("err", err); - setError(key as keyof SignIn, { + setError(key as keyof EmailPasswordFormValues, { type: "manual", message: Array.isArray(err) ? err.join(", ") : err, }); @@ -85,8 +82,8 @@ const EmailPasswordForm = ({ onSuccess }: any) => { placeholder="Enter your password" /> -
-
+
+
Forgot your password? @@ -105,5 +102,3 @@ const EmailPasswordForm = ({ onSuccess }: any) => { ); }; - -export default EmailPasswordForm; diff --git a/apps/app/components/account/email-signin-form.tsx b/apps/app/components/account/email-signin-form.tsx new file mode 100644 index 000000000..3d13ca5a1 --- /dev/null +++ b/apps/app/components/account/email-signin-form.tsx @@ -0,0 +1,46 @@ +import { useState, FC } from "react"; +import { KeyIcon } from "@heroicons/react/24/outline"; +// components +import { EmailCodeForm, EmailPasswordForm } from "components/account"; + +export interface EmailSignInFormProps { + handleSuccess: () => void; +} + +export const EmailSignInForm: FC = (props) => { + const { handleSuccess } = props; + // states + const [useCode, setUseCode] = useState(true); + + return ( + <> + {useCode ? ( + + ) : ( + + )} +
+
+
+
+
+
+ or +
+
+
+ +
+
+ + ); +}; diff --git a/apps/app/components/account/github-login-button.tsx b/apps/app/components/account/github-login-button.tsx new file mode 100644 index 000000000..e93abde88 --- /dev/null +++ b/apps/app/components/account/github-login-button.tsx @@ -0,0 +1,51 @@ +import { useEffect, useState, FC } from "react"; +import Link from "next/link"; +import Image from "next/image"; +import { useRouter } from "next/router"; +// images +import githubImage from "/public/logos/github.png"; + +const { NEXT_PUBLIC_GITHUB_ID } = process.env; + +export interface GithubLoginButtonProps { + handleSignIn: React.Dispatch; +} + +export const GithubLoginButton: FC = (props) => { + const { handleSignIn } = props; + // router + const { + query: { code }, + } = useRouter(); + // states + const [loginCallBackURL, setLoginCallBackURL] = useState(undefined); + + useEffect(() => { + if (code) { + handleSignIn(code.toString()); + } + }, [code, handleSignIn]); + + useEffect(() => { + const origin = + typeof window !== "undefined" && window.location.origin ? window.location.origin : ""; + setLoginCallBackURL(`${origin}/signin` as any); + }, []); + + return ( + + + + ); +}; diff --git a/apps/app/components/socialbuttons/google-login.tsx b/apps/app/components/account/google-login.tsx similarity index 89% rename from apps/app/components/socialbuttons/google-login.tsx rename to apps/app/components/account/google-login.tsx index 6c39c58af..078eef518 100644 --- a/apps/app/components/socialbuttons/google-login.tsx +++ b/apps/app/components/account/google-login.tsx @@ -4,12 +4,13 @@ import Script from "next/script"; export interface IGoogleLoginButton { text?: string; - onSuccess?: (res: any) => void; - onFailure?: (res: any) => void; + handleSignIn: React.Dispatch; styles?: CSSProperties; } export const GoogleLoginButton: FC = (props) => { + const { handleSignIn } = props; + const googleSignInButton = useRef(null); const [gsiScriptLoaded, setGsiScriptLoaded] = useState(false); @@ -17,7 +18,7 @@ export const GoogleLoginButton: FC = (props) => { if (!googleSignInButton.current || gsiScriptLoaded) return; window?.google?.accounts.id.initialize({ client_id: process.env.NEXT_PUBLIC_GOOGLE_CLIENTID || "", - callback: props.onSuccess as any, + callback: handleSignIn, }); window?.google?.accounts.id.renderButton( googleSignInButton.current, @@ -32,7 +33,7 @@ export const GoogleLoginButton: FC = (props) => { ); window?.google?.accounts.id.prompt(); // also display the One Tap dialog setGsiScriptLoaded(true); - }, [props.onSuccess, gsiScriptLoaded]); + }, [handleSignIn, gsiScriptLoaded]); useEffect(() => { if (window?.google?.accounts?.id) { @@ -46,7 +47,7 @@ export const GoogleLoginButton: FC = (props) => { return ( <> ); } diff --git a/apps/app/pages/_document.tsx b/apps/app/pages/_document.tsx new file mode 100644 index 000000000..befe7cd17 --- /dev/null +++ b/apps/app/pages/_document.tsx @@ -0,0 +1,22 @@ +import Document, { Html, Head, Main, NextScript } from "next/document"; + +class MyDocument extends Document { + render() { + return ( + + + + + +