Add favorites feature - toggle, list, and pre-fill on add
This commit is contained in:
@@ -1,47 +1,49 @@
|
||||
import 'dotenv/config';
|
||||
import express from 'express';
|
||||
import cors from 'cors';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import db from './models/db.js';
|
||||
import { initialize, getDb } from './models/db.js';
|
||||
import entriesRouter from './routes/entries.js';
|
||||
import foodsRouter from './routes/foods.js';
|
||||
import summaryRouter from './routes/summary.js';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3000;
|
||||
|
||||
// Middleware
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
// Serve uploaded files statically
|
||||
app.use('/uploads', express.static(path.join(__dirname, process.env.UPLOAD_DIR || '../uploads')));
|
||||
app.use('/uploads', express.static('./uploads'));
|
||||
app.use(express.static('./public'));
|
||||
|
||||
// API Routes
|
||||
initialize();
|
||||
|
||||
// Routes
|
||||
app.use('/api/entries', entriesRouter);
|
||||
app.use('/api/foods', foodsRouter);
|
||||
app.use('/api/summary', summaryRouter);
|
||||
|
||||
// Health check
|
||||
app.get('/api/health', (req, res) => {
|
||||
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
||||
// Favorites routes inline
|
||||
app.get('/api/favorites', (req, res) => {
|
||||
const db = getDb();
|
||||
res.json(db.prepare('SELECT * FROM entries WHERE favorite = 1 ORDER BY name ASC').all());
|
||||
});
|
||||
|
||||
// Initialize database and start server
|
||||
db.initialize()
|
||||
.then(() => {
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Meal Tracker API running on port ${PORT}`);
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Failed to initialize database:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
app.post('/api/entries/:id/favorite', (req, res) => {
|
||||
const db = getDb();
|
||||
const { id } = req.params;
|
||||
const entry = db.prepare('SELECT favorite FROM entries WHERE id = ?').get(id);
|
||||
if (!entry) return res.status(404).json({ error: 'Not found' });
|
||||
const newVal = entry.favorite ? 0 : 1;
|
||||
db.prepare('UPDATE entries SET favorite = ? WHERE id = ?').run(newVal, id);
|
||||
res.json({ id, favorite: newVal });
|
||||
});
|
||||
|
||||
export default app;
|
||||
// SPA fallback
|
||||
app.get('*', (req, res) => {
|
||||
res.sendFile(path.join(process.cwd(), 'public', 'index.html'));
|
||||
});
|
||||
|
||||
app.listen(PORT, '0.0.0.0', () => {
|
||||
console.log('Meal Tracker running on port ' + PORT);
|
||||
});
|
||||
|
||||
32
server/routes/favorites.js
Normal file
32
server/routes/favorites.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import { getDb } from '../models/db.js';
|
||||
|
||||
export default function setupRoutes(app) {
|
||||
// Get all favorites
|
||||
app.get('/api/favorites', (req, res) => {
|
||||
const db = getDb();
|
||||
const stmt = db.prepare('SELECT * FROM entries WHERE favorite = 1 ORDER BY name ASC');
|
||||
const favorites = stmt.all();
|
||||
res.json(favorites);
|
||||
});
|
||||
|
||||
// Toggle favorite
|
||||
app.post('/api/entries/:id/favorite', (req, res) => {
|
||||
const db = getDb();
|
||||
const { id } = req.params;
|
||||
|
||||
// Get current favorite status
|
||||
const getStmt = db.prepare('SELECT favorite FROM entries WHERE id = ?');
|
||||
const entry = getStmt.get(id);
|
||||
|
||||
if (!entry) {
|
||||
return res.status(404).json({ error: 'Entry not found' });
|
||||
}
|
||||
|
||||
// Toggle
|
||||
const newValue = entry.favorite ? 0 : 1;
|
||||
const updateStmt = db.prepare('UPDATE entries SET favorite = ? WHERE id = ?');
|
||||
updateStmt.run(newValue, id);
|
||||
|
||||
res.json({ id, favorite: newValue });
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user