Skip to content

Commit 8843072

Browse files
add signup and style it
1 parent 91fb33e commit 8843072

File tree

3 files changed

+231
-8
lines changed

3 files changed

+231
-8
lines changed

app/login/page.tsx

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,7 @@ const Login = () => {
103103
variant="outline"
104104
type="button"
105105
>
106-
<Image
107-
width="24"
108-
height="24"
109-
src="https://img.icons8.com/material-rounded/24/google-logo.png"
110-
alt="google-logo"
111-
/>
106+
<GoogleIcon className="size-8" />
112107
Login with Google
113108
</Button>
114109
</Field>
@@ -168,4 +163,33 @@ const Login = () => {
168163
);
169164
};
170165

166+
const GoogleIcon = ({ className }: { className?: string }) => (
167+
<svg
168+
xmlns="http://www.w3.org/2000/svg"
169+
x="0px"
170+
y="0px"
171+
width="28"
172+
height="28"
173+
viewBox="0 0 48 48"
174+
className={className}
175+
>
176+
<path
177+
fill="#FFC107"
178+
d="M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12c0-6.627,5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24c0,11.045,8.955,20,20,20c11.045,0,20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z"
179+
></path>
180+
<path
181+
fill="#FF3D00"
182+
d="M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z"
183+
></path>
184+
<path
185+
fill="#4CAF50"
186+
d="M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36c-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z"
187+
></path>
188+
<path
189+
fill="#1976D2"
190+
d="M43.611,20.083H42V20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571c0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z"
191+
></path>
192+
</svg>
193+
);
194+
171195
export default Login;

app/signup/page.tsx

Lines changed: 197 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,201 @@
1+
"use client";
2+
3+
import { Button } from "@/components/ui/button";
4+
import { Card, CardContent } from "@/components/ui/card";
5+
import {
6+
Field,
7+
FieldDescription,
8+
FieldGroup,
9+
FieldLabel,
10+
FieldSeparator,
11+
} from "@/components/ui/field";
12+
import { Input } from "@/components/ui/input";
13+
import { createClient } from "@/lib/supabase/client";
14+
import type { Provider } from "@supabase/auth-js";
15+
import Image from "next/image";
16+
import Link from "next/link";
17+
import { useRouter } from "next/navigation";
18+
import { useState } from "react";
19+
120
const Signup = () => {
2-
return <div>Signup</div>;
21+
const [email, setEmail] = useState("");
22+
const [password, setPassword] = useState("");
23+
const [confirmPassword, setConfirmPassword] = useState("");
24+
const [error, setError] = useState<string | null>(null);
25+
const [isLoading, setIsLoading] = useState(false);
26+
const router = useRouter();
27+
28+
const supabase = createClient();
29+
30+
const handleSignup = async (e: React.FormEvent) => {
31+
e.preventDefault();
32+
setIsLoading(true);
33+
setError(null);
34+
35+
if (password !== confirmPassword) {
36+
setError("Passwords do not match");
37+
setIsLoading(false);
38+
return;
39+
}
40+
41+
try {
42+
const { error } = await supabase.auth.signUp({
43+
email,
44+
password,
45+
});
46+
if (error) throw error;
47+
router.push("/");
48+
} catch (error: unknown) {
49+
console.log(error);
50+
setError(error instanceof Error ? error.message : "An error occurred");
51+
} finally {
52+
setIsLoading(false);
53+
}
54+
};
55+
56+
const handleOAuthLogin = async (provider: Provider) => {
57+
setIsLoading(true);
58+
setError(null);
59+
60+
try {
61+
const { error } = await supabase.auth.signInWithOAuth({
62+
provider,
63+
options: {
64+
redirectTo: `${window.location.origin}`,
65+
},
66+
});
67+
if (error) throw error;
68+
} catch (error: unknown) {
69+
setError(error instanceof Error ? error.message : "An error occurred");
70+
} finally {
71+
setIsLoading(false);
72+
}
73+
};
74+
75+
return (
76+
<section className="flex min-h-svh flex-col items-center justify-center p-6 md:p-10">
77+
<div className="w-full max-w-sm md:max-w-md flex flex-col gap-6">
78+
<Card className="overflow-hidden p-0">
79+
<CardContent>
80+
<form className="px-2 py-6" onSubmit={handleSignup}>
81+
<FieldGroup>
82+
<div className="flex flex-col items-center gap-2 text-center">
83+
<h1 className="text-2xl font-bold">Create your account</h1>
84+
<p className="text-muted-foreground text-sm text-balance">
85+
Enter your email below to create your account
86+
</p>
87+
</div>
88+
<Field>
89+
<FieldLabel htmlFor="email">Email</FieldLabel>
90+
<Input
91+
id="email"
92+
type="email"
93+
placeholder="[email protected]"
94+
required
95+
value={email}
96+
onChange={(e) => setEmail(e.target.value)}
97+
/>
98+
</Field>
99+
<Field>
100+
<Field className="grid grid-cols-2 gap-4">
101+
<Field>
102+
<FieldLabel htmlFor="password">Password</FieldLabel>
103+
<Input
104+
id="password"
105+
type="password"
106+
required
107+
value={password}
108+
onChange={(e) => setPassword(e.target.value)}
109+
/>
110+
</Field>
111+
<Field>
112+
<FieldLabel htmlFor="confirm-password">
113+
Confirm Password
114+
</FieldLabel>
115+
<Input
116+
id="confirm-password"
117+
type="password"
118+
required
119+
value={confirmPassword}
120+
onChange={(e) => setConfirmPassword(e.target.value)}
121+
/>
122+
</Field>
123+
</Field>
124+
<FieldDescription>
125+
Must be at least 8 characters long.
126+
</FieldDescription>
127+
</Field>
128+
{error && <p className="text-sm text-red-500">{error}</p>}
129+
<Field>
130+
<Button type="submit" disabled={isLoading}>
131+
{isLoading ? "Creating Account..." : "Create Account"}
132+
</Button>
133+
</Field>
134+
<FieldSeparator className="*:data-[slot=field-separator-content]:bg-card">
135+
Or continue with
136+
</FieldSeparator>
137+
<Field className="grid grid-cols-2 gap-4">
138+
<Button
139+
variant="outline"
140+
type="button"
141+
onClick={() => handleOAuthLogin("github")}
142+
>
143+
<Image
144+
width="24"
145+
height="24"
146+
src="https://img.icons8.com/material-outlined/24/github.png"
147+
alt="github"
148+
/>
149+
<span className="sr-only">Sign up with Github</span>
150+
</Button>
151+
<Button
152+
variant="outline"
153+
type="button"
154+
onClick={() => handleOAuthLogin("google")}
155+
>
156+
<GoogleIcon className="size-8" />
157+
<span className="sr-only">Sign up with Google</span>
158+
</Button>
159+
</Field>
160+
<FieldDescription className="text-center">
161+
Already have an account? <Link href="/login">Log in</Link>
162+
</FieldDescription>
163+
</FieldGroup>
164+
</form>
165+
</CardContent>
166+
</Card>
167+
</div>
168+
</section>
169+
);
3170
};
4171

172+
const GoogleIcon = ({ className }: { className?: string }) => (
173+
<svg
174+
xmlns="http://www.w3.org/2000/svg"
175+
x="0px"
176+
y="0px"
177+
width="28"
178+
height="28"
179+
viewBox="0 0 48 48"
180+
className={className}
181+
>
182+
<path
183+
fill="#FFC107"
184+
d="M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12c0-6.627,5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24c0,11.045,8.955,20,20,20c11.045,0,20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z"
185+
></path>
186+
<path
187+
fill="#FF3D00"
188+
d="M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z"
189+
></path>
190+
<path
191+
fill="#4CAF50"
192+
d="M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36c-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z"
193+
></path>
194+
<path
195+
fill="#1976D2"
196+
d="M43.611,20.083H42V20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571c0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z"
197+
></path>
198+
</svg>
199+
);
200+
5201
export default Signup;

components/NavbarComponents/AuthButtons.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ const AuthButtons = () => {
1212
useEffect(() => {
1313
const fetchUser = async () => {
1414
const { data } = await supabase.auth.getUser();
15-
if (data.user) setUser(data.user.user_metadata.name);
15+
16+
setUser(
17+
data?.user?.user_metadata?.name || data?.user?.email?.split("@")[0],
18+
);
1619
setLoading(false);
1720
};
1821
fetchUser();

0 commit comments

Comments
 (0)