mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
fix: error layout global app
This commit is contained in:
@@ -4,7 +4,7 @@ import { currentUser } from "@/lib/auth/current-user";
|
|||||||
import { AuthLogoSection } from "@/components/wrappers/auth/auth-logo-section";
|
import { AuthLogoSection } from "@/components/wrappers/auth/auth-logo-section";
|
||||||
import { env } from "@/env.mjs";
|
import { env } from "@/env.mjs";
|
||||||
import { Heart } from "lucide-react";
|
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({
|
export default async function Layout({
|
||||||
children,
|
children,
|
||||||
@@ -24,7 +24,7 @@ export default async function Layout({
|
|||||||
<AuthLogoSection />
|
<AuthLogoSection />
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<AuthLayout>{children}</AuthLayout>
|
<ErrorLayout>{children}</ErrorLayout>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {ReactNode} from "react";
|
import { ReactNode, Suspense } from "react";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
|
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
|
||||||
@@ -6,7 +6,7 @@ import {AppSidebar} from "@/components/wrappers/dashboard/common/sidebar/app-sid
|
|||||||
import { Header } from "@/features/layout/Header";
|
import { Header } from "@/features/layout/Header";
|
||||||
import { currentUser } from "@/lib/auth/current-user";
|
import { currentUser } from "@/lib/auth/current-user";
|
||||||
import { ThemeMetaUpdater } from "@/features/browser/theme-meta-updater";
|
import { ThemeMetaUpdater } from "@/features/browser/theme-meta-updater";
|
||||||
import {BackupModalProvider} from "@/components/wrappers/dashboard/database/backup/backup-modal-context";
|
import { ErrorLayout } from "@/components/wrappers/common/error-layout";
|
||||||
|
|
||||||
export default async function Layout({ children }: { children: ReactNode }) {
|
export default async function Layout({ children }: { children: ReactNode }) {
|
||||||
const user = await currentUser();
|
const user = await currentUser();
|
||||||
@@ -19,7 +19,11 @@ export default async function Layout({children}: { children: ReactNode }) {
|
|||||||
<AppSidebar />
|
<AppSidebar />
|
||||||
<SidebarInset>
|
<SidebarInset>
|
||||||
<Header />
|
<Header />
|
||||||
|
<Suspense>
|
||||||
|
<ErrorLayout>
|
||||||
<main className="h-full">{children}</main>
|
<main className="h-full">{children}</main>
|
||||||
|
</ErrorLayout>
|
||||||
|
</Suspense>
|
||||||
</SidebarInset>
|
</SidebarInset>
|
||||||
</div>
|
</div>
|
||||||
</SidebarProvider>
|
</SidebarProvider>
|
||||||
|
|||||||
@@ -5,8 +5,16 @@ import {useMutation} from "@tanstack/react-query";
|
|||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { CardContent, CardHeader } from "@/components/ui/card";
|
import { CardContent, CardHeader } from "@/components/ui/card";
|
||||||
import { Form } from "@/components/ui/form";
|
import { Form } from "@/components/ui/form";
|
||||||
import {TooltipProvider, TooltipTrigger, Tooltip, TooltipContent} from "@/components/ui/tooltip";
|
import {
|
||||||
import {RegisterSchema, RegisterType} from "@/components/wrappers/auth/register/register-form/register-form.schema";
|
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 { signUp } from "@/lib/auth/auth-client";
|
||||||
import { useZodForm } from "@/components/ui/form";
|
import { useZodForm } from "@/components/ui/form";
|
||||||
import { CardAuth } from "@/features/layout/card-auth";
|
import { CardAuth } from "@/features/layout/card-auth";
|
||||||
@@ -26,7 +34,6 @@ export type registerFormProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const RegisterForm = (props: registerFormProps) => {
|
export const RegisterForm = (props: registerFormProps) => {
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm({
|
||||||
schema: RegisterSchema,
|
schema: RegisterSchema,
|
||||||
});
|
});
|
||||||
@@ -34,7 +41,6 @@ export const RegisterForm = (props: registerFormProps) => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const mutation = useMutation({
|
const mutation = useMutation({
|
||||||
mutationFn: async (values: RegisterType) => {
|
mutationFn: async (values: RegisterType) => {
|
||||||
// @ts-ignore
|
|
||||||
await signUp.email(values, {
|
await signUp.email(values, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
toast.success(`Account successfully created`);
|
toast.success(`Account successfully created`);
|
||||||
@@ -48,14 +54,15 @@ export const RegisterForm = (props: registerFormProps) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<CardAuth>
|
<CardAuth>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="grid gap-2 text-center mb-2">
|
<div className="grid gap-2 text-center mb-2">
|
||||||
<h1 className="text-3xl font-bold">Create an account</h1>
|
<h1 className="text-3xl font-bold">Create an account</h1>
|
||||||
<p className="text-balance text-muted-foreground">Enter your informations below to register</p>
|
<p className="text-balance text-muted-foreground">
|
||||||
|
Enter your informations below to register
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
@@ -105,12 +112,12 @@ export const RegisterForm = (props: registerFormProps) => {
|
|||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<Info className="ml-3" size="15"/>
|
<Info size="15" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>
|
<p>
|
||||||
Min. 8 characters, 1 uppercase (A-Z), 1 lowercase (a-z), 1
|
Min. 8 characters, 1 uppercase (A-Z), 1 lowercase
|
||||||
number (0-9), 1 special character (!, @,
|
(a-z), 1 number (0-9), 1 special character (!, @,
|
||||||
etc.)
|
etc.)
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
@@ -132,13 +139,20 @@ export const RegisterForm = (props: registerFormProps) => {
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Password Confirmation</FormLabel>
|
<FormLabel>Password Confirmation</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<PasswordInput placeholder="Conform your password" {...field} />
|
<PasswordInput
|
||||||
|
placeholder="Conform your password"
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Button type="submit" className="h-11" disabled={mutation.isPending}>
|
<Button
|
||||||
|
type="submit"
|
||||||
|
className="h-11"
|
||||||
|
disabled={mutation.isPending}
|
||||||
|
>
|
||||||
Sign up
|
Sign up
|
||||||
</Button>
|
</Button>
|
||||||
<div className="mt-4 text-center text-sm">
|
<div className="mt-4 text-center text-sm">
|
||||||
@@ -147,7 +161,6 @@ export const RegisterForm = (props: registerFormProps) => {
|
|||||||
Sign in
|
Sign in
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</Form>
|
</Form>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</CardAuth>
|
</CardAuth>
|
||||||
|
|||||||
+5
-2
@@ -4,7 +4,7 @@ import React, { useEffect } from "react";
|
|||||||
import { useSearchParams } from "next/navigation";
|
import { useSearchParams } from "next/navigation";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
export const AuthLayout = ({ children }: { children: React.ReactNode }) => {
|
export const ErrorLayout = ({ children }: { children: React.ReactNode }) => {
|
||||||
const url = useSearchParams();
|
const url = useSearchParams();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -15,6 +15,8 @@ export const AuthLayout = ({ children }: { children: React.ReactNode }) => {
|
|||||||
const errorMessages: Record<string, string> = {
|
const errorMessages: Record<string, string> = {
|
||||||
pending: "Your account is not active.",
|
pending: "Your account is not active.",
|
||||||
invalid_or_expired_token: "Password reset invalid token.",
|
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]) =>
|
const match = Object.entries(errorMessages).find(([key]) =>
|
||||||
@@ -28,7 +30,8 @@ export const AuthLayout = ({ children }: { children: React.ReactNode }) => {
|
|||||||
const params = new URLSearchParams(url.toString());
|
const params = new URLSearchParams(url.toString());
|
||||||
params.delete("error");
|
params.delete("error");
|
||||||
const newUrl =
|
const newUrl =
|
||||||
window.location.pathname + (params.toString() ? `?${params.toString()}` : "");
|
window.location.pathname +
|
||||||
|
(params.toString() ? `?${params.toString()}` : "");
|
||||||
|
|
||||||
window.history.replaceState({}, document.title, newUrl);
|
window.history.replaceState({}, document.title, newUrl);
|
||||||
}, [url]);
|
}, [url]);
|
||||||
@@ -44,6 +44,12 @@ import { getOAuthProviders } from "./oauth";
|
|||||||
const oidcProviders = getOidcProviders();
|
const oidcProviders = getOidcProviders();
|
||||||
|
|
||||||
export const auth = betterAuth({
|
export const auth = betterAuth({
|
||||||
|
onAPIError: {
|
||||||
|
errorURL: "/dashboard/home",
|
||||||
|
onError: (error, ctx) => {
|
||||||
|
//todo: capture errors in a monitoring service
|
||||||
|
},
|
||||||
|
},
|
||||||
database: drizzleAdapter(db, {
|
database: drizzleAdapter(db, {
|
||||||
provider: "pg",
|
provider: "pg",
|
||||||
schema: drizzleDb.schemas,
|
schema: drizzleDb.schemas,
|
||||||
@@ -134,7 +140,7 @@ export const auth = betterAuth({
|
|||||||
trustedProviders: [
|
trustedProviders: [
|
||||||
"credential",
|
"credential",
|
||||||
...getOAuthProviders().map((p) => p.id),
|
...getOAuthProviders().map((p) => p.id),
|
||||||
...oidcProviders.map((p) => p.id)
|
...oidcProviders.map((p) => p.id),
|
||||||
],
|
],
|
||||||
allowDifferentEmails: true,
|
allowDifferentEmails: true,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user