Skip to main content

6 posts tagged with "nodejs"

View All Tags

Node.js - Nền Tảng JavaScript Runtime Hiện Đại

· 3 min read

Node.js Ecosystem

Node.js là một nền tảng JavaScript runtime được xây dựng trên Chrome's V8 JavaScript engine. Nó cho phép các nhà phát triển xây dựng các ứng dụng server-side và networking sử dụng JavaScript, một ngôn ngữ lập trình phổ biến và dễ học.

Tại Sao Chọn Node.js?

1. Hiệu Suất Cao

Node.js sử dụng mô hình event-driven, non-blocking I/O giúp tối ưu hóa hiệu suất và khả năng mở rộng:

  • Xử lý nhiều kết nối đồng thời
  • Tối ưu hóa bộ nhớ
  • Thời gian phản hồi nhanh

2. Hệ Sinh Thái Phong Phú

Node.js có một hệ sinh thái package khổng lồ thông qua npm:

  • Hơn 1.5 triệu package
  • Cộng đồng phát triển lớn
  • Tài liệu phong phú

3. Đa Nền Tảng

Node.js có thể chạy trên nhiều hệ điều hành:

  • Windows
  • macOS
  • Linux
  • Các hệ thống nhúng

Các Framework Phổ Biến

1. Express.js

Express.js là framework web phổ biến nhất cho Node.js:

const express = require('express');
const app = express();

app.get('/', (req, res) => {
res.send('Hello World!');
});

app.listen(3000, () => {
console.log('Server running on port 3000');
});

2. NestJS

NestJS là một framework hiện đại, mạnh mẽ cho các ứng dụng server-side:

import { Controller, Get } from '@nestjs/common';

@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'This action returns all cats';
}
}

3. Fastify

Fastify là một framework web nhanh và hiệu quả:

const fastify = require('fastify')({ logger: true })

fastify.get('/', async (request, reply) => {
return { hello: 'world' }
})

fastify.listen(3000)

Công Cụ Phát Triển

1. npm và yarn

Quản lý package và dependencies:

# Sử dụng npm
npm install express

# Sử dụng yarn
yarn add express

2. nodemon

Tự động khởi động lại server khi có thay đổi:

npm install -g nodemon
nodemon app.js

3. PM2

Quản lý process và deployment:

npm install -g pm2
pm2 start app.js

Best Practices

  1. Xử Lý Lỗi:

    try {
    // Code có thể gây lỗi
    } catch (error) {
    console.error('Error:', error);
    }
  2. Async/Await:

    async function getData() {
    try {
    const result = await fetch('https://api.example.com/data');
    return await result.json();
    } catch (error) {
    console.error('Error:', error);
    }
    }
  3. Environment Variables:

    require('dotenv').config();
    const port = process.env.PORT || 3000;

Kết Luận

Node.js đã trở thành một trong những nền tảng phát triển backend phổ biến nhất hiện nay. Với hiệu suất cao, hệ sinh thái phong phú và cộng đồng lớn, Node.js là lựa chọn tuyệt vời cho cả dự án nhỏ và lớn.

Nếu bạn đang tìm kiếm một nền tảng phát triển backend hiện đại, hiệu quả và dễ học, Node.js chắc chắn là một lựa chọn đáng cân nhắc.

Kiến trúc Microservices với Node.js

· 4 min read

Trong thời đại phát triển phần mềm hiện đại, kiến trúc microservices đã trở thành một lựa chọn phổ biến cho các ứng dụng lớn và phức tạp. Node.js, với các đặc điểm như xử lý bất đồng bộ hiệu quả, hệ sinh thái phong phú và cộng đồng lớn, là một lựa chọn phù hợp để phát triển các microservices.

Bài viết này sẽ giới thiệu về kiến trúc microservices và đi sâu vào lý do tại sao Node.js lại là một lựa chọn tốt cho việc xây dựng các dịch vụ này.

1. Microservices là gì?

Microservices là một kiến trúc phần mềm trong đó ứng dụng được chia thành nhiều dịch vụ nhỏ, độc lập, mỗi dịch vụ chạy một cách độc lập với các dịch vụ khác.

Các đặc điểm chính của microservices:

  • Phân rã theo chức năng: Mỗi dịch vụ tập trung vào một nghiệp vụ cụ thể.
  • Độc lập: Các dịch vụ có thể được phát triển, triển khai và mở rộng riêng biệt.
  • Giao tiếp qua mạng: Thường sử dụng các giao thức nhẹ như HTTP/REST hoặc gRPC.
  • Quản lý dữ liệu phi tập trung: Mỗi dịch vụ có thể có cơ sở dữ liệu riêng.

2. Tại sao chọn Node.js cho Microservices?

Node.js có nhiều đặc điểm khiến nó trở thành một lựa chọn hấp dẫn cho việc xây dựng microservices:

  • Non-blocking I/O: Mô hình xử lý bất đồng bộ giúp Node.js xử lý số lượng lớn kết nối đồng thời hiệu quả, rất quan trọng cho các dịch vụ API.
  • Nhẹ và nhanh: Khởi động nhanh và tiêu thụ ít tài nguyên so với nhiều nền tảng khác.
  • JavaScript ở cả Frontend và Backend: Cho phép sử dụng cùng một ngôn ngữ và chia sẻ code (ví dụ: validation logic) giữa client và server.
  • Hệ sinh thái NPM: Kho lưu trữ package khổng lồ cung cấp sẵn nhiều thư viện cho các tác vụ phổ biến.
  • Phù hợp với các dịch vụ nhỏ: Dễ dàng xây dựng các dịch vụ nhỏ, tập trung vào một nhiệm vụ.

3. Lợi ích khi sử dụng Node.js cho Microservices

  • Tăng tốc độ phát triển: Dễ dàng tạo các dịch vụ mới.
  • Mở rộng linh hoạt: Các dịch vụ Node.js có thể được mở rộng độc lập dựa trên nhu cầu.
  • Tái sử dụng code: Có thể chia sẻ code giữa frontend và backend (Node.js).
  • Hiệu suất cao cho I/O-bound tasks: Rất tốt cho các dịch vụ xử lý nhiều thao tác nhập/xuất (ví dụ: gọi API khác, truy vấn database).

4. Thách thức

  • Quản lý phức tạp: Số lượng dịch vụ tăng lên đòi hỏi hệ thống quản lý, giám sát phức tạp hơn.
  • Giao tiếp giữa các dịch vụ: Cần có chiến lược rõ ràng cho việc giao tiếp và xử lý lỗi giữa các dịch vụ.
  • Nhất quán dữ liệu: Quản lý dữ liệu phân tán có thể phức tạp.
  • Đòi hỏi DevOps: Cần quy trình DevOps mạnh mẽ để tự động hóa triển khai và quản lý.

5. Các khái niệm chính khi xây dựng Microservices với Node.js

  • API Gateway: Điểm vào duy nhất cho client, xử lý routing, authentication và các cross-cutting concerns. Express.js là một lựa chọn tốt để xây dựng API Gateway hiệu suất cao.

  • Service Discovery: Cho phép các dịch vụ tìm và giao tiếp với các dịch vụ khác mà không cần cấu hình tĩnh.

  • Message Queues: Sử dụng để giao tiếp bất đồng bộ giữa các dịch vụ. Thay vì gọi API trực tiếp (giao tiếp đồng bộ), các dịch vụ có thể gửi tin nhắn đến một hàng đợi. Các dịch vụ khác quan tâm đến tin nhắn đó có thể xử lý nó theo tốc độ của riêng họ, giúp giảm tải cho các dịch vụ và tăng khả năng chịu lỗi.

  • Containerization (Docker) và Orchestration (Kubernetes): Rất quan trọng cho việc đóng gói và quản lý các dịch vụ.

Kết luận

Kiến trúc microservices với Node.js mang lại nhiều lợi ích cho việc phát triển và vận hành các ứng dụng lớn, nhưng cũng đòi hỏi sự hiểu biết sâu sắc về kiến trúc và quy trình vận hành.

Tài Liệu Tham Khảo

Tìm Hiểu Về Tính Năng API Của Node.js và Supabase

· 3 min read

Node.js và Supabase là hai công nghệ mạnh mẽ trong việc xây dựng backend và API. Trong bài viết này, chúng ta sẽ tìm hiểu về các tính năng API của cả hai công nghệ này và cách chúng có thể được kết hợp để tạo ra các ứng dụng web hiện đại.

Node.js và Supabase Architecture

Node.js API Features

1. RESTful API với Express.js

Express.js là framework phổ biến nhất để xây dựng RESTful API trong Node.js:

const express = require('express');
const app = express();

app.get('/api/users', (req, res) => {
// Xử lý request
res.json({ users: [] });
});

app.post('/api/users', (req, res) => {
// Tạo user mới
res.status(201).json({ message: 'User created' });
});

Express.js Middleware Flow

2. Middleware System

Node.js cho phép sử dụng middleware để xử lý request:

app.use(express.json());
app.use(cors());
app.use(authenticationMiddleware);

3. Async/Await và Promises

Node.js hỗ trợ xử lý bất đồng bộ hiệu quả:

async function getData() {
try {
const result = await database.query();
return result;
} catch (error) {
console.error(error);
}
}

Node.js Async Flow

Supabase API Features

1. RESTful API Tự Động

Supabase tự động tạo RESTful API cho database:

const { createClient } = require('@supabase/supabase-js')
const supabase = createClient('YOUR_SUPABASE_URL', 'YOUR_SUPABASE_KEY')

// Query data
const { data, error } = await supabase
.from('users')
.select('*')

Supabase Architecture

2. Real-time Subscriptions

Supabase hỗ trợ real-time updates:

const subscription = supabase
.from('users')
.on('INSERT', payload => {
console.log('New user:', payload.new)
})
.subscribe()

Real-time Updates Flow

3. Authentication API

Supabase cung cấp sẵn các API xác thực:

// Đăng ký
const { user, error } = await supabase.auth.signUp({
email: 'example@email.com',
password: 'password'
})

// Đăng nhập
const { session, error } = await supabase.auth.signIn({
email: 'example@email.com',
password: 'password'
})

Authentication Flow

Kết Hợp Node.js và Supabase

1. Tạo Custom API Endpoints

const express = require('express');
const { createClient } = require('@supabase/supabase-js');
const app = express();

const supabase = createClient('YOUR_SUPABASE_URL', 'YOUR_SUPABASE_KEY');

app.get('/api/custom-endpoint', async (req, res) => {
const { data, error } = await supabase
.from('your_table')
.select('*');

if (error) return res.status(500).json({ error });
res.json(data);
});

Integration Architecture

2. Xử Lý Business Logic

app.post('/api/process-data', async (req, res) => {
// Xử lý logic nghiệp vụ
const processedData = await processBusinessLogic(req.body);

// Lưu vào Supabase
const { data, error } = await supabase
.from('processed_data')
.insert(processedData);

if (error) return res.status(500).json({ error });
res.json(data);
});

Best Practices

  1. Bảo Mật:

    • Luôn sử dụng environment variables cho các thông tin nhạy cảm
    • Implement rate limiting
    • Validate input data
  2. Performance:

    • Sử dụng caching khi cần thiết
    • Tối ưu hóa database queries
    • Implement pagination cho large datasets
  3. Error Handling:

    • Xử lý lỗi một cách nhất quán
    • Logging đầy đủ
    • Trả về error messages rõ ràng

Best Practices Diagram

Kết Luận

Node.js và Supabase cung cấp một bộ công cụ mạnh mẽ để xây dựng API hiện đại. Node.js cho phép bạn tạo custom API endpoints và xử lý business logic, trong khi Supabase cung cấp các tính năng sẵn có như database, authentication, và real-time updates. Việc kết hợp cả hai công nghệ này có thể giúp bạn xây dựng các ứng dụng web hiệu quả và dễ bảo trì.

Tài Liệu Tham Khảo

Kết Nối Ứng Dụng Flutter Với API Node.js

· 8 min read

Flutter, một UI toolkit đến từ Google, cho phép xây dựng ứng dụng mobile, web và desktop đẹp và native từ một codebase duy nhất. Node.js là một runtime environment cho JavaScript ở phía server, rất phổ biến để xây dựng các API nhanh và có khả năng mở rộng. Việc kết hợp sức mạnh của Flutter ở frontend và Node.js ở backend tạo nên một stack phát triển hiện đại và hiệu quả.

Bài viết này sẽ đi sâu vào cách ứng dụng Flutter của bạn có thể giao tiếp với API được xây dựng bằng Node.js, tập trung vào việc thực hiện các yêu cầu HTTP và xử lý dữ liệu.

Sơ đồ kiến trúc tổng thể

1. Thiết lập môi trường

Trước khi bắt đầu code, chúng ta cần đảm bảo môi trường phát triển đã sẵn sàng.

1.1 Chuẩn bị API Node.js

Để làm theo hướng dẫn này, bạn cần có một API Node.js đang chạy và có thể truy cập được. Nếu bạn chưa có, bạn có thể tạo một API cơ bản rất nhanh với Express.js. Dưới đây là ví dụ về một API Node.js đơn giản trả về danh sách người dùng và cho phép thêm người dùng mới:

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors'); // Cần thiết nếu chạy Flutter app trên giả lập/thiết bị khác với server

const app = express();
const port = 3000;

// Middleware
app.use(cors());
app.use(bodyParser.json());

// Dữ liệu giả
let users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];

// GET request để lấy tất cả người dùng
app.get('/api/users', (req, res) => {
res.json(users);
});

// POST request để thêm người dùng mới
app.post('/api/users', (req, res) => {
const newUser = req.body;
if (!newUser || !newUser.name) {
return res.status(400).json({ message: 'Name is required' });
}
newUser.id = users.length + 1; // Tạo ID đơn giản
users.push(newUser);
res.status(201).json(newUser);
});

// Khởi chạy server
app.listen(port, () => {
console.log(`Node.js API listening at http://localhost:${port}`);
});

Lưu đoạn code trên vào một file (ví dụ: server.js), cài đặt các dependencies (npm install express body-parser cors) và chạy nó (node server.js). Đảm bảo API chạy trên một địa chỉ và cổng mà thiết bị Flutter của bạn có thể truy cập (ví dụ: http://10.0.2.2:3000 nếu chạy trên Android emulator và server trên localhost).

1.2 Thiết lập Project Flutter

Nếu bạn đã có project Flutter, hãy mở file pubspec.yaml. Nếu chưa, tạo project mới bằng flutter create your_app_name.

Chúng ta sẽ sử dụng package http để đơn giản. Thêm http vào phần dependencies trong pubspec.yaml:

dependencies:
flutter:
sdk: flutter

cupertino_icons: ^1.0.2

# Thêm package http tại đây
http: ^0.13.3 # Hoặc phiên bản mới nhất

dev_dependencies:
flutter_test:
sdk: flutter

flutter_lints: ^2.0.0

flutter:
uses-material-design: true

Sau khi thêm, chạy lệnh flutter pub get trong terminal của project Flutter để cài đặt package.

2. Thực hiện HTTP Request từ Flutter

Package http cung cấp các phương thức dễ sử dụng để thực hiện các yêu cầu HTTP phổ biến như GET, POST, PUT, DELETE.

Trước tiên, import package httpdart:convert (để xử lý JSON) vào file Dart của bạn:

import 'package:http/http.dart' as http;
import 'dart:convert';

Luồng HTTP Request và Response

2.1 GET Request: Lấy dữ liệu

Để lấy danh sách người dùng từ API Node.js ví dụ ở trên, bạn có thể tạo một hàm bất đồng bộ sử dụng http.get():

Future<List<dynamic>> fetchUsers() async {
final response = await http.get(Uri.parse('YOUR_NODEJS_API_URL/api/users'));

if (response.statusCode == 200) {
// Nếu server trả về mã status 200 OK, parse JSON
return jsonDecode(response.body); // response.body là chuỗi JSON
} else {
// Nếu không thành công, throw một exception.
throw Exception('Failed to load users');
}
}

Bạn cần thay thế 'YOUR_NODEJS_API_URL' bằng địa chỉ IP và cổng thực tế của API Node.js server của bạn.

2.2 POST Request: Gửi dữ liệu

Để thêm một người dùng mới, bạn sử dụng phương thức http.post(). Bạn cần cung cấp URL, headers (để thông báo định dạng dữ liệu gửi đi là JSON) và body (dữ liệu cần gửi, đã được encode sang chuỗi JSON).

Future<void> createUser(String name) async {
final response = await http.post(
Uri.parse('YOUR_NODEJS_API_URL/api/users'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{'name': name}),
);

if (response.statusCode == 201) {
// Nếu server trả về mã status 201 Created
print('User created successfully: ${response.body}');
} else {
// Nếu không thành công, throw một exception.
throw Exception('Failed to create user: ${response.statusCode}');
}
}

Sơ đồ luồng truyền và xử lý dữ liệu

3. Xử lý bất đồng bộ với Async/Await

Các thao tác mạng trong Flutter (và Dart) là bất đồng bộ. Điều này có nghĩa là chúng không chặn luồng chính của ứng dụng, giúp UI luôn mượt mà. Từ khóa asyncawait là cách hiện đại và dễ đọc để làm việc với các thao tác bất đồng bộ.

  • async: Được đặt trước một hàm để báo hiệu rằng hàm đó sẽ thực hiện các thao tác bất đồng bộ.
  • await: Được sử dụng bên trong một hàm async để chờ kết quả của một Future mà không chặn toàn bộ luồng thực thi. Khi gặp await, hàm sẽ tạm dừng, giải phóng CPU để làm việc khác, và sẽ tiếp tục chạy khi Future hoàn thành.

Các ví dụ fetchUserscreateUser ở trên đều sử dụng async/await để chờ kết quả từ http.gethttp.post.

4. Xử lý lỗi và phản hồi cho người dùng

Việc xử lý lỗi API là rất quan trọng để ứng dụng của bạn ổn định và cung cấp phản hồi rõ ràng cho người dùng. Luôn bọc các lệnh gọi API trong khối try-catch.

void _loadUsers() async {
try {
List<dynamic> usersList = await fetchUsers();
// Cập nhật UI với dữ liệu người dùng
print('Fetched ${usersList.length} users.');
// setState(() { _users = usersList; }); // Ví dụ cập nhật state
} catch (e) {
// Xử lý lỗi và thông báo cho người dùng
print('Error fetching users: $e');
// ScaffoldMessenger.of(context).showSnackBar(...); // Ví dụ hiển thị thông báo lỗi
}
}

void _addUser(String name) async {
try {
await createUser(name);
print('User added successfully.');
// Có thể fetch lại danh sách người dùng sau khi thêm thành công
// _loadUsers();
// ScaffoldMessenger.of(context).showSnackBar(...); // Ví dụ hiển thị thông báo thành công
} catch (e) {
print('Error adding user: $e');
// ScaffoldMessenger.of(context).showSnackBar(...); // Ví dụ hiển thị thông báo lỗi
}
}

Khi server trả về mã trạng thái lỗi (ví dụ: 400, 404, 500), phương thức http.get hoặc http.post sẽ không tự động throw lỗi. Bạn cần kiểm tra thuộc tính statusCode của response và throw exception một cách thủ công nếu cần xử lý trong khối catch.

5. Best Practices

  • Sử dụng biến môi trường: Không nên hardcode URL API trong code. Sử dụng các package như flutter_dotenv để quản lý biến môi trường.
  • Mô hình hóa dữ liệu: Thay vì làm việc trực tiếp với dynamic hoặc Map<String, dynamic>, hãy tạo các Dart class để mô hình hóa dữ liệu nhận được từ API (sử dụng json_serializable giúp tự động hóa).
  • Xử lý lỗi chi tiết: Phân loại các loại lỗi (lỗi mạng, lỗi server, lỗi parsing) và cung cấp thông báo cụ thể cho người dùng.
  • Sử dụng Dio thay vì http (Tùy chọn): Đối với các ứng dụng lớn hơn, package dio thường được ưa chuộng hơn http vì nó cung cấp nhiều tính năng hơn như interceptors, global configuration, form data, request cancellation, v.v.
  • Bảo mật: Đảm bảo kết nối API của bạn an toàn (sử dụng HTTPS). Xử lý xác thực và ủy quyền đúng cách.

Kết luận

Kết nối ứng dụng Flutter với API Node.js là một tác vụ phổ biến khi xây dựng các ứng dụng full-stack. Bằng cách hiểu rõ cách thực hiện HTTP requests, xử lý bất đồng bộ và quản lý lỗi trong Flutter, bạn có thể dễ dàng tích hợp ứng dụng mobile của mình với backend Node.js mạnh mẽ, mở ra nhiều khả năng phát triển ứng dụng.

Tài Liệu Tham Khảo

Flutter và Node.js: Xây dựng ứng dụng di động full-stack

· 2 min read

Trong thời đại phát triển ứng dụng di động bùng nổ, việc xây dựng một ứng dụng full-stack (bao gồm cả frontend và backend) trở nên ngày càng phổ biến. Flutter của Google cung cấp một framework mạnh mẽ để xây dựng giao diện người dùng đẹp và hiệu quả cho cả Android và iOS từ một codebase duy nhất. Kết hợp với Node.js ở backend, bạn có thể tạo ra các API nhanh chóng và có khả năng mở rộng. Bài viết này sẽ hướng dẫn bạn cách xây dựng một ứng dụng di động full-stack sử dụng Flutter cho frontend và Node.js cho backend.

1. Giới thiệu

Sự kết hợp giữa Flutter và Node.js mang lại nhiều lợi ích:

  • Hiệu suất cao: Flutter biên dịch ra mã native, còn Node.js được xây dựng trên V8 Engine của Chrome, cho hiệu suất xử lý nhanh.
  • Phát triển nhanh: Cả hai đều có cộng đồng lớn, nhiều thư viện hỗ trợ và cú pháp dễ học.
  • Full-stack JavaScript (cho Node.js): Nếu bạn đã quen với JavaScript, Node.js cho phép bạn sử dụng cùng một ngôn ngữ cho cả frontend (nếu dùng React Native, Vue Native,...) và backend.
  • Đa nền tảng: Flutter cho phép triển khai trên nhiều nền tảng (Android, iOS, Web, Desktop) còn Node.js có thể chạy trên hầu hết các hệ điều hành.

Flutter Node.js Architecture

2. Thiết lập môi trường

Trước khi bắt đầu, bạn cần cài đặt:

  • Flutter SDK: Theo hướng dẫn chính thức của Flutter.
  • Node.js và npm/yarn: Tải về từ trang chủ Node.js.

3. Xây dựng Backend với Node.js (Express.js)

Chúng ta sẽ sử dụng Express.js, một framework web phổ biến cho Node.js, để xây dựng RESTful API.

Khởi tạo project Node.js:

mkdir flutter-nodejs-backend
cd flutter-nodejs-backend
npm init -y
npm install express body-parser cors

**Tạo file `

Hướng Dẫn Thực Tập SportSpot API Platform

· 10 min read

1. 📋 Thông Tin Dự Án End User

Tên dự án: SportSpot - Nền tảng đặt sân thể thao
Công nghệ: Node.js, Express, MongoDB, React, Flutter
Môi trường: Development & Production Ready
Database: MongoDB với Mongoose ODM
Website: SportSpot


🎯 Mục Tiêu Thực Tập

1. Kiến Thức Cần Nắm Vững

  • Backend API Development với Node.js/Express
  • Database Design và quản lý MongoDB
  • Authentication & Authorization với Session
  • RESTful API design patterns
  • Error Handling và logging
  • API Documentation và testing

2. Kỹ Năng Phát Triển

  • Thiết kế database schema phù hợp
  • Xây dựng API endpoints hiệu quả
  • Implement authentication flow
  • Testing API với Postman/curl
  • Debug và troubleshoot issues
  • Code documentation và best practices

🏗️ Kiến Trúc Hệ Thống

Backend Structure

server/
├── index.ts # Entry point
├── routes.ts # API routes definition
├── mongoStorage.ts # Database operations
├── db.ts # MongoDB schema definitions
└── middleware/ # Authentication & validation

Database Schema

Users (người dùng)
├── Authentication info
├── Profile details
└── Verification status

SportCategories (danh mục thể thao)
├── Name, description
└── Icon & display info

Facilities (cơ sở thể thao)
├── Basic info (name, address, images)
├── Pricing & capacity
└── Operating hours

SportFields (sân cụ thể)
├── Field details (type, surface, size)
├── Status & availability
└── Linked to facility

PriceTables (bảng giá)
├── Time-based pricing
├── Customer type pricing
└── Weekend/weekday rates

Bookings (đặt sân)
├── Customer information
├── Selected time slots
├── Payment & pricing details
└── Status tracking

🛠️ Các API Endpoints Chính

1. Authentication APIs

POST /api/auth/register    # Đăng ký tài khoản
POST /api/auth/login # Đăng nhập
POST /api/auth/logout # Đăng xuất
GET /api/auth/me # Lấy thông tin user hiện tại

2. Facilities & Categories APIs

GET /api/categories        # Lấy danh mục thể thao
GET /api/facilities # Lấy danh sách cơ sở thể thao
GET /api/facilities/:id # Chi tiết cơ sở thể thao
GET /api/facilities/:id/pricing # Lấy bảng giá theo thời gian

3. Booking APIs

POST /api/bookings/enhanced          # Tạo booking mới (format Flutter)
GET /api/bookings/recent # Lấy lịch sử booking
GET /api/facilities/:id/bookings # Booking theo cơ sở thể thao
GET /api/fields/:id/booked-slots # Lấy slot đã đặt theo sân

4. Admin APIs

GET  /api/bookings/:id     # Chi tiết booking
PUT /api/bookings/:id # Cập nhật booking
DELETE /api/bookings/:id # Hủy booking

💻 Hướng Dẫn Development

1. Setup Môi Trường

# Clone project
git clone [repository-url]
cd sportspot

# Install dependencies
npm install

# Setup environment variables
cp .env.example .env
# Cấu hình DATABASE_URL, SESSION_SECRET, etc.

# Start development server
npm run dev

2. Database Development

// Tạo schema mới trong db.ts
const newSchema = new mongoose.Schema({
field1: { type: String, required: true },
field2: { type: Number, default: 0 },
timestamps: true
});

// Export model
export const NewModel = mongoose.model('NewModel', newSchema);

3. API Development Pattern

// 1. Định nghĩa route trong routes.ts
app.get("/api/endpoint", async (req, res) => {
try {
// Validation
const { param } = req.params;
const { query } = req.query;

// Business logic
const result = await storage.methodName(param, query);

// Response
res.json(result);
} catch (error) {
console.error("Error:", error);
res.status(500).json({ message: "Internal server error" });
}
});

// 2. Implement logic trong mongoStorage.ts
async methodName(param: string, query?: string): Promise<ResultType> {
try {
const data = await Model.find({ conditions });
return data.map(item => ({
// Transform data
}));
} catch (error) {
console.error("Database error:", error);
throw error;
}
}

🧪 Testing Guidelines

1. API Testing với Postman

// Test Enhanced Booking API
POST http://localhost:5000/api/bookings/enhanced
{
"facilityId": "6821c96b3946d6bda8bd87e8",
"selectedSlots": [
{
"fieldId": "682bb2af35339cbc051f6f5",
"timeRange": "06:30-07:30",
"price": 350000
}
],
"bookingDate": "2025-05-27",
"totalPrice": 350000,
"customerName": "Test User",
"customerEmail": "test@example.com",
"customerPhone": "0123456789"
}

2. Testing với cURL

# Login
curl -X POST http://localhost:5000/api/auth/login \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{"username": "tamtest", "password": "123456"}'

# Test API với session
curl -X GET http://localhost:5000/api/bookings/recent \
-H "Content-Type: application/json" \
-b cookies.txt

📊 Database Operations

1. CRUD Operations

// Create
const newItem = new Model(data);
await newItem.save();

// Read
const items = await Model.find(query)
.populate('relatedField')
.sort({ createdAt: -1 });

// Update
await Model.findByIdAndUpdate(id, updateData, { new: true });

// Delete
await Model.findByIdAndDelete(id);

2. Advanced Queries

// Date range query
const bookings = await Booking.find({
bookingDate: {
$gte: startDate,
$lt: endDate
}
});

// Text search
const facilities = await Facility.find({
$or: [
{ name: { $regex: searchTerm, $options: 'i' }},
{ address: { $regex: searchTerm, $options: 'i' }}
]
});

// Aggregation
const stats = await Booking.aggregate([
{ $match: { status: 'confirmed' }},
{ $group: { _id: '$facilityId', total: { $sum: '$totalPrice' }}}
]);

🔐 Authentication Flow

1. Session-based Authentication

// Login endpoint
app.post("/api/auth/login", async (req, res) => {
const { username, password } = req.body;

// Verify credentials
const user = await storage.getUserByUsername(username);
const isValid = await bcrypt.compare(password, user.password);

if (isValid) {
// Set session
req.session.user = { id: user._id, username: user.username };
res.json(userInfo);
} else {
res.status(401).json({ message: "Invalid credentials" });
}
});

// Protected route middleware
const requireAuth = (req, res, next) => {
if (!req.session.user) {
return res.status(401).json({ message: "Not authenticated" });
}
next();
};

📱 Flutter Integration

1. Enhanced Booking Format

{
"facilityId": "facility_id",
"selectedSlots": [
{
"fieldId": "field_id", // ID sân cụ thể
"timeRange": "06:30-07:30", // Khung giờ
"price": 350000 // Giá slot này
}
],
"bookingDate": "2025-05-27",
"totalPrice": 350000,
"totalDuration": 60, // Phút
"customerName": "Tên khách hàng",
"customerEmail": "email@example.com",
"customerPhone": "0123456789",
"customerType": "Khách vãng lai"
}

2. Response Format

{
"id": "booking_id",
"userId": "user_id",
"facilityId": "facility_id",
"selectedSlots": [
{
"fieldId": "field_id",
"timeRange": "06:30-07:30",
"price": 350000
}
],
"status": "pending",
"totalPrice": 350000,
"customerInfo": "...",
"createdAt": "2025-05-27T...",
"facility": {
"name": "Tên cơ sở",
"address": "Địa chỉ"
}
}

⚠️ Error Handling Best Practices

1. Error Response Format

// Standard error response
{
"message": "Human readable error message",
"code": "ERROR_CODE",
"details": "Additional error details"
}

// Validation error response
{
"message": "Validation failed",
"errors": [
{
"field": "fieldName",
"message": "Field specific error"
}
]
}

2. Error Handling Pattern

try {
// Business logic
const result = await operationThatMightFail();
res.json(result);
} catch (error) {
// Log error for debugging
console.error("Operation failed:", error);

// Return appropriate error response
if (error.name === 'ValidationError') {
res.status(400).json({ message: "Invalid input data" });
} else if (error.name === 'CastError') {
res.status(400).json({ message: "Invalid ID format" });
} else {
res.status(500).json({ message: "Internal server error" });
}
}

📈 Performance Optimization

1. Database Indexing

// Tạo index cho truy vấn thường xuyên
facilitySchema.index({ name: 'text', address: 'text' });
bookingSchema.index({ facilityId: 1, bookingDate: 1 });
userSchema.index({ username: 1 }, { unique: true });

2. Query Optimization

// Sử dụng lean() cho read-only queries
const facilities = await Facility.find(query).lean();

// Limit fields với select()
const users = await User.find().select('name email phone');

// Pagination
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const skip = (page - 1) * limit;

const results = await Model.find(query)
.skip(skip)
.limit(limit);

📝 Documentation Standards

1. API Documentation Format

/**
* GET /api/facilities/:id/bookings
*
* Lấy danh sách booking của một cơ sở thể thao
*
* @param {string} id - ID của cơ sở thể thao
* @query {string} date - Ngày cần lọc (YYYY-MM-DD) - optional
*
* @returns {Array} Danh sách booking
* @example
* // Request
* GET /api/facilities/123/bookings?date=2025-05-27
*
* // Response
* [
* {
* "id": "booking_id",
* "customerName": "Tên khách",
* "selectedSlots": [...],
* "totalPrice": 350000
* }
* ]
*/

2. Code Comments

// Xử lý logic đặt sân với multiple time slots
const processBookingSlots = (selectedSlots) => {
// Validate từng slot
selectedSlots.forEach(slot => {
if (!slot.fieldId || !slot.timeRange) {
throw new Error('Missing required slot data');
}
});

// Tính tổng thời gian và giá
const totalDuration = calculateTotalDuration(selectedSlots);
const totalPrice = selectedSlots.reduce((sum, slot) => sum + slot.price, 0);

return { totalDuration, totalPrice };
};

🎯 Assignments cho Thực Tập Sinh

Week 1: Setup & Understanding

  • Setup development environment
  • Understand project structure
  • Run và test existing APIs
  • Study database schema
  • Create first simple API endpoint

Week 2: CRUD Operations

  • Implement facility management APIs
  • Add field validation
  • Create search functionality
  • Practice error handling
  • Write API documentation

Week 3: Advanced Features

  • Implement booking system
  • Add authentication middleware
  • Create reporting APIs
  • Optimize database queries
  • Add logging system

Week 4: Integration & Testing

  • Test with Flutter app
  • Fix integration issues
  • Performance optimization
  • Deploy to staging
  • Final documentation

📚 Tài Liệu Tham Khảo

1. Technologies

2. Best Practices

3. Testing Tools


🔧 Troubleshooting Common Issues

1. Database Connection Issues

// Check MongoDB connection
if (mongoose.connection.readyState !== 1) {
console.error('MongoDB not connected');
// Implement reconnection logic
}

2. Session Problems

// Debug session issues
app.use((req, res, next) => {
console.log('Session:', req.session);
console.log('User:', req.session?.user);
next();
});

3. CORS Issues

// Enable CORS for development
app.use(cors({
origin: 'http://localhost:3000',
credentials: true
}));

🎖️ Đánh Giá & Tiến Độ

Tiêu Chí Đánh Giá

  1. Code Quality (30%)

    • Clean, readable code
    • Proper error handling
    • Following best practices
  2. API Functionality (25%)

    • Correct implementation
    • Proper HTTP status codes
    • Data validation
  3. Database Design (20%)

    • Efficient queries
    • Proper relationships
    • Data integrity
  4. Documentation (15%)

    • API documentation
    • Code comments
    • User guides
  5. Problem Solving (10%)

    • Debugging skills
    • Independent learning
    • Creative solutions

Milestone Checkpoints

  • Week 1: Environment setup + Basic understanding
  • Week 2: First working API endpoints
  • Week 3: Complete booking system
  • Week 4: Integration testing + Deployment

Liên hệ hỗ trợ:

Happy Coding! 🚀

2. 📋 Thông Tin Dự Án Admin

Thông tin admin: thanhdt9279@gmail.com / 123456

📊 Tổng thể nhân sự bao gồm:

  1. Team DB và Backend:

    • 1 Database (DB)
    • 1 API
      Do Thành và Vũ phụ trách backend (DB + API)
  2. 🖥️ Giao diện và chức năng Web Admin:
    Trang tổng quan (Dashboard + trạng thái sân)

    • 1 UI Web: Đã có
    • 1 FE Web: Do Chiến đảm nhiệm
  3. 📱 Giao diện và chức năng App Admin:

    • 1 UI App: Đạt
    • 1 FE App: Chưa