Files
hotel-demo-front/src/components/HotelContext.jsx

392 lines
7.9 KiB
JavaScript

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 (
<HotelContext.Provider
value={{
rooms,
conversations,
messagesByConvId,
users,
usersById,
clientId,
updateRoomStatus,
fetchMessages,
fetchConvUsers,
sendMessage,
fetchHotelUsers,
addUserToConv,
createConversation,
fetchHotelInventory,
updateItemAmount,
createItem
}}
>
{children}
</HotelContext.Provider>
);
}