149 lines
4.7 KiB
TypeScript
149 lines
4.7 KiB
TypeScript
import { ReactNode } from 'react';
|
|
import Switch from '../form/switch/Switch';
|
|
import Button from '../ui/button/Button';
|
|
import Badge from '../ui/badge/Badge';
|
|
import SiteSetupChecklist from '../sites/SiteSetupChecklist';
|
|
import SiteTypeBadge from '../sites/SiteTypeBadge';
|
|
import { Site } from '../../services/api';
|
|
import { BoxCubeIcon as SettingsIcon, EyeIcon, FileIcon, TrashBinIcon } from '../../icons';
|
|
|
|
interface SiteCardProps {
|
|
site: Site;
|
|
icon: ReactNode;
|
|
onToggle: (siteId: number, enabled: boolean) => void;
|
|
onSettings: (site: Site) => void;
|
|
onDetails: (site: Site) => void;
|
|
onDelete?: (site: Site) => void;
|
|
isToggling?: boolean;
|
|
}
|
|
|
|
export default function SiteCard({
|
|
site,
|
|
icon,
|
|
onToggle,
|
|
onSettings,
|
|
onDetails,
|
|
onDelete,
|
|
isToggling = false,
|
|
}: SiteCardProps) {
|
|
const handleToggle = (enabled: boolean) => {
|
|
onToggle(site.id, enabled);
|
|
};
|
|
|
|
// Setup checklist state derived from site data
|
|
const hasIndustry = !!site.industry || !!site.industry_name;
|
|
const hasSectors = site.active_sectors_count > 0;
|
|
const hasWordPressIntegration = site.has_integration ?? false;
|
|
const hasKeywords = (site.keywords_count ?? 0) > 0;
|
|
|
|
return (
|
|
<article className="rounded-2xl border border-gray-200 bg-white dark:border-gray-800 dark:bg-white/3">
|
|
<div className="relative p-3">
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<div className="inline-flex items-center justify-center text-lg">
|
|
{icon}
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<h3 className="text-lg font-semibold text-gray-800 dark:text-white/90">
|
|
{site.name}
|
|
</h3>
|
|
{site.domain && (
|
|
<p className="text-xs text-gray-400 dark:text-gray-500 truncate">
|
|
{site.domain}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
{site.description && (
|
|
<p className="max-w-xs text-sm text-gray-500 dark:text-gray-400 mb-2 ml-8">
|
|
{site.description}
|
|
</p>
|
|
)}
|
|
<div className="flex items-center gap-1.5 mt-2 mb-2 flex-wrap">
|
|
<SiteTypeBadge hostingType={site.hosting_type} size="xs" />
|
|
{site.industry_name && (
|
|
<Badge variant="soft" color="warning" size="xs">
|
|
{site.industry_name}
|
|
</Badge>
|
|
)}
|
|
<Badge variant="soft" color="neutral" size="xs">
|
|
{site.active_sectors_count} / 5 Sectors
|
|
</Badge>
|
|
</div>
|
|
{/* Setup Checklist - Compact View */}
|
|
<div className="mt-2">
|
|
<SiteSetupChecklist
|
|
siteId={site.id}
|
|
siteName={site.name}
|
|
hasIndustry={hasIndustry}
|
|
hasSectors={hasSectors}
|
|
hasWordPressIntegration={hasWordPressIntegration}
|
|
hasKeywords={hasKeywords}
|
|
compact={true}
|
|
/>
|
|
</div>
|
|
{/* Status badge and toggle in top right */}
|
|
<div className="absolute top-3 right-3 flex items-center gap-2">
|
|
<Switch
|
|
label=""
|
|
checked={site.is_active}
|
|
disabled={isToggling}
|
|
onChange={handleToggle}
|
|
/>
|
|
<div className="flex flex-col items-center gap-1">
|
|
<Badge
|
|
variant="solid"
|
|
color={site.is_active ? "success" : "error"}
|
|
size="xs"
|
|
>
|
|
{site.is_active ? 'Active' : 'Inactive'}
|
|
</Badge>
|
|
<span className="text-xs text-gray-500">Button</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center justify-center border-t border-gray-200 p-2 dark:border-gray-800">
|
|
<div className="flex gap-1.5">
|
|
<Button
|
|
variant="primary"
|
|
tone="brand"
|
|
size="sm"
|
|
onClick={() => onDetails(site)}
|
|
startIcon={<EyeIcon className="w-4 h-4" />}
|
|
>
|
|
Dashboard
|
|
</Button>
|
|
<Button
|
|
variant="secondary"
|
|
tone="neutral"
|
|
size="sm"
|
|
onClick={() => onDetails(site)}
|
|
startIcon={<FileIcon className="w-4 h-4" />}
|
|
>
|
|
Content
|
|
</Button>
|
|
<Button
|
|
variant="outline"
|
|
tone="neutral"
|
|
size="sm"
|
|
onClick={() => onSettings(site)}
|
|
startIcon={<SettingsIcon className="w-4 h-4" />}
|
|
>
|
|
Settings
|
|
</Button>
|
|
<Button
|
|
variant="primary"
|
|
tone="danger"
|
|
size="sm"
|
|
onClick={() => onDelete && onDelete(site)}
|
|
startIcon={<TrashBinIcon className="w-4 h-4" />}
|
|
>
|
|
Delete
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
);
|
|
}
|
|
|