feat: 수신함에 사진 미리보기 및 확대 기능 추가 + 대시보드 3개 카드로 간소화
🖼️ Photo Preview & Modal Features: - 수신함 카드에 사진 썸네일 표시 (150x100px) - photo_path, photo_path2 모두 지원 (최대 2장) - 클릭 시 전체화면 모달로 원본 사진 확대 - 호버 효과: 1.05배 확대 애니메이션 🔍 Enhanced Photo Viewing: - 어두운 배경 (80% 투명도) 모달 - 원본 사진을 90% 크기로 표시 - ESC 키 또는 배경 클릭으로 모달 닫기 - 우상단 X 버튼으로 닫기 📊 Dashboard Simplification: - 4개 카드 → 3개 카드로 간소화 - '전체' 카드 제거, 핵심 지표만 유지 - 금일 신규, 금일 처리, 미해결만 표시 - grid-cols-4 → grid-cols-3 레이아웃 변경 🎨 Visual Improvements: - 사진 갤러리 레이아웃 (flex, gap: 8px) - 반응형 사진 표시 (object-fit: cover) - 부드러운 트랜지션 효과 - 모바일 친화적 사진 크기 🔧 Code Enhancements: - openPhotoModal(), closePhotoModal() 함수 - handleEscKey() 키보드 이벤트 처리 - 사진 경로 검증 및 오류 처리 - 통계 함수에서 totalCount 관련 코드 정리 🚀 User Experience: - 직관적인 사진 확인 방식 - 빠른 사진 미리보기 - 키보드 단축키 지원 (ESC) - 터치 친화적 인터페이스 Expected Result: ✨ 수신함에서 바로 사진 확인 가능 ✨ 클릭 한 번으로 사진 확대 보기 ✨ 간소화된 3개 핵심 통계 카드 ✨ 향상된 시각적 정보 제공
This commit is contained in:
@@ -111,6 +111,60 @@
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 사진 미리보기 스타일 */
|
||||||
|
.photo-preview {
|
||||||
|
max-width: 150px;
|
||||||
|
max-height: 100px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-preview:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-gallery {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-modal img {
|
||||||
|
max-width: 90%;
|
||||||
|
max-height: 90%;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-modal .close-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-gray-50 min-h-screen">
|
<body class="bg-gray-50 min-h-screen">
|
||||||
@@ -145,16 +199,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 통계 카드 -->
|
<!-- 통계 카드 -->
|
||||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
<div class="bg-blue-50 p-4 rounded-lg">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<i class="fas fa-list text-blue-500 text-xl mr-3"></i>
|
|
||||||
<div>
|
|
||||||
<p class="text-sm text-blue-600">전체</p>
|
|
||||||
<p class="text-2xl font-bold text-blue-700" id="totalCount">0</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bg-yellow-50 p-4 rounded-lg">
|
<div class="bg-yellow-50 p-4 rounded-lg">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<i class="fas fa-plus-circle text-yellow-500 text-xl mr-3"></i>
|
<i class="fas fa-plus-circle text-yellow-500 text-xl mr-3"></i>
|
||||||
@@ -228,6 +273,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<!-- 사진 확대 모달 -->
|
||||||
|
<div id="photoModal" class="photo-modal hidden" onclick="closePhotoModal()">
|
||||||
|
<button class="close-btn" onclick="closePhotoModal()">×</button>
|
||||||
|
<img id="modalPhoto" src="" alt="확대된 사진">
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 폐기 모달 -->
|
<!-- 폐기 모달 -->
|
||||||
<div id="disposeModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50">
|
<div id="disposeModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50">
|
||||||
<div class="flex items-center justify-center min-h-screen p-4">
|
<div class="flex items-center justify-center min-h-screen p-4">
|
||||||
@@ -729,6 +780,14 @@
|
|||||||
</div>` : ''}
|
</div>` : ''}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 사진 미리보기 -->
|
||||||
|
${photoCount > 0 ? `
|
||||||
|
<div class="photo-gallery">
|
||||||
|
${issue.photo_path ? `<img src="${issue.photo_path}" class="photo-preview" onclick="openPhotoModal('${issue.photo_path}')" alt="첨부 사진 1">` : ''}
|
||||||
|
${issue.photo_path2 ? `<img src="${issue.photo_path2}" class="photo-preview" onclick="openPhotoModal('${issue.photo_path2}')" alt="첨부 사진 2">` : ''}
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
|
||||||
<!-- 워크플로우 액션 버튼들 -->
|
<!-- 워크플로우 액션 버튼들 -->
|
||||||
<div class="flex items-center space-x-2 mt-3">
|
<div class="flex items-center space-x-2 mt-3">
|
||||||
<button onclick="openDisposeModal(${issue.id})"
|
<button onclick="openDisposeModal(${issue.id})"
|
||||||
@@ -759,9 +818,6 @@
|
|||||||
const todayStart = getKSTToday();
|
const todayStart = getKSTToday();
|
||||||
console.log('📅 KST 기준 오늘 시작:', todayStart);
|
console.log('📅 KST 기준 오늘 시작:', todayStart);
|
||||||
|
|
||||||
// 전체: 수신함에 남아있는 목록 개수 (pending_review 상태)
|
|
||||||
const totalCount = issues.length;
|
|
||||||
|
|
||||||
// 금일 신규: 오늘 올라온 목록 숫자 (확인된 것 포함) - KST 기준
|
// 금일 신규: 오늘 올라온 목록 숫자 (확인된 것 포함) - KST 기준
|
||||||
const todayNewCount = issues.filter(issue => {
|
const todayNewCount = issues.filter(issue => {
|
||||||
const reportDate = getKSTDate(new Date(issue.report_date));
|
const reportDate = getKSTDate(new Date(issue.report_date));
|
||||||
@@ -794,13 +850,11 @@
|
|||||||
}).length;
|
}).length;
|
||||||
|
|
||||||
// 통계 업데이트
|
// 통계 업데이트
|
||||||
document.getElementById('totalCount').textContent = totalCount;
|
|
||||||
document.getElementById('todayNewCount').textContent = todayNewCount;
|
document.getElementById('todayNewCount').textContent = todayNewCount;
|
||||||
document.getElementById('todayProcessedCount').textContent = todayProcessedCount;
|
document.getElementById('todayProcessedCount').textContent = todayProcessedCount;
|
||||||
document.getElementById('unresolvedCount').textContent = unresolvedCount;
|
document.getElementById('unresolvedCount').textContent = unresolvedCount;
|
||||||
|
|
||||||
console.log('📊 통계 업데이트 (KST 기준):', {
|
console.log('📊 통계 업데이트 (KST 기준):', {
|
||||||
전체: totalCount,
|
|
||||||
금일신규: todayNewCount,
|
금일신규: todayNewCount,
|
||||||
금일처리: todayProcessedCount,
|
금일처리: todayProcessedCount,
|
||||||
미해결: unresolvedCount,
|
미해결: unresolvedCount,
|
||||||
@@ -810,7 +864,6 @@
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('통계 로드 오류:', error);
|
console.error('통계 로드 오류:', error);
|
||||||
// 오류 시 기본값 설정
|
// 오류 시 기본값 설정
|
||||||
document.getElementById('totalCount').textContent = '0';
|
|
||||||
document.getElementById('todayNewCount').textContent = '0';
|
document.getElementById('todayNewCount').textContent = '0';
|
||||||
document.getElementById('todayProcessedCount').textContent = '0';
|
document.getElementById('todayProcessedCount').textContent = '0';
|
||||||
document.getElementById('unresolvedCount').textContent = '0';
|
document.getElementById('unresolvedCount').textContent = '0';
|
||||||
@@ -828,6 +881,32 @@
|
|||||||
window.location.href = `/issue-view.html#detail-${issueId}`;
|
window.location.href = `/issue-view.html#detail-${issueId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 사진 모달 관련 함수들
|
||||||
|
function openPhotoModal(photoPath) {
|
||||||
|
const modal = document.getElementById('photoModal');
|
||||||
|
const modalPhoto = document.getElementById('modalPhoto');
|
||||||
|
|
||||||
|
modalPhoto.src = photoPath;
|
||||||
|
modal.classList.remove('hidden');
|
||||||
|
|
||||||
|
// ESC 키로 모달 닫기
|
||||||
|
document.addEventListener('keydown', handleEscKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closePhotoModal() {
|
||||||
|
const modal = document.getElementById('photoModal');
|
||||||
|
modal.classList.add('hidden');
|
||||||
|
|
||||||
|
// ESC 키 이벤트 제거
|
||||||
|
document.removeEventListener('keydown', handleEscKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEscKey(event) {
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
closePhotoModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ===== 워크플로우 모달 관련 함수들 =====
|
// ===== 워크플로우 모달 관련 함수들 =====
|
||||||
let currentIssueId = null;
|
let currentIssueId = null;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user