161 lines
4.3 KiB
TypeScript
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;
|
|
},
|
|
],
|
|
},
|
|
},
|
|
],
|
|
};
|