('table');
// Execute modal (individual card)
const [executeModalOpen, setExecuteModalOpen] = useState(false);
@@ -243,10 +243,23 @@ export default function Jobs() {
{/* View mode toggle */}
+
-
@@ -316,9 +316,6 @@ export default function Jobs() {
{getJobLabel(job)}
- {job.displayName && (
- {job.jobName}
- )}
{isRunning && (
@@ -436,12 +433,7 @@ export default function Jobs() {
{isRunning && (
)}
-
-
{getJobLabel(job)}
- {job.displayName && (
-
{job.jobName}
- )}
-
+
{getJobLabel(job)}
diff --git a/frontend/src/pages/Recollects.tsx b/frontend/src/pages/Recollects.tsx
index 7eb4e3b..16ba5db 100644
--- a/frontend/src/pages/Recollects.tsx
+++ b/frontend/src/pages/Recollects.tsx
@@ -477,7 +477,7 @@ export default function Recollects() {
- | API명 |
+ 배치 작업명 |
마지막 수집 완료일시 |
경과시간 |
상태 |
diff --git a/frontend/src/pages/Schedules.tsx b/frontend/src/pages/Schedules.tsx
index 3993886..83e1b0d 100644
--- a/frontend/src/pages/Schedules.tsx
+++ b/frontend/src/pages/Schedules.tsx
@@ -1,4 +1,4 @@
-import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
+import { useState, useEffect, useCallback, useMemo } from 'react';
import { batchApi, type ScheduleResponse, type JobDisplayName } from '../api/batchApi';
import { formatDateTime } from '../utils/formatters';
import { useToastContext } from '../contexts/ToastContext';
@@ -8,6 +8,7 @@ import LoadingSpinner from '../components/LoadingSpinner';
import { getNextExecutions } from '../utils/cronPreview';
type ScheduleMode = 'new' | 'existing';
+type ScheduleViewMode = 'card' | 'table';
interface ConfirmAction {
type: 'toggle' | 'delete';
@@ -95,11 +96,14 @@ export default function Schedules() {
const [listLoading, setListLoading] = useState(true);
const [displayNames, setDisplayNames] = useState([]);
+ // View mode state
+ const [viewMode, setViewMode] = useState('table');
+
// Confirm modal state
const [confirmAction, setConfirmAction] = useState(null);
- // 폼 영역 ref (편집 버튼 클릭 시 스크롤)
- const formRef = useRef(null);
+ // Form modal state
+ const [formOpen, setFormOpen] = useState(false);
const loadSchedules = useCallback(async () => {
try {
@@ -186,8 +190,8 @@ export default function Schedules() {
showToast('스케줄이 등록되었습니다', 'success');
}
await loadSchedules();
- // Reload schedule info for current job
- await handleJobSelect(selectedJob);
+ setFormOpen(false);
+ resetForm();
} catch (err) {
const message = err instanceof Error ? err.message : '저장 실패';
showToast(message, 'error');
@@ -216,12 +220,10 @@ export default function Schedules() {
await batchApi.deleteSchedule(schedule.jobName);
showToast(`${schedule.jobName} 스케줄이 삭제되었습니다`, 'success');
await loadSchedules();
- // Clear form if deleted schedule was selected
+ // Close form if deleted schedule was being edited
if (selectedJob === schedule.jobName) {
- setSelectedJob('');
- setCronExpression('');
- setDescription('');
- setScheduleMode('new');
+ resetForm();
+ setFormOpen(false);
}
} catch (err) {
const message = err instanceof Error ? err.message : '삭제 실패';
@@ -230,124 +232,159 @@ export default function Schedules() {
setConfirmAction(null);
};
+ const resetForm = () => {
+ setSelectedJob('');
+ setCronExpression('');
+ setDescription('');
+ setScheduleMode('new');
+ };
+
const handleEditFromCard = (schedule: ScheduleResponse) => {
setSelectedJob(schedule.jobName);
setCronExpression(schedule.cronExpression);
setDescription(schedule.description ?? '');
setScheduleMode('existing');
- formRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ setFormOpen(true);
+ };
+
+ const handleNewSchedule = () => {
+ resetForm();
+ setFormOpen(true);
};
return (
- {/* Form Section */}
-
- 스케줄 등록 / 수정
-
-
- {/* Job Select */}
-
-
-
- |