So I've encountered a situation where I'm working in a Vue context with Laravel as the backend. On my homepage, I have a select option for searching musicians based on their genre. Now, when I navigate to this page, I want each musician card to display stars corresponding to the average votes they have received.
However, I'm facing challenges when it comes to manipulating the votes within the template and I am clueless about how to handle it in the methods section. It seems like a simple task but I'm having difficulty with it.
Here's a visual representation of the problem highlighted in red
https://i.sstatic.net/PrwP3.jpg
And here's the code snippet:
FilteredMusicians.vue
In this section, I iterate through the musicians array obtained from the Laravel endpoint. To retrieve the votes, I loop through each musician.reviews object to access the review.vote property. The challenge lies in aggregating all the votes and calculating the average.
<template>
<div class="container">
<div class="row py-4">
<div
v-for="musician in musicians"
:key="musician.id"
class="col-xs-12 col-md-4 col-lg-4 my-4"
>
<div class="card">
<div class="musician-img">
<img
:src="'/storage/' + musician.cover"
:alt="musician.stagename"
/>
</div>
<div class="card-body text-center">
<h5 class="card-title py-2">{{ musician.stagename }}</h5>
<!-- reviews -->
<div v-for="review in musician.reviews" :key="review.id">
{{ review.vote }}
</div>
<!-- /reviews -->
<router-link
class="btn btn-orange text-white"
:to="{ name: 'musician', params: { slug: musician.slug } }"
>View Profile</router-link
>
</div>
</div>
</div>
</div>
<div class="text-center">
<router-link class="btn btn-orange text-white mb-3" :to="{ name: 'home' }"
>Go Back</router-link
>
</div>
</div>
</template>
<script>
export default {
name: "FilteredMusicians",
data() {
return {
musicians: [],
};
},
methods: {
getMusicians(slug) {
axios
.get(`http://127.0.0.1:8000/api/musicians/${slug}`)
.then((res) => {
res.data.forEach((el) => {
this.musicians = el.musicians;
});
})
.catch((err) => {
console.log(err);
});
},
},
created() {
this.getMusicians(this.$route.params.slug);
},
};
</script>
This function is used to retrieve all musicians related to a specific genre
public function filterMusicians($slug) {
$genres = Genre::where('slug', $slug)->with('musicians')->get();
return response()->json($genres);
}
Below is the Musician model where I utilized protected $with to fetch the reviews of each musician filtered by genre
class Musician extends Model
{
protected $fillable = [
'user_id',
'stagename',
'slug',
'description',
'bio',
'services',
'typology',
'cover'
];
protected $with = [
'reviews'
];
public function user() {
return $this->hasOne('App\User');
}
public function genres() {
return $this->belongsToMany('App\Genre');
}
public function sponsorships() {
return $this->belongsToMany('App\Sponsorship')->withPivot('end_date');
}
public function messages() {
return $this->hasMany('App\Message');
}
public function reviews() {
return $this->hasMany('App\Review');
}
}
Lastly, we have the Review model defined below
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Review extends Model
{
protected $fillable = [
'name',
'email',
'review',
'vote',
'musician_id'
];
public function musician() {
return $this->belongsTo('App\Musician')->with('reviews');
}
}