style: fix formatting with Prettier

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
SuperComboGamer
2025-12-21 20:31:57 -05:00
parent 584f5a3426
commit 8d578558ff
295 changed files with 9088 additions and 10546 deletions

View File

@@ -1,4 +1,4 @@
import { ReactNode } from "react";
import { ReactNode } from 'react';
interface AuthMethodOption {
id: string;
@@ -17,39 +17,38 @@ interface AuthMethodSelectorProps {
// Map badge colors to complete Tailwind class names
const getBadgeClasses = (badgeColor: string) => {
const colorMap: Record<string, { border: string; bg: string; text: string }> = {
"brand-500": {
border: "hover:border-brand-500/50",
bg: "hover:bg-brand-500/5",
text: "text-brand-500",
'brand-500': {
border: 'hover:border-brand-500/50',
bg: 'hover:bg-brand-500/5',
text: 'text-brand-500',
},
"green-500": {
border: "hover:border-green-500/50",
bg: "hover:bg-green-500/5",
text: "text-green-500",
'green-500': {
border: 'hover:border-green-500/50',
bg: 'hover:bg-green-500/5',
text: 'text-green-500',
},
"blue-500": {
border: "hover:border-blue-500/50",
bg: "hover:bg-blue-500/5",
text: "text-blue-500",
'blue-500': {
border: 'hover:border-blue-500/50',
bg: 'hover:bg-blue-500/5',
text: 'text-blue-500',
},
"purple-500": {
border: "hover:border-purple-500/50",
bg: "hover:bg-purple-500/5",
text: "text-purple-500",
'purple-500': {
border: 'hover:border-purple-500/50',
bg: 'hover:bg-purple-500/5',
text: 'text-purple-500',
},
};
return colorMap[badgeColor] || {
border: "hover:border-brand-500/50",
bg: "hover:bg-brand-500/5",
text: "text-brand-500",
};
return (
colorMap[badgeColor] || {
border: 'hover:border-brand-500/50',
bg: 'hover:bg-brand-500/5',
text: 'text-brand-500',
}
);
};
export function AuthMethodSelector({
options,
onSelect,
}: AuthMethodSelectorProps) {
export function AuthMethodSelector({ options, onSelect }: AuthMethodSelectorProps) {
return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{options.map((option) => {
@@ -65,12 +64,8 @@ export function AuthMethodSelector({
{option.icon}
<div>
<p className="font-medium text-foreground">{option.title}</p>
<p className="text-sm text-muted-foreground mt-1">
{option.description}
</p>
<p className={`text-xs ${badgeClasses.text} mt-2`}>
{option.badge}
</p>
<p className="text-sm text-muted-foreground mt-1">{option.description}</p>
<p className={`text-xs ${badgeClasses.text} mt-2`}>{option.badge}</p>
</div>
</div>
</button>

View File

@@ -1,14 +1,8 @@
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Download, Loader2, AlertCircle } from "lucide-react";
import { CopyableCommandField } from "./copyable-command-field";
import { TerminalOutput } from "./terminal-output";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Download, Loader2, AlertCircle } from 'lucide-react';
import { CopyableCommandField } from './copyable-command-field';
import { TerminalOutput } from './terminal-output';
interface CommandInfo {
label: string; // e.g., "macOS / Linux"
@@ -23,7 +17,7 @@ interface CliInstallationCardProps {
installProgress: { output: string[] };
onInstall: () => void;
warningMessage?: string;
color?: "brand" | "green"; // For different CLI themes
color?: 'brand' | 'green'; // For different CLI themes
}
export function CliInstallationCard({
@@ -34,11 +28,11 @@ export function CliInstallationCard({
installProgress,
onInstall,
warningMessage,
color = "brand",
color = 'brand',
}: CliInstallationCardProps) {
const colorClasses = {
brand: "bg-brand-500 hover:bg-brand-600",
green: "bg-green-500 hover:bg-green-600",
brand: 'bg-brand-500 hover:bg-brand-600',
green: 'bg-green-500 hover:bg-green-600',
};
return (
@@ -52,16 +46,10 @@ export function CliInstallationCard({
</CardHeader>
<CardContent className="space-y-4">
{commands.map((cmd, index) => (
<CopyableCommandField
key={index}
label={cmd.label}
command={cmd.command}
/>
<CopyableCommandField key={index} label={cmd.label} command={cmd.command} />
))}
{isInstalling && (
<TerminalOutput lines={installProgress.output} />
)}
{isInstalling && <TerminalOutput lines={installProgress.output} />}
<Button
onClick={onInstall}
@@ -86,9 +74,7 @@ export function CliInstallationCard({
<div className="p-3 rounded-lg bg-yellow-500/10 border border-yellow-500/20">
<div className="flex items-start gap-2">
<AlertCircle className="w-4 h-4 text-yellow-500 mt-0.5" />
<p className="text-xs text-yellow-600 dark:text-yellow-400">
{warningMessage}
</p>
<p className="text-xs text-yellow-600 dark:text-yellow-400">{warningMessage}</p>
</div>
</div>
)}

View File

@@ -1,26 +1,21 @@
import { Button } from "@/components/ui/button";
import { Copy } from "lucide-react";
import { toast } from "sonner";
import { Button } from '@/components/ui/button';
import { Copy } from 'lucide-react';
import { toast } from 'sonner';
interface CopyableCommandFieldProps {
command: string;
label?: string;
}
export function CopyableCommandField({
command,
label,
}: CopyableCommandFieldProps) {
export function CopyableCommandField({ command, label }: CopyableCommandFieldProps) {
const copyToClipboard = () => {
navigator.clipboard.writeText(command);
toast.success("Command copied to clipboard");
toast.success('Command copied to clipboard');
};
return (
<div className="space-y-2">
{label && (
<span className="text-sm text-muted-foreground">{label}</span>
)}
{label && <span className="text-sm text-muted-foreground">{label}</span>}
<div className="flex items-center gap-2">
<code className="flex-1 bg-muted px-3 py-2 rounded text-sm font-mono text-foreground">
{command}

View File

@@ -1,9 +1,9 @@
// Re-export all setup-view components for easier imports
export { StepIndicator } from "./step-indicator";
export { StatusBadge } from "./status-badge";
export { StatusRow } from "./status-row";
export { TerminalOutput } from "./terminal-output";
export { CopyableCommandField } from "./copyable-command-field";
export { CliInstallationCard } from "./cli-installation-card";
export { ReadyStateCard } from "./ready-state-card";
export { AuthMethodSelector } from "./auth-method-selector";
export { StepIndicator } from './step-indicator';
export { StatusBadge } from './status-badge';
export { StatusRow } from './status-row';
export { TerminalOutput } from './terminal-output';
export { CopyableCommandField } from './copyable-command-field';
export { CliInstallationCard } from './cli-installation-card';
export { ReadyStateCard } from './ready-state-card';
export { AuthMethodSelector } from './auth-method-selector';

View File

@@ -1,25 +1,21 @@
import { Card, CardContent } from "@/components/ui/card";
import { CheckCircle2 } from "lucide-react";
import { Card, CardContent } from '@/components/ui/card';
import { CheckCircle2 } from 'lucide-react';
interface ReadyStateCardProps {
title: string;
description: string;
variant?: "success" | "info";
variant?: 'success' | 'info';
}
export function ReadyStateCard({
title,
description,
variant = "success",
}: ReadyStateCardProps) {
export function ReadyStateCard({ title, description, variant = 'success' }: ReadyStateCardProps) {
const variantClasses = {
success: "bg-green-500/5 border-green-500/20",
info: "bg-blue-500/5 border-blue-500/20",
success: 'bg-green-500/5 border-green-500/20',
info: 'bg-blue-500/5 border-blue-500/20',
};
const iconColorClasses = {
success: "bg-green-500/10 text-green-500",
info: "bg-blue-500/10 text-blue-500",
success: 'bg-green-500/10 text-green-500',
info: 'bg-blue-500/10 text-blue-500',
};
return (

View File

@@ -1,46 +1,46 @@
import { CheckCircle2, XCircle, Loader2, AlertCircle } from "lucide-react";
import { CheckCircle2, XCircle, Loader2, AlertCircle } from 'lucide-react';
interface StatusBadgeProps {
status:
| "installed"
| "not_installed"
| "checking"
| "authenticated"
| "not_authenticated"
| "error"
| "unverified";
| 'installed'
| 'not_installed'
| 'checking'
| 'authenticated'
| 'not_authenticated'
| 'error'
| 'unverified';
label: string;
}
export function StatusBadge({ status, label }: StatusBadgeProps) {
const getStatusConfig = () => {
switch (status) {
case "installed":
case "authenticated":
case 'installed':
case 'authenticated':
return {
icon: <CheckCircle2 className="w-4 h-4" />,
className: "bg-green-500/10 text-green-500 border-green-500/20",
className: 'bg-green-500/10 text-green-500 border-green-500/20',
};
case "not_installed":
case "not_authenticated":
case 'not_installed':
case 'not_authenticated':
return {
icon: <XCircle className="w-4 h-4" />,
className: "bg-red-500/10 text-red-500 border-red-500/20",
className: 'bg-red-500/10 text-red-500 border-red-500/20',
};
case "error":
case 'error':
return {
icon: <XCircle className="w-4 h-4" />,
className: "bg-red-500/10 text-red-500 border-red-500/20",
className: 'bg-red-500/10 text-red-500 border-red-500/20',
};
case "checking":
case 'checking':
return {
icon: <Loader2 className="w-4 h-4 animate-spin" />,
className: "bg-yellow-500/10 text-yellow-500 border-yellow-500/20",
className: 'bg-yellow-500/10 text-yellow-500 border-yellow-500/20',
};
case "unverified":
case 'unverified':
return {
icon: <AlertCircle className="w-4 h-4" />,
className: "bg-yellow-500/10 text-yellow-500 border-yellow-500/20",
className: 'bg-yellow-500/10 text-yellow-500 border-yellow-500/20',
};
}
};

View File

@@ -1,31 +1,19 @@
import { StatusBadge } from "./status-badge";
import { StatusBadge } from './status-badge';
interface StatusRowProps {
label: string;
status:
| "checking"
| "installed"
| "not_installed"
| "authenticated"
| "not_authenticated";
status: 'checking' | 'installed' | 'not_installed' | 'authenticated' | 'not_authenticated';
statusLabel: string;
metadata?: string; // e.g., "(Subscription Token)"
}
export function StatusRow({
label,
status,
statusLabel,
metadata,
}: StatusRowProps) {
export function StatusRow({ label, status, statusLabel, metadata }: StatusRowProps) {
return (
<div className="flex items-center justify-between">
<span className="text-sm text-foreground">{label}</span>
<div className="flex items-center gap-2">
<StatusBadge status={status} label={statusLabel} />
{metadata && (
<span className="text-xs text-muted-foreground">{metadata}</span>
)}
{metadata && <span className="text-xs text-muted-foreground">{metadata}</span>}
</div>
</div>
);

View File

@@ -3,19 +3,14 @@ interface StepIndicatorProps {
totalSteps: number;
}
export function StepIndicator({
currentStep,
totalSteps,
}: StepIndicatorProps) {
export function StepIndicator({ currentStep, totalSteps }: StepIndicatorProps) {
return (
<div className="flex items-center justify-center gap-2 mb-8">
{Array.from({ length: totalSteps }).map((_, index) => (
<div
key={index}
className={`h-2 rounded-full transition-all duration-300 ${
index <= currentStep
? "w-8 bg-brand-500"
: "w-2 bg-muted-foreground/30"
index <= currentStep ? 'w-8 bg-brand-500' : 'w-2 bg-muted-foreground/30'
}`}
/>
))}

View File

@@ -1,4 +1,4 @@
// Re-export all hooks for easier imports
export { useCliStatus } from "./use-cli-status";
export { useCliInstallation } from "./use-cli-installation";
export { useTokenSave } from "./use-token-save";
export { useCliStatus } from './use-cli-status';
export { useCliInstallation } from './use-cli-installation';
export { useTokenSave } from './use-token-save';

View File

@@ -1,8 +1,8 @@
import { useState, useCallback } from "react";
import { toast } from "sonner";
import { useState, useCallback } from 'react';
import { toast } from 'sonner';
interface UseCliInstallationOptions {
cliType: "claude";
cliType: 'claude';
installApi: () => Promise<any>;
onProgressEvent?: (callback: (progress: any) => void) => (() => void) | undefined;
onSuccess?: () => void;
@@ -29,20 +29,22 @@ export function useCliInstallation({
let unsubscribe: (() => void) | undefined;
if (onProgressEvent) {
unsubscribe = onProgressEvent((progress: { cli?: string; data?: string; type?: string }) => {
if (progress.cli === cliType) {
setInstallProgress((prev) => ({
output: [...prev.output, progress.data || progress.type || ""],
}));
unsubscribe = onProgressEvent(
(progress: { cli?: string; data?: string; type?: string }) => {
if (progress.cli === cliType) {
setInstallProgress((prev) => ({
output: [...prev.output, progress.data || progress.type || ''],
}));
}
}
});
);
}
const result = await installApi();
unsubscribe?.();
if (result.success) {
if (cliType === "claude" && onSuccess && getStoreState) {
if (cliType === 'claude' && onSuccess && getStoreState) {
// Claude-specific: retry logic to detect installation
let retries = 5;
let detected = false;
@@ -68,7 +70,7 @@ export function useCliInstallation({
if (!detected) {
toast.success(`${cliType} CLI installation completed`, {
description:
"The CLI was installed but may need a terminal restart to be detected. You can continue with authentication if you have a token.",
'The CLI was installed but may need a terminal restart to be detected. You can continue with authentication if you have a token.',
duration: 7000,
});
}
@@ -77,11 +79,11 @@ export function useCliInstallation({
onSuccess?.();
}
} else {
toast.error("Installation failed", { description: result.error });
toast.error('Installation failed', { description: result.error });
}
} catch (error) {
console.error(`Failed to install ${cliType}:`, error);
toast.error("Installation failed");
toast.error('Installation failed');
} finally {
setIsInstalling(false);
}

View File

@@ -1,7 +1,7 @@
import { useState, useCallback } from "react";
import { useState, useCallback } from 'react';
interface UseCliStatusOptions {
cliType: "claude";
cliType: 'claude';
statusApi: () => Promise<any>;
setCliStatus: (status: any) => void;
setAuthStatus: (status: any) => void;
@@ -24,10 +24,10 @@ export function useCliStatus({
if (result.success) {
const cliStatus = {
installed: result.status === "installed",
installed: result.status === 'installed',
path: result.path || null,
version: result.version || null,
method: result.method || "none",
method: result.method || 'none',
};
console.log(`[${cliType} Setup] CLI Status:`, cliStatus);
setCliStatus(cliStatus);
@@ -35,29 +35,24 @@ export function useCliStatus({
if (result.auth) {
// Validate method is one of the expected values, default to "none"
const validMethods = [
"oauth_token_env",
"oauth_token",
"api_key",
"api_key_env",
"credentials_file",
"cli_authenticated",
"none",
'oauth_token_env',
'oauth_token',
'api_key',
'api_key_env',
'credentials_file',
'cli_authenticated',
'none',
] as const;
type AuthMethod = (typeof validMethods)[number];
const method: AuthMethod = validMethods.includes(
result.auth.method as AuthMethod
)
const method: AuthMethod = validMethods.includes(result.auth.method as AuthMethod)
? (result.auth.method as AuthMethod)
: "none";
: 'none';
const authStatus = {
authenticated: result.auth.authenticated,
method,
hasCredentialsFile: false,
oauthTokenValid:
result.auth.hasStoredOAuthToken ||
result.auth.hasEnvOAuthToken,
apiKeyValid:
result.auth.hasStoredApiKey || result.auth.hasEnvApiKey,
oauthTokenValid: result.auth.hasStoredOAuthToken || result.auth.hasEnvOAuthToken,
apiKeyValid: result.auth.hasStoredApiKey || result.auth.hasEnvApiKey,
hasEnvOAuthToken: result.auth.hasEnvOAuthToken,
hasEnvApiKey: result.auth.hasEnvApiKey,
};

View File

@@ -1,6 +1,6 @@
import { useState, useCallback } from "react";
import { toast } from "sonner";
import { getElectronAPI } from "@/lib/electron";
import { useState, useCallback } from 'react';
import { toast } from 'sonner';
import { getElectronAPI } from '@/lib/electron';
interface UseTokenSaveOptions {
provider: string; // e.g., "anthropic_oauth_token", "anthropic", "openai"
@@ -13,7 +13,7 @@ export function useTokenSave({ provider, onSuccess }: UseTokenSaveOptions) {
const saveToken = useCallback(
async (tokenValue: string) => {
if (!tokenValue.trim()) {
toast.error("Please enter a valid token");
toast.error('Please enter a valid token');
return false;
}
@@ -27,25 +27,23 @@ export function useTokenSave({ provider, onSuccess }: UseTokenSaveOptions) {
console.log(`[Token Save] Store result for ${provider}:`, result);
if (result.success) {
const tokenType = provider.includes("oauth")
? "subscription token"
: "API key";
const tokenType = provider.includes('oauth') ? 'subscription token' : 'API key';
toast.success(`${tokenType} saved successfully`);
onSuccess?.();
return true;
} else {
toast.error("Failed to save token", { description: result.error });
toast.error('Failed to save token', { description: result.error });
return false;
}
} else {
// Web mode fallback - just show success
toast.success("Token saved");
toast.success('Token saved');
onSuccess?.();
return true;
}
} catch (error) {
console.error(`[Token Save] Failed to save ${provider}:`, error);
toast.error("Failed to save token");
toast.error('Failed to save token');
return false;
} finally {
setIsSaving(false);

View File

@@ -1,15 +1,8 @@
import { useState, useEffect, useCallback } from "react";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { useSetupStore } from "@/store/setup-store";
import { getElectronAPI } from "@/lib/electron";
import { useState, useEffect, useCallback } from 'react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { useSetupStore } from '@/store/setup-store';
import { getElectronAPI } from '@/lib/electron';
import {
CheckCircle2,
Loader2,
@@ -21,9 +14,9 @@ import {
AlertTriangle,
Github,
XCircle,
} from "lucide-react";
import { toast } from "sonner";
import { StatusBadge } from "../components";
} from 'lucide-react';
import { toast } from 'sonner';
import { StatusBadge } from '../components';
interface GitHubSetupStepProps {
onNext: () => void;
@@ -31,11 +24,7 @@ interface GitHubSetupStepProps {
onSkip: () => void;
}
export function GitHubSetupStep({
onNext,
onBack,
onSkip,
}: GitHubSetupStepProps) {
export function GitHubSetupStep({ onNext, onBack, onSkip }: GitHubSetupStepProps) {
const { ghCliStatus, setGhCliStatus } = useSetupStore();
const [isChecking, setIsChecking] = useState(false);
@@ -57,7 +46,7 @@ export function GitHubSetupStep({
});
}
} catch (error) {
console.error("Failed to check gh status:", error);
console.error('Failed to check gh status:', error);
} finally {
setIsChecking(false);
}
@@ -69,7 +58,7 @@ export function GitHubSetupStep({
const copyCommand = (command: string) => {
navigator.clipboard.writeText(command);
toast.success("Command copied to clipboard");
toast.success('Command copied to clipboard');
};
const isReady = ghCliStatus?.installed && ghCliStatus?.authenticated;
@@ -93,12 +82,8 @@ export function GitHubSetupStep({
<div className="w-16 h-16 rounded-xl bg-zinc-800 flex items-center justify-center mx-auto mb-4">
<Github className="w-8 h-8 text-white" />
</div>
<h2 className="text-2xl font-bold text-foreground mb-2">
GitHub CLI Setup
</h2>
<p className="text-muted-foreground">
Optional - Used for creating pull requests
</p>
<h2 className="text-2xl font-bold text-foreground mb-2">GitHub CLI Setup</h2>
<p className="text-muted-foreground">Optional - Used for creating pull requests</p>
</div>
{/* Info Banner */}
@@ -107,13 +92,10 @@ export function GitHubSetupStep({
<div className="flex items-start gap-3">
<AlertTriangle className="w-5 h-5 text-amber-500 shrink-0 mt-0.5" />
<div>
<p className="font-medium text-foreground">
This step is optional
</p>
<p className="font-medium text-foreground">This step is optional</p>
<p className="text-sm text-muted-foreground mt-1">
The GitHub CLI allows you to create pull requests directly from
the app. Without it, you can still create PRs manually in your
browser.
The GitHub CLI allows you to create pull requests directly from the app. Without it,
you can still create PRs manually in your browser.
</p>
</div>
</div>
@@ -130,24 +112,17 @@ export function GitHubSetupStep({
</CardTitle>
<div className="flex items-center gap-2">
{getStatusBadge()}
<Button
variant="ghost"
size="sm"
onClick={checkStatus}
disabled={isChecking}
>
<RefreshCw
className={`w-4 h-4 ${isChecking ? "animate-spin" : ""}`}
/>
<Button variant="ghost" size="sm" onClick={checkStatus} disabled={isChecking}>
<RefreshCw className={`w-4 h-4 ${isChecking ? 'animate-spin' : ''}`} />
</Button>
</div>
</div>
<CardDescription>
{ghCliStatus?.installed
? ghCliStatus.authenticated
? `Logged in${ghCliStatus.user ? ` as ${ghCliStatus.user}` : ""}`
: "Installed but not logged in"
: "Not installed on your system"}
? `Logged in${ghCliStatus.user ? ` as ${ghCliStatus.user}` : ''}`
: 'Installed but not logged in'
: 'Not installed on your system'}
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
@@ -156,9 +131,7 @@ export function GitHubSetupStep({
<div className="flex items-center gap-3 p-4 rounded-lg bg-green-500/10 border border-green-500/20">
<CheckCircle2 className="w-5 h-5 text-green-500" />
<div>
<p className="font-medium text-foreground">
GitHub CLI is ready!
</p>
<p className="font-medium text-foreground">GitHub CLI is ready!</p>
<p className="text-sm text-muted-foreground">
You can create pull requests directly from the app.
{ghCliStatus?.version && (
@@ -175,9 +148,7 @@ export function GitHubSetupStep({
<div className="flex items-start gap-3 p-4 rounded-lg bg-muted/30 border border-border">
<XCircle className="w-5 h-5 text-muted-foreground shrink-0 mt-0.5" />
<div className="flex-1">
<p className="font-medium text-foreground">
GitHub CLI not found
</p>
<p className="font-medium text-foreground">GitHub CLI not found</p>
<p className="text-sm text-muted-foreground mt-1">
Install the GitHub CLI to enable PR creation from the app.
</p>
@@ -185,9 +156,7 @@ export function GitHubSetupStep({
</div>
<div className="space-y-3 p-4 rounded-lg bg-muted/30 border border-border">
<p className="font-medium text-foreground text-sm">
Installation Commands:
</p>
<p className="font-medium text-foreground text-sm">Installation Commands:</p>
<div className="space-y-2">
<p className="text-xs text-muted-foreground">macOS (Homebrew)</p>
@@ -198,7 +167,7 @@ export function GitHubSetupStep({
<Button
variant="ghost"
size="icon"
onClick={() => copyCommand("brew install gh")}
onClick={() => copyCommand('brew install gh')}
>
<Copy className="w-4 h-4" />
</Button>
@@ -214,7 +183,7 @@ export function GitHubSetupStep({
<Button
variant="ghost"
size="icon"
onClick={() => copyCommand("winget install GitHub.cli")}
onClick={() => copyCommand('winget install GitHub.cli')}
>
<Copy className="w-4 h-4" />
</Button>
@@ -230,7 +199,7 @@ export function GitHubSetupStep({
<Button
variant="ghost"
size="icon"
onClick={() => copyCommand("sudo apt install gh")}
onClick={() => copyCommand('sudo apt install gh')}
>
<Copy className="w-4 h-4" />
</Button>
@@ -256,9 +225,7 @@ export function GitHubSetupStep({
<div className="flex items-start gap-3 p-4 rounded-lg bg-amber-500/10 border border-amber-500/20">
<AlertTriangle className="w-5 h-5 text-amber-500 shrink-0 mt-0.5" />
<div className="flex-1">
<p className="font-medium text-foreground">
GitHub CLI not logged in
</p>
<p className="font-medium text-foreground">GitHub CLI not logged in</p>
<p className="text-sm text-muted-foreground mt-1">
Run the login command to authenticate with GitHub.
</p>
@@ -266,18 +233,12 @@ export function GitHubSetupStep({
</div>
<div className="space-y-2 p-4 rounded-lg bg-muted/30 border border-border">
<p className="text-sm text-muted-foreground">
Run this command in your terminal:
</p>
<p className="text-sm text-muted-foreground">Run this command in your terminal:</p>
<div className="flex items-center gap-2">
<code className="flex-1 bg-muted px-3 py-2 rounded text-sm font-mono text-foreground">
gh auth login
</code>
<Button
variant="ghost"
size="icon"
onClick={() => copyCommand("gh auth login")}
>
<Button variant="ghost" size="icon" onClick={() => copyCommand('gh auth login')}>
<Copy className="w-4 h-4" />
</Button>
</div>
@@ -290,9 +251,7 @@ export function GitHubSetupStep({
<div className="flex items-center gap-3 p-4 rounded-lg bg-blue-500/10 border border-blue-500/20">
<Loader2 className="w-5 h-5 text-blue-500 animate-spin" />
<div>
<p className="font-medium text-foreground">
Checking GitHub CLI status...
</p>
<p className="font-medium text-foreground">Checking GitHub CLI status...</p>
</div>
</div>
)}
@@ -301,28 +260,20 @@ export function GitHubSetupStep({
{/* Navigation */}
<div className="flex justify-between pt-4">
<Button
variant="ghost"
onClick={onBack}
className="text-muted-foreground"
>
<Button variant="ghost" onClick={onBack} className="text-muted-foreground">
<ArrowLeft className="w-4 h-4 mr-2" />
Back
</Button>
<div className="flex gap-2">
<Button
variant="ghost"
onClick={onSkip}
className="text-muted-foreground"
>
{isReady ? "Skip" : "Skip for now"}
<Button variant="ghost" onClick={onSkip} className="text-muted-foreground">
{isReady ? 'Skip' : 'Skip for now'}
</Button>
<Button
onClick={onNext}
className="bg-brand-500 hover:bg-brand-600 text-white"
data-testid="github-next-button"
>
{isReady ? "Continue" : "Continue without GitHub CLI"}
{isReady ? 'Continue' : 'Continue without GitHub CLI'}
<ArrowRight className="w-4 h-4 ml-2" />
</Button>
</div>