refactor(catalog): extract AddItemFormFields from CatalogItemsTable
Split the Add Item dialog form fields into its own module, reducing the main table component size while preserving all form fields, validation and handler logic.
This commit is contained in:
1 parent
8638e81444
commit
3862649369
2 files changed
+176
-165
No files matched your search
@@ -0,0 +1,175 @@
|
||||
"use client";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { type DEFAULT_NEW_ITEM, POINTS_TYPES } from "./types";
|
||||
|
||||
export interface AddItemFormFieldsProps {
|
||||
data: typeof DEFAULT_NEW_ITEM;
|
||||
onChange: (key: string, value: string | number) => void;
|
||||
}
|
||||
|
||||
export function AddItemFormFields({ data, onChange }: AddItemFormFieldsProps) {
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-2">
|
||||
<Label>Catalog Name</Label>
|
||||
<Input
|
||||
value={data.catalogName}
|
||||
onChange={(e) => onChange("catalogName", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>Item IDs (semicolon-separated)</Label>
|
||||
<Input
|
||||
value={data.itemIds}
|
||||
onChange={(e) => onChange("itemIds", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-2">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Credits</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.costCredits}
|
||||
onChange={(e) =>
|
||||
onChange("costCredits", parseInt(e.target.value, 10) || 0)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Points</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.costPoints}
|
||||
onChange={(e) =>
|
||||
onChange("costPoints", parseInt(e.target.value, 10) || 0)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Points Type</Label>
|
||||
<Select
|
||||
value={String(data.pointsType)}
|
||||
onValueChange={(v) => onChange("pointsType", parseInt(v, 10))}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{Object.entries(POINTS_TYPES).map(([val, { label }]) => (
|
||||
<SelectItem key={val} value={val}>
|
||||
{label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-2">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Amount</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.amount}
|
||||
onChange={(e) =>
|
||||
onChange("amount", parseInt(e.target.value, 10) || 1)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Order</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.orderNumber}
|
||||
onChange={(e) =>
|
||||
onChange("orderNumber", parseInt(e.target.value, 10) || 0)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Offer ID</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.offerId}
|
||||
onChange={(e) => onChange("offerId", parseInt(e.target.value, 10))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Limited Sells</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.limitedSells}
|
||||
onChange={(e) =>
|
||||
onChange("limitedSells", parseInt(e.target.value, 10) || 0)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Limited Stack</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.limitedStack}
|
||||
onChange={(e) =>
|
||||
onChange("limitedStack", parseInt(e.target.value, 10) || 0)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Have Offer</Label>
|
||||
<Select
|
||||
value={data.haveOffer}
|
||||
onValueChange={(v) => onChange("haveOffer", v)}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">Yes</SelectItem>
|
||||
<SelectItem value="0">No</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Club Only</Label>
|
||||
<Select
|
||||
value={data.clubOnly}
|
||||
onValueChange={(v) => onChange("clubOnly", v)}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="0">No</SelectItem>
|
||||
<SelectItem value="1">Yes</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label>Extra Data</Label>
|
||||
<Input
|
||||
value={data.extradata}
|
||||
onChange={(e) => onChange("extradata", e.target.value)}
|
||||
placeholder="Optional extra data"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -95,6 +95,7 @@ import {
|
||||
MovePageCombobox,
|
||||
ToggleField,
|
||||
} from "./field-helpers";
|
||||
import { AddItemFormFields } from "./add-item-form-fields";
|
||||
import { FurniIcon } from "./furni-icon";
|
||||
import { SongPicker } from "./song-picker";
|
||||
import {
|
||||
@@ -796,171 +797,6 @@ export function CatalogItemsTable({
|
||||
}
|
||||
|
||||
// ── Add Item Form Fields (for "Add" dialog) ───────────────────
|
||||
function AddItemFormFields({
|
||||
data,
|
||||
onChange,
|
||||
}: {
|
||||
data: typeof DEFAULT_NEW_ITEM;
|
||||
onChange: (key: string, value: string | number) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-2">
|
||||
<Label>Catalog Name</Label>
|
||||
<Input
|
||||
value={data.catalogName}
|
||||
onChange={(e) => onChange("catalogName", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>Item IDs (semicolon-separated)</Label>
|
||||
<Input
|
||||
value={data.itemIds}
|
||||
onChange={(e) => onChange("itemIds", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-2">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Credits</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.costCredits}
|
||||
onChange={(e) =>
|
||||
onChange("costCredits", parseInt(e.target.value, 10) || 0)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Points</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.costPoints}
|
||||
onChange={(e) =>
|
||||
onChange("costPoints", parseInt(e.target.value, 10) || 0)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Points Type</Label>
|
||||
<Select
|
||||
value={String(data.pointsType)}
|
||||
onValueChange={(v) => onChange("pointsType", parseInt(v, 10))}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{Object.entries(POINTS_TYPES).map(([val, { label }]) => (
|
||||
<SelectItem key={val} value={val}>
|
||||
{label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-2">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Amount</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.amount}
|
||||
onChange={(e) =>
|
||||
onChange("amount", parseInt(e.target.value, 10) || 1)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Order</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.orderNumber}
|
||||
onChange={(e) =>
|
||||
onChange("orderNumber", parseInt(e.target.value, 10) || 0)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Offer ID</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.offerId}
|
||||
onChange={(e) =>
|
||||
onChange("offerId", parseInt(e.target.value, 10))
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Limited Sells</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.limitedSells}
|
||||
onChange={(e) =>
|
||||
onChange("limitedSells", parseInt(e.target.value, 10) || 0)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Limited Stack</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={data.limitedStack}
|
||||
onChange={(e) =>
|
||||
onChange("limitedStack", parseInt(e.target.value, 10) || 0)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Have Offer</Label>
|
||||
<Select
|
||||
value={data.haveOffer}
|
||||
onValueChange={(v) => onChange("haveOffer", v)}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">Yes</SelectItem>
|
||||
<SelectItem value="0">No</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Club Only</Label>
|
||||
<Select
|
||||
value={data.clubOnly}
|
||||
onValueChange={(v) => onChange("clubOnly", v)}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="0">No</SelectItem>
|
||||
<SelectItem value="1">Yes</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label>Extra Data</Label>
|
||||
<Input
|
||||
value={data.extradata}
|
||||
onChange={(e) => onChange("extradata", e.target.value)}
|
||||
placeholder="Optional extra data"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
Reference in new issue
Block a user