# HTML Tool Integration Guide

How to migrate existing standalone HTML tools into React modules within the ArchiTools dashboard.

---

## Overview

ArchiTools currently has four standalone HTML files that implement useful internal tools:

| File | Purpose |
|---|---|
| `emailsignature/emailsignature-config.html` | Email signature configurator with live preview, color pickers, layout sliders, HTML export |
| `wordXMLgenerator/word-xml-generator-basic.html` | Simple Word XML Custom Part generator |
| `wordXMLgenerator/word-xml-generator-medium.html` | Extended version with Short/Upper/Lower/Initials/First field variants |
| `wordXMLgenerator/word-xml-generator-advanced.html` | Full version with categories, localStorage, simple/advanced mode, POT/CUT metrics, ZIP export |

### Why Integrate

Standalone HTML files work, but they cannot:

- Share a consistent UI theme (dark/light toggle, company branding).
- Use shared storage abstraction (configurations saved in one tool are invisible to another).
- Participate in feature flags or access control.
- Link to related data (e.g., an XML template referencing a project tag).
- Provide a unified navigation experience.
- Be tested with standard tooling (Jest, Playwright).

Integration brings these tools into the dashboard shell with shared infrastructure while preserving all existing functionality.

---

## Migration Strategy

Migration happens in three phases. Each phase produces a working state -- there is no "big bang" cutover.

### Phase 1: Embed (Temporary Bridge)

Wrap the existing HTML file in an `<iframe>` inside a dashboard page. This gives immediate navigation integration with zero rewrite.

```tsx
// src/modules/email-signature/pages/email-signature-page.tsx (Phase 1 only)

export function EmailSignaturePage() {
  return (
    <div className="h-[calc(100vh-3.5rem)]">
      <iframe
        src="/legacy/emailsignature-config.html"
        className="w-full h-full border-0"
        title="Email Signature Configurator"
      />
    </div>
  );
}
```

**When to use Phase 1:**
- When a tool needs to appear in the sidebar immediately but rewrite resources are not available.
- As a fallback during Phase 2 development (iframe stays live while React version is being built).

**Limitations:**
- No theme synchronization (iframe has its own styles).
- No shared state between iframe and parent.
- No storage abstraction.
- Content Security Policy may block certain CDN scripts.

**Phase 1 is not recommended as a long-term solution.** Move to Phase 2 as soon as practical.

### Phase 2: Extract

Pull JavaScript logic out of the HTML files into typed TypeScript hooks and utility functions. Build a React UI that replaces the HTML structure.

This is where the bulk of the work happens. The goal is functional parity with the original tool, running inside the React component tree with proper state management.

Detailed extraction plans for each tool are in the sections below.

### Phase 3: Normalize

With React UI in place, integrate with platform-level features:

- **Storage abstraction**: Save/load configurations through the shared storage layer instead of raw `localStorage`.
- **Theming**: All colors respond to dark/light toggle and company accent.
- **Tagging**: Link generated artifacts to project tags from the tag manager.
- **Feature flags**: Gate experimental features behind flags.
- **Company context**: Tool behavior adapts to the selected company (logo, colors, address, namespace).
- **Cross-module linking**: An XML template can reference a project; a signature config can link to a company profile.

---

## Email Signature Generator -- Migration Plan

### Current State Analysis

The existing `emailsignature-config.html` contains:

1. **Data inputs**: prefix, name, title, phone (4 text fields).
2. **Color picker system**: 7 color targets (prefix, name, title, address, phone, website, motto) with 4 swatch options each (Beletage brand palette).
3. **Layout sliders**: 8 range inputs controlling pixel-level spacing (green line width, section spacing, logo spacing, title spacing, gutter alignment, icon-text spacing, icon vertical position, motto spacing).
4. **Options**: 3 checkboxes (reply variant, super-reply variant, SVG images).
5. **Signature HTML template builder**: `generateSignatureHTML(data)` function producing a table-based email signature.
6. **Phone formatter**: Converts `07xxxxxxxx` to `+40 xxx xxx xxx` format.
7. **Live preview**: Real-time DOM update on any input change.
8. **Export**: Downloads the signature HTML as a file.
9. **Zoom toggle**: 100%/200% preview scaling.
10. **Collapsible sections**: Manual accordion implementation.

Everything is Beletage-specific: logo URL, address, website, motto, brand colors.

### Extraction Plan

#### Hook: `useSignatureBuilder`

Encapsulates the signature generation logic.

```
Source: generateSignatureHTML() function (lines 280-361)
Target: src/modules/email-signature/hooks/use-signature-builder.ts

Responsibilities:
- Accept SignatureConfig object (all field values, colors, spacing, variant flags)
- Return generated HTML string
- Return structured SignatureData for preview rendering
- Pure computation, no side effects

Interface:
  Input:  SignatureConfig (typed object with all config fields)
  Output: { html: string; previewData: SignatureData }
```

#### Hook: `useSignatureExport`

Handles file download and clipboard copy.

```
Source: export button click handler (lines 441-450)
Target: src/modules/email-signature/hooks/use-signature-export.ts

Responsibilities:
- Generate Blob from HTML string
- Trigger file download with appropriate filename
- Copy HTML to clipboard
- Filename includes company name and date

Interface:
  Input:  { html: string; companySlug: string }
  Output: { downloadHtml: () => void; copyToClipboard: () => Promise<void> }
```

#### Utility: `formatPhoneNumber`

```
Source: phone formatting logic in updatePreview() (lines 365-372)
Target: src/shared/utils/format-phone.ts

Responsibilities:
- Accept raw phone string
- Detect Romanian mobile format (07xxxxxxxx)
- Return { display: string; tel: string } with formatted display and tel: link

This is a shared utility, not signature-specific.
```

#### React UI Replacements

| Original | React Replacement |
|---|---|
| Text inputs with `document.getElementById` | Controlled `<Input>` components with React state |
| Color swatch grid with DOM event delegation | `<ColorPicker>` component with `useState` |
| Range inputs with manual value display | `<Slider>` (shadcn/ui) with value label |
| Collapsible sections | `<Collapsible>` (shadcn/ui) |
| Checkboxes | `<Switch>` or `<Checkbox>` (shadcn/ui) |
| Live preview via `innerHTML` | React component rendering signature structure |
| `alert()`/`confirm()` | `<AlertDialog>` (shadcn/ui) |
| File download via DOM | `useSignatureExport` hook |

#### Generalization: Multi-Company Support

The current tool is hardcoded for Beletage. The React version must support all three companies.

```ts
// src/config/companies.ts

export interface CompanyProfile {
  id: string;
  name: string;
  slug: string;
  accent: string;          // hex color
  logo: {
    png: string;
    svg: string;
  };
  address: {
    street: string;
    city: string;
    county: string;
    postalCode: string;
    country: string;
    mapsUrl: string;
  };
  website: string;
  motto: string;
  brandColors: Record<string, string>;  // named palette
  signatureIcons: {
    greySlash: { png: string; svg: string };
    greenSlash: { png: string; svg: string };
  };
}
```

The company selector in the header drives `CompanyProfile` into context. The signature builder reads from this context to populate logo, address, website, motto, and available colors.

#### New: Storage Integration

Save and load signature configurations via the storage abstraction:

```ts
// Signature configs are stored as:
{
  id: string;
  companyId: string;
  name: string;              // e.g., "Marius TARAU - Beletage"
  config: SignatureConfig;   // all field values
  createdAt: string;
  updatedAt: string;
}
```

Users can save multiple configs (one per person/company combo), load previous configs, and delete old ones.

### File Structure

```
src/modules/email-signature/
  pages/
    email-signature-page.tsx       -- Main page component
  components/
    signature-form.tsx             -- Config form (inputs, colors, sliders)
    signature-preview.tsx          -- Live preview panel
    signature-color-picker.tsx     -- Color swatch selector
    saved-configs-list.tsx         -- List of saved configurations
  hooks/
    use-signature-builder.ts       -- HTML generation logic
    use-signature-export.ts        -- Download/copy logic
    use-signature-config.ts        -- State management for all config fields
  types.ts                         -- SignatureConfig, SignatureData interfaces
```

---

## Word XML Generators -- Migration Plan (Consolidate 3 into 1)

### Current State Analysis

Three separate HTML files with increasing complexity:

**Basic** (`word-xml-generator-basic.html`):
- Namespace URI, root element name, field list (textarea).
- Generates XML with one element per field.
- Generates XPath list.
- Copy to clipboard, download XML, demo fill.
- Field name sanitization (spaces to underscores, invalid chars removed, dedup).

**Medium** (`word-xml-generator-medium.html`):
- Same as basic, but generates 6 variants per field: base, Short, Upper, Lower, Initials, First.
- `initials()` helper function.

**Advanced** (`word-xml-generator-advanced.html`):
- Category-based organization (Beneficiar, Proiect, Suprafete, Meta) with default presets.
- Per-category namespace (base namespace + `/CategoryName`).
- Per-category root element (`CategoryNameData`).
- Simple/Advanced mode toggle (advanced adds the 6 variants).
- POT/CUT metric computation for "Suprafete" category.
- localStorage persistence for category data.
- Category management (add, delete, reset to preset, clear).
- Single-category XML download.
- ZIP export of all categories via JSZip.
- Pill-based category selector UI.

### Consolidation Strategy

The three tools become a single React module with a complexity toggle:

| Mode | Equivalent to | Behavior |
|---|---|---|
| **Simplu** | basic | One element per field, no variants |
| **Avansat** | advanced | Categories, variants, POT/CUT, ZIP |

The medium version is subsumed by the advanced mode -- it was an intermediate step, not a distinct use case.

### Extraction Plan

#### Hook: `useXmlGenerator`

Core XML generation logic.

```
Source: generateXML() from basic, generateCategory() from advanced
Target: src/modules/xml-generator/hooks/use-xml-generator.ts

Responsibilities:
- Accept field list, namespace, root element name, mode (simple/advanced)
- Generate XML string for a Custom XML Part
- Generate XPath listing
- Handle variant generation (Short, Upper, Lower, Initials, First)
- Handle metric fields (POT/CUT) when category is surface-related

Interface:
  Input:  XmlGeneratorInput { fields: string[]; namespace: string; rootElement: string; mode: 'simple' | 'advanced'; computeMetrics: boolean; categoryName?: string }
  Output: XmlGeneratorResult { xml: string; xpaths: string; fieldCount: number }
```

#### Hook: `useCategoryManager`

Category CRUD and persistence.

```
Source: initCategories(), switchCategory(), addCategoryPrompt(), etc. from advanced
Target: src/modules/xml-generator/hooks/use-category-manager.ts

Responsibilities:
- Manage list of categories with their field text
- Track active category
- Provide CRUD operations (add, delete, rename, reset to preset, clear)
- Persist to storage abstraction (not raw localStorage)
- Load default presets on first use

Interface:
  Input:  StorageAdapter
  Output: { categories: Category[]; activeCategory: string; addCategory, deleteCategory, ... }
```

#### Pure Function: `sanitizeXmlName`

```
Source: sanitizeName() / sanitizeXmlName() (present in all three files)
Target: src/modules/xml-generator/utils/sanitize-xml-name.ts

Responsibilities:
- Trim whitespace
- Replace spaces with underscores
- Remove invalid XML name characters
- Ensure name starts with letter or underscore
- Return null for empty input

Easily unit-tested in isolation.
```

#### Pure Function: `generateFieldVariants`

```
Source: variant generation logic in medium and advanced
Target: src/modules/xml-generator/utils/generate-field-variants.ts

Responsibilities:
- Given a base field name, return array of variant names
- Variants: base, baseShort, baseUpper, baseLower, baseInitials, baseFirst
- Deduplication against a provided Set of used names
```

#### Pure Function: `generateXpaths`

```
Source: XPath string building in all three files
Target: src/modules/xml-generator/utils/generate-xpaths.ts

Responsibilities:
- Given root element and field list (with variants), produce formatted XPath listing
- Include namespace and root info in header
```

#### Service: `zipExportService`

```
Source: downloadZipAll() from advanced
Target: src/modules/xml-generator/services/zip-export-service.ts

Responsibilities:
- Accept map of { filename: xmlContent }
- Use JSZip to create archive
- Return Blob for download

Dependency: jszip (npm package, replaces CDN script tag)
```

### React UI Replacements

| Original | React Replacement |
|---|---|
| Textarea for field list | Controlled `<Textarea>` with React state |
| Pill-based category selector | `<Tabs>` (shadcn/ui) or custom pill component |
| Simple/Advanced pill toggle | `<Tabs>` with two items |
| `prompt()` for new category name | `<Dialog>` with `<Input>` |
| `confirm()` for deletion | `<AlertDialog>` |
| `alert()` for validation | Toast notification (shadcn/ui `sonner`) |
| `<pre>` for XML output | `<pre>` with syntax highlighting (optional) + copy button |
| Direct `localStorage` | Storage abstraction via hook |
| JSZip CDN | `jszip` npm package |

### New Features in React Version

1. **Template presets per company**: Each company can have its own default categories and fields. Driven by company context.
2. **Save/load configurations**: Named configurations stored via storage abstraction. Users can maintain multiple XML schemas.
3. **Project tag linking**: When generating XML for a specific project, link the configuration to a project tag from the tag manager.
4. **Copy individual XPaths**: Click-to-copy on each XPath line, not just the whole block.

### File Structure

```
src/modules/xml-generator/
  pages/
    xml-generator-page.tsx           -- Main page component
  components/
    xml-generator-form.tsx           -- Namespace, root, mode controls
    category-manager.tsx             -- Category tabs/pills + CRUD
    field-editor.tsx                 -- Textarea for field list
    xml-preview.tsx                  -- XML output with copy/download
    xpath-preview.tsx                -- XPath output with copy
    saved-configs-list.tsx           -- Saved configuration browser
  hooks/
    use-xml-generator.ts             -- XML generation logic
    use-category-manager.ts          -- Category state management
    use-xml-export.ts                -- Download/ZIP export
  services/
    zip-export-service.ts            -- JSZip wrapper
  utils/
    sanitize-xml-name.ts             -- Field name sanitization
    generate-field-variants.ts       -- Variant name generation
    generate-xpaths.ts               -- XPath string builder
  data/
    default-presets.ts               -- Default category presets
  types.ts                           -- Category, XmlGeneratorInput, etc.
```

---

## General Extraction Patterns

### DOM Manipulation to React State

| HTML/JS Pattern | React Equivalent |
|---|---|
| `document.getElementById('x').value` | `const [x, setX] = useState('')` + controlled input |
| `element.innerHTML = html` | JSX return with variables |
| `element.textContent = text` | `{text}` in JSX |
| `element.classList.toggle('active')` | Conditional className: `cn('pill', isActive && 'active')` |
| `element.style.backgroundColor = color` | `style={{ backgroundColor: color }}` or Tailwind class |
| `element.addEventListener('input', handler)` | `onChange={handler}` on element |
| `document.createElement('div')` | JSX element or `.map()` rendering |
| `parent.appendChild(child)` | Render in JSX, controlled by state array |
| `element.disabled = true` | `disabled={condition}` prop |

### Refs

Use `useRef` only when React state is insufficient:
- Measuring DOM element dimensions.
- Integrating with third-party DOM libraries.
- Storing mutable values that should not trigger re-render.

Do not use `useRef` as a replacement for `document.getElementById`. That pattern belongs in controlled component state.

### Storage

| HTML Pattern | React Equivalent |
|---|---|
| `localStorage.getItem('key')` | `storageAdapter.get<T>('key')` |
| `localStorage.setItem('key', JSON.stringify(data))` | `storageAdapter.set('key', data)` |
| `JSON.parse(localStorage.getItem('key'))` | `storageAdapter.get<T>('key')` (typed, handles parse errors) |

The storage abstraction (`src/core/storage/`) wraps localStorage with:
- Typed get/set.
- JSON serialization.
- Error handling (quota exceeded, parse failures).
- Key namespacing by module.
- Future: swap backend to IndexedDB or API without changing module code.

### Styling

| HTML Pattern | React Equivalent |
|---|---|
| Inline `style="color: #22B5AB"` | `className="text-teal-500"` or CSS variable |
| Tailwind CDN classes | Same Tailwind classes (compiled at build time, not CDN) |
| Raw CSS in `<style>` block | Tailwind utilities in JSX, or `globals.css` for truly global styles |
| CSS custom properties | Keep if needed for dynamic values (e.g., accent color) |
| `linear-gradient(135deg, #38bdf8, #6366f1)` | Tailwind `bg-gradient-to-br from-sky-400 to-indigo-500` or define in theme |

### Dependencies

| HTML Pattern | React Equivalent |
|---|---|
| `<script src="https://cdn.tailwindcss.com">` | Tailwind installed via npm, configured in `tailwind.config.ts` |
| `<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/...">` | `npm install jszip` + `import JSZip from 'jszip'` |
| Google Fonts CDN link | `next/font/google` in layout |

### Dialogs

| HTML Pattern | React Equivalent |
|---|---|
| `alert('Message')` | `toast('Message')` via sonner, or `<AlertDialog>` for important messages |
| `confirm('Are you sure?')` | `<AlertDialog>` with confirm/cancel buttons |
| `prompt('Enter name:')` | `<Dialog>` with `<Input>` and submit button |

---

## File Placement Conventions

```
src/
  modules/
    email-signature/            -- Email signature module
      pages/                    -- Route-level page components
      components/               -- Module-specific UI components
      hooks/                    -- Module-specific hooks
      services/                 -- Module-specific services (e.g., zip export)
      utils/                    -- Module-specific pure functions
      data/                     -- Static data, presets, defaults
      types.ts                  -- Module type definitions
    xml-generator/              -- XML generator module (consolidated)
      (same structure)

  shared/
    components/
      ui/                       -- shadcn/ui components
    utils/                      -- Cross-module utilities (formatPhoneNumber, etc.)
    hooks/                      -- Cross-module hooks

  core/
    storage/                    -- Storage abstraction
    i18n/
      labels.ts                 -- All UI text
    theme/                      -- Theme configuration

  config/
    companies.ts                -- Company profiles
    modules.ts                  -- Module registry (drives sidebar)
```

Module code never imports from another module directly. Shared functionality lives in `src/shared/` or `src/core/`.

---

## Testing Migrated Logic

### Unit Tests

All extracted pure functions and hooks must have unit tests.

**Pure functions** (sanitize, format, generate): straightforward input/output tests.

```ts
// src/modules/xml-generator/utils/__tests__/sanitize-xml-name.test.ts

import { sanitizeXmlName } from '../sanitize-xml-name';

describe('sanitizeXmlName', () => {
  it('replaces spaces with underscores', () => {
    expect(sanitizeXmlName('Nume Client')).toBe('Nume_Client');
  });

  it('removes invalid XML characters', () => {
    expect(sanitizeXmlName('Preț/m²')).toBe('Prem');
  });

  it('prepends underscore if starts with digit', () => {
    expect(sanitizeXmlName('123Field')).toBe('_123Field');
  });

  it('returns null for empty input', () => {
    expect(sanitizeXmlName('')).toBeNull();
    expect(sanitizeXmlName('   ')).toBeNull();
  });
});
```

**Hooks**: test with `@testing-library/react-hooks` or `renderHook` from `@testing-library/react`.

```ts
import { renderHook, act } from '@testing-library/react';
import { useCategoryManager } from '../use-category-manager';

describe('useCategoryManager', () => {
  it('initializes with default presets', () => {
    const { result } = renderHook(() => useCategoryManager(mockStorage));
    expect(result.current.categories).toHaveLength(4);
    expect(result.current.activeCategory).toBe('Beneficiar');
  });
});
```

### Integration Tests

Test full page rendering with mocked storage. Verify that:
- Form inputs update preview in real time.
- Export produces valid HTML/XML.
- Save/load round-trips correctly.

### Regression Testing

Before removing Phase 1 iframe, verify the React version produces identical output to the original HTML tool for a set of reference inputs. Store reference outputs as test fixtures.

For the email signature generator, compare generated HTML string character-by-character for known input configurations.

---

## Legacy Tool Preservation

Original HTML files are kept in the repository under their current paths for reference:

```
emailsignature/emailsignature-config.html
wordXMLgenerator/word-xml-generator-basic.html
wordXMLgenerator/word-xml-generator-medium.html
wordXMLgenerator/word-xml-generator-advanced.html
```

These files are not served by the Next.js application in production. They remain in the repository as:
- Reference implementation for migration accuracy.
- Fallback if a React module has a blocking bug.
- Historical documentation of original tool behavior.

Once Phase 3 is complete and the React versions are stable, legacy files can be moved to a `legacy/` directory or archived in a separate branch. Do not delete them until the React versions have been in production use for at least one release cycle.
