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
Branches
Tags
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>
<div class="dog-list-container">
<router-link to="/add-dog" class="add-button">Új kutya hozzáadása</router-link>
<div v-if="!loaded">
Loading...
Betöltés...
</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.') }}
</div>
<div v-else class="dog-item-container">
<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>
</div>
</div>
......@@ -38,24 +41,24 @@ export default {
},
async created() {
try {
const response = await axios.get('/api/dogs', { timeout: 5000 }); // 5 seconds timeout
const response = await axios.get('/api/dogs', {timeout: 5000}); // 5 seconds timeout
if (response.status === 200) {
if (response.data && response.data.length > 0) {
this.dogs = response.data;
} else {
this.errorMessage = 'No dogs found.';
this.errorMessage = 'Nem találhatóak kutyák.';
}
} else {
this.fetchError = true;
this.errorMessage = 'Could not fetch dogs.';
this.errorMessage = 'Nem sikerült lekérni a kutyákat.';
}
} catch (error) {
console.error(error);
this.fetchError = true;
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 {
this.errorMessage = 'Could not fetch dogs.';
this.errorMessage = 'Nem sikerült lekérni a kutyákat.';
}
} finally {
this.loaded = true;
......@@ -63,7 +66,7 @@ export default {
},
methods: {
viewDog(id) {
this.$router.push({ name: 'SingleDog', params: { id } });
this.$router.push({name: 'SingleDog', params: {id}});
},
},
};
......@@ -90,7 +93,11 @@ export default {
@apply text-lg font-bold;
}
.error-message {
@apply p-4 bg-red-200 text-red-800 rounded;
.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;
}
</style>
\ No newline at end of file
<template>
<div class="edit-dog-container">
<h1>Kutya szerkesztése</h1>
<form @submit.prevent="editDog">
<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>
</div>
<div class="input-group">
<label for="breed">Breed</label>
<label for="breed">Faja</label>
<input id="breed" v-model="dog.breed" type="text" required>
</div>
<div class="input-group">
<label for="age">Age</label>
<label for="age">Kora</label>
<input id="age" v-model="dog.age" type="number" required>
</div>
<button type="submit">Save</button>
<button type="submit">Mentés</button>
</form>
</div>
</template>
<script>
import axios from 'axios';
axios.defaults.baseURL = 'http://localhost:8080';
import { mapState } from 'vuex';
export default {
name: 'EditDog',
data() {
return {
dog: {
name: '',
breed: '',
age: '',
},
dog: {},
};
},
computed: {
...mapState(['token']),
},
methods: {
async editDog() {
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 fetchDog() {
const response = await axios.get(`/api/dogs/${this.$route.params.id}`);
this.dog = response.data;
},
async fetchDogData() {
try {
const response = await axios.get('/dogs/' + this.$route.params.id);
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() {
// Fetch the dog data when the component is created
this.fetchDogData();
this.fetchDog();
},
};
</script>
......
......@@ -4,9 +4,10 @@
<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"><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 v-else>Loading...</div>
<div v-else>Betöltés...</div>
</template>
<script>
......@@ -31,6 +32,17 @@ export default {
// 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>
......@@ -54,4 +66,8 @@ p {
.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;
}
</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