How to display star rating by Id in laravel/octobercms and twig? - laravel

I have this query to display rating and it works fine
$ads = Advert::find(151);
$this['userAverageRating'] = $ads->ratings()->avg('rating');
to display it in twig i have this that works too
<div align="left" style="font-size: 12px;">
{% if userAverageRating %}
{% for i in range(1,5) %}
{% if userAverageRating >= max(0, i-0.25) %}
<span style="color: orange" class="fa fa-star"></span>
{% elseif (userAverageRating > (i-0.75)) %}
<span style="color: orange" class="fa fa-star-half-o"></span>
{% else %}
<span style="color: orange" class="fa fa-star-o"></span>
{% endif %}
{% endfor %}
<span><b>{{ userAverageRating|round(1, 'floor') }}/5</b></span>
{% else %}
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span style="font-size: 12px"><b></b></span>
{% endif %}
</div>
The above twig tag is in a twig foreach
{% for ad in ads %}
{{ ad.title }}
{{ ad.description }}
...
//the above twig tag here
{% endfor %}
My main problem is that the rating of ad id "151" displays on all the ad foreach results, instead of just ad with id 151. Any ideas why this is and how to fix it

Looking at your php variable $ads = Advert::find(151); this will literally return the advert with id = 151.
try changing this to $ads = Advert::all(); or $ads = Advert::get();
if you need the rating relation attached to each of the Advert results, you could also eager load this.
$ads = Advert:with('ratings')->get();
Then run your logic against ads.rating in twig.
Consider calculating what you need in your component before sending it to the front end. then just looping over the single result.

Two ways to solve this issue and I think the first way is more elegant. Some things to note is I am guessing on how to work with your models. So you might have to adjust the if ($ad->ratings()->first) I am assuming it will return null if there isn't something there. The second way is closer to your logic now but you need to add the id (or something unique) so you can use twig to check ids like {% if userAverageRating and ad.id == userAverageRating.id %}.
1: Foreach and modify the collections of every ad to average the rating.
$ads = Advert::all();
foreach ($ads as $ad) {
if ($ad->ratings()->first) {
$ad->averageRating = $ad->ratings()->avg('rating');
}
else {
$ad->averageRating = null;
}
}
$this['ads'] = $ads;
//Twig Script
{% if ad.averageRating %}
{% for i in range(1,5) %}
{% if ad.averageRating >= max(0, i-0.25) %}
<span style="color: orange" class="fa fa-star"></span>
{% elseif (ad.averageRating > (i-0.75)) %}
<span style="color: orange" class="fa fa-star-half-o"></span>
{% else %}
<span style="color: orange" class="fa fa-star-o"></span>
{% endif %}
{% endfor %}
<span><b>{{ ad.averageRating|round(1, 'floor') }}/5</b></span>
{% else %}
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span style="font-size: 12px"><b></b></span>
{% endif %}
2: Collect the ratings in an array with ad ID.
$ads = Advert::all();
$ratings = [];
foreach ($ads as $key => $ad) {
if ($ad->ratings()->first) {
$ratings[$key] = [ 'id' = $ad->id, 'rating' = $ad->ratings()->avg('rating') ];
}
else {
$ratings[$key] = null;
}
}
$this['userAverageRating'] = $ratings;
//Twig Script
{% if userAverageRating and ad.id == userAverageRating.id %}
{% for i in range(1,5) %}
{% if userAverageRating >= max(0, i-0.25) %}
<span style="color: orange" class="fa fa-star"></span>
{% elseif (userAverageRating > (i-0.75)) %}
<span style="color: orange" class="fa fa-star-half-o"></span>
{% else %}
<span style="color: orange" class="fa fa-star-o"></span>
{% endif %}
{% endfor %}
<span><b>{{ userAverageRating|round(1, 'floor') }}/5</b></span>
{% else %}
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
<span style="font-size: 12px"><b></b></span>
{% endif %}

Related

Why Symfony Controller return template snipped with <html> and <body> tags?

I have a controller-action:
/**
* Get the template for the notifications in the user-navbar
*
* #Route("/notification/get-template", name="get_notifications_template")
* #param Request $request
* #return Response
*/
public function getNotificationsTemplateAction(Request $request)
{
if (!$request->isXmlHttpRequest()) {
return $this->redirect($this->generateUrl('homepage'));
}
return $this->render('Menu/_notifications_block.html.twig');
}
I want to do an AJAX call with to get this template:
refreshNotifications() {
$.ajax({
url: this.$wrapper.data('refresh-action-path'),
method: 'POST',
}).then(function (data) {
// remove old notifications
this.$wrapper.remove();
// append data to the container
$('#user-notifications-container').append(data);
console.log(data);
}.bind(this))
}
The problem is now - that the Symfony container sends a whole html page:
the template is that:
{% if app.user is not null and is_granted('ROLE_USER') %}
{% if app.user|notifications|length != 0 %}
{% set notifications = app.user|notifications %}
{% set all_notification_count = notifications|length %}
<li class="nav-item mx-2 dropdown js-notification-wrapper data-refresh-action-path="{{ path('get_notifications_template') }}"">
<a href="#" class="icon-wrapper nav-link btn-lg" data-toggle="dropdown">
<span class="icon icon-mail" aria-hidden="true"></span>
<span class="badge badge-notification">{{ all_notification_count }}</span>
</a>
<ul class="dropdown-menu dropdown-menu-right notification-list">
{% if app.user is not null and is_granted('ROLE_USER') and all_notification_count != 0 %}
{% for notification in notifications %}
<div class="notification-text">
<div class="d-flex">
<div class="col-10 px-0">
Kurszugang: {{ notification.courseAction.course }} ({{ notification.courseAction.course.school }})
- {{ notification.courseAction.schoolUser }}
</div>
<div class="col-2">
<button class="btn btn-sm btn-success" id="js-accept-course-action" data-course-action-path="{{ path('course_action_accept_join_request', {'courseAction' : notification.courseAction.id}) }}">
<i class="icon icon-thumbs-up"></i>
</button>
<button class="btn btn-sm btn-secondary" id="js-decline-course-action" data-course-action-path="{{ path('course_action_decline_join_request', {'courseAction' : notification.courseAction.id}) }}">
<i class="icon icon-thumbs-down"></i>
</button>
</div>
</div>
</div>
</li>
{% endfor %}
{% endif %}
</ul>
</li>
{% endif %}
{% endif %}
Can somebody tell me - why I can't only the snipped but a whole html page?
I can not append this whole page to the container ...
The way I understand it render returns a complete response(with headers), while renderView will just return the html.
Try changing this line:
return $this->render('Menu/_notifications_block.html.twig');
to this:
return new JsonResponse([
'html'=> $this->renderView('Menu/_notifications_block.html.twig')
]);
then in the ajax function change:
$('#user-notifications-container').append(data);
to this:
$(data.html).appendTo('#user-notifications-container');

Change Index BLog to Directory Blog [Jekyll]

How do I replace a blog list of index
example: mysite.com to mysite.com/blog
I have copied from the index and make myste.com/blog.html , but it does not work
---
layout: default
---
<div class="home">
<div class="site-header-container {% if site.cover %}has-cover{% endif %}" {% if site.cover %}style="background-image: url({{ site.cover | prepend: site.baseurl }});"{% endif %}>
<div class="scrim {% if site.cover %}has-cover{% endif %}">
<header class="site-header">
<h1 class="title">{{ site.title }}</h1>
{% if site.subtitle %}<p class="subtitle">{{ site.subtitle }}</p>{% endif %}
</header>
</div>
</div>
<div class="wrapper">
<ul class="post-list">
{% for post in paginator.posts %}
<li>
<h2>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
</h2>
<section class="post-excerpt" itemprop="description">
<p>{{ post.content | strip_html | truncatewords: 50 }}</p>
</section>
<section class="post-meta">
<div class="post-date">{{ post.date | date: "%B %-d, %Y" }}</div>
<div class="post-categories">
{% if post.categories.size > 0 %}in {% for cat in post.categories %}
{% if site.jekyll-archives %}
{{ cat | capitalize }}{% if forloop.last == false %}, {% endif %}
{% else %}
<span>{{ cat | capitalize }}</span>{% if forloop.last == false %}, {% endif %}
{% endif %}
{% endfor %}{% endif %}
</div>
</section>
</li>
{% if forloop.last == false %}
<hr>
{% endif %}
{% endfor %}
</ul>
<nav class="pagination" role="navigation">
<p>
{% if paginator.next_page %}
<a class="newer-posts" href="{{ site.baseurl }}/page{{paginator.next_page}}">
<span class="fa-stack fa-lg">
<i class="fa fa-square fa-stack-2x"></i>
<i class="fa fa-angle-double-left fa-stack-1x fa-inverse"></i>
</span>
</a>
{% else %}
<span class="fa-stack fa-lg">
<i class="fa fa-square fa-stack-2x"></i>
<i class="fa fa-angle-double-left fa-stack-1x fa-inverse"></i>
</span>
{% endif %}
<span class="page-number">Page {{ paginator.page }} of {{ paginator.total_pages }}</span>
{% if paginator.previous_page %}
{% if paginator.page == 2 %}
<a class="newer-posts" href="{% if site.baseurl %}{{ site.baseurl }}{% endif %}/">
<span class="fa-stack fa-lg">
<i class="fa fa-square fa-stack-2x"></i>
<i class="fa fa-angle-double-right fa-stack-1x fa-inverse"></i>
</span>
</a>
{% else %}
<a class="newer-posts" href="{{ site.baseurl }}/page{{paginator.previous_page}}">
<span class="fa-stack fa-lg">
<i class="fa fa-square fa-stack-2x"></i>
<i class="fa fa-angle-double-right fa-stack-1x fa-inverse"></i>
</span>
</a>
{% endif %}
{% else %}
<span class="fa-stack fa-lg">
<i class="fa fa-square fa-stack-2x"></i>
<i class="fa fa-angle-double-right fa-stack-1x fa-inverse"></i>
</span>
{% endif %}
</p>
<p>
View All Posts by Category
</p>
</nav>
</div>
</div>
Open your config file, and set baseurl as /blog
baseurl: "/blog"
And use prepend:site.baseurl everywhere, just like you have used in above code
{{ site.baseurl }}/category/{{ cat }}

How does the loops and variables in Jekyll?

When I compare in if the post.category is as if there was a post that is the variable is more when I put {{post.category}} it prints the name. It's like if he did not exist in most if I put in if site.post.category handle all values. The problem is that I want to get the current post to compare if that category. I want to list the posts by category.
<div class="posts">
{% for post in site.posts %}
{% if post.category == Eventos %}
<hr>
<div class="post">
<h1 class="post-title">
<a href="{{ site.url }}{{post.url}}">
{{ post.title }}
</a>
</h1>
<span class="post-date">{{ post.date | date_to_string }} / {{ post.category }}</span> {{ post.excerpt }}
<h6>Leia mais...</h6>
</div>
{% endif %}
{% endfor %}
</div>
Try with categories !
{% if post.categories | contains: 'Eventos' %}

How to hide unavailable product variants in Shopify?

I'm trying to make only the available product variants visible in drop downs for products like this one. For example, say you choose 2012 in the first drop down, it would only show the available choices in the second. If you then chose Wed 25th July in the second, it would only show the available variants in the third. At the minute it shows all choices and states 'We don't offer the product in this combination' for an unavailable choice.
So far, my product.liquid page has this code:
<div class="col-7 product-description clearfix">
<h1>{{ product.title }}</h1>
{{ product.description }}
{% include 'addthis' %}
<br/><br/>
{% if product.available %}
{% if product.variants.size > 1 %}
<!-- If the product only has MULTIPLE OPTIONS -->
<form action="/cart/add" method="post" class="product-variants">
<div id="options">
<select id="product-select" name='id'>
{% for variant in product.variants %}
<option value="{{ variant.id }}">{{ variant.title }}</option>
{% endfor %}
</select>
<div class="select-wrapper">
<label for="region">DVD Region</label>
<select id="color" required>
<option value="NTSC">NTSC</option>
<option value="PAL/SECAM" selected="selected">PAL/SECAM</option>
</select>
</div>
<p>Click Here find out more about your region.</p>
</div> <!-- options -->
<div class="price-field"></div>
<input type="submit" name="add" value="Add to cart" id="purchase" />
</form>
{% else %}
<!-- If the product only has ONE variant -->
<form action="/cart/add" method="post" class="product-variants">
<div class="price-field"> {{ product.price | money }}</div>
<input type="submit" name="add" value="Add to cart" id="purchase" />
<input type="hidden" id="{{ variant.id }}" name="id" value="{{ product.variants[0].id }}" /> <!-- passes variant id -->
</form>
{% endif %}
{% else %}
<p>This product is not available</p>
{% endif %}
</div><!-- .col-7 -->
<div class="col-5 last product-thumbs">
<ul>
{% for image in product.images %}
{% if forloop.first %}
<li class="featured-image" >
<a class="zoom " href="{{ image | product_img_url: 'large' }}" title="{{ product.featured_image.alt | escape }}">
<img src="{{ image | product_img_url: 'large' }}" alt="{{ product.featured_image.alt | escape }}" />
</a>
</li>
{% else %}
<li>
<a class="zoom" href="{{ image | product_img_url: 'large' }}" title="{{ image.alt | esacpe }}">
<img class="" src="{{ image | product_img_url: 'small' }}" alt="{{ image.alt | escape }}" />
</a>
</li>
{% endif %}
{% endfor %}
</ul>
</div><!-- .col-5 -->
<script type="text/javascript">
// <![CDATA[
var selectCallback = function(variant, selector) {
if (variant && variant.available == true) {
// selected a valid variant
jQuery('#purchase').removeClass('disabled').removeAttr('disabled'); // remove unavailable class from add-to-cart button, and re-enable button
jQuery('#purchase').fadeIn();
jQuery('.price-field').html(Shopify.formatMoney(variant.price, "{{shop.money_with_currency_format}}")); // update price field
} else {
// variant doesn't exist
jQuery('#purchase').addClass('disabled').attr('disabled', 'disabled'); // set add-to-cart button to unavailable class and disable button
jQuery('#purchase').fadeOut();
var message = variant ? "Sold Out" : "We don't offer the product in this combination";
jQuery('.price-field').text(message); // update price-field message
}
};
// initialize multi selector for product
jQuery(document).ready(function() {
new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback });
{% assign found_one_in_stock = false %}
{% for variant in product.variants %}
{% if variant.available and found_one_in_stock == false %}
{% assign found_one_in_stock = true %}
{% for option in product.options %}
jQuery('.single-option-selector:eq(' + {{ forloop.index0 }} + ')').val({{ variant.options[forloop.index0] | json }}).trigger('change');
{% endfor %}
{% endif %}
{% endfor %}
$('#options div').addClass("selector-wrapper");
{% if product.options.size == 1 %}
$(".selector-wrapper").append("<label>{{ product.options.first }}</label>");
{% endif %}
});
// ]]>
</script>
Any help?

Shopify: Replacing Product Radio Buttons With Dropdown Select

With Shopify I am trying to alter my product template to display a dropdown select list instead of radio buttons for my product variants. I managed to do this but when you try and add a product to the cart from the list it says, "No variant ID was passed."
Here is the code for their radio buttons:
<ul id="product-variants">
{% for variant in product.variants %}
<li>
{% if variant.available %}
<input type="radio" name="id" value="{{variant.id}}" id="radio_{{variant.id}}" style="vertical-align: middle;" {%if forloop.first%} checked="checked" {%endif%} />
<label for="radio_{{variant.id}}"><span class="sku">{{ variant.sku }}</span> {%if variant.title != 'Default' %}{{ variant.title }} for {%endif%} <span class="price">{{ variant.price | money_with_currency }}</span></label>
{% else %}
<del style="margin-left: 26px">{{ variant.title }}</del> <span>Sold Out!</span>
{% endif %}
</li>
{% endfor %}
</ul>
Here is the code for my dropdown select at this point:
<select id="product-variants">
{% for variant in product.variants %}
<li>
{% if variant.available %}
<option value="{{variant.id}}" selected="selected"><span class="sku">{{ variant.sku }}</span> {%if variant.title != 'Default' %}{{ variant.title }} for {%endif%} <span class="price">{{ variant.price | money_with_currency }}</span></option>
{% else %}
<del style="margin-left: 26px">{{ variant.title }}</del> <span>Sold Out!</span>
{% endif %}
</li>
{% endfor %}
</select>
Thanks,
Wade
https://help.shopify.com/themes/development/templates/product-liquid
This wiki had the answer to my question.

Resources