feat(mobile): Phase 4 폼/필터 반응형 구현

- filter-collapsible 컴포넌트 생성 (모바일 필터 토글)
- 10개 index 페이지 헤더/필터 반응형 적용
- 헤더: flex-col sm:flex-row 스택 배치
- 필터: w-full sm:w-40 반응형 너비
- 버튼: flex-1 sm:flex-none 그룹 배치
This commit is contained in:
2025-12-19 16:46:30 +09:00
parent a72e4c4127
commit d43013b4b4
11 changed files with 181 additions and 116 deletions

View File

@@ -4,18 +4,18 @@
@section('content')
<!-- 페이지 헤더 -->
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-bold text-gray-800">📋 시스템 게시판 관리</h1>
<a href="{{ route('boards.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition">
<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>
<a href="{{ route('boards.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition text-center w-full sm:w-auto">
+ 게시판
</a>
</div>
<!-- 필터 영역 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<form id="filterForm" class="flex gap-4 flex-wrap">
<x-filter-collapsible id="filterForm">
<form id="filterForm" class="flex flex-wrap gap-2 sm:gap-4">
<!-- 검색 -->
<div class="flex-1 min-w-[200px]">
<div class="flex-1 min-w-0 w-full sm:w-auto">
<input type="text"
name="search"
placeholder="게시판명, 코드로 검색..."
@@ -23,7 +23,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 게시판 유형 필터 -->
<div class="w-40">
<div class="w-full sm:w-40">
<select name="board_type" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체 유형</option>
<option value="notice">공지사항</option>
@@ -39,7 +39,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 활성 상태 필터 -->
<div class="w-32">
<div class="w-full sm:w-32">
<select name="is_active" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체</option>
<option value="1">활성</option>
@@ -48,7 +48,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 삭제된 항목 포함 -->
<div class="w-36">
<div class="w-full sm:w-36">
<select name="trashed" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">활성만</option>
<option value="with">삭제 포함</option>
@@ -57,11 +57,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 검색 버튼 -->
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition">
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition w-full sm:w-auto">
검색
</button>
</form>
</div>
</x-filter-collapsible>
<!-- 테이블 영역 (HTMX로 로드) -->
<div id="board-table"

View File

@@ -0,0 +1,67 @@
@props(['id' => 'filterForm', 'defaultOpen' => false])
{{-- 모바일 필터 접기/펼치기 컴포넌트 --}}
<div class="bg-white rounded-lg shadow-sm mb-6">
{{-- 모바일 필터 토글 버튼 (sm 미만에서만 표시) --}}
<button type="button"
onclick="toggleFilter('{{ $id }}')"
class="sm:hidden w-full flex items-center justify-between p-4 text-left">
<span class="flex items-center gap-2 text-gray-700 font-medium">
<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="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"/>
</svg>
필터
</span>
<svg id="{{ $id }}-chevron" class="w-5 h-5 text-gray-500 transition-transform duration-200 {{ $defaultOpen ? '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>
{{-- 필터 내용 영역 --}}
<div id="{{ $id }}-content"
class="p-4 pt-0 sm:pt-4 {{ $defaultOpen ? '' : 'hidden' }} sm:block">
{{ $slot }}
</div>
</div>
@once
@push('scripts')
<script>
// 필터 토글 함수
function toggleFilter(formId) {
const content = document.getElementById(formId + '-content');
const chevron = document.getElementById(formId + '-chevron');
if (content && chevron) {
content.classList.toggle('hidden');
chevron.classList.toggle('rotate-180');
// 상태 저장 (선택적)
const isOpen = !content.classList.contains('hidden');
try {
localStorage.setItem('filter_' + formId + '_open', isOpen);
} catch (e) {
// localStorage 사용 불가 시 무시
}
}
}
// 페이지 로드 시 저장된 상태 복원 (선택적)
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('[id$="-content"]').forEach(function(content) {
const formId = content.id.replace('-content', '');
try {
const savedState = localStorage.getItem('filter_' + formId + '_open');
if (savedState === 'true') {
content.classList.remove('hidden');
const chevron = document.getElementById(formId + '-chevron');
if (chevron) chevron.classList.add('rotate-180');
}
} catch (e) {
// localStorage 사용 불가 시 무시
}
});
});
</script>
@endpush
@endonce

View File

@@ -4,18 +4,18 @@
@section('content')
<!-- 페이지 헤더 -->
<div class="flex justify-between items-center mb-6">
<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>
<a href="{{ route('departments.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition">
<a href="{{ route('departments.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition text-center w-full sm:w-auto">
+ 부서
</a>
</div>
<!-- 필터 영역 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<form id="filterForm" class="flex gap-4">
<x-filter-collapsible id="filterForm">
<form id="filterForm" class="flex flex-wrap gap-2 sm:gap-4">
<!-- 검색 -->
<div class="flex-1">
<div class="flex-1 min-w-0 w-full sm:w-auto">
<input type="text"
name="search"
placeholder="부서명, 코드, 설명으로 검색..."
@@ -23,7 +23,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 활성 상태 필터 -->
<div class="w-40">
<div class="w-full sm:w-40">
<select name="is_active" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체 상태</option>
<option value="1">활성</option>
@@ -32,7 +32,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 삭제 상태 필터 -->
<div class="w-40">
<div class="w-full sm:w-40">
<select name="trashed" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">정상만</option>
<option value="with">전체 (삭제 포함)</option>
@@ -41,11 +41,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 검색 버튼 -->
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition">
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition w-full sm:w-auto">
검색
</button>
</form>
</div>
</x-filter-collapsible>
<!-- 테이블 영역 (HTMX로 로드) -->
<div id="department-table"

View File

@@ -4,32 +4,32 @@
@section('content')
<!-- 페이지 헤더 -->
<div class="flex justify-between items-center mb-6">
<div class="flex flex-col lg:flex-row lg:justify-between lg:items-center gap-4 mb-6">
<div>
<h1 class="text-2xl font-bold text-gray-800">메뉴 관리</h1>
<p class="text-sm text-gray-500 mt-1" id="modeDescription">
<p class="text-sm text-gray-500 mt-1 hidden sm:block" id="modeDescription">
드래그: 순서 변경 | <span class="font-medium text-blue-600"> 오른쪽</span>: 하위로 이동 | <span class="font-medium text-orange-600"> 왼쪽</span>: 상위로 이동
</p>
</div>
<div class="flex items-center gap-3">
<div class="flex flex-wrap items-center gap-2 sm:gap-3">
@if(session('selected_tenant_id'))
<!-- 모드 전환 버튼 -->
<div class="flex items-center bg-gray-200 rounded-lg p-1">
<div class="flex items-center bg-gray-200 rounded-lg p-1 w-full sm:w-auto">
<button onclick="switchMode('normal')"
id="normalModeBtn"
class="mode-btn px-4 py-2 text-sm font-medium rounded-md transition bg-white text-gray-900 shadow-sm">
class="mode-btn flex-1 sm:flex-none px-4 py-2 text-sm font-medium rounded-md transition bg-white text-gray-900 shadow-sm">
메뉴
</button>
<button onclick="switchMode('import')"
id="importModeBtn"
class="mode-btn px-4 py-2 text-sm font-medium rounded-md transition bg-gray-200 text-gray-500 hover:text-gray-700 hover:bg-gray-300">
class="mode-btn flex-1 sm:flex-none px-4 py-2 text-sm font-medium rounded-md transition bg-gray-200 text-gray-500 hover:text-gray-700 hover:bg-gray-300">
기본에서 가져오기
</button>
</div>
<!-- 가져오기 버튼 (import 모드에서만 표시) -->
<button onclick="importSelectedMenus()"
id="importBtn"
class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg transition items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed hidden"
class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg transition items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed hidden w-full sm:w-auto text-center"
disabled>
<svg class="w-4 h-4 inline-block mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
@@ -37,28 +37,29 @@ class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg transitio
선택 가져오기 (<span id="selectedCount">0</span>)
</button>
@endif
<a href="{{ route('menus.create') }}" id="newMenuBtn" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition">
<a href="{{ route('menus.create') }}" id="newMenuBtn" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition flex-1 sm:flex-none text-center">
+ 메뉴
</a>
@if(auth()->user()?->is_super_admin)
<a href="{{ route('menus.global.index') }}" class="bg-purple-600 hover:bg-purple-700 text-white px-4 py-2 rounded-lg transition flex items-center gap-2">
<a href="{{ route('menus.global.index') }}" class="bg-purple-600 hover:bg-purple-700 text-white px-4 py-2 rounded-lg transition flex items-center justify-center gap-2 flex-1 sm:flex-none">
<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="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
기본 메뉴 관리
<span class="hidden sm:inline">기본 메뉴 관리</span>
<span class="sm:hidden">기본 메뉴</span>
</a>
@endif
</div>
</div>
<!-- 필터 영역 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<form id="filterForm" class="flex gap-4">
<x-filter-collapsible id="filterForm">
<form id="filterForm" class="flex flex-wrap gap-2 sm:gap-4">
<!-- 모드 (hidden) -->
<input type="hidden" name="mode" id="modeInput" value="">
<!-- 검색 -->
<div class="flex-1">
<div class="flex-1 min-w-0 w-full sm:w-auto">
<input type="text"
name="search"
placeholder="메뉴명, URL로 검색..."
@@ -66,7 +67,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 활성 상태 필터 (일반 모드) -->
<div class="w-48" id="activeFilter">
<div class="w-full sm:w-48" id="activeFilter">
<select name="is_active" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체 상태</option>
<option value="1">활성</option>
@@ -75,7 +76,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 가져오기 상태 필터 (가져오기 모드) -->
<div class="w-48 hidden" id="importFilter">
<div class="w-full sm:w-48 hidden" id="importFilter">
<select name="import_status" id="importStatusSelect" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-green-500" onchange="filterImportedMenus()">
<option value="all">전체 메뉴</option>
<option value="available">가져올 있는 메뉴</option>
@@ -83,11 +84,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 검색 버튼 -->
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition">
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition w-full sm:w-auto">
검색
</button>
</form>
</div>
</x-filter-collapsible>
<!-- 테이블 영역 (HTMX로 로드) -->
<div id="menu-table"

View File

@@ -4,18 +4,18 @@
@section('content')
<!-- 페이지 헤더 -->
<div class="flex justify-between items-center mb-6">
<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>
<a href="{{ route('permissions.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition">
<a href="{{ route('permissions.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition text-center w-full sm:w-auto">
+ 권한
</a>
</div>
<!-- 필터 영역 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<form id="filterForm" class="flex gap-4">
<x-filter-collapsible id="filterForm">
<form id="filterForm" class="flex flex-wrap gap-2 sm:gap-4">
<!-- 검색 -->
<div class="flex-1">
<div class="flex-1 min-w-0 w-full sm:w-auto">
<input type="text"
name="search"
placeholder="권한 이름으로 검색..."
@@ -23,7 +23,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- Guard 필터 -->
<div class="w-48">
<div class="w-full sm:w-48">
<select name="guard_name" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체 Guard</option>
<option value="web">web</option>
@@ -32,11 +32,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 검색 버튼 -->
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition">
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition w-full sm:w-auto">
검색
</button>
</form>
</div>
</x-filter-collapsible>
<!-- 테이블 영역 (HTMX로 로드) -->
<div id="permission-table"

View File

@@ -4,40 +4,37 @@
@section('content')
<!-- 페이지 헤더 -->
<div class="flex justify-between items-center mb-6">
<div class="flex items-center gap-4">
<h1 class="text-2xl font-bold text-gray-800 flex items-center gap-2">
<svg class="w-6 h-6 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
</svg>
프로젝트 목록
</h1>
</div>
<div class="flex gap-2">
<a href="{{ route('pm.index') }}" class="inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-white hover:bg-gray-300 text-gray-700 rounded-lg transition">
<div class="flex flex-col lg:flex-row lg:justify-between lg:items-center gap-4 mb-6">
<h1 class="text-2xl font-bold text-gray-800 flex items-center gap-2">
<svg class="w-6 h-6 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
</svg>
프로젝트 목록
</h1>
<div class="flex flex-wrap items-center gap-2 sm:gap-3">
<a href="{{ route('pm.index') }}" class="flex-1 sm:flex-none inline-flex items-center justify-center gap-1 px-3 py-1.5 text-sm bg-white hover:bg-gray-300 text-gray-700 rounded-lg transition">
<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="M15 19l-7-7 7-7"/>
</svg>
대시보드
</a>
<a href="{{ route('pm.import') }}" class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg transition flex items-center gap-2">
<a href="{{ route('pm.import') }}" class="flex-1 sm:flex-none bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg transition flex items-center justify-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="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" />
</svg>
JSON Import
</a>
<a href="{{ route('pm.projects.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition">
<a href="{{ route('pm.projects.create') }}" class="w-full sm:w-auto bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition text-center">
+ 프로젝트
</a>
</div>
</div>
<!-- 필터 영역 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<form id="filterForm" class="flex gap-4 flex-wrap">
<x-filter-collapsible id="filterForm">
<form id="filterForm" class="flex flex-wrap gap-2 sm:gap-4">
<!-- 검색 -->
<div class="flex-1 min-w-64">
<div class="flex-1 min-w-0 w-full sm:w-auto">
<input type="text"
name="search"
placeholder="프로젝트명, 설명으로 검색..."
@@ -45,7 +42,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 상태 필터 -->
<div class="w-40">
<div class="w-full sm:w-40">
<select name="status" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체 상태</option>
@foreach($statuses as $value => $label)
@@ -55,7 +52,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 삭제된 항목 포함 -->
<div class="w-40">
<div class="w-full sm:w-40">
<select name="trashed" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">활성만</option>
<option value="with">삭제 포함</option>
@@ -64,11 +61,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 검색 버튼 -->
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition">
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition w-full sm:w-auto">
검색
</button>
</form>
</div>
</x-filter-collapsible>
<!-- 테이블 영역 (HTMX로 로드) -->
<div id="project-table"

View File

@@ -5,28 +5,28 @@
@section('content')
<div class="container mx-auto max-w-6xl">
<!-- 헤더 -->
<div class="flex justify-between items-center mb-6">
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-6">
<div>
<h1 class="text-2xl font-bold text-gray-800">수식 카테고리 관리</h1>
<p class="text-sm text-gray-500 mt-1">수식을 그룹화하는 카테고리를 관리합니다.</p>
</div>
<div class="flex gap-2">
<div class="flex flex-wrap gap-2">
<a href="{{ route('quote-formulas.index') }}"
class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors">
class="flex-1 sm:flex-none bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors text-center">
수식 목록
</a>
<a href="{{ route('quote-formulas.categories.create') }}"
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors">
class="flex-1 sm:flex-none bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors text-center">
+ 카테고리 추가
</a>
</div>
</div>
<!-- 필터 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<form id="filterForm" class="flex gap-4 flex-wrap">
<x-filter-collapsible id="filterForm">
<form id="filterForm" class="flex flex-wrap gap-2 sm:gap-4">
<!-- 검색 -->
<div class="flex-1 min-w-[200px]">
<div class="flex-1 min-w-0 w-full sm:w-auto">
<input type="text"
name="search"
placeholder="카테고리명, 코드로 검색..."
@@ -34,7 +34,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 활성 상태 필터 -->
<div class="w-32">
<div class="w-full sm:w-32">
<select name="is_active" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체</option>
<option value="1">활성</option>
@@ -43,7 +43,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 삭제된 항목 포함 -->
<div class="w-36">
<div class="w-full sm:w-36">
<select name="trashed" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">활성만</option>
<option value="with">삭제 포함</option>
@@ -52,11 +52,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 검색 버튼 -->
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition">
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition w-full sm:w-auto">
검색
</button>
</form>
</div>
</x-filter-collapsible>
<!-- 테이블 영역 (HTMX로 로드) -->
<div id="category-table"

View File

@@ -5,32 +5,32 @@
@section('content')
<div class="container mx-auto max-w-7xl">
<!-- 헤더 -->
<div class="flex justify-between items-center mb-6">
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-6">
<div>
<h1 class="text-2xl font-bold text-gray-800">견적수식 관리</h1>
<p class="text-sm text-gray-500 mt-1">견적 산출에 사용되는 수식을 관리합니다.</p>
</div>
<div class="flex gap-2">
<div class="flex flex-wrap gap-2">
<a href="{{ route('quote-formulas.categories.index') }}"
class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors">
class="flex-1 sm:flex-none bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors text-center">
카테고리 관리
</a>
<a href="{{ route('quote-formulas.simulator') }}"
class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors">
class="flex-1 sm:flex-none bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors text-center">
시뮬레이터
</a>
<a href="{{ route('quote-formulas.create') }}"
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors">
class="w-full sm:w-auto bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors text-center">
+ 수식 추가
</a>
</div>
</div>
<!-- 필터 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<form id="filterForm" class="flex flex-wrap gap-4 items-end">
<x-filter-collapsible id="filterForm">
<form id="filterForm" class="flex flex-wrap gap-2 sm:gap-4 items-end">
<!-- 카테고리 필터 -->
<div class="w-48">
<div class="w-full sm:w-48">
<label class="block text-xs font-medium text-gray-600 mb-1">카테고리</label>
<select name="category_id" id="categoryFilter" class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체</option>
@@ -38,7 +38,7 @@ class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm fon
</div>
<!-- 유형 필터 -->
<div class="w-40">
<div class="w-full sm:w-40">
<label class="block text-xs font-medium text-gray-600 mb-1">수식 유형</label>
<select name="type" class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체</option>
@@ -50,7 +50,7 @@ class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm fon
</div>
<!-- 활성 상태 필터 -->
<div class="w-32">
<div class="w-full sm:w-32">
<label class="block text-xs font-medium text-gray-600 mb-1">상태</label>
<select name="is_active" class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체</option>
@@ -60,7 +60,7 @@ class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm fon
</div>
<!-- 삭제된 항목 포함 -->
<div class="w-36">
<div class="w-full sm:w-36">
<label class="block text-xs font-medium text-gray-600 mb-1">삭제 포함</label>
<select name="trashed" class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">활성만</option>
@@ -70,7 +70,7 @@ class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm fon
</div>
<!-- 검색 -->
<div class="flex-1 min-w-[200px]">
<div class="flex-1 min-w-0 w-full sm:w-auto">
<label class="block text-xs font-medium text-gray-600 mb-1">검색</label>
<input type="text" name="search"
placeholder="수식명, 변수명, 수식 내용..."
@@ -79,11 +79,11 @@ class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-
<!-- 검색 버튼 -->
<button type="submit"
class="bg-gray-800 hover:bg-gray-900 text-white px-6 py-2 rounded-lg text-sm font-medium transition-colors">
class="w-full sm:w-auto bg-gray-800 hover:bg-gray-900 text-white px-6 py-2 rounded-lg text-sm font-medium transition-colors">
검색
</button>
</form>
</div>
</x-filter-collapsible>
<!-- 테이블 영역 (HTMX로 로드) -->
<div id="formula-table"

View File

@@ -4,18 +4,18 @@
@section('content')
<!-- 페이지 헤더 -->
<div class="flex justify-between items-center mb-6">
<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>
<a href="{{ route('roles.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition">
<a href="{{ route('roles.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition text-center w-full sm:w-auto">
+ 역할
</a>
</div>
<!-- 필터 영역 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<form id="filterForm" class="flex gap-4">
<x-filter-collapsible id="filterForm">
<form id="filterForm" class="flex flex-wrap gap-2 sm:gap-4">
<!-- Guard 선택 -->
<div class="w-32">
<div class="w-full sm:w-32">
<select name="guard_name"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체 Guard</option>
@@ -25,7 +25,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 검색 -->
<div class="flex-1">
<div class="flex-1 min-w-0 w-full sm:w-auto">
<input type="text"
name="search"
placeholder="역할 이름, 설명으로 검색..."
@@ -33,11 +33,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 검색 버튼 -->
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition">
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition w-full sm:w-auto">
검색
</button>
</form>
</div>
</x-filter-collapsible>
<!-- 테이블 영역 (HTMX로 로드) -->
<div id="role-table"

View File

@@ -5,18 +5,18 @@
@section('content')
<!-- TENANT INDEX PAGE MARKER - 이것이 보이면 tenants/index.blade.php가 로드된 것입니다 -->
<!-- 페이지 헤더 -->
<div class="flex justify-between items-center mb-6">
<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>
<a href="{{ route('tenants.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition">
<a href="{{ route('tenants.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition text-center w-full sm:w-auto">
+ 테넌트
</a>
</div>
<!-- 필터 영역 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<form id="filterForm" class="flex gap-4">
<x-filter-collapsible id="filterForm">
<form id="filterForm" class="flex flex-wrap gap-2 sm:gap-4">
<!-- 검색 -->
<div class="flex-1">
<div class="flex-1 min-w-0 w-full sm:w-auto">
<input type="text"
name="search"
placeholder="회사명, 코드, 이메일로 검색..."
@@ -24,7 +24,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 상태 필터 -->
<div class="w-48">
<div class="w-full sm:w-48">
<select name="tenant_st_code" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체 상태</option>
<option value="trial">트라이얼</option>
@@ -35,7 +35,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 삭제된 항목 포함 -->
<div class="w-48">
<div class="w-full sm:w-48">
<select name="trashed" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">활성만</option>
<option value="with">삭제 포함</option>
@@ -44,11 +44,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 검색 버튼 -->
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition">
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition w-full sm:w-auto">
검색
</button>
</form>
</div>
</x-filter-collapsible>
<!-- 테이블 영역 (HTMX로 로드) -->
<div id="tenant-table"

View File

@@ -4,18 +4,18 @@
@section('content')
<!-- 페이지 헤더 -->
<div class="flex justify-between items-center mb-6">
<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>
<a href="{{ route('users.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition">
<a href="{{ route('users.create') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition text-center w-full sm:w-auto">
+ 사용자
</a>
</div>
<!-- 필터 영역 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<form id="filterForm" class="flex gap-4">
<x-filter-collapsible id="filterForm">
<form id="filterForm" class="flex flex-wrap gap-2 sm:gap-4">
<!-- 검색 -->
<div class="flex-1">
<div class="flex-1 min-w-0 w-full sm:w-auto">
<input type="text"
name="search"
placeholder="이름, 이메일, 연락처로 검색..."
@@ -23,7 +23,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 활성 상태 필터 -->
<div class="w-48">
<div class="w-full sm:w-48">
<select name="is_active" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">전체 상태</option>
<option value="1">활성</option>
@@ -32,11 +32,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</div>
<!-- 검색 버튼 -->
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition">
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition w-full sm:w-auto">
검색
</button>
</form>
</div>
</x-filter-collapsible>
<!-- 테이블 영역 (HTMX로 로드) -->
<div id="user-table"