fix: 📈 update dashboard statistics #52

This commit is contained in:
Alexis Gousseau 2025-01-13 15:43:42 +01:00
parent 184da0204b
commit f454d35960
15 changed files with 419 additions and 254 deletions

View file

@ -19,8 +19,8 @@ final class InvoicingUnit extends BaseEnum
protected static function values(): array
{
return [
'pce' => 'PCE',
'kgm' => 'KGM',
'pce' => 'PCE',
'kgm' => 'KGM',
'colis' => 'COLIS',
];
}
@ -33,8 +33,8 @@ final class InvoicingUnit extends BaseEnum
protected static function labels(): array
{
return [
'pce' => __('Pièce'),
'kgm' => __('Kg'),
'pce' => __('Pièce'),
'kgm' => __('Kg'),
'colis' => __('Colis'),
];
}

View file

@ -19,8 +19,8 @@ final class OrderUnit extends BaseEnum
protected static function values(): array
{
return [
'pce' => 'PCE',
'kgm' => 'KGM',
'pce' => 'PCE',
'kgm' => 'KGM',
'colis' => 'COLIS',
];
}
@ -33,8 +33,8 @@ final class OrderUnit extends BaseEnum
protected static function labels(): array
{
return [
'pce' => __('Pièce'),
'kgm' => __('Kg'),
'pce' => __('Pièce'),
'kgm' => __('Kg'),
'colis' => __('Colis'),
];
}

View file

@ -23,7 +23,7 @@ class PriceShowingMode extends BaseEnumRoutable
{
return [
'authenticated' => 'authenticated',
'guest' => 'guest',
'guest' => 'guest',
];
}
@ -36,7 +36,7 @@ class PriceShowingMode extends BaseEnumRoutable
{
return [
'authenticated' => __('Client Connecté'),
'guest' => __('Public'),
'guest' => __('Public'),
];
}
}

View file

@ -27,12 +27,12 @@ class ProductBrand extends BaseEnumRoutable
public static function labels()
{
return [
'none' => 'Sans marque',
'loue' => 'Loué',
'legaulois' => 'Le Gaulois',
'legauloispro' => 'Le Gaulois Professionnel',
'marie' => 'Marie',
'tregalette' => 'Trégalette',
'none' => 'Sans marque',
'loue' => 'Loué',
'legaulois' => 'Le Gaulois',
'legauloispro' => 'Le Gaulois Professionnel',
'marie' => 'Marie',
'tregalette' => 'Trégalette',
'esprirestauration' => 'Espri Restauration',
];
}

View file

@ -34,21 +34,21 @@ class SalarieSite extends BaseEnumRoutable
protected static function values(): array
{
return [
'slhp' => 'SLHP',
'ldcser' => 'LDCSER',
'ldcvol' => 'LDCVOL',
'ldcter' => 'LDCTER',
'ldctra' => 'LDCTRA',
'ldccav' => 'LDCCAV',
'ldchol' => 'LDCHOL',
'slhp' => 'SLHP',
'ldcser' => 'LDCSER',
'ldcvol' => 'LDCVOL',
'ldcter' => 'LDCTER',
'ldctra' => 'LDCTRA',
'ldccav' => 'LDCCAV',
'ldchol' => 'LDCHOL',
'cepacpe' => 'CEPACP',
'dde' => 'DDE',
'dpe' => 'DPE',
'sl' => 'SL',
'gdfroi' => 'GDFROI',
'ldcplb' => 'LDCPLB',
'slela' => 'SLELA',
'tpwiss' => 'TPWISS'
'dde' => 'DDE',
'dpe' => 'DPE',
'sl' => 'SL',
'gdfroi' => 'GDFROI',
'ldcplb' => 'LDCPLB',
'slela' => 'SLELA',
'tpwiss' => 'TPWISS'
];
}
@ -60,21 +60,21 @@ class SalarieSite extends BaseEnumRoutable
public static function labels()
{
return [
'slhp' => 'Holdings',
'ldcser' => 'LDC Services',
'ldcvol' => 'LDC Sablé',
'ldcter' => 'LDC Intenational',
'ldctra' => 'LDC Traiteur',
'ldccav' => 'Cavol',
'ldchol' => 'LDC Holding',
'slhp' => 'Holdings',
'ldcser' => 'LDC Services',
'ldcvol' => 'LDC Sablé',
'ldcter' => 'LDC Intenational',
'ldctra' => 'LDC Traiteur',
'ldccav' => 'Cavol',
'ldchol' => 'LDC Holding',
'cepacpe' => 'CPE-CEPA',
'dde' => 'Unité Dinde',
'dpe' => 'DPE',
'sl' => 'Saint-Laurent',
'gdfroi' => 'Grand Froid',
'ldcplb' => 'LDC PLB',
'slela' => 'SLELA',
'tpwiss' => 'TPWISS'
'dde' => 'Unité Dinde',
'dpe' => 'DPE',
'sl' => 'Saint-Laurent',
'gdfroi' => 'Grand Froid',
'ldcplb' => 'LDC PLB',
'slela' => 'SLELA',
'tpwiss' => 'TPWISS'
];
}
}

View file

@ -19,8 +19,8 @@ final class SellUnit extends BaseEnum
protected static function values(): array
{
return [
'pce' => 'PCE',
'kgm' => 'KGM',
'pce' => 'PCE',
'kgm' => 'KGM',
'colis' => 'COLIS',
];
}
@ -33,8 +33,8 @@ final class SellUnit extends BaseEnum
protected static function labels(): array
{
return [
'pce' => __('Pièce'),
'kgm' => __('Kg'),
'pce' => __('Pièce'),
'kgm' => __('Kg'),
'colis' => __('Colis'),
];
}

View file

@ -18,7 +18,7 @@ final class SettingRegisterMode extends BaseEnum
protected static function values(): array
{
return [
'public' => 'public',
'public' => 'public',
'salaries' => 'salaries',
];
}
@ -31,7 +31,7 @@ final class SettingRegisterMode extends BaseEnum
protected static function labels(): array
{
return [
'public' => __('Public'),
'public' => __('Public'),
'salaries' => __('Salaries'),
];
}

View file

@ -0,0 +1,41 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnum;
/**
* @method static self nbSalarie()
* @method static self nbSalarieWithAccount()
* @method static self membershipRate()
*
*/
class StatsCustomerType extends BaseEnum
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'nbSalarie' => 1,
'nbSalarieWithAccount' => 2,
'membershipRate' => 3,
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'nbSalarie' => trans('Nombre de salariés'),
'nbSalarieWithAccount' => trans('Nombre de salariés ayant créé un compte'),
'membershipRate' => trans('Taux d\'adhésion à la :appName', ['appName' => config('app.name')]),
];
}
}

View file

@ -5,21 +5,22 @@ namespace App\Enums;
use Kwaadpepper\Enum\BaseEnum;
/**
* @method static self nbActiveClients()
* @method static self nbValidateCmd()
* @method static self nbWaitingCmd()
* @method static self nbCanceledCmd()
* @method static self canceledRate()
* @method static self orderFrequency()
* @method static self nbActiveClients()
* @method static self nbCmdWith7DayDelay()
* @method static self nbCmdWith14DayDelay()
* @method static self nbCmdWithMoreThan14DayDelay()
* @method static self caHt()
* @method static self canceledRate()
* @method static self orderFrequency()
* @method static self purchaseFrequency()
* @method static self averageBasketHt()
* @method static self averageProductCountPerOrder()
* @method static self caHt()
* @method static self caTtc()
*
*/
class StatsType extends BaseEnum
class StatsShopType extends BaseEnum
{
/**
* Enum values
@ -29,18 +30,19 @@ class StatsType extends BaseEnum
protected static function values(): array
{
return [
'nbValidateCmd' => 1,
'nbWaitingCmd' => 2,
'nbCanceledCmd' => 3,
'canceledRate' => 4,
'orderFrequency' => 5,
'nbActiveClients' => 6,
'nbCmdWith7DayDelay' => 7,
'nbCmdWith14DayDelay' => 8,
'nbCmdWithMoreThan14DayDelay' => 9,
'caHt' => 10,
'averageBasketHt' => 11,
'averageProductCountPerOrder' => 12
'nbActiveClients' => 1,
'nbValidateCmd' => 2,
'nbWaitingCmd' => 3,
'nbCanceledCmd' => 4,
'nbCmdWith7DayDelay' => 5,
'nbCmdWith14DayDelay' => 6,
'canceledRate' => 7,
'orderFrequency' => 8,
'purchaseFrequency' => 9,
'averageBasketHt' => 10,
'averageProductCountPerOrder' => 11,
'caHt' => 12,
'caTtc' => 13,
];
}
/**
@ -51,18 +53,19 @@ class StatsType extends BaseEnum
protected static function labels(): array
{
return [
'nbValidateCmd' => trans('Nombre de commandes validées'),
'nbWaitingCmd' => trans('Nombre de commandes en attente'),
'nbCanceledCmd' => trans('Nombre de commandes annulées'),
'canceledRate' => trans('Taux d\'abandon (en pourcentage)'),
'orderFrequency' => trans('Fréquence d\'achat (en jours)'),
'nbActiveClients' => trans('Nombre de clients actifs'),
'nbValidateCmd' => trans('Commandes validées'),
'nbWaitingCmd' => trans('Commandes en attente'),
'nbCanceledCmd' => trans('Commandes annulées'),
'nbCmdWith7DayDelay' => trans('Nombre de commandes à J+7'),
'nbCmdWith14DayDelay' => trans('Nombre de commandes à J+14'),
'nbCmdWithMoreThan14DayDelay' => trans('Nombre de commandes à J+15 et plus'),
'caHt' => trans('Montant total HT'),
'canceledRate' => trans('Taux d\'abandon'),
'orderFrequency' => trans('Fréquence de commande'),
'purchaseFrequency' => trans('Fréquence d\'achat'),
'averageBasketHt' => trans('Prix du panier moyen'),
'averageProductCountPerOrder' => trans('Nombre d\'article moyen par commande')
'averageProductCountPerOrder' => trans('Nombre d\'article moyen par commande'),
'caHt' => trans('Montant total HT'),
'caTtc' => trans('Montant total TTC'),
];
}
}

View file

@ -19,8 +19,8 @@ final class WeightUnit extends BaseEnum
protected static function values(): array
{
return [
'g' => 'G',
'kg' => 'KG',
'g' => 'G',
'kg' => 'KG',
'ton' => 'T',
];
}
@ -33,8 +33,8 @@ final class WeightUnit extends BaseEnum
protected static function labels(): array
{
return [
'g' => __('Gramme'),
'kg' => __('Kg'),
'g' => __('Gramme'),
'kg' => __('Kg'),
'ton' => __('Tonne'),
];
}
@ -48,9 +48,9 @@ final class WeightUnit extends BaseEnum
public static function convert(): array
{
return [
'G' => 0.001,
'G' => 0.001,
'KG' => 1,
'T' => 1000,
'T' => 1000,
];
}

View file

@ -2,6 +2,8 @@
namespace App\Http\Controllers\Bo;
use App\Enums\StatsCustomerType;
use App\Enums\StatsShopType;
use App\Http\Controllers\Controller;
use Carbon\Carbon;
use App\Http\Requests\Bo\DashboardRequest;
@ -17,16 +19,22 @@ class DashboardController extends Controller
*/
public function index(DashboardRequest $request)
{
$stats = [];
$adhesion = StatsHelper::getMembershipPercentage();
$previousDates = [];
$statsShop = [];
$statsCustomer = [];
$prevDates = [];
if ($request->has('start') && $request->has('end')) {
$start = new Carbon($request->start);
$end = new Carbon($request->end);
$previousDates = StatsHelper::getPreviousPeriod($start, $end);
$stats = StatsHelper::getStats($start, $end);
$start = new Carbon($request->start);
$end = new Carbon($request->end);
$prevDates = StatsHelper::getPreviousPeriod($start, $end);
$statsShop = StatsHelper::getStats(StatsShopType::toArray(), $start, $end);
$statsCustomer = StatsHelper::getStats(StatsCustomerType::toArray(), $start, $end);
}
return view('bo.dashboard', compact('stats', 'adhesion', 'previousDates'));
return view('bo.dashboard', compact(
'prevDates',
'statsShop',
'statsCustomer',
));
}
}

View file

@ -9,25 +9,25 @@ use App\Models\Salarie;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Database\Eloquent\Builder;
use App\Enums\StatsType;
final class StatsHelper
{
/**
* getStats
*
* @param array $statsType
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* @return array
*/
public static function getStats(Carbon $start, Carbon $end)
public static function getStats(array $statsType, Carbon $start, Carbon $end)
{
$stats = [];
foreach (StatsType::toArray() as $type) {
foreach ($statsType as $type) {
$stats[$type->value] = [
'previous' => self::getPrevious(sprintf('get%s', ucfirst($type->getDefinition())), $start, $end),
'current' => self::{sprintf('get%s', ucfirst($type->getDefinition()))}($start, $end),
'diff' => self::getDiff(sprintf('get%s', ucfirst($type->getDefinition())), $start, $end),
'current' => self::{sprintf('get%s', ucfirst($type->getDefinition()))}($start, $end),
'diff' => self::getDiff(sprintf('get%s', ucfirst($type->getDefinition())), $start, $end),
];
}
return $stats;
@ -60,16 +60,72 @@ final class StatsHelper
return self::{$method}($start, $end) - self::getPrevious($method, $start, $end);
}
/**
* Get all validated orders.
*
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* @return mixed
*/
private function getNbSalarie(Carbon $start, Carbon $end)
{
return self::getNumberCustomers($start, $end);
}
/**
* Get all validated orders.
*
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* @return mixed
*/
private function getNbSalarieWithAccount(Carbon $start, Carbon $end)
{
return self::getNumberSalaries($start, $end);
}
/**
* Get the percentage of registered people / people with a generated code
*
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* @return integer
*/
public static function getNumberCustomers(Carbon $start, Carbon $end): int
{
return Customers::query()
->whereDate('created_at', '>=', $start)
->whereDate('created_at', '<=', $end)
->count();
}
/**
* Get the percentage of registered people / people with a generated code
*
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* @return integer
*/
public static function getNumberSalaries(Carbon $start, Carbon $end): int
{
return Customers::query()
->has('salarie')
->whereDate('created_at', '>=', $start)
->whereDate('created_at', '<=', $end)
->count();
}
/**
* Get the percentage of registered people / people with a generated code
*
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* @return integer|float
*/
public static function getMembershipPercentage()
public static function getMembershipRate(Carbon $start, Carbon $end): int
{
$employee = Salarie::count();
$registered = Customers::has('salarie')->count();
return round($registered / $employee * 100, 2);
$registered = self::getNumberSalaries($start, $end);
return round($registered / Salarie::count() * 100, 2);
}
/**
@ -164,6 +220,23 @@ final class StatsHelper
return round($nbValidateCmd / $period, 2);
}
/**
* Get the order frequency.
*
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* @return mixed
*/
private function getPurchaseFrequency(Carbon $start, Carbon $end)
{
$activeClients = self::getNbActiveClients($start, $end);
if (!$activeClients) {
return 0;
}
$nbValidateCmd = self::getNbValidateCmd($start, $end);
return round($nbValidateCmd / $activeClients, 2);
}
/**
* Get the number of active clients (ordered in the period).
*
@ -214,23 +287,6 @@ final class StatsHelper
})->count();
}
/**
* Get the number command where the collect day is > 14 days after the order.
*
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* @return mixed
*/
private function getNbCmdWithMoreThan14DayDelay(Carbon $start, Carbon $end)
{
return Order::with('timeslot')->whereHas('status', function (Builder $query) {
$query->whereIn('id', [3, 4, 5, 6]);
})->whereBetween('date', [$start, $end])->get()->filter(function (Order $order) {
return Carbon::create($order->timeslot->day)
->greaterThan(Carbon::create($order->date)->modify('+14 day'));
})->count();
}
/**
* Get the CA HT.
*
@ -254,6 +310,30 @@ final class StatsHelper
return $totalCaHt;
}
/**
* Get the CA TTC.
*
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* @return mixed
*/
private function getCaTtc(Carbon $start, Carbon $end)
{
$orderedProducts = OrderLine::whereHas('order', function (Builder $query) use ($start, $end) {
$query->whereHas('status', function (Builder $query) {
$query->whereIn('id', [3, 4, 5, 6]);
})->whereBetween('date', [$start->toDateString(), $end->toDateString()]);
})->get();
$totalCaTtc = 0;
$orderedProducts->map(function ($item) use (&$totalCaTtc) {
$totalCaTtc += $item->total_ttc;
});
return $totalCaTtc;
}
/**
* Get the average basket HT.
*
@ -312,7 +392,7 @@ final class StatsHelper
$diffDays = $start->copy()->diffInDays($end);
return (object)[
'start' => $start->copy()->subDays($diffDays + 1),
'end' => $start->copy()->subDay()
'end' => $start->copy()->subDay()
];
}
}

View file

@ -98,17 +98,17 @@ class Customers extends Authenticatable
parent::toArray(),
(array)$this->apiData
))->intersectByKeys([
'email' => '',
'firstname' => '',
'lastname' => '',
'address' => '',
'address2' => '',
'postcode' => '',
'email' => '',
'firstname' => '',
'lastname' => '',
'address' => '',
'address2' => '',
'postcode' => '',
'birth_date' => '',
'city' => '',
'country' => '',
'opt_in' => '',
'phone' => ''
'city' => '',
'country' => '',
'opt_in' => '',
'phone' => ''
])->toArray();
} else {
return parent::toArray();

View file

@ -5,40 +5,24 @@
<h1 class="h2">Dashboard</h1>
</div>
<div class="container">
<table class="table table-responsive table-bordered">
<thead>
<tr class="text-center table-secondary">
<th scope="col">{{ __('Nombre de salariés') }}</th>
<th scope="col">{{ __('Nombre de salariés inscrits') }}</th>
<th scope="col">{{ __('Taux d\'adhésion') }}</th>
</tr>
</thead>
<tbody>
<tr class="text-center table-light text-bold fw-semibold">
<td>{{ number_format(App\Models\Salarie::count(), 0, ",", " ") }}</td>
<td>{{ number_format(App\Models\Customers::has('salarie')->count(), 0, ",", " ") }}</td>
<td>{{ number_format($adhesion, 2, ",", " ") }} %</td>
</tr>
</tbody>
</table>
<br />
{{-- DATES --}}
<form action="{{ route('bo.dashboard') }}">
<div class="row">
<div class="col">
<label for="start">{{ __('Date de début') }}:</label>
<input class="form-control" type="date" id="start" name="start" value="{{ request()->start }}" required/>
@if (!empty($stats))
<label for="previousStart">{{ __('Date de début de la période précédente') }}:</label>
<input class="form-control" type="date" id="previousStart" name="previousStart" value="{{ $previousDates->start->toDateString() }}" aria-label="disabled input" disabled>
@if (!empty($statsShop))
<label for="previousStart">{{ __('Date de début de la période précédente') }}:</label>
<input class="form-control" type="date" id="previousStart" name="previousStart" value="{{ $prevDates->start->toDateString() }}" aria-label="disabled input" disabled>
@endif
<br>
</div>
<div class="col">
<label for="end">{{ __('Date de fin') }}:</label>
<input class="form-control" type="date" id="end" name="end" value="{{ request()->end }}" required/>
@if (!empty($stats))
<label for="previousEnd">{{ __('Date de fin de la période précédente') }}:</label>
<input class="form-control" type="date" id="previousEnd" name="previousEnd" value="{{ $previousDates->end->toDateString() }}" aria-label="disabled input" disabled>
@if (!empty($statsShop))
<label for="previousEnd">{{ __('Date de fin de la période précédente') }}:</label>
<input class="form-control" type="date" id="previousEnd" name="previousEnd" value="{{ $prevDates->end->toDateString() }}" aria-label="disabled input" disabled>
@endif
</div>
<div class="col d-inline-flex align-items-center">
@ -46,99 +30,154 @@
</div>
</div>
</form>
<table class="table table-responsive table-bordered table-hover">
<thead>
<tr class="text-center bg-secondary bg-gradient bg-opacity-25">
<th scope="col"></th>
<th scope="col">{{ __('Période précédente') }}</th>
<th scope="col">{{ __('Période actuelle') }}</th>
<th scope="col">{{ __('Différence') }}</th>
</tr>
</thead>
@if(!empty($stats))
<tbody>
@foreach ($stats as $k => $stat)
<tr class="text-center">
@if (
$k === App\Enums\StatsType::nbWaitingCmd()->value ||
$k === App\Enums\StatsType::nbCanceledCmd()->value ||
$k === App\Enums\StatsType::canceledRate()->value ||
$k === App\Enums\StatsType::orderFrequency()->value
)
<th @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>{{ App\Enums\StatsType::make($k)->label }}</th>
<td @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>
@switch($k)
@case(App\Enums\StatsType::canceledRate()->value)
{{ number_format($stat['previous'], 2, ",", " ") }} %
@break
@case(App\Enums\StatsType::orderFrequency()->value)
{{ number_format($stat['previous'], 2, ",", " ") }} {{ __('jours') }}
@break
@default
{{ str_replace(".", ",", $stat['previous']) }}
@endswitch
</td>
<td @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>
@switch($k)
@case(App\Enums\StatsType::canceledRate()->value)
{{ number_format($stat['current'], 2, ",", " ") }} %
@break
@case(App\Enums\StatsType::orderFrequency()->value)
{{ number_format($stat['current'], 2, ",", " ") }} {{ __('jours') }}
@break
@default
{{ str_replace(".", ",", $stat['current']) }}
@endswitch
</td>
<td @if ($stat['diff'] < 0) class="text-success table-success" @else class="text-danger table-danger" @endif>
@switch($k)
@case(App\Enums\StatsType::canceledRate()->value)
<b>{{ number_format($stat['diff'], 2, ",", " ") }} %</b>
@break
@case(App\Enums\StatsType::orderFrequency()->value)
<b>{{ number_format($stat['diff'], 2, ",", " ") }} {{ __('jours') }}</b>
@break
@default
<b>{{ str_replace(".", ",", $stat['diff']) }}</b>
@endswitch
</td>
@else
<th @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>{{ App\Enums\StatsType::make($k)->label }}</th>
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
@switch($k)
@case(App\Enums\StatsType::caHt()->value)
@case(App\Enums\StatsType::averageBasketHt()->value)
{{ number_format($stat['previous'], 2, ",", " ") }} €
@break
@default
{{ str_replace(".", ",", $stat['previous']) }}
@endswitch
</td>
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
@switch($k)
@case(App\Enums\StatsType::caHt()->value)
@case(App\Enums\StatsType::averageBasketHt()->value)
{{ number_format($stat['current'], 2, ",", " ") }} €
@break
@default
{{ str_replace(".", ",", $stat['current']) }}
@endswitch
</td>
<td @if ($stat['diff'] > 0) class="text-success table-success" @else class="text-danger table-danger" @endif>
@switch($k)
@case(App\Enums\StatsType::caHt()->value)
@case(App\Enums\StatsType::averageBasketHt()->value)
<b>{{ number_format($stat['diff'], 2, ",", " ") }} €</b>
@break
@default
<b>{{ str_replace(".", ",", $stat['diff']) }}</b>
@endswitch
</td>
@endif
</tr>
@endforeach
</tbody>
@endif
</table>
{{-- CUSTOMERS DATA --}}
@if(!empty($statsCustomer))
<table class="table table-responsive table-bordered table-hover">
<thead>
<tr class="text-center bg-secondary bg-gradient bg-opacity-25">
<th scope="col">{{-- keep empty --}}</th>
<th scope="col">{{ __('Période précédente') }}</th>
<th scope="col">{{ __('Période actuelle') }}</th>
<th scope="col">{{ __('Différence') }}</th>
</tr>
</thead>
<tbody>
@foreach ($statsCustomer as $k => $stat)
<tr class="text-center">
<th @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
{{ App\Enums\StatsCustomerType::make($k)->label }}
</th>
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
@switch($k)
@case(App\Enums\StatsCustomerType::membershipRate()->value)
{{ number_format($stat['previous'], 2, ",", " ") }} %
@break
@default
{{ $stat['previous'] }}
@endswitch
</td>
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
@switch($k)
@case(App\Enums\StatsCustomerType::membershipRate()->value)
{{ number_format($stat['current'], 2, ",", " ") }} %
@break
@default
{{ $stat['current'] }}
@endswitch
</td>
<td @if ($stat['diff'] > 0) class="text-success table-success" @else class="text-danger table-danger" @endif>
<b>
@switch($k)
@case(App\Enums\StatsCustomerType::membershipRate()->value)
{{ number_format($stat['diff'], 2, ",", " ") }} %
@break
@default
{{ $stat['diff'] }}
@endswitch
</b>
</td>
</tr>
@endforeach
</tbody>
</table>
@endif
@if(!empty($statsShop))
<table class="table table-responsive table-bordered table-hover">
<thead>
<tr class="text-center bg-secondary bg-gradient bg-opacity-25">
<th scope="col">{{-- keep empty --}}</th>
<th scope="col">{{ __('Période précédente') }}</th>
<th scope="col">{{ __('Période actuelle') }}</th>
<th scope="col">{{ __('Différence') }}</th>
</tr>
</thead>
<tbody>
@foreach ($statsShop as $k => $stat)
<tr class="text-center">
@if (
$k === App\Enums\StatsShopType::nbWaitingCmd()->value ||
$k === App\Enums\StatsShopType::nbCanceledCmd()->value ||
$k === App\Enums\StatsShopType::canceledRate()->value
)
<th @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>{{ App\Enums\StatsShopType::make($k)->label }}</th>
<td @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>
@switch($k)
@case(App\Enums\StatsShopType::canceledRate()->value)
{{ number_format($stat['previous'], 2, ",", " ") }} %
@break
@default
{{ str_replace(".", ",", $stat['previous']) }}
@endswitch
</td>
<td @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>
@switch($k)
@case(App\Enums\StatsShopType::canceledRate()->value)
{{ number_format($stat['current'], 2, ",", " ") }} %
@break
@default
{{ str_replace(".", ",", $stat['current']) }}
@endswitch
</td>
<td @if ($stat['diff'] < 0) class="text-success table-success" @else class="text-danger table-danger" @endif>
@switch($k)
@case(App\Enums\StatsShopType::canceledRate()->value)
<b>{{ number_format($stat['diff'], 2, ",", " ") }} %</b>
@break
@default
<b>{{ str_replace(".", ",", $stat['diff']) }}</b>
@endswitch
</td>
@else
<th @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>{{ App\Enums\StatsShopType::make($k)->label }}</th>
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
@switch($k)
@case(App\Enums\StatsShopType::caHt()->value)
@case(App\Enums\StatsShopType::caTtc()->value)
@case(App\Enums\StatsShopType::averageBasketHt()->value)
{{ number_format($stat['previous'], 2, ",", " ") }} €
@break
@case(App\Enums\StatsShopType::orderFrequency()->value)
{{ number_format($stat['previous'], 2, ",", " ") }} {{ __('jours') }}
@break
@default
{{ str_replace(".", ",", $stat['previous']) }}
@endswitch
</td>
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
@switch($k)
@case(App\Enums\StatsShopType::caHt()->value)
@case(App\Enums\StatsShopType::caTtc()->value)
@case(App\Enums\StatsShopType::averageBasketHt()->value)
{{ number_format($stat['current'], 2, ",", " ") }} €
@break
@case(App\Enums\StatsShopType::orderFrequency()->value)
{{ number_format($stat['current'], 2, ",", " ") }} {{ __('jours') }}
@break
@default
{{ str_replace(".", ",", $stat['current']) }}
@endswitch
</td>
<td @if ($stat['diff'] > 0) class="text-success table-success" @else class="text-danger table-danger" @endif>
@switch($k)
@case(App\Enums\StatsShopType::caHt()->value)
@case(App\Enums\StatsShopType::caTtc()->value)
@case(App\Enums\StatsShopType::averageBasketHt()->value)
<b>{{ number_format($stat['diff'], 2, ",", " ") }} €</b>
@break
@case(App\Enums\StatsShopType::orderFrequency()->value)
<b>{{ number_format($stat['diff'], 2, ",", " ") }} {{ __('jours') }}</b>
@break
@default
<b>{{ str_replace(".", ",", $stat['diff']) }}</b>
@endswitch
</td>
@endif
</tr>
@endforeach
</tbody>
</table>
@else
<p>{{ __('Veuillez renseigner une période afin de visualiser les statistiques') }}</p>
@endif
</div>
@endsection

View file

@ -5,11 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ __('Tableau de bord') }}</title>
<script src="https://cdn.ckeditor.com/ckeditor5/23.0.0/classic/ckeditor.js"></script>
<link rel="stylesheet" href="/b-o/css/app.css">
</head>
<body>
@ -25,14 +22,16 @@
</li>
</ul>
</nav>
<div class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div class="position-sticky pt-3">
<ul class="nav flex-column mb-2">
<li class="nav-item">
<a class="nav-link" href="{{route('home')}}" target="_front">{{ __('Voir le site') }}</a>
<a class="nav-link" href="{{ route('home') }}" target="_front">{{ __('Voir le site') }}</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('bo.dashboard') }}">{{ __('Dashboard') }}</a>
</li>
</ul>
<div class="accordion" id="accordionMenu">
@ -76,7 +75,6 @@
<i class="fas fa-warehouse"></i>&nbsp;{{ __('Catalogue') }}
</button>
</h2>
<div id="collapseProduits" class="accordion-collapse collapse {{ ( request()->routeIs('bo.products*') || request()->routeIs('bo.ranges*') || request()->routeIs('bo.tags*') ) ? 'show' : '' }}" aria-labelledby="headingProduits" data-bs-parent="#accordionMenu">
<div class="accordion-body">
<ul class="nav flex-column mb-2">
@ -95,7 +93,6 @@
<i class="fas fa-cart-arrow-down"></i>&nbsp;{{ __('Merchandising') }}
</button>
</h2>
<div id="collapseMerchandising" class="accordion-collapse collapse {{ ( request()->routeIs('bo.promotions*') || request()->routeIs('bo.products.starred') ) ? 'show' : '' }}" aria-labelledby="headingMerchandising" data-bs-parent="#accordionMenu">
<div class="accordion-body">
<ul class="nav flex-column mb-2">
@ -114,7 +111,6 @@
<i class="fas fa-cash-register"></i>&nbsp;{{ __('Commandes') }}
</button>
</h2>
<div id="collapseOrders" class="accordion-collapse collapse {{ ( request()->routeIs('bo.orders*') ) ? 'show' : '' }}" aria-labelledby="headingOrders" data-bs-parent="#accordionMenu">
<div class="accordion-body">
<ul class="nav flex-column mb-2">
@ -149,7 +145,6 @@
<i class="fas fa-cog"></i>&nbsp;Règlages
</button>
</h2>
<div id="collapseSettings" class="accordion-collapse collapse {{ ( request()->routeIs('bo.settings*') ) ? 'show' : '' }}" aria-labelledby="headingSettings" data-bs-parent="#accordionMenu">
<div class="accordion-body">
<ul class="nav flex-column mb-2">
@ -167,7 +162,6 @@
</div>
</div>
</nav>
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
@yield('content')
</main>