111 lines
3.9 KiB
TypeScript
111 lines
3.9 KiB
TypeScript
import { Structure } from "@/payload-types";
|
||
import {
|
||
Item,
|
||
ItemContent,
|
||
ItemHeader,
|
||
ItemTitle,
|
||
} from "@/components/ui/item";
|
||
import {
|
||
CheckCircleIcon,
|
||
XCircleIcon,
|
||
ShieldCheckIcon,
|
||
ListRestartIcon,
|
||
} from "lucide-react";
|
||
|
||
interface StorageRulesProps {
|
||
allowedStorage: Structure["allowedStorage"];
|
||
prohibitedStorage: Structure["prohibitedStorage"];
|
||
restrictToAllowed?: Structure["restrictToAllowed"];
|
||
}
|
||
|
||
export function StorageRules({
|
||
allowedStorage,
|
||
prohibitedStorage,
|
||
restrictToAllowed,
|
||
}: StorageRulesProps) {
|
||
const hasAllowed = allowedStorage && allowedStorage.length > 0;
|
||
const hasProhibited = prohibitedStorage && prohibitedStorage.length > 0;
|
||
|
||
if (!hasAllowed && !hasProhibited && !restrictToAllowed) return null;
|
||
|
||
return (
|
||
<Item variant="outline">
|
||
<ItemHeader>
|
||
<ItemTitle className="flex items-center gap-2">
|
||
<ShieldCheckIcon className="size-4 text-muted-foreground" />
|
||
Storage Rules
|
||
</ItemTitle>
|
||
</ItemHeader>
|
||
<ItemContent>
|
||
<div className="flex flex-col gap-3">
|
||
{restrictToAllowed && (
|
||
<div className="flex items-center gap-2 p-2.5 rounded-md border border-amber-500/30 bg-amber-500/5 text-xs text-amber-400">
|
||
<ListRestartIcon className="size-3.5 shrink-0" />
|
||
<span>
|
||
Whitelist mode — only the items listed under "Allowed" can be
|
||
stored here. All other items are rejected.
|
||
</span>
|
||
</div>
|
||
)}
|
||
{hasAllowed && (
|
||
<div className="flex flex-col gap-1.5">
|
||
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
||
Allowed
|
||
</span>
|
||
<div className="flex flex-wrap gap-1.5">
|
||
{allowedStorage!.map((rule, index) => {
|
||
if (!rule.item) return null;
|
||
const item = rule.item;
|
||
const value = item.value;
|
||
const name =
|
||
typeof value === "object" && value !== null && "name" in value
|
||
? String(value.name)
|
||
: `Item #${value}`;
|
||
return (
|
||
<span
|
||
key={rule.id ?? index}
|
||
className="text-xs bg-green-500/10 text-green-400 border border-green-500/20 px-2 py-0.5 rounded-md flex items-center gap-1"
|
||
>
|
||
<CheckCircleIcon className="size-3" />
|
||
{name}
|
||
{rule.amount && (
|
||
<span className="text-green-400/60">×{rule.amount}</span>
|
||
)}
|
||
</span>
|
||
);
|
||
})}
|
||
</div>
|
||
</div>
|
||
)}
|
||
{hasProhibited && (
|
||
<div className="flex flex-col gap-1.5">
|
||
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
||
Prohibited
|
||
</span>
|
||
<div className="flex flex-wrap gap-1.5">
|
||
{prohibitedStorage!.map((rule, index) => {
|
||
if (!rule.item) return null;
|
||
const item = rule.item;
|
||
const value = item.value;
|
||
const name =
|
||
typeof value === "object" && value !== null && "name" in value
|
||
? String(value.name)
|
||
: `Item #${value}`;
|
||
return (
|
||
<span
|
||
key={rule.id ?? index}
|
||
className="text-xs bg-red-500/10 text-red-400 border border-red-500/20 px-2 py-0.5 rounded-md flex items-center gap-1"
|
||
>
|
||
<XCircleIcon className="size-3" />
|
||
{name}
|
||
</span>
|
||
);
|
||
})}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</ItemContent>
|
||
</Item>
|
||
);
|
||
}
|