@@ -240,15 +240,23 @@ program
240
240
. command ( "list" )
241
241
. description ( "List all projects and their tasks" )
242
242
. option ( '-p, --project <projectId>' , 'Show details for a specific project' )
243
+ . option ( '-s, --state <state>' , "Filter by task/project state (open, pending_approval, completed, all)" )
243
244
. action ( async ( options ) => {
244
245
try {
246
+ // Validate state option if provided
247
+ if ( options . state && ! [ 'open' , 'pending_approval' , 'completed' , 'all' ] . includes ( options . state ) ) {
248
+ console . error ( chalk . red ( `Invalid state value: ${ options . state } ` ) ) ;
249
+ console . log ( chalk . yellow ( 'Valid states are: open, pending_approval, completed, all' ) ) ;
250
+ process . exit ( 1 ) ;
251
+ }
252
+
245
253
const data = await readData ( ) ;
246
254
247
255
if ( data . projects . length === 0 ) {
248
256
console . log ( chalk . yellow ( 'No projects found.' ) ) ;
249
257
return ;
250
258
}
251
-
259
+
252
260
if ( options . project ) {
253
261
// Show details for a specific project
254
262
const project = data . projects . find ( p => p . projectId === options . project ) ;
@@ -260,46 +268,101 @@ program
260
268
} ) ;
261
269
process . exit ( 1 ) ;
262
270
}
263
-
264
- console . log ( chalk . cyan ( `\n📋 Project: ${ chalk . bold ( project . projectId ) } ` ) ) ;
271
+
272
+ // Filter tasks by state if specified
273
+ let tasks = project . tasks ;
274
+ if ( options . state && options . state !== "all" ) {
275
+ tasks = project . tasks . filter ( task => {
276
+ switch ( options . state ) {
277
+ case "open" :
278
+ return task . status !== "done" ;
279
+ case "pending_approval" :
280
+ return task . status === "done" && ! task . approved ;
281
+ case "completed" :
282
+ return task . status === "done" && task . approved ;
283
+ default :
284
+ return true ;
285
+ }
286
+ } ) ;
287
+ }
288
+
289
+ console . log ( chalk . cyan ( `\n📋 Project ${ chalk . bold ( options . project ) } details:` ) ) ;
265
290
console . log ( ` - ${ chalk . bold ( 'Initial Prompt:' ) } ${ project . initialPrompt } ` ) ;
266
- console . log ( ` - ${ chalk . bold ( 'Status:' ) } ${ project . completed ? chalk . green ( 'Completed ✓' ) : chalk . yellow ( 'In Progress ⟳' ) } ` ) ;
291
+ if ( project . projectPlan && project . projectPlan !== project . initialPrompt ) {
292
+ console . log ( ` - ${ chalk . bold ( 'Project Plan:' ) } ${ project . projectPlan } ` ) ;
293
+ }
294
+ console . log ( ` - ${ chalk . bold ( 'Status:' ) } ${ project . completed ? chalk . green ( 'Completed ✓' ) : chalk . yellow ( 'In Progress' ) } ` ) ;
295
+
296
+ // Show progress info
297
+ const totalTasks = project . tasks . length ;
298
+ const completedTasks = project . tasks . filter ( t => t . status === "done" ) . length ;
299
+ const approvedTasks = project . tasks . filter ( t => t . approved ) . length ;
267
300
268
- console . log ( chalk . cyan ( `\n📋 Tasks:` ) ) ;
269
- if ( project . tasks . length === 0 ) {
270
- console . log ( chalk . yellow ( ' No tasks found for this project.' ) ) ;
271
- } else {
272
- project . tasks . forEach ( task => {
273
- console . log ( ` - ${ chalk . bold ( task . id ) } : ${ task . title } ` ) ;
274
- console . log ( ` ${ chalk . dim ( 'Description:' ) } ${ task . description } ` ) ;
275
- console . log ( ` ${ chalk . dim ( 'Status:' ) } ${ task . status === 'done' ? chalk . green ( 'Done ✓' ) : task . status === 'in progress' ? chalk . yellow ( 'In Progress ⟳' ) : chalk . blue ( 'Not Started ○' ) } ` ) ;
276
- console . log ( ` ${ chalk . dim ( 'Approved:' ) } ${ task . approved ? chalk . green ( 'Yes ✓' ) : chalk . red ( 'No ✗' ) } ` ) ;
277
- if ( task . status === 'done' ) {
278
- console . log ( ` ${ chalk . dim ( 'Completed Details:' ) } ${ task . completedDetails || chalk . gray ( "None" ) } ` ) ;
301
+ console . log ( chalk . cyan ( `\n📊 Progress: ${ chalk . bold ( `${ approvedTasks } /${ completedTasks } /${ totalTasks } ` ) } (approved/completed/total)` ) ) ;
302
+
303
+ // Create a progress bar
304
+ const bar = '▓' . repeat ( approvedTasks ) + '▒' . repeat ( completedTasks - approvedTasks ) + '░' . repeat ( totalTasks - completedTasks ) ;
305
+ console . log ( ` ${ bar } ` ) ;
306
+
307
+ if ( tasks . length > 0 ) {
308
+ console . log ( chalk . cyan ( '\n📝 Tasks:' ) ) ;
309
+ tasks . forEach ( t => {
310
+ const status = t . status === 'done' ? chalk . green ( 'Done ✓' ) : t . status === 'in progress' ? chalk . yellow ( 'In Progress ⟳' ) : chalk . blue ( 'Not Started ○' ) ;
311
+ const approved = t . approved ? chalk . green ( 'Yes ✓' ) : chalk . red ( 'No ✗' ) ;
312
+ console . log ( ` - ${ chalk . bold ( t . id ) } : ${ t . title } ` ) ;
313
+ console . log ( ` Status: ${ status } , Approved: ${ approved } ` ) ;
314
+ console . log ( ` Description: ${ t . description } ` ) ;
315
+ if ( t . completedDetails ) {
316
+ console . log ( ` Completed Details: ${ t . completedDetails } ` ) ;
279
317
}
280
- console . log ( ) ;
281
318
} ) ;
319
+ } else {
320
+ console . log ( chalk . yellow ( '\nNo tasks match the specified state filter.' ) ) ;
282
321
}
283
322
} else {
284
323
// List all projects
285
- console . log ( chalk . cyan ( `\n📋 All Projects:` ) ) ;
286
- data . projects . forEach ( project => {
287
- const totalTasks = project . tasks . length ;
288
- const completedTasks = project . tasks . filter ( t => t . status === "done" ) . length ;
289
- const approvedTasks = project . tasks . filter ( t => t . approved ) . length ;
324
+ let projectsToList = data . projects ;
325
+
326
+ if ( options . state && options . state !== "all" ) {
327
+ projectsToList = data . projects . filter ( project => {
328
+ switch ( options . state ) {
329
+ case "open" :
330
+ return ! project . completed && project . tasks . some ( task => task . status !== "done" ) ;
331
+ case "pending_approval" :
332
+ return project . tasks . some ( task => task . status === "done" && ! task . approved ) ;
333
+ case "completed" :
334
+ return project . completed && project . tasks . every ( task => task . status === "done" && task . approved ) ;
335
+ default :
336
+ return true ;
337
+ }
338
+ } ) ;
339
+ }
340
+
341
+ if ( projectsToList . length === 0 ) {
342
+ console . log ( chalk . yellow ( 'No projects match the specified state filter.' ) ) ;
343
+ return ;
344
+ }
345
+
346
+ console . log ( chalk . cyan ( '\n📋 Projects List:' ) ) ;
347
+ projectsToList . forEach ( p => {
348
+ const totalTasks = p . tasks . length ;
349
+ const completedTasks = p . tasks . filter ( t => t . status === "done" ) . length ;
350
+ const approvedTasks = p . tasks . filter ( t => t . approved ) . length ;
351
+ const status = p . completed ? chalk . green ( 'Completed ✓' ) : chalk . yellow ( 'In Progress' ) ;
352
+
353
+ console . log ( `\n${ chalk . bold ( p . projectId ) } : ${ status } ` ) ;
354
+ console . log ( ` Initial Prompt: ${ p . initialPrompt . substring ( 0 , 100 ) } ${ p . initialPrompt . length > 100 ? '...' : '' } ` ) ;
355
+ console . log ( ` Progress: ${ chalk . bold ( `${ approvedTasks } /${ completedTasks } /${ totalTasks } ` ) } (approved/completed/total)` ) ;
290
356
291
- console . log ( ` - ${ chalk . bold ( project . projectId ) } : ${ project . initialPrompt . substring ( 0 , 50 ) } ${ project . initialPrompt . length > 50 ? '...' : '' } ` ) ;
292
- console . log ( ` ${ chalk . dim ( 'Status:' ) } ${ project . completed ? chalk . green ( 'Completed ✓' ) : chalk . yellow ( 'In Progress ⟳' ) } ` ) ;
293
- console . log ( ` ${ chalk . dim ( 'Progress:' ) } ${ chalk . bold ( `${ approvedTasks } /${ completedTasks } /${ totalTasks } ` ) } (approved/completed/total)` ) ;
294
- console . log ( ) ;
357
+ // Create a progress bar
358
+ const bar = '▓' . repeat ( approvedTasks ) + '▒' . repeat ( completedTasks - approvedTasks ) + '░' . repeat ( totalTasks - completedTasks ) ;
359
+ console . log ( ` ${ bar } ` ) ;
295
360
} ) ;
296
-
297
- console . log ( chalk . blue ( `Use '${ chalk . bold ( 'task-manager-cli list -p <projectId>' ) } ' for detailed information about a specific project.` ) ) ;
298
361
}
299
362
} catch ( error ) {
300
363
console . error ( chalk . red ( `An error occurred: ${ error instanceof Error ? error . message : String ( error ) } ` ) ) ;
301
364
process . exit ( 1 ) ;
302
365
}
303
366
} ) ;
304
367
305
- program . parse ( ) ;
368
+ program . parse ( process . argv ) ;
0 commit comments