# Templates React - Documentation FRD

> **Usage:** Templates pour générer la documentation HTML (React) des specs fonctionnelles
> **Output:** `web/smartstack-web/src/pages/docs/business/{app}/{module}/`
> **Context7:** Utiliser pour génération de code React à jour

---

## RÈGLE CONTEXT7 (OBLIGATOIRE)

```
╔══════════════════════════════════════════════════════════════════════════════╗
║  GÉNÉRATION REACT AVEC CONTEXT7                                              ║
╠══════════════════════════════════════════════════════════════════════════════╣
║                                                                              ║
║  TOUJOURS utiliser Context7 pour la génération de composants React:          ║
║                                                                              ║
║  Prompt pattern:                                                             ║
║  "use context7 with /facebook/react and /i18next/react-i18next              ║
║   to generate {component} following SmartStack patterns"                     ║
║                                                                              ║
║  Libraries à référencer:                                                     ║
║  • /facebook/react - React 19 patterns                                       ║
║  • /i18next/react-i18next - Internationalization                             ║
║  • /remix-run/react-router - React Router v7                                 ║
║  • /lucide-icons/lucide-react - Icons                                        ║
║                                                                              ║
╚══════════════════════════════════════════════════════════════════════════════╝
```

---

## Template FrdDocPage.tsx

```tsx
// web/smartstack-web/src/pages/docs/business/{app}/{module}/FrdDocPage.tsx
// GÉNÉRER AVEC: use context7 with /facebook/react

import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import {
  FileText,
  Users,
  Shield,
  CheckCircle,
  AlertTriangle,
  ChevronRight,
  ArrowRight,
  List,
  Layout,
  Database
} from 'lucide-react';

// Types pour les données FRD
interface UseCase {
  id: string;
  name: string;
  actor: string;
  permission: string;
  description: string;
}

interface BusinessRule {
  id: string;
  rule: string;
  category: string;
  priority: 'Must' | 'Should' | 'Could';
}

interface Permission {
  path: string;
  description: string;
  roles: string[];
}

interface FrdData {
  featureId: string;
  moduleName: string;
  applicationName: string;
  version: string;
  useCases: UseCase[];
  businessRules: BusinessRule[];
  permissions: Permission[];
}

// Données chargées depuis le FRD (à générer dynamiquement)
const frdData: FrdData = {
  featureId: 'FEAT-XXX',
  moduleName: '{ModuleName}',
  applicationName: '{ApplicationName}',
  version: '1.0',
  useCases: [
    {
      id: 'UC-001',
      name: '{Use Case Name}',
      actor: '{Actor}',
      permission: 'business.{app}.{module}.{action}',
      description: '{Description}'
    }
  ],
  businessRules: [
    {
      id: 'BR-001',
      rule: '{Business Rule Description}',
      category: 'Validation',
      priority: 'Must'
    }
  ],
  permissions: [
    {
      path: 'business.{app}.{module}.read',
      description: 'View {module} data',
      roles: ['Admin', 'Manager', 'User', 'ReadOnly']
    },
    {
      path: 'business.{app}.{module}.create',
      description: 'Create new {module}',
      roles: ['Admin', 'Manager']
    }
  ]
};

// Composant Badge de priorité
function PriorityBadge({ priority }: { priority: string }) {
  const colors = {
    Must: 'bg-red-500/10 text-red-600',
    Should: 'bg-yellow-500/10 text-yellow-600',
    Could: 'bg-blue-500/10 text-blue-600'
  };
  return (
    <span className={`px-2 py-0.5 rounded text-xs font-medium ${colors[priority as keyof typeof colors] || 'bg-gray-500/10 text-gray-600'}`}>
      {priority}
    </span>
  );
}

// Composant Section numérotée
function NumberedSection({
  number,
  title,
  icon: Icon,
  children
}: {
  number: number;
  title: string;
  icon: React.ComponentType<{ className?: string }>;
  children: React.ReactNode;
}) {
  return (
    <section id={`section-${number}`} className="scroll-mt-4">
      <h2 className="text-xl font-semibold mb-4 flex items-center gap-3">
        <span className="w-8 h-8 rounded-full bg-[var(--color-primary-600)] text-white flex items-center justify-center text-sm font-bold">
          {number}
        </span>
        <Icon className="w-5 h-5 text-[var(--color-primary-600)]" />
        {title}
      </h2>
      <div className="card p-6">
        {children}
      </div>
    </section>
  );
}

export function {ModuleName}FrdDocPage() {
  const { t } = useTranslation('docs-business');

  return (
    <div className="space-y-8">
      {/* Breadcrumb */}
      <nav className="flex items-center gap-2 text-sm text-[var(--text-secondary)]">
        <Link to="/docs" className="hover:text-[var(--color-primary-600)]">
          {t('breadcrumb.docs')}
        </Link>
        <span>/</span>
        <Link to="/docs/business" className="hover:text-[var(--color-primary-600)]">
          {t('breadcrumb.business')}
        </Link>
        <span>/</span>
        <Link to={`/docs/business/${frdData.applicationName.toLowerCase()}`} className="hover:text-[var(--color-primary-600)]">
          {t(`apps.${frdData.applicationName.toLowerCase()}.name`)}
        </Link>
        <span>/</span>
        <span>{t(`modules.${frdData.moduleName.toLowerCase()}.name`)}</span>
      </nav>

      {/* Header */}
      <header>
        <div className="flex items-center gap-2 mb-2">
          <span className="px-2 py-0.5 rounded bg-[var(--color-primary-600)]/10 text-[var(--color-primary-600)] text-xs font-medium">
            {frdData.featureId}
          </span>
          <span className="px-2 py-0.5 rounded bg-green-500/10 text-green-600 text-xs font-medium">
            v{frdData.version}
          </span>
        </div>
        <h1 className="text-3xl font-bold mb-4 flex items-center gap-3">
          <FileText className="w-8 h-8 text-[var(--color-primary-600)]" />
          {t(`modules.${frdData.moduleName.toLowerCase()}.title`)}
        </h1>
        <p className="text-lg text-[var(--text-secondary)]">
          {t(`modules.${frdData.moduleName.toLowerCase()}.subtitle`)}
        </p>
      </header>

      {/* Table des matières */}
      <div className="card p-4 bg-[var(--bg-secondary)]">
        <h2 className="font-semibold mb-3 flex items-center gap-2">
          <List className="w-4 h-4" />
          {t('common.tableOfContents')}
        </h2>
        <nav className="grid grid-cols-2 md:grid-cols-3 gap-2">
          {['overview', 'useCases', 'businessRules', 'permissions', 'wireframes', 'api'].map((section, idx) => (
            <a
              key={section}
              href={`#section-${idx + 1}`}
              className="flex items-center gap-2 p-2 rounded hover:bg-[var(--bg-tertiary)] text-sm"
            >
              <ChevronRight className="w-4 h-4 text-[var(--color-primary-600)]" />
              {t(`sections.${section}`)}
            </a>
          ))}
        </nav>
      </div>

      {/* Section 1: Vue d'ensemble */}
      <NumberedSection number={1} title={t('sections.overview')} icon={Layout}>
        <p className="text-[var(--text-secondary)] mb-4">
          {t(`modules.${frdData.moduleName.toLowerCase()}.overview`)}
        </p>
        <div className="grid grid-cols-2 md:grid-cols-4 gap-4 mt-4">
          <div className="p-4 rounded-lg bg-[var(--bg-secondary)] text-center">
            <div className="text-2xl font-bold text-[var(--color-primary-600)]">
              {frdData.useCases.length}
            </div>
            <div className="text-sm text-[var(--text-secondary)]">{t('stats.useCases')}</div>
          </div>
          <div className="p-4 rounded-lg bg-[var(--bg-secondary)] text-center">
            <div className="text-2xl font-bold text-[var(--color-primary-600)]">
              {frdData.businessRules.length}
            </div>
            <div className="text-sm text-[var(--text-secondary)]">{t('stats.businessRules')}</div>
          </div>
          <div className="p-4 rounded-lg bg-[var(--bg-secondary)] text-center">
            <div className="text-2xl font-bold text-[var(--color-primary-600)]">
              {frdData.permissions.length}
            </div>
            <div className="text-sm text-[var(--text-secondary)]">{t('stats.permissions')}</div>
          </div>
        </div>
      </NumberedSection>

      {/* Section 2: Cas d'utilisation */}
      <NumberedSection number={2} title={t('sections.useCases')} icon={Users}>
        <div className="space-y-4">
          {frdData.useCases.map((uc) => (
            <div key={uc.id} className="border border-[var(--border-color)] rounded-lg p-4">
              <div className="flex items-center justify-between mb-2">
                <h3 className="font-semibold flex items-center gap-2">
                  <span className="px-2 py-0.5 rounded bg-[var(--color-primary-600)]/10 text-[var(--color-primary-600)] text-xs font-mono">
                    {uc.id}
                  </span>
                  {uc.name}
                </h3>
                <span className="text-sm text-[var(--text-secondary)]">
                  {t('labels.actor')}: {uc.actor}
                </span>
              </div>
              <p className="text-sm text-[var(--text-secondary)] mb-2">{uc.description}</p>
              <div className="flex items-center gap-2 text-xs">
                <Shield className="w-3 h-3 text-amber-500" />
                <code className="bg-[var(--bg-secondary)] px-2 py-0.5 rounded">{uc.permission}</code>
              </div>
            </div>
          ))}
        </div>
      </NumberedSection>

      {/* Section 3: Règles métier */}
      <NumberedSection number={3} title={t('sections.businessRules')} icon={CheckCircle}>
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="bg-[var(--bg-secondary)]">
                <th className="text-left py-2 px-3 rounded-tl-lg">ID</th>
                <th className="text-left py-2 px-3">{t('labels.rule')}</th>
                <th className="text-left py-2 px-3">{t('labels.category')}</th>
                <th className="text-left py-2 px-3 rounded-tr-lg">{t('labels.priority')}</th>
              </tr>
            </thead>
            <tbody>
              {frdData.businessRules.map((br, idx) => (
                <tr key={br.id} className={idx % 2 === 1 ? 'bg-[var(--bg-secondary)]/50' : ''}>
                  <td className="py-2 px-3 font-mono text-[var(--color-primary-600)]">{br.id}</td>
                  <td className="py-2 px-3">{br.rule}</td>
                  <td className="py-2 px-3 text-[var(--text-secondary)]">{br.category}</td>
                  <td className="py-2 px-3"><PriorityBadge priority={br.priority} /></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </NumberedSection>

      {/* Section 4: Permissions */}
      <NumberedSection number={4} title={t('sections.permissions')} icon={Shield}>
        <div className="space-y-3">
          {frdData.permissions.map((perm) => (
            <div key={perm.path} className="flex items-center justify-between p-3 rounded-lg bg-[var(--bg-secondary)]">
              <div>
                <code className="text-sm font-mono text-[var(--color-primary-600)]">{perm.path}</code>
                <p className="text-sm text-[var(--text-secondary)] mt-1">{perm.description}</p>
              </div>
              <div className="flex gap-1">
                {perm.roles.map((role) => (
                  <span key={role} className="px-2 py-0.5 rounded bg-[var(--bg-tertiary)] text-xs">
                    {role}
                  </span>
                ))}
              </div>
            </div>
          ))}
        </div>

        {/* Avertissement permissions */}
        <div className="mt-4 p-4 rounded-lg bg-amber-500/10 border border-amber-500/20 flex items-start gap-3">
          <AlertTriangle className="w-5 h-5 text-amber-600 flex-shrink-0 mt-0.5" />
          <div>
            <div className="font-medium text-amber-600">{t('warnings.permissionCheck')}</div>
            <p className="text-sm text-[var(--text-secondary)]">
              {t('warnings.permissionCheckDescription')}
            </p>
          </div>
        </div>
      </NumberedSection>

      {/* Section 5: Wireframes */}
      <NumberedSection number={5} title={t('sections.wireframes')} icon={Layout}>
        <div className="border-2 border-dashed border-[var(--border-color)] rounded-lg p-6">
          <div className="text-center text-sm text-[var(--text-tertiary)] mb-4">
            {t('common.wireframePreview')}
          </div>
          {/* Wireframe simplifié */}
          <div className="space-y-4">
            <div className="h-12 bg-[var(--bg-secondary)] rounded flex items-center px-4 justify-between">
              <span className="text-sm">[Header + Navigation]</span>
              <span className="text-sm">[User Menu]</span>
            </div>
            <div className="grid grid-cols-4 gap-4">
              <div className="col-span-1 h-64 bg-[var(--bg-secondary)] rounded p-4">
                <span className="text-sm">[Filters]</span>
              </div>
              <div className="col-span-3 h-64 bg-[var(--bg-secondary)] rounded p-4">
                <span className="text-sm">[Data Table]</span>
              </div>
            </div>
          </div>
        </div>
      </NumberedSection>

      {/* Section 6: API Endpoints */}
      <NumberedSection number={6} title={t('sections.api')} icon={Database}>
        <div className="overflow-x-auto">
          <table className="w-full text-sm font-mono">
            <thead>
              <tr className="bg-[var(--bg-secondary)]">
                <th className="text-left py-2 px-3 rounded-tl-lg">Method</th>
                <th className="text-left py-2 px-3">Endpoint</th>
                <th className="text-left py-2 px-3 rounded-tr-lg">Permission</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-green-500/10 text-green-600">GET</span></td>
                <td className="py-2 px-3">/api/business/{'{module}'}</td>
                <td className="py-2 px-3 text-[var(--text-secondary)]">.read</td>
              </tr>
              <tr className="bg-[var(--bg-secondary)]/50">
                <td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-blue-500/10 text-blue-600">POST</span></td>
                <td className="py-2 px-3">/api/business/{'{module}'}</td>
                <td className="py-2 px-3 text-[var(--text-secondary)]">.create</td>
              </tr>
              <tr>
                <td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-yellow-500/10 text-yellow-600">PUT</span></td>
                <td className="py-2 px-3">/api/business/{'{module}'}/{'{id}'}</td>
                <td className="py-2 px-3 text-[var(--text-secondary)]">.update</td>
              </tr>
              <tr className="bg-[var(--bg-secondary)]/50">
                <td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-red-500/10 text-red-600">DELETE</span></td>
                <td className="py-2 px-3">/api/business/{'{module}'}/{'{id}'}</td>
                <td className="py-2 px-3 text-[var(--text-secondary)]">.delete</td>
              </tr>
            </tbody>
          </table>
        </div>
      </NumberedSection>

      {/* Navigation footer */}
      <div className="flex justify-between pt-6 border-t border-[var(--border-color)]">
        <Link
          to={`/docs/business/${frdData.applicationName.toLowerCase()}`}
          className="flex items-center gap-2 text-[var(--text-secondary)] hover:text-[var(--color-primary-600)]"
        >
          <ArrowRight className="w-4 h-4 rotate-180" />
          {t('nav.backToApp')}
        </Link>
        <Link
          to="/docs/business"
          className="flex items-center gap-2 text-[var(--color-primary-600)]"
        >
          {t('nav.allModules')}
          <ArrowRight className="w-4 h-4" />
        </Link>
      </div>
    </div>
  );
}
```

---

## Template i18n docs-business.json

```json
{
  "breadcrumb": {
    "docs": "Documentation",
    "business": "Business"
  },
  "common": {
    "tableOfContents": "Table of Contents",
    "wireframePreview": "Wireframe Preview"
  },
  "sections": {
    "overview": "Overview",
    "useCases": "Use Cases",
    "businessRules": "Business Rules",
    "permissions": "Permissions",
    "wireframes": "Wireframes",
    "api": "API Endpoints"
  },
  "labels": {
    "actor": "Actor",
    "rule": "Rule",
    "category": "Category",
    "priority": "Priority"
  },
  "stats": {
    "useCases": "Use Cases",
    "businessRules": "Business Rules",
    "permissions": "Permissions"
  },
  "warnings": {
    "permissionCheck": "Permission Check Required",
    "permissionCheckDescription": "Ensure all permissions are registered in PermissionConfiguration.cs before deployment."
  },
  "nav": {
    "backToApp": "Back to Application",
    "allModules": "All Modules"
  },
  "apps": {
    "{app}": {
      "name": "{Application Name}",
      "description": "{Application description}"
    }
  },
  "modules": {
    "{module}": {
      "name": "{Module Name}",
      "title": "{Module Title}",
      "subtitle": "{Module subtitle description}",
      "overview": "{Detailed overview of the module functionality}"
    }
  }
}
```

---

## Template Index Application

```tsx
// web/smartstack-web/src/pages/docs/business/{app}/index.tsx

import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Folder, FileText, ChevronRight } from 'lucide-react';

interface ModuleLink {
  id: string;
  name: string;
  description: string;
  features: number;
  path: string;
}

const modules: ModuleLink[] = [
  {
    id: '{module}',
    name: '{Module Name}',
    description: '{Module description}',
    features: 3,
    path: '/docs/business/{app}/{module}'
  }
];

export function {App}DocsIndexPage() {
  const { t } = useTranslation('docs-business');

  return (
    <div className="space-y-8">
      {/* Breadcrumb */}
      <nav className="flex items-center gap-2 text-sm text-[var(--text-secondary)]">
        <Link to="/docs">{t('breadcrumb.docs')}</Link>
        <span>/</span>
        <Link to="/docs/business">{t('breadcrumb.business')}</Link>
        <span>/</span>
        <span>{t('apps.{app}.name')}</span>
      </nav>

      {/* Header */}
      <header>
        <h1 className="text-3xl font-bold mb-4 flex items-center gap-3">
          <Folder className="w-8 h-8 text-[var(--color-primary-600)]" />
          {t('apps.{app}.name')}
        </h1>
        <p className="text-lg text-[var(--text-secondary)]">
          {t('apps.{app}.description')}
        </p>
      </header>

      {/* Modules list */}
      <section>
        <h2 className="text-xl font-semibold mb-4">{t('common.modules')}</h2>
        <div className="grid gap-4">
          {modules.map((module) => (
            <Link
              key={module.id}
              to={module.path}
              className="card p-4 hover:border-[var(--color-primary-600)] transition-colors group"
            >
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-3">
                  <FileText className="w-6 h-6 text-[var(--color-primary-600)]" />
                  <div>
                    <h3 className="font-semibold group-hover:text-[var(--color-primary-600)]">
                      {module.name}
                    </h3>
                    <p className="text-sm text-[var(--text-secondary)]">
                      {module.description}
                    </p>
                  </div>
                </div>
                <div className="flex items-center gap-4">
                  <span className="text-sm text-[var(--text-secondary)]">
                    {module.features} features
                  </span>
                  <ChevronRight className="w-5 h-5 text-[var(--text-tertiary)] group-hover:text-[var(--color-primary-600)]" />
                </div>
              </div>
            </Link>
          ))}
        </div>
      </section>
    </div>
  );
}
```

---

## Checklist génération

Lors de la génération avec `/business-analyse:7-doc-html`:

- [ ] Utiliser Context7 pour patterns React actuels
- [ ] Générer `FrdDocPage.tsx` avec données du FRD
- [ ] Créer/mettre à jour `docs-business.json` (4 langues)
- [ ] Ajouter route dans `App.tsx`
- [ ] Mettre à jour index parent si nouveau module
