feat: 카테고리 배지 없음 옵션 추가
- 카테고리 색상 설정 시 '배지 없음' 옵션 추가 - color='none'일 때 배지 대신 일반 텍스트로 표시 - CategoryValueEditDialog, CategoryValueAddDialog에 배지 없음 버튼 추가 - InteractiveDataTable, TableListComponent에서 배지 없음 처리 - CategoryValueManager에서 배지 없음 표시 추가 - 기본 색상을 배지 없음으로 변경
This commit is contained in:
parent
f73f788b0a
commit
a828f54663
|
|
@ -1961,7 +1961,7 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
|
|||
// 실제 웹 타입으로 스위치 (input_type="category"도 포함됨)
|
||||
switch (actualWebType) {
|
||||
case "category": {
|
||||
// 카테고리 타입: 배지로 표시
|
||||
// 카테고리 타입: 배지로 표시 (배지 없음 옵션 지원)
|
||||
if (!value) return "";
|
||||
|
||||
const mapping = categoryMappings[column.columnName];
|
||||
|
|
@ -1971,6 +1971,11 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
|
|||
const displayLabel = categoryData?.label || String(value);
|
||||
const displayColor = categoryData?.color || "#64748b"; // 기본 slate 색상
|
||||
|
||||
// 배지 없음 옵션: color가 "none"이면 텍스트만 표시
|
||||
if (displayColor === "none") {
|
||||
return <span className="text-sm">{displayLabel}</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Badge
|
||||
style={{
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export const CategoryValueAddDialog: React.FC<
|
|||
> = ({ open, onOpenChange, onAdd, columnLabel }) => {
|
||||
const [valueLabel, setValueLabel] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
const [color, setColor] = useState("#3b82f6");
|
||||
const [color, setColor] = useState("none");
|
||||
|
||||
// 라벨에서 코드 자동 생성
|
||||
const generateCode = (label: string): string => {
|
||||
|
|
@ -91,7 +91,7 @@ export const CategoryValueAddDialog: React.FC<
|
|||
// 초기화
|
||||
setValueLabel("");
|
||||
setDescription("");
|
||||
setColor("#3b82f6");
|
||||
setColor("none");
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -123,24 +123,41 @@ export const CategoryValueAddDialog: React.FC<
|
|||
|
||||
<div>
|
||||
<Label className="text-xs sm:text-sm">배지 색상</Label>
|
||||
<div className="mt-1.5 flex items-center gap-3">
|
||||
<div className="grid grid-cols-9 gap-2">
|
||||
{DEFAULT_COLORS.map((c) => (
|
||||
<button
|
||||
key={c}
|
||||
type="button"
|
||||
onClick={() => setColor(c)}
|
||||
className={`h-7 w-7 rounded-md border-2 transition-all ${
|
||||
color === c ? "border-foreground scale-110" : "border-transparent hover:scale-105"
|
||||
}`}
|
||||
style={{ backgroundColor: c }}
|
||||
title={c}
|
||||
/>
|
||||
))}
|
||||
<div className="mt-1.5 space-y-2">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="grid grid-cols-9 gap-2">
|
||||
{DEFAULT_COLORS.map((c) => (
|
||||
<button
|
||||
key={c}
|
||||
type="button"
|
||||
onClick={() => setColor(c)}
|
||||
className={`h-7 w-7 rounded-md border-2 transition-all ${
|
||||
color === c ? "border-foreground scale-110" : "border-transparent hover:scale-105"
|
||||
}`}
|
||||
style={{ backgroundColor: c }}
|
||||
title={c}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{color && color !== "none" ? (
|
||||
<Badge style={{ backgroundColor: color, borderColor: color }} className="text-white">
|
||||
미리보기
|
||||
</Badge>
|
||||
) : (
|
||||
<span className="text-xs text-muted-foreground">배지 없음</span>
|
||||
)}
|
||||
</div>
|
||||
<Badge style={{ backgroundColor: color, borderColor: color }} className="text-white">
|
||||
미리보기
|
||||
</Badge>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setColor("none")}
|
||||
className={`text-xs px-3 py-1.5 rounded-md border transition-colors ${
|
||||
color === "none"
|
||||
? "border-primary bg-primary/10 text-primary font-medium"
|
||||
: "border-border hover:bg-accent"
|
||||
}`}
|
||||
>
|
||||
배지 없음
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -51,12 +51,12 @@ export const CategoryValueEditDialog: React.FC<
|
|||
> = ({ open, onOpenChange, value, onUpdate, columnLabel }) => {
|
||||
const [valueLabel, setValueLabel] = useState(value.valueLabel);
|
||||
const [description, setDescription] = useState(value.description || "");
|
||||
const [color, setColor] = useState(value.color || "#3b82f6");
|
||||
const [color, setColor] = useState(value.color || "none");
|
||||
|
||||
useEffect(() => {
|
||||
setValueLabel(value.valueLabel);
|
||||
setDescription(value.description || "");
|
||||
setColor(value.color || "#3b82f6");
|
||||
setColor(value.color || "none");
|
||||
}, [value]);
|
||||
|
||||
const handleSubmit = () => {
|
||||
|
|
@ -100,24 +100,41 @@ export const CategoryValueEditDialog: React.FC<
|
|||
|
||||
<div>
|
||||
<Label className="text-xs sm:text-sm">배지 색상</Label>
|
||||
<div className="mt-1.5 flex items-center gap-3">
|
||||
<div className="grid grid-cols-9 gap-2">
|
||||
{DEFAULT_COLORS.map((c) => (
|
||||
<button
|
||||
key={c}
|
||||
type="button"
|
||||
onClick={() => setColor(c)}
|
||||
className={`h-7 w-7 rounded-md border-2 transition-all ${
|
||||
color === c ? "border-foreground scale-110" : "border-transparent hover:scale-105"
|
||||
}`}
|
||||
style={{ backgroundColor: c }}
|
||||
title={c}
|
||||
/>
|
||||
))}
|
||||
<div className="mt-1.5 space-y-2">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="grid grid-cols-9 gap-2">
|
||||
{DEFAULT_COLORS.map((c) => (
|
||||
<button
|
||||
key={c}
|
||||
type="button"
|
||||
onClick={() => setColor(c)}
|
||||
className={`h-7 w-7 rounded-md border-2 transition-all ${
|
||||
color === c ? "border-foreground scale-110" : "border-transparent hover:scale-105"
|
||||
}`}
|
||||
style={{ backgroundColor: c }}
|
||||
title={c}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{color && color !== "none" ? (
|
||||
<Badge style={{ backgroundColor: color, borderColor: color }} className="text-white">
|
||||
미리보기
|
||||
</Badge>
|
||||
) : (
|
||||
<span className="text-xs text-muted-foreground">배지 없음</span>
|
||||
)}
|
||||
</div>
|
||||
<Badge style={{ backgroundColor: color, borderColor: color }} className="text-white">
|
||||
미리보기
|
||||
</Badge>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setColor("none")}
|
||||
className={`text-xs px-3 py-1.5 rounded-md border transition-colors ${
|
||||
color === "none"
|
||||
? "border-primary bg-primary/10 text-primary font-medium"
|
||||
: "border-border hover:bg-accent"
|
||||
}`}
|
||||
>
|
||||
배지 없음
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -349,13 +349,18 @@ export const CategoryValueManager: React.FC<CategoryValueManagerProps> = ({
|
|||
/>
|
||||
|
||||
<div className="flex flex-1 items-center gap-2">
|
||||
{/* 색상 표시 (앞쪽으로 이동) */}
|
||||
{value.color && (
|
||||
{/* 색상 표시 (배지 없음 옵션 지원) */}
|
||||
{value.color && value.color !== "none" && (
|
||||
<div
|
||||
className="h-4 w-4 rounded-full border flex-shrink-0"
|
||||
style={{ backgroundColor: value.color }}
|
||||
/>
|
||||
)}
|
||||
{value.color === "none" && (
|
||||
<span className="text-[10px] text-muted-foreground px-1.5 py-0.5 bg-muted rounded">
|
||||
배지 없음
|
||||
</span>
|
||||
)}
|
||||
|
||||
{/* 라벨 */}
|
||||
<span className={`text-sm font-medium ${isInactive ? "line-through" : ""}`}>
|
||||
|
|
|
|||
|
|
@ -1374,28 +1374,22 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
);
|
||||
}
|
||||
|
||||
// 카테고리 타입: 배지로 표시
|
||||
// 카테고리 타입: 배지로 표시 (배지 없음 옵션 지원)
|
||||
if (inputType === "category") {
|
||||
if (!value) return "";
|
||||
|
||||
const mapping = categoryMappings[column.columnName];
|
||||
const categoryData = mapping?.[String(value)];
|
||||
|
||||
// console.log(`🎨 [카테고리 배지] ${column.columnName}:`, {
|
||||
// value,
|
||||
// stringValue: String(value),
|
||||
// mapping,
|
||||
// categoryData,
|
||||
// hasMapping: !!mapping,
|
||||
// hasCategoryData: !!categoryData,
|
||||
// allCategoryMappings: categoryMappings, // 전체 매핑 확인
|
||||
// categoryMappingsKeys: Object.keys(categoryMappings),
|
||||
// });
|
||||
|
||||
// 매핑 데이터가 있으면 라벨과 색상 사용, 없으면 코드값과 기본색상
|
||||
const displayLabel = categoryData?.label || String(value);
|
||||
const displayColor = categoryData?.color || "#64748b"; // 기본 slate 색상
|
||||
|
||||
// 배지 없음 옵션: color가 "none"이면 텍스트만 표시
|
||||
if (displayColor === "none") {
|
||||
return <span className="text-sm">{displayLabel}</span>;
|
||||
}
|
||||
|
||||
const { Badge } = require("@/components/ui/badge");
|
||||
return (
|
||||
<Badge
|
||||
|
|
|
|||
Loading…
Reference in New Issue