in packages/dashboard-app/src/components/installs/modal/login/tabs.tsx [244:381]
export function ProfileTab({
next,
back,
}: {
next: () => void;
back: () => void;
}) {
const [selectedProfile, setSelectedProfile] = useState<ProfileData | null>(
null,
);
const [profiles, setProfiles] = useState<Array<ProfileData>>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [isSubmitting, setIsSubmitting] = useState(false);
// Centralized function to set profile to avoid duplication
const handleSetProfile = useCallback(
(profile: ProfileData | null) => {
if (!profile || isSubmitting) return;
setIsSubmitting(true);
// Set the profile
Profile.setProfile(profile.profileName, profile.arn)
.then(() => {
next();
})
.catch((_) => {
setError("Failed to set profile. Please try again.");
setIsSubmitting(false);
});
},
[isSubmitting, next],
);
useEffect(() => {
// Fetch available profiles
Profile.listAvailableProfiles()
.then(async (res) => {
if (res.profiles && res.profiles.length > 0) {
setProfiles(
res.profiles.map((p) => ({
profileName: p.profileName,
arn: p.arn,
})),
);
} else {
setProfiles([]);
}
})
.catch((_) => {
setError("Failed to fetch available profiles");
})
.finally(async () => {
setLoading(false);
});
}, []);
useEffect(() => {
// Try to get current profile if available and swallow the error otherwise
State.get("api.codewhisperer.profile")
.then((profile) => {
if (profile) {
setSelectedProfile(profile);
}
})
.catch(() => {});
}, []);
// If there's only one profile, automatically select it and continue
useEffect(() => {
if (!loading && profiles.length === 1) {
const profile = profiles[0];
handleSetProfile(profile);
}
}, [loading, profiles, handleSetProfile]);
return (
<div className="flex flex-col items-center gap-8 gradient-q-secondary-light -m-10 p-10 rounded-lg text-white">
<h2 className="text-xl text-white font-semibold select-none leading-none font-ember tracking-tight">
Select a profile
</h2>
{error && (
<div className="flex flex-col items-center gap-2 w-full bg-red-200 border border-red-600 rounded py-2 px-2">
<p className="text-black dark:text-white font-semibold text-center">
Error
</p>
<p className="text-black dark:text-white text-center">{error}</p>
</div>
)}
<div className="flex flex-col items-center gap-4 text-white text-sm w-full max-w-md">
{loading ? (
<div className="flex flex-col items-center justify-center h-20 w-full">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-white"></div>
<p className="mt-4">Loading profiles...</p>
</div>
) : (
<>
<div className="w-full max-h-60 overflow-y-auto pr-2">
{profiles.map((profileItem) => (
<div
key={profileItem.arn}
className={`p-3 mb-2 rounded-md cursor-pointer border ${
selectedProfile && selectedProfile.arn === profileItem.arn
? "bg-white/20 border-white"
: "bg-white/5 border-transparent hover:bg-white/10"
}`}
onClick={() => {
if (!isSubmitting) {
setSelectedProfile(profileItem);
}
}}
>
<div className="font-medium">{profileItem.profileName}</div>
<div className="text-xs text-white/70 truncate">
{profileItem.arn}
</div>
</div>
))}
</div>
<div className="flex justify-between w-full mt-4">
<Button onClick={back}>Back</Button>
<Button
onClick={() => handleSetProfile(selectedProfile)}
disabled={!selectedProfile || isSubmitting}
>
{isSubmitting ? "Setting profile..." : "Continue"}
</Button>
</div>
</>
)}
</div>
</div>
);
}