feat(mng): 고객센터 게시판 목록 페이지 추가

- /customer-center 라우트 신규 생성
- 활성화된 시스템 게시판만 표시
- 테이블 컬럼: ID, 유형, 코드, 게시판명, 게시글 수, 생성일
- 관리 기능(구분, 필드, 상태, 액션) 제외한 읽기 전용 뷰

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-27 20:50:58 +09:00
parent 64fa5f7766
commit b992886fca
6 changed files with 170 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Http\Controllers\Api\Admin;
use App\Http\Controllers\Controller;
use App\Models\Boards\Board;
use Illuminate\Http\Request;
use Illuminate\View\View;
class CustomerCenterController extends Controller
{
/**
* 고객센터 게시판 목록 (활성화된 시스템 게시판만 + 게시글 수)
*/
public function index(Request $request): View
{
$boards = Board::query()
->whereNull('tenant_id') // 시스템 게시판만
->where('is_active', true) // 활성화된 것만
->withCount('posts') // 게시글 수
->orderBy('created_at', 'desc')
->paginate(15);
return view('customer-center.partials.table', compact('boards'));
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers;
use App\Services\BoardService;
use Illuminate\View\View;
class CustomerCenterController extends Controller
{
public function __construct(
private readonly BoardService $boardService
) {}
/**
* 고객센터 게시판 목록 (활성화된 시스템 게시판만)
*/
public function index(): View
{
return view('customer-center.index');
}
}

View File

@@ -0,0 +1,44 @@
@extends('layouts.app')
@section('title', '고객센터')
@section('content')
<!-- 페이지 헤더 -->
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-6">
<h1 class="text-2xl font-bold text-gray-800">고객센터</h1>
</div>
<!-- 테이블 영역 -->
<div id="board-table" class="bg-white rounded-lg shadow-sm overflow-hidden">
<!-- 로딩 스피너 -->
<div class="flex justify-center items-center p-12">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
</div>
</div>
@endsection
@push('scripts')
<script>
// 테이블 로드 함수
function loadTable() {
fetch('/api/admin/customer-center', {
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'HX-Request': 'true'
}
})
.then(response => response.text())
.then(html => {
document.getElementById('board-table').innerHTML = html;
})
.catch(error => {
console.error('Error:', error);
});
}
// 초기 로드
document.addEventListener('DOMContentLoaded', function() {
loadTable();
});
</script>
@endpush

View File

@@ -0,0 +1,71 @@
<!-- 고객센터 게시판 테이블 -->
<div class="bg-white rounded-lg shadow-sm overflow-hidden">
<x-table-swipe>
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-3 py-2 text-center text-sm font-semibold text-gray-700 uppercase tracking-wider whitespace-nowrap">ID</th>
<th class="px-3 py-2 text-center text-sm font-semibold text-gray-700 uppercase tracking-wider whitespace-nowrap">유형</th>
<th class="px-3 py-2 text-center text-sm font-semibold text-gray-700 uppercase tracking-wider whitespace-nowrap">코드</th>
<th class="px-3 py-2 text-center text-sm font-semibold text-gray-700 uppercase tracking-wider whitespace-nowrap">게시판명</th>
<th class="px-3 py-2 text-center text-sm font-semibold text-gray-700 uppercase tracking-wider whitespace-nowrap">게시글 </th>
<th class="px-3 py-2 text-center text-sm font-semibold text-gray-700 uppercase tracking-wider whitespace-nowrap">생성일</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@forelse($boards as $board)
<tr class="hover:bg-gray-50 cursor-pointer" onclick="window.location='{{ route('boards.posts.index', $board->id) }}'">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
{{ $board->id }}
</td>
<td class="px-6 py-4 whitespace-nowrap">
@if($board->board_type)
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full
@switch($board->board_type)
@case('notice') bg-purple-100 text-purple-800 @break
@case('qna') bg-blue-100 text-blue-800 @break
@case('faq') bg-green-100 text-green-800 @break
@case('free') bg-gray-100 text-gray-800 @break
@default bg-yellow-100 text-yellow-800
@endswitch
">
{{ $board->board_type }}
</span>
@else
<span class="text-gray-400">-</span>
@endif
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">
<span class="font-mono text-blue-600">{{ $board->board_code }}</span>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-gray-900">{{ $board->name }}</div>
@if($board->description)
<div class="text-sm text-gray-500 truncate max-w-xs">{{ $board->description }}</div>
@endif
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 text-center">
<span class="px-2 py-1 bg-blue-50 text-blue-700 rounded-full">{{ $board->posts_count }}</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ $board->created_at->format('Y-m-d') }}
</td>
</tr>
@empty
<tr>
<td colspan="6" class="px-6 py-12 text-center text-gray-500">
등록된 게시판이 없습니다.
</td>
</tr>
@endforelse
</tbody>
</table>
</x-table-swipe>
</div>
<!-- 페이지네이션 -->
@if($boards->hasPages())
<div class="px-6 py-4 border-t border-gray-200">
{{ $boards->withQueryString()->links() }}
</div>
@endif

View File

@@ -1,6 +1,7 @@
<?php <?php
use App\Http\Controllers\Api\Admin\BoardController; use App\Http\Controllers\Api\Admin\BoardController;
use App\Http\Controllers\Api\Admin\CustomerCenterController;
use App\Http\Controllers\Api\Admin\DailyLogController; use App\Http\Controllers\Api\Admin\DailyLogController;
use App\Http\Controllers\Api\Admin\DepartmentController; use App\Http\Controllers\Api\Admin\DepartmentController;
use App\Http\Controllers\Api\Admin\GlobalMenuController; use App\Http\Controllers\Api\Admin\GlobalMenuController;
@@ -182,6 +183,9 @@
Route::delete('/{id}', [PermissionController::class, 'destroy'])->name('destroy'); Route::delete('/{id}', [PermissionController::class, 'destroy'])->name('destroy');
}); });
// 고객센터 API (활성화된 시스템 게시판 목록)
Route::get('/customer-center', [CustomerCenterController::class, 'index'])->name('customer-center.index');
// 시스템 게시판 관리 API // 시스템 게시판 관리 API
Route::prefix('boards')->name('boards.')->group(function () { Route::prefix('boards')->name('boards.')->group(function () {
// 고정 경로는 먼저 정의 // 고정 경로는 먼저 정의

View File

@@ -4,6 +4,7 @@
use App\Http\Controllers\ArchivedRecordController; use App\Http\Controllers\ArchivedRecordController;
use App\Http\Controllers\Auth\LoginController; use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\BoardController; use App\Http\Controllers\BoardController;
use App\Http\Controllers\CustomerCenterController;
use App\Http\Controllers\DailyLogController; use App\Http\Controllers\DailyLogController;
use App\Http\Controllers\DepartmentController; use App\Http\Controllers\DepartmentController;
use App\Http\Controllers\DevTools\ApiExplorerController; use App\Http\Controllers\DevTools\ApiExplorerController;
@@ -104,6 +105,9 @@
Route::get('/{id}/edit', [PermissionController::class, 'edit'])->name('edit'); Route::get('/{id}/edit', [PermissionController::class, 'edit'])->name('edit');
}); });
// 고객센터 (활성화된 시스템 게시판 목록)
Route::get('/customer-center', [CustomerCenterController::class, 'index'])->name('customer-center.index');
// 시스템 게시판 관리 (Blade 화면만) // 시스템 게시판 관리 (Blade 화면만)
Route::prefix('boards')->name('boards.')->group(function () { Route::prefix('boards')->name('boards.')->group(function () {
Route::get('/', [BoardController::class, 'index'])->name('index'); Route::get('/', [BoardController::class, 'index'])->name('index');