add webtestversion
This commit is contained in:
		
							
								
								
									
										311
									
								
								Project/Web/wwwroot/DashBoard/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										311
									
								
								Project/Web/wwwroot/DashBoard/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,311 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang="ko"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>근태현황 대시보드</title> | ||||
|     <script src="https://cdn.tailwindcss.com"></script> | ||||
|     <script> | ||||
|         tailwind.config = { | ||||
|             theme: { | ||||
|                 extend: { | ||||
|                     colors: { | ||||
|                         primary: { | ||||
|                             50: '#eff6ff', | ||||
|                             100: '#dbeafe', | ||||
|                             200: '#bfdbfe', | ||||
|                             300: '#93c5fd', | ||||
|                             400: '#60a5fa', | ||||
|                             500: '#3b82f6', | ||||
|                             600: '#2563eb', | ||||
|                             700: '#1d4ed8', | ||||
|                             800: '#1e40af', | ||||
|                             900: '#1e3a8a', | ||||
|                         }, | ||||
|                         success: { | ||||
|                             50: '#f0fdf4', | ||||
|                             100: '#dcfce7', | ||||
|                             200: '#bbf7d0', | ||||
|                             300: '#86efac', | ||||
|                             400: '#4ade80', | ||||
|                             500: '#22c55e', | ||||
|                             600: '#16a34a', | ||||
|                             700: '#15803d', | ||||
|                             800: '#166534', | ||||
|                             900: '#14532d', | ||||
|                         }, | ||||
|                         warning: { | ||||
|                             50: '#fffbeb', | ||||
|                             100: '#fef3c7', | ||||
|                             200: '#fde68a', | ||||
|                             300: '#fcd34d', | ||||
|                             400: '#fbbf24', | ||||
|                             500: '#f59e0b', | ||||
|                             600: '#d97706', | ||||
|                             700: '#b45309', | ||||
|                             800: '#92400e', | ||||
|                             900: '#78350f', | ||||
|                         }, | ||||
|                         danger: { | ||||
|                             50: '#fef2f2', | ||||
|                             100: '#fee2e2', | ||||
|                             200: '#fecaca', | ||||
|                             300: '#fca5a5', | ||||
|                             400: '#f87171', | ||||
|                             500: '#ef4444', | ||||
|                             600: '#dc2626', | ||||
|                             700: '#b91c1c', | ||||
|                             800: '#991b1b', | ||||
|                             900: '#7f1d1d', | ||||
|                         } | ||||
|                     }, | ||||
|                     animation: { | ||||
|                         'fade-in': 'fadeIn 0.5s ease-in-out', | ||||
|                         'slide-up': 'slideUp 0.3s ease-out', | ||||
|                         'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite', | ||||
|                     }, | ||||
|                     keyframes: { | ||||
|                         fadeIn: { | ||||
|                             '0%': { opacity: '0' }, | ||||
|                             '100%': { opacity: '1' }, | ||||
|                         }, | ||||
|                         slideUp: { | ||||
|                             '0%': { transform: 'translateY(10px)', opacity: '0' }, | ||||
|                             '100%': { transform: 'translateY(0)', opacity: '1' }, | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     </script> | ||||
|     <style> | ||||
|         .glass-effect { | ||||
|             background: rgba(255, 255, 255, 0.25); | ||||
|             backdrop-filter: blur(10px); | ||||
|             border: 1px solid rgba(255, 255, 255, 0.18); | ||||
|         } | ||||
|         .gradient-bg { | ||||
|             background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | ||||
|         } | ||||
|         .card-hover { | ||||
|             transition: all 0.3s ease; | ||||
|         } | ||||
|         .card-hover:hover { | ||||
|             transform: translateY(-5px); | ||||
|             box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); | ||||
|         } | ||||
|     </style> | ||||
| </head> | ||||
| <body class="gradient-bg min-h-screen"> | ||||
|     <div class="container mx-auto px-4 py-8"> | ||||
|         <!-- 헤더 --> | ||||
|         <div class="text-center mb-8 animate-fade-in"> | ||||
|             <h1 class="text-4xl font-bold text-white mb-2">근태현황 대시보드</h1> | ||||
|             <p class="text-white/80 text-lg">실시간 근태 현황을 확인하세요</p> | ||||
|         </div> | ||||
|  | ||||
|         <!-- 통계 카드 --> | ||||
|         <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> | ||||
|             <!-- 출근 카드 --> | ||||
|             <div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up"> | ||||
|                 <div class="flex items-center justify-between"> | ||||
|                     <div> | ||||
|                         <p class="text-white/70 text-sm font-medium">출근</p> | ||||
|                         <p class="text-3xl font-bold text-white" id="presentCount">0</p> | ||||
|                     </div> | ||||
|                     <div class="w-12 h-12 bg-success-500/20 rounded-full flex items-center justify-center"> | ||||
|                         <svg class="w-6 h-6 text-success-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||||
|                             <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path> | ||||
|                         </svg> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|             <!-- 휴가 카드 --> | ||||
|             <div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up"> | ||||
|                 <div class="flex items-center justify-between"> | ||||
|                     <div> | ||||
|                         <p class="text-white/70 text-sm font-medium">휴가</p> | ||||
|                         <p class="text-3xl font-bold text-white" id="leaveCount">0</p> | ||||
|                     </div> | ||||
|                     <div class="w-12 h-12 bg-warning-500/20 rounded-full flex items-center justify-center"> | ||||
|                         <svg class="w-6 h-6 text-warning-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||||
|                             <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path> | ||||
|                         </svg> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|             <!-- 휴가요청 카드 --> | ||||
|             <div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up"> | ||||
|                 <div class="flex items-center justify-between"> | ||||
|                     <div> | ||||
|                         <p class="text-white/70 text-sm font-medium">휴가요청</p> | ||||
|                         <p class="text-3xl font-bold text-white" id="leaveRequestCount">0</p> | ||||
|                     </div> | ||||
|                     <div class="w-12 h-12 bg-primary-500/20 rounded-full flex items-center justify-center"> | ||||
|                         <svg class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||||
|                             <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path> | ||||
|                         </svg> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|             <!-- 구매요청 카드 --> | ||||
|             <div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up"> | ||||
|                 <div class="flex items-center justify-between"> | ||||
|                     <div> | ||||
|                         <p class="text-white/70 text-sm font-medium">구매요청</p> | ||||
|                         <p class="text-3xl font-bold text-white" id="purchaseCount">0</p> | ||||
|                     </div> | ||||
|                     <div class="w-12 h-12 bg-danger-500/20 rounded-full flex items-center justify-center"> | ||||
|                         <svg class="w-6 h-6 text-danger-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||||
|                             <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"></path> | ||||
|                         </svg> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <!-- 휴가자 현황 테이블 --> | ||||
|         <div class="glass-effect rounded-2xl overflow-hidden animate-slide-up"> | ||||
|             <div class="px-6 py-4 border-b border-white/10"> | ||||
|                 <h2 class="text-xl font-semibold text-white flex items-center"> | ||||
|                     <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||||
|                         <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path> | ||||
|                     </svg> | ||||
|                     휴가자 현황 | ||||
|                 </h2> | ||||
|             </div> | ||||
|             <div class="overflow-x-auto"> | ||||
|                 <table class="w-full"> | ||||
|                     <thead class="bg-white/10"> | ||||
|                         <tr> | ||||
|                             <th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">이름</th> | ||||
|                             <th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">휴가 종류</th> | ||||
|                             <th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">시작일</th> | ||||
|                             <th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">종료일</th> | ||||
|                             <th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">사유</th> | ||||
|                         </tr> | ||||
|                     </thead> | ||||
|                     <tbody id="holidayTable" class="divide-y divide-white/10"> | ||||
|                         <!-- 데이터가 여기에 표시됩니다 --> | ||||
|                     </tbody> | ||||
|                 </table> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <!-- 로딩 인디케이터 --> | ||||
|         <div id="loadingIndicator" class="fixed top-4 right-4 bg-white/20 backdrop-blur-sm rounded-full px-4 py-2 text-white text-sm hidden"> | ||||
|             <div class="flex items-center"> | ||||
|                 <div class="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div> | ||||
|                 데이터 업데이트 중... | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <script> | ||||
|     // 휴가 인원 Ajax 업데이트 | ||||
|     function updateLeaveCount() { | ||||
|         showLoading(); | ||||
|         fetch('http://127.0.0.1:9000/Dashboard/TodayCountH') | ||||
|             .then(response => response.text()) | ||||
|             .then(data => { | ||||
|                 const cleanData = data.replace(/"/g, ''); | ||||
|                 const count = parseInt(cleanData, 10); | ||||
|                 animateNumberChange('leaveCount', count); | ||||
|                 hideLoading(); | ||||
|             }) | ||||
|             .catch(error => { | ||||
|                 console.error('휴가 인원 업데이트 중 오류 발생:', error); | ||||
|                 hideLoading(); | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     // 휴가자 목록 Ajax 업데이트 | ||||
|     function updateHolidayList() { | ||||
|         showLoading(); | ||||
|         fetch('http://127.0.0.1:9000/Dashboard/GetholyUser') | ||||
|             .then(response => response.json()) | ||||
|             .then(data => { | ||||
|                 let tableRows = ''; | ||||
|                 if (data && data.length > 0) { | ||||
|                     data.forEach(item => { | ||||
|                         tableRows += ` | ||||
|                             <tr class="hover:bg-white/5 transition-colors"> | ||||
|                                 <td class="px-6 py-4 whitespace-nowrap text-white">${item.uid || '-'}</td> | ||||
|                                 <td class="px-6 py-4 whitespace-nowrap"> | ||||
|                                     <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-warning-500/20 text-warning-300"> | ||||
|                                         ${item.cate || '-'} | ||||
|                                     </span> | ||||
|                                 </td> | ||||
|                                 <td class="px-6 py-4 whitespace-nowrap text-white/80">${item.sdate || '-'}</td> | ||||
|                                 <td class="px-6 py-4 whitespace-nowrap text-white/80">${item.edate || '-'}</td> | ||||
|                                 <td class="px-6 py-4 text-white/80">${item.HolyReason || '-'}</td> | ||||
|                             </tr> | ||||
|                         `; | ||||
|                     }); | ||||
|                 } else { | ||||
|                     tableRows = ` | ||||
|                         <tr> | ||||
|                             <td colspan="5" class="px-6 py-8 text-center text-white/50"> | ||||
|                                 현재 휴가자가 없습니다 | ||||
|                             </td> | ||||
|                         </tr> | ||||
|                     `; | ||||
|                 } | ||||
|                 document.getElementById('holidayTable').innerHTML = tableRows; | ||||
|                 hideLoading(); | ||||
|             }) | ||||
|             .catch(error => { | ||||
|                 console.error('휴가자 목록 업데이트 중 오류 발생:', error); | ||||
|                 document.getElementById('holidayTable').innerHTML = ` | ||||
|                     <tr> | ||||
|                         <td colspan="5" class="px-6 py-8 text-center text-danger-400"> | ||||
|                             데이터를 불러오는 중 오류가 발생했습니다 | ||||
|                         </td> | ||||
|                     </tr> | ||||
|                 `; | ||||
|                 hideLoading(); | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     // 숫자 애니메이션 | ||||
|     function animateNumberChange(elementId, newValue) { | ||||
|         const element = document.getElementById(elementId); | ||||
|         const currentValue = parseInt(element.textContent) || 0; | ||||
|         const increment = (newValue - currentValue) / 20; | ||||
|         let current = currentValue; | ||||
|          | ||||
|         const timer = setInterval(() => { | ||||
|             current += increment; | ||||
|             if ((increment > 0 && current >= newValue) || (increment < 0 && current <= newValue)) { | ||||
|                 element.textContent = newValue; | ||||
|                 clearInterval(timer); | ||||
|             } else { | ||||
|                 element.textContent = Math.floor(current); | ||||
|             } | ||||
|         }, 50); | ||||
|     } | ||||
|  | ||||
|     // 로딩 표시 | ||||
|     function showLoading() { | ||||
|         document.getElementById('loadingIndicator').classList.remove('hidden'); | ||||
|     } | ||||
|  | ||||
|     function hideLoading() { | ||||
|         document.getElementById('loadingIndicator').classList.add('hidden'); | ||||
|     } | ||||
|  | ||||
|     // 페이지 로드 시 데이터 업데이트 | ||||
|     updateLeaveCount(); | ||||
|     updateHolidayList(); | ||||
|  | ||||
|     // 30초마다 데이터 새로고침 | ||||
|     setInterval(() => { | ||||
|         updateLeaveCount(); | ||||
|         updateHolidayList(); | ||||
|     }, 30000); | ||||
|     </script> | ||||
| </body> | ||||
| </html>  | ||||
		Reference in New Issue
	
	Block a user
	 backuppc
					backuppc