I am working on getting messages history from ClickSend API, I am trying to message from it API as there documentation. But pagination doesn't work. It's only getting the first 15 recorded. Not getting page number as parameter what I send it. Anyone know how does it do? Can I know where I am wrong?
This is my controller Method.
public function index(Request $request)
{
$config = ClickSend\Configuration::getDefaultConfiguration()
->setUsername('user-name')
->setPassword('password');
$apiInstance = new ClickSend\Api\SMSApi(new GuzzleHttp\Client(),$config);
$page = $request->page ? $request->page: 1; // int | Page number
$limit = 10; // int | Number of records per page
try {
$result = $apiInstance->smsHistoryGet($page, $limit);
$dt = json_decode($result);
$current_page = $dt->data;
$current_page = $current_page->current_page;
$next_page = $current_page+1;
$prev_page = $current_page == 1 ? null : $current_page-1;
$allMessages = $dt->data->data;
return response()->json(['data' => view('staff.history.table', compact('allMessages', 'current_page', 'next_page', 'prev_page'))->render()]);
} catch (Exception $e) {
echo 'Exception when calling SMSApi->smsHistoryGet: ', $e->getMessage(), PHP_EOL;
}
}
This is my blade files
<table id="sms-table" class="table table-hover datatable-User">
<thead>
<th>Date</th>
<th>From</th>
<th>Message</th>
<th>Status</th>
</thead>
<tbody>
#foreach($allMessages as $item)
#if($item->status == "Received")
<tr>
#php $date = \Carbon\Carbon::createFromTimestamp($item->date ) #endphp
<td>{{$date->toDayDateTimeString()}}</td>
<td>{{$item->from}}</td>
<td>{{$item->body}}</td>
<td><span class="badge badge-success">{{$item->status}}</span> </td>
</tr>
#endif
#endforeach
</tbody>
</table>
<div class="mt-5">
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-center">
<li class="page-item {{$prev_page == null ? 'disabled' : ''}}" data-page="{{$prev_page == null ? null : $prev_page }}">
<a class="page-link" {{$prev_page == null ? 'disabled' : ''}} href="" tabindex="-1">Previous</a>
</li>
{{-- <li class="page-item"><a class="page-link" >1</a></li>--}}
{{-- <li class="page-item"><a class="page-link">2</a></li>--}}
{{-- <li class="page-item"><a class="page-link">3</a></li>--}}
<li class="page-item" data-page="{{$next_page == null ? null : $next_page }}">
<a class="page-link" href="#">Next</a>
</li>
</ul>
</nav>
</div>
<script>
$('.page-item').on('click', function () {
var page = $(this).data('page')
$.ajax({
url: 'maindomain/api/all-inbound?page=' + page,
type: 'GET',
success: function (data) {
$('#sms-data').html(data.data);
},
});
})
</script>
Related
Hello I'm following a Shopify Admin REST API and laravel related tutorial.
Currently I have following laravel function to fetch some data from Shopify REST API.
public function bestSelling(Request $request)
{
$organisation = Organisation::findOrFail(Auth::user()->organisation);
// Check if the data is already in the cache
$products = Cache::get('best-selling-products');
if ($products) {
return view('reports.shopify.best-selling', ['products' => $products,'organisation'=>$organisation]);
}
$startDate = $request->input('start_date');
$endDate = Carbon::parse($request->input('end_date'))->addDay()->format('Y-m-d');
if (!$startDate) {
$startDate ='2000-01-01' ;
}
if(!$endDate) {
$endDate = Carbon::now()->format('Y-m-d');
}
// Best selling products list
// Set up the Shopify API request to get a list of all orders placed today
$url = "https://APIKEY:AUTHCODE#somestore.myshopify.com/admin/api/2022-10/orders.json?status=any&created_at_min=$startDate&created_at_max=$endDate"; // append the query to the URL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-Shopify-Access-Token:AUTHCODE', // access token
]);
// Send the request
$response = curl_exec($ch);
$response = json_decode($response);
curl_close($ch);
// Group and sort the orders by product to find the best selling products
$productCounts = [];
foreach ($response->orders as $order) {
foreach ($order->line_items as $item) {
if (!isset($productCounts[$item->product_id])) {
$productCounts[$item->product_id] = 0;
}
$productCounts[$item->product_id] += $item->quantity;
}
}
arsort($productCounts);
$topProductIds = array_keys(array_slice($productCounts, 0, 50, true)); // get the top 10 best selling products
// Get the details for the top products
$products = [];
foreach ($topProductIds as $productId) {
$url = "https://APIKEY:AUTHCODE#somestore.myshopify.com/admin/api/2022-10/products/$productId.json";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-Shopify-Access-Token: AUTHCODE', // access token
]);
// Send the request
$response = curl_exec($ch);
$response = json_decode($response);
curl_close($ch);
// Check if the product has an image and a title
if (isset($response->product->image) && !empty($response->product->image)) {
$image = $response->product->image->src;
} else{
$image = null;
}
if (isset($response->product->title) && !empty($response->product->title)) {
$title = $response->product->title;
} else {
$title = "Untitled Product";
}
if (isset($response->product->vendor) && !empty($response->product->vendor)) {
$vendor = $response->product->vendor;
} else {
$vendor = "N/A";
}
if (isset($response->product->product_type) && !empty($response->product->product_type)) {
$product_type = $response->product->product_type;
} else {
$product_type = "N/A";
}
// Calculate the gross sales value and total returns
$grossSales = 0;
$totalDiscounts = 0;
$totalReturns = 0;
foreach ($response->product->variants as $variant) {
if ($variant->inventory_quantity > 0) {
$grossSales += $variant->price * $productCounts[$productId];
$totalDiscounts += $variant->compare_at_price - $variant->price;
$totalReturns += ($variant->compare_at_price * $productCounts[$productId]) - ($variant->price * $productCounts[$productId]);
}
}
$netSales = $grossSales - $totalReturns - $totalDiscounts;
// Add the product details to the list of top products
$productDetails = [
'id' => $productId,
'title' => $title,
'image' => $image,
'vendor'=>$vendor,
'product_type'=>$product_type,
'gross_sales'=> round($grossSales,2),
'total_sales' => $productCounts[$productId],
'total_discounts' => round($totalDiscounts, 2),
'total_returns' => round($totalReturns, 2),
'net_sales' => round( $netSales, 2)
];
array_push($products, $productDetails);
}
// Store the data in the cache for 60 minutes
Cache::put('best-selling-products', $products, now()->addMinutes(60));
return view('reports.shopify.best-selling', ['products' => $products,'organisation'=>$organisation]);
}
This is my resources/views/reports/shopify/best-selling.blade.php
#extends('layouts.app')
#section('content')
<div id="app">
<best-selling :products="{{ json_encode($products) }}"></best-selling>
</div>
#endsection
And following is my web.php
Route::get('/reports/shopify/best-selling', 'ShopifyReportsController#bestSelling')->name('reports.shopify.best-selling');
And This is my front end component, BestSelling.vue
<template>
<div class="container">
<h3 class="mb-4">Best Selling Products</h3>
<div class="row">
<div class="col-sm-12 col-12">
<div class="table-group-top">
<vue-ctk-date-time-picker v-model="dateRange" :format="'YYYY-MM-DD'" :only-date="true" :range="true" :placeholder="'Select a date range'"></vue-ctk-date-time-picker>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="45" height="32" viewBox="0 0 42 45">
</svg>
<a data-target="#demo-default-modal" data-toggle="modal" style="cursor:pointer;"><i class="feather icon-settings f-30"></i></a>
<a id="export_all" style="cursor:pointer;"><i class="feather icon-download-cloud f-30"></i></a>
</div>
</div>
</div>
<div class="modal fade" id="demo-default-modal" role="dialog" tabindex="-1" aria-labelledby="demo-default-modal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="col border-bottom">
<h4 class="modal-title">Columns</h4>
</div>
<div class="form-check form-check-inline mb-3" v-for="col in columns" :key="col">
<input class="form-check-input" type="checkbox" :id="col" :value="col" v-model="selectedColumns">
<label class="form-check-label" :for="col">{{ col }}</label>
</div>
</div>
</div>
</div>
<div class="form-group mt-3">
<input type="text" class="form-control" placeholder="Search products" v-model="searchQuery">
</div>
<table class="table table-striped table-hover">
<thead>
<tr>
<th v-if="selectedColumns.includes('id')">Product ID</th>
<th v-if="selectedColumns.includes('title')">Product Name</th>
<th v-if="selectedColumns.includes('vendor')">Vendor</th>
<th v-if="selectedColumns.includes('product_type')">Product Type</th>
<th v-if="selectedColumns.includes('gross_sales')">Gross Sales</th>
<th v-if="selectedColumns.includes('total_discounts')">Discounts</th>
<th v-if="selectedColumns.includes('total_returns')">Returns</th>
<th v-if="selectedColumns.includes('net_sales')">Net Sales</th>
<th v-if="selectedColumns.includes('total_sales')">No Of Items Sold</th>
</tr>
</thead>
<tbody>
<tr v-for="product in paginatedProducts" :key="product.id">
<td v-if="selectedColumns.includes('id')">{{ product.id }}</td>
<td v-if="selectedColumns.includes('title')">{{ product.title }}</td>
<td v-if="selectedColumns.includes('vendor')">{{ product.vendor }}</td>
<td v-if="selectedColumns.includes('product_type')">{{ product.product_type }}</td>
<td v-if="selectedColumns.includes('gross_sales')">{{ product.gross_sales }}</td>
<td v-if="selectedColumns.includes('total_discounts')">{{ product.total_discounts }}</td>
<td v-if="selectedColumns.includes('total_returns')">{{ product.total_returns }}</td>
<td v-if="selectedColumns.includes('net_sales')">{{ product.net_sales }}</td>
<td v-if="selectedColumns.includes('total_sales')">{{ product.total_sales }}</td>
</tr>
</tbody>
</table>
<!-- Pagination -->
<div class="d-flex justify-content-center">
<nav>
<ul class="pagination">
<li class="page-item" :class="{disabled: currentPage === 1}">
<a class="page-link" href="#" aria-label="Previous" #click.prevent="currentPage = currentPage - 1">
<span aria-hidden="true">«</span>
</a>
</li>
<li v-for="pageNumber in totalPages" :key="pageNumber" class="page-item" :class="{active: currentPage === pageNumber}">
<a class="page-link" href="#" #click.prevent="currentPage = pageNumber">{{ pageNumber }}</a>
</li>
<li class="page-item" :class="{disabled: currentPage === totalPages}">
<a class="page-link" href="#" aria-label="Next" #click.prevent="currentPage = currentPage + 1">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>
<!---->
</div>
</template>
<script>
export default {
props: {
products: {
type: Array,
required: true,
},
columns: {
type: Array,
default: () => ['id', 'title', 'vendor','product_type','gross_sales','total_discounts','total_returns','net_sales','total_sales']
}
},
data() {
return {
selectedColumns: this.columns,
searchQuery: '', // The search term entered by the user
currentPage: 1,
itemsPerPage: 10,
dateRange: {
start: null,
end: null
}
}
},
computed: {
filteredProducts() {
return this.products.filter(product => {
// Check if the search term is present in any of the selected columns
return this.selectedColumns.some(column => {
return String(product[column]).toLowerCase().includes(this.searchQuery.toLowerCase());
});
});
},
totalPages() {
return Math.ceil(this.filteredProducts.length / this.itemsPerPage);
},
paginatedProducts() {
const startIndex = (this.currentPage - 1) * this.itemsPerPage;
const endIndex = startIndex + this.itemsPerPage;
return this.filteredProducts.slice(startIndex, endIndex);
},
},
};
</script>
Here, every thing works fine.
And This is my app.js
import BestSelling from './components/reports/shopify/BestSelling.vue';
const app = new Vue({
el: '#app',
components: {
ReportsShopifyIndex,``your text``
BestSelling,
},
});
BUT
I'm struggling to filter my table data upon the date range selection....
How can I filter my table data upon the date range(start and end dates) selection...
In Laravel 8 pagination how to show less number of pages and also how to add "First Page" and "Last Page"
Now in Laravel when we have more data, it will show the pagination like this:
But I want my pagination to be like the images given below:
Or
To customizing the pagination view, run below command in console
php artisan vendor:publish --tag=laravel-pagination
in /resources/views/vendor/pagination/bootstrap-4.blade.php add bellow code.
<ul class="pagination">
#if ($paginator->onFirstPage())
<li class="page-item disabled" aria-disabled="true" aria-label="#lang('pagination.first')">
<span class="page-link" aria-hidden="true">«</span>
</li>
#else
<li class="page-item">
<a class="page-link" href="{{ \Request::url() }}" rel="prev" aria-label="#lang('pagination.first')">«</a>
</li>
#endif
...
#if ($paginator->hasMorePages())
<li class="page-item">
<a class="page-link" href="{{ \Request::url().'?page='.$paginator->lastPage() }}" rel="last" aria-label="#lang('pagination.last')">»</a>
</li>
#else
<li class="page-item disabled" aria-disabled="true" aria-label="#lang('pagination.last')">
<span class="page-link" aria-hidden="true">»</span>
</li>
#endif
</ul>
<?php
class MyPresenter extends Illuminate\Pagination\BootstrapPresenter {
public function render()
{
if ($this->currentPage == 1) {
$content = $this->getPageRange(1, $this->currentPage + 2);
}
else if ($this->currentPage >= $this->lastPage) {
$content = $this->getPageRange($this->currentPage - 2, $this->lastPage);
}
else {
$content = $this->getPageRange($this->currentPage - 1, $this->currentPage + 1);
}
return $this->getFirst().$this->getPrevious('‹').$content.$this->getNext('›').$this->getLast();
}
public function getFirst($text = '«')
{
if ($this->currentPage <= 1)
{
return $this->getDisabledTextWrapper($text);
}
else
{
$url = $this->paginator->getUrl(1);
return $this->getPageLinkWrapper($url, $text);
}
}
public function getLast($text = '»')
{
if ($this->currentPage >= $this->lastPage)
{
return $this->getDisabledTextWrapper($text);
}
else
{
$url = $this->paginator->getUrl($this->lastPage);
return $this->getPageLinkWrapper($url, $text);
}
}
}
im making a posts page and the thing in focus is pagination.
I've created a pagination component that looks like this:
<template>
<nav aria-label="Pagination">
<ul class="pagination justify-content-end">
<li class="page-item" v-if="currentPage !== 1">
<a #click="previous" class="page-link" href="javascript:void(0)" tabindex="-1">Previous</a>
</li>
<li v-for="page in getNumberOfPagesShow"
v-bind:class="{ disabled: page === currentPage }"
class="page-item">
<a #click="clickPage(page)" class="page-link" href="javascript:void(0)">
{{ page }}
</a>
</li>
<li class="page-item" v-if="currentPage !== totalPages">
<a #click="next" class="page-link" href="javascript:void(0)">Next</a>
</li>
</ul>
</nav>
</template>
<script>
export default {
name: "pagination",
props: ['app', 'onClickPage', 'totalPages', 'page'],
data()
{
return {
currentPage: this.page,
lastPage: 0
}
},
computed: {
getNumberOfPagesShow()
{
if (this.totalPages > 10)
{
return 10;
}
return this.totalPages;
}
},
methods: {
previous()
{
this.currentPage--;
this.clickPage(this.currentPage);
},
next()
{
this.currentPage++;
this.clickPage(this.currentPage);
},
clickPage(page)
{
this.currentPage = page;
this.onClickPage(page);
}
}
}
</script>
<style scoped>
</style>
and the component is called using
<!-- Pagination Top -->
<pagination :total-pages="thread.posts.last_page"
:page="app.$route.query.page"
style="margin-top: 20px;"
:on-click-page="clickPage">
</pagination>
Everything works, except the :page="app.$route.query.page" attribute, which sets the currentPage inside the pagination component.
Now, this code doesn't work:
<li class="page-item" v-if="currentPage !== 1">
<a #click="previous" class="page-link" href="javascript:void(0)" tabindex="-1">Previous</a>
</li>
It's supposed to hide the previous button if current page is 1. However, this doesn't work, suggesting that app.$route.query.page is not getting the value correctly.
When I debug inside the created() method, I write
console.log(this.app.$route.query.page)
it does return the correct value. So I don't know what the problem is.
Thank you in advance!
Great, the solution was to parse the prop page into int:
data()
{
return {
currentPage: parseInt(this.page),
lastPage: 0
}
},
I felt this code look a bit messy, the logic is to show a link <a href or otherwise show text only.
How can I refactor this to look cleaner and maintainable?
<ol class="breadcrumb">
<li class="{{ $active == 'sign_in'? 'active':'' }}">
#if($active != 'sign_in')
#php($showLink = true)
#else
#php($showLink = false)
#endif
#if($showLink)
<a href="{{ url_secure('sign_in') }}">
#endif
Sign In
#if($showLink)
</a>
#endif
</li>
<li class="{{ $active == 'article'? 'active':'' }}">
#if($active != 'article' && $showLink)
#php($showLink= true)
#else
#php($showLink= false)
#endif
#if($showLink)
<a href="{{ url_secure('article')}}">
#endif
Articles
#if($showLink)</a>#endif
</li>
<li> </li> //repeat the code logic like above
</ol>
It would be good if there a way to reduce if conditions and use loop.
Why not just:
<li class="{{ $active == 'sign_in'? 'active':'' }}">
#if ($active != 'sign_in')
Sign In
#else
Sign In
#endif
</li>
Also it is unclear why you check $showLink that was set previoulsy.
Okay, as I've read your comments, I've modified template a bit with using foreach loop:
#php
// some initial variables
$allowed_to_click = true;
// this is a link to selected page
$selected_link = 'something';
#endphp
#foreach ($links as $link)
#php
// check if this link is ACTIVE
$active = $link == $selected_link;
// check if we can CLICK this link
$allowed_to_click = $active || $allowed_to_click;
#endphp
<li class="{{ $active ? 'active':'' }}">
#if ($allowed_to_click)
Some Caption
#else
Some Caption
#endif
</li>
#php
// if link is ACTIVE - following links are unclickable
if ($active) {
$allowed_to_click = false;
}
#endphp
#endforeach
I have issue with grouping breadcrumbs. Following is my code:
Breadcrumbs::register('front', function($breadcrumbs) {
$breadcrumbs->push('Home', URL::to('/'));
});
Breadcrumbs::group(['prefix' => 'front', 'parent' => 'front'], function($breadcrumbs)
{
Breadcrumbs::register('product', function($breadcrumbs) {
$breadcrumbs->push(trans('front.product'), route('product'));
});
});
And following error occurs:
FatalErrorException in
/project/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php
line 219: Call to undefined method
DaveJamesMiller\Breadcrumbs\Manager::group()
I am trying to use breadcrumb as per following example, but no luck:
https://github.com/davejamesmiller/laravel-breadcrumbs/issues/84
Fast Breadcrumbs, don't forget create layout for optimize code.
#include('page.breadcrumbs')
<nav class="breadcrumb" style="font-size: 18px;">
<?php $breadcrumb = ''?>
#for($i = 0; $i <= count(Request::segments()); $i++)
<?php $breadcrumb .= Request::segment($i).'/'; ?>
#if($i == 1)
<a class="breadcrumb-item" href="{{url($breadcrumb).'/inicio'}}">{{Request::segment($i).' / '}}</a>
#elseif($i == count(Request::segments()))
<a class="breadcrumb-item active" href="{{url($breadcrumb)}}">{{Request::segment($i)}}</a>
#else
<a class="breadcrumb-item" href="{{url($breadcrumb)}}">{{Request::segment($i).' / '}}</a>
#endif
#endfor
</nav>