Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Auth page when user login #107

Merged
merged 7 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .env.local.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Clerk. See https://clerk.com
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=
CLERK_SECRET_KEY=
# DO NOT modify
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/signin
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/join
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want this to be the home page or should it be /settings in the membership tab so that people have direct access to pay?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aftersignin here is not the main logic. if you want this, we have to do it code

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is for, like google login, redirect url

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, okay


# Database. Do not modify in development.
# Database (DO NOT modify in development)
DATABASE_URL=file:dev.sqlite
DATABASE_AUTH_TOKEN=

Expand Down
186 changes: 186 additions & 0 deletions src/app/(account)/forgot-password/ForgotPassword.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
'use client';

import Button from '@/components/Button';
import ControlledField from '@/components/ControlledField';
import FancyRectangle from '@/components/FancyRectangle';
import { useSignIn } from '@clerk/nextjs';
import { zodResolver } from '@hookform/resolvers/zod';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { handleClerkErrors } from '../helpers';
import { codeSchema, emailSchema, passwordSchema } from '../schemas';

const sendCodeSchema = z.object({
email: emailSchema,
});
const resetPasswordSchema = z
.object({
code: codeSchema,
password: passwordSchema,
confirmPassword: z.string().min(1, { message: 'Please confirm password' }),
})
.refine((data) => data.password === data.confirmPassword, {
message: 'Passwords do not match',
path: ['confirmPassword'],
});

const STEP_INSTRUCTIONS = [
'', // Step start from 1
'Enter your email to receive a reset code.',
'Enter your new password and the code received in your email.',
'Password reset complete!',
] as const;

export default function ForgotPassword() {
const [step, setStep] = useState(1);
const { isLoaded, signIn, setActive } = useSignIn();

const sendCodeForm = useForm<z.infer<typeof sendCodeSchema>>({
defaultValues: { email: '' },
resolver: zodResolver(sendCodeSchema),
});
const resetPasswordForm = useForm<z.infer<typeof resetPasswordSchema>>({
defaultValues: { code: '', password: '' },
resolver: zodResolver(resetPasswordSchema),
});

const [sendCodeLoading, setSendCodeLoading] = useState(false);
const [resetPasswordLoading, setResetPasswordLoading] = useState(false);

const handleSendCode = sendCodeForm.handleSubmit(async ({ email }) => {
if (!isLoaded) return;

setSendCodeLoading(true);

try {
const result = await signIn.create({
strategy: 'reset_password_email_code',
identifier: email,
});
if (result) {
setStep(2);
}
} catch (error) {
handleClerkErrors(error, sendCodeForm, [
{
code: 'form_identifier_not_found',
field: 'email',
message:
"Couldn't find account with given email. Please create an account first.",
},
{
code: 'form_conditional_param_value_disallowed',
field: 'email',
message: 'Account was created through Google. Please sign in using Google.',
},
]);
}

setSendCodeLoading(false);
});

const handleResetPassword = resetPasswordForm.handleSubmit(async ({ code, password }) => {
if (!isLoaded) return;

setResetPasswordLoading(true);

try {
const resetResult = await signIn.attemptFirstFactor({
strategy: 'reset_password_email_code',
code,
password,
});
if (resetResult.status === 'complete') {
setActive({ session: resetResult.createdSessionId });
setStep(3);
}
} catch (error) {
handleClerkErrors(error, resetPasswordForm, [
{
code: 'form_password_not_strong_enough',
field: 'password',
message:
'Given password is not strong enough. For account safety, please use a different password.',
},
{
code: 'form_password_not_strong_enough',
field: 'password',
message:
'Password has been found in an online data breach. For account safety, please use a different password.',
},
{
code: 'form_code_incorrect',
field: 'code',
message: 'Incorrect Code. Please enter the code from your email.',
},
]);
}

setResetPasswordLoading(false);
});

return (
<section className="w-full max-w-lg">
<FancyRectangle colour="purple" offset="8" filled fullWidth>
<div className="z-0 w-full border-4 border-black bg-white p-8 text-black md:p-12">
<h3 className="text-3xl font-bold">Forgot Your Password?</h3>
<p className="mb-8 text-xl">{STEP_INSTRUCTIONS[step]}</p>
{step === 1 && (
<form onSubmit={handleSendCode}>
<ControlledField
label="Email"
control={sendCodeForm.control}
name="email"
/>
<Button
colour="orange"
width="w-[19rem] md:w-[25rem]"
type="submit"
loading={sendCodeLoading}
>
Send Code
</Button>
</form>
)}

{step === 2 && (
<form onSubmit={handleResetPassword}>
<ControlledField
label="New password"
type="password"
control={resetPasswordForm.control}
name="password"
/>
<ControlledField
label="Confirm password"
type="password"
control={resetPasswordForm.control}
name="confirmPassword"
/>
<ControlledField
label="Reset code"
control={resetPasswordForm.control}
name="code"
/>
<Button
colour="orange"
width="w-[19rem] md:w-[25rem]"
type="submit"
loading={resetPasswordLoading}
>
Reset Password
</Button>
</form>
)}

{step === 3 && (
<Button href="/" colour="orange" width="w-[19rem] md:w-[25rem]">
Return to Home Page
</Button>
)}
</div>
</FancyRectangle>
</section>
);
}
Loading
Loading