Skip to content

Commit

Permalink
feat: social sign up and welcome page
Browse files Browse the repository at this point in the history
Co-authored-by: CrackThrough <[email protected]>
  • Loading branch information
paring-chan and CrackThrough committed Dec 22, 2023
1 parent 73119fb commit 13e3947
Show file tree
Hide file tree
Showing 19 changed files with 249 additions and 108 deletions.
2 changes: 1 addition & 1 deletion src/assets
7 changes: 5 additions & 2 deletions src/components/atoms/interaction/InputField.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import type { FormEventHandler } from 'svelte/elements';
export let value: string = '';
export let placeholder: string = '';
export let placeholder: TranslationKey | undefined = undefined;
export let type = 'text';
let showPassword: boolean = false;
Expand All @@ -13,7 +13,9 @@
value = (e.target as HTMLInputElement).value;
};
$: localizedPlaceholder = translate(placeholder as TranslationKey, {}, true, $currentLang);
$: localizedPlaceholder = placeholder
? translate(placeholder, {}, true, $currentLang)
: undefined;
$: inputType = type === 'password' ? (showPassword ? 'text' : 'password') : type;
$: passwordVisible = type === 'password';
</script>
Expand All @@ -32,6 +34,7 @@
<button
type="button"
class="input-field__password-button"
tabindex={-1}
on:click={() => {
showPassword = !showPassword;
}}
Expand Down
11 changes: 6 additions & 5 deletions src/components/molecules/auth/OAuth2SignOptions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
import Translation from '@/components/utils/Translation.svelte';
import Button from '@atoms/interaction/Button.svelte';
import Google from 'svelte-icons/fa/FaGoogle.svelte';
import { createEventDispatcher } from 'svelte';
import type { StringTranslationKey } from '@/utils/i18n';
const dispatch = createEventDispatcher();
export let labelKey: StringTranslationKey = 'sign-in:more-options';
type Provider = 'discord' | 'google';
export let providerLinks: Record<Provider, string>;
</script>

<div class="oauth2-container">
Expand All @@ -19,10 +20,10 @@
<div class="oauth2-line" />
</div>
<div class="oauth2-options">
<Button type="authAction" on:click={() => dispatch('googleSignup')}>
<Button type="authAction" href={providerLinks.google}>
<Google />
</Button>
<Button type="authAction" on:click={() => dispatch('discordSignup')}>
<Button type="authAction" href={providerLinks.discord}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36"
><path
fill="#fff"
Expand Down
14 changes: 10 additions & 4 deletions src/components/molecules/form/FormControl.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
$: error = $errors[name];
</script>

<div class="form-control">
<label class="form-control">
{#if labelKey}
<Translation key={labelKey} />
<div>label(TODO)</div>
<span class="form-label">
<Translation key={labelKey} />
</span>
{/if}

<slot />
Expand All @@ -25,12 +26,17 @@
<Translation key="form:error-{error}" />
</Hint>
{/if}
</div>
</label>

<style lang="scss">
.form-control {
display: flex;
flex-direction: column;
gap: 4px;
}
.form-label {
font-weight: 500;
font-size: 16px;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@
placeholder="search:meta-field-song-placeholder"
/>
</LabeledInputContainer>
<LabeledInputContainer key="search:meta-field-creator">
<LabeledInputContainer key="search:meta-field-creator-label">
<SearchMetaInput
on:input={onChangeCreator}
value={$parsedQuery.creator}
Expand Down
10 changes: 10 additions & 0 deletions src/components/utils/Translation.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,23 @@
export let key: TranslationKey;
export let params: Record<string, FluentVariable> = {};
export let allowLinks = false;
export let htmlReplacer: (value: string) => string = (v) => v;
const builtinReplacer = (text: string): string => {
if (allowLinks)
text = text.replace(/\[link="([^"]*)"\]([^"]*)\[\/link\]/g, (_, href, text) => {
return `<a href="${href}" class="link">${decodeURIComponent(text)}</a>`;
});
return text;
};
$: htmlValue = (() => {
let k = translate(key, params, true, $currentLang);
k = htmlReplacer(k);
k = builtinReplacer(k);
return k;
})();
Expand Down
7 changes: 6 additions & 1 deletion src/routes/auth/signin/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@
<Translation key="sign-in:title" />
</Button>

<OAuth2SignOptions />
<OAuth2SignOptions
providerLinks={{
google: '/auth/signin/google',
discord: '/auth/signin/discord'
}}
/>

<div class="new-to-adofaigg-container">
<div class="new-to-adofaigg">
Expand Down
21 changes: 21 additions & 0 deletions src/routes/auth/signup/+page.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { superValidate } from 'sveltekit-superforms/client';
import type { Actions, PageServerLoad } from './$types';
import { schema } from './_schema';
import { fail } from '@sveltejs/kit';

export const load: PageServerLoad = async () => {
return {
minimalFooter: true,
form: await superValidate(schema)
};
};

export const actions: Actions = {
default: async ({ request }) => {
const form = await superValidate(request, schema);

if (!form.valid) return fail(400, { form });

console.log(form.data);
}
};
147 changes: 61 additions & 86 deletions src/routes/auth/signup/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,117 +1,92 @@
<script lang="ts">
import AuthTitle from '@/components/atoms/auth/AuthTitle.svelte';
import Translation from '@/components/utils/Translation.svelte';
import Hint from '@/components/atoms/form/Hint.svelte';
import { setForm } from '@/utils/forms';
import Button from '@atoms/interaction/Button.svelte';
import CheckboxWithLinkedLabel from '@molecules/auth/CheckboxWithLinkedLabel.svelte';
import OAuth2SignOptions from '@molecules/auth/OAuth2SignOptions.svelte';
import { goto } from '$app/navigation';
import type { PageData } from './$types';
import { schema } from './_schema';
import FormControl from '@/components/molecules/form/FormControl.svelte';
import InputField from '@/components/atoms/interaction/InputField.svelte';
let agreeTos = false;
let agreePrivacy = false;
export let data: PageData;
$: legalAgreements = [agreeTos, agreePrivacy];
let signupFailed = false;
let validationResultViaCheckboxUpdate = false;
const validate = (updateSignupFailed = true) => {
const result = legalAgreements.every((agreement) => agreement);
if (updateSignupFailed) signupFailed = !result;
return result;
};
const onCheckboxUpdate = () => {
validationResultViaCheckboxUpdate = validate(false);
};
const emailSignup = () => {
if (!validate()) return;
return goto('/auth/signup/email');
};
const googleSignup = () => {
if (!validate()) return;
// TODO implement after social login is implemented in backend
throw new Error('Not implemented');
};
const discordSignup = () => {
if (!validate()) return;
// TODO implement after social login is implemented in backend
throw new Error('Not implemented');
};
const { form, enhance } = setForm(data.form, { validators: schema });
</script>

<AuthTitle>
<Translation key="sign-up:title" />
</AuthTitle>

<!-- register form -->
<div class="legal-agreement-terms-group">
<h3>
<Translation key="sign-up:section-terms" />
</h3>
<div class="legal-agreement-container">
<CheckboxWithLinkedLabel
labelKey="sign-up:terms-agreement"
extraLabelKey="sign-up:terms-link"
extraLabelLink="../docs/terms"
bind:checked={agreeTos}
onChange={onCheckboxUpdate}
<form class="form-fields" method="POST" use:enhance>
<FormControl name="email" labelKey="sign-up:form-email">
<InputField
name="email"
type="email"
placeholder="sign-up:form-email-placeholder"
bind:value={$form.email}
/>
</FormControl>
<FormControl name="username" labelKey="sign-up:form-username">
<InputField
name="username"
type="text"
placeholder="sign-up:form-username-placeholder"
bind:value={$form.username}
/>
<CheckboxWithLinkedLabel
labelKey="sign-up:privacy-agreement"
extraLabelKey="sign-up:privacy-link"
extraLabelLink="../docs/privacy"
bind:checked={agreePrivacy}
onChange={onCheckboxUpdate}
</FormControl>
<FormControl name="password" labelKey="sign-up:form-password">
<InputField
name="password"
type="password"
placeholder="sign-up:form-password-placeholder"
bind:value={$form.password}
/>
</FormControl>
<FormControl name="confirmPassword" labelKey="sign-up:form-password-confirm">
<InputField
name="confirmPassword"
type="password"
placeholder="sign-up:form-password-confirm-placeholder"
bind:value={$form.confirmPassword}
/>
</FormControl>

<!-- register form -->
<div class="submit-area">
<Button type="authActionAccent" htmlType="submit">
<Translation key="sign-up:strategy-email" />
</Button>
<div class="condition-disclaimer">
<Translation key="sign-up:conditions-disclaimer" allowLinks />
</div>
</div>
{#if signupFailed && !validationResultViaCheckboxUpdate}
<Hint variant="error">
<Translation key="sign-up:error-agreement-required" />
</Hint>
{/if}
</div>
<Button type="authActionAccent" on:click={emailSignup}>
<Translation key="sign-up:strategy-email" />
</Button>
</form>

<!-- oauth2 register buttons -->
<OAuth2SignOptions
labelKey="sign-up:more-options"
on:googleSignup={googleSignup}
on:discordSignup={discordSignup}
providerLinks={{
discord: '/auth/signup/discord',
google: '/auth/signup/google'
}}
/>

<style lang="scss">
.legal-agreement-terms-group {
.form-fields {
display: flex;
flex-direction: column;
gap: 12px;
align-items: flex-start;
align-self: stretch;
justify-content: center;
> h3 {
font-weight: 700;
font-style: normal;
font-size: 16px;
line-height: 1.2;
}
gap: 32px;
}
.legal-agreement-container {
.submit-area {
display: flex;
flex-direction: column;
gap: 12px;
align-items: flex-start;
align-self: stretch;
}
.condition-disclaimer {
margin-top: 8px;
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
}
</style>
7 changes: 0 additions & 7 deletions src/routes/auth/signup/+page.ts

This file was deleted.

32 changes: 32 additions & 0 deletions src/routes/auth/signup/[provider]/+page.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { error, fail } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
import { superValidate } from 'sveltekit-superforms/client';
import { schema } from './_schema';

const providers = ['google', 'discord'] as const;

type ProviderName = (typeof providers)[number];

const providerNames: Record<ProviderName, string> = {
google: 'Google',
discord: 'Discord'
};

export const load: PageServerLoad = async ({ params: { provider } }) => {
if (!(providers as unknown as string[]).includes(provider))
return error(404, { message: 'Not found' });

return {
provider,
providerName: providerNames[provider as ProviderName],
form: await superValidate(schema)
};
};

export const actions: Actions = {
default: async ({ request }) => {
const form = await superValidate(request, schema);

if (!form.valid) return fail(400, { form });
}
};
Loading

0 comments on commit 13e3947

Please sign in to comment.