✏️ JobSelectionPage에 프로젝트 이름 수정 기능 추가
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
- 선택된 프로젝트 옆에 '✏️ 수정' 버튼 추가
- 수정 버튼 클릭 시 편집 폼 표시
- 입력 필드 + 저장/취소 버튼
- Enter 키로 저장 가능
- API 연동: PATCH /dashboard/projects/{id}
- 실시간 업데이트: 드롭다운 목록 및 선택된 이름 자동 갱신
- 간단하고 직관적인 UX
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { fetchJobs } from '../api';
|
import { fetchJobs } from '../api';
|
||||||
|
import api from '../api';
|
||||||
|
|
||||||
const JobSelectionPage = ({ onJobSelect }) => {
|
const JobSelectionPage = ({ onJobSelect }) => {
|
||||||
const [jobs, setJobs] = useState([]);
|
const [jobs, setJobs] = useState([]);
|
||||||
@@ -7,6 +8,36 @@ const JobSelectionPage = ({ onJobSelect }) => {
|
|||||||
const [selectedJobName, setSelectedJobName] = useState('');
|
const [selectedJobName, setSelectedJobName] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState('');
|
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(() => {
|
useEffect(() => {
|
||||||
async function loadJobs() {
|
async function loadJobs() {
|
||||||
@@ -126,9 +157,99 @@ const JobSelectionPage = ({ onJobSelect }) => {
|
|||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
padding: '12px 16px',
|
padding: '12px 16px',
|
||||||
marginBottom: '20px',
|
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>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user