diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 0341f78f..e0b2d566 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -40,6 +40,13 @@ class LoginController extends Controller $this->middleware('guest')->except('logout'); } + protected function credentials(\Illuminate\Http\Request $request) + { + return array_merge($request->only($this->username(), 'password'), [ + 'status' => 'active', + ]); + } + public function username() { return 'username'; diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 937499f9..b300775e 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -155,7 +155,7 @@ class HomeController extends Controller } } - } else { //operasi,jurulelong + } else { //operasi $sag = LelongBid::where('status_semak', 0) //belum disemak ->get(); } @@ -608,7 +608,7 @@ class HomeController extends Controller } } - if ($user->hasAnyRole('operasi', 'pengurus-operasi', 'jurulelong')) { + if ($user->hasAnyRole('operasi', 'pengurus-operasi')) { $arrayinfo = []; diff --git a/app/Http/Controllers/LelongController.php b/app/Http/Controllers/LelongController.php index 9c38aaea..c83e0b69 100644 --- a/app/Http/Controllers/LelongController.php +++ b/app/Http/Controllers/LelongController.php @@ -1948,7 +1948,7 @@ class LelongController extends Controller public function stopcawangan($id,$cawid) { - event(new LelongNotify('start')); + event(new LelongNotify('stop')); $currentdate = Carbon::now(); $currenttime = $currentdate->toTimeString(); $endtime = $currentdate->addHours(2); @@ -1965,7 +1965,7 @@ class LelongController extends Controller $lelong->save(); return redirect()->route('home') - ->with('success','Lelongan bermula'); + ->with('success','Lelongan ditamatkan'); } public function startall($id) diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index 7ac1d92a..4227a5c5 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -843,6 +843,8 @@ class ReportController extends Controller $pdf = PDF::loadView('pdf.simulasireportbycust',compact('simulasilel','cawanganDetail','marhuns','simulasi_id','cawid','ktlhbyr','cawname')) ->setPaper('a4','potrait'); + + $pdf->setPaper('a4', 'landscape'); return $pdf->download('Laporan Simulasi Cawangan by Pelanggan.pdf'); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 6221e573..d532f0ae 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -37,6 +37,7 @@ class Kernel extends HttpKernel \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, + \App\Http\Middleware\EnsureActiveAccount::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], diff --git a/app/Http/Middleware/EnsureActiveAccount.php b/app/Http/Middleware/EnsureActiveAccount.php new file mode 100644 index 00000000..4d3efac4 --- /dev/null +++ b/app/Http/Middleware/EnsureActiveAccount.php @@ -0,0 +1,30 @@ +user(); + + if ($user && $user->status !== 'active') { + $guard->logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + + $message = 'Akaun anda tidak aktif. Sila hubungi pentadbir.'; + if ($request->expectsJson()) { + return response()->json(['message' => $message], 403); + } + + return redirect()->route('login')->withErrors(['username' => $message]); + } + + return $next($request); + } +} diff --git a/database/migrations/2026_09_27_000002_transfer_auction_controls_to_operasi.php b/database/migrations/2026_09_27_000002_transfer_auction_controls_to_operasi.php new file mode 100644 index 00000000..7ba18ebf --- /dev/null +++ b/database/migrations/2026_09_27_000002_transfer_auction_controls_to_operasi.php @@ -0,0 +1,35 @@ +transfer('jurulelong', 'operasi'); + } + + public function down() + { + $this->transfer('operasi', 'jurulelong'); + } + + private function transfer($from, $to) + { + DB::transaction(function () use ($from, $to) { + $source = Role::where('name', $from)->where('guard_name', 'web')->first(); + $target = Role::findOrCreate($to, 'web'); + foreach (['lelongan', 'janapemenang'] as $permission) { + $target->givePermissionTo($permission); + if ($source) { + $source->revokePermissionTo($permission); + } + } + }); + + app(PermissionRegistrar::class)->forgetCachedPermissions(); + } +} diff --git a/database/migrations/2026_09_28_000001_merge_jurulelong_role_into_operasi.php b/database/migrations/2026_09_28_000001_merge_jurulelong_role_into_operasi.php new file mode 100644 index 00000000..8d1f359b --- /dev/null +++ b/database/migrations/2026_09_28_000001_merge_jurulelong_role_into_operasi.php @@ -0,0 +1,84 @@ +backup)) { + Schema::create($this->backup, function (Blueprint $table) { + $table->unsignedBigInteger('id')->primary(); + $table->longText('payload'); + }); + } + + DB::transaction(function () { + $tables = config('permission.table_names'); + $key = config('permission.column_names.role_pivot_key') ?: 'role_id'; + foreach (DB::table($tables['roles'])->where('name', 'jurulelong')->get() as $role) { + $target = DB::table($tables['roles'])->where('name', 'operasi') + ->where('guard_name', $role->guard_name)->first(); + $snapshot = ['role' => (array) $role, 'renamed' => !$target, 'rows' => [], 'added' => []]; + + if (!$target) { + DB::table($tables['roles'])->where('id', $role->id)->update(['name' => 'operasi']); + } else { + foreach (['model_has_roles', 'role_has_permissions'] as $pivot) { + $snapshot['rows'][$pivot] = []; + $snapshot['added'][$pivot] = []; + foreach (DB::table($tables[$pivot])->where($key, $role->id)->get() as $row) { + $original = (array) $row; + $snapshot['rows'][$pivot][] = $original; + $replacement = $original; + $replacement[$key] = $target->id; + if (!DB::table($tables[$pivot])->where($replacement)->exists()) { + DB::table($tables[$pivot])->insert($replacement); + $snapshot['added'][$pivot][] = $replacement; + } + } + DB::table($tables[$pivot])->where($key, $role->id)->delete(); + } + DB::table($tables['roles'])->where('id', $role->id)->delete(); + } + + DB::table($this->backup)->insert([ + 'id' => $role->id, + 'payload' => json_encode($snapshot, JSON_THROW_ON_ERROR), + ]); + } + }); + app(PermissionRegistrar::class)->forgetCachedPermissions(); + } + + public function down() + { + DB::transaction(function () { + $tables = config('permission.table_names'); + foreach (DB::table($this->backup)->get() as $backup) { + $snapshot = json_decode($backup->payload, true, 512, JSON_THROW_ON_ERROR); + if ($snapshot['renamed']) { + DB::table($tables['roles'])->where('id', $backup->id)->update($snapshot['role']); + } else { + DB::table($tables['roles'])->insert($snapshot['role']); + foreach ($snapshot['rows'] as $pivot => $rows) { + foreach ($snapshot['added'][$pivot] as $row) { + DB::table($tables[$pivot])->where($row)->delete(); + } + foreach ($rows as $row) { + DB::table($tables[$pivot])->insert($row); + } + } + } + } + }); + Schema::dropIfExists($this->backup); + app(PermissionRegistrar::class)->forgetCachedPermissions(); + } +} diff --git a/database/seeders/RolesSeeder.php b/database/seeders/RolesSeeder.php index 96ff3dba..1ae5e22e 100644 --- a/database/seeders/RolesSeeder.php +++ b/database/seeders/RolesSeeder.php @@ -82,7 +82,7 @@ class RolesSeeder extends Seeder 'description' => 'Wang Tidak Dituntut Cawangan' ]); - //jurulelong + //operasi Permission::create([ 'name' => 'pendaftaranbatch', 'description' => 'Daftar batch lelong' @@ -238,14 +238,10 @@ class RolesSeeder extends Seeder $role4->givePermissionTo('pengurusangambar'); $role4->givePermissionTo('WTDcaw'); - $role5 = Role::create(['name' => 'jurulelong']); - $role5->givePermissionTo('pendaftaranbatch'); - $role5->givePermissionTo('kemaskinihargaasas'); - $role5->givePermissionTo('import'); - $role5->givePermissionTo('lelongan'); - $role5->givePermissionTo('janapemenang'); - $role6 = Role::create(['name' => 'operasi']); + $role6->givePermissionTo('import'); + $role6->givePermissionTo('lelongan'); + $role6->givePermissionTo('janapemenang'); $role6->givePermissionTo('pengguna'); $role6->givePermissionTo('pendaftaranbatch'); $role6->givePermissionTo('report'); @@ -342,14 +338,6 @@ class RolesSeeder extends Seeder ]); $user->assignRole($role4); - $user = \App\Models\User::factory()->create([ - 'name' => 'Juru Lelong', - 'username' => 'Juru Lelong', - 'email' => 'jurulelong@example.com', - 'user_type' => 1 - ]); - $user->assignRole($role5); - $user = \App\Models\User::factory()->create([ 'name' => 'Operasi', 'username' => 'Operasi', diff --git a/public/css/login.css b/public/css/login.css new file mode 100644 index 00000000..cc2d2428 --- /dev/null +++ b/public/css/login.css @@ -0,0 +1,49 @@ +* { box-sizing: border-box; } +:root { --teal: #008e95; --teal-dark: #00686e; --yellow: #ffce1b; --ink: #183b3e; } +body { margin: 0; min-height: 100vh; padding: 48px 28px; display: grid; place-items: center; background: #edf4f3; color: var(--ink); font-family: 'Segoe UI', Arial, sans-serif; } +.login-shell { width: min(1100px, 100%); min-height: 680px; display: grid; grid-template-columns: 1fr 1fr; overflow: hidden; border: 1px solid #dbe7e5; border-radius: 26px; background: white; box-shadow: 0 24px 70px #164f4d12; } +.brand-panel { position: relative; overflow: hidden; padding: 48px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; background: linear-gradient(145deg, #00969b, #007d84); color: white; } +.brand-logo { position: relative; z-index: 1; width: 250px; max-width: 100%; height: auto; } +.brand-copy { position: relative; z-index: 1; margin: 36px 0; } +.eyebrow { display: flex; align-items: center; justify-content: center; gap: 10px; font-size: 11px; font-weight: 700; letter-spacing: 2px; } +.eyebrow span { width: 7px; height: 7px; background: var(--yellow); border-radius: 50%; } +h1 { margin: 22px 0; font-size: clamp(34px, 3.5vw, 48px); line-height: 1.2; font-weight: 650; letter-spacing: -1.8px; } +h1 em { color: var(--yellow); font-style: normal; } +.brand-copy p { max-width: 340px; color: #e2f3f3; font-size: 15px; line-height: 1.85; } +.brand-divider { height: 3px; width: 42px; background: var(--yellow); margin: 30px auto 18px; } +.brand-caption { font-size: 12px; color: #e2f3f3; letter-spacing: .4px; } +.brand-bottom { display: flex; align-items: center; gap: 13px; justify-content: center; margin-top: 32px; position: relative; z-index: 1; font-size: 11px; line-height: 1.65; color: #e2f3f3; } +.brand-mark { width: 37px; height: 37px; display: grid; place-items: center; border: 1px solid #ffffff55; border-radius: 10px; color: var(--yellow); font-size: 17px; font-weight: 700; } +.brand-orbit { position: absolute; width: 420px; height: 420px; bottom: -235px; right: -200px; border: 1px solid #ffffff29; border-radius: 50%; box-shadow: 0 0 0 45px #ffffff06, 0 0 0 90px #ffffff05; } +.form-panel { padding: 70px 56px 28px; display: flex; flex-direction: column; justify-content: center; } +.form-content { width: 100%; margin: auto 0; } +.section-label { color: var(--teal-dark); font-size: 10px; font-weight: 700; letter-spacing: 2px; } +h2 { margin: 14px 0 10px; font-size: 36px; letter-spacing: -1.2px; font-weight: 650; } +.form-intro { margin: 0 0 34px; color: #64797a; font-size: 14px; line-height: 1.7; } +.field { margin-bottom: 22px; } +label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 9px; } +input { width: 100%; height: 52px; border: 1px solid #cfddda; border-radius: 9px; padding: 0 15px; background: #fcfdfd; font: inherit; font-size: 14px; color: var(--ink); } +input::placeholder { color: #7c8f90; } +input:focus { outline: 3px solid #008e9524; border-color: var(--teal); background: white; } +input[aria-invalid="true"] { border-color: #b73131; } +.password-field { position: relative; } +.password-field input { padding-right: 72px; } +button, a { -webkit-tap-highlight-color: transparent; } +.password-toggle { position: absolute; right: 8px; top: 6px; height: 40px; padding: 0 10px; border: 0; border-radius: 6px; color: var(--teal-dark); background: transparent; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600; } +.form-links { display: flex; justify-content: flex-end; margin: -6px 0 25px; } +a { color: var(--teal-dark); font-size: 13px; font-weight: 600; text-decoration: none; } +a:hover { text-decoration: underline; } +button:focus-visible, a:focus-visible { outline: 3px solid var(--teal); outline-offset: 4px; } +.submit-button { width: 100%; display: flex; align-items: center; justify-content: center; gap: 18px; min-height: 52px; border: 0; border-radius: 9px; background: var(--yellow); color: #233f3c; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; transition: background .15s; } +.submit-button:hover { background: #f3c112; } +.submit-button span { font-size: 22px; line-height: 1; } +.form-note { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 26px; color: #718483; font-size: 11px; } +.note-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--teal); } +footer { padding-top: 55px; text-align: center; color: #6a7f7d; font-size: 10px; line-height: 1.7; } +.notice { padding: 13px 15px; border-radius: 8px; margin-bottom: 20px; font-size: 13px; line-height: 1.5; } +.notice-success { background: #e5f5ed; color: #216348; } +.notice-error { background: #fff0ee; color: #a32626; } +.field-error { color: #a32626; font-size: 12px; margin: 8px 0 0; line-height: 1.5; } +@media (max-width: 800px) { body { padding: 24px; } .brand-panel { padding: 34px; } .form-panel { padding: 42px 30px 24px; } h1 { font-size: 36px; } } +@media (max-width: 600px) { body { padding: 18px 14px; } .login-shell { grid-template-columns: 1fr; min-height: auto; border-radius: 20px; } .brand-panel { padding: 28px; } .brand-logo { width: 210px; } .brand-copy { margin: 26px 0 0; } .eyebrow { font-size: 9px; } h1 { font-size: 32px; margin: 15px 0 10px; } .brand-copy p, .brand-divider, .brand-caption, .brand-bottom { display: none; } .form-panel { padding: 32px 26px 24px; } h2 { font-size: 30px; } .form-intro { margin-bottom: 25px; } footer { padding-top: 35px; } } +@media (prefers-reduced-motion: reduce) { * { transition: none !important; } } diff --git a/resources/views/about.blade.php b/resources/views/about.blade.php index ec699e64..f08ded54 100644 --- a/resources/views/about.blade.php +++ b/resources/views/about.blade.php @@ -27,8 +27,8 @@ @hasrole('pengurus-cawangan') I am a pengurus-cawangan! @endhasrole - @hasrole('jurulelong') - I am a jurulelong! + @hasrole('operasi') + I am an operasi user! @endhasrole @hasrole('operasi') I am a operasi! diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 3887dbcc..5b1604d5 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -1,104 +1,76 @@ - -
- - - -
- {{-- Sistem Lelongan Atas Talian
-|
- @hasrole('jurulelong')
+ @hasrole('operasi')
diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php
index f109aa12..ad690217 100644
--- a/resources/views/home.blade.php
+++ b/resources/views/home.blade.php
@@ -208,8 +208,8 @@
@endhasrole
- @hasrole('jurulelong')
- {{-- Saya jurulelong! --}}
+ @hasrole('operasi')
+ {{-- Kawalan lelong oleh operasi. --}}
{{--
@@ -290,7 +290,7 @@
- @hasrole('jurulelong')
+ @hasrole('operasi')
diff --git a/resources/views/home00.blade.php b/resources/views/home00.blade.php
index 3213870f..96d08218 100644
--- a/resources/views/home00.blade.php
+++ b/resources/views/home00.blade.php
@@ -118,8 +118,8 @@
@endhasrole
- @hasrole('jurulelong')
- Saya jurulelong!
+ @hasrole('operasi')
+ Saya operasi!
|
@@ -200,7 +200,7 @@
- @hasrole('jurulelong')
+ @hasrole('operasi')
diff --git a/resources/views/homeoperasi.blade.php b/resources/views/homeoperasi.blade.php
index 41b871dd..7c04d514 100644
--- a/resources/views/homeoperasi.blade.php
+++ b/resources/views/homeoperasi.blade.php
@@ -12,7 +12,7 @@
{{ session('status') }}
@endif
- @hasrole('jurulelong')
+ @hasrole('operasi')
@if(count($arrayinfo)> 0)
@foreach ($arrayinfo as $lel)
|
@@ -125,8 +125,7 @@
@if($cawangan_detail['status_online'] == 0 && $cawangan_detail['belum_semak'] == 0)
Mula Lelong
@elseif($cawangan_detail['status_online'] == 1)
- Tamat Lelong
-
+ Tamat Lelong
@endif
@elseif($lel['info']['sts_lelong'] == 2)
@endif
diff --git a/resources/views/homexxxx.blade.php b/resources/views/homexxxx.blade.php
index 3035e448..59a7e176 100644
--- a/resources/views/homexxxx.blade.php
+++ b/resources/views/homexxxx.blade.php
@@ -119,8 +119,8 @@
@endhasrole
- @hasrole('jurulelong')
- Saya jurulelong!
+ @hasrole('operasi')
+ Saya operasi!
@@ -201,7 +201,7 @@
- @hasrole('jurulelong')
+ @hasrole('operasi')
diff --git a/resources/views/includes/sidebar.blade.php b/resources/views/includes/sidebar.blade.php
index 0444d3a7..51241986 100644
--- a/resources/views/includes/sidebar.blade.php
+++ b/resources/views/includes/sidebar.blade.php
@@ -673,6 +673,35 @@
@endhasrole
@hasrole('operasi')
+ | |