Files
sam-manage/resources/views/finance/settlement/partials/consulting-tab.blade.php
김보곤 8f308b8877 fix:HTMX 탭 Alpine.js 미정의 오류 수정 (컨설팅/고객사/구독)
Alpine 컴포넌트 함수를 HTMX partial에서 메인 페이지로 이동하여
x-data 처리 시점에 함수가 정의되어 있도록 수정

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 10:19:02 +09:00

133 lines
9.9 KiB
PHP

{{-- 컨설팅비용 (Blade + Alpine.js) --}}
<div x-data="consultingManager()" x-init="fetchData()">
{{-- 통계 카드 --}}
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
<div class="bg-white rounded-lg shadow-sm p-4 border-l-4 border-gray-400">
<p class="text-sm text-gray-500"> 시간</p>
<p class="text-xl font-bold text-gray-700" x-text="stats.totalHours + '시간'">0시간</p>
</div>
<div class="bg-white rounded-lg shadow-sm p-4 border-l-4 border-cyan-500">
<p class="text-sm text-gray-500"> 수수료</p>
<p class="text-xl font-bold text-cyan-600" x-text="formatCurrency(stats.totalAmount) + '원'">0</p>
</div>
<div class="bg-white rounded-lg shadow-sm p-4 border-l-4 border-emerald-500">
<p class="text-sm text-gray-500">지급완료</p>
<p class="text-xl font-bold text-emerald-600" x-text="formatCurrency(stats.paidAmount) + '원'">0</p>
</div>
<div class="bg-white rounded-lg shadow-sm p-4 border-l-4 border-amber-500">
<p class="text-sm text-gray-500">지급예정</p>
<p class="text-xl font-bold text-amber-600" x-text="formatCurrency(stats.pendingAmount) + '원'">0</p>
</div>
</div>
{{-- 필터 + 등록 버튼 --}}
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<div class="flex flex-wrap items-end gap-4">
<div class="flex-1 min-w-[200px]">
<label class="block text-sm font-medium text-gray-700 mb-1">검색</label>
<input type="text" x-model="searchTerm" placeholder="고객사 / 컨설턴트" class="w-full rounded-lg border-gray-300 focus:border-cyan-500 focus:ring-cyan-500">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">상태</label>
<select x-model="filterStatus" class="rounded-lg border-gray-300 focus:border-cyan-500 focus:ring-cyan-500">
<option value="all">전체</option>
<option value="paid">완료</option>
<option value="pending">예정</option>
</select>
</div>
<button @click="openModal('add')" class="px-4 py-2 bg-cyan-600 hover:bg-cyan-700 text-white rounded-lg transition-colors">
+ 등록
</button>
</div>
</div>
{{-- 테이블 --}}
<div class="bg-white rounded-lg shadow-sm overflow-hidden">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">날짜</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">컨설턴트</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">고객사</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">서비스</th>
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase">시간</th>
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase">금액</th>
<th class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase">상태</th>
<th class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase">관리</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<template x-if="loading">
<tr><td colspan="8" class="px-4 py-8 text-center text-gray-400">로딩 ...</td></tr>
</template>
<template x-if="!loading && filteredItems().length === 0">
<tr><td colspan="8" class="px-4 py-8 text-center text-gray-400">데이터가 없습니다.</td></tr>
</template>
<template x-for="item in filteredItems()" :key="item.id">
<tr class="hover:bg-gray-50">
<td class="px-4 py-3 text-sm text-gray-900" x-text="item.date"></td>
<td class="px-4 py-3 text-sm text-gray-900" x-text="item.consultant"></td>
<td class="px-4 py-3 text-sm text-gray-900" x-text="item.customer"></td>
<td class="px-4 py-3 text-sm text-gray-500" x-text="item.service"></td>
<td class="px-4 py-3 text-sm text-right text-gray-900" x-text="item.hours + 'h'"></td>
<td class="px-4 py-3 text-sm text-right font-medium text-cyan-600" x-text="formatCurrency(item.amount) + '원'"></td>
<td class="px-4 py-3 text-center">
<span class="px-2 py-0.5 rounded-full text-xs font-medium"
:class="item.status === 'paid' ? 'bg-green-100 text-green-700' : 'bg-amber-100 text-amber-700'"
x-text="item.status === 'paid' ? '완료' : '예정'"></span>
</td>
<td class="px-4 py-3 text-center">
<button @click="openModal('edit', item)" class="p-1 text-gray-400 hover:text-blue-500" 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="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/></svg>
</button>
<button @click="deleteItem(item.id)" class="p-1 text-gray-400 hover:text-red-500" 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>
</td>
</tr>
</template>
</tbody>
</table>
</div>
</div>
{{-- 모달 --}}
<div x-show="showModal" x-cloak class="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
<div class="bg-white rounded-xl p-6 w-full max-w-lg mx-4 max-h-[90vh] overflow-y-auto" @click.outside="showModal = false">
<div class="flex items-center justify-between mb-6">
<h3 class="text-lg font-bold text-gray-900" x-text="modalMode === 'add' ? '컨설팅비 등록' : '컨설팅비 수정'"></h3>
<button @click="showModal = false" class="p-1 hover:bg-gray-100 rounded-lg">
<svg class="w-5 h-5 text-gray-500" 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>
</div>
<div class="space-y-4">
<div class="grid grid-cols-2 gap-4">
<div><label class="block text-sm font-medium text-gray-700 mb-1">날짜</label><input type="date" x-model="form.date" class="w-full px-3 py-2 border rounded-lg"></div>
<div><label class="block text-sm font-medium text-gray-700 mb-1">컨설턴트 *</label><input type="text" x-model="form.consultant" class="w-full px-3 py-2 border rounded-lg"></div>
</div>
<div class="grid grid-cols-2 gap-4">
<div><label class="block text-sm font-medium text-gray-700 mb-1">고객사</label><input type="text" x-model="form.customer" class="w-full px-3 py-2 border rounded-lg"></div>
<div><label class="block text-sm font-medium text-gray-700 mb-1">서비스</label><input type="text" x-model="form.service" class="w-full px-3 py-2 border rounded-lg"></div>
</div>
<div class="grid grid-cols-3 gap-4">
<div><label class="block text-sm font-medium text-gray-700 mb-1">시간</label><input type="number" x-model="form.hours" step="0.5" class="w-full px-3 py-2 border rounded-lg text-right"></div>
<div><label class="block text-sm font-medium text-gray-700 mb-1">시급</label><input type="number" x-model="form.hourlyRate" class="w-full px-3 py-2 border rounded-lg text-right"></div>
<div><label class="block text-sm font-medium text-gray-700 mb-1">금액 *</label><input type="number" x-model="form.amount" class="w-full px-3 py-2 border rounded-lg text-right"></div>
</div>
<div class="grid grid-cols-2 gap-4">
<div><label class="block text-sm font-medium text-gray-700 mb-1">상태</label>
<select x-model="form.status" class="w-full px-3 py-2 border rounded-lg"><option value="pending">예정</option><option value="paid">완료</option></select>
</div>
<div><label class="block text-sm font-medium text-gray-700 mb-1">메모</label><input type="text" x-model="form.memo" class="w-full px-3 py-2 border rounded-lg"></div>
</div>
</div>
<div class="flex gap-3 mt-6">
<button @click="showModal = false" class="flex-1 px-4 py-2 border text-gray-700 rounded-lg hover:bg-gray-50">취소</button>
<button @click="saveItem()" :disabled="saving" class="flex-1 px-4 py-2 bg-cyan-600 hover:bg-cyan-700 text-white rounded-lg disabled:opacity-50" x-text="saving ? '저장 중...' : '저장'">저장</button>
</div>
</div>
</div>
</div>