Skip to content

Commit 0d5d7a3

Browse files
committed
refactor: Extract registration logic to separate actions file
1 parent c50ed91 commit 0d5d7a3

File tree

2 files changed

+136
-110
lines changed

2 files changed

+136
-110
lines changed
+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
'use server'
2+
3+
import { redirect } from 'next/navigation'
4+
import { z } from 'zod'
5+
import { signIn } from '@/lib/auth'
6+
import axiosInstance from '@/utils/axios'
7+
8+
// Form validation schema
9+
const formSchema = z
10+
.object({
11+
firstName: z
12+
.string()
13+
.min(3, { message: 'First Name must be at least 3 characters.' }),
14+
lastName: z
15+
.string()
16+
.min(3, { message: 'Last Name must be at least 3 characters.' }),
17+
email: z
18+
.string()
19+
.email({ message: 'Please provide a valid email address.' }),
20+
password: z
21+
.string()
22+
.min(5, { message: 'Password must be at least 5 characters long.' }),
23+
confirmPassword: z.string(),
24+
})
25+
.refine((data) => data.password === data.confirmPassword, {
26+
message: 'Passwords must match.',
27+
path: ['confirmPassword'],
28+
})
29+
30+
export async function registerUser(state: { error?: string }, formData: FormData) {
31+
try {
32+
// Extract and validate form data
33+
const rawFormData = {
34+
firstName: formData.get('firstName') as string,
35+
lastName: formData.get('lastName') as string,
36+
email: formData.get('email') as string,
37+
password: formData.get('password') as string,
38+
confirmPassword: formData.get('confirmPassword') as string,
39+
}
40+
41+
// Validate form data
42+
const validationResult = formSchema.safeParse(rawFormData)
43+
if (!validationResult.success) {
44+
const formattedErrors = validationResult.error.format()
45+
const errorMessages = []
46+
47+
if (formattedErrors.firstName?._errors) {
48+
errorMessages.push(formattedErrors.firstName._errors[0])
49+
}
50+
if (formattedErrors.lastName?._errors) {
51+
errorMessages.push(formattedErrors.lastName._errors[0])
52+
}
53+
if (formattedErrors.email?._errors) {
54+
errorMessages.push(formattedErrors.email._errors[0])
55+
}
56+
if (formattedErrors.password?._errors) {
57+
errorMessages.push(formattedErrors.password._errors[0])
58+
}
59+
if (formattedErrors.confirmPassword?._errors) {
60+
errorMessages.push(formattedErrors.confirmPassword._errors[0])
61+
}
62+
63+
return { error: errorMessages.join(', ') }
64+
}
65+
66+
const { firstName, lastName, email, password } = validationResult.data
67+
68+
try {
69+
// Use axios instance instead of fetch
70+
await axiosInstance.post('/api/auth/register', {
71+
firstName,
72+
lastName,
73+
email,
74+
password,
75+
});
76+
77+
// Sign in the user after successful registration
78+
await signIn('credentials', {
79+
email,
80+
password,
81+
redirect: false,
82+
})
83+
84+
// Redirect to dashboard on success
85+
redirect('/dashboard')
86+
} catch (error: any) {
87+
console.error('Registration error:', error)
88+
89+
// Handle sign-in error
90+
if (error.message?.includes('sign')) {
91+
return { error: 'Registration successful, but sign-in failed. Please try logging in.' }
92+
}
93+
94+
// Handle axios error response
95+
if (error.response) {
96+
// The request was made and the server responded with a status code
97+
// that falls out of the range of 2xx
98+
return { error: error.response.data.error || 'Registration failed' }
99+
} else if (error.request) {
100+
// The request was made but no response was received
101+
return { error: 'No response from server. Please try again later.' }
102+
} else {
103+
// Something happened in setting up the request that triggered an Error
104+
return { error: error.message || 'An error occurred during registration' }
105+
}
106+
}
107+
} catch (error: any) {
108+
console.error('Unexpected error during registration:', error)
109+
return { error: error.message || 'An unexpected error occurred' }
110+
}
111+
}

src/app/(admin)/(auth)/register/page.tsx

+25-110
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,10 @@
11
import { redirect } from 'next/navigation'
2-
import { z } from 'zod'
32

3+
import { checkAdminExists } from '@/lib/auth-helpers'
44
import { Input } from '@/components/ui/input'
55
import { Separator } from '@/components/ui/separator'
6-
import { signIn } from '@/lib/auth'
7-
import { checkAdminExists } from '@/lib/auth-helpers'
8-
import axiosInstance from '@/utils/axios'
96
import FormWrapper, { SubmitButton } from './form-wrapper'
10-
11-
// Form validation schema
12-
const formSchema = z
13-
.object({
14-
firstName: z
15-
.string()
16-
.min(3, { message: 'First Name must be at least 3 characters.' }),
17-
lastName: z
18-
.string()
19-
.min(3, { message: 'Last Name must be at least 3 characters.' }),
20-
email: z
21-
.string()
22-
.email({ message: 'Please provide a valid email address.' }),
23-
password: z
24-
.string()
25-
.min(5, { message: 'Password must be at least 5 characters long.' }),
26-
confirmPassword: z.string(),
27-
})
28-
.refine((data) => data.password === data.confirmPassword, {
29-
message: 'Passwords must match.',
30-
path: ['confirmPassword'],
31-
})
32-
33-
// Server action for form submission
34-
async function registerUser(state: { error?: string }, formData: FormData) {
35-
'use server'
36-
37-
try {
38-
// Extract and validate form data
39-
const rawFormData = {
40-
firstName: formData.get('firstName') as string,
41-
lastName: formData.get('lastName') as string,
42-
email: formData.get('email') as string,
43-
password: formData.get('password') as string,
44-
confirmPassword: formData.get('confirmPassword') as string,
45-
}
46-
47-
// Validate form data
48-
const validationResult = formSchema.safeParse(rawFormData)
49-
if (!validationResult.success) {
50-
const formattedErrors = validationResult.error.format()
51-
const errorMessages = []
52-
53-
if (formattedErrors.firstName?._errors) {
54-
errorMessages.push(formattedErrors.firstName._errors[0])
55-
}
56-
if (formattedErrors.lastName?._errors) {
57-
errorMessages.push(formattedErrors.lastName._errors[0])
58-
}
59-
if (formattedErrors.email?._errors) {
60-
errorMessages.push(formattedErrors.email._errors[0])
61-
}
62-
if (formattedErrors.password?._errors) {
63-
errorMessages.push(formattedErrors.password._errors[0])
64-
}
65-
if (formattedErrors.confirmPassword?._errors) {
66-
errorMessages.push(formattedErrors.confirmPassword._errors[0])
67-
}
68-
69-
return { error: errorMessages.join(', ') }
70-
}
71-
72-
const { firstName, lastName, email, password } = validationResult.data
73-
74-
await axiosInstance.post('/api/auth/register', {
75-
firstName,
76-
lastName,
77-
email,
78-
password,
79-
})
80-
81-
await signIn('credentials', {
82-
email,
83-
password,
84-
redirect: false,
85-
})
86-
87-
redirect('/dashboard')
88-
} catch (error: any) {
89-
console.error('Unexpected error during registration:', error)
90-
return { error: error.message || 'An unexpected error occurred' }
91-
}
92-
}
7+
import { registerUser } from './actions'
938

949
export default async function RegisterPage() {
9510
const adminExists = await checkAdminExists()
@@ -112,67 +27,67 @@ export default async function RegisterPage() {
11227
<label htmlFor='firstName' className='text-sm font-medium'>
11328
First Name
11429
</label>
115-
<Input
30+
<Input
11631
id='firstName'
117-
name='firstName'
118-
placeholder='John'
119-
required
32+
name='firstName'
33+
placeholder='John'
34+
required
12035
minLength={3}
12136
/>
12237
</div>
12338
<div className='w-1/2'>
12439
<label htmlFor='lastName' className='text-sm font-medium'>
12540
Last Name
12641
</label>
127-
<Input
42+
<Input
12843
id='lastName'
129-
name='lastName'
130-
placeholder='Doe'
131-
required
44+
name='lastName'
45+
placeholder='Doe'
46+
required
13247
minLength={3}
13348
/>
13449
</div>
13550
</div>
136-
51+
13752
{/* Email Section */}
13853
<div>
13954
<label htmlFor='email' className='text-sm font-medium'>
14055
Email
14156
</label>
142-
<Input
57+
<Input
14358
id='email'
144-
name='email'
59+
name='email'
14560
type='email'
146-
placeholder='johndoe@xyz.com'
147-
required
61+
placeholder='johndoe@xyz.com'
62+
required
14863
/>
14964
</div>
150-
65+
15166
{/* Password Section */}
15267
<div>
15368
<label htmlFor='password' className='text-sm font-medium'>
15469
Password
15570
</label>
156-
<Input
71+
<Input
15772
id='password'
158-
name='password'
73+
name='password'
15974
type='password'
160-
placeholder='••••••••'
161-
required
75+
placeholder='••••••••'
76+
required
16277
minLength={5}
16378
/>
16479
</div>
165-
80+
16681
<div>
16782
<label htmlFor='confirmPassword' className='text-sm font-medium'>
16883
Confirm Password
16984
</label>
170-
<Input
85+
<Input
17186
id='confirmPassword'
172-
name='confirmPassword'
87+
name='confirmPassword'
17388
type='password'
174-
placeholder='••••••••'
175-
required
89+
placeholder='••••••••'
90+
required
17691
/>
17792
</div>
17893

0 commit comments

Comments
 (0)