forked from op7418/CodePilot
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSetupCenter.tsx
More file actions
136 lines (123 loc) · 4.96 KB
/
SetupCenter.tsx
File metadata and controls
136 lines (123 loc) · 4.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
'use client';
import { useState, useEffect, useCallback, useRef } from 'react';
import { Button } from '@/components/ui/button';
import { WelcomeCard } from './WelcomeCard';
import { ClaudeCodeCard } from './ClaudeCodeCard';
import { ProviderCard } from './ProviderCard';
import { ProjectDirCard } from './ProjectDirCard';
import { useTranslation } from '@/hooks/useTranslation';
import type { SetupCardStatus } from '@/types';
interface SetupCenterProps {
onClose: () => void;
initialCard?: 'claude' | 'provider' | 'project';
}
export function SetupCenter({ onClose, initialCard }: SetupCenterProps) {
const { t } = useTranslation();
const [claudeStatus, setClaudeStatus] = useState<SetupCardStatus>('not-configured');
const [providerStatus, setProviderStatus] = useState<SetupCardStatus>('not-configured');
const [projectStatus, setProjectStatus] = useState<SetupCardStatus>('not-configured');
const [defaultProject, setDefaultProject] = useState<string | undefined>();
// Track the initial completedCount from the server so we only auto-close
// when the user completes the last card during this session, not on reopen.
const initialCompletedCountRef = useRef<number | null>(null);
// Load initial status
useEffect(() => {
fetch('/api/setup')
.then(r => r.ok ? r.json() : null)
.then(data => {
if (data) {
setClaudeStatus(data.claude);
setProviderStatus(data.provider);
setProjectStatus(data.project);
if (data.defaultProject) setDefaultProject(data.defaultProject);
// Record how many were already done when we opened
const initial = [data.claude, data.provider, data.project]
.filter((s: string) => s === 'completed' || s === 'skipped').length;
initialCompletedCountRef.current = initial;
}
})
.catch(() => {});
}, []);
const completedCount = [claudeStatus, providerStatus, projectStatus]
.filter(s => s === 'completed' || s === 'skipped').length;
// Auto-close when all done — but only if user made progress during this session
useEffect(() => {
if (
completedCount === 3 &&
initialCompletedCountRef.current !== null &&
initialCompletedCountRef.current < 3
) {
// Mark as completed
fetch('/api/setup', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ card: 'completed', status: 'completed' }),
}).catch(() => {});
// Brief delay before closing
const timer = setTimeout(onClose, 800);
return () => clearTimeout(timer);
}
}, [completedCount, onClose]);
// Scroll to initial card
useEffect(() => {
if (initialCard) {
const el = document.getElementById(`setup-card-${initialCard}`);
el?.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}, [initialCard]);
const handleProjectStatusChange = useCallback((status: SetupCardStatus, _value?: string) => {
setProjectStatus(status);
}, []);
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm">
<div className="w-full max-w-lg max-h-[90vh] overflow-y-auto rounded-xl border bg-card shadow-2xl">
{/* Header */}
<div className="sticky top-0 z-10 flex items-center justify-between bg-card px-6 pt-6 pb-3 border-b">
<div>
<h2 className="text-lg font-semibold">{t('setup.title')}</h2>
<p className="text-xs text-muted-foreground">{t('setup.subtitle')}</p>
</div>
<div className="flex items-center gap-3">
<span className="text-xs text-muted-foreground">
{t('setup.progress', { completed: String(completedCount) })}
</span>
<Button variant="ghost" size="sm" className="text-xs" onClick={() => {
// Persist skip so setup center doesn't reopen on next launch
fetch('/api/setup', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ card: 'completed', status: 'completed' }),
}).catch(() => {});
onClose();
}}>
{t('setup.skipAndEnter')}
</Button>
</div>
</div>
{/* Cards */}
<div className="p-6 space-y-4">
<WelcomeCard />
<div id="setup-card-claude">
<ClaudeCodeCard
status={claudeStatus}
onStatusChange={setClaudeStatus}
/>
</div>
<div id="setup-card-provider">
<ProviderCard
status={providerStatus}
onStatusChange={setProviderStatus}
/>
</div>
<div id="setup-card-project">
<ProjectDirCard
status={projectStatus}
onStatusChange={handleProjectStatusChange}
defaultProject={defaultProject}
/>
</div>
</div>
</div>
</div>
);
}