HotTRDealsBackend/routes/deal.routes.js
2026-01-25 17:50:56 +00:00

220 lines
6.2 KiB
JavaScript

// routes/deals.js
const express = require("express")
const router = express.Router()
const requireAuth = require("../middleware/requireAuth")
const optionalAuth = require("../middleware/optionalAuth")
const { upload } = require("../middleware/upload.middleware")
const { validate } = require("../middleware/validate.middleware")
const { endpoints } = require("@shared/contracts")
const userDB = require("../db/user.db")
const { getDeals, getDealById, createDeal } = require("../services/deal.service")
const { mapCreateDealRequestToDealCreateData } = require("../adapters/requests/dealCreate.adapter")
const { mapDealToDealDetailResponse } = require("../adapters/responses/dealDetail.adapter")
const { mapPaginatedDealsToDealCardResponse } = require("../adapters/responses/dealCard.adapter")
const { deals, users } = endpoints
const listQueryValidator = validate(deals.dealsListRequestSchema, "query", "validatedDealListQuery")
const buildViewer = (req) =>
req.auth ? { userId: req.auth.userId, role: req.auth.role } : null
function createListHandler(preset) {
return async (req, res) => {
try {
const viewer = buildViewer(req)
const { q, page, limit } = req.validatedDealListQuery
const payload = await getDeals({
preset,
q,
page,
limit,
viewer,
})
const response = deals.dealsListResponseSchema.parse(
mapPaginatedDealsToDealCardResponse(payload)
)
res.json(response)
} catch (err) {
console.error(err)
const status = err.statusCode || 500
res.status(status).json({ error: err.message || "Sunucu hatasi" })
}
}
}
// Public deals of a user (viewer optional; self profile => "MY" else "USER_PUBLIC")
router.get(
"/users/:userName/deals",
optionalAuth,
validate(users.userProfileRequestSchema, "params", "validatedUserProfile"),
listQueryValidator,
async (req, res) => {
try {
const { userName } = req.validatedUserProfile
const targetUser = await userDB.findUser(
{ username: userName },
{ select: { id: true } }
)
if (!targetUser) return res.status(404).json({ error: "Kullanici bulunamadi" })
const { q, page, limit } = req.validatedDealListQuery
const viewer = buildViewer(req)
const isSelfProfile = viewer?.userId === targetUser.id
const preset = isSelfProfile ? "MY" : "USER_PUBLIC"
const payload = await getDeals({
preset,
q,
page,
limit,
targetUserId: targetUser.id,
viewer,
})
const response = deals.dealsListResponseSchema.parse(
mapPaginatedDealsToDealCardResponse(payload)
)
res.json(response)
} catch (err) {
console.error(err)
const status = err.statusCode || 500
res.status(status).json({ error: err.message || "Sunucu hatasi" })
}
}
)
// My deals (auth required)
router.get(
"/me/deals",
requireAuth,
listQueryValidator,
createListHandler("MY")
)
router.get("/new", optionalAuth, listQueryValidator, createListHandler("NEW"))
router.get("/hot", optionalAuth, listQueryValidator, createListHandler("HOT"))
router.get("/trending", optionalAuth, listQueryValidator, createListHandler("TRENDING"))
router.get("/", optionalAuth, listQueryValidator, createListHandler("NEW"))
router.get(
"/search",
optionalAuth,
listQueryValidator,
async (req, res) => {
try {
const { q, page, limit } = req.validatedDealListQuery
if (!q || !q.trim()) {
return res.json({ results: [], total: 0, totalPages: 0, page })
}
const payload = await getDeals({
preset: "NEW",
q,
page,
limit,
viewer: buildViewer(req),
})
const response = deals.dealsListResponseSchema.parse(
mapPaginatedDealsToDealCardResponse(payload)
)
res.json(response)
} catch (err) {
console.error(err)
const status = err.statusCode || 500
res.status(status).json({ error: err.message || "Sunucu hatasi" })
}
}
)
// TOP deals (daily/weekly/monthly) - viewer optional
router.get("/top", optionalAuth, async (req, res) => {
try {
const viewer = buildViewer(req)
const range = String(req.query.range || "day")
const limitRaw = Number(req.query.limit ?? 6)
const limit = Number.isFinite(limitRaw) ? Math.max(1, Math.min(20, limitRaw)) : 6
let preset = "HOT_DAY"
if (range === "week") preset = "HOT_WEEK"
else if (range === "month") preset = "HOT_MONTH"
else if (range !== "day") return res.status(400).json({ error: "range invalid" })
const payload = await getDeals({
preset,
q: null,
page: 1,
limit,
viewer,
})
const response = deals.dealsListResponseSchema.parse(
mapPaginatedDealsToDealCardResponse(payload)
)
// frontend DealCard[] bekliyor
res.json(response.results)
} catch (err) {
console.error(err)
const status = err.statusCode || 500
res.status(status).json({ error: err.message || "Sunucu hatasi" })
}
})
router.get(
"/:id",
validate(deals.dealDetailRequestSchema, "params", "validatedDealId"),
async (req, res) => {
try {
const { id } = req.validatedDealId
const deal = await getDealById(id)
if (!deal) return res.status(404).json({ error: "Deal bulunamadi" })
const mapped = mapDealToDealDetailResponse(deal)
console.log(mapped)
res.json(deals.dealDetailResponseSchema.parse(mapped))
} catch (err) {
console.error(err)
res.status(500).json({ error: "Sunucu hatasi" })
}
}
)
// Create deal (auth required)
router.post(
"/",
requireAuth,
upload.array("images", 5),
validate(deals.dealCreateRequestSchema, "body", "validatedDealPayload"),
async (req, res) => {
try {
const userId = req.auth.userId
const dealCreateData = mapCreateDealRequestToDealCreateData(
req.validatedDealPayload,
userId
)
const deal = await createDeal(dealCreateData, req.files || [])
const mapped = mapDealToDealDetailResponse(deal)
res.json(deals.dealCreateResponseSchema.parse(mapped))
} catch (err) {
console.error(err)
res.status(500).json({ error: "Sunucu hatasi" })
}
}
)
module.exports = router