✏️ JobSelectionPage에 프로젝트 이름 수정 기능 추가
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled

- 선택된 프로젝트 옆에 '✏️ 수정' 버튼 추가
- 수정 버튼 클릭 시 편집 폼 표시
- 입력 필드 + 저장/취소 버튼
- Enter 키로 저장 가능
- API 연동: PATCH /dashboard/projects/{id}
- 실시간 업데이트: 드롭다운 목록 및 선택된 이름 자동 갱신
- 간단하고 직관적인 UX
This commit is contained in:
Hyungi Ahn
2025-10-14 06:51:45 +09:00
parent ca0336d627
commit aca00cf3cb

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react';
import { fetchJobs } from '../api';
import api from '../api';
const JobSelectionPage = ({ onJobSelect }) => {
const [jobs, setJobs] = useState([]);
@@ -7,6 +8,36 @@ const JobSelectionPage = ({ onJobSelect }) => {
const [selectedJobName, setSelectedJobName] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [editingJobNo, setEditingJobNo] = useState(null);
const [editedName, setEditedName] = useState('');
// 프로젝트 이름 수정
const updateJobName = async (jobNo) => {
try {
const project = jobs.find(j => j.job_no === jobNo);
if (!project) return;
const response = await api.patch(`/dashboard/projects/${project.id}?job_name=${encodeURIComponent(editedName)}`);
if (response.data.success) {
// 로컬 상태 업데이트
setJobs(jobs.map(j =>
j.job_no === jobNo ? { ...j, job_name: editedName } : j
));
// 선택된 프로젝트 이름도 업데이트
if (selectedJobNo === jobNo) {
setSelectedJobName(editedName);
}
setEditingJobNo(null);
setEditedName('');
}
} catch (error) {
console.error('프로젝트 이름 수정 실패:', error);
alert('프로젝트 이름 수정에 실패했습니다.');
}
};
useEffect(() => {
async function loadJobs() {
@@ -126,9 +157,99 @@ const JobSelectionPage = ({ onJobSelect }) => {
borderRadius: '8px',
padding: '12px 16px',
marginBottom: '20px',
color: '#2f855a'
color: '#2f855a',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}}>
선택된 프로젝트: <strong>{selectedJobNo} - {selectedJobName}</strong>
<div>
선택된 프로젝트: <strong>{selectedJobNo} - {selectedJobName}</strong>
</div>
<button
onClick={() => {
setEditingJobNo(selectedJobNo);
setEditedName(selectedJobName);
}}
style={{
padding: '6px 12px',
background: '#48bb78',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '12px',
fontWeight: '600'
}}
title="프로젝트 이름 수정"
>
수정
</button>
</div>
)}
{editingJobNo && (
<div style={{
background: '#fff5f5',
border: '2px solid #fc8181',
borderRadius: '8px',
padding: '16px',
marginBottom: '20px'
}}>
<div style={{ marginBottom: '12px', fontWeight: '600', color: '#742a2a' }}>
프로젝트 이름 수정
</div>
<div style={{ display: 'flex', gap: '8px' }}>
<input
type="text"
value={editedName}
onChange={(e) => setEditedName(e.target.value)}
onKeyPress={(e) => {
if (e.key === 'Enter') updateJobName(editingJobNo);
}}
placeholder="새 프로젝트 이름"
autoFocus
style={{
flex: 1,
padding: '10px',
border: '2px solid #3b82f6',
borderRadius: '6px',
fontSize: '14px'
}}
/>
<button
onClick={() => updateJobName(editingJobNo)}
style={{
padding: '10px 16px',
background: '#10b981',
color: 'white',
border: 'none',
borderRadius: '6px',
cursor: 'pointer',
fontSize: '14px',
fontWeight: '600'
}}
>
저장
</button>
<button
onClick={() => {
setEditingJobNo(null);
setEditedName('');
}}
style={{
padding: '10px 16px',
background: '#ef4444',
color: 'white',
border: 'none',
borderRadius: '6px',
cursor: 'pointer',
fontSize: '14px',
fontWeight: '600'
}}
>
취소
</button>
</div>
</div>
)}