# 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.