diff --git a/.jpb/persistence-units.xml b/.jpb/persistence-units.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a4ab6eb6024aa6d41a9e6011ae8f8c3c9c8d30b7
--- /dev/null
+++ b/.jpb/persistence-units.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="PersistenceUnitSettings">
+    <persistence-units>
+      <persistence-unit name="Default" />
+    </persistence-units>
+  </component>
+</project>
\ No newline at end of file
diff --git a/BackendFolder/SwitchRoom/build.gradle b/BackendFolder/SwitchRoom/build.gradle
index fb9f39c70a90b989f9c42db07ccde0e0fef2ce3a..836672e13e795c70b9e74f64ed9616578613e3ce 100644
--- a/BackendFolder/SwitchRoom/build.gradle
+++ b/BackendFolder/SwitchRoom/build.gradle
@@ -24,7 +24,9 @@ dependencies {
 	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
 //	implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
 	implementation 'org.springframework.boot:spring-boot-starter-web'
+	implementation 'io.jsonwebtoken:jjwt:0.9.1'
 	implementation 'org.springframework.session:spring-session-core'
+	annotationProcessor 'io.jsonwebtoken:jjwt:0.9.1'
 	compileOnly 'org.projectlombok:lombok'
 	developmentOnly 'org.springframework.boot:spring-boot-devtools'
 	annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/SwitchRoomApplication.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/SwitchRoomApplication.java
index 6e5574b011af1ede2363e739ff80bd09ff151f60..3352310c2925b49733d143cd0c23d6b487dd0ecd 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/SwitchRoomApplication.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/SwitchRoomApplication.java
@@ -2,8 +2,10 @@ package vt.CS5934.SwitchRoom;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 @SpringBootApplication
+@EnableScheduling
 public class SwitchRoomApplication {
 
 	public static void main(String[] args) {
@@ -11,3 +13,10 @@ public class SwitchRoomApplication {
 	}
 
 }
+
+/*
+Change logs:
+Date        |       Author          |   Description
+2022-10-31  |   Fangzheng Zhang     |   Add EnableScheduling to build the scheduled task
+
+ */
\ No newline at end of file
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/MatchedOfferController.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/MatchedOfferController.java
new file mode 100644
index 0000000000000000000000000000000000000000..bede6a5b3582fe55bae9dc9970565ceda78f2872
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/MatchedOfferController.java
@@ -0,0 +1,59 @@
+package vt.CS5934.SwitchRoom.controllers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+import vt.CS5934.SwitchRoom.models.ResponseModel;
+import vt.CS5934.SwitchRoom.models.UserOfferModel;
+import vt.CS5934.SwitchRoom.services.OfferPageService;
+import vt.CS5934.SwitchRoom.services.WishlistPageService;
+
+/**
+ * The "@MatchedController" made the class into rest handle class
+ * The "@RequestMapping("matched")" on the class level make it only react to url ".../example/..."
+ */
+@CrossOrigin(
+        allowCredentials = "true",
+        origins = {"http://localhost:8080/"}
+)
+@RestController
+@RequestMapping("matchedOffer")
+public class MatchedOfferController {
+
+    /**
+     * Autowired is a Spring feature that it will create or looking for the existing object in memory.
+     * It usually uses on Repository class, Service class, or some globe object in the class.
+     */
+    @Autowired
+    OfferPageService offerPageService;
+
+    /**
+     * You can use logger.[trace,debug,info,warn,error]("messages") to log into file
+     */
+    private final Logger logger = LoggerFactory.getLogger(UserController.class);
+
+    /**
+     * This function will handle the post function and change the JSON body into data class
+     */
+    @GetMapping("/{offerId}")
+    public ResponseModel getOffer(@PathVariable long offerId) {
+        logger.info("You reached the getOffer() function.");
+        System.out.println(offerId);
+        try{
+            UserOfferModel offer =  offerPageService.getUserOfferInfo(offerId);
+//            List<MatchedWishlistRecordModel> offerNotifications = matchedWishlistRecordService.getOfferListWithIDFromDB(userId);
+//            List<ExampleModel> exampleModels = exampleService.getAllExampleModelsFromDB();
+            return new ResponseModel(
+                    "This this a offer String response",
+                    HttpStatus.OK,
+                    offer);
+        }catch (Exception e){
+            return new ResponseModel(
+                    "Error occur on get All ExampleModels, Error info is: " + e,
+                    HttpStatus.OK,
+                    null);
+        }
+    }
+}
\ No newline at end of file
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/MatchedWishListController.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/MatchedWishListController.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed7cdec427db88bddd53d6e26e252d540f32546c
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/MatchedWishListController.java
@@ -0,0 +1,57 @@
+package vt.CS5934.SwitchRoom.controllers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+import vt.CS5934.SwitchRoom.models.ResponseModel;
+import vt.CS5934.SwitchRoom.models.WishlistItemModel;
+import vt.CS5934.SwitchRoom.services.WishlistPageService;
+
+
+/**
+ * The "@MatchedController" made the class into rest handle class
+ * The "@RequestMapping("matched")" on the class level make it only react to url ".../example/..."
+ */
+@CrossOrigin(
+        allowCredentials = "true",
+        origins = {"http://localhost:8080/"}
+)
+@RestController
+@RequestMapping("matchedWishList")
+public class MatchedWishListController {
+
+    /**
+     * Autowired is a Spring feature that it will create or looking for the existing object in memory.
+     * It usually uses on Repository class, Service class, or some globe object in the class.
+     */
+    @Autowired
+    WishlistPageService wishlistPageService;
+
+    /**
+     * You can use logger.[trace,debug,info,warn,error]("messages") to log into file
+     */
+    private final Logger logger = LoggerFactory.getLogger(UserController.class);
+
+    /**
+     * This function will handle the post function and change the JSON body into data class
+     */
+    @GetMapping("/{wishlistId}")
+    public ResponseModel getWishList(@PathVariable long wishlistId) {
+        logger.info("You reached the getWishList() function.");
+        System.out.println(wishlistId);
+        try{
+            WishlistItemModel wishlist = wishlistPageService.getWishlistItemInfo(wishlistId);
+            return new ResponseModel(
+                    "This this a offer String response",
+                    HttpStatus.OK,
+                    wishlist);
+        }catch (Exception e){
+            return new ResponseModel(
+                    "Error occur on get All ExampleModels, Error info is: " + e,
+                    HttpStatus.OK,
+                    null);
+        }
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/NotificationController.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/NotificationController.java
new file mode 100644
index 0000000000000000000000000000000000000000..7080bc3e0e6f6aee73a805d845c6ddc34fbc3de8
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/NotificationController.java
@@ -0,0 +1,105 @@
+package vt.CS5934.SwitchRoom.controllers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+import vt.CS5934.SwitchRoom.models.*;
+import vt.CS5934.SwitchRoom.services.DealWithWishlist;
+import vt.CS5934.SwitchRoom.services.MatchedWishlistRecordService;
+import vt.CS5934.SwitchRoom.services.OfferWishlistLookUpService;
+import vt.CS5934.SwitchRoom.services.UserService;
+
+import java.util.List;
+
+
+/**
+ * The "@RestController" made the class into rest handle class
+ * The "@RequestMapping("example")" on the class level make it only react to url ".../example/..."
+ */
+@CrossOrigin(
+        allowCredentials = "true",
+        origins = {"http://localhost:8080/"}
+)
+@RestController
+@RequestMapping("notification")
+public class NotificationController {
+    /**
+     * Autowired is a Spring feature that it will create or looking for the existing object in memory.
+     * It usually uses on Repository class, Service class, or some globe object in the class.
+     */
+    @Autowired
+    MatchedWishlistRecordService matchedWishlistRecordService;
+
+    /**
+     * Autowired is a Spring feature that it will create or looking for the existing object in memory.
+     * It usually uses on Repository class, Service class, or some globe object in the class.
+     */
+    @Autowired
+    OfferWishlistLookUpService offerWishlistLookUpService;
+    /**
+     * Autowired is a Spring feature that it will create or looking for the existing object in memory.
+     * It usually uses on Repository class, Service class, or some globe object in the class.
+     */
+    @Autowired
+    DealWithWishlist dealWithWishlist;
+
+    /**
+     * You can use logger.[trace,debug,info,warn,error]("messages") to log into file
+     */
+    private final Logger logger = LoggerFactory.getLogger(UserController.class);
+
+    /**
+     * This function will handle the post function and change the JSON body into data class
+     */
+    @CrossOrigin
+    @GetMapping("/{userId}")
+    public ResponseModel getNotification(@PathVariable long userId) {
+        logger.info("You reached the getNotification() function.");
+//        System.out.println(userId);
+        try{
+            List<MatchedWishlistRecordModel> offerNotifications = matchedWishlistRecordService.getOfferListWithIDFromDB(userId);
+//            System.out.println(offerNotifications);
+//            List<ExampleModel> exampleModels = exampleService.getAllExampleModelsFromDB();
+            return new ResponseModel(
+                    "This this a notification String response",
+                    HttpStatus.OK,
+                    offerNotifications);
+        }catch (Exception e){
+            return new ResponseModel(
+                    "Error occur on get All ExampleModels, Error info is: " + e,
+                    HttpStatus.OK,
+                    null);
+        }
+    }
+
+    /**
+     * This function will handle the post function and change the JSON body into data class
+     */
+    @CrossOrigin(
+            allowCredentials = "true",
+            origins = {"http://localhost:8080/"}
+    )
+    @GetMapping("/wish/{userId}")
+    public ResponseModel getNotificationwish(@PathVariable long userId) {
+        logger.info("You reached the getNotificationwish() function.");
+//        System.out.println(userId);
+        try{
+            List<UserOfferWishlistLookUpModel> lookup = offerWishlistLookUpService.getOfferWishlistLookUpWithIDFromDB(userId);
+            System.out.println(lookup);
+            List<MatchedWishlistRecordModel> wishlists = dealWithWishlist.getMatchedWishlist(lookup);
+//            List<MatchedWishlistRecordModel> offerNotifications = matchedWishlistRecordService.getOfferListWithIDFromDB(userId);
+//            List<ExampleModel> exampleModels = exampleService.getAllExampleModelsFromDB();
+            return new ResponseModel(
+                    "This this a notification String response",
+                    HttpStatus.OK,
+                    wishlists);
+        }catch (Exception e){
+            return new ResponseModel(
+                    "Error occur on get All ExampleModels, Error info is: " + e,
+                    HttpStatus.OK,
+                    null);
+        }
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/OfferPageController.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/OfferPageController.java
index a170c45d6b17f1dd3574ca4b30c602e10b62a46d..1a9a84181bc4277f2325171f0c5c9be1d3289f1a 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/OfferPageController.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/OfferPageController.java
@@ -10,9 +10,15 @@ import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.*;
 import vt.CS5934.SwitchRoom.models.ResponseModel;
 import vt.CS5934.SwitchRoom.models.UserOfferModel;
+import vt.CS5934.SwitchRoom.models.WishlistMatchRequestInfo;
 import vt.CS5934.SwitchRoom.services.OfferPageService;
 
-@CrossOrigin
+import java.util.ArrayList;
+
+@CrossOrigin(
+        allowCredentials = "true",
+        origins = {"http://localhost:8080/"}
+)
 @RestController
 @RequestMapping("offer")
 public class OfferPageController {
@@ -25,8 +31,8 @@ public class OfferPageController {
      * This class will fetch user's offer from DB and send to front end
      * @return ResponseModel contains offer data
      */
-    @GetMapping("/{userId}")
-    public ResponseModel getUserOfferInfo(@PathVariable Long userId){
+    @GetMapping
+    public ResponseModel getUserOfferInfo(@CookieValue(value = "userId") Long userId){
         ResponseModel responseModel = new ResponseModel();
         try{
             responseModel.setMessage("Success");
@@ -51,7 +57,7 @@ public class OfferPageController {
             responseModel.setData(offerPageService.saveNewUserOffer(offerModel));
             return responseModel;
         }catch (Exception e){
-            logger.error("Error in createNewUserOffer: "+e);
+            logger.error("Error in createNewUserOffer: "+e.fillInStackTrace());
             responseModel.setMessage("Failed, Reason: " + e);
             responseModel.setStatus(HttpStatus.NOT_FOUND);
             responseModel.setData(null);
@@ -60,11 +66,12 @@ public class OfferPageController {
     }
 
     @PostMapping("/updateOffer")
-    public ResponseModel updateUserOffer(UserOfferModel offerModel){
+    public ResponseModel updateUserOffer(@RequestBody UserOfferModel offerModel){
+        offerPageService.removeOfferFromMatchedTable(offerModel.getUserId());
         return createNewUserOffer(offerModel);
     }
 
-    @DeleteMapping("/{userId}")
+    @DeleteMapping("/deleteOffer/{userId}")
     public ResponseModel deleteUserOffer(@PathVariable Long userId){
         ResponseModel responseModel = new ResponseModel();
         try{
@@ -82,4 +89,26 @@ public class OfferPageController {
         }
     }
 
+    @GetMapping("/wishlistMatchRequestInfoList")
+    public ResponseModel getWishlistMatchRequestInfoList(@CookieValue(value = "userId") Long userId){
+        ResponseModel responseModel = new ResponseModel();
+        try{
+            responseModel.setMessage("Success");
+            responseModel.setStatus(HttpStatus.OK);
+            responseModel.setData(offerPageService.getWishlistMatchRequestInfoList(userId));
+            return responseModel;
+        }catch (Exception e){
+            logger.error("Error in getWishlistMatchRequestInfoList: "+e.fillInStackTrace());
+            responseModel.setMessage("Failed, Reason: " + e);
+            responseModel.setStatus(HttpStatus.NOT_FOUND);
+            responseModel.setData(new ArrayList<WishlistMatchRequestInfo>());
+            return responseModel;
+        }
+    }
+
 }
+/*
+Change logs:
+Date        |       Author          |   Description
+2022-11-05  |    Fangzheng Zhang    |   add getWishlistMatchRequestInfoList function
+ */
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/SearchFlightController.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/SearchFlightController.java
index a74b70cc64602b9693e5b905ba34dd5afd7b3c31..575f9adbad9663a7d89357df24a1d80fee6a698f 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/SearchFlightController.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/SearchFlightController.java
@@ -7,27 +7,38 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.*;
+import vt.CS5934.SwitchRoom.models.FlightResultModel;
 import vt.CS5934.SwitchRoom.models.ResponseModel;
 import vt.CS5934.SwitchRoom.models.SerachFlightModel;
+import vt.CS5934.SwitchRoom.services.FlightApiService;
+import org.springframework.beans.factory.annotation.Autowired;
 
+import java.util.List;
 
-@CrossOrigin
+
+@CrossOrigin(
+        allowCredentials = "true",
+        origins = {"http://localhost:8080/"}
+)
 @RestController
 @RequestMapping("searchflight")
 public class SearchFlightController {
 
     private final Logger logger = LoggerFactory.getLogger(SearchFlightController.class);
 
-//    @Autowired
-//    OfferPageService offerPageService;
+    @Autowired
+    FlightApiService flightApiService;
 
     @PostMapping("/newFlight")
     public ResponseModel createNewSearchFlight(@RequestBody SerachFlightModel newFlight){
         ResponseModel responseModel = new ResponseModel();
         try{
+            List<FlightResultModel> flightList = flightApiService.performSearch(newFlight);
             responseModel.setMessage("Success");
             responseModel.setStatus(HttpStatus.OK);
-            responseModel.setData(newFlight);
+            responseModel.setData(flightList);
+//            System.out.println(flightApiService.performSearch(newFlight));
+//            responseModel.setData(newFlight);
             return responseModel;
         }catch (Exception e){
             logger.error("Error in createSearchFlight: "+e);
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/UserController.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/UserController.java
index 89404aff781ece5441a10a98e52dd19a3b1ec78d..f6fb157f2391b6e0ecdaf7c7f02b5ea9b208bafc 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/UserController.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/UserController.java
@@ -1,5 +1,6 @@
 package vt.CS5934.SwitchRoom.controllers;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -7,15 +8,21 @@ import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.*;
 import vt.CS5934.SwitchRoom.models.ResponseModel;
 import vt.CS5934.SwitchRoom.models.UserModel;
+import vt.CS5934.SwitchRoom.services.Token;
 import vt.CS5934.SwitchRoom.services.UserService;
 
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
 import java.security.NoSuchAlgorithmException;
 
 /**
  * The "@RestController" made the class into rest handle class
  * The "@RequestMapping("example")" on the class level make it only react to url ".../example/..."
  */
-@CrossOrigin
+@CrossOrigin(
+        allowCredentials = "true",
+        origins = {"http://localhost:8080/"}
+)
 @RestController
 @RequestMapping("user")
 public class UserController {
@@ -55,36 +62,92 @@ public class UserController {
     }
 
     @PostMapping("/loginUser")
-    public ResponseModel loginUser(@RequestBody UserModel user) throws NoSuchAlgorithmException {
-        logger.info("You reached the handlePost() functions.");
+    public ResponseModel loginUser(@RequestBody UserModel userInfo, HttpServletResponse servletResponse)
+            throws NoSuchAlgorithmException {
         ResponseModel response = new ResponseModel();
-        String inputPassword = userService.hashPassword(user.getPassword());
-//        hash.get_SHA_1_SecurePassword(user.getPassword());
 
-        try{
-            UserModel existUser = userService.loginUser(user.getUsername());
-            if (existUser != null && existUser.getPassword().equals(inputPassword)) {
-                response.setMessage("Login in successfully");
-                response.setStatus(HttpStatus.OK);
-            } else {
-                response.setMessage("Couldn't find an account matching the login info you entered");
-                response.setStatus(HttpStatus.FORBIDDEN);
-            }
-            existUser.setPassword(null);
-            response.setData(existUser);
-
-//            UserModel existUser = userService.loginUser(user.getUsername());
-//            response.setMessage("Login in successfully");
-//            response.setStatus(HttpStatus.OK);
-//            existUser.setPassword(null);
-//            response.setData(existUser);
+        String[] result = userService.loginUser(userInfo);
+
+        if (result.length > 0) {
+            Cookie theCookie = new Cookie("userId", result[0]);
+            theCookie.setHttpOnly(false);
+            theCookie.setSecure(false);
+            theCookie.setPath("/");
+            theCookie.setMaxAge(60*60); // 1 hour
+            servletResponse.addCookie(theCookie);
+
+
+            Cookie theCookie2 = new Cookie("token", result[1]);
+            theCookie2.setHttpOnly(false);
+            theCookie2.setSecure(false);
+            theCookie2.setPath("/");
+            theCookie2.setMaxAge(60*60);
+            servletResponse.addCookie(theCookie2);
+
+            response.setMessage("Login in successfully");
+            response.setStatus(HttpStatus.OK);
+        } else {
+            response.setMessage("Couldn't find an account matching the login info you entered");
+            response.setStatus(HttpStatus.FORBIDDEN);
+        }
+
+        return response;
+    }
+    @GetMapping("/checkLoginSession")
+    public ResponseModel checkLoginSession(
+            @CookieValue(value = "userId", required = false) String userId,
+            @CookieValue(value = "token", required = false) String token) {
+        ResponseModel response = new ResponseModel();
+        boolean result = userService.checkLoginSession(userId, token);
+
+        if (result) {
+            response.setStatus(HttpStatus.OK);
+        } else {
+            response.setMessage("Login session expired or invalid");
+            response.setStatus(HttpStatus.FORBIDDEN);
+        }
+
+        return response;
+    }
 
+    @PostMapping("/resetPassword")
+    public ResponseModel resetPassword(
+            @CookieValue(value = "userId", required = false) String userId,
+            @CookieValue(value = "token", required = false) String token,
+            @RequestBody String payload) throws JsonProcessingException, NoSuchAlgorithmException {
+        ResponseModel response = new ResponseModel();
+
+        if (userId == null || token == null || !userService.checkLoginSession(userId, token)) {
+            response.setMessage("Login session expired or invalid");
+            response.setStatus(HttpStatus.FORBIDDEN);
             return response;
-        }catch (Exception e){
-            return new ResponseModel(
-                    "INTERNAL_SERVER_ERROR",
-                    HttpStatus.INTERNAL_SERVER_ERROR,
-                    null);
         }
+
+        boolean result = userService.resetPassword(userId, payload);
+        if (result) {
+            response.setMessage("Successfully reset your password");
+            response.setStatus(HttpStatus.OK);
+        } else {
+            response.setMessage("Couldn't find an account matching the login info you entered");
+            response.setStatus(HttpStatus.FORBIDDEN);
+        }
+
+        return response;
+    }
+
+    @GetMapping("/profile")
+    public ResponseModel getProfile(
+            @CookieValue(value = "userId", required = false) String userId,
+            @CookieValue(value = "token", required = false) String token) {
+        ResponseModel response = new ResponseModel();
+
+        if (userId == null || token == null || !userService.checkLoginSession(userId, token)) {
+            response.setMessage("Login session expired or invalid");
+            response.setStatus(HttpStatus.FORBIDDEN);
+            return response;
+        }
+
+        response = userService.getProfile(userId);
+        return response;
     }
 }
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/WishlistPageController.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/WishlistPageController.java
index 2f6a29ff46a65a9c0f486f5ea38f09c54bc5615f..869e2825b35b5451ddb386ce9b8d910ba7c967b9 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/WishlistPageController.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/WishlistPageController.java
@@ -5,11 +5,17 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.*;
+import vt.CS5934.SwitchRoom.models.OfferMatchRequestInfo;
 import vt.CS5934.SwitchRoom.models.ResponseModel;
 import vt.CS5934.SwitchRoom.models.WishlistItemModel;
 import vt.CS5934.SwitchRoom.services.WishlistPageService;
 
-@CrossOrigin
+import java.util.List;
+
+@CrossOrigin(
+        allowCredentials = "true",
+        origins = {"http://localhost:8080/"}
+)
 @RestController
 @RequestMapping("wishlist")
 public class WishlistPageController {
@@ -19,8 +25,8 @@ public class WishlistPageController {
     @Autowired
     WishlistPageService wishlistPageService;
 
-    @GetMapping("/{userId}")
-    public ResponseModel getWishlistList(@PathVariable Long userId){
+    @GetMapping
+    public ResponseModel getWishlistList(@CookieValue(value = "userId") Long userId){
         ResponseModel responseModel = new ResponseModel();
         try{
             responseModel.setMessage("Success");
@@ -36,8 +42,8 @@ public class WishlistPageController {
         }
     }
 
-    @PostMapping("/newWishlistItem/{userId}")
-    public ResponseModel saveNewWishlistItem(@PathVariable Long userId,
+    @PostMapping("/newWishlistItem")
+    public ResponseModel saveNewWishlistItem(@CookieValue(value = "userId") Long userId,
                                              @RequestBody WishlistItemModel wishlistItemModel){
         ResponseModel responseModel = new ResponseModel();
         try{
@@ -71,10 +77,11 @@ public class WishlistPageController {
         }
     }
 
-    @DeleteMapping("/deleteWishlistItem/{userId}")
-    public ResponseModel deleteWishlistItem(@PathVariable Long userId, @RequestParam Long wishlistItemId){
+    @DeleteMapping("/deleteWishlistItem/{wishlistItemId}")
+    public ResponseModel deleteWishlistItem(@PathVariable Long wishlistItemId){
         ResponseModel responseModel = new ResponseModel();
         try{
+            Long userId = wishlistPageService.getPairedUserId(wishlistItemId);
             wishlistPageService.deleteWishlistItem(wishlistItemId);
             responseModel.setMessage("Success");
             responseModel.setStatus(HttpStatus.OK);
@@ -88,11 +95,48 @@ public class WishlistPageController {
             return responseModel;
         }
     }
+
+    @GetMapping("/loadOfferMatchList/{wishlistItemId}")
+    public ResponseModel getOfferMatchList(@PathVariable Long wishlistItemId){
+        ResponseModel responseModel = new ResponseModel();
+        try{
+            List<OfferMatchRequestInfo> offerMatchRequestInfoList =
+                    wishlistPageService.getOfferMatchList(wishlistItemId);
+            responseModel.setMessage("Success");
+            responseModel.setStatus(HttpStatus.OK);
+            responseModel.setData(offerMatchRequestInfoList);
+            return responseModel;
+        }catch (Exception e){
+            logger.error("Error in getOfferMatchList: "+e.fillInStackTrace());
+            responseModel.setMessage("getOfferMatchList Failed, Reason: " + e);
+            responseModel.setStatus(HttpStatus.NOT_FOUND);
+            responseModel.setData(null);
+            return responseModel;
+        }
+    }
+    @PostMapping("/loadOfferMatchCount")
+    public ResponseModel getOfferMatchCount(@RequestBody List<Long> wishlistItemIdList){
+        ResponseModel responseModel = new ResponseModel();
+        try{
+            List<Long> offerMatchCount = wishlistPageService.getOfferMatchCount(wishlistItemIdList);
+            responseModel.setMessage("Success");
+            responseModel.setStatus(HttpStatus.OK);
+            responseModel.setData(offerMatchCount);
+            return responseModel;
+        }catch (Exception e){
+            logger.error("Error in getOfferMatchCount: "+e.fillInStackTrace());
+            responseModel.setMessage("getOfferMatchCount Failed, Reason: " + e);
+            responseModel.setStatus(HttpStatus.NOT_FOUND);
+            responseModel.setData(null);
+            return responseModel;
+        }
+    }
 }
 
 /*
 Change logs:
 Date        |       Author          |   Description
 2022-10-21  |    Fangzheng Zhang    |    create class and init
-
+2022-11-03  |    Fangzheng Zhang    |   Remove user id in the parameter, since cookie is ready
+2022-11-05  |    Fangzheng Zhang    |   add getOfferMatchList function and getOfferMatchCount function
  */
\ No newline at end of file
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/jobs/OfferWishlistMatchingJob.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/jobs/OfferWishlistMatchingJob.java
new file mode 100644
index 0000000000000000000000000000000000000000..8abe78e63600f7a9c90f754961b4cfa261a021eb
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/jobs/OfferWishlistMatchingJob.java
@@ -0,0 +1,302 @@
+/**
+ * This class contains the business logic about find matches between offers and wishlist items
+ */
+
+package vt.CS5934.SwitchRoom.jobs;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import vt.CS5934.SwitchRoom.models.*;
+import vt.CS5934.SwitchRoom.repositories.*;
+import vt.CS5934.SwitchRoom.utility.LookupTables;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static vt.CS5934.SwitchRoom.utility.UsefulTools.DATE_FORMAT;
+
+
+@Component
+@EnableAsync
+public class OfferWishlistMatchingJob {
+
+    private final Logger logger = LoggerFactory.getLogger(OfferWishlistMatchingJob.class);
+
+    @Autowired
+    MatchingJobInfoRepository matchingJobInfoRepository;
+    @Autowired
+    UserOfferRepository userOfferRepository;
+    @Autowired
+    OfferWaitingMatchRepository offerWaitingMatchRepository;
+    @Autowired
+    WishlistItemRepository wishlistItemRepository;
+    @Autowired
+    WishlistWaitingMatchRepository wishlistWaitingMatchRepository;
+
+    @Autowired
+    MatchedWishlistRecordRepository matchedWishlistRecordRepository;
+
+
+    @Async
+    @Scheduled(fixedDelayString = "${offer.wishlist.job.gap.seconds:60}000",
+            initialDelayString = "${offer.wishlist.job.init.delay.seconds:60}000")
+    public void jobStarter(){
+        logger.info("Offer Wishlist Job start ...");
+        HashMap<Long, MatchingJobInfoModel> lastPullTimeMap = new HashMap<>();
+        lastPullTimeMap.put(LookupTables.OFFER_JOB_DB_ID, null);
+        lastPullTimeMap.put(LookupTables.WISHLIST_JOB_DB_ID, null);
+        lastPullTimeMap.put(LookupTables.MATCHING_JOB_DB_ID, null);
+        List<OfferWaitingMatchModel> newOfferWaitingRecordList = null;
+        List<WishlistWaitingMatchModel> newWishlistWaitingRecordList = null;
+
+        try{
+            //check the job status table, get the last pull time
+            getLastPullTime(lastPullTimeMap);
+            logger.info("getLastPullTime() finished");
+
+            // Query and push the new offer records into its waiting list
+            newOfferWaitingRecordList =
+                    pushNewOfferRecordsIntoWaitingTable(lastPullTimeMap.get(LookupTables.OFFER_JOB_DB_ID));
+            logger.info("pushNewOfferRecordsIntoWaitingTable() finished");
+
+            // Query and push the new wishlist records into its waiting list
+            newWishlistWaitingRecordList =
+                    pushNewWishlistItemRecordsIntoWaitingTable(lastPullTimeMap.get(LookupTables.WISHLIST_JOB_DB_ID));
+            logger.info("pushNewWishlistItemRecordsIntoWaitingTable() finished");
+
+        }catch (Exception e){
+            logger.error("Error occur when fetch the new records from Offer table / Wishlist table or" +
+                    "push them into their waiting table: " +e.fillInStackTrace());
+            // may need to stop the task if needed.
+        }
+
+        try{
+            //find the match records and push to the matched table
+            findMatchFromWaitingTable(lastPullTimeMap.get(LookupTables.MATCHING_JOB_DB_ID), newOfferWaitingRecordList,
+                    newWishlistWaitingRecordList);
+        }catch (Exception e){
+            logger.error("Error occur when finding matches and push them to matched table: " +e.fillInStackTrace());
+        }
+
+    }
+
+
+
+
+    /**
+     * This function is to get the last pull time into a map, so the job knows the starting time range.
+     * If DB do not have the job record info, it will build a default with starting of time as last pull time
+     * @param lastPullTimeMap a map with job ids
+     */
+    private void getLastPullTime(HashMap<Long, MatchingJobInfoModel> lastPullTimeMap){
+        logger.info("Starting getLastPullTime function");
+        for(Long jobId : lastPullTimeMap.keySet()){
+            MatchingJobInfoModel jobInfo = matchingJobInfoRepository.findByJobId(jobId);
+            logger.info("Got job with id: {} info, the record is: {}", jobId, jobInfo);
+            if(jobInfo == null){
+                logger.info("Offer job info is null, building initial offer job info record");
+                jobInfo = new MatchingJobInfoModel(jobId,LookupTables.JOB_STATUS.Running, new Date(0));
+            }
+            logger.info("The last pull time for job with id: {} is: {}",
+                    jobId, DATE_FORMAT.format(jobInfo.getLastPullTime()));
+            jobInfo.setJobStatus(LookupTables.JOB_STATUS.Running);
+            jobInfo = matchingJobInfoRepository.save(jobInfo);
+            lastPullTimeMap.put(jobId,jobInfo);
+        }
+    }
+
+    /**
+     * This function will pull the new Offer records from Offer_table and push them into offer_waiting_table
+     * @param offerJobRecord offer job information to start the task
+     */
+    private List<OfferWaitingMatchModel> pushNewOfferRecordsIntoWaitingTable(MatchingJobInfoModel offerJobRecord){
+        logger.info("Starting pushNewOfferRecordsIntoWaitingTable function with lastPullTime:{}"
+                ,DATE_FORMAT.format(offerJobRecord.getLastPullTime()));
+
+        // update the job info record time
+        Date lastPullOfferTime = offerJobRecord.getLastPullTime();
+        offerJobRecord.setJobStatus(LookupTables.JOB_STATUS.Done);
+        offerJobRecord.setLastPullTime(new Date(System.currentTimeMillis()));
+
+        // fetch the Offer records and push them to waiting table
+        List<UserOfferModel> newOfferList = userOfferRepository
+                .findAllByOfferingAndModifyDateAfter(true, lastPullOfferTime);
+        logger.info("Fetched {} new Offer records, and set the last pull time to {}", newOfferList.size(),
+                DATE_FORMAT.format(offerJobRecord.getLastPullTime()));
+
+        List<OfferWaitingMatchModel> newOfferWaitingRecordList = newOfferList.parallelStream().map(offerRecord->
+                new OfferWaitingMatchModel(offerRecord.getUserId(), offerRecord.getAvailableTimeStart(),
+                        offerRecord.getAvailableTimeEnd(), offerRecord.getStateCityCode()))
+                        .toList();
+        offerWaitingMatchRepository.saveAll(newOfferWaitingRecordList);
+
+        matchingJobInfoRepository.save(offerJobRecord);
+        return newOfferWaitingRecordList;
+    }
+
+    /**
+     * This function will pull the new wishlist records from wishlist_table and push them into wishlist_waiting_table
+     * @param wishlistJobInfo wishlist job information to start the task
+     */
+    private List<WishlistWaitingMatchModel> pushNewWishlistItemRecordsIntoWaitingTable(MatchingJobInfoModel
+                                                                                               wishlistJobInfo){
+        logger.info("Starting pushNewWishlistItemRecordsIntoWaitingTable function with lastPullTime:{}"
+                ,DATE_FORMAT.format(wishlistJobInfo.getLastPullTime()));
+
+        // update the job info record time
+        Date lastPullOfferTime = wishlistJobInfo.getLastPullTime();
+        wishlistJobInfo.setJobStatus(LookupTables.JOB_STATUS.Done);
+        wishlistJobInfo.setLastPullTime(new Date(System.currentTimeMillis()));
+
+        // fetch the Wishlist records and push them to waiting table
+        List<WishlistItemModel> newWishlistItemList = wishlistItemRepository
+                .findAllByModifyDateAfter(lastPullOfferTime);
+        logger.info("Fetched {} new Offer records, and set the last pull time to {}", newWishlistItemList.size(),
+                DATE_FORMAT.format(wishlistJobInfo.getLastPullTime()));
+
+        List<WishlistWaitingMatchModel> newWishlistWaitingRecordList = newWishlistItemList
+                .parallelStream().map( newWishlistItem -> new WishlistWaitingMatchModel(
+                        newWishlistItem.getWishlistItemId(), newWishlistItem.getStartTime()
+                        , newWishlistItem.getEndTime(), newWishlistItem.getStateCityCode()))
+                .toList();
+        wishlistWaitingMatchRepository.saveAll(newWishlistWaitingRecordList);
+
+        matchingJobInfoRepository.save(wishlistJobInfo);
+        return newWishlistWaitingRecordList;
+    }
+
+    /**
+     * This function will check records in the waiting table and try to match them. if match find, it will push them
+     * into matched table.
+     * @param matchJobRecord job info
+     */
+    private void findMatchFromWaitingTable(MatchingJobInfoModel matchJobRecord,
+                                           List<OfferWaitingMatchModel> newOfferRecords,
+                                           List<WishlistWaitingMatchModel> newWishlistRecords){
+        logger.info("Starting findMatchFromWaitingTable function with lastPullTime:{}"
+                ,DATE_FORMAT.format(matchJobRecord.getLastPullTime()));
+        // update the job info record time
+        Date lastPullOfferTime = matchJobRecord.getLastPullTime();
+        matchJobRecord.setJobStatus(LookupTables.JOB_STATUS.Done);
+        matchJobRecord.setLastPullTime(new Date(System.currentTimeMillis()));
+
+        // if the list is null, fetch new records
+        if(newOfferRecords == null)  newOfferRecords =
+                offerWaitingMatchRepository.findAllByModifyDateAfter(lastPullOfferTime);
+        if(newWishlistRecords == null) newWishlistRecords =
+                wishlistWaitingMatchRepository.findAllByModifyDateAfter(lastPullOfferTime);
+
+        // if one of them have new records
+        if(newOfferRecords.size() > 0 || newWishlistRecords.size() > 0){
+            // load new Offers into map
+
+            ConcurrentMap<Long, List<OfferWaitingMatchModel>> newStateCityCodeOfferMap =
+                    loadOfferListIntoMap(newOfferRecords);
+            ConcurrentMap<Long, List<WishlistWaitingMatchModel>> newStateCityCodeWishlistMap =
+                    loadWishlistListIntoMap(newWishlistRecords);
+
+            // fetch both old records
+            List<OfferWaitingMatchModel> oldOfferRecords =
+                    offerWaitingMatchRepository.findAllByModifyDateLessThanEqualAndStateCityCodeIn(lastPullOfferTime,
+                            newStateCityCodeWishlistMap.keySet());
+            List<WishlistWaitingMatchModel> oldWishlistRecords =
+                    wishlistWaitingMatchRepository.findAllByModifyDateLessThanEqualAndStateCityCodeIn(lastPullOfferTime,
+                            newStateCityCodeOfferMap.keySet());
+
+            // build maps by use the StateCityCode as the key so make the next pair step easier.
+
+            ConcurrentMap<Long, List<OfferWaitingMatchModel>> oldStateCityCodeOfferMap =
+                    loadOfferListIntoMap(oldOfferRecords);
+            ConcurrentMap<Long, List<WishlistWaitingMatchModel>> oldStateCityCodeWishlistMap =
+                    loadWishlistListIntoMap(oldWishlistRecords);
+
+            // after fetch all new Wishlist item records by unique stateCityCode
+            // match them with all Offer records
+            newStateCityCodeWishlistMap.entrySet()
+                    .parallelStream()
+                    .forEach(entry -> {
+                        List<OfferWaitingMatchModel> newStateCityCodeOfferList =
+                                !newStateCityCodeOfferMap.containsKey(entry.getKey())? new ArrayList<>()
+                                : newStateCityCodeOfferMap.get(entry.getKey());
+                        List<OfferWaitingMatchModel> oldStateCityCodeOfferList =
+                                !oldStateCityCodeOfferMap.containsKey(entry.getKey())? new ArrayList<>()
+                                :oldStateCityCodeOfferMap.get(entry.getKey());
+                        List<OfferWaitingMatchModel> offerList =
+                                Stream.concat(newStateCityCodeOfferList.stream(),
+                                        oldStateCityCodeOfferList.stream()).toList();
+                        findMatchedOfferForNewWishlistItemToDB(offerList, entry.getValue());
+                    });
+
+
+            // If new offers and old Wishlist item records' unique stateCityCode has intersection,
+            // fetch old Wishlist item by new Offer stateCityCode
+            if(newOfferRecords.size() > 0){
+                oldStateCityCodeWishlistMap.entrySet()
+                        .parallelStream()
+                        .forEach(entry ->{
+                            List<OfferWaitingMatchModel> newStateCityCodeOfferList =
+                                    !newStateCityCodeOfferMap.containsKey(entry.getKey())? new ArrayList<>()
+                                            : newStateCityCodeOfferMap.get(entry.getKey());
+                            findMatchedOfferForNewWishlistItemToDB(newStateCityCodeOfferList,
+                                    entry.getValue());
+                        });
+            }
+
+        }
+
+        matchingJobInfoRepository.save(matchJobRecord);
+    }
+
+
+    private void findMatchedOfferForNewWishlistItemToDB(List<OfferWaitingMatchModel> offerList,
+                                  List<WishlistWaitingMatchModel> wishlistItemList) {
+        wishlistItemList.parallelStream().forEach(wishlistItem ->
+            useWishlistItemAndOfferListBuildMatchedRecordDB(wishlistItem, offerList)
+        );
+
+    }
+
+    private void useWishlistItemAndOfferListBuildMatchedRecordDB(WishlistWaitingMatchModel wishlistItem,
+                                                               List<OfferWaitingMatchModel> offerList) {
+        List<MatchedWishlistRecordModel> matchedRecordList = offerList.parallelStream()
+                .filter(offer-> isOverlapping(wishlistItem.getStartTime(),wishlistItem.getEndTime(),
+                        offer.getStartTime(),offer.getEndTime()))
+                .map(offer -> new MatchedWishlistRecordModel(wishlistItem.getWishlistItemId(),
+                        offer.getOfferId(), LookupTables.MATCHING_RECORD_USER_RESULT.Waiting,
+                        LookupTables.MATCHING_RECORD_USER_RESULT.Waiting))
+                .toList();
+
+        matchedWishlistRecordRepository.saveAll(matchedRecordList);
+    }
+
+    private ConcurrentMap<Long, List<OfferWaitingMatchModel>> loadOfferListIntoMap(
+            List<OfferWaitingMatchModel> offerRecords){
+        return offerRecords.parallelStream()
+                .collect(Collectors.groupingByConcurrent(OfferWaitingMatchModel::getStateCityCode));
+    }
+
+    private ConcurrentMap<Long, List<WishlistWaitingMatchModel>> loadWishlistListIntoMap(
+            List<WishlistWaitingMatchModel> wishlistRecords){
+        return wishlistRecords.parallelStream()
+                .collect(Collectors.groupingByConcurrent(WishlistWaitingMatchModel::getStateCityCode));
+    }
+
+    private boolean isOverlapping(Date start1, Date end1, Date start2, Date end2) {
+        return start1.before(end2) && start2.before(end1);
+    }
+
+}
+/*
+Change logs:
+Date        |       Author          |   Description
+2022-10-30  |   Fangzheng Zhang     |   implemented match service
+2022-11-03  |   Fangzheng Zhang     |   Optimised the code with parallel stream
+ */
\ No newline at end of file
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/FlightResultModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/FlightResultModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..4a126aa2b41497e2dfacb747b7b6b796f61fa22a
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/FlightResultModel.java
@@ -0,0 +1,192 @@
+package vt.CS5934.SwitchRoom.models;
+
+public class FlightResultModel {
+
+    private Integer id;
+    //    Travel detail
+    private String departure0;
+    private String arrival0;
+    private String departureDateTime_0;
+    private String arrivalDateTime_0;
+    private String classOfService_0;
+    private String aircraftType_0;
+    private Double distance_0;
+
+
+    //    Return detail
+    private String departure_1;
+    private String arrival_1;
+    private String departureDateTime_1;
+    private String arrivalDateTime_1;
+    private String classOfService_1;
+    private String aircraftType_1;
+    private Double distance_1;
+    private Double price;
+    private String airlines;
+    private String detail_url;
+
+
+    public FlightResultModel(Integer id, String departure0, String arrival0, String departureDateTime_0, String arrivalDateTime_0, String classOfService_0, String aircraftType_0, Double distance_0, String departure_1, String arrival_1, String departureDateTime_1, String arrivalDateTime_1, String classOfService_1, String aircraftType_1, Double distance_1, Double price, String airlines, String detail_url) {
+        this.id = id;
+        this.departure0 = departure0;
+        this.arrival0 = arrival0;
+        this.departureDateTime_0 = departureDateTime_0;
+        this.arrivalDateTime_0 = arrivalDateTime_0;
+        this.classOfService_0 = classOfService_0;
+        this.aircraftType_0 = aircraftType_0;
+        this.distance_0 = distance_0;
+        this.departure_1 = departure_1;
+        this.arrival_1 = arrival_1;
+        this.departureDateTime_1 = departureDateTime_1;
+        this.arrivalDateTime_1 = arrivalDateTime_1;
+        this.classOfService_1 = classOfService_1;
+        this.aircraftType_1 = aircraftType_1;
+        this.distance_1 = distance_1;
+        this.price = price;
+        this.airlines = airlines;
+        this.detail_url = detail_url;
+    }
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getDeparture0() {
+        return departure0;
+    }
+
+    public void setDeparture0(String departure0) {
+        this.departure0 = departure0;
+    }
+
+    public String getArrival0() {
+        return arrival0;
+    }
+
+    public void setArrival0(String arrival0) {
+        this.arrival0 = arrival0;
+    }
+
+    public String getDepartureDateTime_0() {
+        return departureDateTime_0;
+    }
+
+    public void setDepartureDateTime_0(String departureDateTime_0) {
+        this.departureDateTime_0 = departureDateTime_0;
+    }
+
+    public String getArrivalDateTime_0() {
+        return arrivalDateTime_0;
+    }
+
+    public void setArrivalDateTime_0(String arrivalDateTime_0) {
+        this.arrivalDateTime_0 = arrivalDateTime_0;
+    }
+
+    public String getClassOfService_0() {
+        return classOfService_0;
+    }
+
+    public void setClassOfService_0(String classOfService_0) {
+        this.classOfService_0 = classOfService_0;
+    }
+
+    public String getAircraftType_0() {
+        return aircraftType_0;
+    }
+
+    public void setAircraftType_0(String aircraftType_0) {
+        this.aircraftType_0 = aircraftType_0;
+    }
+
+    public Double getDistance_0() {
+        return distance_0;
+    }
+
+    public void setDistance_0(Double distance_0) {
+        this.distance_0 = distance_0;
+    }
+
+    public String getDeparture_1() {
+        return departure_1;
+    }
+
+    public void setDeparture_1(String departure_1) {
+        this.departure_1 = departure_1;
+    }
+
+    public String getArrival_1() {
+        return arrival_1;
+    }
+
+    public void setArrival_1(String arrival_1) {
+        this.arrival_1 = arrival_1;
+    }
+
+    public String getDepartureDateTime_1() {
+        return departureDateTime_1;
+    }
+
+    public void setDepartureDateTime_1(String departureDateTime_1) {
+        this.departureDateTime_1 = departureDateTime_1;
+    }
+
+    public String getArrivalDateTime_1() {
+        return arrivalDateTime_1;
+    }
+
+    public void setArrivalDateTime_1(String arrivalDateTime_1) {
+        this.arrivalDateTime_1 = arrivalDateTime_1;
+    }
+
+    public String getClassOfService_1() {
+        return classOfService_1;
+    }
+
+    public void setClassOfService_1(String classOfService_1) {
+        this.classOfService_1 = classOfService_1;
+    }
+
+    public String getAircraftType_1() {
+        return aircraftType_1;
+    }
+
+    public void setAircraftType_1(String aircraftType_1) {
+        this.aircraftType_1 = aircraftType_1;
+    }
+
+    public Double getDistance_1() {
+        return distance_1;
+    }
+
+    public void setDistance_1(Double distance_1) {
+        this.distance_1 = distance_1;
+    }
+
+    public Double getPrice() {
+        return price;
+    }
+
+    public void setPrice(Double price) {
+        this.price = price;
+    }
+
+    public String getAirlines() {
+        return airlines;
+    }
+
+    public void setAirlines(String airlines) {
+        this.airlines = airlines;
+    }
+
+    public String getDetail_url() {
+        return detail_url;
+    }
+
+    public void setDetail_url(String detail_url) {
+        this.detail_url = detail_url;
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/MatchedRecordIdModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/MatchedRecordIdModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..95000dcef8c1f438deb8ff60931e079663b44e91
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/MatchedRecordIdModel.java
@@ -0,0 +1,45 @@
+package vt.CS5934.SwitchRoom.models;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+public class MatchedRecordIdModel implements Serializable {
+
+    private Long offerId;
+    private Long wishlistItemId;
+
+    public MatchedRecordIdModel(){}
+    public MatchedRecordIdModel(Long offerId, Long wishlistItemId) {
+        this.offerId = offerId;
+        this.wishlistItemId = wishlistItemId;
+    }
+
+    public Long getOfferId() {
+        return offerId;
+    }
+
+    public void setOfferId(Long offerId) {
+        this.offerId = offerId;
+    }
+
+    public Long getWishlistItemId() {
+        return wishlistItemId;
+    }
+
+    public void setWishlistItemId(Long wishlistItemId) {
+        this.wishlistItemId = wishlistItemId;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        MatchedRecordIdModel that = (MatchedRecordIdModel) o;
+        return Objects.equals(offerId, that.offerId) && Objects.equals(wishlistItemId, that.wishlistItemId);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(offerId, wishlistItemId);
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/MatchedWishlistRecordModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/MatchedWishlistRecordModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d47292fea38e33f44c5df68d74a35d1548134a5
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/MatchedWishlistRecordModel.java
@@ -0,0 +1,73 @@
+package vt.CS5934.SwitchRoom.models;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.UpdateTimestamp;
+import vt.CS5934.SwitchRoom.utility.LookupTables;
+
+import javax.persistence.*;
+import java.util.Date;
+
+@Entity
+@Data
+@Table(name = "matched_wishlist_record_table")
+@IdClass(MatchedRecordIdModel.class)
+@NoArgsConstructor
+public class MatchedWishlistRecordModel {
+    @Id
+    private Long offerId;
+    @Id
+    private Long wishlistItemId;
+    private LookupTables.MATCHING_RECORD_USER_RESULT offerResult;
+
+    private LookupTables.MATCHING_RECORD_USER_RESULT wishlistResult;
+    @UpdateTimestamp
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name = "modify_date")
+    private Date modifyDate;
+
+    public MatchedWishlistRecordModel(Long wishlistItemId, Long offerId,
+                                      LookupTables.MATCHING_RECORD_USER_RESULT offerResult,
+                                      LookupTables.MATCHING_RECORD_USER_RESULT wishlistResult) {
+        this.wishlistItemId = wishlistItemId;
+        this.offerId = offerId;
+        this.offerResult = offerResult;
+        this.wishlistResult = wishlistResult;
+    }
+
+    public Long getWishlistItemId() {
+        return wishlistItemId;
+    }
+
+    public void setWishlistItemId(Long wishlistItemId) {
+        this.wishlistItemId = wishlistItemId;
+    }
+
+    public Long getOfferId() {
+        return offerId;
+    }
+
+    public void setOfferId(Long offerId) {
+        this.offerId = offerId;
+    }
+
+    public LookupTables.MATCHING_RECORD_USER_RESULT getOfferResult() {
+        return offerResult;
+    }
+
+    public void setOfferResult(LookupTables.MATCHING_RECORD_USER_RESULT offerResult) {
+        this.offerResult = offerResult;
+    }
+
+    public LookupTables.MATCHING_RECORD_USER_RESULT getWishlistResult() {
+        return wishlistResult;
+    }
+
+    public void setWishlistResult(LookupTables.MATCHING_RECORD_USER_RESULT wishlistResult) {
+        this.wishlistResult = wishlistResult;
+    }
+
+    public Date getModifyDate() {
+        return modifyDate;
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/MatchingJobInfoModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/MatchingJobInfoModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..0da2ead69bd8a2d72868b06bf1bb72dd96984e2a
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/MatchingJobInfoModel.java
@@ -0,0 +1,60 @@
+package vt.CS5934.SwitchRoom.models;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.UpdateTimestamp;
+import vt.CS5934.SwitchRoom.utility.LookupTables;
+
+import javax.persistence.*;
+import java.util.Date;
+
+@Data
+@Entity
+@Table(name = "matching_job_info_table")
+@NoArgsConstructor
+public class MatchingJobInfoModel {
+
+    @Id
+    private Long jobId;
+    private LookupTables.JOB_STATUS jobStatus;
+    private java.util.Date lastPullTime;
+    @UpdateTimestamp
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name = "modify_date")
+    private java.util.Date modifyDate;
+
+    public MatchingJobInfoModel(Long jobId, LookupTables.JOB_STATUS jobStatus, Date lastPullTime) {
+        this.jobId = jobId;
+        this.jobStatus = jobStatus;
+        this.lastPullTime = lastPullTime;
+    }
+
+    public Long getJobId() {
+        return jobId;
+    }
+
+    public void setJobId(Long jobId) {
+        this.jobId = jobId;
+    }
+
+    public LookupTables.JOB_STATUS getJobStatus() {
+        return jobStatus;
+    }
+
+    public void setJobStatus(LookupTables.JOB_STATUS jobStatus) {
+        this.jobStatus = jobStatus;
+    }
+
+    public java.util.Date getLastPullTime() {
+        return lastPullTime;
+    }
+
+    public void setLastPullTime(java.util.Date lastStartTime) {
+        this.lastPullTime = lastStartTime;
+    }
+
+    public java.util.Date getModifyDate() {
+        return modifyDate;
+    }
+
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/OfferMatchRequestInfo.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/OfferMatchRequestInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a2378da9c1bb75d0f58229b0ce81e5ff9f00777
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/OfferMatchRequestInfo.java
@@ -0,0 +1,73 @@
+package vt.CS5934.SwitchRoom.models;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class OfferMatchRequestInfo {
+    private Long offerOwnerId;
+    private Long wishListId;
+    private Date startTime;
+    private Date endTime;
+    private Integer zipCode;
+    private String hostName;
+
+    public OfferMatchRequestInfo(Long offerOwnerId, Long wishListId, Date startTime, Date endTime,
+                                 Integer zipCode, String hostName) {
+        this.offerOwnerId = offerOwnerId;
+        this.wishListId = wishListId;
+        this.startTime = startTime;
+        this.endTime = endTime;
+        this.zipCode = zipCode;
+        this.hostName = hostName;
+    }
+
+    public Long getOfferOwnerId() {
+        return offerOwnerId;
+    }
+
+    public void setOfferOwnerId(Long offerOwnerId) {
+        this.offerOwnerId = offerOwnerId;
+    }
+
+    public Long getWishListId() {
+        return wishListId;
+    }
+
+    public void setWishListId(Long wishListId) {
+        this.wishListId = wishListId;
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    public Integer getZipCode() {
+        return zipCode;
+    }
+
+    public void setZipCode(Integer zipCode) {
+        this.zipCode = zipCode;
+    }
+
+    public String getHostName() {
+        return hostName;
+    }
+
+    public void setHostName(String hostName) {
+        this.hostName = hostName;
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/OfferWaitingMatchModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/OfferWaitingMatchModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..9d943f2e7d451c55942200feddabc11c58f6fb82
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/OfferWaitingMatchModel.java
@@ -0,0 +1,68 @@
+package vt.CS5934.SwitchRoom.models;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.UpdateTimestamp;
+
+import javax.persistence.*;
+import java.util.Date;
+
+@Data
+@Entity
+@Table(name = "offer_waiting_match_table")
+@NoArgsConstructor
+public class OfferWaitingMatchModel {
+    @Id
+    private Long offerId;
+    private Date startTime;
+    private Date endTime;
+    private Long stateCityCode;
+    @UpdateTimestamp
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name = "modify_date")
+    private java.util.Date modifyDate;
+
+    public OfferWaitingMatchModel(Long offerId, Date startTime, Date endTime, Long stateCityCode) {
+        this.offerId = offerId;
+        this.startTime = startTime;
+        this.endTime = endTime;
+        this.stateCityCode = stateCityCode;
+    }
+
+    public Long getOfferId() {
+        return offerId;
+    }
+
+    public void setOfferId(Long offerId) {
+        this.offerId = offerId;
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    public Long getStateCityCode() {
+        return stateCityCode;
+    }
+
+    public void setStateCityCode(Long stateCityCode) {
+        this.stateCityCode = stateCityCode;
+    }
+
+    public java.util.Date getModifyDate() {
+        return modifyDate;
+    }
+
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/SerachFlightModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/SerachFlightModel.java
index dc7c1c4438f6fc9b45257a69cf8a0fa38f31b260..61f6277b29437d8bc90a5624a227457267b3183b 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/SerachFlightModel.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/SerachFlightModel.java
@@ -1,6 +1,6 @@
 package vt.CS5934.SwitchRoom.models;
 
-import java.sql.Date;
+import java.util.Date;
 
 public class SerachFlightModel {
 
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/StateCityLookupModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/StateCityLookupModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..b5b47449d446c021092817065cf3b8ad83aeff8c
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/StateCityLookupModel.java
@@ -0,0 +1,48 @@
+package vt.CS5934.SwitchRoom.models;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+
+@Entity
+@Data
+@Table(name = "state_city_lookup_table")
+@NoArgsConstructor
+public class StateCityLookupModel {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long stateCityCode;
+    private Integer stateCode;
+    private String cityName;
+
+    public StateCityLookupModel(Long stateCityCode, Integer stateCode, String cityName) {
+        this.stateCityCode = stateCityCode;
+        this.stateCode = stateCode;
+        this.cityName = cityName;
+    }
+
+    public Long getStateCityCode() {
+        return stateCityCode;
+    }
+
+    public void setStateCityCode(Long stateCityCode) {
+        this.stateCityCode = stateCityCode;
+    }
+
+    public Integer getStateCode() {
+        return stateCode;
+    }
+
+    public void setStateCode(Integer stateCode) {
+        this.stateCode = stateCode;
+    }
+
+    public String getCityName() {
+        return cityName;
+    }
+
+    public void setCityName(String cityName) {
+        this.cityName = cityName;
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserModel.java
index e0d652ea5876ae56f8bf206621a429ff484a040d..1e95cfc1a8f165e633924379e09e09d4e01d0b5a 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserModel.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserModel.java
@@ -39,14 +39,16 @@ public class UserModel {
 
     @Column(name="gender")
     private String gender;
+    private String token;
 
-    public UserModel(String name, String password, String email, String firstname, String lastname, String gender) {
+    public UserModel(String name, String password, String email, String firstname, String lastname, String gender, String token) {
         this.username = name;
         this.password = password;
         this.email = email;
         this.firstname = firstname;
         this.lastname = lastname;
         this.gender = gender;
+        this.token = token;
     }
 
     @Override
@@ -59,6 +61,7 @@ public class UserModel {
                 ", firstname='" + firstname + '\'' +
                 ", lastname='" + lastname + '\'' +
                 ", gender='" + gender + '\'' +
+                ", token='" + token + '\'' +
                 '}';
     }
 
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserOfferModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserOfferModel.java
index 96f6f91aea6761d5277c2e2eddb2d8838a9e8a41..ddd98bd46f1be4dca460a4a9b0c3fbeb3f1c451c 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserOfferModel.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserOfferModel.java
@@ -2,9 +2,10 @@ package vt.CS5934.SwitchRoom.models;
 
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.hibernate.annotations.UpdateTimestamp;
 
 import javax.persistence.*;
-import java.sql.Date;
+import java.util.Date;
 
 @Data
 @Entity
@@ -14,27 +15,38 @@ public class UserOfferModel {
 
     @Id
     private Long userId;
+    private String state;
+    private Integer stateCode;
     private Integer zipCode;
     private String spaceType;
     private String otherSpaceType;
     private String spaceLocateCity;
-    private Long cityCode;
+    private Long stateCityCode;
     private Date availableTimeStart;
     private Date availableTimeEnd;
     private Integer maxNumberOfPeople;
+    @Column(length = 500)
     private String spaceDetails;
     private Boolean offering;
 
-    public UserOfferModel(Long userId, Integer zipCode, String spaceType,
+    @UpdateTimestamp
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name = "modify_date")
+    private java.util.Date modifyDate;
+
+
+    public UserOfferModel(Long userId, String state, Integer stateCode, Integer zipCode, String spaceType,
                           String otherSpaceType, String spaceLocateCity,
                           Long cityCode, Date availableTimeStart, Date availableTimeEnd,
                           Integer maxNumberOfPeople, String spaceDetails, Boolean offering) {
         this.userId = userId;
+        this.state = state;
+        this.stateCode = stateCode;
         this.zipCode = zipCode;
         this.spaceType = spaceType;
         this.otherSpaceType = otherSpaceType;
         this.spaceLocateCity = spaceLocateCity;
-        this.cityCode = cityCode;
+        this.stateCityCode = cityCode;
         this.availableTimeStart = availableTimeStart;
         this.availableTimeEnd = availableTimeEnd;
         this.maxNumberOfPeople = maxNumberOfPeople;
@@ -50,6 +62,22 @@ public class UserOfferModel {
         this.userId = userId;
     }
 
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    public Integer getStateCode() {
+        return stateCode;
+    }
+
+    public void setStateCode(Integer stateCode) {
+        this.stateCode = stateCode;
+    }
+
     public Integer getZipCode() {
         return zipCode;
     }
@@ -82,12 +110,12 @@ public class UserOfferModel {
         this.spaceLocateCity = spaceLocateCity;
     }
 
-    public Long getCityCode() {
-        return cityCode;
+    public Long getStateCityCode() {
+        return stateCityCode;
     }
 
-    public void setCityCode(Long cityCode) {
-        this.cityCode = cityCode;
+    public void setStateCityCode(Long cityCode) {
+        this.stateCityCode = cityCode;
     }
 
     public Date getAvailableTimeStart() {
@@ -135,4 +163,5 @@ public class UserOfferModel {
 Change logs:
 Date        |       Author          |       Description
 2022-10-20  |   Fangzheng Zhang     |    create class and init
+2022-10-30  |   Fangzheng Zhang     |   Add modify_date into DB
  */
\ No newline at end of file
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserOfferWishlistLookUpModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserOfferWishlistLookUpModel.java
index 91cd389ba5e134c9e863de939d564b2013ee2369..fe3ea6401ab5c8380a971cb2428aa522ff57bc80 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserOfferWishlistLookUpModel.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserOfferWishlistLookUpModel.java
@@ -5,11 +5,10 @@ package vt.CS5934.SwitchRoom.models;
 
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.hibernate.annotations.UpdateTimestamp;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import javax.persistence.*;
+import java.util.Date;
 
 @Entity
 @Data
@@ -20,12 +19,15 @@ public class UserOfferWishlistLookUpModel {
     @Id
     private Long wishlistItemId;
     private Long userId;
-    private Long matchingOfferId;
 
-    public UserOfferWishlistLookUpModel(Long userId, Long wishlistItemId, Long matchingOfferId) {
+    @UpdateTimestamp
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name = "modify_date")
+    private Date modifyDate;
+
+    public UserOfferWishlistLookUpModel(Long userId, Long wishlistItemId) {
         this.userId = userId;
         this.wishlistItemId = wishlistItemId;
-        this.matchingOfferId = matchingOfferId;
     }
 
     public Long getUserId() {
@@ -44,18 +46,11 @@ public class UserOfferWishlistLookUpModel {
         this.wishlistItemId = wishlistId;
     }
 
-    public Long getMatchingOfferId() {
-        return matchingOfferId;
-    }
-
-    public void setMatchingOfferId(Long matchingOfferId) {
-        this.matchingOfferId = matchingOfferId;
-    }
 }
 
 /*
 Change logs:
 Date        |       Author          |   Description
 2022-10-21  |    Fangzheng Zhang    |    create class and init
-
+2022-10-30  |   Fangzheng Zhang     |   Add modify_date into DB. Remove matchingOfferId, move it to a match result class
  */
\ No newline at end of file
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/WishlistItemModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/WishlistItemModel.java
index feee5ded6e75893f608b0733e7b08f43e7918f8b..a361cb6046362e48436f761fe0cdb95dd0a42afd 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/WishlistItemModel.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/WishlistItemModel.java
@@ -5,9 +5,10 @@ package vt.CS5934.SwitchRoom.models;
 
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.hibernate.annotations.UpdateTimestamp;
 
 import javax.persistence.*;
-import java.sql.Date;
+import java.util.Date;
 
 @Entity
 @Data
@@ -18,17 +19,25 @@ public class WishlistItemModel {
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long wishlistItemId;
     private String cityName;
+    private Long stateCityCode;
     private Integer zipCode;
     private String state;
     private Integer stateCode;
     private Date startTime;
     private Date endTime;
+    @Column(length = 500)
     private String details;
 
-    public WishlistItemModel(Long wishlistItemId, String cityName, String state, Integer stateCode,
+    @UpdateTimestamp
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name = "modify_date")
+    private java.util.Date modifyDate;
+
+    public WishlistItemModel(Long wishlistItemId, String cityName, Long stateCityCode, String state, Integer stateCode,
                              Date startTime, Date endTime, String details, Integer zipCode) {
         this.wishlistItemId = wishlistItemId;
         this.cityName = cityName;
+        this.stateCityCode = stateCityCode;
         this.zipCode = zipCode;
         this.state = state;
         this.stateCode = stateCode;
@@ -37,9 +46,10 @@ public class WishlistItemModel {
         this.details = details;
     }
 
-    public WishlistItemModel(String cityName, String state, Integer stateCode, Date startTime,
+    public WishlistItemModel(String cityName, Long stateCityCode, String state, Integer stateCode, Date startTime,
                              Date endTime, String details) {
         this.cityName = cityName;
+        this.stateCityCode = stateCityCode;
         this.state = state;
         this.stateCode = stateCode;
         this.startTime = startTime;
@@ -50,6 +60,15 @@ public class WishlistItemModel {
     public Long getWishlistItemId() {
         return wishlistItemId;
     }
+
+    public Long getStateCityCode() {
+        return stateCityCode;
+    }
+
+    public void setStateCityCode(Long stateCityCode) {
+        this.stateCityCode = stateCityCode;
+    }
+
     public Integer getZipCode() {
         return zipCode;
     }
@@ -115,5 +134,6 @@ public class WishlistItemModel {
 Change logs:
 Date        |       Author          |   Description
 2022-10-21  |    Fangzheng Zhang    |    create class and init
+2022-10-30  |   Fangzheng Zhang     |   Add modify_date into DB
 
  */
\ No newline at end of file
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/WishlistMatchRequestInfo.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/WishlistMatchRequestInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..3cacc490f40feac3566ad443d9f55b6b4cdfcfdb
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/WishlistMatchRequestInfo.java
@@ -0,0 +1,83 @@
+package vt.CS5934.SwitchRoom.models;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class WishlistMatchRequestInfo {
+    private Long wishlistOwnerId;
+    private Long wishlistId;
+    private Date startTime;
+    private Date endTime;
+    private String wishListOwnerName;
+    private Boolean hasOffer;
+    private Integer zipCode;
+
+    public WishlistMatchRequestInfo(Long wishlistOwnerId, Long wishlistId, Date startTime, Date endTime,
+                                    String wishListOwnerName, Boolean hasOffer, Integer zipCode) {
+        this.wishlistOwnerId = wishlistOwnerId;
+        this.wishlistId = wishlistId;
+        this.startTime = startTime;
+        this.endTime = endTime;
+        this.wishListOwnerName = wishListOwnerName;
+        this.hasOffer = hasOffer;
+        this.zipCode = zipCode;
+    }
+
+    public Long getWishlistOwnerId() {
+        return wishlistOwnerId;
+    }
+
+    public void setWishlistOwnerId(Long wishlistOwnerId) {
+        this.wishlistOwnerId = wishlistOwnerId;
+    }
+
+    public Long getWishlistId() {
+        return wishlistId;
+    }
+
+    public void setWishlistId(Long wishlistId) {
+        this.wishlistId = wishlistId;
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    public String getWishListOwnerName() {
+        return wishListOwnerName;
+    }
+
+    public void setWishListOwnerName(String wishListOwnerName) {
+        this.wishListOwnerName = wishListOwnerName;
+    }
+
+    public Boolean getHasOffer() {
+        return hasOffer;
+    }
+
+    public void setHasOffer(Boolean hasOffer) {
+        this.hasOffer = hasOffer;
+    }
+
+    public Integer getZipCode() {
+        return zipCode;
+    }
+
+    public void setZipCode(Integer zipCode) {
+        this.zipCode = zipCode;
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/WishlistWaitingMatchModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/WishlistWaitingMatchModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..68a01271b0b73dcb5dc0eca50a739ab4dd16e6a4
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/WishlistWaitingMatchModel.java
@@ -0,0 +1,68 @@
+package vt.CS5934.SwitchRoom.models;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.UpdateTimestamp;
+
+import javax.persistence.*;
+import java.util.Date;
+
+@Data
+@Entity
+@Table(name = "wishlist_waiting_match_table")
+@NoArgsConstructor
+public class WishlistWaitingMatchModel {
+
+    @Id
+    private Long wishlistItemId;
+    private Date startTime;
+    private Date endTime;
+    private Long stateCityCode;
+    @UpdateTimestamp
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name = "modify_date")
+    private java.util.Date modifyDate;
+
+    public WishlistWaitingMatchModel(Long wishlistItemId, Date startTime, Date endTime, Long stateCityCode) {
+        this.wishlistItemId = wishlistItemId;
+        this.startTime = startTime;
+        this.endTime = endTime;
+        this.stateCityCode = stateCityCode;
+    }
+
+    public Long getWishlistItemId() {
+        return wishlistItemId;
+    }
+
+    public void setWishlistItemId(Long wishlistItemId) {
+        this.wishlistItemId = wishlistItemId;
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    public Long getStateCityCode() {
+        return stateCityCode;
+    }
+
+    public void setStateCityCode(Long stateCityCode) {
+        this.stateCityCode = stateCityCode;
+    }
+
+    public java.util.Date getModifyDate() {
+        return modifyDate;
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/MatchedWishlistRecordRepository.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/MatchedWishlistRecordRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..e9ef530a764129d691d31f707e55f231040cd650
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/MatchedWishlistRecordRepository.java
@@ -0,0 +1,30 @@
+package vt.CS5934.SwitchRoom.repositories;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import vt.CS5934.SwitchRoom.models.MatchedRecordIdModel;
+import vt.CS5934.SwitchRoom.models.MatchedWishlistRecordModel;
+
+import java.util.List;
+
+public interface MatchedWishlistRecordRepository extends JpaRepository<MatchedWishlistRecordModel, MatchedRecordIdModel> {
+    /**
+     * The function name is the SQL query:
+     *  findByIdAndName(long inputId, String inputName) == "SELETE * FROM table WHERE Id==inputId" AND name == inputName;
+     * This is an example of how to declare a SQL command, those will be use in service class
+     * @param offerId the id in table you are looking for
+     * @return ExampleModel object
+     */
+    List<MatchedWishlistRecordModel> findAllByOfferId(Long offerId);
+    /**
+     * The function name is the SQL query:
+     *  findByIdAndName(long inputId, String inputName) == "SELETE * FROM table WHERE Id==inputId" AND name == inputName;
+     * This is an example of how to declare a SQL command, those will be use in service class
+     * @param wishlistItemId the id in table you are looking for
+     * @return ExampleModel object
+     */
+    List<MatchedWishlistRecordModel> findAllByWishlistItemId(Long wishlistItemId);
+
+    void deleteAllByOfferId(Long offerId);
+    void deleteAllByWishlistItemId(Long wishlistItemId);
+    Long countByWishlistItemId(Long wishlistItemId);
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/MatchingJobInfoRepository.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/MatchingJobInfoRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..e85b9e57e39b0572d4d481da5af1ba46bdc06178
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/MatchingJobInfoRepository.java
@@ -0,0 +1,8 @@
+package vt.CS5934.SwitchRoom.repositories;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import vt.CS5934.SwitchRoom.models.MatchingJobInfoModel;
+
+public interface MatchingJobInfoRepository extends JpaRepository<MatchingJobInfoModel, Long> {
+    MatchingJobInfoModel findByJobId(Long jobId);
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/OfferWaitingMatchRepository.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/OfferWaitingMatchRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..3672521aa5dcecbff18e9a8b48dc4de9c1e385b4
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/OfferWaitingMatchRepository.java
@@ -0,0 +1,20 @@
+package vt.CS5934.SwitchRoom.repositories;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import vt.CS5934.SwitchRoom.models.OfferWaitingMatchModel;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+public interface OfferWaitingMatchRepository extends JpaRepository<OfferWaitingMatchModel, Long> {
+    List<OfferWaitingMatchModel> findAllByStateCityCodeAndModifyDateAfter(Long stateCityCode, Date lastPullTime);
+    @Query()
+    List<OfferWaitingMatchModel> findAllByStateCityCodeAndModifyDateBefore(Long stateCityCode, Date lastPullTime);
+
+    List<OfferWaitingMatchModel> findAllByModifyDateAfter(Date lastPullTime);
+    List<OfferWaitingMatchModel> findAllByModifyDateLessThanEqualAndStateCityCodeIn(Date lastPullTime, Set<Long> StateCityCodeSet);
+    void deleteAllByOfferId(Long offerId);
+
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/StateCityLookupRepository.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/StateCityLookupRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..e909f2fcb69f182a88cdf933d63e4c795f3558a0
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/StateCityLookupRepository.java
@@ -0,0 +1,9 @@
+package vt.CS5934.SwitchRoom.repositories;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import vt.CS5934.SwitchRoom.models.StateCityLookupModel;
+
+public interface StateCityLookupRepository extends JpaRepository<StateCityLookupModel, Long> {
+    StateCityLookupModel findByCityNameAndStateCode(String cityName, Integer stateCode);
+    StateCityLookupModel findByStateCityCode(Long stateCityCode);
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserOfferRepository.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserOfferRepository.java
index 24fb209ea24cd0018f81f7edad6dde4e6ad08887..4550399df11ef2e44c6b12d8c297ca11b4c2d566 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserOfferRepository.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserOfferRepository.java
@@ -3,8 +3,13 @@ package vt.CS5934.SwitchRoom.repositories;
 import org.springframework.data.jpa.repository.JpaRepository;
 import vt.CS5934.SwitchRoom.models.UserOfferModel;
 
+import javax.xml.crypto.Data;
+import java.util.Date;
+import java.util.List;
+
 public interface UserOfferRepository extends JpaRepository<UserOfferModel, Long> {
 
     UserOfferModel findByUserId(Long userId);
     void deleteByUserId(Long userId);
+    List<UserOfferModel> findAllByOfferingAndModifyDateAfter(Boolean offering, Date modifyDate);
 }
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserOfferWishlistLookUpRepository.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserOfferWishlistLookUpRepository.java
index fd79c1f06b7ef6d65781d609f9d7104002356b7d..02be9157138c577264aaeca9fca8a2d1be1fd4c0 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserOfferWishlistLookUpRepository.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserOfferWishlistLookUpRepository.java
@@ -8,8 +8,7 @@ import java.util.List;
 
 public interface UserOfferWishlistLookUpRepository extends JpaRepository<UserOfferWishlistLookUpModel, Long> {
     List<UserOfferWishlistLookUpModel> findAllByUserId(Long userId);
-    UserOfferModel findByWishlistItemId(Long wishlistItemId);
-    List<UserOfferModel> findAllByMatchingOfferId(Long matchingOfferId);
+    UserOfferWishlistLookUpModel findByWishlistItemId(Long wishlistItemId);
     void deleteByWishlistItemId(Long wishlistItemId);
 }
 
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserRepository.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserRepository.java
index 665888482bf64f4bb2821ae937ce88f8b2876653..a57cb14b937ab5511d02dfa7c04891ea8206cdfd 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserRepository.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserRepository.java
@@ -20,11 +20,11 @@ public interface UserRepository extends JpaRepository<UserModel, Integer> {
      * @param userId the id in table you are looking for
      * @return ExampleModel object
      */
-    UserModel findByUserId(long userId);
+    UserModel findByUserId(int userId);
 
     UserModel findByUsername(String username);
 
     List<UserModel> findAll();
-    void deleteByUserId(long userId);
+    void deleteByUserId(Long userId);
 
 }
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/WishlistItemRepository.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/WishlistItemRepository.java
index 5c89d1bd302177f28d3ebf869820ad5ccc75850c..a1ff688424d6b92b2931cb87b6d7c208264f4b41 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/WishlistItemRepository.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/WishlistItemRepository.java
@@ -3,8 +3,12 @@ package vt.CS5934.SwitchRoom.repositories;
 import org.springframework.data.jpa.repository.JpaRepository;
 import vt.CS5934.SwitchRoom.models.WishlistItemModel;
 
+import java.util.Date;
+import java.util.List;
+
 public interface WishlistItemRepository extends JpaRepository<WishlistItemModel, Long> {
     WishlistItemModel findByWishlistItemId(Long wishlistItemId);
     void deleteByWishlistItemId(Long wishlistItemId);
+    List<WishlistItemModel> findAllByModifyDateAfter(Date modifyDate);
 
 }
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/WishlistWaitingMatchRepository.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/WishlistWaitingMatchRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec4027858c2e4e50c5514a09df143081ba03f6d1
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/WishlistWaitingMatchRepository.java
@@ -0,0 +1,23 @@
+package vt.CS5934.SwitchRoom.repositories;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import vt.CS5934.SwitchRoom.models.WishlistWaitingMatchModel;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+public interface WishlistWaitingMatchRepository extends JpaRepository<WishlistWaitingMatchModel, Long> {
+    @Query("SELECT DISTINCT item.stateCityCode FROM WishlistWaitingMatchModel item WHERE item.modifyDate > ?1")
+    List<Long> findAllUniqueStateCityCodeAfter(Date lastPullTime);
+
+    @Query("SELECT DISTINCT item.stateCityCode FROM WishlistWaitingMatchModel item WHERE item.modifyDate <= ?1")
+    List<Long> findAllUniqueStateCityCodeBefore(Date lastPullTime);
+
+    List<WishlistWaitingMatchModel> findAllByModifyDateAfter(Date lastPullTime);
+    List<WishlistWaitingMatchModel> findAllByModifyDateLessThanEqualAndStateCityCodeIn(Date lastPullTime, Set<Long> stateCityCodeSet);
+
+    void deleteAllByWishlistItemId(Long wishlistItemId);
+
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/DealWithWishlist.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/DealWithWishlist.java
new file mode 100644
index 0000000000000000000000000000000000000000..247b50dfdce25a6f4e50ab124416eb22ade7813a
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/DealWithWishlist.java
@@ -0,0 +1,37 @@
+package vt.CS5934.SwitchRoom.services;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import vt.CS5934.SwitchRoom.models.MatchedWishlistRecordModel;
+import vt.CS5934.SwitchRoom.models.UserOfferWishlistLookUpModel;
+import vt.CS5934.SwitchRoom.repositories.MatchedWishlistRecordRepository;
+import vt.CS5934.SwitchRoom.repositories.UserOfferWishlistLookUpRepository;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class DealWithWishlist {
+
+    /**
+     * You can use logger.[trace,debug,info,warn,error]("messages") to log into file
+     */
+    private final Logger logger = LoggerFactory.getLogger(ExampleService.class);
+
+    @Autowired
+    MatchedWishlistRecordRepository matchedWishlistRecordRepository;
+
+    public List<MatchedWishlistRecordModel> getMatchedWishlist(List<UserOfferWishlistLookUpModel> list) {
+        logger.info("Reached get finalAns");
+        List<MatchedWishlistRecordModel> finalAns = new ArrayList<>();
+        for(int i = 0; i < list.size(); i++) {
+            System.out.println(list.get(i).getWishlistItemId());
+            List<MatchedWishlistRecordModel> ans = matchedWishlistRecordRepository.findAllByWishlistItemId(list.get(i).getWishlistItemId());
+            System.out.println(ans);
+            finalAns.addAll(ans);
+        }
+        return finalAns;
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/FlightApiService.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/FlightApiService.java
new file mode 100644
index 0000000000000000000000000000000000000000..90d04b5c97d4d3bc4b1520ef8f2bc58806f9026f
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/FlightApiService.java
@@ -0,0 +1,253 @@
+package vt.CS5934.SwitchRoom.services;
+
+import org.springframework.stereotype.Service;
+import vt.CS5934.SwitchRoom.models.FlightResultModel;
+import vt.CS5934.SwitchRoom.models.SerachFlightModel;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.io.Serializable;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.springframework.boot.configurationprocessor.json.JSONArray;
+import org.springframework.boot.configurationprocessor.json.JSONObject;
+@Service
+public class FlightApiService implements Serializable {
+    private List<FlightResultModel> listOfFlightResults;
+
+    public List<FlightResultModel> getListOfSearchedFlights() {
+        return listOfFlightResults;
+    }
+
+    public void setListOfSearchedFlights(List<FlightResultModel> listOfFlightResults) {
+        this.listOfFlightResults = listOfFlightResults;
+    }
+    private final Logger logger = LoggerFactory.getLogger(FlightApiService.class);
+    public List<FlightResultModel> performSearch(SerachFlightModel newFlight) {
+
+        listOfFlightResults = new ArrayList<>();
+
+        try {
+//            String URI = "https://tripadvisor16.p.rapidapi.com/api/v1/flights/searchFlights?" +
+//                    "sourceAirportCode=" + upperCase(newFlight.getDeparture()) + "&destinationAirportCode="
+//                    + upperCase(newFlight.getDestination()) + "&date=" + convertDate1(newFlight.getDate1()) + "&itineraryType=ROUND_TRIP&sortOrder=PRICE&numAdults=" + newFlight.getNumAdults() + "&numSeniors=" + newFlight.getNumSeniors() + "&classOfService=" + newFlight.getClassOfService() + "&returnDate=" + convertDate1(newFlight.getDate2()) + "&currencyCode=USD";
+//            System.out.println(URI);
+//            HttpRequest request = HttpRequest.newBuilder()
+//                    .uri(java.net.URI.create(URI))
+//                    .header("X-RapidAPI-Key", "ccf2ddc79amsh1e381193b5f63a9p179bfdjsn9ed1d6b269f7")
+//                    .header("X-RapidAPI-Host", "tripadvisor16.p.rapidapi.com")
+//                    .method("GET", HttpRequest.BodyPublishers.noBody())
+//                    .build();
+//            HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
+//            JSONObject searchResultsJsonObject = new JSONObject(response.body());
+
+            String file = "flightapi.json";
+            String json = readFileAsString(file);
+            JSONObject searchResultsJsonObject = new JSONObject(json);
+
+            JSONObject dataJsonObject = searchResultsJsonObject.getJSONObject("data");
+            JSONArray flightJsonArray = dataJsonObject.getJSONArray("flights");
+
+
+            int index = 0;
+            if (flightJsonArray.length() > index) {
+                while (flightJsonArray.length() > index) {
+                    JSONObject flightObject = flightJsonArray.getJSONObject(index);
+
+                    JSONArray segmentsJSONArray = flightObject.getJSONArray("segments");
+
+                    //    ************* travel **************
+                    JSONObject firstObject = segmentsJSONArray.getJSONObject(0);
+                    JSONArray legsObject = firstObject.getJSONArray("legs");
+                    JSONObject TravelObject = legsObject.getJSONObject(0);
+
+                    JSONObject secondObject = segmentsJSONArray.getJSONObject(1);
+                    JSONArray legsObj = secondObject.getJSONArray("legs");
+                    JSONObject ReturnObject = legsObj.getJSONObject(0);
+
+                    JSONArray purchaseLinksJSONArray = flightObject.getJSONArray("purchaseLinks");
+                    JSONObject purchaseObject = purchaseLinksJSONArray.getJSONObject(0);
+
+                    String departure_0 = TravelObject.optString("originStationCode", "");
+                    if (departure_0.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+                    String arrival_0 = TravelObject.optString("destinationStationCode", "");
+                    if (arrival_0.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+                    String departureDateTime_0 = TravelObject.optString("departureDateTime", "");
+                    if (departureDateTime_0.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+                    String arrivalDateTime_0 = TravelObject.optString("arrivalDateTime", "");
+                    if (arrivalDateTime_0.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+
+                    String classOfService_0 = TravelObject.optString("classOfService", "");
+                    if (classOfService_0.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+                    String aircraftType_0 = TravelObject.optString("equipmentId", "");
+                    if (aircraftType_0.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+                    Double distance_0 = TravelObject.optDouble("distanceInKM", 0.0);
+                    if (distance_0 == 0.0) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }else {
+                        /* Round the calories value to 2 decimal places */
+                        distance_0 = distance_0 * 100;
+                        distance_0 = (double) Math.round(distance_0);
+                        distance_0 = distance_0 / 100;
+                    }
+
+                    //    ************* return **************
+//                    JSONObject secondObject = segmentsJSONArray.getJSONObject(1);
+//                    JSONArray legsObj = secondObject.getJSONArray("legs");
+//                    JSONObject ReturnObject = legsObj.getJSONObject(0);
+
+
+                    String departure_1 = ReturnObject.optString("originStationCode", "");
+                    if (departure_1.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+                    String arrival_1 = ReturnObject.optString("destinationStationCode", "");
+                    if (arrival_1.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+                    String departureDateTime_1 = ReturnObject.optString("departureDateTime", "");
+                    if (departureDateTime_1.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+                    String arrivalDateTime_1 = ReturnObject.optString("arrivalDateTime", "");
+                    if (arrivalDateTime_1.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+
+                    String classOfService_1 = ReturnObject.optString("classOfService", "");
+                    if (classOfService_1.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+                    String aircraftType_1 = ReturnObject.optString("equipmentId", "");
+                    if (aircraftType_1.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+
+                    Double distance_1 = ReturnObject.optDouble("distanceInKM", 0.0);
+                    if (distance_1 == 0.0) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }else {
+                        /* Round the calories value to 2 decimal places */
+                        distance_1 = distance_1 * 100;
+                        distance_1 = (double) Math.round(distance_1);
+                        distance_1 = distance_1 / 100;
+                    }
+
+//                    JSONArray purchaseLinksJSONArray = flightObject.getJSONArray("purchaseLinks");
+//                    JSONObject purchaseObject = purchaseLinksJSONArray.getJSONObject(0);
+
+                    String airline = purchaseObject.optString("providerId", "");
+                    if (airline.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+                    Double price = purchaseObject.optDouble("totalPrice", 0.0);
+                    if (price == 0.0) {
+                        index++;
+                        continue;   // Jump to the next iteration
+
+                    }else {
+                        /* Round the calories value to 2 decimal places */
+                        price = price * 100;
+                        price = (double) Math.round(price);
+                        price = price / 100;
+                    }
+
+                    String url = purchaseObject.optString("url", "");
+                    if (url.equals("")) {
+                        index++;
+                        continue;   // Jump to the next iteration
+                    }
+
+                    FlightResultModel flight = new FlightResultModel(index,departure_0,arrival_0,convertDate(departureDateTime_0),convertDate(arrivalDateTime_0),classOfService_0,aircraftType_0,distance_0,departure_1,arrival_1,convertDate(departureDateTime_1),convertDate(arrivalDateTime_1),classOfService_1,aircraftType_1,distance_1,price,airline,url);
+//                    System.out.println(flight);
+                    listOfFlightResults.add(flight);
+                    index++;
+
+                }
+            }
+            else {
+                logger.error("Error in getFlightApiService: ");
+            }
+        }catch (Exception ex){
+            logger.error("Error in getFlightApiService: "+ex);
+        }
+        return listOfFlightResults;
+    }
+    public static String upperCase(String str) {
+        if (str == null) {
+            return null;
+        }
+        return str.toUpperCase();
+    }
+    public static String convertDate(String d) {
+        try {
+            //2022-12-01T06:30:00+05:30
+            SimpleDateFormat oldDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
+            Date date = oldDateFormat.parse(d);
+            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mmaaa");
+            return simpleDateFormat.format(date);
+        }
+        catch (ParseException exc) {
+            return "N/A";
+        }
+    }
+
+    public static String convertDate1(Date d) {
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        return simpleDateFormat.format(d);
+    }
+    public static String readFileAsString(String file)throws Exception
+    {
+        return new String(Files.readAllBytes(Paths.get(file)));
+    }
+}
+
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/MatchedWishlistRecordService.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/MatchedWishlistRecordService.java
new file mode 100644
index 0000000000000000000000000000000000000000..8840f63b35e7063bca9e7759f319825795d5bc08
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/MatchedWishlistRecordService.java
@@ -0,0 +1,31 @@
+package vt.CS5934.SwitchRoom.services;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import vt.CS5934.SwitchRoom.models.MatchedWishlistRecordModel;
+import vt.CS5934.SwitchRoom.repositories.MatchedWishlistRecordRepository;
+
+import java.util.List;
+
+@Service
+public class MatchedWishlistRecordService {
+
+    /**
+     * You can use logger.[trace,debug,info,warn,error]("messages") to log into file
+     */
+    private final Logger logger = LoggerFactory.getLogger(MatchedWishlistRecordService.class);
+
+    /**
+     * Autowired is a Spring feature that it will create or looking for the existing object in memory.
+     * It usually uses on Repository class, Service class, or some globe object in the class.
+     */
+    @Autowired
+    MatchedWishlistRecordRepository matchedWishlistRecordRepository;
+
+    public List<MatchedWishlistRecordModel> getOfferListWithIDFromDB(long id){
+        logger.info("Reached getOfferListIDFromDB()");
+        return matchedWishlistRecordRepository.findAllByOfferId(id);
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/OfferPageService.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/OfferPageService.java
index f40cc76e4bc8d66b951ffe06c16b2160de621dbd..a1501db98129ccd5802277ba5967435dd0c4c8dd 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/OfferPageService.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/OfferPageService.java
@@ -4,8 +4,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import vt.CS5934.SwitchRoom.models.UserOfferModel;
-import vt.CS5934.SwitchRoom.repositories.UserOfferRepository;
+import org.springframework.transaction.annotation.Transactional;
+import vt.CS5934.SwitchRoom.models.*;
+import vt.CS5934.SwitchRoom.repositories.*;
+import vt.CS5934.SwitchRoom.utility.StateCodeMap;
+
+import java.util.ArrayList;
+import java.util.List;
 
 @Service
 public class OfferPageService {
@@ -13,6 +18,18 @@ public class OfferPageService {
 
     @Autowired
     UserOfferRepository userOfferRepository;
+    @Autowired
+    StateCityLookupRepository stateCityLookupRepository;
+    @Autowired
+    MatchedWishlistRecordRepository matchedWishlistRecordRepository;
+    @Autowired
+    OfferWaitingMatchRepository offerWaitingMatchRepository;
+    @Autowired
+    UserOfferWishlistLookUpRepository userOfferWishlistLookUpRepository;
+    @Autowired
+    UserRepository userRepository;
+    @Autowired
+    WishlistItemRepository wishlistItemRepository;
 
     public UserOfferModel getUserOfferInfo(Long userId) {
         UserOfferModel userOfferModel = userOfferRepository.findByUserId(userId);
@@ -25,10 +42,82 @@ public class OfferPageService {
 
 
     public UserOfferModel saveNewUserOffer(UserOfferModel offerModel) {
+        fillStateCodeAndStateCityCode(offerModel);
         return userOfferRepository.save(offerModel);
     }
+    @Transactional
+    public void removeOfferFromMatchedTable (Long offerId){
+        logger.info("Removing all records related to offerId: {} from matched table.", offerId);
+        matchedWishlistRecordRepository.deleteAllByOfferId(offerId);
+    }
 
+    @Transactional
     public void deleteUserOffer(Long userId) {
+        logger.info("Removing all records related to offerId: {} from offer waiting table.", userId);
         userOfferRepository.deleteByUserId(userId);
+        offerWaitingMatchRepository.deleteAllByOfferId(userId);
+        removeOfferFromMatchedTable(userId);
+    }
+
+
+
+
+    /**
+     * This function will take a UserOfferModel. it will fill the StateCode with it first,
+     * then check and update the StateCityCode. If DB do not have the StateCityCode, then build one and fill it in.
+     * @param offerModel the new or updated offerModel
+     */
+    private void fillStateCodeAndStateCityCode(UserOfferModel offerModel){
+
+        // Fill state code in the record
+        offerModel.setStateCode(StateCodeMap.StringToCodeMap.get(offerModel.getState()));
+
+        // Check if the DB have the state city code or not, if not build one
+        StateCityLookupModel stateCityLookupModel = stateCityLookupRepository
+                .findByCityNameAndStateCode(offerModel.getSpaceLocateCity(), offerModel.getStateCode());
+
+        if(stateCityLookupModel == null){
+            // not in DB yet
+            stateCityLookupModel = stateCityLookupRepository.save(
+                    new StateCityLookupModel(null, offerModel.getStateCode(),
+                            offerModel.getSpaceLocateCity()));
+        }
+        offerModel.setStateCityCode(stateCityLookupModel.getStateCityCode());
+    }
+
+    /**
+     * This service will fetch information from many table to get the WishlistMatchRequestInfo, so we can display it in
+     * the offer page
+     * @param userId The id of user who opened the offer page
+     * @return a list of WishlistMatchRequestInfo.
+     */
+    public List<WishlistMatchRequestInfo> getWishlistMatchRequestInfoList(Long userId) {
+        List<WishlistMatchRequestInfo> wishlistMatchRequestInfoList = new ArrayList<>();
+        List<MatchedWishlistRecordModel> matchedRecordList = matchedWishlistRecordRepository.findAllByOfferId(userId);
+        for(MatchedWishlistRecordModel matchedRecord : matchedRecordList){
+            Long requestedWishlistId = matchedRecord.getWishlistItemId();
+            Long wishlistOwnerId = userOfferWishlistLookUpRepository
+                    .findByWishlistItemId(requestedWishlistId).getUserId();
+            // get user information from userRepository, get wishlistItem information from wishlistItem table,
+            //  check if the wishlistItem owner has Offer or not, if does, find zipcode.
+            UserModel wishlistOwnerInfo = userRepository.findByUserId(wishlistOwnerId.intValue());
+            WishlistItemModel wishlistItem = wishlistItemRepository.findByWishlistItemId(requestedWishlistId);
+            UserOfferModel wishlistOwnerOfferModel = userOfferRepository.findByUserId(wishlistOwnerId);
+            WishlistMatchRequestInfo wishlistMatchRequestInfo = new WishlistMatchRequestInfo(wishlistOwnerId,
+                    requestedWishlistId, wishlistItem.getStartTime(), wishlistItem.getEndTime(),
+                    wishlistOwnerInfo.getFirstname() + " " + wishlistOwnerInfo.getLastname(),
+                    wishlistOwnerOfferModel != null && wishlistOwnerOfferModel.getOffering(),
+                    wishlistOwnerOfferModel == null ? null : wishlistOwnerOfferModel.getZipCode());
+            wishlistMatchRequestInfoList.add(wishlistMatchRequestInfo);
+        }
+        return wishlistMatchRequestInfoList;
     }
 }
+/*
+Change logs:
+Date        |       Author          |   Description
+2022-10-21  |    Fangzheng Zhang    |    create class and init
+2022-10-30  |   Fangzheng Zhang     |   implement state city code feature
+2022-11-03  |   Fangzheng Zhang     |   Added update and remove handling for matching waiting table and matched table
+
+ */
\ No newline at end of file
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/OfferWishlistLookUpService.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/OfferWishlistLookUpService.java
new file mode 100644
index 0000000000000000000000000000000000000000..44bbe0768a9fe9e1cac07245b587e84c8ac6b1f4
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/OfferWishlistLookUpService.java
@@ -0,0 +1,34 @@
+package vt.CS5934.SwitchRoom.services;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import vt.CS5934.SwitchRoom.models.ExampleModel;
+import vt.CS5934.SwitchRoom.models.MatchedWishlistRecordModel;
+import vt.CS5934.SwitchRoom.models.UserOfferWishlistLookUpModel;
+import vt.CS5934.SwitchRoom.repositories.MatchedWishlistRecordRepository;
+import vt.CS5934.SwitchRoom.repositories.UserOfferWishlistLookUpRepository;
+
+import java.util.*;
+
+@Service
+public class OfferWishlistLookUpService {
+
+    /**
+     * You can use logger.[trace,debug,info,warn,error]("messages") to log into file
+     */
+    private final Logger logger = LoggerFactory.getLogger(ExampleService.class);
+
+    /**
+     * Autowired is a Spring feature that it will create or looking for the existing object in memory.
+     * It usually uses on Repository class, Service class, or some globe object in the class.
+     */
+    @Autowired
+    UserOfferWishlistLookUpRepository userOfferWishlistLookUpRepository;
+
+    public List<UserOfferWishlistLookUpModel> getOfferWishlistLookUpWithIDFromDB(long id){
+        logger.info("Reached getWishlistLookUpWithIDFromDB()");
+        return userOfferWishlistLookUpRepository.findAllByUserId(id);
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/Token.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/Token.java
new file mode 100644
index 0000000000000000000000000000000000000000..271828118ca2d1e3b4afd30a2bf9d7fe339b5765
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/Token.java
@@ -0,0 +1,29 @@
+package vt.CS5934.SwitchRoom.services;
+
+import io.jsonwebtoken.SignatureAlgorithm;
+import lombok.Getter;
+import io.jsonwebtoken.Jwts;
+
+import java.sql.Date;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+public class Token {
+    @Getter
+    private final String token;
+
+    private Token(String token) {
+        this.token = token;
+    }
+
+    public static Token of(int userId, Long validityInMinutes, String secretKey) {
+        var issueDate = Instant.now();
+        return new Token(
+                Jwts.builder()
+                    .claim("user_id", userId)
+                    .setIssuedAt(Date.from(issueDate))
+                    .setExpiration(Date.from(issueDate.plus(validityInMinutes, ChronoUnit.MINUTES)))
+                    .signWith(SignatureAlgorithm.HS256, secretKey)
+                .compact());
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/UserService.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/UserService.java
index aac7d5e2da2f1162a67f41df220f4b38fb6b5013..50032ddb4efc8eced728087bffa8caf98b7e658c 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/UserService.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/UserService.java
@@ -1,17 +1,24 @@
 package vt.CS5934.SwitchRoom.services;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import net.bytebuddy.implementation.bytecode.Throw;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Service;
 import vt.CS5934.SwitchRoom.hash.SHAModel;
 import vt.CS5934.SwitchRoom.models.ExampleModel;
+import vt.CS5934.SwitchRoom.models.ResponseModel;
 import vt.CS5934.SwitchRoom.models.UserModel;
 import vt.CS5934.SwitchRoom.repositories.UserRepository;
 
 import javax.transaction.Transactional;
 import java.security.NoSuchAlgorithmException;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 @Service
 public class UserService {
@@ -35,16 +42,45 @@ public class UserService {
 
     public UserModel addUserToDB(String username, String password, String email, String firstname, String lastname, String gender){
         logger.info("Reached addNewExampleModelToDB()");
-        UserModel newUser = new UserModel(username, password, email, firstname, lastname, gender);
+        UserModel newUser = new UserModel(username, password, email, firstname, lastname, gender, null);
         userRepository.save(newUser);
         return newUser;
     }
 
-    public UserModel loginUser(String username) {
-        logger.info("Reached loginUser() in UserService");
+    public String[] loginUser(UserModel userInfo) throws NoSuchAlgorithmException {
+        String username = userInfo.getUsername();
+        String password = hashPassword(userInfo.getPassword());
         UserModel existUser = userRepository.findByUsername(username);
 
-        return existUser;
+        if (existUser == null) {
+            logger.error("loginUser: FORBIDDEN (user not found)");
+            return new String[] {};
+        } else if (existUser.getPassword().equals(password)) {
+            var token = Token.of(existUser.getUserId(), 10L, "secret");
+            existUser.setToken(token.getToken());
+            userRepository.save(existUser);
+
+            String result[] = new String[2];
+            result[0] = existUser.getUserId().toString();
+            result[1] = token.getToken();
+            return result;
+        } else {
+            logger.warn("loginUser: FORBIDDEN (wrong password)");
+            return new String[] {};
+        }
+    }
+
+    public boolean checkLoginSession(String userId, String token) {
+        UserModel existUser = userRepository.findByUserId(Integer.parseInt(userId));
+        if (existUser == null) {
+            logger.error("checkLoginSession: FORBIDDEN (user not found)");
+            return false;
+        } else if (existUser.getToken().equals(token)) {
+            return true;
+        } else {
+            logger.error("checkLoginSession: FORBIDDEN (invalid token)");
+            return false;
+        }
     }
 
     public String hashPassword(String password) throws NoSuchAlgorithmException {
@@ -53,5 +89,53 @@ public class UserService {
         return result;
     }
 
+    public boolean resetPassword(String userId, String payload) throws NoSuchAlgorithmException, JsonProcessingException {
+        UserModel existUser = userRepository.findByUserId(Integer.parseInt(userId));
+
+        if (existUser == null) {
+            logger.warn("checkLoginSession: FORBIDDEN (user not found)");
+            return false;
+        }
+        ObjectMapper mapper = new ObjectMapper();
+        String oldPassword = mapper.readTree(payload)
+                .get("oldPassword")
+                .asText();
+        String newPassword = mapper.readTree(payload)
+                .get("newPassword")
+                .asText();
+        String inputOldPassword = hashPassword(oldPassword);
+
+        if (existUser.getPassword().equals(inputOldPassword)) {
+            String inputNewPassword = hashPassword(newPassword);
+            existUser.setPassword(inputNewPassword);
+            userRepository.save(existUser);
+            return true;
+        } else {
+            logger.warn("checkLoginSession: FORBIDDEN (password not matched)");
+            return false;
+        }
+    }
 
+    public ResponseModel getProfile(String userId) {
+        ResponseModel response = new ResponseModel();
+        UserModel existUser = userRepository.findByUserId(Integer.parseInt(userId));
+
+        if (existUser == null) {
+            logger.warn("getProfile: FORBIDDEN (user not found)");
+            response.setMessage("user not found");
+            response.setStatus(HttpStatus.FORBIDDEN);
+            return response;
+        }
+
+        Map<String, String> profile = new LinkedHashMap<>();
+        profile.put("username", existUser.getUsername());
+        profile.put("email", existUser.getEmail());
+        profile.put("firstName", existUser.getFirstname());
+        profile.put("lastName", existUser.getLastname());
+
+        response.setData(profile);
+        response.setStatus(HttpStatus.OK);
+
+        return response;
+    }
 }
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/WishlistPageService.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/WishlistPageService.java
index 64d9e39925937389fee6ea3004119211437a2865..b9b04765212f9fd4bd49f456cafa4cba8a8817ca 100644
--- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/WishlistPageService.java
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/WishlistPageService.java
@@ -6,10 +6,10 @@ package vt.CS5934.SwitchRoom.services;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import vt.CS5934.SwitchRoom.models.UserOfferWishlistLookUpModel;
-import vt.CS5934.SwitchRoom.models.WishlistItemModel;
-import vt.CS5934.SwitchRoom.repositories.UserOfferWishlistLookUpRepository;
-import vt.CS5934.SwitchRoom.repositories.WishlistItemRepository;
+import vt.CS5934.SwitchRoom.models.*;
+import vt.CS5934.SwitchRoom.repositories.*;
+import vt.CS5934.SwitchRoom.utility.StateCodeMap;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -20,6 +20,16 @@ public class WishlistPageService {
     WishlistItemRepository wishlistItemRepository;
     @Autowired
     UserOfferWishlistLookUpRepository userOfferWishlistLookUpRepository;
+    @Autowired
+    StateCityLookupRepository stateCityLookupRepository;
+    @Autowired
+    MatchedWishlistRecordRepository matchedWishlistRecordRepository;
+    @Autowired
+    WishlistWaitingMatchRepository wishlistWaitingMatchRepository;
+    @Autowired
+    UserOfferRepository userOfferRepository;
+    @Autowired
+    UserRepository userRepository;
 
     /**
      * This function will take userId and look into UserOfferWishlistLookUpModel DB and find all the wishlist item id
@@ -45,10 +55,10 @@ public class WishlistPageService {
      */
     @Transactional
     public WishlistItemModel saveNewWishlistItem(Long userId, WishlistItemModel wishlistItemModel) {
-        wishlistItemModel.setWishlistItemId(null);
+        fillStateCodeAndStateCityCode(wishlistItemModel);
         WishlistItemModel wishlistItemModelWithId = wishlistItemRepository.save(wishlistItemModel);
         UserOfferWishlistLookUpModel lookUpModel = new UserOfferWishlistLookUpModel(userId,
-                wishlistItemModelWithId.getWishlistItemId(), null);
+                wishlistItemModelWithId.getWishlistItemId());
         userOfferWishlistLookUpRepository.save(lookUpModel);
         return wishlistItemModelWithId;
     }
@@ -62,6 +72,8 @@ public class WishlistPageService {
     public void deleteWishlistItem(Long wishlistItemId) {
         wishlistItemRepository.deleteByWishlistItemId(wishlistItemId);
         userOfferWishlistLookUpRepository.deleteByWishlistItemId(wishlistItemId);
+        wishlistWaitingMatchRepository.deleteAllByWishlistItemId(wishlistItemId);
+        matchedWishlistRecordRepository.deleteAllByWishlistItemId(wishlistItemId);
     }
 
     /**
@@ -71,16 +83,76 @@ public class WishlistPageService {
      */
     @Transactional
     public WishlistItemModel updateWishlistItem(WishlistItemModel wishlistItemModel) {
+        fillStateCodeAndStateCityCode(wishlistItemModel);
+        matchedWishlistRecordRepository.deleteAllByWishlistItemId(wishlistItemModel.getWishlistItemId());
         return wishlistItemRepository.save(wishlistItemModel);
     }
 
     public WishlistItemModel getWishlistItemInfo(Long wishlistItemId) {
         return wishlistItemRepository.findByWishlistItemId(wishlistItemId);
     }
+
+    public Long getPairedUserId( Long wishlistItemId ){
+        return userOfferWishlistLookUpRepository.findByWishlistItemId(wishlistItemId).getUserId();
+    }
+
+
+    /**
+     * This function will take a UserOfferModel. it will fill the StateCode with it first,
+     * then check and update the StateCityCode. If DB do not have the StateCityCode, then build one and fill it in.
+     * @param wishlistItemModel the new or updated offerModel
+     */
+    private void fillStateCodeAndStateCityCode(WishlistItemModel wishlistItemModel){
+
+        // Fill state code in the record
+        wishlistItemModel.setStateCode(StateCodeMap.StringToCodeMap.get(wishlistItemModel.getState()));
+
+        // Check if the DB have the state city code or not, if not build one
+        StateCityLookupModel stateCityLookupModel = stateCityLookupRepository
+                .findByCityNameAndStateCode(wishlistItemModel.getCityName(), wishlistItemModel.getStateCode());
+
+        if(stateCityLookupModel == null){
+            // not in DB yet
+            stateCityLookupModel = stateCityLookupRepository.save(
+                    new StateCityLookupModel(null, wishlistItemModel.getStateCode(),
+                            wishlistItemModel.getCityName()));
+        }
+        wishlistItemModel.setStateCityCode(stateCityLookupModel.getStateCityCode());
+    }
+
+    /**
+     * This function is used to get the matched offers of the given wishlist item
+     * @param wishlistItemId the target id
+     * @return a list of matched offer info of the given wishlistItem
+     */
+    public List<OfferMatchRequestInfo> getOfferMatchList(Long wishlistItemId) {
+        List<OfferMatchRequestInfo> offerMatchRequestInfoList = new ArrayList<>();
+        List<MatchedWishlistRecordModel> matchedRecordList =
+                matchedWishlistRecordRepository.findAllByWishlistItemId(wishlistItemId);
+        matchedRecordList.forEach( matchedRecord ->{
+            UserOfferModel userOfferModel = userOfferRepository.findByUserId(matchedRecord.getOfferId());
+            UserModel userInfo = userRepository.findByUserId(userOfferModel.getUserId().intValue());
+            offerMatchRequestInfoList.add(new OfferMatchRequestInfo(userOfferModel.getUserId(),
+                    wishlistItemId, userOfferModel.getAvailableTimeStart(),userOfferModel.getAvailableTimeEnd(),
+                    userOfferModel.getZipCode(), userInfo.getFirstname()+" "+ userInfo.getLastname()));
+        });
+        return offerMatchRequestInfoList;
+    }
+
+    public List<Long> getOfferMatchCount(List<Long> wishlistItemIdList) {
+        List<Long> countList = new ArrayList<>();
+        wishlistItemIdList.forEach((wishListId ->{
+            Long count = matchedWishlistRecordRepository.countByWishlistItemId(wishListId);
+            countList.add(count == null ? 0 : count);
+        }));
+        return countList;
+    }
 }
 /*
 Change logs:
 Date        |       Author          |   Description
 2022-10-21  |    Fangzheng Zhang    |    create class and init
-
+2022-10-30  |   Fangzheng Zhang     |   implement state city code feature
+2022-11-03  |   Fangzheng Zhang     |   handle update and deletion to matched table and waiting table
+2022-11-05  |   Fangzheng Zhang     |   Add getOfferMatchList function
  */
\ No newline at end of file
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/LookupTables.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/LookupTables.java
new file mode 100644
index 0000000000000000000000000000000000000000..eac4ced1a48f075ea634c362945f702a3fd9eee7
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/LookupTables.java
@@ -0,0 +1,13 @@
+package vt.CS5934.SwitchRoom.utility;
+
+public class LookupTables {
+    // Matching job service related fields
+    public static final Long OFFER_JOB_DB_ID = 1L;
+    public static final Long WISHLIST_JOB_DB_ID = 2L;
+    public static final Long MATCHING_JOB_DB_ID = 3L;
+
+    // Matching related DB data fields
+    public enum JOB_STATUS {Running, Done, Stopped}
+    public enum MATCHING_RECORD_USER_RESULT {Waiting, Accepted, Declined}
+
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/StateCodeMap.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/StateCodeMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..a088d31dfacb7c6eb666bfb40651736996e95639
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/StateCodeMap.java
@@ -0,0 +1,27 @@
+package vt.CS5934.SwitchRoom.utility;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class StateCodeMap {
+    public static final Map<String, Integer> StringToCodeMap;
+    static {
+        StringToCodeMap = Map.ofEntries(Map.entry("AK", 0), Map.entry("AL", 1), Map.entry("AR", 2),
+                Map.entry("AZ", 3), Map.entry("CA", 4), Map.entry("CO", 5), Map.entry("CT", 6),
+                Map.entry("DE", 7), Map.entry("FL", 8), Map.entry("GA", 9), Map.entry("HI", 10),
+                Map.entry("IA", 11), Map.entry("ID", 12), Map.entry("IL", 13),
+                Map.entry("IN", 14), Map.entry("KS", 15), Map.entry("KY", 16),
+                Map.entry("LA", 17), Map.entry("MA", 18), Map.entry("MD", 19),
+                Map.entry("ME", 20), Map.entry("MI", 21), Map.entry("MN", 22),
+                Map.entry("MO", 23), Map.entry("MS", 24), Map.entry("MT", 25),
+                Map.entry("NC", 26), Map.entry("ND", 27), Map.entry("NE", 28),
+                Map.entry("NH", 29), Map.entry("NJ", 30), Map.entry("NM", 31),
+                Map.entry("NV", 32), Map.entry("NY", 33), Map.entry("OH", 34),
+                Map.entry("OK", 35), Map.entry("OR", 36), Map.entry("PA", 37),
+                Map.entry("RI", 38), Map.entry("SC", 39), Map.entry("SD", 40),
+                Map.entry("TN", 41), Map.entry("TX", 42), Map.entry("UT", 43),
+                Map.entry("VA", 44), Map.entry("VT", 45), Map.entry("WA", 46),
+                Map.entry("WI", 47), Map.entry("WV", 48), Map.entry("WY", 49));
+    }
+}
diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/UsefulTools.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/UsefulTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..d1cba369c510c563e9b7d15fb95a3f2079a830d3
--- /dev/null
+++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/UsefulTools.java
@@ -0,0 +1,7 @@
+package vt.CS5934.SwitchRoom.utility;
+
+import java.text.SimpleDateFormat;
+
+public class UsefulTools {
+    public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+}
diff --git a/BackendFolder/SwitchRoom/src/main/resources/application.properties b/BackendFolder/SwitchRoom/src/main/resources/application.properties
index e8ebd7b1fed9166552622df9a3b58984e34c3ca7..45dc0326a2a696d0e43297d4b5fe74f10c457db9 100644
--- a/BackendFolder/SwitchRoom/src/main/resources/application.properties
+++ b/BackendFolder/SwitchRoom/src/main/resources/application.properties
@@ -7,6 +7,13 @@ spring.datasource.username=root
 spring.datasource.password=mypassword
 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
 spring.jpa.hibernate.ddl-auto=update
-spring.jpa.show-sql=true
+spring.jpa.show-sql=false
 spring.jpa.properties.hibernate.format_sql=true
 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57InnoDBDialect
+
+# SpringBoot scheduling thread pool
+spring.task.scheduling.pool.size = 1
+
+#SpringBoot Offer Wishlist matching job fields:
+offer.wishlist.job.gap.seconds = 60
+offer.wishlist.job.init.delay.seconds = 10
\ No newline at end of file
diff --git a/BackendFolder/SwitchRoom/src/main/resources/data.sql b/BackendFolder/SwitchRoom/src/main/resources/data.sql
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/FrontendFolder/switch-room/package-lock.json b/FrontendFolder/switch-room/package-lock.json
index ab05d8655f44ace5b38641225e9ecaf098abc844..c77aed193834d70fbd25c8a01d6d183ecb67babb 100644
--- a/FrontendFolder/switch-room/package-lock.json
+++ b/FrontendFolder/switch-room/package-lock.json
@@ -8,16 +8,23 @@
       "name": "switch-room",
       "version": "0.1.0",
       "dependencies": {
+        "@element-plus/icons-vue": "^2.0.10",
         "@fortawesome/fontawesome-svg-core": "^6.2.0",
         "@fortawesome/free-brands-svg-icons": "^6.2.0",
         "@fortawesome/free-regular-svg-icons": "^6.2.0",
         "@fortawesome/free-solid-svg-icons": "^6.2.0",
         "@fortawesome/vue-fontawesome": "^3.0.1",
+        "cookie-parser": "^1.4.6",
+        "cors": "^2.8.5",
         "element-plus": "^2.2.18",
+        "pinia": "^2.0.23",
         "vue": "^3.2.13",
-        "vue-router": "^4.0.3"
+        "vue-router": "^4.0.3",
+        "vuex": "^4.1.0"
       },
       "devDependencies": {
+        "@types/cookie-parser": "^1.4.3",
+        "@types/cors": "^2.8.12",
         "@typescript-eslint/eslint-plugin": "^5.4.0",
         "@typescript-eslint/parser": "^5.4.0",
         "@vue/cli-plugin-router": "~5.0.0",
@@ -680,11 +687,7 @@
       "name": "@sxzz/popperjs-es",
       "version": "2.11.7",
       "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
-      "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==",
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/popperjs"
-      }
+      "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
     },
     "node_modules/@sideway/address": {
       "version": "4.1.4",
@@ -845,6 +848,21 @@
         "@types/node": "*"
       }
     },
+    "node_modules/@types/cookie-parser": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz",
+      "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==",
+      "dev": true,
+      "dependencies": {
+        "@types/express": "*"
+      }
+    },
+    "node_modules/@types/cors": {
+      "version": "2.8.12",
+      "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz",
+      "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==",
+      "dev": true
+    },
     "node_modules/@types/eslint": {
       "version": "8.4.6",
       "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz",
@@ -1412,6 +1430,26 @@
         }
       }
     },
+    "node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15": {
+      "name": "vue-loader",
+      "version": "15.10.0",
+      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.0.tgz",
+      "integrity": "sha512-VU6tuO8eKajrFeBzMssFUP9SvakEeeSi1BxdTH5o3+1yUyrldp8IERkSdXlMI2t4kxF2sqYUDsQY+WJBxzBmZg==",
+      "dev": true,
+      "dependencies": {
+        "@vue/component-compiler-utils": "^3.1.0",
+        "hash-sum": "^1.0.2",
+        "loader-utils": "^1.1.0",
+        "vue-hot-reload-api": "^2.3.0",
+        "vue-style-loader": "^4.1.0"
+      }
+    },
+    "node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/node_modules/hash-sum": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
+      "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
+      "dev": true
+    },
     "node_modules/@vue/cli-shared-utils": {
       "version": "5.0.8",
       "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-5.0.8.tgz",
@@ -1706,38 +1744,6 @@
       "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.41.tgz",
       "integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw=="
     },
-    "node_modules/@vue/vue-loader-v15": {
-      "name": "vue-loader",
-      "version": "15.10.0",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.0.tgz",
-      "integrity": "sha512-VU6tuO8eKajrFeBzMssFUP9SvakEeeSi1BxdTH5o3+1yUyrldp8IERkSdXlMI2t4kxF2sqYUDsQY+WJBxzBmZg==",
-      "dev": true,
-      "dependencies": {
-        "@vue/component-compiler-utils": "^3.1.0",
-        "hash-sum": "^1.0.2",
-        "loader-utils": "^1.1.0",
-        "vue-hot-reload-api": "^2.3.0",
-        "vue-style-loader": "^4.1.0"
-      },
-      "peerDependencies": {
-        "css-loader": "*",
-        "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0"
-      },
-      "peerDependenciesMeta": {
-        "cache-loader": {
-          "optional": true
-        },
-        "vue-template-compiler": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@vue/vue-loader-v15/node_modules/hash-sum": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
-      "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
-      "dev": true
-    },
     "node_modules/@vue/web-component-wrapper": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz",
@@ -3006,11 +3012,30 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/cookie-parser": {
+      "version": "1.4.6",
+      "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
+      "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
+      "dependencies": {
+        "cookie": "0.4.1",
+        "cookie-signature": "1.0.6"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/cookie-parser/node_modules/cookie": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
+      "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
     "node_modules/cookie-signature": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-      "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
-      "dev": true
+      "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
     },
     "node_modules/copy-webpack-plugin": {
       "version": "9.1.0",
@@ -3060,6 +3085,18 @@
       "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
       "dev": true
     },
+    "node_modules/cors": {
+      "version": "2.8.5",
+      "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+      "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+      "dependencies": {
+        "object-assign": "^4",
+        "vary": "^1"
+      },
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
     "node_modules/cosmiconfig": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
@@ -6693,7 +6730,6 @@
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-      "dev": true,
       "engines": {
         "node": ">=0.10.0"
       }
@@ -7097,6 +7133,31 @@
         "url": "https://github.com/sponsors/jonschlinkert"
       }
     },
+    "node_modules/pinia": {
+      "version": "2.0.23",
+      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.23.tgz",
+      "integrity": "sha512-N15hFf4o5STrxpNrib1IEb1GOArvPYf1zPvQVRGOO1G1d74Ak0J0lVyalX/SmrzdT4Q0nlEFjbURsmBmIGUR5Q==",
+      "dependencies": {
+        "@vue/devtools-api": "^6.4.4",
+        "vue-demi": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.4.0",
+        "typescript": ">=4.4.4",
+        "vue": "^2.6.14 || ^3.2.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        },
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/pkg-dir": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
@@ -9177,7 +9238,7 @@
       "version": "4.8.4",
       "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
       "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
-      "dev": true,
+      "devOptional": true,
       "bin": {
         "tsc": "bin/tsc",
         "tsserver": "bin/tsserver"
@@ -9289,7 +9350,6 @@
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
       "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
-      "dev": true,
       "engines": {
         "node": ">= 0.8"
       }
@@ -9306,6 +9366,31 @@
         "@vue/shared": "3.2.41"
       }
     },
+    "node_modules/vue-demi": {
+      "version": "0.13.11",
+      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz",
+      "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
+      "hasInstallScript": true,
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/vue-eslint-parser": {
       "version": "8.3.0",
       "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz",
@@ -9524,6 +9609,17 @@
       "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
       "dev": true
     },
+    "node_modules/vuex": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz",
+      "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==",
+      "dependencies": {
+        "@vue/devtools-api": "^6.0.0-beta.11"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
     "node_modules/watchpack": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
@@ -10828,6 +10924,21 @@
         "@types/node": "*"
       }
     },
+    "@types/cookie-parser": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz",
+      "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==",
+      "dev": true,
+      "requires": {
+        "@types/express": "*"
+      }
+    },
+    "@types/cors": {
+      "version": "2.8.12",
+      "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz",
+      "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==",
+      "dev": true
+    },
     "@types/eslint": {
       "version": "8.4.6",
       "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz",
@@ -11236,6 +11347,29 @@
         "webpack-merge": "^5.7.3",
         "webpack-virtual-modules": "^0.4.2",
         "whatwg-fetch": "^3.6.2"
+      },
+      "dependencies": {
+        "@vue/vue-loader-v15": {
+          "version": "npm:vue-loader@15.10.0",
+          "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.0.tgz",
+          "integrity": "sha512-VU6tuO8eKajrFeBzMssFUP9SvakEeeSi1BxdTH5o3+1yUyrldp8IERkSdXlMI2t4kxF2sqYUDsQY+WJBxzBmZg==",
+          "dev": true,
+          "requires": {
+            "@vue/component-compiler-utils": "^3.1.0",
+            "hash-sum": "^1.0.2",
+            "loader-utils": "^1.1.0",
+            "vue-hot-reload-api": "^2.3.0",
+            "vue-style-loader": "^4.1.0"
+          },
+          "dependencies": {
+            "hash-sum": {
+              "version": "1.0.2",
+              "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
+              "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
+              "dev": true
+            }
+          }
+        }
       }
     },
     "@vue/cli-shared-utils": {
@@ -11488,27 +11622,6 @@
       "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.41.tgz",
       "integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw=="
     },
-    "@vue/vue-loader-v15": {
-      "version": "npm:vue-loader@15.10.0",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.0.tgz",
-      "integrity": "sha512-VU6tuO8eKajrFeBzMssFUP9SvakEeeSi1BxdTH5o3+1yUyrldp8IERkSdXlMI2t4kxF2sqYUDsQY+WJBxzBmZg==",
-      "dev": true,
-      "requires": {
-        "@vue/component-compiler-utils": "^3.1.0",
-        "hash-sum": "^1.0.2",
-        "loader-utils": "^1.1.0",
-        "vue-hot-reload-api": "^2.3.0",
-        "vue-style-loader": "^4.1.0"
-      },
-      "dependencies": {
-        "hash-sum": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
-          "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
-          "dev": true
-        }
-      }
-    },
     "@vue/web-component-wrapper": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz",
@@ -12461,11 +12574,26 @@
       "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
       "dev": true
     },
+    "cookie-parser": {
+      "version": "1.4.6",
+      "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
+      "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
+      "requires": {
+        "cookie": "0.4.1",
+        "cookie-signature": "1.0.6"
+      },
+      "dependencies": {
+        "cookie": {
+          "version": "0.4.1",
+          "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
+          "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
+        }
+      }
+    },
     "cookie-signature": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-      "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
-      "dev": true
+      "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
     },
     "copy-webpack-plugin": {
       "version": "9.1.0",
@@ -12500,6 +12628,15 @@
       "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
       "dev": true
     },
+    "cors": {
+      "version": "2.8.5",
+      "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+      "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+      "requires": {
+        "object-assign": "^4",
+        "vary": "^1"
+      }
+    },
     "cosmiconfig": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
@@ -15200,8 +15337,7 @@
     "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==",
-      "dev": true
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
     },
     "object-inspect": {
       "version": "1.12.2",
@@ -15504,6 +15640,15 @@
       "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
       "dev": true
     },
+    "pinia": {
+      "version": "2.0.23",
+      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.23.tgz",
+      "integrity": "sha512-N15hFf4o5STrxpNrib1IEb1GOArvPYf1zPvQVRGOO1G1d74Ak0J0lVyalX/SmrzdT4Q0nlEFjbURsmBmIGUR5Q==",
+      "requires": {
+        "@vue/devtools-api": "^6.4.4",
+        "vue-demi": "*"
+      }
+    },
     "pkg-dir": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
@@ -16993,10 +17138,10 @@
       }
     },
     "typescript": {
-      "version": "4.5.5",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
-      "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
-      "dev": true
+      "version": "4.8.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
+      "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
+      "devOptional": true
     },
     "universalify": {
       "version": "2.0.0",
@@ -17072,8 +17217,7 @@
     "vary": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-      "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
-      "dev": true
+      "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
     },
     "vue": {
       "version": "3.2.41",
@@ -17087,6 +17231,12 @@
         "@vue/shared": "3.2.41"
       }
     },
+    "vue-demi": {
+      "version": "0.13.11",
+      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz",
+      "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
+      "requires": {}
+    },
     "vue-eslint-parser": {
       "version": "8.3.0",
       "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz",
@@ -17251,6 +17401,14 @@
       "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
       "dev": true
     },
+    "vuex": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz",
+      "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==",
+      "requires": {
+        "@vue/devtools-api": "^6.0.0-beta.11"
+      }
+    },
     "watchpack": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
diff --git a/FrontendFolder/switch-room/package.json b/FrontendFolder/switch-room/package.json
index aae32ab897a79a08d3f6cb5440d998e59619c5f0..7f0c7dcbc9593f40d0fa902650979693a45643cd 100644
--- a/FrontendFolder/switch-room/package.json
+++ b/FrontendFolder/switch-room/package.json
@@ -8,16 +8,23 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "@element-plus/icons-vue": "^2.0.10",
     "@fortawesome/fontawesome-svg-core": "^6.2.0",
     "@fortawesome/free-brands-svg-icons": "^6.2.0",
     "@fortawesome/free-regular-svg-icons": "^6.2.0",
     "@fortawesome/free-solid-svg-icons": "^6.2.0",
     "@fortawesome/vue-fontawesome": "^3.0.1",
+    "cookie-parser": "^1.4.6",
+    "cors": "^2.8.5",
     "element-plus": "^2.2.18",
+    "pinia": "^2.0.23",
     "vue": "^3.2.13",
-    "vue-router": "^4.0.3"
+    "vue-router": "^4.0.3",
+    "vuex": "^4.1.0"
   },
   "devDependencies": {
+    "@types/cookie-parser": "^1.4.3",
+    "@types/cors": "^2.8.12",
     "@typescript-eslint/eslint-plugin": "^5.4.0",
     "@typescript-eslint/parser": "^5.4.0",
     "@vue/cli-plugin-router": "~5.0.0",
diff --git a/FrontendFolder/switch-room/src/App.vue b/FrontendFolder/switch-room/src/App.vue
index 4d3c04cb326c0b33bfcd6b86e4ebe0530f274106..9be9464bf1bc9af89fcec6aaff5fbb7b8d98df45 100644
--- a/FrontendFolder/switch-room/src/App.vue
+++ b/FrontendFolder/switch-room/src/App.vue
@@ -3,9 +3,21 @@ import AppFooter from "@/components/AppFooter.vue";
 import AppHeader from "@/components/AppHeader.vue";
 </script>
 <template>
-  <app-header></app-header>
-  <router-view></router-view>
-  <app-footer></app-footer>
+  <body>
+    <app-header v-if="!$route.meta.hideHeader"></app-header>
+    <router-view class="wrapper"></router-view>
+    <app-footer class="footer"></app-footer>
+  </body>
 </template>
 
-<style></style>
\ No newline at end of file
+<style>
+body {
+  text-align: center;
+  display: flex;
+  flex-direction: column;
+  min-height: 100vh;
+}
+.wrapper {
+  flex: 1;
+}
+</style>
diff --git a/FrontendFolder/switch-room/src/components/AppFooter.vue b/FrontendFolder/switch-room/src/components/AppFooter.vue
index 0b99af330618583e0873ad49c7957175a1543e8d..764cb82d2e93d2448c959dc7fe5acd2a38f0f2ee 100644
--- a/FrontendFolder/switch-room/src/components/AppFooter.vue
+++ b/FrontendFolder/switch-room/src/components/AppFooter.vue
@@ -36,7 +36,7 @@
   text-align: left;
   font: normal 16px sans-serif;
   padding: 45px 50px;
-  position: fixed;
+  /*position: fixed;*/
   bottom: 0;
   left: 0;
   right: 0;
diff --git a/FrontendFolder/switch-room/src/components/AppHeader.vue b/FrontendFolder/switch-room/src/components/AppHeader.vue
index 71e43e1196a1a1545368c33d7d5959afcb7dac6c..97d1133ca1a01e4efd4d460b541d07a39da080c2 100644
--- a/FrontendFolder/switch-room/src/components/AppHeader.vue
+++ b/FrontendFolder/switch-room/src/components/AppHeader.vue
@@ -9,24 +9,71 @@
     active-text-color="#ffd04b"
     @select="handleSelect"
   >
-
-    <el-menu-item index="1" v-on:click="redirect('/login-main-page')">Main</el-menu-item>
-    <el-menu-item index="2" v-on:click="redirect('/offer-page')">Offer Page</el-menu-item>
-    <el-menu-item index="3" v-on:click="redirect('/wishlist-page')">Wish List</el-menu-item>
-    <el-menu-item index="4" v-on:click="redirect('/flight')">Flight Ticket</el-menu-item>
+    <el-menu-item index="1" v-on:click="redirect('/login-main-page')"
+      >Main</el-menu-item
+    >
+    <el-menu-item index="2" v-on:click="redirect('/offer-page')"
+      >Offer Page</el-menu-item
+    >
+    <el-menu-item index="3" v-on:click="redirect('/wishlist-page')"
+      >Wish List</el-menu-item
+    >
+    <el-menu-item index="4" v-on:click="redirect('/flight')"
+      >Flight Ticket</el-menu-item
+    >
+    <el-menu-item index="5" v-on:click="redirect('/profile')"
+      >Profile</el-menu-item
+    >
+    <notification class="position"></notification>
+    <el-menu-item index="6" class="dock-right" @click="hanldeLogOut()"
+      >Log Out</el-menu-item
+    >
   </el-menu>
 </template>
 
 <script lang="ts">
 import { defineComponent } from "vue";
+import { mapActions, mapGetters } from "vuex";
+import Notification from "@/components/Notification.vue";
+import { OfferNotification } from "@/models/OfferNotification";
 export default defineComponent({
+  components: { Notification },
+  props: ["offers"],
+  data() {
+    return {
+      hasToken: document.cookie.length > 0,
+    };
+  },
   name: "LoginMainPage",
   methods: {
     redirect(url: string) {
-      this.$router.push({path: url});
-    }
+      this.$router.push(url);
+    },
+    ...mapActions("auth", {
+      logOut: "logOutApi",
+    }),
+    hanldeLogOut() {
+      this.logOut();
+      document.cookie =
+        "userId=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;";
+      document.cookie =
+        "token=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;";
+      this.$router.push("/");
+    },
   },
 });
 </script>
 
-<style scoped></style>
+<style scoped>
+.h-6 {
+  display: flex;
+}
+.el-menu-demo > .el-menu-item.dock-right {
+  margin-left: auto;
+}
+
+.position {
+  margin-top: 12px;
+  margin-left: auto;
+}
+</style>
diff --git a/FrontendFolder/switch-room/src/components/LoginMainPage.vue b/FrontendFolder/switch-room/src/components/LoginMainPage.vue
index 7d8e3d441dc0396e2a9ce728271395caa0068894..9a9e65050cbe3a06e27ba68b5e465c0a187fd947 100644
--- a/FrontendFolder/switch-room/src/components/LoginMainPage.vue
+++ b/FrontendFolder/switch-room/src/components/LoginMainPage.vue
@@ -1,93 +1,66 @@
 <template>
-    <el-container class="container">
-        <el-main>
-            <el-row :gutter="10" justify="center">
-                <el-col
-                    :span="10"
-                    style="display: flex; justify-content: center;"
-                >
-                    <el-card
-                        class="card"
-                        v-on:click="redirect('/offer-page')"
-                    >
-                        <img
-                        src="../assets/mainPage/offer.png"
-                        class="image"
-                        />
-                        <div>
-                        <p style="font-size: 50px;">Offer</p>
-                        <p>Match results go here</p>
-                        </div>
-                    </el-card>
-                </el-col>
-            <el-col
-                :span="10"
-                style="display: flex; justify-content: center;"
-            >
-                <el-card
-                    class="card"
-                    v-on:click="redirect('/wishlist-page')"
-                >
-                    <img
-                        src="../assets/mainPage/wishlist.jpg"
-                        class="image"
-                    />
-                    <div>
-                        <p style="font-size: 50px;">Wish List</p>
-                        <p>User's wish list go here</p>
-                    </div>
-                </el-card>
-            </el-col>
-        </el-row>
-            <el-row style="margin-top: 5%;">
-                <el-col
-                style="display: flex; justify-content: center;"
-                >
-                <el-card
-                    class="card"
-                    v-on:click="redirect('/flight')"
-                >
-                    <img
-                    src="../assets/mainPage/flight.jpeg"
-                    class="image"
-                    />
-                    <div>
-                    <p style="font-size: 50px;">Flight Ticket</p>
-                    <p>Find your flight!</p>
-                    </div>
-                </el-card>
-                </el-col>
-            </el-row>
-        </el-main>
-    </el-container>
+  <el-container class="container">
+    <el-main>
+      <el-row :gutter="10" justify="center">
+        <el-col :span="10" style="display: flex; justify-content: center">
+          <el-card class="card" v-on:click="redirect('/offer-page')">
+            <img src="../assets/mainPage/offer.png" class="image" />
+            <div>
+              <p style="font-size: 50px">Offer</p>
+              <p>Match results go here</p>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="10" style="display: flex; justify-content: center">
+          <el-card class="card" v-on:click="redirect('/wishlist-page')">
+            <img src="../assets/mainPage/wishlist.jpg" class="image" />
+            <div>
+              <p style="font-size: 50px">Wish List</p>
+              <p>User's wish list go here</p>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+      <el-row style="margin-top: 5%">
+        <el-col style="display: flex; justify-content: center">
+          <el-card class="card" v-on:click="redirect('/flight')">
+            <img src="../assets/mainPage/flight.jpeg" class="image" />
+            <div>
+              <p style="font-size: 50px">Flight Ticket</p>
+              <p>Find your flight!</p>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+    </el-main>
+  </el-container>
 </template>
-    
+
 <script lang="ts">
 import { defineComponent } from "vue";
 export default defineComponent({
-    name: "LoginMainPage",
-    methods: {
-        redirect(url: string) {
-            this.$router.push({path: url});
-        }
+  name: "LoginMainPage",
+  methods: {
+    redirect(url: string) {
+      this.$router.push({ path: url });
     },
+  },
 });
 </script>
-  
+
 <style>
 .image {
-    width: 25vw;
-    display: block;
+  width: 25vw;
+  display: block;
 }
 .card {
-    cursor: pointer
+  cursor: pointer;
 }
 .container {
-    width: 100%;
-    height: 100%;
-    color: #fff;
-    background-image: linear-gradient(135deg, #b3d1ff 10%, #fd5e086b 100%);
-    font-size: 24px;
+  width: 100%;
+  height: 100%;
+  color: #fff;
+  background-image: linear-gradient(135deg, #b3d1ff 10%, #fd5e086b 100%);
+  font-size: 24px;
 }
 </style>
-  
\ No newline at end of file
diff --git a/FrontendFolder/switch-room/src/components/MainPage.vue b/FrontendFolder/switch-room/src/components/MainPage.vue
index 2979082cf3139623c66585c7b319231f2c8cf584..a105bd70bdb1b20945010f443c43fd66b4a10020 100644
--- a/FrontendFolder/switch-room/src/components/MainPage.vue
+++ b/FrontendFolder/switch-room/src/components/MainPage.vue
@@ -23,12 +23,12 @@
           <div class="underline-title"></div>
         </div>
         <form method="post" class="form">
-          <label for="user-name" style="padding-top: 13px; text-align: left">
+          <label for="user-name" style="padding-top: 13px">
             &nbsp;Username
           </label>
           <input
             id="user-name"
-            v-model="userInformation.username"
+            v-model="username"
             class="form-content"
             type="text"
             name="username"
@@ -36,12 +36,12 @@
             required
           />
           <div class="form-border"></div>
-          <label for="user-password" style="padding-top: 22px; text-align: left"
+          <label for="user-password" style="padding-top: 22px"
             >&nbsp;Password
           </label>
           <input
             id="user-password"
-            v-model="userInformation.password"
+            v-model="password"
             class="form-content"
             type="password"
             name="password"
@@ -51,13 +51,9 @@
           <a href="#">
             <legend id="forgot-pass">Forgot password?</legend>
           </a>
-          <input
-            id="submit-btn"
-            type="submit"
-            name="submit"
-            value="LOGIN"
-            @click.prevent="onSubmit"
-          />
+          <button type="button" class="btn btn-primary" @click="handleLogin()">
+            LOGIN
+          </button>
           <router-link to="/register">
             <div id="signup">Don't have account yet?</div>
           </router-link>
@@ -67,33 +63,51 @@
   </div>
 </template>
 
-<script setup lang="ts">
-import { ref, reactive } from "vue";
-import * as UserService from "../services/UserService";
-import { useRouter } from "vue-router";
-import { UserModel } from "@/models/UserModel";
-import { result } from "lodash";
-const router = useRouter();
-const user = ref(new UserModel());
-const userInformation = reactive({
-  username: "",
-  password: "",
-});
+<script lang="ts">
+import { defineComponent } from "vue";
+import { mapActions, mapGetters } from "vuex";
+import { checkLoginSession } from "../services/UserService";
 
-const onSubmit = async () => {
-  await UserService.loginUser(JSON.stringify(userInformation))
-    .then((result) => {
-      if (result.status == "OK") {
-        user.value = result.data;
-        router.push("/login-main-page");
-      } else {
-        alert(result.message);
+export default defineComponent({
+  data() {
+    return {
+      username: "",
+      password: "",
+    };
+  },
+  computed: {
+    ...mapGetters("auth", {
+      getLoginStatus: "getLoginStatus",
+    }),
+  },
+  methods: {
+    ...mapActions("auth", {
+      actionLoginApi: "loginApi",
+    }),
+    async handleCreated() {
+      await checkLoginSession().then((result) => {
+        if (result.status == "OK") {
+          this.$router.push({ name: "LoginMainPage" });
+        } else {
+          this.$router.push({ name: "home" });
+        }
+      });
+    },
+    async handleLogin() {
+      const payload = {
+        username: this.username,
+        password: this.password,
+      };
+      await this.actionLoginApi(payload);
+      if (this.getLoginStatus) {
+        this.$router.push({ name: "LoginMainPage" });
       }
-    })
-    .catch((error) => {
-      alert(error);
-    });
-};
+    },
+  },
+  created: function () {
+    this.handleCreated();
+  },
+});
 </script>
 
 <style scoped>
@@ -112,13 +126,12 @@ body {
   background: url("@/assets/mainPage/headerPhoto.jpeg");
   text-align: center;
   width: 70%;
-  height: 800px;
+  height: auto;
   background-size: cover;
   background-attachment: fixed;
   position: relative;
   overflow: hidden;
   border-radius: 0 0 85% 85% / 30%;
-  display: flex;
 }
 .leftPart .overlay {
   width: 100%;
@@ -172,7 +185,7 @@ label {
   background: #fbfbfb;
   border-radius: 8px;
   box-shadow: 1px 2px 8px rgba(0, 0, 0, 0.65);
-  height: 450px;
+  height: 410px;
   width: 30%;
 }
 #card-content {
diff --git a/FrontendFolder/switch-room/src/components/MatchOffer.vue b/FrontendFolder/switch-room/src/components/MatchOffer.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e9bbdee7837e91396bd1e9239099e6cf65ed75c4
--- /dev/null
+++ b/FrontendFolder/switch-room/src/components/MatchOffer.vue
@@ -0,0 +1,46 @@
+<template>
+  <div class="offerSide">
+    <div class="card">
+      <div class="container">
+        <h4><b>Matched Offer Information</b></h4>
+        <p>Space Located City: {{ offer.spaceLocateCity }}</p>
+        <p>Space Located State: {{ offer.state }}</p>
+        <p>Available Time start: {{ offer.availableTimeStart }}</p>
+        <p>Available Time end: {{ offer.availableTimeEnd }}</p>
+        <p>Max People: {{ offer.maxNumberOfPeople }}</p>
+        <p v-if="offer.offering">It is offering now</p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { defineProps } from "vue";
+import { OfferFormModel } from "@/models/OfferFormModel";
+
+const props = defineProps<{
+  offer: OfferFormModel;
+}>();
+</script>
+
+<style scoped>
+.offerSide {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.card {
+  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
+  transition: 0.3s;
+  width: 40%;
+  text-align: center;
+}
+
+.card:hover {
+  box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
+}
+
+.container {
+  padding: 2px 16px;
+}
+</style>
diff --git a/FrontendFolder/switch-room/src/components/MatchWishList.vue b/FrontendFolder/switch-room/src/components/MatchWishList.vue
new file mode 100644
index 0000000000000000000000000000000000000000..2af628d7c9e746f9e2936e9a8bfe67723a3513ec
--- /dev/null
+++ b/FrontendFolder/switch-room/src/components/MatchWishList.vue
@@ -0,0 +1,45 @@
+<template>
+  <div class="wishlistSide">
+    <div class="card">
+      <div class="container">
+        <h4><b>Matched required space Information</b></h4>
+        <p>required city: {{ wishlist.cityName }}</p>
+        <p>required state: {{ wishlist.state }}</p>
+        <p>required start time: {{ wishlist.startTime }}</p>
+        <p>required end time: {{ wishlist.endTime }}</p>
+        <p>required details: {{ wishlist.details }}</p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { defineProps } from "vue";
+import { WishlistItemModel } from "@/models/WishlistItemModel";
+
+const props = defineProps<{
+  wishlist: WishlistItemModel;
+}>();
+</script>
+
+<style scoped>
+.wishlistSide {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.card {
+  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
+  transition: 0.3s;
+  width: 40%;
+  text-align: center;
+}
+
+.card:hover {
+  box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
+}
+
+.container {
+  padding: 2px 16px;
+}
+</style>
diff --git a/FrontendFolder/switch-room/src/components/Notification.vue b/FrontendFolder/switch-room/src/components/Notification.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f6d35a6340720b4772fa2416918ff17cd77eff67
--- /dev/null
+++ b/FrontendFolder/switch-room/src/components/Notification.vue
@@ -0,0 +1,153 @@
+<template>
+  <el-dropdown class="notification">
+    <el-row>
+      <el-button type="info" :icon="Message" circle>
+        <div class="text-length">{{ length1 + length2 }}</div>
+        <!--        notification-->
+        <!--      <font-awesome-icon icon="fa-solid fa-envelope" />-->
+        <!--      Notification<el-icon class="el-icon--right"><arrow-down /></el-icon>-->
+      </el-button>
+    </el-row>
+    <template #dropdown>
+      <el-dropdown-menu>
+        <el-dropdown-item v-for="offer in offers" :key="offer.offerId">
+          <a>
+            <router-link
+              :to="
+                '/matched-result/' + offer.offerId + '/' + offer.wishlistItemId
+              "
+              style="color: blue"
+            >
+              <div class="offer-match">
+                <div class="offer-text"></div>
+                <font-awesome-icon icon="fa-solid fa-circle-info" />
+                Offer Matched
+              </div>
+            </router-link>
+          </a>
+        </el-dropdown-item>
+        <el-dropdown-item
+          type="primary"
+          v-for="offer in offers2"
+          :key="offer.offerId"
+        >
+          <a
+            ><router-link
+              :to="
+                '/matched-result/' + offer.offerId + '/' + offer.wishlistItemId
+              "
+              style="color: blue"
+            >
+              <div class="offer-match">
+                <font-awesome-icon icon="fa-solid fa-circle-info" />
+                WishList Matched
+              </div>
+            </router-link>
+          </a>
+        </el-dropdown-item>
+      </el-dropdown-menu>
+    </template>
+  </el-dropdown>
+</template>
+
+<script setup lang="ts">
+import { ref, watch } from "vue";
+import { OfferNotification } from "@/models/OfferNotification";
+import * as NotificationService from "@/services/NotificationService";
+import { useRoute } from "vue-router";
+import { onMounted } from "vue";
+import { Message } from "@element-plus/icons-vue";
+
+const route = useRoute();
+
+function getCookie(userId: string) {
+  const value = `; ${document.cookie}`;
+  const parts: string[] = value.split(`; ${userId}=`);
+  if (parts.length === 2) return parts?.pop()?.split(";").shift();
+}
+
+const offers = ref([] as OfferNotification[]);
+const offers2 = ref([] as OfferNotification[]);
+
+const length1 = ref(-1);
+const length2 = ref(-1);
+async function fetchNotification(userId: number) {
+  const response = await NotificationService.getNotificationFromServerWithID(
+    userId
+  );
+  // const response2 =
+  //   await NotificationService.getNotificationwishFromServerWithID(userId);
+  // console.log(response2);
+  offers.value = response.data;
+  length1.value = response.data.length;
+  // offers2.value = response2.data;
+}
+
+async function fetchNotificationwish(userId: number) {
+  const response2 =
+    await NotificationService.getNotificationwishFromServerWithID(userId);
+  offers2.value = response2.data;
+  length2.value = response2.data.length;
+}
+
+watch(
+  () => route.name,
+  (values) => {
+    const userIdString: string = getCookie("userId");
+    let userIdNumber = +userIdString;
+    fetchNotification(userIdNumber);
+    fetchNotificationwish(userIdNumber);
+  },
+  { immediate: true }
+);
+</script>
+
+<style scoped>
+.example-showcase .el-dropdown + .el-dropdown {
+  margin-left: 15px;
+}
+.example-showcase .el-dropdown-link {
+  cursor: pointer;
+  color: var(--el-color-primary);
+  display: flex;
+  align-items: center;
+}
+
+.offer-match {
+  display: flex;
+  margin-right: 2px;
+}
+
+.offer-text {
+  font-size: 25px;
+  font-family: "Apple Symbols";
+  color: #1e5be6;
+  margin-left: 2px;
+}
+
+.text-length {
+  font-size: 20px;
+  color: white;
+  height: 20px;
+  width: 20px;
+  background-color: #cc0000;
+  border-radius: 50%;
+  display: inline-block;
+}
+
+a:link {
+  text-decoration: none;
+}
+
+a:visited {
+  text-decoration: none;
+}
+
+a:hover {
+  text-decoration: none;
+}
+
+a:active {
+  text-decoration: none;
+}
+</style>
diff --git a/FrontendFolder/switch-room/src/components/OfferPage.vue b/FrontendFolder/switch-room/src/components/OfferPage.vue
index e5d189b2beb79f8ba63a8a071c0c176b2dc26764..2508f792b08dc060baada06e5dd7cea8ee93bdd8 100644
--- a/FrontendFolder/switch-room/src/components/OfferPage.vue
+++ b/FrontendFolder/switch-room/src/components/OfferPage.vue
@@ -1,6 +1,6 @@
 <template>
   <el-row :gutter="20">
-    <el-col :span="4"><div class="grid-content ep-bg-purple" /></el-col>
+    <el-col :span="3"><div class="grid-content ep-bg-purple" /></el-col>
     <el-col :span="12">
       <el-card style="width: 100%">
         <template #header>
@@ -19,13 +19,25 @@
           status-icon
         >
           <el-form-item label="Located City" prop="spaceLocateCity">
+            <el-col :span="15">
+              <el-input v-model="ruleForm.spaceLocateCity" :readonly="buttonState === 'edit'"/>
+            </el-col>
+          </el-form-item>
+          <el-form-item label="State" prop="state">
             <el-col :span="8">
-              <el-input v-model="ruleForm.spaceLocateCity" />
+              <el-select
+                  v-model="ruleForm.state"
+                  placeholder="Select state"
+                  :disabled="buttonState === 'edit'"
+              >
+                <el-option v-for="(state_item, index) in USA_STATE_INITAL_LIST"
+                           :label="state_item" :value="state_item" />
+              </el-select>
             </el-col>
           </el-form-item>
           <el-form-item label="Zip Code" prop="zipCode">
-            <el-col :span="5">
-              <el-input v-model="ruleForm.zipCode" placeholder="24061.." />
+            <el-col :span="7">
+              <el-input v-model="ruleForm.zipCode" placeholder="24061" :readonly="buttonState === 'edit'"/>
             </el-col>
           </el-form-item>
           <el-col :span="24">
@@ -33,6 +45,7 @@
               <el-select
                 v-model="ruleForm.spaceType"
                 placeholder="Please select your Space Type"
+                :disabled="buttonState === 'edit'"
               >
                 <el-option
                   label="Apartment (No Roommates)"
@@ -65,13 +78,13 @@
             :required="ruleForm.spaceType === 'other'"
           >
             <el-col :span="8">
-              <el-input v-model="ruleForm.otherSpaceType" />
+              <el-input v-model="ruleForm.otherSpaceType" :readonly="buttonState === 'edit'"/>
             </el-col>
           </el-form-item>
           <el-form-item label="Space Available for Offering?">
             <el-col :span="2">
               <el-form-item prop="offering">
-                <el-switch v-model="ruleForm.offering" />
+                <el-switch v-model="ruleForm.offering" :disabled="buttonState === 'edit'"/>
               </el-form-item>
             </el-col>
           </el-form-item>
@@ -89,6 +102,7 @@
                   label="Pick a date"
                   placeholder="Pick a date"
                   style="width: 100%"
+                  :readonly="buttonState === 'edit'"
                 />
               </el-form-item>
             </el-col>
@@ -102,6 +116,7 @@
                   label="Pick a time"
                   placeholder="Pick a time"
                   style="width: 100%"
+                  :readonly="buttonState === 'edit'"
                 />
               </el-form-item>
             </el-col>
@@ -113,35 +128,60 @@
             prop="maxNumberOfPeople"
           >
             <el-col :span="4">
-              <el-input v-model="ruleForm.maxNumberOfPeople" />
+              <el-input v-model="ruleForm.maxNumberOfPeople" :readonly="buttonState === 'edit'"/>
             </el-col>
           </el-form-item>
           <el-form-item></el-form-item>
 
           <el-form-item label="Space Details:" prop="spaceDetails">
             <el-col :span="16"
-              ><el-input v-model="ruleForm.spaceDetails" type="textarea"
+              ><el-input v-model="ruleForm.spaceDetails" type="textarea" :readonly="buttonState === 'edit'"
             /></el-col>
           </el-form-item>
-          <el-form-item>
+          <el-form-item v-if="buttonState === 'create'">
             <el-button type="primary" @click="submitForm(ruleFormRef)"
-              >Create</el-button
-            >
+              >Create</el-button>
             <el-button @click="resetForm(ruleFormRef)">Reset</el-button>
           </el-form-item>
+          <el-form-item v-if="buttonState === 'edit'">
+            <el-button type="primary" @click="editForm()"
+            >Edit</el-button>
+          </el-form-item>
+          <el-form-item v-if="buttonState === 'update'">
+            <el-button type="success" @click="updateForm(ruleFormRef)"
+            >Save</el-button>
+            <el-button type="danger" @click="deleteForm(ruleFormRef)">Delete</el-button>
+          </el-form-item>
+
         </el-form>
       </el-card>
     </el-col>
-    <el-col :span="4">
-      <el-card style="width: 100%"
-        ><template #header>
+    <el-col :span="6">
+      <el-card style="width: 100%">
+        <template #header>
           <div class="card-header">
             <span>Match Request</span>
           </div>
         </template>
-      </el-card></el-col
-    >
-    <el-col :span="4"></el-col>
+<!--  TODO     -->
+        <el-card
+            v-for="(item, index) in matchRequestList.value"
+            shadow="hover"
+            :fill="true"
+            @click="selectMatchRequestItem(index)"
+        >
+          <time > {{formatDate(item.startTime)}} - {{formatDate(item.endTime)}}</time>
+          <div class="w-bottom">
+            <span class="w-owner"> Wishlist Owner Name: {{item.wishListOwnerName}}</span>
+            <br>
+            <span class="w-zipCode" v-if="!item.hasOffer"> No Available Offer </span>
+            <span class="w-zipCode">Zip Code: {{item.zipCode}}</span>
+          </div>
+        </el-card>
+
+      </el-card>
+    </el-col>
+    <el-col :span="2"></el-col>
   </el-row>
 </template>
 
@@ -150,6 +190,7 @@ import { reactive, ref, onMounted } from "vue";
 import type { FormInstance, FormRules } from "element-plus";
 import { OfferFormModel } from "@/models/OfferFormModel";
 import * as OfferPageService from "@/services/OfferPageService";
+import { USA_STATE_INITAL_LIST } from "@/services/Constans";
 
 // Form verification relate field
 const formSize = ref("default");
@@ -163,6 +204,14 @@ const rules = reactive<FormRules>({
     },
     { min: 0, max: 20, message: "Length should be 0 to 20", trigger: "blur" },
   ],
+  state: [
+    {
+      required: true,
+      message: "Please give your space located state",
+      trigger: "blur",
+    },
+    { min: 0, max: 20, message: "Length should be 0 to 20", trigger: "blur" },
+  ],
   zipCode: [
     {
       required: true,
@@ -179,61 +228,90 @@ const rules = reactive<FormRules>({
   ],
 });
 // TODO: uncomment it when API connection ready
-const userId = 233;
 let ruleForm = ref(new OfferFormModel());
+let buttonState = ref("create");
+let matchRequestList = reactive({value:[]});
 
 onMounted(() => {
-OfferPageService.getUserOfferInfoFromServer(userId).then( (data) => {
-  console.log("Receive user offer data: ", data);
-  if(data["data"] === null){
-    // TODO: Handle fetch error
-  }else{
-    ruleForm.value = data["data"];
-  }
-  })
+  loadInitOfferInfoPage();
+  loadOfferPageMatchRequest();
 })
 
+const loadInitOfferInfoPage = async () =>{
+  await OfferPageService.getUserOfferInfoFromServer().then( (data) => {
+    console.log("Receive user offer data: ", data);
+    if(data["data"] === null){
+      // TODO: Handle fetch error
+    }else{
+      ruleForm.value = data["data"];
+      if(ruleForm.value.spaceLocateCity == null || ruleForm.value.spaceLocateCity == ""){
+        buttonState.value = "create";
+      }else{
+        buttonState.value = "edit";
+      }
+    }
+  });
+}
+
+const loadOfferPageMatchRequest = async() =>{
+  await OfferPageService.getWishlistMatchRequestInfoList().then( (data) =>{
+    console.log("Fetching Offer Page Match Request Info: ", data);
+    matchRequestList.value = data["data"];
+  })
+}
+
+
 const submitForm = async (formEl: FormInstance | undefined) => {
   if (!formEl) return;
   await formEl.validate((valid, fields) => {
     if (valid) {
-      let result = OfferPageService.createNewUserOffer(ruleForm);
       // TODO: Check the return result
       console.log("Form Data before save in DB: ", ruleForm.value);
       OfferPageService.createNewUserOffer(ruleForm.value).then((data) => {
         console.log("Save user offer data: ", data);
+        ruleForm.value = data["data"];
+        buttonState.value = "edit";
       })
       console.log("submit!");
     } else {
       console.log("error submit!", fields);
     }
-    console.log(ruleForm);
   });
 };
 
-const updateFrom = async (formEl: FormInstance | undefined) => {
+const editForm = () => {
+  buttonState.value = "update";
+}
+
+const updateForm = async (formEl: FormInstance | undefined) => {
   if (!formEl) return;
   await formEl.validate((valid, fields) => {
     if (valid) {
-      let result = OfferPageService.updateOffer(ruleForm);
       // TODO: Check the return result
-      console.log("update submit!");
+      OfferPageService.updateOffer(ruleForm.value).then((data) =>{
+        console.log("Update user offer data: ", data);
+        ruleForm.value = data["data"];
+        buttonState.value = "edit";
+      })
     } else {
       console.log("error submit!", fields);
     }
-    console.log(ruleForm);
   });
 };
 
-const deleteFrom = () => {
+const deleteForm = async(formEl: FormInstance | undefined) => {
   // TODO: Check the return result
-  let result = OfferPageService.deleteOffer(userId);
-  console.log("Record deleted");
+  await OfferPageService.deleteOffer(ruleForm.value.userId).then((data) =>{
+    console.log("Deleting Offer Record");
+    console.log("Message: " + data["message"]);
+    resetForm();
+    buttonState.value = "create";
+  });
 };
 
-const resetForm = (formEl: FormInstance | undefined) => {
-  if (!formEl) return;
-  formEl.resetFields();
+const resetForm = () => {
+  let userId = ruleForm.value.userId;
+  ruleForm.value = new OfferFormModel();
   ruleForm.value.userId = userId;
 };
 
@@ -241,4 +319,21 @@ const options = Array.from({ length: 10000 }).map((_, idx) => ({
   value: `${idx + 1}`,
   label: `${idx + 1}`,
 }));
+
+const formatDate = (dateString) => {
+  const date = new Date(dateString);
+  return new Intl.DateTimeFormat('en-US').format(date);
+}
 </script>
+
+<style scoped>
+.time {
+  font-size: 12px;
+}
+.w-zipCode {
+  font-size: 12px;
+}
+.w-owner {
+  font-size: 12px;
+}
+</style>
\ No newline at end of file
diff --git a/FrontendFolder/switch-room/src/components/ProfilePage.vue b/FrontendFolder/switch-room/src/components/ProfilePage.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7bfbf2f5f45b6847637446a4a45a5e5ddbe8ce26
--- /dev/null
+++ b/FrontendFolder/switch-room/src/components/ProfilePage.vue
@@ -0,0 +1,157 @@
+<template>
+  <div class="form_wrapper">
+    <div class="form_container">
+      <div class="title_container">
+        <h2>Profile</h2>
+        <div class="underline-title"></div>
+      </div>
+      <div class="row clearfix">
+        <div class="">
+          <div class="form">
+            <div class="profile-label">
+              <div>&nbsp;Username</div>
+              <div>{{profile.username}}&nbsp;</div>
+            </div>
+            <div class="form-border"></div>
+            <div class="profile-label">
+              <div>&nbsp;Email</div>
+              <div>{{profile.email}}&nbsp;</div>
+            </div>
+            <div class="form-border"></div>
+            <div class="profile-label">
+              <div>&nbsp;First Name</div>
+              <div>{{profile.firstName}}&nbsp;</div>
+            </div>
+            <div class="form-border"></div>
+            <div class="profile-label">
+              <div>&nbsp;Last Name</div>
+              <div>{{profile.lastName}}&nbsp;</div>
+            </div>
+            <div class="form-border"></div>
+            <button id="submit-btn" @click.prevent="onClickResetPassword" type="submit" value="Submit">
+              Reset Password
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive, onMounted } from "vue";
+import { useRouter } from "vue-router";
+import {getProfile} from "../services/UserService";
+const router = useRouter();
+const profile = reactive({
+  username: "",
+  email: "",
+  firstName: "",
+  lastName: "",
+});
+onMounted(async () => {
+  await getProfile()
+    .then((response) => {
+      if (response.status == "OK") {
+        const data = response.data
+        profile.username = data["username"]
+        profile.email = data["email"]
+        profile.firstName = data["firstName"]
+        profile.lastName = data["lastName"]
+      } else {
+        alert(response.message)
+      }
+    })
+})
+const onClickResetPassword = () => {
+  router.push("/resetpassword");
+};
+
+</script>
+
+<style scoped>
+body {
+  font-family: Verdana, Geneva, sans-serif;
+  font-size: 14px;
+  background: #f2f2f2;
+}
+
+.form_wrapper {
+  justify-content: center;
+  align-items: center;
+  display: flex;
+}
+
+.form_container {
+  background: #fbfbfb;
+  border-radius: 8px;
+  box-shadow: 1px 2px 8px rgba(0, 0, 0, 0.65);
+  height: auto;
+  width: 30%;
+  padding: 12px 44px;
+}
+
+.title_container {
+  font-family: "Raleway Thin", sans-serif;
+  letter-spacing: 4px;
+  padding-bottom: 23px;
+  padding-top: 13px;
+  text-align: center;
+}
+
+.form {
+  align-items: left;
+  display: flex;
+  flex-direction: column;
+}
+
+.form-content {
+  background: #fbfbfb;
+  border: none;
+  outline: none;
+  padding-top: 14px;
+}
+
+.form-border {
+  background: #2ec06f;
+  height: 1px;
+  width: 100%;
+}
+
+.profile-label {
+  padding-top: 13px;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+}
+
+#submit-btn {
+  background: #2ec06f;
+  border: none;
+  border-radius: 21px;
+  box-shadow: 0px 1px 8px #24c64f;
+  cursor: pointer;
+  color: white;
+  font-family: "Raleway SemiBold", sans-serif;
+  height: 42.3px;
+  margin: 0 auto;
+  margin-top: 50px;
+  transition: 0.25s;
+  width: 153px;
+}
+
+#submit-btn:hover {
+  box-shadow: 0px 1px 18px #24c64f;
+}
+
+.underline-title {
+  background: -webkit-linear-gradient(right, #a6f77b, #2ec06f);
+  height: 2px;
+  margin: -1.1rem auto 0 auto;
+  width: 200px;
+}
+
+.input_field radio_option {
+  margin-top: 10px;
+}
+</style>
diff --git a/FrontendFolder/switch-room/src/components/ResetPasswordPage.vue b/FrontendFolder/switch-room/src/components/ResetPasswordPage.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1d9aa218d13e9ffa9badec9451e28af03582111e
--- /dev/null
+++ b/FrontendFolder/switch-room/src/components/ResetPasswordPage.vue
@@ -0,0 +1,139 @@
+<template>
+  <div class="form_wrapper">
+    <div class="form_container">
+      <div class="title_container">
+        <h2>Reset Password</h2>
+        <div class="underline-title"></div>
+      </div>
+      <div class="row clearfix">
+        <div class="">
+          <form class="form">
+            <label for="user-oldPassword" style="padding-top: 13px">
+              &nbsp;Old Password
+            </label>
+            <input v-model="userInformation.oldPassword" id="user-oldPassword" class="form-content" type="password"
+              name="oldPassword" required />
+            <div class="form-border"></div>
+
+            <label for="user-newPassword" style="padding-top: 13px">
+              &nbsp;New Password
+            </label>
+            <input v-model="userInformation.newPassword" id="user-newPassword" class="form-content" type="password"
+              name="newPassword" required />
+            <div class="form-border"></div>
+
+            <button id="submit-btn" @click.prevent="onSubmit" type="submit" value="Submit">
+              Submit
+            </button>
+          </form>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive } from "vue";
+import * as UserService from "../services/UserService";
+import { useRouter } from "vue-router";
+import { User } from "@/type/types";
+const router = useRouter();
+const userInformation = reactive({
+  oldPassword: "",
+  newPassword: ""
+});
+
+const onSubmit = async () => {
+  const userInfo = {
+    oldPassword: userInformation.oldPassword,
+    newPassword: userInformation.newPassword,
+  };
+  const response = await UserService.resetPassword(
+    JSON.stringify(userInfo)
+  );
+  alert(response.message)
+  userInformation.oldPassword = ""
+  userInformation.newPassword = ""
+};
+
+</script>
+
+<style scoped>
+body {
+  font-family: Verdana, Geneva, sans-serif;
+  font-size: 14px;
+  background: #f2f2f2;
+}
+
+.form_wrapper {
+  justify-content: center;
+  align-items: center;
+  display: flex;
+}
+
+.form_container {
+  background: #fbfbfb;
+  border-radius: 8px;
+  box-shadow: 1px 2px 8px rgba(0, 0, 0, 0.65);
+  height: auto;
+  width: 30%;
+  padding: 12px 44px;
+}
+
+.title_container {
+  font-family: "Raleway Thin", sans-serif;
+  letter-spacing: 4px;
+  padding-bottom: 23px;
+  padding-top: 13px;
+  text-align: center;
+}
+
+.form {
+  align-items: left;
+  display: flex;
+  flex-direction: column;
+}
+
+.form-content {
+  background: #fbfbfb;
+  border: none;
+  outline: none;
+  padding-top: 14px;
+}
+
+.form-border {
+  background: -webkit-linear-gradient(right, #a6f77b, #2ec06f);
+  height: 1px;
+  width: 100%;
+}
+
+#submit-btn {
+  background: -webkit-linear-gradient(right, #a6f77b, #2dbd6e);
+  border: none;
+  border-radius: 21px;
+  box-shadow: 0px 1px 8px #24c64f;
+  cursor: pointer;
+  color: white;
+  font-family: "Raleway SemiBold", sans-serif;
+  height: 42.3px;
+  margin: 0 auto;
+  margin-top: 50px;
+  transition: 0.25s;
+  width: 153px;
+}
+
+#submit-btn:hover {
+  box-shadow: 0px 1px 18px #24c64f;
+}
+
+.underline-title {
+  background: -webkit-linear-gradient(right, #a6f77b, #2ec06f);
+  height: 2px;
+  margin: -1.1rem auto 0 auto;
+  width: 200px;
+}
+
+.input_field radio_option {
+  margin-top: 10px;
+}
+</style>
diff --git a/FrontendFolder/switch-room/src/components/SearchFlight.vue b/FrontendFolder/switch-room/src/components/SearchFlight.vue
index 1a1aafd36bb8a4ca88e8b141d8779d25e5aac932..5bc26fc26d33d31a790fc1757c7f4f0a4df7967f 100644
--- a/FrontendFolder/switch-room/src/components/SearchFlight.vue
+++ b/FrontendFolder/switch-room/src/components/SearchFlight.vue
@@ -67,7 +67,6 @@
                 v-model="flightForm.numAdults"
                 :min="1"
                 :max="10"
-                @change="handleChange"
               />
             </el-form-item>
             <el-col
@@ -80,7 +79,6 @@
                 v-model="flightForm.numSeniors"
                 :min="0"
                 :max="10"
-                @change="handleChange"
               />
             </el-form-item>
           </el-form-item>
@@ -99,7 +97,7 @@
           </el-form-item>
 
           <el-form-item div="Button">
-            <el-button type="primary" @click.prevent="submitForm(ruleFormRef)"
+            <el-button type="primary" @click="submitForm(ruleFormRef)"
               >Search</el-button
             >
             <el-button @click="resetForm(ruleFormRef)">Cancel</el-button>
@@ -111,14 +109,20 @@
 </template>
 
 <script lang="ts" setup>
+import { useRouter } from "vue-router";
 import { reactive, ref } from "vue";
 import type { FormInstance, FormRules } from "element-plus";
 import { FlightFormModel } from "@/models/FlightFormModel";
+import { FlightResultModel } from "@/models/FlightResultModel";
 import * as FlightTicketService from "@/services/FlightTicketService";
+import { useTicketStore } from "@/store/flightdataStore";
 
 const size = ref("large");
 const labelPosition = ref("left");
 const ruleFormRef = ref<FormInstance>();
+const router = useRouter();
+const results = ref([] as FlightResultModel[]);
+const ticketStore = useTicketStore();
 
 let flightForm = ref(new FlightFormModel());
 // const flightForm = reactive({
@@ -171,17 +175,25 @@ const rules = reactive<FormRules>({
   ],
 });
 
+
 const submitForm = async (formEl: FormInstance | undefined) => {
   if (!formEl) return;
   await formEl.validate((valid, fields) => {
     if (valid) {
-      let result = FlightTicketService.createNewFlight(flightForm);
+      // let result = FlightTicketService.createNewFlight(flightForm);
       // TODO: Check the return result
       // console.log("Form Data before save in DB: ",flightForm.value);
-      FlightTicketService.createNewFlight(flightForm.value).then((data) => {
-        console.log("Save search flight data: ", data);
-      });
-      console.log("submit!");
+
+      // FlightTicketService.createNewFlight(flightForm.value).then((response) => {
+      //
+      //   console.log("Save search flight data: ", response.data);
+      //   results.value = response.data;
+      //   router.push("/flight-ticket");
+      // });
+      // const response = FlightTicketService.createNewFlight(flightForm.value);
+      // console.log("this is a "+response.data);
+      ticketStore.fetchResultTicket(flightForm.value);
+      router.push("/flight-ticket");
     } else {
       console.log("error submit!", fields);
     }
@@ -193,6 +205,7 @@ const resetForm = (formEl: FormInstance | undefined) => {
   if (!formEl) return;
   formEl.resetFields();
 };
+
 </script>
 
 <style>
diff --git a/FrontendFolder/switch-room/src/components/TicketPage.vue b/FrontendFolder/switch-room/src/components/TicketPage.vue
new file mode 100644
index 0000000000000000000000000000000000000000..57c53c329258e235b6b5f08c01f5ffefc41da006
--- /dev/null
+++ b/FrontendFolder/switch-room/src/components/TicketPage.vue
@@ -0,0 +1,163 @@
+<template>
+
+  <div class="container">
+    <h1 class="upcomming">Flight Tickets</h1>
+    <div class="item" v-for="ticket in ticketStore.ticketList">
+      <div class="item-right">
+        <h2 class="sign"><font-awesome-icon icon="fa-solid fa-dollar-sign" /></h2>
+        <p class="price">{{ticket.price}}</p>
+        <span class="up-border"></span>
+        <span class="down-border"></span>
+      </div> <!-- end item-right -->
+
+      <div class="item-left">
+        <p class="airline">{{ticket.airlines}} Airline</p>
+        <h2 class="title">{{ticket.departure0}} <font-awesome-icon icon="fa-solid fa-right-left" /> {{ticket.arrival0}}</h2>
+
+        <div class="sce">
+          <div class="icon">
+            <font-awesome-icon icon="fa-solid fa-calendar-days" />
+          </div>
+          <p>To: {{ticket.departureDateTime_0}}-{{ticket.arrivalDateTime_0}}<br/> Return: {{ticket.departureDateTime_1}}-{{ticket.arrivalDateTime_1}}</p>
+        </div>
+        <div class="fix"></div>
+        <div class="loc">
+          <div class="icon">
+            <font-awesome-icon icon="fa-solid fa-plane-up" />
+          </div>
+          <p>{{ticket.aircraftType_0}} <br/> Class: {{ticket.classOfService_0}}</p>
+        </div>
+        <div class="fix"></div>
+        <a v-bind:href="ticket.detail_url"> <button class="tickets">Buy it</button></a>
+      </div> <!-- end item-right -->
+    </div> <!-- end item -->
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useTicketStore } from "@/store/flightdataStore";
+
+const ticketStore = useTicketStore();
+
+</script>
+
+<style scoped>
+* {
+  box-sizing: border-box;
+  margin:0;
+  padding:0;
+}
+body {
+  background:#DDD;
+  font-family: 'Cabin', sans-serif;
+}
+div.container {
+  max-width: 1350px;
+  margin: 0 auto;
+  overflow: hidden
+}
+.upcomming {
+  font-size: 45px;
+  text-transform: uppercase;
+  border-left: 14px solid rgba(255, 235, 59, 0.78);
+  padding-left: 12px;
+  margin: 18px 8px;
+}
+.container .item {
+  width: 48%;
+  float: left;
+  padding: 0 20px;
+  background: #fff;
+  overflow: hidden;
+  margin: 10px
+}
+.container .item-right, .container .item-left {
+  float: left;
+  padding: 20px
+}
+.container .item-right {
+  padding: 79px 50px;
+  margin-right: 20px;
+  width: 25%;
+  position: relative;
+  height: 286px
+}
+.container .item-right .up-border, .container .item-right .down-border {
+  padding: 14px 15px;
+  background-color: #ddd;
+  border-radius: 50%;
+  position: absolute
+}
+.container .item-right .up-border {
+  top: -8px;
+  right: -35px;
+}
+.container .item-right .down-border {
+  bottom: -13px;
+  right: -35px;
+}
+.container .item-right .sign {
+  font-size: 60px;
+  text-align: center;
+  color: #111
+}
+.container .item-right .price, .container .item-left .airline {
+  color: #555;
+  font-size: 20px;
+  margin-bottom: 9px;
+}
+.container .item-right .price {
+  text-align: center;
+  font-size: 25px;
+}
+.container .item-left {
+  width: 71%;
+  padding: 34px 0px 19px 46px;
+  border-left: 3px dotted #999;
+}
+.container .item-left .title {
+  color: #111;
+  font-size: 34px;
+  margin-bottom: 12px
+}
+.container .item-left .sce {
+  margin-top: 5px;
+  display: block
+}
+.container .item-left .sce .icon, .container .item-left .sce p,
+.container .item-left .loc .icon, .container .item-left .loc p{
+  float: left;
+  word-spacing: 5px;
+  letter-spacing: 1px;
+  color: #555;
+  margin-bottom: 10px;
+  font-size: 15px;
+}
+.container .item-left .sce .icon, .container .item-left .loc .icon {
+  margin-right: 10px;
+  font-size: 20px;
+  color: #666
+}
+.container .item-left .loc {display: block}
+.fix {clear: both}
+.container .item .tickets{
+  color: #fff;
+  padding: 6px 14px;
+  float: right;
+  margin-top: 10px;
+  font-size: 18px;
+  border: none;
+  cursor: pointer
+}
+.container .item .tickets {background: #3D71E9}
+@media only screen and (max-width: 1150px) {
+  .container .item {
+    width: 100%;
+    margin-right: 20px
+  }
+  div.container {
+    margin: 0 20px auto
+  }
+}
+</style>
+
diff --git a/FrontendFolder/switch-room/src/components/WishlistPage.vue b/FrontendFolder/switch-room/src/components/WishlistPage.vue
index 24584eef3d3982fe73265b2fcfdfa734da73797e..335e338e814a914449651f6cfee4205925ee792c 100644
--- a/FrontendFolder/switch-room/src/components/WishlistPage.vue
+++ b/FrontendFolder/switch-room/src/components/WishlistPage.vue
@@ -1,7 +1,7 @@
 <template>
   <el-row :gutter="20">
-    <el-col :span="4"><div class="grid-content ep-bg-purple" /></el-col>
-    <el-col :span="16">
+    <el-col :span="2"><div class="grid-content ep-bg-purple" /></el-col>
+    <el-col :span="20">
       <el-card style="width: 100%">
         <template #header>
           <div class="card-header">
@@ -14,20 +14,28 @@
             <!-- Aside Coding Area -->
             <el-aside width="300px">
               <el-space direction="vertical" width="100%">
-                <el-card
-                  v-for="(item, index) in wishlistList.value"
-                  shadow="hover"
-                  style="width: 280px"
-                  @click="selectItem(index)"
+                <el-badge class="item"
+                          v-for="(item, index) in wishlistList.value"
+                          :value="totalMatchCountList.value[index]"
+                          :hidden = "totalMatchCountList.value[index] === 0"
                 >
-                  <span>{{ item.cityName }}</span>
-                  <div class="bottom">
-                    <time class="time"
-                      >"{{ item.startTime }} to {{ item.endTime }}"</time
-                    >
-                  </div>
-                </el-card>
+                  <el-card
+                      shadow="hover"
+                      style="width: 280px"
+                      @click="selectItem(index)"
+                  >
+                    <span>{{ item.cityName }}, {{ item.state }}</span>
+                    <div class="bottom">
+                      <time class="time"
+                      >"{{ formatDate(item.startTime) }} to {{ formatDate(item.endTime) }}"</time
+                      >
+                    </div>
+                  </el-card>
+
+                </el-badge>
+
                 <el-card
+                    class="item"
                   shadow="hover"
                   style="width: 280px"
                   @click="addNewWishlistItem()"
@@ -54,15 +62,22 @@
                   <el-form-item></el-form-item>
 
                   <el-form-item label="City Name:" prop="cityName">
-                    <el-input v-model="wishlistItem.cityName" />
+                    <el-input v-model="wishlistItem.cityName" :readonly="buttonState === 'edit'" />
                   </el-form-item>
 
                   <el-form-item label="Zip Code:" prop="zipCode">
-                    <el-input v-model="wishlistItem.zipCode" />
+                    <el-input v-model="wishlistItem.zipCode" :readonly="buttonState === 'edit'"/>
                   </el-form-item>
 
-                  <el-form-item label="State:" prop="state">
-                    <el-input v-model="wishlistItem.state" />
+                  <el-form-item  label="State:" prop="state">
+                    <el-select
+                        v-model="wishlistItem.state"
+                        placeholder="Please select state"
+                        :disabled="buttonState === 'edit'"
+                    >
+                      <el-option v-for="(state_item, index) in USA_STATE_INITAL_LIST"
+                                 :label="state_item" :value="state_item" />
+                    </el-select>
                   </el-form-item>
 
                   <el-form-item label="Trip Start Time" required>
@@ -73,6 +88,7 @@
                         label="Pick a date"
                         placeholder="Pick a date"
                         style="width: 100%"
+                        :readonly="buttonState === 'edit'"
                       />
                     </el-form-item>
                   </el-form-item>
@@ -85,6 +101,7 @@
                         label="Pick a date"
                         placeholder="Pick a date"
                         style="width: 100%"
+                        :readonly="buttonState === 'edit'"
                       />
                     </el-form-item>
                   </el-form-item>
@@ -94,21 +111,49 @@
                       v-model="wishlistItem.details"
                       type="textarea"
                       placeholder="Trip plan or want to visit places..."
+                      :readonly="buttonState === 'edit'"
                     />
                   </el-form-item>
 
-                  <el-button type="primary" @click="submitForm(ruleFormRef)"
-                    >Create</el-button
-                  >
-                  <el-button @click="resetForm(ruleFormRef)">Reset</el-button>
+                  <el-button type="primary" v-if="buttonState === 'create'" @click="submitForm(ruleFormRef)"
+                    >Create</el-button>
+                  <el-button type="primary" v-if="buttonState === 'edit'" @click="onEdit(ruleFormRef)"
+                  >Edit</el-button>
+                  <el-button type="success" v-if="buttonState === 'update'" @click="updateForm(ruleFormRef)"
+                  >Save</el-button>
+                  <el-button type="danger" v-if="buttonState === 'update'" @click="deleteForm(ruleFormRef)">
+                    Delete</el-button>
                 </el-form>
               </el-card>
             </el-main>
+
+            <el-aside width="300px" >
+              <el-space direction="vertical" width="100%" :fill="true">
+                <div class="card-header">
+                <span v-if="wishlistItem.cityName.length>0">Matched Offer for:
+                  {{wishlistItem.cityName}}, {{wishlistItem.state}}
+                </span>
+                </div>
+                <el-card
+                    v-for="(item, index) in offerMatchList.value"
+                  shadow="hover"
+                  style="width: 280px"
+                  @click="selectMatchOfferItem(index)"
+                >
+                  <span> {{formatDate(item.startTime)}} - {{formatDate(item.endTime)}} </span>
+                  <div>
+                    <span class="o-zipCode"> Zip code: {{item.zipCode}} </span>
+                    <br>
+                    <span class="o-owner"> Host name: {{item.hostName}} </span>
+                  </div>
+                </el-card>
+              </el-space>
+            </el-aside>
           </el-container>
         </div>
       </el-card>
     </el-col>
-    <el-col :span="4"><div class="grid-content ep-bg-purple" /></el-col>
+    <el-col :span="2"><div class="grid-content ep-bg-purple" /></el-col>
   </el-row>
 </template>
 
@@ -117,6 +162,7 @@ import { reactive, ref, onMounted } from "vue";
 import type { FormInstance, FormRules } from "element-plus";
 import { WishlistItemModel } from "@/models/WishlistItemModel";
 import * as WishlistService from "@/services/WishlistService";
+import { USA_STATE_INITAL_LIST } from "@/services/Constans";
 
 const formSize = ref("default");
 const ruleFormRef = ref<FormInstance>();
@@ -161,30 +207,73 @@ const rules = reactive<FormRules>({
   ],
 });
 
-// TODO: uncomment it when API connection ready
-const userId = 233;
 const wishlistList = reactive({value:[]});
 const wishlistItem = ref(new WishlistItemModel());
 wishlistItem.value.wishlistItemId = null;
+let buttonState = ref("create");
+const selectedIdx = ref(0);
+const offerMatchList = reactive({value:[]});
+const totalMatchCountList = reactive({value:[]});
 
 onMounted(() => {
-  WishlistService.getUserWishlistInfo(userId).then((data)=>{
+  selectedIdx.value = 0;
+  wishlistInitLoad();
+})
+
+const onEdit = () =>{
+  buttonState.value = "update";
+}
+
+const wishlistInitLoad = async() =>{
+  await WishlistService.getUserWishlistInfo().then((data)=>{
     console.log("Receiving wishlist list data", data);
-    if(data["data"] === null){
+    if(data["data"] === null || data["data"].length === 0){
       wishlistList.value = [];
+      buttonState.value = "create";
     }else{
-      wishlistList.value
       wishlistList.value = data["data"];
+      selectItem(0);
+      buttonState.value = "edit";
+      loadMatchNumbersForAllList(data["data"]);
     }
   })
+}
 
-})
+const loadMatchNumbersForAllList = async (wishlistItemList: Array<WishlistItemModel>) =>{
+  await WishlistService.loadMatchOfferNumbersFor(wishlistItemList).then((data) =>{
+    console.log("Receiving offer match count list data: ", data);
+    if(data["data"] === null || data["data"].length === 0){
+      for(let i=0; i<totalMatchCountList.value.length; ++i){
+        totalMatchCountList.value.push(0);
+      }
+    }else{
+      totalMatchCountList.value = data["data"];
+    }
+  })
+}
 
+const loadOfferMatchList = async () =>{
+  await WishlistService.getOfferMatchList(wishlistItem.value.wishlistItemId).then((data) =>{
+    console.log("Receiving offer match list data: ", data);
+    if(data["data"] === null || data["data"].length === 0){
+      offerMatchList.value = [];
+    }else{
+      offerMatchList.value = data["data"];
+    }
+  })
+}
 
+const formatDate = (dateString) => {
+  const date = new Date(dateString);
+  return new Intl.DateTimeFormat('en-US').format(date);
+}
 
 function selectItem(idx: number) {
   console.log("Selected wishlist Item: " + idx);
   wishlistItem.value = reactive(wishlistList.value[idx]);
+  buttonState.value = "edit";
+  selectedIdx.value = idx;
+  loadOfferMatchList(wishlistItem.value.wishlistItemId);
 }
 
 function addNewWishlistItem() {
@@ -192,18 +281,21 @@ function addNewWishlistItem() {
   console.log("addNewWishlistItem");
   wishlistItem.value = new WishlistItemModel();
   wishlistItem.value.wishlistItemId = null;
+  buttonState.value = "create";
 }
+
 const submitForm = async (formEl: FormInstance | undefined) => {
   if (!formEl) return;
   await formEl.validate((valid, fields) => {
     if (valid) {
-      WishlistService.createNewWishlistItem( userId, wishlistItem.value).then((data)=>{
+      WishlistService.createNewWishlistItem( wishlistItem.value).then((data)=>{
         console.log("Receiving create wishlist item data", data);
         if(data["data"] === null){
           // TODO: create failed, handle it later
         }else{
           wishlistItem.value = data["data"];
           wishlistList.value.push(data["data"]);
+          buttonState.value = "edit";
         }
       })
       console.log("submit!");
@@ -214,18 +306,38 @@ const submitForm = async (formEl: FormInstance | undefined) => {
   });
 };
 
-const resetForm = (formEl: FormInstance | undefined) => {
-  // TODO: make it delete to testing, need to change it back
-  // if (!formEl) return;
-  // formEl.resetFields();
+const updateForm = async (formEl: FormInstance | undefined) =>{
+  if (!formEl) return;
+  await formEl.validate((valid, fields) => {
+    if (valid) {
+      WishlistService.createNewWishlistItem( wishlistItem.value).then((data)=>{
+        console.log("Receiving wishlist item data", data);
+        if(data["data"] === null){
+          // TODO: create failed, handle it later
+        }else{
+          wishlistItem.value = data["data"];
+          wishlistList.value[selectedIdx] = data["data"];
+          buttonState.value = "edit";
+        }
+        console.log("submit!");
+        })
+    } else {
+      console.log("error submit!", fields);
+    }
+    console.log(wishlistItem.value);
+  });
+}
+
+const deleteForm = async (formEl: FormInstance | undefined) => {
   if(wishlistItem.value.wishlistItemId !== null){
-    WishlistService.deleteWishlistItem(userId, wishlistItem.value.wishlistItemId).then((data)=>{
+    await WishlistService.deleteWishlistItem( wishlistItem.value.wishlistItemId).then((data)=>{
       console.log("Delete wishlist item", data);
       if(data["data"] === null){
         // TODO: delete failed or something wrong
       }else{
         wishlistList.value=data["data"];
         addNewWishlistItem();
+        loadMatchNumbersForAllList(data["data"]);
       }
     })
   }
@@ -258,4 +370,14 @@ const options = Array.from({ length: 10000 }).map((_, idx) => ({
 .main-card {
   padding: 0 0 0 20px;
 }
+.o-zipCode {
+  font-size: 12px;
+}
+.o-owner {
+  font-size: 12px;
+}
+.item {
+  margin-top: 10px;
+  margin-right: 40px;
+}
 </style>
diff --git a/FrontendFolder/switch-room/src/main.ts b/FrontendFolder/switch-room/src/main.ts
index 68591da5af4259d026dea2f926d0cf00825238bb..d14914943134c533744c0aef973384a2b5f55c73 100644
--- a/FrontendFolder/switch-room/src/main.ts
+++ b/FrontendFolder/switch-room/src/main.ts
@@ -1,5 +1,7 @@
 import { createApp } from "vue";
 import ElementPlus from "element-plus";
+import store from "./store/index";
+import * as cookieParser from "cookie-parser";
 import "element-plus/dist/index.css";
 import App from "./App.vue";
 import router from "./router";
@@ -23,6 +25,9 @@ import { faLinkedin } from "@fortawesome/free-brands-svg-icons";
 import { faGithub } from "@fortawesome/free-brands-svg-icons";
 
 
+
+import {createPinia} from "pinia";
+
 /* add icons to the library */
 library.add(faUserSecret);
 library.add(fas);
@@ -30,9 +35,13 @@ library.add(faFacebook);
 library.add(faTwitter);
 library.add(faLinkedin);
 library.add(faGithub);
+const pinia = createPinia();
+
 
 createApp(App)
   .component("font-awesome-icon", FontAwesomeIcon)
   .use(router)
   .use(ElementPlus)
+  .use(store)
+    .use(pinia)
   .mount("#app");
diff --git a/FrontendFolder/switch-room/src/models/FlightResultModel.ts b/FrontendFolder/switch-room/src/models/FlightResultModel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b1a610d9e7f1d34235da2f62893fef574958d4d8
--- /dev/null
+++ b/FrontendFolder/switch-room/src/models/FlightResultModel.ts
@@ -0,0 +1,44 @@
+export class FlightResultModel {
+    public id : number;
+    public departure0: string;
+    public arrival0: string;
+    public departureDateTime_0: string;
+    public arrivalDateTime_0: string;
+    public classOfService_0: string;
+    public aircraftType_0: string;
+    public distance_0: number;
+
+    public departure1: string;
+    public arrival1: string;
+    public departureDateTime_1: string;
+    public arrivalDateTime_1: string;
+    public classOfService_1: string;
+    public aircraftType_1: string;
+    public distance_1: number;
+
+    public price: number;
+    public airlines: string;
+    public detail_url: string;
+
+
+    constructor(id: number, departure0: string, arrival0: string, departureDateTime_0: string, arrivalDateTime_0: string, classOfService_0: string, aircraftType_0: string, distance_0: number, departure1: string, arrival1: string, departureDateTime_1: string, arrivalDateTime_1: string, classOfService_1: string, aircraftType_1: string, distance_1: number, price: number, airlines: string, detail_url: string) {
+        this.id = id;
+        this.departure0 = departure0;
+        this.arrival0 = arrival0;
+        this.departureDateTime_0 = departureDateTime_0;
+        this.arrivalDateTime_0 = arrivalDateTime_0;
+        this.classOfService_0 = classOfService_0;
+        this.aircraftType_0 = aircraftType_0;
+        this.distance_0 = distance_0;
+        this.departure1 = departure1;
+        this.arrival1 = arrival1;
+        this.departureDateTime_1 = departureDateTime_1;
+        this.arrivalDateTime_1 = arrivalDateTime_1;
+        this.classOfService_1 = classOfService_1;
+        this.aircraftType_1 = aircraftType_1;
+        this.distance_1 = distance_1;
+        this.price = price;
+        this.airlines = airlines;
+        this.detail_url = detail_url;
+    }
+}
diff --git a/FrontendFolder/switch-room/src/models/OfferFormModel.ts b/FrontendFolder/switch-room/src/models/OfferFormModel.ts
index 891d7b5cea584ec2e1e3c17e7fa2d48f3f6b72b8..938328063bc60eeb45cc2851048a63f629a10568 100644
--- a/FrontendFolder/switch-room/src/models/OfferFormModel.ts
+++ b/FrontendFolder/switch-room/src/models/OfferFormModel.ts
@@ -1,10 +1,12 @@
 export class OfferFormModel {
   public readonly userId: number;
+  public state: string;
+  public stateCode: number;
   public zipCode: number | string;
   public spaceType: string;
   public otherSpaceType: string;
   public spaceLocateCity: string;
-  public cityCode: number;
+  public stateCityCode: number;
   public availableTimeStart: Date | string;
   public availableTimeEnd: Date | string;
   public maxNumberOfPeople: number;
@@ -13,11 +15,13 @@ export class OfferFormModel {
 
   constructor(
     userId = -1,
+    state = "",
+    stateCode = -1,
     zipCode = "",
     spaceType = "",
     otherSpaceType = "",
     spaceLocateCity = "",
-    cityCode = 0,
+    stateCityCode = -1,
     offering = false,
     availableTimeStart = new Date(),
     availableTimeEnd = new Date(),
@@ -25,11 +29,13 @@ export class OfferFormModel {
     spaceDetails = ""
   ) {
     this.userId = userId;
+    this.state = state;
+    this.stateCode = stateCode;
     this.zipCode = zipCode;
     this.spaceType = spaceType;
     this.otherSpaceType = otherSpaceType;
     this.spaceLocateCity = spaceLocateCity;
-    this.cityCode = cityCode;
+    this.stateCityCode = stateCityCode;
     this.offering = offering;
     this.availableTimeStart = availableTimeStart;
     this.availableTimeEnd = availableTimeEnd;
diff --git a/FrontendFolder/switch-room/src/models/OfferNotification.ts b/FrontendFolder/switch-room/src/models/OfferNotification.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a9af3a6f2485d4a6be6acdc012c479f77e8cf3df
--- /dev/null
+++ b/FrontendFolder/switch-room/src/models/OfferNotification.ts
@@ -0,0 +1,21 @@
+export class OfferNotification {
+  public offerId: number;
+  public wishlistItemId: number;
+  public modifyDate: Date;
+  public offerResult: number;
+  public wishlistResult: number;
+
+  constructor(
+    offerId = -1,
+    wishlistItemId = -1,
+    modifyDate = new Date(),
+    offerResult = -1,
+    wishlistResult = -1
+  ) {
+    this.offerId = offerId;
+    this.wishlistItemId = wishlistItemId;
+    this.modifyDate = modifyDate;
+    this.offerResult = offerResult;
+    this.wishlistResult = wishlistResult;
+  }
+}
diff --git a/FrontendFolder/switch-room/src/models/OfferPageWishlistMatchRequestInfo.ts b/FrontendFolder/switch-room/src/models/OfferPageWishlistMatchRequestInfo.ts
new file mode 100644
index 0000000000000000000000000000000000000000..763f787145abfa0443c08de8cca3c85a431bc2c9
--- /dev/null
+++ b/FrontendFolder/switch-room/src/models/OfferPageWishlistMatchRequestInfo.ts
@@ -0,0 +1,27 @@
+export class OfferPageWishlistMatchRequestInfo {
+    wishlistOwnerId: number;
+    wishlistId: number;
+    startTime: Date;
+    endTime: Date;
+    wishListOwnerName: string;
+    hasOffer: boolean;
+    zipCode: number;
+
+    constructor(wishlistOwnerId = -1,
+    wishlistId = -1,
+    startTime = new Date(),
+    endTime = new Date(),
+    wishListOwnerName = "",
+    hasOffer = false,
+    zipCode = -1) {
+        this.wishlistOwnerId = wishlistOwnerId;
+        this.wishlistId = wishlistId;
+        this.startTime = startTime;
+        this.endTime = endTime;
+        this.wishListOwnerName = wishListOwnerName;
+        this.hasOffer = hasOffer;
+        this.zipCode = zipCode;
+    }
+
+
+}
\ No newline at end of file
diff --git a/FrontendFolder/switch-room/src/models/WishlistItemModel.ts b/FrontendFolder/switch-room/src/models/WishlistItemModel.ts
index dca073a57f6151b661f992a68581f66abdf49a8c..a537cef3283d49ec13c42d6fb58616f44ebe0148 100644
--- a/FrontendFolder/switch-room/src/models/WishlistItemModel.ts
+++ b/FrontendFolder/switch-room/src/models/WishlistItemModel.ts
@@ -1,9 +1,10 @@
 export class WishlistItemModel {
   public readonly wishlistItemId: number;
   public cityName: string;
+  public stateCityCode: number;
   public zipCode: number| string
   public state: string;
-  public stateCode: number | string;
+  public stateCode: number;
   public startTime: Date | string;
   public endTime: Date | string;
   public details: string;
@@ -12,7 +13,8 @@ export class WishlistItemModel {
     wishlistItemId = -1,
     cityName = "",
     state = "",
-    stateCode = "",
+    stateCityCode = -1,
+    stateCode = -1,
     startTime = "",
     endTime = "",
     details = "",
@@ -22,6 +24,7 @@ export class WishlistItemModel {
     this.cityName = cityName;
     this.state = state;
     this.stateCode = stateCode;
+    this.stateCityCode = stateCityCode;
     this.startTime = startTime;
     this.endTime = endTime;
     this.details = details;
diff --git a/FrontendFolder/switch-room/src/models/WishlistPageOfferMatchRequestInfo.ts b/FrontendFolder/switch-room/src/models/WishlistPageOfferMatchRequestInfo.ts
new file mode 100644
index 0000000000000000000000000000000000000000..471d70302d36a209df463cb0d3a2d31993ddb55f
--- /dev/null
+++ b/FrontendFolder/switch-room/src/models/WishlistPageOfferMatchRequestInfo.ts
@@ -0,0 +1,25 @@
+export class WishlistPageOfferMatchRequestInfo {
+    offerOwnerId: number;
+    wishListId: number;
+    startTime: Date;
+    endTime: Date;
+    zipCode: number;
+    hostName: string;
+
+    constructor(offerOwnerId =-1,
+    wishListId = -1,
+    startTime = new Date(),
+    endTime = new Date(),
+    zipCode = -1,
+    hostName = ""
+    ) {
+        this.offerOwnerId = offerOwnerId;
+        this.wishListId = wishListId;
+        this.startTime = startTime;
+        this.endTime = endTime;
+        this.zipCode = zipCode;
+        this.hostName = hostName;
+    }
+
+
+}
\ No newline at end of file
diff --git a/FrontendFolder/switch-room/src/router/index.ts b/FrontendFolder/switch-room/src/router/index.ts
index 68e81a0fe93ee3d119eec884d3b916558759121a..4ac42f6213ea79c1a4d94c5ec29fe9e4d05ede12 100644
--- a/FrontendFolder/switch-room/src/router/index.ts
+++ b/FrontendFolder/switch-room/src/router/index.ts
@@ -1,27 +1,53 @@
 import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
 import HomeView from "../views/HomeView.vue";
 import RegisterView from "../views/RegisterView.vue";
+import ResetPasswordView from "../views/ResetPasswordView.vue";
+import ProfileView from "../views/ProfileView.vue";
+import MatchedView from "../views/MatchedView.vue";
 
 const routes: Array<RouteRecordRaw> = [
   {
     path: "/",
     name: "home",
     component: HomeView,
+    meta: {
+      hideHeader: true,
+    },
   },
   {
     path: "/register",
     name: "register",
     component: RegisterView,
+    meta: {
+      hideHeader: true,
+    },
+  },
+  {
+    path: "/resetPassword",
+    name: "resetPassword",
+    meta: {
+      requiresAuth: true,
+      hideHeader: false,
+    },
+    component: ResetPasswordView,
   },
   {
     path: "/offer-page",
     name: "OfferPage",
+    meta: {
+      requiresAuth: true,
+      hideHeader: false,
+    },
     component: () =>
       import(/* webpackChunkName:  "about" */ "../views/OfferView.vue"),
   },
   {
     path: "/wishlist-page",
     name: "WishlistPage",
+    meta: {
+      requiresAuth: true,
+      hideHeader: false,
+    },
     component: () =>
       import(/* webpackChunkName: "about" */ "../views/WishlistView.vue"),
   },
@@ -31,15 +57,43 @@ const routes: Array<RouteRecordRaw> = [
     // route level code-splitting
     // this generates a separate chunk (about.[hash].js) for this route
     // which is lazy-loaded when the route is visited.
+    meta: {
+      requiresAuth: true,
+      hideHeader: false,
+    },
     component: () =>
       import(/* webpackChunkName: "about" */ "../views/FlightView.vue"),
   },
+  {
+    path: "/profile",
+    name: "profile",
+    meta: {
+      requiresAuth: true,
+      hideHeader: false,
+    },
+    component: ProfileView,
+  },
   {
     path: "/login-main-page",
     name: "LoginMainPage",
+    meta: {
+      requiresAuth: true,
+      hideHeader: false,
+    },
+    component: () => import("../views/LoginMainPageView.vue"),
+  },
+
+  {
+    path: "/matched-result/:offerId/:wishlistId",
+    name: "MatchResultPage",
+    component: MatchedView,
+  },
+  {
+    path: "/flight-ticket",
+    name: "TicketPage",
     component: () =>
-      import("../views/LoginMainPageView.vue"),
-  }
+        import(/* webpackChunkName: "about" */ "../views/FlightTicket.vue"),
+  },
 ];
 
 const router = createRouter({
@@ -47,4 +101,16 @@ const router = createRouter({
   routes,
 });
 
+router.beforeEach((to, from, next) => {
+  if (to.matched.some((record) => record.meta.requiresAuth)) {
+    if (!document.cookie) {
+      next({ name: "home" });
+    } else {
+      next();
+    }
+  } else {
+    next();
+  }
+});
+
 export default router;
diff --git a/FrontendFolder/switch-room/src/services/Constans.ts b/FrontendFolder/switch-room/src/services/Constans.ts
index 8c8936a3fbf2918b9ac8af231c4fc34dce9cf837..b032e5f6c56fa6f34c0ece6f867cf24e627fef56 100644
--- a/FrontendFolder/switch-room/src/services/Constans.ts
+++ b/FrontendFolder/switch-room/src/services/Constans.ts
@@ -3,11 +3,71 @@
  */
 
 const SEVER_IP = location.hostname;
+
 const SERVER_PORT = 8081;
 const Server_URL =
   location.protocol + "//" + SEVER_IP + ":" + SERVER_PORT + "/";
 
-export { SEVER_IP, SERVER_PORT, Server_URL };
+const USA_STATE_INITAL_LIST = [
+  "AL",
+  "AK",
+  "AS",
+  "AZ",
+  "AR",
+  "CA",
+  "CO",
+  "CT",
+  "DE",
+  "DC",
+  "FL",
+  "GA",
+  "GU",
+  "HI",
+  "ID",
+  "IL",
+  "IN",
+  "IA",
+  "KS",
+  "KY",
+  "LA",
+  "ME",
+  "MD",
+  "MA",
+  "MI",
+  "MN",
+  "MS",
+  "MO",
+  "MT",
+  "NE",
+  "NV",
+  "NH",
+  "NJ",
+  "NM",
+  "NY",
+  "NC",
+  "ND",
+  "MP",
+  "OH",
+  "OK",
+  "OR",
+  "PA",
+  "PR",
+  "RI",
+  "SC",
+  "SD",
+  "TN",
+  "TX",
+  "UT",
+  "VT",
+  "VA",
+  "VI",
+  "WA",
+  "WV",
+  "WI",
+  "WY",
+];
+
+export { SEVER_IP, SERVER_PORT, Server_URL, USA_STATE_INITAL_LIST };
 
 /*
  Change logs:
diff --git a/FrontendFolder/switch-room/src/services/FetchOfferService.ts b/FrontendFolder/switch-room/src/services/FetchOfferService.ts
new file mode 100644
index 0000000000000000000000000000000000000000..428a2b0629103b8102e23538d58fa1511e1d6aed
--- /dev/null
+++ b/FrontendFolder/switch-room/src/services/FetchOfferService.ts
@@ -0,0 +1,10 @@
+import * as serverHttpService from "./ServerHttpService";
+
+const baseUrl = "matchedOffer";
+
+function getOffersFromServerWithID(offerId: number) {
+  const urlPath = "/" + offerId;
+  return serverHttpService.Get(baseUrl + urlPath);
+}
+
+export { getOffersFromServerWithID };
diff --git a/FrontendFolder/switch-room/src/services/FetchWishListService.ts b/FrontendFolder/switch-room/src/services/FetchWishListService.ts
new file mode 100644
index 0000000000000000000000000000000000000000..db9eda30612cdafde08ce653b89a00d58fe8d8ec
--- /dev/null
+++ b/FrontendFolder/switch-room/src/services/FetchWishListService.ts
@@ -0,0 +1,10 @@
+import * as serverHttpService from "./ServerHttpService";
+
+const baseUrl = "matchedWishList";
+
+function getWishListFromServerWithID(wishListId: number) {
+  const urlPath = "/" + wishListId;
+  return serverHttpService.Get(baseUrl + urlPath);
+}
+
+export { getWishListFromServerWithID };
diff --git a/FrontendFolder/switch-room/src/services/NotificationService.ts b/FrontendFolder/switch-room/src/services/NotificationService.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fa8bbace6cac91779a61a09415bf183c9bf28f19
--- /dev/null
+++ b/FrontendFolder/switch-room/src/services/NotificationService.ts
@@ -0,0 +1,15 @@
+import * as serverHttpService from "./ServerHttpService";
+
+const baseUrl = "notification";
+
+function getNotificationFromServerWithID(userId: number) {
+  const urlPath = "/" + userId;
+  return serverHttpService.Get(baseUrl + urlPath);
+}
+
+function getNotificationwishFromServerWithID(userId: number) {
+  const urlPath = "/wish/" + userId;
+  return serverHttpService.Get(baseUrl + urlPath);
+}
+
+export { getNotificationFromServerWithID, getNotificationwishFromServerWithID };
diff --git a/FrontendFolder/switch-room/src/services/OfferPageService.ts b/FrontendFolder/switch-room/src/services/OfferPageService.ts
index 618095a0a27b23b406e3e1d372c1f80cb3836a74..277f08368fd9ff2257608bf13e3625b966e3ee4f 100644
--- a/FrontendFolder/switch-room/src/services/OfferPageService.ts
+++ b/FrontendFolder/switch-room/src/services/OfferPageService.ts
@@ -11,8 +11,8 @@ const baseUrl = "offer";
  * Get offer with userID
  * @param userId the current user's id
  */
-export async function getUserOfferInfoFromServer(userId: number) {
-  return serverHttpService.Get(baseUrl + "/" + userId);
+export async function getUserOfferInfoFromServer() {
+  return serverHttpService.Get(baseUrl);
 }
 
 /**
@@ -38,14 +38,19 @@ export function updateOffer(offerForm: OfferFormModel) {
  * @param userId user's id
  * @param offerId form id
  */
-export function deleteOffer(userId: number) {
-  const urlPath = baseUrl + "/deleteOffer/" + userId;
+export function deleteOffer(userId : number) {
+  const urlPath = baseUrl + "/deleteOffer/"+userId;
   return serverHttpService.Delete(urlPath);
 }
 
+export function getWishlistMatchRequestInfoList(){
+  const urlPath = baseUrl + "/wishlistMatchRequestInfoList"
+  return serverHttpService.Get(urlPath);
+}
+
 /*
 Change logs:
 Date        |       Author          |   Description
 2022-10-20  |    Fangzheng Zhang    |    create class and init
-
+2022-11-03  |    Fangzheng Zhang    |    Remove user Id in parameter because cookie is ready
  */
diff --git a/FrontendFolder/switch-room/src/services/ServerHttpService.ts b/FrontendFolder/switch-room/src/services/ServerHttpService.ts
index ea93675e01d8d8767e377c938f54c0e8396075dc..14c4c3f247daf8efcbf8b4d295f94a967e75f428 100644
--- a/FrontendFolder/switch-room/src/services/ServerHttpService.ts
+++ b/FrontendFolder/switch-room/src/services/ServerHttpService.ts
@@ -11,6 +11,7 @@ function Get(path: string) {
 
   return fetch(url, {
     method: "GET",
+    credentials: "include",
   })
     .then((response) => {
       if (response.ok) {
@@ -31,6 +32,7 @@ function Post(path: string, bodyData: any) {
   console.log("With Data: ", JSON.stringify(bodyData));
   return fetch(url, {
     method: "POST",
+    credentials: "include",
     headers: {
       "Content-Type": "application/json",
     },
diff --git a/FrontendFolder/switch-room/src/services/UserService.ts b/FrontendFolder/switch-room/src/services/UserService.ts
index b3a43ab224a34cba0194e2da6efc3844f4a6b8c6..77fed4b449d1a2805195905150257e14c38d5664 100644
--- a/FrontendFolder/switch-room/src/services/UserService.ts
+++ b/FrontendFolder/switch-room/src/services/UserService.ts
@@ -11,5 +11,23 @@ function loginUser(userData: any) {
   // console.log(Server_URL + baseUrl + urlPath);
   return serverHttpService.Post(baseUrl + urlPath, JSON.parse(userData));
 }
+function checkLoginSession() {
+  const urlPath = "/checkLoginSession";
+  return serverHttpService.Get(baseUrl + urlPath);
+}
+function resetPassword(userData: any) {
+  const urlPath = "/resetPassword";
+  return serverHttpService.Post(baseUrl + urlPath, JSON.parse(userData));
+}
+function getProfile() {
+  const urlPath = "/profile";
+  return serverHttpService.Get(baseUrl + urlPath);
+}
 
-export { postUserDataToServer, loginUser };
+export { 
+  postUserDataToServer,
+  loginUser,
+  checkLoginSession,
+  resetPassword,
+  getProfile
+};
diff --git a/FrontendFolder/switch-room/src/services/WishlistService.ts b/FrontendFolder/switch-room/src/services/WishlistService.ts
index 5d0451f0bb6e3779669be3567128d410e47822e0..9225343f09b617f86e87435d38ed315228368fc6 100644
--- a/FrontendFolder/switch-room/src/services/WishlistService.ts
+++ b/FrontendFolder/switch-room/src/services/WishlistService.ts
@@ -9,19 +9,17 @@ const baseUrl = "wishlist";
 
 /**
  * This function will fetch users wishlist item list
- * @param userId user's id
  */
-export function getUserWishlistInfo(userId: number) {
-  return serverHttpService.Get(baseUrl + "/" + userId);
+export function getUserWishlistInfo() {
+  return serverHttpService.Get(baseUrl);
 }
 
 /**
  * Send new wishlistItem information to server to create new record
- * @param userId user's id
  * @param wishlistItem  new wishlistItem
  */
-export function createNewWishlistItem( userId: number, wishlistItem: WishlistItemModel ) {
-  return serverHttpService.Post(baseUrl + "/newWishlistItem/"+userId, wishlistItem);
+export function createNewWishlistItem( wishlistItem: WishlistItemModel ) {
+  return serverHttpService.Post(baseUrl + "/newWishlistItem", wishlistItem);
 }
 
 /**
@@ -38,20 +36,31 @@ export function updateWishlistItem(wishlistItem: WishlistItemModel) {
  * @param userId user's id
  * @param wishlistItemId wishlist Item's Id
  */
-export function deleteWishlistItem(userId: number, wishlistItemId: number) {
+export function deleteWishlistItem(wishlistItemId: number) {
   const urlPath =
     baseUrl +
     "/deleteWishlistItem/" +
-    userId +
-    "?wishlistItemId=" +
     wishlistItemId;
   return serverHttpService.Delete(urlPath);
 }
 
+export function getOfferMatchList(wishlistItemId: number){
+  const urlPath = baseUrl + "/loadOfferMatchList/"+wishlistItemId;
+  return serverHttpService.Get(urlPath);
+}
+
+export function loadMatchOfferNumbersFor(wishlistItemList: Array<WishlistItemModel>){
+  let wishlistIdList : Array<number>= [];
+  wishlistItemList.forEach((wishlistItem) => {
+    wishlistIdList.push(wishlistItem.wishlistItemId);
+  })
+  const urlPath = baseUrl + "/loadOfferMatchCount";
+  return serverHttpService.Post(urlPath, wishlistIdList);
+}
 
 /*
 Change logs:
 Date        |       Author          |   Description
 2022-10-20  |    Fangzheng Zhang    |    create class and init
-
+2022-11-05  |    Fangzheng Zhang    |   Add loadMatchOfferNumbersFor and getOfferMatchList to fetch match data
  */
diff --git a/FrontendFolder/switch-room/src/store/flightdataStore.ts b/FrontendFolder/switch-room/src/store/flightdataStore.ts
new file mode 100644
index 0000000000000000000000000000000000000000..42b770f3ac34ec316bd5bf5e835f76f3a6eed54c
--- /dev/null
+++ b/FrontendFolder/switch-room/src/store/flightdataStore.ts
@@ -0,0 +1,23 @@
+import { defineStore } from "pinia";
+import { FlightResultModel } from "@/models/FlightResultModel";
+import { FlightFormModel } from "@/models/FlightFormModel";
+import * as FlightTicketService from "@/services/FlightTicketService";
+
+
+export const useTicketStore = defineStore("TicketStore", {
+    //state
+    //options
+    //getters
+    state: () => ({
+        ticketList: [] as FlightResultModel[],
+    }),
+    actions: {
+        async fetchResultTicket(flightModel: FlightFormModel) {
+            await FlightTicketService.createNewFlight(flightModel).then((response) => {
+
+                console.log("Save search flight data: ", response.data);
+                this.ticketList = response.data;
+            });
+        },
+    },
+});
\ No newline at end of file
diff --git a/FrontendFolder/switch-room/src/store/index.ts b/FrontendFolder/switch-room/src/store/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e9519f47c946b10f43ad9c938d1b765983166baa
--- /dev/null
+++ b/FrontendFolder/switch-room/src/store/index.ts
@@ -0,0 +1,10 @@
+import { createStore } from "vuex";
+import authModule from "./modules/auth";
+
+const store = createStore({
+  modules: {
+    auth: authModule,
+  },
+});
+
+export default store;
diff --git a/FrontendFolder/switch-room/src/store/modules/auth.ts b/FrontendFolder/switch-room/src/store/modules/auth.ts
new file mode 100644
index 0000000000000000000000000000000000000000..62609e6dc883ecdb0078891be57cdaf14fca98f6
--- /dev/null
+++ b/FrontendFolder/switch-room/src/store/modules/auth.ts
@@ -0,0 +1,43 @@
+import * as UserService from "../../services/UserService";
+
+const state = () => ({
+  loginStatus: false,
+});
+
+const getters = {
+  getLoginStatus(state: any) {
+    return state.loginStatus;
+  },
+};
+
+const actions = {
+  async loginApi({ commit }: any, payload: any) {
+    const response = await UserService.loginUser(JSON.stringify(payload)).catch(
+      (error) => alert(error)
+    );
+    if (response.status == "OK") {
+      commit("setLoginStatus", true);
+    } else {
+      alert(response.message);
+    }
+  },
+  logOutApi({ commit }: any) {
+    // todo: clear session in backend
+    console.log("logOut");
+    commit("setLoginStatus", false);
+  },
+};
+
+const mutations = {
+  setLoginStatus(state: any, data: any) {
+    state.loginStatus = data;
+  },
+};
+
+export default {
+  namespaced: true,
+  state,
+  getters,
+  actions,
+  mutations,
+};
diff --git a/FrontendFolder/switch-room/src/views/FlightTicket.vue b/FrontendFolder/switch-room/src/views/FlightTicket.vue
new file mode 100644
index 0000000000000000000000000000000000000000..8b86303df4ca6d2ba3674f7fd98900d2ba2486f2
--- /dev/null
+++ b/FrontendFolder/switch-room/src/views/FlightTicket.vue
@@ -0,0 +1,11 @@
+<template>
+<ticket-page></ticket-page>
+</template>
+
+<script setup lang="ts">
+import TicketPage from "@/components/TicketPage.vue";
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/FrontendFolder/switch-room/src/views/LoginMainPageView.vue b/FrontendFolder/switch-room/src/views/LoginMainPageView.vue
index 548ebc671b1c0edc7ee8441cd36ad0d32d103a87..1502ffb97752765dfd2b86edb25bd0e423552964 100644
--- a/FrontendFolder/switch-room/src/views/LoginMainPageView.vue
+++ b/FrontendFolder/switch-room/src/views/LoginMainPageView.vue
@@ -1,8 +1,40 @@
 <template>
-    <main-page></main-page>
+  <main-page></main-page>
 </template>
 
 <script setup lang="ts">
 import MainPage from "@/components/LoginMainPage.vue";
+import AppHeader from "@/components/AppHeader.vue";
+import { watch } from "vue";
+import { useRoute } from "vue-router";
+const route = useRoute();
+import { ref } from "vue";
+import { OfferNotification } from "@/models/OfferNotification";
+import * as NotificationService from "@/services/NotificationService";
+
+// function getCookie(userId: string) {
+//   const value = `; ${document.cookie}`;
+//   const parts: string[] = value.split(`; ${userId}=`);
+//   if (parts.length === 2) return parts?.pop()?.split(";").shift();
+// }
+//
+// const offers = ref([] as OfferNotification[]);
+// async function fetchNotification(userId: number) {
+//   const response = await NotificationService.getNotificationFromServerWithID(
+//     userId
+//   );
+//   console.log(response);
+//   offers.value = response.data;
+// }
+//
+// watch(
+//   () => route.name,
+//   (values) => {
+//     const userIdString: string = getCookie("userId");
+//     let userIdNumber = +userIdString;
+//     console.log(userIdNumber);
+//     fetchNotification(userIdNumber);
+//   },
+//   { immediate: true }
+// );
 </script>
-  
\ No newline at end of file
diff --git a/FrontendFolder/switch-room/src/views/MatchedView.vue b/FrontendFolder/switch-room/src/views/MatchedView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..641b85322d138e981295efb15fd422ca156c2742
--- /dev/null
+++ b/FrontendFolder/switch-room/src/views/MatchedView.vue
@@ -0,0 +1,159 @@
+<template>
+  <div class="match-view">
+    <p>This is the matched result page</p>
+    <match-offer :offer="offer"></match-offer>
+    <match-wish-list :wishlist="wishlist"></match-wish-list>
+    <button>Sign Agreement Documentation</button>
+    <button>It is not suitable</button>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, watch } from "vue";
+import { useRoute } from "vue-router";
+import * as FetchOfferService from "@/services/FetchOfferService";
+import * as FetchWishListService from "@/services/FetchWishListService";
+import { OfferFormModel } from "@/models/OfferFormModel";
+import { WishlistItemModel } from "@/models/WishlistItemModel";
+import MatchOffer from "@/components/MatchOffer.vue";
+import MatchWishList from "@/components/MatchWishList.vue";
+
+const route = useRoute();
+const offer = ref(OfferFormModel);
+const wishlist = ref(WishlistItemModel);
+
+async function fetchOffer(offerId: number) {
+  const response = await FetchOfferService.getOffersFromServerWithID(offerId);
+  console.log(response.data);
+  offer.value = response.data;
+}
+
+async function fetchWishList(wishlistId: number) {
+  const response = await FetchWishListService.getWishListFromServerWithID(
+    wishlistId
+  );
+  console.log(response.data);
+  wishlist.value = response.data;
+}
+
+watch(
+  () => route.name,
+  (values) => {
+    const offerIdName = route.params.offerId;
+    const offerIdNumber = +offerIdName;
+    const wishlistIdName = route.params.wishlistId;
+    const wishlistIdNumber = +wishlistIdName;
+    fetchOffer(offerIdNumber);
+    fetchWishList(wishlistIdNumber);
+  },
+  { immediate: true }
+);
+</script>
+
+<style scoped>
+.match-view {
+  display: block;
+  text-align: center;
+}
+
+.button1 {
+  margin-top: 2%;
+  margin-left: 2%;
+}
+
+button,
+button::after {
+  margin-top: 2%;
+  margin-left: 2%;
+  width: 300px;
+  height: 86px;
+  font-size: 36px;
+  font-family: "Bebas Neue", cursive;
+  background: #1e5be6;
+  border: 0;
+  color: #fff;
+  letter-spacing: 3px;
+  line-height: 88px;
+  box-shadow: 6px 0px 0px #00e6f6;
+  outline: transparent;
+  position: relative;
+}
+
+button::after {
+  --slice-0: inset(50% 50% 50% 50%);
+  --slice-1: inset(80% -6px 0 0);
+  --slice-2: inset(50% -6px 30% 0);
+  --slice-3: inset(10% -6px 85% 0);
+  --slice-4: inset(40% -6px 43% 0);
+  --slice-5: inset(80% -6px 5% 0);
+
+  content: "AVAILABLE NOW";
+  display: block;
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: linear-gradient(
+    45deg,
+    transparent 3%,
+    #00e6f6 3%,
+    #00e6f6 5%,
+    #ff013c 5%
+  );
+  text-shadow: -3px -3px 0px #f8f005, 3px 3px 0px #00e6f6;
+  clip-path: var(--slice-0);
+}
+
+button:hover::after {
+  animation: 1s glitch;
+  animation-timing-function: steps(2, end);
+}
+
+@keyframes glitch {
+  0% {
+    clip-path: var(--slice-1);
+    transform: translate(-20px, -10px);
+  }
+  10% {
+    clip-path: var(--slice-3);
+    transform: translate(10px, 10px);
+  }
+  20% {
+    clip-path: var(--slice-1);
+    transform: translate(-10px, 10px);
+  }
+  30% {
+    clip-path: var(--slice-3);
+    transform: translate(0px, 5px);
+  }
+  40% {
+    clip-path: var(--slice-2);
+    transform: translate(-5px, 0px);
+  }
+  50% {
+    clip-path: var(--slice-3);
+    transform: translate(5px, 0px);
+  }
+  60% {
+    clip-path: var(--slice-4);
+    transform: translate(5px, 10px);
+  }
+  70% {
+    clip-path: var(--slice-2);
+    transform: translate(-10px, 10px);
+  }
+  80% {
+    clip-path: var(--slice-5);
+    transform: translate(20px, -10px);
+  }
+  90% {
+    clip-path: var(--slice-1);
+    transform: translate(-10px, 0px);
+  }
+  100% {
+    clip-path: var(--slice-1);
+    transform: translate(0);
+  }
+}
+</style>
diff --git a/FrontendFolder/switch-room/src/views/ProfileView.vue b/FrontendFolder/switch-room/src/views/ProfileView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..fa0ed4652331ea5833f876defa5a7650e0c9963e
--- /dev/null
+++ b/FrontendFolder/switch-room/src/views/ProfileView.vue
@@ -0,0 +1,7 @@
+<template>
+  <Profile-Page></Profile-Page>
+</template>
+
+<script setup lang="ts">
+import ProfilePage from "@/components/ProfilePage.vue";
+</script>
diff --git a/FrontendFolder/switch-room/src/views/ResetPasswordView.vue b/FrontendFolder/switch-room/src/views/ResetPasswordView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..2c56067f177519c9de0ed9d42474b2d44caa5fbf
--- /dev/null
+++ b/FrontendFolder/switch-room/src/views/ResetPasswordView.vue
@@ -0,0 +1,7 @@
+<template>
+  <ResetPassword-Page></ResetPassword-Page>
+</template>
+
+<script setup lang="ts">
+import ResetPasswordPage from "@/components/ResetPasswordPage.vue";
+</script>
diff --git a/FrontendFolder/switch-room/tsconfig.json b/FrontendFolder/switch-room/tsconfig.json
index b9dc703cfd8386d7c8e1eb0eb5e55edef576b33e..ab6cca7ec0bcfc482ef06b7d6f68ac2a7754d3b7 100644
--- a/FrontendFolder/switch-room/tsconfig.json
+++ b/FrontendFolder/switch-room/tsconfig.json
@@ -33,8 +33,8 @@
     "src/**/*.tsx",
     "src/**/*.vue",
     "tests/**/*.ts",
-    "tests/**/*.tsx"
-  ],
+    "tests/**/*.tsx", 
+    "src/store/index.ts",],
   "exclude": [
     "node_modules"
   ]
diff --git a/flightapi.json b/flightapi.json
new file mode 100644
index 0000000000000000000000000000000000000000..a9fd7bd6585bc73b73cbb927d9f6adf2bab49a3a
--- /dev/null
+++ b/flightapi.json
@@ -0,0 +1,1047 @@
+{
+  "status": true,
+  "message": "Success",
+  "timestamp": 1667401694167,
+  "data": {
+    "session": {
+      "searchHash": "9974755e28e834b916b632b996600560",
+      "pageLoadUid": "93a5b4b8-d5ed-45a4-bef7-7a06d068bc4d",
+      "searchId": "af0e2d98-b24c-43ca-932f-bf4400898499.394"
+    },
+    "complete": false,
+    "numOfFilters": 10,
+    "totalNumResults": 10,
+    "flights": [
+      {
+        "segments": [
+          {
+            "legs": [
+              {
+                "originStationCode": "BOM",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "DEL",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-01T06:00:00+05:30",
+                "arrivalDateTime": "2022-12-01T08:05:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 954,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          },
+          {
+            "legs": [
+              {
+                "originStationCode": "DEL",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "BOM",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-09T21:55:00+05:30",
+                "arrivalDateTime": "2022-12-09T23:55:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 981,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          }
+        ],
+        "purchaseLinks": [
+          {
+            "purchaseLinkId": "Kayak|1|11",
+            "providerId": "Vistara",
+            "partnerSuppliedProvider": {
+              "id": "UK",
+              "displayName": "Vistara",
+              "logoUrl": "https://content.r9cdn.net/rimg/provider-logos/airlines/h/UK.png?crop=false&width=166&height=62&fallback=default2.png&_v=70673476ce3854369868788c913f25cc"
+            },
+            "commerceName": "KayakFlightsMeta",
+            "currency": "USD",
+            "originalCurrency": "USD",
+            "seatAvailability": 0,
+            "taxesAndFees": 0,
+            "taxesAndFeesPerPassenger": 0,
+            "totalPrice": 540.78,
+            "totalPricePerPassenger": 540.78,
+            "fareBasisCodes": [],
+            "containedPurchaseLinks": [],
+            "partnerData": {},
+            "isPaid": false,
+            "fareAttributesList": [],
+            "url": "https://www.tripadvisor.com/CheapFlightsPartnerHandoff?searchHash=9974755e28e834b916b632b996600560&provider=Kayak|1|11&area=FLTCenterColumn|0|1|ItinList|1|Meta_ItineraryPrice&resultsServlet=CheapFlightsSearchResults&handoffPlatform=desktop&impressionId=&totalPricePerPassenger=540.78"
+          }
+        ]
+      },
+      {
+        "segments": [
+          {
+            "legs": [
+              {
+                "originStationCode": "BOM",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "DEL",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-01T06:30:00+05:30",
+                "arrivalDateTime": "2022-12-01T08:35:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 928,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          },
+          {
+            "legs": [
+              {
+                "originStationCode": "DEL",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "BOM",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-09T21:55:00+05:30",
+                "arrivalDateTime": "2022-12-09T23:55:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 981,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          }
+        ],
+        "purchaseLinks": [
+          {
+            "purchaseLinkId": "Kayak|1|8",
+            "providerId": "Vistara",
+            "partnerSuppliedProvider": {
+              "id": "UK",
+              "displayName": "Vistara",
+              "logoUrl": "https://content.r9cdn.net/rimg/provider-logos/airlines/h/UK.png?crop=false&width=166&height=62&fallback=default2.png&_v=70673476ce3854369868788c913f25cc"
+            },
+            "commerceName": "KayakFlightsMeta",
+            "currency": "USD",
+            "originalCurrency": "USD",
+            "seatAvailability": 0,
+            "taxesAndFees": 0,
+            "taxesAndFeesPerPassenger": 0,
+            "totalPrice": 540.78,
+            "totalPricePerPassenger": 540.78,
+            "fareBasisCodes": [],
+            "containedPurchaseLinks": [],
+            "partnerData": {},
+            "isPaid": false,
+            "fareAttributesList": [],
+            "url": "https://www.tripadvisor.com/CheapFlightsPartnerHandoff?searchHash=9974755e28e834b916b632b996600560&provider=Kayak|1|8&area=FLTCenterColumn|0|1|ItinList|2|Meta_ItineraryPrice&resultsServlet=CheapFlightsSearchResults&handoffPlatform=desktop&impressionId=&totalPricePerPassenger=540.78"
+          }
+        ]
+      },
+      {
+        "segments": [
+          {
+            "legs": [
+              {
+                "originStationCode": "BOM",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "DEL",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-01T06:00:00+05:30",
+                "arrivalDateTime": "2022-12-01T08:05:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 954,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          },
+          {
+            "legs": [
+              {
+                "originStationCode": "DEL",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "BOM",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-09T09:30:00+05:30",
+                "arrivalDateTime": "2022-12-09T11:35:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 927,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          }
+        ],
+        "purchaseLinks": [
+          {
+            "purchaseLinkId": "Kayak|1|5",
+            "providerId": "Vistara",
+            "partnerSuppliedProvider": {
+              "id": "UK",
+              "displayName": "Vistara",
+              "logoUrl": "https://content.r9cdn.net/rimg/provider-logos/airlines/h/UK.png?crop=false&width=166&height=62&fallback=default2.png&_v=70673476ce3854369868788c913f25cc"
+            },
+            "commerceName": "KayakFlightsMeta",
+            "currency": "USD",
+            "originalCurrency": "USD",
+            "seatAvailability": 0,
+            "taxesAndFees": 0,
+            "taxesAndFeesPerPassenger": 0,
+            "totalPrice": 540.78,
+            "totalPricePerPassenger": 540.78,
+            "fareBasisCodes": [],
+            "containedPurchaseLinks": [],
+            "partnerData": {},
+            "isPaid": false,
+            "fareAttributesList": [],
+            "url": "https://www.tripadvisor.com/CheapFlightsPartnerHandoff?searchHash=9974755e28e834b916b632b996600560&provider=Kayak|1|5&area=FLTCenterColumn|0|1|ItinList|3|Meta_ItineraryPrice&resultsServlet=CheapFlightsSearchResults&handoffPlatform=desktop&impressionId=&totalPricePerPassenger=540.78"
+          }
+        ]
+      },
+      {
+        "segments": [
+          {
+            "legs": [
+              {
+                "originStationCode": "BOM",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "DEL",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-01T06:30:00+05:30",
+                "arrivalDateTime": "2022-12-01T08:35:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 928,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          },
+          {
+            "legs": [
+              {
+                "originStationCode": "DEL",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "BOM",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-09T09:30:00+05:30",
+                "arrivalDateTime": "2022-12-09T11:35:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 927,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          }
+        ],
+        "purchaseLinks": [
+          {
+            "purchaseLinkId": "Kayak|1|6",
+            "providerId": "Vistara",
+            "partnerSuppliedProvider": {
+              "id": "UK",
+              "displayName": "Vistara",
+              "logoUrl": "https://content.r9cdn.net/rimg/provider-logos/airlines/h/UK.png?crop=false&width=166&height=62&fallback=default2.png&_v=70673476ce3854369868788c913f25cc"
+            },
+            "commerceName": "KayakFlightsMeta",
+            "currency": "USD",
+            "originalCurrency": "USD",
+            "seatAvailability": 0,
+            "taxesAndFees": 0,
+            "taxesAndFeesPerPassenger": 0,
+            "totalPrice": 540.78,
+            "totalPricePerPassenger": 540.78,
+            "fareBasisCodes": [],
+            "containedPurchaseLinks": [],
+            "partnerData": {},
+            "isPaid": false,
+            "fareAttributesList": [],
+            "url": "https://www.tripadvisor.com/CheapFlightsPartnerHandoff?searchHash=9974755e28e834b916b632b996600560&provider=Kayak|1|6&area=FLTCenterColumn|0|1|ItinList|4|Meta_ItineraryPrice&resultsServlet=CheapFlightsSearchResults&handoffPlatform=desktop&impressionId=&totalPricePerPassenger=540.78"
+          }
+        ]
+      },
+      {
+        "segments": [
+          {
+            "legs": [
+              {
+                "originStationCode": "BOM",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "DEL",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-01T07:30:00+05:30",
+                "arrivalDateTime": "2022-12-01T09:40:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 930,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          },
+          {
+            "legs": [
+              {
+                "originStationCode": "DEL",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "BOM",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-09T21:55:00+05:30",
+                "arrivalDateTime": "2022-12-09T23:55:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 981,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          }
+        ],
+        "purchaseLinks": [
+          {
+            "purchaseLinkId": "Kayak|1|9",
+            "providerId": "Vistara",
+            "partnerSuppliedProvider": {
+              "id": "UK",
+              "displayName": "Vistara",
+              "logoUrl": "https://content.r9cdn.net/rimg/provider-logos/airlines/h/UK.png?crop=false&width=166&height=62&fallback=default2.png&_v=70673476ce3854369868788c913f25cc"
+            },
+            "commerceName": "KayakFlightsMeta",
+            "currency": "USD",
+            "originalCurrency": "USD",
+            "seatAvailability": 0,
+            "taxesAndFees": 0,
+            "taxesAndFeesPerPassenger": 0,
+            "totalPrice": 540.78,
+            "totalPricePerPassenger": 540.78,
+            "fareBasisCodes": [],
+            "containedPurchaseLinks": [],
+            "partnerData": {},
+            "isPaid": false,
+            "fareAttributesList": [],
+            "url": "https://www.tripadvisor.com/CheapFlightsPartnerHandoff?searchHash=9974755e28e834b916b632b996600560&provider=Kayak|1|9&area=FLTCenterColumn|0|1|ItinList|5|Meta_ItineraryPrice&resultsServlet=CheapFlightsSearchResults&handoffPlatform=desktop&impressionId=&totalPricePerPassenger=540.78"
+          }
+        ]
+      },
+      {
+        "segments": [
+          {
+            "legs": [
+              {
+                "originStationCode": "BOM",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "DEL",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-01T17:35:00+05:30",
+                "arrivalDateTime": "2022-12-01T19:45:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Boeing 737-800 (winglets)",
+                "amenities": [],
+                "flightNumber": 910,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          },
+          {
+            "legs": [
+              {
+                "originStationCode": "DEL",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "BOM",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-09T21:55:00+05:30",
+                "arrivalDateTime": "2022-12-09T23:55:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 981,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          }
+        ],
+        "purchaseLinks": [
+          {
+            "purchaseLinkId": "Kayak|1|1",
+            "providerId": "Vistara",
+            "partnerSuppliedProvider": {
+              "id": "UK",
+              "displayName": "Vistara",
+              "logoUrl": "https://content.r9cdn.net/rimg/provider-logos/airlines/h/UK.png?crop=false&width=166&height=62&fallback=default2.png&_v=70673476ce3854369868788c913f25cc"
+            },
+            "commerceName": "KayakFlightsMeta",
+            "currency": "USD",
+            "originalCurrency": "USD",
+            "seatAvailability": 0,
+            "taxesAndFees": 0,
+            "taxesAndFeesPerPassenger": 0,
+            "totalPrice": 540.78,
+            "totalPricePerPassenger": 540.78,
+            "fareBasisCodes": [],
+            "containedPurchaseLinks": [],
+            "partnerData": {},
+            "isPaid": false,
+            "fareAttributesList": [],
+            "url": "https://www.tripadvisor.com/CheapFlightsPartnerHandoff?searchHash=9974755e28e834b916b632b996600560&provider=Kayak|1|1&area=FLTCenterColumn|0|1|ItinList|6|Meta_ItineraryPrice&resultsServlet=CheapFlightsSearchResults&handoffPlatform=desktop&impressionId=&totalPricePerPassenger=540.78"
+          }
+        ]
+      },
+      {
+        "segments": [
+          {
+            "legs": [
+              {
+                "originStationCode": "BOM",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "DEL",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-01T22:45:00+05:30",
+                "arrivalDateTime": "2022-12-02T00:55:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 986,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          },
+          {
+            "legs": [
+              {
+                "originStationCode": "DEL",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "BOM",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-09T21:55:00+05:30",
+                "arrivalDateTime": "2022-12-09T23:55:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 981,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          }
+        ],
+        "purchaseLinks": [
+          {
+            "purchaseLinkId": "Kayak|1|4",
+            "providerId": "Vistara",
+            "partnerSuppliedProvider": {
+              "id": "UK",
+              "displayName": "Vistara",
+              "logoUrl": "https://content.r9cdn.net/rimg/provider-logos/airlines/h/UK.png?crop=false&width=166&height=62&fallback=default2.png&_v=70673476ce3854369868788c913f25cc"
+            },
+            "commerceName": "KayakFlightsMeta",
+            "currency": "USD",
+            "originalCurrency": "USD",
+            "seatAvailability": 0,
+            "taxesAndFees": 0,
+            "taxesAndFeesPerPassenger": 0,
+            "totalPrice": 540.78,
+            "totalPricePerPassenger": 540.78,
+            "fareBasisCodes": [],
+            "containedPurchaseLinks": [],
+            "partnerData": {},
+            "isPaid": false,
+            "fareAttributesList": [],
+            "url": "https://www.tripadvisor.com/CheapFlightsPartnerHandoff?searchHash=9974755e28e834b916b632b996600560&provider=Kayak|1|4&area=FLTCenterColumn|0|1|ItinList|7|Meta_ItineraryPrice&resultsServlet=CheapFlightsSearchResults&handoffPlatform=desktop&impressionId=&totalPricePerPassenger=540.78"
+          }
+        ]
+      },
+      {
+        "segments": [
+          {
+            "legs": [
+              {
+                "originStationCode": "BOM",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "DEL",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-01T07:30:00+05:30",
+                "arrivalDateTime": "2022-12-01T09:40:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 930,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          },
+          {
+            "legs": [
+              {
+                "originStationCode": "DEL",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "BOM",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-09T09:30:00+05:30",
+                "arrivalDateTime": "2022-12-09T11:35:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 927,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          }
+        ],
+        "purchaseLinks": [
+          {
+            "purchaseLinkId": "Kayak|1|7",
+            "providerId": "Vistara",
+            "partnerSuppliedProvider": {
+              "id": "UK",
+              "displayName": "Vistara",
+              "logoUrl": "https://content.r9cdn.net/rimg/provider-logos/airlines/h/UK.png?crop=false&width=166&height=62&fallback=default2.png&_v=70673476ce3854369868788c913f25cc"
+            },
+            "commerceName": "KayakFlightsMeta",
+            "currency": "USD",
+            "originalCurrency": "USD",
+            "seatAvailability": 0,
+            "taxesAndFees": 0,
+            "taxesAndFeesPerPassenger": 0,
+            "totalPrice": 540.78,
+            "totalPricePerPassenger": 540.78,
+            "fareBasisCodes": [],
+            "containedPurchaseLinks": [],
+            "partnerData": {},
+            "isPaid": false,
+            "fareAttributesList": [],
+            "url": "https://www.tripadvisor.com/CheapFlightsPartnerHandoff?searchHash=9974755e28e834b916b632b996600560&provider=Kayak|1|7&area=FLTCenterColumn|0|1|ItinList|8|Meta_ItineraryPrice&resultsServlet=CheapFlightsSearchResults&handoffPlatform=desktop&impressionId=&totalPricePerPassenger=540.78"
+          }
+        ]
+      },
+      {
+        "segments": [
+          {
+            "legs": [
+              {
+                "originStationCode": "BOM",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "DEL",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-01T17:35:00+05:30",
+                "arrivalDateTime": "2022-12-01T19:45:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Boeing 737-800 (winglets)",
+                "amenities": [],
+                "flightNumber": 910,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          },
+          {
+            "legs": [
+              {
+                "originStationCode": "DEL",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "BOM",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-09T09:30:00+05:30",
+                "arrivalDateTime": "2022-12-09T11:35:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 927,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          }
+        ],
+        "purchaseLinks": [
+          {
+            "purchaseLinkId": "Kayak|1|2",
+            "providerId": "Vistara",
+            "partnerSuppliedProvider": {
+              "id": "UK",
+              "displayName": "Vistara",
+              "logoUrl": "https://content.r9cdn.net/rimg/provider-logos/airlines/h/UK.png?crop=false&width=166&height=62&fallback=default2.png&_v=70673476ce3854369868788c913f25cc"
+            },
+            "commerceName": "KayakFlightsMeta",
+            "currency": "USD",
+            "originalCurrency": "USD",
+            "seatAvailability": 0,
+            "taxesAndFees": 0,
+            "taxesAndFeesPerPassenger": 0,
+            "totalPrice": 540.78,
+            "totalPricePerPassenger": 540.78,
+            "fareBasisCodes": [],
+            "containedPurchaseLinks": [],
+            "partnerData": {},
+            "isPaid": false,
+            "fareAttributesList": [],
+            "url": "https://www.tripadvisor.com/CheapFlightsPartnerHandoff?searchHash=9974755e28e834b916b632b996600560&provider=Kayak|1|2&area=FLTCenterColumn|0|1|ItinList|9|Meta_ItineraryPrice&resultsServlet=CheapFlightsSearchResults&handoffPlatform=desktop&impressionId=&totalPricePerPassenger=540.78"
+          }
+        ]
+      },
+      {
+        "segments": [
+          {
+            "legs": [
+              {
+                "originStationCode": "BOM",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "DEL",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-01T14:40:00+05:30",
+                "arrivalDateTime": "2022-12-01T16:55:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 944,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          },
+          {
+            "legs": [
+              {
+                "originStationCode": "DEL",
+                "isDifferentOriginStation": false,
+                "destinationStationCode": "BOM",
+                "isDifferentDestinationStation": false,
+                "departureDateTime": "2022-12-09T09:30:00+05:30",
+                "arrivalDateTime": "2022-12-09T11:35:00+05:30",
+                "classOfService": "ECONOMY",
+                "marketingCarrierCode": "UK",
+                "operatingCarrierCode": "UK",
+                "equipmentId": "Airbus A320-100/200",
+                "amenities": [],
+                "flightNumber": 927,
+                "seatGuruEquipmentId": 0,
+                "seatGuruAirlineUrl": "",
+                "numStops": 0,
+                "distanceInKM": 1138.1091,
+                "isInternational": false,
+                "selfTransfer": false,
+                "operatingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                },
+                "marketingCarrier": {
+                  "locationId": 8729207,
+                  "code": "UK",
+                  "logoUrl": "https://static.tacdn.com/img2/flights/airlines/logos/100x100/Vistara.png",
+                  "displayName": "Vistara"
+                }
+              }
+            ],
+            "layovers": []
+          }
+        ],
+        "purchaseLinks": [
+          {
+            "purchaseLinkId": "Kayak|1|3",
+            "providerId": "Vistara",
+            "partnerSuppliedProvider": {
+              "id": "UK",
+              "displayName": "Vistara",
+              "logoUrl": "https://content.r9cdn.net/rimg/provider-logos/airlines/h/UK.png?crop=false&width=166&height=62&fallback=default2.png&_v=70673476ce3854369868788c913f25cc"
+            },
+            "commerceName": "KayakFlightsMeta",
+            "currency": "USD",
+            "originalCurrency": "USD",
+            "seatAvailability": 0,
+            "taxesAndFees": 0,
+            "taxesAndFeesPerPassenger": 0,
+            "totalPrice": 540.78,
+            "totalPricePerPassenger": 540.78,
+            "fareBasisCodes": [],
+            "containedPurchaseLinks": [],
+            "partnerData": {},
+            "isPaid": false,
+            "fareAttributesList": [],
+            "url": "https://www.tripadvisor.com/CheapFlightsPartnerHandoff?searchHash=9974755e28e834b916b632b996600560&provider=Kayak|1|3&area=FLTCenterColumn|0|1|ItinList|10|Meta_ItineraryPrice&resultsServlet=CheapFlightsSearchResults&handoffPlatform=desktop&impressionId=&totalPricePerPassenger=540.78"
+          }
+        ]
+      }
+    ]
+  }
+}
\ No newline at end of file