feature/IO-3725-RPS-Changes - Add AI context files, fix auto start dev tools in local
This commit is contained in:
103
.ai/architecture.md
Normal file
103
.ai/architecture.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# 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 `<App />`.
|
||||
- `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.
|
||||
|
||||
113
.ai/data-graphql-hasura.md
Normal file
113
.ai/data-graphql-hasura.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# Data, GraphQL, Hasura, and Auth Guide
|
||||
|
||||
## GraphQL Client
|
||||
|
||||
Apollo setup lives in `src/graphql/GraphQLClient.js`.
|
||||
|
||||
Links:
|
||||
|
||||
- `HttpLink` uses `import.meta.env.VITE_APP_GRAPHQL_ENDPOINT`.
|
||||
- `authLink` reads Firebase current user token and attaches `Authorization: Bearer <token>`.
|
||||
- `RetryLink` retries transient failures.
|
||||
- `onError` logs GraphQL/network errors.
|
||||
- `SentryLink` records Apollo operations/errors.
|
||||
- `apollo-link-logger` is included in development.
|
||||
|
||||
Default options:
|
||||
|
||||
- `query.fetchPolicy = "network-only"`
|
||||
- `watchQuery.fetchPolicy = "network-only"`
|
||||
- `connectToDevTools` enabled outside production
|
||||
|
||||
Cache:
|
||||
|
||||
- `Query.jobs` uses offset merge policy.
|
||||
- `Query.search_jobs` uses offset merge policy.
|
||||
|
||||
This avoids Apollo "Cache data may be lost when replacing the jobs field" warnings during pagination.
|
||||
|
||||
## GraphQL Operation Files
|
||||
|
||||
- `src/graphql/jobs.queries.js`: job insert, latest pagination, search pagination, job by id, job by claim number, close date lookup, update/delete, estimate scrubber query.
|
||||
- `src/graphql/joblines.queries.js`: jobline update.
|
||||
- `src/graphql/bodyshop.queries.js`: current bodyshop, shop update, notifications.
|
||||
- `src/graphql/user.queries.js`: user upsert/login association.
|
||||
- `src/graphql/reporting.queries.js`: report data.
|
||||
- `src/graphql/notification.queries.js`: accept notification.
|
||||
- `src/graphql/veh_group.queries.js`: vehicle group lookup.
|
||||
|
||||
## Hasura Layout
|
||||
|
||||
Hasura project files:
|
||||
|
||||
- `hasura/config.yaml`
|
||||
- `hasura/config.yaml.prod`
|
||||
- `hasura/metadata/`
|
||||
- `hasura/migrations/default/`
|
||||
- `hasura/migrations_backup/`
|
||||
|
||||
Important metadata:
|
||||
|
||||
- `hasura/metadata/databases/default/tables/`
|
||||
- `hasura/metadata/databases/default/functions/public_search_jobs.yaml`
|
||||
|
||||
Important tables:
|
||||
|
||||
- `users`
|
||||
- `bodyshops`
|
||||
- `associations`
|
||||
- `jobs`
|
||||
- `joblines`
|
||||
- `targets`
|
||||
- `veh_groups`
|
||||
- `groupings`
|
||||
- `notifications`
|
||||
|
||||
Important function:
|
||||
|
||||
- `search_jobs`
|
||||
|
||||
## Core Relationships
|
||||
|
||||
- `users.email` links to `associations.email`.
|
||||
- `associations.bodyshopid` links users to bodyshops.
|
||||
- `jobs.bodyshopid` links jobs to bodyshops.
|
||||
- `joblines.jobid` links joblines to jobs.
|
||||
- Notifications can target a bodyshop.
|
||||
|
||||
## Schema Evolution Notes
|
||||
|
||||
The `jobs` and `joblines` schema has grown significantly over time. Do not assume the original create-table migrations show the current shape.
|
||||
|
||||
Recent-ish/important fields include:
|
||||
|
||||
- `jobs`: `close_date`, `loss_date`, `v_age`, `v_mileage`, `group`, `group_verified`, `requires_reimport`, `ins_rule_set`-related usage through bodyshop settings, owner fields, impact fields, totals/rates JSON, vehicle stage, theft/tlos/insp fields, supplement/betterment amounts, ES fields.
|
||||
- `joblines`: `line_no`, `db_ref`, `price_diff`, `price_diff_pc`, `ignore`, ADAS/claims clerk/ruleset fields, labor/part flags, tax/cert/glass flags, line refs, modified labor/price fields.
|
||||
- `bodyshops`: `accepted_ins_co`, `targets`, `groups`, `features`, `channel`, `phone`, `zip_post`, `es_api_key`, `mpi_count_quantity`, `carfax_exclude`, `ins_rule_set`.
|
||||
|
||||
Use Hasura metadata and current GraphQL query selections to confirm exact field names before changing queries or migrations.
|
||||
|
||||
## Authentication
|
||||
|
||||
Firebase auth utilities live in `src/firebase/firebase.utils.js`.
|
||||
|
||||
Renderer startup:
|
||||
|
||||
1. `src/index.jsx` mounts Redux and App.
|
||||
2. `src/App/App.jsx` dispatches `checkUserSession`.
|
||||
3. User sagas validate/load user state.
|
||||
4. Apollo auth link uses the current Firebase token for GraphQL.
|
||||
|
||||
If a user has no shop access, `RoutesPage` renders a "No shop access" error result.
|
||||
|
||||
## Data Import Boundary
|
||||
|
||||
Electron main decodes local DBF files. Renderer writes decoded results to Hasura. This means import bugs may straddle:
|
||||
|
||||
- DBF decoding in `electron/decoder/decoder.js`.
|
||||
- IPC payloads in `src/ipc/ipc-renderer-handler.js`.
|
||||
- GraphQL upsert helpers in `src/ipc/ipc-estimate-utils.js`.
|
||||
- Hasura insert/update permissions and constraints.
|
||||
|
||||
When debugging import issues, inspect all four layers.
|
||||
|
||||
111
.ai/domain-glossary.md
Normal file
111
.ai/domain-glossary.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# Domain Glossary
|
||||
|
||||
This glossary captures terms that appear in code, database fields, and UI.
|
||||
|
||||
## Business Terms
|
||||
|
||||
- RPS: Repair Performance System, the desktop app/product.
|
||||
- Bodyshop: A repair shop/account using the app.
|
||||
- Association: Link between a user email and a bodyshop.
|
||||
- Job: A repair claim/estimate record.
|
||||
- Jobline: A line item within a repair estimate.
|
||||
- Claim number / `clm_no`: Claim identifier used for lookup/search.
|
||||
- RO number / `ro_number`: Repair order number.
|
||||
- Insurer / `ins_co_nm`: Insurance company name on a job.
|
||||
- Accepted insurers / `accepted_ins_co`: Shop-specific list of insurers to accept/import.
|
||||
- Close date: Claim close date, used in reporting and ruleset selection.
|
||||
- Loss date: Date of loss, used by job queries and reporting.
|
||||
- Vehicle group / `group`: Group assignment based on vehicle make/type/age and configured rules.
|
||||
- Target: Target percentage used in RPS calculations.
|
||||
- Grouping: Hasura data that maps vehicle make/type/date ranges to groups.
|
||||
- Group verified: User/shop-confirmed group assignment.
|
||||
- Requires reimport: Flag indicating a job should be reimported because decoded data or rules changed.
|
||||
|
||||
## Estimate/File Terms
|
||||
|
||||
- EMS: Estimate Management Standard file set. The app watches for estimate files in local folders.
|
||||
- DBF: dBASE file format used by decoded estimate data.
|
||||
- AD1/AD2: Estimate DBF files decoded by `electron/decoder/decoder.js`.
|
||||
- LIN: Estimate line DBF file.
|
||||
- VEH: Vehicle DBF file.
|
||||
- TTL: Totals DBF file.
|
||||
- PFH/PFL/PFM/STL: Additional estimate/system DBF files decoded when present.
|
||||
- Watch path: Local directory watched by chokidar.
|
||||
- File scan: Manual scan of configured watch paths.
|
||||
- Import: Decode local estimate files and upsert the resulting job/joblines into Hasura.
|
||||
|
||||
## Rules and Programs
|
||||
|
||||
- MPI: Manitoba Public Insurance, a ruleset/insurer context used heavily in targets and line rules.
|
||||
- SGI: Saskatchewan Government Insurance, another ruleset context. Some UI warns SGI eligibility rules may fall back to MPI rules.
|
||||
- RCC: A reporting/eligibility flag surfaced as `sgi_rcc`/RCC-related UI.
|
||||
- Ruleset: Date/rule bundle used by decoder logic to mark/interpret joblines.
|
||||
- V1/V2/V3 rulesets: Decoder-era rulesets selected by close date.
|
||||
- Claims Clerk: Domain rule engine that flags line-level issues/alerts.
|
||||
- Estimate Scrubber / ES: External API workflow that validates/scrubs estimate JSON and returns a report.
|
||||
- ES API key: Shop-specific API key stored on `bodyshops.es_api_key`.
|
||||
|
||||
## Common Database Fields
|
||||
|
||||
Jobs:
|
||||
|
||||
- `id`: UUID primary key.
|
||||
- `bodyshopid`: Owning bodyshop.
|
||||
- `clm_no`: Claim number.
|
||||
- `ro_number`: Repair order number.
|
||||
- `ins_co_nm`: Insurer name.
|
||||
- `close_date`: Claim close date.
|
||||
- `loss_date`: Loss date.
|
||||
- `v_vin`: Vehicle VIN.
|
||||
- `v_makedesc` / `v_model`: Vehicle make/model.
|
||||
- `v_model_yr`: Vehicle model year.
|
||||
- `v_type`: Vehicle type.
|
||||
- `v_age`: Vehicle age.
|
||||
- `v_mileage`: Vehicle mileage.
|
||||
- `group`: Vehicle group.
|
||||
- `group_verified`: Whether group was manually verified.
|
||||
- `rates`, `totals`: JSON estimate rate/total blobs.
|
||||
- `requires_reimport`: Indicates data should be imported again.
|
||||
|
||||
Joblines:
|
||||
|
||||
- `id`: UUID primary key.
|
||||
- `jobid`: Parent job.
|
||||
- `line_no`: Estimate line number.
|
||||
- `unq_seq`: Source unique sequence id.
|
||||
- `line_ind`: Source line indicator.
|
||||
- `line_desc`: Line description.
|
||||
- `part_type`: Part type/category.
|
||||
- `db_price`: Database/reference price.
|
||||
- `act_price`: Actual price.
|
||||
- `price_diff`, `price_diff_pc`: Price difference fields.
|
||||
- `ignore`: Whether line is excluded from calculations.
|
||||
- `alerts`: Rules/claims-clerk alert payload.
|
||||
- `line_ref`: Parent/source line reference.
|
||||
|
||||
Bodyshops:
|
||||
|
||||
- `shopname`: Shop display name.
|
||||
- `accepted_ins_co`: JSON array of accepted insurers.
|
||||
- `targets`: JSON target config.
|
||||
- `groups`: JSON group config.
|
||||
- `features`: Feature config.
|
||||
- `channel`: Update/release channel.
|
||||
- `es_api_key`: Estimate scrubber key.
|
||||
- `ins_rule_set`: Shop ruleset, such as SGI.
|
||||
|
||||
## UI/Code Abbreviations
|
||||
|
||||
- `pct`, `pc`: Percent.
|
||||
- `ppd`: Price/part difference domain abbreviation used in settings/alerts.
|
||||
- `rps`: Repair performance score/system.
|
||||
- `asgn`: Assignment.
|
||||
- `insp`: Inspection.
|
||||
- `ded`: Deductible.
|
||||
- `supp`: Supplement.
|
||||
- `tlos`: Total loss indicator.
|
||||
- `prt`: Part.
|
||||
- `lbr`: Labor.
|
||||
- `amt`: Amount.
|
||||
- `qty`: Quantity.
|
||||
|
||||
152
.ai/electron-main.md
Normal file
152
.ai/electron-main.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# Electron Main, IPC, and Packaging Guide
|
||||
|
||||
## Main Files
|
||||
|
||||
- `electron/main.js`: Launch shim. Chooses bundled `dist-electron/main.cjs` in packaged mode when present, otherwise source.
|
||||
- `electron/main-src.js`: Source of truth for main process behavior.
|
||||
- `electron/preload.js`: Launch shim for preload.
|
||||
- `electron/preload-src.js`: Source preload bridge.
|
||||
- `scripts/build-electron.mjs`: Builds `dist-electron/main.cjs` and `dist-electron/preload.cjs`.
|
||||
|
||||
## Main Process Responsibilities
|
||||
|
||||
`electron/main-src.js` handles:
|
||||
|
||||
- App/window lifecycle.
|
||||
- Application menu.
|
||||
- Sentry main process setup.
|
||||
- Auto-updater and update IPC.
|
||||
- DevTools configuration.
|
||||
- Third-party notice window.
|
||||
- Single-instance locking.
|
||||
- Tray behavior on minimize.
|
||||
- Initializing `electron-store`.
|
||||
- Loading IPC handlers.
|
||||
- Dynamic ESM imports for ESM-only Electron packages.
|
||||
|
||||
## Store Initialization
|
||||
|
||||
`electron-store` v11 is ESM-only. The app uses `electron/electron-store.js`:
|
||||
|
||||
- `initializeStore()` dynamically imports and creates the store.
|
||||
- `store` is a proxy that throws if accessed before initialization.
|
||||
|
||||
`main-src.js` must call:
|
||||
|
||||
```js
|
||||
await initializeStore();
|
||||
initializeIpcHandlers();
|
||||
```
|
||||
|
||||
before modules such as analytics, watcher, scanner, audit, or decoder read `store`.
|
||||
|
||||
Store defaults include:
|
||||
|
||||
- `deviceId`
|
||||
- `showChangeLog`
|
||||
- `enableNotifications`
|
||||
- `filePaths`
|
||||
- `accepted_ins_co`
|
||||
- `runWatcherOnStartup`
|
||||
- `polling`
|
||||
- `ins_rule_set`
|
||||
|
||||
## ESM-Only Package Notes
|
||||
|
||||
Current major upgrades made these ESM-only:
|
||||
|
||||
- `electron-context-menu`
|
||||
- `electron-store`
|
||||
- `electron-is-dev`
|
||||
|
||||
The app no longer uses `electron-is-dev`; it uses `!app.isPackaged` in main and `process.defaultApp`/`process.execPath` detection in preload.
|
||||
|
||||
Use dynamic import for `electron-context-menu`:
|
||||
|
||||
```js
|
||||
const { default: contextMenu } = await import("electron-context-menu");
|
||||
```
|
||||
|
||||
## Sentry Electron
|
||||
|
||||
Current dependency: `@sentry/electron@^7.13.0`.
|
||||
|
||||
Main process import:
|
||||
|
||||
```js
|
||||
const Sentry = require("@sentry/electron/main");
|
||||
```
|
||||
|
||||
Renderer import:
|
||||
|
||||
```js
|
||||
import * as Sentry from "@sentry/electron/renderer";
|
||||
```
|
||||
|
||||
Main setup uses:
|
||||
|
||||
```js
|
||||
ipcMode: Sentry.IPCMode.Protocol
|
||||
```
|
||||
|
||||
Keep protocol mode unless deliberately changing Sentry IPC behavior. It avoids the deprecated Electron preload path Sentry can otherwise use.
|
||||
|
||||
## DevTools
|
||||
|
||||
Current behavior:
|
||||
|
||||
- Dev mode: DevTools enabled and auto-open unless `ELECTRON_OPEN_DEVTOOLS=0`.
|
||||
- Packaged mode: DevTools disabled unless `ELECTRON_ENABLE_DEVTOOLS=1`.
|
||||
- Packaged auto-open: requires `ELECTRON_OPEN_DEVTOOLS=1`.
|
||||
- React DevTools extension installation: opt-in with `ELECTRON_INSTALL_REACT_DEVTOOLS=1`.
|
||||
|
||||
Chrome DevTools can emit Electron backend console noise such as `Autofill.enable` and `Autofill.setAddresses` protocol errors. That noise is tied to DevTools/extension behavior, not app runtime failure.
|
||||
|
||||
## IPC Modules
|
||||
|
||||
Shared registration:
|
||||
|
||||
- `electron/ipc-main-handler.js`
|
||||
|
||||
Imported modules:
|
||||
|
||||
- `electron/file-watcher/file-watcher-ipc.js`
|
||||
- `electron/file-scan/file-scan-ipc.js`
|
||||
- `electron/audit/audit-ipc.js`
|
||||
|
||||
Avoid importing `mainWindow` from `main-src.js` in IPC modules. That caused circular dependency warnings. Use:
|
||||
|
||||
```js
|
||||
const parentWindow = BrowserWindow.fromWebContents(event.sender);
|
||||
```
|
||||
|
||||
for dialog parents, or `BrowserWindow.getAllWindows()[0]` for broadcast-style interactions when necessary.
|
||||
|
||||
## Packaging
|
||||
|
||||
`package.json` contains electron-builder config.
|
||||
|
||||
Important scripts:
|
||||
|
||||
- `npm run build:electron`: generates `dist-electron/`.
|
||||
- `npm run pack`: local unpacked package check with `--publish never` and `electron-builder.pack-check.cjs`.
|
||||
- `npm run dist`: full build/package using package config.
|
||||
- `npm run distp`: publishes. Use only when explicitly requested.
|
||||
- `npm run distnopublish`: full build/package with publishing disabled.
|
||||
|
||||
`electron-builder.pack-check.cjs` disables Azure Trusted Signing config for pack checks:
|
||||
|
||||
```js
|
||||
azureSignOptions: null
|
||||
```
|
||||
|
||||
The pack check may still locally sign the unpacked executable with signtool. That is not publishing.
|
||||
|
||||
Generated artifacts:
|
||||
|
||||
- `dist-electron/`: bundled main/preload, ignored.
|
||||
- `build/`: renderer production build, ignored.
|
||||
- `dist/`: electron-builder output, ignored.
|
||||
|
||||
Do not manually edit generated artifacts.
|
||||
|
||||
127
.ai/file-map.md
Normal file
127
.ai/file-map.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# File Map
|
||||
|
||||
Use this as a quick locator before making changes.
|
||||
|
||||
## Root
|
||||
|
||||
- `package.json`: scripts, dependencies, electron-builder config, product metadata.
|
||||
- `package-lock.json`: npm dependency lock.
|
||||
- `vite.config.js`: Vite renderer config.
|
||||
- `index.html`: Vite app HTML entry.
|
||||
- `README.md`: old Create React App boilerplate; partially stale.
|
||||
- `Usage.md`: release usage notes; ignored by git but present.
|
||||
- `deployment.md`: deployment note; very terse.
|
||||
- `update-targets.md`: historical GraphQL target load example.
|
||||
- `SGI.md`: SGI-related domain notes.
|
||||
- `electron-builder.pack-check.cjs`: no-publish local packaging config for `npm run pack`.
|
||||
- `.gitignore`: generated artifacts and local secret files.
|
||||
|
||||
## Electron
|
||||
|
||||
- `electron/main.js`: chooses source or bundled main process.
|
||||
- `electron/main-src.js`: main process source of truth.
|
||||
- `electron/preload.js`: chooses source or bundled preload.
|
||||
- `electron/preload-src.js`: context bridge for IPC/logger.
|
||||
- `electron/ipc-main-handler.js`: shared IPC registration.
|
||||
- `electron/electron-store.js`: async ESM-compatible electron-store wrapper.
|
||||
- `electron/analytics.js`: Amplitude analytics IPC.
|
||||
- `electron/changelog.json`: versioned release notes.
|
||||
- `electron/licenses.txt`: third-party notice content shown in the app.
|
||||
- `electron/file-watcher/`: chokidar watcher and watcher IPC.
|
||||
- `electron/file-scan/`: manual scan/delete estimate file logic and IPC.
|
||||
- `electron/decoder/`: DBF estimate decoding and ruleset application.
|
||||
- `electron/claims-clerk/`: line-level alert rules.
|
||||
- `electron/audit/`: audit spreadsheet dialog/parsing IPC.
|
||||
- `electron/estimate-scrubber/`: external estimate scrubber API integration.
|
||||
- `electron/notification-wrapper/`: native notification helper.
|
||||
|
||||
## Renderer Entrypoints
|
||||
|
||||
- `src/index.jsx`: React root, Redux Provider, MemoryRouter, PersistGate, Sentry renderer.
|
||||
- `src/App/App.jsx`: Apollo provider, AntD theme/app provider, auth check, top-level IPC side effects.
|
||||
- `src/App/App.styles.scss`: app-level styles.
|
||||
- `src/index.css`: global CSS.
|
||||
|
||||
## Renderer Components
|
||||
|
||||
- `src/components/pages/routes/routes.page.jsx`: authenticated app shell and routes.
|
||||
- `src/components/pages/jobs/`: main jobs page.
|
||||
- `src/components/pages/reporting/`: reporting page.
|
||||
- `src/components/pages/audit/`: audit page.
|
||||
- `src/components/pages/scan/`: scan page.
|
||||
- `src/components/pages/settings/`: settings page.
|
||||
- `src/components/pages/admin/`: admin page.
|
||||
- `src/components/pages/sign-in/`: sign-in page.
|
||||
- `src/components/organisms/jobs-list-latest/`: latest jobs infinite list.
|
||||
- `src/components/organisms/jobs-list-search/`: search jobs infinite list.
|
||||
- `src/components/organisms/jobs-detail/`: selected job detail panel.
|
||||
- `src/components/organisms/watcher-manager/`: file watcher controls.
|
||||
- `src/components/organisms/shop-settings/`: shop settings workflows.
|
||||
- `src/components/organisms/update-manager/`: updater UI.
|
||||
- `src/components/organisms/notification-modal/`: notification UI.
|
||||
- `src/components/molecules/jobs-lines-table/`: jobline table.
|
||||
- `src/components/molecules/estimate-scruber-results/`: estimate scrubber results UI. Note the folder name contains `scruber`.
|
||||
- `src/components/molecules/estimate-scrubber-button/`: estimate scrubber action.
|
||||
- `src/components/molecules/reporting-dates/`: reporting date range picker.
|
||||
- `src/components/templates/error-boundary.template.jsx`: app error boundary.
|
||||
- `src/components/templates/ipc-upsert-job/`: IPC import/upsert template.
|
||||
|
||||
## State
|
||||
|
||||
- `src/redux/store.js`: store, saga middleware, logger, persist store.
|
||||
- `src/redux/root.reducer.js`: combines reducers.
|
||||
- `src/redux/root.saga.js`: combines sagas.
|
||||
- `src/redux/application/`: watcher/app/update/selection/scrubber state.
|
||||
- `src/redux/user/`: auth/bodyshop/targets/notifications/dark mode.
|
||||
- `src/redux/reporting/`: report/audit/scorecard state.
|
||||
- `src/redux/scan/`: scan state.
|
||||
|
||||
## GraphQL and Auth
|
||||
|
||||
- `src/graphql/GraphQLClient.js`: Apollo links, auth, retry, Sentry, cache policies.
|
||||
- `src/graphql/jobs.queries.js`: job queries/mutations.
|
||||
- `src/graphql/joblines.queries.js`: jobline mutations.
|
||||
- `src/graphql/bodyshop.queries.js`: shop and notifications.
|
||||
- `src/graphql/user.queries.js`: user upsert/auth lookup.
|
||||
- `src/graphql/reporting.queries.js`: reporting queries.
|
||||
- `src/graphql/notification.queries.js`: notification acceptance.
|
||||
- `src/graphql/veh_group.queries.js`: vehicle groups.
|
||||
- `src/firebase/firebase.utils.js`: Firebase auth/app setup.
|
||||
|
||||
## IPC
|
||||
|
||||
- `src/ipc.types.json`: canonical IPC channel map.
|
||||
- `src/ipc.types.js`: ESM wrapper.
|
||||
- `src/ipc.types.commonjs.js`: CommonJS wrapper.
|
||||
- `src/ipc/ipc-renderer-handler.js`: central renderer IPC listeners.
|
||||
- `src/ipc/ipc-estimate-utils.js`: estimate upsert and close-date GraphQL helpers.
|
||||
|
||||
## Utilities and Assets
|
||||
|
||||
- `src/util/antdFeedback.js`: context-safe AntD message/notification bridge.
|
||||
- `src/util/day.js`: day/date setup.
|
||||
- `src/util/CalculateJobRps.js`: RPS calculation utility.
|
||||
- `src/util/GetJobTarget.js`: target calculation utility.
|
||||
- `src/util/decimalPrecision.js`: numeric precision utility.
|
||||
- `src/util/sorters.js`: table/list sort helpers.
|
||||
- `src/assets/`: app logos/images.
|
||||
- `src/icons/`: app icons by platform/size.
|
||||
- `public/`: web app static files.
|
||||
|
||||
## Hasura and Firebase
|
||||
|
||||
- `hasura/config.yaml`: Hasura project config.
|
||||
- `hasura/config.yaml.prod`: production Hasura config.
|
||||
- `hasura/metadata/`: tracked Hasura metadata.
|
||||
- `hasura/migrations/default/`: active SQL migrations.
|
||||
- `hasura/migrations_backup/`: historical migration backup.
|
||||
- `firebase/functions/`: Firebase functions project.
|
||||
- `firebase/firebase.json`: Firebase config.
|
||||
|
||||
## Generated/Ignored
|
||||
|
||||
- `build/`: renderer production output.
|
||||
- `dist-electron/`: bundled Electron main/preload output.
|
||||
- `dist/`: electron-builder output.
|
||||
- `node_modules/`: dependencies.
|
||||
|
||||
95
.ai/frontend.md
Normal file
95
.ai/frontend.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Frontend Guide
|
||||
|
||||
## Stack
|
||||
|
||||
- React 18
|
||||
- Vite 6
|
||||
- Ant Design 5
|
||||
- React Router DOM 6 with `MemoryRouter`
|
||||
- Redux 5, redux-saga, redux-persist, reselect
|
||||
- Apollo Client 3
|
||||
- SCSS modules/files by component where present
|
||||
|
||||
## Component Layout
|
||||
|
||||
Components are organized by a loose atomic design convention:
|
||||
|
||||
- `src/components/atoms/`
|
||||
- `src/components/molecules/`
|
||||
- `src/components/organisms/`
|
||||
- `src/components/templates/`
|
||||
- `src/components/pages/`
|
||||
|
||||
File naming usually includes the level:
|
||||
|
||||
- `jobs-detail.organism.jsx`
|
||||
- `jobs-list-item.molecule.jsx`
|
||||
- `loading-spinner.atom.jsx`
|
||||
- `error-boundary.template.jsx`
|
||||
- `jobs.page.jsx`
|
||||
|
||||
Preserve this style for new code.
|
||||
|
||||
## AntD 5 Rules
|
||||
|
||||
Use current AntD 5 APIs:
|
||||
|
||||
- `Dropdown menu={{ items, onClick }}` instead of `overlay`.
|
||||
- `Collapse items={[...]}` instead of `Collapse.Panel` children.
|
||||
- `expandIconPosition="start"` or `"end"`, not `"left"` or `"right"`.
|
||||
- `DatePicker.RangePicker presets={...}` instead of `ranges`.
|
||||
- `Table rowKey="stableId"` or a function using a real stable field; do not rely on the deprecated index argument.
|
||||
- Prefer AntD `App` context-aware feedback APIs.
|
||||
|
||||
Global feedback:
|
||||
|
||||
- Use `src/util/antdFeedback.js`.
|
||||
- Import `antdMessage`/`antdNotification` instead of static `message`/`notification` from `antd` in files outside the AntD app context.
|
||||
- `src/App/App.jsx` configures these through `AntdFeedbackBridge`.
|
||||
|
||||
## Theming
|
||||
|
||||
`src/App/App.jsx` wraps the app with:
|
||||
|
||||
- `ConfigProvider`
|
||||
- `theme.darkAlgorithm` or `theme.defaultAlgorithm` based on Redux `darkMode`
|
||||
- AntD locale `en_US`
|
||||
- AntD `App`
|
||||
|
||||
Dark mode is stored in Redux `user.darkMode`.
|
||||
|
||||
## Data Loading Notes
|
||||
|
||||
Apollo defaults are `network-only` for `query` and `watchQuery`. Components should be resilient to loading states and should not assume cached data is available.
|
||||
|
||||
Pagination:
|
||||
|
||||
- Latest jobs and search jobs use offset/limit style pagination.
|
||||
- Apollo cache merge policies exist for `Query.jobs` and `Query.search_jobs`.
|
||||
- Guard `fetchMoreResult` and previous data as arrays before spreading; an earlier crash came from assuming `prev.search_jobs` was iterable.
|
||||
|
||||
Job detail:
|
||||
|
||||
- Selection is debounced briefly to prevent a stale left-panel flash.
|
||||
- Show stable loading/skeleton states during selection/query transitions.
|
||||
- Guard against stale Apollo data that does not match the currently selected job id.
|
||||
|
||||
## Redux Notes
|
||||
|
||||
Reducers are old-style switch reducers with action constants. Sagas are used for side effects. When adding logic:
|
||||
|
||||
- Add action type constants.
|
||||
- Add action creators.
|
||||
- Update reducers immutably.
|
||||
- Add selectors with `reselect` where state is consumed.
|
||||
- Add sagas for async or cross-system side effects.
|
||||
|
||||
## Common UI Pitfalls
|
||||
|
||||
- Avoid static AntD feedback APIs.
|
||||
- Avoid adding in-component globals/listeners without cleanup.
|
||||
- Keep table/list row keys stable.
|
||||
- Keep list pagination state defensive around empty or missing arrays.
|
||||
- Do not introduce new routing assumptions based on browser history; this is a `MemoryRouter` Electron app.
|
||||
- Use existing visual density. This is an operational desktop app, not a marketing site.
|
||||
|
||||
48
.ai/project-overview.md
Normal file
48
.ai/project-overview.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Project Overview
|
||||
|
||||
ImEX RPS is a desktop repair performance system for body shops. It imports estimating-system files, decodes estimates into jobs and joblines, stores and reads them through Hasura GraphQL, and gives users workflows for job review, reporting, audit, scan/import, settings, admin maintenance, updates, and estimate scrubbing.
|
||||
|
||||
## Product Concepts
|
||||
|
||||
- Bodyshop: The shop/account a signed-in user can access.
|
||||
- User association: A user is linked to one or more bodyshops through Hasura data.
|
||||
- Job: A repair estimate/claim. Jobs contain claim number, owner/customer fields, vehicle information, insurer, close/loss dates, totals, rates, group data, flags, and related joblines.
|
||||
- Jobline: A decoded estimate line. Joblines contain part/labor data, pricing deltas, ignore flags, ruleset-derived booleans, and alert metadata.
|
||||
- Targets/groupings: Config data used to calculate target percentages and vehicle group eligibility.
|
||||
- Notifications: Hasura-backed shop/user notifications shown in the app.
|
||||
- Watch paths: Local folders where Electron watches for estimate files.
|
||||
- Scan: Manual folder scan for estimate files.
|
||||
- Audit: Spreadsheet-driven workflow comparing claim data against cached jobs.
|
||||
- Estimate scrubber: External API workflow that sends estimate JSON and opens/sends scrub reports.
|
||||
|
||||
## Main User Workflows
|
||||
|
||||
- Sign in with Firebase auth.
|
||||
- Load user/bodyshop/notifications from Hasura after auth.
|
||||
- Configure watched folders and shop settings.
|
||||
- Watch or scan folders for estimate files.
|
||||
- Decode estimates in Electron main process.
|
||||
- Upsert jobs/joblines through renderer GraphQL helpers.
|
||||
- Review jobs and joblines in the Jobs page.
|
||||
- Search and paginate jobs.
|
||||
- Generate reporting and scorecards over date ranges.
|
||||
- Run audits from selected spreadsheets.
|
||||
- Send eligible estimates to the estimate scrubber service.
|
||||
- Receive update notices through electron-updater/S3 publishing.
|
||||
|
||||
## External Systems
|
||||
|
||||
- Hasura GraphQL/Postgres: Primary app data store.
|
||||
- Firebase: Authentication.
|
||||
- S3 updater bucket: Electron auto-update publishing target.
|
||||
- Sentry: Renderer and main-process error telemetry.
|
||||
- Amplitude: Main-process analytics through IPC.
|
||||
- Estimate scrubber API: External estimate validation/report flow.
|
||||
- Local file system: Estimate file watcher, scan, and DBF decoding.
|
||||
|
||||
## Legacy Context
|
||||
|
||||
The repository started from Create React App but now uses Vite. Some docs and comments are old. Prefer `package.json` scripts and current code over README boilerplate.
|
||||
|
||||
The app uses a mixture of older class-era Redux patterns and current library versions. Preserve working conventions unless a task specifically asks for modernization.
|
||||
|
||||
105
.ai/recent-changes.md
Normal file
105
.ai/recent-changes.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# Recent Changes and Migration Context
|
||||
|
||||
This file captures recent cleanup/migration work so future agents do not reverse it.
|
||||
|
||||
## AntD 5 Deprecation Cleanup
|
||||
|
||||
Warnings addressed:
|
||||
|
||||
- `Collapse expandIconPosition` left/right deprecated.
|
||||
- `rc-collapse children` deprecated.
|
||||
- `Table rowKey` index parameter deprecated.
|
||||
- Static `message` cannot consume dynamic theme context.
|
||||
- `Dropdown overlay` deprecated.
|
||||
- `RangePicker ranges` deprecated.
|
||||
|
||||
Patterns now used:
|
||||
|
||||
- `Collapse items`
|
||||
- `expandIconPosition="end"`
|
||||
- `Dropdown menu`
|
||||
- stable table row keys
|
||||
- `RangePicker presets`
|
||||
- `src/util/antdFeedback.js` for feedback APIs
|
||||
- AntD `<App>` wrapper and bridge in `src/App/App.jsx`
|
||||
|
||||
## Redux CreateStore Warning
|
||||
|
||||
`src/redux/store.js` imports:
|
||||
|
||||
```js
|
||||
import { legacy_createStore as createStore, applyMiddleware, compose } from "redux";
|
||||
```
|
||||
|
||||
This intentionally keeps the current Redux architecture while avoiding the visual deprecation warning. Do not change to plain `createStore`.
|
||||
|
||||
## Job Detail Flash Fix
|
||||
|
||||
`src/components/organisms/jobs-detail/jobs-detail.organism.jsx` debounces selected job id and shows a skeleton during transitions. This prevents a fraction-of-a-second stale/partial render in the left panel.
|
||||
|
||||
When editing this area:
|
||||
|
||||
- Preserve stale-data guards.
|
||||
- Preserve a stable loading state when selected id changes.
|
||||
- Do not render details for a job whose id does not match current selection.
|
||||
|
||||
## Apollo Pagination/Cache Fixes
|
||||
|
||||
`src/graphql/GraphQLClient.js` includes offset merge policies:
|
||||
|
||||
- `Query.jobs`
|
||||
- `Query.search_jobs`
|
||||
|
||||
List components were hardened against missing previous/incoming arrays.
|
||||
|
||||
## Electron Package Upgrades
|
||||
|
||||
Packages upgraded together:
|
||||
|
||||
- `electron-context-menu` to `^4.1.2`
|
||||
- `electron-is-dev` to `^3.0.1`
|
||||
- `electron-store` to `^11.0.2`
|
||||
- `electron` to `^42.3.0`
|
||||
- `electron-builder` to `^26.8.1`
|
||||
- `@sentry/electron` to `^7.13.0`
|
||||
|
||||
Important migration consequences:
|
||||
|
||||
- `electron-store` is initialized asynchronously via dynamic import.
|
||||
- `electron-context-menu` is dynamically imported.
|
||||
- `electron-is-dev` is no longer used in runtime code; use `app.isPackaged`/process checks.
|
||||
- Sentry uses protocol IPC mode.
|
||||
- Electron builder pack check uses `electron-builder.pack-check.cjs`.
|
||||
|
||||
## Electron Warning Cleanup
|
||||
|
||||
Circular dependency warning fixed by removing `mainWindow` export/import patterns. IPC modules use Electron APIs directly:
|
||||
|
||||
```js
|
||||
BrowserWindow.fromWebContents(event.sender)
|
||||
```
|
||||
|
||||
Sentry preload deprecation warnings were addressed by using protocol IPC mode:
|
||||
|
||||
```js
|
||||
ipcMode: Sentry.IPCMode.Protocol
|
||||
```
|
||||
|
||||
DevTools behavior:
|
||||
|
||||
- Development opens DevTools by default again.
|
||||
- Use `ELECTRON_OPEN_DEVTOOLS=0` to suppress.
|
||||
- React DevTools extension install remains opt-in.
|
||||
|
||||
## Pack Check Safety
|
||||
|
||||
User specifically requested pack checks without publishing.
|
||||
|
||||
`package.json`:
|
||||
|
||||
```json
|
||||
"pack": "electron-builder --dir --publish never --config electron-builder.pack-check.cjs"
|
||||
```
|
||||
|
||||
`electron-builder.pack-check.cjs` disables Azure signing options for this local check. Do not remove `--publish never` from the pack script.
|
||||
|
||||
141
.ai/workflows.md
Normal file
141
.ai/workflows.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# Development, Verification, and Release Workflows
|
||||
|
||||
## Local Development
|
||||
|
||||
```powershell
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
This runs:
|
||||
|
||||
- Vite renderer dev server on `http://localhost:3006`
|
||||
- Electron app pointed at that dev server
|
||||
|
||||
The app uses `MemoryRouter`, so browser URL routing behavior does not match a normal web app.
|
||||
|
||||
## Build Verification
|
||||
|
||||
Renderer build:
|
||||
|
||||
```powershell
|
||||
npm run build
|
||||
```
|
||||
|
||||
Electron main/preload bundle:
|
||||
|
||||
```powershell
|
||||
npm run build:electron
|
||||
```
|
||||
|
||||
Run both for most cross-process changes.
|
||||
|
||||
Known existing build warnings:
|
||||
|
||||
- A warning around `true || j.close_date` in `src/components/pages/admin/admin.page.jsx`.
|
||||
- Vite chunk-size warnings for large bundles.
|
||||
|
||||
Do not treat those as newly introduced unless your change touches them.
|
||||
|
||||
## Packaging Check
|
||||
|
||||
Use:
|
||||
|
||||
```powershell
|
||||
npm run pack
|
||||
```
|
||||
|
||||
This runs:
|
||||
|
||||
```text
|
||||
electron-builder --dir --publish never --config electron-builder.pack-check.cjs
|
||||
```
|
||||
|
||||
It is the preferred "does it package?" check because it avoids publishing.
|
||||
|
||||
## Publishing
|
||||
|
||||
Publishing is configured through electron-builder S3 settings in `package.json`. The updater checks periodically.
|
||||
|
||||
Do not run publishing scripts unless explicitly requested:
|
||||
|
||||
- `npm run distp`
|
||||
- Any direct `electron-builder --publish always`
|
||||
|
||||
If asked to release:
|
||||
|
||||
1. Confirm the version in `package.json`.
|
||||
2. Run `npm run build`.
|
||||
3. Run `npm run build:electron`.
|
||||
4. Run a no-publish package check first.
|
||||
5. Only then run the requested publish command.
|
||||
|
||||
## Auto Updates
|
||||
|
||||
Main process:
|
||||
|
||||
- Uses `electron-updater`.
|
||||
- `autoUpdater.autoDownload = true`.
|
||||
- Checks every 30 minutes after app ready.
|
||||
- Sends update events/progress to renderer through IPC.
|
||||
- Renderer `UpdateManagerOrganism` handles UI.
|
||||
|
||||
Release notes:
|
||||
|
||||
- Stored in `electron/changelog.json`.
|
||||
- Main process reads `require("./changelog.json")[app.getVersion()]`.
|
||||
- Store key `showChangeLog` controls initial display.
|
||||
|
||||
## Hasura
|
||||
|
||||
Hasura config and migrations live under `hasura/`.
|
||||
|
||||
Be careful with migrations:
|
||||
|
||||
- Current migrations are under `hasura/migrations/default/`.
|
||||
- `hasura/migrations_backup/` is historical backup material.
|
||||
- Metadata under `hasura/metadata/` should match Hasura's generated layout.
|
||||
|
||||
When changing GraphQL queries, verify the Hasura metadata/schema supports selected fields.
|
||||
|
||||
## Sentry Source Maps
|
||||
|
||||
Script:
|
||||
|
||||
```powershell
|
||||
npm run sentry:sourcemaps
|
||||
```
|
||||
|
||||
Requires a valid `.sentryclirc`/token and should only be run when intentionally uploading source maps.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Electron backend console DevTools noise:
|
||||
|
||||
- `Autofill.enable` and `Autofill.setAddresses` errors are Chromium DevTools protocol noise.
|
||||
- They can appear when Chrome DevTools or React DevTools are open.
|
||||
|
||||
Electron circular dependency warning:
|
||||
|
||||
- Do not import `mainWindow` from `main-src.js` in other Electron modules.
|
||||
- Use `BrowserWindow.fromWebContents(event.sender)` for dialogs.
|
||||
|
||||
AntD theme/static feedback warning:
|
||||
|
||||
- Use `antdMessage`/`antdNotification` from `src/util/antdFeedback.js`.
|
||||
- Ensure `AntdFeedbackBridge` is mounted inside AntD `<App>`.
|
||||
|
||||
Apollo cache replacement warning:
|
||||
|
||||
- Confirm field policies in `GraphQLClient.js`.
|
||||
- Add/adjust merge policies for newly paginated fields.
|
||||
|
||||
Search pagination crash:
|
||||
|
||||
- Guard `prev?.search_jobs` and `fetchMoreResult?.search_jobs` before spreading.
|
||||
|
||||
Git ignore of generated files:
|
||||
|
||||
- `.gitignore` includes `/dist-electron/`.
|
||||
- If generated files still show in status, they are probably already tracked; remove from index with `git rm --cached -r dist-electron` after confirming the local files can stay.
|
||||
|
||||
15
.github/copilot-instructions.md
vendored
Normal file
15
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# Copilot Instructions for ImEX RPS
|
||||
|
||||
Read `AGENTS.md` first. It contains the current project architecture, safety rules, workflows, and migration context.
|
||||
|
||||
When proposing or generating code:
|
||||
|
||||
- Use npm scripts and current Vite/Electron workflows, not stale Create React App/yarn instructions.
|
||||
- Keep changes narrow and preserve existing style.
|
||||
- Do not edit generated `build/`, `dist/`, or `dist-electron/`.
|
||||
- Do not suggest publish commands unless the user explicitly asks to publish.
|
||||
- Prefer AntD v5 APIs and avoid deprecated props.
|
||||
- Preserve Electron security defaults: `contextIsolation: true`, `nodeIntegration: false`, preload bridge for renderer IPC.
|
||||
- Avoid circular Electron main-process imports; IPC modules should not import `mainWindow` from `main-src.js`.
|
||||
- Use `.ai/` files for deeper domain and architecture context.
|
||||
|
||||
162
AGENTS.md
Normal file
162
AGENTS.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# ImEX RPS Agent Guide
|
||||
|
||||
This file is the first stop for coding agents working in this repository. It is intentionally practical: read this before changing code, then use the deeper files in `.ai/` when you need more context.
|
||||
|
||||
## Project Snapshot
|
||||
|
||||
ImEX RPS is an Electron desktop app with a Vite/React renderer. It is used by body shops to import, inspect, report on, and audit repair estimate data. The app reads estimate files from configured local folders, decodes DBF-based estimate data in the Electron main process, stores jobs/joblines in Hasura/Postgres through GraphQL, and presents workflows for jobs, reporting, scanning, settings, admin work, audits, and estimate scrubbing.
|
||||
|
||||
Primary technologies:
|
||||
|
||||
- Electron 42, electron-builder 26, Vite 6, React 18
|
||||
- Ant Design 5
|
||||
- Redux 5, redux-saga, redux-persist, reselect
|
||||
- Apollo Client 3 against a Hasura GraphQL endpoint
|
||||
- Firebase authentication
|
||||
- Sentry Electron 7
|
||||
- Hasura metadata and SQL migrations under `hasura/`
|
||||
|
||||
## Fast Start
|
||||
|
||||
Use npm scripts, not the stale yarn commands in `README.md`.
|
||||
|
||||
```powershell
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Useful scripts:
|
||||
|
||||
- `npm run start` starts Vite on `http://localhost:3006`.
|
||||
- `npm run electron` starts Electron.
|
||||
- `npm run dev` runs Vite and Electron together with `concurrently`.
|
||||
- `npm run build` builds the renderer to `build/`.
|
||||
- `npm run build:electron` bundles `electron/main-src.js` and `electron/preload-src.js` into `dist-electron/`.
|
||||
- `npm run pack` performs a local unpacked electron-builder package check with `--publish never`.
|
||||
- `npm run distp` publishes. Do not run it unless the user explicitly asks to publish.
|
||||
- `npm run distnopublish` builds a distributable with publish disabled.
|
||||
|
||||
Expected local runtime:
|
||||
|
||||
- Node must satisfy Electron 42 requirements. At the time of the upgrade, Node 22.22.1 was used successfully.
|
||||
- `VITE_APP_GRAPHQL_ENDPOINT` must be available in the renderer environment.
|
||||
- Firebase config lives in `src/firebase/firebase.utils.js`.
|
||||
- Electron dev mode loads `http://localhost:3006`; packaged mode loads `build/index.html`.
|
||||
|
||||
## Important Safety Rules
|
||||
|
||||
- Do not publish releases unless the user explicitly says to publish.
|
||||
- `npm run pack` is safe for local packaging checks because it includes `--publish never` and uses `electron-builder.pack-check.cjs`.
|
||||
- `dist-electron/`, `build/`, and `dist/` are generated artifacts and are ignored. Do not manually edit them.
|
||||
- Do not commit local secrets. The repo contains legacy-sensitive assets such as `certificate.p12`, deployment notes, and Sentry/Firebase/AWS-related configuration. Treat them carefully.
|
||||
- Avoid broad refactors. This project has older patterns and domain-heavy workflows; make narrow changes and preserve behavior.
|
||||
- Be careful with Electron main/renderer boundaries. Renderer code should use the exposed preload bridge on `window.ipcRenderer`; main-process code should register IPC handlers under `electron/`.
|
||||
|
||||
## Architecture Map
|
||||
|
||||
Renderer entry:
|
||||
|
||||
- `src/index.jsx` wires Redux, redux-persist, `MemoryRouter`, Sentry renderer, and `<App />`.
|
||||
- `src/App/App.jsx` wires Apollo, AntD `ConfigProvider`, AntD `App`, auth session check, IPC setup, and authorized/unauthorized routing.
|
||||
- `src/components/pages/routes/routes.page.jsx` defines app pages: jobs, reporting, audit, scan, settings, admin.
|
||||
|
||||
Electron entry:
|
||||
|
||||
- `electron/main.js` chooses source vs bundled Electron main file.
|
||||
- `electron/main-src.js` is the source of truth for main-process window creation, Sentry main, auto-updater, app menu, DevTools behavior, and global IPC initialization.
|
||||
- `electron/preload-src.js` exposes `window.ipcRenderer` and `window.logger`.
|
||||
- `electron/ipc-main-handler.js` registers shared IPC channels and imports file watcher, file scan, audit, decoder, and estimate scrubber handlers.
|
||||
- `scripts/build-electron.mjs` produces `dist-electron/main.cjs` and `dist-electron/preload.cjs`.
|
||||
|
||||
State/data:
|
||||
|
||||
- `src/redux/store.js` still uses Redux core with `legacy_createStore` to avoid Redux's visual createStore deprecation.
|
||||
- Root reducers: `application`, `user`, `reporting`, `scan`.
|
||||
- Sagas coordinate auth, user/shop setup, reporting, scanning, and application actions.
|
||||
- `src/graphql/GraphQLClient.js` sets Apollo auth, retry, Sentry, logger, error links, and cache field policies for `jobs` and `search_jobs`.
|
||||
- GraphQL operations live in `src/graphql/*.queries.js`.
|
||||
|
||||
Domain logic:
|
||||
|
||||
- `electron/decoder/decoder.js` decodes estimate files and applies MPI/SGI/ruleset logic.
|
||||
- `electron/file-watcher/` watches configured estimate folders.
|
||||
- `electron/file-scan/` scans configured folders for estimates.
|
||||
- `electron/audit/` reads audit spreadsheets.
|
||||
- `electron/estimate-scrubber/` sends estimate JSON to the external scrubber API and opens/sends report results.
|
||||
- `electron/claims-clerk/` computes jobline alerts.
|
||||
|
||||
## Current Conventions
|
||||
|
||||
Frontend:
|
||||
|
||||
- Components are organized by atomic-ish folders: `atoms`, `molecules`, `organisms`, `templates`, `pages`.
|
||||
- File names generally follow `name.type.jsx` and optional `name.type.styles.scss`.
|
||||
- Use Ant Design 5 APIs. Avoid deprecated props such as `Dropdown overlay`, `Collapse.Panel` children, `expandIconPosition="left/right"`, `RangePicker ranges`, and `Table rowKey` functions that rely on index.
|
||||
- Use `src/util/antdFeedback.js` for message/notification calls outside React component context. Static AntD `message`/`notification` calls can miss dynamic theme context.
|
||||
- Keep UI state stable during data transitions. Job detail selection uses a short debounce/skeleton to avoid flashing stale detail content.
|
||||
|
||||
Electron:
|
||||
|
||||
- `electron-store` v11 is ESM-only. Use `initializeStore()` before modules that read `store`, then access `store` through the proxy exported from `electron/electron-store.js`.
|
||||
- `electron-context-menu` v4 is ESM-only. Import dynamically in `app.whenReady()`.
|
||||
- Do not reintroduce circular imports from `electron/main-src.js` into IPC modules. IPC modules should use `BrowserWindow.fromWebContents(event.sender)` or `BrowserWindow.getAllWindows()` where needed.
|
||||
- Sentry main uses `ipcMode: Sentry.IPCMode.Protocol`; keep this unless deliberately changing Sentry IPC behavior.
|
||||
- DevTools are enabled in dev and auto-open by default. Set `ELECTRON_OPEN_DEVTOOLS=0` to suppress auto-open. In packaged builds DevTools are opt-in via `ELECTRON_ENABLE_DEVTOOLS=1` and auto-open via `ELECTRON_OPEN_DEVTOOLS=1`.
|
||||
- React DevTools extension install is opt-in with `ELECTRON_INSTALL_REACT_DEVTOOLS=1`. It can trigger Chromium DevTools protocol noise.
|
||||
|
||||
GraphQL/Apollo:
|
||||
|
||||
- Default Apollo query/watchQuery fetch policy is `network-only`; do not assume Apollo cache is the source of truth.
|
||||
- Apollo cache has custom offset merge functions for `Query.jobs` and `Query.search_jobs` to avoid cache replacement warnings during pagination.
|
||||
- Firebase current user token is attached as `Authorization: Bearer <token>` through `authLink`.
|
||||
|
||||
## Recent Maintenance Context
|
||||
|
||||
Recent warning/deprecation cleanup included:
|
||||
|
||||
- AntD v5 deprecations fixed for Collapse, Dropdown, RangePicker, Table rowKey, and static message/notification usage.
|
||||
- Redux `createStore` deprecation warning avoided with `legacy_createStore`.
|
||||
- Apollo cache warning fixed with field policies for `jobs` and `search_jobs`.
|
||||
- Job detail left-panel flash reduced by debouncing selected job id and using a skeleton.
|
||||
- Electron circular dependency warnings removed by avoiding `mainWindow` export/import.
|
||||
- Electron Sentry preload deprecation path avoided with protocol IPC mode.
|
||||
- Electron package upgrades completed for `electron`, `electron-builder`, `electron-context-menu`, `electron-is-dev`, `electron-store`, and `@sentry/electron`.
|
||||
- `dist-electron/` is ignored and should remain generated only.
|
||||
|
||||
## Verification Expectations
|
||||
|
||||
For most renderer/main changes:
|
||||
|
||||
```powershell
|
||||
npm run build
|
||||
npm run build:electron
|
||||
```
|
||||
|
||||
For Electron package or builder changes:
|
||||
|
||||
```powershell
|
||||
npm run pack
|
||||
```
|
||||
|
||||
Remember: `npm run pack` is configured to avoid publishing. It may still perform local signing of the unpacked executable.
|
||||
|
||||
For AntD deprecation checks, if `antd-style` tooling is available:
|
||||
|
||||
```powershell
|
||||
npx antd-style-cli lint src --only deprecated
|
||||
```
|
||||
|
||||
If a command is unavailable, report that clearly and run the nearest reliable build/check instead.
|
||||
|
||||
## More Context
|
||||
|
||||
- `.ai/project-overview.md`: product/domain summary.
|
||||
- `.ai/architecture.md`: process, renderer, state, and data architecture.
|
||||
- `.ai/electron-main.md`: Electron-specific lifecycle, packaging, IPC, and upgrade notes.
|
||||
- `.ai/frontend.md`: React/AntD/Redux conventions and common UI pitfalls.
|
||||
- `.ai/data-graphql-hasura.md`: GraphQL, Hasura, auth, cache, and schema notes.
|
||||
- `.ai/workflows.md`: development, packaging, release, and troubleshooting workflows.
|
||||
- `.ai/recent-changes.md`: migration and warning cleanup history.
|
||||
- `.ai/file-map.md`: important files and directories by responsibility.
|
||||
- `.ai/domain-glossary.md`: project/domain terms used across code and UI.
|
||||
- `.github/copilot-instructions.md`, `CLAUDE.md`, and `GEMINI.md` all point agents back to this guide.
|
||||
26
AI_CONTEXT.md
Normal file
26
AI_CONTEXT.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# AI Context Index
|
||||
|
||||
This is the root index for AI/code-agent context in ImEX RPS. Start with `AGENTS.md`; use the `.ai/` files for deeper context.
|
||||
|
||||
## Read Order
|
||||
|
||||
1. `AGENTS.md`
|
||||
2. `.ai/project-overview.md`
|
||||
3. `.ai/architecture.md`
|
||||
4. `.ai/workflows.md`
|
||||
5. Task-specific files:
|
||||
- `.ai/frontend.md` for React, AntD, Redux, and UI work.
|
||||
- `.ai/electron-main.md` for Electron main/preload/IPC/packaging work.
|
||||
- `.ai/data-graphql-hasura.md` for GraphQL, Apollo, Hasura, Firebase auth, schema, and migrations.
|
||||
- `.ai/recent-changes.md` for current deprecation cleanup and package migration context.
|
||||
- `.ai/file-map.md` for locating important code quickly.
|
||||
- `.ai/domain-glossary.md` for domain terms and abbreviations.
|
||||
|
||||
## High-Signal Rules
|
||||
|
||||
- Use npm scripts. The old README still mentions yarn/Create React App.
|
||||
- Do not publish unless explicitly asked. `npm run pack` is the safe local packaging check.
|
||||
- Do not edit generated `build/`, `dist/`, or `dist-electron/`.
|
||||
- Keep Electron main/renderer separation clean.
|
||||
- Use AntD v5 APIs and `src/util/antdFeedback.js` for global message/notification calls.
|
||||
- Treat local certs, deployment scripts, Sentry DSNs, Firebase config, and AWS notes as sensitive.
|
||||
17
CLAUDE.md
Normal file
17
CLAUDE.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Claude Instructions
|
||||
|
||||
Start with `AGENTS.md`. It is the canonical guide for this repository.
|
||||
|
||||
Additional context lives in `.ai/`:
|
||||
|
||||
- `.ai/project-overview.md`
|
||||
- `.ai/architecture.md`
|
||||
- `.ai/frontend.md`
|
||||
- `.ai/electron-main.md`
|
||||
- `.ai/data-graphql-hasura.md`
|
||||
- `.ai/workflows.md`
|
||||
- `.ai/recent-changes.md`
|
||||
- `.ai/file-map.md`
|
||||
- `.ai/domain-glossary.md`
|
||||
|
||||
Do not publish releases unless the user explicitly asks. Use `npm run pack` for local packaging checks.
|
||||
17
GEMINI.md
Normal file
17
GEMINI.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Gemini Instructions
|
||||
|
||||
Start with `AGENTS.md`. It is the canonical guide for this repository.
|
||||
|
||||
Additional context lives in `.ai/`:
|
||||
|
||||
- `.ai/project-overview.md`
|
||||
- `.ai/architecture.md`
|
||||
- `.ai/frontend.md`
|
||||
- `.ai/electron-main.md`
|
||||
- `.ai/data-graphql-hasura.md`
|
||||
- `.ai/workflows.md`
|
||||
- `.ai/recent-changes.md`
|
||||
- `.ai/file-map.md`
|
||||
- `.ai/domain-glossary.md`
|
||||
|
||||
Do not publish releases unless the user explicitly asks. Use `npm run pack` for local packaging checks.
|
||||
@@ -8,7 +8,8 @@ const Sentry = require("@sentry/electron/main");
|
||||
|
||||
const isDev = !app.isPackaged;
|
||||
const enableDevTools = isDev || process.env.ELECTRON_ENABLE_DEVTOOLS === "1";
|
||||
const openDevToolsOnStart = enableDevTools && process.env.ELECTRON_OPEN_DEVTOOLS === "1";
|
||||
const openDevToolsOnStart =
|
||||
enableDevTools && (isDev ? process.env.ELECTRON_OPEN_DEVTOOLS !== "0" : process.env.ELECTRON_OPEN_DEVTOOLS === "1");
|
||||
const installReactDevTools = process.env.ELECTRON_INSTALL_REACT_DEVTOOLS === "1";
|
||||
|
||||
//const Nucleus = require("nucleus-nodejs");
|
||||
@@ -209,8 +210,8 @@ function createWindow() {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
// Open DevTools only when explicitly requested. DevTools itself emits
|
||||
// Chromium protocol noise such as Autofill.* messages in Electron.
|
||||
// Auto-open DevTools in dev. DevTools itself can emit Chromium protocol
|
||||
// noise such as Autofill.* messages in Electron.
|
||||
if (openDevToolsOnStart) {
|
||||
mainWindow.webContents.openDevTools({
|
||||
// mode: "detach"
|
||||
|
||||
Reference in New Issue
Block a user