added last month visits to home

pull/44/head
A1Gard 4 months ago
parent 264e5faed0
commit abb4330d62

@ -2,7 +2,11 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Helpers\TDate;
use App\Models\Visitor;
use Carbon\Carbon;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class HomeController extends Controller class HomeController extends Controller
{ {
@ -23,6 +27,25 @@ class HomeController extends Controller
*/ */
public function index() public function index()
{ {
return view('home');
$visits = Visitor::where('created_at', '>=', Carbon::now()->subMonth())
->groupBy('date')
->orderBy('date', 'DESC')
->get(array(
DB::raw('Date(created_at) as date'),
DB::raw('COUNT(*) as "count"'),
DB::raw('SUM(visit) as "visits"'),
))->toArray();
$dates = range((count($visits) - 1) * -1, 0);
$dt = new TDate();
array_walk($dates, function (&$item, $key) use ($dt) {
$x = strtotime($item . ' days');
if (config('app.locale') == 'fa') {
$item = $dt->PDate('Y/m/d', $x);
} else {
$item = date('Y-m-d', $x);
}
});
return view('home',compact('dates','visits'));
} }
} }

@ -20,7 +20,7 @@ class VisitorFactory extends Factory
{ {
$displays = ['1920x1080', '1366x768', '1920x1080', '1366x768', '1280x1024', null, null]; $displays = ['1920x1080', '1366x768', '1920x1080', '1366x768', '1280x1024', null, null];
$displays_mobile = ['360x780', '430x932', '390x844', '375x667', '412x915', null, null]; $displays_mobile = ['360x780', '430x932', '390x844', '375x667', '412x915', '428x926', null];
if (rand(0, 2) == 1) { if (rand(0, 2) == 1) {
$date = $this->faker->dateTimeBetween('-30 days', 'now'); $date = $this->faker->dateTimeBetween('-30 days', 'now');
} else { } else {

@ -17,6 +17,7 @@
"vue": "^3.2.37" "vue": "^3.2.37"
}, },
"dependencies": { "dependencies": {
"chart.js": "^4.4.3",
"leaflet": "^1.9.4", "leaflet": "^1.9.4",
"remixicon": "^4.2.0", "remixicon": "^4.2.0",
"sortablejs": "^1.15.2", "sortablejs": "^1.15.2",

@ -18,6 +18,7 @@ import { createApp } from 'vue';
import ToastPlugin from 'vue-toast-notification'; import ToastPlugin from 'vue-toast-notification';
import {useToast} from 'vue-toast-notification'; import {useToast} from 'vue-toast-notification';
import store from "./components/libs/store.js"; import store from "./components/libs/store.js";
import chartjs from 'chart.js/auto';
import './panel/raw.js'; import './panel/raw.js';
import './panel/navbar.js'; import './panel/navbar.js';
import './panel/list-checkboxs.js'; import './panel/list-checkboxs.js';
@ -27,6 +28,10 @@ import './panel/step-controller.js';
import './panel/product-upload-controller.js'; import './panel/product-upload-controller.js';
import './panel/setting-section-controller.js'; import './panel/setting-section-controller.js';
import './panel/sotable-controller.js'; import './panel/sotable-controller.js';
import './panel/prototypes.js';
window.chartjs = chartjs;
window.isPaintedChart = false;
/** /**
* Next, we will create a fresh Vue application instance. You may then begin * Next, we will create a fresh Vue application instance. You may then begin

@ -7,6 +7,7 @@ import bootstrap from 'bootstrap/dist/js/bootstrap.bundle.min.js';
*/ */
import axios from 'axios'; import axios from 'axios';
window.axios = axios; window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
@ -34,7 +35,7 @@ window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
// }); // });
// fixed tooptips // fixed tooptips
document.addEventListener('readystatechange',function () { document.addEventListener('DOMContentLoaded',function () {
[...document.querySelectorAll('[data-bs-toggle="tooltip"]')] [...document.querySelectorAll('[data-bs-toggle="tooltip"]')]
.forEach(function (el) { .forEach(function (el) {
let e = new bootstrap.Tooltip(el); let e = new bootstrap.Tooltip(el);

@ -0,0 +1,17 @@
/**
*
* @param key
* @param makeNumber [0 = nothing ,1 = integer, 2 = float]
* @returns {any[]}
*/
Array.prototype.subItem = function (key, makeNumber = 0) {
return this.map(item => {
if (makeNumber == 2){
return parseFloat(item[key]);
}else if(makeNumber == 1){
return parseInt(item[key]);
}else{
return item[key];
}
});
};

@ -197,3 +197,12 @@ a.btn,a.action-btn,a.circle-btn{
[data-open-file]{ [data-open-file]{
cursor: pointer; cursor: pointer;
} }
.avatar-x64{
background: $body-bg;
width: 64px;
height: 64px;
border-radius: 50%;
object-fit: cover;
border: 3px rgba($primary-color-panel,127) solid ;
}

@ -1,125 +1,200 @@
@extends('layouts.app') @extends('layouts.app')
@section('content') @section('content')
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-md-6 mb-4"> <div class="col-md-6 p-0 pe-md-2 mb-3">
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-body">
lorem <div class="row">
</div> <div class="col-3 text-center">
<div class="card-body"> <img src="{{asset('panel/images/xshop-logo.svg')}}" class="avatar-x64" alt="">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. </div>
Aliquam aspernatur, commodi consequatur deleniti dolor, <div class="col-9">
dolore ducimus ipsa laudantium magni natus nemo neque odit {{__("Welcome bak")}}
officia perferendis provident suscipit ullam voluptas voluptate? <h4>
{{auth()->user()->name}}
</h4>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> <div class="col-md-6 p-0 ps-md-2 mb-3">
<div class="col-md-6 mb-4"> <div class="card">
<div class="card"> <div class="card-header">
<div class="card-header"> lorem
lorem </div>
</div> <div class="card-body">
<div class="card-body"> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam aspernatur, commodi consequatur deleniti dolor,
Aliquam aspernatur, commodi consequatur deleniti dolor, dolore ducimus ipsa laudantium magni natus nemo neque odit
dolore ducimus ipsa laudantium magni natus nemo neque odit officia perferendis provident suscipit ullam voluptas voluptate?
officia perferendis provident suscipit ullam voluptas voluptate? </div>
</div> </div>
</div> </div>
</div> <div class="col-md-12 mb-3 p-0" id="visitor-container">
<div class="col-md-4 mb-4"> <div class="card">
<div class="card"> <div class="card-header">
<div class="card-header"> {{__("last month visits")}}
lorem </div>
</div> <div class="card-body">
<div class="card-body"> <canvas id="visitor-chart" height="300"></canvas>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. </div>
Aliquam aspernatur, commodi consequatur deleniti dolor,
dolore ducimus ipsa laudantium magni natus nemo neque odit
officia perferendis provident suscipit ullam voluptas voluptate?
</div> </div>
</div> </div>
</div>
<div class="col-md-4 mb-4"> <div class="col-md-4 mb-4">
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
lorem lorem
</div> </div>
<div class="card-body"> <div class="card-body">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Aliquam aspernatur, commodi consequatur deleniti dolor, Aliquam aspernatur, commodi consequatur deleniti dolor,
dolore ducimus ipsa laudantium magni natus nemo neque odit dolore ducimus ipsa laudantium magni natus nemo neque odit
officia perferendis provident suscipit ullam voluptas voluptate? officia perferendis provident suscipit ullam voluptas voluptate?
</div>
</div> </div>
</div> </div>
</div> <div class="col-md-4 mb-4">
<div class="col-md-4 mb-4"> <div class="card">
<div class="card"> <div class="card-header">
<div class="card-header"> lorem
lorem </div>
</div> <div class="card-body">
<div class="card-body"> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam aspernatur, commodi consequatur deleniti dolor,
Aliquam aspernatur, commodi consequatur deleniti dolor, dolore ducimus ipsa laudantium magni natus nemo neque odit
dolore ducimus ipsa laudantium magni natus nemo neque odit officia perferendis provident suscipit ullam voluptas voluptate?
officia perferendis provident suscipit ullam voluptas voluptate? </div>
</div> </div>
</div> </div>
</div> <div class="col-md-4 mb-4">
<div class="col-md-3 mb-4"> <div class="card">
<div class="card"> <div class="card-header">
<div class="card-header"> lorem
lorem </div>
</div> <div class="card-body">
<div class="card-body"> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam aspernatur, commodi consequatur deleniti dolor,
Aliquam aspernatur, commodi consequatur deleniti dolor, dolore ducimus ipsa laudantium magni natus nemo neque odit
dolore ducimus ipsa laudantium magni natus nemo neque odit officia perferendis provident suscipit ullam voluptas voluptate?
officia perferendis provident suscipit ullam voluptas voluptate? </div>
</div> </div>
</div> </div>
</div> <div class="col-md-3 mb-4">
<div class="col-md-3 mb-4"> <div class="card">
<div class="card"> <div class="card-header">
<div class="card-header"> lorem
lorem </div>
</div> <div class="card-body">
<div class="card-body"> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam aspernatur, commodi consequatur deleniti dolor,
Aliquam aspernatur, commodi consequatur deleniti dolor, dolore ducimus ipsa laudantium magni natus nemo neque odit
dolore ducimus ipsa laudantium magni natus nemo neque odit officia perferendis provident suscipit ullam voluptas voluptate?
officia perferendis provident suscipit ullam voluptas voluptate? </div>
</div> </div>
</div> </div>
</div> <div class="col-md-3 mb-4">
<div class="col-md-3 mb-4"> <div class="card">
<div class="card"> <div class="card-header">
<div class="card-header"> lorem
lorem </div>
</div> <div class="card-body">
<div class="card-body"> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam aspernatur, commodi consequatur deleniti dolor,
Aliquam aspernatur, commodi consequatur deleniti dolor, dolore ducimus ipsa laudantium magni natus nemo neque odit
dolore ducimus ipsa laudantium magni natus nemo neque odit officia perferendis provident suscipit ullam voluptas voluptate?
officia perferendis provident suscipit ullam voluptas voluptate? </div>
</div> </div>
</div> </div>
</div> <div class="col-md-3 mb-4">
<div class="col-md-3 mb-4"> <div class="card">
<div class="card"> <div class="card-header">
<div class="card-header"> lorem
lorem </div>
<div class="card-body">
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Aliquam aspernatur, commodi consequatur deleniti dolor,
dolore ducimus ipsa laudantium magni natus nemo neque odit
officia perferendis provident suscipit ullam voluptas voluptate?
</div>
</div> </div>
<div class="card-body"> </div>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. <div class="col-md-3 mb-4">
Aliquam aspernatur, commodi consequatur deleniti dolor, <div class="card">
dolore ducimus ipsa laudantium magni natus nemo neque odit <div class="card-header">
officia perferendis provident suscipit ullam voluptas voluptate? lorem
</div>
<div class="card-body">
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Aliquam aspernatur, commodi consequatur deleniti dolor,
dolore ducimus ipsa laudantium magni natus nemo neque odit
officia perferendis provident suscipit ullam voluptas voluptate?
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> @endsection
@section('js-content')
<script>
window.addEventListener('load', function () {
if (isPaintedChart) {
return;
}
isPaintedChart = true;
let ctx = document.getElementById('visitor-chart').getContext('2d');
let visits = @json($visits);
document.getElementById('visitor-chart').setAttribute('width', document.querySelector('#visitor-container').clientWidth - 45);
let chart = new window.chartjs(ctx, {
// The type of chart we want to create
type: 'line', // also try bar or other graph types
// The data for our dataset
data: {
labels: @json($dates),
// Information about the dataset
datasets: [
{
label: "{{__('Visitors')}}",
backgroundColor: 'rgba(128,0,255,0.1)',
borderColor: 'rgba(140,0,255,0.6)',
data: visits.subItem('count', 1),
fill: true,
},
{
label: "{{__('Visits')}}",
backgroundColor: 'rgba(255,0,0,0.1)',
borderColor: '#ff000099',
data: visits.subItem('visits', 1),
fill: true,
},
]
},
// Configuration options
options: {
layout: {
padding: 10,
},
legend: {
position: 'bottom',
},
title: {
display: true,
text: 'Precipitation in Toronto'
}
}
});
});
</script>
@endsection @endsection

@ -18,4 +18,5 @@
</div> </div>
</div> </div>
</div> </div>
@yield('js-content')
@include('components.panel-footer') @include('components.panel-footer')

@ -127,6 +127,11 @@
resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
"@kurkle/color@^0.3.0":
version "0.3.2"
resolved "https://registry.yarnpkg.com/@kurkle/color/-/color-0.3.2.tgz#5acd38242e8bde4f9986e7913c8fdf49d3aa199f"
integrity sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==
"@popperjs/core@^2.11.6": "@popperjs/core@^2.11.6":
version "2.11.8" version "2.11.8"
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz" resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"
@ -345,6 +350,13 @@ braces@~3.0.2:
dependencies: dependencies:
fill-range "^7.0.1" fill-range "^7.0.1"
chart.js@^4.4.3:
version "4.4.3"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.4.3.tgz#3b2e11e7010fefa99b07d0349236f5098e5226ad"
integrity sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==
dependencies:
"@kurkle/color" "^0.3.0"
"chokidar@>=3.0.0 <4.0.0": "chokidar@>=3.0.0 <4.0.0":
version "3.6.0" version "3.6.0"
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz"

Loading…
Cancel
Save