@hiver/skills 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/collections/common/skills/discuss-problem/SKILL.md +2 -2
- package/collections/extension/agents/build-feature.md +41 -0
- package/collections/extension/agents/build-milestone.md +62 -0
- package/collections/extension/skills/build-backbone-component/SKILL.md +100 -0
- package/collections/extension/skills/build-backbone-component/references/backbone-scaffolds.md +162 -0
- package/collections/extension/skills/build-backbone-component/references/react-mount-path.md +93 -0
- package/collections/extension/skills/build-component/SKILL.md +33 -0
- package/collections/extension/skills/build-component/palette/README.md +3 -0
- package/collections/extension/skills/build-component/palette/colors.md +87 -0
- package/collections/extension/skills/build-component/references/best-practices.md +8 -0
- package/collections/extension/skills/build-component/references/component-organization.md +21 -0
- package/collections/extension/skills/build-component/references/figma-integration.md +5 -0
- package/collections/extension/skills/build-component/references/icons/brand-icons.png +0 -0
- package/collections/extension/skills/build-component/references/icons/mui-icons.png +0 -0
- package/collections/extension/skills/build-component/references/icons.md +81 -0
- package/collections/extension/skills/build-component/references/layout-and-structure.md +8 -0
- package/collections/extension/skills/build-component/references/state-management.md +25 -0
- package/collections/extension/skills/build-component/references/ui-kit-and-styling.md +13 -0
- package/collections/extension/skills/build-component/typography/README.md +3 -0
- package/collections/extension/skills/build-component/typography/variants.md +139 -0
- package/collections/extension/skills/ci-cd/SKILL.md +67 -0
- package/collections/extension/skills/ci-cd/references/bundle-and-troubleshooting.md +50 -0
- package/collections/extension/skills/ci-cd/references/file-registry.md +28 -0
- package/collections/extension/skills/connect-api/SKILL.md +23 -0
- package/collections/extension/skills/connect-api/references/api-call-structure.md +84 -0
- package/collections/extension/skills/connect-api/references/best-practices.md +10 -0
- package/collections/extension/skills/connect-api/references/data-fetchers.md +52 -0
- package/collections/extension/skills/connect-api/references/error-handling.md +34 -0
- package/collections/extension/skills/connect-api/references/hook-organization.md +11 -0
- package/collections/extension/skills/connect-api/references/query-keys.md +21 -0
- package/collections/extension/skills/connect-api/references/react-query-usage.md +83 -0
- package/collections/extension/skills/connect-api/references/url-placeholders.md +17 -0
- package/collections/extension/skills/modify-extension/SKILL.md +110 -0
- package/collections/extension/skills/modify-extension/references/architecture.md +55 -0
- package/collections/extension/skills/modify-extension/references/implementation-patterns.md +180 -0
- package/collections/extension/skills/scaffold-react-feature/SKILL.md +141 -0
- package/collections/extension/skills/write-test-cases/SKILL.md +93 -0
- package/collections/web/skills/build-component/references/icons/brand-icons.png +0 -0
- package/collections/web/skills/build-component/references/icons/mui-icons.png +0 -0
- package/collections/web/skills/build-component/references/icons.md +79 -6
- package/collections/web/skills/build-component/typography/variants.md +62 -2
- package/package.json +1 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Icons
|
|
2
|
+
|
|
3
|
+
How to import from `@hiver/hiver-ui-kit`:
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
import { brandIcons, icons } from '@hiver/hiver-ui-kit';
|
|
7
|
+
// <brandIcons.Star />
|
|
8
|
+
// <icons.AccountCircle />
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Resolution priority
|
|
12
|
+
|
|
13
|
+
When a Figma design contains an icon, resolve it in this order:
|
|
14
|
+
|
|
15
|
+
1. **User-provided SVG asset** — if the user supplied an `.svg` file, import it directly:
|
|
16
|
+
```js
|
|
17
|
+
import iconName from 'path/to/icon.svg';
|
|
18
|
+
<img src={iconName} alt="description" />
|
|
19
|
+
```
|
|
20
|
+
2. **`brandIcons`** — Hiver-designed icons (see "Brand icon catalog" below).
|
|
21
|
+
3. **`icons`** — curated MUI icons re-exported from hui-kit (see "MUI icon catalog" below).
|
|
22
|
+
4. **`@mui/icons-material`** — **last resort only**, when the icon is not in the design system **and** the user has not provided an asset.
|
|
23
|
+
5. **Never** import icons from FontAwesome, Heroicons, or any other third-party icon library.
|
|
24
|
+
|
|
25
|
+
## How to match a Figma icon to a code name
|
|
26
|
+
|
|
27
|
+
1. **Prefer the Figma layer/component name** if the design exposes one (e.g. a layer named `Brand/Star` → `brandIcons.Star`).
|
|
28
|
+
2. **Otherwise, match visually** against the catalog sheets embedded below. Each icon is rendered with its exact export name underneath.
|
|
29
|
+
3. The export name is what you use in code — including any typos preserved from the design system (see Notes).
|
|
30
|
+
|
|
31
|
+
## Brand icon catalog (`brandIcons`)
|
|
32
|
+
|
|
33
|
+

|
|
34
|
+
|
|
35
|
+
**Hiver Logo**
|
|
36
|
+
- `Logo`
|
|
37
|
+
|
|
38
|
+
**Brand icons** (box 20×20, live area 18×18, stroke 1.4)
|
|
39
|
+
- `SharedMailbox`, `Analytics`, `EmailTemplates`, `Settings`, `HiverAlerts`, `Activity`, `AutoAssignment`, `Workload`, `Lable`, `Permalink`
|
|
40
|
+
- `Star`, `Edit`, `Filters`, `HiverChat`, `AircallPhone`, `Aavatar`, `Unassigned`, `Mine`, `Team`, `Pending`
|
|
41
|
+
- `Closed`, `Tags`, `Crown`, `Dashboard`, `DashboardInactive`, `SharedInboxNav`, `SharedInboxNavInactive`, `SharedLabel`, `SharedLabelInactive`, `KnowledgeBase`
|
|
42
|
+
- `KnowledgeBaseInactive`, `Connector`, `ConnectorInactive`, `SettingsNav`, `SettingsNavInactive`, `UserRole`, `UserRoleInactive`
|
|
43
|
+
|
|
44
|
+
**Activity icons** (box 20×20, live area 16×16, stroke 1.4)
|
|
45
|
+
- `Status`, `Tag`, `Inbox`, `AlertTriangle`, `EnvelopeDownload`, `ActivityStar`, `EnvelopeUpload`, `Envelope`, `ActivityEdit`, `CloseCircle`, `CheckAction`, `UserCheck`
|
|
46
|
+
|
|
47
|
+
**Settings icons** (box 24×24, live area 22×22, stroke 1.4)
|
|
48
|
+
- `AdminPanel`, `Sliders`, `Compass`, `SwitchAccount`, `Gift`, `MessageCircle`, `LifeBuoy`
|
|
49
|
+
|
|
50
|
+
## MUI icon catalog (`icons`)
|
|
51
|
+
|
|
52
|
+

|
|
53
|
+
|
|
54
|
+
- `AccountCircle`, `Add`, `Alarm`, `Close`, `Phone`, `ArchiveOutlined`, `ArrowBack`, `ArrowBackIos`, `ArrowDropDown`, `ArrowDropUp`, `ArrowForward`
|
|
55
|
+
- `ArrowOutward`, `CalendarToday`, `CalendarTodayOutlined`, `CalendarTodayOutlinedIcon`, `Cancel`, `CancelOutlined`, `CheckCircle`, `ChevronRightOutlined`, `CodeSharp`, `DeleteOutline`, `DownloadOutlined`
|
|
56
|
+
- `DragIndicator`, `EditOutlined`, `Error`, `ErrorOutline`, `GroupsOutlined`, `InfoOutlined`, `LabelOutlined`, `Link`, `LockOutlined`, `MailOutlined`, `MicNone`
|
|
57
|
+
- `MoreVert`, `NotificationsOutlined`, `OpenInNew`, `Pause`, `PersonOutline`, `PersonOutlined`, `PlayArrow`, `Public`, `Search`, `Settings`, `SettingsOutlined`
|
|
58
|
+
- `StickyNote2Outlined`, `ThumbDownAlt`, `ThumbDownOffAlt`, `ThumbUpAlt`, `ThumbUpOffAlt`, `TimerOutlined`, `TrackChanges`, `UnarchiveOutlined`, `Voicemail`, `Warning`, `WarningAmber`
|
|
59
|
+
- `ArrowRightAlt`, `Delete`, `Email`, `Favorite`
|
|
60
|
+
|
|
61
|
+
## Notes — Figma → code gotchas
|
|
62
|
+
|
|
63
|
+
- **Typos preserved in exports** — these match the Figma names, so map literally; do not auto-correct:
|
|
64
|
+
- `Lable` (not `Label`)
|
|
65
|
+
- `Aavatar` (not `Avatar`)
|
|
66
|
+
- **`Edit` collision** — three similar icons:
|
|
67
|
+
- `brandIcons.Edit` — pen-on-paper brand icon (yellow accent)
|
|
68
|
+
- `brandIcons.ActivityEdit` — green envelope with a pen, activity style
|
|
69
|
+
- `icons.EditOutlined` — plain MUI outlined pencil
|
|
70
|
+
- **`Settings` collision** — five similar names:
|
|
71
|
+
- `brandIcons.Settings`, `brandIcons.SettingsNav`, `brandIcons.SettingsNavInactive`
|
|
72
|
+
- `icons.Settings`, `icons.SettingsOutlined`
|
|
73
|
+
Pick by Figma category section and visual.
|
|
74
|
+
- **`Star` collision**:
|
|
75
|
+
- `brandIcons.Star` — yellow filled brand star
|
|
76
|
+
- `brandIcons.ActivityStar` — purple activity star
|
|
77
|
+
- **`Tag` vs `Tags`**:
|
|
78
|
+
- `brandIcons.Tags` — brand (plural, box 20×20 live 18×18)
|
|
79
|
+
- `brandIcons.Tag` — activity (singular, box 20×20 live 16×16)
|
|
80
|
+
- **Inactive variants** — many brand icons have `*Inactive` siblings (`DashboardInactive`, `SharedInboxNavInactive`, `SharedLabelInactive`, `KnowledgeBaseInactive`, `ConnectorInactive`, `SettingsNavInactive`, `UserRoleInactive`). Use the inactive variant for the unselected/disabled state of a nav item.
|
|
81
|
+
- **`UserCheck`** — present in `brandIcons` exports but not visible on the current Figma sheet. Use it if a design clearly needs it; otherwise prefer the activity-style icons documented above.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Layout and Structure
|
|
2
|
+
|
|
3
|
+
- **Prefer `Stack` component** for flex layouts instead of raw flexbox CSS
|
|
4
|
+
- Use `Stack` with `direction="row"` or `direction="column"`
|
|
5
|
+
- Use `gap` prop for spacing between items
|
|
6
|
+
- Example: `<Stack direction="row" gap={2} alignItems="center">`
|
|
7
|
+
- **Use `Box`** for simple container elements or when you need custom styling
|
|
8
|
+
- use `sx` prop for component-specific styling
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# State Management
|
|
2
|
+
|
|
3
|
+
## Identifying State
|
|
4
|
+
|
|
5
|
+
- **Connect dynamic elements to state**:
|
|
6
|
+
- User inputs (form fields, toggles, selections)
|
|
7
|
+
- Data that changes based on user interactions
|
|
8
|
+
- UI state (modals open/closed, tabs active, loading states)
|
|
9
|
+
|
|
10
|
+
## State Implementation
|
|
11
|
+
|
|
12
|
+
- **Use React hooks** for local component state:
|
|
13
|
+
- `useState` for simple state values
|
|
14
|
+
- `useReducer` for complex state with multiple sub-values
|
|
15
|
+
- `useMemo` for computed/derived values
|
|
16
|
+
- `useCallback` for memoized functions
|
|
17
|
+
- **Add proper event handlers**:
|
|
18
|
+
- `onChange` handlers for inputs
|
|
19
|
+
- `onClick` handlers for buttons/actions
|
|
20
|
+
- `onSubmit` handlers for forms
|
|
21
|
+
- Ensure handlers update state appropriately
|
|
22
|
+
- **Handle state updates correctly**:
|
|
23
|
+
- Use functional updates when state depends on previous state: `setCount(prev => prev + 1)`
|
|
24
|
+
- Batch related state updates when possible
|
|
25
|
+
- Clean up subscriptions/effects in `useEffect` cleanup functions
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# UI Kit and Styling
|
|
2
|
+
|
|
3
|
+
- **Use `@hiver/hiver-ui-kit` package** for all UI components and styling
|
|
4
|
+
- This package uses Material-UI (MUI) internally, so follow MUI patterns
|
|
5
|
+
- Import components directly from `@hiver/hiver-ui-kit`: `import { Stack, Button, Typography, TextField, Select } from '@hiver/hiver-ui-kit'`
|
|
6
|
+
- **Map Figma to design tokens**: Use [palette/README.md](../palette/README.md) for colors and [typography/README.md](../typography/README.md) for text styles so Figma specs map to the correct `theme.palette.*` and `<Typography variant="...">`.
|
|
7
|
+
- **Analyze the Figma selection** to identify all required components:
|
|
8
|
+
- Form inputs: Use `TextField`, `Select`, `Checkbox`, `Radio`, etc.
|
|
9
|
+
- Typography: Use `Typography` with variants from the typography reference (e.g. `body1_regular`, `h2_medium`, `caption1_medium`)
|
|
10
|
+
- Layout: Use `Stack`, `Box`, `Grid` for layout structure
|
|
11
|
+
- Buttons: Use `Button` with appropriate variants (`contained`, `outlined`, `text`)
|
|
12
|
+
- Modals: Use `Modal`
|
|
13
|
+
- Other: `Tooltip`, `CircularProgress`, `IconButton`, etc.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Typography reference (`@hiver/hiver-ui-kit`)
|
|
2
|
+
|
|
3
|
+
Map Figma text styles to `<Typography variant="...">`. Match by fontSize + fontWeight (regular 400, medium 500, semiBold 600, bold 700).
|
|
4
|
+
|
|
5
|
+
**Font families:**
|
|
6
|
+
- Legacy variants (`h1_*`–`h5_*`, `body0_5_*`–`body4_*`, `caption1_*`, `caption2_*`, `overline_medium`, `overline_semiBold`, `buttonLarge`/`buttonMedium`/`buttonSmall`, `chip`) use **Open Sans**.
|
|
7
|
+
- 2026 tokens (`body_lg_*`–`body_xs_*`, `heading_lg_*`–`heading_sm_*`, `display_lg_*`/`display_md_*`, `caption_regular`/`caption_medium`, `overline_regular`) use **Inter**.
|
|
8
|
+
|
|
9
|
+
## Heading variants
|
|
10
|
+
|
|
11
|
+
| Variant | fontSize | fontWeight | lineHeight | letterSpacing | Figma match |
|
|
12
|
+
|---------|----------|------------|------------|---------------|-------------|
|
|
13
|
+
| `h1_medium` | 20 | 500 | 28px | -0.16px | Large title |
|
|
14
|
+
| `h1_semiBold` | 20 | 600 | 28px | -0.16px | |
|
|
15
|
+
| `h1_bold` | 20 | 700 | 28px | -0.16px | |
|
|
16
|
+
| `h2_regular` | 16 | 400 | 21px | -0.16px | Section title |
|
|
17
|
+
| `h2_medium` | 16 | 500 | 21px | -0.16px | |
|
|
18
|
+
| `h2_semiBold` | 16 | 600 | 21px | -0.16px | |
|
|
19
|
+
| `h2_5_regular` | 15 | 400 | 18px | -0.16px | |
|
|
20
|
+
| `h2_5_medium` | 15 | 500 | 18px | -0.16px | |
|
|
21
|
+
| `h2_5_semiBold` | 15 | 600 | 18px | -0.16px | |
|
|
22
|
+
| `h3_regular` | 14 | 400 | 18px | 0 | Subsection |
|
|
23
|
+
| `h3_medium` | 14 | 500 | 18px | 0 | |
|
|
24
|
+
| `h3_semiBold` | 14 | 600 | 18px | 0 | |
|
|
25
|
+
| `h4_regular` | 13 | 400 | 16px | 0 | |
|
|
26
|
+
| `h4_medium` | 13 | 500 | 16px | 0 | |
|
|
27
|
+
| `h4_semiBold` | 13 | 600 | 16px | 0 | |
|
|
28
|
+
| `h5_regular` | 12 | 400 | 14px | -0.12px | Small heading |
|
|
29
|
+
| `h5_medium` | 12 | 500 | 14px | -0.12px | |
|
|
30
|
+
| `h5_semiBold` | 12 | 600 | 14px | -0.12px | |
|
|
31
|
+
| `h5_bold` | 12 | 700 | 14px | -0.12px | |
|
|
32
|
+
|
|
33
|
+
## Body variants
|
|
34
|
+
|
|
35
|
+
| Variant | fontSize | fontWeight | lineHeight | letterSpacing |
|
|
36
|
+
|---------|----------|------------|------------|---------------|
|
|
37
|
+
| `body0_5_regular` | 16 | 400 | 22px | 0 |
|
|
38
|
+
| `body0_5_medium` | 16 | 500 | 22px | 0 |
|
|
39
|
+
| `body0_5_semiBold` | 16 | 600 | 22px | 0 |
|
|
40
|
+
| `body1_regular` | 14 | 400 | 21px | 0 |
|
|
41
|
+
| `body1_medium` | 14 | 500 | 21px | 0.25px |
|
|
42
|
+
| `body1_semiBold` | 14 | 600 | 21px | 0 |
|
|
43
|
+
| `body2_regular` | 13 | 400 | 18px | 0 |
|
|
44
|
+
| `body2_medium` | 13 | 500 | 18px | 0 |
|
|
45
|
+
| `body2_semiBold` | 13 | 600 | 18px | 0 |
|
|
46
|
+
| `body3_regular` | 12 | 400 | 14px | 0 |
|
|
47
|
+
| `body3_medium` | 12 | 500 | 14px | 0 |
|
|
48
|
+
| `body3_semiBold` | 12 | 600 | 14px | 0 |
|
|
49
|
+
| `body4_regular` | 11 | 400 | 12px | 0 |
|
|
50
|
+
| `body4_medium` | 11 | 500 | 12px | 0 |
|
|
51
|
+
| `body4_semiBold` | 11 | 600 | 12px | 0 |
|
|
52
|
+
|
|
53
|
+
## Caption & overline
|
|
54
|
+
|
|
55
|
+
| Variant | fontSize | fontWeight | lineHeight | letterSpacing | Notes |
|
|
56
|
+
|---------|----------|------------|------------|---------------|-------|
|
|
57
|
+
| `caption1_regular` | 12 | 400 | 16px | 0.25px | |
|
|
58
|
+
| `caption1_medium` | 12 | 500 | 16px | 0.25px | |
|
|
59
|
+
| `caption1_semiBold` | 12 | 600 | 16px | 0.25px | |
|
|
60
|
+
| `caption2_regular` | 11 | 400 | 14px | 0.20px | |
|
|
61
|
+
| `caption2_medium` | 11 | 500 | 14px | 0.20px | |
|
|
62
|
+
| `caption2_semiBold` | 11 | 600 | 14px | 0.20px | |
|
|
63
|
+
| `overline_medium` | 11 | 500 | 18px | 0 | UPPERCASE |
|
|
64
|
+
| `overline_semiBold` | 11 | 600 | 18px | 0 | UPPERCASE |
|
|
65
|
+
|
|
66
|
+
## Button & chip
|
|
67
|
+
|
|
68
|
+
| Variant | fontSize | fontWeight | lineHeight | letterSpacing |
|
|
69
|
+
|---------|----------|------------|------------|---------------|
|
|
70
|
+
| `buttonLarge` | 14 | 500 | 28px | 0.2px |
|
|
71
|
+
| `buttonMedium` | 13 | 500 | 24px | 0.2px |
|
|
72
|
+
| `buttonSmall` | 12 | 500 | 20px | 0.4px |
|
|
73
|
+
| `chip` | 12 | 500 | 12px | 0.4px |
|
|
74
|
+
|
|
75
|
+
## Typography 2026 tokens (Inter)
|
|
76
|
+
|
|
77
|
+
Canonical 2026 design tokens. Use these for new UI built against the 2026 design system. Font family is **Inter**.
|
|
78
|
+
|
|
79
|
+
### Display
|
|
80
|
+
|
|
81
|
+
| Variant | fontSize | fontWeight | lineHeight | letterSpacing |
|
|
82
|
+
|---------|----------|------------|------------|---------------|
|
|
83
|
+
| `display_lg_semiBold` | 28 | 600 | 36px | 0.01em |
|
|
84
|
+
| `display_lg_bold` | 28 | 700 | 36px | 0.01em |
|
|
85
|
+
| `display_md_semiBold` | 24 | 600 | 32px | 0.01em |
|
|
86
|
+
| `display_md_bold` | 24 | 700 | 32px | 0.01em |
|
|
87
|
+
|
|
88
|
+
### Heading
|
|
89
|
+
|
|
90
|
+
| Variant | fontSize | fontWeight | lineHeight | letterSpacing |
|
|
91
|
+
|---------|----------|------------|------------|---------------|
|
|
92
|
+
| `heading_lg_medium` | 20 | 500 | 28px | -0.005em |
|
|
93
|
+
| `heading_lg_semiBold` | 20 | 600 | 28px | -0.005em |
|
|
94
|
+
| `heading_md_medium` | 18 | 500 | 28px | -0.005em |
|
|
95
|
+
| `heading_md_semiBold` | 18 | 600 | 28px | -0.005em |
|
|
96
|
+
| `heading_sm_medium` | 16 | 500 | 22px | -0.005em |
|
|
97
|
+
| `heading_sm_semiBold` | 16 | 600 | 22px | -0.005em |
|
|
98
|
+
|
|
99
|
+
### Body
|
|
100
|
+
|
|
101
|
+
| Variant | fontSize | fontWeight | lineHeight | letterSpacing |
|
|
102
|
+
|---------|----------|------------|------------|---------------|
|
|
103
|
+
| `body_lg_regular` | 16 | 400 | 24px | -0.005em |
|
|
104
|
+
| `body_lg_medium` | 16 | 500 | 24px | -0.005em |
|
|
105
|
+
| `body_lg_semiBold` | 16 | 600 | 24px | -0.005em |
|
|
106
|
+
| `body_md_regular` | 14 | 400 | 20px | -0.005em |
|
|
107
|
+
| `body_md_medium` | 14 | 500 | 20px | -0.005em |
|
|
108
|
+
| `body_md_semiBold` | 14 | 600 | 20px | -0.005em |
|
|
109
|
+
| `body_sm_regular` | 13 | 400 | 19px | -0.005em |
|
|
110
|
+
| `body_sm_medium` | 13 | 500 | 19px | -0.005em |
|
|
111
|
+
| `body_sm_semiBold` | 13 | 600 | 19px | -0.005em |
|
|
112
|
+
| `body_xs_regular` | 12 | 400 | 18px | -0.005em |
|
|
113
|
+
| `body_xs_medium` | 12 | 500 | 18px | -0.005em |
|
|
114
|
+
| `body_xs_semiBold` | 12 | 600 | 18px | -0.005em |
|
|
115
|
+
|
|
116
|
+
### Caption & overline (2026)
|
|
117
|
+
|
|
118
|
+
| Variant | fontSize | fontWeight | lineHeight | letterSpacing | Notes |
|
|
119
|
+
|---------|----------|------------|------------|---------------|-------|
|
|
120
|
+
| `caption_regular` | 12 | 400 | 14px | 0.01em | |
|
|
121
|
+
| `caption_medium` | 12 | 500 | 14px | 0.01em | |
|
|
122
|
+
| `overline_regular` | 12 | 400 | 14px | 0.01em | UPPERCASE |
|
|
123
|
+
|
|
124
|
+
> Note: a 2026 `overline_medium` token also exists in the theme (Inter, 12 / 500 / 14px / 0.01em / UPPERCASE) and shares its name with the legacy Open Sans `overline_medium` (11 / 500 / 18px). The 2026 spread is applied after the legacy block, so the Inter version wins at runtime — use accordingly.
|
|
125
|
+
|
|
126
|
+
## Usage
|
|
127
|
+
|
|
128
|
+
```jsx
|
|
129
|
+
<Typography variant="h2_medium">Section title</Typography>
|
|
130
|
+
<Typography variant="body1_regular">Body text</Typography>
|
|
131
|
+
<Typography variant="caption1_medium" color="text.secondary">Caption</Typography>
|
|
132
|
+
|
|
133
|
+
// 2026 tokens
|
|
134
|
+
<Typography variant="heading_lg_semiBold">Page title</Typography>
|
|
135
|
+
<Typography variant="body_md_regular">Body text</Typography>
|
|
136
|
+
<Typography variant="display_lg_bold">Hero</Typography>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Figma → variant:** Compare Figma text style fontSize and weight (Regular/Medium/Semi Bold/Bold) to the tables above and pick the closest match. For new 2026 designs, prefer the Inter tokens.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ci-cd
|
|
3
|
+
description: Complete knowledge of the Hiver Chrome Extension CI/CD pipelines across Dev, Pre-prod, and Production. Covers all pipeline files, dependency chains, and downstream impact of changes. Use when modifying CI/CD pipelines, adding build outputs, changing build commands, adding env vars, updating S3 targets, debugging pipeline failures, or any task involving GitHub Actions, CodeBuild buildspecs, Docker build scripts, or deployment scripts.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hiver Extension CI/CD
|
|
7
|
+
|
|
8
|
+
## Pipeline Map
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
Dev (PR on qa-* branch)
|
|
12
|
+
1. GitHub Action: .github/workflows/Dev-Extension-Build.yml
|
|
13
|
+
2. CodeBuild (PR create): ci-cd/buddy/buildspec-create-v3.yaml
|
|
14
|
+
3. CodeBuild (PR merge): ci-cd/buddy/buildspec-merge-v3.yaml
|
|
15
|
+
|
|
16
|
+
Pre-Production (manual trigger)
|
|
17
|
+
4. GitHub Action: .github/workflows/Pre-production.yaml
|
|
18
|
+
|
|
19
|
+
Production
|
|
20
|
+
5a. CodeBuild: codebuild/extension-buildspec.yml
|
|
21
|
+
5b. CodeBuild: codebuild/webstore-buildspec-v3.yaml
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Modification Guides
|
|
25
|
+
|
|
26
|
+
### Adding a new JS bundle output file
|
|
27
|
+
Touches **all three environments** — update in 4 places:
|
|
28
|
+
1. `docker/v3/build_dev_extension.sh` — add `mv` to rename from `dist/` output name to final name
|
|
29
|
+
2. `.github/workflows/Pre-production.yaml` — add explicit `cp` in "Prepare extension package" step
|
|
30
|
+
3. `deployment/PushBundleToS3.py` — add entry to `BUNDLE_NAMES` dict; update `validate_upload()` count
|
|
31
|
+
4. `deployment/webstore-deployment/pushBundlesToExtensionPackage.py` — add file to CDN fetch list
|
|
32
|
+
|
|
33
|
+
> Pre-prod uses manual per-file `cp` (not a dict), making it the most fragile env when new files are added.
|
|
34
|
+
|
|
35
|
+
### Changing a build command (backbone or React)
|
|
36
|
+
Each environment has its own copy — update all three:
|
|
37
|
+
- Dev: `Dev-Extension-Build.yml`
|
|
38
|
+
- Pre-prod: `Pre-production.yaml`
|
|
39
|
+
- Production: `codebuild/extension-buildspec.yml`
|
|
40
|
+
|
|
41
|
+
### Adding an env var
|
|
42
|
+
| Layer | Where to add |
|
|
43
|
+
|-------|-------------|
|
|
44
|
+
| GH Actions | top-level `env:` block or step-level `env:` |
|
|
45
|
+
| CodeBuild | `env.variables:` in the buildspec YAML |
|
|
46
|
+
| Docker build-time | `--build-arg` in the `.sh` script **AND** `ARG` in `Dockerfile.v3` |
|
|
47
|
+
| Docker runtime | `-e KEY=VALUE` in `docker run` command in `buildspec-merge-v3.yaml` |
|
|
48
|
+
|
|
49
|
+
### Changing S3 targets
|
|
50
|
+
| Env | File to change |
|
|
51
|
+
|-----|---------------|
|
|
52
|
+
| Dev | `docker/v3/zip_extension.sh` |
|
|
53
|
+
| Pre-prod | `Pre-production.yaml` — "Create zip file" step |
|
|
54
|
+
| Production bundles | `deployment/PushBundleToS3.py` |
|
|
55
|
+
| Production webstore | `codebuild/webstore-buildspec-v3.yaml` |
|
|
56
|
+
|
|
57
|
+
### Gainsight changes
|
|
58
|
+
Update **both** scripts — `codebuild/gainsight_update.sh` (pre-prod + prod) and `updateGainsight.sh` (dev + prod). Production runs both.
|
|
59
|
+
|
|
60
|
+
## Reference files
|
|
61
|
+
|
|
62
|
+
**Load lazily — only read a reference file when you need it. Do NOT read all files upfront.**
|
|
63
|
+
|
|
64
|
+
| Topic | File | When to load |
|
|
65
|
+
|-------|------|--------------|
|
|
66
|
+
| Full file registry (all pipeline files with descriptions) | [references/file-registry.md](references/file-registry.md) | When you need to identify which file to edit |
|
|
67
|
+
| Bundle renaming map, failure patterns, key constants | [references/bundle-and-troubleshooting.md](references/bundle-and-troubleshooting.md) | When debugging failures or working with bundle names |
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Bundle Renaming Map & Troubleshooting
|
|
2
|
+
|
|
3
|
+
## Bundle Renaming Map
|
|
4
|
+
|
|
5
|
+
| `dist/` filename | Final name in extension package |
|
|
6
|
+
|------------------|--------------------------------|
|
|
7
|
+
| `bundle.js` | `gx_combined.js` |
|
|
8
|
+
| `bundle.expanded.js` | `gx_combined.expanded.js` |
|
|
9
|
+
| `bundle.react.prod.js` | `gx_react_combined.js` |
|
|
10
|
+
| `bundle.react.prod.js.map` | `gx_react_combined.js.map` |
|
|
11
|
+
| `bundle.react.prod.expanded.js` | `gx_react_combined.expanded.js` |
|
|
12
|
+
| `src/css/hiver_extension.css` | `hiver_extension.css` |
|
|
13
|
+
|
|
14
|
+
Renaming layer per env:
|
|
15
|
+
- **Dev:** `docker/v3/build_dev_extension.sh` (`mv` commands)
|
|
16
|
+
- **Pre-prod:** manual `cp` with new name in `Pre-production.yaml`
|
|
17
|
+
- **Production:** `deployment/PushBundleToS3.py` `BUNDLE_NAMES` dict (`os.rename`)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Common Failure Patterns
|
|
22
|
+
|
|
23
|
+
| Symptom | Root cause | Where to check |
|
|
24
|
+
|---------|-----------|----------------|
|
|
25
|
+
| Dev zip upload skipped | Neither `CODEBUILD_BUILD_ID` nor `GITHUB_RUN_ID` is set | `docker/v3/zip_extension.sh` env detection block |
|
|
26
|
+
| Bundle count validation fails (prod) | New file added to build but not registered in push script | `BUNDLE_NAMES` + `validate_upload()` in `PushBundleToS3.py` |
|
|
27
|
+
| `APP_ENV` empty in create buildspec | Deployer has no available buddy env to assign | Check `alloc_result.txt` output, deployer capacity |
|
|
28
|
+
| Yarn install fails | NPM token missing | `scripts/setup-npm-token.sh` + `EXT_NPM_TOKEN` secret |
|
|
29
|
+
| PHP config fails | `codebuild/decrypted_key.yaml` missing/malformed | File + `config/configManager.php` paths |
|
|
30
|
+
| Docker build arg missing inside image | Arg not passed via `--build-arg` | `.sh` docker build command + `Dockerfile.v3` `ARG` declaration |
|
|
31
|
+
| Wrong `APP_ENV` in dev extension | Expected — NAMESPACE in dev is injected by `buddy download-extension` CLI, not CI | `docker/v3/replace_env.sh` |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Key Constants
|
|
36
|
+
|
|
37
|
+
| Constant | Value |
|
|
38
|
+
|----------|-------|
|
|
39
|
+
| Dev S3 bucket | `landing-codebuld` |
|
|
40
|
+
| Pre-prod S3 bucket | `pre-prod-extension` |
|
|
41
|
+
| Webstore staging bucket | `testextension/test` |
|
|
42
|
+
| Gainsight CDN S3 | `hivercdn` |
|
|
43
|
+
| Pre-prod `APP_ENV` | `v2master` (hardcoded) |
|
|
44
|
+
| Merge pipeline `APP_ENV` | `dev` (hardcoded in `docker run`) |
|
|
45
|
+
| ECR service name | `extension` |
|
|
46
|
+
| Dockerfile | `Dockerfile.v3` |
|
|
47
|
+
| Deployer base URL | `https://deployer.hiver.space` |
|
|
48
|
+
| Buddy CI URL | `http://buddy-ci.hiver.space` |
|
|
49
|
+
| Production version increment | `+0.1` per build |
|
|
50
|
+
| Chrome Web Store action var | `WEB_STORE_ACTION` (`update_and_publish` / `publish` / default=update only) |
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# CI/CD Full File Registry
|
|
2
|
+
|
|
3
|
+
## GitHub Actions
|
|
4
|
+
- `.github/workflows/Dev-Extension-Build.yml` — Dev build on `qa-*` PR events
|
|
5
|
+
- `.github/workflows/Pre-production.yaml` — Manual pre-prod build
|
|
6
|
+
|
|
7
|
+
## CodeBuild Buildspecs
|
|
8
|
+
- `ci-cd/buddy/buildspec-create-v3.yaml` — PR create: buddy env assign + Docker build + ECR push
|
|
9
|
+
- `ci-cd/buddy/buildspec-merge-v3.yaml` — PR merge: builds `:latest` Docker image, runs container
|
|
10
|
+
- `codebuild/extension-buildspec.yml` — Production: full JS build, pushes bundles to CDN S3
|
|
11
|
+
- `codebuild/webstore-buildspec-v3.yaml` — Production: packages zip, publishes to Chrome Web Store
|
|
12
|
+
|
|
13
|
+
## Docker / Bash Scripts
|
|
14
|
+
- `ci-cd/buddy/build_docker_image_dev_v3.sh` — Builds image tagged `${GITHUB_SHA}`, notifies deployer
|
|
15
|
+
- `ci-cd/buddy/build_docker_image_latest.sh` — Builds image tagged `:latest` + resolved SHA
|
|
16
|
+
- `docker/v3/build_dev_extension.sh` — Assembles dev extension folder, renames bundles
|
|
17
|
+
- `docker/v3/replace_env.sh` — Injects `APP_ENV`/`NAMESPACE` placeholders via `sed`
|
|
18
|
+
- `docker/v3/zip_extension.sh` — Zips extension, uploads to S3 `landing-codebuld`
|
|
19
|
+
- `codebuild/gainsight_update.sh` — Downloads Gainsight JS, pushes to `s3://hivercdn`
|
|
20
|
+
|
|
21
|
+
## Python Deployment Scripts
|
|
22
|
+
- `deployment/GetNextbundleVersion.py` — Reads S3 for latest version, increments +0.1, writes `version.txt`
|
|
23
|
+
- `deployment/PushBundleToS3.py` — Renames + uploads bundles/CSS to CDN S3, validates count, updates DB
|
|
24
|
+
- `deployment/webstore-deployment/pushBundlesToExtensionPackage.py` — Fetches bundles from CDN into extension folder
|
|
25
|
+
- `deployment/webstore-deployment/updateItemInStore.py` — Update without publish
|
|
26
|
+
- `deployment/webstore-deployment/publishItemToStore.py` — Publish only
|
|
27
|
+
- `deployment/webstore-deployment/updateAndPublishItemToStore.py` — Update + publish
|
|
28
|
+
- `deployment/webstore-deployment/updateChromeStoreReleaseInfo.py` — Writes release info to DB
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: connect-api
|
|
3
|
+
description: API integration rules for React Query, custom hooks, and Hiver fetchers. Use when connecting to APIs, creating data-fetching or mutation hooks, or working with React Query and service utilities.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Connect API
|
|
7
|
+
|
|
8
|
+
When integrating APIs, use React Query for data and mutations, put hooks in a `hooks` folder, and use the correct fetcher from `react-extn/src/utils`. Define query keys in `constants/queries.js`.
|
|
9
|
+
|
|
10
|
+
## Reference files
|
|
11
|
+
|
|
12
|
+
**Load lazily — only read a reference file when you are about to perform that specific task. Do NOT read all files upfront.**
|
|
13
|
+
|
|
14
|
+
| Topic | File | When to load |
|
|
15
|
+
|-------|------|--------------|
|
|
16
|
+
| Hook organization | [references/hook-organization.md](references/hook-organization.md) | Before creating a new hook file |
|
|
17
|
+
| React Query (queries & mutations) | [references/react-query-usage.md](references/react-query-usage.md) | Before writing useQuery/useMutation |
|
|
18
|
+
| Query key management | [references/query-keys.md](references/query-keys.md) | Before defining query keys |
|
|
19
|
+
| Data fetcher selection | [references/data-fetchers.md](references/data-fetchers.md) | Before choosing a fetcher utility |
|
|
20
|
+
| API call structure | [references/api-call-structure.md](references/api-call-structure.md) | Before writing the fetch call body |
|
|
21
|
+
| URL and method placeholders | [references/url-placeholders.md](references/url-placeholders.md) | Only when constructing dynamic URLs |
|
|
22
|
+
| Error handling | [references/error-handling.md](references/error-handling.md) | Only when adding error/loading states |
|
|
23
|
+
| Best practices | [references/best-practices.md](references/best-practices.md) | Only when uncertain about a pattern |
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# API Call Structure
|
|
2
|
+
|
|
3
|
+
## For Modern Auth Fetchers (HiverNewAuthCall based)
|
|
4
|
+
|
|
5
|
+
- **Use async/await pattern** with error handling that returns `[data, null]` or `[null, error]`:
|
|
6
|
+
- Applies to: `AiBifrostAuth`, `CustomFieldsService`, `AutomationService`, `HiverSlaNewAuth`, `CsatNewAuthCall`, `TagBifrostAuth`, `HiverIntegrationBifrostAuth`, `HiverChatBifrostAuth`, `HiverNotesAxios`, `OutOfOfficeService`, `CustomerPortalApiService`, `HiverNotifCall`
|
|
7
|
+
```javascript
|
|
8
|
+
import { AiBifrostAuth } from "../../../../utils/AiNewAuth";
|
|
9
|
+
// OR any other modern auth fetcher
|
|
10
|
+
|
|
11
|
+
const fetchData = async (param) => {
|
|
12
|
+
try {
|
|
13
|
+
const response = await AiBifrostAuth({
|
|
14
|
+
url: `/v1/endpoint?param=${param}`,
|
|
15
|
+
method: "GET", // or "POST", "PUT", "PATCH", "DELETE"
|
|
16
|
+
data: {}, // For POST/PUT/PATCH
|
|
17
|
+
});
|
|
18
|
+
return [response.data, null];
|
|
19
|
+
} catch (err) {
|
|
20
|
+
return [null, err.message];
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## For createAxios based Fetchers
|
|
26
|
+
|
|
27
|
+
- **Use async/await pattern** with error handling:
|
|
28
|
+
- Applies to: `AiAxios`, `HiverCustomerPortalAxios`
|
|
29
|
+
```javascript
|
|
30
|
+
import { AiAxios } from "../../../../utils/AiAxios";
|
|
31
|
+
|
|
32
|
+
const fetchData = async (param) => {
|
|
33
|
+
try {
|
|
34
|
+
const response = await AiAxios({
|
|
35
|
+
url: `/v1/endpoint?param=${param}`,
|
|
36
|
+
method: "GET", // or "POST", "PUT", "PATCH", "DELETE"
|
|
37
|
+
data: {}, // For POST/PUT/PATCH
|
|
38
|
+
});
|
|
39
|
+
return [response.data, null];
|
|
40
|
+
} catch (err) {
|
|
41
|
+
return [null, err.message];
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## For Legacy HiverAxios
|
|
47
|
+
|
|
48
|
+
- **Use async/await with try/catch**:
|
|
49
|
+
```javascript
|
|
50
|
+
import { HiverAxios } from "h-extension-common";
|
|
51
|
+
|
|
52
|
+
const fetchData = async (payload) => {
|
|
53
|
+
try {
|
|
54
|
+
const response = await HiverAxios({
|
|
55
|
+
url: `/api/endpoint`,
|
|
56
|
+
type: "GET", // or "POST", "PUT", "DELETE" - Note: uses "type" not "method"
|
|
57
|
+
params: payload, // Request body/params
|
|
58
|
+
});
|
|
59
|
+
return [response.data, null];
|
|
60
|
+
} catch (err) {
|
|
61
|
+
return [null, err.message];
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## For HiverAnalyticsAxios
|
|
67
|
+
|
|
68
|
+
- **Use async/await with try/catch**:
|
|
69
|
+
```javascript
|
|
70
|
+
import { HiverAnalyticsAxios } from "../../../../utils/HiverAnalyticsAxios";
|
|
71
|
+
|
|
72
|
+
const fetchData = async (payload) => {
|
|
73
|
+
try {
|
|
74
|
+
const response = await HiverAnalyticsAxios({
|
|
75
|
+
url: `/api/endpoint`,
|
|
76
|
+
type: "GET", // or "POST", "PUT", "PATCH", "DELETE"
|
|
77
|
+
params: payload, // Request body/params
|
|
78
|
+
});
|
|
79
|
+
return [response.parsedBody, null]; // Note: HiverAnalyticsAxios returns parsedBody
|
|
80
|
+
} catch (err) {
|
|
81
|
+
return [null, err.message];
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Best Practices
|
|
2
|
+
|
|
3
|
+
- **Keep API functions pure** - separate API logic from React Query hooks
|
|
4
|
+
- **Use TypeScript types** if the project uses TypeScript
|
|
5
|
+
- **Add JSDoc comments** for complex hooks explaining parameters and return values
|
|
6
|
+
- **Handle loading states** using `isLoading`, `isFetching` from React Query
|
|
7
|
+
- **Handle error states** using `isError`, `error` from React Query
|
|
8
|
+
- **Use `enabled` option** for conditional queries
|
|
9
|
+
- **Use `refetchOnMount`, `refetchOnWindowFocus`** options when needed
|
|
10
|
+
- **Export query keys** from hook files for use in other components
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Data Fetcher Selection
|
|
2
|
+
|
|
3
|
+
- **All data fetcher utilities are located in `react-extn/src/utils`**
|
|
4
|
+
- **Use the appropriate fetcher** based on the service you're working with:
|
|
5
|
+
|
|
6
|
+
## Modern Auth Fetchers (HiverNewAuthCall based)
|
|
7
|
+
|
|
8
|
+
These use `method` (GET, POST, PUT, PATCH, DELETE) and return promises:
|
|
9
|
+
|
|
10
|
+
| Fetcher | Use Case | Service | Import Path |
|
|
11
|
+
|---------|----------|---------|-------------|
|
|
12
|
+
| `AiBifrostAuth` | AI service endpoints | AI Service | `../../../../utils/AiNewAuth` |
|
|
13
|
+
| `CustomFieldsService` | Custom fields operations | Custom Fields Service | `../../../../utils/CustomFieldsService` |
|
|
14
|
+
| `AutomationService` | Automation workflows | Automations Service | `../../../../utils/AutomationService` |
|
|
15
|
+
| `HiverSlaNewAuth` | SLA management | SLA Service | `../../../../utils/slaNewAuth` |
|
|
16
|
+
| `CsatNewAuthCall` | CSAT surveys | CSAT Service | `../../../../utils/csatNewAuth` |
|
|
17
|
+
| `TagBifrostAuth` | Tag operations | Tags Service | `../../../../utils/tagNewAuth` |
|
|
18
|
+
| `HiverIntegrationBifrostAuth` | Integration endpoints | Integration Service | `../../../../utils/integrationNewAuth` |
|
|
19
|
+
| `HiverChatBifrostAuth` | Chat/channels operations | Channels Service | `../../../../utils/chatNewAuth` |
|
|
20
|
+
| `HiverNotesAxios` | Notes operations | Notes Service | `../../../../utils/HiverNotesNewAuth` |
|
|
21
|
+
| `OutOfOfficeService` | Schedule management | Schedule Service | `../../../../utils/OutOfOfficeService` |
|
|
22
|
+
| `CustomerPortalApiService` | Customer portal | Customer Portal Service | `../../../../utils/CustomerPortalApiService` |
|
|
23
|
+
| `HiverNotifCall` | Notifications | Notifications Service | `../../../../utils/notificationAuthCall` |
|
|
24
|
+
|
|
25
|
+
**Usage pattern for modern auth fetchers:**
|
|
26
|
+
```javascript
|
|
27
|
+
import { AiBifrostAuth } from "../../../../utils/AiNewAuth";
|
|
28
|
+
// OR
|
|
29
|
+
import { CustomFieldsService } from "../../../../utils/CustomFieldsService";
|
|
30
|
+
|
|
31
|
+
const response = await AiBifrostAuth({
|
|
32
|
+
url: `/v1/endpoint`,
|
|
33
|
+
method: "GET", // or "POST", "PUT", "PATCH", "DELETE"
|
|
34
|
+
data: {}, // For POST/PUT/PATCH
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## createAxios based Fetchers
|
|
39
|
+
|
|
40
|
+
These use `method` and return promises:
|
|
41
|
+
|
|
42
|
+
| Fetcher | Use Case | Service | Import Path |
|
|
43
|
+
|---------|----------|---------|-------------|
|
|
44
|
+
| `AiAxios` | AI service (legacy) | AI Service | `../../../../utils/AiAxios` |
|
|
45
|
+
| `HiverCustomerPortalAxios` | Customer portal (legacy) | Customer Portal Service | `../../../../utils/CustomerPortalAxios` |
|
|
46
|
+
|
|
47
|
+
## Legacy/Custom Fetchers
|
|
48
|
+
|
|
49
|
+
| Fetcher | Use Case | Service | Import Path |
|
|
50
|
+
|---------|----------|---------|-------------|
|
|
51
|
+
| `HiverAxios` | Legacy API calls | Default Hiver API | `h-extension-common` |
|
|
52
|
+
| `HiverAnalyticsAxios` | Analytics data | Analytics Service | `../../../../utils/HiverAnalyticsAxios` |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Error Handling
|
|
2
|
+
|
|
3
|
+
- **Handle errors in mutation hooks**:
|
|
4
|
+
```javascript
|
|
5
|
+
import { useSnackbar } from "../../../../common";
|
|
6
|
+
import { theme } from "@hiver/hiver-ui-kit";
|
|
7
|
+
|
|
8
|
+
const showSnackbar = useSnackbar();
|
|
9
|
+
|
|
10
|
+
// In mutation onSuccess handler
|
|
11
|
+
onSuccess: (response) => {
|
|
12
|
+
const [result, error] = response;
|
|
13
|
+
if (error) {
|
|
14
|
+
showSnackbar({
|
|
15
|
+
message: error || "Operation failed",
|
|
16
|
+
background: theme.palette.red.primary,
|
|
17
|
+
});
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
// Handle success...
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
// In mutation onError handler (for unexpected errors)
|
|
24
|
+
onError: (error, variables, context) => {
|
|
25
|
+
showSnackbar({
|
|
26
|
+
message: error.message || "Operation failed",
|
|
27
|
+
background: theme.palette.red.primary,
|
|
28
|
+
});
|
|
29
|
+
// Rollback optimistic updates if needed
|
|
30
|
+
if (context?.previousData) {
|
|
31
|
+
queryClient.setQueryData([API_QUERIES.resource], context.previousData);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Hook Organization
|
|
2
|
+
|
|
3
|
+
- **Always create separate custom hooks** for querying and mutating server data
|
|
4
|
+
- **Place hooks in a `hooks` folder** within the module/component directory
|
|
5
|
+
- Example structure: `react-extn/src/AiCopilot/Pages/Chat/hooks/` or `react-extn/src/AiCopilot/Pages/Tags/hooks/`
|
|
6
|
+
- **Naming convention**:
|
|
7
|
+
- Query hooks: `useGet[ResourceName].js` (e.g., `useGetChatList.js`, `useGetSuggestedTags.js`)
|
|
8
|
+
- Mutation hooks: `use[Action][ResourceName].js` (e.g., `useSendChatMessage.js`, `useApplyTags.js`)
|
|
9
|
+
- **Reference examples**:
|
|
10
|
+
- `react-extn/src/AiCopilot/Pages/Chat/hooks/useGetChatList.js`
|
|
11
|
+
- `react-extn/src/AiCopilot/Pages/Tags/hooks/useGetSuggestedTags.js`
|