feat: implement real-time collaboration and instant updates with socket integration

- Added `SocketProvider` for application-wide WebSocket connection management.
- Introduced real-time updates for projects and groups, including create, update, and delete events.
- Enhanced project and group pages with real-time collaboration, group actions, and data syncing.
- Refactored fetch methods to include loading and refreshing states.
- Integrated `toast` notifications for real-time event feedback.
- Updated `package.json` to include `socket.io-client@4.8.1`.
This commit is contained in:
2025-05-16 16:41:37 +02:00
parent ce7e89d339
commit d7255444f5
5 changed files with 365 additions and 87 deletions

View File

@@ -14,10 +14,12 @@ import {
Loader2,
Wand2,
Save,
RefreshCw
RefreshCw,
Users
} from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { toast } from "sonner";
import { useSocket } from "@/lib/socket-context";
// Mock project data (same as in the groups page)
const getProjectData = (id: string) => {
@@ -78,6 +80,9 @@ export default function AutoCreateGroupsPage() {
const [generating, setGenerating] = useState(false);
const [saving, setSaving] = useState(false);
// Socket connection for real-time updates
const { isConnected, joinProject, leaveProject, onGroupCreated } = useSocket();
// State for auto-generation parameters
const [numberOfGroups, setNumberOfGroups] = useState(4);
const [balanceTags, setBalanceTags] = useState(true);
@@ -86,6 +91,36 @@ export default function AutoCreateGroupsPage() {
const [availableTags, setAvailableTags] = useState<string[]>([]);
const [availableLevels, setAvailableLevels] = useState<string[]>([]);
// Join project room for real-time updates when connected
useEffect(() => {
if (!isConnected) return;
// Join the project room to receive updates
joinProject(projectId);
// Clean up when component unmounts
return () => {
leaveProject(projectId);
};
}, [isConnected, joinProject, leaveProject, projectId]);
// Listen for group created events
useEffect(() => {
if (!isConnected || groups.length === 0) return;
const unsubscribe = onGroupCreated((data) => {
console.log("Group created:", data);
if (data.action === "created" && data.group) {
toast.info(`Nouveau groupe créé par un collaborateur: ${data.group.name}`);
}
});
return () => {
unsubscribe();
};
}, [isConnected, onGroupCreated, groups]);
useEffect(() => {
// Fetch project data from API
const fetchProject = async () => {
@@ -163,6 +198,12 @@ export default function AutoCreateGroupsPage() {
setGenerating(true);
try {
// Notify users that groups are being generated
if (isConnected) {
toast.info("Génération de groupes en cours...", {
description: "Les autres utilisateurs seront notifiés lorsque les groupes seront générés."
});
}
// Use the API service to generate groups
const { groupsAPI } = await import('@/lib/api');
@@ -338,6 +379,12 @@ export default function AutoCreateGroupsPage() {
</Link>
</Button>
<h1 className="text-3xl font-bold">Assistant de création de groupes</h1>
{isConnected && (
<div className="flex items-center gap-2 ml-4 text-sm text-muted-foreground">
<div className="h-2 w-2 rounded-full bg-green-500"></div>
<span>Collaboration en temps réel active</span>
</div>
)}
</div>
<Button onClick={handleSaveGroups} disabled={saving || groups.length === 0}>
{saving ? (
@@ -470,6 +517,12 @@ export default function AutoCreateGroupsPage() {
<p className="text-center text-muted-foreground">
Aucun groupe généré. Cliquez sur "Générer les groupes" pour commencer.
</p>
{isConnected && (
<div className="mt-4 flex items-center gap-2 text-sm text-muted-foreground">
<div className="h-2 w-2 rounded-full bg-green-500"></div>
<span>Collaboration en temps réel active</span>
</div>
)}
</div>
) : (
<div className="space-y-4">