package components import ( "fmt" "github.com/calmcacil/wg-admin/internal/tui/theme" "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 } // Local styles for modal var ( modalBaseStyle = lipgloss.NewStyle().Border(lipgloss.RoundedBorder()).BorderForeground(lipgloss.Color("196")).Background(lipgloss.Color("235")) modalTitleStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("226")).Bold(true) modalMessageStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("255")) modalHelpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("241")) ) // 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 := theme.StyleError.Bold(true).MarginTop(1).Render( fmt.Sprintf("⚠️ This will permanently delete client '%s'", m.clientName), ) // Build message section messageText := modalMessageStyle.Width(60).Render( fmt.Sprintf("This action cannot be undone. Please type the client name to confirm deletion."), ) // Build input section inputSection := lipgloss.JoinVertical( lipgloss.Left, "", theme.StyleValue.Width(60).Render("Client name:"), m.input.View(), ) // Build status section var statusText string if matches { statusText = theme.StyleSuccess.Bold(true).MarginTop(1).Render("✓ Client name matches. Press Enter to confirm deletion.") } else if m.showErrorMessage { statusText = theme.StyleError.Bold(true).MarginTop(1).Render("✗ Client name does not match. Please try again.") } else if m.input.Value() != "" { statusText = modalHelpStyle.Render("Client name does not match yet...") } else { statusText = modalHelpStyle.Render("Type the client name to enable confirmation.") } // Build help section helpText := modalHelpStyle.Render("Esc to cancel • Enter to confirm (when name matches)") // Build modal content content := lipgloss.JoinVertical( lipgloss.Left, modalTitleStyle.Render("🗑️ Delete Client"), "", warningText, "", messageText, inputSection, statusText, "", helpText, ) // Apply modal style modal := modalBaseStyle.Padding(1, 3).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(theme.StyleBackground), ) } // 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 }