feat: visitor counter
This commit is contained in:
parent
7cd72f7f0f
commit
497deeef18
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Homepage;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AboutUsController extends Controller
|
||||
{
|
||||
public function index(){
|
||||
$data = [
|
||||
'title' => 'Tentang Kami',
|
||||
'page' => 'about_us'
|
||||
];
|
||||
|
||||
return view('homepage.about-us.index', $data);
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Homepage;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\News;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AnnouncementController extends Controller
|
||||
{
|
||||
public function index(Request $request){
|
||||
|
||||
$data = [
|
||||
'title' => 'Pengumuman',
|
||||
'page' => 'announcements',
|
||||
];
|
||||
|
||||
$search = $request->input('search', null);
|
||||
|
||||
if($search){
|
||||
$data['announcements'] = News::where('category', '1')->where('title', 'LIKE', "%{$search}%")
|
||||
// ->orWhere('content', 'LIKE', "%{$search}%")
|
||||
->latest()
|
||||
->simplePaginate(6);
|
||||
}else{
|
||||
$data['announcements'] = News::where('category', '1')->latest()->simplePaginate(6);
|
||||
}
|
||||
|
||||
return view('homepage.announcements.index', $data);
|
||||
}
|
||||
|
||||
public function read($slug){
|
||||
$announcement = News::where('slug', $slug)->first();
|
||||
$announcement->increment('views', 1);
|
||||
|
||||
$data = [
|
||||
'title' => 'Pengumuman',
|
||||
'page' => 'announcements',
|
||||
'announcement' => $announcement,
|
||||
'otherAnnouncements' => News::where('category', '1')->orderByDesc('id')->where('id', '!=', $announcement->id)->take(4)->get()
|
||||
];
|
||||
|
||||
return view('homepage.announcements.read', $data);
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Homepage;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ContactController extends Controller
|
||||
{
|
||||
public function index(){
|
||||
$data = [
|
||||
'title' => 'Kontak',
|
||||
'page' => 'contacts'
|
||||
];
|
||||
|
||||
return view('homepage.contacts.index', $data);
|
||||
}
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Homepage;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\News;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LandingPageController extends Controller
|
||||
{
|
||||
public function index(){
|
||||
|
||||
$data = [
|
||||
'title' => 'Beranda',
|
||||
'page' => 'landing',
|
||||
'news' => News::whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()])
|
||||
->where('category', '=', '0')
|
||||
->latest()
|
||||
->get(),
|
||||
'announcements' => News::whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()])
|
||||
->where('category', '=', '1')
|
||||
->latest()
|
||||
->get(),
|
||||
];
|
||||
|
||||
return view('homepage.index', $data);
|
||||
}
|
||||
|
||||
public function search(Request $request){
|
||||
|
||||
$request->validate([
|
||||
'search' => 'nullable|string|max:255|regex:/^[a-zA-Z0-9\s]+$/'
|
||||
], [
|
||||
'search.string' => 'Pencarian harus berupa teks.',
|
||||
'search.max' => 'Pencarian tidak boleh lebih dari 255 karakter.',
|
||||
'search.regex' => 'Pencarian hanya boleh mengandung huruf, angka, dan spasi.'
|
||||
]);
|
||||
|
||||
$search = trim($request->input('search'));
|
||||
|
||||
$data = [
|
||||
'title' => 'Pencarian',
|
||||
'page' => 'search',
|
||||
'data' => News::query()
|
||||
->when($search, function ($query, $search) {
|
||||
return $query->where('title', 'LIKE', '%' . $search . '%');
|
||||
})
|
||||
->latest()
|
||||
->simplePaginate(12)
|
||||
->appends(['search' => $search]),
|
||||
'search' => $search
|
||||
];
|
||||
|
||||
return view('homepage.search', $data);
|
||||
}
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Homepage;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\News;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class NewsController extends Controller
|
||||
{
|
||||
public function index(Request $request){
|
||||
|
||||
$data = [
|
||||
'title' => 'Berita',
|
||||
'page' => 'news',
|
||||
];
|
||||
|
||||
$search = $request->input('search', null);
|
||||
|
||||
if($search){
|
||||
$data['news'] = News::where('title', 'LIKE', "%{$search}%")
|
||||
// ->orWhere('content', 'LIKE', "%{$search}%")
|
||||
->where('category', '0')
|
||||
->latest()
|
||||
->simplePaginate(12);
|
||||
}else{
|
||||
$data['news'] = News::where('category', '0')->latest()->simplePaginate(12);
|
||||
}
|
||||
|
||||
return view('homepage.news.index', $data);
|
||||
}
|
||||
|
||||
public function read($slug){
|
||||
$news = News::where('slug', $slug)->first();
|
||||
$news->increment('views', 1);
|
||||
|
||||
$data = [
|
||||
'title' => 'Berita',
|
||||
'page' => 'news',
|
||||
'news' => $news,
|
||||
'popularNews' => News::where('category', '0')->orderBy('views', 'desc')->take(5)->get(),
|
||||
'otherNews' => News::where('category', '0')->orderByDesc('id')->where('id', '!=', $news->id)->take(3)->get()
|
||||
];
|
||||
|
||||
return view('homepage.news.read', $data);
|
||||
|
||||
}
|
||||
}
|
||||
189
app/Http/Controllers/HomepageController.php
Normal file
189
app/Http/Controllers/HomepageController.php
Normal file
@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\News;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class HomepageController extends Controller
|
||||
{
|
||||
protected $yesterdayVisitor;
|
||||
|
||||
protected $todayVisitor;
|
||||
|
||||
protected $thisMonthVisitor;
|
||||
|
||||
protected $thisYearVisitor;
|
||||
|
||||
protected $totalVisitor;
|
||||
|
||||
public function __construct(){
|
||||
$today = Carbon::today();
|
||||
$yesterday = Carbon::yesterday();
|
||||
$thisMonth = Carbon::now()->startOfMonth();
|
||||
$thisYear = Carbon::now()->startOfYear();
|
||||
|
||||
$this->yesterdayVisitor = DB::table('visitors')
|
||||
->whereDate('date', '=', $yesterday->toDateString())
|
||||
->value('visitors');
|
||||
|
||||
$this->todayVisitor = DB::table('visitors')
|
||||
->whereDate('date', '=', $today->toDateString())
|
||||
->value('visitors');
|
||||
|
||||
$this->thisMonthVisitor = DB::table('visitors')
|
||||
->whereBetween('date', [$thisMonth, Carbon::now()])
|
||||
->sum('visitors');
|
||||
|
||||
$this->thisYearVisitor = DB::table('visitors')
|
||||
->whereBetween('date', [$thisYear, Carbon::now()])
|
||||
->sum('visitors');
|
||||
|
||||
$this->totalVisitor = DB::table('visitors')->sum('visitors');
|
||||
|
||||
View::share('yesterdayVisitor', $this->yesterdayVisitor);
|
||||
View::share('todayVisitor', $this->todayVisitor);
|
||||
View::share('thisMonthVisitor', $this->thisMonthVisitor);
|
||||
View::share('thisYearVisitor', $this->thisYearVisitor);
|
||||
View::share('totalVisitor', $this->totalVisitor);
|
||||
}
|
||||
|
||||
public function landing(){
|
||||
$data = [
|
||||
'title' => 'Beranda',
|
||||
'page' => 'landing',
|
||||
'news' => News::whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()])
|
||||
->where('category', '=', '0')
|
||||
->latest()
|
||||
->get(),
|
||||
'announcements' => News::whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()])
|
||||
->where('category', '=', '1')
|
||||
->latest()
|
||||
->get(),
|
||||
];
|
||||
|
||||
return view('homepage.index', $data);
|
||||
}
|
||||
|
||||
public function search(Request $request){
|
||||
|
||||
$request->validate([
|
||||
'search' => 'nullable|string|max:255|regex:/^[a-zA-Z0-9\s]+$/'
|
||||
], [
|
||||
'search.string' => 'Pencarian harus berupa teks.',
|
||||
'search.max' => 'Pencarian tidak boleh lebih dari 255 karakter.',
|
||||
'search.regex' => 'Pencarian hanya boleh mengandung huruf, angka, dan spasi.'
|
||||
]);
|
||||
|
||||
$search = trim($request->input('search'));
|
||||
|
||||
$data = [
|
||||
'title' => 'Pencarian',
|
||||
'page' => 'search',
|
||||
'data' => News::query()
|
||||
->when($search, function ($query, $search) {
|
||||
return $query->where('title', 'LIKE', '%' . $search . '%');
|
||||
})
|
||||
->latest()
|
||||
->simplePaginate(12)
|
||||
->appends(['search' => $search]),
|
||||
'search' => $search
|
||||
];
|
||||
|
||||
return view('homepage.search', $data);
|
||||
}
|
||||
|
||||
public function news(Request $request){
|
||||
|
||||
$data = [
|
||||
'title' => 'Berita',
|
||||
'page' => 'news',
|
||||
];
|
||||
|
||||
$search = $request->input('search', null);
|
||||
|
||||
if($search){
|
||||
$data['news'] = News::where('title', 'LIKE', "%{$search}%")
|
||||
->where('category', '0')
|
||||
->latest()
|
||||
->simplePaginate(12);
|
||||
}else{
|
||||
$data['news'] = News::where('category', '0')->latest()->simplePaginate(12);
|
||||
}
|
||||
|
||||
return view('homepage.news.index', $data);
|
||||
}
|
||||
|
||||
public function readNews($slug){
|
||||
$news = News::where('slug', $slug)->first();
|
||||
$news->increment('views', 1);
|
||||
|
||||
$data = [
|
||||
'title' => 'Berita',
|
||||
'page' => 'news',
|
||||
'news' => $news,
|
||||
'popularNews' => News::where('category', '0')->orderBy('views', 'desc')->take(5)->get(),
|
||||
'otherNews' => News::where('category', '0')->orderByDesc('id')->where('id', '!=', $news->id)->take(3)->get()
|
||||
];
|
||||
|
||||
return view('homepage.news.read', $data);
|
||||
|
||||
}
|
||||
|
||||
public function announcement(Request $request){
|
||||
|
||||
$data = [
|
||||
'title' => 'Pengumuman',
|
||||
'page' => 'announcements',
|
||||
];
|
||||
|
||||
$search = $request->input('search', null);
|
||||
|
||||
if($search){
|
||||
$data['announcements'] = News::where('category', '1')->where('title', 'LIKE', "%{$search}%")
|
||||
// ->orWhere('content', 'LIKE', "%{$search}%")
|
||||
->latest()
|
||||
->simplePaginate(6);
|
||||
}else{
|
||||
$data['announcements'] = News::where('category', '1')->latest()->simplePaginate(6);
|
||||
}
|
||||
|
||||
return view('homepage.announcements.index', $data);
|
||||
}
|
||||
|
||||
public function readAnnouncement($slug){
|
||||
$announcement = News::where('slug', $slug)->first();
|
||||
$announcement->increment('views', 1);
|
||||
|
||||
$data = [
|
||||
'title' => 'Pengumuman',
|
||||
'page' => 'announcements',
|
||||
'announcement' => $announcement,
|
||||
'otherAnnouncements' => News::where('category', '1')->orderByDesc('id')->where('id', '!=', $announcement->id)->take(4)->get()
|
||||
];
|
||||
|
||||
return view('homepage.announcements.read', $data);
|
||||
|
||||
}
|
||||
|
||||
public function aboutUs(){
|
||||
$data = [
|
||||
'title' => 'Tentang Kami',
|
||||
'page' => 'about_us'
|
||||
];
|
||||
|
||||
return view('homepage.about-us.index', $data);
|
||||
}
|
||||
|
||||
public function contact(){
|
||||
$data = [
|
||||
'title' => 'Kontak',
|
||||
'page' => 'contacts'
|
||||
];
|
||||
|
||||
return view('homepage.contacts.index', $data);
|
||||
}
|
||||
}
|
||||
34
app/Http/Middleware/VisitorCounterMiddleware.php
Normal file
34
app/Http/Middleware/VisitorCounterMiddleware.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Models\Visitor;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class VisitorCounterMiddleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
$ipAddress = $request->ip();
|
||||
|
||||
if (! RateLimiter::tooManyAttempts('visitor:'.$ipAddress, 1)) {
|
||||
RateLimiter::hit('visitor:'.$ipAddress, 900);
|
||||
|
||||
$today = now()->format('Y-m-d');
|
||||
|
||||
$visitor = Visitor::firstOrCreate(['date' => $today]);
|
||||
$visitor->increment('visitors');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
16
app/Models/Visitor.php
Normal file
16
app/Models/Visitor.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Visitor extends Model
|
||||
{
|
||||
protected $table = 'visitors';
|
||||
|
||||
protected $fillable = [
|
||||
'date',
|
||||
'visitors'
|
||||
];
|
||||
|
||||
}
|
||||
@ -3,6 +3,7 @@
|
||||
use App\Http\Middleware\AnnouncementMiddleware;
|
||||
use App\Http\Middleware\AuthenticatedMiddleware;
|
||||
use App\Http\Middleware\RoleMiddleware;
|
||||
use App\Http\Middleware\VisitorCounterMiddleware;
|
||||
use Illuminate\Auth\Middleware\Authenticate;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Foundation\Configuration\Exceptions;
|
||||
@ -22,6 +23,7 @@
|
||||
'role' => RoleMiddleware::class,
|
||||
'authenticated' => AuthenticatedMiddleware::class,
|
||||
'announcement' => AnnouncementMiddleware::class,
|
||||
'visitor.count' => VisitorCounterMiddleware::class,
|
||||
]);
|
||||
})
|
||||
->withExceptions(function (Exceptions $exceptions) {
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
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::create('visitors', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->date('date');
|
||||
$table->integer('visitors')->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('visitors');
|
||||
}
|
||||
};
|
||||
17
database/seeders/VisitorSeeder.php
Normal file
17
database/seeders/VisitorSeeder.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class VisitorSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@ -23,9 +23,9 @@
|
||||
<div class="col-6 col-lg-3 col-sm-4 xs-mb-30px order-sm-3 order-lg-2">
|
||||
<span class="fs-17 fw-500 d-block text-white mb-5px">Statistik Pengunjung</span>
|
||||
<ul>
|
||||
<li>Hari ini: 100</li>
|
||||
<li>Bulan ini: 1000</li>
|
||||
<li>Total: 10000</li>
|
||||
<li>Hari ini: {{$todayVisitor}}</li>
|
||||
<li>Bulan ini: {{$thisMonthVisitor}}</li>
|
||||
<li>Total: {{$totalVisitor}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- end footer column -->
|
||||
|
||||
@ -25,33 +25,29 @@
|
||||
use App\Http\Controllers\Dashboard\SubClassificationController;
|
||||
use App\Http\Controllers\Dashboard\SubLocationController;
|
||||
use App\Http\Controllers\Dashboard\UserController;
|
||||
use App\Http\Controllers\Homepage\AboutUsController;
|
||||
use App\Http\Controllers\Homepage\ContactController;
|
||||
use App\Http\Controllers\Homepage\NewsController as HomepageNewsController;
|
||||
use App\Http\Controllers\Homepage\AnnouncementController as HomepageAnnouncementController;
|
||||
use App\Http\Controllers\Homepage\LandingPageController;
|
||||
use App\Http\Controllers\HomepageController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::name('homepage.')->group(function(){
|
||||
Route::get('/', [LandingPageController::class, 'index'])->name('landing');
|
||||
Route::get('/search', [LandingPageController::class, 'search'])->name('search');
|
||||
Route::name('homepage.')->controller(HomepageController::class)->middleware('visitor.count')->group(function(){
|
||||
Route::get('/', 'landing')->name('landing');
|
||||
Route::get('/search', 'search')->name('search');
|
||||
|
||||
Route::prefix('news')->name('news.')->controller(HomepageNewsController::class)->group(function(){
|
||||
Route::get('/', 'index')->name('index');
|
||||
Route::get('/{slug}', 'read')->name('read');
|
||||
Route::prefix('news')->name('news.')->group(function(){
|
||||
Route::get('/', 'news')->name('index');
|
||||
Route::get('/{slug}', 'readNews')->name('read');
|
||||
});
|
||||
|
||||
Route::prefix('announcements')->name('announcements.')->controller(HomepageAnnouncementController::class)->group(function(){
|
||||
Route::get('/', 'index')->name('index');
|
||||
Route::get('/{slug}', 'read')->name('read');
|
||||
Route::prefix('announcements')->name('announcements.')->group(function(){
|
||||
Route::get('/', 'announcement')->name('index');
|
||||
Route::get('/{slug}', 'readAnnouncement')->name('read');
|
||||
});
|
||||
|
||||
Route::prefix('about-us')->name('about.us.')->controller(AboutUsController::class)->group(function(){
|
||||
Route::get('/', 'index')->name('index');
|
||||
Route::prefix('about-us')->name('about.us.')->group(function(){
|
||||
Route::get('/', 'aboutUs')->name('index');
|
||||
});
|
||||
|
||||
Route::prefix('contacts')->name('contacts.')->controller(ContactController::class)->group(function(){
|
||||
Route::get('/', 'index')->name('index');
|
||||
Route::prefix('contacts')->name('contacts.')->group(function(){
|
||||
Route::get('/', 'contact')->name('index');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user