Skip to content

Commit

Permalink
chore(tap): enhance view
Browse files Browse the repository at this point in the history
  • Loading branch information
Topvennie committed Dec 4, 2024
1 parent 99befcb commit 5f443fb
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 92 deletions.
2 changes: 1 addition & 1 deletion db/queries/tap.sql
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ FROM tap
GROUP BY category;

-- name: GetOrderCountByCategorySinceOrderID :many
SELECT category, COUNT(*)
SELECT category, COUNT(*), CAST(MAX(order_created_at) AS INTEGER) AS latest_order_created_at
FROM tap
WHERE order_id >= ?
GROUP BY category;
9 changes: 5 additions & 4 deletions internal/pkg/db/sqlc/tap.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions ui/view/tap/style.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package tap

import "github.com/charmbracelet/lipgloss"

var base = lipgloss.NewStyle()

// Width
var (
widthAmount = 5
widthCategory = 8
widthLast = 13
)

// Margin
var mStats = 2

// Barchart
var (
widthBar = 40
heightBar = 20
)

// Colors
var (
cMate = lipgloss.Color("#D27D2D")
cSoft = lipgloss.Color("#ADD8E6")
cBeer = lipgloss.Color("#F9B116")
cFood = lipgloss.Color("#00ff00")

cBorder = lipgloss.Color("#383838")
cStatsTitle = lipgloss.Color("#EE4B2B")
)

// Styles Chart
var (
sMate = base.Foreground(cMate)
sSoft = base.Foreground(cSoft)
sBeer = base.Foreground(cBeer)
sFood = base.Foreground(cFood)
sUnknown = base
)

// Styles stats
var (
sStats = base.Border(lipgloss.NormalBorder(), false, false, false, true).BorderForeground(cBorder).MarginLeft(mStats).PaddingLeft(mStats)
sStatsTitle = base.Foreground(cStatsTitle).Bold(true).Width(widthAmount+widthCategory+widthLast).Border(lipgloss.NormalBorder(), false, false, true, false).BorderForeground(cBorder)
sStatsAmount = base.Width(widthAmount).Bold(true)
sStatsCategory = base.Width(widthCategory)
sStatsLast = base.Width(widthLast).Align(lipgloss.Right).Italic(true).Faint(true)
)
159 changes: 72 additions & 87 deletions ui/view/tap/tap.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,37 @@ package tap
import (
"context"
"database/sql"
"slices"
"time"

"github.com/NimbleMarkets/ntcharts/barchart"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/zeusWPI/scc/internal/pkg/db"
"github.com/zeusWPI/scc/pkg/config"
"github.com/zeusWPI/scc/ui/view"
)

type category string

const (
mate category = "Mate"
soft category = "Soft"
beer category = "Beer"
food category = "Food"
)

var categoryToStyle = map[category]lipgloss.Style{
mate: sMate,
soft: sSoft,
beer: sBeer,
food: sFood,
}

// Model represents the tap model
type Model struct {
db *db.DB
lastOrderID int64
mate float64
soft float64
beer float64
food float64
items []tapItem
}

// Msg represents a tap message
Expand All @@ -30,15 +44,9 @@ type Msg struct {
}

type tapItem struct {
category string
amount float64
}

var tapCategoryColor = map[string]lipgloss.Color{
"Mate": lipgloss.Color("208"),
"Soft": lipgloss.Color("86"),
"Beer": lipgloss.Color("160"),
"Food": lipgloss.Color("40"),
category category
amount int
last time.Time
}

// NewModel creates a new tap model
Expand All @@ -51,25 +59,38 @@ func (m *Model) Init() tea.Cmd {
return nil
}

// Name returns the name of the view
func (m *Model) Name() string {
return "Tap"
}

// Update updates the tap model
func (m *Model) Update(msg tea.Msg) (view.View, tea.Cmd) {
switch msg := msg.(type) {
case Msg:
m.lastOrderID = msg.lastOrderID

for _, msg := range msg.items {
switch msg.category {
case "Mate":
m.mate += msg.amount
case "Soft":
m.soft += msg.amount
case "Beer":
m.beer += msg.amount
case "Food":
m.food += msg.amount
for _, msgItem := range msg.items {
found := false
for i, item := range m.items {
if item.category == msgItem.category {
m.items[i].amount += msgItem.amount
m.items[i].last = msgItem.last
found = true
break
}
}

if !found {
m.items = append(m.items, msgItem)
}
}

// Sort to display bars in order
slices.SortFunc(m.items, func(i, j tapItem) int {
return j.amount - i.amount
})

return m, nil
}

Expand All @@ -78,45 +99,15 @@ func (m *Model) Update(msg tea.Msg) (view.View, tea.Cmd) {

// View returns the tap view
func (m *Model) View() string {
chart := barchart.New(20, 20)

barMate := barchart.BarData{
Label: "Mate",
Values: []barchart.BarValue{{
Name: "Mate",
Value: m.mate,
Style: lipgloss.NewStyle().Foreground(tapCategoryColor["Mate"]),
}},
}
barSoft := barchart.BarData{
Label: "Soft",
Values: []barchart.BarValue{{
Name: "Soft",
Value: m.soft,
Style: lipgloss.NewStyle().Foreground(tapCategoryColor["Soft"]),
}},
}
barBeer := barchart.BarData{
Label: "Beer",
Values: []barchart.BarValue{{
Name: "Beer",
Value: m.beer,
Style: lipgloss.NewStyle().Foreground(tapCategoryColor["Beer"]),
}},
}
barFood := barchart.BarData{
Label: "Food",
Values: []barchart.BarValue{{
Name: "Food",
Value: m.food,
Style: lipgloss.NewStyle().Foreground(tapCategoryColor["Food"]),
}},
}
chart := m.viewChart()
stats := m.viewStats()

chart.PushAll([]barchart.BarData{barMate, barSoft, barBeer, barFood})
chart.Draw()
// Give them same height
stats = sStats.Height(lipgloss.Height(chart)).Render(stats)

return chart.View()
// Join them together
view := lipgloss.JoinHorizontal(lipgloss.Top, chart, stats)
return view
}

// GetUpdateDatas returns all the update functions for the tap model
Expand All @@ -140,45 +131,39 @@ func updateOrders(view view.View) (tea.Msg, error) {
if err == sql.ErrNoRows {
err = nil
}
return Msg{lastOrderID: lastOrderID, items: []tapItem{}}, err
return nil, err
}

if order.OrderID <= lastOrderID {
return Msg{lastOrderID: lastOrderID, items: []tapItem{}}, nil
return nil, nil
}

orders, err := m.db.Queries.GetOrderCountByCategorySinceOrderID(context.Background(), lastOrderID)
if err != nil {
return Msg{lastOrderID: lastOrderID, items: []tapItem{}}, err
return nil, err
}

mate, soft, beer, food := 0.0, 0.0, 0.0, 0.0
counts := make(map[category]tapItem)

for _, order := range orders {
switch order.Category {
case "Mate":
mate += float64(order.Count)
case "Soft":
soft += float64(order.Count)
case "Beer":
beer += float64(order.Count)
case "Food":
food += float64(order.Count)
if entry, ok := counts[category(order.Category)]; ok {
entry.amount += int(order.Count)
counts[category(order.Category)] = entry
continue
}
}

messages := make([]tapItem, 0, 4)
if mate > 0 {
messages = append(messages, tapItem{"Mate", mate})
}
if soft > 0 {
messages = append(messages, tapItem{"Soft", soft})
}
if beer > 0 {
messages = append(messages, tapItem{"Beer", beer})
counts[category(order.Category)] = tapItem{
category: category(order.Category),
amount: int(order.Count),
last: time.Unix(order.LatestOrderCreatedAt, 0),
}
}
if food > 0 {
messages = append(messages, tapItem{"Food", food})

items := make([]tapItem, 0, len(counts))

for _, v := range counts {
items = append(items, v)
}

return Msg{lastOrderID: order.OrderID, items: messages}, err
return Msg{lastOrderID: order.OrderID, items: items}, nil
}
55 changes: 55 additions & 0 deletions ui/view/tap/view.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package tap

import (
"strconv"

"github.com/NimbleMarkets/ntcharts/barchart"
"github.com/charmbracelet/lipgloss"
)

func (m *Model) viewChart() string {
chart := barchart.New(widthBar, heightBar)
bars := make([]barchart.BarData, 0, len(m.items))

for _, item := range m.items {
style, ok := categoryToStyle[item.category]
if !ok {
style = sUnknown
}

bars = append(bars, barchart.BarData{
Label: string(item.category),
Values: []barchart.BarValue{{
Name: string(item.category),
Value: float64(item.amount),
Style: style,
}},
})
}

chart.PushAll(bars)
chart.Draw()

return chart.View()
}

func (m *Model) viewStats() string {
rows := make([]string, 0, len(m.items))

for _, item := range m.items {
amount := sStatsAmount.Render(strconv.Itoa(item.amount))
category := sStatsCategory.Inherit(categoryToStyle[item.category]).Render(string(item.category))
last := sStatsLast.Render(item.last.Format("02/01 15:04"))

text := lipgloss.JoinHorizontal(lipgloss.Top, amount, category, last)
rows = append(rows, text)
}

view := lipgloss.JoinVertical(lipgloss.Left, rows...)

// Add title
title := sStatsTitle.Render("Leaderboard")
view = lipgloss.JoinVertical(lipgloss.Left, title, view)

return view
}

0 comments on commit 5f443fb

Please sign in to comment.