feat: added a splash page
This commit is contained in:
@@ -31,5 +31,4 @@ var AccountMenuItems = []string{
|
|||||||
"order history",
|
"order history",
|
||||||
"faq",
|
"faq",
|
||||||
"about",
|
"about",
|
||||||
"something",
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ const (
|
|||||||
paymentPage
|
paymentPage
|
||||||
confirmPage
|
confirmPage
|
||||||
accountPage
|
accountPage
|
||||||
|
splashPage
|
||||||
)
|
)
|
||||||
|
|
||||||
// This msg is sent after a debounce delay to apply a pending resize.
|
// This msg is sent after a debounce delay to apply a pending resize.
|
||||||
@@ -117,6 +118,11 @@ type Model struct {
|
|||||||
FAQs []FAQ // loaded from embedded faq.json
|
FAQs []FAQ // loaded from embedded faq.json
|
||||||
FaqFocused bool // true when FAQ detail is focused
|
FaqFocused bool // true when FAQ detail is focused
|
||||||
|
|
||||||
|
// Splash screen
|
||||||
|
splashDataReady bool // true when products have loaded
|
||||||
|
splashDelayDone bool // true when minimum display time has elapsed
|
||||||
|
splashCursor bool // toggles for blinking cursor animation
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SwitchPage changed the active page and marks that a switch happened
|
// SwitchPage changed the active page and marks that a switch happened
|
||||||
@@ -217,7 +223,16 @@ func (m Model) fetchProductsCmd() tea.Msg {
|
|||||||
|
|
||||||
func (m Model) Init() tea.Cmd {
|
func (m Model) Init() tea.Cmd {
|
||||||
// Fetch products and cart from API on startup, and schedule token refresh
|
// Fetch products and cart from API on startup, and schedule token refresh
|
||||||
cmds := []tea.Cmd{m.fetchProductsCmd, m.fetchCartCmd}
|
cmds := []tea.Cmd {
|
||||||
|
m.fetchProductsCmd,
|
||||||
|
m.fetchCartCmd,
|
||||||
|
tea.Tick(1500*time.Millisecond, func(t time.Time) tea.Msg {
|
||||||
|
return DelayCompleteMsg{}
|
||||||
|
}),
|
||||||
|
tea.Tick(700*time.Microsecond, func(t time.Time) tea.Msg {
|
||||||
|
return splashCursorTickMsg{}
|
||||||
|
}),
|
||||||
|
}
|
||||||
if m.User != nil && m.AuthFingerprintKey != "" {
|
if m.User != nil && m.AuthFingerprintKey != "" {
|
||||||
cmds = append(cmds, m.scheduleTokenRefreshCmd())
|
cmds = append(cmds, m.scheduleTokenRefreshCmd())
|
||||||
}
|
}
|
||||||
@@ -233,7 +248,6 @@ func (m Model) resetPageState() Model {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type StripeTokenMsg struct {
|
type StripeTokenMsg struct {
|
||||||
TokenID string
|
TokenID string
|
||||||
Last4 string
|
Last4 string
|
||||||
@@ -642,6 +656,7 @@ func (m Model) GetCartItemsSlice() []*models.CartItem {
|
|||||||
func NewModel(username string) Model {
|
func NewModel(username string) Model {
|
||||||
m := Model{
|
m := Model{
|
||||||
Username: username,
|
Username: username,
|
||||||
|
currentPage: splashPage,
|
||||||
Coffees: []models.Coffee{
|
Coffees: []models.Coffee{
|
||||||
{
|
{
|
||||||
Name: "Espresso",
|
Name: "Espresso",
|
||||||
|
|||||||
34
pkg/tui/splash.go
Normal file
34
pkg/tui/splash.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package tui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DelayCompleteMsg struct{}
|
||||||
|
type splashCursorTickMsg struct{}
|
||||||
|
|
||||||
|
func (m Model) SplashView() string {
|
||||||
|
accent := lipgloss.NewStyle().Foreground(lipgloss.Color("#AAAAAA")).Bold(true)
|
||||||
|
|
||||||
|
var cursor string
|
||||||
|
if m.splashCursor {
|
||||||
|
cursor = lipgloss.NewStyle().Background(lipgloss.Color("#4682B4")).Render(" ")
|
||||||
|
} else {
|
||||||
|
cursor = " "
|
||||||
|
}
|
||||||
|
|
||||||
|
logo := accent.Render("terminal coffe") + cursor
|
||||||
|
|
||||||
|
content := lipgloss.JoinVertical(
|
||||||
|
lipgloss.Center,
|
||||||
|
logo,
|
||||||
|
)
|
||||||
|
|
||||||
|
return lipgloss.Place(
|
||||||
|
m.viewportWidth,
|
||||||
|
m.viewportHeight,
|
||||||
|
lipgloss.Center,
|
||||||
|
lipgloss.Center,
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -47,6 +47,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.Coffees = msg.Products
|
m.Coffees = msg.Products
|
||||||
m.ErrorMsg = ""
|
m.ErrorMsg = ""
|
||||||
}
|
}
|
||||||
|
m.splashDataReady = true
|
||||||
|
if m.currentPage == splashPage && m.splashDelayDone {
|
||||||
|
return m.SwitchPage(shopPage), nil
|
||||||
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
case CartFetchedMsg:
|
case CartFetchedMsg:
|
||||||
if msg.Err == nil && msg.Cart != nil {
|
if msg.Err == nil && msg.Cart != nil {
|
||||||
@@ -88,6 +92,17 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.ErrorMsg = fmt.Sprintf("failed to delete card: %v", msg.Err)
|
m.ErrorMsg = fmt.Sprintf("failed to delete card: %v", msg.Err)
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
|
case DelayCompleteMsg:
|
||||||
|
m.splashDelayDone = true
|
||||||
|
if m.currentPage == splashPage && m.splashDataReady {
|
||||||
|
return m.SwitchPage(shopPage), nil
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
case splashCursorTickMsg:
|
||||||
|
m.splashCursor = !m.splashCursor
|
||||||
|
return m, tea.Tick(700*time.Millisecond, func(t time.Time) tea.Msg {
|
||||||
|
return splashCursorTickMsg{}
|
||||||
|
})
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
// If a form is active, skip global keys — let the page handler own input
|
// If a form is active, skip global keys — let the page handler own input
|
||||||
if m.ShippingForm != nil || m.PaymentForm != nil {
|
if m.ShippingForm != nil || m.PaymentForm != nil {
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ func (m Model) View() string {
|
|||||||
return m.ResizeView()
|
return m.ResizeView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.currentPage == splashPage {
|
||||||
|
return m.SplashView()
|
||||||
|
}
|
||||||
|
|
||||||
// If the menu modal is showing, render it full-screen (bypass container)
|
// If the menu modal is showing, render it full-screen (bypass container)
|
||||||
if m.ShowingMenu {
|
if m.ShowingMenu {
|
||||||
return m.BuildMenuView()
|
return m.BuildMenuView()
|
||||||
|
|||||||
Reference in New Issue
Block a user