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

feat(dogs): implement frontend CRUD operations for dogs

- Implement UI for adding, modifying, and deleting dogs
- Add functionality for CRUD operations
parent 84a8ccc2
No related branches found
No related tags found
No related merge requests found
<template>
<div class="edit-dog-container">
<h1>Kutya hozzáadása</h1>
<form @submit.prevent="addDog">
<div class="input-group">
<label for="name">Neve</label>
<input id="name" v-model="dog.name" type="text" required>
</div>
<div class="input-group">
<label for="breed">Faja</label>
<input id="breed" v-model="dog.breed" type="text" required>
</div>
<div class="input-group">
<label for="age">Kora</label>
<input id="age" v-model="dog.age" type="number" required>
</div>
<button type="submit">Mentés</button>
</form>
</div>
</template>
<script>
import axios from 'axios';
import { mapState } from 'vuex';
export default {
data() {
return {
dog: {},
};
},
computed: {
...mapState(['token']),
},
methods: {
async addDog() {
const config = {
headers: { Authorization: `Bearer ${this.token}` },
};
await axios.post(`/api/newdog`, this.dog, config);
this.$router.push(`/dogs`);
},
},
};
</script>
<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> <template>
<div class="dog-list-container"> <div class="dog-list-container">
<router-link to="/add-dog" class="add-button">Új kutya hozzáadása</router-link>
<div v-if="!loaded"> <div v-if="!loaded">
Loading... Betöltés...
</div> </div>
<div v-else-if="errorMessage || fetchError || !hasDogs" class="error-message"> <div v-else-if="errorMessage || fetchError || !hasDogs" class="alert alert-error">
{{ errorMessage || (fetchError ? 'Could not fetch dogs.' : 'No dogs found.') }} {{ errorMessage || (fetchError ? 'Could not fetch dogs.' : 'No dogs found.') }}
</div> </div>
<div v-else class="dog-item-container"> <div v-else class="dog-item-container">
<div v-for="dog in dogs" :key="dog.id" class="dog-item" @click="viewDog(dog.id)"> <div v-for="dog in dogs" :key="dog.id" class="dog-item" @click="viewDog(dog.id)">
<img v-if="dog" :src="dog.picture ? 'data:image/jpeg;base64,' + dog.picture : 'data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 50 50\'%3E%3Ctext y=\'.9em\' font-size=\'20\'%3E' + dog.id + '%3C/text%3E%3C/svg%3E'" :alt="`Image of ${dog.name}`" class="dog-image"/> <img v-if="dog"
:src="dog.picture ? 'data:image/jpeg;base64,' + dog.picture : 'data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 50 50\'%3E%3Ctext y=\'.9em\' font-size=\'20\'%3E' + dog.id + '%3C/text%3E%3C/svg%3E'"
:alt="`Image of ${dog.name}`" class="dog-image"/>
<h2 v-if="dog" class="dog-name">{{ dog.name }}</h2> <h2 v-if="dog" class="dog-name">{{ dog.name }}</h2>
</div> </div>
</div> </div>
...@@ -43,19 +46,19 @@ export default { ...@@ -43,19 +46,19 @@ export default {
if (response.data && response.data.length > 0) { if (response.data && response.data.length > 0) {
this.dogs = response.data; this.dogs = response.data;
} else { } else {
this.errorMessage = 'No dogs found.'; this.errorMessage = 'Nem találhatóak kutyák.';
} }
} else { } else {
this.fetchError = true; this.fetchError = true;
this.errorMessage = 'Could not fetch dogs.'; this.errorMessage = 'Nem sikerült lekérni a kutyákat.';
} }
} catch (error) { } catch (error) {
console.error(error); console.error(error);
this.fetchError = true; this.fetchError = true;
if (error.message.includes('timeout')) { if (error.message.includes('timeout')) {
this.errorMessage = 'API request timed out.'; this.errorMessage = 'A kutyák lekérdezése túllépte az időkorlátot. Próbáld újra később.';
} else { } else {
this.errorMessage = 'Could not fetch dogs.'; this.errorMessage = 'Nem sikerült lekérni a kutyákat.';
} }
} finally { } finally {
this.loaded = true; this.loaded = true;
...@@ -90,7 +93,11 @@ export default { ...@@ -90,7 +93,11 @@ export default {
@apply text-lg font-bold; @apply text-lg font-bold;
} }
.error-message { .alert-error {
@apply p-4 bg-red-200 text-red-800 rounded; @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;
} }
</style> </style>
\ No newline at end of file
<template> <template>
<div class="edit-dog-container"> <div class="edit-dog-container">
<h1>Kutya szerkesztése</h1>
<form @submit.prevent="editDog"> <form @submit.prevent="editDog">
<div class="input-group"> <div class="input-group">
<label for="name">Dog Name</label> <label for="name">Neve</label>
<input id="name" v-model="dog.name" type="text" required> <input id="name" v-model="dog.name" type="text" required>
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="breed">Breed</label> <label for="breed">Faja</label>
<input id="breed" v-model="dog.breed" type="text" required> <input id="breed" v-model="dog.breed" type="text" required>
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="age">Age</label> <label for="age">Kora</label>
<input id="age" v-model="dog.age" type="number" required> <input id="age" v-model="dog.age" type="number" required>
</div> </div>
<button type="submit">Save</button> <button type="submit">Mentés</button>
</form> </form>
</div> </div>
</template> </template>
<script> <script>
import axios from 'axios'; import axios from 'axios';
import { mapState } from 'vuex';
axios.defaults.baseURL = 'http://localhost:8080';
export default { export default {
name: 'EditDog',
data() { data() {
return { return {
dog: { dog: {},
name: '',
breed: '',
age: '',
},
}; };
}, },
methods: { computed: {
async editDog() { ...mapState(['token']),
try {
const response = await axios.post('/dogs/' + this.dog.id + '/edit', this.dog);
// Handle response
console.log(response);
} catch (error) {
// Handle error
console.log(error);
}
}, },
async fetchDogData() { methods: {
try { async fetchDog() {
const response = await axios.get('/dogs/' + this.$route.params.id); const response = await axios.get(`/api/dogs/${this.$route.params.id}`);
this.dog = response.data; this.dog = response.data;
} catch (error) { },
console.error(error); async editDog() {
} const config = {
headers: { Authorization: `Bearer ${this.token}` },
};
await axios.post(`/api/dogs/${this.$route.params.id}/edit`, this.dog, config);
this.$router.push(`/dog/${this.$route.params.id}`);
}, },
}, },
created() { created() {
// Fetch the dog data when the component is created this.fetchDog();
this.fetchDogData();
}, },
}; };
</script> </script>
......
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
<img :src="dog.picture" :alt="`Image of ${dog.name}`" class="w-64 h-64 object-cover mb-4 rounded shadow"/> <img :src="dog.picture" :alt="`Image of ${dog.name}`" class="w-64 h-64 object-cover mb-4 rounded shadow"/>
<p class="text-lg mb-2"><strong>Age:</strong> {{ dog.age }}</p> <p class="text-lg mb-2"><strong>Age:</strong> {{ dog.age }}</p>
<p class="text-lg"><strong>Breed:</strong> {{ dog.breed }}</p> <p class="text-lg"><strong>Breed:</strong> {{ dog.breed }}</p>
<router-link :to="`/edit-dog/${dog.id}`" tag="button" class="edit-button">Edit</router-link> <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>
</div> </div>
<div v-else>Loading...</div> <div v-else>Betöltés...</div>
</template> </template>
<script> <script>
...@@ -31,6 +32,17 @@ export default { ...@@ -31,6 +32,17 @@ export default {
// Handle error // Handle error
} }
}, },
methods: {
async deleteDog() {
if (window.confirm('Biztosan törölni akarod ezt a kutyát?')) {
const config = {
headers: { Authorization: `Bearer ${this.token}` },
};
await axios.delete(`/api/dogs/${this.$route.params.id}`, config);
this.$router.push(`/dogs`);
}
},
},
}; };
</script> </script>
...@@ -54,4 +66,8 @@ p { ...@@ -54,4 +66,8 @@ p {
.edit-button { .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; @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;
}
</style> </style>
\ 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