feat(backend): design the cli to look professional

This commit is contained in:
2025-08-28 00:27:13 -04:00
parent 6763a31a41
commit 4df946731a
5 changed files with 339 additions and 185 deletions

View File

@@ -8,13 +8,11 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING:
from backend.cli.base import NimbusFlowCLI
from backend.cli.utils import format_member_row
from backend.cli.utils import format_member_row, create_table_header, create_table_separator, TableColors
def cmd_members_list(cli: "NimbusFlowCLI", args) -> None:
"""List all members with optional filters."""
print("Listing members...")
# Get all classifications for lookup
classifications = cli.classification_repo.list_all()
classification_map = {c.ClassificationId: c.ClassificationName for c in classifications}
@@ -29,7 +27,7 @@ def cmd_members_list(cli: "NimbusFlowCLI", args) -> None:
break
if classification_id is None:
print(f"Classification '{args.classification}' not found")
print(f"{TableColors.ERROR}Classification '{args.classification}' not found{TableColors.RESET}")
return
members = cli.member_repo.get_by_classification_ids([classification_id])
@@ -39,26 +37,28 @@ def cmd_members_list(cli: "NimbusFlowCLI", args) -> None:
members = cli.member_repo.list_all()
if not members:
print("No members found.")
print(f"{TableColors.DIM}No members found.{TableColors.RESET}")
return
# Print header
print(f"\n{'ID':<3} | {'First Name':<12} | {'Last Name':<15} | {'Classification':<12} | {'Active':<6} | {'Email'}")
print("-" * 80)
# Print styled header
print()
print(create_table_header("ID ", "First Name ", "Last Name ", "Classification ", "Status ", "Email"))
print(create_table_separator(90))
# Print members
for member in members:
classification_name = classification_map.get(member.ClassificationId)
print(format_member_row(member, classification_name))
print(f"\nTotal: {len(members)} members")
print()
print(f"{TableColors.SUCCESS}Total: {len(members)} members{TableColors.RESET}")
def cmd_members_show(cli: "NimbusFlowCLI", args) -> None:
"""Show detailed information about a specific member."""
member = cli.member_repo.get_by_id(args.member_id)
if not member:
print(f"Member with ID {args.member_id} not found")
print(f"{TableColors.ERROR}Member with ID {args.member_id} not found{TableColors.RESET}")
return
# Get classification name
@@ -66,20 +66,24 @@ def cmd_members_show(cli: "NimbusFlowCLI", args) -> None:
if member.ClassificationId:
classification = cli.classification_repo.get_by_id(member.ClassificationId)
print(f"\n📋 Member Details (ID: {member.MemberId})")
print("-" * 50)
print(f"Name: {member.FirstName} {member.LastName}")
print(f"Email: {member.Email or 'N/A'}")
print(f"Phone: {member.PhoneNumber or 'N/A'}")
print(f"Classification: {classification.ClassificationName if classification else 'N/A'}")
print(f"Active: {'Yes' if member.IsActive else 'No'}")
print(f"Notes: {member.Notes or 'N/A'}")
print(f"\n{TableColors.HEADER}Member Details (ID: {member.MemberId}){TableColors.RESET}")
print(f"{TableColors.BORDER}{'' * 50}{TableColors.RESET}")
print(f"{TableColors.BOLD}Name:{TableColors.RESET} {member.FirstName} {member.LastName}")
print(f"{TableColors.BOLD}Email:{TableColors.RESET} {member.Email or f'{TableColors.DIM}N/A{TableColors.RESET}'}")
print(f"{TableColors.BOLD}Phone:{TableColors.RESET} {member.PhoneNumber or f'{TableColors.DIM}N/A{TableColors.RESET}'}")
print(f"{TableColors.BOLD}Classification:{TableColors.RESET} {TableColors.YELLOW}{classification.ClassificationName if classification else f'{TableColors.DIM}N/A'}{TableColors.RESET}")
print(f"\n⏰ Schedule History:")
print(f"Last Scheduled: {member.LastScheduledAt or 'Never'}")
print(f"Last Accepted: {member.LastAcceptedAt or 'Never'}")
print(f"Last Declined: {member.LastDeclinedAt or 'Never'}")
print(f"Decline Streak: {member.DeclineStreak}")
active_status = f"{TableColors.SUCCESS}Yes{TableColors.RESET}" if member.IsActive else f"{TableColors.ERROR}No{TableColors.RESET}"
print(f"{TableColors.BOLD}Active:{TableColors.RESET} {active_status}")
print(f"{TableColors.BOLD}Notes:{TableColors.RESET} {member.Notes or f'{TableColors.DIM}N/A{TableColors.RESET}'}")
print(f"\n{TableColors.HEADER}Schedule History:{TableColors.RESET}")
print(f"{TableColors.BOLD}Last Scheduled:{TableColors.RESET} {member.LastScheduledAt or f'{TableColors.DIM}Never{TableColors.RESET}'}")
print(f"{TableColors.BOLD}Last Accepted:{TableColors.RESET} {member.LastAcceptedAt or f'{TableColors.DIM}Never{TableColors.RESET}'}")
print(f"{TableColors.BOLD}Last Declined:{TableColors.RESET} {member.LastDeclinedAt or f'{TableColors.DIM}Never{TableColors.RESET}'}")
decline_color = TableColors.ERROR if member.DeclineStreak > 0 else TableColors.SUCCESS
print(f"{TableColors.BOLD}Decline Streak:{TableColors.RESET} {decline_color}{member.DeclineStreak}{TableColors.RESET}")
def setup_members_parser(subparsers) -> None: