Skip to content
Merged
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
67 changes: 67 additions & 0 deletions apps/frontend/app/components/Onboarding.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
export default function Onboarding({ onBack }: { onBack: () => void }) {
return (
<div className="relative w-full max-w-lg rounded-lg border border-black p-8">
<button onClick={onBack} className="absolute left-8 top-8 text-xl">
</button>

<div className="mb-8 text-center">
<h1 className="text-3xl font-medium">Welcome to CS+SG</h1>
<p className="text-sm">Set up your basic profile</p>
</div>

{/* Avatar and Identity Fields */}
<div className="mb-6 flex gap-8">
<div className="relative">
<div className="flex h-32 w-32 items-center justify-center overflow-hidden rounded-full border border-black">
<div className="relative h-full w-full">
<div className="absolute inset-0 origin-center rotate-45 scale-150 border-t border-black"></div>
<div className="absolute inset-0 origin-center -rotate-45 scale-150 border-t border-black"></div>
</div>
</div>
<button className="absolute bottom-0 right-0 flex h-8 w-8 items-center justify-center rounded-full border border-black bg-white p-1">
</button>
</div>

<div className="flex-1 space-y-4">
<div>
<label className="mb-1 block text-sm">First Name</label>
<input type="text" className="w-full rounded-sm border border-black p-2" />
</div>
<div>
<label className="mb-1 block text-sm">Last Name</label>
<input type="text" className="w-full rounded-sm border border-black p-2" />
</div>
<div>
<label className="mb-1 block text-sm">Pronouns</label>
<select className="w-full rounded-sm border border-black bg-white p-2">
<option value=""></option>
<option value="he-him">He/Him</option>
<option value="she-her">She/Her</option>
<option value="they-them">They/Them</option>
</select>
</div>
</div>
</div>

{/* Links Section */}
<div className="space-y-2">
<label className="block text-sm">Links</label>
<div className="flex gap-2">
<input type="text" className="flex-1 rounded-sm border border-black p-2" />
<button className="border border-black px-4 py-2 transition-colors hover:bg-gray-100">
Add
</button>
</div>
<div className="space-y-1">
<div className="flex items-center gap-2 border-b border-gray-400 py-2">
<span className="cursor-pointer text-sm hover:text-red-500">✕</span>
</div>
</div>
</div>

<button className="mt-8 w-full text-center font-medium hover:underline">Done</button>
</div>
);
}
37 changes: 37 additions & 0 deletions apps/frontend/app/components/SignUpForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Link from "next/link";

export default function SignupForm({ onSignupSuccess }: { onSignupSuccess: () => void }) {
return (
<div className="w-full max-w-md space-y-6 rounded-lg border border-slate-300 bg-white p-8 text-slate-900 shadow-lg">
<h1 className="mb-8 text-center text-4xl font-semibold text-slate-900">Register</h1>
<div className="space-y-4">
<div>
<label className="mb-1 block text-sm font-medium text-slate-800">Email</label>
<input
type="email"
className="w-full rounded-sm border border-slate-300 bg-white p-2 text-slate-900 placeholder:text-slate-400"
/>
</div>
<div>
<label className="mb-1 block text-sm font-medium text-slate-800">Password</label>
<input
type="password"
className="w-full rounded-sm border border-slate-300 bg-white p-2 text-slate-900 placeholder:text-slate-400"
/>
</div>
</div>
<button
onClick={onSignupSuccess}
className="w-full rounded bg-slate-200 py-3 text-lg font-medium text-slate-900 transition-colors hover:bg-slate-300"
>
Register
</button>
<p className="mt-4 text-center text-sm text-slate-700">
Have an account?{" "}
<Link href="/login" className="font-semibold text-slate-900 hover:underline">
Login
</Link>
</p>
</div>
);
}
12 changes: 12 additions & 0 deletions apps/frontend/app/forgot-password/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default function ForgotPasswordPage() {
return (
<div className="flex min-h-screen items-center justify-center bg-white p-4 text-black">
<div className="w-full max-w-md rounded-lg border border-black p-8 text-center">
<h1 className="mb-4 text-2xl">Forgot Password</h1>
<p className="mb-6">Enter your email to reset your password.</p>
<input type="email" className="mb-4 w-full border border-black p-2" placeholder="Email" />
<button className="w-full rounded bg-gray-200 py-2">Send Reset Link</button>
</div>
</div>
);
}
92 changes: 92 additions & 0 deletions apps/frontend/app/login/page.tsx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the login page can we have placeholder functions that will do something when we click the login button and maybe also create a blank forgot password screen

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make functions for logging in with github and google as well

Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"use client";
import { useState } from "react";
import Link from "next/link";

export default function LoginPage() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");

const logLoginAttempt = (method: "standard" | "github" | "google") => {
console.log("Login attempt", {
method,
email,
password,
});
};

const handleLogin = () => logLoginAttempt("standard");
const handleGithubLogin = () => logLoginAttempt("github");
const handleGoogleLogin = () => logLoginAttempt("google");

return (
<div className="flex min-h-screen items-center justify-center bg-white p-4 text-slate-900">
<div className="w-full max-w-md space-y-6 rounded-lg border border-slate-300 bg-white p-8 shadow-lg">
<h1 className="mb-8 text-center text-4xl font-semibold text-slate-900">Login</h1>
<div className="space-y-4">
<div>
<label htmlFor="email" className="mb-1 block text-sm font-medium text-slate-800">
Email
</label>
<input
id="email"
type="email"
value={email}
onChange={(event) => setEmail(event.target.value)}
className="w-full rounded border border-slate-300 bg-white px-3 py-2 text-slate-900 placeholder:text-slate-400"
placeholder="you@example.com"
/>
</div>
<div>
<label htmlFor="password" className="mb-1 block text-sm font-medium text-slate-800">
Password
</label>
<input
id="password"
type="password"
value={password}
onChange={(event) => setPassword(event.target.value)}
className="w-full rounded border border-slate-300 bg-white px-3 py-2 text-slate-900 placeholder:text-slate-400"
placeholder="Enter your password"
/>
</div>
</div>
<button
onClick={handleLogin}
className="w-full rounded bg-slate-200 py-3 text-lg font-medium text-slate-900 transition hover:bg-slate-300"
>
Login
</button>
<div className="text-right">
<Link
href="/forgot-password"
title="Forgot Password?"
className="text-xs text-slate-700 hover:text-slate-900 hover:underline"
>
Forgot Password?
</Link>
</div>
{/* ... Divider ... */}
<div className="space-y-3">
<button
onClick={handleGithubLogin}
className="w-full rounded bg-slate-200 py-3 font-medium text-slate-900 transition hover:bg-slate-300"
>
Login with Github
</button>
<button
onClick={handleGoogleLogin}
className="w-full rounded bg-slate-200 py-3 font-medium text-slate-900 transition hover:bg-slate-300"
>
Login with Google
</button>
</div>
<p className="mt-4 text-center text-sm text-slate-700">
Don&apos;t have an account?{" "}
<Link href="/signup" className="font-semibold text-slate-900 hover:underline">
Register
</Link>
</p>
</div>
</div>
);
}
18 changes: 18 additions & 0 deletions apps/frontend/app/signup/page.tsx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make two separate components for the "signup" view vs the "onboarding" view? You can make a new components directory in the app frontend/app folder and import it from there. Then you can conditionally render the components based on the current state

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use client";
import { useState } from "react";
import SignUpForm from "../components/SignUpForm";
import Onboarding from "../components/Onboarding";

export default function SignupPage() {
const [isSignedUp, setIsSignedUp] = useState(false);

return (
<div className="flex min-h-screen items-center justify-center bg-white p-4 text-slate-900">
{isSignedUp ? (
<Onboarding onBack={() => setIsSignedUp(false)} />
) : (
<SignUpForm onSignupSuccess={() => setIsSignedUp(true)} />
)}
</div>
);
}
Loading