Skip to content

Commit

Permalink
info dump on enter (connections) (#13)
Browse files Browse the repository at this point in the history
* update (#10)

* removed overlap in different models

* implemented showing message after closing table with selection

* added quit option "escape"

quits table with any additional info

* updated to more correct color name lol

* show detailed information for a departure

* fixed import path

* Update README.md

added installation options

* Dev (#8)

* fixed import path

* added autobuild

* Update README.md (#9)

added installation options

* created const

* cleanup and refactor

* corrected if-else block

* refactor of project structure

* rename

* added delay to timetable

* cleanup dependencies

* refactor name

* mega refactor

* abstracted spinner

* print detailed info on enter connections
  • Loading branch information
Kaya-Sem authored Aug 17, 2024
1 parent df8b809 commit 3f2c3ea
Show file tree
Hide file tree
Showing 12 changed files with 302 additions and 211 deletions.
2 changes: 1 addition & 1 deletion cmd/api/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ type ConnectionDeparture struct {
Vehicle string `json:"vehicle"`
Platform string `json:"platform"`
//Stops []Stop `json:"stops"`
//VehicleInfo VehicleInfo `json:"vehicleinfo"`
VehicleInfo VehicleInfo `json:"vehicleinfo"`
// StationInfo StationInfo `json:"stationinfo"`
//PlatformInfo PlatformInfo `json:"platforminfo"`
}
Expand Down
14 changes: 12 additions & 2 deletions cmd/api/irail-api.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ func GetSNCBStationTimeTable(stationName string, time string, arrdep string) ([]
if err != nil {
return nil, err
}
defer resp.Body.Close()
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
fmt.Println(fmt.Errorf("couldn't close response body: %v", err))
}
}(resp.Body)

body, err := io.ReadAll(resp.Body)
if err != nil {
Expand Down Expand Up @@ -54,7 +59,12 @@ func GetSNCBStationsJSON() []byte {
fmt.Println("Error making request:", err)
return nil
}
defer resp.Body.Close()
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
fmt.Println("Error closing response body:", err)
}
}(resp.Body)

// Read the response body
body, err := io.ReadAll(resp.Body)
Expand Down
File renamed without changes.
35 changes: 35 additions & 0 deletions cmd/spinner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package cmd

import (
"time"

"github.com/briandowns/spinner"
)

type Spinner struct {
spinner *spinner.Spinner
prefix string
suffix string
sleep time.Duration
}

func NewSpinner(prefix, suffix string, sleep time.Duration) *Spinner {
s := spinner.New(spinner.CharSets[14], 100*time.Millisecond)
s.Prefix = prefix
s.Suffix = suffix
return &Spinner{
spinner: s,
prefix: prefix,
suffix: suffix,
sleep: sleep,
}
}

func (s *Spinner) Start() {
s.spinner.Start()
time.Sleep(s.sleep)
}

func (s *Spinner) Stop() {
s.spinner.Stop()
}
119 changes: 0 additions & 119 deletions cmd/table.go

This file was deleted.

123 changes: 123 additions & 0 deletions cmd/tables/connectionTable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package table

import (
"fmt"
"github.com/Kaya-Sem/commandtrein/cmd"
"github.com/Kaya-Sem/commandtrein/cmd/api"
"os"

"github.com/charmbracelet/bubbles/table"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)

type connectionTableModel struct {
table table.Model
relativeTime string
showMessage bool
message string
departures []api.Connection
}

func (m connectionTableModel) Init() tea.Cmd { return nil }

func getDetailedConnectionInfo(c api.Connection) string {
return fmt.Sprintf(`
Detailed info:
Destination: %s
Track: %s
Departure Time: %s
Vehicle: %s
`,
c.Departure.Station,
c.Departure.Platform,
cmd.UnixToHHMM(c.Departure.Time),
c.Departure.Vehicle,
)
}

func (m connectionTableModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var teaCmd tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "q", "ctrl+c", "esc":
return m, tea.Quit
case "enter":
selectedRow := m.table.SelectedRow()
if selectedRow != nil {
selectedIndex := m.table.Cursor()
selectedDeparture := m.departures[selectedIndex]
m.showMessage = true
m.message = getDetailedConnectionInfo(selectedDeparture)
}
return m, tea.Quit
}
}

m.table, teaCmd = m.table.Update(msg)

// Calculate the relative time for the currently selected row
selectedRow := m.table.SelectedRow()
if selectedRow != nil {
departureTime := selectedRow[0]
relativeTime := CalculateHumanRelativeTime(departureTime)
m.relativeTime = relativeTime
} else {
m.relativeTime = ""
}

return m, teaCmd
}

func (m connectionTableModel) View() string {
if m.showMessage {
// Show the message instead of the tables if the flag is set
return m.message
}

// Add the relative time to the view only if there is a selected row
if m.relativeTime != "" {
return m.table.View() + "\n\n" + "Departure in: " + m.relativeTime + "\n"
}
return m.table.View() + "\n"
}

func RenderConnectionTable(
columnItems []table.Column,
rowItems []table.Row,
connections []api.Connection,
) {
fmt.Println()

columns := columnItems
rows := rowItems

t := table.New(
table.WithColumns(columns),
table.WithRows(rows),
table.WithFocused(true),
table.WithHeight(tableHeight),
)

s := table.DefaultStyles()
s.Header = s.Header.
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color(BorderColor)).
BorderBottom(true).
Bold(false)
s.Selected = s.Selected.
Foreground(lipgloss.Color(SelectedForeground)).
Background(lipgloss.Color(SelectedBackground))
t.SetStyles(s)

m := connectionTableModel{
table: t,
departures: connections, // Store the departures
}

if _, err := tea.NewProgram(m).Run(); err != nil {
fmt.Println("Error running program:", err)
os.Exit(1)
}
}
55 changes: 55 additions & 0 deletions cmd/tables/tableUtil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package table

import (
"fmt"
"time"
)

const (
BorderColor = "240" // gray
SelectedForeground = "229" // not setting it to yellow will make the text yellow (yellow on purple = white?)
SelectedBackground = "57" // purple
tableHeight = 6
)

// CalculateHumanRelativeTime used for calucating human-readable "from now" time. E.g 'in 20 minutes'
func CalculateHumanRelativeTime(departureTime string) string {
now := time.Now()

depTime, err := time.Parse("15:04", departureTime)
if err != nil {
return ""
}

// Combine the parsed time with today's date
depDateTime := time.Date(now.Year(), now.Month(), now.Day(), depTime.Hour(), depTime.Minute(), 0, 0, now.Location())

// If the departure time is earlier than now, assume it's for the next day
if depDateTime.Before(now) {
depDateTime = depDateTime.Add(24 * time.Hour)
}

// Calculate the duration between now and the departure time
duration := depDateTime.Sub(now)

// Handle special cases
if duration < 1*time.Minute {
return "now"
} else if duration < 60*time.Minute {
return fmt.Sprintf("%d min", int(duration.Minutes()))
} else if duration < 120*time.Minute {
minutes := int(duration.Minutes()) % 60
if minutes == 0 {
return "1 hour"
}
return fmt.Sprintf("1 hour %d min", minutes)
}

hours := int(duration.Hours())
minutes := int(duration.Minutes()) % 60
if minutes == 0 {
return fmt.Sprintf("%d hours", hours)
}

return fmt.Sprintf("%d hours %d min", hours, minutes)
}
Loading

0 comments on commit 3f2c3ea

Please sign in to comment.