203 lines
10 KiB
PHP
203 lines
10 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('title', 'PPTX 관리')
|
|
|
|
@push('styles')
|
|
<style>
|
|
.pptx { max-width: 1100px; margin: 0 auto; padding: 32px 20px 48px; }
|
|
|
|
/* 헤더 */
|
|
.pptx-header { text-align: center; margin-bottom: 32px; }
|
|
.pptx-header h1 { font-size: 1.75rem; font-weight: 700; color: #1e293b; margin-bottom: 6px; }
|
|
.pptx-header p { color: #64748b; font-size: 0.95rem; }
|
|
|
|
/* 통계 바 */
|
|
.pptx-stats { display: flex; gap: 16px; justify-content: center; margin-bottom: 28px; }
|
|
.pptx-stat { background: #fff; border: 1px solid #e2e8f0; border-radius: 10px; padding: 14px 24px; display: flex; align-items: center; gap: 10px; }
|
|
.pptx-stat-icon { width: 38px; height: 38px; border-radius: 10px; display: flex; align-items: center; justify-content: center; }
|
|
.pptx-stat-icon svg { width: 20px; height: 20px; }
|
|
.pptx-stat-icon.count { background: #dbeafe; color: #2563eb; }
|
|
.pptx-stat-icon.size { background: #dcfce7; color: #16a34a; }
|
|
.pptx-stat-num { font-size: 1.3rem; font-weight: 700; color: #1e293b; }
|
|
.pptx-stat-label { font-size: 0.75rem; color: #94a3b8; }
|
|
|
|
/* 검색 + 필터 바 */
|
|
.pptx-toolbar { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-bottom: 24px; }
|
|
.pptx-search { flex: 1; min-width: 200px; position: relative; }
|
|
.pptx-search input { width: 100%; padding: 10px 14px 10px 38px; border: 1px solid #e2e8f0; border-radius: 10px; font-size: 0.88rem; outline: none; transition: border-color 0.2s; background: #fff; }
|
|
.pptx-search input:focus { border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,0.1); }
|
|
.pptx-search svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: #94a3b8; }
|
|
|
|
/* 필터 탭 */
|
|
.pptx-filters { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
.pptx-filter-btn { padding: 6px 14px; border: 1px solid #e2e8f0; border-radius: 8px; background: #fff; font-size: 0.8rem; color: #64748b; cursor: pointer; transition: all 0.2s; white-space: nowrap; }
|
|
.pptx-filter-btn:hover { border-color: #3b82f6; color: #3b82f6; }
|
|
.pptx-filter-btn.active { background: #3b82f6; border-color: #3b82f6; color: #fff; }
|
|
|
|
/* 파일 목록 */
|
|
.pptx-list { display: flex; flex-direction: column; gap: 10px; }
|
|
.pptx-item { background: #fff; border: 1px solid #e2e8f0; border-radius: 12px; padding: 18px 20px; display: flex; align-items: center; gap: 16px; transition: all 0.2s; }
|
|
.pptx-item:hover { border-color: #3b82f6; box-shadow: 0 4px 12px rgba(59,130,246,0.08); }
|
|
|
|
/* 파일 아이콘 */
|
|
.pptx-icon { width: 44px; height: 44px; border-radius: 10px; background: #fff7ed; color: #ea580c; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
|
|
.pptx-icon svg { width: 22px; height: 22px; }
|
|
|
|
/* 파일 정보 */
|
|
.pptx-info { flex: 1; min-width: 0; }
|
|
.pptx-name { font-size: 0.92rem; font-weight: 600; color: #1e293b; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.pptx-meta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 5px; align-items: center; }
|
|
.pptx-badge { display: inline-block; padding: 2px 8px; border-radius: 6px; font-size: 0.7rem; font-weight: 500; }
|
|
.pptx-badge.cat { background: #dbeafe; color: #1d4ed8; }
|
|
.pptx-badge.src { background: #f1f5f9; color: #64748b; }
|
|
.pptx-meta-text { font-size: 0.75rem; color: #94a3b8; }
|
|
.pptx-meta-sep { color: #e2e8f0; font-size: 0.7rem; }
|
|
|
|
/* 다운로드 버튼 */
|
|
.pptx-dl { display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; border: 1px solid #e2e8f0; border-radius: 8px; background: #fff; font-size: 0.8rem; font-weight: 500; color: #334155; text-decoration: none; transition: all 0.2s; flex-shrink: 0; }
|
|
.pptx-dl:hover { background: #3b82f6; border-color: #3b82f6; color: #fff; }
|
|
.pptx-dl svg { width: 14px; height: 14px; }
|
|
|
|
/* 빈 상태 */
|
|
.pptx-empty { text-align: center; padding: 60px 20px; color: #94a3b8; }
|
|
.pptx-empty svg { width: 48px; height: 48px; margin: 0 auto 12px; color: #cbd5e1; }
|
|
.pptx-empty p { font-size: 0.9rem; }
|
|
|
|
@media (max-width: 768px) {
|
|
.pptx-stats { flex-direction: column; align-items: stretch; }
|
|
.pptx-item { flex-direction: column; align-items: flex-start; gap: 12px; }
|
|
.pptx-dl { align-self: flex-end; }
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
@section('content')
|
|
<div class="pptx">
|
|
{{-- 헤더 --}}
|
|
<div class="pptx-header">
|
|
<h1>PPTX 관리</h1>
|
|
<p>회사 프레젠테이션 자료를 한 곳에서 관리합니다</p>
|
|
</div>
|
|
|
|
{{-- 통계 바 --}}
|
|
<div class="pptx-stats">
|
|
<div class="pptx-stat">
|
|
<div class="pptx-stat-icon count">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg>
|
|
</div>
|
|
<div>
|
|
<div class="pptx-stat-num">{{ $totalCount }}</div>
|
|
<div class="pptx-stat-label">전체 파일</div>
|
|
</div>
|
|
</div>
|
|
<div class="pptx-stat">
|
|
<div class="pptx-stat-icon size">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4" /></svg>
|
|
</div>
|
|
<div>
|
|
<div class="pptx-stat-num">{{ $totalSize }}</div>
|
|
<div class="pptx-stat-label">총 크기</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- 검색 + 필터 --}}
|
|
<div class="pptx-toolbar">
|
|
<div class="pptx-search">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>
|
|
<input type="text" id="pptxSearch" placeholder="파일명 검색..." autocomplete="off">
|
|
</div>
|
|
<div class="pptx-filters">
|
|
<button class="pptx-filter-btn active" data-category="all">전체</button>
|
|
@foreach ($categories as $cat)
|
|
<button class="pptx-filter-btn" data-category="{{ $cat }}">{{ $cat }}</button>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
|
|
{{-- 파일 목록 --}}
|
|
<div class="pptx-list" id="pptxList">
|
|
@forelse ($files as $file)
|
|
<div class="pptx-item" data-category="{{ $file['category'] }}" data-name="{{ mb_strtolower($file['name']) }}">
|
|
<div class="pptx-icon">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" /></svg>
|
|
</div>
|
|
<div class="pptx-info">
|
|
<div class="pptx-name" title="{{ $file['name'] }}">{{ $file['name'] }}</div>
|
|
<div class="pptx-meta">
|
|
<span class="pptx-badge cat">{{ $file['category'] }}</span>
|
|
<span class="pptx-badge src">{{ $file['source_dir'] }}</span>
|
|
<span class="pptx-meta-sep">|</span>
|
|
<span class="pptx-meta-text">{{ $file['size'] }}</span>
|
|
<span class="pptx-meta-sep">|</span>
|
|
<span class="pptx-meta-text">{{ $file['modified_date'] }}</span>
|
|
</div>
|
|
</div>
|
|
<a href="{{ route('additional.pptx.download', ['file' => $file['path']]) }}" class="pptx-dl">
|
|
<svg 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" /></svg>
|
|
다운로드
|
|
</a>
|
|
</div>
|
|
@empty
|
|
<div class="pptx-empty">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg>
|
|
<p>PPTX 파일이 없습니다</p>
|
|
</div>
|
|
@endforelse
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@push('scripts')
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const searchInput = document.getElementById('pptxSearch');
|
|
const filterBtns = document.querySelectorAll('.pptx-filter-btn');
|
|
const items = document.querySelectorAll('.pptx-item');
|
|
let activeCategory = 'all';
|
|
|
|
function filterItems() {
|
|
const query = searchInput.value.toLowerCase().trim();
|
|
let visibleCount = 0;
|
|
|
|
items.forEach(function (item) {
|
|
const name = item.dataset.name;
|
|
const category = item.dataset.category;
|
|
const matchCategory = activeCategory === 'all' || category === activeCategory;
|
|
const matchSearch = !query || name.includes(query);
|
|
const visible = matchCategory && matchSearch;
|
|
|
|
item.style.display = visible ? '' : 'none';
|
|
if (visible) visibleCount++;
|
|
});
|
|
|
|
// 빈 상태 메시지
|
|
let emptyEl = document.getElementById('pptxFilterEmpty');
|
|
if (visibleCount === 0) {
|
|
if (!emptyEl) {
|
|
emptyEl = document.createElement('div');
|
|
emptyEl.id = 'pptxFilterEmpty';
|
|
emptyEl.className = 'pptx-empty';
|
|
emptyEl.innerHTML = '<p>검색 결과가 없습니다</p>';
|
|
document.getElementById('pptxList').appendChild(emptyEl);
|
|
}
|
|
emptyEl.style.display = '';
|
|
} else if (emptyEl) {
|
|
emptyEl.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
filterBtns.forEach(function (btn) {
|
|
btn.addEventListener('click', function () {
|
|
filterBtns.forEach(function (b) { b.classList.remove('active'); });
|
|
btn.classList.add('active');
|
|
activeCategory = btn.dataset.category;
|
|
filterItems();
|
|
});
|
|
});
|
|
|
|
searchInput.addEventListener('input', filterItems);
|
|
});
|
|
</script>
|
|
@endpush
|