141 lines
3.9 KiB
TypeScript
141 lines
3.9 KiB
TypeScript
import { Router, Request, Response, NextFunction } from 'express';
|
|
import { UserRole } from '@prisma/client';
|
|
import { galleryAdsService } from './gallery-ads.service';
|
|
import { createAdSchema, updateAdSchema, listAdsSchema, reorderAdsSchema, adAnalyticsQuerySchema } from './gallery-ads.schemas';
|
|
import { validate } from '../../middleware/validate';
|
|
import { authenticate } from '../../middleware/auth.middleware';
|
|
import { requireRole } from '../../middleware/rbac.middleware';
|
|
|
|
const router = Router();
|
|
|
|
router.use(authenticate);
|
|
router.use(requireRole(UserRole.SUPER_ADMIN));
|
|
|
|
// GET /api/gallery-ads/admin — list all ads (paginated)
|
|
router.get(
|
|
'/',
|
|
validate(listAdsSchema, 'query'),
|
|
async (req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const result = await galleryAdsService.listAll(req.query as any);
|
|
res.json(result);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
}
|
|
);
|
|
|
|
// GET /api/gallery-ads/admin/analytics/aggregate — aggregate analytics across all ads
|
|
router.get(
|
|
'/analytics/aggregate',
|
|
validate(adAnalyticsQuerySchema, 'query'),
|
|
async (req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const { days } = req.query as any;
|
|
const analytics = await galleryAdsService.getAggregateAnalytics(days);
|
|
res.json(analytics);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
}
|
|
);
|
|
|
|
// GET /api/gallery-ads/admin/:id/analytics — per-ad time-series analytics
|
|
router.get(
|
|
'/:id/analytics',
|
|
validate(adAnalyticsQuerySchema, 'query'),
|
|
async (req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const id = parseInt(req.params.id as string, 10);
|
|
const { days } = req.query as any;
|
|
const analytics = await galleryAdsService.getAdAnalytics(id, days);
|
|
res.json(analytics);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
}
|
|
);
|
|
|
|
// GET /api/gallery-ads/admin/:id — get single ad
|
|
router.get('/:id', async (req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const id = parseInt(req.params.id as string, 10);
|
|
const ad = await galleryAdsService.getById(id);
|
|
if (!ad) {
|
|
res.status(404).json({ error: 'Ad not found' });
|
|
return;
|
|
}
|
|
res.json(ad);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
});
|
|
|
|
// POST /api/gallery-ads/admin — create ad
|
|
router.post(
|
|
'/',
|
|
validate(createAdSchema),
|
|
async (req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const ad = await galleryAdsService.create(req.body);
|
|
res.status(201).json(ad);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
}
|
|
);
|
|
|
|
// PUT /api/gallery-ads/admin/reorder — bulk reorder
|
|
router.put(
|
|
'/reorder',
|
|
validate(reorderAdsSchema),
|
|
async (req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
await galleryAdsService.reorder(req.body.ids);
|
|
res.json({ success: true });
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
}
|
|
);
|
|
|
|
// PUT /api/gallery-ads/admin/:id — update ad
|
|
router.put(
|
|
'/:id',
|
|
validate(updateAdSchema),
|
|
async (req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const id = parseInt(req.params.id as string, 10);
|
|
const ad = await galleryAdsService.update(id, req.body);
|
|
if (!ad) {
|
|
res.status(404).json({ error: 'Ad not found' });
|
|
return;
|
|
}
|
|
res.json(ad);
|
|
} catch (err) {
|
|
if (err instanceof Error && err.message.includes('Cannot change type')) {
|
|
res.status(400).json({ error: err.message });
|
|
return;
|
|
}
|
|
next(err);
|
|
}
|
|
}
|
|
);
|
|
|
|
// DELETE /api/gallery-ads/admin/:id — delete ad
|
|
router.delete('/:id', async (req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const id = parseInt(req.params.id as string, 10);
|
|
await galleryAdsService.delete(id);
|
|
res.json({ success: true });
|
|
} catch (err) {
|
|
if (err instanceof Error && err.message.includes('Cannot delete')) {
|
|
res.status(400).json({ error: err.message });
|
|
return;
|
|
}
|
|
next(err);
|
|
}
|
|
});
|
|
|
|
export { router as galleryAdsAdminRouter };
|