feat:바로빌 서비스 설정 체크박스 즉시 저장 기능 추가

This commit is contained in:
김보곤
2026-02-02 20:57:44 +09:00
parent aef480f646
commit 26e007c6a0
3 changed files with 100 additions and 21 deletions

View File

@@ -102,6 +102,53 @@ public function store(Request $request): JsonResponse
}
}
/**
* 서비스 설정 개별 저장 (체크박스 변경 시 즉시 저장)
*/
public function updateService(Request $request): JsonResponse
{
$tenantId = session('selected_tenant_id', 1);
$validated = $request->validate([
'field' => 'required|in:use_tax_invoice,use_bank_account,use_card_usage,use_hometax',
'value' => 'required|boolean',
]);
try {
$setting = BarobillSetting::updateOrCreate(
['tenant_id' => $tenantId],
[
$validated['field'] => $validated['value'],
'corp_name' => '미설정',
'ceo_name' => '미설정',
'corp_num' => '0000000000',
]
);
$serviceNames = [
'use_tax_invoice' => '전자세금계산서',
'use_bank_account' => '계좌조회',
'use_card_usage' => '카드사용내역',
'use_hometax' => '홈텍스매입/매출',
];
$serviceName = $serviceNames[$validated['field']] ?? $validated['field'];
$status = $validated['value'] ? '활성화' : '비활성화';
return response()->json([
'success' => true,
'message' => "{$serviceName} 서비스가 {$status}되었습니다.",
]);
} catch (\Exception $e) {
Log::error('바로빌 서비스 설정 저장 실패', ['error' => $e->getMessage()]);
return response()->json([
'success' => false,
'message' => '설정 저장에 실패했습니다.',
], 500);
}
}
/**
* 서비스 이용 여부 확인 (다른 메뉴에서 참조용)
*/

View File

@@ -83,7 +83,7 @@
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<!-- 전자세금계산서 -->
<label class="flex items-start gap-3 p-4 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition border-2 border-transparent has-[:checked]:border-blue-500 has-[:checked]:bg-blue-50">
<input type="checkbox" name="use_tax_invoice" id="use_tax_invoice" class="mt-1 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500">
<input type="checkbox" name="use_tax_invoice" id="use_tax_invoice" class="service-checkbox mt-1 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500" onchange="saveServiceSetting('use_tax_invoice', this.checked)">
<div>
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -97,7 +97,7 @@
<!-- 계좌조회 -->
<label class="flex items-start gap-3 p-4 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition border-2 border-transparent has-[:checked]:border-green-500 has-[:checked]:bg-green-50">
<input type="checkbox" name="use_bank_account" id="use_bank_account" class="mt-1 w-4 h-4 text-green-600 bg-gray-100 border-gray-300 rounded focus:ring-green-500">
<input type="checkbox" name="use_bank_account" id="use_bank_account" class="service-checkbox mt-1 w-4 h-4 text-green-600 bg-gray-100 border-gray-300 rounded focus:ring-green-500" onchange="saveServiceSetting('use_bank_account', this.checked)">
<div>
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -111,7 +111,7 @@
<!-- 카드사용내역 -->
<label class="flex items-start gap-3 p-4 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition border-2 border-transparent has-[:checked]:border-purple-500 has-[:checked]:bg-purple-50">
<input type="checkbox" name="use_card_usage" id="use_card_usage" class="mt-1 w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 rounded focus:ring-purple-500">
<input type="checkbox" name="use_card_usage" id="use_card_usage" class="service-checkbox mt-1 w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 rounded focus:ring-purple-500" onchange="saveServiceSetting('use_card_usage', this.checked)">
<div>
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -125,7 +125,7 @@
<!-- 홈텍스매입/매출 -->
<label class="flex items-start gap-3 p-4 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition border-2 border-transparent has-[:checked]:border-orange-500 has-[:checked]:bg-orange-50">
<input type="checkbox" name="use_hometax" id="use_hometax" class="mt-1 w-4 h-4 text-orange-600 bg-gray-100 border-gray-300 rounded focus:ring-orange-500">
<input type="checkbox" name="use_hometax" id="use_hometax" class="service-checkbox mt-1 w-4 h-4 text-orange-600 bg-gray-100 border-gray-300 rounded focus:ring-orange-500" onchange="saveServiceSetting('use_hometax', this.checked)">
<div>
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-orange-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -224,29 +224,60 @@
@push('scripts')
<script>
// 서비스 설정 개별 저장 (체크박스 변경 시 즉시 저장)
async function saveServiceSetting(field, value) {
const toast = document.getElementById('toast');
try {
const response = await fetch('/api/admin/barobill/settings/service', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
},
body: JSON.stringify({ field: field, value: value }),
});
const result = await response.json();
if (result.success) {
showToast(result.message || '설정이 저장되었습니다.', 'success');
} else {
showToast(result.message || '설정 저장에 실패했습니다.', 'error');
// 실패 시 체크박스 원상복구
document.getElementById(field).checked = !value;
}
} catch (error) {
console.error('설정 저장 실패:', error);
showToast('설정 저장 중 오류가 발생했습니다.', 'error');
// 실패 시 체크박스 원상복구
document.getElementById(field).checked = !value;
}
}
// 토스트 표시 (전역 함수)
function showToast(message, type = 'success') {
const toast = document.getElementById('toast');
toast.textContent = message;
toast.className = 'fixed bottom-4 right-4 px-4 py-3 rounded-lg shadow-lg transform transition-all duration-300 z-50';
if (type === 'success') {
toast.classList.add('bg-green-600', 'text-white');
} else {
toast.classList.add('bg-red-600', 'text-white');
}
toast.classList.remove('translate-y-full', 'opacity-0');
setTimeout(() => {
toast.classList.add('translate-y-full', 'opacity-0');
}, 3000);
}
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('settings-form');
const toast = document.getElementById('toast');
const saveSpinner = document.getElementById('save-spinner');
const btnSave = document.getElementById('btn-save');
const btnReset = document.getElementById('btn-reset');
// 토스트 표시
function showToast(message, type = 'success') {
toast.textContent = message;
toast.className = 'fixed bottom-4 right-4 px-4 py-3 rounded-lg shadow-lg transform transition-all duration-300 z-50';
if (type === 'success') {
toast.classList.add('bg-green-600', 'text-white');
} else {
toast.classList.add('bg-red-600', 'text-white');
}
toast.classList.remove('translate-y-full', 'opacity-0');
setTimeout(() => {
toast.classList.add('translate-y-full', 'opacity-0');
}, 3000);
}
// 설정 로드
async function loadSettings() {
try {

View File

@@ -108,6 +108,7 @@
Route::prefix('barobill/settings')->name('barobill.settings.')->group(function () {
Route::get('/', [\App\Http\Controllers\Api\Admin\Barobill\BarobillSettingController::class, 'show'])->name('show');
Route::post('/', [\App\Http\Controllers\Api\Admin\Barobill\BarobillSettingController::class, 'store'])->name('store');
Route::post('/service', [\App\Http\Controllers\Api\Admin\Barobill\BarobillSettingController::class, 'updateService'])->name('update-service');
Route::get('/check/{service}', [\App\Http\Controllers\Api\Admin\Barobill\BarobillSettingController::class, 'checkService'])->name('check');
});