Init Project
This is a pretty far-developed starting point. Authentication has been intialized with Better-Auth, a database has been setup with Prisma, and Google + email logins have been enabled, as well as Google + Email registration.
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import Window from '$lib/components/containers/Window.svelte';
|
||||
</script>
|
||||
|
||||
<Window>
|
||||
{#if $page.status === 403}
|
||||
<h1>Not Authorized</h1>
|
||||
<p>
|
||||
You don't have permission to view this page. Click <a
|
||||
href="/"
|
||||
class="underlined text-blue-600">here</a
|
||||
> to return home.
|
||||
</p>
|
||||
{/if}
|
||||
</Window>
|
||||
@@ -0,0 +1,14 @@
|
||||
<script lang="ts">
|
||||
import './layout.css';
|
||||
import favicon from '$lib/assets/favicon.svg';
|
||||
import TopBar from '$lib/components/ui/topBar/TopBar.svelte';
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<svelte:head><link rel="icon" href={favicon} /></svelte:head>
|
||||
|
||||
<TopBar />
|
||||
<div class="flex px-4">
|
||||
{@render children()}
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Center from '$lib/components/containers/Center.svelte';
|
||||
</script>
|
||||
|
||||
<Center>
|
||||
<h1>Hello</h1>
|
||||
</Center>
|
||||
@@ -0,0 +1,3 @@
|
||||
@import 'tailwindcss';
|
||||
@plugin '@tailwindcss/forms';
|
||||
@plugin '@tailwindcss/typography';
|
||||
@@ -0,0 +1,52 @@
|
||||
<script lang="ts">
|
||||
import { authClient } from '$lib/auth-client';
|
||||
import Window from '$lib/components/containers/Window.svelte';
|
||||
let email = $state('');
|
||||
let password = $state('');
|
||||
let error = $state('');
|
||||
let rememberMe = $state(false);
|
||||
|
||||
async function handleSubmit() {
|
||||
const { data, error: authError } = await authClient.signIn.email({
|
||||
email,
|
||||
password,
|
||||
rememberMe
|
||||
});
|
||||
|
||||
if (authError) {
|
||||
console.log(data);
|
||||
console.log(authError);
|
||||
error = authError.message as string;
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.href = '/';
|
||||
}
|
||||
</script>
|
||||
|
||||
<Window>
|
||||
<div>
|
||||
{#if error}
|
||||
<span class="text-red-600">{error}</span>
|
||||
{/if}
|
||||
<form
|
||||
onsubmit={handleSubmit}
|
||||
class="bg-grey-200 my-6 flex flex-col items-center justify-center"
|
||||
>
|
||||
<p>Login</p>
|
||||
<input type="email" placeholder="Email Address" bind:value={email} required class="my-2" />
|
||||
<input type="password" placeholder="Password" bind:value={password} required class="my-2" />
|
||||
<button class="mt-4 rounded bg-blue-200 px-4 py-2" type="submit">Sign In</button>
|
||||
</form>
|
||||
<div class="mt-4 flex flex-col items-center justify-center">
|
||||
<span>Or</span>
|
||||
<button
|
||||
onclick={async () => {
|
||||
authClient.signIn.social({ provider: 'google' });
|
||||
}}
|
||||
>
|
||||
<img src="light/web_light_sq_SI.svg" alt="Sign In with Google" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Window>
|
||||
@@ -0,0 +1,13 @@
|
||||
import { page } from 'vitest/browser';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { render } from 'vitest-browser-svelte';
|
||||
import Page from './+page.svelte';
|
||||
|
||||
describe('/+page.svelte', () => {
|
||||
it('should render h1', async () => {
|
||||
render(Page);
|
||||
|
||||
const heading = page.getByRole('heading', { level: 1 });
|
||||
await expect.element(heading).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import type { Actions } from "./$types";
|
||||
import { auth } from "$lib/auth";
|
||||
import { fail } from "@sveltejs/kit";
|
||||
|
||||
export const actions: Actions = {
|
||||
default: async ({ request }) => {
|
||||
const data = await request.formData();
|
||||
|
||||
const firstName = data.get('firstName') as string;
|
||||
const lastName = data.get('lastName') as string;
|
||||
const email = data.get('email') as string;
|
||||
const password = data.get('password') as string;
|
||||
const password2 = data.get('password2') as string;
|
||||
|
||||
if (password != password2) {
|
||||
return fail(400, 'an email address is required!');
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await auth.api.signUpEmail({
|
||||
body: {
|
||||
name: `${firstName} ${lastName}`,
|
||||
email: email,
|
||||
password: password
|
||||
}
|
||||
})
|
||||
|
||||
if (response.user) {
|
||||
return { success: true }
|
||||
}
|
||||
} catch (err) {
|
||||
return fail(400, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<script lang="ts">
|
||||
import Window from '$lib/components/containers/Window.svelte';
|
||||
</script>
|
||||
|
||||
<Window>
|
||||
<form method="POST" class="flex flex-col items-start">
|
||||
<input type="text" name="firstName" placeholder="First Name" required class="mb-2" />
|
||||
<input type="text" name="lastName" placeholder="Last Name" required class="mb-2" />
|
||||
<input type="email" name="email" placeholder="Email Address" required class="mb-2" />
|
||||
<input type="password" name="password" placeholder="Password" required class="mb-2" />
|
||||
<input type="password" name="password2" placeholder="Verify Password" required class="mb-2" />
|
||||
<button type="submit" class="ml-auto rounded-full bg-blue-600 px-6 py-2 text-white"
|
||||
>Submit</button
|
||||
>
|
||||
</form>
|
||||
</Window>
|
||||
Reference in New Issue
Block a user