# RIU Company Admin — Frontend

React admin dashboard for company ESG reporting: data management, KPI configuration, audits, dashboards, and settings. Talks to the NestJS API in the sibling repo [`riu-company-admin-backend`](../riu-company-admin-backend).

Built with Create React App (react-scripts 4) on **React 16.14**.

## Getting started

```bash
npm install
npm start          # dev server on http://localhost:3000
```

The app expects the backend API to be running; endpoint base URLs live in `src/config/config.js`.

## Scripts

| Command | What it does |
|---|---|
| `npm start` | Dev server with hot reload |
| `npm test` | Jest in interactive watch mode |
| `CI=true npx react-scripts test --watchAll=false` | One-off test run (CI style) |
| `NODE_OPTIONS=--openssl-legacy-provider npm run build` | Production build into `build/` |

> **Build fails with `ERR_OSSL_EVP_UNSUPPORTED`?** react-scripts 4 uses webpack 4, which is incompatible with the OpenSSL shipped in Node 17+. Prefix the build with `NODE_OPTIONS=--openssl-legacy-provider` (already shown above), or build on Node 16.

## Project structure

```
src/
  _services/          apiCall wrapper (auth headers, global alerts) + alert service
  config/             environment / endpoint configuration
  globalComponents/   shared UI (dropdowns, spinner, form controls)
  hooks/              shared hooks (usePermission, …)
  component/          feature areas (Settings, DataManagment, audit, dashboards, …)
```

### Feature folders

New/refactored pages follow a feature-folder layout — see `src/component/Settings/KpiAssets/` for the reference implementation:

```
KpiAssets/
  index.jsx             page component (default export; folder resolves the old import path)
  kpiAssetApi.js        every API call as a named function — components never build URLs
  useKpiAssetsData.js   data hook: race-guarded fetch, background refresh, error + retry
  useSaveMappings.js    shared save-mutation hook (saving/error state, one endpoint call)
  AddAssetPanel.jsx     feature components
  KpiAssetRow.jsx / AssetRows.jsx / KpiList.jsx / CopyFromFYModal.jsx
  helpers.js            pure domain logic
  __tests__/            unit tests for helpers
  KpiAssets.css         scoped styles (feature class prefix + CSS-variable tokens)
```

Conventions worth knowing before contributing:

- **Styling** is scoped CSS per feature (e.g. `.kpa-*` classes) with design tokens as CSS variables. No global selectors inside components; hover/focus via CSS pseudo-classes, not mouse-event style mutation.
- **Data flows down from hooks**; components render from props (no copying props into state). After a mutation, call the hook's `refresh()` — it re-fetches in the background without unmounting the page.
- **MySQL `tinyint` booleans arrive as `0`/`1`** — always use truthy/falsy checks, never `=== true`.
- **Bulk actions call one bulk endpoint.** If the backend lacks one, add it there rather than looping single-item requests.
- **One endpoint, one builder.** When several components call the same endpoint, build the request body in a single pure helper (e.g. `KpiAssets/helpers.js` `buildMapping`) and share the mutation lifecycle (saving/error state, post-save refresh) through a hook (e.g. `useSaveMappings`) instead of duplicating either per component.
- **Comments are JSDoc only.** Document code with `/** … */` blocks on the declaration (function, component, hook, or `const`). No inline `//` comments inside function bodies and no `{/* section */}` markers in JSX — fold anything worth keeping into the nearest declaration's JSDoc.

## Testing

```bash
CI=true npx react-scripts test --watchAll=false                                # all tests
CI=true npx react-scripts test --watchAll=false --testPathPattern="KpiAssets"  # one feature
```

Tests live next to their feature in `__tests__/` and focus on pure logic (helpers, validation rules). `src/setupTests.js` wires jest-dom.

## Feature notes: KPI Asset Settings

`Settings → KPI Assets` maps assets (location-scoped) or global assets (KPI-wide) to emission KPIs per financial year:

- Each KPI holds a single scope: all location assets or all global assets, never mixed.
- Asset names are unique per KPI + unit (or per KPI for global); the same name may exist across KPIs.
- **Multi-add mode** (top-bar button) ticks KPIs directly in the list and saves one bulk request; names that already exist in some selected KPIs are skipped and reported, not blocked.
- Renaming/deleting an asset that also exists in other KPIs offers a cross-KPI apply, backed by bulk endpoints.
- Deletes are refused by the backend when reported data references the mapping (bulk deletes skip and report those rows).
- Renames apply across financial years — asset names are shared between FYs that copied the same mappings.
