Revert "feat: [tenant] 컨텍스트 메뉴 테넌트 설정 + 콘솔 사이드바 DB 메뉴 적용"

This reverts commit cb254cf138.
This commit is contained in:
2026-03-13 21:21:21 +09:00
parent cb254cf138
commit c3bc7912dd
5 changed files with 87 additions and 165 deletions

View File

@@ -64,18 +64,5 @@ public function boot(): void
'favoriteMenuIds' => $menuService->getFavoriteMenuIds(),
]);
});
// 테넌트 콘솔 사이드바에 해당 테넌트의 메뉴 데이터 전달
View::composer('partials.tenant-console-sidebar', function ($view) {
$tenantId = $view->getData()['consoleTenantId'] ?? request()->route('tenantId');
if ($tenantId) {
$menuService = app(SidebarMenuService::class);
$menusBySection = $menuService->getTenantMenusBySection((int) $tenantId);
$view->with([
'tenantMainMenus' => $menusBySection['main'],
]);
}
});
}
}

View File

@@ -131,35 +131,6 @@ public function getMenusBySection(?User $user = null): array
];
}
/**
* 특정 테넌트의 전체 메뉴 트리 조회 (권한 필터 없음, 관리 콘솔용)
*/
public function getTenantMenuTree(int $tenantId): Collection
{
$allMenus = Menu::withoutGlobalScopes()
->where('tenant_id', $tenantId)
->where('is_active', true)
->where('hidden', false)
->orderBy('sort_order')
->get();
return $this->buildMenuTree($allMenus);
}
/**
* 특정 테넌트의 섹션별 메뉴 조회 (관리 콘솔용)
*/
public function getTenantMenusBySection(int $tenantId): array
{
$menuTree = $this->getTenantMenuTree($tenantId);
return [
'main' => $menuTree->filter(fn ($m) => $m->getSection() === 'main')->values(),
'tools' => $menuTree->filter(fn ($m) => $m->getSection() === 'tools')->values(),
'labs' => $menuTree->filter(fn ($m) => $m->getSection() === 'labs')->values(),
];
}
/**
* 메뉴 트리 구성
*/

View File

@@ -121,11 +121,8 @@ class ContextMenu {
window.location.href = `/tenants/${id}/edit`;
break;
case 'switch-tenant':
{
const w = 1400, h = 900;
const l = (screen.width - w) / 2, t = (screen.height - h) / 2;
window.open(`/tenant-console/${id}`, `tenant_${id}`,
`width=${w},height=${h},left=${l},top=${t},resizable=yes,scrollbars=yes`);
if (typeof openTenantConsole === 'function') {
openTenantConsole(id, name);
}
break;
case 'view-user':

View File

@@ -28,12 +28,11 @@ class="w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100 flex i
<button type="button"
data-menu-for="tenant"
onclick="handleContextMenuAction('switch-tenant')"
class="w-full px-4 py-2 text-left text-sm text-purple-600 hover:bg-gray-100 flex items-center gap-2">
class="w-full px-4 py-2 text-left text-sm text-green-600 hover:bg-gray-100 flex items-center gap-2">
<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="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.573-1.066z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
</svg>
테넌트 설정
테넌트 전환
</button>
{{-- 사용자 관련 메뉴 --}}

View File

@@ -1,8 +1,51 @@
{{-- 테넌트 콘솔 전용 사이드바 (DB 기반 메뉴 시스템) --}}
{{-- 테넌트 콘솔 전용 사이드바 (메인 사이드바 스타일 통일) --}}
@php
$tenantId = $consoleTenantId ?? 0;
$currentUrl = request()->url();
$baseUrl = "/tenant-console/{$tenantId}";
$menus = $tenantMainMenus ?? collect();
$menuGroups = [
[
'title' => '권한 관리',
'icon' => 'ri-shield-keyhole-line',
'items' => [
['name' => '권한 관리', 'url' => "{$baseUrl}/permissions", 'icon' => 'ri-key-2-line'],
['name' => '역할 관리', 'url' => "{$baseUrl}/roles", 'icon' => 'ri-user-settings-line'],
['name' => '역할-권한 매핑', 'url' => "{$baseUrl}/role-permissions", 'icon' => 'ri-links-line'],
['name' => '부서-권한 매핑', 'url' => "{$baseUrl}/department-permissions", 'icon' => 'ri-building-2-line'],
['name' => '사용자-권한 매핑', 'url' => "{$baseUrl}/user-permissions", 'icon' => 'ri-user-star-line'],
],
],
[
'title' => '시스템 관리',
'icon' => 'ri-settings-3-line',
'items' => [
['name' => 'AI 설정', 'url' => "{$baseUrl}/system/ai-config", 'icon' => 'ri-robot-line'],
['name' => '휴일 관리', 'url' => "{$baseUrl}/system/holidays", 'icon' => 'ri-calendar-event-line'],
['name' => '시스템 알림', 'url' => "{$baseUrl}/system/alerts", 'icon' => 'ri-notification-3-line'],
['name' => '공통코드', 'url' => "{$baseUrl}/common-codes", 'icon' => 'ri-code-s-slash-line'],
['name' => '카테고리', 'url' => "{$baseUrl}/categories", 'icon' => 'ri-node-tree'],
['name' => '감사 로그', 'url' => "{$baseUrl}/audit-logs", 'icon' => 'ri-file-list-3-line'],
],
],
[
'title' => '생산관리',
'icon' => 'ri-instance-line',
'items' => [
['name' => '품목관리', 'url' => "{$baseUrl}/production/items", 'icon' => 'ri-box-3-line'],
['name' => '품목필드', 'url' => "{$baseUrl}/production/item-fields", 'icon' => 'ri-list-settings-line'],
['name' => '견적수식', 'url' => "{$baseUrl}/production/quote-formulas", 'icon' => 'ri-calculator-line'],
['name' => '카테고리', 'url' => "{$baseUrl}/production/categories", 'icon' => 'ri-node-tree'],
],
],
[
'title' => '게시판관리',
'icon' => 'ri-article-line',
'items' => [
['name' => '게시판 목록', 'url' => "{$baseUrl}/boards", 'icon' => 'ri-layout-grid-line'],
],
],
];
@endphp
<aside class="w-64 bg-white border-r border-gray-200 flex flex-col shrink-0">
@@ -17,120 +60,45 @@
</a>
</div>
{{-- 메뉴 영역 (DB 기반) --}}
{{-- 메뉴 영역 --}}
<nav class="flex-1 overflow-y-auto p-4">
<ul class="space-y-1">
@foreach($menus as $menu)
@if($menu->menuChildren && $menu->menuChildren->isNotEmpty())
{{-- 1depth: 그룹 헤더 --}}
@php
$groupId = 'tc-menu-group-' . $menu->id;
$children = $menu->menuChildren;
@endphp
<li class="pt-4 pb-1 border-t border-gray-200 mt-2">
<button onclick="document.getElementById('{{ $groupId }}').classList.toggle('hidden')"
class="w-full flex items-center justify-between px-3 py-2 text-sm font-semibold text-gray-700 hover:bg-gray-50 rounded"
style="padding-left: 0.75rem">
<span class="flex items-center gap-2">
@if($menu->icon)
<i class="{{ $menu->icon }} w-4 h-4 text-base"></i>
@endif
{{ $menu->name }}
</span>
<svg class="w-3 h-3 transition-transform rotate-180" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
@foreach($menuGroups as $groupIndex => $group)
{{-- 1depth: 그룹 헤더 (메인 사이드바 menu-group 스타일) --}}
<li class="pt-4 pb-1 border-t border-gray-200 mt-2">
<button @click="$refs.group{{ $groupIndex }}.classList.toggle('hidden')"
class="w-full flex items-center justify-between px-3 py-2 text-sm font-semibold text-gray-700 hover:bg-gray-50 rounded"
style="padding-left: 0.75rem">
<span class="flex items-center gap-2">
<i class="{{ $group['icon'] }} w-4 h-4 text-base"></i>
{{ $group['title'] }}
</span>
<svg class="w-3 h-3 transition-transform rotate-180" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
{{-- 2depth: 메뉴 아이템 --}}
<ul id="{{ $groupId }}" class="space-y-1 mt-1">
@foreach($children as $child)
@if($child->menuChildren && $child->menuChildren->isNotEmpty())
{{-- 3depth: 서브그룹 --}}
@php
$subGroupId = 'tc-menu-group-' . $child->id;
$subChildren = $child->menuChildren;
@endphp
<li>
<button onclick="document.getElementById('{{ $subGroupId }}').classList.toggle('hidden')"
class="w-full flex items-center justify-between px-3 py-2 text-sm text-gray-700 hover:bg-gray-100 rounded-lg"
style="padding-left: 1.5rem">
<span class="flex items-center gap-2">
@if($child->icon)
<i class="{{ $child->icon }} text-base text-gray-400"></i>
@endif
<span class="font-semibold">{{ $child->name }}</span>
</span>
<svg class="w-3 h-3 transition-transform rotate-180" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<ul id="{{ $subGroupId }}" class="space-y-1 mt-1">
@foreach($subChildren as $subChild)
@php
$subItemUrl = $subChild->url ? $baseUrl . $subChild->url : '#';
$isSubActive = $subChild->url && str_ends_with(request()->path(), ltrim($subChild->url, '/'));
$subActiveClass = $isSubActive
? 'bg-primary text-white hover:bg-primary'
: 'text-gray-700 hover:bg-gray-100';
@endphp
<li>
<a href="{{ $subItemUrl }}"
class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm {{ $subActiveClass }}"
style="padding-left: 2.25rem">
@if($subChild->icon)
<i class="{{ $subChild->icon }} text-base {{ $isSubActive ? '' : 'text-gray-400' }}"></i>
@endif
{{ $subChild->name }}
</a>
</li>
@endforeach
</ul>
</li>
@else
{{-- 2depth: 단일 메뉴 아이템 --}}
@php
$itemUrl = $child->url ? $baseUrl . $child->url : '#';
$isActive = $child->url && str_ends_with(request()->path(), ltrim($child->url, '/'));
$activeClass = $isActive
? 'bg-primary text-white hover:bg-primary'
: 'text-gray-700 hover:bg-gray-100';
@endphp
<li>
<a href="{{ $itemUrl }}"
class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm {{ $activeClass }}"
style="padding-left: 1.5rem">
@if($child->icon)
<i class="{{ $child->icon }} text-base {{ $isActive ? '' : 'text-gray-400' }}"></i>
@endif
{{ $child->name }}
</a>
</li>
@endif
@endforeach
</ul>
</li>
@else
{{-- 1depth: 단일 메뉴 아이템 (그룹이 아닌 경우) --}}
@php
$itemUrl = $menu->url ? $baseUrl . $menu->url : '#';
$isActive = $menu->url && str_ends_with(request()->path(), ltrim($menu->url, '/'));
$activeClass = $isActive
? 'bg-primary text-white hover:bg-primary'
: 'text-gray-700 hover:bg-gray-100';
@endphp
<li>
<a href="{{ $itemUrl }}"
class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm {{ $activeClass }}"
style="padding-left: 0.75rem">
@if($menu->icon)
<i class="{{ $menu->icon }} text-base {{ $isActive ? '' : 'text-gray-400' }}"></i>
@endif
{{ $menu->name }}
</a>
</li>
@endif
@endforeach
{{-- 2depth: 메뉴 아이템 (메인 사이드바 menu-item 스타일) --}}
<ul x-ref="group{{ $groupIndex }}" class="space-y-1 mt-1">
@foreach($group['items'] as $item)
@php
$isActive = str_starts_with($currentUrl, url($item['url']));
$activeClass = $isActive
? 'bg-primary text-white hover:bg-primary'
: 'text-gray-700 hover:bg-gray-100';
@endphp
<li>
<a href="{{ $item['url'] }}"
class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm {{ $activeClass }}"
style="padding-left: 1.5rem">
<i class="{{ $item['icon'] }} text-base {{ $isActive ? '' : 'text-gray-400' }}"></i>
{{ $item['name'] }}
</a>
</li>
@endforeach
</ul>
</li>
@endforeach
</ul>
</nav>
@@ -142,4 +110,4 @@ class="flex items-center gap-2 text-sm text-gray-500 hover:text-gray-700 transit
테넌트 목록으로
</a>
</div>
</aside>
</aside>