eletrotupi / tcc/ api/src/reports/report.router.tsc901c35af9c84b6a29e5185545ced1129f33b8f4
1.8 KB | 62 lines Raw
1
import { Router, Response, NextFunction } from 'express'
2
import React from 'react'
3
import { renderToBuffer } from '@react-pdf/renderer'
4
import { z } from 'zod'
5
import { requireAuth, AuthenticatedRequest } from '@app/middleware/auth'
6
import { buildReportData } from './report.data'
7
import ReportDocument from './ReportDocument'
8

9
const router = Router()
10

11
const ReportSchema = z
12
  .object({
13
    periodStart: z.iso.datetime({ offset: true }),
14
    periodEnd: z.iso.datetime({ offset: true }),
15
  })
16
  .refine(
17
    (d) => {
18
      const start = new Date(d.periodStart)
19
      const end = new Date(d.periodEnd)
20
      const diff = (end.getTime() - start.getTime()) / 86_400_000
21
      return diff > 0 && diff <= 90
22
    },
23
    { message: 'periodEnd must be after periodStart and range ≤ 90 days' },
24
  )
25

26
router.post(
27
  '/',
28
  requireAuth,
29
  async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
30
    try {
31
      req.log.info("Requirements: %s", req.body.periodStart, req.body.periodEnd)
32

33
      const parsed = ReportSchema.safeParse(req.body)
34
      if (!parsed.success) {
35
        return res.status(400).json({ error: parsed.error.issues[0]?.message ?? 'Invalid request' })
36
      }
37

38
      const { periodStart, periodEnd } = parsed.data
39
      const data = await buildReportData(
40
        req.userId!,
41
        new Date(periodStart),
42
        new Date(periodEnd),
43
      )
44

45
      const element = React.createElement(ReportDocument, { data })
46
      const buffer = await renderToBuffer(
47
        element as React.ReactElement<any>,
48
      )
49

50
      res.setHeader('Content-Type', 'application/pdf')
51
      res.setHeader(
52
        'Content-Disposition',
53
        `attachment; filename="Nexo-report-${periodStart.slice(0, 7)}.pdf"`,
54
      )
55
      return res.send(buffer)
56
    } catch (err) {
57
      return next(err)
58
    }
59
  },
60
)
61

62
export default router