diff --git a/src/app/(login)/actions.ts b/src/app/(login)/actions.ts index 9c3b2f6..bd21d72 100644 --- a/src/app/(login)/actions.ts +++ b/src/app/(login)/actions.ts @@ -12,48 +12,10 @@ import { authRateLimit, signUpRateLimit } from "@/lib/rate-limit"; const authSchema = z.object({ username: z.string().min(1), password: z.string().min(1), - mode: z.enum(["signin", "signup"]), }); -async function signIn(input: z.infer) { - const { username, password } = input; - const ip = (await headers()).get("x-real-ip") ?? "local"; - const rl = await authRateLimit.limit(ip); - - if (!rl.success) { - return { - error: { - code: "AUTH_ERROR", - message: "Too many attempts. Try again later", - }, - }; - } - const user = await db - .select({ - user: users, - }) - .from(users) - .where(eq(users.username, username)) - .limit(1); - - if (user.length === 0) { - return { error: "Invalid email or password. Please try again." }; - } - - const { user: foundUser } = user[0]; - - const isPasswordValid = await comparePasswords( - password, - foundUser.passwordHash, - ); - - if (!isPasswordValid) { - return { error: "Invalid email or password. Please try again." }; - } - await setSession(foundUser); -} -async function signUp(input: z.infer) { - const { username, password } = input; +export const signUp = validatedAction(authSchema, async (data) => { + const { username, password } = data; const ip = (await headers()).get("x-real-ip") ?? "local"; const rl2 = await signUpRateLimit.limit(ip); if (!rl2.success) { @@ -88,14 +50,44 @@ async function signUp(input: z.infer) { return { error: "Failed to create user. Please try again." }; } await setSession(createdUser); -} -export const signInSignUp = validatedAction(authSchema, async (data) => { - const { mode } = data; - if (mode === "signin") { - return signIn(data); - } else { - return signUp(data); +}); + +export const signIn = validatedAction(authSchema, async (data) => { + const { username, password } = data; + const ip = (await headers()).get("x-real-ip") ?? "local"; + const rl = await authRateLimit.limit(ip); + + if (!rl.success) { + return { + error: { + code: "AUTH_ERROR", + message: "Too many attempts. Try again later", + }, + }; } + const user = await db + .select({ + user: users, + }) + .from(users) + .where(eq(users.username, username)) + .limit(1); + + if (user.length === 0) { + return { error: "Invalid email or password. Please try again." }; + } + + const { user: foundUser } = user[0]; + + const isPasswordValid = await comparePasswords( + password, + foundUser.passwordHash, + ); + + if (!isPasswordValid) { + return { error: "Invalid email or password. Please try again." }; + } + await setSession(foundUser); }); export async function signOut() { diff --git a/src/app/auth.client.tsx b/src/app/auth.client.tsx index 959c80f..540f51e 100644 --- a/src/app/auth.client.tsx +++ b/src/app/auth.client.tsx @@ -6,15 +6,82 @@ import { PopoverTrigger, } from "@/components/ui/popover"; import { ActionState } from "@/lib/middleware"; -import { signInSignUp } from "./(login)/actions"; +import { signIn, signUp } from "./(login)/actions"; import { useActionState } from "react"; import { Button } from "@/components/ui/button"; -export function SignInSignUp() { - const [state, formAction, pending] = useActionState( - signInSignUp, - { error: "" }, +export function LoginForm() { + const [signInState, signInFormAction, signInPending] = useActionState< + ActionState, + FormData + >(signIn, { error: "" }); + const [signUpState, signUpFormAction, signUpPending] = useActionState< + ActionState, + FormData + >(signUp, { error: "" }); + const pending = signInPending || signUpPending; + const state = signInState.error ? signInState : signUpState; + + return ( +
+
+
+ +
+ +
+
+ +
+
+ + + + +
+ {state?.error && ( +
{state.error}
+ )} +
); +} + +export function SignInSignUp() { return ( @@ -23,76 +90,9 @@ export function SignInSignUp() { - -
- Log in -
-
- -
- -
-
- -
-
- {/* todo: rather than using a hidden input, we could use the formAction prop on button */} - {/* store sign in / sign up here */} - - - - - -
- {state?.error && ( -
{state.error}
- )} -
+ + Log in +
); diff --git a/src/app/auth.server.tsx b/src/app/auth.server.tsx index a622b28..dd37773 100644 --- a/src/app/auth.server.tsx +++ b/src/app/auth.server.tsx @@ -1,5 +1,5 @@ import { getUser } from "@/lib/queries"; -import { SignInSignUp, SignOut } from "./auth.client"; +import { LoginForm, SignInSignUp, SignOut } from "./auth.client"; export async function AuthServer() { const user = await getUser(); @@ -8,3 +8,16 @@ export async function AuthServer() { } return ; } + +export async function PlaceOrderAuth() { + const user = await getUser(); + if (user) { + return null; + } + return ( + <> +

Log in to place an order

+ + + ); +} diff --git a/src/app/order-history/page.tsx b/src/app/order-history/page.tsx index b910646..379141b 100644 --- a/src/app/order-history/page.tsx +++ b/src/app/order-history/page.tsx @@ -1,19 +1,25 @@ -import { LoginForm } from "@/components/login-form"; +import { getUser } from "@/lib/queries"; import { Metadata } from "next"; export const metadata: Metadata = { title: "Order History", }; -export default function Page() { +export default async function Page() { + const user = await getUser(); return (
-
-

ORDER HISTORY

-

- Log in to view order history -

- +

+ Order History +

+
+ {user ? ( +

You have no orders yet.

+ ) : ( +

+ Log in to view order history +

+ )}
); diff --git a/src/app/order/page.tsx b/src/app/order/page.tsx index 94376fd..cc07989 100644 --- a/src/app/order/page.tsx +++ b/src/app/order/page.tsx @@ -1,7 +1,7 @@ -import { LoginForm } from "@/components/login-form"; import { Metadata } from "next"; import { Suspense } from "react"; import { CartItems, TotalCost } from "./dynamic"; +import { PlaceOrderAuth } from "../auth.server"; export const metadata: Metadata = { title: "Order", @@ -34,10 +34,9 @@ export default async function Page() { Applicable shipping and tax will be added.

-

- Log in to place an order -

- + + +