Skip to content

Commit f58167a

Browse files
devdornBernhard Dorn
andauthored
7 show the current aktive tracked task at the top (#8)
* feat: navigation to section incl. active tracked task * nav sorted, active button w/ time display * addad collapse/expand functionality * Update Time display * added time tracked for today --------- Co-authored-by: Bernhard Dorn <b.dorn@svg.de>
1 parent 07bbdae commit f58167a

3 files changed

Lines changed: 380 additions & 115 deletions

File tree

src/App.tsx

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import type { AppSettings } from "./lib/types";
55
import { Settings as SettingsIcon, Clock, ListChecks, HelpCircle } from "lucide-react";
66
import { Button } from "./components/ui/Button";
77
import { TicketList } from "./components/TicketList";
8-
import { cn } from "./lib/utils";
8+
import { cn, formatDuration } from "./lib/utils";
9+
import { fetchTodaysTime } from "./lib/jira";
910

1011

1112

@@ -15,6 +16,22 @@ function App() {
1516
const [view, setView] = useState<View>("list");
1617
const [settings, setSettings] = useState<AppSettings | null>(null);
1718
const [loading, setLoading] = useState(true);
19+
const [todaysTimeSeconds, setTodaysTimeSeconds] = useState<number | null>(null);
20+
const [isTimeRefreshing, setIsTimeRefreshing] = useState(false);
21+
22+
const fetchTime = async (currentSettings: AppSettings) => {
23+
setIsTimeRefreshing(true);
24+
try {
25+
const time = await fetchTodaysTime(currentSettings);
26+
setTodaysTimeSeconds(time);
27+
} catch (e) {
28+
console.error("Failed to fetch time:", e);
29+
// Don't reset to 0 on error, keep last known good value or 0 if none
30+
if (todaysTimeSeconds === null) setTodaysTimeSeconds(0);
31+
} finally {
32+
setIsTimeRefreshing(false);
33+
}
34+
};
1835

1936
// Easter Egg State
2037
const [logoClicks, setLogoClicks] = useState(0);
@@ -76,6 +93,10 @@ function App() {
7693
setView("settings");
7794
}
7895
setLoading(false);
96+
// Fetch time after config is loaded
97+
if (s?.jiraHost && s?.jiraPat) {
98+
fetchTime(s);
99+
}
79100
};
80101

81102
const handleSaveSettings = () => {
@@ -105,6 +126,27 @@ function App() {
105126
<h1 className="text-lg font-bold tracking-tight text-gray-900 dark:text-white">JiraTime</h1>
106127
</div>
107128

129+
{/* Today's Time Display - Centered/Right in header */}
130+
{settings && view !== "settings" && (
131+
<div className="flex flex-col items-end mr-auto ml-4">
132+
<span className="text-[10px] text-gray-400 dark:text-gray-500 uppercase font-bold leading-none">Today</span>
133+
{todaysTimeSeconds !== null ? (
134+
<span className={cn(
135+
"text-xs font-semibold text-gray-700 dark:text-gray-300 tabular-nums transition-opacity duration-300",
136+
isTimeRefreshing && "opacity-50"
137+
)}>
138+
{formatDuration(todaysTimeSeconds)}
139+
</span>
140+
) : (
141+
<div className="flex items-center gap-1 h-4">
142+
<div className="w-1.5 h-1.5 bg-gray-300 dark:bg-gray-600 rounded-full animate-pulse"></div>
143+
<div className="w-1.5 h-1.5 bg-gray-300 dark:bg-gray-600 rounded-full animate-pulse delay-75"></div>
144+
<div className="w-1.5 h-1.5 bg-gray-300 dark:bg-gray-600 rounded-full animate-pulse delay-150"></div>
145+
</div>
146+
)}
147+
</div>
148+
)}
149+
108150
<div className="flex items-center gap-1">
109151
{settings && view !== "about" && (
110152
<Button variant="ghost" className="p-2 h-auto text-gray-500" onClick={() => setView("about")} title="About">
@@ -127,15 +169,17 @@ function App() {
127169
{/* Main Content */}
128170
<main className="flex-1 overflow-auto">
129171
{view === "settings" ? (
130-
<Settings
131-
onSave={handleSaveSettings}
132-
showCancel={!!settings}
133-
onCancel={() => {
134-
setPreviewTheme(null);
135-
setView("list");
136-
}}
137-
onThemeChange={setPreviewTheme}
138-
/>
172+
<div className="h-full overflow-y-auto">
173+
<Settings
174+
onSave={handleSaveSettings}
175+
showCancel={!!settings}
176+
onCancel={() => {
177+
setPreviewTheme(null);
178+
setView("list");
179+
}}
180+
onThemeChange={setPreviewTheme}
181+
/>
182+
</div>
139183
) : view === "about" ? (
140184
<div className="flex flex-col items-center justify-center h-full p-8 text-center space-y-6">
141185
<div className="bg-blue-100 dark:bg-blue-900/30 p-6 rounded-full text-blue-600 dark:text-blue-400 mb-2 animate-bounce">
@@ -159,7 +203,11 @@ function App() {
159203
</Button>
160204
</div>
161205
) : settings ? (
162-
<TicketList settings={settings} onSettingsChange={checkConfig} />
206+
<TicketList
207+
settings={settings}
208+
onSettingsChange={checkConfig}
209+
onTimeUpdate={() => fetchTime(settings)}
210+
/>
163211
) : (
164212
<div className="p-8 text-center text-gray-500">
165213
Please configure settings first.

0 commit comments

Comments
 (0)