미소를뿌리는감자의 코딩

[CatchLounge] countdown 적용 본문

프로젝트

[CatchLounge] countdown 적용

미뿌감 2024. 9. 5. 12:05
728x90

1. 개요

이번 프로젝트에서는 자리를 예약하는 것을 구현하게 되었다.

이에 특정 위치에 마우스 커서를 올리면, 남은 시간을 나타내도록 하는 기능이 필요했는데, 이를 구현해 보았다.

 

 

위 사진과 같이 사용자와, 남은 시간을 나타내 준다.

 

먼저 client측 코드를 확인해 보자.

        $(document).ready(function () {
            showLeftime();
        });

 

document가 준비가 되면, 바로 showLefttime()이라는 함수를 실행되도록 하였다.

 

        function showLeftime() {
            $(".button").on("mouseenter", function (event) {
                const button = this;
                timeCall(button);

                $("#time-display").css({
                    left: event.pageX + 15 + "px",
                    top: event.pageY + 15 + "px",
                    display: "block",
                });
            });

            $(".button").on("mousemove", function (event) {
                $("#time-display").css({
                    left: event.pageX + 15 + "px",
                    top: event.pageY + 15 + "px",
                });
            });

            $(".button").on("mouseleave", function () {
                clearInterval(intervalId);
                $("#time-display").hide();
            });
        }

 

좌석 (버튼) 에 마우스가 올라가게 되면, timeCall이라는 함수를 실행시키도록 하였다.

 

        function timeCall(button) {
            const tableNum = $(button).data("table-num");
            $.ajax({
                type: "GET",
                url: "/time",
                data: { tableNum: tableNum },
                success: function (response) {
                    if (response.result === "success" && (response.time[0] > 0 || response.time[1] > 0)) {
                        let minutes = response.time[0];
                        let seconds = response.time[1];
                        let username = response.user;
                        console.log(`${minutes}분 ${seconds}초`);

                        $("#time-display").text(`${username}, ${minutes}분 ${seconds}초`);
                        $(button).removeClass("bg-gray-500").addClass("bg-red-500");

                        if (typeof intervalId !== "undefined") {
                            clearInterval(intervalId);
                        }

                        intervalId = setInterval(function () {
                            if (seconds === 0) {
                                if (minutes > 0) {
                                    minutes--;
                                    seconds = 59;
                                } else {
                                    clearInterval(intervalId);
                                    console.log("Time is up!");
                                    window.location.reload();
                                    return;
                                }
                            } else {
                                seconds--;
                            }
                            $("#time-display").text(`${username}, ${minutes}분 ${seconds}초`);
                        }, 1000);
                    } else {
                        $("#time-display").text("");
                        if (typeof intervalId !== "undefined") {
                            clearInterval(intervalId);
                        }
                        console.log("No time left or invalid data");
                    }
                },
                error: function () {
                    $("#time-display").text("");
                    if (typeof intervalId !== "undefined") {
                        clearInterval(intervalId);
                    }
                    console.log("Error retrieving time data");
                },
            });
        }

인자로 받아온 button에서 table-num을 가져와 준 후, /time API에 GET 요청을 보내주었다.

 

/time API 코드를 확인하기 전에, 시간 저장을 어떻게 해두었는 지 확인해 보자.

현재 시간에서, 현재 UTC + 15초를 추가해서 column에 저장해 주었다.

time = datetime.now() + timedelta(seconds=15)
    tableNum = int(tableNum_receive)
    collection_table.update_one(
        {"tableNum": int(tableNum_receive)},
        {
            "$set": {
                "occupied": True,
                "user_name": current_user["username"],
                "time": time,
            }
        },
    )

 

/time API 코드는 아래와 같다.

@app.route("/time", methods=["GET"])
def timeRecall():
    tableNum = request.args.get("tableNum")
    if tableNum is None:
        return jsonify({"result": "fail", "message": "tableNum is missing"}), 400
    table = collection_table.find_one({"tableNum": int(tableNum)})
    savedTime = table.get("time")
    user = table.get("user_name")

    if savedTime is None:
        return jsonify({"result": "failure", "message": "no time saved"})

    currentTime = datetime.now()
    timeDifference = savedTime - currentTime
    total_seconds = int(timeDifference.total_seconds())

    if total_seconds < 0:
        return jsonify({"result": "failure", "message": "no time saved"})

    minutes = total_seconds // 60
    seconds = total_seconds % 60

    return jsonify({"result": "success", "time": [minutes, seconds], "user": user})

 

마우스가 버튼 위가 아닌, 여백에 있어도, 해당 함수가 호출될 것이기 때문에, 

tableNum이 None으로 넘어오는 경우가 있을 것이다. 

따라서, 이에 대한 예외 처리를 진행해 주었다. table collection에는 해당 예약이 실행된 시간 + 15초가 db에 기록되어 있는 상태이다.

따라서 savedTime으로 이를 가져와 주고, 현재 시간을 datetime 모듈을 이용해서 알아내 준 후, 남은 시간을 json으로 반환해 주었다.

다시 client 측으로 넘어가서, 

                    if (response.result === "success" && (response.time[0] > 0 || response.time[1] > 0)) {
                        let minutes = response.time[0];
                        let seconds = response.time[1];
                        let username = response.user;
                        console.log(`${minutes}분 ${seconds}초`);

                        $("#time-display").text(`${username}, ${minutes}분 ${seconds}초`);
                        $(button).removeClass("bg-gray-500").addClass("bg-red-500");

                        if (typeof intervalId !== "undefined") {
                            clearInterval(intervalId);
                        }

                        intervalId = setInterval(function () {
                            if (seconds === 0) {
                                if (minutes > 0) {
                                    minutes--;
                                    seconds = 59;
                                } else {
                                    clearInterval(intervalId);
                                    console.log("Time is up!");
                                    window.location.reload();
                                    return;
                                }
                            } else {
                                seconds--;
                            }
                            $("#time-display").text(`${username}, ${minutes}분 ${seconds}초`);
                        }, 1000);

 

응답 결과가 success라면, 응답으로 받아온 분과 초를 가져와 주고, 이를 마우스 옆에 display 해주었다.

이후, javascript 내장 함수 interval을 이용해 주었다.

 

기존에 정의되어 있던 interval이 있다면 clear해주었다. (이전 타이머 삭제하는 과정)

 

그리고, Interval을 설정해 주었다.

따라서 1000 즉, 1초마다 setInterval 안에 있는 function을 실행시켜 준다.

여기서, intervalId에는 setInterval 함수가 실행될 때 반환되는 타이머 ID가 담기게 된다.

 

이를 통해 실행 중인 이전 타이머가 있는 지 확인할 수 있다.

 

            $(".button").on("mousemove", function (event) {
                $("#time-display").css({
                    left: event.pageX + 15 + "px",
                    top: event.pageY + 15 + "px",
                });
            });

            $(".button").on("mouseleave", function () {
                clearInterval(intervalId);
                $("#time-display").hide();
            });

마우스가 움직일 때도 커서 옆에 시간 초를 띄워주고, 

mouseleave 즉, 버튼에서 마우스가 떠날 때는 interval을 멈추고, 커서 옆에 나올 time-display도 숨겨주었다.

728x90