feat: 5장 사진 지원 및 엑셀 내보내기 UI 개선
- 신고 및 완료 사진 5장 지원 (photo_path3, photo_path4, photo_path5 추가) - 엑셀 일일 리포트 개선: - 사진 5장 모두 한 행에 일렬 배치 (A, C, E, G, I 열) - 상태별 색상 구분 (지연중: 빨강, 진행중: 노랑, 완료: 진한 초록) - 우선순위 기반 정렬 (지연중 → 진행중 → 완료됨) - 프로젝트 현황 통계 박스 UI 개선 (색상 구분) - 프론트엔드 모든 페이지 5장 사진 표시 (flex-wrap 레이아웃) - 관리함, 수신함, 현황판, 신고내용 확인 페이지 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -271,17 +271,17 @@
|
||||
</div>
|
||||
|
||||
<form id="reportForm" class="space-y-4">
|
||||
<!-- 사진 업로드 (선택사항, 최대 2장) -->
|
||||
<!-- 사진 업로드 (선택사항, 최대 5장) -->
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="text-sm font-medium text-gray-700">
|
||||
📸 사진 첨부
|
||||
</label>
|
||||
<span class="text-xs text-gray-500 bg-gray-100 px-2 py-1 rounded-full">
|
||||
선택사항 • 최대 2장
|
||||
선택사항 • 최대 5장
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 사진 미리보기 영역 -->
|
||||
<div id="photoPreviewContainer" class="grid grid-cols-2 gap-2 mb-3" style="display: none;">
|
||||
<!-- 첫 번째 사진 -->
|
||||
@@ -298,6 +298,27 @@
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- 세 번째 사진 -->
|
||||
<div id="photo3Container" class="relative hidden">
|
||||
<img id="previewImg3" class="w-full h-24 object-cover rounded-xl border-2 border-gray-200">
|
||||
<button type="button" onclick="removePhoto(2)" class="absolute -top-1 -right-1 w-6 h-6 bg-red-500 text-white rounded-full text-xs hover:bg-red-600 flex items-center justify-center shadow-lg">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- 네 번째 사진 -->
|
||||
<div id="photo4Container" class="relative hidden">
|
||||
<img id="previewImg4" class="w-full h-24 object-cover rounded-xl border-2 border-gray-200">
|
||||
<button type="button" onclick="removePhoto(3)" class="absolute -top-1 -right-1 w-6 h-6 bg-red-500 text-white rounded-full text-xs hover:bg-red-600 flex items-center justify-center shadow-lg">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- 다섯 번째 사진 -->
|
||||
<div id="photo5Container" class="relative hidden">
|
||||
<img id="previewImg5" class="w-full h-24 object-cover rounded-xl border-2 border-gray-200">
|
||||
<button type="button" onclick="removePhoto(4)" class="absolute -top-1 -right-1 w-6 h-6 bg-red-500 text-white rounded-full text-xs hover:bg-red-600 flex items-center justify-center shadow-lg">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 업로드 버튼들 -->
|
||||
@@ -329,7 +350,7 @@
|
||||
|
||||
<!-- 현재 상태 표시 -->
|
||||
<div class="text-center mt-2">
|
||||
<p class="text-sm text-gray-500" id="photoUploadText">사진 추가 (0/2)</p>
|
||||
<p class="text-sm text-gray-500" id="photoUploadText">사진 추가 (0/5)</p>
|
||||
</div>
|
||||
|
||||
<!-- 숨겨진 입력 필드들 -->
|
||||
@@ -880,23 +901,23 @@
|
||||
// 사진 업로드 처리 함수
|
||||
async function handlePhotoUpload(files) {
|
||||
const filesArray = Array.from(files);
|
||||
|
||||
|
||||
// 현재 사진 개수 확인
|
||||
if (currentPhotos.length >= 2) {
|
||||
alert('최대 2장까지 업로드 가능합니다.');
|
||||
if (currentPhotos.length >= 5) {
|
||||
alert('최대 5장까지 업로드 가능합니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 추가 가능한 개수만큼만 처리
|
||||
const availableSlots = 2 - currentPhotos.length;
|
||||
const availableSlots = 5 - currentPhotos.length;
|
||||
const filesToProcess = filesArray.slice(0, availableSlots);
|
||||
|
||||
|
||||
// 로딩 표시
|
||||
showUploadProgress(true);
|
||||
|
||||
|
||||
try {
|
||||
for (const file of filesToProcess) {
|
||||
if (currentPhotos.length >= 2) break;
|
||||
if (currentPhotos.length >= 5) break;
|
||||
|
||||
// 원본 파일 크기 확인
|
||||
const originalSize = file.size;
|
||||
@@ -923,18 +944,18 @@
|
||||
const cameraBtn = document.getElementById('cameraUpload');
|
||||
const galleryBtn = document.getElementById('galleryUpload');
|
||||
const uploadText = document.getElementById('photoUploadText');
|
||||
|
||||
|
||||
if (show) {
|
||||
cameraBtn.classList.add('opacity-50', 'cursor-not-allowed');
|
||||
galleryBtn.classList.add('opacity-50', 'cursor-not-allowed');
|
||||
uploadText.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>이미지 처리 중...';
|
||||
uploadText.classList.add('text-blue-600');
|
||||
} else {
|
||||
if (currentPhotos.length < 2) {
|
||||
if (currentPhotos.length < 5) {
|
||||
cameraBtn.classList.remove('opacity-50', 'cursor-not-allowed');
|
||||
galleryBtn.classList.remove('opacity-50', 'cursor-not-allowed');
|
||||
}
|
||||
uploadText.textContent = `사진 추가 (${currentPhotos.length}/2)`;
|
||||
uploadText.textContent = `사진 추가 (${currentPhotos.length}/5)`;
|
||||
uploadText.classList.remove('text-blue-600');
|
||||
}
|
||||
}
|
||||
@@ -964,43 +985,37 @@
|
||||
// 사진 미리보기 업데이트
|
||||
function updatePhotoPreview() {
|
||||
const container = document.getElementById('photoPreviewContainer');
|
||||
const photo1Container = document.getElementById('photo1Container');
|
||||
const photo2Container = document.getElementById('photo2Container');
|
||||
const uploadText = document.getElementById('photoUploadText');
|
||||
const cameraUpload = document.getElementById('cameraUpload');
|
||||
const galleryUpload = document.getElementById('galleryUpload');
|
||||
|
||||
|
||||
// 텍스트 업데이트
|
||||
uploadText.textContent = `사진 추가 (${currentPhotos.length}/2)`;
|
||||
|
||||
// 첫 번째 사진
|
||||
if (currentPhotos[0]) {
|
||||
document.getElementById('previewImg1').src = currentPhotos[0];
|
||||
photo1Container.classList.remove('hidden');
|
||||
container.style.display = 'grid';
|
||||
} else {
|
||||
photo1Container.classList.add('hidden');
|
||||
uploadText.textContent = `사진 추가 (${currentPhotos.length}/5)`;
|
||||
|
||||
// 모든 사진 미리보기 업데이트 (최대 5장)
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const photoContainer = document.getElementById(`photo${i + 1}Container`);
|
||||
const previewImg = document.getElementById(`previewImg${i + 1}`);
|
||||
|
||||
if (currentPhotos[i]) {
|
||||
previewImg.src = currentPhotos[i];
|
||||
photoContainer.classList.remove('hidden');
|
||||
container.style.display = 'grid';
|
||||
} else {
|
||||
photoContainer.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// 두 번째 사진
|
||||
if (currentPhotos[1]) {
|
||||
document.getElementById('previewImg2').src = currentPhotos[1];
|
||||
photo2Container.classList.remove('hidden');
|
||||
container.style.display = 'grid';
|
||||
} else {
|
||||
photo2Container.classList.add('hidden');
|
||||
}
|
||||
|
||||
|
||||
// 미리보기 컨테이너 표시/숨김
|
||||
if (currentPhotos.length === 0) {
|
||||
container.style.display = 'none';
|
||||
}
|
||||
|
||||
// 2장이 모두 업로드되면 업로드 버튼 스타일 변경
|
||||
if (currentPhotos.length >= 2) {
|
||||
|
||||
// 5장이 모두 업로드되면 업로드 버튼 스타일 변경
|
||||
if (currentPhotos.length >= 5) {
|
||||
cameraUpload.classList.add('opacity-50', 'cursor-not-allowed');
|
||||
galleryUpload.classList.add('opacity-50', 'cursor-not-allowed');
|
||||
uploadText.textContent = '최대 2장 업로드 완료';
|
||||
uploadText.textContent = '최대 5장 업로드 완료';
|
||||
uploadText.classList.add('text-green-600', 'font-medium');
|
||||
} else {
|
||||
cameraUpload.classList.remove('opacity-50', 'cursor-not-allowed');
|
||||
|
||||
Reference in New Issue
Block a user