From 89bf88ee236bc9215a7388c854efd47840c545d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frane=20Poli=C4=87?= <16856471+fPolic@users.noreply.github.com> Date: Mon, 23 Sep 2024 09:12:20 +0200 Subject: [PATCH] feat(dashboard): login and invite redesign (#9214) **What** - new UI for login and invite pages --- ![Screenshot 2024-09-20 at 15 24 31](https://github.com/user-attachments/assets/abaea120-6e93-4962-9865-bd52c0f67fb9) ![Screenshot 2024-09-20 at 15 24 40](https://github.com/user-attachments/assets/037fa81c-66a5-4764-aff1-5b5f9ac102d2) --- CLOSES CC-131 --- .../admin/dashboard/public/medusa-avatar.png | Bin 0 -> 4459 bytes .../components/common/logo-box/avatar-box.tsx | 51 ++++++++ .../src/components/common/logo-box/index.ts | 1 + .../dashboard/src/i18n/translations/en.json | 16 ++- .../dashboard/src/routes/invite/invite.tsx | 120 ++++++++++-------- .../dashboard/src/routes/login/login.tsx | 59 ++++++--- 6 files changed, 167 insertions(+), 80 deletions(-) create mode 100644 packages/admin/dashboard/public/medusa-avatar.png create mode 100644 packages/admin/dashboard/src/components/common/logo-box/avatar-box.tsx diff --git a/packages/admin/dashboard/public/medusa-avatar.png b/packages/admin/dashboard/public/medusa-avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..868804a9db5c1288b64ee90fbccf6d0b4bed3f4b GIT binary patch literal 4459 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 + {checked && ( + + + + + + )} + + + + ) +} diff --git a/packages/admin/dashboard/src/components/common/logo-box/index.ts b/packages/admin/dashboard/src/components/common/logo-box/index.ts index ee20f53faa..96e7eccdda 100644 --- a/packages/admin/dashboard/src/components/common/logo-box/index.ts +++ b/packages/admin/dashboard/src/components/common/logo-box/index.ts @@ -1 +1,2 @@ export * from "./logo-box" +export * from "./avatar-box" diff --git a/packages/admin/dashboard/src/i18n/translations/en.json b/packages/admin/dashboard/src/i18n/translations/en.json index c2d4ed74c3..510d176b1e 100644 --- a/packages/admin/dashboard/src/i18n/translations/en.json +++ b/packages/admin/dashboard/src/i18n/translations/en.json @@ -115,6 +115,7 @@ "close": "Close", "showMore": "Show more", "continue": "Continue", + "continueWithEmail": "Continue with Email", "addReason": "Add Reason", "addNote": "Add Note", "reset": "Reset", @@ -546,7 +547,7 @@ "inventory": { "notManaged": "Not managed", "manageItems": "Manage inventory items", - "notManagedDesc":"Inventory is not managed for this variant. Turn on ‘Manage Inventory’ to track the variant's inventory.", + "notManagedDesc": "Inventory is not managed for this variant. Turn on ‘Manage Inventory’ to track the variant's inventory.", "manageKit": "Manage inventory kit", "navigateToItem": "Go to inventory item", "actions": { @@ -2338,19 +2339,20 @@ }, "login": { "forgotPassword": "Forgot password? - <0>Reset", - "title": "Log in", - "hint": "to continue to Medusa" + "title": "Welcome to Medusa", + "hint": "Sign in to access the account area" }, "invite": { - "title": "Create your account", - "hint": "to continue to Medusa", + "title": "Welcome to Medusa", + "hint": "Create you account below", + "backToLogin": "Back to login", "createAccount": "Create account", "alreadyHaveAccount": "Already have an account? - <0>Log in", "emailTooltip": "Your email cannot be changed. If you would like to use another email, a new invite must be sent.", "invalidInvite": "The invite is invalid or has expired.", - "successTitle": "Your account has been created", + "successTitle": "Your account has is registered", "successHint": "Get started with Medusa Admin right away.", - "successAction": "Sign in to start using Medusa", + "successAction": "Start Medusa Admin", "invalidTokenTitle": "Your invite token is invalid", "invalidTokenHint": "Try requesting a new invite link.", "passwordMismatch": "Passwords do not match", diff --git a/packages/admin/dashboard/src/routes/invite/invite.tsx b/packages/admin/dashboard/src/routes/invite/invite.tsx index 84f6048760..d5e71828f1 100644 --- a/packages/admin/dashboard/src/routes/invite/invite.tsx +++ b/packages/admin/dashboard/src/routes/invite/invite.tsx @@ -1,18 +1,18 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { Alert, Button, Heading, Input, Text, toast } from "@medusajs/ui" +import { Alert, Button, Heading, Hint, Input, Text, toast } from "@medusajs/ui" import { AnimatePresence, motion } from "framer-motion" import i18n from "i18next" import { useState } from "react" import { useForm } from "react-hook-form" -import { Trans, useTranslation } from "react-i18next" +import { useTranslation } from "react-i18next" import { decodeToken } from "react-jwt" import { Link, useSearchParams } from "react-router-dom" import * as z from "zod" import { Form } from "../../components/common/form" -import { LogoBox } from "../../components/common/logo-box" import { useSignUpWithEmailPass } from "../../hooks/api/auth" import { useAcceptInvite } from "../../hooks/api/invites" import { isFetchError } from "../../lib/is-fetch-error" +import AvatarBox from "../../components/common/logo-box/avatar-box" const CreateAccountSchema = z .object({ @@ -50,23 +50,9 @@ export const Invite = () => { const isValidInvite = invite && validateDecodedInvite(invite) return ( -
-
- +
+
+
{isValidInvite ? ( @@ -150,19 +136,13 @@ const LoginLink = () => { return (
- - , - ]} - /> - + + {t("invite.backToLogin")} +
) } @@ -250,6 +230,14 @@ const CreateView = ({ } }) + const serverError = form.formState.errors.root?.message + const validationError = + form.formState.errors.email?.message || + form.formState.errors.password?.message || + form.formState.errors.repeat_password?.message || + form.formState.errors.first_name?.message || + form.formState.errors.last_name?.message + return (
@@ -260,18 +248,21 @@ const CreateView = ({
-
+
{ return ( - {t("fields.email")} - + - ) }} @@ -282,11 +273,14 @@ const CreateView = ({ render={({ field }) => { return ( - {t("fields.firstName")} - + - ) }} @@ -297,11 +291,14 @@ const CreateView = ({ render={({ field }) => { return ( - {t("fields.lastName")} - + - ) }} @@ -312,15 +309,15 @@ const CreateView = ({ render={({ field }) => { return ( - {t("fields.password")} - ) }} @@ -331,22 +328,33 @@ const CreateView = ({ render={({ field }) => { return ( - {t("fields.repeatPassword")} - + - ) }} /> - {form.formState.errors.root && ( + {validationError && ( +
+ + {validationError} + +
+ )} + {serverError && ( - {form.formState.errors.root.message} + {serverError} )}
@@ -381,6 +389,14 @@ const SuccessView = () => { {t("invite.successAction")} + + + {t("invite.backToLogin")} +
) } diff --git a/packages/admin/dashboard/src/routes/login/login.tsx b/packages/admin/dashboard/src/routes/login/login.tsx index ec62128014..44081f4668 100644 --- a/packages/admin/dashboard/src/routes/login/login.tsx +++ b/packages/admin/dashboard/src/routes/login/login.tsx @@ -1,18 +1,18 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { Alert, Button, Heading, Input, Text } from "@medusajs/ui" +import { Alert, Button, Heading, Hint, Input, Text } from "@medusajs/ui" import { useForm } from "react-hook-form" import { Trans, useTranslation } from "react-i18next" import { Link, useLocation, useNavigate } from "react-router-dom" import * as z from "zod" -import { Divider } from "../../components/common/divider" import { Form } from "../../components/common/form" -import { LogoBox } from "../../components/common/logo-box" + import { useSignInWithEmailPassword } from "../../hooks/api/auth" import after from "virtual:medusa/widgets/login/after" import before from "virtual:medusa/widgets/login/before" import { isFetchError } from "../../lib/is-fetch-error" +import AvatarBox from "../../components/common/logo-box/avatar-box" const LoginSchema = z.object({ email: z.string().email(), @@ -68,11 +68,14 @@ export const Login = () => { }) const serverError = form.formState.errors?.root?.serverError?.message + const validationError = + form.formState.errors.email?.message || + form.formState.errors.password?.message return ( -
-
- +
+
+
{t("login.title")} @@ -92,18 +95,21 @@ export const Login = () => { onSubmit={handleSubmit} className="flex w-full flex-col gap-y-6" > -
+
{ return ( - {t("fields.email")} - + - ) }} @@ -114,29 +120,41 @@ export const Login = () => { render={({ field }) => { return ( - {t("fields.password")} + {} - ) }} />
+ {validationError && ( +
+ + {validationError} + +
+ )} + {serverError && ( + + {serverError} + + )} - {serverError && ( - - {serverError} - - )} {after.widgets.map((w, i) => { return ( @@ -146,15 +164,14 @@ export const Login = () => { ) })}
- - + , ]} />