Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementado sistema de grupos completo #113

Merged
merged 21 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions gatewayservice/gateway-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 5 additions & 15 deletions users/userservice/user-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
module.exports = { User, Group };
94 changes: 88 additions & 6 deletions users/userservice/user-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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}`);
});
Expand Down
8 changes: 8 additions & 0 deletions webapp/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -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!";
Expand All @@ -40,6 +44,10 @@ function App() {
<Route path="/ranking" element={<Ranking />} />
<Route path="/social/usuarios" element={<UsersPage />} />
<Route path="/social/amigos" element={<FriendList />} />
<Route path="/social/grupos" element={<Groups />} />
<Route path="/social/misgrupos" element={<UserGroups />} />
<Route path="/social/grupo/:groupName" element={<GroupDetails />} />

<Route path="/perfil" element={<Perfil />} />
<Route path="/history" element={<History />} />
<Route path="/config" element={<Config />} />
Expand Down
16 changes: 16 additions & 0 deletions webapp/src/components/Nav/Nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,22 @@ const Nav = () => {
>
{t("components.nav.friends")}
</Text>
<Text
data-testid="groups"
cursor="pointer"
onClick={() => handleNavigate("/social/grupos")}
color={textColor}
>
Grupos
</Text>
<Text
data-testid="mygroups"
cursor="pointer"
onClick={() => handleNavigate("/social/misgrupos")}
color={textColor}
>
Mis grupos
</Text>
</PopoverBody>
</PopoverContent>
</Popover>
Expand Down
76 changes: 76 additions & 0 deletions webapp/src/pages/Social/GroupDetails.js
Original file line number Diff line number Diff line change
@@ -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 (
<>
<Nav/>
<Container maxW="md" mt="5">
<Heading as="h1" mb="5">Detalles del grupo: {groupName}</Heading>
{group ? (
<Box>
<Text fontSize="lg" fontWeight="bold" mb="4">
Creado por {group.members.length > 0 ? group.members[0] : ''} el {new Date(group.createdAt).toLocaleDateString()}
</Text>

<Text fontSize="lg" fontWeight="bold" mb="2">Participantes ({group.members.length}) :</Text>
<Table variant="striped">
<Thead>
<Tr>
<Th>Avatar</Th>
<Th>Nombre</Th>
<Th>Ver perfil</Th>
</Tr>
</Thead>
<Tbody>
{group.members.map((member, index) => (
<Tr key={index}>
<Td>
<Avatar size="sm" name={member} />
</Td>
<Td>{member}</Td>
<Td>
<Link color="blue.500" onClick={() => redirectToProfile(member)}>Ver perfil</Link>
</Td>
</Tr>
))}
</Tbody>
</Table>
</Box>
) : (
<Text>Loading...</Text>
)}
</Container>
<Footer/>
</>
);
};

export default GroupDetails;

Empty file.
Loading
Loading