feat(cli): improve member design and usability
This commit is contained in:
@@ -12,7 +12,7 @@ if TYPE_CHECKING:
|
||||
|
||||
from .commands import (
|
||||
cmd_members_list, cmd_members_show,
|
||||
cmd_schedules_list, cmd_schedules_show, cmd_schedules_accept, cmd_schedules_decline, cmd_schedules_schedule,
|
||||
cmd_schedules_list, cmd_schedules_show, cmd_schedules_accept, cmd_schedules_decline, cmd_schedules_remove, cmd_schedules_schedule,
|
||||
cmd_services_list,
|
||||
)
|
||||
|
||||
@@ -173,15 +173,12 @@ def display_schedules_menu():
|
||||
print(f"\n{Colors.HEADER}Schedules{Colors.RESET}")
|
||||
print(f"{Colors.GREY}─" * 50 + f"{Colors.RESET}")
|
||||
print()
|
||||
print(f" {Colors.CYAN}1.{Colors.RESET} List all schedules")
|
||||
print(f" {Colors.CYAN}2.{Colors.RESET} List pending schedules")
|
||||
print(f" {Colors.CYAN}3.{Colors.RESET} List accepted schedules")
|
||||
print(f" {Colors.CYAN}4.{Colors.RESET} List declined schedules")
|
||||
print(f" {Colors.CYAN}5.{Colors.RESET} Show schedule details")
|
||||
print(f" {Colors.CYAN}6.{Colors.RESET} {Colors.GREEN}Accept a schedule{Colors.RESET}")
|
||||
print(f" {Colors.CYAN}7.{Colors.RESET} {Colors.RED}Decline a schedule{Colors.RESET}")
|
||||
print(f" {Colors.CYAN}8.{Colors.RESET} {Colors.YELLOW}Schedule next member for service{Colors.RESET}")
|
||||
print(f" {Colors.CYAN}9.{Colors.RESET} {Colors.DIM}Back to main menu{Colors.RESET}")
|
||||
print(f" {Colors.CYAN}1.{Colors.RESET} Browse schedules")
|
||||
print(f" {Colors.CYAN}2.{Colors.RESET} {Colors.GREEN}Accept a schedule{Colors.RESET}")
|
||||
print(f" {Colors.CYAN}3.{Colors.RESET} {Colors.RED}Decline a schedule{Colors.RESET}")
|
||||
print(f" {Colors.CYAN}4.{Colors.RESET} {Colors.ERROR}Remove scheduled members{Colors.RESET}")
|
||||
print(f" {Colors.CYAN}5.{Colors.RESET} {Colors.YELLOW}Schedule next member for service{Colors.RESET}")
|
||||
print(f" {Colors.CYAN}6.{Colors.RESET} {Colors.DIM}Back to main menu{Colors.RESET}")
|
||||
print()
|
||||
|
||||
|
||||
@@ -251,6 +248,25 @@ def get_date_input(prompt: str = "Enter date (YYYY-MM-DD)") -> str:
|
||||
return ""
|
||||
|
||||
|
||||
def get_date_input_optional(prompt: str = "Enter date (YYYY-MM-DD)") -> str:
|
||||
"""Get optional date input from user (allows empty input)."""
|
||||
while True:
|
||||
try:
|
||||
print(create_simple_input_box(prompt))
|
||||
date_str = input(f"{Colors.INPUT_BOX}└─> {Colors.RESET}").strip()
|
||||
if not date_str:
|
||||
return "" # Allow empty input
|
||||
# Basic date format validation
|
||||
if len(date_str) == 10 and date_str.count('-') == 2:
|
||||
parts = date_str.split('-')
|
||||
if len(parts[0]) == 4 and len(parts[1]) == 2 and len(parts[2]) == 2:
|
||||
return date_str
|
||||
print(f"{Colors.ERROR}Please use format YYYY-MM-DD (e.g., 2025-09-07){Colors.RESET}")
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
print(f"\n{Colors.WARNING}Operation cancelled{Colors.RESET}")
|
||||
return ""
|
||||
|
||||
|
||||
class MockArgs:
|
||||
"""Mock args object for interactive commands."""
|
||||
def __init__(self, **kwargs):
|
||||
@@ -306,73 +322,105 @@ def handle_schedules_menu(cli: "NimbusFlowCLI"):
|
||||
while True:
|
||||
clear_screen()
|
||||
display_schedules_menu()
|
||||
choice = get_user_choice(9)
|
||||
choice = get_user_choice(6)
|
||||
|
||||
if choice == 1: # List all schedules
|
||||
clear_screen()
|
||||
print(f"{Colors.SUCCESS}Listing all schedules...{Colors.RESET}\n")
|
||||
cmd_schedules_list(cli, MockArgs(service_id=None, status=None))
|
||||
input(f"\n{Colors.DIM}Press Enter to continue...{Colors.RESET}")
|
||||
|
||||
elif choice == 2: # List pending schedules
|
||||
clear_screen()
|
||||
print(f"{Colors.WARNING}Listing pending schedules...{Colors.RESET}\n")
|
||||
cmd_schedules_list(cli, MockArgs(service_id=None, status="pending"))
|
||||
input(f"\n{Colors.DIM}Press Enter to continue...{Colors.RESET}")
|
||||
|
||||
elif choice == 3: # List accepted schedules
|
||||
clear_screen()
|
||||
print(f"{Colors.SUCCESS}Listing accepted schedules...{Colors.RESET}\n")
|
||||
cmd_schedules_list(cli, MockArgs(service_id=None, status="accepted"))
|
||||
input(f"\n{Colors.DIM}Press Enter to continue...{Colors.RESET}")
|
||||
|
||||
elif choice == 4: # List declined schedules
|
||||
clear_screen()
|
||||
print(f"{Colors.ERROR}Listing declined schedules...{Colors.RESET}\n")
|
||||
cmd_schedules_list(cli, MockArgs(service_id=None, status="declined"))
|
||||
input(f"\n{Colors.DIM}Press Enter to continue...{Colors.RESET}")
|
||||
|
||||
elif choice == 5: # Show schedule details
|
||||
clear_screen()
|
||||
schedule_id = get_text_input("Enter schedule ID", True)
|
||||
if schedule_id.isdigit():
|
||||
# Get date filter
|
||||
date = get_date_input_optional("Enter date to filter schedules (or press Enter to skip)")
|
||||
if not date:
|
||||
clear_screen()
|
||||
print(f"{Colors.SUCCESS}Showing details for schedule {schedule_id}...{Colors.RESET}\n")
|
||||
cmd_schedules_show(cli, MockArgs(schedule_id=int(schedule_id)))
|
||||
cmd_schedules_list(cli, MockArgs(service_id=None, status=None))
|
||||
else:
|
||||
print(f"{Colors.ERROR}Invalid schedule ID{Colors.RESET}")
|
||||
# Find services for the date
|
||||
try:
|
||||
from datetime import date as date_type
|
||||
target_date = date_type.fromisoformat(date)
|
||||
all_services = cli.service_repo.list_all()
|
||||
services_on_date = [s for s in all_services if s.ServiceDate == target_date]
|
||||
except ValueError:
|
||||
clear_screen()
|
||||
print(f"{Colors.ERROR}Invalid date format. Please use YYYY-MM-DD format.{Colors.RESET}")
|
||||
services_on_date = []
|
||||
|
||||
if not services_on_date:
|
||||
clear_screen()
|
||||
print(f"{Colors.ERROR}No services found for {date}{Colors.RESET}")
|
||||
else:
|
||||
clear_screen()
|
||||
|
||||
# Show available services for selection
|
||||
service_type_map = {st.ServiceTypeId: st.TypeName for st in cli.service_type_repo.list_all()}
|
||||
|
||||
print(f"\n{Colors.HEADER}Services available on {date}{Colors.RESET}")
|
||||
print(f"{Colors.GREY}─" * 50 + f"{Colors.RESET}")
|
||||
print()
|
||||
for i, service in enumerate(services_on_date, 1):
|
||||
type_name = service_type_map.get(service.ServiceTypeId, "Unknown")
|
||||
print(f" {Colors.CYAN}{i}.{Colors.RESET} {type_name}")
|
||||
print()
|
||||
|
||||
# Get service selection
|
||||
try:
|
||||
print(create_simple_input_box(f"Select service (1-{len(services_on_date)}) or press Enter to show all"))
|
||||
choice_input = input(f"{Colors.INPUT_BOX}└─> {Colors.RESET}").strip()
|
||||
|
||||
if not choice_input:
|
||||
# Empty input - show all services for this date
|
||||
clear_screen()
|
||||
cmd_schedules_list(cli, MockArgs(service_id=None, status=None, date=date))
|
||||
elif not choice_input.isdigit():
|
||||
print(f"{Colors.ERROR}Invalid selection{Colors.RESET}")
|
||||
else:
|
||||
service_choice = int(choice_input)
|
||||
|
||||
if service_choice < 1 or service_choice > len(services_on_date):
|
||||
print(f"{Colors.ERROR}Please enter a number between 1 and {len(services_on_date)}{Colors.RESET}")
|
||||
else:
|
||||
clear_screen()
|
||||
selected_service = services_on_date[service_choice - 1]
|
||||
cmd_schedules_list(cli, MockArgs(service_id=selected_service.ServiceId, status=None))
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
print(f"\n{Colors.WARNING}Operation cancelled{Colors.RESET}")
|
||||
|
||||
input(f"\n{Colors.DIM}Press Enter to continue...{Colors.RESET}")
|
||||
|
||||
elif choice == 6: # Accept schedule
|
||||
elif choice == 2: # Accept schedule
|
||||
clear_screen()
|
||||
date = get_date_input("Enter date for interactive accept")
|
||||
if date:
|
||||
clear_screen()
|
||||
print(f"{Colors.SUCCESS}Starting interactive accept for {date}...{Colors.RESET}\n")
|
||||
cmd_schedules_accept(cli, MockArgs(date=date, schedule_id=None))
|
||||
input(f"\n{Colors.DIM}Press Enter to continue...{Colors.RESET}")
|
||||
|
||||
elif choice == 7: # Decline schedule
|
||||
elif choice == 3: # Decline schedule
|
||||
clear_screen()
|
||||
date = get_date_input("Enter date for interactive decline")
|
||||
if date:
|
||||
clear_screen()
|
||||
reason = get_text_input("Enter decline reason (optional)", False)
|
||||
clear_screen()
|
||||
print(f"{Colors.ERROR}Starting interactive decline for {date}...{Colors.RESET}\n")
|
||||
cmd_schedules_decline(cli, MockArgs(date=date, schedule_id=None, reason=reason))
|
||||
input(f"\n{Colors.DIM}Press Enter to continue...{Colors.RESET}")
|
||||
|
||||
elif choice == 8: # Schedule next member
|
||||
elif choice == 4: # Remove scheduled members
|
||||
clear_screen()
|
||||
date = get_date_input("Enter date to remove schedules for")
|
||||
if date:
|
||||
clear_screen()
|
||||
cmd_schedules_remove(cli, MockArgs(date=date, schedule_id=None))
|
||||
input(f"\n{Colors.DIM}Press Enter to continue...{Colors.RESET}")
|
||||
|
||||
elif choice == 5: # Schedule next member
|
||||
clear_screen()
|
||||
date = get_date_input("Enter date to schedule for")
|
||||
if date:
|
||||
clear_screen()
|
||||
print(f"{Colors.WARNING}Starting scheduling for {date}...{Colors.RESET}\n")
|
||||
cmd_schedules_schedule(cli, MockArgs(service_id=None, date=date, classifications=None))
|
||||
input(f"\n{Colors.DIM}Press Enter to continue...{Colors.RESET}")
|
||||
|
||||
elif choice == 9: # Back to main menu
|
||||
elif choice == 6: # Back to main menu
|
||||
break
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user