summaryrefslogtreecommitdiff
path: root/components/pq-input
diff options
context:
space:
mode:
Diffstat (limited to 'components/pq-input')
-rw-r--r--components/pq-input/pq-input-tabs.tsx136
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>