# AdAstra App

Frontend of the AdAstra platform — a multi-domain Angular application covering e-commerce, CMS, skydive club management, and Hero Wars guild analytics.

## Tech stack

| Layer     | Choice                                                             |
| --------- | ------------------------------------------------------------------ |
| Framework | Angular 21 (standalone components, no NgModules)                   |
| Language  | TypeScript 5.9 — strict mode + strictTemplates                     |
| UI        | Angular Material 21, Bootstrap 5                                   |
| Charts    | Chart.js 4 (ng2-charts), Chartist                                  |
| HTTP      | Angular HttpClient with three interceptors (base URL, JWT, errors) |
| Tests     | Karma + Jasmine                                                    |
| Linting   | angular-eslint + Prettier (enforced via lint-staged)               |
| Node      | `^20.19.0 \|\| ^22.12.0`                                           |

## Related repository

The backend API lives in [`adastra_api`](../adastra_api) — an Express + Sequelize stack, routes grouped under `/api/ecommerce`, `/api/cms`, `/api/skydive`, `/api/herowars`.

## Getting started

```bash
npm install
npm run local    # dev server on :4400, uses environment.local.ts
```

Copy and configure your local environment:

```bash
cp src/environments/environment.example.ts src/environments/environment.local.ts
# fill in: apiBaseUrl, apiKey, googleMapApiKey, …
```

## Commands

| Command         | Description                                           |
| --------------- | ----------------------------------------------------- |
| `npm start`     | Dev server on :4200 with production config            |
| `npm run dev`   | Dev server on :4300 with `environment.development.ts` |
| `npm run local` | Dev server on :4400 with `environment.local.ts`       |
| `npm run build` | Production build → `dist/adastra_angular/`            |
| `npm run watch` | Incremental build in development configuration        |
| `npm run lint`  | angular-eslint on `**/*.ts` and `**/*.html`           |
| `npm test`      | Karma + Jasmine unit tests                            |

Run a single spec:

```bash
ng test --include src/path/to/file.spec.ts
```

## Architecture

### Bootstrap

`AppComponent` renders a single `FullComponent` shell (Material sidenav + toolbar). Routes are split into two arrays in `app.routes.ts`:

- `auth.routes.ts` — protected by `authGuard`; admin sections additionally require `adminGuard`
- `noauth.routes.ts` — public pages and auth entry points, blocked by `noauthGuard` when already authenticated

Data is pre-fetched by resolvers under `src/app/core/resolvers/` — new route components should follow this pattern rather than fetching in `ngOnInit`.

### HTTP pipeline

Three interceptors applied in order:

1. **`apiInterceptor`** — prepends `environment.apiBaseUrl` to every request. Services use relative paths (`/cms/user`, `/skydive/jumps`, …), never absolute URLs.
2. **`tokenInterceptor`** — attaches `Authorization: Token <jwt>` when a token exists in `localStorage['jwtToken']`.
3. **`errorInterceptor`** — unwraps `err.error` and rethrows.

### Feature domains

| Domain     | Routes                                                 | Backend prefix   |
| ---------- | ------------------------------------------------------ | ---------------- |
| E-commerce | `products`, `product/:slug`, `products/:category`      | `/api/ecommerce` |
| CMS        | `pages`, `page/:slug`, `home`, profiles, articles      | `/api/cms`       |
| Skydive    | `skydive/*` — aeronefs, canopies, dropzones, jumps     | `/api/skydive`   |
| Hero Wars  | Guild analytics, weekly snapshots in `src/files-data/` | `/api/herowars`  |

### Path aliases

Defined in `tsconfig.json`; always prefer them over relative imports:

```
@components   @services    @models      @guards
@interceptors @resolvers   @viewmodels  @interfaces
@constants    @core/*      @environments/*
@data/*       @assets/*    @styles/*
```

When adding a new file, export it from the appropriate `index.ts` barrel so the alias resolves correctly.

### Styling

SCSS with `includePaths: ["src/styles"]` — imports like `@use 'variables'` resolve globally. Material date locale is set to `fr-FR` with `DD/MM/YYYY` format.
