/opt/canhelp/apps/api/src/routes
NameSizeModeActions
admin.ts950570644editdlrm
auto-match.ts74060644editdlrm
auto-response.ts81110644editdlrm
availability.ts72940644editdlrm
categories.ts18670644editdlrm
chat.ts93770644editdlrm
dashboard.ts51420644editdlrm
favorites.ts44410644editdlrm
fomo.ts68440644editdlrm
google.ts48720644editdlrm
health.ts12140644editdlrm
i18n.ts1670860644editdlrm
locations.ts17810644editdlrm
notifications.ts28620644editdlrm
offers.ts100470644editdlrm
payments.ts211670644editdlrm
plans.ts13520644editdlrm
portfolio.ts66580644editdlrm
price-list.ts144170644editdlrm
reports.ts20070644editdlrm
reviews.ts27830644editdlrm
skill-suggestions.ts10350644editdlrm
specialist-cards.ts186410644editdlrm
stats.ts10930644editdlrm
statuses.ts37310644editdlrm
support.ts84520644editdlrm
tasks.ts300180644editdlrm
uploads.ts15260644editdlrm
users.ts371570644editdlrm
Edit: /opt/canhelp/apps/api/src/routes/favorites.ts (4441B)
import { Hono } from 'hono' import { eq, and, desc } from 'drizzle-orm' import { db } from '../db.js' import { favorites, tasks, specialistFavorites, users, plans } from '@canhelp/db' import { requireAuth, type AuthVariables } from '../middleware/auth.js' const app = new Hono<{ Variables: AuthVariables }>() /** Check if user's plan includes favorites */ async function checkFavoritesAccess(userId: string): Promise { const [user] = await db.select({ planId: users.planId, role: users.role }).from(users).where(eq(users.id, userId)) if (user?.role === 'admin') return true if (!user?.planId) return false const [plan] = await db.select({ hasFavorites: plans.hasFavorites }).from(plans).where(eq(plans.id, user.planId)) return !!plan?.hasFavorites } // GET /favorites app.get('/', requireAuth, async (c) => { const user = c.get('user') const rows = await db .select({ favorite: favorites, task: tasks }) .from(favorites) .leftJoin(tasks, eq(favorites.taskId, tasks.id)) .where(eq(favorites.userId, user.id)) .orderBy(desc(favorites.createdAt)) return c.json(rows) }) // POST /favorites/:taskId app.post('/:taskId', requireAuth, async (c) => { const user = c.get('user') const taskId = c.req.param('taskId') const hasAccess = await checkFavoritesAccess(user.id) if (!hasAccess) { return c.json({ error: 'Your plan does not include favorites', code: 'PLAN_FEATURE_RESTRICTED' }, 403) } const [task] = await db.select().from(tasks).where(eq(tasks.id, taskId)) if (!task) return c.json({ error: 'Task not found' }, 404) const [existing] = await db .select() .from(favorites) .where(and(eq(favorites.userId, user.id), eq(favorites.taskId, taskId))) if (existing) return c.json(existing) const [fav] = await db .insert(favorites) .values({ userId: user.id, taskId }) .returning() return c.json(fav, 201) }) // DELETE /favorites/:taskId app.delete('/:taskId', requireAuth, async (c) => { const user = c.get('user') await db .delete(favorites) .where(and(eq(favorites.userId, user.id), eq(favorites.taskId, c.req.param('taskId')))) return c.json({ ok: true }) }) // ─── Specialist favorites ────────────────────────────────────────────────── // GET /favorites/specialists app.get('/specialists', requireAuth, async (c) => { const user = c.get('user') const rows = await db .select({ id: specialistFavorites.id, createdAt: specialistFavorites.createdAt, specialist: { id: users.id, name: users.name, firstName: users.firstName, lastName: users.lastName, image: users.image, bio: users.bio, }, }) .from(specialistFavorites) .leftJoin(users, eq(specialistFavorites.specialistId, users.id)) .where(eq(specialistFavorites.userId, user.id)) .orderBy(desc(specialistFavorites.createdAt)) return c.json(rows) }) // POST /favorites/specialists/:specialistId app.post('/specialists/:specialistId', requireAuth, async (c) => { const user = c.get('user') const specialistId = c.req.param('specialistId') if (specialistId === user.id) return c.json({ error: 'Cannot favorite yourself' }, 400) const hasAccess = await checkFavoritesAccess(user.id) if (!hasAccess) { return c.json({ error: 'Your plan does not include favorites', code: 'PLAN_FEATURE_RESTRICTED' }, 403) } const [specialist] = await db.select({ id: users.id }).from(users).where(eq(users.id, specialistId)) if (!specialist) return c.json({ error: 'Specialist not found' }, 404) const [existing] = await db .select() .from(specialistFavorites) .where(and(eq(specialistFavorites.userId, user.id), eq(specialistFavorites.specialistId, specialistId))) if (existing) return c.json(existing) const [fav] = await db .insert(specialistFavorites) .values({ userId: user.id, specialistId }) .returning() return c.json(fav, 201) }) // DELETE /favorites/specialists/:specialistId app.delete('/specialists/:specialistId', requireAuth, async (c) => { const user = c.get('user') await db .delete(specialistFavorites) .where(and( eq(specialistFavorites.userId, user.id), eq(specialistFavorites.specialistId, c.req.param('specialistId')), )) return c.json({ ok: true }) }) export default app