MAESTRO: wire analyse shortcut action feedback

This commit is contained in:
Mariusz Banach
2026-02-18 00:46:15 +01:00
parent e669a16d02
commit 37ac150a94
2 changed files with 31 additions and 3 deletions

View File

@@ -41,7 +41,7 @@ Note: `npx vitest run src/__tests__/AnalyseButton.test.tsx` passes; Vitest emits
- [x] User can paste text into the header input area - [x] User can paste text into the header input area
- [x] User can drop an EML/TXT file and see it auto-populate the input - [x] User can drop an EML/TXT file and see it auto-populate the input
- [x] Analyse button is disabled when input is empty - [x] Analyse button is disabled when input is empty
- [ ] Ctrl+Enter keyboard shortcut triggers the analyse action - [x] Ctrl+Enter keyboard shortcut triggers the analyse action
- [ ] Dark hacker theme is visible with correct colour palette - [ ] Dark hacker theme is visible with correct colour palette
- [ ] Validation shows user-friendly errors for empty and oversized input - [ ] Validation shows user-friendly errors for empty and oversized input
- [ ] `npx eslint src/` and `npx prettier --check src/` pass with zero errors - [ ] `npx eslint src/` and `npx prettier --check src/` pass with zero errors

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { useState } from "react"; import { useEffect, useRef, useState } from "react";
import AnalyseButton from "../components/AnalyseButton"; import AnalyseButton from "../components/AnalyseButton";
import FileDropZone from "../components/FileDropZone"; import FileDropZone from "../components/FileDropZone";
@@ -8,7 +8,31 @@ import HeaderInput from "../components/HeaderInput";
export default function Home() { export default function Home() {
const [headerInput, setHeaderInput] = useState(""); const [headerInput, setHeaderInput] = useState("");
const [isAnalyzing, setIsAnalyzing] = useState(false);
const hasHeaderInput = headerInput.trim().length > 0; const hasHeaderInput = headerInput.trim().length > 0;
const analyseTimeoutRef = useRef<number | null>(null);
useEffect(() => {
return () => {
if (analyseTimeoutRef.current !== null) {
window.clearTimeout(analyseTimeoutRef.current);
}
};
}, []);
const handleAnalyse = () => {
if (!hasHeaderInput) {
return;
}
setIsAnalyzing(true);
if (analyseTimeoutRef.current !== null) {
window.clearTimeout(analyseTimeoutRef.current);
}
analyseTimeoutRef.current = window.setTimeout(() => {
setIsAnalyzing(false);
}, 800);
};
return ( return (
<main className="min-h-screen bg-background text-text"> <main className="min-h-screen bg-background text-text">
@@ -44,7 +68,11 @@ export default function Home() {
heuristics, and delivery path insights. heuristics, and delivery path insights.
</p> </p>
<div className="mt-4 flex flex-col gap-3 sm:flex-row sm:items-center"> <div className="mt-4 flex flex-col gap-3 sm:flex-row sm:items-center">
<AnalyseButton hasInput={hasHeaderInput} onAnalyse={() => undefined} /> <AnalyseButton
hasInput={hasHeaderInput}
onAnalyse={handleAnalyse}
isLoading={isAnalyzing}
/>
<div className="flex items-center gap-2 text-xs text-text/60"> <div className="flex items-center gap-2 text-xs text-text/60">
<kbd className="rounded-md border border-info/30 bg-background/40 px-2 py-1 font-mono"> <kbd className="rounded-md border border-info/30 bg-background/40 px-2 py-1 font-mono">
Ctrl Ctrl