package components import ( "fmt" "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) // DeleteConfirmModel represents a deletion confirmation modal with name verification type DeleteConfirmModel struct { clientName string input textinput.Model Visible bool Width int Height int showErrorMessage bool } // Styles var ( deleteModalStyle = lipgloss.NewStyle(). Border(lipgloss.RoundedBorder()). BorderForeground(lipgloss.Color("196")). Padding(1, 3). Background(lipgloss.Color("235")) deleteTitleStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("226")). Bold(true) deleteMessageStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("255")). Width(60) deleteWarningStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("196")). Bold(true). MarginTop(1) deleteInputStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("255")). Width(60) deleteHelpStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("241")). MarginTop(1) deleteErrorStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("196")). Bold(true). MarginTop(1) deleteSuccessStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("46")). Bold(true). MarginTop(1) ) // NewDeleteConfirm creates a new deletion confirmation modal func NewDeleteConfirm(clientName string, width, height int) *DeleteConfirmModel { ti := textinput.New() ti.Placeholder = "Type client name to confirm" ti.Focus() ti.CharLimit = 100 ti.Width = 40 return &DeleteConfirmModel{ clientName: clientName, input: ti, Visible: true, Width: width, Height: height, showErrorMessage: false, } } // Init initializes the deletion confirmation modal func (m *DeleteConfirmModel) Init() tea.Cmd { return textinput.Blink } // Update handles messages for the deletion confirmation modal func (m *DeleteConfirmModel) Update(msg tea.Msg) (*DeleteConfirmModel, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "esc": m.Visible = false return m, nil case "enter": if m.input.Value() == m.clientName { m.Visible = false return m, nil } m.showErrorMessage = true return m, nil } } m.input, cmd = m.input.Update(msg) return m, cmd } // View renders the deletion confirmation modal func (m *DeleteConfirmModel) View() string { if !m.Visible { return "" } // Check if input matches client name matches := m.input.Value() == m.clientName // Build warning section warningText := deleteWarningStyle.Render( fmt.Sprintf("⚠️ This will permanently delete client '%s'", m.clientName), ) // Build message section messageText := deleteMessageStyle.Render( fmt.Sprintf("This action cannot be undone. Please type the client name to confirm deletion."), ) // Build input section inputSection := lipgloss.JoinVertical( lipgloss.Left, "", deleteInputStyle.Render("Client name:"), m.input.View(), ) // Build status section var statusText string if matches { statusText = deleteSuccessStyle.Render("✓ Client name matches. Press Enter to confirm deletion.") } else if m.showErrorMessage { statusText = deleteErrorStyle.Render("✗ Client name does not match. Please try again.") } else if m.input.Value() != "" { statusText = deleteHelpStyle.Render("Client name does not match yet...") } else { statusText = deleteHelpStyle.Render("Type the client name to enable confirmation.") } // Build help section helpText := deleteHelpStyle.Render("Esc to cancel • Enter to confirm (when name matches)") // Build modal content content := lipgloss.JoinVertical( lipgloss.Left, deleteTitleStyle.Render("🗑️ Delete Client"), "", warningText, "", messageText, inputSection, statusText, "", helpText, ) // Apply modal style modal := deleteModalStyle.Render(content) // Center modal on screen modalWidth := lipgloss.Width(modal) modalHeight := lipgloss.Height(modal) x := (m.Width - modalWidth) / 2 if x < 0 { x = 0 } y := (m.Height - modalHeight) / 2 if y < 0 { y = 0 } return lipgloss.Place(m.Width, m.Height, lipgloss.Left, lipgloss.Top, modal, lipgloss.WithWhitespaceChars(" "), lipgloss.WithWhitespaceForeground(lipgloss.Color("235")), ) } // IsConfirmed returns true if user confirmed the deletion func (m *DeleteConfirmModel) IsConfirmed() bool { return !m.Visible && m.input.Value() == m.clientName } // IsCancelled returns true if user cancelled func (m *DeleteConfirmModel) IsCancelled() bool { return !m.Visible && m.input.Value() != m.clientName } // Reset resets the modal for reuse func (m *DeleteConfirmModel) Reset() { m.input.SetValue("") m.input.Reset() m.Visible = true m.showErrorMessage = false }