220 lines
6.2 KiB
JavaScript
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
|