Skip to content

Commit c54d838

Browse files
Copilotmikebarkmin
andcommitted
Add save feedback, unsaved changes warning, and UI alignment fixes
Co-authored-by: mikebarkmin <2592379+mikebarkmin@users.noreply.github.com>
1 parent b89a744 commit c54d838

1 file changed

Lines changed: 33 additions & 6 deletions

File tree

src/ConfigView.tsx

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { shallow } from "zustand/shallow";
22
import useStore, { RFState } from "./store";
3-
import { useCallback, useState } from "react";
3+
import { useCallback, useState, useEffect } from "react";
44
import { DataType, primitveDataTypes } from "./memory";
55

66
const selector = (state: RFState) => ({
@@ -22,6 +22,8 @@ export const ConfigView = () => {
2222
} | null>(null);
2323
const [newAttrName, setNewAttrName] = useState("");
2424
const [newAttrType, setNewAttrType] = useState<DataType>("String");
25+
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
26+
const [showSaveSuccess, setShowSaveSuccess] = useState(false);
2527

2628
// Get available data types: primitives + Array + defined classes
2729
const availableDataTypes = [
@@ -30,17 +32,33 @@ export const ConfigView = () => {
3032
...Object.keys(klasses),
3133
];
3234

35+
// Track changes
36+
useEffect(() => {
37+
const klassesChanged = JSON.stringify(klasses) !== JSON.stringify(memory.klasses);
38+
const optionsChanged = JSON.stringify(options) !== JSON.stringify(memory.options);
39+
setHasUnsavedChanges(klassesChanged || optionsChanged);
40+
}, [klasses, options, memory.klasses, memory.options]);
41+
3342
const onSave = useCallback(() => {
3443
updateMemory({
3544
...memory,
3645
klasses,
3746
options,
3847
});
48+
setHasUnsavedChanges(false);
49+
setShowSaveSuccess(true);
50+
setTimeout(() => setShowSaveSuccess(false), 2000);
3951
}, [memory, klasses, options, updateMemory]);
4052

4153
const onView = useCallback(() => {
42-
setRoute("view");
43-
}, [setRoute]);
54+
if (hasUnsavedChanges) {
55+
if (window.confirm("You have unsaved changes. Are you sure you want to leave?")) {
56+
setRoute("view");
57+
}
58+
} else {
59+
setRoute("view");
60+
}
61+
}, [setRoute, hasUnsavedChanges]);
4462

4563
const handleOptionChange = useCallback(
4664
(key: string, value: boolean) => {
@@ -178,11 +196,11 @@ export const ConfigView = () => {
178196
fontWeight: "600"
179197
}}>Configuration</h1>
180198

181-
<div style={{ display: "flex", gap: "8px" }}>
199+
<div style={{ display: "flex", gap: "8px", alignItems: "center" }}>
182200
<button
183201
onClick={onSave}
184202
style={{
185-
backgroundColor: "#111827",
203+
backgroundColor: hasUnsavedChanges ? "#111827" : "#6b7280",
186204
color: "white",
187205
padding: "8px 16px",
188206
fontSize: "14px",
@@ -191,7 +209,7 @@ export const ConfigView = () => {
191209
borderRadius: "6px",
192210
cursor: "pointer"
193211
}}
194-
>Save</button>
212+
>{hasUnsavedChanges ? "Save" : "Saved"}</button>
195213
<button
196214
onClick={onView}
197215
style={{
@@ -205,6 +223,15 @@ export const ConfigView = () => {
205223
cursor: "pointer"
206224
}}
207225
>View</button>
226+
{showSaveSuccess && (
227+
<span style={{
228+
color: "#10b981",
229+
fontSize: "14px",
230+
fontWeight: "500"
231+
}}>
232+
✓ Changes saved successfully
233+
</span>
234+
)}
208235
</div>
209236
</div>
210237

0 commit comments

Comments
 (0)