1192 lines
29 KiB
HTML
1192 lines
29 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ko">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>어록 관리</title>
|
||
<style>
|
||
* { box-sizing: border-box; }
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
margin: 0;
|
||
padding: 20px;
|
||
background-color: #f8f9fa;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
h2 {
|
||
text-align: center;
|
||
margin-bottom: 20px;
|
||
color: #2c3e50;
|
||
}
|
||
|
||
/* 필터 섹션 스타일 */
|
||
.filter-section {
|
||
background: white;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
margin-bottom: 20px;
|
||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.filter-row {
|
||
display: flex;
|
||
gap: 15px;
|
||
align-items: center;
|
||
margin-bottom: 15px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.filter-group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 5px;
|
||
}
|
||
|
||
.filter-group label {
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
color: #555;
|
||
}
|
||
|
||
.filter-group select,
|
||
.filter-group input {
|
||
padding: 8px 12px;
|
||
border: 1px solid #ddd;
|
||
border-radius: 4px;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.filter-buttons {
|
||
display: flex;
|
||
gap: 10px;
|
||
align-items: end;
|
||
}
|
||
|
||
.filter-btn {
|
||
padding: 8px 16px;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.filter-btn.primary {
|
||
background: #3498db;
|
||
color: white;
|
||
}
|
||
|
||
.filter-btn.secondary {
|
||
background: #95a5a6;
|
||
color: white;
|
||
}
|
||
|
||
.filter-btn:hover {
|
||
opacity: 0.8;
|
||
}
|
||
|
||
/* 통계 정보 스타일 */
|
||
.stats-info {
|
||
background: #f8f9fa;
|
||
border: 1px solid #dee2e6;
|
||
border-radius: 6px;
|
||
padding: 15px;
|
||
margin-bottom: 20px;
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
color: #495057;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
/* 어록 추가 버튼 스타일 */
|
||
.add-saying-btn {
|
||
padding: 10px 20px;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.add-saying-btn:hover {
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 4px 8px rgba(102, 126, 234, 0.3);
|
||
}
|
||
|
||
.add-saying-btn:active {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
/* 어록 카드 컨테이너 */
|
||
.sayings-container {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
||
gap: 20px;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
/* 어록 카드 스타일 */
|
||
.saying-card {
|
||
background: white;
|
||
border-radius: 12px;
|
||
padding: 20px;
|
||
margin-bottom: 16px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||
border-left: 4px solid #007bff;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.saying-card:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 16px rgba(0,0,0,0.15);
|
||
}
|
||
|
||
.saying-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.saying-title {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
color: #2c3e50;
|
||
margin: 0;
|
||
flex: 1;
|
||
}
|
||
|
||
.saying-meta {
|
||
display: flex;
|
||
gap: 8px;
|
||
flex-shrink: 0;
|
||
margin-left: 12px;
|
||
}
|
||
|
||
.saying-category, .saying-target {
|
||
background: #f8f9fa;
|
||
color: #495057;
|
||
padding: 4px 8px;
|
||
border-radius: 12px;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.saying-category {
|
||
background: #e3f2fd;
|
||
color: #1976d2;
|
||
}
|
||
|
||
.saying-target {
|
||
background: #f3e5f5;
|
||
color: #7b1fa2;
|
||
}
|
||
|
||
.saying-content {
|
||
margin: 12px 0;
|
||
line-height: 1.6;
|
||
color: #2c3e50;
|
||
}
|
||
|
||
.saying-content h1, .saying-content h2, .saying-content h3 {
|
||
margin-top: 16px;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.saying-content p {
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.saying-content blockquote {
|
||
border-left: 4px solid #007bff;
|
||
padding-left: 16px;
|
||
margin: 12px 0;
|
||
color: #6c757d;
|
||
font-style: italic;
|
||
}
|
||
|
||
.saying-content code {
|
||
background: #f8f9fa;
|
||
padding: 2px 4px;
|
||
border-radius: 4px;
|
||
font-family: 'Consolas', 'Monaco', monospace;
|
||
font-size: 0.9em;
|
||
}
|
||
|
||
.saying-content pre {
|
||
background: #f8f9fa;
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
overflow-x: auto;
|
||
margin: 12px 0;
|
||
}
|
||
|
||
.saying-footer {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-top: 12px;
|
||
padding-top: 12px;
|
||
border-top: 1px solid #e9ecef;
|
||
font-size: 14px;
|
||
color: #6c757d;
|
||
}
|
||
|
||
.saying-author {
|
||
font-weight: 500;
|
||
}
|
||
|
||
.saying-date {
|
||
color: #adb5bd;
|
||
}
|
||
|
||
/* 로딩 표시 */
|
||
.loading {
|
||
text-align: center;
|
||
padding: 40px;
|
||
font-size: 16px;
|
||
color: #3498db;
|
||
}
|
||
|
||
/* 빈 상태 */
|
||
.empty-state {
|
||
text-align: center;
|
||
padding: 60px 20px;
|
||
color: #666;
|
||
}
|
||
|
||
.empty-state .icon {
|
||
font-size: 48px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.empty-state .title {
|
||
font-size: 18px;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.empty-state .description {
|
||
font-size: 14px;
|
||
color: #999;
|
||
}
|
||
|
||
/* 모달 스타일 */
|
||
.modal {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: rgba(0,0,0,0.5);
|
||
display: none;
|
||
justify-content: center;
|
||
align-items: center;
|
||
z-index: 1000;
|
||
}
|
||
|
||
.modal-content {
|
||
background: white;
|
||
padding: 30px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
|
||
min-width: 500px;
|
||
max-width: 700px;
|
||
max-height: 90vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.modal-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20px;
|
||
padding-bottom: 15px;
|
||
border-bottom: 1px solid #eee;
|
||
}
|
||
|
||
.modal-title {
|
||
font-size: 20px;
|
||
font-weight: bold;
|
||
color: #2c3e50;
|
||
margin: 0;
|
||
}
|
||
|
||
.modal-close {
|
||
background: none;
|
||
border: none;
|
||
font-size: 24px;
|
||
cursor: pointer;
|
||
color: #999;
|
||
padding: 0;
|
||
width: 30px;
|
||
height: 30px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.modal-close:hover {
|
||
color: #333;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.form-label {
|
||
display: block;
|
||
margin-bottom: 8px;
|
||
font-weight: bold;
|
||
color: #555;
|
||
}
|
||
|
||
.form-input {
|
||
width: 100%;
|
||
padding: 10px 12px;
|
||
border: 2px solid #ddd;
|
||
border-radius: 4px;
|
||
font-size: 14px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.form-textarea {
|
||
width: 100%;
|
||
padding: 10px 12px;
|
||
border: 2px solid #ddd;
|
||
border-radius: 4px;
|
||
font-size: 14px;
|
||
box-sizing: border-box;
|
||
min-height: 120px;
|
||
resize: vertical;
|
||
font-family: inherit;
|
||
}
|
||
|
||
.form-select {
|
||
width: 100%;
|
||
padding: 10px 12px;
|
||
border: 2px solid #ddd;
|
||
border-radius: 4px;
|
||
font-size: 14px;
|
||
background: white;
|
||
}
|
||
|
||
.form-help {
|
||
font-size: 12px;
|
||
color: #666;
|
||
margin-top: 4px;
|
||
}
|
||
|
||
.markdown-preview {
|
||
border: 2px solid #ddd;
|
||
border-radius: 4px;
|
||
padding: 10px 12px;
|
||
min-height: 120px;
|
||
background: #f9f9f9;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
.preview-tabs {
|
||
display: flex;
|
||
gap: 10px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.preview-tab {
|
||
padding: 6px 12px;
|
||
border: 1px solid #ddd;
|
||
background: #f8f9fa;
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.preview-tab.active {
|
||
background: #007bff;
|
||
color: white;
|
||
border-color: #007bff;
|
||
}
|
||
|
||
.modal-buttons {
|
||
display: flex;
|
||
gap: 12px;
|
||
justify-content: flex-end;
|
||
margin-top: 30px;
|
||
padding-top: 20px;
|
||
border-top: 1px solid #eee;
|
||
}
|
||
|
||
.btn {
|
||
padding: 10px 20px;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.btn-primary {
|
||
background: #28a745;
|
||
color: white;
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
background: #218838;
|
||
}
|
||
|
||
.btn-secondary {
|
||
background: #6c757d;
|
||
color: white;
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background: #5a6268;
|
||
}
|
||
|
||
/* 디버그 정보 */
|
||
.debug-info {
|
||
margin-top: 20px;
|
||
padding: 10px;
|
||
background: #f8f9fa;
|
||
border: 1px solid #dee2e6;
|
||
border-radius: 4px;
|
||
font-size: 12px;
|
||
color: #6c757d;
|
||
}
|
||
|
||
.debug-info button {
|
||
margin-top: 10px;
|
||
padding: 5px 10px;
|
||
font-size: 12px;
|
||
background: #007acc;
|
||
color: white;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.debug-info button:hover {
|
||
background: #005a9e;
|
||
}
|
||
|
||
/* 반응형 디자인 */
|
||
@media (max-width: 768px) {
|
||
.sayings-container {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.filter-row {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
}
|
||
|
||
.filter-buttons {
|
||
justify-content: center;
|
||
}
|
||
|
||
.stats-info {
|
||
flex-direction: column;
|
||
gap: 15px;
|
||
text-align: center;
|
||
}
|
||
|
||
.modal-content {
|
||
min-width: 90%;
|
||
margin: 20px;
|
||
}
|
||
|
||
.saying-meta {
|
||
justify-content: center;
|
||
}
|
||
}
|
||
|
||
.header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 30px;
|
||
padding: 20px;
|
||
background: white;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.header h1 {
|
||
margin: 0;
|
||
color: #2c3e50;
|
||
font-size: 24px;
|
||
}
|
||
|
||
.header-right {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 15px;
|
||
}
|
||
|
||
.current-user {
|
||
padding: 8px 12px;
|
||
background: #e3f2fd;
|
||
border: 1px solid #2196f3;
|
||
border-radius: 20px;
|
||
font-size: 14px;
|
||
color: #1976d2;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* 새로운 블록 에디터 스타일 */
|
||
.content-blocks-editor {
|
||
border: 2px dashed #e0e0e0;
|
||
border-radius: 12px;
|
||
padding: 20px;
|
||
background: #fafafa;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.content-blocks-editor:hover {
|
||
border-color: #4CAF50;
|
||
background: #f8fff8;
|
||
}
|
||
|
||
.editor-toolbar {
|
||
display: flex;
|
||
gap: 10px;
|
||
margin-bottom: 15px;
|
||
padding-bottom: 15px;
|
||
border-bottom: 1px solid #e0e0e0;
|
||
}
|
||
|
||
.toolbar-btn {
|
||
background: linear-gradient(135deg, #4CAF50, #45a049);
|
||
color: white;
|
||
border: none;
|
||
padding: 8px 16px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.toolbar-btn:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3);
|
||
}
|
||
|
||
.content-blocks {
|
||
min-height: 100px;
|
||
}
|
||
|
||
.content-block {
|
||
background: white;
|
||
border: 1px solid #e0e0e0;
|
||
border-radius: 8px;
|
||
margin-bottom: 10px;
|
||
padding: 15px;
|
||
position: relative;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.content-block:hover {
|
||
border-color: #4CAF50;
|
||
box-shadow: 0 2px 8px rgba(76, 175, 80, 0.1);
|
||
}
|
||
|
||
.content-block.dragging {
|
||
opacity: 0.5;
|
||
transform: rotate(5deg);
|
||
}
|
||
|
||
.block-controls {
|
||
position: absolute;
|
||
top: -5px;
|
||
right: -5px;
|
||
display: flex;
|
||
gap: 5px;
|
||
opacity: 0;
|
||
transition: opacity 0.3s ease;
|
||
}
|
||
|
||
.content-block:hover .block-controls {
|
||
opacity: 1;
|
||
}
|
||
|
||
.block-control-btn {
|
||
width: 24px;
|
||
height: 24px;
|
||
border-radius: 50%;
|
||
border: none;
|
||
cursor: pointer;
|
||
font-size: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.block-control-btn.move {
|
||
background: #2196F3;
|
||
color: white;
|
||
}
|
||
|
||
.block-control-btn.delete {
|
||
background: #f44336;
|
||
color: white;
|
||
}
|
||
|
||
.block-control-btn:hover {
|
||
transform: scale(1.1);
|
||
}
|
||
|
||
.text-block textarea {
|
||
width: 100%;
|
||
min-height: 80px;
|
||
border: 1px solid #ddd;
|
||
border-radius: 6px;
|
||
padding: 10px;
|
||
font-family: inherit;
|
||
resize: vertical;
|
||
}
|
||
|
||
.image-block {
|
||
text-align: center;
|
||
}
|
||
|
||
.image-upload-area {
|
||
border: 2px dashed #ccc;
|
||
border-radius: 8px;
|
||
padding: 40px 20px;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
background: #f9f9f9;
|
||
}
|
||
|
||
.image-upload-area:hover {
|
||
border-color: #4CAF50;
|
||
background: #f0fff0;
|
||
}
|
||
|
||
.image-upload-area.dragover {
|
||
border-color: #4CAF50;
|
||
background: #e8f5e8;
|
||
transform: scale(1.02);
|
||
}
|
||
|
||
.uploaded-image {
|
||
max-width: 100%;
|
||
max-height: 200px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||
cursor: pointer;
|
||
transition: transform 0.3s ease;
|
||
}
|
||
|
||
.uploaded-image:hover {
|
||
transform: scale(1.05);
|
||
}
|
||
|
||
.image-info {
|
||
margin-top: 10px;
|
||
font-size: 12px;
|
||
color: #666;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.image-alt-input {
|
||
width: 100%;
|
||
padding: 8px;
|
||
border: 1px solid #ddd;
|
||
border-radius: 4px;
|
||
margin-top: 10px;
|
||
font-size: 14px;
|
||
}
|
||
|
||
/* 이미지 모달 */
|
||
.image-modal {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: rgba(0,0,0,0.9);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 10000;
|
||
opacity: 0;
|
||
visibility: hidden;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.image-modal.active {
|
||
opacity: 1;
|
||
visibility: visible;
|
||
}
|
||
|
||
.image-modal img {
|
||
max-width: 90%;
|
||
max-height: 90%;
|
||
border-radius: 8px;
|
||
box-shadow: 0 4px 20px rgba(0,0,0,0.5);
|
||
}
|
||
|
||
.image-modal-close {
|
||
position: absolute;
|
||
top: 20px;
|
||
right: 30px;
|
||
color: white;
|
||
font-size: 40px;
|
||
cursor: pointer;
|
||
z-index: 10001;
|
||
}
|
||
|
||
/* 드래그 앤 드롭 표시 */
|
||
.drop-indicator {
|
||
height: 3px;
|
||
background: #4CAF50;
|
||
border-radius: 2px;
|
||
margin: 5px 0;
|
||
opacity: 0;
|
||
transition: opacity 0.3s ease;
|
||
}
|
||
|
||
.drop-indicator.active {
|
||
opacity: 1;
|
||
}
|
||
|
||
/* 반응형 */
|
||
@media (max-width: 768px) {
|
||
.editor-toolbar {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.toolbar-btn {
|
||
justify-content: center;
|
||
}
|
||
|
||
.image-info {
|
||
flex-direction: column;
|
||
gap: 5px;
|
||
}
|
||
}
|
||
|
||
/* 상세 보기 모달 스타일 */
|
||
.view-field {
|
||
padding: 12px;
|
||
background: #f8f9fa;
|
||
border: 1px solid #e9ecef;
|
||
border-radius: 6px;
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
color: #2c3e50;
|
||
}
|
||
|
||
.view-content {
|
||
padding: 15px;
|
||
background: #f8f9fa;
|
||
border: 1px solid #e9ecef;
|
||
border-radius: 6px;
|
||
min-height: 100px;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.view-content .content-text-block {
|
||
margin-bottom: 15px;
|
||
padding: 10px;
|
||
background: white;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.view-content .content-image-block {
|
||
margin: 15px 0;
|
||
text-align: center;
|
||
}
|
||
|
||
.view-content .content-image {
|
||
max-width: 100%;
|
||
height: auto;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||
cursor: pointer;
|
||
transition: transform 0.3s ease;
|
||
}
|
||
|
||
.view-content .content-image:hover {
|
||
transform: scale(1.02);
|
||
}
|
||
|
||
.view-content .image-caption {
|
||
font-size: 12px;
|
||
color: #666;
|
||
margin-top: 8px;
|
||
font-style: italic;
|
||
}
|
||
|
||
.view-meta {
|
||
display: flex;
|
||
gap: 10px;
|
||
align-items: center;
|
||
}
|
||
|
||
.view-meta .meta-badge {
|
||
padding: 6px 12px;
|
||
border-radius: 20px;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.view-meta .category-badge {
|
||
background: #e3f2fd;
|
||
color: #1976d2;
|
||
border: 1px solid #bbdefb;
|
||
}
|
||
|
||
.view-meta .target-badge {
|
||
background: #f3e5f5;
|
||
color: #7b1fa2;
|
||
border: 1px solid #e1bee7;
|
||
}
|
||
|
||
.view-author-info {
|
||
padding: 12px;
|
||
background: #f8f9fa;
|
||
border: 1px solid #e9ecef;
|
||
border-radius: 6px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.author-details {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
}
|
||
|
||
.author-avatar {
|
||
width: 32px;
|
||
height: 32px;
|
||
background: #007bff;
|
||
color: white;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-weight: bold;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.author-name {
|
||
font-weight: 500;
|
||
color: #2c3e50;
|
||
}
|
||
|
||
.creation-date {
|
||
color: #6c757d;
|
||
font-size: 14px;
|
||
}
|
||
|
||
/* 어록 카드 클릭 효과 */
|
||
.saying-card {
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.saying-card:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 16px rgba(0,0,0,0.15);
|
||
border-left-color: #28a745;
|
||
}
|
||
|
||
.saying-card:active {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
/* 삭제 버튼 스타일 */
|
||
.btn-danger {
|
||
background: #dc3545;
|
||
color: white;
|
||
}
|
||
|
||
.btn-danger:hover {
|
||
background: #c82333;
|
||
}
|
||
|
||
/* 편집 모드 전환 애니메이션 */
|
||
#view-mode, #edit-mode {
|
||
transition: opacity 0.3s ease;
|
||
}
|
||
|
||
/* 모달 버튼 그룹 */
|
||
.modal-buttons {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.modal-buttons .btn {
|
||
min-width: 100px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="header">
|
||
<h1>📚 타냐대장경 관리</h1>
|
||
<div class="header-right">
|
||
<div id="current-user" class="current-user">👤 로딩 중...</div>
|
||
<button id="add-saying-btn" class="add-saying-btn">✨ 타냐대장경 등록</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 디버그 정보 -->
|
||
<div class="debug-info" id="debug-info" style="display: block;">
|
||
초기화 중...
|
||
<br>
|
||
<button id="log-check-btn" style="margin-top: 10px; padding: 5px 10px; font-size: 12px;">📋 로그 확인</button>
|
||
</div>
|
||
|
||
<!-- 필터 섹션 -->
|
||
<div class="filter-section">
|
||
<div class="filter-row">
|
||
<div class="filter-group">
|
||
<label for="category-filter">카테고리</label>
|
||
<select id="category-filter" class="filter-select">
|
||
<option value="all">모든 카테고리</option>
|
||
<!-- 동적으로 추가됨 -->
|
||
</select>
|
||
</div>
|
||
|
||
<div class="filter-group">
|
||
<label for="target-filter">타겟</label>
|
||
<select id="target-filter" class="filter-select">
|
||
<option value="all">모든 타겟</option>
|
||
<!-- 동적으로 추가됨 -->
|
||
</select>
|
||
</div>
|
||
|
||
<div class="filter-group">
|
||
<label for="date-filter">기간</label>
|
||
<select id="date-filter" class="filter-select">
|
||
<option value="all">전체 기간</option>
|
||
<option value="today">오늘</option>
|
||
<option value="week">최근 1주일</option>
|
||
<option value="month">최근 1개월</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="filter-group">
|
||
<label for="search-input">검색</label>
|
||
<input type="text" id="search-input" placeholder="타냐대장경 검색..." class="search-input">
|
||
</div>
|
||
|
||
<div class="filter-buttons">
|
||
<button class="filter-btn primary" id="apply-filter">🔍 필터 적용</button>
|
||
<button class="filter-btn secondary" id="reset-filters">🔄 초기화</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 통계 정보 -->
|
||
<div id="sayings-stats" class="stats-info">
|
||
<div>
|
||
<!-- 통계 정보가 여기에 표시됩니다 -->
|
||
</div>
|
||
<button class="add-saying-btn" id="add-saying-btn">
|
||
➕ 타냐대장경 등록
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 어록 등록 모달 -->
|
||
<div id="add-saying-modal" class="modal">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h3 class="modal-title">➕ 새 타냐대장경 등록</h3>
|
||
<button class="modal-close" id="modal-close">×</button>
|
||
</div>
|
||
|
||
<form id="saying-form">
|
||
<div class="form-group">
|
||
<label class="form-label" for="saying-title">타냐대장경 제목</label>
|
||
<input type="text" id="saying-title" class="form-input" placeholder="타냐대장경의 제목을 입력하세요" required>
|
||
<div class="form-help">타냐대장경을 대표하는 제목을 입력해주세요.</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="saying-content">타냐대장경 내용</label>
|
||
<div class="preview-tabs">
|
||
<div class="preview-tab active" data-tab="edit">✏️ 편집</div>
|
||
<div class="preview-tab" data-tab="preview">👁️ 미리보기</div>
|
||
</div>
|
||
|
||
<!-- 새로운 블록 기반 에디터 -->
|
||
<div id="content-blocks-editor" class="content-blocks-editor">
|
||
<div class="editor-toolbar">
|
||
<button type="button" class="toolbar-btn" id="add-text-block">📝 텍스트 추가</button>
|
||
<button type="button" class="toolbar-btn" id="add-image-block">🖼️ 이미지 추가</button>
|
||
</div>
|
||
<div id="content-blocks" class="content-blocks">
|
||
<!-- 블록들이 동적으로 추가됩니다 -->
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 기존 텍스트 에리어 (하위 호환성) -->
|
||
<textarea id="saying-content" class="form-textarea" placeholder="어록 내용을 입력하세요 (마크다운 지원)" style="display: none;"></textarea>
|
||
|
||
<div id="markdown-preview" class="markdown-preview" style="display: none;"></div>
|
||
<div class="form-help">
|
||
💡 텍스트와 이미지를 자유롭게 조합할 수 있습니다.
|
||
이미지는 자동으로 압축되어 저장됩니다. (최대 2MB)
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="saying-category">카테고리</label>
|
||
<select id="saying-category" class="form-select" required>
|
||
<option value="">카테고리를 선택하세요</option>
|
||
<!-- 동적으로 로드됩니다 -->
|
||
</select>
|
||
<div class="form-help">타냐대장경의 성격에 맞는 카테고리를 선택해주세요.</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="saying-target">타겟</label>
|
||
<select id="saying-target" class="form-select" required>
|
||
<option value="">타겟을 선택하세요</option>
|
||
<!-- 동적으로 로드됩니다 -->
|
||
</select>
|
||
<div class="form-help">타냐대장경의 대상을 선택해주세요. (기본값: 누구나)</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">등록자</label>
|
||
<div id="modal-current-user" style="padding: 10px; background: #f8f9fa; border-radius: 4px; color: #666;">
|
||
로그인된 사용자 정보를 가져오는 중...
|
||
</div>
|
||
<div class="form-help">현재 로그인한 사용자 이름이 자동으로 등록됩니다.</div>
|
||
</div>
|
||
</form>
|
||
|
||
<div class="modal-buttons">
|
||
<button type="button" class="btn btn-secondary" id="cancel-btn">취소</button>
|
||
<button type="submit" class="btn btn-primary" id="submit-btn">📝 등록하기</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 어록 상세 보기/편집 모달 -->
|
||
<div id="view-saying-modal" class="modal">
|
||
<div class="modal-content" style="max-width: 800px;">
|
||
<div class="modal-header">
|
||
<h3 class="modal-title" id="view-modal-title">📖 타냐대장경 상세 보기</h3>
|
||
<button class="modal-close" id="view-modal-close">×</button>
|
||
</div>
|
||
|
||
<!-- 보기 모드 -->
|
||
<div id="view-mode" style="display: none;">
|
||
<div class="form-group">
|
||
<label class="form-label">제목</label>
|
||
<div id="view-title" class="view-field"></div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">내용</label>
|
||
<div id="view-content" class="view-content"></div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">카테고리 / 타겟</label>
|
||
<div id="view-meta" class="view-meta"></div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">등록 정보</label>
|
||
<div id="view-author-info" class="view-author-info"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 편집 모드 -->
|
||
<div id="edit-mode" style="display: none;">
|
||
<form id="edit-saying-form">
|
||
<div class="form-group">
|
||
<label class="form-label" for="edit-saying-title">타냐대장경 제목</label>
|
||
<input type="text" id="edit-saying-title" class="form-input" placeholder="타냐대장경의 제목을 입력하세요" required>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="edit-saying-content">타냐대장경 내용</label>
|
||
<div class="preview-tabs">
|
||
<div class="preview-tab active" data-tab="edit">✏️ 편집</div>
|
||
<div class="preview-tab" data-tab="preview">👁️ 미리보기</div>
|
||
</div>
|
||
|
||
<!-- 편집용 블록 에디터 -->
|
||
<div id="edit-content-blocks-editor" class="content-blocks-editor">
|
||
<div class="editor-toolbar">
|
||
<button type="button" class="toolbar-btn" id="edit-add-text-block">📝 텍스트 추가</button>
|
||
<button type="button" class="toolbar-btn" id="edit-add-image-block">🖼️ 이미지 추가</button>
|
||
</div>
|
||
<div id="edit-content-blocks" class="content-blocks">
|
||
<!-- 블록들이 동적으로 추가됩니다 -->
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 기존 텍스트 에리어 (하위 호환성) -->
|
||
<textarea id="edit-saying-content" class="form-textarea" placeholder="타냐대장경 내용을 입력하세요" style="display: none;"></textarea>
|
||
|
||
<div id="edit-markdown-preview" class="markdown-preview" style="display: none;"></div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="edit-saying-category">카테고리</label>
|
||
<select id="edit-saying-category" class="form-select" required>
|
||
<option value="">카테고리를 선택하세요</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="edit-saying-target">타겟</label>
|
||
<select id="edit-saying-target" class="form-select" required>
|
||
<option value="">타겟을 선택하세요</option>
|
||
</select>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="modal-buttons">
|
||
<!-- 보기 모드 버튼 -->
|
||
<div id="view-mode-buttons" style="display: none;">
|
||
<button type="button" class="btn btn-secondary" id="view-close-btn">닫기</button>
|
||
<button type="button" class="btn btn-primary" id="edit-mode-btn" style="display: none;">✏️ 편집하기</button>
|
||
</div>
|
||
|
||
<!-- 편집 모드 버튼 -->
|
||
<div id="edit-mode-buttons" style="display: none;">
|
||
<button type="button" class="btn btn-secondary" id="edit-cancel-btn">취소</button>
|
||
<button type="button" class="btn btn-danger" id="delete-saying-btn" style="margin-right: auto;">🗑️ 삭제</button>
|
||
<button type="submit" class="btn btn-primary" id="update-saying-btn">💾 수정 완료</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 어록 컨테이너 -->
|
||
<div id="sayings-container" class="sayings-container">
|
||
<!-- 동적으로 생성됨 -->
|
||
</div>
|
||
|
||
<div class="loading" id="sayings-loading" style="display: none;">
|
||
🔄 타냐대장경을 불러오는 중...
|
||
</div>
|
||
|
||
<!-- 마크다운 라이브러리는 sayings.js 내장 함수 사용 (CSP 호환) -->
|
||
<script src="sayings.js"></script>
|
||
</body>
|
||
</html> |