-
Notifications
You must be signed in to change notification settings - Fork 0
[CSSG-13]: Added login and signup page #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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> | ||
| ); | ||
| } |
| 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> | ||
| ); | ||
| } |
| 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> | ||
| ); | ||
| } |
| 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"> | ||
| </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't have an account?{" "} | ||
| <Link href="/signup" className="font-semibold text-slate-900 hover:underline"> | ||
| Register | ||
| </Link> | ||
| </p> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
| 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> | ||
| ); | ||
| } |

There was a problem hiding this comment.
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
There was a problem hiding this comment.
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