import {createContext, useContext, useState, useEffect, useRef } from "react"; import { API_BASE } from "../config"; const HotelContext = createContext(null); export function useHotel() { return useContext(HotelContext); } export function HotelProvider({ accessToken, children, resClientId}) { const [rooms, setRooms] = useState([]); const [conversations, setConversations] = useState([]); const [messagesByConvId, setMessagesByConvId] = useState({}); const [users, setUsers] = useState([]); const [usersById, setUsersById] = useState({}); const [clientId, setClientId] = useState(resClientId|| null); const tokens = JSON.parse(accessToken); const accessTokenSingle = tokens[0]; const wsRef = useRef(null); // --- API FUNCTIONS --- // ROOMS 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); } // CHAT async function createConversation(name) { const payload = { name }; const res = await fetch(`${API_BASE}/chat/create_conversation`, { method: "POST", headers: { Authorization: `Bearer ${accessTokenSingle}`, "Content-Type": "application/json", }, body: JSON.stringify(payload), }); } function appendMessage(msg) { setMessagesByConvId(prev => ({ ...prev, [msg.conv_id]: [ ...(prev[msg.conv_id] ?? []), msg, ], })); } 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 fetchMessages({ conv_id }) { const payload = { conv_id, timestamp: "2025-09-25 11:05:33", }; //console.log(JSON.stringify(payload)); const res = await fetch(`${API_BASE}/chat/get_message`, { method: "POST", headers: { Authorization: `Bearer ${accessTokenSingle}`, "Content-Type": "application/json", }, body: JSON.stringify(payload), }); const messages = await res.json(); setMessagesByConvId(prev => ({ ...prev, [conv_id]: messages, })); return messages; //return res.json } async function fetchConvUsers({ conv_id }) { const payload = { conv_id, timestamp: "2025-09-25 11:05:33", }; //console.log(JSON.stringify(payload)); const res = await fetch(`${API_BASE}/chat/get_conv_users/${conv_id}`, { method: "POST", headers: { Authorization: `Bearer ${accessTokenSingle}`, "Content-Type": "application/json", }, body: JSON.stringify(payload), }); return res.json(); //return res.json } async function sendMessage({ conv_id, message }) { if (!conv_id) { console.log("conv_id null at sendMessage") return }; const payload = { conv_id, message }; //console.log(JSON.stringify(payload)); const res = await fetch(`${API_BASE}/chat/send_message`, { method: "POST" , headers: { Authorization: `Bearer ${accessTokenSingle}`, "Content-Type" : "application/json", }, body: JSON.stringify(payload), }) } async function addUserToConv({ conv_id, users}) { if (!conv_id || !users) { console.log("error in convs or user to add") }; const payload = { conv_id, users }; const res = await fetch(`${API_BASE}/chat/add_users_conv`, { method: "PUT" , headers: { Authorization: `Bearer ${accessTokenSingle}`, "Content-Type" : "application/json", }, body: JSON.stringify(payload), }) } async function preloadMessages(conversations) { for (const conv of conversations) { await fetchMessages({ conv_id: conv.id }); } } // INVENTORY async function fetchHotelInventory() { const res = await fetch ( `${API_BASE}/inventory/get_item/`, { headers: { Authorization: `Bearer ${accessTokenSingle}`}, }); console.log ("fetched inventory") return res.json() } async function updateItemAmount(item_id, item_amount) { const res = await fetch ( `${API_BASE}/inventory/update_item/${item_id}/${item_amount}`, { method: "PUT", headers: { Authorization: `Bearer ${accessTokenSingle}` } }); } async function createItem(item_name, item_amount){ const res = await fetch ( `${API_BASE}/inventory/add_item/${item_name}/${item_amount}`, { method:"POST", headers: { Authorization: `Bearer ${accessTokenSingle}` } }); } async function fetchHotelUsers() { const res = await fetch(`${API_BASE}/chat/hotel_users`, { method: "POST", headers: { Authorization: `Bearer ${accessTokenSingle}`, "Content-Type": "application/json", }, }); const users = await res.json(); const map = {}; for (const u of users) { map[u.id] = u.username; } setUsersById(map); // setUsers(users) return users; } // --- WS DISPATCH MESSAGE ---- function handleWsMessage(msg) { console.log("websocket message is :" + msg.event_type, typeof msg.event_type); switch (msg.event_type) { case "room_update": { setRooms(prev => prev.map(r => r.id === msg.room_id ? { ...r, status: msg.status } : r ) ); break; } case "chat_message": { appendMessage(msg); break; } default: console.warn("Unhandled WS message bruuuuh:", msg); } } // --- WS USE EFFECT ---- // --- INITIAL DATA LOADING --- useEffect(() => { if (!accessToken) return; async function load() { const [roomsData, convData, usersData] = await Promise.all([ fetchRooms(), fetchConversations(), fetchHotelUsers(), ]); setClientId(resClientId); setRooms(roomsData); setConversations(convData); setUsers(usersData); } load(); //console.log("USERS 2 =",usersById) }, []); useEffect(() => { if (conversations.length === 0) return; preloadMessages(conversations); }, [conversations]); useEffect(() => { //if (!accessTokenSingle || !clientId) return; const ws = new WebSocket( `http://localhost:7080/auth/ws/${accessTokenSingle}` ); wsRef.current = ws; ws.onopen = () => { console.log("WS connected"); }; ws.onmessage = (event) => { const msg = JSON.parse(event.data); console.log("WS :", msg); handleWsMessage(msg); }; ws.onerror = (err) => { console.error("WS error", err); }; ws.onclose = () => { console.log("WS disconnected"); }; return () => { ws.close(); }; }, [accessTokenSingle]); return ( {children} ); }