feat(get session and push to protected route)
This commit is contained in:
parent
99781de44c
commit
7c58a7e46c
|
@ -0,0 +1,39 @@
|
||||||
|
"use server";
|
||||||
|
|
||||||
|
import { createClient } from "@/utils/supabase/server";
|
||||||
|
|
||||||
|
export const checkSession = async () => {
|
||||||
|
const supabase = await createClient();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
data: { session },
|
||||||
|
error,
|
||||||
|
} = await supabase.auth.getSession();
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: error.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
session,
|
||||||
|
redirectTo: "/protected/dashboard", // or your preferred authenticated route
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "No active session",
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "An unexpected error occurred",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,9 +1,17 @@
|
||||||
|
import { checkSession } from "@/actions/auth/session";
|
||||||
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
export default async function Layout({
|
export default async function Layout({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
const sessionResult = await checkSession();
|
||||||
<div className="max-w-full gap-12 items-start">{children}</div>
|
|
||||||
);
|
// If there's an active session, redirect to dashboard
|
||||||
|
if (sessionResult.success && sessionResult.redirectTo) {
|
||||||
|
redirect(sessionResult.redirectTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="max-w-full gap-12 items-start">{children}</div>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { FormMessage, Message } from "@/components/form-message";
|
import { FormMessage, Message } from "@/components/form-message";
|
||||||
import { LoginForm } from "@/components/auth/login-form";
|
|
||||||
import { SubmitButton } from "@/components/submit-button";
|
import { SubmitButton } from "@/components/submit-button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
|
|
|
@ -31,6 +31,7 @@ export default function RootLayout({
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang="en" className={geistSans.className} suppressHydrationWarning>
|
<html lang="en" className={geistSans.className} suppressHydrationWarning>
|
||||||
<body className="bg-background text-foreground">
|
<body className="bg-background text-foreground">
|
||||||
|
|
|
@ -1,16 +1,29 @@
|
||||||
import { cn } from "@/lib/utils";
|
"use client";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
|
||||||
import { Github, Lock } from "lucide-react";
|
import { Github, Lock } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { SubmitButton } from "../submit-button";
|
import { SubmitButton } from "../submit-button";
|
||||||
import { signInAction } from "@/actions/auth/sign-in";
|
|
||||||
|
import { FormField } from "../form-field";
|
||||||
|
import { useSignInForm } from "@/src/infrastructure/hooks/use-signin";
|
||||||
|
|
||||||
export function LoginForm2({
|
export function LoginForm2({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentPropsWithoutRef<"form">) {
|
}: React.ComponentPropsWithoutRef<"form">) {
|
||||||
|
const {
|
||||||
|
formData,
|
||||||
|
errors,
|
||||||
|
isSubmitting,
|
||||||
|
setFormData,
|
||||||
|
handleChange,
|
||||||
|
handleSelectChange,
|
||||||
|
handleSubmit,
|
||||||
|
} = useSignInForm();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="flex-1 flex items-center justify-center px-6">
|
<div className="flex-1 flex items-center justify-center px-6">
|
||||||
|
@ -35,6 +48,7 @@ export function LoginForm2({
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="w-full bg-[#1C1C1C] text-white border-gray-800 hover:bg-[#2C2C2C] hover:border-gray-700"
|
className="w-full bg-[#1C1C1C] text-white border-gray-800 hover:bg-[#2C2C2C] hover:border-gray-700"
|
||||||
size="lg"
|
size="lg"
|
||||||
|
disabled={isSubmitting}
|
||||||
>
|
>
|
||||||
<Lock className="mr-2 h-5 w-5" />
|
<Lock className="mr-2 h-5 w-5" />
|
||||||
Continue with SSO
|
Continue with SSO
|
||||||
|
@ -50,51 +64,35 @@ export function LoginForm2({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form className="space-y-4" {...props}>
|
<form onSubmit={handleSubmit} className="space-y-4" {...props}>
|
||||||
<div className="space-y-2">
|
<FormField
|
||||||
<Label htmlFor="email" className="text-sm text-gray-300">
|
label="Email"
|
||||||
Email
|
input={
|
||||||
</Label>
|
|
||||||
<Input
|
<Input
|
||||||
id="email"
|
id="email"
|
||||||
type="email"
|
type="email"
|
||||||
name="email"
|
name="email"
|
||||||
placeholder="you@example.com"
|
placeholder="you@example.com"
|
||||||
className="bg-[#1C1C1C] border-gray-800 text-white placeholder:text-gray-500 focus:border-emerald-600 focus:ring-emerald-600"
|
className={`bg-[#1C1C1C] border-gray-800 text-white placeholder:text-gray-500 focus:border-emerald-600 focus:ring-emerald-600 ${
|
||||||
required
|
errors.email ? "border-red-500" : ""
|
||||||
|
}`}
|
||||||
|
value={formData.email}
|
||||||
|
onChange={handleChange}
|
||||||
|
disabled={isSubmitting}
|
||||||
/>
|
/>
|
||||||
<Link
|
}
|
||||||
|
error={errors.email}
|
||||||
|
/>
|
||||||
|
{/* <Link
|
||||||
href="email-recovery"
|
href="email-recovery"
|
||||||
className="flex items-end justify-end text-xs text-gray-400 hover:text-emerald-500"
|
className="flex items-end justify-end text-xs text-gray-400 hover:text-emerald-500"
|
||||||
>
|
>
|
||||||
Forgot Email?
|
Forgot Email?
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
{/* <Label htmlFor="password" className="text-sm text-gray-300">
|
|
||||||
Password
|
|
||||||
</Label> */}
|
|
||||||
{/* <Link
|
|
||||||
href="#"
|
|
||||||
className="text-xs text-gray-400 hover:text-gray-300"
|
|
||||||
>
|
|
||||||
Forgot Email?
|
|
||||||
</Link> */}
|
</Link> */}
|
||||||
</div>
|
|
||||||
{/* <Input
|
|
||||||
id="password"
|
|
||||||
type="password"
|
|
||||||
className="bg-[#1C1C1C] border-gray-800 text-white focus:border-emerald-600 focus:ring-emerald-600"
|
|
||||||
required
|
|
||||||
/> */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
className="w-full bg-emerald-600 hover:bg-emerald-700 text-white"
|
className="w-full bg-emerald-600 hover:bg-emerald-700 text-white"
|
||||||
size="lg"
|
size="lg"
|
||||||
pendingText="Signing In..."
|
pendingText="Signing In..."
|
||||||
formAction={signInAction}
|
|
||||||
>
|
>
|
||||||
Sign In
|
Sign In
|
||||||
</SubmitButton>
|
</SubmitButton>
|
||||||
|
|
|
@ -27,23 +27,23 @@ export const selectContactUsSchema = z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
email: z.string(),
|
email: z.string(),
|
||||||
phone: z.string(),
|
phone: z.string(),
|
||||||
message_type: z.string(),
|
typeMessage: z.string(),
|
||||||
message_type_label: z.string(),
|
message_type_label: z.string(),
|
||||||
message: z.string(),
|
message: z.string(),
|
||||||
status: z.nativeEnum(statusEnum),
|
status: z.nativeEnum(statusEnum),
|
||||||
created_at: z.string(),
|
createdAt: z.string(),
|
||||||
updated_at: z.string(),
|
updatedAt: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type ContactUs = z.infer<typeof selectContactUsSchema>;
|
export type ContactUs = z.infer<typeof selectContactUsSchema>;
|
||||||
|
|
||||||
// Schema for form input
|
// Schema for form input
|
||||||
export const insertContactUsSchema = z.object({
|
export const insertContactUsSchema = selectContactUsSchema.pick({
|
||||||
name: z.string(),
|
name: true,
|
||||||
email: z.string(),
|
email: true,
|
||||||
phone: z.string(),
|
phone: true,
|
||||||
typeMessage: z.string(),
|
typeMessage: true,
|
||||||
message: z.string(),
|
message: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
export type ContactUsInsert = z.infer<typeof insertContactUsSchema>;
|
export type ContactUsInsert = z.infer<typeof insertContactUsSchema>;
|
||||||
|
|
|
@ -41,7 +41,9 @@ export const updateSession = async (request: NextRequest) => {
|
||||||
|
|
||||||
// protected routes
|
// protected routes
|
||||||
if (request.nextUrl.pathname === "/" && !user.error) {
|
if (request.nextUrl.pathname === "/" && !user.error) {
|
||||||
return NextResponse.redirect(new URL("/protected", request.url));
|
return NextResponse.redirect(
|
||||||
|
new URL("/protected/dashboard", request.url)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.nextUrl.pathname.startsWith("/protected") && user.error) {
|
if (request.nextUrl.pathname.startsWith("/protected") && user.error) {
|
||||||
|
|
Loading…
Reference in New Issue