# Architecture ## Process Model ImEX RPS has two main runtimes: - Electron main process: window lifecycle, native menus, file system access, estimate decoding, file watching/scanning, audit file dialogs, updater, app-level settings, analytics, and IPC. - React renderer process: UI, routing, Redux state, Apollo GraphQL operations, Firebase auth, and renderer-side IPC listeners. The renderer does not get Node integration. The preload script exposes a controlled bridge: - `window.ipcRenderer.send(channel, data)` - `window.ipcRenderer.on(channel, handler)` - `window.ipcRenderer.invoke(channel, data)` - `window.ipcRenderer.removeAllListeners(...)` - `window.logger.*` ## Entrypoints Electron: - `electron/main.js` decides whether to run the source main file or bundled `dist-electron/main.cjs`. - `electron/main-src.js` is the main source file. - `electron/preload.js` decides whether to run the source preload or bundled `dist-electron/preload.cjs`. - `electron/preload-src.js` exposes IPC/logger bridges. - `scripts/build-electron.mjs` bundles main/preload outputs. Renderer: - `src/index.jsx` initializes Sentry renderer, Redux Provider, `MemoryRouter`, `PersistGate`, and ``. - `src/App/App.jsx` initializes Apollo, AntD context/theme, auth session check, IPC side effects, and authorized/unauthorized routing. - `src/components/pages/routes/routes.page.jsx` renders the main app shell and routes. ## Routing Routes are memory-router routes because this is an Electron app: - `/` Jobs - `/settings` Settings - `/reporting` Reporting - `/audit` Audit - `/scan` Scan - `/admin` Admin The app shell includes the side menu, notifications modal, release notes, and update manager. ## Redux Shape Store setup: - `src/redux/store.js` - Redux core `legacy_createStore` - Saga middleware - Redux logger in development - Redux DevTools compose if present - redux-persist wrapper with all active reducers currently blacklisted Reducers: - `application`: watcher status, watched paths, selected job id, selected target percent, settings, update state, release notes, estimate scrubber results. - `user`: current user, bodyshop, targets, fingerprint, auth errors, notifications, dark mode. - `reporting`: report date range, report rows, scorecard, audit data/errors/loading, excluded ids, cached jobs. - `scan`: scan loading state, last scanned, estimate list. Sagas: - `applicationSagas` - `userSagas` - `reportingSagas` - `scanSagas` ## Data Flow for Estimate Import 1. User configures `filePaths` in settings. 2. Electron store persists those paths. 3. `electron/file-watcher/file-watcher.js` watches paths with chokidar. 4. New/changed estimate files are decoded by `electron/decoder/decoder.js`. 5. Main process sends decoded payloads over IPC. 6. Renderer `src/ipc/ipc-renderer-handler.js` receives decoded estimates. 7. Renderer GraphQL helper `UpsertEstimate` writes jobs/joblines to Hasura. 8. Jobs UI queries data back through Apollo. ## Data Flow for Job Details 1. A list item dispatches selected job id to Redux `application`. 2. `jobs-detail.organism.jsx` debounces selected id briefly to avoid rendering a stale/partial left panel. 3. Apollo queries `QUERY_JOB_BY_PK`. 4. Detail subcomponents render job metadata, joblines, targets, group controls, claims clerk, estimate scrubber, and other actions. ## IPC Contract IPC channel names live in `src/ipc.types.json`, imported by: - `src/ipc.types.js` for ESM renderer code. - `src/ipc.types.commonjs.js` for CommonJS Electron code. When adding IPC: - Add channel names to `src/ipc.types.json`. - Register main handlers in the relevant Electron module. - Register renderer listeners in `src/ipc/ipc-renderer-handler.js` or a local component effect. - Keep handlers idempotent when possible; repeated imports/listeners can create duplicate events.