feat:수퍼관리자 가망고객 삭제 기능 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -224,7 +224,9 @@ private function getIndexData(Request $request): array
|
||||
];
|
||||
});
|
||||
|
||||
return compact('prospects', 'stats', 'salesPartners', 'partnerStats', 'filters');
|
||||
$isSuperAdmin = auth()->user()->isSuperAdmin();
|
||||
|
||||
return compact('prospects', 'stats', 'salesPartners', 'partnerStats', 'filters', 'isSuperAdmin');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,6 +304,29 @@ public function updateCommissionDate(int $id, Request $request)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 가망고객 삭제 (슈퍼관리자 전용)
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
{
|
||||
$prospect = TenantProspect::findOrFail($id);
|
||||
|
||||
// 연관 데이터 삭제
|
||||
$management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();
|
||||
if ($management) {
|
||||
SalesCommission::where('management_id', $management->id)->delete();
|
||||
$management->delete();
|
||||
}
|
||||
SalesScenarioChecklist::where('tenant_prospect_id', $prospect->id)->delete();
|
||||
|
||||
$prospect->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "'{$prospect->company_name}' 가망고객이 삭제되었습니다.",
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 수당 날짜 삭제 (초기화)
|
||||
*/
|
||||
|
||||
@@ -52,6 +52,36 @@ class="refresh-btn inline-flex items-center gap-1.5 px-4 py-2 text-sm text-gray-
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 삭제 확인 모달 -->
|
||||
@if(auth()->user()->isSuperAdmin())
|
||||
<div id="deleteModal" class="hidden fixed inset-0 z-50 overflow-y-auto">
|
||||
<div class="fixed inset-0 bg-black bg-opacity-50 transition-opacity" onclick="closeDeleteModal()"></div>
|
||||
<div class="flex min-h-full items-center justify-center p-4">
|
||||
<div class="relative bg-white rounded-xl shadow-2xl w-full max-w-md p-6">
|
||||
<div class="text-center">
|
||||
<div class="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-red-100 mb-4">
|
||||
<svg class="h-6 w-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-lg font-bold text-gray-900 mb-2">가망고객 삭제</h3>
|
||||
<p class="text-sm text-gray-500 mb-1">다음 가망고객을 삭제하시겠습니까?</p>
|
||||
<p id="deleteTargetName" class="text-base font-semibold text-red-600 mb-4"></p>
|
||||
<p class="text-xs text-gray-400 mb-6">관련된 시나리오 체크리스트, 관리 정보, 수당 정보가 함께 삭제됩니다.</p>
|
||||
</div>
|
||||
<div class="flex gap-3">
|
||||
<button type="button" onclick="closeDeleteModal()" class="flex-1 px-4 py-2.5 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg transition">
|
||||
취소
|
||||
</button>
|
||||
<button type="button" id="confirmDeleteBtn" onclick="confirmDelete()" class="flex-1 px-4 py-2.5 text-sm font-medium text-white bg-red-600 hover:bg-red-700 rounded-lg transition">
|
||||
삭제
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- 상세 모달 -->
|
||||
<div id="detailModal" class="hidden fixed inset-0 z-50 overflow-y-auto">
|
||||
<div class="fixed inset-0 bg-black bg-opacity-50 transition-opacity"></div>
|
||||
@@ -165,6 +195,55 @@ function closeDetailModal() {
|
||||
}
|
||||
});
|
||||
|
||||
// 삭제 모달
|
||||
let deleteProspectId = null;
|
||||
|
||||
function openDeleteModal(id, companyName) {
|
||||
deleteProspectId = id;
|
||||
document.getElementById('deleteTargetName').textContent = companyName;
|
||||
document.getElementById('deleteModal').classList.remove('hidden');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function closeDeleteModal() {
|
||||
document.getElementById('deleteModal').classList.add('hidden');
|
||||
document.body.style.overflow = '';
|
||||
deleteProspectId = null;
|
||||
}
|
||||
|
||||
function confirmDelete() {
|
||||
if (!deleteProspectId) return;
|
||||
|
||||
const btn = document.getElementById('confirmDeleteBtn');
|
||||
btn.disabled = true;
|
||||
btn.textContent = '삭제 중...';
|
||||
|
||||
fetch(`/sales/admin-prospects/${deleteProspectId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
closeDeleteModal();
|
||||
window.location.reload();
|
||||
} else {
|
||||
alert(result.message || '삭제에 실패했습니다.');
|
||||
btn.disabled = false;
|
||||
btn.textContent = '삭제';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('삭제 중 오류가 발생했습니다.');
|
||||
btn.disabled = false;
|
||||
btn.textContent = '삭제';
|
||||
});
|
||||
}
|
||||
|
||||
// 수당 날짜 저장 (date input에서 호출)
|
||||
function saveCommissionDate(prospectId, field, date) {
|
||||
const input = document.querySelector(`input[data-prospect-id="${prospectId}"][data-field="${field}"]`);
|
||||
|
||||
@@ -213,7 +213,19 @@ class="text-xs font-medium rounded-lg px-2 py-1 border cursor-pointer
|
||||
{{ $prospect->created_at->format('Y-m-d') }}
|
||||
</td>
|
||||
<td class="px-4 py-3 whitespace-nowrap text-right text-sm font-medium">
|
||||
<button type="button" onclick="openDetailModal({{ $prospect->id }})" class="text-blue-600 hover:text-blue-900">상세</button>
|
||||
<div class="flex items-center justify-end gap-2">
|
||||
<button type="button" onclick="openDetailModal({{ $prospect->id }})" class="text-blue-600 hover:text-blue-900">상세</button>
|
||||
@if($isSuperAdmin)
|
||||
<button type="button"
|
||||
onclick="openDeleteModal({{ $prospect->id }}, '{{ addslashes($prospect->company_name) }}')"
|
||||
class="text-red-500 hover:text-red-700"
|
||||
title="삭제">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
||||
</svg>
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
|
||||
@@ -1151,6 +1151,7 @@
|
||||
Route::post('admin-prospects/{id}/hq-status', [\App\Http\Controllers\Sales\AdminProspectController::class, 'updateHqStatus'])->name('admin-prospects.update-hq-status');
|
||||
Route::post('admin-prospects/{id}/commission-date', [\App\Http\Controllers\Sales\AdminProspectController::class, 'updateCommissionDate'])->name('admin-prospects.update-commission-date');
|
||||
Route::delete('admin-prospects/{id}/commission-date', [\App\Http\Controllers\Sales\AdminProspectController::class, 'clearCommissionDate'])->name('admin-prospects.clear-commission-date');
|
||||
Route::delete('admin-prospects/{id}', [\App\Http\Controllers\Sales\AdminProspectController::class, 'destroy'])->name('admin-prospects.destroy')->middleware('super.admin');
|
||||
|
||||
// 영업 시나리오 관리
|
||||
Route::prefix('scenarios')->name('scenarios.')->group(function () {
|
||||
|
||||
Reference in New Issue
Block a user