feat: midterm shit done

This commit is contained in:
Tony Yang
2025-04-15 03:59:33 +08:00
parent f093df29a1
commit f7ee02586b
34 changed files with 1460 additions and 197 deletions
+109
View File
@@ -0,0 +1,109 @@
<script setup>
import { ref, watch } from 'vue';
import { login } from '../../lib/api';
import { useRouter } from 'vue-router';
import { useAuthStore } from '../../stores/auth';
const username = ref('');
const password = ref('');
const router = useRouter();
const usernameError = ref('');
const passwordError = ref('');
const authStore = useAuthStore();
function validateUsername() {
if (!username.value) {
usernameError.value = 'Username is required.';
} else if (username.value.length < 3) {
usernameError.value = 'Username must be at least 3 characters.';
} else {
usernameError.value = '';
}
}
function validatePassword() {
if (!password.value) {
passwordError.value = 'Password is required.';
} else if (password.value.length < 8) {
passwordError.value = 'Password must be at least 8 characters.';
} else {
passwordError.value = '';
}
}
watch(
() => username.value,
() => {
validateUsername();
}
);
watch(
() => password.value,
() => {
validatePassword();
}
);
const onSubmit = async () => {
validateUsername();
validatePassword();
if (usernameError.value || passwordError.value) {
return;
}
try {
const response = await login(username.value, password.value);
const { jwt } = response;
authStore.setJwt(jwt);
alert('Login successful!');
router.push('/profile');
} catch (error) {
alert("Login failed: " + error.message);
}
};
</script>
<template>
<form @submit.prevent="onSubmit">
<fieldset class="ts-fieldset">
<legend class="ts-legend">Login</legend>
<div class="ts-wrap is-vertical">
<div class="ts-control">
<div class="label">Username</div>
<div class="content is-fluid">
<div class="ts-input" :class="{'is-negative': usernameError}">
<input name="username" type="text" placeholder="Username" v-model="username" />
</div>
<div class="ts-text is-small is-negative" v-if="usernameError">{{ usernameError }}</div>
</div>
</div>
<div class="ts-control">
<div class="label">Password</div>
<div class="content is-fluid">
<div class="ts-input" :class="{'is-negative': passwordError}">
<input name="password" type="password" placeholder="Password" v-model="password" />
</div>
<div class="ts-text is-small is-negative" v-if="passwordError">{{ passwordError }}</div>
<div class="ts-text is-small is-negative">Warning: This is for demonstration purposes only. Passwords are stored in plaintext!</div>
</div>
</div>
</div>
<div class="ts-wrap has-top-spaced is-end-aligned">
<button class="ts-button" type="submit" :class="{
'is-disabled': username === '' || password === '' || usernameError !== '' || passwordError !== ''
}">Submit</button>
</div>
</fieldset>
</form>
</template>
<style scoped>
.ts-error {
color: red;
font-size: 0.8em;
}
</style>