Skip to content

Commit e244071

Browse files
committed
feat: integrate node-fetch for API calls and enhance server logging
- Added node-fetch dependency for making API requests. - Refactored server.js to replace axios with fetch for API interactions. - Improved logging middleware to provide better request tracking. - Updated package.json and package-lock.json to include new dependencies. - Enhanced index.ejs to display a calendar using FullCalendar with improved styling and responsiveness. - Implemented dynamic class details display on event click in the calendar.
1 parent ddcd694 commit e244071

File tree

7 files changed

+883
-1658
lines changed

7 files changed

+883
-1658
lines changed

01-contenedores/lemoncode-challenge/node-stack/backend/app.js

Lines changed: 71 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ const app = express();
1010
// CONFIGURACIÓN
1111
// ============================================
1212
const DB_URL = process.env.DATABASE_URL || 'mongodb://localhost:27017';
13-
const DB_NAME = process.env.DATABASE_NAME || 'TopicstoreDb';
13+
const DB_NAME = process.env.DATABASE_NAME || 'ClassesDb';
1414
const HOST = process.env.HOST || '0.0.0.0';
15-
const PORT = 5001;
15+
const PORT = 5000;
1616

1717
let db;
18-
let topicsCollection;
18+
let classesCollection;
1919
let mongoClient;
2020

2121
// ============================================
@@ -25,6 +25,13 @@ app.use(cors());
2525
app.use(express.json());
2626
app.use(express.urlencoded({ extended: true }));
2727

28+
// Middleware de logging
29+
app.use((req, res, next) => {
30+
const timestamp = new Date().toLocaleTimeString('es-ES');
31+
console.log(`📍 [${timestamp}] ${req.method} ${req.path}`);
32+
next();
33+
});
34+
2835
// ============================================
2936
// CONEXIÓN A MONGODB
3037
// ============================================
@@ -36,123 +43,124 @@ async function connectDB() {
3643
console.log('✅ Conexión a MongoDB exitosa');
3744

3845
db = mongoClient.db(DB_NAME);
39-
topicsCollection = db.collection('Topics');
40-
console.log('📋 Colección Topics cargada');
46+
classesCollection = db.collection('Classes');
47+
console.log('📚 Colección Classes cargada');
4148
} catch (error) {
4249
console.error('❌ Error al conectar a MongoDB:', error.message);
4350
process.exit(1);
4451
}
4552
}
4653

4754
// ============================================
48-
// RUTAS - TOPICS
55+
// RUTAS - CLASSES
4956
// ============================================
5057

51-
// GET /api/topics - Obtener todos los tópicos
52-
app.get('/api/topics', async (req, res) => {
58+
// GET /api/classes - Obtener todas las clases
59+
app.get('/api/classes', async (req, res) => {
5360
try {
54-
console.log('📥 GET /api/topics');
55-
const topics = await topicsCollection.find({}).toArray();
56-
console.log(`✅ Se obtuvieron ${topics.length} tópicos`);
57-
res.json(topics);
61+
const classes = await classesCollection.find({}).toArray();
62+
console.log(`✅ Se obtuvieron ${classes.length} clases`);
63+
res.json(classes);
5864
} catch (error) {
59-
console.error('❌ Error al obtener tópicos:', error.message);
60-
res.status(500).json({ error: 'Error al obtener tópicos' });
65+
console.error('❌ Error al obtener clases:', error.message);
66+
res.status(500).json({ error: 'Error al obtener clases' });
6167
}
6268
});
6369

64-
// GET /api/topics/:id - Obtener un tópico por ID
65-
app.get('/api/topics/:id', async (req, res) => {
70+
// GET /api/classes/:id - Obtener una clase por ID
71+
app.get('/api/classes/:id', async (req, res) => {
6672
try {
6773
const { id } = req.params;
68-
console.log(`📥 GET /api/topics/${id}`);
6974

7075
if (!ObjectId.isValid(id)) {
7176
return res.status(400).json({ error: 'ID inválido' });
7277
}
7378

74-
const topic = await topicsCollection.findOne({ _id: new ObjectId(id) });
75-
if (!topic) {
76-
return res.status(404).json({ error: 'Tópico no encontrado' });
79+
const classItem = await classesCollection.findOne({ _id: new ObjectId(id) });
80+
if (!classItem) {
81+
return res.status(404).json({ error: 'Clase no encontrada' });
7782
}
7883

79-
console.log(`✅ Tópico ${id} obtenido`);
80-
res.json(topic);
84+
console.log(`✅ Clase ${id} obtenida`);
85+
res.json(classItem);
8186
} catch (error) {
82-
console.error('❌ Error al obtener tópico:', error.message);
83-
res.status(500).json({ error: 'Error al obtener tópico' });
87+
console.error('❌ Error al obtener clase:', error.message);
88+
res.status(500).json({ error: 'Error al obtener clase' });
8489
}
8590
});
8691

87-
// POST /api/topics - Crear un nuevo tópico
88-
app.post('/api/topics', async (req, res) => {
92+
// POST /api/classes - Crear una nueva clase
93+
app.post('/api/classes', async (req, res) => {
8994
try {
90-
const topic = req.body;
91-
console.log(`📥 POST /api/topics - ${JSON.stringify(topic)}`);
92-
93-
if (!topic.Name) {
94-
return res.status(400).json({ error: 'El campo Name es requerido' });
95+
const classItem = req.body;
96+
console.log(`📝 Creando clase: ${classItem.name}`);
97+
98+
// Validación de campos requeridos
99+
if (!classItem.name || !classItem.instructor || !classItem.level) {
100+
return res.status(400).json({
101+
error: 'Los campos name, instructor y level son requeridos'
102+
});
95103
}
96104

97-
const result = await topicsCollection.insertOne(topic);
98-
const createdTopic = { _id: result.insertedId, ...topic };
99-
console.log(`✅ Tópico creado: ${topic.Name}`);
100-
res.status(201).json(createdTopic);
105+
const result = await classesCollection.insertOne(classItem);
106+
const createdClass = { _id: result.insertedId, ...classItem };
107+
console.log(`✅ Clase creada: ${classItem.name}`);
108+
res.status(201).json(createdClass);
101109
} catch (error) {
102-
console.error('❌ Error al crear tópico:', error.message);
103-
res.status(500).json({ error: 'Error al crear tópico' });
110+
console.error('❌ Error al crear clase:', error.message);
111+
res.status(500).json({ error: 'Error al crear clase' });
104112
}
105113
});
106114

107-
// PUT /api/topics/:id - Actualizar un tópico
108-
app.put('/api/topics/:id', async (req, res) => {
115+
// PUT /api/classes/:id - Actualizar una clase
116+
app.put('/api/classes/:id', async (req, res) => {
109117
try {
110118
const { id } = req.params;
111-
const topic = req.body;
112-
console.log(`📥 PUT /api/topics/${id} - ${JSON.stringify(topic)}`);
119+
const classItem = req.body;
120+
console.log(`📝 Actualizando clase ${id}`);
113121

114122
if (!ObjectId.isValid(id)) {
115123
return res.status(400).json({ error: 'ID inválido' });
116124
}
117125

118-
const result = await topicsCollection.updateOne(
126+
const result = await classesCollection.updateOne(
119127
{ _id: new ObjectId(id) },
120-
{ $set: topic }
128+
{ $set: classItem }
121129
);
122130

123131
if (result.matchedCount === 0) {
124-
return res.status(404).json({ error: 'Tópico no encontrado' });
132+
return res.status(404).json({ error: 'Clase no encontrada' });
125133
}
126134

127-
console.log(`✅ Tópico ${id} actualizado`);
128-
res.json({ _id: id, ...topic });
135+
console.log(`✅ Clase ${id} actualizada`);
136+
res.json({ _id: id, ...classItem });
129137
} catch (error) {
130-
console.error('❌ Error al actualizar tópico:', error.message);
131-
res.status(500).json({ error: 'Error al actualizar tópico' });
138+
console.error('❌ Error al actualizar clase:', error.message);
139+
res.status(500).json({ error: 'Error al actualizar clase' });
132140
}
133141
});
134142

135-
// DELETE /api/topics/:id - Eliminar un tópico
136-
app.delete('/api/topics/:id', async (req, res) => {
143+
// DELETE /api/classes/:id - Eliminar una clase
144+
app.delete('/api/classes/:id', async (req, res) => {
137145
try {
138146
const { id } = req.params;
139-
console.log(`📥 DELETE /api/topics/${id}`);
147+
console.log(`🗑️ Eliminando clase ${id}`);
140148

141149
if (!ObjectId.isValid(id)) {
142150
return res.status(400).json({ error: 'ID inválido' });
143151
}
144152

145-
const result = await topicsCollection.deleteOne({ _id: new ObjectId(id) });
153+
const result = await classesCollection.deleteOne({ _id: new ObjectId(id) });
146154

147155
if (result.deletedCount === 0) {
148-
return res.status(404).json({ error: 'Tópico no encontrado' });
156+
return res.status(404).json({ error: 'Clase no encontrada' });
149157
}
150158

151-
console.log(`✅ Tópico ${id} eliminado`);
159+
console.log(`✅ Clase ${id} eliminada`);
152160
res.status(204).send();
153161
} catch (error) {
154-
console.error('❌ Error al eliminar tópico:', error.message);
155-
res.status(500).json({ error: 'Error al eliminar tópico' });
162+
console.error('❌ Error al eliminar clase:', error.message);
163+
res.status(500).json({ error: 'Error al eliminar clase' });
156164
}
157165
});
158166

@@ -161,16 +169,17 @@ app.delete('/api/topics/:id', async (req, res) => {
161169
// ============================================
162170
async function startServer() {
163171
try {
164-
console.log('\n🔧 Inicializando backend...');
172+
console.log('\n' + '═'.repeat(70));
173+
console.log('🍋 LEMONCODE CALENDAR - BACKEND (Node.js + Express)');
174+
console.log('═'.repeat(70));
165175
await connectDB();
166176

167177
app.listen(PORT, HOST, () => {
168178
const url = `http://${HOST === '0.0.0.0' ? 'localhost' : HOST}:${PORT}`;
169-
console.log('');
170-
console.log('═══════════════════════════════════════════════════════════════');
171-
console.log(`🚀 Servidor ejecutándose en: ${url}/api/topics`);
172-
console.log('═══════════════════════════════════════════════════════════════');
173-
console.log('');
179+
console.log(`🚀 Servidor ejecutándose en: ${url}`);
180+
console.log(`📚 API: ${url}/api/classes`);
181+
console.log(`⏰ Hora: ${new Date().toLocaleString('es-ES')}`);
182+
console.log('═'.repeat(70) + '\n');
174183
});
175184
} catch (error) {
176185
console.error('❌ Error al iniciar servidor:', error.message);

0 commit comments

Comments
 (0)