floq 1.3.3 → 1.4.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.
- package/README.ja.md +8 -0
- package/README.md +8 -0
- package/dist/cli.js +10 -0
- package/dist/commands/insights.d.ts +1 -0
- package/dist/commands/insights.js +283 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +6 -0
- package/dist/db/index.js +24 -0
- package/dist/db/schema.d.ts +37 -0
- package/dist/db/schema.js +2 -0
- package/dist/i18n/en.d.ts +82 -0
- package/dist/i18n/en.js +57 -5
- package/dist/i18n/ja.js +57 -5
- package/dist/ui/App.js +110 -7
- package/dist/ui/components/GtdDQ.js +117 -9
- package/dist/ui/components/GtdMario.js +113 -8
- package/dist/ui/components/HelpModal.js +8 -0
- package/dist/ui/components/InsightsModal.d.ts +6 -0
- package/dist/ui/components/InsightsModal.js +272 -0
- package/dist/ui/components/KanbanBoard.js +119 -11
- package/dist/ui/components/KanbanColumn.js +7 -2
- package/dist/ui/components/KanbanDQ.js +120 -11
- package/dist/ui/components/KanbanMario.js +125 -11
- package/dist/ui/components/TaskItem.js +7 -2
- package/dist/ui/history/commands/SetEffortCommand.d.ts +20 -0
- package/dist/ui/history/commands/SetEffortCommand.js +37 -0
- package/dist/ui/history/commands/SetFocusCommand.d.ts +20 -0
- package/dist/ui/history/commands/SetFocusCommand.js +37 -0
- package/dist/ui/history/commands/index.d.ts +2 -0
- package/dist/ui/history/commands/index.js +2 -0
- package/dist/ui/history/index.d.ts +1 -1
- package/dist/ui/history/index.js +1 -1
- package/package.json +1 -1
package/dist/i18n/en.d.ts
CHANGED
|
@@ -71,6 +71,27 @@ export declare const en: {
|
|
|
71
71
|
notFound: string;
|
|
72
72
|
noContexts: string;
|
|
73
73
|
};
|
|
74
|
+
insights: {
|
|
75
|
+
title: string;
|
|
76
|
+
period: string;
|
|
77
|
+
weeklyCompletion: string;
|
|
78
|
+
weekLabel: string;
|
|
79
|
+
tasksCompleted: string;
|
|
80
|
+
dailyBreakdown: string;
|
|
81
|
+
currentStatus: string;
|
|
82
|
+
byContext: string;
|
|
83
|
+
byEffort: string;
|
|
84
|
+
noContext: string;
|
|
85
|
+
noEffort: string;
|
|
86
|
+
projectProgress: string;
|
|
87
|
+
activeProjects: string;
|
|
88
|
+
tasksRemaining: string;
|
|
89
|
+
averageCompletion: string;
|
|
90
|
+
daysAverage: string;
|
|
91
|
+
noData: string;
|
|
92
|
+
total: string;
|
|
93
|
+
andMore: string;
|
|
94
|
+
};
|
|
74
95
|
};
|
|
75
96
|
tui: {
|
|
76
97
|
title: string;
|
|
@@ -121,6 +142,9 @@ export declare const en: {
|
|
|
121
142
|
comment: string;
|
|
122
143
|
back: string;
|
|
123
144
|
delete: string;
|
|
145
|
+
focus: string;
|
|
146
|
+
focusFilter: string;
|
|
147
|
+
effort: string;
|
|
124
148
|
pause: string;
|
|
125
149
|
resume: string;
|
|
126
150
|
skip: string;
|
|
@@ -155,6 +179,9 @@ export declare const en: {
|
|
|
155
179
|
searchTasks: string;
|
|
156
180
|
filterByContext: string;
|
|
157
181
|
setContext: string;
|
|
182
|
+
toggleFocus: string;
|
|
183
|
+
toggleFocusFilter: string;
|
|
184
|
+
setEffort: string;
|
|
158
185
|
pomodoro: string;
|
|
159
186
|
startPomodoro: string;
|
|
160
187
|
pauseResume: string;
|
|
@@ -167,6 +194,7 @@ export declare const en: {
|
|
|
167
194
|
other: string;
|
|
168
195
|
showHelp: string;
|
|
169
196
|
showCalendar: string;
|
|
197
|
+
showInsights: string;
|
|
170
198
|
quit: string;
|
|
171
199
|
undo: string;
|
|
172
200
|
redo: string;
|
|
@@ -194,6 +222,9 @@ export declare const en: {
|
|
|
194
222
|
moveRight: string;
|
|
195
223
|
moveLeft: string;
|
|
196
224
|
searchTasks: string;
|
|
225
|
+
toggleFocus: string;
|
|
226
|
+
toggleFocusFilter: string;
|
|
227
|
+
setEffort: string;
|
|
197
228
|
settings: string;
|
|
198
229
|
changeTheme: string;
|
|
199
230
|
changeViewMode: string;
|
|
@@ -246,6 +277,25 @@ export declare const en: {
|
|
|
246
277
|
newContext: string;
|
|
247
278
|
newContextPlaceholder: string;
|
|
248
279
|
};
|
|
280
|
+
focus: {
|
|
281
|
+
label: string;
|
|
282
|
+
focused: string;
|
|
283
|
+
taskFocused: string;
|
|
284
|
+
taskUnfocused: string;
|
|
285
|
+
filterOn: string;
|
|
286
|
+
filterOff: string;
|
|
287
|
+
};
|
|
288
|
+
effort: {
|
|
289
|
+
label: string;
|
|
290
|
+
small: string;
|
|
291
|
+
medium: string;
|
|
292
|
+
large: string;
|
|
293
|
+
clear: string;
|
|
294
|
+
set: string;
|
|
295
|
+
setHelp: string;
|
|
296
|
+
effortSet: string;
|
|
297
|
+
effortCleared: string;
|
|
298
|
+
};
|
|
249
299
|
pomodoro: {
|
|
250
300
|
work: string;
|
|
251
301
|
shortBreak: string;
|
|
@@ -385,6 +435,9 @@ export type HelpTranslations = {
|
|
|
385
435
|
searchTasks: string;
|
|
386
436
|
filterByContext: string;
|
|
387
437
|
setContext: string;
|
|
438
|
+
toggleFocus?: string;
|
|
439
|
+
toggleFocusFilter?: string;
|
|
440
|
+
setEffort?: string;
|
|
388
441
|
pomodoro: string;
|
|
389
442
|
startPomodoro: string;
|
|
390
443
|
pauseResume: string;
|
|
@@ -397,6 +450,7 @@ export type HelpTranslations = {
|
|
|
397
450
|
other: string;
|
|
398
451
|
showHelp: string;
|
|
399
452
|
showCalendar?: string;
|
|
453
|
+
showInsights?: string;
|
|
400
454
|
quit: string;
|
|
401
455
|
undo: string;
|
|
402
456
|
redo: string;
|
|
@@ -424,6 +478,9 @@ export type KanbanHelpTranslations = {
|
|
|
424
478
|
moveRight: string;
|
|
425
479
|
moveLeft: string;
|
|
426
480
|
searchTasks: string;
|
|
481
|
+
toggleFocus?: string;
|
|
482
|
+
toggleFocusFilter?: string;
|
|
483
|
+
setEffort?: string;
|
|
427
484
|
settings: string;
|
|
428
485
|
changeTheme: string;
|
|
429
486
|
changeViewMode: string;
|
|
@@ -451,6 +508,9 @@ export type KeyBarTranslations = {
|
|
|
451
508
|
comment: string;
|
|
452
509
|
back: string;
|
|
453
510
|
delete: string;
|
|
511
|
+
focus?: string;
|
|
512
|
+
focusFilter?: string;
|
|
513
|
+
effort?: string;
|
|
454
514
|
pause: string;
|
|
455
515
|
resume: string;
|
|
456
516
|
skip: string;
|
|
@@ -479,6 +539,25 @@ export type ContextTranslations = {
|
|
|
479
539
|
newContext: string;
|
|
480
540
|
newContextPlaceholder: string;
|
|
481
541
|
};
|
|
542
|
+
export type FocusTranslations = {
|
|
543
|
+
label: string;
|
|
544
|
+
focused: string;
|
|
545
|
+
taskFocused: string;
|
|
546
|
+
taskUnfocused: string;
|
|
547
|
+
filterOn: string;
|
|
548
|
+
filterOff: string;
|
|
549
|
+
};
|
|
550
|
+
export type EffortTranslations = {
|
|
551
|
+
label: string;
|
|
552
|
+
small: string;
|
|
553
|
+
medium: string;
|
|
554
|
+
large: string;
|
|
555
|
+
clear: string;
|
|
556
|
+
set: string;
|
|
557
|
+
setHelp: string;
|
|
558
|
+
effortSet: string;
|
|
559
|
+
effortCleared: string;
|
|
560
|
+
};
|
|
482
561
|
export type PomodoroTranslations = {
|
|
483
562
|
work: string;
|
|
484
563
|
shortBreak: string;
|
|
@@ -577,6 +656,8 @@ export type TuiTranslations = {
|
|
|
577
656
|
kanbanHelp: KanbanHelpTranslations;
|
|
578
657
|
search: SearchTranslations;
|
|
579
658
|
context: ContextTranslations;
|
|
659
|
+
focus?: FocusTranslations;
|
|
660
|
+
effort?: EffortTranslations;
|
|
580
661
|
info: InfoTranslations;
|
|
581
662
|
pomodoro?: PomodoroTranslations;
|
|
582
663
|
calendar?: CalendarTranslations;
|
|
@@ -667,6 +748,7 @@ export type Translations = {
|
|
|
667
748
|
project: Record<string, string>;
|
|
668
749
|
comment: Record<string, string>;
|
|
669
750
|
context: Record<string, string>;
|
|
751
|
+
insights?: Record<string, string>;
|
|
670
752
|
};
|
|
671
753
|
tui: TuiTranslations;
|
|
672
754
|
splash?: SplashTranslations;
|
package/dist/i18n/en.js
CHANGED
|
@@ -75,6 +75,27 @@ export const en = {
|
|
|
75
75
|
notFound: 'Context @{context} not found.',
|
|
76
76
|
noContexts: 'No contexts configured.',
|
|
77
77
|
},
|
|
78
|
+
insights: {
|
|
79
|
+
title: 'Task Insights',
|
|
80
|
+
period: 'Period',
|
|
81
|
+
weeklyCompletion: 'Weekly Completion',
|
|
82
|
+
weekLabel: 'Week of {date}',
|
|
83
|
+
tasksCompleted: '{count} tasks completed',
|
|
84
|
+
dailyBreakdown: 'Daily Breakdown',
|
|
85
|
+
currentStatus: 'Current Status',
|
|
86
|
+
byContext: 'By Context',
|
|
87
|
+
byEffort: 'By Effort',
|
|
88
|
+
noContext: 'No context',
|
|
89
|
+
noEffort: 'No effort set',
|
|
90
|
+
projectProgress: 'Project Progress',
|
|
91
|
+
activeProjects: 'Active Projects',
|
|
92
|
+
tasksRemaining: '{count} tasks remaining',
|
|
93
|
+
averageCompletion: 'Average Completion Time',
|
|
94
|
+
daysAverage: '{days} days',
|
|
95
|
+
noData: 'No completed tasks in this period',
|
|
96
|
+
total: 'Total',
|
|
97
|
+
andMore: ' ... and {count} more',
|
|
98
|
+
},
|
|
78
99
|
},
|
|
79
100
|
// TUI
|
|
80
101
|
tui: {
|
|
@@ -90,17 +111,17 @@ export const en = {
|
|
|
90
111
|
movedToWaiting: 'Moved "{title}" to Waiting (for {person})',
|
|
91
112
|
waitingFor: 'Waiting for: ',
|
|
92
113
|
refreshed: 'Refreshed',
|
|
93
|
-
footer: 'a=add d=done D=delete n=next s=someday w=waiting i=inbox p=project P=link c=context',
|
|
114
|
+
footer: 'a=add d=done D=delete n=next s=someday w=waiting i=inbox p=project P=link c=context g=focus G=filter E=effort',
|
|
94
115
|
// DQ/Mario style footers
|
|
95
116
|
dqFooter: {
|
|
96
|
-
tabs: 'j/k=select l/Enter=tasks 1-6=tab a=add @=filter /=search',
|
|
97
|
-
tasks: 'j/k=select Enter=detail h/Esc=back d=done n=next s=someday w=wait i=inbox c=context p=project P=link D=delete u=undo /=search',
|
|
117
|
+
tabs: 'j/k=select l/Enter=tasks 1-6=tab a=add @=filter g=focus G=filter E=effort /=search',
|
|
118
|
+
tasks: 'j/k=select Enter=detail h/Esc=back d=done n=next s=someday w=wait i=inbox c=context g=focus E=effort p=project P=link D=delete u=undo /=search',
|
|
98
119
|
projectDetail: 'j/k=select a=add d=done Esc/b=back /=search',
|
|
99
120
|
taskDetail: 'j/k=select c/i=add comment P=link D=delete comment Esc/b=back',
|
|
100
121
|
},
|
|
101
122
|
kanbanFooter: {
|
|
102
|
-
category: 'j/k=select l/Enter=tasks a=add @=filter /=search',
|
|
103
|
-
tasks: 'j/k=select h/Esc=back d=done m=move a=add u=undo /=search',
|
|
123
|
+
category: 'j/k=select l/Enter=tasks a=add @=filter g=focus G=filter E=effort /=search',
|
|
124
|
+
tasks: 'j/k=select h/Esc=back d=done m=move a=add g=focus E=effort u=undo /=search',
|
|
104
125
|
},
|
|
105
126
|
noTasks: 'No tasks',
|
|
106
127
|
// Tab labels
|
|
@@ -130,6 +151,9 @@ export const en = {
|
|
|
130
151
|
comment: 'Comment',
|
|
131
152
|
back: 'Back',
|
|
132
153
|
delete: 'Delete',
|
|
154
|
+
focus: 'Focus',
|
|
155
|
+
focusFilter: 'Focus Filter',
|
|
156
|
+
effort: 'Effort',
|
|
133
157
|
// Pomodoro keys
|
|
134
158
|
pause: 'Pause',
|
|
135
159
|
resume: 'Resume',
|
|
@@ -166,6 +190,9 @@ export const en = {
|
|
|
166
190
|
searchTasks: 'Search tasks',
|
|
167
191
|
filterByContext: 'Filter by context',
|
|
168
192
|
setContext: 'Set context',
|
|
193
|
+
toggleFocus: 'Toggle focus',
|
|
194
|
+
toggleFocusFilter: 'Toggle focus filter',
|
|
195
|
+
setEffort: 'Set effort size',
|
|
169
196
|
pomodoro: 'Pomodoro',
|
|
170
197
|
startPomodoro: 'Start Pomodoro',
|
|
171
198
|
pauseResume: 'Pause/Resume',
|
|
@@ -178,6 +205,7 @@ export const en = {
|
|
|
178
205
|
other: 'Other',
|
|
179
206
|
showHelp: 'Show this help',
|
|
180
207
|
showCalendar: 'Show calendar',
|
|
208
|
+
showInsights: 'Show insights',
|
|
181
209
|
quit: 'Quit',
|
|
182
210
|
undo: 'Undo',
|
|
183
211
|
redo: 'Redo',
|
|
@@ -207,6 +235,9 @@ export const en = {
|
|
|
207
235
|
moveRight: 'Move task to next column',
|
|
208
236
|
moveLeft: 'Move task to previous column',
|
|
209
237
|
searchTasks: 'Search tasks',
|
|
238
|
+
toggleFocus: 'Toggle focus',
|
|
239
|
+
toggleFocusFilter: 'Toggle focus filter',
|
|
240
|
+
setEffort: 'Set effort size',
|
|
210
241
|
settings: 'Settings',
|
|
211
242
|
changeTheme: 'Change theme',
|
|
212
243
|
changeViewMode: 'Change view mode',
|
|
@@ -262,6 +293,27 @@ export const en = {
|
|
|
262
293
|
newContext: 'New context: ',
|
|
263
294
|
newContextPlaceholder: 'Enter context name...',
|
|
264
295
|
},
|
|
296
|
+
// Focus
|
|
297
|
+
focus: {
|
|
298
|
+
label: 'Focus',
|
|
299
|
+
focused: '★ Focused',
|
|
300
|
+
taskFocused: 'Focused: "{title}"',
|
|
301
|
+
taskUnfocused: 'Unfocused: "{title}"',
|
|
302
|
+
filterOn: 'Focus filter ON',
|
|
303
|
+
filterOff: 'Focus filter OFF',
|
|
304
|
+
},
|
|
305
|
+
// Effort
|
|
306
|
+
effort: {
|
|
307
|
+
label: 'Effort',
|
|
308
|
+
small: 'Small',
|
|
309
|
+
medium: 'Medium',
|
|
310
|
+
large: 'Large',
|
|
311
|
+
clear: 'Clear',
|
|
312
|
+
set: 'Set effort',
|
|
313
|
+
setHelp: 'j/k: select, Enter: confirm, Esc: cancel',
|
|
314
|
+
effortSet: 'Set effort {effort} for "{title}"',
|
|
315
|
+
effortCleared: 'Cleared effort for "{title}"',
|
|
316
|
+
},
|
|
265
317
|
// Pomodoro
|
|
266
318
|
pomodoro: {
|
|
267
319
|
work: 'Work',
|
package/dist/i18n/ja.js
CHANGED
|
@@ -75,6 +75,27 @@ export const ja = {
|
|
|
75
75
|
notFound: 'コンテキスト @{context} が見つかりません。',
|
|
76
76
|
noContexts: 'コンテキストが設定されていません。',
|
|
77
77
|
},
|
|
78
|
+
insights: {
|
|
79
|
+
title: 'タスクインサイト',
|
|
80
|
+
period: '期間',
|
|
81
|
+
weeklyCompletion: '週別完了数',
|
|
82
|
+
weekLabel: '{date}の週',
|
|
83
|
+
tasksCompleted: '{count}件完了',
|
|
84
|
+
dailyBreakdown: '曜日別内訳',
|
|
85
|
+
currentStatus: '現在のステータス',
|
|
86
|
+
byContext: 'コンテキスト別',
|
|
87
|
+
byEffort: '作業量別',
|
|
88
|
+
noContext: 'コンテキストなし',
|
|
89
|
+
noEffort: '作業量未設定',
|
|
90
|
+
projectProgress: 'プロジェクト進捗',
|
|
91
|
+
activeProjects: 'アクティブ',
|
|
92
|
+
tasksRemaining: '残り{count}件',
|
|
93
|
+
averageCompletion: '平均完了時間',
|
|
94
|
+
daysAverage: '{days}日',
|
|
95
|
+
noData: 'この期間に完了したタスクはありません',
|
|
96
|
+
total: '合計',
|
|
97
|
+
andMore: ' ... 他{count}件',
|
|
98
|
+
},
|
|
78
99
|
},
|
|
79
100
|
// TUI
|
|
80
101
|
tui: {
|
|
@@ -90,17 +111,17 @@ export const ja = {
|
|
|
90
111
|
movedToWaiting: '「{title}」を連絡待ち({person})に移動しました',
|
|
91
112
|
waitingFor: '待機相手: ',
|
|
92
113
|
refreshed: '更新しました',
|
|
93
|
-
footer: 'a=追加 d=完了 D=削除 n=次 s=いつか w=待ち i=Inbox p=プロジェクト化 P=紐づけ c=コンテキスト',
|
|
114
|
+
footer: 'a=追加 d=完了 D=削除 n=次 s=いつか w=待ち i=Inbox p=プロジェクト化 P=紐づけ c=コンテキスト g=集中 G=フィルター E=作業量',
|
|
94
115
|
// DQ/Mario style footers
|
|
95
116
|
dqFooter: {
|
|
96
|
-
tabs: 'j/k=選択 l/Enter=タスク 1-6=タブ a=追加 @=フィルター /=検索',
|
|
97
|
-
tasks: 'j/k=選択 Enter=詳細 h/Esc=戻る d=完了 n=次 s=いつか w=待ち i=inbox c=コンテキスト p=プロジェクト化 P=紐づけ D=削除 u=戻す /=検索',
|
|
117
|
+
tabs: 'j/k=選択 l/Enter=タスク 1-6=タブ a=追加 @=フィルター g=集中 G=フィルター E=作業量 /=検索',
|
|
118
|
+
tasks: 'j/k=選択 Enter=詳細 h/Esc=戻る d=完了 n=次 s=いつか w=待ち i=inbox c=コンテキスト g=集中 E=作業量 p=プロジェクト化 P=紐づけ D=削除 u=戻す /=検索',
|
|
98
119
|
projectDetail: 'j/k=選択 a=追加 d=完了 Esc/b=戻る /=検索',
|
|
99
120
|
taskDetail: 'j/k=選択 c/i=コメント追加 P=紐づけ D=コメント削除 Esc/b=戻る',
|
|
100
121
|
},
|
|
101
122
|
kanbanFooter: {
|
|
102
|
-
category: 'j/k=選択 l/Enter=タスク a=追加 @=フィルター /=検索',
|
|
103
|
-
tasks: 'j/k=選択 h/Esc=戻る d=完了 m=移動 a=追加 u=戻す /=検索',
|
|
123
|
+
category: 'j/k=選択 l/Enter=タスク a=追加 @=フィルター g=集中 G=フィルター E=作業量 /=検索',
|
|
124
|
+
tasks: 'j/k=選択 h/Esc=戻る d=完了 m=移動 a=追加 g=集中 E=作業量 u=戻す /=検索',
|
|
104
125
|
},
|
|
105
126
|
noTasks: 'タスクなし',
|
|
106
127
|
// Tab labels
|
|
@@ -130,6 +151,9 @@ export const ja = {
|
|
|
130
151
|
comment: 'コメント',
|
|
131
152
|
back: '戻る',
|
|
132
153
|
delete: '削除',
|
|
154
|
+
focus: '集中',
|
|
155
|
+
focusFilter: '集中フィルター',
|
|
156
|
+
effort: '作業量',
|
|
133
157
|
// Pomodoro keys
|
|
134
158
|
pause: '一時停止',
|
|
135
159
|
resume: '再開',
|
|
@@ -166,6 +190,9 @@ export const ja = {
|
|
|
166
190
|
searchTasks: 'タスク検索',
|
|
167
191
|
filterByContext: 'コンテキストフィルター',
|
|
168
192
|
setContext: 'コンテキスト設定',
|
|
193
|
+
toggleFocus: '集中モード切替',
|
|
194
|
+
toggleFocusFilter: '集中フィルター切替',
|
|
195
|
+
setEffort: '作業量設定',
|
|
169
196
|
pomodoro: 'ポモドーロ',
|
|
170
197
|
startPomodoro: 'ポモドーロ開始',
|
|
171
198
|
pauseResume: '一時停止/再開',
|
|
@@ -178,6 +205,7 @@ export const ja = {
|
|
|
178
205
|
other: 'その他',
|
|
179
206
|
showHelp: 'このヘルプを表示',
|
|
180
207
|
showCalendar: 'カレンダーを表示',
|
|
208
|
+
showInsights: 'インサイトを表示',
|
|
181
209
|
quit: '終了',
|
|
182
210
|
undo: '元に戻す',
|
|
183
211
|
redo: 'やり直し',
|
|
@@ -207,6 +235,9 @@ export const ja = {
|
|
|
207
235
|
moveRight: '次のカラムへ移動',
|
|
208
236
|
moveLeft: '前のカラムへ戻す',
|
|
209
237
|
searchTasks: 'タスク検索',
|
|
238
|
+
toggleFocus: '集中モード切替',
|
|
239
|
+
toggleFocusFilter: '集中フィルター切替',
|
|
240
|
+
setEffort: '作業量設定',
|
|
210
241
|
settings: '設定',
|
|
211
242
|
changeTheme: 'テーマ変更',
|
|
212
243
|
changeViewMode: '表示モード変更',
|
|
@@ -262,6 +293,27 @@ export const ja = {
|
|
|
262
293
|
newContext: '新規コンテキスト: ',
|
|
263
294
|
newContextPlaceholder: 'コンテキスト名を入力...',
|
|
264
295
|
},
|
|
296
|
+
// Focus
|
|
297
|
+
focus: {
|
|
298
|
+
label: '集中',
|
|
299
|
+
focused: '★ 集中',
|
|
300
|
+
taskFocused: '集中設定: 「{title}」',
|
|
301
|
+
taskUnfocused: '集中解除: 「{title}」',
|
|
302
|
+
filterOn: '集中フィルター ON',
|
|
303
|
+
filterOff: '集中フィルター OFF',
|
|
304
|
+
},
|
|
305
|
+
// Effort
|
|
306
|
+
effort: {
|
|
307
|
+
label: '作業量',
|
|
308
|
+
small: '小',
|
|
309
|
+
medium: '中',
|
|
310
|
+
large: '大',
|
|
311
|
+
clear: 'クリア',
|
|
312
|
+
set: '作業量設定',
|
|
313
|
+
setHelp: 'j/k: 選択, Enter: 確定, Esc: キャンセル',
|
|
314
|
+
effortSet: '「{title}」の作業量を{effort}に設定しました',
|
|
315
|
+
effortCleared: '「{title}」の作業量をクリアしました',
|
|
316
|
+
},
|
|
265
317
|
// Pomodoro
|
|
266
318
|
pomodoro: {
|
|
267
319
|
work: '作業中',
|
package/dist/ui/App.js
CHANGED
|
@@ -6,6 +6,7 @@ import { eq, and, gte } from 'drizzle-orm';
|
|
|
6
6
|
import { v4 as uuidv4 } from 'uuid';
|
|
7
7
|
import { TaskItem } from './components/TaskItem.js';
|
|
8
8
|
import { HelpModal } from './components/HelpModal.js';
|
|
9
|
+
import { InsightsModal } from './components/InsightsModal.js';
|
|
9
10
|
import { CalendarModal } from './components/CalendarModal.js';
|
|
10
11
|
import { FunctionKeyBar } from './components/FunctionKeyBar.js';
|
|
11
12
|
import { SearchBar } from './components/SearchBar.js';
|
|
@@ -22,14 +23,14 @@ import { LanguageSelector } from './LanguageSelector.js';
|
|
|
22
23
|
import { getDb, schema } from '../db/index.js';
|
|
23
24
|
import { t, fmt } from '../i18n/index.js';
|
|
24
25
|
import { ThemeProvider, useTheme, getTheme } from './theme/index.js';
|
|
25
|
-
import { getThemeName, getViewMode, setThemeName, setViewMode, setLocale, isTursoEnabled, getContexts, addContext, getSplashDuration, getContextFilter, setContextFilter as saveContextFilter, getPomodoroFocusMode, setPomodoroFocusMode } from '../config.js';
|
|
26
|
+
import { getThemeName, getViewMode, setThemeName, setViewMode, setLocale, isTursoEnabled, getContexts, addContext, getSplashDuration, getContextFilter, setContextFilter as saveContextFilter, getPomodoroFocusMode, setPomodoroFocusMode, getFocusFilter, setFocusFilter } from '../config.js';
|
|
26
27
|
import { KanbanBoard } from './components/KanbanBoard.js';
|
|
27
28
|
import { KanbanDQ } from './components/KanbanDQ.js';
|
|
28
29
|
import { KanbanMario } from './components/KanbanMario.js';
|
|
29
30
|
import { GtdDQ } from './components/GtdDQ.js';
|
|
30
31
|
import { GtdMario } from './components/GtdMario.js';
|
|
31
32
|
import { VERSION } from '../version.js';
|
|
32
|
-
import { HistoryProvider, useHistory, CreateTaskCommand, DeleteTaskCommand, MoveTaskCommand, LinkTaskCommand, ConvertToProjectCommand, CreateCommentCommand, DeleteCommentCommand, SetContextCommand, } from './history/index.js';
|
|
33
|
+
import { HistoryProvider, useHistory, CreateTaskCommand, DeleteTaskCommand, MoveTaskCommand, LinkTaskCommand, ConvertToProjectCommand, CreateCommentCommand, DeleteCommentCommand, SetContextCommand, SetFocusCommand, SetEffortCommand, } from './history/index.js';
|
|
33
34
|
const TABS = ['inbox', 'next', 'waiting', 'someday', 'projects', 'done'];
|
|
34
35
|
export function App() {
|
|
35
36
|
const [themeName, setThemeNameState] = useState(getThemeName);
|
|
@@ -123,7 +124,15 @@ function AppContent({ onOpenSettings }) {
|
|
|
123
124
|
});
|
|
124
125
|
}, []);
|
|
125
126
|
const [availableContexts, setAvailableContexts] = useState([]);
|
|
127
|
+
const [focusFilterState, setFocusFilterState] = useState(getFocusFilter());
|
|
128
|
+
const [effortSelectIndex, setEffortSelectIndex] = useState(0);
|
|
126
129
|
const i18n = t();
|
|
130
|
+
const EFFORT_OPTIONS = [
|
|
131
|
+
{ value: 'small', label: i18n.tui.effort?.small || 'Small' },
|
|
132
|
+
{ value: 'medium', label: i18n.tui.effort?.medium || 'Medium' },
|
|
133
|
+
{ value: 'large', label: i18n.tui.effort?.large || 'Large' },
|
|
134
|
+
{ value: null, label: i18n.tui.effort?.clear || 'Clear' },
|
|
135
|
+
];
|
|
127
136
|
// Pomodoro timer
|
|
128
137
|
const handlePomodoroPhaseComplete = useCallback((type, completedCount) => {
|
|
129
138
|
if (type === 'work') {
|
|
@@ -173,6 +182,9 @@ function AppContent({ onOpenSettings }) {
|
|
|
173
182
|
allTasks = allTasks.filter(t => t.context === contextFilter);
|
|
174
183
|
}
|
|
175
184
|
}
|
|
185
|
+
if (focusFilterState) {
|
|
186
|
+
allTasks = allTasks.filter(t => t.isFocused);
|
|
187
|
+
}
|
|
176
188
|
newTasks[status] = allTasks;
|
|
177
189
|
}
|
|
178
190
|
// Load projects (isProject = true, not done) - projects don't get context filtered
|
|
@@ -194,7 +206,7 @@ function AppContent({ onOpenSettings }) {
|
|
|
194
206
|
setProjectProgress(progress);
|
|
195
207
|
setTasks(newTasks);
|
|
196
208
|
setAvailableContexts(getContexts());
|
|
197
|
-
}, [contextFilter]);
|
|
209
|
+
}, [contextFilter, focusFilterState]);
|
|
198
210
|
// Get parent project for a task
|
|
199
211
|
const getParentProject = (parentId) => {
|
|
200
212
|
if (!parentId)
|
|
@@ -222,6 +234,11 @@ function AppContent({ onOpenSettings }) {
|
|
|
222
234
|
}, [loadTasks]);
|
|
223
235
|
const currentTab = TABS[currentListIndex];
|
|
224
236
|
const currentTasks = mode === 'project-detail' ? projectTasks : tasks[currentTab];
|
|
237
|
+
const getCurrentTask = () => {
|
|
238
|
+
if (currentTasks.length === 0)
|
|
239
|
+
return undefined;
|
|
240
|
+
return currentTasks[selectedTaskIndex];
|
|
241
|
+
};
|
|
225
242
|
// Get all tasks for search (across all statuses)
|
|
226
243
|
const getAllTasks = useCallback(() => {
|
|
227
244
|
const allTasks = [];
|
|
@@ -446,6 +463,48 @@ function AppContent({ onOpenSettings }) {
|
|
|
446
463
|
setMessage(description);
|
|
447
464
|
await loadTasks();
|
|
448
465
|
}, [i18n.tui.context, loadTasks, history]);
|
|
466
|
+
const toggleTaskFocus = async () => {
|
|
467
|
+
const task = getCurrentTask();
|
|
468
|
+
if (!task)
|
|
469
|
+
return;
|
|
470
|
+
const newFocused = !task.isFocused;
|
|
471
|
+
const description = newFocused
|
|
472
|
+
? fmt(i18n.tui.focus?.taskFocused || 'Focused: "{title}"', { title: task.title })
|
|
473
|
+
: fmt(i18n.tui.focus?.taskUnfocused || 'Unfocused: "{title}"', { title: task.title });
|
|
474
|
+
const command = new SetFocusCommand({
|
|
475
|
+
taskId: task.id,
|
|
476
|
+
fromFocused: task.isFocused,
|
|
477
|
+
toFocused: newFocused,
|
|
478
|
+
description,
|
|
479
|
+
});
|
|
480
|
+
await history.execute(command);
|
|
481
|
+
setMessage(description);
|
|
482
|
+
await loadTasks();
|
|
483
|
+
};
|
|
484
|
+
const toggleFocusFilter = () => {
|
|
485
|
+
const newValue = !focusFilterState;
|
|
486
|
+
setFocusFilterState(newValue);
|
|
487
|
+
setFocusFilter(newValue);
|
|
488
|
+
setMessage(newValue ? (i18n.tui.focus?.filterOn || 'Focus filter ON') : (i18n.tui.focus?.filterOff || 'Focus filter OFF'));
|
|
489
|
+
};
|
|
490
|
+
const setTaskEffort = async (effort) => {
|
|
491
|
+
const task = getCurrentTask();
|
|
492
|
+
if (!task)
|
|
493
|
+
return;
|
|
494
|
+
const description = effort
|
|
495
|
+
? fmt(i18n.tui.effort?.effortSet || 'Set effort {effort} for "{title}"', { effort: i18n.tui.effort?.[effort] || effort, title: task.title })
|
|
496
|
+
: fmt(i18n.tui.effort?.effortCleared || 'Cleared effort for "{title}"', { title: task.title });
|
|
497
|
+
const command = new SetEffortCommand({
|
|
498
|
+
taskId: task.id,
|
|
499
|
+
fromEffort: task.effort,
|
|
500
|
+
toEffort: effort,
|
|
501
|
+
description,
|
|
502
|
+
});
|
|
503
|
+
await history.execute(command);
|
|
504
|
+
setMessage(description);
|
|
505
|
+
setMode('normal');
|
|
506
|
+
await loadTasks();
|
|
507
|
+
};
|
|
449
508
|
const deleteTask = useCallback(async (task) => {
|
|
450
509
|
const command = new DeleteTaskCommand({
|
|
451
510
|
task,
|
|
@@ -652,6 +711,26 @@ function AppContent({ onOpenSettings }) {
|
|
|
652
711
|
}
|
|
653
712
|
return;
|
|
654
713
|
}
|
|
714
|
+
// Handle set-effort mode
|
|
715
|
+
if (mode === 'set-effort') {
|
|
716
|
+
if (key.escape) {
|
|
717
|
+
setMode('normal');
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
if (input === 'j' || key.downArrow) {
|
|
721
|
+
setEffortSelectIndex(prev => Math.min(prev + 1, EFFORT_OPTIONS.length - 1));
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
if (input === 'k' || key.upArrow) {
|
|
725
|
+
setEffortSelectIndex(prev => Math.max(prev - 1, 0));
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
if (key.return) {
|
|
729
|
+
setTaskEffort(EFFORT_OPTIONS[effortSelectIndex].value);
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
655
734
|
// Handle set-context mode
|
|
656
735
|
if (mode === 'set-context') {
|
|
657
736
|
if (key.escape) {
|
|
@@ -793,6 +872,11 @@ function AppContent({ onOpenSettings }) {
|
|
|
793
872
|
setMode('help');
|
|
794
873
|
return;
|
|
795
874
|
}
|
|
875
|
+
// Show insights
|
|
876
|
+
if (input === 'I') {
|
|
877
|
+
setMode('insights');
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
796
880
|
// Show calendar
|
|
797
881
|
if (input === 'C') {
|
|
798
882
|
setMode('calendar');
|
|
@@ -818,6 +902,21 @@ function AppContent({ onOpenSettings }) {
|
|
|
818
902
|
setMode('set-context');
|
|
819
903
|
return;
|
|
820
904
|
}
|
|
905
|
+
if (input === 'g') {
|
|
906
|
+
toggleTaskFocus();
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
if (input === 'G') {
|
|
910
|
+
toggleFocusFilter();
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
if (input === 'E') {
|
|
914
|
+
if (getCurrentTask()) {
|
|
915
|
+
setEffortSelectIndex(0);
|
|
916
|
+
setMode('set-effort');
|
|
917
|
+
}
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
821
920
|
// Settings: Theme selector
|
|
822
921
|
if (input === 'T') {
|
|
823
922
|
onOpenSettings('theme-select');
|
|
@@ -1055,11 +1154,15 @@ function AppContent({ onOpenSettings }) {
|
|
|
1055
1154
|
});
|
|
1056
1155
|
return;
|
|
1057
1156
|
}
|
|
1058
|
-
}, { isActive: mode !== 'help' && mode !== 'calendar' });
|
|
1157
|
+
}, { isActive: mode !== 'help' && mode !== 'insights' && mode !== 'calendar' });
|
|
1059
1158
|
// Help modal overlay
|
|
1060
1159
|
if (mode === 'help') {
|
|
1061
1160
|
return (_jsx(Box, { flexDirection: "column", padding: 1, children: _jsx(HelpModal, { onClose: () => setMode('normal') }) }));
|
|
1062
1161
|
}
|
|
1162
|
+
// Insights modal overlay
|
|
1163
|
+
if (mode === 'insights') {
|
|
1164
|
+
return (_jsx(Box, { flexDirection: "column", padding: 1, children: _jsx(InsightsModal, { onClose: () => setMode('normal') }) }));
|
|
1165
|
+
}
|
|
1063
1166
|
// Calendar modal overlay
|
|
1064
1167
|
if (mode === 'calendar') {
|
|
1065
1168
|
return (_jsx(Box, { flexDirection: "column", padding: 1, children: _jsx(CalendarModal, { onClose: () => setMode('normal') }) }));
|
|
@@ -1080,12 +1183,12 @@ function AppContent({ onOpenSettings }) {
|
|
|
1080
1183
|
const tursoEnabled = isTursoEnabled();
|
|
1081
1184
|
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, justifyContent: "space-between", children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: theme.colors.primary, children: formatTitle(i18n.tui.title) }), _jsx(Text, { color: theme.colors.textMuted, children: theme.name === 'modern' ? ` v${VERSION}` : ` VER ${VERSION}` }), _jsx(Text, { color: tursoEnabled ? theme.colors.accent : theme.colors.textMuted, children: theme.name === 'modern'
|
|
1082
1185
|
? (tursoEnabled ? ' ☁️ turso' : ' 💾 local')
|
|
1083
|
-
: (tursoEnabled ? ' [DB]TURSO' : ' [DB]local') }), contextFilter !== null && (_jsxs(Text, { color: theme.colors.accent, children: [' ', "@", contextFilter === '' ? (i18n.tui.context?.none || 'none') : contextFilter] }))] }), _jsxs(Box, { children: [_jsx(CalendarEvents, { compact: true, showLabel: true, withSeparator: true }), _jsx(Clock, {}), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.helpHint] })] })] }), pomodoro.isRunning && (_jsx(Box, { marginBottom: 1, children: _jsx(PomodoroTimer, { state: pomodoro.state, remainingSeconds: pomodoro.remainingSeconds, isPaused: pomodoro.isPaused }) })), _jsx(Box, { marginBottom: 1, children: TABS.map((tab, index) => {
|
|
1186
|
+
: (tursoEnabled ? ' [DB]TURSO' : ' [DB]local') }), contextFilter !== null && (_jsxs(Text, { color: theme.colors.accent, children: [' ', "@", contextFilter === '' ? (i18n.tui.context?.none || 'none') : contextFilter] })), focusFilterState && (_jsxs(Text, { color: theme.colors.accent, children: [" ", i18n.tui.focus?.focused || '★ Focused'] }))] }), _jsxs(Box, { children: [_jsx(CalendarEvents, { compact: true, showLabel: true, withSeparator: true }), _jsx(Clock, {}), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.helpHint] })] })] }), pomodoro.isRunning && (_jsx(Box, { marginBottom: 1, children: _jsx(PomodoroTimer, { state: pomodoro.state, remainingSeconds: pomodoro.remainingSeconds, isPaused: pomodoro.isPaused }) })), _jsx(Box, { marginBottom: 1, children: TABS.map((tab, index) => {
|
|
1084
1187
|
const isActive = index === currentListIndex && mode !== 'project-detail';
|
|
1085
1188
|
const count = tasks[tab].length;
|
|
1086
1189
|
const label = `${index + 1}:${getTabLabel(tab)}(${count})`;
|
|
1087
1190
|
return (_jsx(Box, { marginRight: 1, children: _jsx(Text, { color: isActive ? theme.colors.textSelected : theme.colors.textMuted, bold: isActive, inverse: isActive && theme.style.tabActiveInverse, children: formatTabLabel(` ${label} `, isActive) }) }, tab));
|
|
1088
|
-
}) }), mode === 'project-detail' && selectedProject && (_jsxs(_Fragment, { children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: theme.colors.accent, bold: true, children: [theme.name === 'modern' ? '📁 ' : '>> ', selectedProject.title] }), _jsxs(Text, { color: theme.colors.textMuted, children: [" (Esc/b: ", i18n.tui.back || 'back', ")"] })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.projectTasks || 'Tasks', " (", projectTasks.length, ")"] }) })] })), (mode === 'task-detail' || mode === 'add-comment') && selectedTask && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: theme.colors.accent, bold: true, children: [theme.name === 'modern' ? '📋 ' : '>> ', i18n.tui.taskDetailTitle || 'Task Details'] }), _jsxs(Text, { color: theme.colors.textMuted, children: [" (Esc/b: ", i18n.tui.back || 'back', ", ", i18n.tui.commentHint || 'i: add comment', ")"] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, marginBottom: 1, children: [_jsx(Text, { color: theme.colors.text, bold: true, children: selectedTask.title }), selectedTask.description && (_jsx(Text, { color: theme.colors.textMuted, children: selectedTask.description })), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.taskDetailStatus, ": "] }), _jsxs(Text, { color: theme.colors.accent, children: [i18n.status[selectedTask.status], selectedTask.waitingFor && ` (${selectedTask.waitingFor})`] })] }), _jsxs(Box, { children: [_jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.context?.label || 'Context', ": "] }), _jsx(Text, { color: theme.colors.accent, children: selectedTask.context ? `@${selectedTask.context}` : (i18n.tui.context?.none || 'No context') })] })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.comments || 'Comments', " (", taskComments.length, ")"] }) }), _jsx(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, minHeight: 5, children: taskComments.length === 0 ? (_jsx(Text, { color: theme.colors.textMuted, italic: true, children: i18n.tui.noComments || 'No comments yet' })) : (taskComments.map((comment, index) => {
|
|
1191
|
+
}) }), mode === 'project-detail' && selectedProject && (_jsxs(_Fragment, { children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: theme.colors.accent, bold: true, children: [theme.name === 'modern' ? '📁 ' : '>> ', selectedProject.title] }), _jsxs(Text, { color: theme.colors.textMuted, children: [" (Esc/b: ", i18n.tui.back || 'back', ")"] })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.projectTasks || 'Tasks', " (", projectTasks.length, ")"] }) })] })), (mode === 'task-detail' || mode === 'add-comment') && selectedTask && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: theme.colors.accent, bold: true, children: [theme.name === 'modern' ? '📋 ' : '>> ', i18n.tui.taskDetailTitle || 'Task Details'] }), _jsxs(Text, { color: theme.colors.textMuted, children: [" (Esc/b: ", i18n.tui.back || 'back', ", ", i18n.tui.commentHint || 'i: add comment', ")"] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, marginBottom: 1, children: [_jsx(Text, { color: theme.colors.text, bold: true, children: selectedTask.title }), selectedTask.description && (_jsx(Text, { color: theme.colors.textMuted, children: selectedTask.description })), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.taskDetailStatus, ": "] }), _jsxs(Text, { color: theme.colors.accent, children: [i18n.status[selectedTask.status], selectedTask.waitingFor && ` (${selectedTask.waitingFor})`] })] }), _jsxs(Box, { children: [_jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.context?.label || 'Context', ": "] }), _jsx(Text, { color: theme.colors.accent, children: selectedTask.context ? `@${selectedTask.context}` : (i18n.tui.context?.none || 'No context') })] }), _jsxs(Box, { children: [_jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.effort?.label || 'Effort', ": "] }), _jsx(Text, { color: theme.colors.accent, children: selectedTask.effort ? (i18n.tui.effort?.[selectedTask.effort] || selectedTask.effort) : '-' })] }), _jsxs(Box, { children: [_jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.focus?.label || 'Focus', ": "] }), _jsx(Text, { color: theme.colors.accent, children: selectedTask.isFocused ? '★' : '-' })] })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.comments || 'Comments', " (", taskComments.length, ")"] }) }), _jsx(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, minHeight: 5, children: taskComments.length === 0 ? (_jsx(Text, { color: theme.colors.textMuted, italic: true, children: i18n.tui.noComments || 'No comments yet' })) : (taskComments.map((comment, index) => {
|
|
1089
1192
|
const isSelected = index === selectedCommentIndex && mode === 'task-detail';
|
|
1090
1193
|
return (_jsxs(Box, { flexDirection: "row", marginBottom: 1, children: [_jsx(Text, { color: isSelected ? theme.colors.textSelected : theme.colors.textMuted, children: isSelected ? theme.style.selectedPrefix : theme.style.unselectedPrefix }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: theme.colors.textMuted, children: ["[", comment.createdAt.toLocaleString(), "]"] }), _jsx(Text, { color: isSelected ? theme.colors.textSelected : theme.colors.text, bold: isSelected, children: comment.content })] })] }, comment.id));
|
|
1091
1194
|
})) }), mode === 'add-comment' && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: theme.colors.secondary, bold: true, children: i18n.tui.addComment || 'New comment: ' }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleInputSubmit, placeholder: "" }), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.inputHelp] })] }))] })), mode === 'search' && searchQuery && (_jsx(SearchResults, { results: searchResults, selectedIndex: searchResultIndex, query: searchQuery })), mode !== 'task-detail' && mode !== 'add-comment' && mode !== 'search' && (theme.uiStyle === 'titled-box' ? (_jsx(TitledBox, { title: mode === 'project-detail' && selectedProject ? selectedProject.title : getTabLabel(currentTab), borderColor: theme.colors.border, minHeight: 10, children: currentTasks.length === 0 ? (_jsx(Text, { color: theme.colors.textMuted, italic: true, children: i18n.tui.noTasks })) : (currentTasks.map((task, index) => {
|
|
@@ -1118,7 +1221,7 @@ function AppContent({ onOpenSettings }) {
|
|
|
1118
1221
|
const isActive = (ctx === 'clear' && !currentContext) ||
|
|
1119
1222
|
(ctx !== 'clear' && ctx !== 'new' && currentContext === ctx);
|
|
1120
1223
|
return (_jsxs(Text, { color: index === contextSelectIndex ? theme.colors.textSelected : theme.colors.text, bold: index === contextSelectIndex, children: [index === contextSelectIndex ? theme.style.selectedPrefix : theme.style.unselectedPrefix, label, isActive && ' *'] }, ctx));
|
|
1121
|
-
}) }), _jsx(Text, { color: theme.colors.textMuted, children: i18n.tui.context?.setContextHelp || 'j/k: select, Enter: confirm, Esc: cancel' })] })), mode === 'add-context' && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: theme.colors.secondary, bold: true, children: i18n.tui.context?.newContext || 'New context: ' }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleInputSubmit, placeholder: i18n.tui.context?.newContextPlaceholder || 'Enter context name...' }), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.inputHelp] })] })), mode === 'search' && (_jsx(SearchBar, { value: searchQuery, onChange: handleSearchChange, onSubmit: handleInputSubmit })), mode === 'confirm-delete' && taskToDelete && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.colors.accent, bold: true, children: fmt(i18n.tui.deleteConfirm || 'Delete "{title}"? (y/n)', { title: taskToDelete.title }) }) })), message && mode === 'normal' && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.colors.textHighlight, children: message }) })), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [(mode === 'task-detail' || mode === 'add-comment') ? (theme.style.showFunctionKeys ? (_jsx(FunctionKeyBar, { keys: [
|
|
1224
|
+
}) }), _jsx(Text, { color: theme.colors.textMuted, children: i18n.tui.context?.setContextHelp || 'j/k: select, Enter: confirm, Esc: cancel' })] })), mode === 'set-effort' && (_jsxs(Box, { flexDirection: "column", borderStyle: theme.borders.modal, borderColor: theme.colors.borderActive, paddingX: 2, paddingY: 1, children: [_jsx(Text, { bold: true, color: theme.colors.accent, children: i18n.tui.effort?.set || 'Set effort' }), _jsx(Text, { color: theme.colors.textMuted, children: i18n.tui.effort?.setHelp || 'j/k: select, Enter: confirm, Esc: cancel' }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: EFFORT_OPTIONS.map((option, index) => (_jsxs(Text, { color: index === effortSelectIndex ? theme.colors.textSelected : theme.colors.text, bold: index === effortSelectIndex, children: [index === effortSelectIndex ? theme.style.selectedPrefix : theme.style.unselectedPrefix, option.label] }, option.label))) })] })), mode === 'add-context' && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: theme.colors.secondary, bold: true, children: i18n.tui.context?.newContext || 'New context: ' }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleInputSubmit, placeholder: i18n.tui.context?.newContextPlaceholder || 'Enter context name...' }), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.inputHelp] })] })), mode === 'search' && (_jsx(SearchBar, { value: searchQuery, onChange: handleSearchChange, onSubmit: handleInputSubmit })), mode === 'confirm-delete' && taskToDelete && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.colors.accent, bold: true, children: fmt(i18n.tui.deleteConfirm || 'Delete "{title}"? (y/n)', { title: taskToDelete.title }) }) })), message && mode === 'normal' && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.colors.textHighlight, children: message }) })), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [(mode === 'task-detail' || mode === 'add-comment') ? (theme.style.showFunctionKeys ? (_jsx(FunctionKeyBar, { keys: [
|
|
1122
1225
|
{ key: 'i', label: i18n.tui.keyBar.comment },
|
|
1123
1226
|
{ key: 'd', label: i18n.tui.keyBar.delete },
|
|
1124
1227
|
{ key: 'P', label: i18n.tui.keyBar.project },
|