import { Form, useActionData, useLoaderData } from '@remix-run/react'; import type { ActionArgs, LoaderArgs } from '@remix-run/server-runtime'; import { json } from '@remix-run/server-runtime'; import { redirect } from '@remix-run/server-runtime'; import { useState } from 'react'; import { z } from 'zod'; import { getPasswordStrength, getSignedInUser } from '../auth.server'; import { Alert } from '../components/Alert'; import { Button } from '../components/Button'; import { IconButton } from '../components/IconButton'; import { TextInput } from '../components/TextInput'; import { resetPassword } from '../data/zippo.server'; import { Eye } from '../icons/Eye'; import { EyeOff } from '../icons/EyeOff'; import { validateFormData } from '../utils/utils'; import { createFlashMessage } from '../utils/utils.server'; const zodResetPasswordModel = z.object({ password: z.string().min(1, { message: 'Password is required' }), email: z.string().email({ message: 'Email is required' }), token: z.string().min(1, { message: 'Token is required' }), }); type ActionInput = z.TypeOf; type WithGeneral = ActionInput & { general: string }; export async function action({ request }: ActionArgs) { const [user, headers] = await getSignedInUser(request); if (user) { throw redirect('/apps', { headers }); } const { body, errors } = validateFormData({ formData: await request.formData(), schema: zodResetPasswordModel, }); if (errors) { return json({ errors: errors as Partial, values: body }); } const [pwStrength, feedback] = getPasswordStrength(body.password); if (pwStrength < 4) { return json({ errors: { password: feedback.warning ? feedback.warning : feedback.suggestions?.[0] ?? 'Please enter a stronger password', // feedback.suggestions might be empty } as Partial, values: body, }); } const success = await resetPassword({ password: body.password, verificationToken: body.token }); if (success.result !== 'SUCCESS') { return json({ errors: { general: 'There was an issue resetting your password. Please try again.', } as Partial, values: body, }); } const flashHeaders = await createFlashMessage( request, 'pw-reset-success', 'Password reset successfully. Please log in.', ); throw redirect('/login', { headers: flashHeaders }); } export async function loader({ request }: LoaderArgs) { const [user, headers] = await getSignedInUser(request); if (user) { throw redirect('/apps', { headers }); } const url = new URL(request.url); const token = url.searchParams.get('token'); const email = url.searchParams.get('email'); if (!token || !email) { throw redirect('/reset-password'); } return { token, email }; } export default function SetNewPassword() { const { email, token } = useLoaderData(); const actionData = useActionData(); const [showPassword, setShowPassword] = useState(false); return (
{(actionData?.errors.email || actionData?.errors.token || actionData?.errors.general) && ( {actionData?.errors.email || actionData?.errors.token || actionData?.errors.general} )}

Type your new password for {email}

setShowPassword(!showPassword)} color="white" className="h-11 w-11 shadow-md" size="xs" roundness="sm" type="button" aria-label={showPassword ? 'Hide password' : 'Show password'} > {showPassword ? : } } />
); }