Skip to content

Commit

Permalink
finished signup ui and repository
Browse files Browse the repository at this point in the history
  • Loading branch information
bonfry committed Sep 22, 2024
1 parent e736e87 commit db8b2ba
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 57 deletions.
2 changes: 1 addition & 1 deletion .astro/astro/content.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,5 +307,5 @@ declare module 'astro:content' {

type AnyEntryMap = ContentEntryMap & DataEntryMap;

export type ContentConfig = typeof import("../../src/content/config.js");
export type ContentConfig = typeof import("./../../src/content/config.js");
}
11 changes: 11 additions & 0 deletions src/data/api/authentication_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { CheckTokenResponse, SignupResponse } from "../types/authentication";

export class AuthenticationApi {
async checkToken(token: string): Promise<CheckTokenResponse> {
return { status: true, errorMessage: null };
}

async signInWithEmailAndPassword(email: string, password: string): Promise<SignupResponse> {
return { status: true, errorMessage: null };
}
}
Empty file removed src/data/api/firebase_api.ts
Empty file.
25 changes: 25 additions & 0 deletions src/data/repositories/authentication_repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { AuthenticationApi } from "../api/authentication_api";
import type { SignUpException } from "../types/authentication";

export class AuthenticationRepository {
api: AuthenticationApi;

constructor() {
this.api = new AuthenticationApi();
}

async checkToken(token: string): Promise<boolean> {
const result = await this.api.checkToken(token);
return result.status;
}

async signInWithEmailAndPassword(email: string, password: string): Promise<void> {
const result = await this.api.signInWithEmailAndPassword(email, password);

if (!result.status) {
throw {
message: result.errorMessage
} as SignUpException;
}
}
}
13 changes: 13 additions & 0 deletions src/data/types/authentication.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type CheckTokenResponse = {
status: boolean;
errorMessage: string | null;
}

export type SignupResponse = {
status: boolean;
errorMessage: string | null;
}

export type SignUpException = {
message: string;
}
143 changes: 87 additions & 56 deletions src/react/pages/SignupPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,35 @@ import { useForm } from "@mantine/form"
import { useEffect, useState } from "react";
import { notifications, showNotification } from "@mantine/notifications";
import { isEmailValid } from "../utils";
import { useFirebaseUserInfo } from "../utils/query";
import { WebsiteConfig } from "../../config";
import { useTranslations } from "../../i18n/utils";
import { AuthenticationRepository } from "../../data/repositories/authentication_repository";

export const SignupPage = ({ token }: { token:string }) => {
enum SignUpPageStatus { Initial, InvalidToken, Ready, SignUpInProgress, SignUpError, SignUpComplete }

export const SignupPage = ({ token }: { token: string }) => {
const t = useTranslations("en")
const authRepository = new AuthenticationRepository();
const [pageStatus, setPageStatus] = useState(SignUpPageStatus.Initial);
const [showPasswords, setShowPasswords] = useState(false)

useEffect(() => {
if (pageStatus !== SignUpPageStatus.Initial) {
return;
} else if (token) {
authRepository
.checkToken(token)
.then((tokenIsValid) => {
setPageStatus(tokenIsValid
? SignUpPageStatus.Ready
: SignUpPageStatus.InvalidToken
);
});
} else {
setPageStatus(SignUpPageStatus.InvalidToken);
}
}, [pageStatus, token]);


const checkErrors = () => {
if (!form.isValid()) {
Expand All @@ -28,9 +51,9 @@ export const SignupPage = ({ token }: { token:string }) => {
confirmPassword: "",
},
validate: {
email: (value) => value.length > 0? isEmailValid(value)? undefined: "The email given is invalid": "Email is required",
password: (value) => value.length > 0? undefined: "Password is required",
confirmPassword: (value, values) => value === values.password? undefined: "Passwords do not match"
email: (value) => value.length > 0 ? isEmailValid(value) ? undefined : "The email given is invalid" : "Email is required",
password: (value) => value.length > 0 ? undefined : "Password is required",
confirmPassword: (value, values) => value === values.password ? undefined : "Passwords do not match"
},
validateInputOnChange: true,
initialErrors: {
Expand All @@ -40,82 +63,90 @@ export const SignupPage = ({ token }: { token:string }) => {
}
})

const [showPasswords, setShowPasswords] = useState(false)
const [loading, setLoading] = useState(false)

const { user, hasLoaded } = useFirebaseUserInfo()
useEffect(() => {
if(user != null && hasLoaded) {
location.href = "/app"
}
}, [user])

if(!token) {
if (pageStatus === SignUpPageStatus.Initial) {
return <AppMain><div></div></AppMain>
} else if (pageStatus === SignUpPageStatus.InvalidToken) {
return <AppMain>Invalid token</AppMain>
}


return (
<AppMain>
{/* <p>registration token: {token}</p> */}

<Form onSubmit={form.onSubmit((data)=>{
const requestId = notifications.show({
loading: true,
title: "Signing up...",
message: "Please wait untils the registration is complete",
autoClose: false
})
setLoading(true)
fetch("http://127.0.0.1/fakeAPI")
.then((userInfo) => {
notifications.update({
id: requestId,
loading: false,
title: "Registration Completed",
message: `Welcome ${user?.displayName}`,
color: "green",
autoClose: true
})
}).catch((error) => {
notifications.update({
id: requestId,
loading: false,
title: `Registration error [${error.code}]`,
message: error.message,
color: "red",
autoClose: true
})
}).finally(() => {
setLoading(false)
})
<Form onSubmit={form.onSubmit((data) => {
const requestId = notifications.show({
loading: true,
title: "Signing up...",
message: "Please wait untils the sign up is complete",
autoClose: false
})

setPageStatus(SignUpPageStatus.SignUpInProgress);

authRepository
.signInWithEmailAndPassword(data.email, data.password)
.then(() => {
notifications.update({
id: requestId,
loading: false,
title: "Sign up Completed",
message: `Welcome ${form.values.email}`,
color: "green",
autoClose: true
});
setPageStatus(SignUpPageStatus.SignUpComplete);

setTimeout(() => {
location.href = "/login";
}, 1500);

}).catch((error) => {
notifications.update({
id: requestId,
loading: false,
title: `Registration error [${error.code}]`,
message: error.message,
color: "red",
autoClose: true
});
setPageStatus(SignUpPageStatus.SignUpError);
});
})
}>
<Card className="md:px-20 md:py-16 bg-black md:bg-opacity-60 bg-opacity-25 z-10 md:h-fit md:w-fit h-screen w-screen justify-center rounded-none px-5 md:rounded-xl">
<div className="flex flex-col opacity-100 justify-center items-center">
<img src="/assets/vectors/logo_big.svg" className="h-36 m-2 px-8 md:p-0 md:m-6" />
<p className="text-2xl md:text-3xl font-semibold mt-5">
{
WebsiteConfig.EVENT_START.toLocaleDateString("en", {
timeZone: WebsiteConfig.EVENT_TIMEZONE,
day: "numeric",
month: "long",
year: "numeric",
})
WebsiteConfig.EVENT_START.toLocaleDateString("en", {
timeZone: WebsiteConfig.EVENT_TIMEZONE,
day: "numeric",
month: "long",
year: "numeric",
})
}
</p>
<p className="text-2xl md:text-3xl font-semibold">{t("info.locationName")}</p>
<div className="flex flex-col mt-10 w-full">
<Input placeholder="Email" type="text" {...form.getInputProps("email")} />
<Input placeholder="Password" type={showPasswords?"text":"password"} className="mt-3" {...form.getInputProps("password")} />
<Input placeholder="Confirm Password" type={showPasswords?"text":"password"} className="mt-3" {...form.getInputProps("confirmPassword")} />

<Input placeholder="Password" type={showPasswords ? "text" : "password"} className="mt-3" {...form.getInputProps("password")} />
<Input placeholder="Confirm Password" type={showPasswords ? "text" : "password"} className="mt-3" {...form.getInputProps("confirmPassword")} />
<div className="flex w-full justify-end mt-2">
<Form.Label title="Show passwords">
<Checkbox className="ml-3" size="md" onChange={(e)=>setShowPasswords(e.target.checked)} checked={showPasswords} />
<Checkbox className="ml-3" size="md" onChange={(e) => setShowPasswords(e.target.checked)} checked={showPasswords} />
</Form.Label>
</div>
</div>
<div className="flex flex-col mt-10 items-center w-full">
<Input type="submit" value={loading?"Loading":"Signup"} className={`btn btn-primary btn-wide ${loading?"opacity-40 btn-warning":""}`} onClick={checkErrors} disabled={loading} />
<Input
type="submit"
value={pageStatus == SignUpPageStatus.SignUpInProgress ? "Loading" : "Signup"}
className={`btn btn-primary btn-wide ${pageStatus == SignUpPageStatus.SignUpInProgress ? "opacity-40 btn-warning" : ""}`}
onClick={checkErrors}
disabled={pageStatus == SignUpPageStatus.SignUpInProgress} />
</div>
</div>
</Card>
Expand Down

0 comments on commit db8b2ba

Please sign in to comment.