# Architecture

How the Parcel2Go Shipping plugin and React app fit together.

## Bootstrap

1. **Plugin entry:** `parcel2go-shipping.php` runs on WordPress load. It defines `PARCEL2GO_SHIPPING_MAIN_PLUGIN_FILE`, loads Composer autoload (`vendor/autoload_packages.php`), and hooks `plugins_loaded` to `parcel2go_shipping_init`.
2. **Init:** After checking WooCommerce is active and loading the text domain, `parcel2go_shipping_init` calls `Parcel2GoShipping::instance()`, adds the "Settings" link on the Plugins screen, and registers REST routes for all API controllers (Orders, Quotes, Countries, Dropshop, Checkout, Payment, Settings, Shipments).
3. **Parcel2GoShipping:** The main class constructor only runs when `is_admin()`; it then instantiates `Parcel2GoShipping\Admin\Setup`.
4. **Setup:** Registers and enqueues the built script (`build/index.js`) and style (`build/index.css`) on WooCommerce Admin pages, and localizes `parcel2goShipping` (REST base URL, Sentry DSN/environment, asset URLs, etc.) for the frontend.

## Admin UI

- **Page registration:** Done in two places:
  - **PHP:** `includes/Admin/Setup.php` uses `wc_admin_register_page()` to register the WC Admin pages: landing (`/parcel2go-shipping`), shipments (`/parcel2go-shipping/shipments`), and settings (`/parcel2go-shipping/settings`).
  - **React:** `src/index.tsx` uses `addFilter('woocommerce_admin_pages_list', ...)` to provide the actual containers and breadcrumbs for those paths.
- **Script/style:** Enqueued only when `PageController::is_admin_or_embed_page()` is true, so the app loads only in the WC Admin context.
- **Localized config:** `parcel2goShipping` includes `apiUrl` (REST base), `dsn` / `environment` (Sentry), `flagsBaseUrl`, `couriersBaseUrl`, `editOrderUrlTemplate`, `storeAddressUrl`, and similar.

## Frontend

- **Entry:** Single React app in `src/index.tsx`. Sentry is initialized first; then the app registers with the `woocommerce_admin_pages_list` filter.
- **Routing:** The main component uses `useNavigation()` and `selectedOrderId`. If `selectedOrderId !== null`, it renders `OrderShipPage`; otherwise it renders `LandingPage`. Settings and Previous Shipments are lazy-loaded and rendered via the WC Admin page list (containers for `/parcel2go-shipping/settings` and `/parcel2go-shipping/shipments`).
- **Flow:** User starts on the landing page, picks an order to ship ("Ship now"), then goes through Order Ship (quotes, service selection, booking, payment). Settings and Shipments are separate flows from the sidebar/menu.

## High-level data flow

```mermaid
flowchart LR
	Landing[LandingPage]
	OrderShip[OrderShipPage]
	Quotes[Quotes]
	Booking[Booking]
	Payment[Payment]
	Complete[Complete]
	Settings[Settings]
	Shipments[Shipments]

	Landing -->|"Ship now"| OrderShip
	OrderShip --> Quotes
	Quotes --> Booking
	Booking --> Payment
	Payment --> Complete
	Settings --> Landing
	Shipments --> Landing
```

Landing shows orders; choosing one opens Order Ship. Order Ship fetches quotes, then checkout/validate, then payment (Braintree or prepay), then order completion. Settings and Previous Shipments are separate pages.

## Key directories

| Path | Purpose |
|------|--------|
| `includes/` | PHP backend: `Api/` (REST controllers), `Helpers/` (OrderCompletionService, OrderFormatter, P2GApiClient, etc.), `Constants/P2GApi.php`, `Admin/Setup.php` |
| `src/` | React app: `index.tsx` (entry), `pages/` (LandingPage, OrderShipPage, SettingsPage, PreviousShipmentsPage), `features/` (order-ship, settings, shipments, orders), `shared/` (components, hooks, utils, sentry), `types/`, `constants/`, `public/couriers/` (and flags) |
| `build/` | Output of `npm run build`: `index.js`, `index.asset.php`, `index.css` |
| `vendor/` | Composer autoload; plugin requires `vendor/autoload_packages.php` |
