Adding 17 CLAUDE.md files across the project to provide detailed context and implementation guidelines for AI development agents: Root Documentation: - CLAUDE.md - Main project guide with Git workflow requirements Component Documentation: - commands/CLAUDE.md - Command architecture and patterns - models/CLAUDE.md - Pydantic models and validation - services/CLAUDE.md - Service layer and API interactions - tasks/CLAUDE.md - Background tasks and automation - tests/CLAUDE.md - Testing strategies and patterns - utils/CLAUDE.md - Utility functions and decorators - views/CLAUDE.md - Discord UI components and embeds Command Package Documentation: - commands/help/CLAUDE.md - Help system implementation - commands/injuries/CLAUDE.md - Injury management commands - commands/league/CLAUDE.md - League-wide commands - commands/players/CLAUDE.md - Player information commands - commands/profile/CLAUDE.md - User profile commands - commands/teams/CLAUDE.md - Team information commands - commands/transactions/CLAUDE.md - Transaction management - commands/utilities/CLAUDE.md - Utility commands - commands/voice/CLAUDE.md - Voice channel management Key Updates: - Updated .gitignore to track CLAUDE.md files in version control - Added Git Workflow section requiring branch-based development - Documented all architectural patterns and best practices - Included comprehensive command/service implementation guides These files provide essential context for AI agents working on the codebase, ensuring consistent patterns, proper error handling, and maintainable code. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
709 lines
22 KiB
Markdown
709 lines
22 KiB
Markdown
# Views Directory
|
||
|
||
The views directory contains Discord UI components for Discord Bot v2.0, providing consistent visual interfaces and interactive elements. This includes embeds, modals, buttons, select menus, and other Discord UI components.
|
||
|
||
## Architecture
|
||
|
||
### Component-Based UI Design
|
||
Views in Discord Bot v2.0 follow these principles:
|
||
- **Consistent styling** via centralized templates
|
||
- **Reusable components** for common UI patterns
|
||
- **Error handling** with graceful degradation
|
||
- **User interaction tracking** and validation
|
||
- **Accessibility** with proper labeling and feedback
|
||
|
||
### Base Components
|
||
All view components inherit from Discord.py base classes with enhanced functionality:
|
||
- **BaseView** - Enhanced discord.ui.View with logging and user validation
|
||
- **BaseModal** - Enhanced discord.ui.Modal with error handling
|
||
- **EmbedTemplate** - Centralized embed creation with consistent styling
|
||
|
||
## View Components
|
||
|
||
### Base View System (`base.py`)
|
||
|
||
#### BaseView Class
|
||
Foundation for all interactive views:
|
||
|
||
```python
|
||
class BaseView(discord.ui.View):
|
||
def __init__(self, timeout=180.0, user_id=None):
|
||
super().__init__(timeout=timeout)
|
||
self.user_id = user_id
|
||
self.logger = get_contextual_logger(f'{__name__}.BaseView')
|
||
|
||
async def interaction_check(self, interaction) -> bool:
|
||
"""Validate user permissions for interaction."""
|
||
|
||
async def on_timeout(self) -> None:
|
||
"""Handle view timeout gracefully."""
|
||
|
||
async def on_error(self, interaction, error, item) -> None:
|
||
"""Handle view errors with user feedback."""
|
||
```
|
||
|
||
#### ConfirmationView Class (Updated January 2025)
|
||
Reusable confirmation dialog with Confirm/Cancel buttons (`confirmations.py`):
|
||
|
||
**Key Features:**
|
||
- **User restriction**: Only specified users can interact
|
||
- **Customizable labels and styles**: Flexible button appearance
|
||
- **Timeout handling**: Automatic cleanup after timeout
|
||
- **Three-state result**: `True` (confirmed), `False` (cancelled), `None` (timeout)
|
||
- **Clean interface**: Automatically removes buttons after interaction
|
||
|
||
**Usage Pattern:**
|
||
```python
|
||
from views.confirmations import ConfirmationView
|
||
|
||
# Create confirmation dialog
|
||
view = ConfirmationView(
|
||
responders=[interaction.user], # Only this user can interact
|
||
timeout=30.0, # 30 second timeout
|
||
confirm_label="Yes, delete", # Custom label
|
||
cancel_label="No, keep it" # Custom label
|
||
)
|
||
|
||
# Send confirmation
|
||
await interaction.edit_original_response(
|
||
content="⚠️ Are you sure you want to delete this?",
|
||
view=view
|
||
)
|
||
|
||
# Wait for user response
|
||
await view.wait()
|
||
|
||
# Check result
|
||
if view.confirmed is True:
|
||
# User clicked Confirm
|
||
await interaction.edit_original_response(
|
||
content="✅ Deleted successfully",
|
||
view=None
|
||
)
|
||
elif view.confirmed is False:
|
||
# User clicked Cancel
|
||
await interaction.edit_original_response(
|
||
content="❌ Cancelled",
|
||
view=None
|
||
)
|
||
else:
|
||
# Timeout occurred (view.confirmed is None)
|
||
await interaction.edit_original_response(
|
||
content="⏱️ Request timed out",
|
||
view=None
|
||
)
|
||
```
|
||
|
||
**Real-World Example (Scorecard Submission):**
|
||
```python
|
||
# From commands/league/submit_scorecard.py
|
||
if duplicate_game:
|
||
view = ConfirmationView(
|
||
responders=[interaction.user],
|
||
timeout=30.0
|
||
)
|
||
await interaction.edit_original_response(
|
||
content=(
|
||
f"⚠️ This game has already been played!\n"
|
||
f"Would you like me to wipe the old one and re-submit?"
|
||
),
|
||
view=view
|
||
)
|
||
await view.wait()
|
||
|
||
if view.confirmed:
|
||
# User confirmed - proceed with wipe and resubmit
|
||
await wipe_old_data()
|
||
else:
|
||
# User cancelled - exit gracefully
|
||
return
|
||
```
|
||
|
||
**Configuration Options:**
|
||
```python
|
||
ConfirmationView(
|
||
responders=[user1, user2], # Multiple users allowed
|
||
timeout=60.0, # Custom timeout
|
||
confirm_label="Approve", # Custom confirm text
|
||
cancel_label="Reject", # Custom cancel text
|
||
confirm_style=discord.ButtonStyle.red, # Custom button style
|
||
cancel_style=discord.ButtonStyle.grey # Custom button style
|
||
)
|
||
```
|
||
|
||
#### PaginationView Class
|
||
Multi-page navigation for large datasets:
|
||
|
||
```python
|
||
pages = [embed1, embed2, embed3]
|
||
pagination = PaginationView(
|
||
pages=pages,
|
||
user_id=interaction.user.id,
|
||
show_page_numbers=True
|
||
)
|
||
await interaction.followup.send(embed=pagination.get_current_embed(), view=pagination)
|
||
```
|
||
|
||
### Embed Templates (`embeds.py`)
|
||
|
||
#### EmbedTemplate Class
|
||
Centralized embed creation with consistent styling:
|
||
|
||
```python
|
||
# Success embed
|
||
embed = EmbedTemplate.success(
|
||
title="Operation Completed",
|
||
description="Your request was processed successfully."
|
||
)
|
||
|
||
# Error embed
|
||
embed = EmbedTemplate.error(
|
||
title="Operation Failed",
|
||
description="Please check your input and try again."
|
||
)
|
||
|
||
# Warning embed
|
||
embed = EmbedTemplate.warning(
|
||
title="Careful!",
|
||
description="This action cannot be undone."
|
||
)
|
||
|
||
# Info embed
|
||
embed = EmbedTemplate.info(
|
||
title="Information",
|
||
description="Here's what you need to know."
|
||
)
|
||
```
|
||
|
||
#### EmbedColors Dataclass
|
||
Consistent color scheme across all embeds:
|
||
|
||
```python
|
||
@dataclass(frozen=True)
|
||
class EmbedColors:
|
||
PRIMARY: int = 0xa6ce39 # SBA green
|
||
SUCCESS: int = 0x28a745 # Green
|
||
WARNING: int = 0xffc107 # Yellow
|
||
ERROR: int = 0xdc3545 # Red
|
||
INFO: int = 0x17a2b8 # Blue
|
||
SECONDARY: int = 0x6c757d # Gray
|
||
```
|
||
|
||
### Modal Forms (`modals.py`)
|
||
|
||
#### BaseModal Class
|
||
Foundation for interactive forms:
|
||
|
||
```python
|
||
class BaseModal(discord.ui.Modal):
|
||
def __init__(self, title: str, timeout=300.0):
|
||
super().__init__(title=title, timeout=timeout)
|
||
self.logger = get_contextual_logger(f'{__name__}.BaseModal')
|
||
self.result = None
|
||
|
||
async def on_submit(self, interaction):
|
||
"""Handle form submission."""
|
||
|
||
async def on_error(self, interaction, error):
|
||
"""Handle form errors."""
|
||
```
|
||
|
||
#### Usage Pattern
|
||
```python
|
||
class CustomCommandModal(BaseModal):
|
||
def __init__(self):
|
||
super().__init__(title="Create Custom Command")
|
||
|
||
name = discord.ui.TextInput(
|
||
label="Command Name",
|
||
placeholder="Enter command name...",
|
||
required=True,
|
||
max_length=50
|
||
)
|
||
|
||
response = discord.ui.TextInput(
|
||
label="Response",
|
||
placeholder="Enter command response...",
|
||
style=discord.TextStyle.paragraph,
|
||
required=True,
|
||
max_length=2000
|
||
)
|
||
|
||
async def on_submit(self, interaction):
|
||
# Process form data
|
||
command_data = {
|
||
"name": self.name.value,
|
||
"response": self.response.value
|
||
}
|
||
# Handle creation logic
|
||
```
|
||
|
||
### Common UI Elements (`common.py`)
|
||
|
||
#### Shared Components
|
||
- **Loading indicators** for async operations
|
||
- **Status messages** for operation feedback
|
||
- **Navigation elements** for multi-step processes
|
||
- **Validation displays** for form errors
|
||
|
||
### Specialized Views
|
||
|
||
#### Custom Commands (`custom_commands.py`)
|
||
Views specific to custom command management:
|
||
- Command creation forms
|
||
- Command listing with actions
|
||
- Bulk management interfaces
|
||
|
||
#### Player Information (`players.py`)
|
||
Interactive views for player information display with toggleable statistics:
|
||
|
||
**PlayerStatsView** - Toggle batting and pitching statistics independently
|
||
|
||
```python
|
||
from views.players import PlayerStatsView
|
||
|
||
# Create interactive player stats view
|
||
view = PlayerStatsView(
|
||
player=player_with_team,
|
||
season=search_season,
|
||
batting_stats=batting_stats,
|
||
pitching_stats=pitching_stats,
|
||
user_id=interaction.user.id
|
||
)
|
||
|
||
# Get initial embed with stats hidden
|
||
embed = await view.get_initial_embed()
|
||
|
||
# Send with interactive view
|
||
await interaction.followup.send(embed=embed, view=view)
|
||
```
|
||
|
||
**Key Features:**
|
||
- **Basic Info Always Visible**: Name, position, team, sWAR, injury status displayed by default
|
||
- **Stats Hidden by Default**: Batting and pitching stats are hidden until user clicks toggle buttons
|
||
- **Independent Toggles**: Users can show/hide batting and pitching stats separately
|
||
- **Conditional Buttons**: Buttons only appear if corresponding stats are available
|
||
- **User Restriction**: Only the user who ran the command can toggle stats
|
||
- **Timeout Handling**: View times out after 5 minutes with graceful cleanup
|
||
- **Professional UI**: Uses baseball emojis (💥 batting impact, ⚾ pitching) and primary button style
|
||
- **Dynamic Updates**: Embed updates in-place when buttons are clicked
|
||
|
||
**Button Behavior:**
|
||
- **Initial State**: "Show Batting Stats" and "Show Pitching Stats"
|
||
- **Toggled State**: "Hide Batting Stats" and "Hide Pitching Stats"
|
||
- **Visual Feedback**: Button labels change to reflect current state
|
||
- **Clean Interface**: Only relevant buttons are shown based on available data
|
||
|
||
**Implementation Notes:**
|
||
- Inherits from `BaseView` for consistent error handling and logging
|
||
- Stats formatting matches existing player card design with rounded box code blocks
|
||
- Preserves all player card features (images, thumbnails, team colors)
|
||
- Comprehensive logging for debugging and monitoring
|
||
|
||
#### Transaction Management (`transaction_embed.py`) (Updated October 2025)
|
||
Views for player transaction interfaces with dual-mode submission support:
|
||
- **Transaction builder** with interactive controls
|
||
- **Comprehensive validation** and sWAR display
|
||
- **Pre-existing transaction** context
|
||
- **Dual submission modes**: Scheduled (/dropadd) and Immediate (/ilmove)
|
||
- **Dynamic UI instructions**: Context-aware command references
|
||
|
||
**Key Classes:**
|
||
```python
|
||
class TransactionEmbedView(discord.ui.View):
|
||
def __init__(
|
||
self,
|
||
builder: TransactionBuilder,
|
||
user_id: int,
|
||
submission_handler: str = "scheduled", # "scheduled" or "immediate"
|
||
command_name: str = "/dropadd" # Command for UI instructions
|
||
):
|
||
"""
|
||
Interactive transaction builder view supporting both scheduled and immediate execution.
|
||
|
||
Args:
|
||
builder: TransactionBuilder instance
|
||
user_id: Discord user ID (for permission checking)
|
||
submission_handler: "scheduled" for /dropadd, "immediate" for /ilmove
|
||
command_name: Command name shown in "Add More Moves" instructions
|
||
"""
|
||
|
||
async def create_transaction_embed(
|
||
builder: TransactionBuilder,
|
||
command_name: str = "/dropadd"
|
||
) -> discord.Embed:
|
||
"""
|
||
Create transaction builder embed with context-aware instructions.
|
||
|
||
Args:
|
||
builder: TransactionBuilder instance
|
||
command_name: Command name for "Add More Moves" instruction
|
||
|
||
Returns:
|
||
Discord embed showing transaction state with appropriate instructions
|
||
"""
|
||
```
|
||
|
||
**Submission Handler Behavior:**
|
||
- **"scheduled" mode** (/dropadd):
|
||
- Creates transactions for NEXT week
|
||
- No database POST - stays in memory
|
||
- Background task processes later
|
||
- Instructions say "Use `/dropadd` to add more moves"
|
||
|
||
- **"immediate" mode** (/ilmove):
|
||
- Creates transactions for THIS week
|
||
- Immediately POSTs to database API
|
||
- Immediately updates player teams
|
||
- Instructions say "Use `/ilmove` to add more moves"
|
||
|
||
**Usage Examples:**
|
||
```python
|
||
# For /dropadd (scheduled submission)
|
||
embed = await create_transaction_embed(builder, command_name="/dropadd")
|
||
view = TransactionEmbedView(
|
||
builder,
|
||
user_id,
|
||
submission_handler="scheduled",
|
||
command_name="/dropadd"
|
||
)
|
||
|
||
# For /ilmove (immediate submission)
|
||
embed = await create_transaction_embed(builder, command_name="/ilmove")
|
||
view = TransactionEmbedView(
|
||
builder,
|
||
user_id,
|
||
submission_handler="immediate",
|
||
command_name="/ilmove"
|
||
)
|
||
```
|
||
|
||
**Implementation Notes:**
|
||
- **95% code reuse** between /dropadd and /ilmove
|
||
- **Same TransactionBuilder** instance shared between both commands
|
||
- **Dynamic embed description**: Changes based on command_name
|
||
- **Context propagation**: command_name passed through all UI components
|
||
- **Backwards compatible**: Default parameters maintain /dropadd behavior
|
||
|
||
## Styling Guidelines
|
||
|
||
### Embed Consistency
|
||
All embeds should use EmbedTemplate methods:
|
||
|
||
```python
|
||
# ✅ Consistent styling
|
||
embed = EmbedTemplate.success("Player Added", "Player successfully added to roster")
|
||
|
||
# ❌ Inconsistent styling
|
||
embed = discord.Embed(title="Player Added", color=0x00ff00)
|
||
```
|
||
|
||
### Color Usage
|
||
Use the standard color palette:
|
||
- **PRIMARY (SBA Green)** - Default for neutral information
|
||
- **SUCCESS (Green)** - Successful operations
|
||
- **ERROR (Red)** - Errors and failures
|
||
- **WARNING (Yellow)** - Warnings and cautions
|
||
- **INFO (Blue)** - General information
|
||
- **SECONDARY (Gray)** - Less important information
|
||
|
||
### User Feedback
|
||
Provide clear feedback for all user interactions:
|
||
|
||
```python
|
||
# Loading state
|
||
embed = EmbedTemplate.info("Processing", "Please wait while we process your request...")
|
||
|
||
# Success state
|
||
embed = EmbedTemplate.success("Complete", "Your request has been processed successfully.")
|
||
|
||
# Error state with helpful information
|
||
embed = EmbedTemplate.error(
|
||
"Request Failed",
|
||
"The player name was not found. Please check your spelling and try again."
|
||
)
|
||
```
|
||
|
||
## Interactive Components
|
||
|
||
### Button Patterns
|
||
|
||
#### Action Buttons
|
||
```python
|
||
@discord.ui.button(label="Confirm", style=discord.ButtonStyle.success, emoji="✅")
|
||
async def confirm_button(self, interaction, button):
|
||
self.increment_interaction_count()
|
||
# Handle confirmation
|
||
await interaction.response.edit_message(content="Confirmed!", view=None)
|
||
```
|
||
|
||
#### Navigation Buttons
|
||
```python
|
||
@discord.ui.button(emoji="◀️", style=discord.ButtonStyle.primary)
|
||
async def previous_page(self, interaction, button):
|
||
self.current_page = max(0, self.current_page - 1)
|
||
await interaction.response.edit_message(embed=self.get_current_embed(), view=self)
|
||
```
|
||
|
||
### Select Menu Patterns
|
||
|
||
#### Option Selection
|
||
```python
|
||
@discord.ui.select(placeholder="Choose an option...")
|
||
async def select_option(self, interaction, select):
|
||
selected_value = select.values[0]
|
||
# Handle selection
|
||
await interaction.response.send_message(f"You selected: {selected_value}")
|
||
```
|
||
|
||
#### Dynamic Options
|
||
```python
|
||
class PlayerSelectMenu(discord.ui.Select):
|
||
def __init__(self, players: List[Player]):
|
||
options = [
|
||
discord.SelectOption(
|
||
label=player.name,
|
||
value=str(player.id),
|
||
description=f"{player.position} - {player.team.abbrev}"
|
||
)
|
||
for player in players[:25] # Discord limit
|
||
]
|
||
super().__init__(placeholder="Select a player...", options=options)
|
||
```
|
||
|
||
## Error Handling
|
||
|
||
### View Error Handling
|
||
All views implement comprehensive error handling:
|
||
|
||
```python
|
||
async def on_error(self, interaction, error, item):
|
||
"""Handle view errors gracefully."""
|
||
self.logger.error("View error", error=error, item_type=type(item).__name__)
|
||
|
||
try:
|
||
embed = EmbedTemplate.error(
|
||
"Interaction Error",
|
||
"Something went wrong. Please try again."
|
||
)
|
||
|
||
if not interaction.response.is_done():
|
||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||
else:
|
||
await interaction.followup.send(embed=embed, ephemeral=True)
|
||
except Exception as e:
|
||
self.logger.error("Failed to send error message", error=e)
|
||
```
|
||
|
||
### User Input Validation
|
||
Forms validate user input before processing:
|
||
|
||
```python
|
||
async def on_submit(self, interaction):
|
||
# Validate input
|
||
if len(self.name.value) < 2:
|
||
embed = EmbedTemplate.error(
|
||
"Invalid Input",
|
||
"Command name must be at least 2 characters long."
|
||
)
|
||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||
return
|
||
|
||
# Process valid input
|
||
await self.create_command(interaction)
|
||
```
|
||
|
||
## Accessibility Features
|
||
|
||
### User-Friendly Labels
|
||
- **Clear button labels** with descriptive text
|
||
- **Helpful placeholders** in form fields
|
||
- **Descriptive error messages** with actionable guidance
|
||
- **Consistent emoji usage** for visual recognition
|
||
|
||
### Permission Validation
|
||
Views respect user permissions and provide appropriate feedback:
|
||
|
||
```python
|
||
async def interaction_check(self, interaction) -> bool:
|
||
"""Check if user can interact with this view."""
|
||
if self.user_id and interaction.user.id != self.user_id:
|
||
await interaction.response.send_message(
|
||
"❌ You cannot interact with this menu.",
|
||
ephemeral=True
|
||
)
|
||
return False
|
||
return True
|
||
```
|
||
|
||
## Performance Considerations
|
||
|
||
### View Lifecycle Management
|
||
- **Timeout handling** prevents orphaned views
|
||
- **Resource cleanup** in view destructors
|
||
- **Interaction tracking** for usage analytics
|
||
- **Memory management** for large datasets
|
||
|
||
### Efficient Updates
|
||
```python
|
||
# ✅ Efficient - Only update what changed
|
||
await interaction.response.edit_message(embed=new_embed, view=self)
|
||
|
||
# ❌ Inefficient - Sends new message
|
||
await interaction.response.send_message(embed=new_embed, view=new_view)
|
||
```
|
||
|
||
## Testing Strategies
|
||
|
||
### View Testing
|
||
```python
|
||
@pytest.mark.asyncio
|
||
async def test_confirmation_view():
|
||
view = ConfirmationView(user_id=123)
|
||
|
||
# Mock interaction
|
||
interaction = Mock()
|
||
interaction.user.id = 123
|
||
|
||
# Test button click
|
||
await view.confirm_button.callback(interaction)
|
||
|
||
assert view.result is True
|
||
```
|
||
|
||
### Modal Testing
|
||
```python
|
||
@pytest.mark.asyncio
|
||
async def test_custom_command_modal():
|
||
modal = CustomCommandModal()
|
||
|
||
# Set form values
|
||
modal.name.value = "test"
|
||
modal.response.value = "Test response"
|
||
|
||
# Mock interaction
|
||
interaction = Mock()
|
||
|
||
# Test form submission
|
||
await modal.on_submit(interaction)
|
||
|
||
# Verify processing
|
||
assert modal.result is not None
|
||
```
|
||
|
||
## Development Guidelines
|
||
|
||
### Creating New Views
|
||
1. **Inherit from base classes** for consistency
|
||
2. **Use EmbedTemplate** for all embed creation
|
||
3. **Implement proper error handling** in all interactions
|
||
4. **Add user permission checks** where appropriate
|
||
5. **Include comprehensive logging** with context
|
||
6. **Follow timeout patterns** to prevent resource leaks
|
||
|
||
### View Composition
|
||
- **Keep views focused** on single responsibilities
|
||
- **Use composition** over complex inheritance
|
||
- **Separate business logic** from UI logic
|
||
- **Make views testable** with dependency injection
|
||
|
||
### UI Guidelines
|
||
- **Follow Discord design patterns** for familiarity
|
||
- **Use consistent colors** from EmbedColors
|
||
- **Provide clear user feedback** for all actions
|
||
- **Handle edge cases** gracefully
|
||
- **Consider mobile users** in layout design
|
||
|
||
## Transaction Embed Enhancements (January 2025)
|
||
|
||
### Enhanced Display Features
|
||
The transaction embed now provides comprehensive information for better decision-making:
|
||
|
||
#### New Embed Sections
|
||
```python
|
||
async def create_transaction_embed(builder: TransactionBuilder) -> discord.Embed:
|
||
"""
|
||
Creates enhanced transaction embed with sWAR and pre-existing transaction context.
|
||
"""
|
||
# Existing sections...
|
||
|
||
# NEW: Team Cost (sWAR) Display
|
||
swar_status = f"{validation.major_league_swar_status}\n{validation.minor_league_swar_status}"
|
||
embed.add_field(name="Team sWAR", value=swar_status, inline=False)
|
||
|
||
# NEW: Pre-existing Transaction Context (when applicable)
|
||
if validation.pre_existing_transactions_note:
|
||
embed.add_field(
|
||
name="📋 Transaction Context",
|
||
value=validation.pre_existing_transactions_note,
|
||
inline=False
|
||
)
|
||
```
|
||
|
||
### Enhanced Information Display
|
||
|
||
#### sWAR Tracking
|
||
- **Major League sWAR**: Projected team cost for ML roster
|
||
- **Minor League sWAR**: Projected team cost for MiL roster
|
||
- **Formatted Display**: Uses 📊 emoji with 1 decimal precision
|
||
|
||
#### Pre-existing Transaction Context
|
||
Dynamic context display based on scheduled moves:
|
||
|
||
```python
|
||
# Example displays:
|
||
"ℹ️ **Pre-existing Moves**: 3 scheduled moves (+3.7 sWAR)"
|
||
"ℹ️ **Pre-existing Moves**: 2 scheduled moves (-2.5 sWAR)"
|
||
"ℹ️ **Pre-existing Moves**: 1 scheduled moves (no sWAR impact)"
|
||
# No display when no pre-existing moves (clean interface)
|
||
```
|
||
|
||
### Complete Embed Structure
|
||
The enhanced transaction embed now includes:
|
||
|
||
1. **Current Moves** - List of moves in transaction builder
|
||
2. **Roster Status** - Legal/illegal roster counts with limits
|
||
3. **Team Cost (sWAR)** - sWAR for both rosters
|
||
4. **Transaction Context** - Pre-existing moves impact (conditional)
|
||
5. **Errors/Suggestions** - Validation feedback and recommendations
|
||
|
||
### Usage Examples
|
||
|
||
#### Basic Transaction Display
|
||
```python
|
||
# Standard transaction without pre-existing moves
|
||
builder = get_transaction_builder(user_id, team)
|
||
embed = await create_transaction_embed(builder)
|
||
# Shows: moves, roster status, sWAR, errors/suggestions
|
||
```
|
||
|
||
#### Enhanced Context Display
|
||
```python
|
||
# Transaction with pre-existing moves context
|
||
validation = await builder.validate_transaction(next_week=current_week + 1)
|
||
embed = await create_transaction_embed(builder)
|
||
# Shows: all above + pre-existing transaction impact
|
||
```
|
||
|
||
### User Experience Improvements
|
||
- **Complete Context**: Users see full impact including scheduled moves
|
||
- **Visual Clarity**: Consistent emoji usage and formatting
|
||
- **Conditional Display**: Context only shown when relevant
|
||
- **Decision Support**: sWAR projections help strategic planning
|
||
|
||
### Implementation Notes
|
||
- **Backwards Compatible**: Existing embed functionality preserved
|
||
- **Conditional Sections**: Pre-existing context only appears when applicable
|
||
- **Performance**: Validation data cached to avoid repeated calculations
|
||
- **Accessibility**: Clear visual hierarchy with emojis and formatting
|
||
|
||
---
|
||
|
||
**Next Steps for AI Agents:**
|
||
1. Review existing view implementations for patterns
|
||
2. Understand the Discord UI component system
|
||
3. Follow the EmbedTemplate system for consistent styling
|
||
4. Implement proper error handling and user validation
|
||
5. Test interactive components thoroughly
|
||
6. Consider accessibility and user experience in design
|
||
7. Leverage enhanced transaction context for better user guidance |