From 445781bc40afee2c64f645abcfa2575b4218aa08 Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Sun, 7 Dec 2025 23:37:31 +0900
Subject: feat(client): add manual sync button
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Add SyncButton component that allows users to manually trigger
data synchronization. The button is disabled when offline or
when sync is already in progress.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---
 src/client/components/SyncButton.tsx | 39 ++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 src/client/components/SyncButton.tsx

(limited to 'src/client/components/SyncButton.tsx')

diff --git a/src/client/components/SyncButton.tsx b/src/client/components/SyncButton.tsx
new file mode 100644
index 0000000..1ebfa2e
--- /dev/null
+++ b/src/client/components/SyncButton.tsx
@@ -0,0 +1,39 @@
+import { useSync } from "../stores";
+
+export function SyncButton() {
+	const { isOnline, isSyncing, sync } = useSync();
+
+	const handleSync = async () => {
+		await sync();
+	};
+
+	const isDisabled = !isOnline || isSyncing;
+
+	const getButtonText = (): string => {
+		if (isSyncing) {
+			return "Syncing...";
+		}
+		return "Sync";
+	};
+
+	return (
+		<button
+			type="button"
+			data-testid="sync-button"
+			onClick={handleSync}
+			disabled={isDisabled}
+			title={!isOnline ? "Cannot sync while offline" : undefined}
+			style={{
+				padding: "0.25rem 0.5rem",
+				borderRadius: "4px",
+				border: "1px solid #dee2e6",
+				backgroundColor: isDisabled ? "#e9ecef" : "#007bff",
+				color: isDisabled ? "#6c757d" : "white",
+				cursor: isDisabled ? "not-allowed" : "pointer",
+				fontSize: "0.875rem",
+			}}
+		>
+			{getButtonText()}
+		</button>
+	);
+}
-- 
cgit v1.2.3-70-g09d2

