AI Coach messages bookmarking. Top bar refined.

This commit is contained in:
AG
2025-12-16 16:41:50 +02:00
parent cb0bd1a55d
commit dd027e1615
26 changed files with 2496 additions and 270 deletions

View File

@@ -0,0 +1,79 @@
import { Request, Response } from 'express';
import prisma from '../lib/prisma';
export class BookmarksController {
static async getAll(req: Request, res: Response) {
try {
const userId = (req as any).user?.userId;
if (!userId) {
return res.status(401).json({ success: false, error: 'Unauthorized' });
}
const messages = await prisma.savedMessage.findMany({
where: { userId },
orderBy: { createdAt: 'desc' },
});
return res.json({ success: true, data: messages });
} catch (error) {
console.error('Failed to get bookmarks:', error);
return res.status(500).json({ success: false, error: 'Internal server error' });
}
}
static async create(req: Request, res: Response) {
try {
const userId = (req as any).user?.userId;
if (!userId) {
return res.status(401).json({ success: false, error: 'Unauthorized' });
}
const { content, role } = req.body;
if (!content) {
return res.status(400).json({ success: false, error: 'Content is required' });
}
const message = await prisma.savedMessage.create({
data: {
userId,
content,
role: role || 'model',
},
});
return res.json({ success: true, data: message });
} catch (error) {
console.error('Failed to create bookmark:', error);
return res.status(500).json({ success: false, error: 'Internal server error' });
}
}
static async delete(req: Request, res: Response) {
try {
const userId = (req as any).user?.userId;
if (!userId) {
return res.status(401).json({ success: false, error: 'Unauthorized' });
}
const { id } = req.params;
// Verify ownership
const existing = await prisma.savedMessage.findFirst({
where: { id, userId },
});
if (!existing) {
return res.status(404).json({ success: false, error: 'Bookmark not found' });
}
await prisma.savedMessage.delete({
where: { id },
});
return res.json({ success: true });
} catch (error) {
console.error('Failed to delete bookmark:', error);
return res.status(500).json({ success: false, error: 'Internal server error' });
}
}
}

View File

@@ -11,6 +11,7 @@ import sessionRoutes from './routes/sessions';
import planRoutes from './routes/plans';
import aiRoutes from './routes/ai';
import weightRoutes from './routes/weight';
import bookmarksRoutes from './routes/bookmarks';
import bcrypt from 'bcryptjs';
import { PrismaClient } from '@prisma/client';
@@ -88,6 +89,7 @@ app.use('/api/sessions', sessionRoutes);
app.use('/api/plans', planRoutes);
app.use('/api/ai', aiRoutes);
app.use('/api/weight', weightRoutes);
app.use('/api/bookmarks', bookmarksRoutes);
app.get('/', (req, res) => {

View File

@@ -0,0 +1,13 @@
import express from 'express';
import { BookmarksController } from '../controllers/bookmarks.controller';
import { authenticateToken } from '../middleware/auth';
const router = express.Router();
router.use(authenticateToken);
router.get('/', BookmarksController.getAll);
router.post('/', BookmarksController.create);
router.delete('/:id', BookmarksController.delete);
export default router;