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á
-
Code Quality (30%)
- Clean, readable code
- Proper error handling
- Following best practices
-
API Functionality (25%)
- Correct implementation
- Proper HTTP status codes
- Data validation
-
Database Design (20%)
- Efficient queries
- Proper relationships
- Data integrity
-
Documentation (15%)
- API documentation
- Code comments
- User guides
-
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ợ:
- Email: support@sportspot.com
- Slack: #dev-team
- Documentation: [Internal Wiki]
Happy Coding! 🚀
2. 📋 Thông Tin Dự Án Admin
- Họp nhóm 18h hằng ngày
- Github: https://github.com/huongnghiepdulieu/AdminDatSan_Web
Thông tin admin: thanhdt9279@gmail.com / 123456
📊 Tổng thể nhân sự bao gồm:
-
Team DB và Backend:
- 1 Database (DB)
- 1 API
Do Thành và Vũ phụ trách backend (DB + API)
-
🖥️ 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
-
📱 Giao diện và chức năng App Admin:
- 1 UI App: Đạt
- 1 FE App: Chưa