Skip to content

Commit 3bf09ec

Browse files
committed
include email signup
1 parent 8355a49 commit 3bf09ec

File tree

5 files changed

+120
-1
lines changed

5 files changed

+120
-1
lines changed

apps/codingcatdev/src/lib/client/firebase.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { toastStore } from '@codingcatdev/blackcatui';
22
import { initializeApp, getApps, FirebaseError } from 'firebase/app';
3-
import { getAuth, setPersistence, browserSessionPersistence, signInWithEmailAndPassword, signInWithPopup, type AuthProvider, type Auth } from 'firebase/auth';
3+
import { getAuth, setPersistence, browserSessionPersistence, signInWithEmailAndPassword, signInWithPopup, type AuthProvider, type Auth, createUserWithEmailAndPassword } from 'firebase/auth';
44
import { getFirestore, collection, doc, addDoc, onSnapshot, Firestore } from 'firebase/firestore';
55
import { httpsCallable, getFunctions, type Functions } from 'firebase/functions';
66

@@ -51,6 +51,12 @@ export const ccdSignInWithEmailAndPassword = async ({ email, password }: { email
5151
setCookie(idToken);
5252
}
5353

54+
export const ccdSignUpWithEmailAndPassword = async ({ email, password }: { email: string, password: string }) => {
55+
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
56+
const idToken = await userCredential.user.getIdToken();
57+
setCookie(idToken);
58+
}
59+
5460
export const ccdSignInWithPopUp = async (provider: AuthProvider) => {
5561
try {
5662
const result = await signInWithPopup(auth, provider)

apps/codingcatdev/src/routes/login/+page.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<LayoutWrapper>
1717
<section class="bcu-card flex flex-col gap-4 p-4">
1818
<EmailAuth {action} />
19+
<a href={`/signup${action.replace('/login&', '')}`}>Sign Up</a>
1920
<hr />
2021

2122
<GoogleAuth {action} />
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { ccdCreateSessionCookie } from '$lib/server/firebase';
2+
import type { Actions } from './$types';
3+
import { fail, redirect } from '@sveltejs/kit'
4+
5+
export const actions = {
6+
signup: async ({ cookies, url }) => {
7+
const ccdLoginIdToken = cookies.get('__ccdlogin');
8+
9+
if (!ccdLoginIdToken) {
10+
return fail(400, { missing: true });
11+
}
12+
13+
const sessionCookie = await ccdCreateSessionCookie(ccdLoginIdToken);
14+
if (!sessionCookie) {
15+
return fail(400, { incorrect: true });
16+
}
17+
cookies.set(sessionCookie.name, sessionCookie.sessionCookie, sessionCookie.options);
18+
cookies.set('__ccdlogin', '', { expires: new Date(Date.now() - 3600) });
19+
20+
if (url.searchParams.has('redirectTo')) {
21+
throw redirect(303, url.searchParams.get('redirectTo') || '/');
22+
}
23+
throw redirect(303, '/');
24+
},
25+
} satisfies Actions;
26+
27+
export const load = (async ({ parent, url }) => {
28+
const { user } = await parent();
29+
if (user) throw redirect(303, '/account');
30+
31+
return {
32+
redirectTo: url.searchParams.get('redirectTo') || ''
33+
}
34+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script lang="ts">
2+
import LayoutWrapper from '../(layout-partials)/LayoutWrapper.svelte';
3+
4+
// TODO: More actions
5+
// export let form: ActionData;
6+
7+
import type { PageData } from './$types';
8+
import SignupAuth from './SignupAuth.svelte';
9+
export let data: PageData;
10+
$: action = `?/signup&redirectTo=${data.redirectTo ? data.redirectTo : '/dashboard'}`;
11+
</script>
12+
13+
<LayoutWrapper>
14+
<section class="bcu-card flex flex-col gap-4 p-4">
15+
<SignupAuth {action} />
16+
</section>
17+
</LayoutWrapper>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<script lang="ts">
2+
import { enhance } from '$app/forms';
3+
4+
import { ccdSignUpWithEmailAndPassword } from '$lib/client/firebase';
5+
6+
import { toastStore } from '@codingcatdev/blackcatui';
7+
8+
export let action: string;
9+
</script>
10+
11+
<form
12+
class="flex justify-center w-full"
13+
method="POST"
14+
{action}
15+
use:enhance={async ({ action, cancel, controller, data, form }) => {
16+
// `form` is the `<form>` element
17+
// `data` is its `FormData` object
18+
// `action` is the URL to which the form is posted
19+
// `cancel()` will prevent the submission
20+
21+
const email = `${data.get('email')}`;
22+
const password = `${data.get('password')}`;
23+
24+
if (!email || !password) {
25+
toastStore.trigger({
26+
message: 'Please Provide Username and Password.'
27+
});
28+
cancel();
29+
} else {
30+
try {
31+
await ccdSignUpWithEmailAndPassword({ email, password });
32+
} catch (err) {
33+
if (err instanceof Error) {
34+
toastStore.trigger({
35+
message: err.message,
36+
background: 'variant-filled-error'
37+
});
38+
}
39+
}
40+
}
41+
42+
return async ({ result, update }) => {
43+
// `result` is an `ActionResult` object
44+
// `update` is a function which triggers the logic that would be triggered if this callback wasn't set
45+
46+
update();
47+
};
48+
}}
49+
>
50+
<div class="flex flex-col gap-4 text-token">
51+
<label class="label">
52+
<span>Email</span>
53+
<input class="input" name="email" type="email" placeholder="alex@codingcat.dev" />
54+
</label>
55+
<label class="label">
56+
<span>Password</span>
57+
<input class="input" name="password" type="password" />
58+
</label>
59+
<button class="bcu-button variant-filled-primary" type="submit">Sign Up</button>
60+
</div>
61+
</form>

0 commit comments

Comments
 (0)