<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard - ระบบจัดการ</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Thai:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Noto Sans Thai', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #6fa8dc 75%, #4285f4 100%);
background-attachment: fixed;
min-height: 100vh;
color: #212121;
}
/* Material Design Shadows */
.elevation-1 { box-shadow: 0px 2px 1px -1px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 1px 3px 0px rgba(0,0,0,0.12); }
.elevation-2 { box-shadow: 0px 3px 1px -2px rgba(0,0,0,0.2), 0px 2px 2px 0px rgba(0,0,0,0.14), 0px 1px 5px 0px rgba(0,0,0,0.12); }
.elevation-4 { box-shadow: 0px 2px 4px -1px rgba(0,0,0,0.2), 0px 4px 5px 0px rgba(0,0,0,0.14), 0px 1px 10px 0px rgba(0,0,0,0.12); }
.elevation-8 { box-shadow: 0px 5px 5px -3px rgba(0,0,0,0.2), 0px 8px 10px 1px rgba(0,0,0,0.14), 0px 3px 14px 2px rgba(0,0,0,0.12); }
/* Login Page Styles */
.login-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 24px;
}
.login-card {
background: #ffffff;
border-radius: 8px;
padding: 48px;
width: 100%;
max-width: 400px;
transition: box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.login-card:hover {
box-shadow: 0px 8px 10px -5px rgba(0,0,0,0.2), 0px 16px 24px 2px rgba(0,0,0,0.14), 0px 6px 30px 5px rgba(0,0,0,0.12);
}
.login-header {
text-align: center;
margin-bottom: 32px;
}
.login-header h2 {
color: #1976d2;
font-size: 24px;
font-weight: 500;
margin-bottom: 8px;
letter-spacing: 0.25px;
}
.login-header p {
color: #757575;
font-size: 14px;
letter-spacing: 0.25px;
}
.form-group {
margin-bottom: 24px;
position: relative;
}
.form-group label {
position: absolute;
top: 16px;
left: 12px;
color: #757575;
font-size: 16px;
font-weight: 400;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
pointer-events: none;
letter-spacing: 0.15px;
}
.form-group input {
width: 100%;
padding: 16px 12px;
border: 1px solid #e0e0e0;
border-radius: 4px;
font-size: 16px;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
font-family: 'Noto Sans Thai', sans-serif;
background: transparent;
letter-spacing: 0.15px;
}
.form-group input:focus {
outline: none;
border-color: #1976d2;
border-width: 2px;
}
.form-group input:focus + label,
.form-group input:not(:placeholder-shown) + label {
top: -8px;
left: 8px;
font-size: 12px;
color: #1976d2;
background: white;
padding: 0 4px;
}
.login-btn {
width: 100%;
padding: 12px 24px;
background: #1976d2;
color: white;
border: none;
border-radius: 4px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
font-family: 'Noto Sans Thai', sans-serif;
letter-spacing: 1.25px;
text-transform: uppercase;
min-height: 36px;
}
.login-btn:hover {
background: #1565c0;
box-shadow: 0px 2px 4px -1px rgba(0,0,0,0.2), 0px 4px 5px 0px rgba(0,0,0,0.14), 0px 1px 10px 0px rgba(0,0,0,0.12);
}
.login-btn:active {
background: #0d47a1;
}
/* Dashboard Styles */
.dashboard {
display: none;
min-height: 100vh;
background: linear-gradient(135deg, #e3f2fd 0%, #f1f8e9 30%, #fff3e0 60%, #fce4ec 100%);
}
.dashboard.active {
display: block;
}
.sidebar {
position: fixed;
left: 0;
top: 0;
width: 280px;
height: 100vh;
background: #ffffff;
border-right: 1px solid #e0e0e0;
padding: 0;
z-index: 1000;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
overflow-y: auto;
}
.sidebar.collapsed {
width: 72px;
}
.sidebar-header {
padding: 24px 24px 16px;
border-bottom: 1px solid #e0e0e0;
margin-bottom: 8px;
display: flex;
align-items: center;
}
.sidebar-header .material-icons {
color: #1976d2;
margin-right: 16px;
font-size: 32px;
}
.sidebar-header h3 {
color: #1976d2;
font-size: 20px;
font-weight: 500;
transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
letter-spacing: 0.15px;
}
.sidebar.collapsed .sidebar-header h3 {
opacity: 0;
}
.nav-menu {
list-style: none;
padding: 8px 0;
}
.nav-item {
margin-bottom: 0;
}
.nav-link {
display: flex;
align-items: center;
padding: 12px 24px;
color: #616161;
text-decoration: none;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
font-weight: 500;
letter-spacing: 0.1px;
position: relative;
}
.nav-link:hover {
background: rgba(25, 118, 210, 0.04);
color: #1976d2;
}
.nav-link.active {
background: rgba(25, 118, 210, 0.12);
color: #1976d2;
}
.nav-link.active::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 4px;
background: #1976d2;
}
.nav-icon {
margin-right: 24px;
font-size: 24px;
transition: margin 0.3s cubic-bezier(0.4, 0, 0.2, 1);
width: 24px;
text-align: center;
}
.sidebar.collapsed .nav-icon {
margin-right: 0;
}
.nav-text {
transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
font-size: 14px;
}
.sidebar.collapsed .nav-text {
opacity: 0;
}
.main-content {
margin-left: 280px;
transition: margin-left 0.3s cubic-bezier(0.4, 0, 0.2, 1);
min-height: 100vh;
}
.sidebar.collapsed + .main-content {
margin-left: 72px;
}
.header {
background: #ffffff;
padding: 16px 24px;
border-bottom: 1px solid #e0e0e0;
display: flex;
justify-content: space-between;
align-items: center;
position: sticky;
top: 0;
z-index: 999;
}
.header-left {
display: flex;
align-items: center;
}
.toggle-btn {
background: none;
border: none;
cursor: pointer;
margin-right: 16px;
padding: 8px;
border-radius: 50%;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
color: #616161;
}
.toggle-btn:hover {
background: rgba(0, 0, 0, 0.04);
}
.toggle-btn .material-icons {
font-size: 24px;
}
.page-title {
font-size: 20px;
font-weight: 500;
color: #212121;
letter-spacing: 0.15px;
}
.header-right {
display: flex;
align-items: center;
gap: 16px;
}
.search-container {
position: relative;
display: flex;
align-items: center;
}
.search-input {
padding: 8px 12px 8px 40px;
border: 1px solid #e0e0e0;
border-radius: 4px;
font-family: 'Noto Sans Thai', sans-serif;
font-size: 14px;
width: 200px;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
background: #fafafa;
}
.search-input:focus {
outline: none;
border-color: #1976d2;
background: white;
width: 280px;
}
.search-icon {
position: absolute;
left: 12px;
color: #757575;
}
.user-profile {
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
padding: 8px 12px;
border-radius: 20px;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.user-profile:hover {
background: rgba(0, 0, 0, 0.04);
}
.user-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: #1976d2;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 500;
font-size: 14px;
}
.user-name {
font-size: 14px;
font-weight: 500;
color: #212121;
}
.logout-btn {
background: none;
color: #d32f2f;
border: 1px solid #d32f2f;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
font-family: 'Noto Sans Thai', sans-serif;
font-weight: 500;
font-size: 14px;
letter-spacing: 1.25px;
text-transform: uppercase;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.logout-btn:hover {
background: rgba(211, 47, 47, 0.04);
}
.content {
padding: 24px;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
margin-bottom: 32px;
}
.stat-card {
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
padding: 28px;
border-radius: 16px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border: none;
position: relative;
overflow: hidden;
backdrop-filter: blur(10px);
box-shadow:
0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06),
0 0 0 1px rgba(255, 255, 255, 0.05) inset;
}
.stat-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--card-gradient);
border-radius: 16px 16px 0 0;
}
.stat-card:hover {
transform: translateY(-8px) scale(1.02);
box-shadow:
0 20px 25px -5px rgba(0, 0, 0, 0.1),
0 10px 10px -5px rgba(0, 0, 0, 0.04),
0 0 0 1px rgba(255, 255, 255, 0.05) inset;
}
.stat-card.users {
--card-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
background: linear-gradient(135deg, rgba(102, 126, 234, 0.03) 0%, rgba(118, 75, 162, 0.03) 100%), linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
}
.stat-card.sales {
--card-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
background: linear-gradient(135deg, rgba(240, 147, 251, 0.03) 0%, rgba(245, 87, 108, 0.03) 100%), linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
}
.stat-card.orders {
--card-gradient: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
background: linear-gradient(135deg, rgba(79, 172, 254, 0.03) 0%, rgba(0, 242, 254, 0.03) 100%), linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
}
.stat-card.conversion {
--card-gradient: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
background: linear-gradient(135deg, rgba(67, 233, 123, 0.03) 0%, rgba(56, 249, 215, 0.03) 100%), linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
}
.stat-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 16px;
}
.stat-title {
color: #757575;
font-size: 14px;
font-weight: 500;
letter-spacing: 0.1px;
line-height: 1.43;
}
.stat-icon {
width: 48px;
height: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
position: relative;
backdrop-filter: blur(10px);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
.stat-icon.users {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.stat-icon.sales {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
color: white;
box-shadow: 0 4px 15px rgba(240, 147, 251, 0.4);
}
.stat-icon.orders {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
box-shadow: 0 4px 15px rgba(79, 172, 254, 0.4);
}
.stat-icon.conversion {
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
color: white;
box-shadow: 0 4px 15px rgba(67, 233, 123, 0.4);
}
.stat-value {
font-size: 36px;
font-weight: 600;
color: #212121;
margin-bottom: 12px;
line-height: 1.1;
background: linear-gradient(135deg, #212121 0%, #424242 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.stat-change {
font-size: 12px;
font-weight: 500;
letter-spacing: 0.4px;
display: flex;
align-items: center;
gap: 4px;
}
.stat-change.positive {
color: #4caf50;
}
.stat-change.negative {
color: #f44336;
}
.chart-section {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 24px;
margin-bottom: 32px;
}
.chart-card {
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
padding: 28px;
border-radius: 16px;
border: none;
backdrop-filter: blur(10px);
box-shadow:
0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06),
0 0 0 1px rgba(255, 255, 255, 0.05) inset;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.chart-card:hover {
transform: translateY(-4px);
box-shadow:
0 20px 25px -5px rgba(0, 0, 0, 0.1),
0 10px 10px -5px rgba(0, 0, 0, 0.04),
0 0 0 1px rgba(255, 255, 255, 0.05) inset;
}
.chart-header {
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 1px solid #e0e0e0;
}
.chart-title {
font-size: 20px;
font-weight: 500;
color: #212121;
margin-bottom: 4px;
letter-spacing: 0.15px;
}
.chart-subtitle {
color: #757575;
font-size: 14px;
letter-spacing: 0.25px;
}
.chart-container {
position: relative;
height: 300px;
}
.recent-activity {
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
padding: 28px;
border-radius: 16px;
border: none;
backdrop-filter: blur(10px);
box-shadow:
0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06),
0 0 0 1px rgba(255, 255, 255, 0.05) inset;
}
.activity-item {
display: flex;
align-items: flex-start;
padding: 16px 0;
border-bottom: 1px solid #f5f5f5;
}
.activity-item:last-child {
border-bottom: none;
}
.activity-avatar {
width: 44px;
height: 44px;
border-radius: 50%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 16px;
font-weight: 600;
margin-right: 16px;
flex-shrink: 0;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}
.activity-content {
flex: 1;
min-width: 0;
}
.activity-text {
color: #212121;
font-size: 14px;
margin-bottom: 4px;
line-height: 1.43;
}
.activity-time {
color: #757575;
font-size: 12px;
letter-spacing: 0.4px;
}
.fab {
position: fixed;
bottom: 24px;
right: 24px;
width: 56px;
height: 56px;
border-radius: 50%;
background: #1976d2;
color: white;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 1000;
}
.fab:hover {
background: #1565c0;
box-shadow: 0px 5px 5px -3px rgba(0,0,0,0.2), 0px 8px 10px 1px rgba(0,0,0,0.14), 0px 3px 14px 2px rgba(0,0,0,0.12);
}
@media (max-width: 768px) {
.sidebar {
width: 72px;
}
.main-content {
margin-left: 72px;
}
.chart-section {
grid-template-columns: 1fr;
}
.stats-grid {
grid-template-columns: 1fr;
}
.search-input {
width: 140px;
}
.search-input:focus {
width: 200px;
}
.user-name {
display: none;
}
}
.hidden {
display: none;
}
/* Snackbar */
.snackbar {
position: fixed;
bottom: 24px;
left: 50%;
transform: translateX(-50%) translateY(100px);
background: #323232;
color: white;
padding: 14px 24px;
border-radius: 4px;
font-size: 14px;
font-weight: 400;
letter-spacing: 0.25px;
z-index: 10000;
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.snackbar.show {
transform: translateX(-50%) translateY(0);
}
/* Ripple Effect */
.ripple {
position: relative;
overflow: hidden;
}
.ripple::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width 0.3s, height 0.3s;
}
.ripple:active::before {
width: 300px;
height: 300px;
}
</style>
</head>
<body>
<!-- Login Page -->
<div id="loginPage" class="login-container">
<div class="login-card elevation-8">
<div class="login-header">
<h2>เข้าสู่ระบบ</h2>
<p>กรุณาใส่ข้อมูลเพื่อเข้าสู่ระบบ</p>
</div>
<form id="loginForm">
<div class="form-group">
<input type="text" id="username" name="username" required placeholder=" ">
<label for="username">ชื่อผู้ใช้</label>
</div>
<div class="form-group">
<input type="password" id="password" name="password" required placeholder=" ">
<label for="password">รหัสผ่าน</label>
</div>
<button type="submit" class="login-btn ripple elevation-2">เข้าสู่ระบบ</button>
</form>
</div>
</div>
<!-- Dashboard -->
<div id="dashboard" class="dashboard">
<div class="sidebar elevation-4" id="sidebar">
<div class="sidebar-header">
<span class="material-icons">dashboard</span>
<h3>ระบบจัดการ</h3>
</div>
<ul class="nav-menu">
<li class="nav-item">
<a href="#" class="nav-link active ripple" data-page="dashboard">
<span class="material-icons nav-icon">dashboard</span>
<span class="nav-text">หน้าหลัก</span>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link ripple" data-page="users">
<span class="material-icons nav-icon">people</span>
<span class="nav-text">จัดการผู้ใช้</span>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link ripple" data-page="products">
<span class="material-icons nav-icon">inventory</span>
<span class="nav-text">สินค้า</span>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link ripple" data-page="orders">
<span class="material-icons nav-icon">shopping_cart</span>
<span class="nav-text">คำสั่งซื้อ</span>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link ripple" data-page="analytics">
<span class="material-icons nav-icon">analytics</span>
<span class="nav-text">รายงาน</span>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link ripple" data-page="settings">
<span class="material-icons nav-icon">settings</span>
<span class="nav-text">ตั้งค่า</span>
</a>
</li>
</ul>
</div>
<div class="main-content">
<header class="header elevation-1">
<div class="header-left">
<button class="toggle-btn ripple" id="toggleSidebar">
<span class="material-icons">menu</span>
</button>
<h1 class="page-title">หน้าหลัก</h1>
</div>
<div class="header-right">
<div class="search-container">
<input type="text" class="search-input" placeholder="ค้นหา...">
<span class="material-icons search-icon">search</span>
</div>
<div class="user-profile ripple">
<div class="user-avatar">A</div>
<span class="user-name">ผู้ดูแลระบบ</span>
</div>
<button class="logout-btn ripple" id="logoutBtn">ออกจากระบบ</button>
</div>
</header>
<div class="content">
<div class="stats-grid">
<div class="stat-card elevation-1 users">
<div class="stat-header">
<span class="stat-title">ผู้ใช้ทั้งหมด</span>
<div class="stat-icon users">
<span class="material-icons">people</span>
</div>
</div>
<div class="stat-value">2,847</div>
<div class="stat-change positive">
<span class="material-icons" style="font-size: 16px;">trending_up</span>
+12% จากเดือนที่แล้ว
</div>
</div>
<div class="stat-card elevation-1 sales">
<div class="stat-header">
<span class="stat-title">ยอดขายวันนี้</span>
<div class="stat-icon sales">
<span class="material-icons">attach_money</span>
</div>
</div>
<div class="stat-value">฿125,480</div>
<div class="stat-change positive">
<span class="material-icons" style="font-size: 16px;">trending_up</span>
+8.5% จากเมื่อวาน
</div>
</div>
<div class="stat-card elevation-1 orders">
<div class="stat-header">
<span class="stat-title">คำสั่งซื้อใหม่</span>
<div class="stat-icon orders">
<span class="material-icons">shopping_cart</span>
</div>
</div>
<div class="stat-value">156</div>
<div class="stat-change negative">
<span class="material-icons" style="font-size: 16px;">trending_down</span>
-3.2% จากเมื่อวาน
</div>
</div>
<div class="stat-card elevation-1 conversion">
<div class="stat-header">
<span class="stat-title">อัตราการแปลง</span>
<div class="stat-icon conversion">
<span class="material-icons">trending_up</span>
</div>
</div>
<div class="stat-value">3.24%</div>
<div class="stat-change positive">
<span class="material-icons" style="font-size: 16px;">trending_up</span>
+0.8% จากสัปดาห์ที่แล้ว
</div>
</div>
</div>
<div class="chart-section">
<div class="chart-card elevation-1">
<div class="chart-header">
<h3 class="chart-title">ยอดขาย 30 วันที่ผ่านมา</h3>
<p class="chart-subtitle">เปรียบเทียบกับช่วงเวลาเดียวกันของเดือนที่แล้ว</p>
</div>
<div class="chart-container">
<canvas id="salesChart"></canvas>
</div>
</div>
<div class="chart-card elevation-1">
<div class="chart-header">
<h3 class="chart-title">สินค้าขายดี</h3>
<p class="chart-subtitle">อันดับสินค้าที่ขายดีที่สุด</p>
</div>
<div class="chart-container">
<canvas id="topProductsChart"></canvas>
</div>
</div>
</div>
<div class="recent-activity elevation-1">
<div class="chart-header">
<h3 class="chart-title">กิจกรรมล่าสุด</h3>
<p class="chart-subtitle">การเคลื่อนไหวล่าสุดในระบบ</p>
</div>
<div class="activity-item">
<div class="activity-avatar">สม</div>
<div class="activity-content">
<div class="activity-text">สมชาย ใสใจ ทำการสั่งซื้อสินค้า 3 รายการ</div>
<div class="activity-time">5 นาทีที่แล้ว</div>
</div>
</div>
<div class="activity-item">
<div class="activity-avatar">มา</div>
<div class="activity-content">
<div class="activity-text">มาลี ดีใจ เพิ่มสินค้าใหม่ "กระเป๋าหนัง" เข้าระบบ</div>
<div class="activity-time">15 นาทีที่แล้ว</div>
</div>
</div>
<div class="activity-item">
<div class="activity-avatar">จิ</div>
<div class="activity-content">
<div class="activity-text">จิตรา สบายใจ อัปเดตโปรไฟล์ส่วนตัว</div>
<div class="activity-time">30 นาทีที่แล้ว</div>
</div>
</div>
<div class="activity-item">
<div class="activity-avatar">วิ</div>
<div class="activity-content">
<div class="activity-text">วิชัย รักดี ชำระเงินคำสั่งซื้อ #ORD-2024-001</div>
<div class="activity-time">45 นาทีที่แล้ว</div>
</div>
</div>
<div class="activity-item">
<div class="activity-avatar">อร</div>
<div class="activity-content">
<div class="activity-text">อรทัย มีสุข ยกเลิกคำสั่งซื้อ #ORD-2024-002</div>
<div class="activity-time">1 ชั่วโมงที่แล้ว</div>
</div>
</div>
</div>
</div>
</div>
<!-- Floating Action Button -->
<button class="fab elevation-8 ripple">
<span class="material-icons">add</span>
</button>
</div>
<script>
// ตัวแปรสำหรับจัดการสถานะ
let isLoggedIn = false;
let salesChart, topProductsChart;
// อ้างอิง DOM elements
const loginPage = document.getElementById('loginPage');
const dashboard = document.getElementById('dashboard');
const loginForm = document.getElementById('loginForm');
const sidebar = document.getElementById('sidebar');
const toggleBtn = document.getElementById('toggleSidebar');
const logoutBtn = document.getElementById('logoutBtn');
const navLinks = document.querySelectorAll('.nav-link');
const pageTitle = document.querySelector('.page-title');
// Material Design Ripple Effect
function createRipple(event) {
const button = event.currentTarget;
const circle = document.createElement('span');
const diameter = Math.max(button.clientWidth, button.clientHeight);
const radius = diameter / 2;
circle.style.width = circle.style.height = `${diameter}px`;
circle.style.left = `${event.clientX - button.offsetLeft - radius}px`;
circle.style.top = `${event.clientY - button.offsetTop - radius}px`;
circle.classList.add('ripple-effect');
const ripple = button.getElementsByClassName('ripple-effect')[0];
if (ripple) {
ripple.remove();
}
button.appendChild(circle);
}
// เพิ่ม Ripple Effect CSS
const rippleStyle = document.createElement('style');
rippleStyle.textContent = `
.ripple-effect {
position: absolute;
border-radius: 50%;
transform: scale(0);
animation: ripple 600ms linear;
background-color: rgba(255, 255, 255, 0.6);
}
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
`;
document.head.appendChild(rippleStyle);
// เพิ่ม Ripple Effect ให้กับปุ่มทั้งหมด
document.querySelectorAll('.ripple').forEach(button => {
button.addEventListener('click', createRipple);
});
// ฟังก์ชันแสดง Snackbar
function showSnackbar(message, duration = 3000) {
const snackbar = document.createElement('div');
snackbar.className = 'snackbar elevation-8';
snackbar.textContent = message;
document.body.appendChild(snackbar);
setTimeout(() => snackbar.classList.add('show'), 100);
setTimeout(() => {
snackbar.classList.remove('show');
setTimeout(() => document.body.removeChild(snackbar), 300);
}, duration);
}
// จัดการการเข้าสู่ระบบ
loginForm.addEventListener('submit', function(e) {
e.preventDefault();
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
if (username && password) {
isLoggedIn = true;
showDashboard();
// เอฟเฟกต์การเข้าสู่ระบบ
loginPage.style.transform = 'scale(0.95)';
loginPage.style.opacity = '0';
setTimeout(() => {
loginPage.style.display = 'none';
dashboard.classList.add('active');
dashboard.style.opacity = '0';
dashboard.style.transform = 'translateY(20px)';
setTimeout(() => {
dashboard.style.transition = 'all 0.5s cubic-bezier(0.4, 0, 0.2, 1)';
dashboard.style.opacity = '1';
dashboard.style.transform = 'translateY(0)';
initCharts();
showSnackbar('เข้าสู่ระบบสำเร็จ!');
}, 50);
}, 300);
} else {
showSnackbar('กรุณากรอกชื่อผู้ใช้และรหัสผ่าน');
}
});
// แสดง Dashboard
function showDashboard() {
loginPage.classList.add('hidden');
dashboard.classList.add('active');
}
// แสดง Login
function showLogin() {
dashboard.classList.remove('active');
loginPage.classList.remove('hidden');
loginPage.style.display = 'flex';
loginPage.style.transform = 'scale(1)';
loginPage.style.opacity = '1';
// รีเซ็ตฟอร์ม
loginForm.reset();
}
// ออกจากระบบ
logoutBtn.addEventListener('click', function() {
isLoggedIn = false;
dashboard.style.transform = 'translateY(-20px)';
dashboard.style.opacity = '0';
setTimeout(() => {
showLogin();
showSnackbar('ออกจากระบบแล้ว');
}, 300);
});
// Toggle Sidebar
toggleBtn.addEventListener('click', function() {
sidebar.classList.toggle('collapsed');
});
// จัดการเมนูนาวิเกชัน
navLinks.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
// ลบ active class จากลิงก์ทั้งหมด
navLinks.forEach(l => l.classList.remove('active'));
// เพิ่ม active class ให้ลิงก์ที่คลิก
this.classList.add('active');
// อัปเดตชื่อหน้า
const page = this.dataset.page;
const pageNames = {
'dashboard': 'หน้าหลัก',
'users': 'จัดการผู้ใช้',
'products': 'สินค้า',
'orders': 'คำสั่งซื้อ',
'analytics': 'รายงาน',
'settings': 'ตั้งค่า'
};
pageTitle.textContent = pageNames[page] || 'หน้าหลัก';
// เอฟเฟกต์การเปลี่ยนหน้า
const content = document.querySelector('.content');
content.style.opacity = '0.7';
content.style.transform = 'translateY(10px)';
setTimeout(() => {
content.style.transition = 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)';
content.style.opacity = '1';
content.style.transform = 'translateY(0)';
}, 150);
});
});
// สร้างกราฟด้วย Chart.js
function initCharts() {
// กราฟยอดขาย
const salesCtx = document.getElementById('salesChart').getContext('2d');
salesChart = new Chart(salesCtx, {
type: 'line',
data: {
labels: ['1 ม.ค.', '5 ม.ค.', '10 ม.ค.', '15 ม.ค.', '20 ม.ค.', '25 ม.ค.', '30 ม.ค.'],
datasets: [{
label: 'ยอดขายปีนี้',
data: [12000, 19000, 15000, 25000, 22000, 30000, 35000],
borderColor: '#1976d2',
backgroundColor: 'rgba(25, 118, 210, 0.1)',
borderWidth: 3,
fill: true,
tension: 0.4,
pointBackgroundColor: '#1976d2',
pointBorderColor: '#ffffff',
pointBorderWidth: 2,
pointRadius: 6,
pointHoverRadius: 8
}, {
label: 'ยอดขายปีที่แล้ว',
data: [8000, 15000, 12000, 20000, 18000, 25000, 28000],
borderColor: '#757575',
backgroundColor: 'rgba(117, 117, 117, 0.05)',
borderWidth: 2,
fill: false,
tension: 0.4,
pointBackgroundColor: '#757575',
pointBorderColor: '#ffffff',
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6,
borderDash: [5, 5]
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true,
position: 'top',
labels: {
fontFamily: 'Noto Sans Thai',
fontSize: 12,
usePointStyle: true,
padding: 20
}
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: '#f5f5f5'
},
ticks: {
fontFamily: 'Noto Sans Thai',
fontSize: 11,
color: '#757575',
callback: function(value) {
return '฿' + value.toLocaleString('th-TH');
}
}
},
x: {
grid: {
display: false
},
ticks: {
fontFamily: 'Noto Sans Thai',
fontSize: 11,
color: '#757575'
}
}
},
elements: {
point: {
hoverBorderWidth: 3
}
}
}
});
// กราหสินค้าขายดี
const topProductsCtx = document.getElementById('topProductsChart').getContext('2d');
topProductsChart = new Chart(topProductsCtx, {
type: 'doughnut',
data: {
labels: ['เสื้อผ้า', 'รองเท้า', 'กระเป๋า', 'นาฬิกา', 'อื่นๆ'],
datasets: [{
data: [30, 25, 20, 15, 10],
backgroundColor: [
'#1976d2',
'#2196f3',
'#4caf50',
'#ff9800',
'#9c27b0'
],
borderWidth: 0,
hoverBorderWidth: 3,
hoverBorderColor: '#ffffff'
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true,
position: 'bottom',
labels: {
fontFamily: 'Noto Sans Thai',
fontSize: 12,
usePointStyle: true,
padding: 15,
generateLabels: function(chart) {
const data = chart.data;
if (data.labels.length && data.datasets.length) {
return data.labels.map((label, i) => {
const dataset = data.datasets[0];
const value = dataset.data[i];
return {
text: `${label} (${value}%)`,
fillStyle: dataset.backgroundColor[i],
strokeStyle: dataset.backgroundColor[i],
pointStyle: 'circle'
};
});
}
return [];
}
}
}
},
cutout: '60%',
animation: {
animateScale: true,
animateRotate: true
}
}
});
}
// อัปเดตข้อมูลแบบเรียลไทม์
function updateStats() {
const statValues = document.querySelectorAll('.stat-value');
statValues.forEach(stat => {
const currentValue = parseInt(stat.textContent.replace(/[^\d]/g, ''));
const randomChange = Math.floor(Math.random() * 10) - 5;
const newValue = Math.max(0, currentValue + randomChange);
if (stat.textContent.includes('฿')) {
stat.textContent = '฿' + newValue.toLocaleString('th-TH');
} else if (stat.textContent.includes('%')) {
stat.textContent = (newValue / 100).toFixed(2) + '%';
} else {
stat.textContent = newValue.toLocaleString('th-TH');
}
// เอฟเฟกต์ highlight
const card = stat.closest('.stat-card');
card.style.background = '#e3f2fd';
setTimeout(() => {
card.style.background = '#ffffff';
}, 1000);
});
}
// อัปเดตสถิติทุก 30 วินาที
setInterval(updateStats, 30000);
// เพิ่ม Animation เมื่อโหลดหน้า
window.addEventListener('load', function() {
const cards = document.querySelectorAll('.stat-card');
cards.forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(30px)';
setTimeout(() => {
card.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)';
card.style.opacity = '1';
card.style.transform = 'translateY(0)';
}, index * 100);
});
});
// จัดการ Responsive
function handleMobileView() {
if (window.innerWidth <= 768) {
sidebar.classList.add('collapsed');
} else {
sidebar.classList.remove('collapsed');
}
}
window.addEventListener('resize', handleMobileView);
handleMobileView();
// FAB Click Event
document.querySelector('.fab').addEventListener('click', function() {
showSnackbar('เพิ่มรายการใหม่');
});
// เพิ่มฟังก์ชันค้นหา
const searchInput = document.querySelector('.search-input');
searchInput.addEventListener('input', function(e) {
const query = e.target.value.toLowerCase();
if (query.length > 2) {
showSnackbar(`กำลังค้นหา: ${query}`);
}
});
// การจัดการ Focus States สำหรับ Accessibility
document.addEventListener('keydown', function(e) {
if (e.key === 'Tab') {
document.body.classList.add('keyboard-navigation');
}
});
document.addEventListener('mousedown', function() {
document.body.classList.remove('keyboard-navigation');
});
// เพิ่ม CSS สำหรับ Keyboard Navigation
const keyboardStyle = document.createElement('style');
keyboardStyle.textContent = `
.keyboard-navigation *:focus {
outline: 2px solid #1976d2 !important;
outline-offset: 2px !important;
}
`;
document.head.appendChild(keyboardStyle);
</script>
</body>
</html>