Update Lihat Jumlah Kunjungan

This commit is contained in:
2026-11-06 14:21:26 +07:00
parent 9cdd178297
commit f78b74519a
6 changed files with 136 additions and 0 deletions
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Web\Konfigurasi;
use App\Http\Controllers\Controller;
use App\Http\Requests\Konfigurasi\FilterLogAktivitasRequest;
use App\Models\Konfigurasi\KunjunganPengguna;
use App\Models\Konfigurasi\LogAktivitas;
use App\Models\Pertanian\Petani;
use App\Models\User;
@@ -64,6 +65,7 @@ class LogAktivitasController extends Controller
'jenis' => self::JENIS,
'perPage' => self::PER_PAGE,
'namaPetani' => $namaPetani,
'kunjungan' => KunjunganPengguna::ringkasan(),
]);
}
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace App\Http\Middleware;
use App\Models\Konfigurasi\KunjunganPengguna;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpFoundation\Response;
class CatatKunjungan
{
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
$user = $request->user() ?? $request->user('sanctum');
if (! $user) {
return $response;
}
$tanda = today()->toDateString() . ':' . $user->id;
// Web: tanda di session, tanpa query tambahan
if ($request->hasSession()) {
if ($request->session()->get('kunjungan_tercatat') !== $tanda) {
KunjunganPengguna::catat($user->id);
$request->session()->put('kunjungan_tercatat', $tanda);
}
return $response;
}
// API: tanda di cache sampai akhir hari
if (Cache::add("kunjungan:{$tanda}", true, now()->endOfDay())) {
KunjunganPengguna::catat($user->id);
}
return $response;
}
}
@@ -0,0 +1,49 @@
<?php
namespace App\Models\Konfigurasi;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class KunjunganPengguna extends Model
{
public const UPDATED_AT = null;
protected $table = 'kunjungan_pengguna';
protected $fillable = ['tanggal', 'user_id'];
protected function casts(): array
{
return ['tanggal' => 'date'];
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
// Catat kunjungan (abaikan jika hari ini sudah tercatat)
public static function catat(int $userId): void
{
static::query()->insertOrIgnore([
'tanggal' => today()->toDateString(),
'user_id' => $userId,
'created_at' => now(),
]);
}
// Ringkasan pengunjung hari ini, bulan ini, dan total (satu query)
public static function ringkasan(): object
{
return static::query()
->selectRaw('count(*) filter (where tanggal = ?) as hari_ini', [today()->toDateString()])
->selectRaw('count(distinct user_id) filter (where tanggal >= ?) as bulan_ini', [today()->startOfMonth()->toDateString()])
->selectRaw('count(*) filter (where tanggal >= ?) as kunjungan_bulan_ini', [today()->startOfMonth()->toDateString()])
->selectRaw('count(*) as total_kunjungan')
->selectRaw('count(distinct user_id) as total_pengguna')
->toBase()
->first();
}
}
+2
View File
@@ -16,6 +16,8 @@ return Application::configure(basePath: dirname(__DIR__))
->withMiddleware(function (Middleware $middleware): void {
$middleware->append(\App\Http\Middleware\ResolveProgram::class);
$middleware->append(\App\Http\Middleware\SimpanLogAktivitas::class);
$middleware->web(append: [\App\Http\Middleware\CatatKunjungan::class]);
$middleware->api(append: [\App\Http\Middleware\CatatKunjungan::class]);
$middleware->alias([
'akses.petani' => \App\Http\Middleware\BatasiAksesPetani::class,
@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
// Satu baris = satu pengguna yang membuka aplikasi pada satu hari
Schema::create('kunjungan_pengguna', function (Blueprint $table) {
$table->id();
$table->date('tanggal');
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
$table->timestamp('created_at')->nullable();
$table->unique(['tanggal', 'user_id']);
});
}
public function down(): void
{
Schema::dropIfExists('kunjungan_pengguna');
}
};
@@ -5,6 +5,22 @@
@section('content')
<div class="container-xxl flex-grow-1 container-p-y">
{{-- Ringkasan pengunjung --}}
<div class="row g-4 mb-4">
<div class="col-sm-6 col-xl-4">
<x-summary-card title="Pengunjung Hari Ini" :count="number_format($kunjungan->hari_ini)"
subtitle="Pengguna yang membuka aplikasi hari ini" icon="user-check" color="success" />
</div>
<div class="col-sm-6 col-xl-4">
<x-summary-card title="Pengunjung Bulan Ini" :count="number_format($kunjungan->bulan_ini)"
:subtitle="number_format($kunjungan->kunjungan_bulan_ini) . ' kunjungan harian bulan ini'" icon="calendar-stats" color="primary" />
</div>
<div class="col-sm-6 col-xl-4">
<x-summary-card title="Total Pengunjung" :count="number_format($kunjungan->total_kunjungan)"
:subtitle="number_format($kunjungan->total_pengguna) . ' pengguna berbeda sejak dicatat'" icon="users" color="info" />
</div>
</div>
<div class="card">
<div class="card-header border-bottom">
<h5 class="card-title mb-1">Log Aktivitas</h5>