import { useTranslation } from 'react-i18next';
import { useQuery, useMutation } from '@tanstack/react-query';
import { motion } from 'framer-motion';
import { authApi } from '../api/auth';
import { useToast } from '../components/Toast';
import { Card } from '@/components/data-display/Card';
import { Button } from '@/components/primitives/Button';
import { staggerContainer, staggerItem } from '@/components/motion/transitions';
import OAuthProviderIcon from '../components/OAuthProviderIcon';
import type { LinkedProvider } from '../types';
const OAUTH_PROVIDERS = ['google', 'yandex', 'discord', 'vk'];
const isOAuthProvider = (provider: string): boolean => OAUTH_PROVIDERS.includes(provider);
// Icons for providers not covered by OAuthProviderIcon
function TelegramIcon({ className = 'h-5 w-5' }: { className?: string }) {
return (
);
}
function EmailIcon({ className = 'h-5 w-5' }: { className?: string }) {
return (
);
}
function ProviderIcon({ provider }: { provider: string }) {
switch (provider) {
case 'telegram':
return ;
case 'email':
return ;
default:
return ;
}
}
function LoadingSkeleton() {
return (
{Array.from({ length: 4 }).map((_, i) => (
))}
);
}
export default function ConnectedAccounts() {
const { t } = useTranslation();
const { showToast } = useToast();
const { data, isLoading, refetch } = useQuery({
queryKey: ['linked-providers'],
queryFn: () => authApi.getLinkedProviders(),
});
const unlinkMutation = useMutation({
mutationFn: (provider: string) => authApi.unlinkProvider(provider),
onSuccess: () => {
refetch();
showToast({
type: 'success',
message: t('profile.accounts.unlinkSuccess'),
});
},
onError: () => {
showToast({
type: 'error',
message: t('profile.accounts.unlinkError'),
});
},
});
const canUnlink = (provider: LinkedProvider): boolean => {
if (!provider.linked) return false;
if (!isOAuthProvider(provider.provider)) return false;
const linkedCount = data?.providers.filter((p) => p.linked).length ?? 0;
return linkedCount > 1;
};
const handleLink = async (provider: string) => {
try {
const { authorize_url, state } = await authApi.linkProviderInit(provider);
sessionStorage.setItem('link_oauth_state', state);
sessionStorage.setItem('link_oauth_provider', provider);
window.location.href = authorize_url;
} catch {
showToast({
type: 'error',
message: t('profile.accounts.linkError'),
});
}
};
const handleUnlink = (provider: string) => {
if (window.confirm(t('profile.accounts.unlinkConfirm'))) {
unlinkMutation.mutate(provider);
}
};
return (
{/* Page title */}
{t('profile.accounts.title')}
{t('profile.accounts.subtitle')}
{/* Loading state */}
{isLoading && (
)}
{/* Provider cards */}
{data?.providers.map((provider) => (
{t(`profile.accounts.providers.${provider.provider}`)}
{provider.identifier && (
{provider.identifier}
)}
{provider.linked ? (
<>
{t('profile.accounts.linked')}
{canUnlink(provider) && (
)}
>
) : (
isOAuthProvider(provider.provider) && (
)
)}
))}
);
}