feat: add Review Management module and UI layout fixes
This commit is contained in:
74
src/features/ad-control/components/SurfaceTabs.tsx
Normal file
74
src/features/ad-control/components/SurfaceTabs.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { cn } from '@/lib/utils';
|
||||
import {
|
||||
Sparkles, TrendingUp, Layers, MapPin, Search,
|
||||
} from 'lucide-react';
|
||||
import type { Surface, PlacementItem } from '@/lib/types/ad-control';
|
||||
|
||||
const SURFACE_ICONS: Record<string, React.ElementType> = {
|
||||
Sparkles, TrendingUp, Layers, MapPin, Search,
|
||||
};
|
||||
|
||||
interface SurfaceTabsProps {
|
||||
surfaces: Surface[];
|
||||
activeSurfaceId: string;
|
||||
onSelect: (surfaceId: string) => void;
|
||||
placementCounts: Record<string, number>; // surfaceId → active/scheduled count
|
||||
}
|
||||
|
||||
export function SurfaceTabs({ surfaces, activeSurfaceId, onSelect, placementCounts }: SurfaceTabsProps) {
|
||||
return (
|
||||
<div className="w-64 flex-shrink-0">
|
||||
<div className="sticky top-24 space-y-1.5">
|
||||
<p className="px-3 text-[10px] uppercase tracking-widest text-muted-foreground font-semibold mb-3">
|
||||
Placement Surfaces
|
||||
</p>
|
||||
{surfaces.map((surface) => {
|
||||
const Icon = SURFACE_ICONS[surface.icon] || Sparkles;
|
||||
const count = placementCounts[surface.id] || 0;
|
||||
const isActive = surface.id === activeSurfaceId;
|
||||
|
||||
return (
|
||||
<button
|
||||
key={surface.id}
|
||||
onClick={() => onSelect(surface.id)}
|
||||
className={cn(
|
||||
'w-full flex items-center gap-3 px-3 py-3 rounded-xl text-left transition-all duration-200',
|
||||
isActive
|
||||
? 'bg-primary text-primary-foreground shadow-lg'
|
||||
: 'hover:bg-muted/50 text-foreground'
|
||||
)}
|
||||
>
|
||||
<div className={cn(
|
||||
'h-9 w-9 rounded-lg flex items-center justify-center flex-shrink-0',
|
||||
isActive ? 'bg-white/20' : 'bg-muted'
|
||||
)}>
|
||||
<Icon className="h-4 w-4" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm font-medium truncate">{surface.name.replace('Home ', '').replace(' Events', '')}</p>
|
||||
<p className={cn(
|
||||
'text-[11px]',
|
||||
isActive ? 'text-primary-foreground/70' : 'text-muted-foreground'
|
||||
)}>
|
||||
{surface.layoutType} · {surface.sortBehavior}
|
||||
</p>
|
||||
</div>
|
||||
<Badge
|
||||
variant={isActive ? 'secondary' : 'outline'}
|
||||
className={cn(
|
||||
'text-[10px] h-5 min-w-[36px] justify-center font-mono',
|
||||
isActive && 'bg-white/20 text-primary-foreground border-transparent',
|
||||
count >= surface.maxSlots && !isActive && 'bg-red-50 text-red-600 border-red-200'
|
||||
)}
|
||||
>
|
||||
{count}/{surface.maxSlots}
|
||||
</Badge>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user