@explorer02/cfm-survey-sdk 0.2.0 → 0.2.2
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/dist/cli/index.js +18 -18
- package/dist/cli/index.mjs +14 -14
- package/dist/index.d.mts +465 -580
- package/dist/index.d.ts +465 -580
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +6 -4
- package/postinstall.js +96 -64
- package/templates/AGENT.md +15 -7
- package/templates/docs/00-integration/answer-logic-and-navigation.md +50 -0
- package/templates/docs/00-integration/aws-deploy.md +281 -0
- package/templates/docs/00-integration/client-integration-guide.md +351 -0
- package/templates/docs/00-integration/component-checklist.md +84 -0
- package/templates/docs/00-integration/constraints.md +65 -3
- package/templates/docs/00-integration/custom-field-logic-and-navigation.md +174 -0
- package/templates/docs/00-integration/display-logic-and-navigation.md +49 -0
- package/templates/docs/00-integration/end-page-logic.md +64 -0
- package/templates/docs/00-integration/partial-save-and-recovery.md +74 -0
- package/templates/docs/00-integration/placeholders-and-tokens.md +116 -0
- package/templates/docs/00-integration/progress.md +61 -0
- package/templates/docs/00-integration/question-display-variants.md +65 -0
- package/templates/docs/00-integration/question-numbering.md +51 -0
- package/templates/docs/00-integration/question-type-sdk-matrix.md +242 -0
- package/templates/docs/00-integration/setup.md +84 -0
- package/templates/docs/00-integration/skip-logic-and-navigation.md +80 -0
- package/templates/docs/00-integration/survey-lifecycle-analytics.md +94 -0
- package/templates/docs/00-integration/useSurveySDK.md +151 -23
- package/templates/docs/01-components/01-survey-page.md +76 -54
- package/templates/docs/01-components/02-question.md +77 -89
- package/templates/docs/01-components/03-rating-scale.md +11 -1
- package/templates/docs/01-components/04-star-rating-scale.md +45 -0
- package/templates/docs/01-components/05-csat-matrix-scale.md +20 -11
- package/templates/docs/01-components/06-likert-matrix-scale.md +12 -3
- package/templates/docs/01-components/07-slider-matrix-scale.md +11 -2
- package/templates/docs/01-components/08-file-upload-scale.md +10 -1
- package/templates/docs/01-components/09-custom-slider-track.md +2 -2
- package/templates/docs/01-components/11-progress-bar.md +10 -4
- package/templates/docs/01-components/13-matrix-dropdown.md +3 -1
- package/templates/docs/01-components/14-intro-page.md +34 -0
- package/templates/docs/01-components/15-end-page.md +31 -0
- package/templates/docs/01-components/16-paused-page.md +27 -0
- package/templates/docs/01-components/17-heatmap-scale.md +75 -0
- package/templates/docs/01-components/18-rank-order-scale.md +100 -0
- package/templates/docs/01-components/README.md +44 -36
- package/templates/docs/02-reference/config-field-index.md +141 -139
- package/templates/docs/02-reference/exports.md +149 -0
- package/templates/docs/02-reference/question-types/01-rating.md +31 -32
- package/templates/docs/02-reference/question-types/04-csat.md +51 -42
- package/templates/docs/02-reference/question-types/05-rating-scale.md +16 -11
- package/templates/docs/02-reference/question-types/06-slider.md +2 -2
- package/templates/docs/02-reference/question-types/07-matrix-cfm.md +44 -30
- package/templates/docs/02-reference/question-types/08-matrix-csat.md +4 -26
- package/templates/docs/02-reference/question-types/09-matrix-rating.md +29 -13
- package/templates/docs/02-reference/question-types/10-slider-matrix.md +15 -4
- package/templates/docs/02-reference/question-types/11-file-upload.md +13 -2
- package/templates/docs/02-reference/question-types/12-heatmap.md +59 -0
- package/templates/docs/02-reference/question-types/13-rank-order.md +101 -0
- package/templates/docs/02-reference/question-types/README.md +86 -47
- package/templates/docs/02-reference/routing-table.md +33 -18
- package/templates/docs/02-reference/value-derivation.md +63 -0
- package/templates/docs/03-ui-specs/00-question-shell.md +24 -80
- package/templates/docs/03-ui-specs/01-rating.md +12 -54
- package/templates/docs/03-ui-specs/02-radio.md +21 -33
- package/templates/docs/03-ui-specs/03-text.md +2 -2
- package/templates/docs/03-ui-specs/04-csat.md +38 -33
- package/templates/docs/03-ui-specs/05-rating-scale.md +21 -18
- package/templates/docs/03-ui-specs/06-slider.md +3 -1
- package/templates/docs/03-ui-specs/07-matrix-cfm.md +25 -22
- package/templates/docs/03-ui-specs/08-matrix-csat-rating.md +18 -46
- package/templates/docs/03-ui-specs/09-slider-matrix.md +2 -2
- package/templates/docs/03-ui-specs/10-file-upload.md +2 -2
- package/templates/docs/03-ui-specs/11-text-and-media.md +29 -29
- package/templates/docs/03-ui-specs/12-survey-chrome.md +20 -14
- package/templates/docs/03-ui-specs/13-heatmap.md +73 -0
- package/templates/docs/03-ui-specs/14-rank-order.md +59 -0
- package/templates/docs/03-ui-specs/README.md +14 -13
- package/templates/docs/03-ui-specs/shared/custom-slider-track.md +3 -3
- package/templates/docs/03-ui-specs/shared/matrix-dropdown.md +6 -1
- package/templates/docs/MANIFEST.json +454 -67
- package/templates/docs/index.md +84 -29
- package/templates/docs/templates/Question.tsx +310 -0
- package/templates/docs/templates/deploy-to-aws.sh +114 -0
- package/templates/docs/templates/heatmapCoords.ts +58 -0
- package/templates/docs/templates/implementation_plan.md +115 -49
- package/templates/docs/templates/survey-inventory.schema.json +72 -0
- package/templates/docs/templates/verify-agent-build.sh +53 -0
- package/templates/docs/01-components/04-csat-scale.md +0 -40
- package/templates/docs/02-question-types/01-rating.md +0 -44
|
@@ -12,80 +12,146 @@
|
|
|
12
12
|
## 1. Data Fetching & State
|
|
13
13
|
|
|
14
14
|
- [ ] `useSurveySDK` options: instanceId, language, placeholders, debug
|
|
15
|
-
- [ ] `
|
|
15
|
+
- [ ] `surveyOptions` wrapped in `useMemo` (stable refs for placeholders / customFieldValues)
|
|
16
|
+
- [ ] `customFieldValues` map when survey logic references `CUSTOM_FIELD` entities (see `custom-field-logic-and-navigation.md`)
|
|
17
|
+
- [ ] `savePartialResponse` enabled if required (`true` or `{ debounceMs }`)
|
|
18
|
+
- [ ] Monorepo: `packages/sdk` built (`npm run build`) before client dev
|
|
19
|
+
- [ ] `SurveyPage` phase router: loading / error / empty / intro / paused / end / terminal / content
|
|
16
20
|
- [ ] `surveyQueryResults.isLoading`, `.error`, `.data` handling
|
|
17
21
|
- [ ] `submitSurveyResults.isLoading`, `.error`, `.data` handling
|
|
22
|
+
- [ ] Answers read from `state.answers` (`SurveyAnswers`); changes via `payload.answerValue`
|
|
18
23
|
|
|
19
24
|
## 2. Pagination, Actions & Flow
|
|
20
25
|
|
|
21
|
-
- [ ] `onAction` NEXT / PREVIOUS / SUBMIT wiring
|
|
22
|
-
- [ ] `
|
|
23
|
-
- [ ]
|
|
24
|
-
- [ ]
|
|
26
|
+
- [ ] `onAction` START / NEXT / PREVIOUS / SUBMIT wiring
|
|
27
|
+
- [ ] `onAction(SCROLL)` once on first scroll (mark as started)
|
|
28
|
+
- [ ] `onAction(RECORD_QUESTION_VIEW)` via IntersectionObserver on question wrappers
|
|
29
|
+
- [ ] `ProgressBar` bound to `state.progressPercentage` (path-scoped — see `00-integration/progress.md`)
|
|
30
|
+
- [ ] Back via `state.canGoBack`; primary label via `state.primaryButtonType`
|
|
31
|
+
- [ ] Read `00-integration/skip-logic-and-navigation.md` for skip/Back behavior
|
|
32
|
+
- [ ] Read `00-integration/client-integration-guide.md` for full wiring map
|
|
33
|
+
|
|
34
|
+
## 1b. Lifecycle & Analytics
|
|
35
|
+
|
|
36
|
+
- [ ] `onAction(SCROLL)` once on first scroll (see `survey-lifecycle-analytics.md`)
|
|
37
|
+
- [ ] First `CHANGE` auto mark-as-started (SDK — no extra client call)
|
|
38
|
+
- [ ] `onAction(RECORD_QUESTION_VIEW)` via IntersectionObserver on `#question-{id}` wrappers
|
|
39
|
+
- [ ] Effect re-runs when `currentQuestions` changes (multi-page / display logic)
|
|
40
|
+
- [ ] Partial save: `savePartialResponse` + monitor `partialSaveResults` if enabled (see `partial-save-and-recovery.md`)
|
|
41
|
+
- [ ] Placeholders: stable `SURVEY_PLACEHOLDERS` ref + `useMemo` on hook options (see `placeholders-and-tokens.md`)
|
|
25
42
|
|
|
26
43
|
## 3. Question Dispatching (`Question.tsx`)
|
|
27
44
|
|
|
28
|
-
Exhaustive switch — check each:
|
|
29
|
-
|
|
30
|
-
- [ ] `
|
|
31
|
-
- [ ] `
|
|
32
|
-
- [ ] `
|
|
33
|
-
- [ ] `
|
|
34
|
-
- [ ] `
|
|
35
|
-
- [ ] `
|
|
36
|
-
- [ ] `
|
|
37
|
-
- [ ] `
|
|
38
|
-
- [ ] `
|
|
39
|
-
- [ ] `
|
|
40
|
-
- [ ] `
|
|
41
|
-
- [ ] `
|
|
42
|
-
- [ ] `
|
|
45
|
+
Exhaustive switch — check each (**11** `QUESTION_TYPE` literals):
|
|
46
|
+
|
|
47
|
+
- [ ] `NPS_SCALE` → `RatingScale`
|
|
48
|
+
- [ ] `MCQ` → inline MCQ
|
|
49
|
+
- [ ] `TEXTFIELD` → inline textarea/input
|
|
50
|
+
- [ ] `CFM_MATRIX` → `LikertMatrixScale`
|
|
51
|
+
- [ ] `CSAT_MATRIX`, `RATING_MATRIX` → `CsatMatrixScale`
|
|
52
|
+
- [ ] `SLIDER_MATRIX` → `SliderMatrixScale`
|
|
53
|
+
- [ ] `FILE_UPLOAD` → `FileUploadScale`
|
|
54
|
+
- [ ] `TEXT_AND_MEDIA` → inline media (no scale)
|
|
55
|
+
- [ ] `HEATMAP` → `HeatmapScale`
|
|
56
|
+
- [ ] `RANK_ORDER` → `RankOrderScale`
|
|
57
|
+
- [ ] `allAnswers` + `allQuestions` passed for placeholder resolution
|
|
58
|
+
- [ ] `customFieldValues` passed from SurveyPage when survey uses custom-field or answer logic on CRM data
|
|
59
|
+
- [ ] Answer logic: `getVisibleMcqOptionsForAnswers` / `getVisibleMatrixItemsForAnswers` with `customFieldValues` 4th arg
|
|
60
|
+
- [ ] `dangerouslySetInnerHTML` for `question.questionText` / `questionDescription`
|
|
43
61
|
- [ ] `validationError` banner per question
|
|
44
62
|
- [ ] `id={question.id}` on every question wrapper
|
|
63
|
+
- [ ] Copied from `docs/templates/Question.tsx` — no stub/default fallback branches
|
|
45
64
|
|
|
46
|
-
##
|
|
65
|
+
## 3a. Value Derivation (client-side)
|
|
47
66
|
|
|
48
|
-
|
|
49
|
-
|-----------|------------|---------------|--------------------------|
|
|
50
|
-
| RatingScale | | `01-components/03-rating-scale.md` | |
|
|
51
|
-
| CsatScale | | `01-components/04-csat-scale.md` | |
|
|
52
|
-
| CsatMatrixScale | | `01-components/05-csat-matrix-scale.md` | |
|
|
53
|
-
| LikertMatrixScale | | `01-components/06-likert-matrix-scale.md` | |
|
|
54
|
-
| SliderMatrixScale | | `01-components/07-slider-matrix-scale.md` | |
|
|
55
|
-
| FileUploadScale | | `01-components/08-file-upload-scale.md` | |
|
|
56
|
-
| CustomSliderTrack | | `01-components/09-custom-slider-track.md` | |
|
|
57
|
-
| Header / Footer | | `01-components/10-header-footer.md` | |
|
|
58
|
-
| ProgressBar | | `01-components/11-progress-bar.md` | |
|
|
59
|
-
| LanguageSelector | | `01-components/12-language-selector.md` | |
|
|
60
|
-
| MatrixDropdown | | `01-components/13-matrix-dropdown.md` | |
|
|
67
|
+
Read `02-reference/value-derivation.md`:
|
|
61
68
|
|
|
62
|
-
|
|
69
|
+
- [ ] Import `matrixColumnStoredValue` from SDK for matrix cells
|
|
70
|
+
- [ ] Matrix keys = `statementRows[].id`; values = column **`id`** or `null`
|
|
71
|
+
- [ ] NPS: derive numeric value from `optionLabel` or index
|
|
72
|
+
- [ ] MCQ: store `option.id`
|
|
73
|
+
|
|
74
|
+
## 3b. Required Component Files (from fetched survey)
|
|
75
|
+
|
|
76
|
+
Fill from `00-integration/component-checklist.md`:
|
|
77
|
+
|
|
78
|
+
| Component file | Required if survey contains | Created? |
|
|
79
|
+
|----------------|----------------------------|----------|
|
|
80
|
+
| `IntroPage.tsx` | intro page | |
|
|
81
|
+
| `EndPage.tsx` | end pages | |
|
|
82
|
+
| `PausedPage.tsx` | paused flag | |
|
|
83
|
+
| `LikertMatrixScale.tsx` | `CFM_MATRIX` | |
|
|
84
|
+
| `CsatMatrixScale.tsx` | `CSAT_MATRIX` or `RATING_MATRIX` | |
|
|
85
|
+
| `SliderMatrixScale.tsx` | `SLIDER_MATRIX` | **blocking** |
|
|
86
|
+
| `FileUploadScale.tsx` | `FILE_UPLOAD` | **blocking** |
|
|
87
|
+
| `MatrixDropdown.tsx` | matrix dropdown/selectbox | |
|
|
88
|
+
| `CustomSliderTrack.tsx` | `SLIDER_MATRIX` or matrix graphics | |
|
|
89
|
+
| `RatingScale.tsx` | `NPS_SCALE` | |
|
|
90
|
+
| `HeatmapScale.tsx` | `HEATMAP` | |
|
|
91
|
+
| `RankOrderScale.tsx` | `RANK_ORDER` | |
|
|
92
|
+
| `lib/heatmapCoords.ts` | `HEATMAP` | copy from `templates/heatmapCoords.ts` |
|
|
93
|
+
|
|
94
|
+
## 3c. Logic inventory (from fetched survey)
|
|
95
|
+
|
|
96
|
+
Scan `survey.pages` for logic flags. Fill after fetch:
|
|
63
97
|
|
|
64
|
-
|
|
98
|
+
| questionId | skipLogics | displayLogic | answerLogic (options/rows/cols) | customField refs (`_c_…`) |
|
|
99
|
+
|------------|------------|--------------|----------------------------------|---------------------------|
|
|
100
|
+
| | | | | |
|
|
65
101
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
102
|
+
Custom field ids found → populate `CUSTOM_FIELD_VALUES` map. See `00-integration/custom-field-logic-and-navigation.md`.
|
|
103
|
+
|
|
104
|
+
## 3d. Per-Type SDK Integration (from fetched survey)
|
|
105
|
+
|
|
106
|
+
Fill from `00-integration/question-type-sdk-matrix.md`:
|
|
107
|
+
|
|
108
|
+
| questionId | type | answer shape | visibility helper | customField refs | component files |
|
|
109
|
+
|------------|------|--------------|-------------------|------------------|-----------------|
|
|
110
|
+
| | | | | | |
|
|
111
|
+
|
|
112
|
+
## 4. Component Architecture Checklist
|
|
113
|
+
|
|
114
|
+
| Component | In survey? | Blueprint doc |
|
|
115
|
+
|-----------|------------|---------------|
|
|
116
|
+
| IntroPage / EndPage / PausedPage | | `14` / `15` / `16` |
|
|
117
|
+
| RatingScale | | `03-rating-scale.md` |
|
|
118
|
+
| CsatMatrixScale | | `05-csat-matrix-scale.md` |
|
|
119
|
+
| LikertMatrixScale | | `06-likert-matrix-scale.md` |
|
|
120
|
+
| SliderMatrixScale | | `07-slider-matrix-scale.md` |
|
|
121
|
+
| FileUploadScale | | `08-file-upload-scale.md` |
|
|
122
|
+
| Header / Footer / ProgressBar / LanguageSelector | | `10`–`12` |
|
|
123
|
+
|
|
124
|
+
## 4b. Per-Question Config & UI Coverage
|
|
69
125
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
- **branches implemented:** list decision-tree branches from the ui-spec (e.g. dropdown vs grid vs carousel)
|
|
126
|
+
| questionId | type | configs detected | uiSpec read | component files | branches implemented |
|
|
127
|
+
|------------|------|------------------|-------------|-----------------|---------------------|
|
|
128
|
+
| | | | | | |
|
|
74
129
|
|
|
75
130
|
## 5. Theme, Brand & Logo
|
|
76
131
|
|
|
77
132
|
- [ ] CSS-only logo (no `<img>`, no `public/` uploads)
|
|
78
133
|
- [ ] Primary / hover colors from client prompt
|
|
79
|
-
- [ ] Header / Footer / ProgressBar / LanguageSelector per layout
|
|
80
134
|
|
|
81
135
|
## 6. Submit & Thank You
|
|
82
136
|
|
|
83
|
-
- [ ] `onAction({ type: '
|
|
84
|
-
- [ ]
|
|
85
|
-
- [ ] Custom thank-you message from client prompt if provided
|
|
137
|
+
- [ ] `onAction({ type: 'NEXT' })` when `primaryButtonType === 'submit'`
|
|
138
|
+
- [ ] End UI when `state.phase.kind === 'end'` with `EndPage`
|
|
86
139
|
|
|
87
140
|
## 7. Pre-Build Verification
|
|
88
141
|
|
|
89
142
|
- [ ] No imports from `.../src/` internal paths
|
|
90
|
-
- [ ] All mutations via `onAction`
|
|
91
|
-
- [ ] `
|
|
143
|
+
- [ ] All mutations via `onAction`
|
|
144
|
+
- [ ] Stable `customFieldValues` ref; passed to hook and Question visibility helpers
|
|
145
|
+
- [ ] `bash templates/verify-agent-build.sh` passes
|
|
146
|
+
- [ ] `grep -r "not yet implemented"` → zero matches
|
|
147
|
+
|
|
148
|
+
## 8. AWS Deploy Readiness (fill if client prompt mentions AWS / CloudFront / S3 / EC2 / Sprinklr)
|
|
149
|
+
|
|
150
|
+
- [ ] Next.js `output: "export"` + `assetPrefix: "./"` configured (see `setup.md#nextjs-aws-static-export`)
|
|
151
|
+
- [ ] `images.unoptimized: true` in `next.config.js`
|
|
152
|
+
- [ ] Build produces `out/index.html` (+ `index.html.txt` copy step in build script)
|
|
153
|
+
- [ ] `SURVEY_INSTANCE_ID` matches deploy JWT (`CFM_INSTANCE_ID`)
|
|
154
|
+
- [ ] Logo/media paths are relative (no leading `/`)
|
|
155
|
+
- [ ] Rank-order uses `option.imageUrl` before `option.previewImageUrl`
|
|
156
|
+
- [ ] `CFM_DEPLOY_API_BASE=http://43.204.26.213:3000` noted in plan
|
|
157
|
+
- [ ] Static file count ≤ 500 (`find out -type f | wc -l`)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://cfm-survey-sdk/templates/survey-inventory.schema.json",
|
|
4
|
+
"title": "Survey Question Inventory",
|
|
5
|
+
"description": "Post-fetch inventory agents fill before Phase 5 BUILD",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["questions", "uniqueTypes"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"instanceId": { "type": "string", "description": "JWT used to fetch survey" },
|
|
10
|
+
"uniqueTypes": {
|
|
11
|
+
"type": "array",
|
|
12
|
+
"items": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"enum": [
|
|
15
|
+
"nps",
|
|
16
|
+
"mcq",
|
|
17
|
+
"text_input",
|
|
18
|
+
"csat",
|
|
19
|
+
"star_rating",
|
|
20
|
+
"slider",
|
|
21
|
+
"cfm_matrix",
|
|
22
|
+
"rating_matrix",
|
|
23
|
+
"slider_matrix",
|
|
24
|
+
"file_upload",
|
|
25
|
+
"text_and_media"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"uniqueItems": true
|
|
29
|
+
},
|
|
30
|
+
"questions": {
|
|
31
|
+
"type": "array",
|
|
32
|
+
"items": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"required": ["id", "type", "uiSpecRead", "implemented"],
|
|
35
|
+
"properties": {
|
|
36
|
+
"id": { "type": "string" },
|
|
37
|
+
"type": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"enum": [
|
|
40
|
+
"nps",
|
|
41
|
+
"mcq",
|
|
42
|
+
"text_input",
|
|
43
|
+
"csat",
|
|
44
|
+
"star_rating",
|
|
45
|
+
"slider",
|
|
46
|
+
"cfm_matrix",
|
|
47
|
+
"rating_matrix",
|
|
48
|
+
"slider_matrix",
|
|
49
|
+
"file_upload",
|
|
50
|
+
"text_and_media"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
"configFlags": {
|
|
54
|
+
"type": "array",
|
|
55
|
+
"items": { "type": "string" },
|
|
56
|
+
"description": "Non-default config, e.g. gridLayout:carousel"
|
|
57
|
+
},
|
|
58
|
+
"uiSpecRead": { "type": "string" },
|
|
59
|
+
"componentFiles": {
|
|
60
|
+
"type": "array",
|
|
61
|
+
"items": { "type": "string" }
|
|
62
|
+
},
|
|
63
|
+
"branchesImplemented": {
|
|
64
|
+
"type": "array",
|
|
65
|
+
"items": { "type": "string" }
|
|
66
|
+
},
|
|
67
|
+
"implemented": { "type": "boolean" }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Agent build verification — run from project root after Phase 5 BUILD
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
echo "=== CFM Survey SDK — Agent Build Verification ==="
|
|
6
|
+
|
|
7
|
+
STUB_MATCHES=$(grep -r "not yet implemented" src/ components/ app/ 2>/dev/null || true)
|
|
8
|
+
if [ -n "$STUB_MATCHES" ]; then
|
|
9
|
+
echo "FAIL: Stub placeholder text found:"
|
|
10
|
+
echo "$STUB_MATCHES"
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
echo "OK: No stub placeholder text"
|
|
14
|
+
|
|
15
|
+
INTERNAL_IMPORTS=$(grep -rE "@explorer02/cfm-survey-sdk/src|@repo/sdk/src" src/ components/ app/ 2>/dev/null || true)
|
|
16
|
+
if [ -n "$INTERNAL_IMPORTS" ]; then
|
|
17
|
+
echo "FAIL: Internal SDK imports found:"
|
|
18
|
+
echo "$INTERNAL_IMPORTS"
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
echo "OK: No internal SDK imports"
|
|
22
|
+
|
|
23
|
+
REQUIRED_TYPES=(MCQ TEXTFIELD NPS_SCALE CFM_MATRIX CSAT_MATRIX RATING_MATRIX SLIDER_MATRIX FILE_UPLOAD TEXT_AND_MEDIA HEATMAP RANK_ORDER)
|
|
24
|
+
QUESTION_FILE=""
|
|
25
|
+
for candidate in src/components/Question.tsx components/Question.tsx app/components/Question.tsx; do
|
|
26
|
+
if [ -f "$candidate" ]; then
|
|
27
|
+
QUESTION_FILE="$candidate"
|
|
28
|
+
break
|
|
29
|
+
fi
|
|
30
|
+
done
|
|
31
|
+
|
|
32
|
+
if [ -z "$QUESTION_FILE" ]; then
|
|
33
|
+
echo "WARN: Question.tsx not found in expected paths — skip type coverage check"
|
|
34
|
+
else
|
|
35
|
+
echo "Checking dispatcher types in $QUESTION_FILE"
|
|
36
|
+
for t in "${REQUIRED_TYPES[@]}"; do
|
|
37
|
+
if ! grep -q "QUESTION_TYPE.${t}" "$QUESTION_FILE" && \
|
|
38
|
+
! grep -q "type === '${t}'" "$QUESTION_FILE" && \
|
|
39
|
+
! grep -q "type === \"${t}\"" "$QUESTION_FILE"; then
|
|
40
|
+
echo "FAIL: Missing dispatcher branch for type: ${t}"
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
done
|
|
44
|
+
if grep -q "subType" "$QUESTION_FILE"; then
|
|
45
|
+
echo "FAIL: Legacy subType routing found in Question.tsx — use flat question.type literals"
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
echo "OK: All 11 question.type branches present"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
echo "Running npm run build..."
|
|
52
|
+
npm run build
|
|
53
|
+
echo "=== All checks passed ==="
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# CSAT & Rating Architectural Blueprints
|
|
2
|
-
|
|
3
|
-
> **UI spec (authoritative):** `03-ui-specs/04-csat.md`
|
|
4
|
-
> **Reference implementation:** `apps/client/src/components/CsatScale.tsx`
|
|
5
|
-
> **Target Components**: `CsatScale`
|
|
6
|
-
> **Handles**: `type: 'csat'`, `'rating'`, `'rating_scale'`, CSAT matrices.
|
|
7
|
-
|
|
8
|
-
## Core Responsibility
|
|
9
|
-
Render sentiment arrays (Faces, Stars, Numbers) ensuring that active selections are unmistakably highlighted using bounding boxes or strong border accents, NEVER just by changing the SVG fill color.
|
|
10
|
-
|
|
11
|
-
## State Management & Mapping
|
|
12
|
-
- **Emojis**: `buttonType === 'emoji'`
|
|
13
|
-
- Map values using `getEmojiForIndex(index, totalLength)` from your icons utility.
|
|
14
|
-
- **Stars**: `buttonType === 'star'`
|
|
15
|
-
- Active stars (index <= selectedValue) get `CsatStarIcons.filled`.
|
|
16
|
-
- **Numbers**: Default for rating scales.
|
|
17
|
-
- Apply `option.color` to the background if provided by the SDK (NPS tracking).
|
|
18
|
-
|
|
19
|
-
## UX Bounding Box Rules (CRITICAL)
|
|
20
|
-
|
|
21
|
-
The UI must exactly match the "Active Box" standard.
|
|
22
|
-
|
|
23
|
-
### For Emojis & Stars:
|
|
24
|
-
- **Unselected**: `inline-flex p-2 border-2 border-transparent opacity-40 hover:opacity-100 hover:scale-110 transition-all cursor-pointer`.
|
|
25
|
-
- **Selected**: The specific selected icon MUST be wrapped in a prominent square box with rounded corners.
|
|
26
|
-
- **CSS**: `border-2 border-[#e20074] rounded-lg p-2 bg-pink-50 shadow-sm scale-110 opacity-100`.
|
|
27
|
-
|
|
28
|
-
### For Numbered Badges (Rating):
|
|
29
|
-
- **Shape**: MUST be square with rounded corners (`rounded-lg w-12 h-12`). Do not use full circles.
|
|
30
|
-
- **Selected**: `border-2 border-[#e20074] opacity-100 font-bold scale-105 shadow-md`.
|
|
31
|
-
- **Unselected**: `opacity-30 border-transparent`.
|
|
32
|
-
|
|
33
|
-
## Bounding Boxes inside Matrices
|
|
34
|
-
When emojis or stars are rendered inside `CsatMatrixScale`, the exact same bounding box logic applies. The table cell `<td>` should center the icon, and the icon wrapper `<div>` or `<button>` should toggle between `border-transparent` and `border-[#e20074]` based on the active state.
|
|
35
|
-
|
|
36
|
-
## Tooltips & Label Positions
|
|
37
|
-
- **Tooltips**: Every single emoji, star, and badge MUST have `title={label}` applied so the user sees the semantic text string on hover.
|
|
38
|
-
- **Labels (`minLabel`, `midLabel`, `maxLabel`)**:
|
|
39
|
-
- Must be rendered absolutely below the track.
|
|
40
|
-
- `midLabel` must use inline styles to calculate its exact centered position: `style={{ left: \`\${(midLabelIndex / (options.length - 1)) * 100}%\` }}`.
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# Rating Question (NPS 0-10)
|
|
2
|
-
|
|
3
|
-
> **Type**: `'rating'` | **API Source**: `SCALE` with `SCALE_TYPE=TEN_POINT` or `NPS_SCALE`
|
|
4
|
-
> **Mapper**: `ratingMapper.ts` | **Component**: `RatingScale`
|
|
5
|
-
|
|
6
|
-
## TypeScript Type
|
|
7
|
-
|
|
8
|
-
```typescript
|
|
9
|
-
type RatingQuestion = QuestionBase & {
|
|
10
|
-
type: 'rating';
|
|
11
|
-
options: SurveyOption[]; // 0-10 with NPS traffic-light colors
|
|
12
|
-
minLabel?: string; // Left label (e.g. "Not Likely")
|
|
13
|
-
midLabel?: string; // Middle label (e.g. "Neutral")
|
|
14
|
-
maxLabel?: string; // Right label (e.g. "Extremely Likely")
|
|
15
|
-
midLabelIndex?: number; // Fractional position for mid-label CSS
|
|
16
|
-
reverseScaleOrder?: boolean; // Render high→low
|
|
17
|
-
buttonVariant?: 'radio' | 'numbered' | 'emoji';
|
|
18
|
-
};
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Answer Shape: `number`
|
|
22
|
-
Example: `7` (the selected badge value)
|
|
23
|
-
|
|
24
|
-
## NPS Traffic-Light Colors
|
|
25
|
-
```
|
|
26
|
-
0: #e2001a (red) 3: #f18b00 (orange) 6: #fcd900 (yellow)
|
|
27
|
-
1: #e4251b 4: #f7b200 7: #9fca00 (lime)
|
|
28
|
-
2: #ec610a 5: #fcd900 8: #6bb300 (green)
|
|
29
|
-
9: #339a00
|
|
30
|
-
10: #008000
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Mid-Label Positioning
|
|
34
|
-
```typescript
|
|
35
|
-
// CSS left percentage for mid-label
|
|
36
|
-
const left = (midLabelIndex / (options.length - 1)) * 100;
|
|
37
|
-
// For 11-point scale: midLabelIndex defaults to 7.5
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Rendering Guidance
|
|
41
|
-
- Display as horizontal row of numbered badge buttons
|
|
42
|
-
- Each badge uses `option.color` as background
|
|
43
|
-
- Selected badge: emphasized border/scale, all others dimmed
|
|
44
|
-
- Labels positioned: minLabel (left), midLabel (calculated %), maxLabel (right)
|