Files
sam-manage/resources/views/sales/business-cards/admin-index.blade.php
김보곤 5793845def feat: [business-cards] 처리완료 삭제 기능 추가 및 기본 매수 500매로 변경
- 관리자 화면 처리완료 카드에 삭제 버튼 추가
- processed 상태만 삭제 가능 (서비스 검증)
- 파트너 명함신청 기본 매수 100매 → 500매 변경
2026-02-26 14:06:36 +09:00

357 lines
19 KiB
PHP

@extends('layouts.app')
@section('title', '명함신청 처리')
@section('content')
<div class="flex flex-col h-full">
<!-- 페이지 헤더 -->
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-4 flex-shrink-0">
<div>
<h1 class="text-2xl font-bold text-gray-800">명함신청 처리</h1>
<p class="text-sm text-gray-500 mt-1">
요청 <span class="text-blue-600 font-medium">제작의뢰</span> <span class="text-emerald-600 font-medium">처리완료</span>
</p>
</div>
</div>
<!-- 통계 카드 -->
<div class="grid grid-cols-4 gap-3 mb-4 flex-shrink-0">
<div class="bg-yellow-50 rounded-lg shadow-sm p-3">
<div class="text-xs text-yellow-600">신규 요청</div>
<div class="text-xl font-bold text-yellow-800">{{ number_format($stats['pending']) }}</div>
</div>
<div class="bg-blue-50 rounded-lg shadow-sm p-3">
<div class="text-xs text-blue-600">제작의뢰</div>
<div class="text-xl font-bold text-blue-800">{{ number_format($stats['ordered']) }}</div>
</div>
<div class="bg-emerald-50 rounded-lg shadow-sm p-3">
<div class="text-xs text-emerald-600">오늘 처리</div>
<div class="text-xl font-bold text-emerald-800">{{ number_format($stats['processed_today']) }}</div>
</div>
<div class="bg-gray-50 rounded-lg shadow-sm p-3">
<div class="text-xs text-gray-500">전체</div>
<div class="text-xl font-bold text-gray-700">{{ number_format($stats['total']) }}</div>
</div>
</div>
<!-- 검색 -->
<div class="flex-shrink-0 mb-4">
<form method="GET" class="flex flex-wrap gap-2 sm:gap-4 items-center bg-white p-3 rounded-lg shadow-sm">
<div class="flex-1 min-w-0 w-full sm:w-auto">
<input type="text"
name="search"
value="{{ $search }}"
placeholder="성함, 전화번호, 이메일로 검색..."
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm">
</div>
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg transition text-sm">
검색
</button>
</form>
</div>
<!-- 2분할: 신규 요청 / 제작의뢰 -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4 mb-4" style="min-height: 300px;">
<!-- 좌측: 신규 요청 -->
<div class="bg-white rounded-lg shadow-sm overflow-hidden flex flex-col min-h-0">
<div class="bg-yellow-500 text-white px-4 py-3 flex items-center gap-2 flex-shrink-0">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="font-semibold">신규 요청</span>
<span class="ml-auto bg-yellow-600 px-2 py-0.5 rounded-full text-xs">{{ $pendingRequests->total() }}</span>
</div>
<div class="overflow-y-auto flex-1">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 sticky top-0">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">신청자</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">연락처</th>
<th class="px-4 py-2 text-center text-xs font-medium text-gray-500 uppercase">수량</th>
<th class="px-4 py-2 text-center text-xs font-medium text-gray-500 uppercase">처리</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@forelse($pendingRequests as $req)
<tr class="hover:bg-yellow-50">
<td class="px-4 py-3">
<div class="font-medium text-gray-900 text-sm">{{ $req->name }}</div>
<div class="text-xs text-gray-500">{{ $req->title ?: '-' }}</div>
<div class="text-xs text-gray-400">{{ $req->created_at->format('m/d H:i') }}</div>
</td>
<td class="px-4 py-3">
<div class="text-sm text-gray-900">{{ $req->phone }}</div>
<div class="text-xs text-gray-500">{{ $req->email ?: '-' }}</div>
</td>
<td class="px-4 py-3 text-center text-sm text-gray-700">
{{ number_format($req->quantity) }}
</td>
<td class="px-4 py-3 text-center">
<button type="button"
onclick="orderRequest({{ $req->id }}, '{{ $req->name }}')"
class="px-3 py-1 bg-blue-500 hover:bg-blue-600 text-white text-xs font-medium rounded transition">
제작의뢰
</button>
</td>
</tr>
@if($req->memo)
<tr>
<td colspan="4" class="px-4 py-1 bg-yellow-50">
<div class="text-xs text-gray-500"><span class="font-medium">메모:</span> {{ $req->memo }}</div>
</td>
</tr>
@endif
@empty
<tr>
<td colspan="4" class="px-4 py-8 text-center text-gray-500 text-sm">
<svg class="w-12 h-12 mx-auto text-gray-300 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
신규 요청이 없습니다.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if($pendingRequests->hasPages())
<div class="px-4 py-2 border-t border-gray-200 flex-shrink-0 bg-gray-50">
{{ $pendingRequests->withQueryString()->links() }}
</div>
@endif
</div>
<!-- 우측: 제작의뢰 -->
<div class="bg-white rounded-lg shadow-sm overflow-hidden flex flex-col min-h-0">
<div class="bg-blue-500 text-white px-4 py-3 flex items-center gap-2 flex-shrink-0">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
</svg>
<span class="font-semibold">제작 </span>
<span class="ml-auto bg-blue-600 px-2 py-0.5 rounded-full text-xs">{{ $orderedRequests->total() }}</span>
</div>
<div class="overflow-y-auto flex-1">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 sticky top-0">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">신청자</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">연락처</th>
<th class="px-4 py-2 text-center text-xs font-medium text-gray-500 uppercase">수량</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">의뢰일</th>
<th class="px-4 py-2 text-center text-xs font-medium text-gray-500 uppercase">처리</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@forelse($orderedRequests as $req)
<tr class="hover:bg-blue-50">
<td class="px-4 py-3">
<div class="font-medium text-gray-900 text-sm">{{ $req->name }}</div>
<div class="text-xs text-gray-500">{{ $req->title ?: '-' }}</div>
</td>
<td class="px-4 py-3">
<div class="text-sm text-gray-900">{{ $req->phone }}</div>
<div class="text-xs text-gray-500">{{ $req->email ?: '-' }}</div>
</td>
<td class="px-4 py-3 text-center text-sm text-gray-700">
{{ number_format($req->quantity) }}
</td>
<td class="px-4 py-3">
<div class="text-xs text-gray-700">{{ $req->ordered_at?->format('m/d H:i') }}</div>
<div class="text-xs text-gray-400">{{ $req->orderer?->name }}</div>
</td>
<td class="px-4 py-3 text-center">
<button type="button"
onclick="processRequest({{ $req->id }}, '{{ $req->name }}')"
class="px-3 py-1 bg-emerald-500 hover:bg-emerald-600 text-white text-xs font-medium rounded transition">
처리완료
</button>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="px-4 py-8 text-center text-gray-500 text-sm">
<svg class="w-12 h-12 mx-auto text-gray-300 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
</svg>
제작의뢰 중인 건이 없습니다.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if($orderedRequests->hasPages())
<div class="px-4 py-2 border-t border-gray-200 flex-shrink-0 bg-gray-50">
{{ $orderedRequests->withQueryString()->links() }}
</div>
@endif
</div>
</div>
<!-- 하단: 처리 완료 -->
<div class="bg-white rounded-lg shadow-sm overflow-hidden flex-shrink-0">
<div class="bg-emerald-500 text-white px-4 py-3 flex items-center gap-2">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="font-semibold">처리 완료</span>
<span class="ml-auto bg-emerald-600 px-2 py-0.5 rounded-full text-xs">{{ $processedRequests->total() }}</span>
</div>
<div class="overflow-x-auto" style="max-height: 300px; overflow-y: auto;">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 sticky top-0">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">신청자</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">연락처</th>
<th class="px-4 py-2 text-center text-xs font-medium text-gray-500 uppercase">수량</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">의뢰일</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">처리일</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">처리자</th>
<th class="px-4 py-2 text-center text-xs font-medium text-gray-500 uppercase" style="width: 50px;"></th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@forelse($processedRequests as $req)
<tr class="hover:bg-emerald-50">
<td class="px-4 py-2">
<div class="font-medium text-gray-900 text-sm">{{ $req->name }}</div>
<div class="text-xs text-gray-500">{{ $req->title ?: '-' }}</div>
</td>
<td class="px-4 py-2">
<div class="text-sm text-gray-900">{{ $req->phone }}</div>
</td>
<td class="px-4 py-2 text-center text-sm text-gray-700">
{{ number_format($req->quantity) }}
</td>
<td class="px-4 py-2 text-xs text-gray-500">
{{ $req->ordered_at?->format('m/d H:i') ?? '-' }}
</td>
<td class="px-4 py-2 text-xs text-gray-700">
{{ $req->processed_at?->format('m/d H:i') }}
</td>
<td class="px-4 py-2 text-xs text-gray-500">
{{ $req->processor?->name }}
</td>
<td class="px-4 py-2 text-center">
<button type="button"
onclick="deleteRequest({{ $req->id }}, '{{ $req->name }}')"
class="text-red-400 hover:text-red-600 transition" 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="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-6 text-center text-gray-500 text-sm">
처리된 명함 신청이 없습니다.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if($processedRequests->hasPages())
<div class="px-4 py-2 border-t border-gray-200 bg-gray-50">
{{ $processedRequests->withQueryString()->links() }}
</div>
@endif
</div>
</div>
@endsection
@push('scripts')
<script>
function orderRequest(id, name) {
showConfirm(
`<strong>${name}</strong>님의 명함을 제작의뢰 하시겠습니까?`,
() => {
fetch(`/sales/business-cards/${id}/order`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'Accept': 'application/json',
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast(data.message, 'success');
window.location.reload();
} else {
showToast(data.message || '처리에 실패했습니다.', 'error');
}
})
.catch(error => {
showToast('서버 오류가 발생했습니다.', 'error');
console.error(error);
});
},
{ title: '제작의뢰', icon: 'question', confirmText: '의뢰하기' }
);
}
function processRequest(id, name) {
showConfirm(
`<strong>${name}</strong>님의 명함 제작이 완료되었습니까?`,
() => {
fetch(`/sales/business-cards/${id}/process`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'Accept': 'application/json',
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast(data.message, 'success');
window.location.reload();
} else {
showToast(data.message || '처리에 실패했습니다.', 'error');
}
})
.catch(error => {
showToast('서버 오류가 발생했습니다.', 'error');
console.error(error);
});
},
{ title: '처리 완료', icon: 'question', confirmText: '처리완료' }
);
}
function deleteRequest(id, name) {
showConfirm(
`<strong>${name}</strong>님의 처리완료된 명함신청을 삭제하시겠습니까?`,
() => {
fetch(`/sales/business-cards/${id}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'Accept': 'application/json',
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast(data.message, 'success');
window.location.reload();
} else {
showToast(data.message || '삭제에 실패했습니다.', 'error');
}
})
.catch(error => {
showToast('서버 오류가 발생했습니다.', 'error');
console.error(error);
});
},
{ title: '삭제 확인', icon: 'warning', confirmText: '삭제' }
);
}
</script>
@endpush