feature(deal-modal): count view interaction

This commit is contained in:
kusowl 2026-01-22 14:55:09 +05:30
parent 9e61dd9f51
commit 3cd2644582
9 changed files with 95 additions and 21 deletions

View File

@ -11,4 +11,5 @@ enum InteractionType: string
case Like = 'like'; case Like = 'like';
case Favorite = 'favorite'; case Favorite = 'favorite';
case Redirection = 'redirect'; case Redirection = 'redirect';
case View = 'view';
} }

View File

@ -96,4 +96,36 @@ public function redirect(Deal $deal)
return redirect()->away($deal->link); return redirect()->away($deal->link);
} }
public function view(Deal $deal)
{
ds('hi');
try {
$interaction = $deal->interactions()->firstOrCreate([
'type' => InteractionType::View,
'user_id' => Auth::id(),
]);
if (! $interaction->wasRecentlyCreated) {
$interaction->increment('count');
}
ds($interaction);
} catch (\Throwable $e) {
Log::error('Error when view a deal',
[
'deal_id' => $deal->id,
'user_id' => Auth::id(),
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]
);
return response()->json(['error' => 'Something went wrong.'], 500);
}
return response()->json([
'message' => 'View counted',
]);
}
} }

View File

@ -0,0 +1,27 @@
<?php
use App\Enums\InteractionType;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('interactions', function (Blueprint $table) {
$table->enum('type', InteractionType::values())->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('interactions', function (Blueprint $table) {});
}
};

View File

@ -2,7 +2,7 @@ import {showToast} from "@/toast.js";
import {closeModal, showModal} from "@/modal.js"; import {closeModal, showModal} from "@/modal.js";
import {redirect} from "./interaction.js"; import {redirect} from "./interaction.js";
async function showDealModal(dealId, dealTitle) { async function showDealModal(dealId) {
if (dealId === null || dealId === "") { if (dealId === null || dealId === "") {
showToast('Something went wrong!'); showToast('Something went wrong!');
return; return;
@ -20,6 +20,8 @@ async function showDealModal(dealId, dealTitle) {
// Add the id so that action buttons can identify the route // Add the id so that action buttons can identify the route
dealModal.dataset.dealId = dealId; dealModal.dataset.dealId = dealId;
// Increment the view count
await axios.post(`/api/view/${dealId}`);
} catch (e) { } catch (e) {
console.error(e) console.error(e)
closeModal('deal-modal') closeModal('deal-modal')

10
routes/api/api.php Normal file
View File

@ -0,0 +1,10 @@
<?php
use Illuminate\Support\Facades\Route;
Route::prefix('/api')
->middleware('auth')
->group(function () {
include __DIR__.'/interactions.php';
include __DIR__.'/deals.php';
});

View File

@ -1,19 +0,0 @@
<?php
use App\Http\Resources\DealResource;
use App\Models\Deal;
use App\Queries\ExplorePageDealsQuery;
use Illuminate\Support\Facades\Route;
Route::prefix('/api')
->middleware('auth')
->group(function () {
Route::get('/deals/{deal}', function (Deal $deal) {
return new DealResource(
(new ExplorePageDealsQuery)
->builder()
->where('id', $deal->id)
->first()
);
});
});

14
routes/api/deals.php Normal file
View File

@ -0,0 +1,14 @@
<?php
use App\Http\Resources\DealResource;
use App\Models\Deal;
use App\Queries\ExplorePageDealsQuery;
Route::get('/deals/{deal}', function (Deal $deal) {
return new DealResource(
(new ExplorePageDealsQuery)
->builder()
->where('id', $deal->id)
->first()
);
});

View File

@ -0,0 +1,7 @@
<?php
use App\Http\Controllers\InteractionController;
Route::post('/view/{deal}', [InteractionController::class, 'view'])
->middleware('throttle:30,1')
->name('view-deal');

View File

@ -25,4 +25,4 @@
* we do not want to use sanctum for web requests * we do not want to use sanctum for web requests
*/ */
// ------------- API Routes ------------ // ------------- API Routes ------------
require __DIR__.'/api/deal.php'; require __DIR__.'/api/api.php';