david-clifford's picture
UI Bug
f6875cc verified
from fasthtml.common import *
# using https://www.fastht.ml/docs/tutorials/by_example.html
app,rt = fast_app(pico=True)
## From HF
## Initial set of scores information
scores = {
# Team A
'A_goals': 0, # goals
'A_points': 0, # points
# Team B
'B_goals': 0, # goals
'B_points': 0, # points
}
# Track scores time series in memory
scores_ts = {}
scores_id = len(scores_ts)+1
scores_ts[scores_id] = {"scores": scores.copy()}
# Default team names
team_A = "Bishopstown"
team_B = "Other Team"
def create_score_button(team_code, score_type):
# Determine the unique ID for the button's target span
span_id = f"{team_code}_{score_type}"
# Determine the key to pass to the increment function
counter_name = f"{team_code}_{score_type}"
return Button(
Span(f"{scores[counter_name]}", id=span_id),
hx_post="/increment",
hx_target=f"#{span_id}",
hx_vals=f'{{"counter": "{counter_name}"}}',
hx_swap="innerHTML"
)
def create_score_section(team_code):
return (
H1(create_score_button(f"{team_code}", "goals"),
Span(" "),
create_score_button(f"{team_code}", "points"),
cls="card-title"),
)
verbose = False
@app.post("/increment")
def increment(counter: str):
if verbose: print("incrementing")
global scores
if counter in scores:
scores[counter] += 1
## Add new score to time series
global scores_ts
scores_id = len(scores_ts)
scores_ts[scores_id+1] = {"scores": scores.copy()}
## Return the text that is expected for the button update
return f"{scores[counter]}"
@app.post("/reset")
def reset_scores_and_page():
if verbose: print("reseting")
global scores
scores = {
# Team A
'A_goals': 0, # goals
'A_points': 0, # points
# Team B
'B_goals': 0, # goals
'B_points': 0, # points
}
global scores_ts
scores_ts = {}
scores_id = len(scores_ts)+1
scores_ts[scores_id] = {"scores": scores.copy()}
# Return a response to reload the table
return set_table(team_A, team_B)
@app.post("/reset_recent")
def reset_to_last_score_and_page():
if verbose: print("reseting to recent")
global scores
global scores_ts
## previous index
scores_id = len(scores_ts)
if scores_id > 1:
scores = scores_ts[scores_id-1]["scores"]
## Drop the latest entry in the score time series
#scores_ts[scores_id+1] = {"scores": scores.copy()}
scores_ts.pop(scores_id)
# Return a response to reload the score table
return set_table(team_A, team_B)
@rt
def index():
return Titled('GAA Score Keeper',
Div(
P('Enter the team names'),
Form(Input(name='team_name_A', value=team_A),
Input(name='team_name_B', value=team_B),
Button('Click'),
hx_post='/set_table', hx_target='#main'),
id='main'))
@rt
def set_table(team_name_A:str, team_name_B:str):
global team_A
global team_B
team_A = team_name_A ## Update global
team_B = team_name_B ## Update global
print("set_table called"+team_A+team_B)
return Main(
Div(
Table(
Tr(
Th(H2(team_A)),
Th(H2(team_B))
),
Tr(
Td(create_score_section(team_code = "A"),style="text-align: center;"),
Td(create_score_section(team_code = "B"),style="text-align: center;")
)
),
Br(),
Br(),
Div(
id="timer_display", hx_get="/timer",
hx_trigger="every 1s",
style="text-align: center; margin-top: 20px; cursor: pointer;"
),
style="flex-grow: 1;"
),
Div(
Button( Span("Undo"), hx_post="/reset_recent", hx_target='#main' ),
Button( Span("Toggle Clock"), hx_post="/timer_toggle", hx_target='#timer_display' ),
Button( Span("Full Reset"), hx_post="/reset", hx_target='#main' ),
style = "display: flex; justify-content: space-between;"
),
style="display: flex; flex-direction: column; min-height: 80vh;"
)
# Timer state
timer_state = {
'start_time': None,
'is_running': False
}
@app.get("/timer")
def get_timer():
import time
if timer_state['is_running'] and timer_state['start_time']:
elapsed = time.time() - timer_state['start_time']
minutes = int(elapsed // 60)
seconds = int(elapsed % 60)
color = "red" if minutes >= 30 else "green"
return Span(f"{minutes:02d}:{seconds:02d}", style=f"color: {color}; font-size: 2em;")
return Span("00:00", style="color: green; font-size: 2em;")
@app.post("/timer_toggle")
def toggle_timer():
import time
if timer_state['is_running']:
timer_state['is_running'] = False
else:
timer_state['start_time'] = time.time()
timer_state['is_running'] = True
return get_timer()
serve(port=7860)