import { CollectionConfig, Where } from "payload"; import type { User } from "@/payload-types"; import { requirePermission, hasPermission } from "@/utils/access-control/hasPermission"; export const MarketNegotiations: CollectionConfig = { slug: "market-negotiations", admin: { group: "Market", useAsTitle: "id", defaultColumns: [ "id", "listing", "buyer", "amount", "patience", "proposedBy", "status", "updatedAt", ], pagination: { defaultLimit: 50 }, }, access: { read: async ({ req }) => { const user = req.user as User | null; if (!user) return false; if (await hasPermission(req.payload, user, "market-negotiations:read")) return true; return { or: [{ buyer: { equals: user.id } }, { "listing.seller": { equals: user.id } }], } as Where; }, create: ({ req }) => !!req.user, update: async ({ req }) => { const user = req.user as User | null; if (!user) return false; if (await hasPermission(req.payload, user, "market-negotiations:update")) return true; return { or: [{ buyer: { equals: user.id } }, { "listing.seller": { equals: user.id } }], } as Where; }, delete: requirePermission("market-negotiations:delete"), }, fields: [ { name: "listing", type: "relationship", relationTo: "market-listings", required: true, index: true, admin: { description: "The market listing this negotiation thread belongs to.", }, }, { name: "buyer", type: "relationship", relationTo: "users", required: true, index: true, admin: { description: "The player interested in buying the listing.", }, }, { name: "status", type: "select", required: true, defaultValue: "open", options: [ { label: "Open", value: "open" }, { label: "Accepted", value: "accepted" }, { label: "Rejected", value: "rejected" }, { label: "Closed (patience exhausted)", value: "closed" }, { label: "Cancelled", value: "cancelled" }, { label: "Expired", value: "expired" }, ], index: true, }, { name: "patience", type: "number", defaultValue: 0, min: 0, max: 100, admin: { description: "NPC vendor patience (0–100). Rises each bargaining round and sharply for lowball offers; at 100 the negotiation closes and the buyer can only buy at the asking price.", }, }, { name: "quantity", type: "number", min: 1, defaultValue: 1, admin: { description: "How many units the buyer wants from the listing.", }, }, { name: "amount", type: "number", required: true, min: 0, admin: { description: "The per-unit price currently on the table. Proposed by the buyer or the seller depending on the proposal.", }, }, { name: "proposedBy", type: "select", required: true, defaultValue: "buyer", options: [ { label: "Buyer", value: "buyer" }, { label: "Seller", value: "seller" }, ], }, { name: "acceptedPrice", type: "number", admin: { description: "The per-unit price agreed when the negotiation is accepted.", }, }, { name: "history", type: "array", fields: [ { name: "amount", type: "number", required: true, }, { name: "from", type: "select", required: true, options: [ { label: "Buyer", value: "buyer" }, { label: "Seller", value: "seller" }, ], }, { name: "note", type: "text", }, { name: "at", type: "date", required: true, defaultValue: () => new Date().toISOString(), }, ], }, ], timestamps: true, };