summaryrefslogtreecommitdiff
path: root/frontend/src/pages/Dashboard.tsx
blob: 6b43bf8faf87f3859c7e74427a8a1c0d30db3e2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { FadeLoader } from "react-spinners";
import { io } from "socket.io-client";
import CityMap from "../components/CityMap";
import Header from "../components/Header";
import API_URL from "../config";
import "../styles/dashboard.css";
import type { ErrorResponse } from "../types/error";
import type { AuthorizedUser } from "../types/login";
import type { Robot, RobotsResponse } from "../types/robot";

function Dashboard() {
    const [isLoading, setIsLoading] = useState<boolean>(true);
    const [robots, setRobots] = useState<Robot[]>([]);

    const navigate = useNavigate();

    const userString = localStorage.getItem("user");
    const user: AuthorizedUser = userString ? JSON.parse(userString) : null;
    const token = localStorage.getItem("token-robot-tracker");

    async function handleLogout() {
        localStorage.removeItem("token-robot-tracker");
        localStorage.removeItem("user");
        navigate("/login", { replace: true });
    }

    useEffect(() => {
	// Additional safety check to protect this page from unauthorized access
        if (!token || token === "undefined" || token === "null") {
            navigate("/login");
            return;
        }

        // Request robot data from backend
        async function fetchRobots() {
            try {
                setIsLoading(true);

                const response = await fetch(`${API_URL}/robots`, {
                    method: "GET",
                    headers: {
                        Authorization: `Bearer ${token}`,
                        "Content-Type": "application/json",
                    },
                });

                if (!response.ok) {
                    const errorData: ErrorResponse = await response.json();
                    throw new Error(
                        errorData.message ||
                            `Failed to load the robots: ${response.status}`
                    );
                }

                const data: RobotsResponse = await response.json();
                setRobots(data.data);
            } catch (error) {
                console.error("Failed to load the robots:", error);
            } finally {
                setIsLoading(false);
            }
        }

        fetchRobots();

        // Establish WebSocket connection to backend
        const socket = io(API_URL);

        // Listen for real-time robot updates
        socket.on("robots_update", (updatedRobots) => {
            setRobots(updatedRobots);
        });

        // Cleanup when component unmounts
        return () => {
            socket.disconnect();
        };
    }, [token, navigate]);

    return isLoading ? (
        <FadeLoader />
    ) : (
        <div className="dashboard-page">
            <CityMap robots={robots} />
            <Header user={user} logout={handleLogout} />
        </div>
    );
}

export default Dashboard;