/* ✅ modern-dashboard.css - 모던 대시보드 전용 스타일 */ /* ========== 대시보드 레이아웃 ========== */ .dashboard-container { min-height: 100vh; display: flex; flex-direction: column; background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); } /* ========== 헤더 ========== */ .dashboard-header { background: linear-gradient(135deg, #1e40af 0%, #1d4ed8 50%, #2563eb 100%); color: var(--text-inverse); padding: var(--space-4) var(--space-6); box-shadow: var(--shadow-lg); position: sticky; top: 0; z-index: 100; } .header-content { display: flex; align-items: center; justify-content: space-between; max-width: 1400px; margin: 0 auto; } .header-left .brand { display: flex; align-items: center; gap: var(--space-3); } .brand-logo { width: 48px; height: 48px; border-radius: var(--radius-lg); box-shadow: var(--shadow-md); } .brand-title { font-size: var(--text-2xl); font-weight: var(--font-bold); margin: 0; line-height: 1.2; } .brand-subtitle { font-size: var(--text-sm); opacity: 0.9; margin: 0; font-weight: var(--font-normal); } .header-center .current-time { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: var(--radius-full); padding: var(--space-3) var(--space-4); text-align: center; } .time-label { display: block; font-size: var(--text-xs); opacity: 0.8; margin-bottom: var(--space-1); } .time-value { display: block; font-size: var(--text-lg); font-weight: var(--font-bold); font-family: 'Courier New', monospace; } .header-right .user-profile { position: relative; display: flex; align-items: center; gap: var(--space-3); background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: var(--radius-full); padding: var(--space-2) var(--space-4); cursor: pointer; transition: var(--transition-normal); } .user-profile:hover { background: rgba(255, 255, 255, 0.2); } .user-avatar { width: 40px; height: 40px; border-radius: var(--radius-full); background: var(--primary-300); display: flex; align-items: center; justify-content: center; font-weight: var(--font-bold); color: var(--primary-800); } .user-info { display: flex; flex-direction: column; } .user-name { font-size: var(--text-sm); font-weight: var(--font-semibold); line-height: 1.2; } .user-role { font-size: var(--text-xs); opacity: 0.8; } .profile-menu { position: absolute; top: 100%; right: 0; margin-top: var(--space-2); background: var(--bg-primary); border-radius: var(--radius-lg); box-shadow: var(--shadow-xl); border: 1px solid var(--border-light); min-width: 200px; opacity: 0; visibility: hidden; transform: translateY(-10px); transition: var(--transition-normal); z-index: 1000; } .user-profile:hover .profile-menu, .profile-menu:hover { opacity: 1; visibility: visible; transform: translateY(0); } .menu-item { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); color: var(--text-primary); text-decoration: none; border: none; background: none; width: 100%; text-align: left; font-size: var(--text-sm); cursor: pointer; transition: var(--transition-fast); } .menu-item:hover { background: var(--gray-50); } .menu-item:first-child { border-radius: var(--radius-lg) var(--radius-lg) 0 0; } .menu-item:last-child { border-radius: 0 0 var(--radius-lg) var(--radius-lg); } .logout-btn { color: var(--error-600); border-top: 1px solid var(--border-light); } .logout-btn:hover { background: var(--error-50); } /* ========== 메인 콘텐츠 ========== */ .dashboard-main { flex: 1; padding: var(--space-8) var(--space-6); max-width: 1400px; margin: 0 auto; width: 100%; } /* ========== 요약 섹션 ========== */ .summary-section { margin-bottom: var(--space-8); } .summary-card { position: relative; overflow: hidden; transition: var(--transition-normal); } .summary-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, var(--primary-500), var(--primary-600)); } .summary-card .card-body { display: flex; align-items: flex-start; gap: var(--space-4); } .summary-icon { width: 56px; height: 56px; border-radius: var(--radius-xl); display: flex; align-items: center; justify-content: center; font-size: var(--text-2xl); flex-shrink: 0; } .summary-icon.success { background: var(--success-100); color: var(--success-700); } .summary-icon.primary { background: var(--primary-100); color: var(--primary-700); } .summary-icon.warning { background: var(--warning-100); color: var(--warning-700); } .summary-icon.error { background: var(--error-100); color: var(--error-700); } .summary-content { flex: 1; } .summary-title { font-size: var(--text-sm); font-weight: var(--font-medium); color: var(--text-secondary); margin: 0 0 var(--space-2) 0; } .summary-value { display: flex; align-items: baseline; gap: var(--space-1); margin-bottom: var(--space-2); } .value-number { font-size: var(--text-3xl); font-weight: var(--font-bold); color: var(--text-primary); line-height: 1; } .value-unit { font-size: var(--text-sm); color: var(--text-secondary); font-weight: var(--font-medium); } .summary-change { display: flex; align-items: center; gap: var(--space-1); font-size: var(--text-xs); font-weight: var(--font-medium); margin: 0; } .summary-change.positive { color: var(--success-600); } .summary-change.negative { color: var(--error-600); } .summary-change.neutral { color: var(--text-tertiary); } .change-icon { font-size: var(--text-sm); } /* ========== 콘텐츠 섹션 ========== */ .content-section { margin-bottom: var(--space-8); } .content-card { height: fit-content; } .col-span-2 { grid-column: span 2; } .card-title { font-size: var(--text-lg); font-weight: var(--font-semibold); color: var(--text-primary); margin: 0; display: flex; align-items: center; gap: var(--space-2); } .date-selector { display: flex; align-items: center; gap: var(--space-3); } .date-input { padding: var(--space-2) var(--space-3); border: 1px solid var(--border-medium); border-radius: var(--radius-md); font-size: var(--text-sm); background: var(--bg-primary); color: var(--text-primary); } .date-input:focus { outline: none; border-color: var(--primary-500); box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); } /* ========== 작업 현황 ========== */ .work-status-container { min-height: 300px; display: flex; align-items: center; justify-content: center; } .loading-state { display: flex; flex-direction: column; align-items: center; gap: var(--space-4); color: var(--text-secondary); } /* ========== 빠른 작업 ========== */ .quick-actions { display: flex; flex-direction: column; gap: var(--space-3); } .quick-action-btn { display: flex; align-items: center; gap: var(--space-4); padding: var(--space-4); background: var(--bg-tertiary); border-radius: var(--radius-lg); text-decoration: none; color: var(--text-primary); transition: var(--transition-normal); border: 1px solid var(--border-light); } .quick-action-btn:hover { background: var(--bg-primary); box-shadow: var(--shadow-md); transform: translateY(-2px); } .action-icon { width: 48px; height: 48px; background: var(--primary-100); border-radius: var(--radius-lg); display: flex; align-items: center; justify-content: center; font-size: var(--text-xl); flex-shrink: 0; } .action-content h3 { font-size: var(--text-sm); font-weight: var(--font-semibold); margin: 0 0 var(--space-1) 0; color: var(--text-primary); } .action-content p { font-size: var(--text-xs); color: var(--text-secondary); margin: 0; line-height: 1.4; } .admin-only { opacity: 0.6; pointer-events: none; } .admin-only.visible { opacity: 1; pointer-events: auto; } /* ========== 작업자 섹션 ========== */ .workers-section { margin-bottom: var(--space-8); } .view-controls { display: flex; gap: var(--space-2); } .workers-container { min-height: 200px; } /* ========== 푸터 ========== */ .dashboard-footer { background: var(--bg-primary); border-top: 1px solid var(--border-light); padding: var(--space-6); margin-top: auto; } .footer-content { max-width: 1400px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center; } .footer-text { font-size: var(--text-sm); color: var(--text-secondary); margin: 0; } .footer-links { display: flex; gap: var(--space-6); } .footer-link { font-size: var(--text-sm); color: var(--text-secondary); text-decoration: none; transition: var(--transition-fast); } .footer-link:hover { color: var(--primary-600); } /* ========== 토스트 알림 ========== */ .toast-container { position: fixed; top: var(--space-6); right: var(--space-6); z-index: 1000; display: flex; flex-direction: column; gap: var(--space-3); } .toast { background: var(--bg-primary); border-radius: var(--radius-lg); box-shadow: var(--shadow-xl); border: 1px solid var(--border-light); padding: var(--space-4); min-width: 300px; display: flex; align-items: center; gap: var(--space-3); animation: slideInRight var(--transition-normal) ease-out; } .toast.success { border-left: 4px solid var(--success-500); } .toast.error { border-left: 4px solid var(--error-500); } .toast.warning { border-left: 4px solid var(--warning-500); } .toast.info { border-left: 4px solid var(--info-500); } @keyframes slideInRight { from { opacity: 0; transform: translateX(100%); } to { opacity: 1; transform: translateX(0); } } /* ========== 작업 현황 스타일 ========== */ .work-status-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--space-4); } .project-status-card { background: var(--bg-tertiary); border-radius: var(--radius-lg); padding: var(--space-4); border: 1px solid var(--border-light); } .project-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-3); } .project-name { font-size: var(--text-base); font-weight: var(--font-semibold); margin: 0; color: var(--text-primary); } .work-count { font-size: var(--text-xs); } .project-stats { display: flex; justify-content: space-between; gap: var(--space-3); } .stat-item { text-align: center; } .stat-label { display: block; font-size: var(--text-xs); color: var(--text-secondary); margin-bottom: var(--space-1); } .stat-value { display: block; font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--text-primary); } .stat-value.error { color: var(--error-600); } /* ========== 작업자 카드 스타일 ========== */ .workers-grid { gap: var(--space-4); } .worker-card { transition: var(--transition-normal); } .worker-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); } .worker-header { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-4); } .worker-avatar { width: 48px; height: 48px; border-radius: var(--radius-full); background: var(--primary-100); display: flex; align-items: center; justify-content: center; font-weight: var(--font-bold); color: var(--primary-700); font-size: var(--text-lg); } .worker-avatar.small { width: 32px; height: 32px; font-size: var(--text-sm); } .worker-info { flex: 1; } .worker-name { font-size: var(--text-sm); font-weight: var(--font-semibold); margin: 0 0 var(--space-1) 0; color: var(--text-primary); } .worker-job { font-size: var(--text-xs); color: var(--text-secondary); margin: 0; } .worker-status { display: flex; align-items: center; } .worker-stats { display: flex; justify-content: space-between; gap: var(--space-2); } .stat { text-align: center; flex: 1; } .stat.error .stat-value { color: var(--error-600); } /* ========== 테이블 스타일 ========== */ .workers-table { overflow-x: auto; } .table { width: 100%; border-collapse: collapse; background: var(--bg-primary); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-sm); } .table th { background: var(--gray-50); padding: var(--space-4); text-align: left; font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--text-secondary); border-bottom: 1px solid var(--border-light); } .table td { padding: var(--space-4); border-bottom: 1px solid var(--border-light); font-size: var(--text-sm); color: var(--text-primary); } .table tr:last-child td { border-bottom: none; } .table tr:hover { background: var(--gray-50); } .worker-cell { display: flex; align-items: center; gap: var(--space-3); } /* ========== 빈 상태 및 오류 상태 ========== */ .empty-state, .error-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-12); text-align: center; color: var(--text-secondary); } .empty-icon, .error-icon { font-size: var(--text-5xl); margin-bottom: var(--space-4); opacity: 0.5; } .empty-state h3, .error-state h3 { font-size: var(--text-lg); font-weight: var(--font-semibold); margin: 0 0 var(--space-2) 0; color: var(--text-primary); } .empty-state p, .error-state p { font-size: var(--text-sm); margin: 0 0 var(--space-4) 0; max-width: 400px; line-height: 1.5; } /* ========== 토스트 스타일 보완 ========== */ .toast-icon { font-size: var(--text-lg); flex-shrink: 0; } .toast-message { flex: 1; font-size: var(--text-sm); color: var(--text-primary); } .toast-close { background: none; border: none; font-size: var(--text-lg); color: var(--text-secondary); cursor: pointer; padding: 0; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; border-radius: var(--radius-sm); transition: var(--transition-fast); } .toast-close:hover { background: var(--gray-100); color: var(--text-primary); } /* ========== 반응형 디자인 ========== */ @media (max-width: 1024px) { .grid-cols-4 { grid-template-columns: repeat(2, 1fr); } .grid-cols-3 { grid-template-columns: 1fr; } .col-span-2 { grid-column: span 1; } } @media (max-width: 768px) { .dashboard-main { padding: var(--space-4); } .header-content { flex-direction: column; gap: var(--space-4); } .header-center, .header-right { order: 3; } .grid-cols-4, .grid-cols-2 { grid-template-columns: 1fr; } .summary-card .card-body { flex-direction: column; text-align: center; } .footer-content { flex-direction: column; gap: var(--space-4); text-align: center; } } @media (max-width: 640px) { .dashboard-header { padding: var(--space-3) var(--space-4); } .brand-title { font-size: var(--text-lg); } .brand-subtitle { font-size: var(--text-xs); } .user-info { display: none; } .toast-container { left: var(--space-4); right: var(--space-4); } .toast { min-width: auto; } }