Lin / frontend /src /components /LinkedInAccount /LinkedInAccountCard.jsx
Zelyanoth's picture
fff
25f22bf
raw
history blame
7.28 kB
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { deleteLinkedInAccount, setPrimaryLinkedInAccount } from '../../store/reducers/linkedinAccountsSlice';
const LinkedInAccountCard = ({ account, onRefresh }) => {
const dispatch = useDispatch();
const { deletingAccount, settingPrimary } = useSelector(state => state.linkedinAccounts);
const handleDelete = async () => {
if (window.confirm(`Are you sure you want to disconnect ${account.account_name}?`)) {
try {
await dispatch(deleteLinkedInAccount(account.id)).unwrap();
onRefresh();
} catch (error) {
console.error('Failed to delete account:', error);
}
}
};
const handleSetPrimary = async () => {
try {
await dispatch(setPrimaryLinkedInAccount(account.id)).unwrap();
onRefresh();
} catch (error) {
console.error('Failed to set primary account:', error);
}
};
const isDeleting = deletingAccount === account.id;
const isSettingPrimary = settingPrimary === account.id;
return (
<div className="linkedin-account-card bg-white/90 backdrop-blur-sm rounded-xl p-6 border border-gray-200/50 shadow-sm hover:shadow-lg transition-all duration-300 transform hover:scale-[1.02] animate-slide-up">
<div className="account-header flex items-start space-x-4">
{account.picture ? (
<img
src={account.picture}
alt={`${account.given_name} ${account.family_name}`}
className="w-16 h-16 rounded-full object-cover border-2 border-gray-200 shadow-sm"
/>
) : (
<div className="w-16 h-16 rounded-full bg-gradient-to-br from-blue-100 to-blue-200 flex items-center justify-center border-2 border-gray-200 shadow-sm">
<svg className="w-8 h-8 text-blue-600" fill="currentColor" viewBox="0 0 24 24">
<path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14m-.5 15.5v-5.3a3.26 3.26 0 0 0-3.26-3.26c-.85 0-1.84.52-2.32 1.3v-1.11h-2.79v8.37h2.79v-4.93c0-.77.62-1.4 1.39-1.4a1.4 1.4 0 0 1 1.4 1.4v4.93h2.79M6.88 8.56a1.68 1.68 0 0 0 1.68-1.68c0-.93-.75-1.69-1.68-1.69a1.69 1.69 0 0 0-1.69 1.69c0 .93.76 1.68 1.69 1.68m1.39 9.94v-8.37H5.5v8.37h2.77z"/>
</svg>
</div>
)}
<div className="account-info flex-1 min-w-0">
<div className="flex items-center space-x-2 mb-1">
<h3 className="account-name text-lg font-semibold text-gray-900 truncate">
{account.given_name} {account.family_name}
</h3>
{account.is_primary && (
<span className="primary-badge inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gradient-to-r from-purple-500 to-purple-600 text-white shadow-sm">
<svg className="w-3 h-3 mr-1" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
</svg>
Primary
</span>
)}
</div>
<p className="account-handle text-sm text-gray-600 mb-3">@{account.sub}</p>
{/* Account Status */}
<div className="flex items-center space-x-4 text-xs text-gray-500">
<div className="flex items-center space-x-1">
<div className="w-2 h-2 bg-green-400 rounded-full"></div>
<span>Connected</span>
</div>
<div className="flex items-center space-x-1">
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>Active</span>
</div>
</div>
</div>
</div>
<div className="account-actions flex flex-col sm:flex-row gap-3 mt-6 pt-6 border-t border-gray-200">
<button
onClick={handleSetPrimary}
disabled={account.is_primary || isSettingPrimary}
className={`flex-1 font-medium py-2 px-4 rounded-lg transition-all duration-200 ${
account.is_primary
? 'bg-gray-100 text-gray-500 cursor-not-allowed'
: 'bg-gradient-to-r from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-700 text-white shadow-sm hover:shadow-md disabled:from-blue-300 disabled:to-blue-400 disabled:cursor-not-allowed'
}`}
>
{isSettingPrimary ? (
<>
<svg className="animate-spin w-4 h-4 inline-block mr-2" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Setting...
</>
) : account.is_primary ? (
<>
<svg className="w-4 h-4 inline-block mr-2" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
</svg>
Primary
</>
) : (
<>
<svg className="w-4 h-4 inline-block mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
Set Primary
</>
)}
</button>
<button
onClick={handleDelete}
disabled={isDeleting}
className="flex-1 font-medium py-2 px-4 bg-gradient-to-r from-red-500 to-red-600 hover:from-red-600 hover:to-red-700 text-white rounded-lg transition-all duration-200 shadow-sm hover:shadow-md disabled:from-red-300 disabled:to-red-400 disabled:cursor-not-allowed"
>
{isDeleting ? (
<>
<svg className="animate-spin w-4 h-4 inline-block mr-2" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Disconnecting...
</>
) : (
<>
<svg className="w-4 h-4 inline-block mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
Disconnect
</>
)}
</button>
</div>
</div>
);
};
export default LinkedInAccountCard;