import { BracesIcon, HeadingIcon, ImageIcon, LayoutGridIcon, Link2Icon, MapIcon, MilestoneIcon, RouteIcon, SearchXIcon, StoreIcon, UsersIcon, ZapIcon, type LucideIcon, } from 'lucide-react'; import { Link } from 'react-router-dom'; import { classNames } from '../../lib/utils'; import type { ISeoModule } from '../../service/seo/seo.interface'; import { Badge } from '../ui/badge'; import { Button } from '../ui/button'; import { Card, CardContent, CardFooter } from '../ui/card'; import { Switch } from '../ui/switch'; /** What each module does, in the words a merchant reads on its card. */ export const MODULE_COPY: Record = { head: 'Prints the title, meta description, robots, canonical and Open Graph tags of every page. Steps aside on its own while another SEO plugin runs.', schema: 'Structured data (JSON-LD) for the site, articles, products and breadcrumbs, so pages qualify for rich results.', breadcrumbs: 'The breadcrumb trail as a shortcode, block or WooCommerce replacement. The BreadcrumbList in the schema comes with the Schema module either way.', sitemap: 'The XML sitemap at /sitemap_index.xml: one file per post type, taxonomy and author, refreshed on every publish.', links: 'Counts internal, external and incoming links per post and finds pages no other page links to.', redirects: 'Redirect rules (301, 302, 307, 410, 451) in their own table, with automatic redirects when a slug changes.', monitor_404: 'Logs every URL that answers 404, so it can be redirected. Keeps its own table.', image_seo: 'Fills missing alt and title attributes from a template when images are printed.', local_seo: 'Business address, opening hours and LocalBusiness schema; locations for multi-store sites.', indexnow: 'Pings IndexNow (Bing, Yandex and others) when a page is published, updated or deleted.', role_manager: 'Which roles may change the SEO settings, edit the SEO fields, manage redirects and read the 404 log.', }; const ICONS: Record = { head: HeadingIcon, schema: BracesIcon, breadcrumbs: MilestoneIcon, sitemap: MapIcon, links: Link2Icon, redirects: RouteIcon, monitor_404: SearchXIcon, image_seo: ImageIcon, local_seo: StoreIcon, indexnow: ZapIcon, role_manager: UsersIcon, }; /** The tint of each module's icon well, one colour per module. */ const ACCENTS: Record = { head: 'bg-brand/10 text-brand', schema: 'bg-violet-500/10 text-violet-600 dark:text-violet-400', breadcrumbs: 'bg-amber-500/10 text-amber-600 dark:text-amber-400', sitemap: 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400', links: 'bg-sky-500/10 text-sky-600 dark:text-sky-400', redirects: 'bg-orange-500/10 text-orange-600 dark:text-orange-400', monitor_404: 'bg-red-500/10 text-red-600 dark:text-red-400', image_seo: 'bg-cyan-500/10 text-cyan-600 dark:text-cyan-400', local_seo: 'bg-lime-500/10 text-lime-700 dark:text-lime-400', indexnow: 'bg-fuchsia-500/10 text-fuchsia-600 dark:text-fuchsia-400', role_manager: 'bg-slate-500/10 text-slate-600 dark:text-slate-400', }; /** Where a module's options live, for the Settings button on its card. */ const SETTINGS_LINKS: Record = { head: '/seo/titles', schema: '/seo/titles?section=local', breadcrumbs: '/seo/general?section=breadcrumbs', sitemap: '/seo/sitemap', links: '/seo/links', indexnow: '/seo/sitemap?section=indexnow', redirects: '/seo/redirects', monitor_404: '/seo/404', image_seo: '/seo/general?section=images', local_seo: '/seo/local', role_manager: '/seo/roles', }; /** * The module cards of the dashboard, laid out the way Rank Math lays out * its modules: the icon in a tinted well, the name and what the module * does under it, and a footer with the way to its settings and its switch. */ export const ModulesGrid = ({ modules, busy, onToggle, }: { modules: Record; busy: string | null; onToggle: (slug: string, active: boolean) => void; }): JSX.Element => (
{Object.entries(modules).map(([slug, module]) => { const Icon = ICONS[slug] ?? LayoutGridIcon; const link = SETTINGS_LINKS[slug]; return (

{module.label}

{!module.default && ( Off by default )}

{MODULE_COPY[slug]}

{link ? ( ) : ( {module.active ? 'On' : 'Off'} )} onToggle(slug, next)} />
); })}
);