diff --git a/src/App.jsx b/src/App.jsx index 1a2bca7..89736f7 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -3,9 +3,12 @@ import reactLogo from './assets/react.svg' import viteLogo from '/vite.svg' import './App.css' +import { API_BASE } from './config.js' + import Login from './components/login.jsx' import MainApp from './components/MainApp.jsx' + export default function App() { const [loading, setLoading] = useState(true); // true while checking auth const [loggedIn, setLoggedIn] = useState(false); @@ -14,7 +17,7 @@ export default function App() { async function checkAuth() { try { // This endpoint should validate the refresh token cookie and return an access token - const res = await fetch("http://localhost:7080/auth/login_refresh_token", { + const res = await fetch(`${API_BASE}/auth/login_refresh_token`, { method: "POST", headers: { "Content-Type": "application/json", diff --git a/src/components/HotelContext.jsx b/src/components/HotelContext.jsx new file mode 100644 index 0000000..fc3d891 --- /dev/null +++ b/src/components/HotelContext.jsx @@ -0,0 +1,94 @@ +import { createContext, useContext, useState, useEffect } from "react"; +import { API_BASE } from "../config"; + +const HotelContext = createContext(null); + +export function useHotel() { + return useContext(HotelContext); +} + +export function HotelProvider({ accessToken, children }) { + const [rooms, setRooms] = useState([]); + const [conversations, setConversations] = useState([]); + const [users, setUsers] = useState([]); + + const tokens = JSON.parse(accessToken); + const accessTokenSingle = tokens[0]; + + // --- API FUNCTIONS --- + async function fetchRooms() { + const res = await fetch( `${API_BASE}/rooms/rooms`, { + headers: { Authorization: `Bearer ${accessTokenSingle}` }, + }); + return res.json(); + } + +async function updateRoomStatus(roomId, status) { + await fetch(`${API_BASE}/rooms/clean_db_update/${roomId}`, { + method: "PUT", + headers: { + Authorization: `Bearer ${accessTokenSingle}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ status }), + }); + + // refresh cached rooms + const updated = await fetchRooms(); + setRooms(updated); +} + + async function fetchConversations() { + const res = await fetch(`${API_BASE}/chat/get_conv`, { + method: "POST", + headers: { + Authorization: `Bearer ${accessTokenSingle}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + conv_id: 4, + timestamp: "2025-09-25 11:05:33", + }), + }); + return res.json(); + } + + async function fetchHotelUsers() { + const res = await fetch(`${API_BASE}/chat/hotel_users`, { + headers: { Authorization: `Bearer ${accessTokenSingle}` }, + }); + return res.json(); + } + + // --- INITIAL DATA LOADING --- + useEffect(() => { + if (!accessToken) return; + + async function load() { + const [roomsData, convData, usersData] = await Promise.all([ + fetchRooms(), + fetchConversations(), + //fetchHotelUsers(), + ]); + + setRooms(roomsData); + setConversations(convData); + //setUsers(usersData); + } + + load(); + }, [accessToken]); + + return ( + + {children} + + ); +} diff --git a/src/components/MainApp.jsx b/src/components/MainApp.jsx index 4f37b9c..ee7d509 100644 --- a/src/components/MainApp.jsx +++ b/src/components/MainApp.jsx @@ -1,24 +1,41 @@ +import { HotelProvider, useHotel } from "./HotelContext"; +import RoomWidget from "./widget/roomWidget" -export default function MainApp() { - // You could fetch your short-lived access token from localStorage +export default function MainAppWrapper() { const accessToken = localStorage.getItem("access_tokens"); - console.log("the accesToken in Mainapp is :" + accessToken); + + return ( + + + + ); +} + +function MainApp() { + const accessToken = localStorage.getItem("access_tokens"); + const { rooms, conversations, users } = useHotel(); + return (

Welcome to MyHotel!

-

Your access token (short-lived) is:

+ +

Access token

{accessToken}

Dashboard

); + + + + } diff --git a/src/components/RoomManagement.jsx b/src/components/RoomManagement.jsx new file mode 100644 index 0000000..68f417c --- /dev/null +++ b/src/components/RoomManagement.jsx @@ -0,0 +1,16 @@ +import { useHotel } from "./HotelContext"; + +export default function RoomManagement() { + const { rooms } = useHotel(); + + return ( +
+

Rooms

+ {rooms.map(r => ( +
+ Room {r.number} — {r.status} +
+ ))} +
+ ); +} diff --git a/src/components/auth_checking.jsx b/src/components/auth_checking.jsx index 95c77e1..cdba32a 100644 --- a/src/components/auth_checking.jsx +++ b/src/components/auth_checking.jsx @@ -1,3 +1,6 @@ + +import { API_BASE } from "../config"; + import { useEffect, useState } from "react"; import Login from "./components/Login"; import MainApp from "./MainApp"; @@ -10,7 +13,7 @@ export default function App() { async function checkLogin() { try { // Call the endpoint that validates the refresh token cookie - const res = await fetch("http://localhost:7080/auth/login_refresh_token", { + const res = await fetch(`${API_BASE}/auth/login_refresh_token`, { method: "POST", headers: { "Content-Type": "application/json", diff --git a/src/components/login.jsx b/src/components/login.jsx index a465e5b..34b2e08 100644 --- a/src/components/login.jsx +++ b/src/components/login.jsx @@ -1,3 +1,5 @@ +import { API_BASE } from "../config"; + import { useState } from "react"; export default function Login({ onLogin }) { @@ -9,10 +11,10 @@ export default function Login({ onLogin }) { e.preventDefault(); setError(""); - const device_id = "147ac10b-58cc-4372-a567-0e02b2c3d479" ; + const device_id = "147ac10b-58cc-4372-a567-0e02b2c3d479"; try { - const res = await fetch("http://localhost:7080/auth/create_refresh", { + const res = await fetch(`${API_BASE}/auth/create_refresh`, { method: "POST", headers: { "Content-Type": "application/json", diff --git a/src/components/widget/ConvWiget.jsx b/src/components/widget/ConvWiget.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/widget/RoomWidget.css b/src/components/widget/RoomWidget.css new file mode 100644 index 0000000..6e7ca97 --- /dev/null +++ b/src/components/widget/RoomWidget.css @@ -0,0 +1,25 @@ +.grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + gap: 1px; + background-color: #777777; +} + +.card { + gap: 1px; + background-color: #a3a3a3; + padding: 5px; + + } + +.card input { + width: 90%; + box-sizing: border-box; /* important */ + max-width: 100%; /* prevents overflow */ +} + +.actions { + display: flex; + +} + diff --git a/src/components/widget/roomWidget.jsx b/src/components/widget/roomWidget.jsx new file mode 100644 index 0000000..614ee32 --- /dev/null +++ b/src/components/widget/roomWidget.jsx @@ -0,0 +1,68 @@ + +import "./RoomWidget.css"; +import { useHotel } from "../HotelContext"; +import { useState } from "react"; +export default function RoomWidget({ roomlist }) { + + return ( +
+ {roomlist.map(room => ( + + ))} +
+ ); +} + +function RoomCard({ number, status ,id}) { +const { updateRoomStatus } = useHotel(); +const [editing, setEditing] = useState(false); +const [value, SetValue] = useState(status); + + + function submit() { + updateRoomStatus(id,value); + setEditing(false); + } + + return ( +
+

Room {number}

+

Id {id}

+ + {!editing ?( +

setEditing(true)} style={{ cursor: "pointer" }}> + Status: {status} +

+ ): ( +
+ SetValue(e.target.value)} + onKeyDown={e => e.key === "Enter" && submit()} + /> +
+ )} + + +
+ + + +
+ +
+ ); +} + +//export default roomWidget \ No newline at end of file diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000..4bcc492 --- /dev/null +++ b/src/config.js @@ -0,0 +1 @@ +export const API_BASE = "http://localhost:7080"; \ No newline at end of file