Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
262 changes: 131 additions & 131 deletions apps/web/app/(auth)/signin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import { signIn } from "next-auth/react";
import { useRouter } from "next/navigation";
import Link from "next/link";

export default function SignIn() {
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Code, ArrowLeft } from "lucide-react";

export default function SignInPage() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isLoading, setIsLoading] = useState(false);
Expand All @@ -25,159 +31,153 @@ export default function SignIn() {
});

if (result?.error) {
setError("Invalid credentials");
setError("Invalid email or password. Please try again.");
} else {
router.push("/");
router.push("/dashboard"); // Redirect to dashboard on success
router.refresh();
}
} catch (error: unknown) {
console.error("Sign in error:", error);
setError("An error occurred. Please try again.");
setError("An unexpected error occurred. Please try again.");
} finally {
setIsLoading(false);
}
};

const handleOAuthSignIn = async (provider: string) => {
setIsLoading(true);
await signIn(provider, { callbackUrl: "/" });
await signIn(provider, { callbackUrl: "/dashboard" });
// No need to setIsLoading(false) here, as the page will redirect
};

return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-md w-full space-y-8">
<div>
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
Sign in to your account
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Or{" "}
<Link
href="/signup"
className="font-medium text-indigo-600 hover:text-indigo-500"
>
create a new account
</Link>
</p>
</div>
<form className="mt-8 space-y-6" onSubmit={handleSubmit}>
{error && (
<div className="rounded-md bg-red-50 p-4">
<div className="flex">
<div className="ml-3">
<h3 className="text-sm font-medium text-red-800">{error}</h3>
</div>
<div className="min-h-screen bg-background flex flex-col">
{/* Header */}
<header className="border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex h-16 items-center justify-between">
<Link href="/" className="flex items-center space-x-2">
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary text-primary-foreground">
<Code className="h-5 w-5" />
</div>
</div>
)}
<div className="rounded-md shadow-sm -space-y-px">
<div>
<label htmlFor="email-address" className="sr-only">
Email address
</label>
<input
id="email-address"
name="email"
type="email"
autoComplete="email"
required
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
placeholder="Email address"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div>
<label htmlFor="password" className="sr-only">
Password
</label>
<input
id="password"
name="password"
type="password"
autoComplete="current-password"
required
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<span className="text-xl font-bold text-foreground">Dev8.dev</span>
</Link>
<Button variant="ghost" size="sm" onClick={() => router.push("/")}>
<ArrowLeft className="mr-2 h-4 w-4" />
Back to Home
</Button>
</div>
</div>
</header>

<div>
<button
type="submit"
disabled={isLoading}
className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50"
>
{isLoading ? "Signing in..." : "Sign in"}
</button>
{/* Sign In Form */}
<div className="flex-1 flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
<div className="w-full max-w-md space-y-8">
<div className="text-center">
<h2 className="text-3xl font-bold tracking-tight text-foreground">Welcome back</h2>
<p className="mt-2 text-muted-foreground">Sign in to access your Dev8.dev workspace</p>
</div>

<div className="mt-6">
<div className="relative">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-gray-300" />
</div>
<div className="relative flex justify-center text-sm">
<span className="px-2 bg-gray-50 text-gray-500">
Or continue with
</span>
</div>
</div>

<div className="mt-6 grid grid-cols-2 gap-3">
<button
type="button"
onClick={() => handleOAuthSignIn("google")}
disabled={isLoading}
className="w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 disabled:opacity-50"
>
<svg className="w-5 h-5" viewBox="0 0 24 24">
<path
fill="currentColor"
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
/>
<path
fill="currentColor"
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
/>
<path
fill="currentColor"
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
<Card className="border-border/50 bg-card/50 backdrop-blur">
<CardHeader className="space-y-1 text-center">
<CardTitle className="text-2xl">Sign In</CardTitle>
<CardDescription>Enter your credentials to continue</CardDescription>
</CardHeader>
<CardContent>
{error && (
<div className="mb-4 rounded-md border border-destructive/50 bg-destructive/10 p-3">
<p className="text-sm font-medium text-destructive">{error}</p>
</div>
)}
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
name="email"
type="email"
autoComplete="email"
placeholder="Enter your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
disabled={isLoading}
/>
<path
fill="currentColor"
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
</div>
<div className="space-y-2">
<Label htmlFor="password">Password</Label>
<Input
id="password"
name="password"
type="password"
autoComplete="current-password"
placeholder="Enter your password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
disabled={isLoading}
/>
</svg>
<span className="ml-2">Google</span>
</button>
</div>
<Button type="submit" className="w-full" disabled={isLoading}>
{isLoading ? "Signing In..." : "Sign In with Email"}
</Button>
</form>

<button
type="button"
onClick={() => handleOAuthSignIn("github")}
disabled={isLoading}
className="w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 disabled:opacity-50"
>
<svg
className="w-5 h-5"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M10 0C4.477 0 0 4.484 0 10.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0110 4.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.203 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.942.359.31.678.921.678 1.856 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0020 10.017C20 4.484 15.522 0 10 0z"
clipRule="evenodd"
/>
</svg>
<span className="ml-2">GitHub</span>
</button>
</div>
</div>
</form>
<div className="relative my-6">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t border-border" />
</div>
<div className="relative flex justify-center text-xs uppercase">
<span className="bg-card px-2 text-muted-foreground">Or continue with</span>
</div>
</div>

<div className="grid grid-cols-2 gap-3">
<Button variant="outline" type="button" onClick={() => handleOAuthSignIn("google")} disabled={isLoading}>
<svg className="mr-2 h-4 w-4" viewBox="0 0 24 24">
<path
fill="currentColor"
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
/>
<path
fill="currentColor"
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
/>
<path
fill="currentColor"
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
/>
<path
fill="currentColor"
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
/>
</svg>
Google
</Button>
<Button variant="outline" type="button" onClick={() => handleOAuthSignIn("github")} disabled={isLoading}>
<svg className="mr-2 h-4 w-4" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 0C4.477 0 0 4.484 0 10.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0110 4.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.203 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.942.359.31.678.921.678 1.856 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0020 10.017C20 4.484 15.522 0 10 0z"
clipRule="evenodd"
/>
</svg>
GitHub
</Button>
</div>

<div className="mt-6 text-center">
<p className="text-sm text-muted-foreground">
Don't have an account?{" "}
<Link href="/signup" className="font-medium text-primary hover:underline">
Sign up
</Link>
</p>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
);
}
}
Loading
Loading