diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 213dd5a1..d1fef78b 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -90,6 +90,68 @@ app.post("/saveGameList", async (req, res) => { } }); +app.get("/friends", async (req, res) => { + try { + // Forward the question request to the user service + const userResponse = await axios.get( + userServiceUrl + "/friends", + { params: req.query } + ); + res.json(userResponse.data); + } catch (error) { + returnError(res, error); + } +}); + +app.post("/group/add", async (req, res) => { + try { + // Forward the save game request to the stats service + const gameResponse = await axios.post( + userServiceUrl + "/group/add", + req.body + ); + res.json(gameResponse.data); + } catch (error) { + returnError(res, error); + } +}); + +app.post("/group/join", async (req, res) => { + try { + // Forward the save game request to the stats service + const gameResponse = await axios.post( + userServiceUrl + "/group/join", + req.body + ); + res.json(gameResponse.data); + } catch (error) { + returnError(res, error); + } +}); + +app.get("/group/list", async (req, res) => { + try { + // Forward the question request to the user service + const userResponse = await axios.get( + userServiceUrl + "/group/list", + { params: req.query } + ); + res.json(userResponse.data); + } catch (error) { + returnError(res, error); + } +}); + +app.get('/group/:groupName', async (req, res) => { + try { + const groupName = req.params.groupName; + const userResponse = await axios.get(`${userServiceUrl}/group/${groupName}`); + res.json(userResponse.data); + } catch (error) { + res.status(400).json({ error: error.message }); + } +}); + app.get("/users/search", async (req, res) => { try { // Forward the question request to the user service diff --git a/users/userservice/user-model.js b/users/userservice/user-model.js index a1c047e7..ae347c9a 100644 --- a/users/userservice/user-model.js +++ b/users/userservice/user-model.js @@ -50,24 +50,14 @@ const groupSchema = new mongoose.Schema({ type: Date, default: Date.now }, + members: [{ + type: String, + required: true + }] }); const Group = mongoose.model('Group', groupSchema); -// Modelo para la relación entre usuarios y grupos -const userGroupSchema = new mongoose.Schema({ - user: { - type: mongoose.Schema.Types.ObjectId, - ref: 'User', - required: true - }, - group: { - type: mongoose.Schema.Types.ObjectId, - ref: 'Group', - required: true - }, -}); -const UserGroup = mongoose.model('UserGroup', userGroupSchema); -module.exports = { User, Group, UserGroup }; \ No newline at end of file +module.exports = { User, Group }; \ No newline at end of file diff --git a/users/userservice/user-service.js b/users/userservice/user-service.js index 5a0e5de3..531ec5da 100644 --- a/users/userservice/user-service.js +++ b/users/userservice/user-service.js @@ -4,7 +4,7 @@ const mongoose = require("mongoose"); const bcrypt = require("bcrypt"); const bodyParser = require("body-parser"); const jwt = require("jsonwebtoken"); -const { User } = require("./user-model"); +const { User, Group } = require("./user-model"); const app = express(); const port = 8001; @@ -246,14 +246,96 @@ app.post("/saveGameList", async (req, res) => { res.json({ message: "Partida guardada exitosamente" }); } catch (error) { - res - .status(400) - .json({ - error: "Error al guardar partida en la lista: " + error.message, - }); + res.status(400).json({ error: "Error al guardar partida en la lista: " + error.message }); } }); +app.get('/group/list', async (req, res) => { + try { + const allGroups = await Group.find(); + res.json({ groups: allGroups }); + } catch (error) { + res.status(500).json({ error: 'Internal Server Error' }); + } +}); + +// Obtener un grupo por su nombre +app.get('/group/:groupName', async (req, res) => { + try { + const groupName = req.params.groupName; + const group = await Group.findOne({ name: groupName }); + + if (!group) { + return res.status(404).json({ error: 'Group not found' }); + } + + res.json({ group }); + } catch (error) { + res.status(400).json({ error: error.message }); + } +}); + + +// Crear un nuevo grupo +app.post('/group/add', async (req, res) => { + try { + const name= req.body.name; + const username= req.body.username; + + if (!name) { + return res.status(400).json({ error: 'Group name cannot be empty' }); + } + + const existingGroup = await Group.findOne({ name: name }); + if (existingGroup) { + return res.status(400).json({ error: 'Group name already exists' }); + } + + const user = await User.findOne({ username:username }); + if (!user) { + return res.status(404).json({ error: 'User not found' }); + } + + const newGroup = new Group({ name: name, + members: [username] }); + await newGroup.save(); + + res.json({ message: 'Group created successfully' }); + } catch (error) { + res.status(400).json({ error: error.message }); + } +}); + +// Unirse a un grupo existente +app.post('/group/join', async (req, res) => { + try { + const groupId=req.body.groupId; + const username=req.body.username; + + const user = await User.findOne({ username }); + if (!user) { + return res.status(404).json({ error: 'User not found' }); + } + + const group = await Group.findById(groupId); + if (!group) { + return res.status(404).json({ error: 'Group not found' }); + } + + if (group.members.includes(username)) { + return res.status(400).json({ error: 'User already a member of this group' }); + } + + group.members.push(username); + await group.save(); + + res.json({ message: 'User joined the group successfully' }); + } catch (error) { + res.status(400).json({ error: error.message }); + } +}); + + const server = app.listen(port, () => { console.log(`User Service listening at http://localhost:${port}`); }); diff --git a/webapp/src/App.js b/webapp/src/App.js index cf723fb7..3c7c44ac 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -16,8 +16,12 @@ import Perfil from "./pages/Perfil/Perfil.js"; import CalculadoraHumana from "./pages/Calculadora/Calculadora.js"; import UsersPage from "./pages/Social/UsersPage.js"; import FriendList from "./pages/Social/FriendsList.js"; +import Groups from "./pages/Social/Groups.js"; +import UserGroups from "./pages/Social/UserGroups.js"; +import GroupDetails from "./pages/Social/GroupDetails.js"; import History from "./pages/History/History.js"; + function App() { useEffect(() => { document.title = "WIQ!"; @@ -40,6 +44,10 @@ function App() { } /> } /> } /> + } /> + } /> + } /> + } /> } /> } /> diff --git a/webapp/src/components/Nav/Nav.js b/webapp/src/components/Nav/Nav.js index 182fec81..ebf626c9 100644 --- a/webapp/src/components/Nav/Nav.js +++ b/webapp/src/components/Nav/Nav.js @@ -178,6 +178,22 @@ const Nav = () => { > {t("components.nav.friends")} + handleNavigate("/social/grupos")} + color={textColor} + > + Grupos + + handleNavigate("/social/misgrupos")} + color={textColor} + > + Mis grupos + diff --git a/webapp/src/pages/Social/GroupDetails.js b/webapp/src/pages/Social/GroupDetails.js new file mode 100644 index 00000000..cba5e34b --- /dev/null +++ b/webapp/src/pages/Social/GroupDetails.js @@ -0,0 +1,76 @@ +import React, { useState, useEffect } from 'react'; +import { useParams, useNavigate } from 'react-router-dom'; +import axios from 'axios'; +import { Container, Box, Text, Heading, Table, Thead, Tbody, Tr, Th, Td, Avatar, Link } from '@chakra-ui/react'; +import Nav from "../../components/Nav/Nav.js"; +import Footer from "../../components/Footer/Footer.js"; + +const GroupDetails = () => { + const [group, setGroup] = useState(null); + const { groupName } = useParams(); + const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; + const navigate = useNavigate(); + + useEffect(() => { + const fetchGroupDetails = async () => { + try { + const response = await axios.get(`${apiEndpoint}/group/${encodeURIComponent(groupName)}`); + setGroup(response.data.group); + } catch (error) { + console.error('Error fetching group details:', error); + } + }; + + fetchGroupDetails(); + }, [groupName]); + + const redirectToProfile = (username) => { + navigate(`/perfil?user=${username}`); + }; + + return ( + <> +