import React, { useState, useRef } from 'react'; import { Account } from '@/types/account'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { Badge } from '@/components/ui/badge'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { MoreVertical, Trash2, RefreshCw } from 'lucide-react'; import { formatDistanceToNow, type Locale } from 'date-fns'; import { enUS, zhCN, ru, vi } from 'date-fns/locale'; import { cn } from '@/lib/utils'; import { useTranslation } from 'react-i18next'; const DEFAULT_GLARE_POSITION = { x: 50, y: 50 }; const DEFAULT_CARD_TRANSFORM = 'perspective(1000px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)'; const DATE_LOCALE_MAP: Record = { en: enUS, 'zh-CN': zhCN, ru: ru, vi: vi, }; interface AccountCardProps { account: Account; isCurrent: boolean; onSwitch: (id: string) => void; onDelete: (id: string) => void; isSwitching?: boolean; isDeleting?: boolean; } export const AccountCard: React.FC = ({ account, isCurrent, onSwitch, onDelete, isSwitching, isDeleting, }) => { const { t, i18n } = useTranslation(); const cardRef = useRef(null); const [cardTransform, setCardTransform] = useState(''); const [glarePosition, setGlarePosition] = useState(DEFAULT_GLARE_POSITION); const initials = account.name ? account.name .split(' ') .map((n) => n[0]) .join('') .toUpperCase() .slice(0, 2) : account.email[0].toUpperCase(); // Handle pointer movement and calculate 3D rotation angles const handleMouseMove = (event: React.MouseEvent) => { if (!cardRef.current) return; const rect = cardRef.current.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; // Calculate pointer position relative to the card center (-1 to 1) const relativeX = (event.clientX - centerX) / (rect.width / 2); const relativeY = (event.clientY - centerY) / (rect.height / 2); // Maximum rotation angle const maxRotation = 15; const rotateX = -relativeY * maxRotation; // Vertical tilt const rotateY = relativeX * maxRotation; // Horizontal tilt setCardTransform( `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.02, 1.02, 1.02)`, ); // Update glare position setGlarePosition({ x: ((event.clientX - rect.left) / rect.width) * 100, y: ((event.clientY - rect.top) / rect.height) * 100, }); }; // Reset when pointer leaves const handleMouseLeave = () => { setCardTransform(DEFAULT_CARD_TRANSFORM); setGlarePosition(DEFAULT_GLARE_POSITION); }; return (
{/* Glare overlay */}
!isCurrent && !isSwitching && !isDeleting && onSwitch(account.id)} >
{initials}

{account.name}

{isCurrent && ( {t('account.current')} )} {isSwitching && ( )}

{account.email}

{t('account.lastUsed', { time: formatDistanceToNow(new Date(account.last_used), { addSuffix: true, locale: DATE_LOCALE_MAP[i18n.language] || enUS, }), })}

{ e.stopPropagation(); onDelete(account.id); }} disabled={isDeleting} > {t('action.deleteBackup')}
); };