Files
TK-FB-Project/fastapi-bridge/static/pages/common/daily-work-report.html

1062 lines
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>일일 작업보고서 작성 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/main-layout.css">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/auth-check.js" defer></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f7fa;
color: #333;
line-height: 1.6;
}
/* 메인 레이아웃 조정 */
.main-layout-with-navbar {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.content-wrapper {
flex: 1;
padding: 20px;
}
.work-form-container {
max-width: 1000px;
margin: 0 auto;
}
.page-header {
text-align: center;
margin-bottom: 2.5rem;
padding: 3rem 2rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 16px;
box-shadow: 0 6px 24px rgba(0,0,0,0.12);
}
.page-header h1 {
font-size: 2.5rem;
margin-bottom: 0.8rem;
font-weight: 700;
}
.subtitle {
font-size: 1.1rem;
opacity: 0.9;
}
.card {
background: white;
border-radius: 16px;
padding: 2.5rem;
box-shadow: 0 6px 24px rgba(0,0,0,0.08);
margin-bottom: 2.5rem;
}
/* 스테퍼 스타일 */
.step-section {
margin-bottom: 32px;
opacity: 0.5;
transition: opacity 0.3s ease;
}
.step-section.active {
opacity: 1;
}
.step-section.completed {
opacity: 0.8;
}
.step-header {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 24px;
}
.step-number {
background: #007bff;
color: white;
width: 48px;
height: 48px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 18px;
}
.step-number.completed {
background: #28a745;
}
.step-title {
font-size: 22px;
font-weight: 700;
color: #333;
}
/* 작업자 선택 그리드 */
.worker-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 16px;
margin-bottom: 32px;
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
.worker-btn {
padding: 24px 16px;
border: 3px solid #e1e5e9;
border-radius: 12px;
background: white;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
font-size: 16px;
font-weight: 600;
min-height: 80px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
.worker-btn:hover {
border-color: #007bff;
background: #f8f9fa;
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0,0,0,0.1);
}
.worker-btn.selected {
border-color: #007bff;
background: #007bff;
color: white;
box-shadow: 0 4px 16px rgba(0, 123, 255, 0.3);
}
/* 폼 그룹 */
.form-group {
margin-bottom: 2rem;
}
.form-group label {
display: block;
margin-bottom: 12px;
font-weight: 700;
color: #555;
font-size: 18px;
}
.large-select {
width: 100%;
padding: 20px;
border: 3px solid #e1e5e9;
border-radius: 12px;
font-size: 18px;
background: white;
cursor: pointer;
transition: border-color 0.3s;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
.large-select:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 4px rgba(0, 123, 255, 0.15);
}
/* 작업 항목 스타일 */
.work-entry {
border: 2px solid #e1e5e9;
border-radius: 16px;
padding: 24px;
margin-bottom: 24px;
background: white;
position: relative;
box-shadow: 0 4px 16px rgba(0,0,0,0.06);
}
.work-entry-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 2px solid #f0f0f0;
}
.work-entry-title {
font-weight: 700;
color: #333;
font-size: 20px;
}
.remove-work-btn {
background: #dc3545;
color: white;
border: none;
border-radius: 50%;
width: 48px;
height: 48px;
cursor: pointer;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s;
box-shadow: 0 2px 8px rgba(220, 53, 69, 0.3);
}
.remove-work-btn:hover {
background: #c82333;
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(220, 53, 69, 0.4);
}
.work-entry-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
margin-bottom: 20px;
}
.time-input-row {
grid-column: span 2;
}
.quick-time-buttons {
display: flex;
gap: 12px;
margin-top: 16px;
flex-wrap: wrap;
justify-content: center;
}
.quick-time-btn {
padding: 16px 24px;
background: #f8f9fa;
border: 2px solid #dee2e6;
border-radius: 12px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
transition: all 0.3s;
min-width: 80px;
text-align: center;
}
.quick-time-btn:hover {
border-color: #007bff;
background: #e7f3ff;
transform: translateY(-1px);
}
.quick-time-btn:active {
background: #007bff;
color: white;
transform: translateY(0);
}
.total-hours-display {
text-align: center;
font-size: 24px;
font-weight: 700;
padding: 24px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 16px;
margin-bottom: 24px;
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3);
}
.error-type-section {
display: none;
}
.error-type-section.visible {
display: block;
margin-top: 24px;
padding: 24px;
background: #fff3cd;
border: 2px solid #ffeaa7;
border-radius: 12px;
}
/* 버튼 스타일 */
.btn {
padding: 20px 40px;
border: none;
border-radius: 12px;
font-size: 18px;
font-weight: 700;
cursor: pointer;
transition: all 0.3s;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 12px;
text-decoration: none;
min-height: 60px;
box-shadow: 0 3px 12px rgba(0,0,0,0.1);
}
.btn-primary {
background: #007bff;
color: white;
}
.btn-primary:disabled {
background: #6c757d;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.btn-success {
background: #28a745;
color: white;
}
.btn-success:disabled {
background: #6c757d;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.btn-secondary {
background: #6c757d;
color: white;
}
.btn-block {
width: 100%;
justify-content: center;
}
.btn-primary:hover:not(:disabled) {
background: #0056b3;
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 123, 255, 0.3);
}
.btn-success:hover:not(:disabled) {
background: #1e7e34;
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(40, 167, 69, 0.3);
}
.btn-secondary:hover {
background: #545b62;
transform: translateY(-2px);
}
/* 뒤로가기 버튼 */
.back-btn {
background: rgba(255,255,255,0.95);
color: #667eea;
border: 3px solid #667eea;
padding: 16px 32px;
border-radius: 12px;
text-decoration: none;
font-weight: 700;
font-size: 18px;
display: inline-flex;
align-items: center;
gap: 12px;
margin-bottom: 24px;
transition: all 0.3s ease;
box-shadow: 0 3px 12px rgba(102, 126, 234, 0.2);
}
.back-btn:hover {
background: #667eea;
color: white;
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3);
}
/* 알림 메시지 */
.message {
padding: 20px 32px;
border-radius: 12px;
margin-bottom: 32px;
font-weight: 600;
font-size: 18px;
box-shadow: 0 3px 12px rgba(0,0,0,0.1);
}
.message.error {
background: #f8d7da;
color: #721c24;
border: 2px solid #f5c6cb;
}
.message.success {
background: #d4edda;
color: #155724;
border: 2px solid #c3e6cb;
}
.message.loading {
background: #cce5ff;
color: #0066cc;
border: 2px solid #99d6ff;
}
.message.warning {
background: #fff3cd;
color: #856404;
border: 2px solid #ffeaa7;
}
/* 당일 작업자 현황 스타일 */
.daily-workers-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 2px solid #f0f0f0;
}
.refresh-btn {
background: #28a745;
color: white;
border: none;
border-radius: 8px;
padding: 12px 20px;
cursor: pointer;
font-size: 14px;
font-weight: 600;
transition: all 0.3s;
display: flex;
align-items: center;
gap: 8px;
}
.refresh-btn:hover {
background: #1e7e34;
transform: translateY(-1px);
}
.worker-status-grid {
display: grid;
gap: 16px;
}
.worker-status-item {
background: #f8f9fa;
border-radius: 12px;
padding: 20px;
border-left: 4px solid #007bff;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
.worker-status-item:hover {
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0,0,0,0.1);
}
/* 작업자 헤더 스타일 */
.worker-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 12px 12px 0 0;
margin: -20px -20px 20px -20px;
}
.worker-name {
font-size: 18px;
font-weight: 700;
margin: 0;
}
.worker-total-hours {
background: rgba(255,255,255,0.2);
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
font-weight: 700;
}
/* 개별 작업 항목 스타일 */
.individual-works-container {
display: flex;
flex-direction: column;
gap: 12px;
}
.individual-work-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px;
background: #f8f9fa;
border-radius: 8px;
border: 1px solid #e9ecef;
transition: all 0.3s ease;
}
.individual-work-item:hover {
background: #e9ecef;
transform: translateX(4px);
}
.work-details-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 12px;
flex: 1;
}
.detail-item {
display: flex;
flex-direction: column;
gap: 4px;
}
.detail-label {
font-size: 12px;
color: #666;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.detail-value {
font-size: 14px;
color: #333;
font-weight: 600;
}
/* 액션 버튼 스타일 */
.action-buttons {
display: flex;
gap: 8px;
margin-left: 16px;
}
.edit-btn, .delete-btn {
padding: 8px 12px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
font-weight: 600;
transition: all 0.3s;
white-space: nowrap;
}
.edit-btn {
background: #007bff;
color: white;
}
.edit-btn:hover {
background: #0056b3;
transform: translateY(-1px);
}
.delete-btn {
background: #dc3545;
color: white;
}
.delete-btn:hover {
background: #c82333;
transform: translateY(-1px);
}
/* 🛠️ 수정 모달 스타일 */
.edit-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.edit-modal-content {
background: white;
border-radius: 16px;
width: 90%;
max-width: 600px;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
animation: slideIn 0.3s ease;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(-50px) scale(0.9);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.edit-modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24px;
border-bottom: 2px solid #f0f0f0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 16px 16px 0 0;
}
.edit-modal-header h3 {
margin: 0;
font-size: 20px;
font-weight: 700;
}
.close-modal-btn {
background: rgba(255,255,255,0.2);
color: white;
border: none;
border-radius: 50%;
width: 32px;
height: 32px;
cursor: pointer;
font-size: 18px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s;
}
.close-modal-btn:hover {
background: rgba(255,255,255,0.3);
transform: rotate(90deg);
}
.edit-modal-body {
padding: 24px;
}
.edit-form-group {
margin-bottom: 20px;
}
.edit-form-group label {
display: block;
margin-bottom: 8px;
font-weight: 700;
color: #555;
font-size: 14px;
}
.edit-select, .edit-input {
width: 100%;
padding: 12px 16px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 16px;
background: white;
transition: border-color 0.3s;
}
.edit-select:focus, .edit-input:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}
.edit-modal-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
padding: 24px;
border-top: 2px solid #f0f0f0;
background: #f8f9fa;
border-radius: 0 0 16px 16px;
}
.no-data-message {
text-align: center;
padding: 40px 20px;
color: #666;
font-size: 16px;
background: #f8f9fa;
border-radius: 12px;
border: 2px dashed #dee2e6;
}
.loading-spinner {
text-align: center;
padding: 40px 20px;
color: #007bff;
font-size: 16px;
}
/* 가이드 카드 */
.guide-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
max-width: 800px;
margin: 0 auto;
}
.guide-item {
text-align: center;
padding: 20px;
background: #f8f9fa;
border-radius: 12px;
border: 2px solid #e9ecef;
transition: all 0.3s ease;
}
.guide-item:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0,0,0,0.1);
border-color: #667eea;
}
.guide-icon {
font-size: 28px;
margin-bottom: 12px;
}
.guide-item strong {
display: block;
font-size: 16px;
font-weight: 700;
margin-bottom: 8px;
color: #333;
}
/* 반응형 디자인 */
@media (max-width: 1200px) and (min-width: 769px) {
.work-form-container {
max-width: 900px;
}
.worker-grid {
max-width: 700px;
grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
}
}
@media (max-width: 768px) {
.content-wrapper {
padding: 16px;
}
.worker-grid {
grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
gap: 12px;
max-width: 600px;
}
.worker-btn {
padding: 20px 12px;
font-size: 15px;
min-height: 70px;
}
.work-entry-row {
grid-template-columns: 1fr;
gap: 20px;
}
.time-input-row {
grid-column: span 1;
}
.card {
padding: 2rem;
}
.page-header {
padding: 2rem 1.5rem;
}
.page-header h1 {
font-size: 2rem;
}
.btn {
padding: 18px 32px;
font-size: 17px;
}
.step-number {
width: 40px;
height: 40px;
font-size: 16px;
}
.step-title {
font-size: 20px;
}
.quick-time-buttons {
justify-content: center;
}
.quick-time-btn {
padding: 14px 20px;
font-size: 15px;
}
.work-details-grid {
grid-template-columns: 1fr;
gap: 8px;
}
.individual-work-item {
flex-direction: column;
align-items: stretch;
gap: 12px;
}
.action-buttons {
margin-left: 0;
justify-content: center;
}
.worker-header {
flex-direction: column;
gap: 8px;
text-align: center;
}
.edit-modal-content {
width: 95%;
margin: 20px;
}
.edit-modal-footer {
flex-direction: column;
}
.edit-btn, .delete-btn {
flex: 1;
padding: 12px;
font-size: 14px;
}
}
@media (max-width: 480px) {
.content-wrapper {
padding: 12px;
}
.worker-grid {
grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
max-width: 400px;
}
.card {
padding: 1.5rem;
}
.page-header h1 {
font-size: 1.7rem;
}
.btn {
padding: 16px 24px;
font-size: 16px;
}
.quick-time-btn {
padding: 12px 16px;
font-size: 14px;
min-width: 60px;
}
.detail-item {
text-align: center;
}
.detail-label {
font-size: 11px;
}
.detail-value {
font-size: 13px;
}
.edit-modal-body {
padding: 16px;
}
.edit-modal-header {
padding: 16px;
}
.edit-modal-footer {
padding: 16px;
}
}
</style>
</head>
<body>
<div class="main-layout-with-navbar">
<!-- 네비게이션 바 -->
<div id="navbar-container"></div>
<div class="content-wrapper">
<div class="work-form-container">
<!-- 뒤로가기 버튼 -->
<a href="javascript:history.back()" class="back-btn">
← 뒤로가기
</a>
<div class="page-header">
<h1>✍️ 일일 작업보고서 작성</h1>
<p class="subtitle">단계별로 오늘의 작업 내용을 간편하게 기록하고 관리하세요.</p>
</div>
<!-- 메시지 영역 -->
<div id="message-container"></div>
<!-- 1단계: 날짜 선택 -->
<div id="step1" class="step-section card active">
<div class="step-header">
<div class="step-number">1</div>
<div class="step-title">작업 날짜 선택</div>
</div>
<div class="form-group">
<input type="date" id="reportDate" class="large-select" required>
</div>
<button type="button" class="btn btn-primary" id="nextStep1">다음 단계</button>
</div>
<!-- 2단계: 작업자 선택 -->
<div id="step2" class="step-section card">
<div class="step-header">
<div class="step-number">2</div>
<div class="step-title">작업자 선택</div>
</div>
<div id="workerGrid" class="worker-grid">
<!-- 작업자 버튼들이 여기에 동적으로 추가됩니다 -->
</div>
<button type="button" class="btn btn-primary" id="nextStep2" disabled>다음 단계</button>
</div>
<!-- 3단계: 작업 내역 입력 -->
<div id="step3" class="step-section card">
<div class="step-header">
<div class="step-number">3</div>
<div class="step-title">작업 내역 입력</div>
</div>
<!-- 총 작업시간 표시 -->
<div class="total-hours-display" id="totalHoursDisplay">
총 작업시간: 0시간
</div>
<!-- 작업 항목들 -->
<div id="workEntriesList">
<!-- 작업 항목들이 여기에 동적으로 추가됩니다 -->
</div>
<!-- 작업 추가 버튼 -->
<button type="button" class="btn btn-secondary btn-block" id="addWorkBtn">
작업 추가
</button>
<!-- 저장 버튼 -->
<button type="button" class="btn btn-success btn-block" id="submitBtn" style="margin-top: 1rem;">
💾 작업보고서 저장
</button>
</div>
<!-- 📊 내가 입력한 당일 작업 현황 (수정/삭제 가능) -->
<div class="card" id="dailyWorkersSection" style="display: none;">
<h3>📊 내가 입력한 작업 현황</h3>
<p style="color: #666; margin-bottom: 20px;">
✏️ 내가 입력한 작업만 표시되며, 각 작업을 <strong>수정</strong>하거나 <strong>삭제</strong>할 수 있습니다.
</p>
<div id="dailyWorkersContent">
<!-- 작업자 현황이 여기에 표시됩니다 -->
</div>
</div>
<!-- 사용법 안내 -->
<div class="card">
<h3>📖 사용 가이드</h3>
<div class="guide-grid">
<div class="guide-item">
<div class="guide-icon">📅</div>
<strong>1단계</strong><br>
작업 날짜 선택
</div>
<div class="guide-item">
<div class="guide-icon">👤</div>
<strong>2단계</strong><br>
작업자 선택 (터치)
</div>
<div class="guide-item">
<div class="guide-icon">🔧</div>
<strong>3단계</strong><br>
작업 내역 입력
</div>
<div class="guide-item">
<div class="guide-icon">💾</div>
<strong>완료</strong><br>
저장하여 마무리
</div>
<div class="guide-item">
<div class="guide-icon">✏️</div>
<strong>관리</strong><br>
입력한 작업 수정/삭제
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 스크립트 -->
<script type="module" src="/js/load-navbar.js"></script>
<!-- ⚠️ 중요: 모듈 타입으로 수정 -->
<script type="module" src="/js/daily-work-report.js"></script>
</body>
</html>