diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ff232dc..60f1d6e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -3,11 +3,10 @@ name: Deploy to Netlify on: push: branches: - - main - - feat/kakao-map + - release pull_request: branches: - - main + - release jobs: build-and-deploy: @@ -35,7 +34,7 @@ jobs: uses: nwtgck/actions-netlify@v3.0 with: publish-dir: './dist' - production-branch: main + production-branch: release github-token: ${{ secrets.GITHUB_TOKEN }} deploy-message: 'Deploy from GitHub Actions' enable-pull-request-comment: true diff --git a/src/components/badge/BadgeForm.jsx b/src/components/badge/BadgeForm.jsx index fc57947..d18c72e 100644 --- a/src/components/badge/BadgeForm.jsx +++ b/src/components/badge/BadgeForm.jsx @@ -2,6 +2,7 @@ import React, { useState, useRef } from 'react'; import { registerBadge } from '../../api/badgeApi'; import { uploadImageToFirebase } from '../../util/imageUpload'; import { Upload, X } from 'lucide-react'; +import MessageModal from '../common/MessageModal'; // 뱃지 카테고리 키워드 (챌린지와 동일) const VALID_CATEGORIES = [ @@ -15,7 +16,6 @@ const VALID_CATEGORIES = [ const BadgeForm = () => { const [isLoading, setIsLoading] = useState(false); const [isUploading, setIsUploading] = useState(false); - const [error, setError] = useState(''); const [name, setName] = useState(''); const [description, setDescription] = useState(''); const [icon, setIcon] = useState(''); @@ -24,6 +24,9 @@ const BadgeForm = () => { const [previewImage, setPreviewImage] = useState(''); const [selectedFile, setSelectedFile] = useState(null); const fileInputRef = useRef(null); + const [modalMessage, setModalMessage] = useState(''); + const [modalType, setModalType] = useState('error'); + const [showModal, setShowModal] = useState(false); // 파일 선택 핸들러 const handleFileSelect = (e) => { @@ -32,18 +35,21 @@ const BadgeForm = () => { // 파일 크기 검증 (5MB) if (file.size > 5 * 1024 * 1024) { - setError('이미지 파일은 5MB 이하여야 합니다.'); + setModalMessage('이미지 파일은 5MB 이하여야 합니다.'); + setModalType('error'); + setShowModal(true); return; } // 파일 타입 검증 if (!file.type.startsWith('image/')) { - setError('이미지 파일만 업로드 가능합니다.'); + setModalMessage('이미지 파일만 업로드 가능합니다.'); + setModalType('error'); + setShowModal(true); return; } setSelectedFile(file); - setError(''); // 미리보기 생성 const reader = new FileReader(); @@ -56,12 +62,13 @@ const BadgeForm = () => { // 이미지 업로드 핸들러 const handleImageUpload = async () => { if (!selectedFile) { - setError('이미지 파일을 선택해주세요.'); + setModalMessage('이미지 파일을 선택해주세요.'); + setModalType('error'); + setShowModal(true); return; } setIsUploading(true); - setError(''); try { // Firebase Storage에 업로드하고 URL 받기 @@ -73,10 +80,16 @@ const BadgeForm = () => { // 받은 URL을 icon state에 저장 (이 URL이 서버로 전달됨!) setIcon(imageUrl); - alert('✅ 이미지가 성공적으로 업로드되었습니다!'); + setModalMessage('이미지가 성공적으로 업로드되었습니다!'); + setModalType('success'); + setShowModal(true); } catch (err) { console.error('이미지 업로드 실패', err); - setError('❌ 이미지 업로드 중 오류가 발생했습니다: ' + err.message); + setModalMessage( + '이미지 업로드 중 오류가 발생했습니다: ' + err.message + ); + setModalType('error'); + setShowModal(true); setSelectedFile(null); setPreviewImage(''); if (fileInputRef.current) { @@ -99,11 +112,12 @@ const BadgeForm = () => { const handleSubmit = async (e) => { e.preventDefault(); - setError(''); // 필수 필드 검사 if (!name || !icon || !category || !requirement) { - setError('비어있는 칸이 있습니다. 칸을 모두 채워주세요.'); + setModalMessage('비어있는 칸이 있습니다. 칸을 모두 채워주세요.'); + setModalType('error'); + setShowModal(true); return; } @@ -111,7 +125,9 @@ const BadgeForm = () => { const requirementNum = parseInt(requirement, 10); if (isNaN(requirementNum) || requirementNum <= 0) { - setError('요구 포인트는 양수여야 합니다.'); + setModalMessage('획득 기준은 양수여야 합니다.'); + setModalType('error'); + setShowModal(true); return; } @@ -128,7 +144,9 @@ const BadgeForm = () => { const res = await registerBadge(badgeData); console.log('뱃지 추가 응답:', res); - alert('✅ 뱃지가 성공적으로 등록되었습니다!'); + setModalMessage('뱃지가 성공적으로 등록되었습니다!'); + setModalType('success'); + setShowModal(true); // 폼 초기화 setName(''); setDescription(''); @@ -143,272 +161,280 @@ const BadgeForm = () => { } catch (err) { console.error('뱃지 추가 실패', err.response || err); + let errorMessage = '뱃지 추가 중 오류가 발생했습니다.'; if (err.response?.status === 401) { - setError('❌ 인증이 필요합니다. 다시 로그인해주세요.'); + errorMessage = '인증이 필요합니다. 다시 로그인해주세요.'; } else if (err.response?.status === 400) { - setError('❌ 입력 형식이 올바르지 않습니다.'); + errorMessage = '입력 형식이 올바르지 않습니다.'; } else if (err.response?.data?.message) { - setError(`❌ ${err.response.data.message}`); - } else { - setError('❌ 뱃지 추가 중 오류가 발생했습니다.'); + errorMessage = err.response.data.message; } + + setModalMessage(errorMessage); + setModalType('error'); + setShowModal(true); } finally { setIsLoading(false); } }; return ( -