import { useEffect, useMemo, useState } from "react"; import { useNavigate, useSearchParams } from "react-router-dom"; import { useMutation, useQuery } from "@tanstack/react-query"; import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { authService } from "@/services/auth.service"; import { brandingService } from "@/services/branding.service"; import { cn } from "@/lib/utils"; import { toast } from "sonner"; const schema = z .object({ password: z.string().min(8, "At least 8 characters"), confirm: z.string(), }) .refine((d) => d.password === d.confirm, { message: "Passwords must match", path: ["confirm"] }); type FormValues = z.infer; function strengthLabel(p: string): "weak" | "medium" | "strong" { let s = 0; if (p.length >= 8) s++; if (p.length >= 12) s++; if (/[A-Z]/.test(p) && /[a-z]/.test(p)) s++; if (/\d/.test(p)) s++; if (/[^A-Za-z0-9]/.test(p)) s++; if (s <= 2) return "weak"; if (s <= 4) return "medium"; return "strong"; } export default function ResetPassword() { const [searchParams] = useSearchParams(); const token = searchParams.get("token") ?? ""; const navigate = useNavigate(); const { data: branding } = useQuery({ queryKey: ["branding", "current"], queryFn: () => brandingService.getCurrentBranding(), }); const entityName = branding?.entity_name ?? "your organization"; const form = useForm({ resolver: zodResolver(schema), defaultValues: { password: "", confirm: "" }, }); const pwd = form.watch("password"); const strength = useMemo(() => strengthLabel(pwd), [pwd]); useEffect(() => { const root = document.documentElement; if (branding?.primary_color) root.style.setProperty("--encoach-brand-primary", branding.primary_color); if (branding?.secondary_color) root.style.setProperty("--encoach-brand-secondary", branding.secondary_color); if (branding?.background_color) root.style.setProperty("--encoach-brand-bg", branding.background_color); return () => { root.style.removeProperty("--encoach-brand-primary"); root.style.removeProperty("--encoach-brand-secondary"); root.style.removeProperty("--encoach-brand-bg"); }; }, [branding]); const submitMut = useMutation({ mutationFn: (values: FormValues) => authService.setInvitePassword({ token, password: values.password }), onSuccess: () => { toast.success("Password saved."); navigate("/student/placement", { replace: true }); }, onError: (e) => toast.error(e instanceof Error ? e.message : "Could not set password"), }); const onSubmit = (values: FormValues) => { if (!token) { toast.error("Missing invite token."); return; } submitMut.mutate(values); }; return (
Welcome to {entityName}'s Learning Platform Set a new password
( New password
{pwd ? `${strength.charAt(0).toUpperCase() + strength.slice(1)} password` : " "}
)} /> ( Confirm password )} />
); }