package banking import ( "fmt" "strings" tea "github.com/charmbracelet/bubbletea" ) const ( transferStepRouting = iota transferStepDest transferStepBeneficiary transferStepBankName transferStepAmount transferStepMemo transferStepConfirm transferStepAuthCode transferStepComplete ) var transferPrompts = []string{ " ROUTING NUMBER (ABA): ", " DESTINATION ACCOUNT: ", " BENEFICIARY NAME: ", " RECEIVING BANK NAME: ", " AMOUNT (USD): ", " MEMO / REFERENCE: ", "", " AUTHORIZATION CODE: ", } type transferModel struct { step int fields [8]string // indexed by step transfer WireTransfer confirm string // y/n input for confirm step } func newTransferModel() transferModel { return transferModel{} } func (m transferModel) Update(msg tea.Msg) (transferModel, tea.Cmd) { keyMsg, ok := msg.(tea.KeyMsg) if !ok { return m, nil } if m.step == transferStepComplete { return m, nil } if m.step == transferStepConfirm { switch keyMsg.Type { case tea.KeyEnter: switch strings.ToUpper(m.confirm) { case "Y", "YES": m.step = transferStepAuthCode case "N", "NO": m.confirm = "cancelled" } return m, nil case tea.KeyBackspace: if len(m.confirm) > 0 { m.confirm = m.confirm[:len(m.confirm)-1] } default: ch := keyMsg.String() if len(ch) == 1 && ch[0] >= 32 && ch[0] < 127 && len(m.confirm) < 3 { m.confirm += ch } } return m, nil } switch keyMsg.Type { case tea.KeyEnter: val := strings.TrimSpace(m.fields[m.step]) if val == "" { return m, nil } if m.step == transferStepAuthCode { m.transfer.AuthCode = val m.step = transferStepComplete return m, nil } switch m.step { case transferStepRouting: m.transfer.RoutingNumber = val case transferStepDest: m.transfer.DestAccount = val case transferStepBeneficiary: m.transfer.Beneficiary = val case transferStepBankName: m.transfer.BankName = val case transferStepAmount: m.transfer.Amount = val case transferStepMemo: m.transfer.Memo = val } m.step++ return m, nil case tea.KeyBackspace: if len(m.fields[m.step]) > 0 { m.fields[m.step] = m.fields[m.step][:len(m.fields[m.step])-1] } default: ch := keyMsg.String() if len(ch) == 1 && ch[0] >= 32 && ch[0] < 127 && len(m.fields[m.step]) < 40 { m.fields[m.step] += ch } } return m, nil } func (m transferModel) View() string { var b strings.Builder b.WriteString("\n") b.WriteString(centerText("WIRE TRANSFER")) b.WriteString("\n\n") b.WriteString(thinDivider()) b.WriteString("\n\n") // Show completed fields. for i := 0; i < m.step && i < len(transferPrompts); i++ { if i == transferStepConfirm { continue } prompt := transferPrompts[i] if prompt == "" { continue } b.WriteString(baseStyle.Render(prompt)) b.WriteString(baseStyle.Render(m.fields[i])) b.WriteString("\n") } // Current field. switch { case m.step == transferStepConfirm: b.WriteString("\n") b.WriteString(titleStyle.Render(" === TRANSFER SUMMARY ===")) b.WriteString("\n\n") b.WriteString(baseStyle.Render(fmt.Sprintf(" ROUTING: %s", m.transfer.RoutingNumber))) b.WriteString("\n") b.WriteString(baseStyle.Render(fmt.Sprintf(" ACCOUNT: %s", m.transfer.DestAccount))) b.WriteString("\n") b.WriteString(baseStyle.Render(fmt.Sprintf(" BENEFICIARY: %s", m.transfer.Beneficiary))) b.WriteString("\n") b.WriteString(baseStyle.Render(fmt.Sprintf(" BANK: %s", m.transfer.BankName))) b.WriteString("\n") b.WriteString(baseStyle.Render(fmt.Sprintf(" AMOUNT: $%s", m.transfer.Amount))) b.WriteString("\n") b.WriteString(baseStyle.Render(fmt.Sprintf(" MEMO: %s", m.transfer.Memo))) b.WriteString("\n\n") b.WriteString(titleStyle.Render(" CONFIRM TRANSFER? (Y/N): ")) b.WriteString(inputStyle.Render(m.confirm)) b.WriteString(inputStyle.Render("_")) b.WriteString("\n") case m.step == transferStepComplete: b.WriteString("\n") b.WriteString(thinDivider()) b.WriteString("\n\n") b.WriteString(titleStyle.Render(" TRANSFER QUEUED FOR PROCESSING")) b.WriteString("\n\n") b.WriteString(baseStyle.Render(fmt.Sprintf(" CONFIRMATION #: WR-%s-%s", m.transfer.RoutingNumber[:4], "847291"))) b.WriteString("\n") b.WriteString(baseStyle.Render(" STATUS: PENDING FEDWIRE SETTLEMENT")) b.WriteString("\n") b.WriteString(baseStyle.Render(" ESTIMATED COMPLETION: NEXT BUSINESS DAY")) b.WriteString("\n\n") b.WriteString(dimStyle.Render(" PRESS ANY KEY TO RETURN TO MAIN MENU")) b.WriteString("\n") case m.step < len(transferPrompts): prompt := transferPrompts[m.step] b.WriteString(titleStyle.Render(prompt)) b.WriteString(inputStyle.Render(m.fields[m.step])) b.WriteString(inputStyle.Render("_")) b.WriteString("\n") } if m.step < transferStepConfirm { b.WriteString("\n") b.WriteString(thinDivider()) b.WriteString("\n\n") b.WriteString(dimStyle.Render(fmt.Sprintf(" STEP %d OF 6", m.step+1))) b.WriteString("\n") } return b.String() }