SPB Git forge

spb/polyllm

Public
15commits 1branches 0releases
2.2 MBsize
maindefault branch
13 days agolast push
TypeScript 97.4% SQL 1% JavaScript 0.9% CSS 0.6%
2.1 KB · 55 lines tsx
Raw Blame History
1"use client";2import * as React from "react";3import { authClient } from "@/lib/auth-client";4import { Button } from "@/components/ui/button";5import { toast } from "@/components/ui/toast";6import { humanAuthError, type AuthClientError } from "./auth-errors";78export const RESEND_COOLDOWN_S = 30;910/** Ticks a cooldown down to zero. `start(seconds)` resets it. */11export function useCooldown(initial = 0) {12  const [left, setLeft] = React.useState(initial);13  React.useEffect(() => {14    if (left <= 0) return;15    const t = setTimeout(() => setLeft((v) => Math.max(0, v - 1)), 1000);16    return () => clearTimeout(t);17  }, [left]);18  return { left, start: (s: number) => setLeft(s) };19}2021export function ResendVerification({ email, initialCooldown = 0, variant = "outline", className }: { email: string; initialCooldown?: number; variant?: "outline" | "ghost" | "primary" | "link"; className?: string }) {22  const { left, start } = useCooldown(initialCooldown);23  const [loading, setLoading] = React.useState(false);2425  async function resend() {26    if (!email || loading || left > 0) return;27    setLoading(true);28    try {29      const { error } = await authClient.sendVerificationEmail({ email, callbackURL: "/verify-email" });30      if (error) {31        const e = error as AuthClientError;32        if (e.status === 429) {33          toast.error("Slow down", "Too many emails requested. Please wait a minute before trying again.");34          start(60);35        } else {36          toast.error("Couldn't send the email", humanAuthError(e, "verify"));37        }38        return;39      }40      toast.success("Verification email sent", `Check ${email} — the link is valid for 24 hours.`);41      start(RESEND_COOLDOWN_S);42    } catch {43      toast.error("Couldn't send the email", "Check your connection and try again.");44    } finally {45      setLoading(false);46    }47  }4849  return (50    <Button type="button" variant={variant} onClick={resend} loading={loading} disabled={left > 0 || !email} className={className} aria-live="polite">51      {left > 0 ? `Resend available in ${left}s` : "Resend verification email"}52    </Button>53  );54}55