1
0
Fork 0
polaris-task-force/src/collections/locker/LockerStorages.ts

161 lines
4.3 KiB
TypeScript

import { CollectionConfig } from "payload";
import { isDeveloper } from "@/utils/access-control/isRole";
export const LockerStorages: CollectionConfig = {
slug: "locker-storages",
admin: {
group: "Locker",
useAsTitle: "name",
defaultColumns: ["name", "ownerUser", "itemCount"],
},
access: {
read: ({ req }) => {
if (!req.user) return false;
if (isDeveloper({ req })) return true;
return { ownerUser: { equals: req.user.id } };
},
create: ({ req }) => !!req.user && isDeveloper({ req }),
update: ({ req }) => {
if (!req.user) return false;
if (isDeveloper({ req })) return true;
return { ownerUser: { equals: req.user.id } };
},
delete: isDeveloper,
},
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;
},
],
},
},
],
};