@rashidee/co2 1.2.5

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.
Files changed (190) hide show
  1. package/dist/index.js +25449 -0
  2. package/drizzle/0000_remarkable_charles_xavier.sql +210 -0
  3. package/drizzle/0001_wise_wolf_cub.sql +13 -0
  4. package/drizzle/0002_secret_spyke.sql +16 -0
  5. package/drizzle/0003_workspace_config_singleton.sql +16 -0
  6. package/drizzle/0004_terminal_claim_v120.sql +11 -0
  7. package/drizzle/0005_brainstorm_v124.sql +10 -0
  8. package/drizzle/0006_project_v140.sql +6 -0
  9. package/drizzle/0007_prd_wizard_v124.sql +14 -0
  10. package/drizzle/0008_workflow_artifact_v126.sql +24 -0
  11. package/drizzle/0009_project_import_v150.sql +7 -0
  12. package/drizzle/0010_quality_v151.sql +3 -0
  13. package/drizzle/meta/0000_snapshot.json +1335 -0
  14. package/drizzle/meta/0001_snapshot.json +1416 -0
  15. package/drizzle/meta/0002_snapshot.json +1510 -0
  16. package/drizzle/meta/_journal.json +83 -0
  17. package/package.json +41 -0
  18. package/plugin/.claude-plugin/marketplace.json +36 -0
  19. package/plugin/.claude-plugin/plugin.json +22 -0
  20. package/plugin/README.md +625 -0
  21. package/plugin/SKILLS.md +350 -0
  22. package/plugin/co2.svg +5 -0
  23. package/plugin/commands/brainstorm-loop.md +129 -0
  24. package/plugin/skills/conductor-defect/SKILL.md +898 -0
  25. package/plugin/skills/conductor-feature-develop/SKILL.md +1383 -0
  26. package/plugin/skills/conductor-feature-develop/references/implementation-domain-template.md +131 -0
  27. package/plugin/skills/conductor-feature-develop/references/implementation-master-template.md +89 -0
  28. package/plugin/skills/conductor-feature-develop/references/playwright-setup.md +224 -0
  29. package/plugin/skills/conductor-feature-prepare/SKILL.md +604 -0
  30. package/plugin/skills/depgen-k8s/SKILL.md +468 -0
  31. package/plugin/skills/depgen-k8s/references/dockerfile-laravel.md +197 -0
  32. package/plugin/skills/depgen-k8s/references/dockerfile-nodejs.md +163 -0
  33. package/plugin/skills/depgen-k8s/references/dockerfile-spring-boot.md +174 -0
  34. package/plugin/skills/depgen-k8s/references/k8s-patterns.md +869 -0
  35. package/plugin/skills/mockgen-shadcn/SKILL.md +1067 -0
  36. package/plugin/skills/mockgen-shadcn/references/admin-layout-template.md +1467 -0
  37. package/plugin/skills/mockgen-shadcn/references/mockup-hub-template.md +498 -0
  38. package/plugin/skills/mockgen-shadcn/references/mockup-index-template.md +216 -0
  39. package/plugin/skills/mockgen-tailwind/SKILL.md +904 -0
  40. package/plugin/skills/mockgen-tailwind/references/admin-layout-template.md +720 -0
  41. package/plugin/skills/mockgen-tailwind/references/mockup-hub-template.md +498 -0
  42. package/plugin/skills/mockgen-tailwind/references/mockup-index-template.md +190 -0
  43. package/plugin/skills/modelgen-nosql/SKILL.md +617 -0
  44. package/plugin/skills/modelgen-nosql/references/model-extraction-methodology.md +497 -0
  45. package/plugin/skills/modelgen-nosql/references/nosql-design-guide.md +258 -0
  46. package/plugin/skills/modelgen-relational/SKILL.md +707 -0
  47. package/plugin/skills/modelgen-relational/references/model-extraction-methodology.md +499 -0
  48. package/plugin/skills/specgen-flutter-riverpod/SKILL.md +898 -0
  49. package/plugin/skills/specgen-flutter-riverpod/references/component-patterns.md +971 -0
  50. package/plugin/skills/specgen-flutter-riverpod/references/notification-patterns.md +457 -0
  51. package/plugin/skills/specgen-flutter-riverpod/references/routing-patterns.md +362 -0
  52. package/plugin/skills/specgen-flutter-riverpod/references/security-patterns.md +709 -0
  53. package/plugin/skills/specgen-flutter-riverpod/references/spec-template.md +1566 -0
  54. package/plugin/skills/specgen-flutter-riverpod/references/state-patterns.md +518 -0
  55. package/plugin/skills/specgen-flutter-riverpod/references/storage-patterns.md +370 -0
  56. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/SKILL.md +984 -0
  57. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/batch-patterns.md +359 -0
  58. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/messaging-patterns.md +468 -0
  59. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/modulith-patterns.md +461 -0
  60. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/reporting-patterns.md +803 -0
  61. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/security-patterns.md +501 -0
  62. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/spec-template.md +1268 -0
  63. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/web-patterns.md +301 -0
  64. package/plugin/skills/specgen-node-cli-web/SKILL.md +561 -0
  65. package/plugin/skills/specgen-node-cli-web/references/auth-patterns.md +293 -0
  66. package/plugin/skills/specgen-node-cli-web/references/cli-packaging-patterns.md +250 -0
  67. package/plugin/skills/specgen-node-cli-web/references/server-patterns.md +247 -0
  68. package/plugin/skills/specgen-node-cli-web/references/spec-template.md +401 -0
  69. package/plugin/skills/specgen-node-cli-web/references/testing-patterns.md +174 -0
  70. package/plugin/skills/specgen-react-mui/SKILL.md +789 -0
  71. package/plugin/skills/specgen-react-mui/references/component-patterns.md +1077 -0
  72. package/plugin/skills/specgen-react-mui/references/reporting-patterns.md +1998 -0
  73. package/plugin/skills/specgen-react-mui/references/routing-patterns.md +461 -0
  74. package/plugin/skills/specgen-react-mui/references/security-patterns.md +599 -0
  75. package/plugin/skills/specgen-react-mui/references/spec-template.md +1030 -0
  76. package/plugin/skills/specgen-react-mui/references/state-patterns.md +327 -0
  77. package/plugin/skills/specgen-react-tailwind/SKILL.md +859 -0
  78. package/plugin/skills/specgen-react-tailwind/references/component-patterns.md +1212 -0
  79. package/plugin/skills/specgen-react-tailwind/references/reporting-patterns.md +1529 -0
  80. package/plugin/skills/specgen-react-tailwind/references/routing-patterns.md +669 -0
  81. package/plugin/skills/specgen-react-tailwind/references/security-patterns.md +656 -0
  82. package/plugin/skills/specgen-react-tailwind/references/spec-template.md +1237 -0
  83. package/plugin/skills/specgen-react-tailwind/references/state-patterns.md +327 -0
  84. package/plugin/skills/specgen-sdk-java/SKILL.md +933 -0
  85. package/plugin/skills/specgen-sdk-java/references/api-extraction-patterns.md +247 -0
  86. package/plugin/skills/specgen-sdk-java/references/http-client-patterns.md +495 -0
  87. package/plugin/skills/specgen-sdk-java/references/packaging-patterns.md +366 -0
  88. package/plugin/skills/specgen-sdk-java/references/spec-template.md +956 -0
  89. package/plugin/skills/specgen-spring-jpa-jtehtmx/SKILL.md +1284 -0
  90. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/batch-patterns.md +1224 -0
  91. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/jasper-patterns.md +1638 -0
  92. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/messaging-patterns.md +512 -0
  93. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/modulith-patterns.md +354 -0
  94. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/security-patterns.md +551 -0
  95. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/spec-template.md +2502 -0
  96. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/web-patterns.md +503 -0
  97. package/plugin/skills/specgen-spring-jpa-restapi/SKILL.md +990 -0
  98. package/plugin/skills/specgen-spring-jpa-restapi/references/batch-patterns.md +1224 -0
  99. package/plugin/skills/specgen-spring-jpa-restapi/references/messaging-patterns.md +512 -0
  100. package/plugin/skills/specgen-spring-jpa-restapi/references/modulith-patterns.md +279 -0
  101. package/plugin/skills/specgen-spring-jpa-restapi/references/reporting-patterns.md +1536 -0
  102. package/plugin/skills/specgen-spring-jpa-restapi/references/restapi-patterns.md +722 -0
  103. package/plugin/skills/specgen-spring-jpa-restapi/references/security-patterns.md +351 -0
  104. package/plugin/skills/specgen-spring-jpa-restapi/references/spec-template.md +553 -0
  105. package/plugin/skills/specgen-ts-cli/SKILL.md +861 -0
  106. package/plugin/skills/specgen-ts-cli/references/async-patterns.md +1101 -0
  107. package/plugin/skills/specgen-ts-cli/references/command-patterns.md +383 -0
  108. package/plugin/skills/specgen-ts-cli/references/config-patterns.md +430 -0
  109. package/plugin/skills/specgen-ts-cli/references/database-patterns.md +750 -0
  110. package/plugin/skills/specgen-ts-cli/references/packaging-patterns.md +426 -0
  111. package/plugin/skills/specgen-ts-cli/references/spec-template.md +1391 -0
  112. package/plugin/skills/specgen-ts-cli/references/testing-patterns.md +909 -0
  113. package/plugin/skills/testgen-functional/SKILL.md +1381 -0
  114. package/plugin/skills/tracegen-matrix/SKILL.md +243 -0
  115. package/plugin/skills/util-preparek8senv/SKILL.md +422 -0
  116. package/plugin/skills/util-projectinit/SKILL.md +307 -0
  117. package/plugin/skills/util-projectinit/reference/brainstorm-loop.md +129 -0
  118. package/plugin/skills/util-projectinit/reference/brainstorm-protocol.md +144 -0
  119. package/plugin/skills/util-projectinit/reference/brainstorm-setup-guide.md +153 -0
  120. package/plugin/skills/util-projectinit/reference/brainstorm-template-appdev.md +87 -0
  121. package/plugin/skills/util-projectinit/reference/co2-context-generation-guide.md +761 -0
  122. package/plugin/skills/util-projectsync/SKILL.md +501 -0
  123. package/plugin/skills/util-updprd/SKILL.md +324 -0
  124. package/plugin/skills/util-usanalyzer/SKILL.md +307 -0
  125. package/plugin/skills/util-ustagger/SKILL.md +154 -0
  126. package/static/assets/abnfDiagram-VRR7QNED-DvPuwyCV.js +1 -0
  127. package/static/assets/arc-DRKw7sjs.js +1 -0
  128. package/static/assets/architectureDiagram-ZJ3FMSHR-CaNcxUbC.js +36 -0
  129. package/static/assets/blockDiagram-677ZJIJ3-Demd4AOK.js +132 -0
  130. package/static/assets/c4Diagram-LMCZKHZV-PVKUfc2x.js +10 -0
  131. package/static/assets/channel-C2nVbuwv.js +1 -0
  132. package/static/assets/chunk-2Q5K7J3B-CExf8ww_.js +1 -0
  133. package/static/assets/chunk-32BRIVSS-CFPaoONF.js +1 -0
  134. package/static/assets/chunk-5VM5RSS4-DE2esM67.js +15 -0
  135. package/static/assets/chunk-EX3LRPZG-SON_YdDG.js +231 -0
  136. package/static/assets/chunk-JWPE2WC7-Qxah8LNr.js +1 -0
  137. package/static/assets/chunk-MOJQB5TN-BcWGQV3j.js +88 -0
  138. package/static/assets/chunk-RYQCIY6F-DkDj-OR5.js +1 -0
  139. package/static/assets/chunk-V7JOEXUC-BlI1Mrah.js +206 -0
  140. package/static/assets/chunk-VR4S4FIN-Agf__duj.js +1 -0
  141. package/static/assets/chunk-XXDRQBXY-B5CfAh85.js +1 -0
  142. package/static/assets/classDiagram-OUVF2IWQ-DXJIljsR.js +1 -0
  143. package/static/assets/classDiagram-v2-EOCWNBFH-DXJIljsR.js +1 -0
  144. package/static/assets/cose-bilkent-JH36ORCC-DO0cQkcy.js +1 -0
  145. package/static/assets/cynefin-VYW2F7L2-CfOnsnXc.js +178 -0
  146. package/static/assets/cynefinDiagram-TSTJHNR4-BJ8tULAv.js +62 -0
  147. package/static/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
  148. package/static/assets/dagre-VKFMJZFB-DfjwzHqP.js +4 -0
  149. package/static/assets/defaultLocale-DX6XiGOO.js +1 -0
  150. package/static/assets/diagram-FQU43EPY-CndSOIIM.js +3 -0
  151. package/static/assets/diagram-G47NLZAW-Czf5hN0Z.js +24 -0
  152. package/static/assets/diagram-NH7WQ7WH-COAyojGh.js +24 -0
  153. package/static/assets/diagram-OA4YK3LP-H8PoiN2m.js +30 -0
  154. package/static/assets/diagram-WEI45ONY-DzcaVzjp.js +41 -0
  155. package/static/assets/ebnfDiagram-CCIWWBDH-DPazGYLJ.js +1 -0
  156. package/static/assets/erDiagram-Q63AITRT-Bo-fubgF.js +85 -0
  157. package/static/assets/flowDiagram-23GEKE2U-CSvxUDwh.js +156 -0
  158. package/static/assets/ganttDiagram-NO4QXBWP-DnBveWX6.js +292 -0
  159. package/static/assets/gitGraphDiagram-IHSO6WYX-B3rVL8c-.js +106 -0
  160. package/static/assets/graph-C9eacEi8.js +1 -0
  161. package/static/assets/index-LZSQkLE2.css +41 -0
  162. package/static/assets/index-y7XDSgMG.js +495 -0
  163. package/static/assets/infoDiagram-FWYZ7A6U-CvWV9yy2.js +2 -0
  164. package/static/assets/init-Gi6I4Gst.js +1 -0
  165. package/static/assets/ishikawaDiagram-FXEZZL3T-DF28a1N6.js +70 -0
  166. package/static/assets/journeyDiagram-5HDEW3XC-CB6CugYk.js +139 -0
  167. package/static/assets/kanban-definition-HUTT4EX6-ResSLF6d.js +89 -0
  168. package/static/assets/katex-C5jXJg4s.js +257 -0
  169. package/static/assets/layout-DEXfKzaS.js +1 -0
  170. package/static/assets/linear-CLO--ryk.js +1 -0
  171. package/static/assets/map-Czzmt4hB.js +1 -0
  172. package/static/assets/mindmap-definition-LN4V7U3C-BvW3EbxX.js +96 -0
  173. package/static/assets/ordinal-Cboi1Yqb.js +1 -0
  174. package/static/assets/pegDiagram-2B236MQR-BHCgqrrM.js +1 -0
  175. package/static/assets/pieDiagram-ENE6RG2P-DVmCQ5FA.js +39 -0
  176. package/static/assets/quadrantDiagram-ABIIQ3AL-B3e5KR52.js +7 -0
  177. package/static/assets/railroadDiagram-RFXS5EU6-Csv5ysLc.js +1 -0
  178. package/static/assets/requirementDiagram-TGXJPOKE-DOMVzvnB.js +84 -0
  179. package/static/assets/sankeyDiagram-HTMAVEWB-B1dcTOvy.js +40 -0
  180. package/static/assets/sequenceDiagram-DBY2YBRQ-BY414yeO.js +162 -0
  181. package/static/assets/sizeCapture-X5ZJPWSS-CuJfrfBN.js +1 -0
  182. package/static/assets/stateDiagram-2N3HPSRC-FX4rJkzV.js +1 -0
  183. package/static/assets/stateDiagram-v2-6OUMAXLB-BVufbO_H.js +1 -0
  184. package/static/assets/swimlanes-5IMT3BWC-Sfy58mmv.js +2 -0
  185. package/static/assets/swimlanesDiagram-G3AALYLV-wDCDw08H.js +8 -0
  186. package/static/assets/timeline-definition-FHXFAJF6-CmV7by8p.js +120 -0
  187. package/static/assets/vennDiagram-L72KCM5P-FqIyFZFt.js +34 -0
  188. package/static/assets/wardleyDiagram-EHGQE667-BZ06O45i.js +78 -0
  189. package/static/assets/xychartDiagram-FW5EYKEG-BOkffR06.js +7 -0
  190. package/static/index.html +24 -0
@@ -0,0 +1,327 @@
1
+ # State Management Patterns — Zustand Feature Stores & TanStack Query
2
+
3
+ This reference describes when and how to use feature-level Zustand stores alongside
4
+ TanStack Query. Include this content in Section 9 of the generated specification and
5
+ in any module SPEC.md that requires client-side state beyond server cache.
6
+
7
+ The state model is identical to the MUI variant — TanStack Query owns server state, Zustand
8
+ owns UI state, React Hook Form owns form state. Only the rendered UI in the examples is
9
+ Tailwind/Headless UI instead of MUI.
10
+
11
+ ---
12
+
13
+ ## State Separation Principle
14
+
15
+ The golden rule for React SPA state management:
16
+
17
+ | State Type | Tool | Examples |
18
+ |---|---|---|
19
+ | **Server state** (data from API) | TanStack Query | Hero section list, user profile, blog posts |
20
+ | **UI state** (ephemeral, per-session) | Zustand | Selected rows, filter panel open/closed, active tab |
21
+ | **Global UI state** | Zustand (persisted) | Theme mode, sidebar open, user preferences |
22
+ | **Auth state** | Zustand (memory-only, no persist) | JWT token, logged-in user info |
23
+ | **Form state** | React Hook Form | All form field values and validation errors |
24
+
25
+ **Do NOT use Zustand to cache API responses.** If data comes from the server, TanStack
26
+ Query owns it. Zustand holds only the filters/pagination params that TanStack Query uses
27
+ as its query key.
28
+
29
+ ---
30
+
31
+ ## Feature Store Pattern
32
+
33
+ Create a feature store only when the module has complex UI state that needs to be shared
34
+ between sibling components (e.g., a list page and a detail panel rendered side-by-side).
35
+
36
+ ### When to create a feature store
37
+
38
+ | Scenario | Use feature store? |
39
+ |---|---|
40
+ | List page with filter bar → filter values | **Yes** — filter state drives TanStack Query params |
41
+ | Multi-step form with shared wizard state | **Yes** — wizard step and accumulated values |
42
+ | List page + slide-over detail panel (side-by-side) | **Yes** — selected item ID |
43
+ | Simple list page with local filter `useState` | **No** — keep state local |
44
+ | Simple create/edit form | **No** — React Hook Form handles form state |
45
+
46
+ ### Feature Store Template
47
+
48
+ ```typescript
49
+ // Example: src/features/heroSection/store/heroSection.store.ts
50
+ import { create } from 'zustand';
51
+ import type { HeroSectionListParams } from '../heroSection.types';
52
+
53
+ interface HeroSectionState {
54
+ // Filter and pagination params — these drive the TanStack Query key
55
+ filters: HeroSectionListParams;
56
+
57
+ // UI state
58
+ selectedIds: Set<string>;
59
+ isDetailPanelOpen: boolean;
60
+ selectedId: string | null;
61
+
62
+ // Actions
63
+ setFilter: (key: keyof HeroSectionListParams, value: unknown) => void;
64
+ resetFilters: () => void;
65
+ setPage: (page: number) => void;
66
+ toggleSelectId: (id: string) => void;
67
+ clearSelection: () => void;
68
+ openDetail: (id: string) => void;
69
+ closeDetail: () => void;
70
+ }
71
+
72
+ const DEFAULT_FILTERS: HeroSectionListParams = { page: 0, size: 10, status: '' };
73
+
74
+ export const useHeroSectionStore = create<HeroSectionState>((set) => ({
75
+ filters: { ...DEFAULT_FILTERS },
76
+ selectedIds: new Set(),
77
+ isDetailPanelOpen: false,
78
+ selectedId: null,
79
+
80
+ setFilter: (key, value) =>
81
+ set((state) => ({ filters: { ...state.filters, [key]: value, page: 0 } })),
82
+
83
+ resetFilters: () => set({ filters: { ...DEFAULT_FILTERS } }),
84
+
85
+ setPage: (page) => set((state) => ({ filters: { ...state.filters, page } })),
86
+
87
+ toggleSelectId: (id) =>
88
+ set((state) => {
89
+ const next = new Set(state.selectedIds);
90
+ next.has(id) ? next.delete(id) : next.add(id);
91
+ return { selectedIds: next };
92
+ }),
93
+
94
+ clearSelection: () => set({ selectedIds: new Set() }),
95
+
96
+ openDetail: (id) => set({ selectedId: id, isDetailPanelOpen: true }),
97
+
98
+ closeDetail: () => set({ isDetailPanelOpen: false, selectedId: null }),
99
+ }));
100
+ ```
101
+
102
+ ### Integration with TanStack Query
103
+
104
+ ```tsx
105
+ // src/features/heroSection/pages/HeroSectionListPage.tsx
106
+ import { useHeroSectionStore } from '../store/heroSection.store';
107
+ import { useHeroSections } from '../hooks/useHeroSections';
108
+ import { SearchInput } from '../../../shared/components/SearchInput';
109
+ import { DataTable } from '../../../shared/components/DataTable';
110
+ import { Pagination } from '../../../shared/components/Pagination';
111
+
112
+ export function HeroSectionListPage() {
113
+ // Filter state lives in Zustand — changes trigger React re-render
114
+ const { filters, setFilter, setPage } = useHeroSectionStore();
115
+
116
+ // TanStack Query uses filters as the query key — auto-refetches when filters change
117
+ const { data, isLoading } = useHeroSections(filters);
118
+
119
+ return (
120
+ <div className="space-y-4">
121
+ <div className="flex flex-wrap items-center gap-3">
122
+ <SearchInput
123
+ placeholder="Search…"
124
+ onChange={(value) => setFilter('search', value)}
125
+ />
126
+ <select
127
+ value={filters.status ?? ''}
128
+ onChange={(e) => setFilter('status', e.target.value)}
129
+ className="rounded border border-slate-300 bg-surface px-3 py-2 text-sm focus:border-primary focus:ring-1 focus:ring-primary dark:border-slate-600"
130
+ >
131
+ <option value="">All Statuses</option>
132
+ <option value="ACTIVE">Active</option>
133
+ <option value="DRAFT">Draft</option>
134
+ </select>
135
+ </div>
136
+
137
+ {/* DataTable + Pagination — see routing-patterns.md for implementations */}
138
+ <DataTable columns={columns} data={data?.content ?? []} emptyMessage={isLoading ? 'Loading…' : undefined} />
139
+ <Pagination
140
+ page={filters.page ?? 0}
141
+ size={filters.size ?? 10}
142
+ totalElements={data?.totalElements ?? 0}
143
+ onPageChange={(page) => setPage(page)}
144
+ onSizeChange={(size) => setFilter('size', size)}
145
+ />
146
+ </div>
147
+ );
148
+ }
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Optimistic Updates Pattern
154
+
155
+ For fast UI feedback on mutations (useful for toggle operations like status changes):
156
+
157
+ ```typescript
158
+ // src/features/heroSection/hooks/useHeroSectionMutations.ts
159
+ import { useMutation, useQueryClient } from '@tanstack/react-query';
160
+ import { heroSectionApi } from '../api/heroSectionApi';
161
+ import { heroSectionKeys } from './useHeroSections';
162
+ import type { HeroSection } from '../heroSection.types';
163
+
164
+ export function useToggleHeroSectionStatus() {
165
+ const queryClient = useQueryClient();
166
+
167
+ return useMutation({
168
+ mutationFn: ({ id, status }: { id: string; status: HeroSection['status'] }) =>
169
+ heroSectionApi.update(id, { status }),
170
+
171
+ // Optimistic update — immediately update the cache before the API responds
172
+ onMutate: async ({ id, status }) => {
173
+ await queryClient.cancelQueries({ queryKey: heroSectionKeys.all });
174
+ const previousData = queryClient.getQueryData<HeroSection>(heroSectionKeys.detail(id));
175
+ queryClient.setQueryData<HeroSection>(heroSectionKeys.detail(id), (old) =>
176
+ old ? { ...old, status } : old,
177
+ );
178
+ return { previousData };
179
+ },
180
+
181
+ // On error, roll back to the previous value
182
+ onError: (_error, { id }, context) => {
183
+ if (context?.previousData) {
184
+ queryClient.setQueryData(heroSectionKeys.detail(id), context.previousData);
185
+ }
186
+ },
187
+
188
+ // Always refetch after error or success to sync with server
189
+ onSettled: (_, __, { id }) => {
190
+ queryClient.invalidateQueries({ queryKey: heroSectionKeys.detail(id) });
191
+ queryClient.invalidateQueries({ queryKey: heroSectionKeys.lists() });
192
+ },
193
+ });
194
+ }
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Multi-Step Form Pattern (Wizard)
200
+
201
+ For complex forms spanning multiple steps (e.g., blog post creation with metadata, content, and preview steps):
202
+
203
+ ```typescript
204
+ // src/features/blog/store/blogCreate.store.ts
205
+ import { create } from 'zustand';
206
+ import type { BlogCreateStep1Values, BlogCreateStep2Values } from '../blog.schema';
207
+
208
+ type WizardStep = 'metadata' | 'content' | 'preview';
209
+
210
+ interface BlogCreateState {
211
+ currentStep: WizardStep;
212
+ step1Data: BlogCreateStep1Values | null;
213
+ step2Data: BlogCreateStep2Values | null;
214
+
215
+ goToStep: (step: WizardStep) => void;
216
+ saveStep1: (data: BlogCreateStep1Values) => void;
217
+ saveStep2: (data: BlogCreateStep2Values) => void;
218
+ reset: () => void;
219
+ }
220
+
221
+ export const useBlogCreateStore = create<BlogCreateState>((set) => ({
222
+ currentStep: 'metadata',
223
+ step1Data: null,
224
+ step2Data: null,
225
+
226
+ goToStep: (step) => set({ currentStep: step }),
227
+ saveStep1: (data) => set({ step1Data: data, currentStep: 'content' }),
228
+ saveStep2: (data) => set({ step2Data: data, currentStep: 'preview' }),
229
+ reset: () => set({ currentStep: 'metadata', step1Data: null, step2Data: null }),
230
+ }));
231
+ ```
232
+
233
+ > Render wizard steps with the Headless UI `Tab` group, or with conditional rendering keyed
234
+ > on `currentStep`. A step indicator can be a simple Tailwind flex row of numbered badges.
235
+
236
+ ---
237
+
238
+ ## Cache Invalidation Strategy
239
+
240
+ Follow this decision tree when invalidating TanStack Query cache after mutations:
241
+
242
+ | Mutation | Invalidation Target |
243
+ |---|---|
244
+ | Create item | `queryKey: entityKeys.lists()` — all list queries |
245
+ | Update item | `queryKey: entityKeys.detail(id)` + `entityKeys.lists()` |
246
+ | Delete item | `queryKey: entityKeys.lists()` |
247
+ | Bulk action (delete multiple) | `queryKey: entityKeys.all` |
248
+ | Status toggle | `queryKey: entityKeys.detail(id)` + `entityKeys.lists()` |
249
+
250
+ Always use `invalidateQueries` (not `removeQueries`) so the UI shows stale data with
251
+ a loading indicator rather than an empty flash.
252
+
253
+ ---
254
+
255
+ ## Prefetching for Navigation
256
+
257
+ Prefetch list data when hovering a navigation link to make page transitions feel instant:
258
+
259
+ ```typescript
260
+ // In AppSidebar or a NavLink wrapper component
261
+ import { useQueryClient } from '@tanstack/react-query';
262
+ import { heroSectionKeys } from '../../features/heroSection/hooks/useHeroSections';
263
+ import { heroSectionApi } from '../../features/heroSection/api/heroSectionApi';
264
+
265
+ function useHeroSectionPrefetch() {
266
+ const queryClient = useQueryClient();
267
+
268
+ return () =>
269
+ queryClient.prefetchQuery({
270
+ queryKey: heroSectionKeys.list({ page: 0, size: 10 }),
271
+ queryFn: () => heroSectionApi.list({ page: 0, size: 10 }),
272
+ staleTime: 30_000,
273
+ });
274
+ }
275
+
276
+ // Usage: <NavLink to="/hero-section" onMouseEnter={prefetch}>…</NavLink>
277
+ ```
278
+
279
+ ---
280
+
281
+ ## Error State Handling in Pages
282
+
283
+ ```tsx
284
+ // Pattern for handling query errors in page components (Tailwind alert)
285
+ import { ExclamationTriangleIcon } from '@heroicons/react/24/outline';
286
+ import { Button } from '../../../shared/components/Button';
287
+
288
+ export function HeroSectionListPage() {
289
+ const { data, isLoading, isError, error, refetch } = useHeroSections(filters);
290
+
291
+ if (isError) {
292
+ return (
293
+ <div className="mt-6 flex items-start gap-3 rounded border border-danger/40 bg-danger/5 p-4">
294
+ <ExclamationTriangleIcon className="mt-0.5 h-5 w-5 shrink-0 text-danger" />
295
+ <div className="flex-1">
296
+ <p className="text-sm text-danger">
297
+ {error instanceof Error ? error.message : 'Failed to load data. Please try again.'}
298
+ </p>
299
+ </div>
300
+ <Button variant="outline" size="sm" onClick={() => refetch()}>
301
+ Retry
302
+ </Button>
303
+ </div>
304
+ );
305
+ }
306
+
307
+ // Normal render...
308
+ }
309
+ ```
310
+
311
+ ---
312
+
313
+ ## Scroll Position Restoration
314
+
315
+ React Router v7 handles scroll restoration automatically when navigating between routes.
316
+ For paginated lists, use TanStack Query's `placeholderData` to keep showing previous data
317
+ while new data loads (avoids an empty flash on page change):
318
+
319
+ ```typescript
320
+ export function useHeroSections(params: HeroSectionListParams) {
321
+ return useQuery({
322
+ queryKey: heroSectionKeys.list(params),
323
+ queryFn: () => heroSectionApi.list(params),
324
+ placeholderData: (previousData) => previousData,
325
+ });
326
+ }
327
+ ```