more sign-in/sign-up fixes
This commit is contained in:
parent
9f1dffb3b5
commit
ad728d579f
2 changed files with 48 additions and 86 deletions
|
|
@ -1,51 +1,13 @@
|
|||
// app/auth/sign-in/page.tsx
|
||||
import { Suspense } from "react";
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
|
||||
// UI (shadcn)
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
export const metadata: Metadata = { title: "Sign in" };
|
||||
|
||||
// Server Component wrapper — no hooks here
|
||||
export default function SignInPage() {
|
||||
return (
|
||||
<div className="min-h-[60vh] flex items-center justify-center px-4">
|
||||
<div className="w-full max-w-md space-y-6">
|
||||
<div className="text-center space-y-2">
|
||||
<h1 className="text-2xl font-bold">Sign in</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Welcome back. Enter your credentials to continue.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Client sub-component wrapped in Suspense so useSearchParams is allowed */}
|
||||
<Suspense fallback={<div className="text-sm text-muted-foreground">Loading…</div>}>
|
||||
<SignInClient />
|
||||
</Suspense>
|
||||
|
||||
<p className="text-sm text-center text-muted-foreground">
|
||||
Don’t have an account?{" "}
|
||||
<Link href="/auth/sign-up" className="underline underline-offset-4 hover:opacity-80">
|
||||
Create one
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Client piece that actually uses useSearchParams/router/fetch
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
function SignInClient() {
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
export default function SignInPage() {
|
||||
const router = useRouter();
|
||||
const sp = useSearchParams();
|
||||
|
||||
|
|
@ -61,8 +23,6 @@ function SignInClient() {
|
|||
setErr(null);
|
||||
setSubmitting(true);
|
||||
try {
|
||||
// Post both a generic "identity" and the same value under email/username
|
||||
// so the API route can accept any of them.
|
||||
const res = await fetch("/api/auth/login", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
|
|
@ -76,7 +36,6 @@ function SignInClient() {
|
|||
const data = await res.json().catch(() => ({}));
|
||||
if (!res.ok) throw new Error(data?.error || "Login failed");
|
||||
|
||||
// Cookies (httpOnly) were set server-side; client just navigates.
|
||||
router.replace(next);
|
||||
} catch (e: any) {
|
||||
setErr(e?.message || "Login failed");
|
||||
|
|
@ -86,12 +45,22 @@ function SignInClient() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-[60vh] flex items-center justify-center px-4">
|
||||
<div className="w-full max-w-md space-y-6">
|
||||
<div className="text-center space-y-2">
|
||||
<h1 className="text-2xl font-bold">Sign in</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Welcome back. Enter your credentials to continue.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form onSubmit={onSubmit} className="space-y-4">
|
||||
{err && (
|
||||
<div className="text-sm rounded border border-destructive/30 bg-destructive/10 px-3 py-2 text-destructive">
|
||||
{err}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">Email or Username</label>
|
||||
<Input
|
||||
|
|
@ -103,6 +72,7 @@ function SignInClient() {
|
|||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">Password</label>
|
||||
<Input
|
||||
|
|
@ -118,8 +88,16 @@ function SignInClient() {
|
|||
{submitting ? "Signing in…" : "Sign in"}
|
||||
</Button>
|
||||
|
||||
{/* keep the next param visible to the client sub-component */}
|
||||
<input type="hidden" name="next" value={next} />
|
||||
</form>
|
||||
|
||||
<p className="text-sm text-center text-muted-foreground">
|
||||
Don’t have an account?{" "}
|
||||
<Link href="/auth/sign-up" className="underline underline-offset-4 hover:opacity-80">
|
||||
Create one
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,46 +1,13 @@
|
|||
// app/auth/sign-up/page.tsx
|
||||
import { Suspense } from "react";
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
|
||||
// UI (shadcn)
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
export const metadata: Metadata = { title: "Create account" };
|
||||
|
||||
export default function SignUpPage() {
|
||||
return (
|
||||
<div className="min-h-[60vh] flex items-center justify-center px-4">
|
||||
<div className="w-full max-w-md space-y-6">
|
||||
<div className="text-center space-y-2">
|
||||
<h1 className="text-2xl font-bold">Create account</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Pick a username and password. Email is optional (recommended for password reset).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Suspense fallback={<div className="text-sm text-muted-foreground">Loading…</div>}>
|
||||
<SignUpClient />
|
||||
</Suspense>
|
||||
|
||||
<p className="text-sm text-center text-muted-foreground">
|
||||
Already have an account?{" "}
|
||||
<Link href="/auth/sign-in" className="underline underline-offset-4 hover:opacity-80">
|
||||
Sign in
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
function SignUpClient() {
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
export default function SignUpPage() {
|
||||
const router = useRouter();
|
||||
const sp = useSearchParams();
|
||||
|
||||
|
|
@ -69,7 +36,6 @@ function SignUpClient() {
|
|||
const data = await res.json().catch(() => ({}));
|
||||
if (!res.ok) throw new Error(data?.error || "Registration failed");
|
||||
|
||||
// Registration API should already log user in (sets cookies), then redirect
|
||||
router.replace(next);
|
||||
} catch (e: any) {
|
||||
setErr(e?.message || "Registration failed");
|
||||
|
|
@ -79,6 +45,15 @@ function SignUpClient() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-[60vh] flex items-center justify-center px-4">
|
||||
<div className="w-full max-w-md space-y-6">
|
||||
<div className="text-center space-y-2">
|
||||
<h1 className="text-2xl font-bold">Create account</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Pick a username and password. Email is optional (recommended for password reset).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form onSubmit={onSubmit} className="space-y-4">
|
||||
{err && (
|
||||
<div className="text-sm rounded border border-destructive/30 bg-destructive/10 px-3 py-2 text-destructive">
|
||||
|
|
@ -130,5 +105,14 @@ function SignUpClient() {
|
|||
|
||||
<input type="hidden" name="next" value={next} />
|
||||
</form>
|
||||
|
||||
<p className="text-sm text-center text-muted-foreground">
|
||||
Already have an account?{" "}
|
||||
<Link href="/auth/sign-in" className="underline underline-offset-4 hover:opacity-80">
|
||||
Sign in
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue