feat(server+cli): configurable menu via --menu JSON; UI tweaks to form layout
This commit is contained in:
parent
c93b38e8ec
commit
e998fbd230
26
main.go
26
main.go
@ -12,7 +12,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/charmbracelet/bubbles/key"
|
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/huh"
|
"github.com/charmbracelet/huh"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
@ -427,7 +426,7 @@ func (m model) View() string {
|
|||||||
|
|
||||||
var leftCol string
|
var leftCol string
|
||||||
if m.form != nil {
|
if m.form != nil {
|
||||||
formView := m.form.View()
|
formView := m.form.WithHeight(m.height - 10).View()
|
||||||
leftCol = lipgloss.NewStyle().
|
leftCol = lipgloss.NewStyle().
|
||||||
Width(m.width/2 - 2).
|
Width(m.width/2 - 2).
|
||||||
Height(m.height - 6).
|
Height(m.height - 6).
|
||||||
@ -465,12 +464,6 @@ func (m *model) buildForm() *huh.Form {
|
|||||||
m.formFields.quantityStr = ""
|
m.formFields.quantityStr = ""
|
||||||
m.formFields.confirm = false
|
m.formFields.confirm = false
|
||||||
|
|
||||||
keymap := huh.NewDefaultKeyMap()
|
|
||||||
keymap.Quit = key.NewBinding(
|
|
||||||
key.WithKeys("ctrl+c", "esc"),
|
|
||||||
key.WithHelp("ctrl+c/esc", "quit"),
|
|
||||||
)
|
|
||||||
|
|
||||||
f := huh.NewForm(
|
f := huh.NewForm(
|
||||||
huh.NewGroup(
|
huh.NewGroup(
|
||||||
huh.NewInput().
|
huh.NewInput().
|
||||||
@ -494,6 +487,8 @@ func (m *model) buildForm() *huh.Form {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}),
|
}),
|
||||||
|
),
|
||||||
|
huh.NewGroup(
|
||||||
huh.NewInput().
|
huh.NewInput().
|
||||||
Title("Quantity").
|
Title("Quantity").
|
||||||
Prompt("> ").
|
Prompt("> ").
|
||||||
@ -512,7 +507,7 @@ func (m *model) buildForm() *huh.Form {
|
|||||||
Negative("No").
|
Negative("No").
|
||||||
Value(&m.formFields.confirm),
|
Value(&m.formFields.confirm),
|
||||||
),
|
),
|
||||||
).WithTheme(huh.ThemeBase()).WithKeyMap(keymap)
|
).WithTheme(huh.ThemeBase())
|
||||||
|
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
@ -652,20 +647,27 @@ func main() {
|
|||||||
var (
|
var (
|
||||||
host string
|
host string
|
||||||
serverOnly bool
|
serverOnly bool
|
||||||
|
menuJSON string
|
||||||
)
|
)
|
||||||
flag.StringVar(&host, "host", "localhost:9000", "host:port to connect to or bind the server on")
|
flag.StringVar(&host, "host", "localhost:9000", "host:port to connect to or bind the server on")
|
||||||
flag.BoolVar(&serverOnly, "server", false, "run only the server")
|
flag.BoolVar(&serverOnly, "server", false, "run only the server")
|
||||||
|
flag.StringVar(&menuJSON, "menu", "", "JSON array of menu items (server mode only), e.g. '[{\"id\":\"tea\",\"name\":\"Green Tea\",\"price\":2.5}]'")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// If requested, start the TCP server (chat server as-is).
|
|
||||||
if serverOnly {
|
if serverOnly {
|
||||||
if err := startTCPServer(host); err != nil {
|
var menu []menuItem
|
||||||
|
if menuJSON != "" {
|
||||||
|
if err := json.Unmarshal([]byte(menuJSON), &menu); err != nil {
|
||||||
|
fmt.Printf("Invalid menu JSON: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := startTCPServer(host, menu); err != nil {
|
||||||
fmt.Println("Server error:", err)
|
fmt.Println("Server error:", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client TUI
|
|
||||||
m := initialModel(host)
|
m := initialModel(host)
|
||||||
p := tea.NewProgram(m, tea.WithAltScreen())
|
p := tea.NewProgram(m, tea.WithAltScreen())
|
||||||
if _, err := p.Run(); err != nil {
|
if _, err := p.Run(); err != nil {
|
||||||
|
|||||||
18
server.go
18
server.go
@ -19,6 +19,8 @@ var defaultMenu = []menuItem{
|
|||||||
{ID: "esp", Name: "Espresso", Price: 3.00},
|
{ID: "esp", Name: "Espresso", Price: 3.00},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var serverMenu []menuItem
|
||||||
|
|
||||||
// order is the structure the server expects for ORDER.
|
// order is the structure the server expects for ORDER.
|
||||||
type order struct {
|
type order struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@ -147,7 +149,7 @@ func handleConn(h *Hub, c net.Conn) {
|
|||||||
// New protocol commands:
|
// New protocol commands:
|
||||||
// MENU -> server returns single-line JSON array of menuItem
|
// MENU -> server returns single-line JSON array of menuItem
|
||||||
if strings.EqualFold(line, "MENU") {
|
if strings.EqualFold(line, "MENU") {
|
||||||
b, err := json.Marshal(defaultMenu)
|
b, err := json.Marshal(serverMenu)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(c, `[error] failed to encode menu`)
|
fmt.Fprintln(c, `[error] failed to encode menu`)
|
||||||
continue
|
continue
|
||||||
@ -191,9 +193,9 @@ func handleConn(h *Hub, c net.Conn) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var chosen *menuItem
|
var chosen *menuItem
|
||||||
for i := range defaultMenu {
|
for i := range serverMenu {
|
||||||
if defaultMenu[i].ID == ord.ItemID {
|
if serverMenu[i].ID == ord.ItemID {
|
||||||
chosen = &defaultMenu[i]
|
chosen = &serverMenu[i]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,12 +250,18 @@ func handleConn(h *Hub, c net.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// startTCPServer starts a TCP chat server and never returns unless an error occurs.
|
// startTCPServer starts a TCP chat server and never returns unless an error occurs.
|
||||||
func startTCPServer(addr string) error {
|
func startTCPServer(addr string, menu []menuItem) error {
|
||||||
|
if len(menu) == 0 {
|
||||||
|
menu = defaultMenu
|
||||||
|
}
|
||||||
|
serverMenu = menu
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", addr)
|
ln, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Printf("TCP chat server listening on %s", ln.Addr())
|
log.Printf("TCP chat server listening on %s", ln.Addr())
|
||||||
|
log.Printf("Menu items: %d", len(serverMenu))
|
||||||
|
|
||||||
hub := NewHub()
|
hub := NewHub()
|
||||||
go hub.Run()
|
go hub.Run()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user