Skip to content
Snippets Groups Projects
Commit 4ad459bd authored by Laczkó Csongor Loránd's avatar Laczkó Csongor Loránd
Browse files

feat(frontend): Update frontend validation and authorization, refactor CSS...

feat(frontend): Update frontend validation and authorization, refactor CSS rules, and fix minor issues

- Overhauled the CSS rules, added the common ones to the index.css and made the media tags more robust.
- Updated the frontend validation to match with backend.
- Made the webpage redirect to login page if authorization is required.
- Minor fixes.
parent 9a44924c
No related branches found
No related tags found
No related merge requests found
<template>
<div class="login-container">
<div class="global-container">
<h1 class="title">Bejelentkezés</h1>
<div v-if="registrationSuccess" class="alert alert-success">
Regisztráció sikeres! Most már bejelentkezhetsz.
......@@ -19,7 +19,7 @@
<button type="submit">Bejelentkezés</button>
</form>
<p>Még nem vagy regisztrálva?</p>
<router-link to="/register" tag="button" class="register-button">Regisztrálás</router-link>
<router-link to="/register" tag="button" class="button">Regisztrálás</router-link>
</div>
</template>
......@@ -42,8 +42,14 @@ export default {
if (response.status === 200) {
this.$store.commit('setToken', response.data.token);
const redirect = this.$route.query.redirect;
if (redirect) {
this.$router.push(redirect);
} else {
this.$router.push('/');
}
}
} catch (error) {
this.error = 'Helytelen felhasználónév vagy jelszó';
this.$store.commit('setRegistrationSuccess', false);
......@@ -59,45 +65,3 @@ export default {
},
};
</script>
\ No newline at end of file
<style lang="postcss">
.login-container {
@apply flex flex-col items-center justify-center min-h-screen bg-blue-200;
}
.input-group {
@apply mb-4;
}
label {
@apply block mb-2 text-sm font-bold text-gray-700;
}
input {
@apply w-full px-3 py-2 text-sm leading-tight text-gray-700 border rounded shadow appearance-none;
}
button {
@apply px-4 py-2 mt-4 text-sm font-medium text-white bg-blue-500 rounded hover:bg-blue-700 focus:outline-none;
}
p {
@apply mt-10;
}
.register-button {
@apply px-4 py-2 mt-4 text-sm font-medium text-white bg-blue-500 rounded hover:bg-blue-700 focus:outline-none mb-8;
}
.alert-success {
@apply bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative mb-4;
}
.alert-error {
@apply bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4;
}
.title {
@apply text-4xl font-bold mb-8 text-center p-4;
}
</style>
\ No newline at end of file
<template>
<div class="login-container">
<div class="global-container">
<h1 class="title">Regisztráció</h1>
<div v-if="errorMessage" class="alert alert-error">
{{ errorMessage }}
......@@ -40,21 +40,16 @@ export default {
};
const validateForm = () => {
const usernameRegex = /^[a-zA-Z0-9]+$/;
const minLength = 5;
const usernameRegex = /^\w{5,20}$/; // username can contain numbers, upper and lowercase characters
const passwordRegex = /^(?=.*[A-Z])(?=.*\d)[A-Za-z\d]{8,20}$/; // password must contain at least one uppercase letter and one digit
if (!username.value) {
errorMessage.value = 'Felhasználónév megadása kötelező';
return false;
}
if (username.value.length < minLength) {
errorMessage.value = 'A felhasználónév legalább 5 karakter hosszú kell legyen';
return false;
}
if (!username.value.match(usernameRegex)) {
errorMessage.value = 'Felhasználónév csak betűket és számokat tartalmazhat';
errorMessage.value = 'Érvénytelen felhasználónév. A felhasználónévnek legalább 5 és legfeljebb 20 karakter hosszúnak kell lennie.';
return false;
}
......@@ -63,12 +58,12 @@ export default {
return false;
}
if (password.value.length < minLength) {
errorMessage.value = 'A jelszó legalább 5 karakter hosszú kell legyen';
if (!password.value.match(passwordRegex)) {
errorMessage.value = 'Érvénytelen jelszó. A jelszónak legalább 8 és legfeljebb 20 karakter hosszúnak kell lennie, és tartalmaznia kell legalább egy nagybetűt és egy számot.';
return false;
}
errorMessage.value = ''; // Clear the error message if all fields are valid
errorMessage.value = '';
return true;
};
......@@ -90,9 +85,9 @@ export default {
// Display error message
if (error.response && error.response.data) {
errorMessage.value = 'Registration failed: ' + error.response.data;
errorMessage.value = 'Regisztráció sikertelen: ' + error.response.data;
} else {
errorMessage.value = 'Registration failed: ' + error.message;
errorMessage.value = 'Regisztráció sikertelen: ' + error.message;
}
}
};
......@@ -106,33 +101,3 @@ export default {
},
};
</script>
\ No newline at end of file
<style lang="postcss">
.login-container {
@apply flex flex-col items-center justify-center min-h-screen bg-blue-200;
}
.input-group {
@apply mb-4;
}
label {
@apply block mb-2 text-sm font-bold text-gray-700;
}
input {
@apply w-full px-3 py-2 text-sm leading-tight text-gray-700 border rounded shadow appearance-none;
}
button {
@apply px-4 py-2 mt-4 text-sm font-medium text-white bg-blue-500 rounded hover:bg-blue-700 focus:outline-none mb-8;
}
.title {
@apply text-4xl font-bold mb-8 text-center p-4;
}
.alert-error {
@apply bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4;
}
</style>
\ No newline at end of file
......@@ -9,7 +9,3 @@ export default {
name: 'Footer'
}
</script>
\ No newline at end of file
<style scoped lang="postcss">
/* Add your styles here */
</style>
\ No newline at end of file
<template>
<nav>
<h1 class="title">Vau-Vau Alapítvány</h1>
<router-link to="/" class="title">Vau-Vau Alapítvány</router-link>
<ul>
<li><router-link to="/" class="nav-link" active-class="active-link">Főoldal</router-link></li>
<li><router-link to="/dogs" class="nav-link" active-class="active-link">Kutyák</router-link></li>
......
<template>
<div class="edit-dog-container">
<div class="global-container">
<h1>Kutya hozzáadása</h1>
<div v-if="errorMessage" class="alert alert-error">
{{ errorMessage }}
......@@ -76,25 +76,3 @@ export default {
},
};
</script>
\ No newline at end of file
<style lang="postcss">
.edit-dog-container {
@apply flex flex-col items-center justify-center min-h-screen bg-blue-200;
}
.input-group {
@apply mb-4;
}
label {
@apply block mb-2 text-sm font-bold text-gray-700;
}
input {
@apply w-full px-3 py-2 text-sm leading-tight text-gray-700 border rounded shadow appearance-none;
}
button {
@apply px-4 py-2 mt-4 text-sm font-medium text-white bg-blue-500 rounded hover:bg-blue-700 focus:outline-none;
}
</style>
\ No newline at end of file
<template>
<div class="dog-list-container">
<router-link to="/add-dog" class="add-button">Új kutya hozzáadása</router-link>
<div class="global-container">
<router-link to="/add-dog" class="button">Új kutya hozzáadása</router-link>
<div v-if="!loaded">
Betöltés...
</div>
......@@ -71,31 +71,21 @@ export default {
</script>
<style scoped lang="postcss">
.dog-list-container {
@apply flex flex-col justify-center items-center flex-grow bg-blue-200;
}
.dog-item-container {
@apply flex flex-wrap justify-around p-4 rounded;
}
.dog-item {
@apply flex flex-col items-center bg-white m-4 p-4 rounded shadow w-1/4;
@apply flex flex-col items-center bg-white m-4 p-4 rounded shadow w-1/4 min-w-64 min-h-64;
}
.dog-image {
@apply w-full h-64 object-cover mb-4 rounded;
@apply w-full h-64 object-cover mb-4 rounded min-w-64 min-h-64;
}
.dog-name {
@apply text-lg font-bold;
}
.alert-error {
@apply bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4;
}
.add-button {
@apply px-4 py-2 mt-4 text-sm font-medium text-white bg-blue-500 rounded hover:bg-blue-700 focus:outline-none mb-8;
}
</style>
\ No newline at end of file
<template>
<div class="edit-dog-container">
<div class="global-container">
<h1>Kutya szerkesztése</h1>
<div v-if="errorMessage" class="alert alert-error">
{{ errorMessage }}
......
<template>
<div v-if="dog" class="single-dog flex flex-col items-center bg-gray-100 p-4 rounded shadow">
<div v-if="dog" class="global-container">
<h1 class="text-2xl font-bold mb-4">{{ dog.name }}</h1>
<img :src="dog.picture" :alt="`${dog.name} képe`" class="w-64 h-64 object-cover mb-4 rounded shadow"/>
<p class="text-lg mb-2"><strong>Kor:</strong> {{ dog.age }}</p>
<p class="text-lg"><strong>Faj:</strong> {{ dog.breed }}</p>
<router-link :to="`/edit-dog/${dog.id}`" tag="button" class="edit-button">Szerkesztés</router-link>
<button @click="deleteDog" class="delete-button">Törlés</button>
<router-link :to="`/edit-dog/${dog.id}`" tag="button" class="button">Szerkesztés</router-link>
<button @click="deleteDog" class="button delete-button ">Törlés</button>
</div>
<div v-else>Betöltés...</div>
</template>
......@@ -36,8 +36,17 @@ export default {
const config = {
headers: { Authorization: `Bearer ${this.token}` },
};
try {
await axios.delete(apiURL + `/dogs/${this.$route.params.id}`, config);
this.$router.push(`/dogs`);
} catch (error) {
if (error.response && error.response.status === 401) {
this.$router.push('/login');
} else {
console.error(error);
// Handle other types of errors
}
}
}
},
},
......@@ -45,27 +54,11 @@ export default {
</script>
<style scoped lang="postcss">
.single-dog {
@apply flex flex-col items-center bg-blue-200 p-4 rounded shadow;
}
h1 {
@apply text-2xl font-bold mb-4;
}
img {
@apply w-64 h-64 object-cover mb-4 rounded shadow bg-white;
}
p {
@apply text-lg mb-2;
}
.edit-button {
@apply px-4 py-2 mt-4 text-sm font-medium text-white bg-blue-500 rounded hover:bg-blue-700 focus:outline-none;
}
.delete-button {
@apply px-4 py-2 mt-4 text-sm font-medium text-white bg-red-500 rounded hover:bg-red-700 focus:outline-none;
@apply bg-red-500 hover:bg-red-700;
}
</style>
\ No newline at end of file
......@@ -50,123 +50,156 @@ p {
@apply mb-4;
}
@media (max-width: 600px) {
nav ul {
@apply flex flex-col space-y-4 items-center;
.global-container {
@apply flex flex-col items-center justify-center min-h-screen bg-blue-200;
}
nav ul li {
@apply block;
.input-group {
@apply mb-4;
}
nav ul li a {
@apply text-lg;
.label {
@apply block mb-2 text-sm font-bold text-gray-700;
}
nav h1 {
@apply text-2xl;
.input {
@apply w-full px-3 py-2 text-sm leading-tight text-gray-700 border rounded shadow appearance-none;
}
.hero {
@apply py-12;
.button {
@apply px-4 py-2 mt-4 text-sm font-medium text-white bg-blue-500 rounded hover:bg-blue-700 focus:outline-none mb-8;
}
.features {
@apply py-12;
.title {
@apply text-4xl font-bold mb-8 text-center p-4;
}
.cta {
@apply py-12;
.alert-error {
@apply bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4;
}
footer {
@apply py-4;
.global-container label,
.global-container input,
.global-container button {
@apply text-lg;
}
footer p {
@apply text-sm;
button {
@apply text-lg px-2 py-1 mt-4 mb-4 rounded transition-colors duration-150 ease-in-out;
}
h2 {
@apply text-xl;
.button {
@apply text-lg px-2 py-1 mt-4 mb-4 bg-blue-500 text-white rounded transition-colors duration-150 ease-in-out;
}
p {
@apply text-sm;
.button:hover {
@apply bg-blue-700;
}
.login-container {
@apply p-4;
.alert-success {
@apply bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative mb-4;
}
.login-container label,
.login-container input,
.login-container button {
@apply text-xs;
.alert-error {
@apply bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4;
}
.title {
@apply text-lg font-bold mb-4;
}
/* Styles for extra small devices (phones, 600px and below) */
@media (max-width: 600px) {
@media (min-width: 600px) {
body {
@apply text-sm;
@apply text-base;
}
.login-container label,
.login-container input,
.login-container button {
@apply text-sm;
}
.global-container {
@apply p-6;
}
/* Styles for small devices (portrait tablets and large phones, 600px and up) */
@media (min-width: 600px) {
body {
.global-container label,
.global-container input,
.global-container button {
@apply text-base;
}
.login-container label,
.login-container input,
.login-container button {
@apply text-base;
button {
@apply text-base px-3 py-2 mt-6 mb-6;
}
.title {
@apply text-xl font-bold mb-6;
}
}
/* Styles for medium devices (landscape tablets, 768px and up) */
@media (min-width: 768px) {
body {
@apply text-lg;
}
.login-container label,
.login-container input,
.login-container button {
.global-container {
@apply p-8;
}
.global-container label,
.global-container input,
.global-container button {
@apply text-lg;
}
button {
@apply text-lg px-4 py-2 mt-8 mb-8;
}
.title {
@apply text-2xl font-bold mb-8;
}
}
/* Styles for large devices (laptops/desktops, 992px and up) */
@media (min-width: 992px) {
body {
@apply text-xl;
}
.login-container label,
.login-container input,
.login-container button {
.global-container {
@apply p-10;
}
.global-container label,
.global-container input,
.global-container button {
@apply text-xl;
}
button {
@apply text-xl px-5 py-3 mt-10 mb-10;
}
.title {
@apply text-3xl font-bold mb-10;
}
}
/* Styles for extra large devices (large laptops and desktops, 1200px and up) */
@media (min-width: 1200px) {
body {
@apply text-2xl;
}
.login-container label,
.login-container input,
.login-container button {
.global-container {
@apply p-12;
}
.global-container label,
.global-container input,
.global-container button {
@apply text-2xl;
}
button {
@apply text-2xl px-6 py-4 mt-12 mb-12;
}
.title {
@apply text-4xl font-bold mb-12;
}
}
......@@ -21,7 +21,7 @@ const routes = [
{path: '/faq', component: FAQ},
{path: '/dog/:id', name: 'SingleDog', component: SingleDog},
{path: '/edit-dog/:id', name: 'EditDog', component: EditDog, meta: {requiresAuth: true}},
{path: '/login', component: Login},
{path: '/login', component: Login, name: 'Login'},
{path: '/register', component: Register},
{path: '/add-dog', name: 'AddDog', component: AddDog, meta: {requiresAuth: true}},
{path: '/:pathMatch(.*)*', redirect: '/'}
......@@ -33,11 +33,18 @@ const router = createRouter({
})
router.beforeEach((to, from, next) => {
if (to.name === 'edit' && !store.state.token) {
next({ name: 'login' })
if (to.meta.requiresAuth) {
store.dispatch('checkAuthenticationStatus')
.then(isAuthenticated => {
if (!isAuthenticated) {
next({ name: 'Login', query: { redirect: to.fullPath } });
} else {
next()
next();
}
})
});
} else {
next();
}
});
createApp(App).use(router).use(store).mount('#app');
\ No newline at end of file
......@@ -23,4 +23,12 @@ export default createStore({
state.registrationSuccess = success;
}
},
getters: {
isAuthenticated: state => !!state.token,
},
actions: {
checkAuthenticationStatus: ({ getters }) => {
return Promise.resolve(getters.isAuthenticated);
},
},
});
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment