feat: add sign in page
This commit is contained in:
parent
240e2f97fb
commit
55d67cf118
46
src/pages/SignIn.vue
Normal file
46
src/pages/SignIn.vue
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<script setup>
|
||||||
|
import { Button, InputText, Message } from 'primevue';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useAuthStore } from '@/store/auth';
|
||||||
|
import Loader from '@/components/Loader.vue';
|
||||||
|
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
|
const email = ref('')
|
||||||
|
const password = ref('')
|
||||||
|
|
||||||
|
const signin = async () => {
|
||||||
|
await authStore.auth('signIn',{ email: email.value, password: password.value })
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<h2>Sign In</h2>
|
||||||
|
<form class="flex flex-column gap-3" @submit.prevent="signin">
|
||||||
|
<transition-group name="p-message" tag="div" class="flex flex-col">
|
||||||
|
<Message v-if="authStore.error" closable icon="pi pi-times-circle" class="flex-1" severity="error">{{authStore.error}}</Message>
|
||||||
|
</transition-group>
|
||||||
|
|
||||||
|
<div class="p-inputgroup flex align-items-center gap-4">
|
||||||
|
<span class="p-inputgroup-addon">
|
||||||
|
<i class="pi pi-user"></i>
|
||||||
|
</span>
|
||||||
|
<InputText type="email" class="flex-1" v-model="email" placeholder="Your Email" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-inputgroup flex align-items-center gap-4">
|
||||||
|
<span class="p-inputgroup-addon">
|
||||||
|
<i class="pi pi-at"></i>
|
||||||
|
</span>
|
||||||
|
<InputText type="password" class="flex-1" v-model="password" placeholder="Password" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-column gap-3">
|
||||||
|
<Loader v-if="authStore.loading" />
|
||||||
|
<Button v-else label="Signin" type="submit" />
|
||||||
|
|
||||||
|
<span>Are you not registered yet? <router-link to="/sign-up">Sign up</router-link></span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
const password = ref('')
|
const password = ref('')
|
||||||
|
|
||||||
const signup = async () => {
|
const signup = async () => {
|
||||||
await authStore.signUp({ email: email.value, password: password.value })
|
await authStore.auth('signUp', { email: email.value, password: password.value })
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@ -19,7 +19,7 @@
|
|||||||
<h2>Sign Up</h2>
|
<h2>Sign Up</h2>
|
||||||
<form class="flex flex-column gap-3" @submit.prevent="signup">
|
<form class="flex flex-column gap-3" @submit.prevent="signup">
|
||||||
<transition-group name="p-message" tag="div" class="flex flex-col">
|
<transition-group name="p-message" tag="div" class="flex flex-col">
|
||||||
<Message v-if="authStore.error" closable icon="pi pi-times-circle" severity="error">{{authStore.error}}</Message>
|
<Message v-if="authStore.error" closable icon="pi pi-times-circle" class="flex-1" severity="error">{{authStore.error}}</Message>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
|
|
||||||
<div class="p-inputgroup flex align-items-center gap-4">
|
<div class="p-inputgroup flex align-items-center gap-4">
|
||||||
@ -38,9 +38,9 @@
|
|||||||
|
|
||||||
<div class="flex flex-column gap-3">
|
<div class="flex flex-column gap-3">
|
||||||
<Loader v-if="authStore.loading" />
|
<Loader v-if="authStore.loading" />
|
||||||
<Button v-else label="Signup" @click="signup"/>
|
<Button v-else label="Signup" type="submit" />
|
||||||
|
|
||||||
<span>Are you already registered? <router-link to="/signin">Sign in</router-link></span>
|
<span>Are you already registered? <router-link to="/sign-in">Sign in</router-link></span>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -8,6 +8,11 @@ const router = createRouter({
|
|||||||
path: '/sign-up',
|
path: '/sign-up',
|
||||||
name: 'SignUp',
|
name: 'SignUp',
|
||||||
component: () => import('../pages/SignUp.vue')
|
component: () => import('../pages/SignUp.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/sign-in',
|
||||||
|
name: 'SignIn',
|
||||||
|
component: () => import('../pages/SignIn.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|||||||
@ -13,11 +13,13 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const error = ref('');
|
const error = ref('');
|
||||||
|
|
||||||
const signUp = async (payload: {email: string; password: string}) => {
|
const auth = async <T extends 'signUp' | 'signIn'>(type: T, payload: {email: string; password: string}) => {
|
||||||
error.value = '';
|
error.value = '';
|
||||||
const url = `https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${process.env.FIREBASE_API_KEY}`
|
const url = type === 'signUp'
|
||||||
|
? `https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${process.env.FIREBASE_API_KEY}`
|
||||||
|
: `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${process.env.FIREBASE_API_KEY}`;
|
||||||
|
|
||||||
type AuthResponse = {
|
type SignUpResponse = {
|
||||||
kind: string
|
kind: string
|
||||||
idToken: string
|
idToken: string
|
||||||
email: string;
|
email: string;
|
||||||
@ -25,9 +27,19 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
expiresIn: string;
|
expiresIn: string;
|
||||||
localId: string;
|
localId: string;
|
||||||
}
|
}
|
||||||
|
type SignInResponse = {
|
||||||
|
kind: string;
|
||||||
|
localId: string;
|
||||||
|
email: string;
|
||||||
|
displayName: string;
|
||||||
|
idToken: string;
|
||||||
|
registered: boolean;
|
||||||
|
refreshToken: string;
|
||||||
|
expiresIn: string;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const { data } = await axios.post<AuthResponse>(url, {
|
const { data } = await axios.post<SignUpResponse | SignInResponse>(url, {
|
||||||
...payload,
|
...payload,
|
||||||
returnSecureToken: true
|
returnSecureToken: true
|
||||||
})
|
})
|
||||||
@ -40,43 +52,47 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
token: data.idToken,
|
token: data.idToken,
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof AxiosError) {
|
if (!(e instanceof AxiosError)){
|
||||||
switch (e?.response?.data?.error?.message) {
|
error.value = 'Something went wrong';
|
||||||
case 'EMAIL_EXISTS':
|
return;
|
||||||
error.value = 'Email already exists';
|
|
||||||
break;
|
|
||||||
case 'OPERATION_NOT_ALLOWED':
|
|
||||||
error.value = 'Operation not allowed';
|
|
||||||
break;
|
|
||||||
case 'TOO_MANY_ATTEMPTS_TRY_LATER':
|
|
||||||
error.value = 'Too many attempts';
|
|
||||||
break;
|
|
||||||
case 'EMAIL_NOT_FOUND':
|
|
||||||
error.value = 'Email not found';
|
|
||||||
break;
|
|
||||||
case 'INVALID_PASSWORD':
|
|
||||||
error.value = 'Invalid password';
|
|
||||||
break;
|
|
||||||
case 'WEAK_PASSWORD':
|
|
||||||
error.value = 'Password is weak';
|
|
||||||
break;
|
|
||||||
case 'USER_DISABLED':
|
|
||||||
error.value = 'User disabled';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error.value = 'Something went wrong';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error.value = 'Something went wrong';
|
switch (e?.response?.data?.error?.message) {
|
||||||
|
case 'EMAIL_EXISTS':
|
||||||
|
error.value = 'Email already exists';
|
||||||
|
return;
|
||||||
|
case 'OPERATION_NOT_ALLOWED':
|
||||||
|
error.value = 'Operation not allowed';
|
||||||
|
return;
|
||||||
|
case 'TOO_MANY_ATTEMPTS_TRY_LATER':
|
||||||
|
error.value = 'Too many attempts';
|
||||||
|
return;
|
||||||
|
case 'EMAIL_NOT_FOUND':
|
||||||
|
error.value = 'Email not found';
|
||||||
|
return;
|
||||||
|
case 'INVALID_LOGIN_CREDENTIALS':
|
||||||
|
error.value = 'Invalid credentials';
|
||||||
|
return;
|
||||||
|
case 'INVALID_PASSWORD':
|
||||||
|
error.value = 'Invalid password';
|
||||||
|
return;
|
||||||
|
case 'WEAK_PASSWORD':
|
||||||
|
error.value = 'Password is weak';
|
||||||
|
return;
|
||||||
|
case 'USER_DISABLED':
|
||||||
|
error.value = 'User disabled';
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
error.value = 'Something went wrong';
|
||||||
|
return;
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
signUp,
|
auth,
|
||||||
userInfo,
|
userInfo,
|
||||||
error,
|
error,
|
||||||
loading,
|
loading,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user