diff --git a/frontend/app/(auth)/forgot-password/page.tsx b/frontend/app/(auth)/forgot-password/page.tsx
index e64ec57..c3b421e 100644
--- a/frontend/app/(auth)/forgot-password/page.tsx
+++ b/frontend/app/(auth)/forgot-password/page.tsx
@@ -7,6 +7,7 @@ import { AuthShell, Field, FormAlert } from "@/components/auth/auth-ui";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { authClient } from "@/lib/auth-client";
+import { notify } from "@/lib/toast";
export default function ForgotPasswordPage() {
const [email, setEmail] = useState("");
@@ -27,9 +28,12 @@ export default function ForgotPasswordPage() {
setSubmitting(false);
if (err) {
- setError(err.message ?? "Could not send the reset email.");
+ const message = err.message ?? "Could not send the reset email.";
+ setError(message);
+ notify.error("Couldn't send reset link", message);
return;
}
+ notify.success("Reset link sent", "Check your inbox for the link.");
setSent(true);
};
diff --git a/frontend/app/(auth)/onboarding/page.tsx b/frontend/app/(auth)/onboarding/page.tsx
index 67155a1..bdcea5d 100644
--- a/frontend/app/(auth)/onboarding/page.tsx
+++ b/frontend/app/(auth)/onboarding/page.tsx
@@ -7,6 +7,7 @@ import { AuthShell, Field, FormAlert } from "@/components/auth/auth-ui";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { authClient } from "@/lib/auth-client";
+import { notify } from "@/lib/toast";
function slugify(value: string): string {
return value
@@ -45,12 +46,15 @@ export default function OnboardingPage() {
);
if (createErr || !org) {
- setError(createErr?.message ?? "Could not create the clinic.");
+ const message = createErr?.message ?? "Could not create the clinic.";
+ setError(message);
+ notify.error("Couldn't create clinic", message);
setSubmitting(false);
return;
}
await authClient.organization.setActive({ organizationId: org.id });
+ notify.success("Clinic created", `${org.name} is ready.`);
router.push("/");
};
diff --git a/frontend/app/(auth)/reset-password/page.tsx b/frontend/app/(auth)/reset-password/page.tsx
index c45a87d..7259e56 100644
--- a/frontend/app/(auth)/reset-password/page.tsx
+++ b/frontend/app/(auth)/reset-password/page.tsx
@@ -8,6 +8,7 @@ import { AuthShell, Field, FormAlert } from "@/components/auth/auth-ui";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { authClient } from "@/lib/auth-client";
+import { notify } from "@/lib/toast";
const MIN_PASSWORD = 12;
@@ -46,9 +47,12 @@ function ResetPasswordInner() {
});
setSubmitting(false);
if (err) {
- setError(err.message ?? "Could not reset your password.");
+ const message = err.message ?? "Could not reset your password.";
+ setError(message);
+ notify.error("Couldn't reset password", message);
return;
}
+ notify.success("Password updated", "Redirecting you to sign in…");
setDone(true);
setTimeout(() => router.push("/login"), 1500);
};
diff --git a/frontend/app/globals.css b/frontend/app/globals.css
index 2a35832..5f741e4 100644
--- a/frontend/app/globals.css
+++ b/frontend/app/globals.css
@@ -59,7 +59,51 @@
background-position: -200% 0;
}
}
-}
+ --animate-toast-success-odd: toast-success-odd 0.32s cubic-bezier(0.5, 1, 0.89, 1);
+ --animate-toast-success-even: toast-success-even 0.32s cubic-bezier(0.5, 1, 0.89, 1);
+ --animate-toast-error-odd: toast-error-odd 0.28s cubic-bezier(0.5, 1, 0.89, 1);
+ --animate-toast-error-even: toast-error-even 0.28s cubic-bezier(0.5, 1, 0.89, 1)
+;
+ @keyframes toast-success-odd {
+ 0% {
+ scale: 1;}
+ 30% {
+ scale: 1.025;}
+ 60% {
+ scale: 0.99;}
+ 100% {
+ scale: 1;}}
+ @keyframes toast-error-odd {
+ 0% {
+ translate: 0 0;}
+ 25% {
+ translate: -3px 0;}
+ 50% {
+ translate: 3px 0;}
+ 75% {
+ translate: -3px 0;}
+ 100% {
+ translate: 0 0;}}
+ @keyframes toast-success-even {
+ 0% {
+ scale: 1;}
+ 30% {
+ scale: 1.025;}
+ 60% {
+ scale: 0.99;}
+ 100% {
+ scale: 1;}}
+ @keyframes toast-error-even {
+ 0% {
+ translate: 0 0;}
+ 25% {
+ translate: -3px 0;}
+ 50% {
+ translate: 3px 0;}
+ 75% {
+ translate: -3px 0;}
+ 100% {
+ translate: 0 0;}}}
:root {
--card: var(--color-white);
diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx
index b673e65..8a1072a 100644
--- a/frontend/app/layout.tsx
+++ b/frontend/app/layout.tsx
@@ -4,6 +4,7 @@ import "./globals.css";
import { cn } from "@/lib/utils";
import { ThemeProvider } from "@/components/theme-provider";
import { I18nProvider } from "@/components/i18n-provider";
+import { ToastProvider } from "@/components/ui/toast";
// COSS font-variable contract: --font-sans, --font-heading, --font-mono.
const inter = Inter({ subsets: ["latin"], variable: "--font-sans" });
@@ -48,7 +49,9 @@ export default function RootLayout({
enableSystem
disableTransitionOnChange
>
- {children}
+
+ {children}
+