skyrama-clone/backend/server/homepage.go

205 lines
5.5 KiB
Go
Raw Permalink Normal View History

2026-05-24 12:37:14 +03:00
package main
2026-05-25 20:07:14 +03:00
import (
"fmt"
"os"
"strings"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
// ============================================================================
// STYLING DEFINITIONS (Lipgloss)
// ============================================================================
var (
// Colors
skyBlue = lipgloss.Color("117")
neonPink = lipgloss.Color("205")
moneyGreen = lipgloss.Color("85")
gray = lipgloss.Color("240")
// Component Styles
titleStyle = lipgloss.NewStyle().
Foreground(skyBlue).
Bold(true).
MarginTop(1).
MarginBottom(1)
headerBoxStyle = lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(skyBlue).
Padding(0, 2).
MarginBottom(1)
listStyle = lipgloss.NewStyle().MarginLeft(2)
itemStyle = lipgloss.NewStyle().
PaddingLeft(2).
Foreground(lipgloss.Color("252"))
selectedItemStyle = lipgloss.NewStyle().
PaddingLeft(2).
Foreground(neonPink).
Bold(true).
Background(lipgloss.Color("236")) // Slight background highlight
footerStyle = lipgloss.NewStyle().
Foreground(gray).
MarginTop(2)
)
// ============================================================================
// 1. THE MODEL
// ============================================================================
type homepageModel struct {
cursor int
choices []string
selected string
// Mock Player Data (In a real app, pass this in via initialModel)
playerName string
cash int
fleetCount int
}
func initialHomepageModel() homepageModel {
return homepageModel{
// Our interactive menu options
choices: []string{
"🗄️ Manage Hangar Fleet",
"🏢 View Airport Infrastructure",
"🏁 Active Runways & Service Loop",
"🚪 Logout / Quit",
},
playerName: "CaptainGo",
cash: 14500,
fleetCount: 12,
}
}
// ============================================================================
// 2. THE INIT FUNCTION
// ============================================================================
func (m homepageModel) Init() tea.Cmd {
return nil // No background tasks to start immediately
}
// ============================================================================
// 3. THE UPDATE FUNCTION (Handles inputs)
// ============================================================================
func (m homepageModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
// Handle keyboard events
case tea.KeyMsg:
switch msg.String() {
// Quit commands
case "ctrl+c", "q", "esc":
m.selected = "quit"
return m, tea.Quit
// Move up the menu
case "up", "k":
if m.cursor > 0 {
m.cursor--
} else {
m.cursor = len(m.choices) - 1 // Wrap around to bottom
}
// Move down the menu
case "down", "j":
if m.cursor < len(m.choices)-1 {
m.cursor++
} else {
m.cursor = 0 // Wrap around to top
}
// Select an option
case "enter", " ":
m.selected = m.choices[m.cursor]
return m, tea.Quit
}
}
return m, nil
}
// ============================================================================
// 4. THE VIEW FUNCTION (Renders the UI)
// ============================================================================
func (m homepageModel) View() string {
var b strings.Builder
// --- 1. TITLE ---
b.WriteString(titleStyle.Render("✈️ SKYRAMA COMMAND CENTER"))
b.WriteString("\n")
// --- 2. HEADER BAR (Player Stats) ---
statsLine := fmt.Sprintf("[ 🔑 Player: %s ] [ 💰 Cash: %s ] [ 🛩️ Fleet: %d ]",
lipgloss.NewStyle().Foreground(lipgloss.Color("252")).Bold(true).Render(m.playerName),
lipgloss.NewStyle().Foreground(moneyGreen).Render(fmt.Sprintf("%d €", m.cash)),
m.fleetCount,
)
b.WriteString(headerBoxStyle.Render(statsLine))
b.WriteString("\n\n")
// --- 3. INTERACTIVE MENU ---
b.WriteString(" Main Operations Menu:\n\n")
for i, choice := range m.choices {
// Is the cursor pointing at this choice?
cursorStr := " " // no cursor
if m.cursor == i {
cursorStr = lipgloss.NewStyle().Foreground(neonPink).Render(">")
b.WriteString(fmt.Sprintf("%s %s\n", cursorStr, selectedItemStyle.Render(choice)))
} else {
b.WriteString(fmt.Sprintf("%s %s\n", cursorStr, itemStyle.Render(choice)))
}
}
// --- 4. FOOTER ---
b.WriteString(footerStyle.Render("\n ↑/↓: Navigate • Enter: Select • q/esc: Quit"))
// Return the final drawn screen with a little left margin padding
return lipgloss.NewStyle().MarginLeft(2).Render(b.String()) + "\n"
}
// ============================================================================
// THE WRAPPER FUNCTION
// ============================================================================
// RunHomepageScreen starts the TUI and returns the menu string the user selected.
func RunHomepageScreen() string {
p := tea.NewProgram(initialHomepageModel(), tea.WithAltScreen()) // AltScreen creates a full-screen view
finalModel, err := p.Run()
if err != nil {
fmt.Printf("Error running dashboard: %v", err)
os.Exit(1)
}
if m, ok := finalModel.(homepageModel); ok {
return m.selected
}
return "quit"
}
/*
// Optional Main function to test it directly
func main() {
selection := RunHomepageScreen()
// Clear the screen on exit to print standard output
fmt.Print("\033[H\033[2J")
if selection == "quit" || selection == "🚪 Logout / Quit" {
fmt.Println("Gracefully disconnected from SkyRama servers. Goodbye!")
os.Exit(0)
}
fmt.Printf("You selected: %s\n", selection)
fmt.Println("Here is where you would load the next Bubble Tea model for that screen!")
}
*/