import { CollectionConfig } from "payload"; import { requirePermission, hasPermission } from "@/utils/access-control/hasPermission"; export const LockerStorages: CollectionConfig = { slug: "locker-storages", admin: { group: "Locker", useAsTitle: "name", defaultColumns: ["name", "ownerUser", "itemCount"], }, access: { read: async ({ req }) => { if (!req.user) return false; if (await hasPermission(req.payload, req.user, "locker-storages:read")) return true; return { ownerUser: { equals: req.user.id } }; }, create: ({ req }) => { if (!req.user) return false; return hasPermission(req.payload, req.user, "locker-storages:create"); }, update: async ({ req }) => { if (!req.user) return false; if (await hasPermission(req.payload, req.user, "locker-storages:update")) return true; return { ownerUser: { equals: req.user.id } }; }, delete: async ({ req }) => { return await hasPermission(req.payload, req.user, "locker-storages:delete"); }, }, fields: [ { name: "name", type: "text", required: true, defaultValue: "Personal Locker", admin: { description: "Display name for this locker.", }, }, { name: "ownerUser", type: "relationship", relationTo: "users", required: true, admin: { description: "The operator who owns this locker.", }, }, { name: "items", type: "array", admin: { description: "Items stored in the locker grid. Position and rotation are managed from the member locker UI.", }, fields: [ { name: "asset", type: "relationship", relationTo: "assets", required: true, }, { name: "quantity", type: "number", required: true, min: 1, defaultValue: 1, }, { name: "gridX", type: "number", required: true, min: 0, defaultValue: 0, admin: { description: "Column position in the locker grid (0-indexed).", }, }, { name: "gridY", type: "number", required: true, min: 0, defaultValue: 0, admin: { description: "Row position in the locker grid (0-indexed).", }, }, { name: "rotated", type: "checkbox", defaultValue: false, admin: { description: "Whether this item is rotated 90 degrees (swaps width and height).", }, }, { name: "equipment", type: "group", label: "Equipment Customization", admin: { description: "Per-instance customization for this item: installed attachments, applied skin, and a custom name. Managed from the member locker UI.", }, fields: [ { name: "attachments", type: "array", label: "Installed Attachments", admin: { description: "Attachments installed on this item (e.g. optics, muzzles, bipods on a weapon). Installing consumes the attachment from the locker grid.", }, fields: [ { name: "asset", type: "relationship", relationTo: "assets", required: true, }, ], }, { name: "skin", type: "relationship", relationTo: "assets", admin: { description: "Skin applied to this item. Applying consumes the skin from the locker grid.", }, filterOptions: { assetType: { equals: "skin", }, }, }, { name: "customName", type: "text", admin: { description: 'Optional custom name for this item (e.g. "Frank\'s Karma").', }, }, ], }, ], }, { name: "itemCount", type: "number", admin: { readOnly: true, description: "Total number of distinct entries currently in this locker.", }, hooks: { beforeChange: [ ({ data }) => { const items = (data as { items?: unknown[] } | undefined)?.items; return Array.isArray(items) ? items.length : 0; }, ], }, }, ], };