Ignore:
Timestamp:
01/21/26 13:35:44 (6 months ago)
Author:
istevanoska <ilinastevanoska@…>
Branches:
master
Children:
d42aac3
Parents:
2058e5c
Message:

Added OAuth/prototype

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lan-frontend/src/App.jsx

    r2058e5c r505f39a  
    1 import React from "react";
    2 import {useEffect, useMemo, useState} from "react";
     1import React, {useEffect, useMemo, useState} from "react";
    32import "./styles/theme.css";
    43
     4import Login from "./components/Login";
    55import TopBar from "./components/TopBar";
    66import ComputerCard from "./components/ComputerCard";
     
    2222    const [selectedEnv, setSelectedEnv] = useState("default");
    2323
     24    const [me, setMe] = useState(null);
     25    const [meLoading, setMeLoading] = useState(true);
     26
     27    // const [openAI, setOpenAI] = useState(false);
     28    // const [scope, setScope] = useState(null);
     29
     30
     31    async function loadMe() {
     32        setMeLoading(true);
     33        try {
     34            const r = await fetch("/api/me", {credentials: "include"});
     35            if (r.ok) {
     36                const data = await r.json();
     37                setMe(data.user);
     38            } else {
     39                setMe(null);
     40            }
     41        } catch (e) {
     42            console.error("loadMe error", e);
     43            setMe(null);
     44        } finally {
     45            setMeLoading(false);
     46        }
     47    }
     48
    2449    async function refresh() {
    2550        try {
    2651            setLoading(true);
    2752            const [s, c] = await Promise.all([
    28                 fetch("/api/stats").then((r) => r.json()),
     53                fetch("/api/stats", {credentials: "include"}).then((r) => r.json()),
    2954                fetch("/api/computers", {
     55                    credentials: "include",
    3056                    headers: {"X-Env": selectedEnv},
    3157                }).then((r) => r.json()),
    3258            ]);
     59
    3360            setStats(s);
    3461            setComputers(Array.isArray(c) ? c : []);
     
    4168    }
    4269
     70    // on mount: check session
    4371    useEffect(() => {
    44         refresh();
    45     }, [selectedEnv]);
     72        loadMe();
     73    }, []);
     74
     75    // when logged in OR env changed, refresh data
     76    useEffect(() => {
     77        if (me) refresh();
     78        // eslint-disable-next-line react-hooks/exhaustive-deps
     79    }, [me, selectedEnv]);
    4680
    4781    const filtered = useMemo(() => {
     
    5185            .filter((c) => {
    5286                if (!q) return true;
    53                 const hay = [c.name, c.user, c.ip, c.os, c.status].filter(Boolean).join(" ").toLowerCase();
     87                const hay = [c.name, c.user, c.ip, c.os, c.status]
     88                    .filter(Boolean)
     89                    .join(" ")
     90                    .toLowerCase();
    5491                return hay.includes(q);
    5592            });
    5693    }, [computers, query, status]);
     94
     95    // Gate UI
     96    if (meLoading) return <div style={{padding: 20}}>Loading…</div>;
     97    if (!me) return <Login onDone={loadMe}/>;
    5798
    5899    return (
     
    64105                onEnvChange={(env) => setSelectedEnv(env)}
    65106                selectedEnv={selectedEnv}
     107                me={me}
     108                onLoggedOut={loadMe}
    66109            />
     110
    67111
    68112            {/* STATS */}
     
    104148                        />
    105149
    106                         <select className="select" value={status} onChange={(e) => setStatus(e.target.value)}>
     150                        <select
     151                            className="select"
     152                            value={status}
     153                            onChange={(e) => setStatus(e.target.value)}
     154                        >
    107155                            <option value="">All status</option>
    108156                            <option value="online">Online</option>
     
    111159                        </select>
    112160
    113                         <button className="btn primary" onClick={refresh}>Refresh</button>
     161                        <button className="btn primary" onClick={refresh}>
     162                            Refresh
     163                        </button>
    114164                    </div>
    115165                </div>
     
    122172                    <div style={{display: "flex", gap: 10, alignItems: "center"}}>
    123173                        <span className="pill">{filtered.length} computers</span>
    124                         <button className="btn" onClick={() => {
    125                             setQuery("");
    126                             setStatus("");
    127                         }}>Reset
     174                        <button
     175                            className="btn"
     176                            onClick={() => {
     177                                setQuery("");
     178                                setStatus("");
     179                            }}
     180                        >
     181                            Reset
    128182                        </button>
    129183                    </div>
     
    142196                        ))}
    143197                        {filtered.length === 0 && (
    144                             <div style={{color: "var(--dim)"}}>No computers match filter.</div>
     198                            <div style={{color: "var(--dim)"}}>
     199                                No computers match filter.
     200                            </div>
    145201                        )}
    146202                    </div>
     
    160216
    161217            {/* AI DRAWER */}
     218            {/*<button onClick={() => setOpenAI(true)}>AI</button>*/}
     219
     220            {/*<AIAssistantDrawer*/}
     221            {/*    open={openAI}*/}
     222            {/*    onClose={() => setOpenAI(false)}*/}
     223            {/*    computers={computers}*/}
     224            {/*    scope={scope}*/}
     225            {/*    setScope={setScope}*/}
     226            {/*    apiBase={import.meta.env.VITE_API_BASE}*/}
     227            {/*/>*/}
     228
    162229            <AIAssistantDrawer
    163230                open={aiOpen}
     
    166233                scope={aiScope}
    167234                setScope={setAiScope}
     235                apiBase={import.meta.env.VITE_API_BASE}
    168236            />
     237
     238
    169239        </div>
    170240    );
Note: See TracChangeset for help on using the changeset viewer.