Merge branch 'feature/broker-dashboard'
# Conflicts: # app/Models/User.php
This commit is contained in:
commit
45196cba56
22
app/Actions/GetBrokerStatsAction.php
Normal file
22
app/Actions/GetBrokerStatsAction.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions;
|
||||||
|
|
||||||
|
use App\Enums\InteractionType;
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
final readonly class GetBrokerStatsAction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, int>
|
||||||
|
*/
|
||||||
|
public function execute(User $user): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'listings' => $user->deals()->count(),
|
||||||
|
'likes' => $user->dealsInteractions()->where('type', InteractionType::Like)->count(),
|
||||||
|
'views' => $user->dealsInteractions()->where('type', InteractionType::View)->sum('count'),
|
||||||
|
'clicks' => $user->dealsInteractions()->where('type', InteractionType::Redirection)->sum('count'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,15 +2,17 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Broker;
|
namespace App\Http\Controllers\Broker;
|
||||||
|
|
||||||
|
use App\Actions\GetBrokerStatsAction;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class BrokerDashboardController extends Controller
|
class BrokerDashboardController extends Controller
|
||||||
{
|
{
|
||||||
public function index()
|
public function index(GetBrokerStatsAction $getBrokerStatsAction)
|
||||||
{
|
{
|
||||||
return view('dashboards.broker.index')
|
return view('dashboards.broker.index')
|
||||||
->with('deals', $this->deals());
|
->with('deals', $this->deals())
|
||||||
|
->with('stats', $getBrokerStatsAction->execute(Auth::user()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function deals()
|
protected function deals()
|
||||||
@ -28,6 +30,9 @@ protected function deals()
|
|||||||
'deal_category_id',
|
'deal_category_id',
|
||||||
])
|
])
|
||||||
->with('category:id,name')
|
->with('category:id,name')
|
||||||
|
->WithLikePerDeal()
|
||||||
|
->WithRedirectionPerDeal()
|
||||||
|
->withViewPerDeal()
|
||||||
->latest()
|
->latest()
|
||||||
->paginate();
|
->paginate();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,6 +86,19 @@ public function WithRedirectionPerDeal(Builder $query): Builder
|
|||||||
], 'count');
|
], 'count');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope a query to get a view count per deal
|
||||||
|
*/
|
||||||
|
#[Scope]
|
||||||
|
public function withViewPerDeal(Builder $query): Builder
|
||||||
|
{
|
||||||
|
return $query->withSum([
|
||||||
|
'interactions as total_views' => function ($query) {
|
||||||
|
$query->where('type', InteractionType::View);
|
||||||
|
},
|
||||||
|
], 'count');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scope a search in a query
|
* Scope a search in a query
|
||||||
*/
|
*/
|
||||||
@ -105,4 +118,5 @@ public function filterByCategory(Builder $query, string $category): Builder
|
|||||||
{
|
{
|
||||||
return $query->where('deal_category_id', $category);
|
return $query->where('deal_category_id', $category);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
@ -82,4 +84,9 @@ public function isCustomer(): bool
|
|||||||
{
|
{
|
||||||
return $this->type instanceof Customer;
|
return $this->type instanceof Customer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function dealsInteractions(): HasManyThrough
|
||||||
|
{
|
||||||
|
return $this->hasManyThrough(Interaction::class, Deal::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
@props(['deal'])
|
@props(['deal'])
|
||||||
|
|
||||||
<x-ui.image-card :image="asset('storage/'.$deal->image)">
|
<x-ui.image-card :image="asset('storage/'.$deal->image)">
|
||||||
<div class="bg-white pt-8 p-4 h-full space-y-4 flex flex-col justify-between">
|
<div class="bg-white pt-8 p-4 h-full space-y-4 flex flex-col justify-between">
|
||||||
<div class="flex justify-between items-start">
|
<div class="flex justify-between items-start">
|
||||||
@ -27,7 +26,7 @@ class="text-xs underline text-accent-601 mt-1">
|
|||||||
<div class="flex flex-col space-y-4">
|
<div class="flex flex-col space-y-4">
|
||||||
<p class="text-accent-600">{{$deal->category->name}}</p>
|
<p class="text-accent-600">{{$deal->category->name}}</p>
|
||||||
|
|
||||||
<x-dashboard.broker.listing-stats impression="0" likes="0" clicks="0"/>
|
<x-dashboard.broker.listing-stats :views="$deal->total_views ?? 0" :likes="$deal->total_likes ?? 0" :clicks="$deal->total_redirection ?? 0"/>
|
||||||
|
|
||||||
<div class="flex justify-between space-x-4">
|
<div class="flex justify-between space-x-4">
|
||||||
<x-ui.button :link="route('broker.deals.edit', $deal->id)" class="w-full border border-accent-600/30"
|
<x-ui.button :link="route('broker.deals.edit', $deal->id)" class="w-full border border-accent-600/30"
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
@props(['impression' => 0, 'likes' => 0, 'clicks' => 0])
|
@props(['views' => 0, 'likes' => 0, 'clicks' => 0])
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div class=" text-accent-600 flex space-x-2">
|
<div class=" text-accent-600 flex space-x-2">
|
||||||
<x-heroicon-o-eye class="w-4"/>
|
<x-heroicon-o-eye class="w-4"/>
|
||||||
<p class="text-sm">{{$impression}}</p>
|
<p class="text-sm">{{$views}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class=" text-accent-600 flex space-x-2">
|
<div class=" text-accent-600 flex space-x-2">
|
||||||
|
|||||||
@ -1,22 +1,22 @@
|
|||||||
@props(['list_count' => 0])
|
@props(['stats' => []])
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 wrapper gap-y-4 gap-x-8">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 wrapper gap-y-4 gap-x-8">
|
||||||
<x-dashboard.stats-card title="My Listings" :score="$list_count">
|
<x-dashboard.stats-card title="My Listings" :score="$stats['listings']">
|
||||||
<x-icon-square variant="blue">
|
<x-icon-square variant="blue">
|
||||||
<x-heroicon-o-document-text class="w-8" />
|
<x-heroicon-o-document-text class="w-8" />
|
||||||
</x-icon-square>
|
</x-icon-square>
|
||||||
</x-dashboard.stats-card>
|
</x-dashboard.stats-card>
|
||||||
|
|
||||||
<x-dashboard.stats-card title="Total Views" score="12,483">
|
<x-dashboard.stats-card title="Total Views" :score="$stats['views'] ?? 0">
|
||||||
<x-icon-square variant="purple">
|
<x-icon-square variant="purple">
|
||||||
<x-heroicon-o-eye class="w-8" />
|
<x-heroicon-o-eye class="w-8" />
|
||||||
</x-icon-square>
|
</x-icon-square>
|
||||||
</x-dashboard.stats-card>
|
</x-dashboard.stats-card>
|
||||||
<x-dashboard.stats-card title="Total Likes" score="1,847">
|
<x-dashboard.stats-card title="Total Likes" :score="$stats['likes'] ?? 0">
|
||||||
<x-icon-square variant="pink">
|
<x-icon-square variant="pink">
|
||||||
<x-heroicon-o-heart class="w-8" />
|
<x-heroicon-o-heart class="w-8" />
|
||||||
</x-icon-square>
|
</x-icon-square>
|
||||||
</x-dashboard.stats-card>
|
</x-dashboard.stats-card>
|
||||||
<x-dashboard.stats-card title="Total Clicks" score="3,246">
|
<x-dashboard.stats-card title="Total Clicks" :score="$stats['clicks'] ?? 0">
|
||||||
<x-icon-square variant="green">
|
<x-icon-square variant="green">
|
||||||
<x-heroicon-o-cursor-arrow-rays class="w-8" />
|
<x-heroicon-o-cursor-arrow-rays class="w-8" />
|
||||||
</x-icon-square>
|
</x-icon-square>
|
||||||
|
|||||||
@ -2,6 +2,6 @@
|
|||||||
<x-slot:heading>
|
<x-slot:heading>
|
||||||
<x-dashboard.broker.navbar/>
|
<x-dashboard.broker.navbar/>
|
||||||
</x-slot:heading>
|
</x-slot:heading>
|
||||||
<x-dashboard.broker.stats :list_count="$deals->count()"/>
|
<x-dashboard.broker.stats :stats="$stats"/>
|
||||||
<x-dashboard.broker.listing :deals="$deals"/>
|
<x-dashboard.broker.listing :deals="$deals"/>
|
||||||
</x-dashboard.broker.layout>
|
</x-dashboard.broker.layout>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user