AeThex-Connect/src/frontend/components/GameForgeChat/index.jsx
2026-01-12 01:39:23 +00:00

139 lines
3.6 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { useSocket } from '../../contexts/SocketContext';
import { useAuth } from '../../contexts/AuthContext';
import ChannelList from './ChannelList';
import ChannelView from './ChannelView';
import './GameForgeChat.css';
/**
* Embedded chat component for GameForge projects
* Can be embedded in GameForge UI via iframe or direct integration
*/
export default function GameForgeChat({ projectId: propProjectId, embedded = false }) {
const { projectId: paramProjectId } = useParams();
const projectId = propProjectId || paramProjectId;
const { socket } = useSocket();
const { user } = useAuth();
const [channels, setChannels] = useState([]);
const [activeChannel, setActiveChannel] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
// Load channels
useEffect(() => {
if (projectId) {
loadChannels();
}
}, [projectId]);
// Socket listeners for system notifications
useEffect(() => {
if (!socket) return;
socket.on('gameforge:notification', handleNotification);
return () => {
socket.off('gameforge:notification', handleNotification);
};
}, [socket]);
const loadChannels = async () => {
try {
setLoading(true);
setError(null);
const response = await fetch(`/api/gameforge/projects/${projectId}/channels`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
});
const data = await response.json();
if (data.success) {
setChannels(data.channels);
// Auto-select general channel
const generalChannel = data.channels.find(c => c.name === 'general');
if (generalChannel) {
setActiveChannel(generalChannel);
}
} else {
setError(data.error);
}
} catch (err) {
console.error('Failed to load channels:', err);
setError('Failed to load project channels');
} finally {
setLoading(false);
}
};
const handleNotification = (notification) => {
// Update channel with new system message
const { channelId, message } = notification;
setChannels(prev => prev.map(channel => {
if (channel.id === channelId) {
return {
...channel,
lastMessage: message,
unreadCount: activeChannel?.id === channelId ? 0 : channel.unreadCount + 1
};
}
return channel;
}));
};
if (loading) {
return (
<div className={`gameforge-chat ${embedded ? 'embedded' : ''}`}>
<div className="loading">Loading project chat...</div>
</div>
);
}
if (error) {
return (
<div className={`gameforge-chat ${embedded ? 'embedded' : ''}`}>
<div className="error">
<p>{error}</p>
<button onClick={loadChannels}>Retry</button>
</div>
</div>
);
}
return (
<div className={`gameforge-chat ${embedded ? 'embedded' : ''}`}>
<div className="gameforge-chat-sidebar">
<div className="project-header">
<h3>Project Channels</h3>
</div>
<ChannelList
channels={channels}
activeChannel={activeChannel}
onSelectChannel={setActiveChannel}
/>
</div>
<div className="gameforge-chat-main">
{activeChannel ? (
<ChannelView
channel={activeChannel}
projectId={projectId}
/>
) : (
<div className="no-channel-selected">
<p>Select a channel to start chatting</p>
</div>
)}
</div>
</div>
);
}