Spaces:
Running
Running
| interface Module { | |
| name: string; | |
| icon: string; | |
| color: "yellow" | "green" | "teal" | "cyan"; | |
| tagline: string; | |
| capabilities: string[]; | |
| } | |
| interface FeatureGridData { | |
| title: string; | |
| subtitle: string; | |
| audience: "manufacturers" | "retailers"; | |
| modules: Module[]; | |
| } | |
| const COLOR_MAP = { | |
| yellow: { accent: "#C7D92F", bg: "#C7D92F15" }, | |
| green: { accent: "#8FD15E", bg: "#8FD15E15" }, | |
| teal: { accent: "#47C3A6", bg: "#47C3A615" }, | |
| cyan: { accent: "#14B7CC", bg: "#14B7CC15" }, | |
| }; | |
| export default function FeatureGrid({ data }: { data: FeatureGridData }) { | |
| return ( | |
| <div className="mt-3 rounded-xl border border-[#E2E8F0] overflow-hidden shadow-sm"> | |
| {/* Header */} | |
| <div className="bg-white px-5 py-4 border-b border-[#E2E8F0]"> | |
| <div className="flex items-center justify-between"> | |
| <div> | |
| <div className="flex items-center gap-2 mb-1"> | |
| <div className="w-1 h-4 rounded-full bg-brand-gradient-h" /> | |
| <h3 className="text-sm font-semibold text-[#1A202C]">{data.title}</h3> | |
| </div> | |
| <p className="text-xs text-[#64748B] ml-3">{data.subtitle}</p> | |
| </div> | |
| <span className="text-[10px] font-medium text-[#47C3A6] border border-[#47C3A630] bg-[#47C3A610] px-2 py-1 rounded uppercase tracking-wider"> | |
| {data.audience} | |
| </span> | |
| </div> | |
| </div> | |
| {/* Module grid */} | |
| <div className="grid grid-cols-1 sm:grid-cols-2 gap-px bg-[#E2E8F0]"> | |
| {data.modules.map((mod) => { | |
| const { accent, bg } = COLOR_MAP[mod.color]; | |
| return ( | |
| <div key={mod.name} className="bg-white p-4 hover:bg-[#F8FAFC] transition-colors"> | |
| <div className="flex items-center gap-3 mb-3"> | |
| <div className="w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0" style={{ background: bg }}> | |
| <ModuleIcon name={mod.icon} color={accent} /> | |
| </div> | |
| <div> | |
| <p className="text-sm font-semibold text-[#1A202C]">{mod.name}</p> | |
| <p className="text-[10px] leading-snug mt-0.5" style={{ color: accent }}>{mod.tagline}</p> | |
| </div> | |
| </div> | |
| <ul className="space-y-1.5"> | |
| {mod.capabilities.map((cap) => ( | |
| <li key={cap} className="flex items-start gap-2"> | |
| <div className="w-1 h-1 rounded-full mt-1.5 flex-shrink-0" style={{ background: accent }} /> | |
| <span className="text-xs text-[#64748B] leading-snug">{cap}</span> | |
| </li> | |
| ))} | |
| </ul> | |
| </div> | |
| ); | |
| })} | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function ModuleIcon({ name, color }: { name: string; color: string }) { | |
| const props = { width: 16, height: 16, viewBox: "0 0 16 16", fill: "none", stroke: color, strokeWidth: 1.5, strokeLinecap: "round" as const }; | |
| switch (name) { | |
| case "negotiations": | |
| return <svg {...props}><path d="M2 10l4-4 3 3 5-6" /><path d="M11 4h3v3" /></svg>; | |
| case "promotions": | |
| return <svg {...props}><path d="M3 13L8 3l5 10" /><path d="M5 9h6" /></svg>; | |
| case "assortment": | |
| return <svg {...props}><rect x="1.5" y="1.5" width="5" height="5" rx="0.5" /><rect x="9.5" y="1.5" width="5" height="5" rx="0.5" /><rect x="1.5" y="9.5" width="5" height="5" rx="0.5" /><rect x="9.5" y="9.5" width="5" height="5" rx="0.5" /></svg>; | |
| case "finances": | |
| return <svg {...props}><circle cx="8" cy="8" r="6.5" /><path d="M8 4.5v7M6 6.5c0-1.1.9-2 2-2s2 .9 2 2-.9 2-2 2-2 .9-2 2 .9 2 2 2 2-.9 2-2" /></svg>; | |
| case "collaborative": | |
| return <svg {...props}><circle cx="8" cy="8" r="2" /><circle cx="2.5" cy="4" r="1.5" /><circle cx="13.5" cy="4" r="1.5" /><circle cx="8" cy="13.5" r="1.5" /><path d="M4 4.5L6.5 7M11.5 4.5L9.5 7M8 10v2" /></svg>; | |
| case "tenders": | |
| return <svg {...props}><path d="M10 1.5H3.5A1.5 1.5 0 002 3v10a1.5 1.5 0 001.5 1.5h9A1.5 1.5 0 0014 13V5.5L10 1.5z" /><path d="M10 1.5V5.5H14M5 8.5h6M5 11h4" /></svg>; | |
| default: | |
| return <svg {...props}><circle cx="8" cy="8" r="5" /></svg>; | |
| } | |
| } | |