feat: Add image upload functionality to item info page

- Integrated ImageUpload component for handling item images in the item info form.
- Updated the data table to include an image column, allowing for image display.
- Enhanced form fields to support image uploads, improving the user experience for managing item images.

These changes aim to provide a more comprehensive item management experience by allowing users to upload and view images directly within the item info page.
This commit is contained in:
kjs
2026-04-07 09:53:30 +09:00
parent f2ebd6ae1b
commit 2494a96bad

View File

@@ -36,6 +36,7 @@ import {
Pencil, Copy, Settings2, Check, ChevronsUpDown,
} from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { ImageUpload } from "@/components/common/ImageUpload";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { EDataTable, EDataTableColumn } from "@/components/common/EDataTable";
@@ -88,6 +89,7 @@ const TABLE_NAME = "item_info";
const GRID_COLUMNS = [
{ key: "item_number", label: "품목코드" },
{ key: "item_name", label: "품명" },
{ key: "image", label: "이미지", type: "image" },
{ key: "division", label: "관리품목" },
{ key: "type", label: "품목구분" },
{ key: "size", label: "규격" },
@@ -122,6 +124,7 @@ const FORM_FIELDS = [
{ key: "user_type01", label: "대분류", type: "category" },
{ key: "user_type02", label: "중분류", type: "category" },
{ key: "lead_time", label: "생산 리드타임(일)", type: "text", placeholder: "숫자 입력 (예: 7)" },
{ key: "image", label: "품목 이미지", type: "image" },
{ key: "meno", label: "메모", type: "textarea" },
];
@@ -407,8 +410,14 @@ export default function ItemInfoPage() {
columns={ts.visibleColumns.map((col): EDataTableColumn => ({
key: col.key,
label: col.label,
align: col.align as "left" | "center" | "right" | undefined,
align: (col as any).type === "image" ? "center" : col.align as "left" | "center" | "right" | undefined,
formatNumber: (col as any).formatNumber,
width: (col as any).type === "image" ? "w-[50px]" : undefined,
render: (col as any).type === "image" ? (val: any) => (
val ? (
<img src={String(val).startsWith("http") || String(val).startsWith("/") ? val : `/api/files/preview/${val}`} alt="" className="h-8 w-8 rounded object-cover border border-border mx-auto" onError={(e) => { (e.target as HTMLImageElement).style.display = "none"; }} />
) : <div className="h-8 w-8 rounded bg-muted mx-auto" />
) : undefined,
}))}
data={ts.groupData(items)}
loading={loading}
@@ -435,13 +444,22 @@ export default function ItemInfoPage() {
{FORM_FIELDS.map((field) => (
<div
key={field.key}
className={cn("space-y-1.5", field.type === "textarea" && "col-span-2")}
className={cn("space-y-1.5", (field.type === "textarea" || field.type === "image") && "col-span-2")}
>
<Label className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
{field.label}
{field.required && <span className="text-destructive ml-1">*</span>}
</Label>
{field.type === "category" ? (
{field.type === "image" ? (
<ImageUpload
value={formData[field.key] || ""}
onChange={(v) => setFormData((prev) => ({ ...prev, [field.key]: v }))}
tableName={TABLE_NAME}
recordId={formData.id || ""}
columnName={field.key}
height="h-32"
/>
) : field.type === "category" ? (
<CategoryCombobox
options={categoryOptions[field.key] || []}
value={formData[field.key] || ""}