diff --git a/app/(auth)/layout.tsx b/app/(auth)/layout.tsx
index a5a19baa..35e362a7 100644
--- a/app/(auth)/layout.tsx
+++ b/app/(auth)/layout.tsx
@@ -4,7 +4,7 @@ import { currentUser } from "@/lib/auth/current-user";
import { AuthLogoSection } from "@/components/wrappers/auth/auth-logo-section";
import { env } from "@/env.mjs";
import { Heart } from "lucide-react";
-import { AuthLayout } from "@/components/wrappers/auth/auth-layout";
+import { ErrorLayout } from "@/components/wrappers/common/error-layout";
export default async function Layout({
children,
@@ -24,7 +24,7 @@ export default async function Layout({
- {children}
+ {children}
diff --git a/app/(customer)/dashboard/layout.tsx b/app/(customer)/dashboard/layout.tsx
index bf04ccf7..f364638d 100644
--- a/app/(customer)/dashboard/layout.tsx
+++ b/app/(customer)/dashboard/layout.tsx
@@ -1,27 +1,31 @@
-import React, {ReactNode} from "react";
-import {redirect} from "next/navigation";
+import { ReactNode, Suspense } from "react";
+import { redirect } from "next/navigation";
-import {SidebarInset, SidebarProvider} from "@/components/ui/sidebar";
-import {AppSidebar} from "@/components/wrappers/dashboard/common/sidebar/app-sidebar";
-import {Header} from "@/features/layout/Header";
-import {currentUser} from "@/lib/auth/current-user";
-import {ThemeMetaUpdater} from "@/features/browser/theme-meta-updater";
-import {BackupModalProvider} from "@/components/wrappers/dashboard/database/backup/backup-modal-context";
+import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
+import { AppSidebar } from "@/components/wrappers/dashboard/common/sidebar/app-sidebar";
+import { Header } from "@/features/layout/Header";
+import { currentUser } from "@/lib/auth/current-user";
+import { ThemeMetaUpdater } from "@/features/browser/theme-meta-updater";
+import { ErrorLayout } from "@/components/wrappers/common/error-layout";
-export default async function Layout({children}: { children: ReactNode }) {
- const user = await currentUser();
- if (!user) redirect("/login");
+export default async function Layout({ children }: { children: ReactNode }) {
+ const user = await currentUser();
+ if (!user) redirect("/login");
- return (
-
-
-
- );
+ return (
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+ );
}
diff --git a/src/components/wrappers/auth/register/register-form/register-form.tsx b/src/components/wrappers/auth/register/register-form/register-form.tsx
index 81e6ea9c..c00dc971 100644
--- a/src/components/wrappers/auth/register/register-form/register-form.tsx
+++ b/src/components/wrappers/auth/register/register-form/register-form.tsx
@@ -1,156 +1,169 @@
"use client";
-import {useRouter} from "next/navigation";
-import {useMutation} from "@tanstack/react-query";
-import {toast} from "sonner";
-import {CardContent, CardHeader} from "@/components/ui/card";
-import {Form} from "@/components/ui/form";
-import {TooltipProvider, TooltipTrigger, Tooltip, TooltipContent} from "@/components/ui/tooltip";
-import {RegisterSchema, RegisterType} from "@/components/wrappers/auth/register/register-form/register-form.schema";
-import {signUp} from "@/lib/auth/auth-client";
-import {useZodForm} from "@/components/ui/form";
-import {CardAuth} from "@/features/layout/card-auth";
-import {FormField} from "@/components/ui/form";
-import {FormItem} from "@/components/ui/form";
-import {FormLabel} from "@/components/ui/form";
-import {FormControl} from "@/components/ui/form";
-import {FormMessage} from "@/components/ui/form";
-import {Input} from "@/components/ui/input";
-import {PasswordInput} from "@/components/ui/password-input";
-import {Button} from "@/components/ui/button";
+import { useRouter } from "next/navigation";
+import { useMutation } from "@tanstack/react-query";
+import { toast } from "sonner";
+import { CardContent, CardHeader } from "@/components/ui/card";
+import { Form } from "@/components/ui/form";
+import {
+ TooltipProvider,
+ TooltipTrigger,
+ Tooltip,
+ TooltipContent,
+} from "@/components/ui/tooltip";
+import {
+ RegisterSchema,
+ RegisterType,
+} from "@/components/wrappers/auth/register/register-form/register-form.schema";
+import { signUp } from "@/lib/auth/auth-client";
+import { useZodForm } from "@/components/ui/form";
+import { CardAuth } from "@/features/layout/card-auth";
+import { FormField } from "@/components/ui/form";
+import { FormItem } from "@/components/ui/form";
+import { FormLabel } from "@/components/ui/form";
+import { FormControl } from "@/components/ui/form";
+import { FormMessage } from "@/components/ui/form";
+import { Input } from "@/components/ui/input";
+import { PasswordInput } from "@/components/ui/password-input";
+import { Button } from "@/components/ui/button";
import Link from "next/link";
-import {Info} from "lucide-react";
+import { Info } from "lucide-react";
export type registerFormProps = {
- defaultValues?: RegisterType;
+ defaultValues?: RegisterType;
};
export const RegisterForm = (props: registerFormProps) => {
+ const form = useZodForm({
+ schema: RegisterSchema,
+ });
- const form = useZodForm({
- schema: RegisterSchema,
- });
-
- const router = useRouter();
- const mutation = useMutation({
- mutationFn: async (values: RegisterType) => {
- // @ts-ignore
- await signUp.email(values, {
- onSuccess: () => {
- toast.success(`Account successfully created`);
- router.refresh();
- router.push(`/login`);
- },
- onError: (error) => {
- toast.error(error.error.message);
- },
- });
+ const router = useRouter();
+ const mutation = useMutation({
+ mutationFn: async (values: RegisterType) => {
+ await signUp.email(values, {
+ onSuccess: () => {
+ toast.success(`Account successfully created`);
+ router.refresh();
+ router.push(`/login`);
},
- });
+ onError: (error) => {
+ toast.error(error.error.message);
+ },
+ });
+ },
+ });
-
- return (
-
-
-
-
-
Create an account
-
Enter your informations below to register
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
Create an account
+
+ Enter your informations below to register
+
+
+
+
+
+
+
+
+ );
};
diff --git a/src/components/wrappers/auth/auth-layout.tsx b/src/components/wrappers/common/error-layout.tsx
similarity index 67%
rename from src/components/wrappers/auth/auth-layout.tsx
rename to src/components/wrappers/common/error-layout.tsx
index 384c3835..078cc24f 100644
--- a/src/components/wrappers/auth/auth-layout.tsx
+++ b/src/components/wrappers/common/error-layout.tsx
@@ -4,7 +4,7 @@ import React, { useEffect } from "react";
import { useSearchParams } from "next/navigation";
import { toast } from "sonner";
-export const AuthLayout = ({ children }: { children: React.ReactNode }) => {
+export const ErrorLayout = ({ children }: { children: React.ReactNode }) => {
const url = useSearchParams();
useEffect(() => {
@@ -15,6 +15,8 @@ export const AuthLayout = ({ children }: { children: React.ReactNode }) => {
const errorMessages: Record = {
pending: "Your account is not active.",
invalid_or_expired_token: "Password reset invalid token.",
+ account_already_linked_to_different_user:
+ "An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address.",
};
const match = Object.entries(errorMessages).find(([key]) =>
@@ -28,7 +30,8 @@ export const AuthLayout = ({ children }: { children: React.ReactNode }) => {
const params = new URLSearchParams(url.toString());
params.delete("error");
const newUrl =
- window.location.pathname + (params.toString() ? `?${params.toString()}` : "");
+ window.location.pathname +
+ (params.toString() ? `?${params.toString()}` : "");
window.history.replaceState({}, document.title, newUrl);
}, [url]);
diff --git a/src/lib/auth/auth.ts b/src/lib/auth/auth.ts
index 44d79a3d..f2379f3a 100644
--- a/src/lib/auth/auth.ts
+++ b/src/lib/auth/auth.ts
@@ -44,6 +44,12 @@ import { getOAuthProviders } from "./oauth";
const oidcProviders = getOidcProviders();
export const auth = betterAuth({
+ onAPIError: {
+ errorURL: "/dashboard/home",
+ onError: (error, ctx) => {
+ //todo: capture errors in a monitoring service
+ },
+ },
database: drizzleAdapter(db, {
provider: "pg",
schema: drizzleDb.schemas,
@@ -134,7 +140,7 @@ export const auth = betterAuth({
trustedProviders: [
"credential",
...getOAuthProviders().map((p) => p.id),
- ...oidcProviders.map((p) => p.id)
+ ...oidcProviders.map((p) => p.id),
],
allowDifferentEmails: true,
},