feat: Add visual success/error states to save instructions button
All checks were successful
Automated Container Build / build-and-push (push) Successful in 57s
All checks were successful
Automated Container Build / build-and-push (push) Successful in 57s
This commit is contained in:
parent
ff80bde45a
commit
c37029a890
1 changed files with 24 additions and 3 deletions
|
|
@ -6,6 +6,7 @@ export function GenerateTab({ importType }: { importType: "flashcards" | "quizze
|
||||||
const [instructions, setInstructions] = useState("");
|
const [instructions, setInstructions] = useState("");
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
|
const [saveResult, setSaveResult] = useState<"success" | "error" | null>(null);
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -17,14 +18,20 @@ export function GenerateTab({ importType }: { importType: "flashcards" | "quizze
|
||||||
|
|
||||||
async function handleSave() {
|
async function handleSave() {
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
|
setSaveResult(null);
|
||||||
try {
|
try {
|
||||||
await fetch(`/api/settings/llm-instructions?type=${importType}`, {
|
const res = await fetch(`/api/settings/llm-instructions?type=${importType}`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ value: instructions }),
|
body: JSON.stringify({ value: instructions }),
|
||||||
});
|
});
|
||||||
|
if (!res.ok) throw new Error("Failed to save");
|
||||||
|
setSaveResult("success");
|
||||||
|
} catch {
|
||||||
|
setSaveResult("error");
|
||||||
} finally {
|
} finally {
|
||||||
setSaving(false);
|
setSaving(false);
|
||||||
|
setTimeout(() => setSaveResult(null), 2500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,9 +98,23 @@ export function GenerateTab({ importType }: { importType: "flashcards" | "quizze
|
||||||
<button
|
<button
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
className="px-4 py-2 rounded-lg border border-border text-sm text-text-secondary hover:bg-bg-surface-alt transition-all duration-200 cursor-pointer disabled:opacity-50"
|
className={`inline-flex items-center gap-2 px-4 py-2 rounded-lg border text-sm transition-all duration-200 cursor-pointer disabled:opacity-50 ${
|
||||||
|
saveResult === "success" ? "border-success text-success bg-success-bg" :
|
||||||
|
saveResult === "error" ? "border-error text-error bg-error-bg" :
|
||||||
|
"border-border text-text-secondary hover:bg-bg-surface-alt"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{saving ? "Saving..." : "Save Changes"}
|
{saving ? "Saving..." :
|
||||||
|
saveResult === "success" ? (
|
||||||
|
<>
|
||||||
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||||
|
</svg>
|
||||||
|
Saved!
|
||||||
|
</>
|
||||||
|
) :
|
||||||
|
saveResult === "error" ? "Failed to Save" :
|
||||||
|
"Save Changes"}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleReset}
|
onClick={handleReset}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue