diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-11-18 10:33:20 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-11-18 10:33:20 +0000 |
| commit | 41ad2455ac47d8e2da331d7240ded1354df9a784 (patch) | |
| tree | 7980d9a6e260f774dd3ff97c541399a32b9c9b4f /components/pq-input/pq-input-tabs.tsx | |
| parent | 1e6d30c9f649dcaa0c1d24561af35d7a77fd51b2 (diff) | |
(최겸) 구매 피드백 반영
Diffstat (limited to 'components/pq-input/pq-input-tabs.tsx')
| -rw-r--r-- | components/pq-input/pq-input-tabs.tsx | 136 |
1 files changed, 109 insertions, 27 deletions
diff --git a/components/pq-input/pq-input-tabs.tsx b/components/pq-input/pq-input-tabs.tsx index f0d44d04..df911d5e 100644 --- a/components/pq-input/pq-input-tabs.tsx +++ b/components/pq-input/pq-input-tabs.tsx @@ -276,6 +276,55 @@ export function PQInputTabs({ setAllSaved(allItemsSaved) }, [form.watch()]) + // ---------------------------------------------------------------------- + // C-1) Calculate item counts for display + // ---------------------------------------------------------------------- + + // ---------------------------------------------------------------------- + // C-2) Tab color mapping for better visual distinction + // ---------------------------------------------------------------------- + const getTabColorClasses = (groupName: string) => { + switch (groupName.toLowerCase()) { + case 'general': + return { + tab: 'data-[state=active]:bg-blue-50 data-[state=active]:text-blue-700 data-[state=active]:border-blue-200', + badge: 'bg-blue-100 text-blue-800 border-blue-200' + } + case 'hsg': + return { + tab: 'data-[state=active]:bg-green-50 data-[state=active]:text-green-700 data-[state=active]:border-green-200', + badge: 'bg-green-100 text-green-800 border-green-200' + } + case 'qms': + return { + tab: 'data-[state=active]:bg-orange-50 data-[state=active]:text-orange-700 data-[state=active]:border-orange-200', + badge: 'bg-orange-100 text-orange-800 border-orange-200' + } + case 'warranty': + return { + tab: 'data-[state=active]:bg-red-50 data-[state=active]:text-red-700 data-[state=active]:border-red-200', + badge: 'bg-red-100 text-red-800 border-red-200' + } + default: + return { + tab: 'data-[state=active]:bg-gray-50 data-[state=active]:text-gray-700 data-[state=active]:border-gray-200', + badge: 'bg-gray-100 text-gray-800 border-gray-200' + } + } + } + const getItemCounts = () => { + const values = form.getValues() + const totalItems = values.answers.length + const savedItems = values.answers.filter( + (answer) => answer.saved && (answer.answer || answer.uploadedFiles.length > 0) + ).length + const notSavedItems = totalItems - savedItems + + return { totalItems, savedItems, notSavedItems } + } + + const { totalItems, savedItems, notSavedItems } = getItemCounts() + // Helper to find the array index by criteriaId const getAnswerIndex = (criteriaId: number): number => { return form.getValues().answers.findIndex((a) => a.criteriaId === criteriaId) @@ -677,6 +726,30 @@ export function PQInputTabs({ <Tabs defaultValue={data[0]?.groupName || ""} className="w-full"> {/* Top Controls - Sticky Header */} <div className="sticky top-0 z-10 bg-background border-b border-border mb-4 pb-4"> + {/* Item Count Display */} + <div className="mb-3 flex items-center gap-6 text-sm"> + <div className="flex items-center gap-4"> + <span className="font-medium">총 항목:</span> + <Badge variant="outline" className="text-xs"> + {totalItems} + </Badge> + </div> + <div className="flex items-center gap-2"> + <CheckCircle2 className="h-4 w-4 text-green-600" /> + <span className="text-green-600 font-medium">Saved:</span> + <Badge variant="outline" className="bg-green-50 text-green-700 border-green-200 text-xs"> + {savedItems} + </Badge> + </div> + <div className="flex items-center gap-2"> + <AlertTriangle className="h-4 w-4 text-amber-600" /> + <span className="text-amber-600 font-medium">Not Saved:</span> + <Badge variant="outline" className="bg-amber-50 text-amber-700 border-amber-200 text-xs"> + {notSavedItems} + </Badge> + </div> + </div> + {/* Filter Controls */} <div className="mb-3 flex items-center gap-4"> <span className="text-sm font-medium">필터:</span> @@ -702,8 +775,11 @@ export function PQInputTabs({ checked={filterOptions.showSaved} onCheckedChange={(checked) => { const newOptions = { ...filterOptions, showSaved: !!checked }; - if (!checked && !filterOptions.showAll && !filterOptions.showNotSaved) { - // 최소 하나는 체크되어 있어야 함 + // Save 항목이나 Not Save 항목을 선택하면 전체 항목 자동 해제 + if (checked) { + newOptions.showAll = false; + } else if (!filterOptions.showNotSaved && !filterOptions.showAll) { + // 최소 하나는 체크되어 있어야 함 - 모두 해제되면 전체 항목 체크 newOptions.showAll = true; } setFilterOptions(newOptions); @@ -717,8 +793,11 @@ export function PQInputTabs({ checked={filterOptions.showNotSaved} onCheckedChange={(checked) => { const newOptions = { ...filterOptions, showNotSaved: !!checked }; - if (!checked && !filterOptions.showAll && !filterOptions.showSaved) { - // 최소 하나는 체크되어 있어야 함 + // Save 항목이나 Not Save 항목을 선택하면 전체 항목 자동 해제 + if (checked) { + newOptions.showAll = false; + } else if (!filterOptions.showSaved && !filterOptions.showAll) { + // 최소 하나는 체크되어 있어야 함 - 모두 해제되면 전체 항목 체크 newOptions.showAll = true; } setFilterOptions(newOptions); @@ -731,27 +810,30 @@ export function PQInputTabs({ <div className="flex justify-between items-center"> <TabsList className="grid grid-cols-4"> - {data.map((group) => ( - <TabsTrigger - key={group.groupName} - value={group.groupName} - className="truncate" - > - <div className="flex items-center gap-2"> - {/* Mobile: truncated version */} - <span className="block sm:hidden"> - {group.groupName.length > 5 - ? group.groupName.slice(0, 5) + "..." - : group.groupName} - </span> - {/* Desktop: full text */} - <span className="hidden sm:block">{group.groupName}</span> - <span className="inline-flex items-center justify-center h-5 min-w-5 px-1 rounded-full bg-muted text-xs font-medium"> - {group.items.length} - </span> - </div> - </TabsTrigger> - ))} + {data.map((group) => { + const colorClasses = getTabColorClasses(group.groupName) + return ( + <TabsTrigger + key={group.groupName} + value={group.groupName} + className={`truncate ${colorClasses.tab}`} + > + <div className="flex items-center gap-2"> + {/* Mobile: truncated version */} + <span className="block sm:hidden"> + {group.groupName.length > 5 + ? group.groupName.slice(0, 5) + "..." + : group.groupName} + </span> + {/* Desktop: full text */} + <span className="hidden sm:block">{group.groupName}</span> + <span className={`inline-flex items-center justify-center h-5 min-w-5 px-1 rounded-full text-xs font-medium ${colorClasses.badge}`}> + {group.items.length} + </span> + </div> + </TabsTrigger> + ) + })} </TabsList> <div className="flex gap-2"> @@ -849,13 +931,13 @@ export function PQInputTabs({ {/* Save Status & Button */} <div className="flex items-center gap-2"> {!isSaved && canSave && ( - <span className="text-amber-600 text-xs flex items-center"> + <span className="text-amber-600 text-sm font-medium flex items-center"> <AlertTriangle className="h-4 w-4 mr-1" /> Not Saved </span> )} {isSaved && ( - <span className="text-green-600 text-xs flex items-center"> + <span className="text-green-600 text-sm font-medium flex items-center"> <CheckCircle2 className="h-4 w-4 mr-1" /> Saved </span> |
