diff --git a/README.md b/README.md
index f3e9824..3a3d244 100644
--- a/README.md
+++ b/README.md
@@ -1,69 +1,135 @@
# 🏥 ระบบบริหารจัดการโรงพยาบาล - ฝั่งผู้ใช้งาน (Frontend)
-โปรเจคระบบบริหารจัดการโรงพยาบาล (Hospital Management System)
-ส่วน Frontend พัฒนาโดยใช้ **React (Vite)** สำหรับให้บริการทั้งผู้ใช้งานทั่วไป (เช่น ผู้ป่วย) และผู้ดูแลระบบ (Admin)
+โปรเจคนี้เป็น **ส่วน Frontend ของระบบบริหารจัดการโรงพยาบาล (Hospital Management System)**
+Frontend พัฒนาโดยใช้ **React (Vite)** ทำงานร่วมกับ **Backend API v2.0** ที่เก็บอยู่ที่:
+🌐 [Hospital Management API - Gitea](https://gitea.softwarecraft.tech/gitea/hospital-management-api)
+
+ส่วน Frontend ให้บริการทั้งผู้ใช้งานทั่วไป (ผู้ป่วย) และผู้ดูแลระบบ (Admin) โดยเชื่อมต่อกับ API สำหรับฟีเจอร์ต่าง ๆ ตามเวอร์ชัน 2.0
---
-## 🚀 ฟีเจอร์ที่มีให้ใช้งาน
+## 🚀 ฟีเจอร์หลักที่รองรับ (v2.0)
-### 👥 ส่วนของผู้ใช้งานทั่วไป (ผู้ป่วย)
+### 👨⚕️ การจัดการข้อมูลหลัก (Core Data Management)
-- 📝 **จองนัดหมายแพทย์ (Book Appointment):**
- ใช้สำหรับการจองคิวนัดพบแพทย์ได้อย่างสะดวก
+**แพทย์ (Doctor)**
+- R1 - ลงทะเบียนแพทย์
+- R2 - รายชื่อแพทย์
+- R3 - แก้ไขข้อมูลแพทย์
+- R4 - ลบข้อมูลแพทย์
-- 📩 **ส่งข้อความถึงแอดมิน (Send Message):**
- ผู้ใช้งานสามารถติดต่อสอบถามข้อมูลกับแอดมินผ่านแบบฟอร์ม
+**ผู้ป่วย (Patient)**
+- R5 - ลงทะเบียนผู้ป่วย
+- R6 - รายชื่อผู้ป่วย
+- R7 - แก้ไขข้อมูลผู้ป่วย
+- R8 - ลบข้อมูลผู้ป่วย
-- 🔐 **เข้าสู่ระบบ / สมัครสมาชิก (Login / Register):**
- ระบบล็อกอินและลงทะเบียนใช้งานด้วยความปลอดภัย
+**พนักงาน / นางพยาบาล (Staff / Nurse)**
+- R9 - เพิ่มพนักงาน
+- R10 - ลงทะเบียนนางพยาบาล
+- R11 - รายชื่อนางพยาบาล
+- R12 - แก้ไขข้อมูลนางพยาบาล
+- R13 - ลบข้อมูลนางพยาบาล
---
-### 🛠️ ส่วนแดชบอร์ดสำหรับแอดมิน (Admin Dashboard)
+### 🩺 การจัดการเฉพาะทาง (Specialized Management)
-แดชบอร์ดนี้ออกแบบมาเพื่อใช้บริหารจัดการระบบโดยแอดมิน
+**การนัดหมาย (Consultation)**
+- R14 - จัดตารางการนัดหมาย
+- R15 - ยกเลิกนัดหมาย
+- R16 - ดูรายละเอียดการนัดหมายแต่ละรายการ
-- 📊 **ภาพรวมระบบ (Dashboard Overview):**
- แสดงสถิติ เช่น จำนวนแพทย์ จำนวนผู้ป่วย การนัดหมาย ฯลฯ
+**ตารางแพทย์ / นางพยาบาล (Doctor / Nurse Schedule)**
+- R17 - เพิ่มตารางแพทย์
+- R18 - เพิ่มตารางนางพยาบาล
+- R19 - ดูตารางนางพยาบาล (Pagination)
-- ➕ **เพิ่มผู้ใช้งาน (Add Admin / Doctor / Receptionist):**
- เพิ่มผู้ใช้งานตามบทบาทในระบบได้อย่างง่ายดาย
+**ห้องผ่าตัด (Operating Room)**
+- R20 - เพิ่ม / แก้ไข / ลบ ห้องผ่าตัด
+- R21 - ดูรายชื่อห้องผ่าตัด
+- R22 - จัดตารางใช้งานห้องผ่าตัด
-- 👨⚕️ **ดูรายชื่อแพทย์ (See all doctors):**
- ตรวจสอบรายชื่อและรายละเอียดของแพทย์ที่ลงทะเบียนแล้ว
+**เวชระเบียน / ใบสั่งยา / ผลวินิจฉัย (Medical Record / Prescription / Lab Result / Medical Image)**
+- R23 - สร้างเวชระเบียน
+- R24 - แก้ไขเวชระเบียน
+- R25 - ลบเวชระเบียน
+- R26 - ดูเวชระเบียนตาม ID
+- R27 - สร้างใบสั่งยาใหม่
+- R28 - อัปโหลด / ดาวน์โหลดภาพทางการแพทย์
+- R29 - สร้าง / ดูผล Lab ตามเวชระเบียน
-- 📅 **จัดการนัดหมาย (Manage Appointments):**
- ตรวจสอบ อนุมัติ แก้ไข หรือยกเลิกการนัดหมาย
+**การจัดการคลังสินค้า (Inventory Management)**
+- R30-R33 - จัดการ Inventory Item
+- R34 - สร้าง Inventory Transaction
+- R35 - จัดการ Supplier
+- R36 - จัดการ Item Type
+
+**การประกัน / การเรียกร้อง (Insurance Management)**
+- R37-R38 - จัดการ Insurance Provider
+- R39-R40 - จัดการ Insurance Claim
+
+**การเรียกเก็บเงิน / การชำระเงิน (Billing & Payment)**
+- R41-R45 - จัดการ Billing / Payment
+
+**รายงาน (Reports)**
+- R46 - รายงานสินค้าคงเหลือต่ำ
+- R47 - รายงานสรุปการเงิน
+- R48 - รายงานการนัดหมาย
+
+**การจัดการผู้ใช้งาน (User Management)**
+- R49-R56 - อัปเดตบัญชีผู้ใช้ / ตั้งค่าบทบาท / เชื่อมต่อผู้ป่วยและผู้ใช้งานอื่น ๆ
+
+---
+
+## 🔑 Default Credentials
+
+สำหรับเข้าระบบครั้งแรก (Admin)
+- Username: `admin@softwarecraft.tech`
+- Password: `pasword123`
+
+---
+
+## 📖 API Endpoints
+
+Frontend ใช้ API v2.0 สำหรับฟีเจอร์ต่าง ๆ เช่น:
+
+**Authentication**
+- POST `/api/auth/register-patient` - ลงทะเบียนผู้ป่วย
+- POST `/api/auth/register-doctor-and-link` - ลงทะเบียนแพทย์และเชื่อมบัญชี
+- POST `/api/auth/register-staff` - เพิ่มพนักงาน
+- POST `/api/auth/login` - เข้าสู่ระบบ
+- POST `/api/auth/link-patient-to-user` - เชื่อมผู้ป่วยกับบัญชี
+
+**User Management**
+- PUT `/api/v1.0/users/{id}/username` - อัปเดต username
+- PUT `/api/v1.0/users/{id}/role` - อัปเดต role
+- PUT `/api/v1.0/users/{id}/password` - อัปเดต password
+- PATCH `/api/v1.0/users/{id}/deactivate` - ปิดใช้งานบัญชี
+- PATCH `/api/v1.0/users/{id}/activate` - เปิดใช้งานบัญชี
+
+**Doctor / Patient / Staff / Consultation / Medical Record / Prescription / Payment / Inventory**
+- รองรับ CRUD ตามฟีเจอร์ v2.0 (ดูรายละเอียด API ด้านบน)
---
## 🧰 เทคโนโลยีที่ใช้
- **Frontend Framework:** React (Vite)
-- **การจัดการสถานะ (State):** React Hooks
- **UI Library:** Tailwind CSS / Daisy UI
- **Routing:** React Router
-- **การเชื่อมต่อ API:** Fetch (เชื่อมต่อกับ Backend)
-- **ระบบยืนยันตัวตน:** JWT (JSON Web Token)
+- **State Management:** React Hooks
+- **API Integration:** Fetch / Axios (เชื่อมต่อกับ [Hospital Management API](https://gitea.softwarecraft.tech/gitea/hospital-management-api))
+- **Authentication:** JWT
---
-## 🔄 การพัฒนาแบบ CI/CD
-
-โปรเจคนี้จะถูกพัฒนาโดยใช้แนวทาง **CI/CD** เพื่อให้สามารถ Build และ Deploy ได้อัตโนมัติผ่านระบบ Drone CI
-
-สามารถเข้าใช้งานระบบเพื่อทดสอบฟีเจอร์ได้ที่:
-🌐 [https://frontend-sandbox.softwarecraft.tech/](https://frontend-sandbox.softwarecraft.tech/)
-
----
-
-## 🧪 วิธีใช้งานในเครื่องนักพัฒนา (Dev Environment)
+## 🧪 การรันในเครื่องนักพัฒนา (Dev Environment)
```bash
-# ติดตั้งแพ็กเกจที่จำเป็น
+# ติดตั้ง dependencies
npm install
-# รันโปรเจคบนโหมดพัฒนา
+# รัน Frontend บนโหมดพัฒนา
npm run dev
```
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 0097fa3..3ff0880 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,13 +8,17 @@
"name": "healthcare_app",
"version": "0.0.0",
"dependencies": {
+ "@reduxjs/toolkit": "^2.8.2",
"@tailwindcss/vite": "^4.1.4",
"@tanstack/react-query": "^5.74.4",
"axios": "^1.8.4",
"daisyui": "^5.0.20",
+ "prop-types": "^15.8.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-hook-form": "^7.56.1",
+ "react-icons": "^5.5.0",
+ "react-redux": "^9.2.0",
"react-router-dom": "^7.5.1",
"tailwindcss": "^4.1.4"
},
@@ -769,9 +773,9 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz",
- "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
+ "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -784,9 +788,9 @@
}
},
"node_modules/@eslint/config-helpers": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.1.tgz",
- "integrity": "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==",
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz",
+ "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -794,9 +798,9 @@
}
},
"node_modules/@eslint/core": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz",
- "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==",
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz",
+ "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -844,13 +848,16 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.24.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz",
- "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==",
+ "version": "9.34.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz",
+ "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
}
},
"node_modules/@eslint/object-schema": {
@@ -864,32 +871,19 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.2.8",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz",
- "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==",
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz",
+ "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^0.13.0",
+ "@eslint/core": "^0.15.2",
"levn": "^0.4.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz",
- "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@types/json-schema": "^7.0.15"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- }
- },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -1009,6 +1003,32 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@reduxjs/toolkit": {
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.8.2.tgz",
+ "integrity": "sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A==",
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.0.0",
+ "@standard-schema/utils": "^0.3.0",
+ "immer": "^10.0.3",
+ "redux": "^5.0.1",
+ "redux-thunk": "^3.1.0",
+ "reselect": "^5.1.0"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17.0.0 || ^18 || ^19",
+ "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-redux": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz",
@@ -1269,6 +1289,18 @@
"win32"
]
},
+ "node_modules/@standard-schema/spec": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
+ "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
+ "license": "MIT"
+ },
+ "node_modules/@standard-schema/utils": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
+ "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==",
+ "license": "MIT"
+ },
"node_modules/@tailwindcss/node": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.4.tgz",
@@ -1611,7 +1643,7 @@
"version": "19.1.2",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.2.tgz",
"integrity": "sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"csstype": "^3.0.2"
@@ -1627,6 +1659,12 @@
"@types/react": "^19.0.0"
}
},
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
+ "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
+ "license": "MIT"
+ },
"node_modules/@vitejs/plugin-react": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.0.tgz",
@@ -1648,9 +1686,9 @@
}
},
"node_modules/acorn": {
- "version": "8.14.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
- "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"bin": {
@@ -1735,9 +1773,9 @@
"license": "MIT"
},
"node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1913,7 +1951,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/daisyui": {
@@ -2111,20 +2149,20 @@
}
},
"node_modules/eslint": {
- "version": "9.24.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz",
- "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==",
+ "version": "9.34.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.34.0.tgz",
+ "integrity": "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.20.0",
- "@eslint/config-helpers": "^0.2.0",
- "@eslint/core": "^0.12.0",
+ "@eslint/config-array": "^0.21.0",
+ "@eslint/config-helpers": "^0.3.1",
+ "@eslint/core": "^0.15.2",
"@eslint/eslintrc": "^3.3.1",
- "@eslint/js": "9.24.0",
- "@eslint/plugin-kit": "^0.2.7",
+ "@eslint/js": "9.34.0",
+ "@eslint/plugin-kit": "^0.3.5",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
@@ -2135,9 +2173,9 @@
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.3.0",
- "eslint-visitor-keys": "^4.2.0",
- "espree": "^10.3.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
"esquery": "^1.5.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -2195,9 +2233,9 @@
}
},
"node_modules/eslint-scope": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
- "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@@ -2212,9 +2250,9 @@
}
},
"node_modules/eslint-visitor-keys": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
- "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -2225,15 +2263,15 @@
}
},
"node_modules/espree": {
- "version": "10.3.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
- "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "acorn": "^8.14.0",
+ "acorn": "^8.15.0",
"acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.2.0"
+ "eslint-visitor-keys": "^4.2.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2395,14 +2433,15 @@
}
},
"node_modules/form-data": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
- "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
+ "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
@@ -2582,6 +2621,16 @@
"node": ">= 4"
}
},
+ "node_modules/immer": {
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
+ "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
@@ -2652,7 +2701,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/js-yaml": {
@@ -2990,6 +3038,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -3082,6 +3142,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -3221,6 +3290,17 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -3274,6 +3354,44 @@
"react": "^16.8.0 || ^17 || ^18 || ^19"
}
},
+ "node_modules/react-icons": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
+ "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "license": "MIT"
+ },
+ "node_modules/react-redux": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
+ "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/use-sync-external-store": "^0.0.6",
+ "use-sync-external-store": "^1.4.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^18.2.25 || ^19",
+ "react": "^18.0 || ^19",
+ "redux": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "redux": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-refresh": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
@@ -3322,6 +3440,27 @@
"react-dom": ">=18"
}
},
+ "node_modules/redux": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
+ "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
+ "license": "MIT"
+ },
+ "node_modules/redux-thunk": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
+ "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "redux": "^5.0.0"
+ }
+ },
+ "node_modules/reselect": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
+ "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
+ "license": "MIT"
+ },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -3536,6 +3675,15 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
+ "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/vite": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
diff --git a/package.json b/package.json
index 4a7334a..bf15233 100644
--- a/package.json
+++ b/package.json
@@ -10,13 +10,17 @@
"preview": "vite preview"
},
"dependencies": {
+ "@reduxjs/toolkit": "^2.8.2",
"@tailwindcss/vite": "^4.1.4",
"@tanstack/react-query": "^5.74.4",
"axios": "^1.8.4",
"daisyui": "^5.0.20",
+ "prop-types": "^15.8.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-hook-form": "^7.56.1",
+ "react-icons": "^5.5.0",
+ "react-redux": "^9.2.0",
"react-router-dom": "^7.5.1",
"tailwindcss": "^4.1.4"
},
diff --git a/src/App.jsx b/src/App.jsx
index 9b4a2a5..bdc11fc 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,15 +1,29 @@
-import {BrowserRouter, Route, Routes} from "react-router-dom";
+// src/App.jsx
+import { Route, Routes } from "react-router-dom";
import PublicRoutes from "./routes/PublicRoutes.jsx";
+import AdminRoutes from "./routes/AdminRoutes.jsx";
+import ProtectedRoute from "./components/ProtectedRoute.jsx"; // Import ProtectedRoute
function App() {
-
return (
-
+ {description} +
+{description}
++ {description} +
+เข้าสู่ระบบเพื่อเข้าถึงแดชบอร์ด จัดการข้อมูล และสำรวจฟีเจอร์ทั้งหมดที่เราพร้อมมอบให้คุณ ปลอดภัย รวดเร็ว และง่ายต่อการใช้งาน +export default function AuthLayout({ description }) { + return ( +
+ {description}
-| แพทย์ | +ผู้ป่วย | +วันที่ | +เวลา | +การดำเนินการ | +
|---|---|---|---|---|
| {consultation.doctor.name} | +{consultation.patient.name} | +{consultation.date} | +{consultation.time} | ++ + | +
| ชื่อ | +อีเมล | +CRM | +สาขา | +เบอร์โทรศัพท์ | +การดำเนินการ | +
|---|---|---|---|---|---|
| {doctor.name} | +{doctor.email} | +{doctor.crm} | +{doctor.specialty} | +{doctor.telephone} | ++ + | +
+ ยังไม่มีบัญชี?{' '} + + ลงทะเบียน + +
+| ชื่อ | +อีเมล | +วันเกิด | +การดำเนินการ | +
|---|---|---|---|
| {patient.name} | +{patient.email} | +{patient.birthday} | ++ + | +
| ชื่อผู้ใช้ | +บทบาท | +สถานะ | +การจัดการ | +
|---|---|---|---|
| {user.username} | ++ + {user.role} + + | +Active | ++ + | +