SearchTrademark/sayings.html

688 lines
16 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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;
}
</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">&times;</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>
<textarea id="saying-content" class="form-textarea" placeholder="어록 내용을 입력하세요 (마크다운 지원)" required></textarea>
<div id="markdown-preview" class="markdown-preview" style="display: none;"></div>
<div class="form-help">
💡 마크다운 문법을 사용할 수 있습니다.
<strong>**굵게**</strong>, <em>*기울임*</em>,
<code>`코드`</code>, 링크 등을 지원합니다.
</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="sayings-container" class="sayings-container">
<!-- 동적으로 생성됨 -->
</div>
<div class="loading" id="sayings-loading" style="display: none;">
🔄 어록을 불러오는 중...
</div>
<!-- 마크다운 라이브러리를 직접 로드 -->
<script src="https://cdn.jsdelivr.net/npm/marked@9.1.6/marked.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.8/dist/purify.min.js"></script>
<script src="sayings.js"></script>
</body>
</html>