| import React, { useState, useEffect } from 'react'; |
| import { useDispatch, useSelector } from 'react-redux'; |
| import { fetchAccounts } from '../store/reducers/accountsSlice'; |
| import { fetchLinkedInAccounts, deleteLinkedInAccount, setPrimaryLinkedInAccount, clearLinkedInError } from '../store/reducers/linkedinAccountsSlice'; |
| import LinkedInAccountsManager from '../components/LinkedInAccount/LinkedInAccountsManager'; |
| import { testApiStructure, testServiceBehavior } from '../debug/testApi'; |
|
|
| const Accounts = () => { |
| const dispatch = useDispatch(); |
| const { items: accounts, loading, error } = useSelector(state => state.accounts); |
| const { linkedinAccounts, loading: linkedinLoading, error: linkedinError } = useSelector(state => state.linkedinAccounts); |
| |
| useEffect(() => { |
| |
| dispatch(fetchAccounts()); |
| |
| |
| dispatch(fetchLinkedInAccounts()); |
| dispatch(clearLinkedInError()); |
| |
| |
| testApiStructure(); |
| testServiceBehavior(); |
| }, [dispatch]); |
| |
| return ( |
| <div className="accounts-page min-h-screen bg-gradient-to-br from-gray-50 via-white to-gray-50 p-3 sm:p-4 lg:p-6"> |
| <div className="max-w-7xl mx-auto"> |
| {/* Header Section */} |
| <div className="accounts-header mb-6 sm:mb-8 lg:mb-10 animate-slide-up"> |
| <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-3 sm:mb-4 gap-4"> |
| <div className="flex-1"> |
| <h1 className="accounts-title text-2xl sm:text-3xl lg:text-4xl font-bold bg-gradient-to-r from-gray-900 via-gray-800 to-gray-900 bg-clip-text text-transparent mb-1 sm:mb-2"> |
| Account Management |
| </h1> |
| <p className="accounts-subtitle text-base sm:text-lg text-gray-600 font-medium max-w-2xl sm:max-w-3xl"> |
| Manage your social media accounts and connections for seamless content distribution |
| </p> |
| </div> |
| <div className="hidden sm:block lg:block"> |
| <div className="w-12 h-12 sm:w-16 sm:h-16 bg-gradient-to-br from-blue-500 to-purple-600 rounded-2xl shadow-lg flex items-center justify-center"> |
| <svg className="w-6 h-6 sm:w-8 sm:h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" /> |
| </svg> |
| </div> |
| </div> |
| </div> |
| |
| {/* Stats Cards */} |
| <div className="grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 mt-6 sm:mt-8"> |
| <div className="bg-white/80 backdrop-blur-sm rounded-xl p-3 sm:p-4 border border-gray-200/50 shadow-sm hover:shadow-md transition-all duration-300"> |
| <div className="flex items-center justify-between"> |
| <div> |
| <p className="text-xs sm:text-sm font-medium text-gray-600">Total Accounts</p> |
| <p className="text-lg sm:text-2xl font-bold text-gray-900">{accounts.length}</p> |
| </div> |
| <div className="w-8 h-8 sm:w-10 sm:h-10 bg-blue-100 rounded-lg flex items-center justify-center"> |
| <svg className="w-4 h-4 sm:w-5 sm:h-5 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" /> |
| </svg> |
| </div> |
| </div> |
| </div> |
| |
| <div className="bg-white/80 backdrop-blur-sm rounded-xl p-3 sm:p-4 border border-gray-200/50 shadow-sm hover:shadow-md transition-all duration-300"> |
| <div className="flex items-center justify-between"> |
| <div> |
| <p className="text-xs sm:text-sm font-medium text-gray-600">Active</p> |
| <p className="text-lg sm:text-2xl font-bold text-gray-900">{accounts.filter(account => account.token).length}</p> |
| </div> |
| <div className="w-8 h-8 sm:w-10 sm:h-10 bg-green-100 rounded-lg flex items-center justify-center"> |
| <svg className="w-4 h-4 sm:w-5 sm:h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /> |
| </svg> |
| </div> |
| </div> |
| </div> |
| |
| <div className="bg-white/80 backdrop-blur-sm rounded-xl p-3 sm:p-4 border border-gray-200/50 shadow-sm hover:shadow-md transition-all duration-300"> |
| <div className="flex items-center justify-between"> |
| <div> |
| <p className="text-xs sm:text-sm font-medium text-gray-600">Primary</p> |
| <p className="text-lg sm:text-2xl font-bold text-gray-900">{accounts.filter(account => account.is_primary).length}</p> |
| </div> |
| <div className="w-8 h-8 sm:w-10 sm:h-10 bg-purple-100 rounded-lg flex items-center justify-center"> |
| <svg className="w-4 h-4 sm:w-5 sm:h-5 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" /> |
| </svg> |
| </div> |
| </div> |
| </div> |
| |
| <div className="bg-white/80 backdrop-blur-sm rounded-xl p-3 sm:p-4 border border-gray-200/50 shadow-sm hover:shadow-md transition-all duration-300"> |
| <div className="flex items-center justify-between"> |
| <div> |
| <p className="text-xs sm:text-sm font-medium text-gray-600">Connected</p> |
| <p className="text-lg sm:text-2xl font-bold text-gray-900"> |
| {accounts.length > 0 ? Math.round((accounts.filter(account => account.token).length / accounts.length) * 100) : 0}% |
| </p> |
| </div> |
| <div className="w-8 h-8 sm:w-10 sm:h-10 bg-orange-100 rounded-lg flex items-center justify-center"> |
| <svg className="w-4 h-4 sm:w-5 sm:h-5 text-orange-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" /> |
| </svg> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| {/* Error Display */} |
| {(error || linkedinError) && ( |
| <div className="mb-6 sm:mb-8 animate-fade-in"> |
| <div className="bg-red-50 border border-red-200 rounded-xl p-3 sm:p-4 flex items-start space-x-3"> |
| <div className="flex-shrink-0"> |
| <svg className="w-4 h-4 sm:w-5 sm:h-5 text-red-400" fill="currentColor" viewBox="0 0 20 20"> |
| <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" /> |
| </svg> |
| </div> |
| <div className="flex-1"> |
| <p className="text-xs sm:text-sm font-medium text-red-800"> |
| {error || linkedinError} |
| </p> |
| </div> |
| </div> |
| </div> |
| )} |
| |
| <div className="accounts-content"> |
| <LinkedInAccountsManager |
| accounts={accounts.length > 0 ? accounts : linkedinAccounts} |
| loading={loading || linkedinLoading} |
| /> |
| </div> |
| </div> |
| </div> |
| ); |
| }; |
|
|
| export default Accounts; |