# Centre Cluster Page — Drupal 10 Mapping Sheet

This mapping shows how each component maps to a Drupal 10 implementation target (Block, Paragraph, View, Menu, Template). It follows the pattern the Drupal team established for the homepage and cataract page (`docs/drupal-mapping.md`, `docs/cataract-drupal-mapping.md`).

## Suggested content architecture

**Content type:** `node--landing_page` with a Paragraph field `field_sections` (bundle-restricted entity reference).

**Taxonomy vocabularies:**
- `state` — term fields: `name`, `slug` (auto), `display_order` (optional). Populates state chips and the dropdown.

**Content types:**
- `node--centre` — fields: `title` (centre name, e.g. "Mogalrajpuram"), `field_city`, `field_state` (term ref → `state`), `field_image` (media), `field_phone`, `field_booking_url`, `field_address`, `field_lat`, `field_lng`, etc. The Drupal team renders these via a Views display.

## Section-by-section mapping

| # | Component | Drupal implementation target | Notes |
|---|-----------|-----------------------------|-------|
| 1 | `01-utility-bar.html` | `region--secondary.html.twig` (utility region) + menu block | Same as homepage |
| 2 | `02-main-nav.html` | `region--header.html.twig` + `menu.html.twig` for main menu + CTA button as separate block | Same as homepage |
| 3 | `01-breadcrumb.html` | Drupal breadcrumb block (`system_breadcrumb_block`) → `breadcrumb.html.twig` override | Path-aware; standard Drupal |
| 4 | `02-hero-banner.html` | Paragraph bundle `hero_banner_form` — fields: `field_heading`, `field_subtitle`, `field_hero_image` (media), `field_contact_placeholder`, `field_cta_label`. Phone form can post to a Webform or custom route. | Page-specific hero; do not reuse generic hero paragraph |
| 5 | `03-search-filter.html` | Views exposed form (`views-exposed-form.html.twig`) on the "centres" view, exposing `field_state` (dropdown) and `title` (text search). Optional: custom block if Views AJAX feels heavy. | Populate state options from `state` taxonomy |
| 6 | `04-state-chips.html` | Custom block using a Twig loop over `state` taxonomy terms (`views-view-list.html.twig` from a Views block) — each term → `<li><a href="#state-{{ term.slug }}">{{ term.name }}</a></li>` | Auto-scales with term count |
| 7 | `05-centre-card.html` | View mode `card` on `node--centre` → `node--centre--card.html.twig`. This single Twig file renders every centre card consistently. | Reused inside state sections |
| 8 | `06-state-section.html` | Views display "centres_by_state" with **Grouping field: `field_state`**. Views grouping header = state name (the `<h2>`). Row template = `node--centre--card.html.twig`. | One Views config handles all state sections; no hardcoded states |
| 9 | `07-load-more.html` | `views_load_more` contrib module → renders the "Load More" button under the state sections. Wire `data-centre-load-more` in the override. | No custom AJAX |
| 10 | `08-our-story.html` | Paragraph bundle `text_callout` — fields: `field_heading`, `field_body` (long text). Can be reused on other pages. | Content-managed by editors |
| 11 | `05-specialities.html` (shared) | Paragraph bundle `specialities_accordion` + nested paragraph `speciality_item` (title, bg_color, description, bullets, CTA). Already mapped in homepage mapping doc. | Shared; no new mapping needed |
| 12 | `09-experts-split.html` | Paragraph bundle `split_content` — fields: `field_heading`, `field_body`, `field_cta_label`, `field_cta_link`, `field_media_image`. Reusable across pages. | Mirrors international-patients pattern from homepage |
| 13 | `10-why-cfs.html` | Paragraph bundle `feature_card_grid` containing a field `field_cards` (entity reference to paragraph bundle `feature_card` with `field_heading`). | Variable card count supported |
| 14 | `11-faq.html` | Paragraph bundle `faq_section` with nested paragraph bundle `faq_item` (`field_question`, `field_answer`). Mirrors `cataract-components/15-faq.html` exactly. | Accordion JS lives in `js/main.js` (shared) |
| 15 | `14-callback-form.html` (shared) | Drupal Webform module — "request_a_callback" webform rendered inside a Paragraph `callback_cta` with `field_background_image`. | Shared across pages |
| 16 | `15-footer.html` (shared) | `region--footer.html.twig` split into 3–4 blocks (quick-links, phone numbers, address+social, copyright+sitemap nav). | Same as homepage |
| 17 | `16-sticky-bar.html` (shared) | Custom block rendered inside `region--bottom.html.twig`. CSS handles desktop (chat bubble, right-fixed) vs mobile (full-width bar) via breakpoint visibility. | Same as homepage |

## Layout risks / notes for Drupal team

1. **State sections are grouped via Views grouping, not separate Paragraphs.** This means the Drupal editor adds a centre node and selects its state; the state section appears automatically. Do not expose "state sections" as a Paragraph bundle — it would force editors to duplicate state groupings.

2. **Centre cards should always be rendered by the `node--centre--card.html.twig` template**, not duplicated inline per page. The same template renders on the homepage's centre listing (shared pattern with `html/components/04-centres-listing.html`).

3. **The hero form's `+91` prefix is cosmetic** — the Webform field handles validation. Pass the full raw phone to Webform via hidden field; display the `+91` box as HTML.

4. **Accordion JS is already shared** — when the Drupal team ports FAQ to Twig, do not add per-page JS. Use the existing `data-faq-toggle` handler from `js/main.js` (currently inlined in `centre-cluster.html`; move to `js/main.js` during handoff).

5. **State chip anchors** (`#state-{slug}`) require the state section `id="state-{slug}"` to match exactly. Drupal Twig: `<section id="state-{{ term.slug }}">`. The slug must be a URL-safe machine name — use `\Drupal\Component\Utility\Html::getUniqueId()` or the term's machine name.

6. **No nth-child grid tricks** — the card grid uses `grid-cols-1 md:grid-cols-2 lg:grid-cols-3` which scales cleanly for 1, 2, 3, 4, 5, 6, 7, 8, 9, … cards. Delhi shows 9 (fills 3 rows); Assam shows 1 (left-aligned in row 1). No JS or CSS adjustment needed per count.

7. **The state chip count might grow** — if a new state gets a centre later, Views will auto-include its term in the filter dropdown and auto-emit a chip. No frontend change needed.

## Required Drupal modules (suggested)

- `paragraphs` (core candidate, currently contrib)
- `views_load_more`
- `webform` (for callback form)
- `media` + `media_library`
- `pathauto` (for state term URL aliases)

## Testing checklist for Drupal theme integration

- [ ] Every state in `state` taxonomy emits one chip + one state section
- [ ] Centre node `view_mode: card` renders identically to `05-centre-card.html`
- [ ] FAQ accordion `data-faq-toggle` click opens/closes the answer
- [ ] "Load More" reveals next batch of state sections (or next page of centres within a state — implementer's choice)
- [ ] Mobile hamburger (`data-menu-toggle`) opens full-screen nav overlay
- [ ] Sticky bottom bar visible on mobile, chat bubble visible on desktop (not both)
- [ ] Breadcrumb shows `Home › Locate Us › Eye Hospitals in India`
