From 19d8d31f562bb0ba75e7ee06ef5fe52b2cbe2495 Mon Sep 17 00:00:00 2001 From: Anton Bochkovskyi <98012691+firehawk89@users.noreply.github.com> Date: Wed, 31 Jan 2024 19:42:04 +0200 Subject: [PATCH] Add Verification Page (#101) PR: https://github.com/dev-KPI/messenger-frontend/pull/101 --- project-words.txt | 1 + src/app/auth/page.tsx | 32 ++++----- src/app/layout.tsx | 4 +- src/app/profile/page.tsx | 32 ++++----- src/app/verification/page.tsx | 22 ++++++ src/components/pages/auth-content.tsx | 22 ++++++ src/components/pages/auth/form-auth.tsx | 15 ++-- src/components/pages/profile/form-profile.tsx | 4 +- .../pages/verification/control-otp.tsx | 69 +++++++++++++++++++ .../{auth => verification}/otp-input.tsx | 2 +- src/components/ui/button.tsx | 5 +- src/components/ui/content.tsx | 8 +-- src/components/ui/icons.tsx | 36 ++++++++++ .../{pages/auth => ui}/image-card.tsx | 6 +- src/components/ui/theme-toggler.tsx | 8 +-- 15 files changed, 199 insertions(+), 67 deletions(-) create mode 100644 src/app/verification/page.tsx create mode 100644 src/components/pages/auth-content.tsx create mode 100644 src/components/pages/verification/control-otp.tsx rename src/components/pages/{auth => verification}/otp-input.tsx (95%) rename src/components/{pages/auth => ui}/image-card.tsx (63%) diff --git a/project-words.txt b/project-words.txt index dcfb3c9..4f6896a 100644 --- a/project-words.txt +++ b/project-words.txt @@ -11,3 +11,4 @@ linejoin mingcute shadcn clsx +didn diff --git a/src/app/auth/page.tsx b/src/app/auth/page.tsx index ad2fb6a..31c5da8 100644 --- a/src/app/auth/page.tsx +++ b/src/app/auth/page.tsx @@ -1,26 +1,22 @@ import FormAuth from '@/components/pages/auth/form-auth' -import ImageCard from '@/components/pages/auth/image-card' -import Content from '@/components/ui/content' +import AuthContent from '@/components/pages/auth-content' import { Icons } from '@/components/ui/icons' +import ImageCard from '@/components/ui/image-card' import { ThemeToggler } from '@/components/ui/theme-toggler' export default function Auth() { return ( -
- -
- - - -
-
-

Authentication

- -
- -
-
-
-
+ + + + +
+
+

Authentication

+ +
+ +
+
) } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index fb6f272..8017a66 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -14,7 +14,9 @@ const Layout: FC = ({ children } = { children: [] }) => { return ( - {children} + +
{children}
+
diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx index fdeb527..e649bcb 100644 --- a/src/app/profile/page.tsx +++ b/src/app/profile/page.tsx @@ -1,26 +1,22 @@ -import ImageCard from '@/components/pages/auth/image-card' +import AuthContent from '@/components/pages/auth-content' import FileInput from '@/components/pages/profile/file-input' import FormProfile from '@/components/pages/profile/form-profile' -import Content from '@/components/ui/content' +import ImageCard from '@/components/ui/image-card' import { ThemeToggler } from '@/components/ui/theme-toggler' export default function Profile() { return ( -
- -
- - - -
-
-

Profile

- -
- -
-
-
-
+ + + + +
+
+

Profile

+ +
+ +
+
) } diff --git a/src/app/verification/page.tsx b/src/app/verification/page.tsx new file mode 100644 index 0000000..2fe206b --- /dev/null +++ b/src/app/verification/page.tsx @@ -0,0 +1,22 @@ +import AuthContent from '@/components/pages/auth-content' +import ControlOtp from '@/components/pages/verification/control-otp' +import { Icons } from '@/components/ui/icons' +import ImageCard from '@/components/ui/image-card' +import { ThemeToggler } from '@/components/ui/theme-toggler' + +export default function Verification() { + return ( + + + + +
+
+

Check your Email

+ +
+ +
+
+ ) +} diff --git a/src/components/pages/auth-content.tsx b/src/components/pages/auth-content.tsx new file mode 100644 index 0000000..be7b665 --- /dev/null +++ b/src/components/pages/auth-content.tsx @@ -0,0 +1,22 @@ +import Content from '@/components/ui/content' +import { cn } from '@/lib/utils' +import { FC, ReactNode } from 'react' + +type AuthContentProps = { + children: ReactNode + className?: string +} + +const AuthContent: FC = ({ children, className }) => { + return ( +
+ +
+ {children} +
+
+
+ ) +} + +export default AuthContent diff --git a/src/components/pages/auth/form-auth.tsx b/src/components/pages/auth/form-auth.tsx index 946df23..57fee4d 100644 --- a/src/components/pages/auth/form-auth.tsx +++ b/src/components/pages/auth/form-auth.tsx @@ -1,6 +1,5 @@ 'use client' -import OtpInput from '@/components/pages/auth/otp-input' import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' import { @@ -12,10 +11,9 @@ import { FormMessage, } from '@/components/ui/form' import { Input } from '@/components/ui/input' -import { LENGTH_OTP } from '@/constants' -import { classnames } from '@/utils' +import { cn } from '@/lib/utils' import { zodResolver } from '@hookform/resolvers/zod' -import { FC, useState } from 'react' +import { FC } from 'react' import { useForm } from 'react-hook-form' import * as z from 'zod' @@ -27,8 +25,6 @@ const formSchema = z.object({ }) const AuthForm: FC = ({ className }) => { - const [otp, setOtp] = useState('') - const form = useForm>({ defaultValues: { agreement: false, @@ -37,17 +33,15 @@ const AuthForm: FC = ({ className }) => { resolver: zodResolver(formSchema), }) - const otpChange = (value: string) => setOtp(value.trim()) - function onSubmit(values: z.infer) { - alert(JSON.stringify({ ...values, otp })) + alert(JSON.stringify(values)) console.log(values) } return (
= ({ className }) => { )} /> - = ({ className }) => { return ( = ({ className }) => { + const [otp, setOtp] = useState('') + const [otpIsInvalid, setOtpIsInvalid] = useState(false) + + const otpIncomplete = otp.length < LENGTH_OTP + + const otpChange = (value: string) => { + if (otpIsInvalid) { + setOtpIsInvalid(false) + } + setOtp(value.trim()) + } + + const validateOtp = () => { + if (otp !== MOCK_OTP) { + setOtpIsInvalid(true) + return + } + + // TODO: send otp to server + } + + return ( +
+

+ {otpIsInvalid + ? 'The code is not correct. Try again' + : 'Paste dynamically generated code'} +

+ + + +
+ ) +} + +export default ControlOtp diff --git a/src/components/pages/auth/otp-input.tsx b/src/components/pages/verification/otp-input.tsx similarity index 95% rename from src/components/pages/auth/otp-input.tsx rename to src/components/pages/verification/otp-input.tsx index 2190309..ad4f76f 100644 --- a/src/components/pages/auth/otp-input.tsx +++ b/src/components/pages/verification/otp-input.tsx @@ -142,7 +142,7 @@ const OtpInput: FC = ({ = ({ children, className }) => { - return ( -
- {children} -
- ) + return
{children}
} export default Content diff --git a/src/components/ui/icons.tsx b/src/components/ui/icons.tsx index 4d546d3..a25f1bc 100644 --- a/src/components/ui/icons.tsx +++ b/src/components/ui/icons.tsx @@ -82,6 +82,24 @@ export const Icons = { /> ), + moon: ({ size, ...props }: IconProps) => { + const dimension = getIconDimension(size) + return ( + + + + ) + }, photo_profile: (props: IconProps) => ( ), + sun: ({ size, ...props }: IconProps) => { + const dimension = getIconDimension(size) + return ( + + + + ) + }, } diff --git a/src/components/pages/auth/image-card.tsx b/src/components/ui/image-card.tsx similarity index 63% rename from src/components/pages/auth/image-card.tsx rename to src/components/ui/image-card.tsx index 05e1269..eabd771 100644 --- a/src/components/pages/auth/image-card.tsx +++ b/src/components/ui/image-card.tsx @@ -1,4 +1,4 @@ -import { classnames } from '@/utils' +import { cn } from '@/lib/utils' import { FC, ReactNode } from 'react' type ImageCardProps = { @@ -9,8 +9,8 @@ type ImageCardProps = { const ImageCard: FC = ({ children, className }) => { return (
diff --git a/src/components/ui/theme-toggler.tsx b/src/components/ui/theme-toggler.tsx index 269ffcd..33d3885 100644 --- a/src/components/ui/theme-toggler.tsx +++ b/src/components/ui/theme-toggler.tsx @@ -7,7 +7,7 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { Moon, Sun } from 'lucide-react' +import { Icons } from '@/components/ui/icons' import { useTheme } from 'next-themes' import * as React from 'react' @@ -21,9 +21,9 @@ export function ThemeToggler() { return ( -