// frontend/components/AdminTabs/IntegrationsTab.jsx import React, { useEffect, useState } from "react"; import { apiUrl, safeFetchJSON } from "../../utils/api.js"; /** * Integrations tab — shows connection status for GitHub (and future * third-party integrations) with Connect/Disconnect actions. * * Best practices applied: * - Fetch current status on mount via /api/auth/status * - Show connected user info if already authenticated * - "Connect GitHub" button opens /api/auth/url in the same window * (OAuth flow will redirect back with ?code=...) * - Disconnect clears localStorage token and re-fetches status * - Handles both Web OAuth and Device Flow modes */ export default function IntegrationsTab({ userInfo, onDisconnect, showToast }) { const [authStatus, setAuthStatus] = useState(null); const [loading, setLoading] = useState(true); const [connecting, setConnecting] = useState(false); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; (async () => { try { const data = await safeFetchJSON(apiUrl("/api/auth/status"), { timeout: 5000 }); if (!cancelled) setAuthStatus(data); } catch (err) { if (!cancelled) setError(err?.message || "Failed to check auth status"); } finally { if (!cancelled) setLoading(false); } })(); return () => { cancelled = true; }; }, []); const handleConnect = async () => { setConnecting(true); setError(null); try { if (authStatus?.mode === "web") { // Web OAuth flow — redirect to GitHub authorization URL const { authorization_url, state } = await safeFetchJSON( apiUrl("/api/auth/url"), { timeout: 5000 } ); if (state) { sessionStorage.setItem("gitpilot_oauth_state", state); } // Full page redirect (OAuth providers don't support iframes) window.location.href = authorization_url; } else { // Device flow — the LoginPage already handles this. showToast?.( "Device flow", "GitHub device flow is configured. Sign out and sign in again to reconnect." ); } } catch (err) { setError(err?.message || "Failed to start OAuth flow"); setConnecting(false); } }; const handleDisconnect = () => { if (!window.confirm("Disconnect GitHub? You will be signed out.")) return; localStorage.removeItem("github_token"); localStorage.removeItem("github_user"); onDisconnect?.(); showToast?.("Disconnected", "GitHub token removed."); }; const isConnected = !!(userInfo && userInfo.login); return (
Connect third-party services to unlock additional GitPilot features.
{/* GitHub integration card */}Pull requests, issues, and remote repository workflows.
More integrations coming soon (GitLab, Bitbucket, Jira, Slack)