Spaces:
Sleeping
Sleeping
import { Spin } from 'antd'; | |
import { useCallback, useEffect } from 'react'; | |
import { | |
CheckCircleOutlined, | |
CloseCircleOutlined, | |
GlobalOutlined, | |
DoubleRightOutlined, | |
SyncOutlined | |
} from '@ant-design/icons'; | |
import { useUploadStore } from '@/store/useUploadStore'; | |
import { useLoadInfoStore } from '@/store/useLoadInfoStore'; | |
import classNames from 'classnames'; | |
import LoadMore from '../LoadMore'; | |
const colorClasses = [ | |
'bg-red-500', | |
'bg-pink-500', | |
'bg-purple-500', | |
'bg-indigo-500', | |
'bg-blue-500', | |
'bg-cyan-500', | |
'bg-teal-500', | |
'bg-green-500', | |
'bg-lime-500', | |
'bg-yellow-500', | |
'bg-amber-500', | |
'bg-orange-500' | |
]; | |
const NetWorkMemberList = () => { | |
const loading = useUploadStore((state) => state.loading); | |
const total = useUploadStore((state) => state.total); | |
const uploads = useUploadStore((state) => state.uploads); | |
const fetchUploadList = useUploadStore((state) => state.fetchUploadList); | |
const loadInfo = useLoadInfoStore((state) => state.loadInfo); | |
useEffect(() => { | |
fetchUploadList(); | |
}, []); | |
const getRandomColor = (str: string) => { | |
if (!str) return 'bg-gray-400'; | |
let hash = 0; | |
for (let i = 0; i < str.length; i++) { | |
hash = str.charCodeAt(i) + ((hash << 5) - hash); | |
} | |
const index = Math.abs(hash) % colorClasses.length; | |
return colorClasses[index]; | |
}; | |
const renderUploadList = useCallback(() => { | |
return uploads?.map((upload) => { | |
const uploadStatus = | |
upload.instance_id == loadInfo?.instance_id ? loadInfo?.status : upload?.status; | |
return ( | |
<div | |
key={upload?.instance_id} | |
className={classNames( | |
'flex items-center justify-between px-4 py-3 rounded-lg shadow-sm transition-all duration-200 hover:shadow-md border ', | |
uploadStatus === 'online' ? 'bg-blue-50 border-blue-100' : 'bg-gray-50 border-gray-200', | |
'group' | |
)} | |
onClick={() => { | |
window.open( | |
`https://app.secondme.io/${upload.upload_name}/${upload.instance_id}`, | |
'_blank' | |
); | |
}} | |
> | |
<div className="flex items-center gap-3 w-full"> | |
<div | |
className={`flex-shrink-0 w-10 h-10 rounded-full flex items-center justify-center text-white ${getRandomColor(upload?.upload_name)}`} | |
> | |
{upload?.upload_name ? upload?.upload_name.charAt(0).toUpperCase() : '?'} | |
</div> | |
<div> | |
<div className={`font-medium text-gray-700`}>{upload?.upload_name || 'Unknown'}</div> | |
<div className="flex items-center gap-2 mt-1"> | |
<div | |
className={`px-2 py-0.5 text-xs rounded-full flex items-center gap-1.5 ${ | |
uploadStatus === 'offline' | |
? 'bg-gray-100 text-gray-800' | |
: uploadStatus === 'registered' | |
? 'bg-yellow-100 text-yellow-800' | |
: 'bg-green-100 text-green-800' | |
}`} | |
> | |
{uploadStatus === 'offline' ? ( | |
<CloseCircleOutlined className="text-gray-500" /> | |
) : uploadStatus === 'registered' ? ( | |
<SyncOutlined className="text-yellow-600" spin /> | |
) : ( | |
<CheckCircleOutlined className="text-green-600" /> | |
)} | |
{uploadStatus || 'Unknown'} | |
</div> | |
</div> | |
</div> | |
</div> | |
<DoubleRightOutlined | |
className="text-[12px] !text-blue-500 transition-colors" | |
style={{ fontSize: '12px' }} | |
/> | |
</div> | |
); | |
}); | |
}, [uploads, loadInfo]); | |
if (loading && uploads.length == 0) { | |
return <Spin className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2" />; | |
} | |
if (uploads.length === 0) { | |
return ( | |
<div className="text-gray-500 text-sm p-8 bg-gray-50 rounded-lg border border-gray-200 text-center shadow-sm"> | |
<div className="flex justify-center mb-4"> | |
<div className="w-16 h-16 bg-gray-200 rounded-full flex items-center justify-center text-gray-400"> | |
<GlobalOutlined style={{ fontSize: '24px' }} /> | |
</div> | |
</div> | |
<p className="text-gray-600 font-medium">Network is Empty</p> | |
<p className="text-sm text-gray-400 mt-2">Be the first to join the Second Me network!</p> | |
</div> | |
); | |
} | |
return ( | |
<div className="flex flex-col h-full gap-2"> | |
{renderUploadList()} | |
{total !== uploads.length && ( | |
<LoadMore | |
className="my-5" | |
loadMore={() => fetchUploadList(false)} | |
scrollContainerId="#netWorkMemberScrollList" | |
/> | |
)} | |
</div> | |
); | |
}; | |
export default NetWorkMemberList; | |