create-arete-workspace 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/README.md +77 -0
  2. package/bin/arete.js +156 -0
  3. package/bin/create.js +111 -0
  4. package/lib/install-openclaw.js +50 -0
  5. package/lib/scaffold.js +213 -0
  6. package/lib/setup-wizard.js +88 -0
  7. package/lib/updater.js +130 -0
  8. package/package.json +34 -0
  9. package/packages/gatsaeng-os/README.md +36 -0
  10. package/packages/gatsaeng-os/components.json +23 -0
  11. package/packages/gatsaeng-os/eslint.config.mjs +18 -0
  12. package/packages/gatsaeng-os/next.config.ts +7 -0
  13. package/packages/gatsaeng-os/package.json +59 -0
  14. package/packages/gatsaeng-os/postcss.config.mjs +7 -0
  15. package/packages/gatsaeng-os/public/file.svg +1 -0
  16. package/packages/gatsaeng-os/public/globe.svg +1 -0
  17. package/packages/gatsaeng-os/public/next.svg +1 -0
  18. package/packages/gatsaeng-os/public/vercel.svg +1 -0
  19. package/packages/gatsaeng-os/public/window.svg +1 -0
  20. package/packages/gatsaeng-os/python/api_server.py +248 -0
  21. package/packages/gatsaeng-os/python/briefing.py +145 -0
  22. package/packages/gatsaeng-os/python/config.py +55 -0
  23. package/packages/gatsaeng-os/python/goal_context_agent.py +193 -0
  24. package/packages/gatsaeng-os/python/gyeokguk.py +171 -0
  25. package/packages/gatsaeng-os/python/proactive.py +158 -0
  26. package/packages/gatsaeng-os/python/requirements.txt +11 -0
  27. package/packages/gatsaeng-os/python/run.py +28 -0
  28. package/packages/gatsaeng-os/python/scoring.py +44 -0
  29. package/packages/gatsaeng-os/python/streak.py +70 -0
  30. package/packages/gatsaeng-os/python/telegram_bot.py +331 -0
  31. package/packages/gatsaeng-os/python/timing_engine.py +117 -0
  32. package/packages/gatsaeng-os/python/vault_io.py +423 -0
  33. package/packages/gatsaeng-os/src/app/(dashboard)/areas/[id]/page.tsx +215 -0
  34. package/packages/gatsaeng-os/src/app/(dashboard)/areas/page.tsx +161 -0
  35. package/packages/gatsaeng-os/src/app/(dashboard)/books/[id]/page.tsx +215 -0
  36. package/packages/gatsaeng-os/src/app/(dashboard)/books/page.tsx +268 -0
  37. package/packages/gatsaeng-os/src/app/(dashboard)/calendar/page.tsx +379 -0
  38. package/packages/gatsaeng-os/src/app/(dashboard)/error.tsx +30 -0
  39. package/packages/gatsaeng-os/src/app/(dashboard)/focus/page.tsx +293 -0
  40. package/packages/gatsaeng-os/src/app/(dashboard)/goals/[id]/page.tsx +426 -0
  41. package/packages/gatsaeng-os/src/app/(dashboard)/goals/page.tsx +178 -0
  42. package/packages/gatsaeng-os/src/app/(dashboard)/layout.tsx +29 -0
  43. package/packages/gatsaeng-os/src/app/(dashboard)/notes/[id]/page.tsx +147 -0
  44. package/packages/gatsaeng-os/src/app/(dashboard)/notes/page.tsx +254 -0
  45. package/packages/gatsaeng-os/src/app/(dashboard)/page.tsx +26 -0
  46. package/packages/gatsaeng-os/src/app/(dashboard)/projects/[id]/page.tsx +86 -0
  47. package/packages/gatsaeng-os/src/app/(dashboard)/projects/page.tsx +215 -0
  48. package/packages/gatsaeng-os/src/app/(dashboard)/review/page.tsx +475 -0
  49. package/packages/gatsaeng-os/src/app/(dashboard)/routines/page.tsx +436 -0
  50. package/packages/gatsaeng-os/src/app/(dashboard)/tasks/[id]/page.tsx +210 -0
  51. package/packages/gatsaeng-os/src/app/(dashboard)/tasks/page.tsx +307 -0
  52. package/packages/gatsaeng-os/src/app/(dashboard)/voice/page.tsx +212 -0
  53. package/packages/gatsaeng-os/src/app/api/areas/[id]/route.ts +26 -0
  54. package/packages/gatsaeng-os/src/app/api/areas/route.ts +22 -0
  55. package/packages/gatsaeng-os/src/app/api/auth/login/route.ts +52 -0
  56. package/packages/gatsaeng-os/src/app/api/auth/logout/route.ts +8 -0
  57. package/packages/gatsaeng-os/src/app/api/books/[id]/route.ts +27 -0
  58. package/packages/gatsaeng-os/src/app/api/books/route.ts +20 -0
  59. package/packages/gatsaeng-os/src/app/api/calendar/[id]/route.ts +24 -0
  60. package/packages/gatsaeng-os/src/app/api/calendar/import/route.ts +52 -0
  61. package/packages/gatsaeng-os/src/app/api/calendar/route.ts +37 -0
  62. package/packages/gatsaeng-os/src/app/api/daily/route.ts +51 -0
  63. package/packages/gatsaeng-os/src/app/api/goals/[id]/route.ts +34 -0
  64. package/packages/gatsaeng-os/src/app/api/goals/route.ts +30 -0
  65. package/packages/gatsaeng-os/src/app/api/logs/energy/route.ts +40 -0
  66. package/packages/gatsaeng-os/src/app/api/logs/focus/route.ts +22 -0
  67. package/packages/gatsaeng-os/src/app/api/logs/routine/route.ts +54 -0
  68. package/packages/gatsaeng-os/src/app/api/milestones/[id]/route.ts +26 -0
  69. package/packages/gatsaeng-os/src/app/api/milestones/route.ts +47 -0
  70. package/packages/gatsaeng-os/src/app/api/notes/[id]/route.ts +29 -0
  71. package/packages/gatsaeng-os/src/app/api/notes/route.ts +37 -0
  72. package/packages/gatsaeng-os/src/app/api/profile/route.ts +17 -0
  73. package/packages/gatsaeng-os/src/app/api/projects/[id]/route.ts +27 -0
  74. package/packages/gatsaeng-os/src/app/api/projects/route.ts +25 -0
  75. package/packages/gatsaeng-os/src/app/api/reviews/[id]/route.ts +26 -0
  76. package/packages/gatsaeng-os/src/app/api/reviews/route.ts +29 -0
  77. package/packages/gatsaeng-os/src/app/api/routines/[id]/route.ts +26 -0
  78. package/packages/gatsaeng-os/src/app/api/routines/route.ts +28 -0
  79. package/packages/gatsaeng-os/src/app/api/tasks/[id]/route.ts +28 -0
  80. package/packages/gatsaeng-os/src/app/api/tasks/route.ts +66 -0
  81. package/packages/gatsaeng-os/src/app/api/timing/current/route.ts +63 -0
  82. package/packages/gatsaeng-os/src/app/api/voice/chat/route.ts +50 -0
  83. package/packages/gatsaeng-os/src/app/api/voice/transcribe/route.ts +25 -0
  84. package/packages/gatsaeng-os/src/app/api/voice/tts/route.ts +36 -0
  85. package/packages/gatsaeng-os/src/app/error.tsx +30 -0
  86. package/packages/gatsaeng-os/src/app/favicon.ico +0 -0
  87. package/packages/gatsaeng-os/src/app/globals.css +208 -0
  88. package/packages/gatsaeng-os/src/app/layout.tsx +33 -0
  89. package/packages/gatsaeng-os/src/app/login/page.tsx +87 -0
  90. package/packages/gatsaeng-os/src/app/providers.tsx +27 -0
  91. package/packages/gatsaeng-os/src/components/ErrorBoundary.tsx +46 -0
  92. package/packages/gatsaeng-os/src/components/dashboard/DashboardGrid.tsx +86 -0
  93. package/packages/gatsaeng-os/src/components/dashboard/DdayWidget.tsx +88 -0
  94. package/packages/gatsaeng-os/src/components/dashboard/EnergyTracker.tsx +87 -0
  95. package/packages/gatsaeng-os/src/components/dashboard/FocusTimer.tsx +139 -0
  96. package/packages/gatsaeng-os/src/components/dashboard/GatsaengScore.tsx +30 -0
  97. package/packages/gatsaeng-os/src/components/dashboard/GoalRings.tsx +107 -0
  98. package/packages/gatsaeng-os/src/components/dashboard/ProactiveBar.tsx +98 -0
  99. package/packages/gatsaeng-os/src/components/dashboard/RoutineChecklist.tsx +81 -0
  100. package/packages/gatsaeng-os/src/components/dashboard/TimingWidget.tsx +86 -0
  101. package/packages/gatsaeng-os/src/components/dashboard/WidgetCustomizer.tsx +95 -0
  102. package/packages/gatsaeng-os/src/components/dashboard/WidgetWrapper.tsx +33 -0
  103. package/packages/gatsaeng-os/src/components/dashboard/ZeigarnikPanel.tsx +43 -0
  104. package/packages/gatsaeng-os/src/components/editor/EditorToolbar.tsx +186 -0
  105. package/packages/gatsaeng-os/src/components/editor/TiptapEditor.tsx +114 -0
  106. package/packages/gatsaeng-os/src/components/layout/Header.tsx +47 -0
  107. package/packages/gatsaeng-os/src/components/layout/MobileBottomNav.tsx +122 -0
  108. package/packages/gatsaeng-os/src/components/layout/MobileSidebar.tsx +29 -0
  109. package/packages/gatsaeng-os/src/components/layout/Sidebar.tsx +142 -0
  110. package/packages/gatsaeng-os/src/components/onboarding/OnboardingFlow.tsx +229 -0
  111. package/packages/gatsaeng-os/src/components/onboarding/OnboardingGate.tsx +78 -0
  112. package/packages/gatsaeng-os/src/components/projects/CalendarView.tsx +152 -0
  113. package/packages/gatsaeng-os/src/components/projects/KanbanView.tsx +180 -0
  114. package/packages/gatsaeng-os/src/components/projects/ListView.tsx +82 -0
  115. package/packages/gatsaeng-os/src/components/projects/TableView.tsx +206 -0
  116. package/packages/gatsaeng-os/src/components/projects/TaskCard.tsx +154 -0
  117. package/packages/gatsaeng-os/src/components/projects/TaskForm.tsx +128 -0
  118. package/packages/gatsaeng-os/src/components/projects/ViewSwitcher.tsx +40 -0
  119. package/packages/gatsaeng-os/src/components/search/GlobalSearch.tsx +179 -0
  120. package/packages/gatsaeng-os/src/components/shared/InlineEdit.tsx +77 -0
  121. package/packages/gatsaeng-os/src/components/shared/PinButton.tsx +42 -0
  122. package/packages/gatsaeng-os/src/components/tasks/DDayBadge.tsx +34 -0
  123. package/packages/gatsaeng-os/src/components/ui/badge.tsx +48 -0
  124. package/packages/gatsaeng-os/src/components/ui/button.tsx +64 -0
  125. package/packages/gatsaeng-os/src/components/ui/card.tsx +92 -0
  126. package/packages/gatsaeng-os/src/components/ui/checkbox.tsx +32 -0
  127. package/packages/gatsaeng-os/src/components/ui/command.tsx +184 -0
  128. package/packages/gatsaeng-os/src/components/ui/dialog.tsx +158 -0
  129. package/packages/gatsaeng-os/src/components/ui/input.tsx +21 -0
  130. package/packages/gatsaeng-os/src/components/ui/label.tsx +24 -0
  131. package/packages/gatsaeng-os/src/components/ui/popover.tsx +89 -0
  132. package/packages/gatsaeng-os/src/components/ui/progress.tsx +31 -0
  133. package/packages/gatsaeng-os/src/components/ui/select.tsx +190 -0
  134. package/packages/gatsaeng-os/src/components/ui/sheet.tsx +143 -0
  135. package/packages/gatsaeng-os/src/components/ui/tabs.tsx +91 -0
  136. package/packages/gatsaeng-os/src/components/ui/toggle-group.tsx +83 -0
  137. package/packages/gatsaeng-os/src/components/ui/toggle.tsx +47 -0
  138. package/packages/gatsaeng-os/src/components/ui/tooltip.tsx +57 -0
  139. package/packages/gatsaeng-os/src/hooks/useAreas.ts +53 -0
  140. package/packages/gatsaeng-os/src/hooks/useBooks.ts +62 -0
  141. package/packages/gatsaeng-os/src/hooks/useCalendar.ts +59 -0
  142. package/packages/gatsaeng-os/src/hooks/useDaily.ts +15 -0
  143. package/packages/gatsaeng-os/src/hooks/useGlobalTasks.ts +45 -0
  144. package/packages/gatsaeng-os/src/hooks/useGoals.ts +53 -0
  145. package/packages/gatsaeng-os/src/hooks/useMilestones.ts +75 -0
  146. package/packages/gatsaeng-os/src/hooks/useNotes.ts +65 -0
  147. package/packages/gatsaeng-os/src/hooks/useProjects.ts +102 -0
  148. package/packages/gatsaeng-os/src/hooks/useRoutines.ts +76 -0
  149. package/packages/gatsaeng-os/src/hooks/useTiming.ts +27 -0
  150. package/packages/gatsaeng-os/src/lib/apiFetch.ts +14 -0
  151. package/packages/gatsaeng-os/src/lib/auth.ts +32 -0
  152. package/packages/gatsaeng-os/src/lib/date.ts +7 -0
  153. package/packages/gatsaeng-os/src/lib/editor/markdown.ts +35 -0
  154. package/packages/gatsaeng-os/src/lib/llm-governor.ts +167 -0
  155. package/packages/gatsaeng-os/src/lib/neuroscience/energyCycle.ts +35 -0
  156. package/packages/gatsaeng-os/src/lib/neuroscience/habitStack.ts +22 -0
  157. package/packages/gatsaeng-os/src/lib/neuroscience/scoring.ts +32 -0
  158. package/packages/gatsaeng-os/src/lib/routes.ts +15 -0
  159. package/packages/gatsaeng-os/src/lib/utils.ts +6 -0
  160. package/packages/gatsaeng-os/src/lib/vault/config.ts +29 -0
  161. package/packages/gatsaeng-os/src/lib/vault/frontmatter.ts +84 -0
  162. package/packages/gatsaeng-os/src/lib/vault/index.ts +180 -0
  163. package/packages/gatsaeng-os/src/lib/vault/schemas.ts +274 -0
  164. package/packages/gatsaeng-os/src/middleware.ts +34 -0
  165. package/packages/gatsaeng-os/src/stores/dashboardStore.ts +26 -0
  166. package/packages/gatsaeng-os/src/stores/favoritesStore.ts +47 -0
  167. package/packages/gatsaeng-os/src/stores/timerStore.ts +65 -0
  168. package/packages/gatsaeng-os/src/types/index.ts +320 -0
  169. package/packages/gatsaeng-os/tsconfig.json +34 -0
  170. package/templates/scripts/forge_qa.sh.tmpl +237 -0
  171. package/templates/scripts/forge_ship.sh.tmpl +183 -0
  172. package/templates/scripts/session_indexer.py.tmpl +420 -0
  173. package/templates/scripts/tracer.py.tmpl +266 -0
  174. package/templates/workspace/AGENTS.md.tmpl +190 -0
  175. package/templates/workspace/BOOTSTRAP.md.tmpl +27 -0
  176. package/templates/workspace/HEARTBEAT.md.tmpl +23 -0
  177. package/templates/workspace/MEMORY.md.tmpl +35 -0
  178. package/templates/workspace/SOUL.md.tmpl +258 -0
  179. package/templates/workspace/TOOLS.md.tmpl +28 -0
  180. package/templates/workspace/USER.md.tmpl +43 -0
@@ -0,0 +1,215 @@
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { useProjects, useTasks, useCreateProject, useUpdateProject } from '@/hooks/useProjects'
5
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
6
+ import { Badge } from '@/components/ui/badge'
7
+ import { Button } from '@/components/ui/button'
8
+ import { Input } from '@/components/ui/input'
9
+ import { Label } from '@/components/ui/label'
10
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
11
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'
12
+ import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'
13
+ import { Progress } from '@/components/ui/progress'
14
+ import { DDayBadge } from '@/components/tasks/DDayBadge'
15
+ import { FolderKanban, Plus, Archive, CheckCircle2 } from 'lucide-react'
16
+ import { useGoals } from '@/hooks/useGoals'
17
+ import Link from 'next/link'
18
+ import type { ViewType, GoalStatus } from '@/types'
19
+
20
+ export default function ProjectsPage() {
21
+ const { data: projects, isLoading } = useProjects()
22
+ const { data: goals } = useGoals()
23
+ const { data: allTasks = [] } = useTasks()
24
+ const createProject = useCreateProject()
25
+ const updateProject = useUpdateProject()
26
+ const [open, setOpen] = useState(false)
27
+ const [tab, setTab] = useState<string>('active')
28
+
29
+ const activeProjects = (projects ?? []).filter(p => p.status === 'active')
30
+ const completedProjects = (projects ?? []).filter(p => p.status === 'completed')
31
+ const archivedProjects = (projects ?? []).filter(p => p.status === 'archived')
32
+ const displayProjects = tab === 'active' ? activeProjects
33
+ : tab === 'completed' ? completedProjects
34
+ : archivedProjects
35
+
36
+ const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
37
+ e.preventDefault()
38
+ const form = new FormData(e.currentTarget)
39
+ await createProject.mutateAsync({
40
+ title: form.get('title') as string,
41
+ description: (form.get('description') as string) || undefined,
42
+ default_view: (form.get('default_view') as ViewType) || 'kanban',
43
+ goal_id: (form.get('goal_id') as string) || undefined,
44
+ color: (form.get('color') as string) || '#58a6ff',
45
+ })
46
+ setOpen(false)
47
+ }
48
+
49
+ const handleStatusChange = (id: string, status: GoalStatus) => {
50
+ updateProject.mutate({ id, status })
51
+ }
52
+
53
+ return (
54
+ <div className="max-w-4xl mx-auto">
55
+ <div className="flex items-center justify-between mb-6">
56
+ <div>
57
+ <h1 className="text-2xl font-bold text-foreground">프로젝트</h1>
58
+ <p className="text-sm text-muted-foreground mt-1">프로젝트별 태스크 관리</p>
59
+ </div>
60
+ <Dialog open={open} onOpenChange={setOpen}>
61
+ <DialogTrigger asChild>
62
+ <Button className="bg-gatsaeng-amber hover:bg-gatsaeng-amber/80 text-black">
63
+ <Plus className="w-4 h-4 mr-2" /> 프로젝트 추가
64
+ </Button>
65
+ </DialogTrigger>
66
+ <DialogContent className="max-w-lg">
67
+ <DialogHeader>
68
+ <DialogTitle>프로젝트 만들기</DialogTitle>
69
+ </DialogHeader>
70
+ <form onSubmit={handleSubmit} className="space-y-4">
71
+ <div>
72
+ <Label>프로젝트 이름</Label>
73
+ <Input name="title" required placeholder="갓생 OS 개발" />
74
+ </div>
75
+ <div>
76
+ <Label>설명</Label>
77
+ <Input name="description" placeholder="프로젝트 설명 (선택)" />
78
+ </div>
79
+ <div className="grid grid-cols-2 gap-4">
80
+ <div>
81
+ <Label>기본 뷰</Label>
82
+ <Select name="default_view" defaultValue="kanban">
83
+ <SelectTrigger><SelectValue /></SelectTrigger>
84
+ <SelectContent>
85
+ <SelectItem value="kanban">Kanban</SelectItem>
86
+ <SelectItem value="table">Table</SelectItem>
87
+ <SelectItem value="list">List</SelectItem>
88
+ <SelectItem value="calendar">Calendar</SelectItem>
89
+ </SelectContent>
90
+ </Select>
91
+ </div>
92
+ <div>
93
+ <Label>컬러</Label>
94
+ <Input name="color" type="color" defaultValue="#58a6ff" className="h-9" />
95
+ </div>
96
+ </div>
97
+ {(goals ?? []).length > 0 && (
98
+ <div>
99
+ <Label>연결 목표</Label>
100
+ <Select name="goal_id">
101
+ <SelectTrigger><SelectValue placeholder="목표 선택 (선택)" /></SelectTrigger>
102
+ <SelectContent>
103
+ {(goals ?? []).map(goal => (
104
+ <SelectItem key={goal.id} value={goal.id}>{goal.title}</SelectItem>
105
+ ))}
106
+ </SelectContent>
107
+ </Select>
108
+ </div>
109
+ )}
110
+ <Button type="submit" className="w-full bg-gatsaeng-amber hover:bg-gatsaeng-amber/80 text-black">
111
+ 프로젝트 생성
112
+ </Button>
113
+ </form>
114
+ </DialogContent>
115
+ </Dialog>
116
+ </div>
117
+
118
+ <Tabs value={tab} onValueChange={setTab} className="mb-6">
119
+ <TabsList>
120
+ <TabsTrigger value="active">진행 중 ({activeProjects.length})</TabsTrigger>
121
+ <TabsTrigger value="completed">완료 ({completedProjects.length})</TabsTrigger>
122
+ <TabsTrigger value="archived">보관 ({archivedProjects.length})</TabsTrigger>
123
+ </TabsList>
124
+ </Tabs>
125
+
126
+ {isLoading ? (
127
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
128
+ {[1, 2].map(i => <div key={i} className="h-32 bg-card rounded-lg animate-pulse" />)}
129
+ </div>
130
+ ) : displayProjects.length === 0 ? (
131
+ <Card>
132
+ <CardContent className="py-12 text-center text-muted-foreground">
133
+ {tab === 'active' ? '진행 중인 프로젝트가 없습니다' : tab === 'completed' ? '완료된 프로젝트가 없습니다' : '보관된 프로젝트가 없습니다'}
134
+ </CardContent>
135
+ </Card>
136
+ ) : (
137
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
138
+ {displayProjects.map(project => {
139
+ const projectTasks = allTasks.filter(t => t.project_id === project.id)
140
+ const totalTasks = projectTasks.length
141
+ const doneTasks = projectTasks.filter(t => t.status === 'done').length
142
+ const pendingTasks = totalTasks - doneTasks
143
+ const progress = totalTasks > 0 ? Math.round((doneTasks / totalTasks) * 100) : 0
144
+ return (
145
+ <Card key={project.id} className="hover:border-primary/50 transition-colors group relative">
146
+ <Link href={`/projects/${project.id}`}>
147
+ <CardHeader className="pb-2">
148
+ <CardTitle className="text-base flex items-center gap-2">
149
+ <FolderKanban className="w-4 h-4" style={{ color: project.color }} />
150
+ <span className="truncate">{project.title}</span>
151
+ {project.due_date && <DDayBadge dueDate={project.due_date} className="ml-auto" />}
152
+ </CardTitle>
153
+ </CardHeader>
154
+ <CardContent>
155
+ {project.description && (
156
+ <p className="text-sm text-muted-foreground mb-2 truncate">{project.description}</p>
157
+ )}
158
+ {totalTasks > 0 && (
159
+ <div className="mb-2">
160
+ <div className="flex items-center justify-between text-[10px] text-muted-foreground mb-1">
161
+ <span>{pendingTasks}개 남음 · {doneTasks}개 완료</span>
162
+ <span className="tabular-nums font-medium">{progress}%</span>
163
+ </div>
164
+ <Progress value={progress} className="h-1.5" />
165
+ </div>
166
+ )}
167
+ <div className="flex gap-2">
168
+ <Badge variant="outline">{project.default_view}</Badge>
169
+ {totalTasks === 0 && (
170
+ <Badge variant="outline" className="text-muted-foreground">태스크 없음</Badge>
171
+ )}
172
+ </div>
173
+ </CardContent>
174
+ </Link>
175
+ {/* Status change buttons */}
176
+ <div className="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity flex gap-1">
177
+ {tab === 'active' && (
178
+ <>
179
+ <Button
180
+ variant="ghost" size="icon"
181
+ className="h-7 w-7 text-muted-foreground hover:text-gatsaeng-teal"
182
+ title="완료로 이동"
183
+ onClick={(e) => { e.preventDefault(); handleStatusChange(project.id, 'completed') }}
184
+ >
185
+ <CheckCircle2 className="w-4 h-4" />
186
+ </Button>
187
+ <Button
188
+ variant="ghost" size="icon"
189
+ className="h-7 w-7 text-muted-foreground hover:text-foreground"
190
+ title="보관으로 이동"
191
+ onClick={(e) => { e.preventDefault(); handleStatusChange(project.id, 'archived') }}
192
+ >
193
+ <Archive className="w-4 h-4" />
194
+ </Button>
195
+ </>
196
+ )}
197
+ {(tab === 'completed' || tab === 'archived') && (
198
+ <Button
199
+ variant="ghost" size="icon"
200
+ className="h-7 w-7 text-muted-foreground hover:text-primary"
201
+ title="다시 활성화"
202
+ onClick={(e) => { e.preventDefault(); handleStatusChange(project.id, 'active') }}
203
+ >
204
+ <FolderKanban className="w-4 h-4" />
205
+ </Button>
206
+ )}
207
+ </div>
208
+ </Card>
209
+ )
210
+ })}
211
+ </div>
212
+ )}
213
+ </div>
214
+ )
215
+ }