"""Small input-prompting and formatting helpers shared by the menu screens.""" import datetime import re GUID_RE = re.compile(r"^\d{12}$") PHONE_RE = re.compile(r"^\d{10}$") def pause(): input("\nPress Enter to continue...") def clear_hint(): print("\n" + "-" * 60 + "\n") def prompt_str(label, max_len=None, required=True, allow_blank_skip=False): """Prompt for a string. allow_blank_skip=True returns None on empty input (for 'leave unchanged').""" while True: suffix = f" (max {max_len} chars)" if max_len else "" val = input(f"{label}{suffix}: ").strip() if not val: if allow_blank_skip: return None if required: print(" This field is required.") continue return "" if max_len and len(val) > max_len: print(f" Too long — max {max_len} characters.") continue return val def prompt_int(label, max_digits=None, allow_blank_skip=False): while True: val = input(f"{label}: ").strip() if not val: if allow_blank_skip: return None print(" This field is required.") continue if not val.isdigit(): print(" Please enter a whole number.") continue if max_digits and len(val) > max_digits: print(f" Too many digits — max {max_digits}.") continue return int(val) def prompt_guid(label="Guardian ID / GUID (12-digit Aadhaar number)", allow_blank_skip=False): while True: val = input(f"{label}: ").strip() if not val: if allow_blank_skip: return None print(" This field is required.") continue if not GUID_RE.match(val): print(" GUID must be exactly 12 digits.") continue return val def prompt_phone(label="Guardian phone (10 digits, optional)", allow_blank_skip=True): while True: val = input(f"{label}: ").strip() if not val: return None # NULL is allowed for GPhone if not PHONE_RE.match(val): print(" Phone must be exactly 10 digits (or leave blank).") continue return val def prompt_date(label, allow_blank_skip=False): while True: val = input(f"{label} (YYYY-MM-DD): ").strip() if not val: if allow_blank_skip: return None print(" This field is required.") continue try: return datetime.datetime.strptime(val, "%Y-%m-%d").date() except ValueError: print(" Invalid date — use format YYYY-MM-DD, e.g. 2015-08-21.") def prompt_attendance_status(label="Status (P=present, A=absent)"): while True: val = input(f"{label}: ").strip().upper() if val in ("P", "A"): return val print(" Please enter 'P' or 'A'.") def print_table(rows, columns=None): """Pretty-print a list of dict rows as a simple aligned table.""" if not rows: print(" (no records found)") return if columns is None: columns = list(rows[0].keys()) widths = {} for col in columns: widths[col] = max(len(str(col)), *(len(str(r.get(col, ""))) for r in rows)) header = " " + " | ".join(str(col).ljust(widths[col]) for col in columns) print(header) print(" " + "-+-".join("-" * widths[col] for col in columns)) for r in rows: print(" " + " | ".join(str(r.get(col, "")).ljust(widths[col]) for col in columns)) print(f"\n ({len(rows)} record{'s' if len(rows) != 1 else ''})")