feat:영업파트너 유치 현황 대시보드 탭 추가
- SalesDashboardController에 partnerActivity() 메서드 추가 - 유치 파트너 요약 통계 (파트너 수, 영업권, 계약, 예상수당) - 파트너별 상세 활동 테이블 (펼침/접기 기능) - 기존 대시보드에 탭 UI 통합 (내 활동 / 유치 파트너 현황) - HTMX로 탭 콘텐츠 지연 로드 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -311,6 +311,149 @@ public function getManagers(Request $request): JsonResponse
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 유치 파트너 활동 현황 (HTMX 탭 로드)
|
||||
*/
|
||||
public function partnerActivity(Request $request): View
|
||||
{
|
||||
$data = $this->getPartnerActivityData();
|
||||
|
||||
return view('sales.dashboard.partials.partner-activity', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 유치 파트너 활동 데이터 조회
|
||||
*/
|
||||
private function getPartnerActivityData(): array
|
||||
{
|
||||
$currentUser = auth()->user();
|
||||
$currentUserId = $currentUser->id;
|
||||
|
||||
// 직접 유치한 하위 파트너 목록 (parent_id가 현재 사용자인 사용자들)
|
||||
$recruitedPartners = User::where('parent_id', $currentUserId)
|
||||
->where('is_active', true)
|
||||
->with(['userRoles.role'])
|
||||
->get();
|
||||
|
||||
$partnerIds = $recruitedPartners->pluck('id')->toArray();
|
||||
|
||||
// 요약 통계 계산
|
||||
$summaryStats = $this->calculatePartnerSummaryStats($partnerIds, $currentUserId);
|
||||
|
||||
// 파트너별 상세 활동 데이터
|
||||
$partnerActivities = $this->getPartnerActivitiesDetail($recruitedPartners, $currentUserId);
|
||||
|
||||
return [
|
||||
'summaryStats' => $summaryStats,
|
||||
'partnerActivities' => $partnerActivities,
|
||||
'recruitedPartners' => $recruitedPartners,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 유치 파트너 요약 통계 계산
|
||||
*/
|
||||
private function calculatePartnerSummaryStats(array $partnerIds, int $currentUserId): array
|
||||
{
|
||||
// 유치 파트너 수
|
||||
$partnerCount = count($partnerIds);
|
||||
|
||||
// 하위 파트너들이 등록한 총 영업권(명함) 수
|
||||
$totalProspects = TenantProspect::whereIn('registered_by', $partnerIds)->count();
|
||||
|
||||
// 하위 파트너들의 계약 성사 건수
|
||||
$totalConversions = TenantProspect::whereIn('registered_by', $partnerIds)
|
||||
->where('status', TenantProspect::STATUS_CONVERTED)
|
||||
->count();
|
||||
|
||||
// 매니저로서 받을 수당 (내가 매니저로 지정된 수당 중 하위 파트너 관련)
|
||||
$expectedCommission = SalesCommission::where('manager_user_id', $currentUserId)
|
||||
->whereHas('partner', function ($query) use ($partnerIds) {
|
||||
$query->whereIn('user_id', $partnerIds);
|
||||
})
|
||||
->sum('manager_commission');
|
||||
|
||||
return [
|
||||
'partner_count' => $partnerCount,
|
||||
'total_prospects' => $totalProspects,
|
||||
'total_conversions' => $totalConversions,
|
||||
'expected_commission' => $expectedCommission,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 파트너별 상세 활동 데이터
|
||||
*/
|
||||
private function getPartnerActivitiesDetail($recruitedPartners, int $currentUserId): array
|
||||
{
|
||||
$activities = [];
|
||||
|
||||
foreach ($recruitedPartners as $partner) {
|
||||
// 파트너의 영업파트너 정보
|
||||
$salesPartner = SalesPartner::where('user_id', $partner->id)->first();
|
||||
|
||||
// 파트너가 등록한 영업권 수
|
||||
$prospectCount = TenantProspect::where('registered_by', $partner->id)->count();
|
||||
|
||||
// 진행 중인 영업권 (active 상태)
|
||||
$activeProspects = TenantProspect::where('registered_by', $partner->id)
|
||||
->where('status', TenantProspect::STATUS_ACTIVE)
|
||||
->count();
|
||||
|
||||
// 계약 성사 건수
|
||||
$conversions = TenantProspect::where('registered_by', $partner->id)
|
||||
->where('status', TenantProspect::STATUS_CONVERTED)
|
||||
->count();
|
||||
|
||||
// 이 파트너로 인한 나의 매니저 수당
|
||||
$managerCommission = 0;
|
||||
if ($salesPartner) {
|
||||
$managerCommission = SalesCommission::where('manager_user_id', $currentUserId)
|
||||
->where('partner_id', $salesPartner->id)
|
||||
->sum('manager_commission');
|
||||
}
|
||||
|
||||
// 최근 활동 내역 (최근 전환된 테넌트 5개)
|
||||
$recentTenants = TenantProspect::where('registered_by', $partner->id)
|
||||
->where('status', TenantProspect::STATUS_CONVERTED)
|
||||
->with(['tenant'])
|
||||
->orderBy('converted_at', 'desc')
|
||||
->limit(5)
|
||||
->get();
|
||||
|
||||
// 활동 상태 판단
|
||||
$lastActivity = TenantProspect::where('registered_by', $partner->id)
|
||||
->orderBy('updated_at', 'desc')
|
||||
->first();
|
||||
$status = 'inactive';
|
||||
if ($lastActivity) {
|
||||
$daysSinceActivity = now()->diffInDays($lastActivity->updated_at);
|
||||
if ($daysSinceActivity <= 7) {
|
||||
$status = 'active';
|
||||
} elseif ($daysSinceActivity <= 30) {
|
||||
$status = 'moderate';
|
||||
}
|
||||
}
|
||||
|
||||
// 역할 정보
|
||||
$roles = $partner->userRoles->pluck('role.name')->filter()->toArray();
|
||||
$roleLabel = !empty($roles) ? implode(', ', $roles) : '영업';
|
||||
|
||||
$activities[] = [
|
||||
'partner' => $partner,
|
||||
'role_label' => $roleLabel,
|
||||
'prospect_count' => $prospectCount,
|
||||
'active_prospects' => $activeProspects,
|
||||
'conversions' => $conversions,
|
||||
'manager_commission' => $managerCommission,
|
||||
'status' => $status,
|
||||
'recent_tenants' => $recentTenants,
|
||||
];
|
||||
}
|
||||
|
||||
return $activities;
|
||||
}
|
||||
|
||||
/**
|
||||
* 영업파트너 수당 정보 조회
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<div class="space-y-6">
|
||||
<div class="space-y-6" x-data="{ activeTab: 'my-activity' }">
|
||||
<!-- 페이지 헤더 -->
|
||||
<div class="flex justify-between items-center">
|
||||
<h1 class="text-2xl font-bold text-gray-800">영업관리 대시보드</h1>
|
||||
@@ -38,9 +38,57 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 대시보드 데이터 컨테이너 (HTMX로 새로고침되는 영역) -->
|
||||
<div id="dashboard-data" class="space-y-6">
|
||||
@include('sales.dashboard.partials.data-container')
|
||||
<!-- 탭 네비게이션 -->
|
||||
<div class="border-b border-gray-200">
|
||||
<nav class="flex gap-4" aria-label="Tabs">
|
||||
<button type="button"
|
||||
@click="activeTab = 'my-activity'"
|
||||
:class="activeTab === 'my-activity'
|
||||
? 'border-blue-500 text-blue-600'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'"
|
||||
class="whitespace-nowrap py-3 px-1 border-b-2 font-medium text-sm transition-colors 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 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||
</svg>
|
||||
내 활동
|
||||
</button>
|
||||
<button type="button"
|
||||
@click="activeTab = 'partner-activity'"
|
||||
hx-get="{{ route('sales.salesmanagement.dashboard.partner-activity') }}"
|
||||
hx-target="#partner-activity-content"
|
||||
hx-trigger="click once"
|
||||
hx-swap="innerHTML"
|
||||
:class="activeTab === 'partner-activity'
|
||||
? 'border-blue-500 text-blue-600'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'"
|
||||
class="whitespace-nowrap py-3 px-1 border-b-2 font-medium text-sm transition-colors 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="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
유치 파트너 현황
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<!-- 탭 콘텐츠: 내 활동 -->
|
||||
<div x-show="activeTab === 'my-activity'" x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100">
|
||||
<div id="dashboard-data" class="space-y-6">
|
||||
@include('sales.dashboard.partials.data-container')
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 탭 콘텐츠: 유치 파트너 현황 -->
|
||||
<div x-show="activeTab === 'partner-activity'" x-cloak x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100">
|
||||
<div id="partner-activity-content" class="space-y-6">
|
||||
<!-- HTMX로 로드되는 콘텐츠 -->
|
||||
<div class="flex items-center justify-center py-12">
|
||||
<svg class="w-8 h-8 animate-spin text-blue-600" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
<span class="ml-3 text-gray-500">로딩 중...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
{{-- 유치 파트너 활동 현황 --}}
|
||||
<div class="space-y-6">
|
||||
{{-- 요약 카드 섹션 --}}
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
<!-- 유치 파트너 수 -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl p-5 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-start justify-between mb-3">
|
||||
<span class="text-sm text-gray-500">유치 파트너</span>
|
||||
<div class="p-2 bg-indigo-50 rounded-lg">
|
||||
<svg class="w-5 h-5 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-3xl font-bold text-gray-900">{{ $summaryStats['partner_count'] }}명</p>
|
||||
<p class="text-xs text-gray-400 mt-1">직접 유치한 파트너</p>
|
||||
</div>
|
||||
|
||||
<!-- 총 영업권 -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl p-5 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-start justify-between mb-3">
|
||||
<span class="text-sm text-gray-500">총 영업권</span>
|
||||
<div class="p-2 bg-blue-50 rounded-lg">
|
||||
<svg class="w-5 h-5 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-3xl font-bold text-gray-900">{{ $summaryStats['total_prospects'] }}건</p>
|
||||
<p class="text-xs text-gray-400 mt-1">파트너들이 등록한 명함</p>
|
||||
</div>
|
||||
|
||||
<!-- 총 계약 -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl p-5 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-start justify-between mb-3">
|
||||
<span class="text-sm text-gray-500">총 계약</span>
|
||||
<div class="p-2 bg-green-50 rounded-lg">
|
||||
<svg class="w-5 h-5 text-green-600" 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>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-3xl font-bold text-green-600">{{ $summaryStats['total_conversions'] }}건</p>
|
||||
<p class="text-xs text-gray-400 mt-1">계약 성사 건수</p>
|
||||
</div>
|
||||
|
||||
<!-- 예상 수당 -->
|
||||
<div class="bg-gradient-to-br from-amber-50 to-orange-50 border border-amber-200 rounded-xl p-5 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-start justify-between mb-3">
|
||||
<span class="text-sm text-amber-700">예상 수당</span>
|
||||
<div class="p-2 bg-amber-100 rounded-lg">
|
||||
<svg class="w-5 h-5 text-amber-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-3xl font-bold text-amber-700">{{ number_format($summaryStats['expected_commission']) }}원</p>
|
||||
<p class="text-xs text-amber-600 mt-1">매니저 수당 합계</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 하위 파트너 활동 테이블 --}}
|
||||
<div class="bg-white rounded-xl shadow-sm">
|
||||
<div class="p-6 border-b border-gray-100">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="p-2 bg-indigo-100 rounded-lg">
|
||||
<svg class="w-6 h-6 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5-9a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-xl font-bold text-gray-800">유치 파트너 활동 현황</h2>
|
||||
<p class="text-sm text-gray-500">직접 유치한 파트너들의 영업 활동을 확인하세요</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if(count($partnerActivities) === 0)
|
||||
<div class="text-center py-16">
|
||||
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg class="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="text-gray-600 font-medium mb-1">유치한 파트너가 없습니다</p>
|
||||
<p class="text-sm text-gray-400">파트너를 유치하면 이곳에서 활동 현황을 확인할 수 있습니다</p>
|
||||
</div>
|
||||
@else
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider">파트너</th>
|
||||
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 uppercase tracking-wider">역할</th>
|
||||
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 uppercase tracking-wider">영업권</th>
|
||||
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 uppercase tracking-wider">진행중</th>
|
||||
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 uppercase tracking-wider">성공</th>
|
||||
<th class="px-6 py-3 text-right text-xs font-semibold text-gray-500 uppercase tracking-wider">예상수당</th>
|
||||
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 uppercase tracking-wider">상태</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100" x-data="{ expandedPartner: null }">
|
||||
@foreach($partnerActivities as $activity)
|
||||
@php
|
||||
$statusColors = [
|
||||
'active' => 'bg-green-100 text-green-800',
|
||||
'moderate' => 'bg-yellow-100 text-yellow-800',
|
||||
'inactive' => 'bg-gray-100 text-gray-800',
|
||||
];
|
||||
$statusLabels = [
|
||||
'active' => '활동중',
|
||||
'moderate' => '보통',
|
||||
'inactive' => '비활동',
|
||||
];
|
||||
@endphp
|
||||
<!-- 파트너 메인 행 -->
|
||||
<tr class="hover:bg-gray-50 cursor-pointer transition-colors"
|
||||
@click="expandedPartner = expandedPartner === {{ $activity['partner']->id }} ? null : {{ $activity['partner']->id }}">
|
||||
<td class="px-6 py-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<button type="button" class="text-gray-400 hover:text-gray-600 transition-transform"
|
||||
:class="{ 'rotate-90': expandedPartner === {{ $activity['partner']->id }} }">
|
||||
<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="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
</button>
|
||||
<div>
|
||||
<p class="font-semibold text-gray-900">{{ $activity['partner']->name }}</p>
|
||||
<p class="text-xs text-gray-500">{{ $activity['partner']->email }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-center">
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
|
||||
{{ $activity['role_label'] }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-center">
|
||||
<span class="font-semibold text-gray-900">{{ $activity['prospect_count'] }}</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-center">
|
||||
<span class="font-semibold text-blue-600">{{ $activity['active_prospects'] }}</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-center">
|
||||
<span class="font-semibold text-green-600">{{ $activity['conversions'] }}</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-right">
|
||||
<span class="font-semibold text-amber-600">{{ number_format($activity['manager_commission']) }}원</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-center">
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium {{ $statusColors[$activity['status']] ?? $statusColors['inactive'] }}">
|
||||
{{ $statusLabels[$activity['status']] ?? '비활동' }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 확장 영역: 최근 테넌트 목록 -->
|
||||
<tr x-show="expandedPartner === {{ $activity['partner']->id }}"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition ease-in duration-150"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
x-cloak>
|
||||
<td colspan="7" class="px-6 py-4 bg-gray-50">
|
||||
@if($activity['recent_tenants']->isEmpty())
|
||||
<div class="text-center py-4 text-sm text-gray-500">
|
||||
아직 계약 성사 내역이 없습니다
|
||||
</div>
|
||||
@else
|
||||
<div class="ml-8 space-y-2">
|
||||
<p class="text-xs font-semibold text-gray-500 uppercase mb-3">최근 계약 성사 내역</p>
|
||||
@foreach($activity['recent_tenants'] as $prospect)
|
||||
<div class="flex items-center justify-between bg-white rounded-lg px-4 py-3 border border-gray-200">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-2 h-2 rounded-full bg-green-500"></div>
|
||||
<div>
|
||||
<p class="font-medium text-gray-900">{{ $prospect->company_name }}</p>
|
||||
<p class="text-xs text-gray-500">{{ $prospect->tenant?->company_name ?? '-' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
{{-- 진행 단계 표시 --}}
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="w-2 h-2 rounded-full bg-green-500" title="상담"></span>
|
||||
<span class="w-2 h-2 rounded-full bg-green-500" title="견적"></span>
|
||||
<span class="w-2 h-2 rounded-full bg-green-500" title="계약"></span>
|
||||
<span class="w-2 h-2 rounded-full bg-green-500" title="완료"></span>
|
||||
</div>
|
||||
<span class="text-xs text-gray-500">
|
||||
{{ $prospect->converted_at?->format('Y-m-d') ?? '-' }}
|
||||
</span>
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800">
|
||||
계약완료
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@@ -880,6 +880,7 @@
|
||||
Route::get('salesmanagement/dashboard', [\App\Http\Controllers\Sales\SalesDashboardController::class, 'index'])->name('salesmanagement.dashboard');
|
||||
Route::get('salesmanagement/dashboard/refresh', [\App\Http\Controllers\Sales\SalesDashboardController::class, 'refresh'])->name('salesmanagement.dashboard.refresh');
|
||||
Route::get('salesmanagement/dashboard/tenants', [\App\Http\Controllers\Sales\SalesDashboardController::class, 'refreshTenantList'])->name('salesmanagement.dashboard.tenants');
|
||||
Route::get('salesmanagement/dashboard/partner-activity', [\App\Http\Controllers\Sales\SalesDashboardController::class, 'partnerActivity'])->name('salesmanagement.dashboard.partner-activity');
|
||||
|
||||
// 영업파트너 승인 (본사 관리자 전용) - resource 전에 정의해야 함
|
||||
Route::get('managers/approvals', [\App\Http\Controllers\Sales\SalesManagerController::class, 'approvals'])->name('managers.approvals');
|
||||
|
||||
Reference in New Issue
Block a user