diff --git a/frontend/tasks/src/context/RoomContext.ts b/frontend/tasks/src/context/RoomContext.ts index b747c93..9fccdc5 100644 --- a/frontend/tasks/src/context/RoomContext.ts +++ b/frontend/tasks/src/context/RoomContext.ts @@ -6,7 +6,7 @@ interface RoomContextType { room: Room[]; getRoom: () => Promise; createRoom: (room_name: string, description: string, members: User[]) => Promise; - addMember: (roomId: string, memberId: User) => Promise; + addMember: (roomId: string, memberId: string) => Promise; deleteMemberToRoom: (roomId: string, memberId: string) => Promise; updateRoomInformation: (roomId: string, room: Room) => Promise; deleteRoom: (roomId: string) => Promise diff --git a/frontend/tasks/src/context/RoomProvider.tsx b/frontend/tasks/src/context/RoomProvider.tsx index 500c101..672d78f 100644 --- a/frontend/tasks/src/context/RoomProvider.tsx +++ b/frontend/tasks/src/context/RoomProvider.tsx @@ -86,10 +86,10 @@ export const RoomProvider = ({ children }: RoomProviderProps) => { } }; - const addMember = async (roomId: string, memberId: User) => { + const addMember = async (roomId: string, memberId: string) => { try { setLoading(true); - const response = await instance.post(`/room/add/${roomId}/${memberId._id}`); + const response = await instance.post(`/room/add/${roomId}/${memberId}`); if (!response.data.success) { throw new Error(response.data.error || "Failed to add member"); @@ -102,9 +102,10 @@ export const RoomProvider = ({ children }: RoomProviderProps) => { ) ); setErrors(null); + return response.data; } - throw new Error("Failed to update room after adding member"); + throw new Error("No room data returned from server"); } catch (error) { const apiError = error as ApiError; const errorMessage = diff --git a/frontend/tasks/src/hook/useRoom.ts b/frontend/tasks/src/hook/useRoom.ts index 8ee80e6..90153c6 100644 --- a/frontend/tasks/src/hook/useRoom.ts +++ b/frontend/tasks/src/hook/useRoom.ts @@ -12,8 +12,9 @@ export const useRoom = () => { return context as { room: Room[]; getRoom: () => Promise; + loading: boolean; createRoom: (room_name: string, description: string, members: User[]) => Promise; - addMember: (roomId: string, memberId: User) => Promise; + addMember: (roomId: string, memberId: string) => Promise; deleteMemberToRoom: (roomId: string, memberId: string) => Promise; updateRoomInformation: (roomId: string, room: Room) => Promise; deleteRoom: (roomId: string) => Promise; diff --git a/frontend/tasks/src/pages/RoomId.tsx b/frontend/tasks/src/pages/RoomId.tsx index bfd803e..a36b740 100644 --- a/frontend/tasks/src/pages/RoomId.tsx +++ b/frontend/tasks/src/pages/RoomId.tsx @@ -17,10 +17,12 @@ import { } from "lucide-react"; import AddMember from "../ui/room/AddMember"; import { AuthContext } from "../context"; +import { CheckmarkIcon } from "react-hot-toast"; const RoomId = () => { const { id } = useParams<{ id: string }>(); const { room, getRoom } = useRoom(); + // const {deleteTask} = useContext(TaskContext) //Au cas ou on veut supprimer directement dans la salle const {currentUser} = useContext(AuthContext) const [currentRoom, setCurrentRoom] = useState(null); const [isLoading, setIsLoading] = useState(true); @@ -61,8 +63,10 @@ const RoomId = () => { switch (status) { case 'completed': return 'bg-emerald-900/30 text-emerald-400 border-emerald-800/50'; - case 'in-progress': + case 'in_progress': return 'bg-blue-900/30 text-blue-400 border-blue-800/50'; + case 'done': + return 'bg-green-900/30 text-blue-400 border-green-800/50'; default: return 'bg-slate-800/50 text-slate-300 border-slate-700/50'; } @@ -70,10 +74,14 @@ const RoomId = () => { const getPriorityColor = (priority: string) => { switch (priority) { + case 'low': + return 'bg-yellow-200' case 'high': return 'bg-red-500'; case 'medium': return 'bg-yellow-500'; + case 'critical': + return 'bg-red-500'; default: return 'bg-green-500'; } @@ -83,8 +91,12 @@ const RoomId = () => { switch (status) { case 'completed': return ; - case 'in-progress': + case 'in_progress': return ; + case 'done': + return ( + + ) default: return ; } @@ -139,10 +151,10 @@ const RoomId = () => {
- -
@@ -232,9 +244,11 @@ const RoomId = () => { Tasks - @@ -250,15 +264,33 @@ const RoomId = () => {

- {task.title} + {task.title || 'Sans titre'}

{getStatusIcon(task.status || 'todo')} {(task.status || 'todo').replace('-', ' ')}
-

{task.description}

+

+ {task.description || 'Aucune description'} +

+ {/* +

+ Modifier +

+ */} + {/* */}
@@ -279,7 +311,7 @@ const RoomId = () => { {new Date(task.dueDate).toLocaleDateString()}
)} - @@ -294,9 +326,11 @@ const RoomId = () => {

No tasks yet

Get started by creating your first task for this room.

- )} diff --git a/frontend/tasks/src/ui/Tasks.tsx b/frontend/tasks/src/ui/Tasks.tsx index 40d9eaa..a1af737 100644 --- a/frontend/tasks/src/ui/Tasks.tsx +++ b/frontend/tasks/src/ui/Tasks.tsx @@ -111,7 +111,7 @@ const Tasks = ({ viewMode }: {viewMode: string}) => {

Aucune tâche

Créez votre première tâche pour commencer !

- diff --git a/frontend/tasks/src/ui/UtilsBar.tsx b/frontend/tasks/src/ui/UtilsBar.tsx index f1719a6..74f08de 100644 --- a/frontend/tasks/src/ui/UtilsBar.tsx +++ b/frontend/tasks/src/ui/UtilsBar.tsx @@ -42,6 +42,7 @@ const UtilsBar = ({ diff --git a/frontend/tasks/src/ui/home/Cta.tsx b/frontend/tasks/src/ui/home/Cta.tsx index 1f10901..27f58e9 100644 --- a/frontend/tasks/src/ui/home/Cta.tsx +++ b/frontend/tasks/src/ui/home/Cta.tsx @@ -12,10 +12,10 @@ const Cta = () => { Rejoignez des milliers d'utilisateurs qui ont déjà adopté TaskFlow pour gérer leurs tâches

- -
diff --git a/frontend/tasks/src/ui/home/Header.tsx b/frontend/tasks/src/ui/home/Header.tsx index db70bd2..2ab717a 100644 --- a/frontend/tasks/src/ui/home/Header.tsx +++ b/frontend/tasks/src/ui/home/Header.tsx @@ -35,10 +35,11 @@ const Header = ({ isMenuOpen, setIsMenuOpen }: { isMenuOpen: boolean, setIsMenuO {/* CTA et Menu Mobile */}
-
diff --git a/frontend/tasks/src/ui/home/Hero.tsx b/frontend/tasks/src/ui/home/Hero.tsx index 5dfd4f5..6e303fc 100644 --- a/frontend/tasks/src/ui/home/Hero.tsx +++ b/frontend/tasks/src/ui/home/Hero.tsx @@ -19,11 +19,11 @@ const Hero = () => {

- - diff --git a/frontend/tasks/src/ui/home/Pricing.tsx b/frontend/tasks/src/ui/home/Pricing.tsx index 176e591..e0854c1 100644 --- a/frontend/tasks/src/ui/home/Pricing.tsx +++ b/frontend/tasks/src/ui/home/Pricing.tsx @@ -37,7 +37,7 @@ const Pricing = () => { Support email -
@@ -72,7 +72,7 @@ const Pricing = () => { Support prioritaire - @@ -102,7 +102,7 @@ const Pricing = () => { Support 24/7 - diff --git a/frontend/tasks/src/ui/room/AddMember.tsx b/frontend/tasks/src/ui/room/AddMember.tsx index 38ec42a..bb1d6b6 100644 --- a/frontend/tasks/src/ui/room/AddMember.tsx +++ b/frontend/tasks/src/ui/room/AddMember.tsx @@ -2,6 +2,7 @@ import { useContext, useEffect, useState } from "react"; import { AuthContext } from "../../context"; import { useRoom } from "../../hook/useRoom"; import Loader from "../../components/Loader"; +import toast from "react-hot-toast"; const AddMember = ({ roomId }: { roomId: string }) => { const { user, getAllUser, loading: authLoading } = useContext(AuthContext); @@ -31,6 +32,7 @@ const AddMember = ({ roomId }: { roomId: string }) => { try { setAddingMemberId(userId); await addMember(roomId, userId); + toast.success("Ajouté avec succès") setErrors("") } catch (error) { setErrors("Erreur lors de l'ajout du membre"); diff --git a/frontend/tasks/src/ui/room/CreateRoom.tsx b/frontend/tasks/src/ui/room/CreateRoom.tsx index 2dce20f..49760b0 100644 --- a/frontend/tasks/src/ui/room/CreateRoom.tsx +++ b/frontend/tasks/src/ui/room/CreateRoom.tsx @@ -4,6 +4,7 @@ import { AuthContext } from "../../context"; import { useRoom } from "../../hook/useRoom"; import type { User } from "../../types/user"; import Loader from "../../components/Loader"; +import toast from "react-hot-toast"; interface RoomFormData { room_name: string; @@ -79,6 +80,7 @@ const CreateRoom = () => { formData.members ); + toast.success("Créé avec succès") // Reset form on success setFormData({ room_name: "", description: "", members: [] }); } catch (error: any) { diff --git a/frontend/tasks/src/ui/room/Room.tsx b/frontend/tasks/src/ui/room/Room.tsx index 6143d51..e694915 100644 --- a/frontend/tasks/src/ui/room/Room.tsx +++ b/frontend/tasks/src/ui/room/Room.tsx @@ -1,16 +1,21 @@ -import React, { useContext, useEffect } from "react"; +import React, { useContext, useEffect} from "react"; import { AuthContext } from "../../context"; import { Link } from "react-router-dom"; import { useRoom } from "../../hook/useRoom"; +import Loader from "../../components/Loader"; const RoomUI = () => { - const { room, getRoom } = useRoom(); + const { room, getRoom, loading} = useRoom(); const { user } = useContext(AuthContext); useEffect(() => { getRoom(); }, [getRoom]); + if (loading) { + return + } + if (user && room.length === 0) { return (
@@ -18,6 +23,7 @@ const RoomUI = () => {
); } + const RoomRow = React.memo(() => room.map((r) => { // Get the first user in the array or undefined if empty @@ -27,9 +33,9 @@ const RoomUI = () => { key={r._id} className="text-white p-4 border-2 border-gray-300 rounded-md bg-gradient-to-br from-white/20 to-indigo-300/50 opacity-80 backdrop-blur-lg" > -

Room

-

{r.room_name}

-

{r.description}

+

Room: {room.findIndex((room) => room._id === r._id) + 1}

+

Titre: {r.room_name}

+ {/*

{r.description}

*/}
Membres : @@ -43,7 +49,7 @@ const RoomUI = () => { diff --git a/src/models/room.model.js b/src/models/room.model.js index d845de5..ee2cd07 100644 --- a/src/models/room.model.js +++ b/src/models/room.model.js @@ -42,6 +42,7 @@ const roomSchema = new mongoose.Schema( { type: mongoose.Schema.Types.ObjectId, ref: "Task", + default: [], }, ], admin: { diff --git a/src/routes/room.route.js b/src/routes/room.route.js index 0ed4993..01fa0f0 100644 --- a/src/routes/room.route.js +++ b/src/routes/room.route.js @@ -22,6 +22,14 @@ export const roomRoutes = async (fastify, options) => { Room.find({ admin: userId, isActive: true }) .populate("admin", "userName email avatar") .populate("members", "userName email avatar") + .populate({ + path: "tasks", + select: "title description status priority dueDate assignees", + populate: { + path: "assignees", + select: "userName email", + }, + }) .sort({ updatedAt: -1 }), Room.find({ @@ -31,6 +39,14 @@ export const roomRoutes = async (fastify, options) => { }) .populate("admin", "userName email avatar") .populate("members", "userName email avatar") + .populate({ + path: "tasks", + select: "title description status priority dueDate assignees", + populate: { + path: "assignees", + select: "userName email", + }, + }) .sort({ updatedAt: -1 }), ]); @@ -40,6 +56,7 @@ export const roomRoutes = async (fastify, options) => { memberRooms, count: adminRooms.length + memberRooms.length, total: adminRooms.length + memberRooms.length, + // tasks, }; } catch (error) { return handleError(error, reply); @@ -175,26 +192,19 @@ export const roomRoutes = async (fastify, options) => { }); } - // Vérifier la limite de membres - const maxMembers = - Room.schema.obj.members[0].validate[0].validator.MAX_MEMBERS; - if (room.members.length >= maxMembers) { - await session.abortTransaction(); - session.endSession(); - console.log(error.message); - return reply.code(400).send({ - success: false, - error: ERROR_MESSAGES.ROOM_LIMIT_REACHED, - }); - } - // Ajouter l'utilisateur à la salle - room.members.push(memberId); - await room.save({ session }); + await Room.updateOne( + { _id: roomId }, + { $addToSet: { members: memberId } }, + { session } + ); // Mettre à jour la référence de l'utilisateur - userToAdd.rooms.push(roomId); - await userToAdd.save({ session }); + await User.updateOne( + { _id: memberId }, + { $addToSet: { rooms: roomId } }, + { session } + ); await session.commitTransaction(); session.endSession();