Add comprehensive file management system with admin/user separation

Features added:
- Admin interface with full CRUD operations and multi-file upload
- User interface with read-only access and download functionality
- Board-style table layout with pagination (10 items per page)
- Category-specific file icons and attachment management
- Drag & drop file upload with preview and individual file removal
- Individual and bulk download with ZIP compression support
- Offline mode with localStorage fallback for both interfaces
- Responsive design with modern UI components

Technical improvements:
- Separated admin (/admin/) and user (/) interfaces
- Enhanced file data structure with consistent naming
- Improved error handling and user notifications
- Multi-file upload processing with base64 encoding
- File type detection and appropriate icon mapping
- Download functionality with single/multiple file handling

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-19 19:56:16 +09:00
parent 033eb567c5
commit 7a08bf9b4c
13 changed files with 3559 additions and 1170 deletions

View File

@@ -39,6 +39,47 @@ header p {
font-size: 1.1rem;
}
/* 페이지네이션 스타일 */
.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
margin-top: 30px;
padding: 20px;
background: rgba(255, 255, 255, 0.9);
border-radius: 10px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}
.page-btn {
background: #4299e1;
color: white;
border: none;
padding: 10px 20px;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
transition: all 0.3s ease;
}
.page-btn:hover:not(:disabled) {
background: #3182ce;
transform: translateY(-2px);
}
.page-btn:disabled {
background: #a0aec0;
cursor: not-allowed;
transform: none;
}
#pageInfo {
font-weight: 600;
color: #4a5568;
font-size: 1.1rem;
}
.auth-section {
margin-top: 20px;
display: flex;
@@ -360,6 +401,215 @@ header p {
cursor: pointer;
}
/* 게시판 스타일 */
.board-container {
background: rgba(255, 255, 255, 0.95);
border-radius: 12px;
padding: 20px;
margin-top: 20px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
}
.board-table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.board-table thead {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.board-table th {
padding: 15px 12px;
text-align: center;
font-weight: 600;
font-size: 0.95rem;
border-right: 1px solid rgba(255, 255, 255, 0.2);
}
.board-table th:last-child {
border-right: none;
}
.board-table tbody tr {
border-bottom: 1px solid #e5e7eb;
transition: background-color 0.2s ease;
}
.board-table tbody tr:hover {
background-color: #f8fafc;
}
.board-table tbody tr:last-child {
border-bottom: none;
}
.board-table td {
padding: 12px;
text-align: center;
vertical-align: middle;
font-size: 0.9rem;
}
/* 컬럼 너비 설정 */
.col-no { width: 60px; }
.col-category { width: 100px; }
.col-title { width: auto; min-width: 200px; text-align: left; }
.col-attachment { width: 80px; }
.col-date { width: 120px; }
.col-actions { width: 150px; }
/* 제목 스타일 */
.board-title {
color: #374151;
font-weight: 500;
text-decoration: none;
cursor: pointer;
display: block;
padding: 8px;
border-radius: 4px;
transition: all 0.2s ease;
}
.board-title:hover {
background-color: #e0e7ff;
color: #4f46e5;
}
/* 카테고리 배지 */
.category-badge {
display: inline-block;
padding: 4px 10px;
border-radius: 12px;
font-size: 0.8rem;
font-weight: 500;
color: white;
}
.category-문서 { background: #3b82f6; }
.category-이미지 { background: #10b981; }
.category-동영상 { background: #f59e0b; }
.category-프레젠테이션 { background: #ef4444; }
.category-기타 { background: #6b7280; }
/* 첨부파일 아이콘 */
.attachment-icon {
font-size: 1.2rem;
color: #10b981;
}
.attachment-icons {
display: flex;
gap: 2px;
justify-content: center;
align-items: center;
flex-wrap: wrap;
font-size: 1rem;
line-height: 1.2;
}
.attachment-icons span {
display: inline-block;
}
.attachment-icon-clickable {
cursor: pointer;
transition: all 0.2s ease;
padding: 2px;
border-radius: 3px;
}
.attachment-icon-clickable:hover {
background-color: #e0e7ff;
transform: scale(1.1);
}
.no-attachment {
color: #9ca3af;
}
/* 액션 버튼 */
.action-buttons {
display: flex;
gap: 5px;
justify-content: center;
align-items: center;
}
.action-btn {
padding: 6px 12px;
border: none;
border-radius: 4px;
font-size: 0.8rem;
cursor: pointer;
transition: all 0.2s ease;
font-weight: 500;
}
.btn-download {
background: #10b981;
color: white;
}
.btn-download:hover {
background: #059669;
transform: translateY(-1px);
}
/* 빈 상태 */
.empty-state td {
padding: 60px 20px;
text-align: center;
color: #6b7280;
font-size: 1.1rem;
}
/* 페이지네이션 스타일 */
.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: 15px;
margin-top: 20px;
padding: 20px 0;
}
.page-btn {
padding: 8px 16px;
border: 2px solid #e2e8f0;
border-radius: 6px;
background: white;
color: #4a5568;
cursor: pointer;
font-size: 0.9rem;
font-weight: 500;
transition: all 0.2s ease;
}
.page-btn:hover:not(:disabled) {
border-color: #667eea;
color: #667eea;
background: #f0f4ff;
}
.page-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
color: #9ca3af;
}
#pageInfo {
font-weight: 600;
color: #4a5568;
font-size: 1rem;
}
.file-list {
display: grid;
gap: 20px;
@@ -470,10 +720,47 @@ header p {
.download-btn {
background: #38a169;
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 0.9rem;
transition: all 0.3s ease;
font-weight: 500;
}
.download-btn:hover {
background: #2f855a;
transform: translateY(-1px);
}
.no-files {
color: #a0aec0;
font-style: italic;
font-size: 0.9rem;
}
.file-attachments {
margin-top: 10px;
padding: 8px 12px;
background: rgba(59, 130, 246, 0.1);
border-radius: 6px;
border: 1px solid rgba(59, 130, 246, 0.2);
}
.file-attachments strong {
color: #1e40af;
margin-right: 8px;
}
.attachment {
display: inline-block;
background: rgba(59, 130, 246, 0.2);
color: #1e40af;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.85rem;
margin: 2px;
}
.empty-state {