근태(Holyday) API 추가 및 일별/업무형태별 집계 다이얼로그 구현, OT 시작/종료시간 필드 추가

This commit is contained in:
backuppc
2025-12-02 08:26:24 +09:00
parent adcdc40169
commit aa956cf063
14 changed files with 2012 additions and 240 deletions

View File

@@ -5,10 +5,13 @@ import {
RefreshCw,
Copy,
Plus,
Calendar,
} from 'lucide-react';
import { comms } from '@/communication';
import { JobReportItem, JobReportUser } from '@/types';
import { JobreportEditModal, JobreportFormData, initialFormData } from '@/components/jobreport/JobreportEditModal';
import { JobReportDayDialog } from '@/components/jobreport/JobReportDayDialog';
import { JobreportTypeModal } from '@/components/jobreport/JobreportTypeModal';
export function Jobreport() {
const [jobreportList, setJobreportList] = useState<JobReportItem[]>([]);
@@ -24,6 +27,8 @@ export function Jobreport() {
// 모달 상태
const [showModal, setShowModal] = useState(false);
const [showDayReportModal, setShowDayReportModal] = useState(false);
const [showTypeReportModal, setShowTypeReportModal] = useState(false);
const [editingItem, setEditingItem] = useState<JobReportItem | null>(null);
const [formData, setFormData] = useState<JobreportFormData>(initialFormData);
@@ -200,6 +205,8 @@ export function Jobreport() {
description: data.description || '',
hrs: 0, // 시간 초기화
ot: 0, // OT 초기화
otStart: data.otStart ? data.otStart.substring(11, 16) : '18:00',
otEnd: data.otEnd ? data.otEnd.substring(11, 16) : '20:00',
jobgrp: '',
tag: '',
});
@@ -230,6 +237,8 @@ export function Jobreport() {
description: data.description || '',
hrs: data.hrs || 0,
ot: data.ot || 0,
otStart: data.otStart ? data.otStart.substring(11, 16) : '18:00',
otEnd: data.otEnd ? data.otEnd.substring(11, 16) : '20:00',
jobgrp: data.jobgrp || '',
tag: data.tag || '',
});
@@ -276,7 +285,9 @@ export function Jobreport() {
formData.hrs || 0,
formData.ot || 0,
formData.jobgrp || '',
formData.tag || ''
formData.tag || '',
formData.otStart || '18:00',
formData.otEnd || '20:00'
);
} else {
response = await comms.addJobReport(
@@ -292,7 +303,9 @@ export function Jobreport() {
formData.hrs || 0,
formData.ot || 0,
formData.jobgrp || '',
formData.tag || ''
formData.tag || '',
formData.otStart || '18:00',
formData.otEnd || '20:00'
);
}
@@ -419,7 +432,7 @@ export function Jobreport() {
</div>
{/* 버튼 영역: 우측 수직 배치 */}
<div className="grid grid-rows-2 gap-y-3">
<div className="flex flex-col gap-3">
<button
onClick={handleSearchWithReset}
disabled={loading}
@@ -443,6 +456,24 @@ export function Jobreport() {
</div>
</div>
{/* 중앙: 집계 메뉴 */}
<div className="flex-shrink-0 flex flex-col gap-3 justify-center">
<button
onClick={() => setShowDayReportModal(true)}
className="h-12 bg-indigo-500 hover:bg-indigo-600 text-white px-6 rounded-lg transition-colors flex items-center justify-center whitespace-nowrap"
>
<Calendar className="w-4 h-4 mr-2" />
</button>
<button
onClick={() => setShowTypeReportModal(true)}
className="h-12 bg-purple-500 hover:bg-purple-600 text-white px-6 rounded-lg transition-colors flex items-center justify-center whitespace-nowrap"
>
<FileText className="w-4 h-4 mr-2" />
</button>
</div>
{/* 우측: 오늘 근무시간 */}
<div className="flex-shrink-0 w-48">
<div className="bg-white/10 rounded-xl p-4 h-full flex flex-col justify-center">
@@ -523,9 +554,8 @@ export function Jobreport() {
</td>
<td className="px-4 py-3 text-white text-sm">{item.type || '-'}</td>
<td className="px-4 py-3 text-sm">
<span className={`px-2 py-1 rounded text-xs ${
item.status?.includes('완료') ? 'bg-green-500/20 text-green-400' : 'bg-white/20 text-white/70'
}`}>
<span className={`px-2 py-1 rounded text-xs ${item.status?.includes('완료') ? 'bg-green-500/20 text-green-400' : 'bg-white/20 text-white/70'
}`}>
{item.status || '-'}
</span>
</td>
@@ -602,6 +632,22 @@ export function Jobreport() {
setShowModal(false);
}}
/>
{/* 일별 집계 모달 */}
<JobReportDayDialog
isOpen={showDayReportModal}
onClose={() => setShowDayReportModal(false)}
initialMonth={startDate.substring(0, 7)}
/>
{/* 업무형태별 집계 모달 */}
<JobreportTypeModal
isOpen={showTypeReportModal}
onClose={() => setShowTypeReportModal(false)}
startDate={startDate}
endDate={endDate}
userId={selectedUser}
/>
</div>
);
}