fix(CalendarSync): replace window.confirm() with inline confirmation and rename file

- Replace blocking window.confirm() with showRevokeConfirm state + inline
  confirmation dialog in CalendarSyncSection
- Rename CalendarSync.tsx to CalendarSyncSection.tsx to match export convention

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Flea Flicker
2026-03-26 08:18:54 +00:00
parent 1e84823656
commit 21b7eff326
@@ -12,6 +12,7 @@ export function CalendarSyncSection({ staffId }: Props) {
const [actionLoading, setActionLoading] = useState<"generate" | "revoke" | null>(null);
const [error, setError] = useState<string | null>(null);
const [copied, setCopied] = useState(false);
const [showRevokeConfirm, setShowRevokeConfirm] = useState(false);
useEffect(() => {
fetchToken();
@@ -51,7 +52,8 @@ export function CalendarSyncSection({ staffId }: Props) {
}
async function revokeToken() {
if (!confirm("Revoke your calendar feed link? Anyone with the current link will lose access.")) {
if (!showRevokeConfirm) {
setShowRevokeConfirm(true);
return;
}
setActionLoading("revoke");
@@ -67,6 +69,7 @@ export function CalendarSyncSection({ staffId }: Props) {
setError(e instanceof Error ? e.message : "Failed to revoke token");
} finally {
setActionLoading(null);
setShowRevokeConfirm(false);
}
}
@@ -120,32 +123,59 @@ export function CalendarSyncSection({ staffId }: Props) {
</div>
</div>
<div className="flex gap-2">
<button
onClick={generateToken}
disabled={actionLoading !== null}
className="flex items-center gap-1.5 px-3 py-2 bg-(--color-accent) text-white rounded-lg text-sm font-medium hover:bg-(--color-accent-hover) disabled:opacity-50"
>
{actionLoading === "generate" ? (
<RefreshCw size={14} className="animate-spin" />
) : (
<RefreshCw size={14} />
)}
Regenerate
</button>
<button
onClick={revokeToken}
disabled={actionLoading !== null}
className="flex items-center gap-1.5 px-3 py-2 border border-red-200 rounded-lg text-sm text-red-600 hover:bg-red-50 disabled:opacity-50"
>
{actionLoading === "revoke" ? (
<RefreshCw size={14} className="animate-spin" />
) : (
<Trash2 size={14} />
)}
Revoke
</button>
</div>
{showRevokeConfirm ? (
<div className="flex items-center gap-3 p-3 bg-red-50 border border-red-200 rounded-lg">
<p className="flex-1 text-sm text-red-700">
Revoke your calendar feed link? Anyone with the current link will lose access.
</p>
<button
onClick={revokeToken}
disabled={actionLoading !== null}
className="flex items-center gap-1.5 px-3 py-1.5 bg-red-600 text-white rounded-lg text-sm font-medium hover:bg-red-700 disabled:opacity-50"
>
{actionLoading === "revoke" ? (
<RefreshCw size={14} className="animate-spin" />
) : (
<Trash2 size={14} />
)}
Revoke
</button>
<button
onClick={() => setShowRevokeConfirm(false)}
disabled={actionLoading !== null}
className="px-3 py-1.5 border border-stone-200 rounded-lg text-sm text-stone-600 hover:bg-stone-50 disabled:opacity-50"
>
Cancel
</button>
</div>
) : (
<div className="flex gap-2">
<button
onClick={generateToken}
disabled={actionLoading !== null}
className="flex items-center gap-1.5 px-3 py-2 bg-(--color-accent) text-white rounded-lg text-sm font-medium hover:bg-(--color-accent-hover) disabled:opacity-50"
>
{actionLoading === "generate" ? (
<RefreshCw size={14} className="animate-spin" />
) : (
<RefreshCw size={14} />
)}
Regenerate
</button>
<button
onClick={revokeToken}
disabled={actionLoading !== null}
className="flex items-center gap-1.5 px-3 py-2 border border-red-200 rounded-lg text-sm text-red-600 hover:bg-red-50 disabled:opacity-50"
>
{actionLoading === "revoke" ? (
<RefreshCw size={14} className="animate-spin" />
) : (
<Trash2 size={14} />
)}
Revoke
</button>
</div>
)}
<p className="text-xs text-stone-400">
Regenerating will create a new URL and invalidate the old one.