diff --git a/TODO.md b/TODO.md index 8af4f5d2..d0552bac 100644 --- a/TODO.md +++ b/TODO.md @@ -8,6 +8,6 @@ X Style verify email X Clean out route names (make components/home components/dashboard so app/home can be there) X Add update password X Add reset password - https://github.com/alexrusin/nextjs-cognito-auth/tree/5-reset-password-end + X Add resend verification email - Clean up dashboard template - Deploy to AWS (SST) -- Add resend verification email diff --git a/frontend/src/app/(app)/accounts/page.tsx b/frontend/src/app/(app)/contacts/page.tsx similarity index 52% rename from frontend/src/app/(app)/accounts/page.tsx rename to frontend/src/app/(app)/contacts/page.tsx index 4decfb33..2915b87e 100644 --- a/frontend/src/app/(app)/accounts/page.tsx +++ b/frontend/src/app/(app)/contacts/page.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import { Accounts } from '@/components/accounts'; +import { Contacts } from '@/components/contacts'; const accounts = () => { - return ; + return ; }; export default accounts; diff --git a/frontend/src/components/auth/reset-password.tsx b/frontend/src/components/auth/reset-password.tsx index 5f6a2ade..226a59e7 100644 --- a/frontend/src/components/auth/reset-password.tsx +++ b/frontend/src/components/auth/reset-password.tsx @@ -3,7 +3,7 @@ import { Button } from '@/components/ui/button'; import { useFormState, useFormStatus } from 'react-dom'; import { handleResetPassword } from '@/lib/cognitoActions'; -import { AtSignIcon, CircleCheckIcon, TriangleAlertIcon } from 'lucide-react'; +import { CircleCheckIcon, TriangleAlertIcon } from 'lucide-react'; import { Card, CardContent, CardHeader, CardDescription, CardTitle, CardFooter } from '../ui/card'; import { Label } from '../ui/label'; import { Input } from '../ui/input'; @@ -24,7 +24,6 @@ export default function ResetPasswordFrom() { Email - {errorMessage && ( diff --git a/frontend/src/components/auth/verify-form.tsx b/frontend/src/components/auth/verify-form.tsx index c3380dcc..c03275fe 100644 --- a/frontend/src/components/auth/verify-form.tsx +++ b/frontend/src/components/auth/verify-form.tsx @@ -1,13 +1,23 @@ 'use client'; +import { useFormState } from 'react-dom'; import { Card, CardContent, CardDescription, CardHeader, CardFooter, CardTitle } from '@/components/ui/card'; import { Button, buttonVariants } from '@/components/ui/button'; import Link from 'next/link'; import { cn } from '@/lib/utils'; +import { handleSendEmailVerification } from '@/lib/cognitoActions'; +import { Input } from '@nextui-org/react'; +import { useSearchParams } from 'next/navigation'; +import { TriangleAlertIcon } from 'lucide-react'; export default function VerifyForm() { + const [result, dispatch] = useFormState(handleSendEmailVerification, { message: '', errorMessage: '' }); + + const params = useSearchParams(); + const email = params.get('email') ?? ''; + return ( -
+
Verify Email @@ -20,6 +30,9 @@ export default function VerifyForm() {

Please check your email and click on the verification link to proceed.

+
+ +

Didn't receive an email?

+ {(result.message || result.errorMessage) && ( +
+ {result.errorMessage && ( + <> + +

Could not resend verification email.

+ + )} + {result.message &&

{result.message}

} +
+ )} - + Sign In - + ); } diff --git a/frontend/src/components/accounts/add-user.tsx b/frontend/src/components/contacts/add-user.tsx similarity index 100% rename from frontend/src/components/accounts/add-user.tsx rename to frontend/src/components/contacts/add-user.tsx diff --git a/frontend/src/components/accounts/index.tsx b/frontend/src/components/contacts/index.tsx similarity index 98% rename from frontend/src/components/accounts/index.tsx rename to frontend/src/components/contacts/index.tsx index ee0dc2c0..72f5c695 100644 --- a/frontend/src/components/accounts/index.tsx +++ b/frontend/src/components/contacts/index.tsx @@ -12,7 +12,7 @@ import { SettingsIcon } from '@/components/icons/sidebar/settings-icon'; import { TableWrapper } from '@/components/table/table'; import { AddUser } from './add-user'; -export const Accounts = () => { +export const Contacts = () => { return (
    diff --git a/frontend/src/components/sidebar/sidebar.tsx b/frontend/src/components/sidebar/sidebar.tsx index 93608c98..67a03402 100644 --- a/frontend/src/components/sidebar/sidebar.tsx +++ b/frontend/src/components/sidebar/sidebar.tsx @@ -19,6 +19,7 @@ import { FilterIcon } from '../icons/sidebar/filter-icon'; import { useSidebarContext } from '../layout/layout-context'; import { ChangeLogIcon } from '../icons/sidebar/changelog-icon'; import { usePathname } from 'next/navigation'; +import { UserIcon } from 'lucide-react'; export const SidebarWrapper = () => { const pathname = usePathname(); @@ -39,9 +40,9 @@ export const SidebarWrapper = () => {
    } isActive={pathname === '/dashboard'} href='/dashboard' /> - } href='accounts' /> + } items={['Banks Accounts', 'Credit Cards', 'Loans']} title='Balances' /> } /> - } items={['Banks Accounts', 'Credit Cards', 'Loans']} title='Balances' /> + } href='contacts' /> } /> } /> } /> diff --git a/frontend/src/lib/cognitoActions.ts b/frontend/src/lib/cognitoActions.ts index 73c60ceb..bbe65dbe 100644 --- a/frontend/src/lib/cognitoActions.ts +++ b/frontend/src/lib/cognitoActions.ts @@ -32,18 +32,19 @@ export async function handleSignUp(prevState: string | undefined, formData: Form } catch (error) { return getErrorMessage(error); } - redirect('/auth/verify'); + redirect('/auth/verify?email=' + encodeURIComponent(String(formData.get('email')))); } -export async function handleSendEmailVerificationCode(prevState: { message: string; errorMessage: string }, formData: FormData) { +export async function handleSendEmailVerification(prevState: { message: string; errorMessage: string }, formData: FormData) { let currentState; try { + // Sends verificaiton email (despite the funciton name saying 'code') await resendSignUpCode({ username: String(formData.get('email')), }); currentState = { ...prevState, - message: 'Code sent successfully', + message: 'Verification email sent successfully', }; } catch (error) { currentState = { @@ -55,20 +56,6 @@ export async function handleSendEmailVerificationCode(prevState: { message: stri return currentState; } -export async function handleConfirmSignUp(prevState: string | undefined, formData: FormData) { - try { - const { isSignUpComplete, nextStep } = await confirmSignUp({ - username: String(formData.get('email')), - confirmationCode: String(formData.get('code')), - }); - - autoSignIn(); - } catch (error) { - return getErrorMessage(error); - } - redirect('/auth/login'); -} - export async function handleSignIn(prevState: string | undefined, formData: FormData) { let redirectLink = '/dashboard'; try { @@ -85,6 +72,7 @@ export async function handleSignIn(prevState: string | undefined, formData: Form } catch (error) { return getErrorMessage(error); } + nextRedirect(redirectLink); } @@ -101,52 +89,6 @@ export async function handleSignOut() { nextRedirect('/'); } -export async function handleUpdateUserAttribute(prevState: string, formData: FormData) { - let attributeKey = 'given_name'; - let attributeValue; - let currentAttributeValue; - - if (formData.get('email')) { - attributeKey = 'email'; - attributeValue = formData.get('email'); - currentAttributeValue = formData.get('current_email'); - } else { - attributeValue = formData.get('name'); - currentAttributeValue = formData.get('current_name'); - } - - console.log('AttributeValue', attributeValue); - - if (attributeValue === currentAttributeValue) { - return ''; - } - - try { - const output = await updateUserAttribute({ - userAttribute: { - attributeKey: String(attributeKey), - value: String(attributeValue), - }, - }); - return handleUpdateUserAttributeNextSteps(output); - } catch (error) { - console.log(error); - return 'error'; - } -} - -function handleUpdateUserAttributeNextSteps(output: UpdateUserAttributeOutput) { - const { nextStep } = output; - - switch (nextStep.updateAttributeStep) { - case 'CONFIRM_ATTRIBUTE_WITH_CODE': - const codeDeliveryDetails = nextStep.codeDeliveryDetails; - return `Confirmation code was sent to ${codeDeliveryDetails?.deliveryMedium}.`; - case 'DONE': - return 'success'; - } -} - export async function handleUpdatePassword(prevState: 'success' | 'error' | undefined, formData: FormData) { const currentPassword = formData.get('current_password'); const newPassword = formData.get('new_password');