feature(external link redirection count of deal):
add a controller which increments the count for the click of external link of a deal.
This commit is contained in:
parent
688fd02e26
commit
af6d629b68
@ -18,7 +18,7 @@ class InteractionController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function togglesState(Deal $deal, InteractionType $type)
|
public function togglesState(Deal $deal, InteractionType $type)
|
||||||
{
|
{
|
||||||
if (! in_array($type, [InteractionType::Like, InteractionType::Favorite])) {
|
if (!in_array($type, [InteractionType::Like, InteractionType::Favorite])) {
|
||||||
return response()->json(['error' => 'This interaction is not supported'], 400);
|
return response()->json(['error' => 'This interaction is not supported'], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ public function togglesState(Deal $deal, InteractionType $type)
|
|||||||
Log::error('Error when liked a deal',
|
Log::error('Error when liked a deal',
|
||||||
[
|
[
|
||||||
'deal_id' => $deal->id,
|
'deal_id' => $deal->id,
|
||||||
'use_id' => Auth::id(),
|
'user_id' => Auth::id(),
|
||||||
'type' => $type,
|
'type' => $type,
|
||||||
'error' => $e->getMessage(),
|
'error' => $e->getMessage(),
|
||||||
'trace' => $e->getTraceAsString(),
|
'trace' => $e->getTraceAsString(),
|
||||||
@ -63,4 +63,37 @@ public function togglesState(Deal $deal, InteractionType $type)
|
|||||||
return response()->json(['error' => 'Something went wrong.'], 500);
|
return response()->json(['error' => 'Something went wrong.'], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function redirect(Deal $deal)
|
||||||
|
{
|
||||||
|
if (blank($deal->link)) {
|
||||||
|
abort(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
\Illuminate\Support\defer(function () use ($deal) {
|
||||||
|
try {
|
||||||
|
$interaction = $deal->interactions()->firstOrCreate([
|
||||||
|
'type' => InteractionType::Redirection,
|
||||||
|
'user_id' => Auth::id(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!$interaction->wasRecentlyCreated) {
|
||||||
|
$interaction->increment('count');
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Error when redirecting a deal external link',
|
||||||
|
[
|
||||||
|
'deal_id' => $deal->id,
|
||||||
|
'user_id' => Auth::id(),
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString(),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
abort(500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->away($deal->link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
28
app/Http/Requests/DealOutboundRequest.php
Normal file
28
app/Http/Requests/DealOutboundRequest.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class DealOutboundRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,6 +8,11 @@
|
|||||||
|
|
||||||
class Interaction extends Model
|
class Interaction extends Model
|
||||||
{
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'type',
|
||||||
|
'user_id',
|
||||||
|
];
|
||||||
|
|
||||||
public function user(): BelongsTo
|
public function user(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Deal::class);
|
return $this->belongsTo(Deal::class);
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
@props(['id' => '', 'image' => '', 'title' => '', 'category' => '', 'impressions' => 0, 'likes' => 0, 'clicks' => 0, 'status' => false, 'external_link' => ''])
|
@props(['deal'])
|
||||||
|
|
||||||
<x-ui.image-card :image="$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">
|
||||||
|
|
||||||
<div class="flex items-start space-x-1 mr-2">
|
<div class="flex items-start space-x-1 mr-2">
|
||||||
<p class="font-bold text-lg ">{{$title}}</p>
|
<p class="font-bold text-lg ">{{$deal->title}}</p>
|
||||||
|
|
||||||
@if($external_link !== '')
|
@if(filled($deal->link))
|
||||||
<a href="{{$external_link}}" target="_blank" title="{{$external_link}}"
|
<a href="{{\Illuminate\Support\Facades\URL::signedRoute('redirect', $deal->id)}}" target="_blank" title="{{$deal->link}}"
|
||||||
class="text-xs underline text-accent-601 mt-1">
|
class="text-xs underline text-accent-601 mt-1">
|
||||||
<x-heroicon-o-arrow-top-right-on-square class="w-4 stroke-2 "/>
|
<x-heroicon-o-arrow-top-right-on-square class="w-4 stroke-2 "/>
|
||||||
</a>
|
</a>
|
||||||
@ -16,7 +16,7 @@ class="text-xs underline text-accent-601 mt-1">
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if($status == 1)
|
@if($deal->active == 1)
|
||||||
<x-ui.badge title="Active"/>
|
<x-ui.badge title="Active"/>
|
||||||
@else
|
@else
|
||||||
<x-ui.badge title="Pending" variant="ghost"/>
|
<x-ui.badge title="Pending" variant="ghost"/>
|
||||||
@ -25,15 +25,15 @@ class="text-xs underline text-accent-601 mt-1">
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col space-y-4">
|
<div class="flex flex-col space-y-4">
|
||||||
<p class="text-accent-600">{{$category}}</p>
|
<p class="text-accent-600">{{$deal->category->name}}</p>
|
||||||
|
|
||||||
<x-dashboard.broker.listing-stats :impression="$impressions" :likes="$likes" :clicks="$clicks"/>
|
<x-dashboard.broker.listing-stats impression="0" likes="0" clicks="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', $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"
|
||||||
icon="pencil-square">Edit
|
icon="pencil-square">Edit
|
||||||
</x-ui.button>
|
</x-ui.button>
|
||||||
<form class="w-full" onsubmit="return confirm('Are you sure to delete this ?')" method="post" action="{{route('broker.deals.destroy', $id)}}">
|
<form class="w-full" onsubmit="return confirm('Are you sure to delete this ?')" method="post" action="{{route('broker.deals.destroy', $deal->id)}}">
|
||||||
@csrf
|
@csrf
|
||||||
@method("DELETE")
|
@method("DELETE")
|
||||||
<x-ui.button variant="red" class="w-full" icon="trash" >Delete</x-ui.button>
|
<x-ui.button variant="red" class="w-full" icon="trash" >Delete</x-ui.button>
|
||||||
|
|||||||
@ -4,17 +4,7 @@
|
|||||||
<p class="font-bold mb-6">My Listings</p>
|
<p class="font-bold mb-6">My Listings</p>
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||||
@forelse($deals as $deal)
|
@forelse($deals as $deal)
|
||||||
<x-dashboard.broker.listing-card
|
<x-dashboard.broker.listing-card :deal="$deal" />
|
||||||
:id="$deal->id"
|
|
||||||
:image="asset('storage/'.$deal->image)"
|
|
||||||
:title="$deal->title"
|
|
||||||
:category="$deal->category->name"
|
|
||||||
:status="$deal->active"
|
|
||||||
impressions="1245"
|
|
||||||
likes="89"
|
|
||||||
class="156"
|
|
||||||
:external_link="$deal->link"
|
|
||||||
/>
|
|
||||||
@empty
|
@empty
|
||||||
<p class="text-center text-xs text-accent-600 lg:col-span-3">No Deals created</p>
|
<p class="text-center text-xs text-accent-600 lg:col-span-3">No Deals created</p>
|
||||||
@endforelse
|
@endforelse
|
||||||
|
|||||||
@ -1,5 +1,15 @@
|
|||||||
@props(['deal_id', 'deal_title', 'like' => false, 'favourite' => false])
|
@props(['deal_id', 'deal_title', 'like' => false, 'favourite' => false, 'deal_link' => ''])
|
||||||
<div class="">
|
<div class="">
|
||||||
|
@if(filled($deal_link))
|
||||||
|
<x-ui.button-sm @class(["text-accent-600"]) external="true" :link="\Illuminate\Support\Facades\URL::signedRoute('redirect', $deal_id)">
|
||||||
|
<x-heroicon-o-arrow-top-right-on-square
|
||||||
|
@class([
|
||||||
|
"w-4",
|
||||||
|
])
|
||||||
|
/>
|
||||||
|
</x-ui.button-sm>
|
||||||
|
@endif
|
||||||
|
|
||||||
<x-ui.button-sm @class(["text-accent-600", 'liked' => $like]) onclick="like(this, {{$deal_id}})">
|
<x-ui.button-sm @class(["text-accent-600", 'liked' => $like]) onclick="like(this, {{$deal_id}})">
|
||||||
<x-heroicon-o-heart
|
<x-heroicon-o-heart
|
||||||
@class([
|
@class([
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
{{$deal->category->name}}
|
{{$deal->category->name}}
|
||||||
</x-ui.button-sm>
|
</x-ui.button-sm>
|
||||||
@ds($deal)
|
@ds($deal)
|
||||||
<x-dashboard.user.action-toolbar :deal_title="$deal->title" :deal_id="$deal->id" :like="$deal->is_liked" :favourite="$deal->is_favorite" />
|
<x-dashboard.user.action-toolbar :deal_link="$deal->link" :deal_title="$deal->title" :deal_id="$deal->id" :like="$deal->is_liked" :favourite="$deal->is_favorite" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="font-bold text-lg ">{{$deal->title}}</p>
|
<p class="font-bold text-lg ">{{$deal->title}}</p>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
@props(['variant' => '', 'link' => ''])
|
@props(['variant' => '', 'link' => '', 'external' => false])
|
||||||
@php
|
@php
|
||||||
$variants = [
|
$variants = [
|
||||||
'neutral' => 'bg-primary-600 text-white',
|
'neutral' => 'bg-primary-600 text-white',
|
||||||
@ -8,7 +8,7 @@
|
|||||||
$variantClass = $variants[$variant] ?? '';
|
$variantClass = $variants[$variant] ?? '';
|
||||||
@endphp
|
@endphp
|
||||||
@if($link !== '')
|
@if($link !== '')
|
||||||
<a href="{{$link}}" {{$attributes->merge(['class' => "px-2 py-1 text-xs rounded-md font-medium hover:opacity-80 hover: active:scale-80 transition-all duration-300 ease-in-out $variantClass"])}}>
|
<a href="{{$link}}" @if($external) target="_blank" @endif {{$attributes->merge(['class' => "inline-flex px-2 py-1 text-xs rounded-md font-medium hover:opacity-80 hover: active:scale-80 transition-all duration-300 ease-in-out $variantClass"])}}>
|
||||||
{{$slot}}
|
{{$slot}}
|
||||||
</a>
|
</a>
|
||||||
@else
|
@else
|
||||||
|
|||||||
@ -17,5 +17,11 @@
|
|||||||
->middleware('throttle:30,1')
|
->middleware('throttle:30,1')
|
||||||
->name('favorite');
|
->name('favorite');
|
||||||
|
|
||||||
Route::post('/report/{deal}', [ReportController::class, 'store'])->name('report.store');
|
Route::post('/report/{deal}', [ReportController::class, 'store'])
|
||||||
|
->middleware('throttle:5,1')
|
||||||
|
->name('report.store');
|
||||||
|
|
||||||
|
Route::get('/redirect/{deal}', [InteractionController::class, 'redirect'])
|
||||||
|
->middleware(['throttle:10,1', 'signed'])
|
||||||
|
->name('redirect');
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user