1. Trang chủ
  2. » Luận Văn - Báo Cáo

Báo Cáo Đồ Áncông Nghệ Phần Mềm Mớibooking App Mern Stack.pdf

49 0 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Báo Cáo Đồ Án Công Nghệ Phần Mềm Mới Booking App MERN Stack
Tác giả Phan Thái Bảo
Người hướng dẫn ThS. Nguyễn Minh Đạo
Trường học Trường Đại Học Sư Phạm Kỹ Thuật Thành Phố Hồ Chí Minh
Chuyên ngành Công Nghệ Thông Tin
Thể loại Báo cáo đồ án
Năm xuất bản 2023
Thành phố Thành phố Hồ Chí Minh
Định dạng
Số trang 49
Dung lượng 2,95 MB

Cấu trúc

  • Chương 1: Tổng quan chương trình (0)
    • 1.1. Giới thiệu về chương trình (6)
    • 1.2. Các yêu cầu chức năng (6)
    • 1.3. Các yêu cầu phi chức năng (6)
  • Chương 2. Nội dung (0)
    • 2.1. Database (7)
      • 2.1.1 Class diagram (7)
      • 2.1.2 Lược đồ Use Case (8)
      • 2.1.3 Models (8)
      • 2.1.4 Tóm tắt database (9)
    • 2.2. Backend (9)
      • 2.2.1 Register (9)
      • 2.2.2 Login (10)
      • 2.2.3 Get profile (10)
      • 2.2.4 Log out (11)
      • 2.2.5 Upload ảnh bằng link (11)
      • 2.2.6 Upload ảnh từ máy (11)
      • 2.2.7 Tạo place (12)
      • 2.2.8 Get place của user (12)
      • 2.2.9 Get place by id (13)
      • 2.2.10 Chỉnh sửa nơi ở (13)
      • 2.2.11 Get place (13)
      • 2.2.12 Đặt chỗ (13)
      • 2.2.13 Get booking (14)
      • 2.2.14 Hủy booking (14)
    • 2.3. FrontEnd (15)
      • 2.3.1. Giao diện Trang chủ (15)
      • 2.3.2 Giao diện trang Đăng nhập (16)
      • 2.3.3 Giao diện trang đăng ký (17)
      • 2.3.4 Giao diện trang Tài khoản (18)
      • 2.3.5 Giao diện trang chi tiết nơi ở (20)
      • 2.3.6 Giao diện trang Booking (23)
      • 2.3.7 Giao diện trang My Booking (24)
      • 2.3.8 Giao diện trang My accommodations (25)
      • 2.3.9 Giao diện trang thêm nơi ở mới (27)
  • Chương 3. Cài đặt và kiểm thử (0)
    • 3.1. Cài đặt (30)
      • 3.1.1 Back end (30)
      • 3.1.2 Front end (30)
    • 3.2. Demo chương trình (31)
  • Chương 4. Kết Luận (0)
    • 41. Kết Luận (49)
      • 4.2. Hướng phát triển (49)

Nội dung

Các yêu cầu chức năng:- Người dùng có thể tạo tài khoản với các thông tin cơ bản, đăng nhập vào hệ thống để có thể tiến hành lựa chọn, đặt chỗ hoặc chia sẽ chỗ ở của mình - Người dùng có

Tổng quan chương trình

Giới thiệu về chương trình

Booking app Airbnb là một nơi giúp chúng ta có thể đặt được những chỗ yêu thích ở những nơi mà chúng ta muốn đến Chúng ta có thể lựa chọn được những nơi ở có giá vừa phải, có thời gian check in, check out và có giới hạn số người khi ở Bên cạnh đó nó còn cho phép chúng ta có thể chia sẻ chỗ ở của mình đến với mọi người

Các yêu cầu chức năng

- Người dùng có thể tạo tài khoản với các thông tin cơ bản, đăng nhập vào hệ thống để có thể tiến hành lựa chọn, đặt chỗ hoặc chia sẽ chỗ ở của mình

- Người dùng có thể xem chi tiết nơi ở và tiến hành đặt chỗ

- Người dùng có thể xem lại chi tiết đơn đã đặt hoặc hủy đơn

- Người dùng có thể chia sẽ nơi ở của mình

- Người dùng có thể xem và chỉnh sửa nơi ở đã chia sẽ

Các yêu cầu phi chức năng

- Hệ thống đảm bảo tính dễ sử dụng cho người dùng

- Thông tin mô tả, hình ảnh nơi ở đúng với thực tế

- Website dễ sử dụng cho các nền tảng khác nhau (desktop, mobile, tablet…)

Nội dung

Database

- User model: const UserSchema = new Schema({ name: String, email: {type:String, unique:true}, password: String,

Tạo bảng User với với các trường như name, email, password

- Booking model const bookingSchema = new mongoose.Schema({ place: {type:mongoose.Schema.Types.ObjectId, required:true, ref:'Place'}, user: {type:mongoose.Schema.Types.ObjectId, required:true}, checkIn: {type:Date, required:true}, checkOut: {type:Date, required:true}, name: {type:String, required:true}, phone: {type:String, required:true}, price: Number,

Tạo bảng booking với các trường như place (khóa ngoại đến bảng Place), user (khóa ngoại đến bảng User), checkIn, checkout, name, phone, price.

- Place model const placeSchema = new mongoose.Schema({ owner: {type:mongoose.Schema.Types.ObjectId, ref:'User'}, title: String, address: String, photos: [String], description: String, perks: [String], extraInfo: String, checkIn: Number, checkOut: Number, maxGuests: Number, price: Number,

Tạo bảng Place với các trường như owner (khóa ngoại đến bảng User), title, address, photos, description, perks, extraInfo, checkIn, checkout, maxGuests, price

2.1.4 Tóm tắt database Đây là một hệ thống dùng để đặt chỗ ở Người dùng có thể xem thông tin phòng, đặt chỗ, hủy chỗ đã đặt đồng thời người dùng cũng có thể chia sẽ nơi ở của mình đến người khác và có thể chỉnh sửa chỗ ở đã chia sẽ.

Mỗi người dùng có thể đặt nhiều chỗ , những mỗi chỗ đặt chỉ thuộc về một người dùng (1 – N)

Mỗi nơi ở có thể có nhiều lượt đặt chỗ và mỗi lượt đặt chỗ chỉ thuộc về một nơi (1 – N)

Mỗi người dùng có thể đặt nhiều nơi và mỗi nơi có thể được đặt bởi nhiều người dùng (N – N)

Backend

2.2.1 Register app.post('/api/register', async (req,res) => { mongoose.connect(process.env.MONGO_URL); const {name,email,password} = req.body; try { const userDoc = await User.create({ name, email, password:bcrypt.hashSync(password, bcryptSalt),

Tiến hành tạo mới user với name, email, password từ request gửi đến (password được mã hóa) sau đó trả về thông tin user được tạo Nếu lỗi trả về lỗi 422 và thông tin lỗi

2.2.2 Login app.post('/api/login', async (req,res) => { mongoose.connect(process.env.MONGO_URL); const {email,password} = req.body; const userDoc = await User.findOne({email}); if (userDoc) { const passOk = bcrypt.compareSync(password, userDoc.password); if (passOk) { jwt.sign({ email:userDoc.email, id:userDoc._id

}, jwtSecret, {}, (err,token) => { if (err) throw err; res.cookie('token', token).json(userDoc);

} else { res.status(422).json('pass not ok');

} else { res.json('not found');

}); Đầu tiên sẽ dùng findOne để tìm email trong bảng user Nếu có thì sẽ tiến hành check password xem có đúng không Nếu password đúng thì dùng jwt.sign để chuỗi JWT với email và id của user, sau đó gửi token đã tạo đến client thông qua cookie Nếu password sai thì trả lỗi 422 với nội dung password không đúng Nếu không tìm được email thì trả lỗi not found.

2.2.3 Get profile app.get('/api/profile', (req,res) => { mongoose.connect(process.env.MONGO_URL); const {token} = req.cookies; if (token) { jwt.verify(token, jwtSecret, {}, async (err, userData) => { if (err) throw err; const {name,email,_id} = await User.findById(userData.id); res.json({name,email,_id});

Check token nếu có dùng jwt.verify để xác thực token và tiến hành giải mã token và trả name, email, và id của user đó.

2.2.4 Log out app.post('/api/logout', (req,res) => { res.cookie('token', '').json(true);

Tiến hành xóa token trong cookie

2.2.5 Upload ảnh bằng link app.post('/api/upload-by-link', async (req,res) => { const {link} = req.body; const newName = 'photo' + Date.now() + '.jpg'; await imageDownloader.image({ url: link,

// dest: '/tmp/' +newName, dest: dirname + '/uploads/' + newName

// const url = await uploadToS3('/tmp/' +newName, newName, mime.lookup('/tmp/' +newName)); // res.json(url); res.json( 'http://localhost:4000/uploads/' + newName)

Dùng imageDownloader để tiến hành download ảnh và lưu lại với tên mới với đuôi file jpg, ảnh sẽ được lưu lại ở folder uploads ở phía backend, sau đó trả về ảnh được upload.

2.2.6 Upload ảnh từ máy const photosMiddleware = multer({dest:'uploads/'}); app.post('/api/upload', photosMiddleware.array('photos', 100), async (req,res) => { const uploadedFiles = []; for (let i = 0; i < req.files.length; i++) { const {path,originalname,mimetype} = req.files[i]; const parts = originalname.split('.') const ext = parts[parts.length -1] const newPath = path + "." + ext fs.renameSync(path, newPath)

// const url = await uploadToS3(path, originalname, mimetype); uploadedFiles.push(newPath);

Dùng mutler để xử lí việc tải ảnh lên từ các tệp tin được gửi từ client photosMiddleware.array('photos', 100) định nghĩa rằng middleware này sẽ xử lý tệp tin được gửi dưới dạng một mảng có tên là 'photos', và tối đa 100 tệp tin có thể được tải lên trong một lần yêu cầu.

Sau đó tiến hành xử lí các tệp ảnh được gửi đó bằng cách lấy ra tên file của từng ảnh đó và dùng fs.renameSync để tiến hành đổi tên cho các file đó và lưu lại vào mảng uploadedFile và trả về các ảnh đó về bên phía client.

2.2.7 Tạo place app.post('/api/places', (req,res) => { mongoose.connect(process.env.MONGO_URL); const {token} = req.cookies; const { title,address,addedPhotos,description,price, perks,extraInfo,checkIn,checkOut,maxGuests,

} = req.body; jwt.verify(token, jwtSecret, {}, async (err, userData) => { if (err) throw err; const placeDoc = await Place.create({ owner:userData.id,price, title,address,photos:addedPhotos,description, perks,extraInfo,checkIn,checkOut,maxGuests,

}); Đầu tiên sẽ tiến hành xác thực token, sau đó thực hiện việc tạo nơi ở trong bản Place với các thông tin được gửi từ phía client và trả về thông tin đã tạo thành công.

2.2.8 Get place của user app.get('/api/user-places', (req,res) => { mongoose.connect(process.env.MONGO_URL); const {token} = req.cookies; jwt.verify(token, jwtSecret, {}, async (err, userData) => { const {id} = userData; res.json( await Place.find({owner:id}) );

}); Đầu tiên sẽ tiến hành xác thực token, nếu đúng thì sẽ trả về những nơi mà user đó đã tạo thông qua userId của họ.

2.2.9 Get place by id app.get('/api/places/:id', async (req,res) => { mongoose.connect(process.env.MONGO_URL); const {id} = req.params; res.json(await Place.findById(id));

Dùng findById để trả về nơi theo id được truyền từ client.

2.2.10 Chỉnh sửa nơi ở app.put('/api/places', async (req,res) => { mongoose.connect(process.env.MONGO_URL); const {token} = req.cookies; const { id, title,address,addedPhotos,description, perks,extraInfo,checkIn,checkOut,maxGuests,price,

} = req.body; jwt.verify(token, jwtSecret, {}, async (err, userData) => { if (err) throw err; const placeDoc = await Place.findById(id); if (userData.id === placeDoc.owner.toString()) { placeDoc.set({ title,address,photos:addedPhotos,description, perks,extraInfo,checkIn,checkOut,maxGuests,price,

}); await placeDoc.save(); res.json('ok');

Tiến hành xác thực token, nếu đúng thì sẽ dùng findById để tìm đến nơi ở đó theo id, sau đó kiểm tra thông tin id của user đang cần chỉnh sửa và id của người tạo xem đúng không, nếu đúng thì sẽ tiến hành lưu lại các thông tin cần chỉnh sửa và trả về kết quả cập nhật thành công.

2.2.11 Get place app.get('/api/places', async (req,res) => { mongoose.connect(process.env.MONGO_URL); res.json( await Place.find() );

Dùng find() để lấy ra được tất cả các nơi trong bảng Place

2.2.12 Đặt chỗ app.post('/api/bookings', async (req, res) => { mongoose.connect(process.env.MONGO_URL); const userData = await getUserDataFromReq(req); const { place,checkIn,checkOut,numberOfGuests,name,phone,price,

Booking.create({ place,checkIn,checkOut,numberOfGuests,name,phone,price, user:userData.id,

}).then((doc) => { res.json(doc);

FrontEnd

- Gọi api get places để lấy ra tất cả các phòng trong hệ thống sau đó hiển thị lên trang người dùng

2.3.2 Giao diện trang Đăng nhập

- Gọi api login và truyền vào thông tin đăng nhập để tiến hành đăng nhập, sau đó dùng UseContext để tiến hành lưu trữ thông tin đăng nhập và hiển thị tên người dùng trên trang web async function handleLoginSubmit(ev) { ev.preventDefault(); try { const {data} = await axios.post('/login', {email,password}); setUser(data); alert('Login successful'); setRedirect(true);

} if (redirect) { return

} Đăng nhập thành công thì chuyển đến trang chủ

2.3.3 Giao diện trang đăng ký

- Gọi api register và truyền vào thông tin đăng kí để tiến hành đăng kí, nếu đăng kí thành công thì sẽ chuyển đến trang đăng nhập, sai thì sẽ thông báo lỗi async function registerUser(ev) { ev.preventDefault(); try { await axios.post('/register', { name, email, password,

}); alert('Registration successful Now you can log in'); setRedirect(true);

} catch (e) { alert('Registration failed Please try again later');

} if (redirect) { return ;

2.3.4 Giao diện trang Tài khoản

Dùng UserContext để hiển thị thông tin user và gọi api logout nếu muốn đăng xuất Nếu chưa đăng nhập thì sẽ chuyển đến trang login const [redirect,setRedirect] = useState(null); const {ready,user,setUser} = useContext(UserContext); let {subpage} = useParams(); if (subpage === undefined) { subpage = 'profile';

} async function logout() { await axios.post('/logout'); setRedirect('/'); setUser(null);

// } if (ready && !user && !redirect) { return

} if (redirect) { return

Trong UseContext gọi api get profile để lấy ra thông tin user useEffect(() => { if (!user) { axios.get('/profile').then(({data}) => { setUser(data); setReady(true);

2.3.5 Giao diện trang chi tiết nơi ở

- Gọi api get place by id và truyền id của phòng được chọn để lấy được thông tin chi tiết của phòng đó và hiển thị lên trên giao diện useEffect(() => { if (!id) { return;

} axios.get(`/places/${id}`).then(response => { setPlace(response.data);

- Gọi api booking và truyền thời gian, số lượng người, tên, số điện thoại để tiến hành đặt phòng async function bookThisPlace() { const response = await axios.post('/bookings', { checkIn,checkOut,numberOfGuests,name,phone, place:place._id, price:numberOfNights * place.price,

}); const bookingId = response.data._id; setRedirect(`/account/bookings/${bookingId}`);

- Gọi api get booking và tìm đến đơn có id bằng id trên url để lấy ra được thông tin chi tết của đơn hàng đó useEffect(() => { if (id) { axios.get('/bookings').then(response => { const foundBooking = response.data.find(({_id}) => _id === id); if (foundBooking) { setBooking(foundBooking);

- Gọi api delete booking và truyền id vào để tiến hành xóa đơn hàng const handleDeleteOrder = async() => { const userConfirmed = window.confirm(

"Bạn có chắA c muốA n hu Cy đơn đặt phòng khống?"

// NếA u người dùng đã xác nhận, thực hiện xóa if (userConfirmed && id) { axios

then((response) => { if (response?.data.message === "Booking deleted successfully") { alert("Đã xóa đơn đặt phòng thành cống!"); window.location.reload();

catch((error) => { console.error("Error deleting order:", error); alert("Đã xa Cy ra lốT i khi xóa đơn đặt phòng.");

2.3.7 Giao diện trang My Booking

- Gọi api get booking để lấy ra toàn bộ đơn hàng và hiển thị lên giao diện useEffect(() => { axios.get('/bookings').then(response => { setBookings(response.data);

2.3.8 Giao diện trang My accommodations

- Gọi api get user-place để lấy được tất cả nơi mà user này đã đăng useEffect(() => { axios.get('/user-places').then(({data}) => { setPlaces(data);

2.3.9 Giao diện trang thêm nơi ở mới

- Gọi api get place by id để tiến hành truyền dữ liệu vào các ô input để tiến hành update dữ liệu useEffect(() => { if (!id) { return;

} axios.get('/places/'+id).then(response => { const {data} = response; setTitle(data.title); setAddress(data.address); setAddedPhotos(data.photos); setDescription(data.description); setPerks(data.perks); setExtraInfo(data.extraInfo); setCheckIn(data.checkIn); setCheckOut(data.checkOut); setMaxGuests(data.maxGuests); setPrice(data.price);

}, [id]); async function savePlace(ev) { ev.preventDefault(); const placeData = { title, address, addedPhotos, description, perks, extraInfo, checkIn, checkOut, maxGuests, price,

// update await axios.put('/places', { id, placeData

// new place await axios.post('/places', placeData); setRedirect(true);

Nếu tạo mới thì sẽ gọi api post places để tạo nơi ở mới

- Ở phần hình ảnh: gọi api upload by link nếu tải ảnh bằng link và gọi api upload nếu tải ảnh từ thiết bị async function addPhotoByLink(ev) { ev.preventDefault(); const {data:filename} = await axios.post('/upload-by-link',

{link: photoLink}); onChange(prev => { if (filename) { return [ prev, filename];

} function uploadPhoto(ev) { const files = ev.target.files; const data = new FormData(); for (let i = 0; i < files.length; i++) { data.append('photos', files[i]);

} axios.post('/upload', data, { headers: {'Content-type':'multipart/form-data'}

}).then(response => { const {data:filenames} = response; onChange(prev => { return [ prev, filenames];

Dùng 'Content-type':'multipart/form-data' để có thể gửi nhiều file cùng lúc

Cài đặt và kiểm thử

Cài đặt

- Bước 1: Mở terminal và cd đến folder api

- Bước 2: Tạo một env với nội dung là đường link kết nối với mongoodb

MONGO_URL = mongodb+srv://booking:gvF7bIzlGMh40ptv@cluster0.jhiwsro.mongodb.net/? retryWrites=true&w=majority

- Bước 3 : Tạo folder uploads trong folder api

- Bước 4: chạy câu lệnh npm install để download node modules

- Bước 5: chạy câu lệnh npm start để khởi động

- Bước 1: Mở terminal và cd đến folder client

- Bước 2: Tạo file evn với nội dung là url của backend

VITE_API_BASE_URL = http://localhost:4000/api

- Bước 3: Chạy câu lệnh npm install để download node modules

- Bước 4: Chạy câu lệnh npm run dev để khởi động chương trình

- Bước 5: Truy cập đường dẫn http://localhost:5173/

Demo chương trình

- Đăng ký: Chọn vào avatar phía trên góc phải ở trang chủ để chuyển đến trang đăng nhập Sau đó chọn “Register now” để chuyển đến trang đăng ký và nhập thông tin đăng ký rồi nhấn “Register”

Sau khi đăng kí thành công trang sẽ chuyển đến trang đăng nhập

- Đăng nhập: Chọn vào avatar phía trên góc phải ở trang chủ để chuyển đến trang đăng nhập Sau đó nhập thông tin đăng nhập và bấm “Login”

Sau khi đăng nhập thành công thì sẽ chuyển đến trang chủ

- Xem thông tin chi tiết của từng phòng: Ở trang chủ, ta sẽ chọn phòng mà chúng ta muốn xem Trang web sẽ chuyển đến trang xem thông tin chi tiết của phòng đó và hiển thị tất cả thông tin của phòng đó bao gồm hình ảnh, mô tả, vị trí, giá, ….

- Booking: Khi chọn được phòng mong muốn, người dùng sẽ tiến hành nhập thời gian checkIn, checkOut, số lượng người, tên, số điện thoại và nhấn

“Booking this place” để đặt hàng

Sau khi đặt hàng thành công thì trang sẽ chuyển đến trang chi tiết đơn hàng

- Hủy đơn đặt hàng: Khi booking thành công thì trang sẽ chuyển đến chi tiết đơn hàng, nếu muốn hủy đơn thì nhấn chọn “Cancel order” và xác nhận hủy Hoặc người dùng có thể chọn vào tên của mình ở phía trên bên phải trang web và chọn vào “My booking” sau đó chọn đến nơi mà bạn muốn hủy nhấn chọn vào nơi đó và nhấn “Cancel order” và xác nhận hủy.

- Xem và chỉnh sửa các nơi đã đăng: Chọn vào tên người dùng ở phía trên bên phải trang web và chọn “My accommodation” để xem tất cả các nơi đã đăng

Nếu muốn chỉnh thử thông tin của nơi nào thì chọn vào nơi đó trang web sẽ chuyển đến trang cập nhật và nhập nội dung cần chỉnh sửa vào và nhấn

- Thêm nơi ở mới: Chọn vào “Add new place” ở trong “My accommodation” sao đó nhập tất cả các thông tin cần thiết và hình ảnh(có thể tải bằng link hoặc từ thiết bị cá nhân) và nhấn “Save” để đăng nơi ở mới.

Nếu upload ảnh bằng link thì sẽ dán link ảnh vào và nhấn “Add photo”

Nếu tải ảnh từ thiết bị thì nhấn chọn “Upload” và tải ảnh lên và có thể tải lên nhiều ảnh cung lúc

Thêm các thông tin cần thiết và giá phòng vào và nhấn “Save”

Nơi ở mới đã được thêm

- Đăng xuất: Chọn “Log out” trong My profile để tiến hành đăng xuất

Ngày đăng: 09/04/2024, 22:01

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w