HansTran commited on
Commit
57e2194
·
verified ·
1 Parent(s): 91258bf

Upload 21 files

Browse files
__pycache__/app.cpython-312.pyc CHANGED
Binary files a/__pycache__/app.cpython-312.pyc and b/__pycache__/app.cpython-312.pyc differ
 
app.py CHANGED
@@ -1,6 +1,6 @@
1
  import streamlit as st
2
- from datetime import datetime
3
 
 
4
  from components.buttons import render_top_buttons
5
  from components.card import render_card
6
  from components.header import render_header
@@ -35,6 +35,8 @@ def initialize_state() -> None:
35
  st.session_state.time_checked = False
36
  if "checked_at" not in st.session_state:
37
  st.session_state.checked_at = None
 
 
38
 
39
 
40
  def set_status(message: str, status_type: str = "info") -> None:
@@ -67,8 +69,13 @@ def add_card() -> None:
67
 
68
 
69
  def check_time() -> None:
 
 
 
 
 
70
  st.session_state.time_checked = True
71
- st.session_state.checked_at = datetime.now().astimezone().isoformat()
72
  set_status("Time check completed.", "info")
73
 
74
 
@@ -115,6 +122,7 @@ def handle_save(index: int) -> None:
115
 
116
  load_css()
117
  initialize_state()
 
118
  fetch_cards_once()
119
  render_top_buttons(add_card, check_time)
120
  render_header()
 
1
  import streamlit as st
 
2
 
3
+ from components.browser_time import get_browser_time
4
  from components.buttons import render_top_buttons
5
  from components.card import render_card
6
  from components.header import render_header
 
35
  st.session_state.time_checked = False
36
  if "checked_at" not in st.session_state:
37
  st.session_state.checked_at = None
38
+ if "browser_time" not in st.session_state:
39
+ st.session_state.browser_time = None
40
 
41
 
42
  def set_status(message: str, status_type: str = "info") -> None:
 
69
 
70
 
71
  def check_time() -> None:
72
+ browser_time = st.session_state.get("browser_time")
73
+ if not browser_time:
74
+ set_status("Browser time is not ready yet. Try again in a moment.", "warning")
75
+ return
76
+
77
  st.session_state.time_checked = True
78
+ st.session_state.checked_at = browser_time
79
  set_status("Time check completed.", "info")
80
 
81
 
 
122
 
123
  load_css()
124
  initialize_state()
125
+ st.session_state.browser_time = get_browser_time()
126
  fetch_cards_once()
127
  render_top_buttons(add_card, check_time)
128
  render_header()
assets/style.css CHANGED
@@ -30,6 +30,12 @@
30
  padding-right: 0.75rem;
31
  }
32
 
 
 
 
 
 
 
33
  [data-testid="stHeader"] {
34
  background: transparent;
35
  }
@@ -97,8 +103,8 @@
97
  }
98
 
99
  .tone-strip-default {
100
- background: rgba(18, 32, 51, 0.06);
101
- color: var(--muted);
102
  }
103
 
104
  .tone-strip-success {
@@ -151,15 +157,15 @@
151
  }
152
 
153
  .end-time-inline-default {
154
- background: rgba(18, 32, 51, 0.05);
155
  }
156
 
157
  .end-time-inline-success {
158
- background: rgba(20, 125, 114, 0.12);
159
  }
160
 
161
  .end-time-inline-danger {
162
- background: rgba(214, 69, 69, 0.12);
163
  }
164
 
165
  .end-time-inline-label {
 
30
  padding-right: 0.75rem;
31
  }
32
 
33
+ iframe[title="browser_time_component.browser_time_component"] {
34
+ display: none !important;
35
+ height: 0 !important;
36
+ min-height: 0 !important;
37
+ }
38
+
39
  [data-testid="stHeader"] {
40
  background: transparent;
41
  }
 
103
  }
104
 
105
  .tone-strip-default {
106
+ background: rgba(18, 32, 51, 0.08);
107
+ color: #55657d;
108
  }
109
 
110
  .tone-strip-success {
 
157
  }
158
 
159
  .end-time-inline-default {
160
+ background: rgba(18, 32, 51, 0.08);
161
  }
162
 
163
  .end-time-inline-success {
164
+ background: rgba(20, 125, 114, 0.2);
165
  }
166
 
167
  .end-time-inline-danger {
168
+ background: rgba(214, 69, 69, 0.2);
169
  }
170
 
171
  .end-time-inline-label {
components/__pycache__/browser_time.cpython-312.pyc ADDED
Binary file (771 Bytes). View file
 
components/__pycache__/card.cpython-312.pyc CHANGED
Binary files a/components/__pycache__/card.cpython-312.pyc and b/components/__pycache__/card.cpython-312.pyc differ
 
components/browser_time.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+ import streamlit.components.v1 as components
4
+
5
+
6
+ _COMPONENT_DIR = Path(__file__).resolve().parent / "browser_time_component"
7
+ _browser_time_component = components.declare_component(
8
+ "browser_time_component",
9
+ path=str(_COMPONENT_DIR),
10
+ )
11
+
12
+
13
+ def get_browser_time(key: str = "browser_time_component") -> str | None:
14
+ return _browser_time_component(key=key, default=None)
components/browser_time_component/index.html ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <script src="https://unpkg.com/streamlit-component-lib@2.0.0/dist/index.js"></script>
7
+ </head>
8
+ <body>
9
+ <script>
10
+ function sendBrowserTime() {
11
+ const now = new Date().toISOString();
12
+ Streamlit.setComponentValue(now);
13
+ Streamlit.setFrameHeight(0);
14
+ }
15
+
16
+ function onRender(event) {
17
+ const { disabled } = event.detail.args || {};
18
+ if (!disabled) {
19
+ sendBrowserTime();
20
+ }
21
+ }
22
+
23
+ Streamlit.events.addEventListener(Streamlit.RENDER_EVENT, onRender);
24
+ Streamlit.setComponentReady();
25
+ Streamlit.setFrameHeight(0);
26
+ </script>
27
+ </body>
28
+ </html>
components/card.py CHANGED
@@ -1,7 +1,7 @@
1
  import streamlit as st
2
  from datetime import datetime
3
 
4
- from utils.time_utils import compute_end_time, format_time, get_card_tone, get_tone_message
5
 
6
 
7
  def render_card(index: int, on_save, on_delete) -> None:
@@ -17,13 +17,14 @@ def render_card(index: int, on_save, on_delete) -> None:
17
  card["endMinute"] = end_minute
18
  checked_at_raw = st.session_state.get("checked_at")
19
  checked_at = datetime.fromisoformat(checked_at_raw) if checked_at_raw else None
 
20
  tone = get_card_tone(
21
  end_hour,
22
  end_minute,
23
  reference_time=checked_at,
24
- enabled=st.session_state.get("time_checked", False),
25
  )
26
- tone_message = get_tone_message(tone)
27
 
28
  with st.container(border=True):
29
  st.markdown(
 
1
  import streamlit as st
2
  from datetime import datetime
3
 
4
+ from utils.time_utils import compute_end_time, format_time, get_card_tone, get_check_message
5
 
6
 
7
  def render_card(index: int, on_save, on_delete) -> None:
 
17
  card["endMinute"] = end_minute
18
  checked_at_raw = st.session_state.get("checked_at")
19
  checked_at = datetime.fromisoformat(checked_at_raw) if checked_at_raw else None
20
+ is_checked = st.session_state.get("time_checked", False)
21
  tone = get_card_tone(
22
  end_hour,
23
  end_minute,
24
  reference_time=checked_at,
25
+ enabled=is_checked,
26
  )
27
+ tone_message = get_check_message(tone, is_checked)
28
 
29
  with st.container(border=True):
30
  st.markdown(
utils/__pycache__/time_utils.cpython-312.pyc CHANGED
Binary files a/utils/__pycache__/time_utils.cpython-312.pyc and b/utils/__pycache__/time_utils.cpython-312.pyc differ
 
utils/time_utils.py CHANGED
@@ -50,6 +50,16 @@ def get_tone_message(tone: str) -> str:
50
  return "Press Check Time"
51
 
52
 
 
 
 
 
 
 
 
 
 
 
53
  def build_card_payload() -> dict[str, str]:
54
  end_hour, end_minute = compute_end_time("08", "00")
55
  return {
 
50
  return "Press Check Time"
51
 
52
 
53
+ def get_check_message(tone: str, checked: bool) -> str:
54
+ if not checked:
55
+ return "Press Check Time"
56
+ if tone == "danger":
57
+ return "Less than 5 minutes left"
58
+ if tone == "success":
59
+ return "Less than 10 minutes left"
60
+ return "More than 10 minutes left"
61
+
62
+
63
  def build_card_payload() -> dict[str, str]:
64
  end_hour, end_minute = compute_end_time("08", "00")
65
  return {