- 관리자 화면 처리완료 카드에 삭제 버튼 추가 - processed 상태만 삭제 가능 (서비스 검증) - 파트너 명함신청 기본 매수 100매 → 500매 변경
357 lines
19 KiB
PHP
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
|