Skip to content

Commit

Permalink
Auth pages
Browse files Browse the repository at this point in the history
  • Loading branch information
Temmmmmo committed Oct 19, 2023
1 parent 4997001 commit 666ae19
Show file tree
Hide file tree
Showing 25 changed files with 1,255 additions and 109 deletions.
15 changes: 7 additions & 8 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { computed, onMounted } from 'vue';
import { IrdomNavbar, NavbarItem, IrdomToastList } from './components';
import { IrdomNavbar, IrdomToastList, NavbarItem } from './components';
import { useProfileStore, useTimetableStore } from './store';
import { marketingApi } from './api/marketing';
Expand All @@ -20,11 +20,11 @@ const navbarItems = computed<NavbarItem[]>(() => {
name: 'Сервисы',
path: ['/apps'],
},
// {
// icon: 'account_circle',
// name: 'Профиль',
// path: ['/profile', '/auth'],
// },
{
icon: 'account_circle',
name: 'Профиль',
path: ['/profile', '/auth'],
},
];
// if (profileStore.isAdmin) {
// common.push({
Expand Down Expand Up @@ -52,8 +52,7 @@ onMounted(async () => {
<template>
<v-app>
<RouterView />
<IrdomToastList />
<IrdomNavbar :items="navbarItems" />
</v-app>

<IrdomToastList />
</template>
14 changes: 11 additions & 3 deletions src/api/auth/AuthEmailApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ interface RequestResetPasswordBody {
new_password: string;
}

interface RequestResetForgottenPasswordBody {
email: string;
}

interface ResetPasswordParams {
'reset-token': string;
new_password: string;
}

interface LoginResponse {
Expand Down Expand Up @@ -73,8 +77,12 @@ class AuthEmailApi extends AuthBaseApi {
return this.post<DefaultResponse, RequestResetPasswordBody>('/reset/password/request', body);
}

public async resetPassword(params: ResetPasswordParams) {
return this.post<DefaultResponse, ResetPasswordParams>('/reset/password', params);
public async requestResetForgottenPassword(body: RequestResetForgottenPasswordBody) {
return this.post<DefaultResponse, RequestResetForgottenPasswordBody>('/reset/password/restore', body);
}

public async resetPassword(body: ResetPasswordParams, token: string) {
return this.post<DefaultResponse, ResetPasswordParams>('/reset/password', body, { 'reset-token': token });
}
}

Expand Down
42 changes: 42 additions & 0 deletions src/api/controllers/auth/AuthApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,46 @@ export class AuthApi {
[checkToken],
[showErrorToast],
);

static requestResetForgottenPassword = apply(
async (email: string) => {
const data = await authEmailApi.requestResetForgottenPassword({ email });
return data;
},
[showErrorToast],
);

static requestResetPassword = apply(
async (email: string, password: string, new_password: string) => {
const data = await authEmailApi.requestResetPassword({ email, password, new_password });
return data;
},
[showErrorToast],
[checkToken],
);

static resetPassword = apply(
async (new_password: string, token: string) => {
const data = await authEmailApi.resetPassword({ new_password }, token);
return data;
},
[showErrorToast],
);

static resetEmail = apply(
async (token: string) => {
const data = await authEmailApi.resetEmail({ token });
return data;
},
[showErrorToast],
);

static requestResetEmail = apply(
async (email: string) => {
const data = await authEmailApi.requestResetEmail({ email });
return data;
},
[checkToken],
[showErrorToast],
);
}
96 changes: 81 additions & 15 deletions src/components/EmailPasswordForm.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<script setup lang="ts">
import { computed } from 'vue';
import { computed, ref } from 'vue';
const checkPasswords = ref(false);
checkPasswords.value = false;
export interface SubmitData {
email: string;
Expand All @@ -19,13 +22,18 @@ const submitHandler = async (event: Event) => {
const formData = new FormData(form);
const email = formData.get('email')?.toString();
const password = formData.get('password')?.toString();
const repeat_password = formData.get('repeat-password')?.toString();
if (email && password) {
emits('submit', { email, password });
if (password === repeat_password || props.mode === 'login') {
if (email && password) {
emits('submit', { email, password });
}
} else {
checkPasswords.value = true;
}
};
const buttonText = computed(() => (props.mode === 'login' ? 'Вход' : 'Регистрация'));
const buttonText = computed(() => (props.mode === 'login' ? 'Войти' : 'Зарегистрироваться'));
</script>

<template>
Expand All @@ -34,46 +42,104 @@ const buttonText = computed(() => (props.mode === 'login' ? 'Вход' : 'Рег
type="email"
name="email"
autocomplete="email"
placeholder="Введите почту"
class="input"
density="compact"
required
variant="outlined"
label="Email"
/>
<v-text-field
variant="outlined"
type="password"
name="password"
:autocomplete="mode === 'login' ? 'current-password' : 'new-password'"
placeholder="Введите пароль"
class="input"
density="compact"
label="Пароль"
required
/>

<div v-if="$props.mode === 'login'" class="forgot-pass">
<router-link to="/auth/forgot-password">Не помню пароль</router-link>
</div>

<v-text-field
v-if="$props.mode === 'register'"
variant="outlined"
type="password"
name="repeat-password"
class="input"
density="compact"
label="Повтор пароля"
required
/>
<v-btn type="submit" class="submit">{{ buttonText }}</v-btn>
<div v-if="checkPasswords" class="password-validate">Пароли должны совпадать</div>
<v-btn v-if="$props.mode === 'register'" type="submit" class="submit-register" color="#fff">{{
buttonText
}}</v-btn>
<v-btn v-if="$props.mode === 'login'" type="submit" class="submit-login" color="#fff">{{ buttonText }}</v-btn>
</form>
</template>

<style scoped>
.submit {
.field {
text-align: left;
width: 100%;
max-width: 400px;
align-self: center;
background: rgb(var(--v-theme-primary));
color: rgb(var(--v-theme-on-primary));
margin: 0 auto 16px;
}
.forgot-pass {
align-self: center;
padding-bottom: 10px;
max-width: 333px;
justify-self: right;
text-align: right;
width: 100%;
color: #18185c;
font-size: 14px;
font-style: normal;
font-weight: 700;
line-height: normal;
}
.submit-login {
width: 100%;
max-width: 150px;
align-self: center;
margin: 5px auto 16px;
border-radius: 8px !important;
}
.submit-register {
width: 100%;
max-width: 200px;
align-self: center;
margin: 20px auto 16px;
border-radius: 8px !important;
}
.input {
align-self: center;
align-items: center;
width: 100%;
max-width: 400px;
margin: 0 auto 24px;
margin: 0 auto 5px;
}
.form {
display: flex;
flex-direction: column;
align-items: center;
}
@media screen and (width <= 575px) {
margin-top: 50%;
}
.password-validate {
color: #f19035;
font-size: 14px;
font-style: normal;
font-weight: 700;
line-height: normal;
margin: 0 auto;
text-align: center;
}
</style>
1 change: 0 additions & 1 deletion src/components/IrdomAuthButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ const clickHandler = async () => {

<style scoped>
.icon {
filter: grayscale(1);
margin-right: 11px;
}
</style>
18 changes: 10 additions & 8 deletions src/components/IrdomLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,17 @@ defineProps<{
</IrdomToolbar>

<div v-touch="touch" class="v-main-wrapper">
<v-main>
<v-container>
<v-row>
<v-col class="d-flex flex-column">
<slot />
</v-col>
</v-row>
<v-main class="main">
<v-container class="container">
<slot />
</v-container>
</v-main>
</div>
</template>

<style scoped>
v-main,
.main,
.container,
.v-main-wrapper {
height: 100%;
width: 100%;
Expand All @@ -58,4 +55,9 @@ v-main,
.profile-toolbar :global(.v-toolbar-title__placeholder) {
margin-left: 3%;
}
.container {
display: flex;
flex-direction: column;
}
</style>
2 changes: 1 addition & 1 deletion src/components/IrdomToastList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const toastStore = useToastStore();
position: fixed;
left: 0;
right: 0;
bottom: var(--navbar-height);
top: 70%;
z-index: 10;
width: min(100%, 344px);
margin: 0 auto;
Expand Down
4 changes: 2 additions & 2 deletions src/components/lib/IrdomToast.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ const icon = computed(() => {
<div class="header">
<b class="title">{{ props.toast.title }}</b>
<div>
<button type="button" class="close" @click="$emit('close')">
<v-btn type="button" class="close" @click="$emit('close')">
<v-icon icon="md:close" />
</button>
</v-btn>
</div>
</div>
<p>{{ props.toast.description }}</p>
Expand Down
2 changes: 1 addition & 1 deletion src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const authButtons: AuthButton[] = [
name: '@my.msu.ru',
api: authMymsuApi,
method: AuthMethod.MyMsu,
icon: `${logos}#msu`,
icon: `${logos}#yandex`,
color: '#2f39500d',
},
{
Expand Down
20 changes: 20 additions & 0 deletions src/router/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ export const authRoutes: RouteRecordRaw[] = [
path: '',
component: () => import('@/views/auth/AuthView.vue'),
},
{
path: 'register-all',
component: () => import('@/views/auth/RegisterAllView.vue'),
},
{
path: 'forgot-password',
component: () => import('@/views/auth/ForgotPassword.vue'),
},
{
path: 'reset/password',
component: () => import('@/views/auth/ResetPassword.vue'),
},
{
path: 'reset/email',
component: () => import('@/views/auth/ResetEmail.vue'),
},
{
path: 'auth-forgot-password',
component: () => import('@/views/auth/AuthForgottenPasswordView.vue'),
},
{
path: 'all',
component: () => import('@/views/auth/AuthAllView.vue'),
Expand Down
12 changes: 12 additions & 0 deletions src/router/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,16 @@ export const profileRoutes: RouteRecordRaw[] = [
path: 'edit-auth',
component: () => import('@/views/profile/ProfileEditAuthView.vue'),
},
{
path: 'settings',
component: () => import('@/views/profile/ProfileSettingsView.vue'),
},
{
path: 'change-password',
component: () => import('@/views/auth/ChangePasswordView.vue'),
},
{
path: 'change-email',
component: () => import('@/views/auth/ChangeEmailView.vue'),
},
];
2 changes: 1 addition & 1 deletion src/store/toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ref } from 'vue';
export const useToastStore = defineStore('toast', () => {
const list = ref<Map<number, Toast>>(new Map());

function push(toast: Toast, timeout: number | null = 3000) {
function push(toast: Toast, timeout: number | null = 30000000) {
const id = Math.round(Number.MAX_SAFE_INTEGER * Math.random());
list.value.set(id, toast);
if (timeout !== null) {
Expand Down
Loading

0 comments on commit 666ae19

Please sign in to comment.