index.html

23.63 KB
25/07/2025 13:43
HTML
<!DOCTYPE html>
<html lang="th">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Performance Evaluation System</title>
  <!-- Material Icons -->
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <!-- Chart.js CDN -->
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <!-- Google Fonts: Prompt (Thai) and Roboto (Latin) -->
  <link href="https://fonts.googleapis.com/css2?family=Prompt:wght@400;600;700&family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: 'Prompt', 'Roboto', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      background: linear-gradient(135deg, #0D47A1 0%, #0B3578 100%);
      min-height: 100vh;
      overflow-x: hidden;
    }

    /* Login Page Styles */
    .login-container {
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      padding: 20px;
    }

    .login-card {
      background: rgba(255, 255, 255, 0.95);
      backdrop-filter: blur(10px);
      border-radius: 20px;
      padding: 40px;
      box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
      max-width: 400px;
      width: 100%;
      text-align: center;
      transform: translateY(0);
      transition: all 0.3s ease;
    }

    .login-card:hover {
      transform: translateY(-5px);
      box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15);
    }

    .login-logo {
      width: 80px;
      height: 80px;
      background: linear-gradient(135deg, #0D47A1 0%, #0B3578 100%);
      border-radius: 50%;
      margin: 0 auto 20px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 32px;
      color: white;
      font-weight: bold;
    }

    .login-title {
      color: #333;
      margin-bottom: 10px;
      font-size: 28px;
      font-weight: 600;
    }

    .login-subtitle {
      color: #666;
      margin-bottom: 30px;
      font-size: 14px;
    }

    .form-group {
      margin-bottom: 20px;
      text-align: left;
    }

    .form-group label {
      display: block;
      margin-bottom: 8px;
      color: #555;
      font-weight: 500;
    }

    .form-input {
      width: 100%;
      padding: 15px;
      border: 2px solid #e0e0e0;
      border-radius: 12px;
      font-size: 16px;
      transition: all 0.3s ease;
      background: #f8f9fa;
    }

    .form-input:focus {
      outline: none;
      border-color: #2196F3;
      background: white;
      box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);
    }

    .login-btn {
      width: 100%;
      padding: 15px;
      background: linear-gradient(135deg, #2196F3, #1976D2);
      color: white;
      border: none;
      border-radius: 12px;
      font-size: 16px;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s ease;
      margin-top: 10px;
    }

    .login-btn:hover {
      transform: translateY(-2px);
      box-shadow: 0 10px 20px rgba(33, 150, 243, 0.3);
    }

    .login-btn:active {
      transform: translateY(0);
    }

    /* Dashboard Styles */
    .dashboard {
      display: none;
      min-height: 100vh;
      background: #f5f7fa;
    }

    .sidebar {
      position: fixed;
      left: 0;
      top: 0;
      width: 280px;
      height: 100vh;
      background: linear-gradient(135deg, #0D47A1 0%, #0B3578 100%);
      box-shadow: 4px 0 20px rgba(0, 0, 0, 0.1);
      transition: all 0.3s ease;
      z-index: 1000;
    }

    .sidebar-header {
      display: flex;
      align-items: center;
      padding: 30px 25px;
      border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    }

    .sidebar-logo {
      width: 50px;
      height: 50px;
      background: rgba(255, 255, 255, 0.2);
      border-radius: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 24px;
      color: white;
      margin-right: 15px;
    }

    .sidebar-title {
      color: white;
      font-size: 20px;
      font-weight: 600;
    }

    .sidebar-menu {
      padding: 20px 0;
    }

    .menu-item {
      display: flex;
      align-items: center;
      padding: 15px 25px;
      color: rgba(255, 255, 255, 0.8);
      text-decoration: none;
      transition: all 0.3s ease;
      border-left: 4px solid transparent;
    }

    .menu-item:hover,
    .menu-item.active {
      background: rgba(255, 255, 255, 0.1);
      color: white;
      border-left-color: white;
    }

    .menu-icon {
      width: 24px;
      height: 24px;
      margin-right: 15px;
      font-size: 18px;
      text-align: center;
    }

    .main-content {
      margin-left: 280px;
      transition: margin-left 0.3s ease;
    }

    .top-bar {
      background: white;
      padding: 20px 30px;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .page-title {
      font-size: 24px;
      font-weight: 600;
      color: #333;
    }

    .user-profile {
      display: flex;
      align-items: center;
      gap: 15px;
    }

    .user-avatar {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      background: linear-gradient(135deg, #2196F3, #1976D2);
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-weight: 600;
    }

    .logout-btn {
      background: #f44336;
      color: white;
      border: none;
      padding: 8px 16px;
      border-radius: 8px;
      cursor: pointer;
      font-size: 14px;
      transition: all 0.3s ease;
    }

    .logout-btn:hover {
      background: #d32f2f;
      transform: translateY(-1px);
    }

    .content-area {
      padding: 30px;
    }

    .stats-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
      gap: 25px;
      margin-bottom: 30px;
    }

    .stat-card {
      background: white;
      padding: 25px;
      border-radius: 16px;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
      transition: all 0.3s ease;
      position: relative;
      overflow: hidden;
    }

    .stat-card:hover {
      transform: translateY(-5px);
      box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
    }

    .stat-card::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 4px;
      background: linear-gradient(90deg, #2196F3, #1976D2);
    }

    .stat-value {
      font-size: 36px;
      font-weight: 700;
      color: #2196F3;
      margin-bottom: 5px;
    }

    .stat-label {
      color: #666;
      font-size: 14px;
      text-transform: uppercase;
      letter-spacing: 0.5px;
    }

    .chart-container {
      background: white;
      border-radius: 16px;
      padding: 25px;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
    }

    .chart-title {
      color: #333;
      font-size: 20px;
      font-weight: 600;
      margin-bottom: 20px;
    }

    .chart-placeholder {
      height: 300px;
      width: 100%;
      background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
      border-radius: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #666;
      font-size: 16px;
    }

    .recent-evaluations {
      background: white;
      border-radius: 16px;
      padding: 25px;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
    }

    .table-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 20px;
    }

    .table-title {
      color: #333;
      font-size: 20px;
      font-weight: 600;
    }

    .add-btn {
      background: linear-gradient(135deg, #2196F3, #1976D2);
      color: white;
      border: none;
      padding: 10px 20px;
      border-radius: 8px;
      cursor: pointer;
      font-size: 14px;
      font-weight: 500;
      transition: all 0.3s ease;
    }

    .add-btn:hover {
      transform: translateY(-2px);
      box-shadow: 0 6px 15px rgba(33, 150, 243, 0.3);
    }

    .table {
      width: 100%;
      border-collapse: collapse;
    }

    .table th,
    .table td {
      padding: 15px;
      text-align: left;
      border-bottom: 1px solid #eee;
    }

    .table th {
      background: #f8f9fa;
      color: #666;
      font-weight: 600;
      text-transform: uppercase;
      font-size: 12px;
      letter-spacing: 0.5px;
    }

    .status-badge {
      padding: 4px 12px;
      border-radius: 20px;
      font-size: 12px;
      font-weight: 500;
    }

    .status-completed {
      background: #e8f5e8;
      color: #2e7d32;
    }

    .status-pending {
      background: #fff3e0;
      color: #f57c00;
    }

    .status-draft {
      background: #f3e5f5;
      color: #7b1fa2;
    }

    /* Mobile Responsive */
    .mobile-toggle {
      display: none;
      background: none;
      border: none;
      font-size: 24px;
      cursor: pointer;
      color: #333;
    }

    .charts-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 30px;
      margin-bottom: 30px;
    }

    @media (max-width: 768px) {
      .sidebar {
        transform: translateX(-100%);
      }

      .sidebar.mobile-open {
        transform: translateX(0);
      }

      .main-content {
        margin-left: 0;
      }

      .mobile-toggle {
        display: block;
      }

      .top-bar {
        padding: 15px 20px;
      }

      .content-area {
        padding: 20px;
      }

      .stats-grid {
        grid-template-columns: 1fr;
        gap: 15px;
      }

      .user-profile {
        gap: 10px;
      }

      .login-card {
        padding: 30px 20px;
        margin: 20px;
      }

      .table {
        font-size: 14px;
      }

      .table th,
      .table td {
        padding: 10px 8px;
      }
    }

    @media (max-width: 900px) {
      .charts-grid {
        grid-template-columns: 1fr;
      }
    }

    /* Animations */
    @keyframes fadeIn {
      from {
        opacity: 0;
        transform: translateY(20px);
      }

      to {
        opacity: 1;
        transform: translateY(0);
      }
    }

    .fade-in {
      animation: fadeIn 0.6s ease;
    }

    /* Overlay for mobile sidebar */
    .sidebar-overlay {
      display: none;
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(0, 0, 0, 0.5);
      z-index: 999;
    }

    .sidebar-overlay.active {
      display: block;
    }
  </style>
</head>

<body>
  <!-- Login Page -->
  <div id="loginPage" class="login-container">
    <div class="login-card fade-in">
      <div class="login-logo">PE</div>
      <h1 class="login-title">Performance Evaluation</h1>
      <p class="login-subtitle">เข้าสู่ระบบประเมินผลการปฏิบัติงาน</p>

      <form id="loginForm">
        <div class="form-group">
          <label for="username">ชื่อผู้ใช้</label>
          <input type="text" id="username" class="form-input" placeholder="กรอกชื่อผู้ใช้" required>
        </div>

        <div class="form-group">
          <label for="password">รหัสผ่าน</label>
          <input type="password" id="password" class="form-input" placeholder="กรอกรหัสผ่าน" required>
        </div>

        <button type="submit" class="login-btn">เข้าสู่ระบบ</button>
      </form>
    </div>
  </div>

  <!-- Dashboard -->
  <div id="dashboard" class="dashboard">
    <!-- Sidebar -->
    <nav class="sidebar" id="sidebar">
      <div class="sidebar-header">
        <div class="sidebar-logo">PE</div>
        <div class="sidebar-title">Performance<br>Evaluation</div>
      </div>

      <div class="sidebar-menu">
        <a href="#" class="menu-item active">
          <span class="menu-icon material-icons">dashboard</span>
          แดชบอร์ด
        </a>
        <a href="#" class="menu-item">
          <span class="menu-icon material-icons">assignment</span>
          การประเมิน
        </a>
        <a href="#" class="menu-item">
          <span class="menu-icon material-icons">group</span>
          พนักงาน
        </a>
        <a href="#" class="menu-item">
          <span class="menu-icon material-icons">bar_chart</span>
          รายงาน
        </a>
        <a href="#" class="menu-item">
          <span class="menu-icon material-icons">settings</span>
          ตั้งค่า
        </a>
      </div>
    </nav>

    <!-- Mobile Sidebar Overlay -->
    <div class="sidebar-overlay" id="sidebarOverlay"></div>

    <!-- Main Content -->
    <main class="main-content">
      <!-- Top Bar -->
      <header class="top-bar">
        <div style="display: flex; align-items: center; gap: 15px;">
          <button class="mobile-toggle" id="mobileToggle">☰</button>
          <h1 class="page-title">Dashboard</h1>
        </div>

        <div class="user-profile">
          <div class="user-avatar">A</div>
          <span>Admin User</span>
          <button class="logout-btn" id="logoutBtn">ออกจากระบบ</button>
        </div>
      </header>

      <!-- Content Area -->
      <div class="content-area">
        <!-- Stats Grid -->
        <div class="stats-grid">
          <div class="stat-card fade-in">
            <div class="stat-value">156</div>
            <div class="stat-label">การประเมินทั้งหมด</div>
          </div>

          <div class="stat-card fade-in">
            <div class="stat-value">89</div>
            <div class="stat-label">การประเมินเสร็จสิ้น</div>
          </div>

          <div class="stat-card fade-in">
            <div class="stat-value">34</div>
            <div class="stat-label">รอการประเมิน</div>
          </div>

          <div class="stat-card fade-in">
            <div class="stat-value">4.2</div>
            <div class="stat-label">คะแนนเฉลี่ย</div>
          </div>
        </div>

        <!-- Charts Grid -->
        <div class="charts-grid">
          <div class="chart-container fade-in">
            <h2 class="chart-title">ผลการประเมินรายเดือน</h2>
            <div class="chart-placeholder">
              <canvas id="monthlyChart" height="300"></canvas>
            </div>
          </div>
          <div class="chart-container fade-in">
            <h2 class="chart-title">ผลการประเมินรายไตรมาส</h2>
            <div class="chart-placeholder">
              <canvas id="quarterChart" height="300"></canvas>
            </div>
          </div>
        </div>

        <!-- Recent Evaluations Table -->
        <div class="recent-evaluations fade-in">
          <div class="table-header">
            <h2 class="table-title">การประเมินล่าสุด</h2>
            <button class="add-btn">+ เพิ่มการประเมิน</button>
          </div>

          <table class="table">
            <thead>
              <tr>
                <th>ชื่อพนักงาน</th>
                <th>ตำแหน่ง</th>
                <th>วันที่ประเมิน</th>
                <th>คะแนน</th>
                <th>สถานะ</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>สมชาย ใจดี</td>
                <td>นักพัฒนาระบบ</td>
                <td>25/07/2025</td>
                <td>4.5</td>
                <td><span class="status-badge status-completed">เสร็จสิ้น</span></td>
              </tr>
              <tr>
                <td>สมหญิง รักงาน</td>
                <td>นักวิเคราะห์ระบบ</td>
                <td>24/07/2025</td>
                <td>4.2</td>
                <td><span class="status-badge status-pending">รอการอนุมัติ</span></td>
              </tr>
              <tr>
                <td>สมศักดิ์ ทำงาน</td>
                <td>ผู้จัดการโครงการ</td>
                <td>23/07/2025</td>
                <td>4.8</td>
                <td><span class="status-badge status-completed">เสร็จสิ้น</span></td>
              </tr>
              <tr>
                <td>สมใจ ขยันงาน</td>
                <td>นักทดสอบระบบ</td>
                <td>22/07/2025</td>
                <td>-</td>
                <td><span class="status-badge status-draft">ร่าง</span></td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </main>
  </div>

  <script>
    // Chart.js: Render two sample line charts for evaluation results
    document.addEventListener('DOMContentLoaded', function() {
      // Chart 1: Monthly
      const departmentChartCtx = document.getElementById('monthlyChart');
      if (departmentChartCtx) {
        new Chart(departmentChartCtx, {
          type: 'bar',
          data: {
            labels: ['ฝ่ายขาย', 'การตลาด', 'ไอที', 'บุคคล', 'บัญชี'],
            datasets: [{
              label: 'คะแนนเฉลี่ย',
              data: [82, 78, 90, 85, 75],
              backgroundColor: [
                'rgba(33, 150, 243, 0.7)',
                'rgba(76, 175, 80, 0.7)',
                'rgba(255, 152, 0, 0.7)',
                'rgba(244, 67, 54, 0.7)',
                'rgba(156, 39, 176, 0.7)'
              ],
              borderColor: [
                '#2196F3',
                '#4CAF50',
                '#FF9800',
                '#F44336',
                '#9C27B0'
              ],
              borderWidth: 1,
              borderRadius: 5,
            }]
          },
          options: {
            responsive: true,
            maintainAspectRatio: false,
            scales: {
              y: {
                beginAtZero: true,
                max: 100
              }
            },
            plugins: {
              legend: {
                display: false
              }
            }
          }
        });
      }

      // Chart 2: Quarterly
      const trendChartCtx = document.getElementById('quarterChart');
      if (trendChartCtx) {
        new Chart(trendChartCtx, {
          type: 'line',
          data: {
            labels: ['ไตรมาส 1', 'ไตรมาส 2', 'ไตรมาส 3', 'ไตรมาส 4'],
            datasets: [{
              label: 'คะแนนเฉลี่ยรวม',
              data: [75, 80, 79, 88],
              fill: true,
              backgroundColor: 'rgba(33, 150, 243, 0.2)',
              borderColor: '#2196F3',
              tension: 0.4 // Makes the line smooth
            }]
          },
          options: {
            responsive: true,
            maintainAspectRatio: false,
            scales: {
              y: {
                beginAtZero: true,
                max: 100
              }
            },
            plugins: {
              legend: {
                display: true
              }
            }
          }
        });
      }
    });
    // Login functionality
    const loginForm = document.getElementById('loginForm');
    const loginPage = document.getElementById('loginPage');
    const dashboard = document.getElementById('dashboard');
    const logoutBtn = document.getElementById('logoutBtn');
    const mobileToggle = document.getElementById('mobileToggle');
    const sidebar = document.getElementById('sidebar');
    const sidebarOverlay = document.getElementById('sidebarOverlay');

    // Login form submission
    loginForm.addEventListener('submit', function(e) {
      e.preventDefault();

      const username = document.getElementById('username').value;
      const password = document.getElementById('password').value;

      // Simple validation (in real application, this would be server-side)
      if (username && password) {
        loginPage.style.display = 'none';
        dashboard.style.display = 'block';

        // Add fade-in animation to dashboard elements
        setTimeout(() => {
          const elements = document.querySelectorAll('.fade-in');
          elements.forEach((el, index) => {
            setTimeout(() => {
              el.style.opacity = '1';
            }, index * 100);
          });
        }, 100);
      } else {
        alert('กรุณากรอกชื่อผู้ใช้และรหัสผ่าน');
      }
    });

    // Logout functionality
    logoutBtn.addEventListener('click', function() {
      if (confirm('คุณต้องการออกจากระบบหรือไม่?')) {
        dashboard.style.display = 'none';
        loginPage.style.display = 'flex';

        // Reset form
        document.getElementById('username').value = '';
        document.getElementById('password').value = '';
      }
    });

    // Mobile sidebar toggle
    mobileToggle.addEventListener('click', function() {
      sidebar.classList.toggle('mobile-open');
      sidebarOverlay.classList.toggle('active');
    });

    // Close sidebar when clicking overlay
    sidebarOverlay.addEventListener('click', function() {
      sidebar.classList.remove('mobile-open');
      sidebarOverlay.classList.remove('active');
    });

    // Menu item click handling
    const menuItems = document.querySelectorAll('.menu-item');
    menuItems.forEach(item => {
      item.addEventListener('click', function(e) {
        e.preventDefault();

        // Remove active class from all items
        menuItems.forEach(i => i.classList.remove('active'));

        // Add active class to clicked item
        this.classList.add('active');

        // Close mobile sidebar
        sidebar.classList.remove('mobile-open');
        sidebarOverlay.classList.remove('active');
      });
    });

    // Add hover effects to cards
    const cards = document.querySelectorAll('.stat-card, .chart-container, .recent-evaluations');
    cards.forEach(card => {
      card.addEventListener('mouseenter', function() {
        this.style.transform = 'translateY(-5px)';
      });

      card.addEventListener('mouseleave', function() {
        this.style.transform = 'translateY(0)';
      });
    });

    // Add button click animations
    const buttons = document.querySelectorAll('.login-btn, .add-btn, .logout-btn');
    buttons.forEach(btn => {
      btn.addEventListener('click', function(e) {
        // Create ripple effect
        const ripple = document.createElement('span');
        const rect = this.getBoundingClientRect();
        const size = Math.max(rect.width, rect.height);
        const x = e.clientX - rect.left - size / 2;
        const y = e.clientY - rect.top - size / 2;

        ripple.style.width = ripple.style.height = size + 'px';
        ripple.style.left = x + 'px';
        ripple.style.top = y + 'px';
        ripple.classList.add('ripple');

        this.appendChild(ripple);

        setTimeout(() => {
          ripple.remove();
        }, 600);
      });
    });

    // Add CSS for ripple effect
    const style = document.createElement('style');
    style.textContent = `
            .ripple {
                position: absolute;
                border-radius: 50%;
                background: rgba(255, 255, 255, 0.6);
                transform: scale(0);
                animation: ripple 0.6s ease-out;
                pointer-events: none;
            }

            @keyframes ripple {
                to {
                    transform: scale(4);
                    opacity: 0;
                }
            }
        `;
    document.head.appendChild(style);
  </script>
</body>

</html>