This repository has been archived on 2026-03-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
oubliette/internal/shell/banking/screen_changepin.go
Torjus Håkestad adfe372d13 refactor: extract changePinModel into its own sub-model
The Change PIN screen was the only screen with its state (pinInput,
pinStage, pinMessage) stored directly on the top-level model. Extract
it into a changePinModel in screen_changepin.go to match the pattern
used by all other screens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 09:34:56 +01:00

112 lines
2.4 KiB
Go

package banking
import (
"strings"
tea "github.com/charmbracelet/bubbletea"
)
type changePinModel struct {
input string
stage int // 0=old, 1=new, 2=confirm, 3=done
newPin string
done bool
}
func newChangePinModel() changePinModel {
return changePinModel{}
}
func (m changePinModel) Update(msg tea.Msg) (changePinModel, tea.Cmd) {
keyMsg, ok := msg.(tea.KeyMsg)
if !ok {
return m, nil
}
if m.stage == 3 {
m.done = true
return m, nil
}
switch keyMsg.Type {
case tea.KeyEnter:
switch m.stage {
case 0:
if m.input != "" {
m.stage = 1
m.input = ""
}
case 1:
if len(m.input) >= 4 {
m.newPin = m.input
m.stage = 2
m.input = ""
}
case 2:
if m.input == m.newPin {
m.stage = 3
} else {
m.input = ""
m.newPin = ""
m.stage = 1
}
}
case tea.KeyEscape:
m.done = true
case tea.KeyBackspace:
if len(m.input) > 0 {
m.input = m.input[:len(m.input)-1]
}
default:
ch := keyMsg.String()
if len(ch) == 1 && ch[0] >= 32 && ch[0] < 127 && len(m.input) < 12 {
m.input += ch
}
}
return m, nil
}
func (m changePinModel) View() string {
var b strings.Builder
b.WriteString("\n")
b.WriteString(centerText("CHANGE PIN"))
b.WriteString("\n\n")
b.WriteString(thinDivider())
b.WriteString("\n\n")
if m.stage == 3 {
b.WriteString(titleStyle.Render(" PIN CHANGED SUCCESSFULLY"))
b.WriteString("\n\n")
b.WriteString(baseStyle.Render(" YOUR NEW PIN IS NOW ACTIVE."))
b.WriteString("\n")
b.WriteString(baseStyle.Render(" PLEASE USE YOUR NEW PIN FOR ALL FUTURE TRANSACTIONS."))
b.WriteString("\n\n")
b.WriteString(dimStyle.Render(" PRESS ANY KEY TO RETURN TO MAIN MENU"))
} else {
prompts := []string{" CURRENT PIN: ", " NEW PIN: ", " CONFIRM PIN: "}
for i := 0; i < m.stage; i++ {
b.WriteString(baseStyle.Render(prompts[i]))
b.WriteString(baseStyle.Render(strings.Repeat("*", 4)))
b.WriteString("\n")
}
if m.stage < 3 {
b.WriteString(titleStyle.Render(prompts[m.stage]))
masked := strings.Repeat("*", len(m.input))
b.WriteString(inputStyle.Render(masked))
b.WriteString(inputStyle.Render("_"))
b.WriteString("\n")
}
b.WriteString("\n")
if m.stage == 1 {
b.WriteString(dimStyle.Render(" PIN MUST BE AT LEAST 4 CHARACTERS"))
b.WriteString("\n")
}
b.WriteString("\n")
b.WriteString(dimStyle.Render(" PRESS ESC TO RETURN TO MAIN MENU"))
}
b.WriteString("\n")
return b.String()
}