phase 1 complete

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-05 05:06:30 +00:00
parent de0e42cca8
commit abc6c011ea
4 changed files with 58 additions and 72 deletions

View File

@@ -28,22 +28,6 @@ export default function SiteCard({
onToggle(site.id, enabled); onToggle(site.id, enabled);
}; };
const getStatusColor = () => {
if (site.is_active) {
return 'bg-success-500 dark:bg-success-600';
}
return 'bg-gray-400 dark:bg-gray-500';
};
const getStatusText = () => {
if (site.is_active) {
return { text: 'Active', color: 'text-success-600 dark:text-success-400', bold: true };
}
return { text: 'Inactive', color: 'text-gray-400 dark:text-gray-500', bold: false };
};
const statusText = getStatusText();
// Setup checklist state derived from site data // Setup checklist state derived from site data
const hasIndustry = !!site.industry || !!site.industry_name; const hasIndustry = !!site.industry || !!site.industry_name;
const hasSectors = site.active_sectors_count > 0; const hasSectors = site.active_sectors_count > 0;
@@ -52,26 +36,28 @@ export default function SiteCard({
return ( return (
<article className="rounded-2xl border border-gray-200 bg-white dark:border-gray-800 dark:bg-white/3"> <article className="rounded-2xl border border-gray-200 bg-white dark:border-gray-800 dark:bg-white/3">
<div className="relative p-3 pb-5"> <div className="relative p-3">
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<div className="inline-flex items-center justify-center"> <div className="inline-flex items-center justify-center text-lg">
{icon} {icon}
</div> </div>
<h3 className="text-lg font-semibold text-gray-800 dark:text-white/90"> <div className="flex-1 min-w-0">
{site.name} <h3 className="text-lg font-semibold text-gray-800 dark:text-white/90">
</h3> {site.name}
</h3>
{site.domain && (
<p className="text-xs text-gray-400 dark:text-gray-500 truncate">
{site.domain}
</p>
)}
</div>
</div> </div>
{site.domain && (
<p className="text-xs text-gray-400 dark:text-gray-500 mb-2 ml-8">
{site.domain}
</p>
)}
{site.description && ( {site.description && (
<p className="max-w-xs text-sm text-gray-500 dark:text-gray-400 mb-2"> <p className="max-w-xs text-sm text-gray-500 dark:text-gray-400 mb-2 ml-8">
{site.description} {site.description}
</p> </p>
)} )}
<div className="flex items-center gap-1.5 mb-2 flex-wrap"> <div className="flex items-center gap-1.5 mt-2 mb-2 flex-wrap">
<SiteTypeBadge hostingType={site.hosting_type} size="xs" /> <SiteTypeBadge hostingType={site.hosting_type} size="xs" />
{site.industry_name && ( {site.industry_name && (
<Badge variant="soft" color="warning" size="xs"> <Badge variant="soft" color="warning" size="xs">
@@ -81,11 +67,6 @@ export default function SiteCard({
<Badge variant="soft" color="neutral" size="xs"> <Badge variant="soft" color="neutral" size="xs">
{site.active_sectors_count} / 5 Sectors {site.active_sectors_count} / 5 Sectors
</Badge> </Badge>
{site.status && (
<Badge variant={site.is_active ? 'solid' : 'soft'} color={site.status === 'active' ? 'success' : 'neutral'} size="xs">
{site.status}
</Badge>
)}
</div> </div>
{/* Setup Checklist - Compact View */} {/* Setup Checklist - Compact View */}
<div className="mt-2"> <div className="mt-2">
@@ -99,19 +80,25 @@ export default function SiteCard({
compact={true} compact={true}
/> />
</div> </div>
{/* Status Text and Circle - Same row */} {/* Status badge and toggle in top right */}
<div className="absolute top-3 right-3 flex items-center gap-2"> <div className="absolute top-3 right-3 flex items-center gap-2">
<span className={`text-sm ${statusText.color} ${statusText.bold ? 'font-bold' : ''} transition-colors duration-200`}> <Switch
{statusText.text} label=""
</span> checked={site.is_active}
<div disabled={isToggling}
className={`w-[20px] h-[20px] rounded-full ${getStatusColor()} transition-colors duration-200`} onChange={handleToggle}
title={site.is_active ? 'Active site' : 'Inactive site'}
/> />
<Badge
variant="solid"
color={site.is_active ? "success" : "error"}
size="xs"
>
{site.is_active ? 'Active' : 'Inactive'}
</Badge>
</div> </div>
</div> </div>
<div className="flex items-center justify-between border-t border-gray-200 p-2 dark:border-gray-800"> <div className="flex items-center justify-center border-t border-gray-200 p-2 dark:border-gray-800">
<div className="flex gap-1.5 flex-1"> <div className="flex gap-1.5">
<Button <Button
variant="primary" variant="primary"
tone="brand" tone="brand"
@@ -140,12 +127,6 @@ export default function SiteCard({
Settings Settings
</Button> </Button>
</div> </div>
<Switch
label=""
checked={site.is_active}
disabled={isToggling}
onChange={handleToggle}
/>
</div> </div>
</article> </article>
); );

View File

@@ -105,9 +105,9 @@ const toneStyles: Record<
}; };
const sizeClasses: Record<BadgeSize, string> = { const sizeClasses: Record<BadgeSize, string> = {
xs: "min-h-[20px] px-2.5 py-1 leading-[1.4]", xs: "min-h-[18px] px-1.5 py-0.5 text-xs leading-tight",
sm: "min-h-[24px] px-3 py-1 leading-[1.4]", sm: "min-h-[22px] px-2 py-0.5 text-xs leading-tight",
md: "min-h-[28px] px-3.5 py-1.5 leading-[1.4]", md: "min-h-[26px] px-3 py-1 text-sm leading-tight",
}; };
const Badge: React.FC<BadgeProps> = ({ const Badge: React.FC<BadgeProps> = ({

View File

@@ -3,7 +3,7 @@ import clsx from "clsx";
import Button from "../button/Button"; import Button from "../button/Button";
type CardVariant = "surface" | "panel" | "frosted" | "borderless" | "gradient"; type CardVariant = "surface" | "panel" | "frosted" | "borderless" | "gradient";
type CardPadding = "none" | "sm" | "md" | "lg"; type CardPadding = "none" | "xs" | "sm" | "md" | "lg";
type CardShadow = "none" | "sm" | "md"; type CardShadow = "none" | "sm" | "md";
interface CardProps { interface CardProps {
@@ -37,6 +37,7 @@ export const Card: React.FC<CardProps> = ({
const paddingClasses: Record<CardPadding, string> = { const paddingClasses: Record<CardPadding, string> = {
none: "p-0", none: "p-0",
xs: "p-3",
sm: "p-4 sm:p-5", sm: "p-4 sm:p-5",
md: "p-5 sm:p-6", md: "p-5 sm:p-6",
lg: "p-6 sm:p-8", lg: "p-6 sm:p-8",

View File

@@ -393,37 +393,41 @@ export default function SiteList() {
const renderGridView = () => ( const renderGridView = () => (
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 xl:grid-cols-3"> <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 xl:grid-cols-3">
{filteredSites.map((site) => ( {filteredSites.map((site) => (
<Card key={site.id} className="rounded-xl border-2 border-gray-200 bg-white dark:border-gray-800 dark:bg-white/3 hover:border-[var(--color-primary)] hover:shadow-lg transition-all"> <Card key={site.id} padding="xs" className="rounded-xl border-2 border-gray-200 bg-white dark:border-gray-800 dark:bg-white/3 hover:border-[var(--color-primary)] hover:shadow-lg transition-all">
<div className="relative p-4 pb-6"> <div className="relative">
<div className="flex items-center gap-3 mb-4"> <div className="flex items-center gap-2 mb-1">
<div className="size-6 rounded-lg bg-gradient-to-br from-[var(--color-primary)] to-[var(--color-primary-dark)] flex items-center justify-center text-white shadow-md flex-shrink-0"> <div className="size-8 rounded-lg bg-gradient-to-br from-[var(--color-primary)] to-[var(--color-primary-dark)] flex items-center justify-center text-white shadow-md flex-shrink-0">
<svg className="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg> </svg>
</div> </div>
<h3 className="text-lg font-semibold text-gray-800 dark:text-white/90"> <div className="flex-1 min-w-0">
{site.name} <h3 className="text-lg font-semibold text-gray-800 dark:text-white/90">
</h3> {site.name}
</h3>
{site.domain && (
<p className="text-xs text-gray-400 dark:text-gray-500 truncate">
{site.domain}
</p>
)}
</div>
</div> </div>
<p className="max-w-xs text-sm text-gray-500 dark:text-gray-400 mb-2"> {site.description && (
{site.description || 'No description'} <p className="max-w-xs text-sm text-gray-500 dark:text-gray-400 mb-2 ml-10">
</p> {site.description}
{site.domain && (
<p className="text-xs text-gray-400 dark:text-gray-500 mb-2">
{site.domain}
</p> </p>
)} )}
{/* Centered badges with uniform size */} {/* Centered badges with smaller size */}
<div className="flex items-center justify-center gap-2 mb-2 flex-wrap"> <div className="flex items-center justify-center gap-1.5 mt-3 mb-2 flex-wrap">
<SiteTypeBadge hostingType={site.hosting_type} size="sm" /> <SiteTypeBadge hostingType={site.hosting_type} size="xs" />
{site.industry_name && ( {site.industry_name && (
<Badge variant="soft" color="warning" size="sm"> <Badge variant="soft" color="warning" size="xs">
{site.industry_name} {site.industry_name}
</Badge> </Badge>
)} )}
</div> </div>
{/* Status badge and toggle in top right */} {/* Status badge and toggle in top right */}
<div className="absolute top-4 right-4 flex items-center gap-3"> <div className="absolute top-0 right-0 flex items-center gap-2">
<Switch <Switch
checked={site.is_active} checked={site.is_active}
onChange={(enabled) => handleToggle(site.id, enabled)} onChange={(enabled) => handleToggle(site.id, enabled)}
@@ -439,7 +443,7 @@ export default function SiteList() {
</div> </div>
</div> </div>
{/* Centered button row */} {/* Centered button row */}
<div className="border-t border-gray-200 p-3 dark:border-gray-800"> <div className="border-t border-gray-200 mt-3 -mx-3 -mb-3 px-3 py-2 dark:border-gray-800">
<div className="flex justify-center gap-2"> <div className="flex justify-center gap-2">
<Button <Button
onClick={() => navigate(`/sites/${site.id}`)} onClick={() => navigate(`/sites/${site.id}`)}