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

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

Đ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

Trang 1

TRƯỜNG ĐẠI HỌC

SƯ PHẠM KỸ THUẬT THÀNH PHỐ HỒ CHÍ MINH

 HCMC University of Technology and Education KHOA CÔNG NGHỆ THÔNG TIN

NGÀNH CÔNG NGHỆ THÔNG TIN

BÁO CÁO ĐỒ ÁN

CÔNG NGHỆ PHẦN MỀM MỚIBOOKING APP MERN STACK

GVHD: ThS Nguyễn Minh Đạo Sinh viên thực hiện:

Thành phố Hồ Chí Minh, tháng 12 năm 2023

Trang 2

ĐIỂM SỐ

NHẬN XÉT CỦA GIÁO VIÊN HƯỚNG DẪN:

(Kí và ghi rõ họ tên)

Trang 3

LỜI CẢM ƠN

Để hoàn thành tốt đề tài và bài báo cáo này, em xin gửi lời cảm ơn chân thành

đến giảng viên Nguyễn Minh Đạo, các quý thầy cô trong khoa Công Nghệ Thông Tin đã tận tình truyền đạt những kiến thức cần thiết giúp em có nền tảng để làm nên đề tài này, đã tạo điều kiện để em có thể tìm hiểu và thực hiện tốt đề tài Cùng với đó, em xin được gửi cảm ơn đến các bạn cùng khóa đã cung cấp nhiều thông tin và kiến thức hữu ích giúp em có thể hoàn thiện hơn đề tài của mình

Đề tài và bài báo cáo được em thực hiện trong khoảng thời gian ngắn, với những kiến thức còn hạn chế cùng nhiều hạn chế khác về mặt kĩ thuật và kinh nghiệm trong việc thực hiện một dự án phần mềm Do đó, trong quá trình làm nên đề tài có những thiếu sót là điều không thể tránh khỏi nên em rất mong nhận được những ý kiến đóng góp quý báu của các quý thầy cô để kiến thức của em được hoàn thiện hơn và em có thể làm tốt hơn nữa trong những lần sau Em xin chân thành cảm ơn

Cuối lời, em kính chúc quý thầy, quý cô luôn dồi dào sức khỏe và thành công hơn nữa trong sự nghiệp trồng người Một lần nữa em xin chân thành cảm ơn

Trang 4

Mục lục

Chương 1: Tổng quan chương trình 1

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

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

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

Chương 2 Nội dung 2

2.2.8 Get place của user 7

2.2.9 Get place by id 7

2.3.1 Giao diện Trang chủ: 10

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

2.3.3 Giao diện trang đăng ký 12

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

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

2.3.6 Giao diện trang Booking 16

2.3.7 Giao diện trang My Booking 17

Trang 5

2.3.8 Giao diện trang My accommodations 18

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

Chương 3 Cài đặt và kiểm thử 23

Trang 6

Chương 1: Tổng quan chương trình

1.1 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

1.2 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ẽ

1.3 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…)

Trang 7

Chương 2 Nội dung

2.1 Database:

2.1.1 Class diagram

Trang 8

2.1.2 Lược đồ Use Case

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'},

Trang 9

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ề

app.post('/api/register', async (req,res) => { mongoose.connect(process.env.MONGO_URL); const {name,email,password} = req.body;

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

Trang 10

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 (err) throw err;

res.cookie('token', token).json(userDoc);

Đầ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 đó.

Trang 11

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({

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 = 0i< 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);

Trang 12

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({

Đầ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ọ.

Trang 13

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);

Trang 14

const userData = await getUserDataFromReq(req);

Tiến hành xác thực token để lấy user id, sau đó tiến hành tạo đơn trong bảng Booking với dữ liệu được truyền từ bên phía client và trả về thông tin đơn đã được đặt thành công.

2.2.13 Get booking

app.get('/api/bookings', async (req,res) => { mongoose.connect(process.env.MONGO_URL); const userData = await getUserDataFromReq(req);

res.json( await Booking.find({user:userData.id}).populate('place') );});

Tiến hành xác thực token và trả về thông tin booking trong bảng Booking thông qua id của user.

2.2.14 Hủy booking

app.delete('/api/bookings/:id', async (req, res) => { mongoose.connect(process.env.MONGO_URL); const bookingId = req.params.id;

const booking = await Booking.findById(bookingId);

await Booking.findByIdAndDelete(bookingId); res.json({ message: 'Booking deleted successfully' }); } catch (error) {

console.error(error);

res.status(500).json({ message: 'Internal server error' });

Trang 15

}});

Tìm đơn hàng trong bảng Booking thông qua id được truyền từ client Sau đó tiến hành check xem có id đó không, nếu không thì thông báo lỗi booking not found, nếu có thì dùng findByIdAndDelete để tiến hành xóa dữ liệu trong bảng Booking thông qua id đó và trả về xóa thành công.

2.3 FrontEnd

2.3.1 Giao diện Trang chủ:

- 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

Trang 16

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) {

Trang 17

  }

  if (redirect) {

    return <Navigate to='/'} />  }

Đă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) {

Trang 18

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

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();

Trang 19

  if (subpage === undefined) {    subpage 'profile';

  }

  async function logout() {    await axios.post('/logout');

  if (ready && !user && redirect) {    return <Navigate to='/login'}/>

Trang 20

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

Trang 22

- 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}`);  }

Trang 23

2.3.6 Giao diện trang Booking

- 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 ===

- 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ắAc muốAn huCy đơn đặt phòng khống?"

    );

    // NếAu người dùng đã xác nhận, thực hiện xóa

    if (userConfirmed && id) {

      console.error("Error deleting order:", error);      alert("Đã xaCy ra lốTi khi xóa đơn đặt phòng.");        });

    }   }

Trang 24

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);

Trang 25

    });  }, []);

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

Trang 27

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

    axios.get('/places/'+id).then(response => {       const {data} = response;

      title, address, addedPhotos,      description, perks, extraInfo,

      checkIn, checkOut, maxGuests, price,

Trang 28

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) {

function uploadPhoto(ev) {

    const files ev.target.files;    const data =new FormData();

    for (let i=0; i <files.length; i++) {      data.append('photos', files[]);

    }

    axios.post('/upload', data, {

      headers: {'Content-type':'multipart/form-data'}

Trang 30

Chương 3 Cài đặt và kiểm thử

3.1 Cài đặt:

3.1.1 Back end:

- 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

3.1.2 Front end:

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

Trang 31

- 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/

3.2 Demo chương trình

- Trang chủ:

- Đă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”

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