refactor: replace hardcoded URL strings with dynamic route helpers across services and frontend components.
This commit is contained in:
parent
2f8ece4b0a
commit
dfd2c5560b
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use App\Enums\EmployeeStatus;
|
|
||||||
use App\Models\Attendance;
|
use App\Models\Attendance;
|
||||||
use App\Models\Employee;
|
use App\Models\Employee;
|
||||||
use App\Services\System\PushNotificationService;
|
use App\Services\System\PushNotificationService;
|
||||||
@ -31,8 +30,7 @@ public function handle(PushNotificationService $pushNotificationService): int
|
|||||||
$scheduledCheckIn = Carbon::createFromFormat('Y-m-d H:i', $now->format('Y-m-d').' '.$scheduledTime);
|
$scheduledCheckIn = Carbon::createFromFormat('Y-m-d H:i', $now->format('Y-m-d').' '.$scheduledTime);
|
||||||
|
|
||||||
$employees = Employee::query()
|
$employees = Employee::query()
|
||||||
->where('status', EmployeeStatus::ACTIVE)
|
->whereHas('user', fn ($query) => $query->active())
|
||||||
->whereNotNull('user_id')
|
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
$sentCount = 0;
|
$sentCount = 0;
|
||||||
@ -51,7 +49,7 @@ public function handle(PushNotificationService $pushNotificationService): int
|
|||||||
'⏰ Pengingat Presensi',
|
'⏰ Pengingat Presensi',
|
||||||
"Jangan lupa melakukan presensi masuk sebelum pukul {$scheduledTime}.",
|
"Jangan lupa melakukan presensi masuk sebelum pukul {$scheduledTime}.",
|
||||||
$employee->user_id,
|
$employee->user_id,
|
||||||
'/admin/hr/attendances',
|
route('admin.hr.attendances.index'),
|
||||||
);
|
);
|
||||||
|
|
||||||
$sentCount++;
|
$sentCount++;
|
||||||
|
|||||||
@ -97,7 +97,7 @@ public function deposit(CashAccount $cashAccount, array $validated, User $user):
|
|||||||
'💰 Setoran Kas',
|
'💰 Setoran Kas',
|
||||||
"Setoran kas baru {$transaction->amount_formatted} dengan keterangan: {$transaction->description} oleh {$user->profile?->full_name}.",
|
"Setoran kas baru {$transaction->amount_formatted} dengan keterangan: {$transaction->description} oleh {$user->profile?->full_name}.",
|
||||||
['owner', 'developer', 'admin-toko'],
|
['owner', 'developer', 'admin-toko'],
|
||||||
'/admin/finance/cash',
|
route('admin.finance.cash.index'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $transaction;
|
return $transaction;
|
||||||
@ -141,7 +141,7 @@ public function withdraw(CashAccount $cashAccount, array $validated, User $user)
|
|||||||
'🏦 Tarik Kas',
|
'🏦 Tarik Kas',
|
||||||
"Tarik kas {$transaction->amount_formatted} dengan keterangan: {$transaction->description} oleh {$user->profile?->full_name}.",
|
"Tarik kas {$transaction->amount_formatted} dengan keterangan: {$transaction->description} oleh {$user->profile?->full_name}.",
|
||||||
['owner', 'developer', 'admin-toko'],
|
['owner', 'developer', 'admin-toko'],
|
||||||
'/admin/finance/cash',
|
route('admin.finance.cash.index'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $transaction;
|
return $transaction;
|
||||||
@ -250,7 +250,7 @@ public function updateDeposit(CashTransaction $transaction, array $validated): v
|
|||||||
'✏️ Transaksi Kas Diperbarui',
|
'✏️ Transaksi Kas Diperbarui',
|
||||||
"Transaksi kas dengan keterangan {$transaction->description} diperbarui menjadi senilai {$transaction->amount_formatted}.",
|
"Transaksi kas dengan keterangan {$transaction->description} diperbarui menjadi senilai {$transaction->amount_formatted}.",
|
||||||
['owner', 'developer', 'admin-toko'],
|
['owner', 'developer', 'admin-toko'],
|
||||||
'/admin/finance/cash',
|
route('admin.finance.cash.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ public function deleteTransaction(CashTransaction $transaction): void
|
|||||||
'🗑️ Transaksi Kas Dihapus',
|
'🗑️ Transaksi Kas Dihapus',
|
||||||
"Transaksi kas senilai {$transaction->amount_formatted} dengan keterangan {$transaction->description} telah dihapus.",
|
"Transaksi kas senilai {$transaction->amount_formatted} dengan keterangan {$transaction->description} telah dihapus.",
|
||||||
['owner', 'developer', 'admin-toko'],
|
['owner', 'developer', 'admin-toko'],
|
||||||
'/admin/finance/cash',
|
route('admin.finance.cash.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -90,7 +90,7 @@ public function create(array $validated, User $user): void
|
|||||||
'💰 Pengajuan Kasbon Baru',
|
'💰 Pengajuan Kasbon Baru',
|
||||||
"Karyawan {$user->profil?->full_name} mengajukan kasbon sebesar {$employeeAdvance->amount_formatted} dengan keterangan: {$employeeAdvance->description}.",
|
"Karyawan {$user->profil?->full_name} mengajukan kasbon sebesar {$employeeAdvance->amount_formatted} dengan keterangan: {$employeeAdvance->description}.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/finance/employee-advances',
|
route('admin.finance.employee-advances.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ public function update(EmployeeAdvance $employeeAdvance, array $validated, User
|
|||||||
'✏️ Kasbon Diperbarui',
|
'✏️ Kasbon Diperbarui',
|
||||||
"Kasbon sebesar {$employeeAdvance->amount_formatted} telah diperbarui oleh {$user->profile?->full_name}.",
|
"Kasbon sebesar {$employeeAdvance->amount_formatted} telah diperbarui oleh {$user->profile?->full_name}.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/finance/employee-advances',
|
route('admin.finance.employee-advances.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ public function delete(EmployeeAdvance $employeeAdvance, User $user): void
|
|||||||
'🗑️ Kasbon Dihapus',
|
'🗑️ Kasbon Dihapus',
|
||||||
"Kasbon sebesar {$amount} dengan keterangan {$description} telah dihapus.",
|
"Kasbon sebesar {$amount} dengan keterangan {$description} telah dihapus.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/finance/employee-advances',
|
route('admin.finance.employee-advances.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ public function approve(EmployeeAdvance $employeeAdvance, User $user): void
|
|||||||
'💰 Kasbon Disetujui',
|
'💰 Kasbon Disetujui',
|
||||||
"Pengajuan kasbon Anda sebesar {$employeeAdvance->amount_formatted} telah disetujui.",
|
"Pengajuan kasbon Anda sebesar {$employeeAdvance->amount_formatted} telah disetujui.",
|
||||||
$employeeAdvance->employee->user_id,
|
$employeeAdvance->employee->user_id,
|
||||||
'/admin/finance/employee-advances',
|
route('admin.finance.employee-advances.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,7 +187,7 @@ public function reject(EmployeeAdvance $employeeAdvance, string $reason, User $u
|
|||||||
'💰 Kasbon Ditolak',
|
'💰 Kasbon Ditolak',
|
||||||
"Pengajuan kasbon Anda sebesar {$employeeAdvance->amount_formatted} ditolak dengan alasan: {$reason}.",
|
"Pengajuan kasbon Anda sebesar {$employeeAdvance->amount_formatted} ditolak dengan alasan: {$reason}.",
|
||||||
$employeeAdvance->employee->user_id,
|
$employeeAdvance->employee->user_id,
|
||||||
'/admin/finance/employee-advances',
|
route('admin.finance.employee-advances.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,7 +85,7 @@ public function create(array $validated, User $user): void
|
|||||||
'💸 Pengeluaran Baru',
|
'💸 Pengeluaran Baru',
|
||||||
"Pengeluaran baru sebesar {$expense->amount_formatted} dengan keterangan {$expense->description} telah dicatat oleh {$user->profile?->full_name}.",
|
"Pengeluaran baru sebesar {$expense->amount_formatted} dengan keterangan {$expense->description} telah dicatat oleh {$user->profile?->full_name}.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/finance/expenses',
|
route('admin.finance.expenses.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ public function update(Expense $expense, array $validated): void
|
|||||||
'✏️ Pengeluaran Diperbarui',
|
'✏️ Pengeluaran Diperbarui',
|
||||||
"Pengeluaran dengan keterangan {$expense->description} diperbarui menjadi sebesar {$expense->amount_formatted}.",
|
"Pengeluaran dengan keterangan {$expense->description} diperbarui menjadi sebesar {$expense->amount_formatted}.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/finance/expenses',
|
route('admin.finance.expenses.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ public function delete(Expense $expense): void
|
|||||||
'🗑️ Pengeluaran Dihapus',
|
'🗑️ Pengeluaran Dihapus',
|
||||||
"Pengeluaran sebesar {$expense->amount_formatted} dengan keterangan {$expense->description} telah dihapus.",
|
"Pengeluaran sebesar {$expense->amount_formatted} dengan keterangan {$expense->description} telah dihapus.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/finance/expenses',
|
route('admin.finance.expenses.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -224,7 +224,7 @@ public function addAdjustment(Payroll $payroll, array $validated, User $user): v
|
|||||||
"📊 Penyesuaian Gaji: {$typeLabel}",
|
"📊 Penyesuaian Gaji: {$typeLabel}",
|
||||||
"Gaji periode {$payroll->payrollPeriod->period_label} disesuaikan: {$typeLabel} sebesar {$formattedAmount} ({$validated['description']}).",
|
"Gaji periode {$payroll->payrollPeriod->period_label} disesuaikan: {$typeLabel} sebesar {$formattedAmount} ({$validated['description']}).",
|
||||||
$payroll->employee->user_id,
|
$payroll->employee->user_id,
|
||||||
'/admin/finance/payrolls',
|
route('admin.finance.payroll.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,7 +252,7 @@ public function updateAdjustment(PayrollAdjustment $adjustment, array $validated
|
|||||||
"📊 Penyesuaian Gaji Diperbarui: {$typeLabel}",
|
"📊 Penyesuaian Gaji Diperbarui: {$typeLabel}",
|
||||||
"Penyesuaian gaji Anda untuk periode {$payroll->payrollPeriod->period_label} diperbarui: {$typeLabel} menjadi {$formattedAmount} ({$validated['description']}).",
|
"Penyesuaian gaji Anda untuk periode {$payroll->payrollPeriod->period_label} diperbarui: {$typeLabel} menjadi {$formattedAmount} ({$validated['description']}).",
|
||||||
$payroll->employee->user_id,
|
$payroll->employee->user_id,
|
||||||
'/admin/finance/payrolls',
|
route('admin.finance.payroll.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,7 +275,7 @@ public function deleteAdjustment(PayrollAdjustment $adjustment): void
|
|||||||
'📊 Penyesuaian Gaji Dihapus',
|
'📊 Penyesuaian Gaji Dihapus',
|
||||||
"Penyesuaian gaji Anda untuk periode {$payroll->payrollPeriod->period_label} telah dihapus.",
|
"Penyesuaian gaji Anda untuk periode {$payroll->payrollPeriod->period_label} telah dihapus.",
|
||||||
$payroll->employee->user_id,
|
$payroll->employee->user_id,
|
||||||
'/admin/finance/payrolls',
|
route('admin.finance.payroll.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,7 +325,7 @@ public function pay(Payroll $payroll, User $user): void
|
|||||||
'💸 Gaji Dibayarkan',
|
'💸 Gaji Dibayarkan',
|
||||||
"Gaji Anda untuk periode {$payroll->payrollPeriod->period_label} senilai {$payroll->total_amount_formatted} telah dibayarkan.",
|
"Gaji Anda untuk periode {$payroll->payrollPeriod->period_label} senilai {$payroll->total_amount_formatted} telah dibayarkan.",
|
||||||
$payroll->employee->user_id,
|
$payroll->employee->user_id,
|
||||||
'/admin/finance/payrolls',
|
route('admin.finance.payroll.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -105,7 +105,7 @@ public function checkIn(array $validated, User $user): void
|
|||||||
'⏰ Presensi Masuk',
|
'⏰ Presensi Masuk',
|
||||||
"Karyawan {$user->profile?->full_name} melakukan presensi masuk.",
|
"Karyawan {$user->profile?->full_name} melakukan presensi masuk.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/hr/attendances',
|
route('admin.hr.attendances.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ public function checkOut(array $validated, User $user): void
|
|||||||
'⏰ Presensi Pulang',
|
'⏰ Presensi Pulang',
|
||||||
"Karyawan {$user->profile?->full_name} melakukan presensi pulang (Durasi kerja: ".round($workDurationMinutes / 60, 1).' jam).',
|
"Karyawan {$user->profile?->full_name} melakukan presensi pulang (Durasi kerja: ".round($workDurationMinutes / 60, 1).' jam).',
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/hr/attendances',
|
route('admin.hr.attendances.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ public function delete(Attendance $attendance): void
|
|||||||
'🗑️ Presensi Dihapus',
|
'🗑️ Presensi Dihapus',
|
||||||
"Data presensi {$employeeName} tanggal {$date} telah dihapus.",
|
"Data presensi {$employeeName} tanggal {$date} telah dihapus.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/hr/attendances',
|
route('admin.hr.attendances.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,7 +83,7 @@ public function create(array $validated, User $user): void
|
|||||||
'🏖️ Pengajuan Cuti Baru',
|
'🏖️ Pengajuan Cuti Baru',
|
||||||
"Karyawan {$user->profile?->full_name} mengajukan cuti selama {$leaveRequest->total_days} hari mulai dari tanggal {$leaveRequest->start_date_formatted}.",
|
"Karyawan {$user->profile?->full_name} mengajukan cuti selama {$leaveRequest->total_days} hari mulai dari tanggal {$leaveRequest->start_date_formatted}.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/hr/leave-requests',
|
route('admin.hr.leave_requests.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ public function update(LeaveRequest $leaveRequest, array $validated, User $user)
|
|||||||
'✏️ Pengajuan Cuti Diperbarui',
|
'✏️ Pengajuan Cuti Diperbarui',
|
||||||
"Pengajuan cuti oleh {$user->profile?->full_name} telah diperbarui.",
|
"Pengajuan cuti oleh {$user->profile?->full_name} telah diperbarui.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/hr/leave-requests',
|
route('admin.hr.leave_requests.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ public function delete(LeaveRequest $leaveRequest): void
|
|||||||
'🗑️ Pengajuan Cuti Dihapus',
|
'🗑️ Pengajuan Cuti Dihapus',
|
||||||
"Pengajuan cuti {$totalDays} hari oleh {$employeeName} telah dihapus.",
|
"Pengajuan cuti {$totalDays} hari oleh {$employeeName} telah dihapus.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/hr/leave-requests',
|
route('admin.hr.leave_requests.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ public function approve(LeaveRequest $leaveRequest, User $user): void
|
|||||||
'🏖️ Pengajuan Cuti Disetujui',
|
'🏖️ Pengajuan Cuti Disetujui',
|
||||||
"Pengajuan cuti Anda selama {$leaveRequest->total_days} hari ({$leaveRequest->start_date_formatted} - {$leaveRequest->end_date_formatted}) telah disetujui.",
|
"Pengajuan cuti Anda selama {$leaveRequest->total_days} hari ({$leaveRequest->start_date_formatted} - {$leaveRequest->end_date_formatted}) telah disetujui.",
|
||||||
$leaveRequest->employee->user_id,
|
$leaveRequest->employee->user_id,
|
||||||
'/admin/hr/leave-requests',
|
route('admin.hr.leave_requests.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,7 +168,7 @@ public function reject(LeaveRequest $leaveRequest, string $reason, User $user):
|
|||||||
'🏖️ Pengajuan Cuti Ditolak',
|
'🏖️ Pengajuan Cuti Ditolak',
|
||||||
"Pengajuan cuti Anda selama {$leaveRequest->total_days} hari ({$leaveRequest->start_date_formatted} - {$leaveRequest->end_date_formatted}) ditolak dengan alasan: '{$reason}'.",
|
"Pengajuan cuti Anda selama {$leaveRequest->total_days} hari ({$leaveRequest->start_date_formatted} - {$leaveRequest->end_date_formatted}) ditolak dengan alasan: '{$reason}'.",
|
||||||
$leaveRequest->employee->user_id,
|
$leaveRequest->employee->user_id,
|
||||||
'/admin/hr/leave-requests',
|
route('admin.hr.leave_requests.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -476,7 +476,7 @@ public function create(array $validated, User $user): Cutting
|
|||||||
'✂️ Proses Cutting Baru',
|
'✂️ Proses Cutting Baru',
|
||||||
"Proses cutting dengan deskripsi ({$cutting->description}) telah dimulai oleh {$user->profile?->full_name}.",
|
"Proses cutting dengan deskripsi ({$cutting->description}) telah dimulai oleh {$user->profile?->full_name}.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/cuttings',
|
route('admin.manage.cuttings.index'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $cutting;
|
return $cutting;
|
||||||
@ -536,7 +536,7 @@ public function update(Cutting $cutting, array $validated): void
|
|||||||
'✏️ Proses Cutting Diperbarui',
|
'✏️ Proses Cutting Diperbarui',
|
||||||
"Proses cutting dengan deskripsi '{$description}' telah diperbarui.",
|
"Proses cutting dengan deskripsi '{$description}' telah diperbarui.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/cuttings',
|
route('admin.manage.cuttings.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +568,7 @@ public function delete(Cutting $cutting): void
|
|||||||
'🗑️ Proses Cutting Dihapus',
|
'🗑️ Proses Cutting Dihapus',
|
||||||
"Proses cutting dengan deskripsi {$description} telah dihapus.",
|
"Proses cutting dengan deskripsi {$description} telah dihapus.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/cuttings',
|
route('admin.manage.cuttings.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,7 +655,7 @@ public function transitionStatus(
|
|||||||
$title,
|
$title,
|
||||||
$message,
|
$message,
|
||||||
$roles,
|
$roles,
|
||||||
'/admin/manage/cuttings',
|
route('admin.manage.cuttings.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -483,7 +483,7 @@ public function create(array $validated, User $user): Order
|
|||||||
'📦 Pesanan Baru',
|
'📦 Pesanan Baru',
|
||||||
"Pesanan baru {$order->order_number} senilai {$order->total_amount_formatted} telah dibuat oleh {$user->profile?->full_name}.",
|
"Pesanan baru {$order->order_number} senilai {$order->total_amount_formatted} telah dibuat oleh {$user->profile?->full_name}.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/orders',
|
route('admin.manage.orders.index'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $order;
|
return $order;
|
||||||
@ -563,7 +563,7 @@ public function update(Order $order, array $validated): void
|
|||||||
'✏️ Pesanan Diperbarui',
|
'✏️ Pesanan Diperbarui',
|
||||||
"Pesanan {$order->order_number} senilai {$order->total_amount_formatted} telah diperbarui.",
|
"Pesanan {$order->order_number} senilai {$order->total_amount_formatted} telah diperbarui.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/orders',
|
route('admin.manage.orders.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,7 +593,7 @@ public function delete(Order $order): void
|
|||||||
'🗑️ Pesanan Dihapus',
|
'🗑️ Pesanan Dihapus',
|
||||||
"Pesanan {$orderNumber} senilai {$order->total_amount_formatted} telah dihapus.",
|
"Pesanan {$orderNumber} senilai {$order->total_amount_formatted} telah dihapus.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/orders',
|
route('admin.manage.orders.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -627,7 +627,7 @@ public function transitionStatus(Order $order, OrderStatus $status): void
|
|||||||
'📦 Status Pesanan Diubah',
|
'📦 Status Pesanan Diubah',
|
||||||
"Pesanan {$order->order_number} diubah statusnya menjadi {$status->label()}.",
|
"Pesanan {$order->order_number} diubah statusnya menjadi {$status->label()}.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/orders',
|
route('admin.manage.orders.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -253,7 +253,7 @@ public function create(array $validated, User $user): Purchase
|
|||||||
'🛒 Belanja Baru',
|
'🛒 Belanja Baru',
|
||||||
"Pembelian dari supplier {$purchase->supplier->name} senilai {$purchase->total_formatted} telah ditambahkan oleh {$user->profile?->full_name}.",
|
"Pembelian dari supplier {$purchase->supplier->name} senilai {$purchase->total_formatted} telah ditambahkan oleh {$user->profile?->full_name}.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/purchases',
|
route('admin.manage.purchases.index'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $purchase;
|
return $purchase;
|
||||||
@ -301,7 +301,7 @@ public function update(Purchase $purchase, array $validated): void
|
|||||||
'✏️ Belanja Diperbarui',
|
'✏️ Belanja Diperbarui',
|
||||||
"Pembelian dari supplier {$purchase->supplier->name} senilai {$purchase->total_formatted} telah diperbarui.",
|
"Pembelian dari supplier {$purchase->supplier->name} senilai {$purchase->total_formatted} telah diperbarui.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/purchases',
|
route('admin.manage.purchases.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ public function delete(Purchase $purchase): void
|
|||||||
'🗑️ Belanja Dihapus',
|
'🗑️ Belanja Dihapus',
|
||||||
"Pembelian dari supplier {$supplierName} senilai {$purchase->total_formatted} telah dihapus.",
|
"Pembelian dari supplier {$supplierName} senilai {$purchase->total_formatted} telah dihapus.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/purchases',
|
route('admin.manage.purchases.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -120,7 +120,7 @@ public function submitVerification(
|
|||||||
'📦 Verifikasi Stok Menunggu Persetujuan',
|
'📦 Verifikasi Stok Menunggu Persetujuan',
|
||||||
"Cutting dengan deskripsi '{$description}' telah diajukan verifikasi dan menunggu persetujuan owner.",
|
"Cutting dengan deskripsi '{$description}' telah diajukan verifikasi dan menunggu persetujuan owner.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/owner-verifications',
|
route('admin.manage.owner_verifications.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ public function approveVerification(
|
|||||||
'📦 Stok Cutting Diverifikasi',
|
'📦 Stok Cutting Diverifikasi',
|
||||||
"Cutting dengan deskripsi '{$description}' telah disetujui owner dan stok produk telah ditambahkan ke toko.",
|
"Cutting dengan deskripsi '{$description}' telah disetujui owner dan stok produk telah ditambahkan ke toko.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/owner-verifications',
|
route('admin.manage.owner_verifications.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ public function rejectVerification(
|
|||||||
'📦 Verifikasi Cutting Ditolak Owner',
|
'📦 Verifikasi Cutting Ditolak Owner',
|
||||||
"Cutting dengan deskripsi '{$description}' ditolak oleh owner dengan alasan: '{$reason}'.",
|
"Cutting dengan deskripsi '{$description}' ditolak oleh owner dengan alasan: '{$reason}'.",
|
||||||
['owner', 'developer'],
|
['owner', 'developer'],
|
||||||
'/admin/manage/owner-verifications',
|
route('admin.manage.owner_verifications.index'),
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($cutting->submitted_by_id) {
|
if ($cutting->submitted_by_id) {
|
||||||
@ -202,7 +202,7 @@ public function rejectVerification(
|
|||||||
'📦 Verifikasi Cutting Ditolak Owner',
|
'📦 Verifikasi Cutting Ditolak Owner',
|
||||||
"Cutting dengan deskripsi '{$description}' yang Anda verifikasi ditolak oleh owner dengan alasan: '{$reason}'.",
|
"Cutting dengan deskripsi '{$description}' yang Anda verifikasi ditolak oleh owner dengan alasan: '{$reason}'.",
|
||||||
$cutting->submitted_by_id,
|
$cutting->submitted_by_id,
|
||||||
'/admin/manage/owner-verifications',
|
route('admin.manage.owner_verifications.index'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import {
|
|||||||
SidebarRail,
|
SidebarRail,
|
||||||
} from '@/components/ui/sidebar';
|
} from '@/components/ui/sidebar';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
|
import admin from '@/routes/admin';
|
||||||
|
|
||||||
const page = usePage();
|
const page = usePage();
|
||||||
const { can } = useCan();
|
const { can } = useCan();
|
||||||
@ -36,52 +37,52 @@ const menuGroups: MenuGroup[] = [
|
|||||||
{
|
{
|
||||||
label: 'Menu',
|
label: 'Menu',
|
||||||
items: [
|
items: [
|
||||||
{ title: 'Dasbor', href: '/admin/dashboard', icon: LayoutDashboard },
|
{ title: 'Dasbor', href: admin.dashboard.url(), icon: LayoutDashboard },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Master',
|
label: 'Master',
|
||||||
items: [
|
items: [
|
||||||
{ title: 'Kategori', href: '/admin/master/categories', icon: FolderTree, permission: 'categories.view' },
|
{ title: 'Kategori', href: admin.master.categories.index.url(), icon: FolderTree, permission: 'categories.view' },
|
||||||
{ title: 'Produk', href: '/admin/master/products', icon: Package, permission: 'products.view' },
|
{ title: 'Produk', href: admin.master.products.index.url(), icon: Package, permission: 'products.view' },
|
||||||
{ title: 'Bahan Baku', href: '/admin/master/raw-materials', icon: Layers, permission: 'raw_materials.view' },
|
{ title: 'Bahan Baku', href: admin.master.raw_materials.index.url(), icon: Layers, permission: 'raw_materials.view' },
|
||||||
{ title: 'Supplier', href: '/admin/master/suppliers', icon: User, permission: 'suppliers.view' },
|
{ title: 'Supplier', href: admin.master.suppliers.index.url(), icon: User, permission: 'suppliers.view' },
|
||||||
{ title: 'Customer', href: '/admin/master/customers', icon: UserCheck, permission: 'customers.view' },
|
{ title: 'Customer', href: admin.master.customers.index.url(), icon: UserCheck, permission: 'customers.view' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Kelola',
|
label: 'Kelola',
|
||||||
items: [
|
items: [
|
||||||
{ title: 'Belanja', href: '/admin/manage/purchases', icon: ShoppingBag, permission: 'purchases.view' },
|
{ title: 'Belanja', href: admin.manage.purchases.index.url(), icon: ShoppingBag, permission: 'purchases.view' },
|
||||||
{ title: 'Cutting', href: '/admin/manage/cuttings', icon: Scissors, permission: 'cuttings.view' },
|
{ title: 'Cutting', href: admin.manage.cuttings.index.url(), icon: Scissors, permission: 'cuttings.view' },
|
||||||
{ title: 'Stok', href: '/admin/manage/stocks', icon: Warehouse, permission: 'stocks.view', badgeKey: 'pendingCuttings' },
|
{ title: 'Stok', href: admin.manage.stocks.index.url(), icon: Warehouse, permission: 'stocks.view', badgeKey: 'pendingCuttings' },
|
||||||
{ title: 'Verifikasi Owner', href: '/admin/manage/owner-verifications', icon: CheckCircle, permission: 'owner_verifications.view', badgeKey: 'pendingOwnerVerifications' },
|
{ title: 'Verifikasi Owner', href: admin.manage.owner_verifications.index.url(), icon: CheckCircle, permission: 'owner_verifications.view', badgeKey: 'pendingOwnerVerifications' },
|
||||||
{ title: 'Pesanan', href: '/admin/manage/orders', icon: ShoppingCart, permission: 'orders.view' },
|
{ title: 'Pesanan', href: admin.manage.orders.index.url(), icon: ShoppingCart, permission: 'orders.view' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Keuangan',
|
label: 'Keuangan',
|
||||||
items: [
|
items: [
|
||||||
{ title: 'Kas Toko', href: '/admin/finance/cash', icon: Wallet, permission: 'cash.view' },
|
{ title: 'Kas Toko', href: admin.finance.cash.index.url(), icon: Wallet, permission: 'cash.view' },
|
||||||
{ title: 'Pengeluaran', href: '/admin/finance/expenses', icon: Receipt, permission: 'expenses.view' },
|
{ title: 'Pengeluaran', href: admin.finance.expenses.index.url(), icon: Receipt, permission: 'expenses.view' },
|
||||||
{ title: 'Kasbon', href: '/admin/finance/employee-advances', icon: Banknote, permission: 'employee_advances.view', badgeKey: 'pendingEmployeeAdvances' },
|
{ title: 'Kasbon', href: admin.finance.employee_advances.index.url(), icon: Banknote, permission: 'employee_advances.view', badgeKey: 'pendingEmployeeAdvances' },
|
||||||
{ title: 'Gaji', href: '/admin/finance/payroll', icon: WalletCards, permission: 'payroll.view' },
|
{ title: 'Gaji', href: admin.finance.payroll.index.url(), icon: WalletCards, permission: 'payroll.view' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'HR',
|
label: 'HR',
|
||||||
items: [
|
items: [
|
||||||
{ title: 'Pegawai', href: '/admin/hr/employees', icon: Users, permission: 'employees.view' },
|
{ title: 'Pegawai', href: admin.hr.employees.index.url(), icon: Users, permission: 'employees.view' },
|
||||||
{ title: 'Presensi', href: '/admin/hr/attendances', icon: Clock, permission: 'attendances.view' },
|
{ title: 'Presensi', href: admin.hr.attendances.index.url(), icon: Clock, permission: 'attendances.view' },
|
||||||
{ title: 'Cuti', href: '/admin/hr/leave-requests', icon: CalendarDays, permission: 'leave_requests.view', badgeKey: 'pendingLeaveRequests' },
|
{ title: 'Cuti', href: admin.hr.leave_requests.index.url(), icon: CalendarDays, permission: 'leave_requests.view', badgeKey: 'pendingLeaveRequests' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Sistem',
|
label: 'Sistem',
|
||||||
items: [
|
items: [
|
||||||
{ title: 'Role & Permission', href: '/admin/system/roles', icon: Shield, permission: 'roles.view' },
|
{ title: 'Role & Permission', href: admin.system.roles.index.url(), icon: Shield, permission: 'roles.view' },
|
||||||
{ title: 'Pengaturan', href: '/admin/system/settings', icon: Settings2, permission: 'settings.view' },
|
{ title: 'Pengaturan', href: admin.system.settings.index.url(), icon: Settings2, permission: 'settings.view' },
|
||||||
{ title: 'Log Aktivitas', href: '/admin/system/activity-logs', icon: History, permission: 'activity_logs.view' },
|
{ title: 'Log Aktivitas', href: admin.system.activity_logs.index.url(), icon: History, permission: 'activity_logs.view' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -93,7 +94,7 @@ const menuGroups: MenuGroup[] = [
|
|||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
<SidebarMenuButton size="lg" as-child>
|
<SidebarMenuButton size="lg" as-child>
|
||||||
<Link href="/admin/dashboard">
|
<Link :href="admin.dashboard.url()">
|
||||||
<img
|
<img
|
||||||
v-if="page.props.logo_url"
|
v-if="page.props.logo_url"
|
||||||
:src="page.props.logo_url"
|
:src="page.props.logo_url"
|
||||||
|
|||||||
@ -13,6 +13,8 @@ import {
|
|||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/components/ui/dropdown-menu';
|
||||||
import { usePushNotification } from '@/composables/usePushNotification';
|
import { usePushNotification } from '@/composables/usePushNotification';
|
||||||
import Separator from './ui/separator/Separator.vue';
|
import Separator from './ui/separator/Separator.vue';
|
||||||
|
import { logout as logoutRoute } from '@/routes';
|
||||||
|
import { profile } from '@/routes/admin/account';
|
||||||
|
|
||||||
const page = usePage();
|
const page = usePage();
|
||||||
|
|
||||||
@ -27,7 +29,7 @@ const initials = computed(() => {
|
|||||||
const { isSupported, isSubscribed, isLoading, toggle } = usePushNotification();
|
const { isSupported, isSubscribed, isLoading, toggle } = usePushNotification();
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
router.post('/auth/logout');
|
router.post(logoutRoute.url());
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -69,7 +71,7 @@ function logout() {
|
|||||||
</div>
|
</div>
|
||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem @click="router.visit('/admin/account/profile')">
|
<DropdownMenuItem @click="router.visit(profile.url())">
|
||||||
<User />
|
<User />
|
||||||
Profil
|
Profil
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
|||||||
@ -5,23 +5,25 @@ import { computed } from 'vue';
|
|||||||
import AdminLayout from '@/layouts/AdminLayout.vue';
|
import AdminLayout from '@/layouts/AdminLayout.vue';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
|
import { profile, password, appearance } from '@/routes/admin/account';
|
||||||
|
|
||||||
const page = usePage();
|
const page = usePage();
|
||||||
|
|
||||||
const currentPath = computed(() => page.url.split('?')[0]);
|
const currentPath = computed(() => page.url.split('?')[0]);
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{
|
{
|
||||||
href: '/admin/account/profile',
|
href: profile.url(),
|
||||||
label: 'Profil',
|
label: 'Profil',
|
||||||
icon: User,
|
icon: User,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: '/admin/account/password',
|
href: password.url(),
|
||||||
label: 'Kata Sandi',
|
label: 'Kata Sandi',
|
||||||
icon: KeyRound,
|
icon: KeyRound,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: '/admin/account/appearance',
|
href: appearance.url(),
|
||||||
label: 'Tampilan',
|
label: 'Tampilan',
|
||||||
icon: Palette,
|
icon: Palette,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -19,6 +19,8 @@ import { formErrors } from '@/lib/form';
|
|||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import type { AppearanceFormData, AppearanceMode } from '@/types/account';
|
import type { AppearanceFormData, AppearanceMode } from '@/types/account';
|
||||||
|
|
||||||
|
import { update } from '@/routes/admin/account/appearance';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
appearance: AppearanceMode;
|
appearance: AppearanceMode;
|
||||||
}>();
|
}>();
|
||||||
@ -63,7 +65,7 @@ function onAppearanceChange(value: AcceptableValue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
form.put('/admin/account/appearance', {
|
form.put(update.url(), {
|
||||||
onError: () => {
|
onError: () => {
|
||||||
toast.error('Gagal menyimpan tampilan.');
|
toast.error('Gagal menyimpan tampilan.');
|
||||||
},
|
},
|
||||||
|
|||||||
@ -17,6 +17,8 @@ import AccountLayout from '@/layouts/AccountLayout.vue';
|
|||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import type { PasswordFormData } from '@/types/account';
|
import type { PasswordFormData } from '@/types/account';
|
||||||
|
|
||||||
|
import { update } from '@/routes/admin/account/password';
|
||||||
|
|
||||||
const form = useForm<PasswordFormData>({
|
const form = useForm<PasswordFormData>({
|
||||||
current_password: '',
|
current_password: '',
|
||||||
password: '',
|
password: '',
|
||||||
@ -28,7 +30,7 @@ const showPassword = ref(false);
|
|||||||
const showPasswordConfirmation = ref(false);
|
const showPasswordConfirmation = ref(false);
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
form.put('/admin/account/password', {
|
form.put(update.url(), {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
form.reset();
|
form.reset();
|
||||||
},
|
},
|
||||||
|
|||||||
@ -25,6 +25,8 @@ import type {
|
|||||||
ProfileUser,
|
ProfileUser,
|
||||||
} from '@/types/account';
|
} from '@/types/account';
|
||||||
|
|
||||||
|
import { update } from '@/routes/admin/account/profile';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
user: ProfileUser;
|
user: ProfileUser;
|
||||||
genders: EnumOption[];
|
genders: EnumOption[];
|
||||||
@ -41,7 +43,7 @@ const form = useForm<ProfileFormData>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
form.put('/admin/account/profile', {
|
form.put(update.url(), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onError: () => {
|
onError: () => {
|
||||||
toast.error('Gagal menyimpan profil. Periksa kembali formulir.');
|
toast.error('Gagal menyimpan profil. Periksa kembali formulir.');
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import type { CashAccount, CashTransactionListItem, PaginatedCashTransactions }
|
|||||||
import type { DataTableFilterDef, DataTableSort } from '@/types/data-table';
|
import type { DataTableFilterDef, DataTableSort } from '@/types/data-table';
|
||||||
import CashTransactionFormModal from './form/CashTransactionFormModal.vue';
|
import CashTransactionFormModal from './form/CashTransactionFormModal.vue';
|
||||||
import { createColumns } from './table/columns';
|
import { createColumns } from './table/columns';
|
||||||
|
import { index } from '@/routes/admin/finance/cash';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
cashAccount: CashAccount;
|
cashAccount: CashAccount;
|
||||||
@ -33,7 +34,7 @@ const formModalMode = ref<'deposit' | 'withdrawal'>(CashTransactionType.DEPOSIT)
|
|||||||
const editingTransaction = ref<CashTransactionListItem | null>(null);
|
const editingTransaction = ref<CashTransactionListItem | null>(null);
|
||||||
|
|
||||||
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } = useDataTableQuery({
|
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } = useDataTableQuery({
|
||||||
url: '/admin/finance/cash',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
filterKeys: ['reference_type'],
|
filterKeys: ['reference_type'],
|
||||||
});
|
});
|
||||||
|
|||||||
@ -29,6 +29,8 @@ import { parseRupiah } from '@/lib/rupiah';
|
|||||||
import type { CashTransactionListItem } from '@/types/cash';
|
import type { CashTransactionListItem } from '@/types/cash';
|
||||||
import { appendRootPhotosToFormData, createMediaUploadState } from '@/types/media';
|
import { appendRootPhotosToFormData, createMediaUploadState } from '@/types/media';
|
||||||
import type { MediaUploadState } from '@/types/media';
|
import type { MediaUploadState } from '@/types/media';
|
||||||
|
import { withdraw, deposit } from '@/routes/admin/finance/cash';
|
||||||
|
import { update } from '@/routes/admin/finance/cash/transactions';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -111,12 +113,12 @@ function submit() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isEditing.value && props.transaction) {
|
if (isEditing.value && props.transaction) {
|
||||||
form.transform(() => payload).put(`/admin/finance/cash/transactions/${props.transaction.id}`, options);
|
form.transform(() => payload).put(update.url(props.transaction.id), options);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const endpoint = isWithdrawal.value ? '/admin/finance/cash/withdraw' : '/admin/finance/cash/deposit';
|
const endpoint = isWithdrawal.value ? withdraw.url() : deposit.url();
|
||||||
|
|
||||||
form.transform(() => payload).post(endpoint, options);
|
form.transform(() => payload).post(endpoint, options);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { CashTransactionListItem } from '@/types/cash';
|
import type { CashTransactionListItem } from '@/types/cash';
|
||||||
|
import { destroy } from '@/routes/admin/finance/cash/transactions';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
transaction: CashTransactionListItem;
|
transaction: CashTransactionListItem;
|
||||||
@ -27,7 +28,7 @@ const deleteProcessing = ref(false);
|
|||||||
function destroyTransaction() {
|
function destroyTransaction() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/finance/cash/transactions/${props.transaction.id}`, {
|
router.delete(destroy.url(props.transaction.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
|
|||||||
@ -21,6 +21,8 @@ import EmployeeAdvanceFormModal from './form/EmployeeAdvanceFormModal.vue';
|
|||||||
import RejectEmployeeAdvanceModal from './form/RejectEmployeeAdvanceModal.vue';
|
import RejectEmployeeAdvanceModal from './form/RejectEmployeeAdvanceModal.vue';
|
||||||
import { createColumns } from './table/columns';
|
import { createColumns } from './table/columns';
|
||||||
|
|
||||||
|
import { index } from '@/routes/admin/finance/employee_advances';
|
||||||
|
|
||||||
const props = defineProps<EmployeeAdvancePageProps>();
|
const props = defineProps<EmployeeAdvancePageProps>();
|
||||||
|
|
||||||
const { can } = useCan();
|
const { can } = useCan();
|
||||||
@ -32,7 +34,7 @@ const rejectingEmployeeAdvance = ref<EmployeeAdvanceListItem | null>(null);
|
|||||||
|
|
||||||
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } =
|
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } =
|
||||||
useDataTableQuery({
|
useDataTableQuery({
|
||||||
url: '/admin/finance/employee-advances',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
filterKeys: ['status'],
|
filterKeys: ['status'],
|
||||||
});
|
});
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import { FIELD_LIMITS } from '@/lib/field-limits';
|
|||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import { parseRupiah } from '@/lib/rupiah';
|
import { parseRupiah } from '@/lib/rupiah';
|
||||||
import type { EmployeeAdvanceFormData, EmployeeAdvanceListItem } from '@/types/employee-advance';
|
import type { EmployeeAdvanceFormData, EmployeeAdvanceListItem } from '@/types/employee-advance';
|
||||||
|
import { store, update } from '@/routes/admin/finance/employee_advances';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -94,12 +95,12 @@ function submit() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isEditing.value && props.employeeAdvance) {
|
if (isEditing.value && props.employeeAdvance) {
|
||||||
form.transform(() => payload).put(`/admin/finance/employee-advances/${props.employeeAdvance.id}`, options);
|
form.transform(() => payload).put(update.url(props.employeeAdvance.id), options);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.transform(() => payload).post('/admin/finance/employee-advances', options);
|
form.transform(() => payload).post(store.url(), options);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import { Textarea } from '@/components/ui/textarea';
|
|||||||
import { FIELD_LIMITS } from '@/lib/field-limits';
|
import { FIELD_LIMITS } from '@/lib/field-limits';
|
||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import type { EmployeeAdvanceListItem } from '@/types/employee-advance';
|
import type { EmployeeAdvanceListItem } from '@/types/employee-advance';
|
||||||
|
import { reject } from '@/routes/admin/finance/employee_advances';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ function submit() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.post(`/admin/finance/employee-advances/${props.employeeAdvance.id}/reject`, {
|
form.post(reject.url(props.employeeAdvance.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
open.value = false;
|
open.value = false;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { EmployeeAdvanceListItem } from '@/types/employee-advance';
|
import type { EmployeeAdvanceListItem } from '@/types/employee-advance';
|
||||||
|
import { destroy, approve, pay } from '@/routes/admin/finance/employee_advances';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
employeeAdvance: EmployeeAdvanceListItem;
|
employeeAdvance: EmployeeAdvanceListItem;
|
||||||
@ -50,7 +51,7 @@ const payProcessing = ref(false);
|
|||||||
function destroyEmployeeAdvance() {
|
function destroyEmployeeAdvance() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/finance/employee-advances/${props.employeeAdvance.id}`, {
|
router.delete(destroy.url(props.employeeAdvance.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
@ -67,7 +68,7 @@ function destroyEmployeeAdvance() {
|
|||||||
function approveEmployeeAdvance() {
|
function approveEmployeeAdvance() {
|
||||||
approveProcessing.value = true;
|
approveProcessing.value = true;
|
||||||
|
|
||||||
router.post(`/admin/finance/employee-advances/${props.employeeAdvance.id}/approve`, {}, {
|
router.post(approve.url(props.employeeAdvance.id), {}, {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
approveConfirmOpen.value = false;
|
approveConfirmOpen.value = false;
|
||||||
@ -84,7 +85,7 @@ function approveEmployeeAdvance() {
|
|||||||
function payEmployeeAdvance() {
|
function payEmployeeAdvance() {
|
||||||
payProcessing.value = true;
|
payProcessing.value = true;
|
||||||
|
|
||||||
router.post(`/admin/finance/employee-advances/${props.employeeAdvance.id}/pay`, {}, {
|
router.post(pay.url(props.employeeAdvance.id), {}, {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
payConfirmOpen.value = false;
|
payConfirmOpen.value = false;
|
||||||
|
|||||||
@ -15,6 +15,8 @@ import { computed, ref, watch } from 'vue';
|
|||||||
import ExpenseFormModal from './form/ExpenseFormModal.vue';
|
import ExpenseFormModal from './form/ExpenseFormModal.vue';
|
||||||
import { createColumns } from './table/columns';
|
import { createColumns } from './table/columns';
|
||||||
|
|
||||||
|
import { index } from '@/routes/admin/finance/expenses';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
expenses: PaginatedExpenses;
|
expenses: PaginatedExpenses;
|
||||||
filters: {
|
filters: {
|
||||||
@ -31,7 +33,7 @@ const editingExpense = ref<ExpenseListItem | null>(null);
|
|||||||
|
|
||||||
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
||||||
useDataTableQuery({
|
useDataTableQuery({
|
||||||
url: '/admin/finance/expenses',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,8 @@ import type { ExpenseListItem } from '@/types/expense';
|
|||||||
import { appendRootPhotosToFormData, createMediaUploadState } from '@/types/media';
|
import { appendRootPhotosToFormData, createMediaUploadState } from '@/types/media';
|
||||||
import type { MediaUploadState } from '@/types/media';
|
import type { MediaUploadState } from '@/types/media';
|
||||||
|
|
||||||
|
import { store, update } from '@/routes/admin/finance/expenses';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -99,12 +101,12 @@ function submit() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isEditing.value && props.expense) {
|
if (isEditing.value && props.expense) {
|
||||||
form.transform(() => payload).put(`/admin/finance/expenses/${props.expense.id}`, options);
|
form.transform(() => payload).put(update.url(props.expense.id), options);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.transform(() => payload).post('/admin/finance/expenses', options);
|
form.transform(() => payload).post(store.url(), options);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,8 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip
|
|||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { ExpenseListItem } from '@/types/expense';
|
import type { ExpenseListItem } from '@/types/expense';
|
||||||
|
|
||||||
|
import { destroy } from '@/routes/admin/finance/expenses';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
expense: ExpenseListItem;
|
expense: ExpenseListItem;
|
||||||
}>();
|
}>();
|
||||||
@ -25,7 +27,7 @@ const deleteProcessing = ref(false);
|
|||||||
function destroyExpense() {
|
function destroyExpense() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/finance/expenses/${props.expense.id}`, {
|
router.delete(destroy.url(props.expense.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
|
|||||||
@ -27,6 +27,8 @@ import type { PayrollListItem, PayrollPageProps } from '@/types/payroll';
|
|||||||
import PayrollAdjustmentModal from './form/PayrollAdjustmentModal.vue';
|
import PayrollAdjustmentModal from './form/PayrollAdjustmentModal.vue';
|
||||||
import { createColumns } from './table/columns';
|
import { createColumns } from './table/columns';
|
||||||
|
|
||||||
|
import { index } from '@/routes/admin/finance/payroll';
|
||||||
|
|
||||||
const props = defineProps<PayrollPageProps>();
|
const props = defineProps<PayrollPageProps>();
|
||||||
|
|
||||||
const { can } = useCan();
|
const { can } = useCan();
|
||||||
@ -48,7 +50,7 @@ const currentAdjustingPayroll = computed(() => {
|
|||||||
|
|
||||||
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } =
|
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } =
|
||||||
useDataTableQuery({
|
useDataTableQuery({
|
||||||
url: '/admin/finance/payroll',
|
url: index.url(),
|
||||||
initial: {
|
initial: {
|
||||||
...props.filters,
|
...props.filters,
|
||||||
period_id: props.filters.period_id
|
period_id: props.filters.period_id
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import { FIELD_LIMITS } from '@/lib/field-limits';
|
|||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import { parseRupiah } from '@/lib/rupiah';
|
import { parseRupiah } from '@/lib/rupiah';
|
||||||
import type { PayrollAdjustmentFormData, PayrollAdjustmentItem, PayrollListItem, SelectOption } from '@/types/payroll';
|
import type { PayrollAdjustmentFormData, PayrollAdjustmentItem, PayrollListItem, SelectOption } from '@/types/payroll';
|
||||||
|
import { store, update, destroy } from '@/routes/admin/finance/payroll/adjustments';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ function cancelEdit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function deleteAdj(adjustment: PayrollAdjustmentItem) {
|
function deleteAdj(adjustment: PayrollAdjustmentItem) {
|
||||||
router.delete(`/admin/finance/payroll/adjustments/${adjustment.id}`, {
|
router.delete(destroy.url(adjustment.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
toast.success('Penyesuaian berhasil dihapus.');
|
toast.success('Penyesuaian berhasil dihapus.');
|
||||||
@ -98,7 +99,7 @@ function submit() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
if (editingAdjustment.value) {
|
if (editingAdjustment.value) {
|
||||||
payload.put(`/admin/finance/payroll/adjustments/${editingAdjustment.value.id}`, {
|
payload.put(update.url(editingAdjustment.value.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
cancelEdit();
|
cancelEdit();
|
||||||
@ -108,7 +109,7 @@ function submit() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
payload.post(`/admin/finance/payroll/${props.payroll.id}/adjustments`, {
|
payload.post(store.url(props.payroll.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
resetForm();
|
resetForm();
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { useForm } from '@inertiajs/vue3';
|
|||||||
import { Camera, Loader2 } from '@lucide/vue';
|
import { Camera, Loader2 } from '@lucide/vue';
|
||||||
import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue';
|
import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue';
|
||||||
import { toast } from 'vue-sonner';
|
import { toast } from 'vue-sonner';
|
||||||
|
import { check_in, check_out } from '@/routes/admin/hr/attendances';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -44,8 +45,8 @@ const submitLabel = computed(() =>
|
|||||||
);
|
);
|
||||||
const submitUrl = computed(() =>
|
const submitUrl = computed(() =>
|
||||||
props.mode === 'check-in'
|
props.mode === 'check-in'
|
||||||
? '/admin/hr/attendances/check-in'
|
? check_in.url()
|
||||||
: '/admin/hr/attendances/check-out',
|
: check_out.url(),
|
||||||
);
|
);
|
||||||
|
|
||||||
async function initializeCamera() {
|
async function initializeCamera() {
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { DatePicker } from '@/components/ui/date-picker';
|
import { DatePicker } from '@/components/ui/date-picker';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import type { AttendanceListItem, CalendarRange } from '@/types/attendance';
|
import type { AttendanceListItem, CalendarRange } from '@/types/attendance';
|
||||||
|
import { index } from '@/routes/admin/hr/attendances';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
attendances: AttendanceListItem[];
|
attendances: AttendanceListItem[];
|
||||||
@ -180,7 +181,7 @@ function handleDatesSet(arg: DatesSetArg) {
|
|||||||
|
|
||||||
isNavigating.value = true;
|
isNavigating.value = true;
|
||||||
|
|
||||||
router.get('/admin/hr/attendances', { start, end }, {
|
router.get(index.url(), { start, end }, {
|
||||||
preserveState: true,
|
preserveState: true,
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
only: ['attendances', 'calendarRange'],
|
only: ['attendances', 'calendarRange'],
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import {
|
|||||||
} from '@/components/ui/dialog';
|
} from '@/components/ui/dialog';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { AttendanceListItem } from '@/types/attendance';
|
import type { AttendanceListItem } from '@/types/attendance';
|
||||||
|
import { destroy } from '@/routes/admin/hr/attendances';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { required: true });
|
const open = defineModel<boolean>('open', { required: true });
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ function destroyAttendance() {
|
|||||||
|
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/hr/attendances/${props.attendance.id}`, {
|
router.delete(destroy.url(props.attendance.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { AttendanceListItem } from '@/types/attendance';
|
import type { AttendanceListItem } from '@/types/attendance';
|
||||||
|
import { destroy } from '@/routes/admin/hr/attendances';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
attendance: AttendanceListItem;
|
attendance: AttendanceListItem;
|
||||||
@ -21,7 +22,7 @@ const deleteProcessing = ref(false);
|
|||||||
function destroyAttendance() {
|
function destroyAttendance() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/hr/attendances/${props.attendance.id}`, {
|
router.delete(destroy.url(props.attendance.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import AdminLayout from '@/layouts/AdminLayout.vue';
|
|||||||
import type { EnumOption } from '@/types/employee';
|
import type { EnumOption } from '@/types/employee';
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import EmployeeForm from './form/EmployeeForm.vue';
|
import EmployeeForm from './form/EmployeeForm.vue';
|
||||||
|
import { index, store } from '@/routes/admin/hr/employees';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
genders: EnumOption[];
|
genders: EnumOption[];
|
||||||
@ -25,11 +26,11 @@ defineProps<{
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/hr/employees" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<EmployeeForm
|
<EmployeeForm
|
||||||
submit-url="/admin/hr/employees"
|
:submit-url="store.url()"
|
||||||
:genders="genders"
|
:genders="genders"
|
||||||
:employment-statuses="employmentStatuses"
|
:employment-statuses="employmentStatuses"
|
||||||
:roles="roles"
|
:roles="roles"
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import type { EmployeeListItem, EnumOption } from '@/types/employee';
|
|||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import EmployeeForm from './form/EmployeeForm.vue';
|
import EmployeeForm from './form/EmployeeForm.vue';
|
||||||
|
import { index, update } from '@/routes/admin/hr/employees';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
employee: EmployeeListItem;
|
employee: EmployeeListItem;
|
||||||
@ -42,11 +43,11 @@ const initialData = computed(() => ({
|
|||||||
<h2 class="text-2xl font-bold tracking-tight">Ubah Pegawai</h2>
|
<h2 class="text-2xl font-bold tracking-tight">Ubah Pegawai</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/hr/employees" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<EmployeeForm
|
<EmployeeForm
|
||||||
:submit-url="`/admin/hr/employees/${employee.id}`"
|
:submit-url="update.url(employee.id)"
|
||||||
method="put"
|
method="put"
|
||||||
submit-label="Perbarui"
|
submit-label="Perbarui"
|
||||||
:initial-data="initialData"
|
:initial-data="initialData"
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import type { EnumOption, PaginatedEmployees } from '@/types/employee';
|
|||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import { columns } from './table/columns';
|
import { columns } from './table/columns';
|
||||||
|
import { index, create } from '@/routes/admin/hr/employees';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
employees: PaginatedEmployees;
|
employees: PaginatedEmployees;
|
||||||
@ -36,7 +37,7 @@ const search = ref(props.filters.search ?? '');
|
|||||||
|
|
||||||
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } =
|
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } =
|
||||||
useDataTableQuery({
|
useDataTableQuery({
|
||||||
url: '/admin/hr/employees',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
filterKeys: ['role', 'gender', 'employment_status', 'is_active'],
|
filterKeys: ['role', 'gender', 'employment_status', 'is_active'],
|
||||||
});
|
});
|
||||||
@ -123,7 +124,7 @@ watch(
|
|||||||
|
|
||||||
<CreateButton
|
<CreateButton
|
||||||
v-if="can('employees.create')"
|
v-if="can('employees.create')"
|
||||||
href="/admin/hr/employees/create"
|
:href="create.url()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import {
|
|||||||
AlertDialogTrigger,
|
AlertDialogTrigger,
|
||||||
} from '@/components/ui/alert-dialog';
|
} from '@/components/ui/alert-dialog';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { reset_password } from '@/routes/admin/hr/employees';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
employeeId: number;
|
employeeId: number;
|
||||||
@ -29,7 +30,7 @@ const processing = ref(false);
|
|||||||
function resetPassword() {
|
function resetPassword() {
|
||||||
processing.value = true;
|
processing.value = true;
|
||||||
|
|
||||||
router.post(`/admin/hr/employees/${props.employeeId}/reset-password`, {}, {
|
router.post(reset_password.url(props.employeeId), {}, {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
open.value = false;
|
open.value = false;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { EmployeeListItem } from '@/types/employee';
|
import type { EmployeeListItem } from '@/types/employee';
|
||||||
|
import { edit, destroy, reset_password } from '@/routes/admin/hr/employees';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
employee: EmployeeListItem;
|
employee: EmployeeListItem;
|
||||||
@ -25,7 +26,7 @@ const resetPasswordProcessing = ref(false);
|
|||||||
function destroyEmployee() {
|
function destroyEmployee() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/hr/employees/${props.employee.id}`, {
|
router.delete(destroy.url(props.employee.id), {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
},
|
},
|
||||||
@ -41,7 +42,7 @@ function destroyEmployee() {
|
|||||||
function resetPassword() {
|
function resetPassword() {
|
||||||
resetPasswordProcessing.value = true;
|
resetPasswordProcessing.value = true;
|
||||||
|
|
||||||
router.post(`/admin/hr/employees/${props.employee.id}/reset-password`, {}, {
|
router.post(reset_password.url(props.employee.id), {}, {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
resetPasswordConfirmOpen.value = false;
|
resetPasswordConfirmOpen.value = false;
|
||||||
@ -61,7 +62,7 @@ function resetPassword() {
|
|||||||
<Tooltip v-if="can('employees.update')">
|
<Tooltip v-if="can('employees.update')">
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button variant="ghost" size="icon" class="size-8" as-child>
|
<Button variant="ghost" size="icon" class="size-8" as-child>
|
||||||
<Link :href="`/admin/hr/employees/${employee.id}/edit`">
|
<Link :href="edit.url(employee.id)">
|
||||||
<Pencil class="size-4" />
|
<Pencil class="size-4" />
|
||||||
<span class="sr-only">Ubah</span>
|
<span class="sr-only">Ubah</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { Badge } from '@/components/ui/badge';
|
|||||||
import { Switch } from '@/components/ui/switch';
|
import { Switch } from '@/components/ui/switch';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { EmployeeListItem } from '@/types/employee';
|
import type { EmployeeListItem } from '@/types/employee';
|
||||||
|
import { toggle_status } from '@/routes/admin/hr/employees';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
employee: EmployeeListItem;
|
employee: EmployeeListItem;
|
||||||
@ -32,7 +33,7 @@ function toggleStatus(checked: boolean) {
|
|||||||
isActive.value = checked;
|
isActive.value = checked;
|
||||||
processing.value = true;
|
processing.value = true;
|
||||||
|
|
||||||
router.patch(`/admin/hr/employees/${props.employee.id}/toggle-status`, {
|
router.patch(toggle_status.url(props.employee.id), {
|
||||||
is_active: checked,
|
is_active: checked,
|
||||||
}, {
|
}, {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import { computed, ref, watch } from 'vue';
|
|||||||
import LeaveRequestFormModal from './form/LeaveRequestFormModal.vue';
|
import LeaveRequestFormModal from './form/LeaveRequestFormModal.vue';
|
||||||
import RejectLeaveRequestModal from './form/RejectLeaveRequestModal.vue';
|
import RejectLeaveRequestModal from './form/RejectLeaveRequestModal.vue';
|
||||||
import { createColumns } from './table/columns';
|
import { createColumns } from './table/columns';
|
||||||
|
import { index } from '@/routes/admin/hr/leave_requests';
|
||||||
|
|
||||||
const props = defineProps<LeaveRequestPageProps>();
|
const props = defineProps<LeaveRequestPageProps>();
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ const rejectingLeaveRequest = ref<LeaveRequestListItem | null>(null);
|
|||||||
|
|
||||||
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
||||||
useDataTableQuery({
|
useDataTableQuery({
|
||||||
url: '/admin/hr/leave-requests',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import {
|
|||||||
import { useFormDialog } from '@/composables/useFormDialog';
|
import { useFormDialog } from '@/composables/useFormDialog';
|
||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import type { LeaveRequestFormData, LeaveRequestListItem } from '@/types/leave-request';
|
import type { LeaveRequestFormData, LeaveRequestListItem } from '@/types/leave-request';
|
||||||
|
import { store, update } from '@/routes/admin/hr/leave_requests';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -71,12 +72,12 @@ function submit() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isEditing.value && props.leaveRequest) {
|
if (isEditing.value && props.leaveRequest) {
|
||||||
form.put(`/admin/hr/leave-requests/${props.leaveRequest.id}`, options);
|
form.put(update.url(props.leaveRequest.id), options);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.post('/admin/hr/leave-requests', options);
|
form.post(store.url(), options);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import { Textarea } from '@/components/ui/textarea';
|
|||||||
import { FIELD_LIMITS } from '@/lib/field-limits';
|
import { FIELD_LIMITS } from '@/lib/field-limits';
|
||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import type { LeaveRequestListItem } from '@/types/leave-request';
|
import type { LeaveRequestListItem } from '@/types/leave-request';
|
||||||
|
import { reject } from '@/routes/admin/hr/leave_requests';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ function submit() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.post(`/admin/hr/leave-requests/${props.leaveRequest.id}/reject`, {
|
form.post(reject.url(props.leaveRequest.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
open.value = false;
|
open.value = false;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { LeaveRequestListItem } from '@/types/leave-request';
|
import type { LeaveRequestListItem } from '@/types/leave-request';
|
||||||
|
import { destroy, approve } from '@/routes/admin/hr/leave_requests';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
leaveRequest: LeaveRequestListItem;
|
leaveRequest: LeaveRequestListItem;
|
||||||
@ -48,7 +49,7 @@ const approveProcessing = ref(false);
|
|||||||
function destroyLeaveRequest() {
|
function destroyLeaveRequest() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/hr/leave-requests/${props.leaveRequest.id}`, {
|
router.delete(destroy.url(props.leaveRequest.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
@ -65,7 +66,7 @@ function destroyLeaveRequest() {
|
|||||||
function approveLeaveRequest() {
|
function approveLeaveRequest() {
|
||||||
approveProcessing.value = true;
|
approveProcessing.value = true;
|
||||||
|
|
||||||
router.post(`/admin/hr/leave-requests/${props.leaveRequest.id}/approve`, {}, {
|
router.post(approve.url(props.leaveRequest.id), {}, {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
approveConfirmOpen.value = false;
|
approveConfirmOpen.value = false;
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import type {
|
|||||||
} from '@/types/cutting';
|
} from '@/types/cutting';
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import CuttingPosForm from './form/CuttingPosForm.vue';
|
import CuttingPosForm from './form/CuttingPosForm.vue';
|
||||||
|
import { index, store } from '@/routes/admin/manage/cuttings';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
rawMaterialCatalog: CuttingRawMaterialCatalogItem[];
|
rawMaterialCatalog: CuttingRawMaterialCatalogItem[];
|
||||||
@ -31,7 +32,7 @@ defineProps<{
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/manage/cuttings" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CuttingPosForm
|
<CuttingPosForm
|
||||||
@ -39,7 +40,7 @@ defineProps<{
|
|||||||
:product-catalog="productCatalog"
|
:product-catalog="productCatalog"
|
||||||
:draft-materials="draftMaterials"
|
:draft-materials="draftMaterials"
|
||||||
:draft-results="draftResults"
|
:draft-results="draftResults"
|
||||||
submit-url="/admin/manage/cuttings"
|
:submit-url="store.url()"
|
||||||
method="post"
|
method="post"
|
||||||
submit-label="Simpan"
|
submit-label="Simpan"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import type {
|
|||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import CuttingPosForm from './form/CuttingPosForm.vue';
|
import CuttingPosForm from './form/CuttingPosForm.vue';
|
||||||
|
import { index, update } from '@/routes/admin/manage/cuttings';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
cutting: CuttingEditItem;
|
cutting: CuttingEditItem;
|
||||||
@ -56,14 +57,14 @@ const initialData = computed(() => ({
|
|||||||
<h2 class="text-2xl font-bold tracking-tight">Ubah Cutting</h2>
|
<h2 class="text-2xl font-bold tracking-tight">Ubah Cutting</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/manage/cuttings" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CuttingPosForm
|
<CuttingPosForm
|
||||||
:raw-material-catalog="rawMaterialCatalog"
|
:raw-material-catalog="rawMaterialCatalog"
|
||||||
:product-catalog="productCatalog"
|
:product-catalog="productCatalog"
|
||||||
:initial-data="initialData"
|
:initial-data="initialData"
|
||||||
:submit-url="`/admin/manage/cuttings/${cutting.id}`"
|
:submit-url="update.url(props.cutting.id)"
|
||||||
method="put"
|
method="put"
|
||||||
submit-label="Perbarui"
|
submit-label="Perbarui"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import { Head } from '@inertiajs/vue3';
|
|||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import CuttingGroupedTable from './table/CuttingGroupedTable.vue';
|
import CuttingGroupedTable from './table/CuttingGroupedTable.vue';
|
||||||
import CuttingInProgressSection from './table/CuttingInProgressSection.vue';
|
import CuttingInProgressSection from './table/CuttingInProgressSection.vue';
|
||||||
|
import { index, create } from '@/routes/admin/manage/cuttings';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
cuttings: PaginatedCuttings;
|
cuttings: PaginatedCuttings;
|
||||||
@ -27,7 +28,7 @@ const { can, hasAnyRole } = useCan();
|
|||||||
const search = ref(props.filters.search ?? '');
|
const search = ref(props.filters.search ?? '');
|
||||||
|
|
||||||
const { setSearch, resetFilters, syncFromServer } = useDataTableQuery({
|
const { setSearch, resetFilters, syncFromServer } = useDataTableQuery({
|
||||||
url: '/admin/manage/cuttings',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ watch(
|
|||||||
|
|
||||||
<CreateButton
|
<CreateButton
|
||||||
v-if="can('cuttings.create')"
|
v-if="can('cuttings.create')"
|
||||||
href="/admin/manage/cuttings/create"
|
:href="create.url()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,8 @@ import type {
|
|||||||
} from '@/types/cutting';
|
} from '@/types/cutting';
|
||||||
import PosCatalogCard from '../../shared/PosCatalogCard.vue';
|
import PosCatalogCard from '../../shared/PosCatalogCard.vue';
|
||||||
import PosCatalogVariantThumb from '../../shared/PosCatalogVariantThumb.vue';
|
import PosCatalogVariantThumb from '../../shared/PosCatalogVariantThumb.vue';
|
||||||
|
import draft_materials from '@/routes/admin/manage/cuttings/draft_materials';
|
||||||
|
import draft_results from '@/routes/admin/manage/cuttings/draft_results';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
rawMaterialCatalog: CuttingRawMaterialCatalogItem[];
|
rawMaterialCatalog: CuttingRawMaterialCatalogItem[];
|
||||||
@ -245,7 +247,7 @@ function upsertResultCartItem(item: CuttingResultCartItem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function syncDraftMaterial(rawMaterial: CuttingRawMaterialCatalogItem, price: CatalogPrice, materialUsage: string, remainingMaterial: string) {
|
async function syncDraftMaterial(rawMaterial: CuttingRawMaterialCatalogItem, price: CatalogPrice, materialUsage: string, remainingMaterial: string) {
|
||||||
const { item } = await apiFetch<{ item: CuttingMaterialCartItem }>('/admin/manage/cuttings/draft-materials', {
|
const { item } = await apiFetch<{ item: CuttingMaterialCartItem }>(draft_materials.store.url(), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
raw_material_price_id: price.id,
|
raw_material_price_id: price.id,
|
||||||
@ -258,7 +260,7 @@ async function syncDraftMaterial(rawMaterial: CuttingRawMaterialCatalogItem, pri
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function syncDraftResult(product: CuttingProductCatalogItem, variant: CuttingProductCatalogItem['variants'][number], cuttingResult: string, warehouseStock: string, cuttingReject: string) {
|
async function syncDraftResult(product: CuttingProductCatalogItem, variant: CuttingProductCatalogItem['variants'][number], cuttingResult: string, warehouseStock: string, cuttingReject: string) {
|
||||||
const { item } = await apiFetch<{ item: CuttingResultCartItem }>('/admin/manage/cuttings/draft-results', {
|
const { item } = await apiFetch<{ item: CuttingResultCartItem }>(draft_results.store.url(), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
product_variant_id: variant.id,
|
product_variant_id: variant.id,
|
||||||
@ -371,7 +373,7 @@ async function removeMaterial(index: number) {
|
|||||||
if (isCreateMode.value) {
|
if (isCreateMode.value) {
|
||||||
try {
|
try {
|
||||||
await apiFetch(
|
await apiFetch(
|
||||||
`/admin/manage/cuttings/draft-materials/${item.raw_material_price_id}`,
|
draft_materials.destroy.url(item.raw_material_price_id),
|
||||||
{ method: 'DELETE' },
|
{ method: 'DELETE' },
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -487,7 +489,7 @@ async function removeResult(index: number) {
|
|||||||
if (isCreateMode.value) {
|
if (isCreateMode.value) {
|
||||||
try {
|
try {
|
||||||
await apiFetch(
|
await apiFetch(
|
||||||
`/admin/manage/cuttings/draft-results/${item.product_variant_id}`,
|
draft_results.destroy.url(item.product_variant_id),
|
||||||
{ method: 'DELETE' },
|
{ method: 'DELETE' },
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -516,7 +518,7 @@ async function syncMaterialField(index: number) {
|
|||||||
const item = materialCart.value[index];
|
const item = materialCart.value[index];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await apiFetch<{ item: CuttingMaterialCartItem }>('/admin/manage/cuttings/draft-materials', {
|
await apiFetch<{ item: CuttingMaterialCartItem }>(draft_materials.store.url(), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
raw_material_price_id: item.raw_material_price_id,
|
raw_material_price_id: item.raw_material_price_id,
|
||||||
@ -537,7 +539,7 @@ async function syncResultField(index: number) {
|
|||||||
const item = resultCart.value[index];
|
const item = resultCart.value[index];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await apiFetch<{ item: CuttingResultCartItem }>('/admin/manage/cuttings/draft-results', {
|
await apiFetch<{ item: CuttingResultCartItem }>(draft_results.store.url(), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
product_variant_id: item.product_variant_id,
|
product_variant_id: item.product_variant_id,
|
||||||
|
|||||||
@ -38,6 +38,8 @@ import {
|
|||||||
PRICE_TYPE_LABELS,
|
PRICE_TYPE_LABELS,
|
||||||
} from '@/types/product';
|
} from '@/types/product';
|
||||||
import type { CuttingListItem, CuttingStatusAction } from '@/types/cutting';
|
import type { CuttingListItem, CuttingStatusAction } from '@/types/cutting';
|
||||||
|
import { edit, destroy, transition_status } from '@/routes/admin/manage/cuttings';
|
||||||
|
import { FIELD_LIMITS } from '@/lib/field-limits';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
cutting: CuttingListItem;
|
cutting: CuttingListItem;
|
||||||
@ -152,7 +154,7 @@ const canEdit = computed(
|
|||||||
() => props.cutting.is_editable && can('cuttings.update'),
|
() => props.cutting.is_editable && can('cuttings.update'),
|
||||||
);
|
);
|
||||||
const canDelete = computed(
|
const canDelete = computed(
|
||||||
() => can('cuttings.delete') && [CuttingStatus.IN_PROGRESS, CuttingStatus.REJECTED].includes(props.cutting.status),
|
() => can('cuttings.delete') && (props.cutting.status === CuttingStatus.IN_PROGRESS || props.cutting.status === CuttingStatus.REJECTED),
|
||||||
);
|
);
|
||||||
|
|
||||||
function canPerformAction(action: CuttingStatusAction): boolean {
|
function canPerformAction(action: CuttingStatusAction): boolean {
|
||||||
@ -206,7 +208,7 @@ function submitVerify() {
|
|||||||
})),
|
})),
|
||||||
result_prices: buildResultPricesPayload(),
|
result_prices: buildResultPricesPayload(),
|
||||||
}))
|
}))
|
||||||
.post(`/admin/manage/cuttings/${props.cutting.id}/status`, {
|
.post(transition_status.url(props.cutting.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
verifyDialogOpen.value = false;
|
verifyDialogOpen.value = false;
|
||||||
@ -231,7 +233,7 @@ function transitionStatus() {
|
|||||||
statusProcessing.value = true;
|
statusProcessing.value = true;
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
`/admin/manage/cuttings/${props.cutting.id}/status`,
|
transition_status.url(props.cutting.id),
|
||||||
{
|
{
|
||||||
status: pendingAction.value.status,
|
status: pendingAction.value.status,
|
||||||
},
|
},
|
||||||
@ -258,7 +260,7 @@ function transitionStatus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function submitReject() {
|
function submitReject() {
|
||||||
rejectForm.post(`/admin/manage/cuttings/${props.cutting.id}/status`, {
|
rejectForm.post(transition_status.url(props.cutting.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
rejectDialogOpen.value = false;
|
rejectDialogOpen.value = false;
|
||||||
@ -285,7 +287,7 @@ watch(rejectDialogOpen, (isOpen) => {
|
|||||||
function destroyCutting() {
|
function destroyCutting() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/manage/cuttings/${props.cutting.id}`, {
|
router.delete(destroy.url(props.cutting.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
@ -348,7 +350,7 @@ function actionIcon(status: string) {
|
|||||||
<Tooltip v-if="canEdit">
|
<Tooltip v-if="canEdit">
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button variant="ghost" size="icon" class="size-8" as-child>
|
<Button variant="ghost" size="icon" class="size-8" as-child>
|
||||||
<Link :href="`/admin/manage/cuttings/${cutting.id}/edit`">
|
<Link :href="edit.url(cutting.id)">
|
||||||
<Pencil class="size-4" />
|
<Pencil class="size-4" />
|
||||||
<span class="sr-only">Ubah</span>
|
<span class="sr-only">Ubah</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import type {
|
|||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import OrderPosForm from './form/OrderPosForm.vue';
|
import OrderPosForm from './form/OrderPosForm.vue';
|
||||||
|
import { index, store } from '@/routes/admin/manage/orders';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
customers: SelectOption[];
|
customers: SelectOption[];
|
||||||
@ -41,7 +42,7 @@ function onCustomerCreated(customer: { id: number; name: string }) {
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/manage/orders" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<OrderPosForm
|
<OrderPosForm
|
||||||
@ -52,7 +53,7 @@ function onCustomerCreated(customer: { id: number; name: string }) {
|
|||||||
:store-price-types="storePriceTypes"
|
:store-price-types="storePriceTypes"
|
||||||
:payment-types="paymentTypes"
|
:payment-types="paymentTypes"
|
||||||
:draft-items="draftItems"
|
:draft-items="draftItems"
|
||||||
submit-url="/admin/manage/orders"
|
:submit-url="store.url()"
|
||||||
method="post"
|
method="post"
|
||||||
submit-label="Simpan"
|
submit-label="Simpan"
|
||||||
@customer-created="onCustomerCreated"
|
@customer-created="onCustomerCreated"
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import type {
|
|||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import OrderPosForm from './form/OrderPosForm.vue';
|
import OrderPosForm from './form/OrderPosForm.vue';
|
||||||
|
import { index, update } from '@/routes/admin/manage/orders';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
order: OrderEditItem;
|
order: OrderEditItem;
|
||||||
@ -69,7 +70,7 @@ function onCustomerCreated(customer: { id: number; name: string }) {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/manage/orders" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<OrderPosForm
|
<OrderPosForm
|
||||||
@ -80,7 +81,7 @@ function onCustomerCreated(customer: { id: number; name: string }) {
|
|||||||
:store-price-types="storePriceTypes"
|
:store-price-types="storePriceTypes"
|
||||||
:payment-types="paymentTypes"
|
:payment-types="paymentTypes"
|
||||||
:initial-data="initialData"
|
:initial-data="initialData"
|
||||||
:submit-url="`/admin/manage/orders/${order.id}`"
|
:submit-url="update.url(props.order.id)"
|
||||||
method="put"
|
method="put"
|
||||||
submit-label="Perbarui"
|
submit-label="Perbarui"
|
||||||
@customer-created="onCustomerCreated"
|
@customer-created="onCustomerCreated"
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import type { PaginatedOrders } from '@/types/order';
|
|||||||
import { Head, usePage } from '@inertiajs/vue3';
|
import { Head, usePage } from '@inertiajs/vue3';
|
||||||
import { computed, onMounted, ref, watch } from 'vue';
|
import { computed, onMounted, ref, watch } from 'vue';
|
||||||
import { toast } from 'vue-sonner';
|
import { toast } from 'vue-sonner';
|
||||||
|
import { index, create } from '@/routes/admin/manage/orders';
|
||||||
import ThermalPrinterConnectButton from './form/ThermalPrinterConnectButton.vue';
|
import ThermalPrinterConnectButton from './form/ThermalPrinterConnectButton.vue';
|
||||||
import OrderGroupedTable from './table/OrderGroupedTable.vue';
|
import OrderGroupedTable from './table/OrderGroupedTable.vue';
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ const { isConnected, printOrderReceipt, tryReconnect } = useThermalPrinter();
|
|||||||
const search = ref(props.filters.search ?? '');
|
const search = ref(props.filters.search ?? '');
|
||||||
|
|
||||||
const { setSearch, resetFilters, syncFromServer } = useDataTableQuery({
|
const { setSearch, resetFilters, syncFromServer } = useDataTableQuery({
|
||||||
url: '/admin/manage/orders',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -125,7 +126,7 @@ onMounted(async () => {
|
|||||||
>
|
>
|
||||||
<ThermalPrinterConnectButton />
|
<ThermalPrinterConnectButton />
|
||||||
|
|
||||||
<CreateButton href="/admin/manage/orders/create" />
|
<CreateButton :href="create.url()" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import { OrderStatus } from '@/constants/order-status';
|
|||||||
import { StockQuality } from '@/constants/stock-quality';
|
import { StockQuality } from '@/constants/stock-quality';
|
||||||
import AdminLayout from '@/layouts/AdminLayout.vue';
|
import AdminLayout from '@/layouts/AdminLayout.vue';
|
||||||
import type { OrderDetail, OrderStatusAction } from '@/types/order';
|
import type { OrderDetail, OrderStatusAction } from '@/types/order';
|
||||||
|
import { index, edit, destroy, transition_status } from '@/routes/admin/manage/orders';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
order: OrderDetail;
|
order: OrderDetail;
|
||||||
@ -97,7 +98,7 @@ function transitionStatus() {
|
|||||||
|
|
||||||
statusProcessing.value = true;
|
statusProcessing.value = true;
|
||||||
|
|
||||||
router.post(`/admin/manage/orders/${props.order.id}/status`, {
|
router.post(transition_status.url(props.order.id), {
|
||||||
status: pendingAction.value.status,
|
status: pendingAction.value.status,
|
||||||
}, {
|
}, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
@ -117,7 +118,7 @@ function transitionStatus() {
|
|||||||
function destroyOrder() {
|
function destroyOrder() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/manage/orders/${props.order.id}`, {
|
router.delete(destroy.url(props.order.id), {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
},
|
},
|
||||||
@ -239,7 +240,7 @@ const feeEntries = computed(() => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<Button v-if="canEdit" variant="outline" size="sm" as-child>
|
<Button v-if="canEdit" variant="outline" size="sm" as-child>
|
||||||
<Link :href="`/admin/manage/orders/${order.id}/edit`">
|
<Link :href="edit.url(props.order.id)">
|
||||||
<Pencil class="size-3.5" />
|
<Pencil class="size-3.5" />
|
||||||
Ubah
|
Ubah
|
||||||
</Link>
|
</Link>
|
||||||
@ -256,7 +257,7 @@ const feeEntries = computed(() => {
|
|||||||
Hapus
|
Hapus
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<BackButton href="/admin/manage/orders" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Save } from '@lucide/vue';
|
|
||||||
import { reactive, ref } from 'vue';
|
|
||||||
import { toast } from 'vue-sonner';
|
|
||||||
import { PhoneNumberInput } from '@/components/form/phone-number-input';
|
import { PhoneNumberInput } from '@/components/form/phone-number-input';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
@ -22,6 +19,10 @@ import { Input } from '@/components/ui/input';
|
|||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
import { apiFetch } from '@/lib/api';
|
import { apiFetch } from '@/lib/api';
|
||||||
import { FIELD_LIMITS } from '@/lib/field-limits';
|
import { FIELD_LIMITS } from '@/lib/field-limits';
|
||||||
|
import { Save } from '@lucide/vue';
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import { toast } from 'vue-sonner';
|
||||||
|
import { api } from '@/routes/admin/master/customers/store';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -50,21 +51,25 @@ async function submit() {
|
|||||||
processing.value = true;
|
processing.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const customer = await apiFetch<{ id: number; name: string }>('/admin/master/customers/api', {
|
const customer = await apiFetch<{ id: number; name: string }>(
|
||||||
method: 'POST',
|
api.url(),
|
||||||
body: JSON.stringify({
|
{
|
||||||
name: form.name,
|
method: 'POST',
|
||||||
phone_number: form.phone_number || null,
|
body: JSON.stringify({
|
||||||
address: form.address || null,
|
name: form.name,
|
||||||
}),
|
phone_number: form.phone_number || null,
|
||||||
});
|
address: form.address || null,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
emit('created', customer);
|
emit('created', customer);
|
||||||
open.value = false;
|
open.value = false;
|
||||||
resetForm();
|
resetForm();
|
||||||
toast.success('Pelanggan berhasil ditambahkan.');
|
toast.success('Pelanggan berhasil ditambahkan.');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = error instanceof Error ? error.message : 'Gagal menyimpan data.';
|
const message =
|
||||||
|
error instanceof Error ? error.message : 'Gagal menyimpan data.';
|
||||||
|
|
||||||
if (message.includes('nama')) {
|
if (message.includes('nama')) {
|
||||||
errors.name = message;
|
errors.name = message;
|
||||||
@ -88,26 +93,53 @@ async function submit() {
|
|||||||
<FieldGroup>
|
<FieldGroup>
|
||||||
<FieldSet class="grid gap-4">
|
<FieldSet class="grid gap-4">
|
||||||
<Field>
|
<Field>
|
||||||
<FieldLabel for="quick-customer-name" required>Nama</FieldLabel>
|
<FieldLabel for="quick-customer-name" required
|
||||||
<Input id="quick-customer-name" v-model="form.name" type="text"
|
>Nama</FieldLabel
|
||||||
placeholder="Contoh: Budi Santoso" autofocus :maxlength="FIELD_LIMITS.name" />
|
>
|
||||||
<FieldError v-if="errors.name" :errors="[errors.name]" />
|
<Input
|
||||||
|
id="quick-customer-name"
|
||||||
|
v-model="form.name"
|
||||||
|
type="text"
|
||||||
|
placeholder="Contoh: Budi Santoso"
|
||||||
|
autofocus
|
||||||
|
:maxlength="FIELD_LIMITS.name"
|
||||||
|
/>
|
||||||
|
<FieldError
|
||||||
|
v-if="errors.name"
|
||||||
|
:errors="[errors.name]"
|
||||||
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
<Field>
|
<Field>
|
||||||
<FieldLabel for="quick-customer-phone">Nomor Telepon</FieldLabel>
|
<FieldLabel for="quick-customer-phone"
|
||||||
<PhoneNumberInput id="quick-customer-phone" v-model="form.phone_number"
|
>Nomor Telepon</FieldLabel
|
||||||
placeholder="Contoh: 08123456789" />
|
>
|
||||||
|
<PhoneNumberInput
|
||||||
|
id="quick-customer-phone"
|
||||||
|
v-model="form.phone_number"
|
||||||
|
placeholder="Contoh: 08123456789"
|
||||||
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
<Field>
|
<Field>
|
||||||
<FieldLabel for="quick-customer-address">Alamat</FieldLabel>
|
<FieldLabel for="quick-customer-address"
|
||||||
<Textarea id="quick-customer-address" v-model="form.address" rows="3"
|
>Alamat</FieldLabel
|
||||||
placeholder="Contoh: Jl. Mawar No. 12, Surabaya" />
|
>
|
||||||
|
<Textarea
|
||||||
|
id="quick-customer-address"
|
||||||
|
v-model="form.address"
|
||||||
|
rows="3"
|
||||||
|
placeholder="Contoh: Jl. Mawar No. 12, Surabaya"
|
||||||
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
</FieldGroup>
|
</FieldGroup>
|
||||||
|
|
||||||
<DialogFooter class="mt-6">
|
<DialogFooter class="mt-6">
|
||||||
<Button type="button" variant="outline" :disabled="processing" @click="open = false">
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
:disabled="processing"
|
||||||
|
@click="open = false"
|
||||||
|
>
|
||||||
Batal
|
Batal
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="submit" :disabled="processing">
|
<Button type="submit" :disabled="processing">
|
||||||
|
|||||||
@ -55,6 +55,7 @@ import type { ProductPriceItem, ProductVariantItem } from '@/types/product';
|
|||||||
import PosCatalogCard from '../../shared/PosCatalogCard.vue';
|
import PosCatalogCard from '../../shared/PosCatalogCard.vue';
|
||||||
import PosCatalogVariantThumb from '../../shared/PosCatalogVariantThumb.vue';
|
import PosCatalogVariantThumb from '../../shared/PosCatalogVariantThumb.vue';
|
||||||
import CustomerQuickCreateModal from './CustomerQuickCreateModal.vue';
|
import CustomerQuickCreateModal from './CustomerQuickCreateModal.vue';
|
||||||
|
import { store as syncDraftRoute, resync_prices as resyncPricesRoute, destroy as destroyDraftRoute } from '@/routes/admin/manage/orders/draft_items';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
customers: SelectOption[];
|
customers: SelectOption[];
|
||||||
@ -200,7 +201,7 @@ watch(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const { items } = await apiFetch<{ items: OrderCartItem[] }>(
|
const { items } = await apiFetch<{ items: OrderCartItem[] }>(
|
||||||
'/admin/manage/orders/draft-items/resync-prices',
|
resyncPricesRoute.url(),
|
||||||
{
|
{
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: JSON.stringify({ price_type: priceType }),
|
body: JSON.stringify({ price_type: priceType }),
|
||||||
@ -286,7 +287,7 @@ function lineSubtotal(item: OrderCartItem): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function syncDraftItem(variantId: number, quantity: number, stockQuality = selectedStockQuality.value) {
|
async function syncDraftItem(variantId: number, quantity: number, stockQuality = selectedStockQuality.value) {
|
||||||
const { item } = await apiFetch<{ item: OrderCartItem }>('/admin/manage/orders/draft-items', {
|
const { item } = await apiFetch<{ item: OrderCartItem }>(syncDraftRoute.url(), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
product_variant_id: variantId,
|
product_variant_id: variantId,
|
||||||
@ -364,7 +365,9 @@ async function removeFromCart(index: number) {
|
|||||||
if (isCreateMode.value) {
|
if (isCreateMode.value) {
|
||||||
try {
|
try {
|
||||||
await apiFetch(
|
await apiFetch(
|
||||||
`/admin/manage/orders/draft-items/${item.product_variant_id}?stock_quality=${item.stock_quality}`,
|
destroyDraftRoute.url(item.product_variant_id, {
|
||||||
|
query: { stock_quality: item.stock_quality }
|
||||||
|
}),
|
||||||
{
|
{
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip
|
|||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import { OrderStatus } from '@/constants/order-status';
|
import { OrderStatus } from '@/constants/order-status';
|
||||||
import type { OrderListItem, OrderStatusAction } from '@/types/order';
|
import type { OrderListItem, OrderStatusAction } from '@/types/order';
|
||||||
|
import { show, edit, destroy, transition_status } from '@/routes/admin/manage/orders';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
order: OrderListItem;
|
order: OrderListItem;
|
||||||
@ -56,7 +57,7 @@ function transitionStatus() {
|
|||||||
|
|
||||||
statusProcessing.value = true;
|
statusProcessing.value = true;
|
||||||
|
|
||||||
router.post(`/admin/manage/orders/${props.order.id}/status`, {
|
router.post(transition_status.url(props.order.id), {
|
||||||
status: pendingAction.value.status,
|
status: pendingAction.value.status,
|
||||||
}, {
|
}, {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
@ -78,7 +79,7 @@ function transitionStatus() {
|
|||||||
function destroyOrder() {
|
function destroyOrder() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/manage/orders/${props.order.id}`, {
|
router.delete(destroy.url(props.order.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
@ -141,7 +142,7 @@ function actionIcon(status: string) {
|
|||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button variant="ghost" size="icon" class="size-8" as-child>
|
<Button variant="ghost" size="icon" class="size-8" as-child>
|
||||||
<Link :href="`/admin/manage/orders/${order.id}`">
|
<Link :href="show.url(props.order.id)">
|
||||||
<Eye class="size-4" />
|
<Eye class="size-4" />
|
||||||
<span class="sr-only">Detail</span>
|
<span class="sr-only">Detail</span>
|
||||||
</Link>
|
</Link>
|
||||||
@ -153,7 +154,7 @@ function actionIcon(status: string) {
|
|||||||
<Tooltip v-if="canEdit">
|
<Tooltip v-if="canEdit">
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button variant="ghost" size="icon" class="size-8" as-child>
|
<Button variant="ghost" size="icon" class="size-8" as-child>
|
||||||
<Link :href="`/admin/manage/orders/${order.id}/edit`">
|
<Link :href="edit.url(props.order.id)">
|
||||||
<Pencil class="size-4" />
|
<Pencil class="size-4" />
|
||||||
<span class="sr-only">Ubah</span>
|
<span class="sr-only">Ubah</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import {
|
|||||||
} from '@/components/ui/tooltip';
|
} from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { CuttingListItem } from '@/types/cutting';
|
import type { CuttingListItem } from '@/types/cutting';
|
||||||
|
import { approve, reject } from '@/routes/admin/manage/owner_verifications';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
cutting: CuttingListItem;
|
cutting: CuttingListItem;
|
||||||
@ -41,7 +42,7 @@ const rejectForm = useForm({
|
|||||||
|
|
||||||
function submitApprove() {
|
function submitApprove() {
|
||||||
approveForm
|
approveForm
|
||||||
.post(`/admin/manage/owner-verifications/${props.cutting.id}/approve`, {
|
.post(approve.url(props.cutting.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onError: (errors) => {
|
onError: (errors) => {
|
||||||
const message = Object.values(errors)[0];
|
const message = Object.values(errors)[0];
|
||||||
@ -52,7 +53,7 @@ function submitApprove() {
|
|||||||
|
|
||||||
function submitReject() {
|
function submitReject() {
|
||||||
rejectForm
|
rejectForm
|
||||||
.post(`/admin/manage/owner-verifications/${props.cutting.id}/reject`, {
|
.post(reject.url(props.cutting.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
rejectDialogOpen.value = false;
|
rejectDialogOpen.value = false;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import type {
|
|||||||
} from '@/types/purchase';
|
} from '@/types/purchase';
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import PurchasePosForm from './form/PurchasePosForm.vue';
|
import PurchasePosForm from './form/PurchasePosForm.vue';
|
||||||
|
import { index, store } from '@/routes/admin/manage/purchases';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
suppliers: SelectOption[];
|
suppliers: SelectOption[];
|
||||||
@ -29,14 +30,14 @@ defineProps<{
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/manage/purchases" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<PurchasePosForm
|
<PurchasePosForm
|
||||||
:suppliers="suppliers"
|
:suppliers="suppliers"
|
||||||
:catalog="catalog"
|
:catalog="catalog"
|
||||||
:draft-items="draftItems"
|
:draft-items="draftItems"
|
||||||
submit-url="/admin/manage/purchases"
|
:submit-url="store.url()"
|
||||||
method="post"
|
method="post"
|
||||||
submit-label="Simpan"
|
submit-label="Simpan"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import type {
|
|||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import PurchasePosForm from './form/PurchasePosForm.vue';
|
import PurchasePosForm from './form/PurchasePosForm.vue';
|
||||||
|
import { index, update } from '@/routes/admin/manage/purchases';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
purchase: PurchaseEditItem;
|
purchase: PurchaseEditItem;
|
||||||
@ -45,14 +46,14 @@ const initialData = computed(() => ({
|
|||||||
<h2 class="text-2xl font-bold tracking-tight">Ubah Belanja</h2>
|
<h2 class="text-2xl font-bold tracking-tight">Ubah Belanja</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/manage/purchases" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<PurchasePosForm
|
<PurchasePosForm
|
||||||
:suppliers="suppliers"
|
:suppliers="suppliers"
|
||||||
:catalog="catalog"
|
:catalog="catalog"
|
||||||
:initial-data="initialData"
|
:initial-data="initialData"
|
||||||
:submit-url="`/admin/manage/purchases/${purchase.id}`"
|
:submit-url="update.url(props.purchase.id)"
|
||||||
method="put"
|
method="put"
|
||||||
submit-label="Perbarui"
|
submit-label="Perbarui"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import AdminLayout from '@/layouts/AdminLayout.vue';
|
|||||||
import type { PaginatedPurchases } from '@/types/purchase';
|
import type { PaginatedPurchases } from '@/types/purchase';
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import { index, create } from '@/routes/admin/manage/purchases';
|
||||||
import PurchaseGroupedTable from './table/PurchaseGroupedTable.vue';
|
import PurchaseGroupedTable from './table/PurchaseGroupedTable.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -25,7 +26,7 @@ const { can } = useCan();
|
|||||||
const search = ref(props.filters.search ?? '');
|
const search = ref(props.filters.search ?? '');
|
||||||
|
|
||||||
const { setSearch, resetFilters, syncFromServer } = useDataTableQuery({
|
const { setSearch, resetFilters, syncFromServer } = useDataTableQuery({
|
||||||
url: '/admin/manage/purchases',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ watch(
|
|||||||
|
|
||||||
<CreateButton
|
<CreateButton
|
||||||
v-if="can('purchases.create')"
|
v-if="can('purchases.create')"
|
||||||
href="/admin/manage/purchases/create"
|
:href="create.url()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -49,6 +49,7 @@ import type { MediaItem, MediaUploadState } from '@/types/media';
|
|||||||
import type { PurchaseCartItem, PurchaseCatalogItem, SelectOption } from '@/types/purchase';
|
import type { PurchaseCartItem, PurchaseCatalogItem, SelectOption } from '@/types/purchase';
|
||||||
import PosCatalogCard from '../../shared/PosCatalogCard.vue';
|
import PosCatalogCard from '../../shared/PosCatalogCard.vue';
|
||||||
import PosCatalogVariantThumb from '../../shared/PosCatalogVariantThumb.vue';
|
import PosCatalogVariantThumb from '../../shared/PosCatalogVariantThumb.vue';
|
||||||
|
import { store as syncDraftRoute, destroy as destroyDraftRoute } from '@/routes/admin/manage/purchases/draft_items';
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
suppliers: SelectOption[];
|
suppliers: SelectOption[];
|
||||||
catalog: PurchaseCatalogItem[];
|
catalog: PurchaseCatalogItem[];
|
||||||
@ -175,7 +176,7 @@ function lineSubtotal(item: PurchaseCartItem): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function syncDraftItem(priceId: number, quantity: number) {
|
async function syncDraftItem(priceId: number, quantity: number) {
|
||||||
const { item } = await apiFetch<{ item: PurchaseCartItem }>('/admin/manage/purchases/draft-items', {
|
const { item } = await apiFetch<{ item: PurchaseCartItem }>(syncDraftRoute.url(), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
raw_material_price_id: priceId,
|
raw_material_price_id: priceId,
|
||||||
@ -224,7 +225,7 @@ async function removeFromCart(index: number) {
|
|||||||
|
|
||||||
if (isCreateMode.value) {
|
if (isCreateMode.value) {
|
||||||
try {
|
try {
|
||||||
await apiFetch(`/admin/manage/purchases/draft-items/${item.raw_material_price_id}`, {
|
await apiFetch(destroyDraftRoute.url(item.raw_material_price_id), {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { PurchaseListItem } from '@/types/purchase';
|
import type { PurchaseListItem } from '@/types/purchase';
|
||||||
|
import { edit, destroy } from '@/routes/admin/manage/purchases';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
purchase: PurchaseListItem;
|
purchase: PurchaseListItem;
|
||||||
@ -21,7 +22,7 @@ const deleteProcessing = ref(false);
|
|||||||
function destroyPurchase() {
|
function destroyPurchase() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/manage/purchases/${props.purchase.id}`, {
|
router.delete(destroy.url(props.purchase.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
@ -41,7 +42,7 @@ function destroyPurchase() {
|
|||||||
<Tooltip v-if="can('purchases.update')">
|
<Tooltip v-if="can('purchases.update')">
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button variant="ghost" size="icon" class="size-8" as-child>
|
<Button variant="ghost" size="icon" class="size-8" as-child>
|
||||||
<Link :href="`/admin/manage/purchases/${purchase.id}/edit`">
|
<Link :href="edit.url(props.purchase.id)">
|
||||||
<Pencil class="size-4" />
|
<Pencil class="size-4" />
|
||||||
<span class="sr-only">Ubah</span>
|
<span class="sr-only">Ubah</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import {
|
|||||||
PRICE_TYPE_LABELS,
|
PRICE_TYPE_LABELS,
|
||||||
} from '@/types/product';
|
} from '@/types/product';
|
||||||
import type { CuttingListItem } from '@/types/cutting';
|
import type { CuttingListItem } from '@/types/cutting';
|
||||||
|
import { verify } from '@/routes/admin/manage/stocks';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
cutting: CuttingListItem;
|
cutting: CuttingListItem;
|
||||||
@ -145,7 +146,7 @@ function submitVerify() {
|
|||||||
})),
|
})),
|
||||||
result_prices: buildResultPricesPayload(),
|
result_prices: buildResultPricesPayload(),
|
||||||
}))
|
}))
|
||||||
.post(`/admin/manage/stocks/${props.cutting.id}/verify`, {
|
.post(verify.url(props.cutting.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
verifyDialogOpen.value = false;
|
verifyDialogOpen.value = false;
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { Head } from '@inertiajs/vue3';
|
|||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import CategoryFormModal from './form/CategoryFormModal.vue';
|
import CategoryFormModal from './form/CategoryFormModal.vue';
|
||||||
import { createColumns } from './table/columns';
|
import { createColumns } from './table/columns';
|
||||||
|
import { index } from '@/routes/admin/master/categories';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
categories: PaginatedCategories;
|
categories: PaginatedCategories;
|
||||||
@ -31,7 +32,7 @@ const editingCategory = ref<CategoryListItem | null>(null);
|
|||||||
|
|
||||||
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
||||||
useDataTableQuery({
|
useDataTableQuery({
|
||||||
url: '/admin/master/categories',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import { useFormDialog } from '@/composables/useFormDialog';
|
|||||||
import { FIELD_LIMITS } from '@/lib/field-limits';
|
import { FIELD_LIMITS } from '@/lib/field-limits';
|
||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import type { CategoryFormData, CategoryListItem } from '@/types/category';
|
import type { CategoryFormData, CategoryListItem } from '@/types/category';
|
||||||
|
import { store, update } from '@/routes/admin/master/categories';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -70,12 +71,12 @@ function submit() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isEditing.value && props.category) {
|
if (isEditing.value && props.category) {
|
||||||
form.put(`/admin/master/categories/${props.category.id}`, options);
|
form.put(update.url(props.category.id), options);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.post('/admin/master/categories', options);
|
form.post(store.url(), options);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { CategoryListItem } from '@/types/category';
|
import type { CategoryListItem } from '@/types/category';
|
||||||
|
import { destroy } from '@/routes/admin/master/categories';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
category: CategoryListItem;
|
category: CategoryListItem;
|
||||||
@ -25,7 +26,7 @@ const deleteProcessing = ref(false);
|
|||||||
function destroyCategory() {
|
function destroyCategory() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/master/categories/${props.category.id}`, {
|
router.delete(destroy.url(props.category.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { Head } from '@inertiajs/vue3';
|
|||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import CustomerFormModal from './form/CustomerFormModal.vue';
|
import CustomerFormModal from './form/CustomerFormModal.vue';
|
||||||
import { createColumns } from './table/columns';
|
import { createColumns } from './table/columns';
|
||||||
|
import { index } from '@/routes/admin/master/customers';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
customers: PaginatedCustomers;
|
customers: PaginatedCustomers;
|
||||||
@ -31,7 +32,7 @@ const editingCustomer = ref<CustomerListItem | null>(null);
|
|||||||
|
|
||||||
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
||||||
useDataTableQuery({
|
useDataTableQuery({
|
||||||
url: '/admin/master/customers',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import { useFormDialog } from '@/composables/useFormDialog';
|
|||||||
import { FIELD_LIMITS } from '@/lib/field-limits';
|
import { FIELD_LIMITS } from '@/lib/field-limits';
|
||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import type { CustomerFormData, CustomerListItem } from '@/types/customer';
|
import type { CustomerFormData, CustomerListItem } from '@/types/customer';
|
||||||
|
import { store, update } from '@/routes/admin/master/customers';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -76,12 +77,12 @@ function submit() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isEditing.value && props.customer) {
|
if (isEditing.value && props.customer) {
|
||||||
form.put(`/admin/master/customers/${props.customer.id}`, options);
|
form.put(update.url(props.customer.id), options);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.post('/admin/master/customers', options);
|
form.post(store.url(), options);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { CustomerListItem } from '@/types/customer';
|
import type { CustomerListItem } from '@/types/customer';
|
||||||
|
import { destroy } from '@/routes/admin/master/customers';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
customer: CustomerListItem;
|
customer: CustomerListItem;
|
||||||
@ -25,7 +26,7 @@ const deleteProcessing = ref(false);
|
|||||||
function destroyCustomer() {
|
function destroyCustomer() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/master/customers/${props.customer.id}`, {
|
router.delete(destroy.url(props.customer.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import AdminLayout from '@/layouts/AdminLayout.vue';
|
|||||||
import type { CategoryOption } from '@/types/product';
|
import type { CategoryOption } from '@/types/product';
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import ProductForm from './form/ProductForm.vue';
|
import ProductForm from './form/ProductForm.vue';
|
||||||
|
import { index, store } from '@/routes/admin/master/products';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
categories: CategoryOption[];
|
categories: CategoryOption[];
|
||||||
@ -21,11 +22,11 @@ defineProps<{
|
|||||||
<h2 class="text-2xl font-bold tracking-tight">Tambah Produk</h2>
|
<h2 class="text-2xl font-bold tracking-tight">Tambah Produk</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/master/products" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ProductForm
|
<ProductForm
|
||||||
submit-url="/admin/master/products"
|
:submit-url="store.url()"
|
||||||
method="post"
|
method="post"
|
||||||
submit-label="Simpan"
|
submit-label="Simpan"
|
||||||
:categories="categories"
|
:categories="categories"
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import type { CategoryOption, ProductListItem } from '@/types/product';
|
|||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import ProductForm from './form/ProductForm.vue';
|
import ProductForm from './form/ProductForm.vue';
|
||||||
|
import { index, update } from '@/routes/admin/master/products';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
product: ProductListItem & { description?: string | null };
|
product: ProductListItem & { description?: string | null };
|
||||||
@ -36,11 +37,11 @@ const initialData = computed(() => ({
|
|||||||
<h2 class="text-2xl font-bold tracking-tight">Ubah Produk</h2>
|
<h2 class="text-2xl font-bold tracking-tight">Ubah Produk</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/master/products" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ProductForm
|
<ProductForm
|
||||||
:submit-url="`/admin/master/products/${product.id}`"
|
:submit-url="update.url(props.product.id)"
|
||||||
method="put"
|
method="put"
|
||||||
submit-label="Perbarui"
|
submit-label="Perbarui"
|
||||||
:initial-data="initialData"
|
:initial-data="initialData"
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import type { DataTableFilterDef } from '@/types/data-table';
|
|||||||
import type { CategoryOption, PaginatedProducts } from '@/types/product';
|
import type { CategoryOption, PaginatedProducts } from '@/types/product';
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import { index, create } from '@/routes/admin/master/products';
|
||||||
import ProductGroupedTable from './table/ProductGroupedTable.vue';
|
import ProductGroupedTable from './table/ProductGroupedTable.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -33,7 +34,7 @@ const search = ref(props.filters.search ?? '');
|
|||||||
|
|
||||||
const { query, setSearch, setFilter, resetFilters, syncFromServer } =
|
const { query, setSearch, setFilter, resetFilters, syncFromServer } =
|
||||||
useDataTableQuery({
|
useDataTableQuery({
|
||||||
url: '/admin/master/products',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
filterKeys: ['is_active', 'category_id', 'stock_status'],
|
filterKeys: ['is_active', 'category_id', 'stock_status'],
|
||||||
});
|
});
|
||||||
@ -114,7 +115,7 @@ watch(
|
|||||||
|
|
||||||
<CreateButton
|
<CreateButton
|
||||||
v-if="can('products.create')"
|
v-if="can('products.create')"
|
||||||
href="/admin/master/products/create"
|
:href="create.url()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { ProductListItem } from '@/types/product';
|
import type { ProductListItem } from '@/types/product';
|
||||||
|
import { edit, destroy } from '@/routes/admin/master/products';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
product: ProductListItem;
|
product: ProductListItem;
|
||||||
@ -21,7 +22,7 @@ const deleteProcessing = ref(false);
|
|||||||
function destroyProduct() {
|
function destroyProduct() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/master/products/${props.product.id}`, {
|
router.delete(destroy.url(props.product.id), {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
},
|
},
|
||||||
@ -40,7 +41,7 @@ function destroyProduct() {
|
|||||||
<Tooltip v-if="can('products.update')">
|
<Tooltip v-if="can('products.update')">
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button variant="ghost" size="icon" class="size-8" as-child>
|
<Button variant="ghost" size="icon" class="size-8" as-child>
|
||||||
<Link :href="`/admin/master/products/${product.id}/edit`">
|
<Link :href="edit.url(props.product.id)">
|
||||||
<Pencil class="size-4" />
|
<Pencil class="size-4" />
|
||||||
<span class="sr-only">Ubah</span>
|
<span class="sr-only">Ubah</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { Badge } from '@/components/ui/badge';
|
|||||||
import { Switch } from '@/components/ui/switch';
|
import { Switch } from '@/components/ui/switch';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { ProductListItem } from '@/types/product';
|
import type { ProductListItem } from '@/types/product';
|
||||||
|
import { toggle_status } from '@/routes/admin/master/products';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
product: ProductListItem;
|
product: ProductListItem;
|
||||||
@ -32,7 +33,7 @@ function toggleStatus(checked: boolean) {
|
|||||||
isActive.value = checked;
|
isActive.value = checked;
|
||||||
processing.value = true;
|
processing.value = true;
|
||||||
|
|
||||||
router.patch(`/admin/master/products/${props.product.id}/toggle-status`, {
|
router.patch(toggle_status.url(props.product.id), {
|
||||||
is_active: checked,
|
is_active: checked,
|
||||||
}, {
|
}, {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import AdminLayout from '@/layouts/AdminLayout.vue';
|
|||||||
import type { EnumOption } from '@/types/raw-material';
|
import type { EnumOption } from '@/types/raw-material';
|
||||||
import RawMaterialForm from './form/RawMaterialForm.vue';
|
import RawMaterialForm from './form/RawMaterialForm.vue';
|
||||||
import BackButton from '@/components/button/BackButton.vue';
|
import BackButton from '@/components/button/BackButton.vue';
|
||||||
|
import { index, store } from '@/routes/admin/master/raw_materials';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
units: EnumOption[];
|
units: EnumOption[];
|
||||||
@ -22,9 +23,9 @@ defineProps<{
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/master/raw-materials" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<RawMaterialForm submit-url="/admin/master/raw-materials" method="post" submit-label="Simpan" :units="units" />
|
<RawMaterialForm :submit-url="store.url()" method="post" submit-label="Simpan" :units="units" />
|
||||||
</AdminLayout>
|
</AdminLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import type { EnumOption, RawMaterialListItem } from '@/types/raw-material';
|
|||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import RawMaterialForm from './form/RawMaterialForm.vue';
|
import RawMaterialForm from './form/RawMaterialForm.vue';
|
||||||
|
import { index, update } from '@/routes/admin/master/raw_materials';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
rawMaterial: RawMaterialListItem;
|
rawMaterial: RawMaterialListItem;
|
||||||
@ -37,11 +38,11 @@ const initialData = computed(() => ({
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/master/raw-materials" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<RawMaterialForm
|
<RawMaterialForm
|
||||||
:submit-url="`/admin/master/raw-materials/${rawMaterial.id}`"
|
:submit-url="update.url(props.rawMaterial.id)"
|
||||||
method="put"
|
method="put"
|
||||||
submit-label="Perbarui"
|
submit-label="Perbarui"
|
||||||
:initial-data="initialData"
|
:initial-data="initialData"
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import type { DataTableFilterDef } from '@/types/data-table';
|
|||||||
import type { PaginatedRawMaterials } from '@/types/raw-material';
|
import type { PaginatedRawMaterials } from '@/types/raw-material';
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import { index, create } from '@/routes/admin/master/raw_materials';
|
||||||
import RawMaterialGroupedTable from './table/RawMaterialGroupedTable.vue';
|
import RawMaterialGroupedTable from './table/RawMaterialGroupedTable.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -31,7 +32,7 @@ const search = ref(props.filters.search ?? '');
|
|||||||
|
|
||||||
const { query, setSearch, setFilter, resetFilters, syncFromServer } =
|
const { query, setSearch, setFilter, resetFilters, syncFromServer } =
|
||||||
useDataTableQuery({
|
useDataTableQuery({
|
||||||
url: '/admin/master/raw-materials',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
filterKeys: ['is_active', 'stock_status'],
|
filterKeys: ['is_active', 'stock_status'],
|
||||||
});
|
});
|
||||||
@ -103,7 +104,7 @@ watch(
|
|||||||
|
|
||||||
<CreateButton
|
<CreateButton
|
||||||
v-if="can('raw_materials.create')"
|
v-if="can('raw_materials.create')"
|
||||||
href="/admin/master/raw-materials/create"
|
:href="create.url()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { RawMaterialListItem } from '@/types/raw-material';
|
import type { RawMaterialListItem } from '@/types/raw-material';
|
||||||
|
import { edit, destroy } from '@/routes/admin/master/raw_materials';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
material: RawMaterialListItem;
|
material: RawMaterialListItem;
|
||||||
@ -21,7 +22,7 @@ const deleteProcessing = ref(false);
|
|||||||
function destroyRawMaterial() {
|
function destroyRawMaterial() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/master/raw-materials/${props.material.id}`, {
|
router.delete(destroy.url(props.material.id), {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
},
|
},
|
||||||
@ -40,7 +41,7 @@ function destroyRawMaterial() {
|
|||||||
<Tooltip v-if="can('raw_materials.update')">
|
<Tooltip v-if="can('raw_materials.update')">
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button variant="ghost" size="icon" class="size-8" as-child>
|
<Button variant="ghost" size="icon" class="size-8" as-child>
|
||||||
<Link :href="`/admin/master/raw-materials/${material.id}/edit`">
|
<Link :href="edit.url(props.material.id)">
|
||||||
<Pencil class="size-4" />
|
<Pencil class="size-4" />
|
||||||
<span class="sr-only">Ubah</span>
|
<span class="sr-only">Ubah</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { Badge } from '@/components/ui/badge';
|
|||||||
import { Switch } from '@/components/ui/switch';
|
import { Switch } from '@/components/ui/switch';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { RawMaterialListItem } from '@/types/raw-material';
|
import type { RawMaterialListItem } from '@/types/raw-material';
|
||||||
|
import { toggle_status } from '@/routes/admin/master/raw_materials';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
material: RawMaterialListItem;
|
material: RawMaterialListItem;
|
||||||
@ -32,7 +33,7 @@ function toggleStatus(checked: boolean) {
|
|||||||
isActive.value = checked;
|
isActive.value = checked;
|
||||||
processing.value = true;
|
processing.value = true;
|
||||||
|
|
||||||
router.patch(`/admin/master/raw-materials/${props.material.id}/toggle-status`, {
|
router.patch(toggle_status.url(props.material.id), {
|
||||||
is_active: checked,
|
is_active: checked,
|
||||||
}, {
|
}, {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { Head } from '@inertiajs/vue3';
|
|||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import SupplierFormModal from './form/SupplierFormModal.vue';
|
import SupplierFormModal from './form/SupplierFormModal.vue';
|
||||||
import { createColumns } from './table/columns';
|
import { createColumns } from './table/columns';
|
||||||
|
import { index } from '@/routes/admin/master/suppliers';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
suppliers: PaginatedSuppliers;
|
suppliers: PaginatedSuppliers;
|
||||||
@ -31,7 +32,7 @@ const editingSupplier = ref<SupplierListItem | null>(null);
|
|||||||
|
|
||||||
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
||||||
useDataTableQuery({
|
useDataTableQuery({
|
||||||
url: '/admin/master/suppliers',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import { useFormDialog } from '@/composables/useFormDialog';
|
|||||||
import { FIELD_LIMITS } from '@/lib/field-limits';
|
import { FIELD_LIMITS } from '@/lib/field-limits';
|
||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import type { SupplierFormData, SupplierListItem } from '@/types/supplier';
|
import type { SupplierFormData, SupplierListItem } from '@/types/supplier';
|
||||||
|
import { store, update } from '@/routes/admin/master/suppliers';
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -76,12 +77,12 @@ function submit() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isEditing.value && props.supplier) {
|
if (isEditing.value && props.supplier) {
|
||||||
form.put(`/admin/master/suppliers/${props.supplier.id}`, options);
|
form.put(update.url(props.supplier.id), options);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.post('/admin/master/suppliers', options);
|
form.post(store.url(), options);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { SupplierListItem } from '@/types/supplier';
|
import type { SupplierListItem } from '@/types/supplier';
|
||||||
|
import { destroy } from '@/routes/admin/master/suppliers';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
supplier: SupplierListItem;
|
supplier: SupplierListItem;
|
||||||
@ -25,7 +26,7 @@ const deleteProcessing = ref(false);
|
|||||||
function destroySupplier() {
|
function destroySupplier() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/master/suppliers/${props.supplier.id}`, {
|
router.delete(destroy.url(props.supplier.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import type { ActivityLogListItem, PaginatedActivityLogs, SelectOption } from '@
|
|||||||
import type { DataTableSort } from '@/types/data-table';
|
import type { DataTableSort } from '@/types/data-table';
|
||||||
import ActivityLogDetailModal from './table/ActivityLogDetailModal.vue';
|
import ActivityLogDetailModal from './table/ActivityLogDetailModal.vue';
|
||||||
import { createColumns } from './table/columns';
|
import { createColumns } from './table/columns';
|
||||||
|
import { index } from '@/routes/admin/system/activity_logs';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
activityLogs: PaginatedActivityLogs;
|
activityLogs: PaginatedActivityLogs;
|
||||||
@ -28,7 +29,7 @@ const detailModalOpen = ref(false);
|
|||||||
const selectedActivityLog = ref<ActivityLogListItem | null>(null);
|
const selectedActivityLog = ref<ActivityLogListItem | null>(null);
|
||||||
|
|
||||||
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } = useDataTableQuery({
|
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } = useDataTableQuery({
|
||||||
url: '/admin/system/activity-logs',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
filterKeys: ['event', 'subject_type'],
|
filterKeys: ['event', 'subject_type'],
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { Head, Link } from '@inertiajs/vue3';
|
|||||||
import AdminLayout from '@/layouts/AdminLayout.vue';
|
import AdminLayout from '@/layouts/AdminLayout.vue';
|
||||||
import RoleForm from './form/RoleForm.vue';
|
import RoleForm from './form/RoleForm.vue';
|
||||||
import BackButton from '@/components/button/BackButton.vue';
|
import BackButton from '@/components/button/BackButton.vue';
|
||||||
|
import { index, store } from '@/routes/admin/system/roles';
|
||||||
|
|
||||||
interface PermissionOption {
|
interface PermissionOption {
|
||||||
value: string;
|
value: string;
|
||||||
@ -27,9 +28,9 @@ defineProps<{
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/system/roles" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<RoleForm submit-url="/admin/system/roles" method="post" submit-label="Simpan" :permissions="permissions" />
|
<RoleForm :submit-url="store.url()" method="post" submit-label="Simpan" :permissions="permissions" />
|
||||||
</AdminLayout>
|
</AdminLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import BackButton from '@/components/button/BackButton.vue';
|
|||||||
import AdminLayout from '@/layouts/AdminLayout.vue';
|
import AdminLayout from '@/layouts/AdminLayout.vue';
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import RoleForm from './form/RoleForm.vue';
|
import RoleForm from './form/RoleForm.vue';
|
||||||
|
import { index, update } from '@/routes/admin/system/roles';
|
||||||
|
|
||||||
interface PermissionOption {
|
interface PermissionOption {
|
||||||
value: string;
|
value: string;
|
||||||
@ -33,11 +34,11 @@ defineProps<{
|
|||||||
<h2 class="text-2xl font-bold tracking-tight">Ubah Role</h2>
|
<h2 class="text-2xl font-bold tracking-tight">Ubah Role</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BackButton href="/admin/system/roles" />
|
<BackButton :href="index.url()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<RoleForm
|
<RoleForm
|
||||||
:submit-url="`/admin/system/roles/${role.id}`"
|
:submit-url="update.url(role.id)"
|
||||||
method="put"
|
method="put"
|
||||||
submit-label="Perbarui"
|
submit-label="Perbarui"
|
||||||
:initial-data="role"
|
:initial-data="role"
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import AdminLayout from '@/layouts/AdminLayout.vue';
|
|||||||
import type { DataTableSort } from '@/types/data-table';
|
import type { DataTableSort } from '@/types/data-table';
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import { index, create } from '@/routes/admin/system/roles';
|
||||||
import type { RoleListItem } from './table/columns';
|
import type { RoleListItem } from './table/columns';
|
||||||
import { createColumns } from './table/columns';
|
import { createColumns } from './table/columns';
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ const search = ref(props.filters.search ?? '');
|
|||||||
|
|
||||||
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
const { query, setSearch, setSort, resetFilters, syncFromServer } =
|
||||||
useDataTableQuery({
|
useDataTableQuery({
|
||||||
url: '/admin/system/roles',
|
url: index.url(),
|
||||||
initial: { ...props.filters },
|
initial: { ...props.filters },
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -90,7 +91,7 @@ watch(
|
|||||||
|
|
||||||
<CreateButton
|
<CreateButton
|
||||||
v-if="can('roles.create')"
|
v-if="can('roles.create')"
|
||||||
href="/admin/system/roles/create"
|
:href="create.url()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Link, router } from '@inertiajs/vue3';
|
import { Link, router } from '@inertiajs/vue3';
|
||||||
import { Pencil, Trash2 } from '@lucide/vue';
|
import { Pencil, Trash2 } from '@lucide/vue';
|
||||||
import { ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { toast } from 'vue-sonner';
|
import { toast } from 'vue-sonner';
|
||||||
import ConfirmDialog from '@/components/ConfirmDialog.vue';
|
import ConfirmDialog from '@/components/ConfirmDialog.vue';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { useCan } from '@/composables/useCan';
|
import { useCan } from '@/composables/useCan';
|
||||||
import type { RoleListItem } from './columns';
|
import type { RoleListItem } from './columns';
|
||||||
|
import { edit, destroy } from '@/routes/admin/system/roles';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
role: RoleListItem;
|
role: RoleListItem;
|
||||||
@ -18,10 +19,14 @@ const { can } = useCan();
|
|||||||
const deleteConfirmOpen = ref(false);
|
const deleteConfirmOpen = ref(false);
|
||||||
const deleteProcessing = ref(false);
|
const deleteProcessing = ref(false);
|
||||||
|
|
||||||
|
const isSystemRole = computed(() => {
|
||||||
|
return ['developer', 'owner', 'admin-toko', 'admin-bahan-baku', 'direktur', 'marketing', 'cashier', 'non-operator'].includes(props.role.name);
|
||||||
|
});
|
||||||
|
|
||||||
function destroyRole() {
|
function destroyRole() {
|
||||||
deleteProcessing.value = true;
|
deleteProcessing.value = true;
|
||||||
|
|
||||||
router.delete(`/admin/system/roles/${props.role.id}`, {
|
router.delete(destroy.url(props.role.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
deleteConfirmOpen.value = false;
|
deleteConfirmOpen.value = false;
|
||||||
@ -41,7 +46,7 @@ function destroyRole() {
|
|||||||
<Tooltip v-if="can('roles.update')">
|
<Tooltip v-if="can('roles.update')">
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button variant="ghost" size="icon" class="size-8" as-child>
|
<Button variant="ghost" size="icon" class="size-8" as-child>
|
||||||
<Link :href="`/admin/system/roles/${role.id}/edit`">
|
<Link :href="edit.url(props.role.id)">
|
||||||
<Pencil class="size-4" />
|
<Pencil class="size-4" />
|
||||||
<span class="sr-only">Ubah</span>
|
<span class="sr-only">Ubah</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { Card, CardContent } from '@/components/ui/card';
|
|||||||
import { createMediaUploadState } from '@/types/media';
|
import { createMediaUploadState } from '@/types/media';
|
||||||
import type { MediaUploadState } from '@/types/media';
|
import type { MediaUploadState } from '@/types/media';
|
||||||
import type { HomepageSettingsData } from '@/types/setting';
|
import type { HomepageSettingsData } from '@/types/setting';
|
||||||
|
import { update } from '@/routes/admin/system/settings/homepage';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: HomepageSettingsData;
|
data: HomepageSettingsData;
|
||||||
@ -42,7 +43,7 @@ function submit() {
|
|||||||
formData.append('gallery_images_remove[]', String(id));
|
formData.append('gallery_images_remove[]', String(id));
|
||||||
});
|
});
|
||||||
|
|
||||||
router.put('/admin/system/settings/homepage', formData, {
|
router.put(update.url(), formData, {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
heroImage.value = createMediaUploadState();
|
heroImage.value = createMediaUploadState();
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { Field, FieldError, FieldGroup, FieldLabel, FieldSet } from '@/component
|
|||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import type { HrSettingsData } from '@/types/setting';
|
import type { HrSettingsData } from '@/types/setting';
|
||||||
|
import { update } from '@/routes/admin/system/settings/hr';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: HrSettingsData;
|
data: HrSettingsData;
|
||||||
@ -22,7 +23,7 @@ const form = useForm({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
form.put('/admin/system/settings/hr', {
|
form.put(update.url(), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onError: () => {
|
onError: () => {
|
||||||
toast.error('Gagal menyimpan pengaturan HR.');
|
toast.error('Gagal menyimpan pengaturan HR.');
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import type {
|
|||||||
MarketplaceSettingsData,
|
MarketplaceSettingsData,
|
||||||
} from '@/types/setting';
|
} from '@/types/setting';
|
||||||
import MarketplaceFeeField from './MarketplaceFeeField.vue';
|
import MarketplaceFeeField from './MarketplaceFeeField.vue';
|
||||||
|
import { update } from '@/routes/admin/system/settings/marketplace';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: MarketplaceSettingsData;
|
data: MarketplaceSettingsData;
|
||||||
@ -64,7 +65,7 @@ function feeErrors(key: string): string[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
form.put('/admin/system/settings/marketplace', {
|
form.put(update.url(), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onError: () => {
|
onError: () => {
|
||||||
toast.error('Gagal menyimpan pengaturan marketplace.');
|
toast.error('Gagal menyimpan pengaturan marketplace.');
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Field, FieldError, FieldGroup, FieldLabel, FieldSet } from '@/component
|
|||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import type { SocialMediaSettingsData } from '@/types/setting';
|
import type { SocialMediaSettingsData } from '@/types/setting';
|
||||||
|
import { update } from '@/routes/admin/system/settings/social_media';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: SocialMediaSettingsData;
|
data: SocialMediaSettingsData;
|
||||||
@ -20,7 +21,7 @@ const form = useForm({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
form.put('/admin/system/settings/social-media', {
|
form.put(update.url(), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onError: () => {
|
onError: () => {
|
||||||
toast.error('Gagal menyimpan pengaturan media sosial.');
|
toast.error('Gagal menyimpan pengaturan media sosial.');
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { formErrors } from '@/lib/form';
|
|||||||
import { createMediaUploadState } from '@/types/media';
|
import { createMediaUploadState } from '@/types/media';
|
||||||
import type { MediaUploadState } from '@/types/media';
|
import type { MediaUploadState } from '@/types/media';
|
||||||
import type { SystemSettingsData } from '@/types/setting';
|
import type { SystemSettingsData } from '@/types/setting';
|
||||||
|
import { update } from '@/routes/admin/system/settings/system';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: SystemSettingsData;
|
data: SystemSettingsData;
|
||||||
@ -58,7 +59,7 @@ function buildFormData(): FormData {
|
|||||||
function submit() {
|
function submit() {
|
||||||
const payload = buildFormData();
|
const payload = buildFormData();
|
||||||
|
|
||||||
form.transform(() => payload).put('/admin/system/settings/system', {
|
form.transform(() => payload).put(update.url(), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onError: () => {
|
onError: () => {
|
||||||
toast.error('Gagal menyimpan pengaturan sistem.');
|
toast.error('Gagal menyimpan pengaturan sistem.');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user