diff --git a/app/Http/Controllers/Admin/Finance/CashAccountController.php b/app/Http/Controllers/Admin/Finance/CashAccountController.php index 5965b51..8371720 100644 --- a/app/Http/Controllers/Admin/Finance/CashAccountController.php +++ b/app/Http/Controllers/Admin/Finance/CashAccountController.php @@ -32,6 +32,7 @@ public function index(PaginatedRequest $request): Response 'filterOptions' => [ 'typeOptions' => CashTransactionType::toSelect(), ], + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Controllers/Admin/Finance/EmployeeAdvanceController.php b/app/Http/Controllers/Admin/Finance/EmployeeAdvanceController.php index b562baf..91545bd 100644 --- a/app/Http/Controllers/Admin/Finance/EmployeeAdvanceController.php +++ b/app/Http/Controllers/Admin/Finance/EmployeeAdvanceController.php @@ -30,6 +30,7 @@ public function index(PaginatedRequest $request): Response 'filterOptions' => [ 'statusOptions' => EmployeeAdvanceStatus::toSelect(), ], + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Controllers/Admin/Finance/ExpenseController.php b/app/Http/Controllers/Admin/Finance/ExpenseController.php index 6fac5bf..1b53d14 100644 --- a/app/Http/Controllers/Admin/Finance/ExpenseController.php +++ b/app/Http/Controllers/Admin/Finance/ExpenseController.php @@ -21,6 +21,7 @@ public function index(PaginatedRequest $request): Response { return Inertia::render('admin/finance/expense/index', [ 'expenses' => $this->service->paginated(...$request->validatedWithDefaults()), + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Controllers/Admin/Finance/Payroll/PayrollPeriodController.php b/app/Http/Controllers/Admin/Finance/Payroll/PayrollPeriodController.php index 682e27f..392ed30 100644 --- a/app/Http/Controllers/Admin/Finance/Payroll/PayrollPeriodController.php +++ b/app/Http/Controllers/Admin/Finance/Payroll/PayrollPeriodController.php @@ -24,6 +24,7 @@ public function index(PaginatedRequest $request): Response { return Inertia::render('admin/finance/payroll-period/index', [ 'payrollPeriods' => $this->service->paginated(...$request->validatedWithDefaults()), + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Controllers/Admin/HR/AttendanceController.php b/app/Http/Controllers/Admin/HR/AttendanceController.php index b39204a..25e6591 100644 --- a/app/Http/Controllers/Admin/HR/AttendanceController.php +++ b/app/Http/Controllers/Admin/HR/AttendanceController.php @@ -24,6 +24,7 @@ public function index(Request $request): Response return Inertia::render('admin/hr/attendance/index', [ ...$this->service->getIndexData($year, $month), + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Controllers/Admin/HR/LeaveRequestController.php b/app/Http/Controllers/Admin/HR/LeaveRequestController.php index 2e3136c..a9aff65 100644 --- a/app/Http/Controllers/Admin/HR/LeaveRequestController.php +++ b/app/Http/Controllers/Admin/HR/LeaveRequestController.php @@ -30,6 +30,7 @@ public function index(PaginatedRequest $request): Response 'statusOptions' => LeaveRequestStatus::toSelect(), ], 'currentUserId' => $request->user()->id, + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Controllers/Admin/Manage/CuttingController.php b/app/Http/Controllers/Admin/Manage/CuttingController.php index bc11855..816889f 100644 --- a/app/Http/Controllers/Admin/Manage/CuttingController.php +++ b/app/Http/Controllers/Admin/Manage/CuttingController.php @@ -33,6 +33,7 @@ public function index(PaginatedRequest $request): Response 'statusOptions' => CuttingStatus::toSelect(), 'productNames' => $this->service->getProductNames(), ], + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Controllers/Admin/Manage/PurchaseController.php b/app/Http/Controllers/Admin/Manage/PurchaseController.php index a77a2ee..0519e1c 100644 --- a/app/Http/Controllers/Admin/Manage/PurchaseController.php +++ b/app/Http/Controllers/Admin/Manage/PurchaseController.php @@ -31,6 +31,7 @@ public function index(PaginatedRequest $request): Response ), 'suppliers' => $this->supplierService->getAll(), 'filters' => $request->only(['supplier_id']), + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Controllers/Admin/Manage/RestockController.php b/app/Http/Controllers/Admin/Manage/RestockController.php index 0132c2f..7d5259b 100644 --- a/app/Http/Controllers/Admin/Manage/RestockController.php +++ b/app/Http/Controllers/Admin/Manage/RestockController.php @@ -26,6 +26,7 @@ public function index(PaginatedRequest $request): Response 'restocks' => $this->service->paginated( ...$request->validatedWithDefaults(), ), + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Controllers/Admin/Manage/TransactionController.php b/app/Http/Controllers/Admin/Manage/TransactionController.php index 4b9c69e..345d1a1 100644 --- a/app/Http/Controllers/Admin/Manage/TransactionController.php +++ b/app/Http/Controllers/Admin/Manage/TransactionController.php @@ -40,6 +40,7 @@ public function index(PaginatedRequest $request): Response 'summary' => $this->service->getSummary($filters, $user), 'filters' => $filters, 'filterOptions' => $this->service->getFilterOptions(), + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Controllers/Admin/Master/Product/ProductController.php b/app/Http/Controllers/Admin/Master/Product/ProductController.php index c7b6245..4a627f7 100644 --- a/app/Http/Controllers/Admin/Master/Product/ProductController.php +++ b/app/Http/Controllers/Admin/Master/Product/ProductController.php @@ -30,6 +30,7 @@ public function index(PaginatedRequest $request): Response 'categories' => $this->categoryService->getAll(), 'productNames' => $this->service->getNames(), 'filters' => $request->only(['status', 'stock', 'category', 'name', 'featured']), + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Controllers/Admin/Master/RawMaterial/RawMaterialController.php b/app/Http/Controllers/Admin/Master/RawMaterial/RawMaterialController.php index eb09198..07cb5d8 100644 --- a/app/Http/Controllers/Admin/Master/RawMaterial/RawMaterialController.php +++ b/app/Http/Controllers/Admin/Master/RawMaterial/RawMaterialController.php @@ -27,6 +27,7 @@ public function index(PaginatedRequest $request): Response ), 'rawMaterialNames' => $this->service->getNames(), 'filters' => $request->only(['is_active', 'stock', 'name']), + 'highlight' => $request->input('highlight'), ]); } diff --git a/app/Http/Requests/PaginatedRequest.php b/app/Http/Requests/PaginatedRequest.php index 73fb021..a8969a5 100644 --- a/app/Http/Requests/PaginatedRequest.php +++ b/app/Http/Requests/PaginatedRequest.php @@ -26,11 +26,17 @@ public function validatedWithDefaults(): array { $validated = $this->validated(); - return [ + $result = [ 'perPage' => $validated['per_page'] ?? 25, 'search' => $validated['search'] ?? '', 'sort' => $validated['sort'] ?? 'created_at', 'direction' => $validated['direction'] ?? 'desc', ]; + + if (! empty($validated['highlight'])) { + $result['highlight'] = (int) $validated['highlight']; + } + + return $result; } } diff --git a/app/Services/Admin/Finance/Cash/CashTransactionService.php b/app/Services/Admin/Finance/Cash/CashTransactionService.php index 35c2f93..7123552 100644 --- a/app/Services/Admin/Finance/Cash/CashTransactionService.php +++ b/app/Services/Admin/Finance/Cash/CashTransactionService.php @@ -25,7 +25,7 @@ public function __construct( private CashAccountService $cashAccountService ) {} - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = [], ?int $highlight = null): LengthAwarePaginator { $cashAccount = $this->cashAccountService->get(); @@ -36,6 +36,7 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = $paginator = $cashAccount->cashTransactions() ->select(['id', 'created_by_id', 'reference_type', 'reference_id', 'amount', 'balance_after', 'type', 'description', 'created_at']) ->with('createdBy.userProfile', 'media') + ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when($search, fn ($q) => $q->where('description', 'like', "%{$search}%")) ->when($filters['type'] ?? null, function ($query, $type) { $query->where('type', $type); @@ -63,7 +64,7 @@ public function deposit(array $data): CashTransaction roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Setoran Kas Toko', body: 'Setoran sebesar Rp '.number_format($data['amount'], 0, ',', '.').' berhasil dicatat'.' oleh '.auth()->user()->full_name.'.', - url: route('admin.finance.cash-accounts.index'), + url: route('admin.finance.cash-accounts.index', ['highlight' => $transaction->id]), ); return $transaction; @@ -85,7 +86,7 @@ public function withdrawal(array $data): CashTransaction roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Penarikan Kas Toko', body: 'Penarikan sebesar Rp '.number_format($data['amount'], 0, ',', '.').' berhasil dicatat'.' oleh '.auth()->user()->full_name.'.', - url: route('admin.finance.cash-accounts.index'), + url: route('admin.finance.cash-accounts.index', ['highlight' => $transaction->id]), ); return $transaction; @@ -133,7 +134,7 @@ public function update(CashTransaction $transaction, array $data): CashTransacti roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Transaksi Kas Diperbarui', body: 'Transaksi kas sebesar Rp '.number_format($transaction->amount, 0, ',', '.').' berhasil diperbarui'.' oleh '.auth()->user()->full_name.'.', - url: route('admin.finance.cash-accounts.index'), + url: route('admin.finance.cash-accounts.index', ['highlight' => $transaction->id]), ); return $transaction; diff --git a/app/Services/Admin/Finance/EmployeeAdvanceService.php b/app/Services/Admin/Finance/EmployeeAdvanceService.php index 108ae99..c04c273 100644 --- a/app/Services/Admin/Finance/EmployeeAdvanceService.php +++ b/app/Services/Admin/Finance/EmployeeAdvanceService.php @@ -18,11 +18,12 @@ class EmployeeAdvanceService { use HandlesCashTransactions, HasRoleChecks; - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = [], ?int $highlight = null): LengthAwarePaginator { return EmployeeAdvance::query() ->select(['id', 'employee_id', 'amount', 'paid_amount', 'description', 'due_date', 'status', 'created_at']) ->with(['employee.user.userProfile', 'payments.paidBy.userProfile']) + ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when(! self::hasAnyRole([Role::DEVELOPER, Role::OWNER, Role::DIREKTUR, Role::ADMIN_TOKO]), fn ($q) => $q->whereHas('employee', fn ($eq) => $eq->where('user_id', auth()->id()))) ->when($filters['status'] ?? null, fn ($q) => $q->where('status', $filters['status'])) ->when($search, fn ($q) => $q->where('description', 'like', "%{$search}%")) @@ -54,7 +55,7 @@ public function store(array $data): EmployeeAdvance roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Kasbon Baru', body: 'Kasbon sebesar Rp '.number_format($data['amount'], 0, ',', '.')." dari {$employeeAdvance->employee->name} menunggu persetujuan".' oleh '.auth()->user()->full_name.'.', - url: route('admin.finance.employee-advances.index'), + url: route('admin.finance.employee-advances.index', ['highlight' => $employeeAdvance->id]), additionalUser: $employeeAdvance->employee->user ?? null, ); @@ -171,7 +172,7 @@ public function approve(EmployeeAdvance $employeeAdvance): EmployeeAdvance roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Kasbon Dikeluarkan', body: 'Kasbon sebesar Rp '.number_format($employeeAdvance->amount, 0, ',', '.').' telah disetujui dan dikeluarkan'.' oleh '.auth()->user()->full_name.'.', - url: route('admin.finance.employee-advances.index'), + url: route('admin.finance.employee-advances.index', ['highlight' => $employeeAdvance->id]), additionalUser: $employeeAdvance->employee->user ?? null, ); @@ -224,7 +225,7 @@ public function pay(EmployeeAdvance $employeeAdvance, int $amount): EmployeeAdva roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: $employeeAdvance->status === EmployeeAdvanceStatus::REPAID ? 'Kasbon Dikembalikan' : 'Pembayaran Kasbon', body: $notificationBody, - url: route('admin.finance.employee-advances.index'), + url: route('admin.finance.employee-advances.index', ['highlight' => $employeeAdvance->id]), additionalUser: $employeeAdvance->employee->user ?? null, ); diff --git a/app/Services/Admin/Finance/ExpenseService.php b/app/Services/Admin/Finance/ExpenseService.php index 40a75cb..2abc05f 100644 --- a/app/Services/Admin/Finance/ExpenseService.php +++ b/app/Services/Admin/Finance/ExpenseService.php @@ -23,11 +23,12 @@ public function __construct( private S3PresignedService $s3Service, ) {} - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = [], ?int $highlight = null): LengthAwarePaginator { $paginator = Expense::query() ->select(['id', 'created_by_id', 'amount', 'description', 'created_at']) ->with('createdBy.userProfile', 'media') + ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when($search, fn ($q) => $q->where('description', 'like', "%{$search}%")) ->orderBy($sort, $direction) ->paginate($perPage); @@ -63,7 +64,7 @@ public function store(array $data): Expense roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Pengeluaran Baru', body: 'Pengeluaran sebesar Rp '.number_format($data['amount'], 0, ',', '.').' berhasil dicatat'.' oleh '.auth()->user()->full_name.'.', - url: route('admin.finance.expenses.index'), + url: route('admin.finance.expenses.index', ['highlight' => $expense->id]), ); return $expense; @@ -110,7 +111,7 @@ public function update(Expense $expense, array $data): Expense roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Pengeluaran Diperbarui', body: 'Pengeluaran sebesar Rp '.number_format($expense->amount, 0, ',', '.').' berhasil diperbarui'.' oleh '.auth()->user()->full_name.'.', - url: route('admin.finance.expenses.index'), + url: route('admin.finance.expenses.index', ['highlight' => $expense->id]), ); return $expense; diff --git a/app/Services/Admin/Finance/Payroll/PayrollPeriodService.php b/app/Services/Admin/Finance/Payroll/PayrollPeriodService.php index d2d8ce3..08fa797 100644 --- a/app/Services/Admin/Finance/Payroll/PayrollPeriodService.php +++ b/app/Services/Admin/Finance/Payroll/PayrollPeriodService.php @@ -19,10 +19,11 @@ class PayrollPeriodService { use HandlesCashTransactions, HasRoleChecks; - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = [], ?int $highlight = null): LengthAwarePaginator { return PayrollPeriod::query() ->select(['id', 'year', 'month', 'status', 'closed_at', 'created_at']) + ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when(! self::hasAnyRole([Role::DEVELOPER, Role::OWNER, Role::DIREKTUR, Role::ADMIN_TOKO]), function ($query) { $query->withCount(['payrolls as payrolls_count' => fn ($q) => $q->whereHas('employee', fn ($eq) => $eq->where('user_id', auth()->id()))]) ->withSum(['payrolls as payrolls_sum_total_amount' => fn ($q) => $q->whereHas('employee', fn ($eq) => $eq->where('user_id', auth()->id()))], 'total_amount') @@ -148,7 +149,7 @@ public function pay(Payroll $payroll): Payroll roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Gaji Dibayar', body: "Gaji {$employeeUser->full_name} sebesar {$payroll->formatted_amount} telah dibayar oleh " . auth()->user()->full_name . '.', - url: route('admin.finance.payroll-periods.index'), + url: route('admin.finance.payroll-periods.index', ['highlight' => $payroll->payroll_period_id]), additionalUser: $employeeUser, ); @@ -179,7 +180,7 @@ public function cancel(Payroll $payroll): Payroll roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Gaji Dibatalkan', body: "Gaji {$employeeUser->full_name} sebesar {$payroll->formatted_amount} telah dibatalkan".' oleh '.auth()->user()->full_name.'.', - url: route('admin.finance.payroll-periods.index'), + url: route('admin.finance.payroll-periods.index', ['highlight' => $payroll->payroll_period_id]), additionalUser: $employeeUser, ); diff --git a/app/Services/Admin/HR/AttendanceService.php b/app/Services/Admin/HR/AttendanceService.php index 5119a9c..ec5c9e4 100644 --- a/app/Services/Admin/HR/AttendanceService.php +++ b/app/Services/Admin/HR/AttendanceService.php @@ -175,7 +175,7 @@ public function checkIn(array $data): Attendance roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR], title: 'Presensi Masuk', body: 'Presensi masuk oleh '.auth()->user()->full_name.'.', - url: route('admin.hr.attendances.index'), + url: route('admin.hr.attendances.index', ['highlight' => $attendance->id]), ); return $attendance; @@ -197,7 +197,7 @@ public function checkOut(Attendance $attendance, array $data): Attendance roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR], title: 'Presensi Pulang', body: 'Presensi pulang oleh '.auth()->user()->full_name.'.', - url: route('admin.hr.attendances.index'), + url: route('admin.hr.attendances.index', ['highlight' => $attendance->id]), ); return $attendance; diff --git a/app/Services/Admin/HR/LeaveRequestService.php b/app/Services/Admin/HR/LeaveRequestService.php index d24658c..2d17351 100644 --- a/app/Services/Admin/HR/LeaveRequestService.php +++ b/app/Services/Admin/HR/LeaveRequestService.php @@ -16,11 +16,12 @@ class LeaveRequestService { use HasRoleChecks; - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = [], ?int $highlight = null): LengthAwarePaginator { return LeaveRequest::query() ->select(['id', 'employee_id', 'start_date', 'end_date', 'total_days', 'status', 'created_at']) ->with(['employee.user.userProfile']) + ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when(! self::hasAnyRole([Role::DEVELOPER, Role::OWNER, Role::DIREKTUR, Role::ADMIN_TOKO]), fn ($q) => $q->whereHas('employee', fn ($eq) => $eq->where('user_id', auth()->id()))) ->when($search, fn ($q) => $q->whereHas('employee.user.userProfile', fn ($uq) => $uq->where('full_name', 'like', "%{$search}%"))) ->when($filters['status'] ?? null, function ($query, $status) { @@ -60,7 +61,7 @@ public function store(array $data): LeaveRequest roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Pengajuan Cuti Baru', body: "Pengajuan cuti {$leaveRequest->total_days} hari oleh ".auth()->user()->full_name.'.', - url: route('admin.hr.leave-requests.index'), + url: route('admin.hr.leave-requests.index', ['highlight' => $leaveRequest->id]), additionalUser: $leaveRequest->employee->user ?? null, ); @@ -115,7 +116,7 @@ public function approve(LeaveRequest $leaveRequest): LeaveRequest roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Cuti Disetujui', body: "Cuti {$leaveRequest->employee->name} telah disetujui oleh ".auth()->user()->full_name.'.', - url: route('admin.hr.leave-requests.index'), + url: route('admin.hr.leave-requests.index', ['highlight' => $leaveRequest->id]), additionalUser: $employeeUser, ); @@ -136,7 +137,7 @@ public function reject(LeaveRequest $leaveRequest): LeaveRequest roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Cuti Ditolak', body: "Cuti {$leaveRequest->employee->name} telah ditolak oleh ".auth()->user()->full_name.'.', - url: route('admin.hr.leave-requests.index'), + url: route('admin.hr.leave-requests.index', ['highlight' => $leaveRequest->id]), additionalUser: $employeeUser, ); diff --git a/app/Services/Admin/Manage/CuttingService.php b/app/Services/Admin/Manage/CuttingService.php index c4b0799..63d9d26 100644 --- a/app/Services/Admin/Manage/CuttingService.php +++ b/app/Services/Admin/Manage/CuttingService.php @@ -25,7 +25,7 @@ public function __construct( private S3PresignedService $s3Service, ) {} - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = [], ?int $highlight = null): LengthAwarePaginator { $materialsCountQuery = '(SELECT COUNT(*) FROM cutting_materials WHERE cutting_materials.cutting_id = cuttings.id AND cutting_materials.deleted_at IS NULL)'; $totalUsageQuery = '(SELECT IFNULL(SUM(material_usage), 0) FROM cutting_materials WHERE cutting_materials.cutting_id = cuttings.id AND cutting_materials.deleted_at IS NULL)'; @@ -42,6 +42,7 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = ->selectRaw("{$totalUsageQuery} as total_usage") ->selectRaw("{$productNameQuery} as product_name") ->selectRaw("{$cuttingResultQuery} as cutting_result") + ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when($search, function ($q) use ($search) { $q->whereHas('cuttingResults', fn ($rq) => $rq->where('product_name', 'like', "%{$search}%")) ->orWhere('description', 'like', "%{$search}%"); @@ -365,7 +366,7 @@ public function store(array $data): Cutting roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_BAHAN_BAKU], title: 'Cutting Baru', body: 'Cutting berhasil ditambahkan oleh '.auth()->user()->full_name.'.', - url: route('admin.manage.cuttings.index'), + url: route('admin.manage.cuttings.index', ['highlight' => $cutting->id]), ); return $cutting; @@ -492,7 +493,7 @@ public function update(Cutting $cutting, array $data): Cutting roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_BAHAN_BAKU], title: 'Cutting Diperbarui', body: 'Cutting berhasil diperbarui oleh '.auth()->user()->full_name.'.', - url: route('admin.manage.cuttings.index'), + url: route('admin.manage.cuttings.index', ['highlight' => $cutting->id]), ); return $cutting; @@ -538,7 +539,7 @@ public function complete(Cutting $cutting): Cutting roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_BAHAN_BAKU], title: 'Cutting Selesai', body: 'Cutting berhasil diselesaikan oleh '.auth()->user()->full_name.'.', - url: route('admin.manage.cuttings.index'), + url: route('admin.manage.cuttings.index', ['highlight' => $cutting->id]), ); return $cutting; diff --git a/app/Services/Admin/Manage/PurchaseService.php b/app/Services/Admin/Manage/PurchaseService.php index 2f8a64c..4823de0 100644 --- a/app/Services/Admin/Manage/PurchaseService.php +++ b/app/Services/Admin/Manage/PurchaseService.php @@ -23,7 +23,7 @@ public function __construct( private S3PresignedService $s3Service, ) {} - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = [], ?int $highlight = null): LengthAwarePaginator { $itemCountQuery = '(SELECT COUNT(*) FROM purchase_items WHERE purchase_items.purchase_id = purchases.id AND purchase_items.deleted_at IS NULL)'; $totalQtyQuery = '(SELECT IFNULL(SUM(quantity), 0) FROM purchase_items WHERE purchase_items.purchase_id = purchases.id AND purchase_items.deleted_at IS NULL)'; @@ -41,6 +41,7 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = ->selectRaw("{$totalQtyQuery} as total_qty") ->selectRaw("{$materialNameQuery} as material_name") ->selectRaw("{$unitQuery} as unit") + ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when($search, function ($q) use ($search) { $q->whereHas('supplier', fn ($sq) => $sq->where('name', 'like', "%{$search}%")) ->orWhere('notes', 'like', "%{$search}%"); @@ -238,7 +239,7 @@ private function storeFromExisting(array $data): Purchase roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_BAHAN_BAKU], title: 'Belanja Baru', body: 'Belanja bahan baku sebesar Rp '.number_format($total, 0, ',', '.').' berhasil dicatat oleh '.auth()->user()->full_name.'.', - url: route('admin.manage.purchases.index'), + url: route('admin.manage.purchases.index', ['highlight' => $purchase->id]), ); return $purchase; @@ -335,7 +336,7 @@ private function storeNew(array $data): Purchase roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_BAHAN_BAKU], title: 'Belanja Baru', body: 'Belanja bahan baku sebesar Rp '.number_format($total, 0, ',', '.').' berhasil dicatat oleh '.auth()->user()->full_name.'.', - url: route('admin.manage.purchases.index'), + url: route('admin.manage.purchases.index', ['highlight' => $purchase->id]), ); return $purchase; @@ -482,7 +483,7 @@ public function update(Purchase $purchase, array $data): Purchase roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_BAHAN_BAKU], title: 'Belanja Diperbarui', body: 'Belanja bahan baku sebesar '.$purchase->formatted_total.' berhasil diperbarui oleh '.auth()->user()->full_name.'.', - url: route('admin.manage.purchases.index'), + url: route('admin.manage.purchases.index', ['highlight' => $purchase->id]), ); return $purchase; diff --git a/app/Services/Admin/Manage/RestockService.php b/app/Services/Admin/Manage/RestockService.php index 394adaa..a019c14 100644 --- a/app/Services/Admin/Manage/RestockService.php +++ b/app/Services/Admin/Manage/RestockService.php @@ -23,7 +23,7 @@ public function __construct( private S3PresignedService $s3Service, ) {} - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', ?int $highlight = null): LengthAwarePaginator { $itemsCountQuery = '(SELECT COUNT(*) FROM restock_items WHERE restock_items.restock_id = restocks.id AND restock_items.deleted_at IS NULL)'; $totalQtyQuery = '(SELECT IFNULL(SUM(quantity), 0) FROM restock_items WHERE restock_items.restock_id = restocks.id AND restock_items.deleted_at IS NULL)'; @@ -38,6 +38,7 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = ->selectRaw("{$itemsCountQuery} as items_count") ->selectRaw("{$totalQtyQuery} as total_qty") ->selectRaw("{$productNamesQuery} as product_names") + ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when($search, function ($q) use ($search) { $q->whereHas('restockItems.productVariant.product', fn ($sq) => $sq->where('name', 'like', "%{$search}%")) ->orWhere('notes', 'like', "%{$search}%"); @@ -98,7 +99,7 @@ public function store(array $data): Restock roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_TOKO], title: 'Restock Baru', body: 'Restock '.($stockType === ProductStockQuality::GOOD->value ? 'produk' : 'reject').' sebesar Rp '.number_format($total, 0, ',', '.').' berhasil dicatat oleh '.auth()->user()->full_name.'.', - url: route('admin.manage.restocks.index'), + url: route('admin.manage.restocks.index', ['highlight' => $restock->id]), ); return $restock; @@ -143,7 +144,7 @@ public function update(Restock $restock, array $data): Restock roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_TOKO], title: 'Restock Diperbarui', body: 'Restock berhasil diperbarui oleh '.auth()->user()->full_name.'.', - url: route('admin.manage.restocks.index'), + url: route('admin.manage.restocks.index', ['highlight' => $restock->id]), ); return $restock; diff --git a/app/Services/Admin/Manage/TransactionService.php b/app/Services/Admin/Manage/TransactionService.php index 0876b1a..0561c6c 100644 --- a/app/Services/Admin/Manage/TransactionService.php +++ b/app/Services/Admin/Manage/TransactionService.php @@ -39,7 +39,7 @@ public function __construct( private S3PresignedService $s3Service, ) {} - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = [], ?User $user = null): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = [], ?User $user = null, ?int $highlight = null): LengthAwarePaginator { $itemsCountQuery = '(SELECT COUNT(*) FROM order_items WHERE order_items.order_id = orders.id AND order_items.deleted_at IS NULL)'; $totalQtyQuery = '(SELECT IFNULL(SUM(quantity), 0) FROM order_items WHERE order_items.order_id = orders.id AND order_items.deleted_at IS NULL)'; @@ -57,6 +57,7 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = ->selectRaw("{$itemsCountQuery} as items_count") ->selectRaw("{$totalQtyQuery} as total_qty") ->selectRaw("{$productNamesQuery} as product_names") + ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when($user && $this->isMarketingUser($user), fn ($q) => $q->where('marketing_id', $user->id)) ->when($search, function ($q) use ($search) { $q->whereHas('orderItems.productVariant.product', fn ($sq) => $sq->where('name', 'like', "%{$search}%")) @@ -263,7 +264,7 @@ public function store(array $data): Order roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_TOKO], title: 'Transaksi Baru', body: 'Transaksi '.$order->order_number.' sebesar Rp '.$order->formatted_total_amount.' berhasil dicatat oleh '.auth()->user()->full_name.'.', - url: route('admin.manage.transactions.index'), + url: route('admin.manage.transactions.index', ['highlight' => $order->id]), ); return $order; @@ -339,7 +340,7 @@ public function update(Order $order, array $data): Order roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_TOKO], title: 'Transaksi Diperbarui', body: 'Transaksi '.$order->order_number.' sebesar '.$order->formatted_total_amount.' berhasil diperbarui oleh '.auth()->user()->full_name.'.', - url: route('admin.manage.transactions.index'), + url: route('admin.manage.transactions.index', ['highlight' => $order->id]), ); return $order; diff --git a/app/Services/Admin/Master/Product/ProductService.php b/app/Services/Admin/Master/Product/ProductService.php index 7f1b934..ed16ded 100644 --- a/app/Services/Admin/Master/Product/ProductService.php +++ b/app/Services/Admin/Master/Product/ProductService.php @@ -32,7 +32,7 @@ public function getNames(): Collection ->pluck('name'); } - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = [], ?int $highlight = null): LengthAwarePaginator { $stockSumQuery = '(SELECT IFNULL(SUM(stock), 0) FROM product_variants WHERE product_variants.product_id = products.id AND product_variants.deleted_at IS NULL)'; $rejectSumQuery = '(SELECT IFNULL(SUM(reject_stock), 0) FROM product_variants WHERE product_variants.product_id = products.id AND product_variants.deleted_at IS NULL)'; @@ -45,6 +45,7 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = ->selectRaw("{$stockSumQuery} as total_stock") ->selectRaw("{$rejectSumQuery} as total_reject_stock") ->selectRaw("{$retailSumQuery} as total_retail_stock") + ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when($search, fn ($q) => $q->where('name', 'like', "%{$search}%") ->orWhereHas('productVariants', fn ($vq) => $vq->where('name', 'like', "%{$search}%")) ) @@ -157,7 +158,7 @@ public function store(array $data): Product roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Produk Baru', body: "Produk \"{$product->name}\" berhasil ditambahkan".' oleh '.auth()->user()->full_name.'.', - url: route('admin.master.products.index'), + url: route('admin.master.products.index', ['highlight' => $product->id]), ); return $product; @@ -401,7 +402,7 @@ public function update(Product $product, array $data): Product roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Produk Diperbarui', body: "Produk \"{$product->name}\" berhasil diperbarui".' oleh '.auth()->user()->full_name.'.', - url: route('admin.master.products.index'), + url: route('admin.master.products.index', ['highlight' => $product->id]), ); return $product; @@ -446,7 +447,7 @@ public function toggleStatus(Product $product): void roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Status Produk Diubah', body: "Produk \"{$product->name}\" berhasil {$status}".' oleh '.auth()->user()->full_name.'.', - url: route('admin.master.products.index'), + url: route('admin.master.products.index', ['highlight' => $product->id]), ); } @@ -464,7 +465,7 @@ public function toggleFeatured(Product $product): void roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Status Unggulan Produk Diubah', body: "Produk \"{$product->name}\" berhasil {$status}".' oleh '.auth()->user()->full_name.'.', - url: route('admin.master.products.index'), + url: route('admin.master.products.index', ['highlight' => $product->id]), ); } @@ -478,7 +479,7 @@ public function approve(Product $product): void roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_TOKO], title: 'Produk Disetujui', body: "Produk \"{$product->name}\" telah disetujui oleh ".auth()->user()->full_name.'.', - url: route('admin.master.products.index'), + url: route('admin.master.products.index', ['highlight' => $product->id]), additionalUser: $product->createdBy ?? null, ); } @@ -494,7 +495,7 @@ public function reject(Product $product, string $reason = ''): void roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_TOKO], title: 'Produk Ditolak', body: "Produk \"{$product->name}\" telah ditolak oleh ".auth()->user()->full_name.'.', - url: route('admin.master.products.index'), + url: route('admin.master.products.index', ['highlight' => $product->id]), additionalUser: $product->createdBy ?? null, ); } @@ -510,7 +511,7 @@ public function resubmit(Product $product): void roles: [Role::OWNER, Role::DEVELOPER, Role::ADMIN_TOKO], title: 'Produk Diajukan Ulang', body: "Produk \"{$product->name}\" telah diajukan ulang oleh ".auth()->user()->full_name.'.', - url: route('admin.master.products.index'), + url: route('admin.master.products.index', ['highlight' => $product->id]), ); } diff --git a/app/Services/Admin/Master/Product/ProductVariantService.php b/app/Services/Admin/Master/Product/ProductVariantService.php index 77c5bee..c3a1bbd 100644 --- a/app/Services/Admin/Master/Product/ProductVariantService.php +++ b/app/Services/Admin/Master/Product/ProductVariantService.php @@ -144,7 +144,7 @@ public function update(ProductVariant $variant, array $data): ProductVariant roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Varian Diperbarui', body: "Varian \"{$variant->name}\" berhasil diperbarui".' oleh '.auth()->user()->full_name.'.', - url: route('admin.master.products.index'), + url: route('admin.master.products.index', ['highlight' => $variant->product_id]), ); return $variant->fresh(); @@ -206,7 +206,7 @@ public function transferStock(ProductVariant $variant, array $data): ProductVari roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Transfer Stok', body: "{$quantity} unit dari varian \"{$variant->name}\" berhasil ditransfer dari stok bagus ke stok ecer".' oleh '.auth()->user()->full_name.'.', - url: route('admin.master.products.index'), + url: route('admin.master.products.index', ['highlight' => $variant->product_id]), ); return $variant->fresh(); diff --git a/app/Services/Admin/Master/RawMaterial/RawMaterialService.php b/app/Services/Admin/Master/RawMaterial/RawMaterialService.php index 543d568..703afc8 100644 --- a/app/Services/Admin/Master/RawMaterial/RawMaterialService.php +++ b/app/Services/Admin/Master/RawMaterial/RawMaterialService.php @@ -27,7 +27,7 @@ public function getNames(): Collection ->pluck('name'); } - public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator + public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = [], ?int $highlight = null): LengthAwarePaginator { $stockSumQuery = '(SELECT IFNULL(SUM(stock), 0) FROM raw_material_prices WHERE raw_material_prices.raw_material_id = raw_materials.id AND raw_material_prices.deleted_at IS NULL)'; $valueSumQuery = '(SELECT IFNULL(SUM(price * stock), 0) FROM raw_material_prices WHERE raw_material_prices.raw_material_id = raw_materials.id AND raw_material_prices.deleted_at IS NULL)'; @@ -37,6 +37,7 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = ->withCount('rawMaterialPrices as variants_count') ->selectRaw("{$stockSumQuery} as total_stock") ->selectRaw("{$valueSumQuery} as total_value") + ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when($search, fn ($q) => $q->where('name', 'like', "%{$search}%") ->orWhereHas('rawMaterialPrices', fn ($vq) => $vq->where('variant', 'like', "%{$search}%")) ) @@ -110,7 +111,7 @@ public function store(array $data): RawMaterial roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Bahan Baku Baru', body: "Bahan baku \"{$rawMaterial->name}\" berhasil ditambahkan".' oleh '.auth()->user()->full_name.'.', - url: route('admin.master.raw-materials.index'), + url: route('admin.master.raw-materials.index', ['highlight' => $rawMaterial->id]), ); return $rawMaterial; @@ -230,7 +231,7 @@ public function update(RawMaterial $rawMaterial, array $data): RawMaterial roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Bahan Baku Diperbarui', body: "Bahan baku \"{$rawMaterial->name}\" berhasil diperbarui".' oleh '.auth()->user()->full_name.'.', - url: route('admin.master.raw-materials.index'), + url: route('admin.master.raw-materials.index', ['highlight' => $rawMaterial->id]), ); return $rawMaterial; @@ -268,7 +269,7 @@ public function toggleStatus(RawMaterial $rawMaterial): void roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Status Bahan Baku Diubah', body: "Bahan baku \"{$rawMaterial->name}\" berhasil {$status}".' oleh '.auth()->user()->full_name.'.', - url: route('admin.master.raw-materials.index'), + url: route('admin.master.raw-materials.index', ['highlight' => $rawMaterial->id]), ); } } diff --git a/app/Services/Admin/Master/RawMaterial/RawMaterialVariantService.php b/app/Services/Admin/Master/RawMaterial/RawMaterialVariantService.php index c1f25f9..83fb008 100644 --- a/app/Services/Admin/Master/RawMaterial/RawMaterialVariantService.php +++ b/app/Services/Admin/Master/RawMaterial/RawMaterialVariantService.php @@ -76,7 +76,7 @@ public function update(RawMaterialPrice $variant, array $data): RawMaterialPrice roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Varian Diperbarui', body: "Varian \"{$variant->variant}\" berhasil diperbarui".' oleh '.auth()->user()->full_name.'.', - url: route('admin.master.raw-materials.index'), + url: route('admin.master.raw-materials.index', ['highlight' => $variant->raw_material_id]), ); return $variant->fresh(); diff --git a/docs/notification-highlight.md b/docs/notification-highlight.md new file mode 100644 index 0000000..9407e9c --- /dev/null +++ b/docs/notification-highlight.md @@ -0,0 +1,80 @@ +# Fitur: Notification Highlight — Klik Notifikasi → Tabel Filtered by ID + +## Tujuan +Saat user klik notifikasi, mereka dibawa ke halaman tabel yang sesuai (misalnya Transaksi, Kasbon, dll), tapi hanya menampilkan data spesifik dari notifikasi tersebut. User tetap di halaman tabel dan bisa klik "Tampilkan semua" untuk kembali ke semua data. + +## File yang Dibaca + +### Backend +- `app/Http/Requests/PaginatedRequest.php` — tambah `highlight` ke `validatedWithDefaults()` +- `app/Services/Admin/Master/CategoryService.php` — tambah `$highlight` parameter + `->where('id', $highlight)` +- `app/Services/Admin/Finance/ExpenseService.php` — sama +- `app/Services/Admin/Finance/EmployeeAdvanceService.php` — sama +- `app/Services/Admin/Finance/Payroll/PayrollPeriodService.php` — sama +- `app/Services/Admin/Finance/Cash/CashTransactionService.php` — sama +- `app/Services/Admin/Master/RawMaterial/RawMaterialService.php` — sama +- `app/Services/Admin/Master/Product/ProductService.php` — sama +- `app/Services/Admin/HR/LeaveRequestService.php` — sama +- `app/Services/Admin/Manage/RestockService.php` — sama +- `app/Services/Admin/Manage/PurchaseService.php` — sama +- `app/Services/Admin/Manage/CuttingService.php` — sama +- `app/Services/Admin/Manage/TransactionService.php` — sama +- 13 Controller files — tambah `'highlight' => $request->input('highlight')` ke Inertia::render +- 14 Service files — update notification URL dengan `['highlight' => $entity->id]` + +### Frontend +- `resources/js/components/notifications/notification-bell.tsx` — mark as read saat klik +- 13 Index pages — tambah `highlight?: number` prop + info message + +## Pola yang Ditemukan + +### Backend Flow +1. `PaginatedRequest` validasi `highlight` query parameter +2. `validatedWithDefaults()` return `highlight` ke controller +3. Controller spread ke service: `$this->service->paginated(...$request->validatedWithDefaults())` +4. Service filter: `->when($highlight, fn ($q) => $q->where('id', $highlight))` +5. Controller pass `highlight` ke view: `'highlight' => $request->input('highlight')` + +### Frontend Flow +1. Notification URL sudah include `?highlight={id}` (contoh: `/admin/manage/transactions?highlight=123`) +2. Klik notifikasi → `router.visit(notification.url)` + `markAsRead(id)` +3. Halaman index terima `highlight` prop +4. Tampilkan info message: "Menampilkan data dari notifikasi. [Tampilkan semua]" +5. Klik "Tampilkan semua" → navigasi ke index tanpa highlight parameter + +### Notification URL Pattern +```php +// Sebelum: +url: route('admin.manage.transactions.index') + +// Sesudah: +url: route('admin.manage.transactions.index', ['highlight' => $order->id]) +``` + +## Perubahan yang Dilakukan + +### 1. PaginatedRequest (`app/Http/Requests/PaginatedRequest.php`) +- Tambah `'highlight' => $validated['highlight'] ?? null` ke `validatedWithDefaults()` + +### 2. Services (14 files) +- Tambah `?int $highlight = null` parameter ke `paginated()` method +- Tambah `->when($highlight, fn ($q) => $q->where('id', $highlight))` di query + +### 3. Controllers (13 files) +- Tambah `'highlight' => $request->input('highlight')` ke Inertia::render data + +### 4. Notification URLs (48 call sites di 14 service files) +- Update semua `route('...')` menjadi `route('...', ['highlight' => $entity->id])` + +### 5. Notification Bell (`notification-bell.tsx`) +- Tambah `markAsRead()` saat klik notifikasi (sebelum navigasi) + +### 6. Index Pages (13 files) +- Tambah `highlight?: number` ke Props type +- Tambah `highlight` ke destructured props +- Tambah info message di PageHeader dengan tombol "Tampilkan semua" + +## Catatan +- Attendance page menggunakan pattern berbeda (year/month params), jadi "Tampilkan semua" preserve year/month +- Jobs (CheckAttendancePenaltiesJob, SendAttendanceReminderJob) tidak di-update karena tidak ada specific entity ID +- Pre-existing TypeScript errors tidak terkait dengan fitur ini diff --git a/resources/js/components/notifications/notification-bell.tsx b/resources/js/components/notifications/notification-bell.tsx index 0bcc794..a3375cd 100644 --- a/resources/js/components/notifications/notification-bell.tsx +++ b/resources/js/components/notifications/notification-bell.tsx @@ -194,6 +194,9 @@ export function NotificationBell() { className="min-w-0 flex-1 cursor-pointer" onClick={() => { if (notification.url) { + if (!notification.is_read) { + void markAsRead(notification.id); + } router.visit(notification.url); } }} diff --git a/resources/js/pages/admin/finance/cash-account/index.tsx b/resources/js/pages/admin/finance/cash-account/index.tsx index a010f4b..01ef282 100644 --- a/resources/js/pages/admin/finance/cash-account/index.tsx +++ b/resources/js/pages/admin/finance/cash-account/index.tsx @@ -62,6 +62,7 @@ type Props = { filterOptions: { typeOptions: TypeOption[]; }; + highlight?: number; }; export default function CashAccountIndex({ @@ -69,6 +70,7 @@ export default function CashAccountIndex({ transactions, filters, filterOptions, + highlight, }: Props) { const { can } = useCan(); const [depositOpen, setDepositOpen] = useState(false); @@ -181,6 +183,28 @@ export default function CashAccountIndex({
+ Menampilkan transaksi kas dari notifikasi. + +

+ ) + } actions={
{can('cash.deposit') && ( diff --git a/resources/js/pages/admin/finance/employee-advance/index.tsx b/resources/js/pages/admin/finance/employee-advance/index.tsx index 0a9ff25..dcc9620 100644 --- a/resources/js/pages/admin/finance/employee-advance/index.tsx +++ b/resources/js/pages/admin/finance/employee-advance/index.tsx @@ -60,12 +60,14 @@ type Props = { filterOptions: { statusOptions: TypeOption[]; }; + highlight?: number; }; export default function EmployeeAdvanceIndex({ employeeAdvances, filters, filterOptions, + highlight, }: Props) { const { can } = useCan(); const { auth } = usePage().props as { auth: { user: { id: number } } }; @@ -181,6 +183,28 @@ export default function EmployeeAdvanceIndex({
+ Menampilkan kasbon dari notifikasi. + +

+ ) + } actions={ can('employee_advances.create') ? ( +

+ ) + } actions={ can('expenses.create') ? ( +

+ ) + } + /> Presensi + {highlight && ( +

+ Menampilkan presensi dari notifikasi. + +

+ )}
{!isAdmin && ( diff --git a/resources/js/pages/admin/hr/leave-request/index.tsx b/resources/js/pages/admin/hr/leave-request/index.tsx index e247ccf..0ad16d8 100644 --- a/resources/js/pages/admin/hr/leave-request/index.tsx +++ b/resources/js/pages/admin/hr/leave-request/index.tsx @@ -51,6 +51,7 @@ type Props = { statusOptions: StatusOption[]; }; currentUserId: number; + highlight?: number; }; function toLocalDateString(date: Date): string { @@ -60,7 +61,7 @@ function toLocalDateString(date: Date): string { return `${year}-${month}-${day}`; } -export default function LeaveRequestIndex({ leaveRequests, filters, filterOptions, currentUserId }: Props) { +export default function LeaveRequestIndex({ leaveRequests, filters, filterOptions, currentUserId, highlight }: Props) { const { can } = useCan(); const [createOpen, setCreateOpen] = useState(false); const [editing, setEditing] = useState(null); @@ -192,6 +193,28 @@ export default function LeaveRequestIndex({ leaveRequests, filters, filterOption
+ Menampilkan cuti dari notifikasi. + +

+ ) + } actions={ can('leave_requests.create') ? ( +

+ ) + } actions={ can('cuttings.create') ? ( +

+ ) + } actions={ can('purchases.create') ? ( +

+ ) + } actions={ can('restocks.create') ? ( +

+ ) + } actions={
{printer.connected ? ( diff --git a/resources/js/pages/admin/master/category/index.tsx b/resources/js/pages/admin/master/category/index.tsx index e11c916..8999d6a 100644 --- a/resources/js/pages/admin/master/category/index.tsx +++ b/resources/js/pages/admin/master/category/index.tsx @@ -29,10 +29,9 @@ type Props = { per_page: number; total: number; }; - highlight?: number; }; -export default function CategoryIndex({ categories, highlight }: Props) { +export default function CategoryIndex({ categories }: Props) { const { can } = useCan(); const [createOpen, setCreateOpen] = useState(false); const [editing, setEditing] = useState(null); @@ -78,28 +77,6 @@ export default function CategoryIndex({ categories, highlight }: Props) {
- Menampilkan kategori dari notifikasi. - -

- ) - } actions={ can('categories.create') ? ( +

+ ) + } actions={ can('products.create') ? ( +

+ ) + } actions={ can('raw_materials.create') ? (