Files
LazyPM/cmd/pm/intro.go
2026-03-12 14:56:07 +01:00

160 lines
3.6 KiB
Go

package main
import (
"strings"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/style"
"github.com/charmbracelet/bubbles/key"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
const stages = 2
const (
IntroTitle = "✦ Project Management Interface Survey ✦"
IntroductionText = `Welcome! This survey gathers feedback on task management interfaces.
Your responses will help us improve our services. All data is anonymized
and used solely for research purposes.
By participating, you consent to data collection as described below.`
Disclaimer = `📋 Data Collection Notice
• All responses are completely anonymized
• Data is used for research purposes only
• No personally identifiable information is collected
• You may exit at any time by pressing Esc
• We get no data unless you complete the survey and submit.`
)
type keyMap struct {
Start key.Binding
Continue key.Binding
Back key.Binding
Quit key.Binding
}
type introModel struct {
stage int
width, height int
userQuit bool
keys keyMap
}
func newIntroModel() introModel {
var keys = keyMap{
Start: key.NewBinding(
key.WithKeys("enter"),
key.WithHelp("enter", "start survey"),
),
Continue: key.NewBinding(
key.WithKeys(" ", "j", "l", "down", "right"),
key.WithHelp("space", "continue"),
),
Back: key.NewBinding(
key.WithKeys("b", "k", "h", "backspace", "up", "left"),
key.WithHelp("b", "back"),
),
Quit: key.NewBinding(
key.WithKeys("esc", "ctrl+c", "q"),
key.WithHelp("esc", "quit"),
),
}
return introModel{
stage: 1,
keys: keys,
}
}
func (m introModel) Run() error {
model, err := tea.NewProgram(m, tea.WithAltScreen()).Run()
if err != nil {
return err
}
if m, ok := model.(introModel); ok && m.userQuit {
return models.ErrUserQuit
}
return nil
}
func (m introModel) Init() tea.Cmd {
return nil
}
func (m introModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.SetSize(msg.Width, msg.Height)
case tea.KeyMsg:
switch {
case key.Matches(msg, m.keys.Start) && m.stage == stages:
return m, tea.Quit
case key.Matches(msg, m.keys.Continue):
if m.stage < stages {
m.stage++
}
case key.Matches(msg, m.keys.Back):
if m.stage > 1 {
m.stage--
}
return m, nil
case key.Matches(msg, m.keys.Quit):
m.userQuit = true
return m, tea.Quit
}
}
return m, nil
}
func (m introModel) View() string {
if m.width < 55 || m.height < 16 {
return lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center,
style.TextStyle.Render("Terminal too small."))
}
var content string
switch m.stage {
case 1:
content = IntroductionText
case 2:
content = Disclaimer
default:
return ""
}
boxWidth := min(m.width-10, 80)
boxStyle := style.BorderStyle.
Margin(1, 0).Padding(2, 4).Width(boxWidth)
var b strings.Builder
b.WriteString(style.TitleStyle.Render(IntroTitle))
b.WriteString("\n")
b.WriteString(boxStyle.Render(style.TextStyle.Render(content)))
b.WriteString("\n")
helpText := "Press " + m.keys.Continue.Help().Key + " to continue • " +
m.keys.Back.Help().Key + " to go back • " + m.keys.Quit.Help().Key + " to quit"
if m.stage == stages {
helpText += "\nPress " + m.keys.Start.Help().Key + " to start the survey"
}
b.WriteString(style.HelpStyle.Render(helpText))
final := lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, b.String())
return final
}
func (m *introModel) SetSize(width, height int) {
m.width, m.height = width, height
}