@designcrowd/fe-shared-lib 1.5.34 → 1.5.36
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/css/tailwind-brandCrowd.css +2 -65
- package/dist/css/tailwind-brandPage.css +3 -54
- package/dist/css/tailwind-crazyDomains.css +2 -65
- package/dist/css/tailwind-designCom.css +2 -65
- package/dist/css/tailwind-designCrowd.css +2 -65
- package/docs/plans/DY-957-plan-phase-2-fe-shared-lib.md +382 -0
- package/package.json +1 -1
- package/public/css/tailwind-brandCrowd.css +2472 -0
- package/public/css/tailwind-brandPage.css +2156 -0
- package/public/css/tailwind-crazyDomains.css +2472 -0
- package/public/css/tailwind-designCom.css +2472 -0
- package/public/css/tailwind-designCrowd.css +2472 -0
- package/src/atoms/components/Icon/Icon.vue +4 -0
- package/src/atoms/components/Icon/icons/history.vue +12 -0
- package/src/atoms/components/Icon/icons/save.vue +6 -0
- package/src/bundles/bundled-translations.de-DE.json +3 -1
- package/src/bundles/bundled-translations.es-ES.json +3 -1
- package/src/bundles/bundled-translations.fr-CA.json +3 -1
- package/src/bundles/bundled-translations.fr-FR.json +3 -1
- package/src/bundles/bundled-translations.json +3 -1
- package/src/bundles/bundled-translations.pt-BR.json +3 -1
- package/src/bundles/bundled-translations.pt-PT.json +3 -1
- package/src/experiences/clients/brand-crowd-api.client.js +18 -0
- package/src/experiences/components/UploadYourLogoApplication/UploadYourLogoApplication.stories.js +49 -0
- package/src/experiences/components/UploadYourLogoApplication/UploadYourLogoApplication.vue +28 -0
- package/src/experiences/components/UploadYourLogoOnBoarding/LogoKeywords.stories.js +65 -0
- package/src/experiences/components/UploadYourLogoOnBoarding/LogoKeywords.vue +156 -0
- package/src/experiences/components/UploadYourLogoOnBoarding/UploadYourLogoOnBoarding.vue +61 -9
- package/src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.de-DE.json +34 -31
- package/src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.es-ES.json +34 -31
- package/src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.fr-CA.json +34 -31
- package/src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.fr-FR.json +34 -31
- package/src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.json +3 -1
- package/src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.pt-BR.json +34 -31
- package/src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.pt-PT.json +34 -31
- package/src/experiences/constants/api.js +1 -0
|
@@ -617,9 +617,6 @@ video {
|
|
|
617
617
|
.tw-m-3 {
|
|
618
618
|
margin: 0.75rem;
|
|
619
619
|
}
|
|
620
|
-
.tw-m-4 {
|
|
621
|
-
margin: 1rem;
|
|
622
|
-
}
|
|
623
620
|
.tw-m-5 {
|
|
624
621
|
margin: 1.25rem;
|
|
625
622
|
}
|
|
@@ -946,9 +943,6 @@ video {
|
|
|
946
943
|
.tw-w-96 {
|
|
947
944
|
width: 24rem;
|
|
948
945
|
}
|
|
949
|
-
.tw-w-\[14rem\] {
|
|
950
|
-
width: 14rem;
|
|
951
|
-
}
|
|
952
946
|
.tw-w-auto {
|
|
953
947
|
width: auto;
|
|
954
948
|
}
|
|
@@ -962,9 +956,6 @@ video {
|
|
|
962
956
|
.tw-max-w-2xl {
|
|
963
957
|
max-width: 42rem;
|
|
964
958
|
}
|
|
965
|
-
.tw-max-w-3xl {
|
|
966
|
-
max-width: 48rem;
|
|
967
|
-
}
|
|
968
959
|
.tw-max-w-full {
|
|
969
960
|
max-width: 100%;
|
|
970
961
|
}
|
|
@@ -1213,9 +1204,6 @@ video {
|
|
|
1213
1204
|
.tw-rounded-full {
|
|
1214
1205
|
border-radius: 9999px;
|
|
1215
1206
|
}
|
|
1216
|
-
.tw-rounded-lg {
|
|
1217
|
-
border-radius: 0.5rem;
|
|
1218
|
-
}
|
|
1219
1207
|
.tw-rounded-md {
|
|
1220
1208
|
border-radius: 0.375rem;
|
|
1221
1209
|
}
|
|
@@ -1332,10 +1320,6 @@ video {
|
|
|
1332
1320
|
--tw-border-opacity: 1;
|
|
1333
1321
|
border-color: rgb(125 130 132 / var(--tw-border-opacity));
|
|
1334
1322
|
}
|
|
1335
|
-
.tw-border-grayscale-700 {
|
|
1336
|
-
--tw-border-opacity: 1;
|
|
1337
|
-
border-color: rgb(82 93 96 / var(--tw-border-opacity));
|
|
1338
|
-
}
|
|
1339
1323
|
.tw-border-info-300 {
|
|
1340
1324
|
--tw-border-opacity: 1;
|
|
1341
1325
|
border-color: rgb(112 193 243 / var(--tw-border-opacity));
|
|
@@ -1830,10 +1814,6 @@ video {
|
|
|
1830
1814
|
font-size: 1.5rem;
|
|
1831
1815
|
line-height: 2rem;
|
|
1832
1816
|
}
|
|
1833
|
-
.tw-text-3xl {
|
|
1834
|
-
font-size: 1.875rem;
|
|
1835
|
-
line-height: 2.25rem;
|
|
1836
|
-
}
|
|
1837
1817
|
.tw-text-4xl {
|
|
1838
1818
|
font-size: 2.25rem;
|
|
1839
1819
|
line-height: 2.5rem;
|
|
@@ -1857,9 +1837,6 @@ video {
|
|
|
1857
1837
|
.tw-font-bold {
|
|
1858
1838
|
font-weight: 700;
|
|
1859
1839
|
}
|
|
1860
|
-
.tw-font-medium {
|
|
1861
|
-
font-weight: 500;
|
|
1862
|
-
}
|
|
1863
1840
|
.tw-font-normal {
|
|
1864
1841
|
font-weight: 400;
|
|
1865
1842
|
}
|
|
@@ -2071,10 +2048,6 @@ video {
|
|
|
2071
2048
|
--tw-border-opacity: 1;
|
|
2072
2049
|
border-color: rgb(230 230 230 / var(--tw-border-opacity));
|
|
2073
2050
|
}
|
|
2074
|
-
.hover\:tw-border-grayscale-500:hover {
|
|
2075
|
-
--tw-border-opacity: 1;
|
|
2076
|
-
border-color: rgb(204 204 204 / var(--tw-border-opacity));
|
|
2077
|
-
}
|
|
2078
2051
|
.hover\:tw-border-info-600:hover {
|
|
2079
2052
|
--tw-border-opacity: 1;
|
|
2080
2053
|
border-color: rgb(14 121 188 / var(--tw-border-opacity));
|
|
@@ -2111,10 +2084,6 @@ video {
|
|
|
2111
2084
|
--tw-bg-opacity: 1;
|
|
2112
2085
|
background-color: rgb(230 230 230 / var(--tw-bg-opacity));
|
|
2113
2086
|
}
|
|
2114
|
-
.hover\:tw-bg-grayscale-500:hover {
|
|
2115
|
-
--tw-bg-opacity: 1;
|
|
2116
|
-
background-color: rgb(204 204 204 / var(--tw-bg-opacity));
|
|
2117
|
-
}
|
|
2118
2087
|
.hover\:tw-bg-info-100:hover {
|
|
2119
2088
|
--tw-bg-opacity: 1;
|
|
2120
2089
|
background-color: rgb(207 234 251 / var(--tw-bg-opacity));
|
|
@@ -2139,10 +2108,6 @@ video {
|
|
|
2139
2108
|
--tw-bg-opacity: 1;
|
|
2140
2109
|
background-color: rgb(14 121 188 / var(--tw-bg-opacity));
|
|
2141
2110
|
}
|
|
2142
|
-
.hover\:tw-bg-primary-700:hover {
|
|
2143
|
-
--tw-bg-opacity: 1;
|
|
2144
|
-
background-color: rgb(10 91 141 / var(--tw-bg-opacity));
|
|
2145
|
-
}
|
|
2146
2111
|
.hover\:tw-bg-secondary-100:hover {
|
|
2147
2112
|
--tw-bg-opacity: 1;
|
|
2148
2113
|
background-color: rgb(223 226 230 / var(--tw-bg-opacity));
|
|
@@ -2159,10 +2124,6 @@ video {
|
|
|
2159
2124
|
--tw-bg-opacity: 1;
|
|
2160
2125
|
background-color: rgb(74 87 103 / var(--tw-bg-opacity));
|
|
2161
2126
|
}
|
|
2162
|
-
.hover\:tw-bg-secondary-700:hover {
|
|
2163
|
-
--tw-bg-opacity: 1;
|
|
2164
|
-
background-color: rgb(56 65 77 / var(--tw-bg-opacity));
|
|
2165
|
-
}
|
|
2166
2127
|
.hover\:tw-bg-success-100:hover {
|
|
2167
2128
|
--tw-bg-opacity: 1;
|
|
2168
2129
|
background-color: rgb(213 242 223 / var(--tw-bg-opacity));
|
|
@@ -2175,9 +2136,9 @@ video {
|
|
|
2175
2136
|
--tw-bg-opacity: 1;
|
|
2176
2137
|
background-color: rgb(194 140 34 / var(--tw-bg-opacity));
|
|
2177
2138
|
}
|
|
2178
|
-
.hover\:tw-text-
|
|
2139
|
+
.hover\:tw-text-grayscale-800:hover {
|
|
2179
2140
|
--tw-text-opacity: 1;
|
|
2180
|
-
color: rgb(
|
|
2141
|
+
color: rgb(39 52 56 / var(--tw-text-opacity));
|
|
2181
2142
|
}
|
|
2182
2143
|
.hover\:tw-text-secondary-500:hover {
|
|
2183
2144
|
--tw-text-opacity: 1;
|
|
@@ -2333,18 +2294,10 @@ video {
|
|
|
2333
2294
|
}
|
|
2334
2295
|
@media (min-width: 768px) {
|
|
2335
2296
|
|
|
2336
|
-
.md\:tw-relative {
|
|
2337
|
-
position: relative;
|
|
2338
|
-
}
|
|
2339
|
-
|
|
2340
2297
|
.md\:tw-right-6 {
|
|
2341
2298
|
right: 1.5rem;
|
|
2342
2299
|
}
|
|
2343
2300
|
|
|
2344
|
-
.md\:tw-order-first {
|
|
2345
|
-
order: -9999;
|
|
2346
|
-
}
|
|
2347
|
-
|
|
2348
2301
|
.md\:tw-mb-0 {
|
|
2349
2302
|
margin-bottom: 0px;
|
|
2350
2303
|
}
|
|
@@ -2409,10 +2362,6 @@ video {
|
|
|
2409
2362
|
width: 6rem;
|
|
2410
2363
|
}
|
|
2411
2364
|
|
|
2412
|
-
.md\:tw-w-3\/4 {
|
|
2413
|
-
width: 75%;
|
|
2414
|
-
}
|
|
2415
|
-
|
|
2416
2365
|
.md\:tw-w-auto {
|
|
2417
2366
|
width: auto;
|
|
2418
2367
|
}
|
|
@@ -2425,10 +2374,6 @@ video {
|
|
|
2425
2374
|
max-width: 100%;
|
|
2426
2375
|
}
|
|
2427
2376
|
|
|
2428
|
-
.md\:tw-flex-1 {
|
|
2429
|
-
flex: 1 1 0%;
|
|
2430
|
-
}
|
|
2431
|
-
|
|
2432
2377
|
.md\:tw-grow {
|
|
2433
2378
|
flex-grow: 1;
|
|
2434
2379
|
}
|
|
@@ -2488,10 +2433,6 @@ video {
|
|
|
2488
2433
|
object-fit: contain;
|
|
2489
2434
|
}
|
|
2490
2435
|
|
|
2491
|
-
.md\:tw-p-0 {
|
|
2492
|
-
padding: 0px;
|
|
2493
|
-
}
|
|
2494
|
-
|
|
2495
2436
|
.md\:tw-p-2 {
|
|
2496
2437
|
padding: 0.5rem;
|
|
2497
2438
|
}
|
|
@@ -2528,10 +2469,6 @@ video {
|
|
|
2528
2469
|
padding-bottom: 0.5rem;
|
|
2529
2470
|
}
|
|
2530
2471
|
|
|
2531
|
-
.md\:tw-pb-0 {
|
|
2532
|
-
padding-bottom: 0px;
|
|
2533
|
-
}
|
|
2534
|
-
|
|
2535
2472
|
.md\:tw-pl-4 {
|
|
2536
2473
|
padding-left: 1rem;
|
|
2537
2474
|
}
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# DY-957 Phase 2: fe-shared-lib Wizard Changes
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Add an optional keywords step to the BYO upload wizard in `@designcrowd/fe-shared-lib`. The step fetches AI keyword suggestions, displays them in an editable textbox, and emits the keywords for the consumer to use. The step is opt-in via a `showKeywordsStep` prop (default `false`).
|
|
6
|
+
|
|
7
|
+
## Repo
|
|
8
|
+
|
|
9
|
+
`fe-shared-lib`
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
- Phase 1 backend endpoint deployed (needed for integration testing, not for Storybook development)
|
|
14
|
+
|
|
15
|
+
## Implementation Decisions (Confirmed)
|
|
16
|
+
|
|
17
|
+
- The keyword suggestions endpoint path is `/api/ai-keyword-suggestion` (this is intentionally **not** maker-prefixed).
|
|
18
|
+
- `templateType` is required end-to-end; consumers must pass a non-null default value.
|
|
19
|
+
- Continue action in the keywords step must be disabled while suggestions are loading.
|
|
20
|
+
- Storybook coverage for `LogoKeywords` is required for this task (not optional).
|
|
21
|
+
- Publishing/version bump and final validation are human-owned follow-up steps, not coding-agent scope.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Tasks
|
|
26
|
+
|
|
27
|
+
### 1. Add API constant
|
|
28
|
+
|
|
29
|
+
**File**: `src/experiences/constants/api.js`
|
|
30
|
+
|
|
31
|
+
Add one line to the exported object:
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
KEYWORD_SUGGESTIONS_API_URL: '/api/ai-keyword-suggestion',
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Add `getKeywordSuggestionsAsync` to API client
|
|
38
|
+
|
|
39
|
+
**File**: `src/experiences/clients/brand-crowd-api.client.js`
|
|
40
|
+
|
|
41
|
+
Add a new async method following the `searchDomainNamesByKeywordAsync` pattern (lines 71-117):
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
const getKeywordSuggestionsAsync = async ({ businessName, templateType }) => {
|
|
45
|
+
try {
|
|
46
|
+
const url = `${API.KEYWORD_SUGGESTIONS_API_URL}?businessName=${encodeURIComponent(businessName)}&templateType=${encodeURIComponent(templateType)}`;
|
|
47
|
+
const response = await getAxios()({
|
|
48
|
+
method: 'get',
|
|
49
|
+
url,
|
|
50
|
+
});
|
|
51
|
+
return response.data;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Behavior note: if `businessName` is empty, still call the endpoint with `businessName=` and continue normally (expected to return empty suggestions).
|
|
59
|
+
|
|
60
|
+
Add `getKeywordSuggestionsAsync` to the default export object (lines 119-124).
|
|
61
|
+
|
|
62
|
+
### 3. Create `LogoKeywords.vue` component
|
|
63
|
+
|
|
64
|
+
**File**: Create `src/experiences/components/UploadYourLogoOnBoarding/LogoKeywords.vue`
|
|
65
|
+
|
|
66
|
+
Clone the structure from `LogoBusinessText.vue` (same directory). The component should:
|
|
67
|
+
|
|
68
|
+
**Props:**
|
|
69
|
+
- `progressLabel` (String, required) — "Step X of Y"
|
|
70
|
+
- `eventCategory` (String, required) — for analytics tracking
|
|
71
|
+
- `savedKeywords` (String, optional, default: `null`) — restored keywords if user navigated back then forward
|
|
72
|
+
- `businessName` (String, optional, default: `''`) — from previous step (may be empty)
|
|
73
|
+
- `templateType` (String, required) — e.g. "business card"
|
|
74
|
+
|
|
75
|
+
Behavior note: keep current wizard behavior where empty business name is allowed; do not block navigation if no business name is entered.
|
|
76
|
+
|
|
77
|
+
**Data:**
|
|
78
|
+
- `keywordsText: ''` — the editable comma-separated keywords string
|
|
79
|
+
- `isLoading: false`
|
|
80
|
+
|
|
81
|
+
**Mounted lifecycle:**
|
|
82
|
+
```js
|
|
83
|
+
async mounted() {
|
|
84
|
+
if (this.savedKeywords !== null) {
|
|
85
|
+
this.keywordsText = this.savedKeywords;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.isLoading = true;
|
|
89
|
+
try {
|
|
90
|
+
const result = await brandCrowdClient.getKeywordSuggestionsAsync({
|
|
91
|
+
businessName: this.businessName,
|
|
92
|
+
templateType: this.templateType,
|
|
93
|
+
});
|
|
94
|
+
if (result && result.keywords && result.keywords.length > 0) {
|
|
95
|
+
this.keywordsText = result.keywords.join(', ');
|
|
96
|
+
}
|
|
97
|
+
} catch {
|
|
98
|
+
// leave keywordsText as empty string
|
|
99
|
+
} finally {
|
|
100
|
+
this.isLoading = false;
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Methods:**
|
|
106
|
+
- `back()` — emits `on-go-back`
|
|
107
|
+
- `save()` — no-op if `isLoading` is true; otherwise tracks event with `eventAction: 'keywords'`, `eventLabel: 'Clicked_Continue'`, then emits `on-save` with `{ keywords: this.keywordsText }`
|
|
108
|
+
- `onKeywordsKeyUp(e)` — if `e.key === 'Enter'` and `!isLoading`, call `this.save()`
|
|
109
|
+
|
|
110
|
+
**Template:** Mirror `LogoBusinessText.vue` layout:
|
|
111
|
+
- Progress label header: `{{ progressLabel }}`
|
|
112
|
+
- Heading: `{{ uploadYourLogoTr('keywords') }}`
|
|
113
|
+
- Description: `{{ uploadYourLogoTr('keywordsDescription') }}`
|
|
114
|
+
- Single `<input>` or `<textarea>` bound to `keywordsText`, disabled while `isLoading`, with `@keyup="onKeywordsKeyUp"`
|
|
115
|
+
- Show a loading indicator (spinner or skeleton) when `isLoading` is true
|
|
116
|
+
- Footer with Back button (emits `on-go-back`) and Continue button (calls `save()`)
|
|
117
|
+
- Continue button must be disabled while `isLoading` is `true`
|
|
118
|
+
|
|
119
|
+
**i18n:** Use the `uploadYourLogoTr` mixin (same as `LogoBusinessText.vue`).
|
|
120
|
+
|
|
121
|
+
### 4. Add i18n translation keys
|
|
122
|
+
|
|
123
|
+
**Files**: All 7 locale files in `src/experiences/components/UploadYourLogoOnBoarding/i18n/`
|
|
124
|
+
|
|
125
|
+
Add two new keys inside the `"uploadYourLogo"` object in **every** locale file, using the **English text** in all of them:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
"keywords": "Keywords",
|
|
129
|
+
"keywordsDescription": "Add keywords related to your business and logo"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Add this identical English text to:
|
|
133
|
+
- `upload-your-logo.json` (English)
|
|
134
|
+
- `upload-your-logo.de-DE.json`
|
|
135
|
+
- `upload-your-logo.es-ES.json`
|
|
136
|
+
- `upload-your-logo.fr-CA.json`
|
|
137
|
+
- `upload-your-logo.fr-FR.json`
|
|
138
|
+
- `upload-your-logo.pt-BR.json`
|
|
139
|
+
- `upload-your-logo.pt-PT.json`
|
|
140
|
+
|
|
141
|
+
**Do not translate** — a separate process will sweep the codebase and replace the English placeholders with proper translations.
|
|
142
|
+
|
|
143
|
+
After editing all files, run `npm run bundle-translation` to regenerate bundled translation files.
|
|
144
|
+
|
|
145
|
+
### 5. Update `UploadYourLogoOnBoarding.vue` orchestrator
|
|
146
|
+
|
|
147
|
+
**File**: `src/experiences/components/UploadYourLogoOnBoarding/UploadYourLogoOnBoarding.vue`
|
|
148
|
+
|
|
149
|
+
#### 5a. Add new props (after existing props at lines 115-136)
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
showKeywordsStep: {
|
|
153
|
+
type: Boolean,
|
|
154
|
+
required: false,
|
|
155
|
+
default: false,
|
|
156
|
+
},
|
|
157
|
+
templateType: {
|
|
158
|
+
type: String,
|
|
159
|
+
required: true,
|
|
160
|
+
},
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Note: `templateType` must be provided by the consumer (fallback/defaulting happens in consumer app config, not in this component).
|
|
164
|
+
|
|
165
|
+
#### 5b. Update `data()` (lines 142-154)
|
|
166
|
+
|
|
167
|
+
Change `totalNumSteps` to be dynamic:
|
|
168
|
+
```js
|
|
169
|
+
totalNumSteps: this.useDropzone
|
|
170
|
+
? (this.showKeywordsStep ? 6 : 5)
|
|
171
|
+
: (this.showKeywordsStep ? 5 : 4),
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Add new data property:
|
|
175
|
+
```js
|
|
176
|
+
savedKeywords: null,
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### 5c. Add computed property for brand colours step number
|
|
180
|
+
|
|
181
|
+
```js
|
|
182
|
+
brandColoursStep() {
|
|
183
|
+
return this.showKeywordsStep ? 5 : 4;
|
|
184
|
+
},
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### 5d. Update `currentStepProgressLabel` (lines 157-163)
|
|
188
|
+
|
|
189
|
+
Replace hard-coded totals with `this.totalNumSteps`:
|
|
190
|
+
```js
|
|
191
|
+
currentStepProgressLabel() {
|
|
192
|
+
if (this.includeDropzoneInModal) {
|
|
193
|
+
const currentStepDisplay = this.currentStep === 0 ? 1 : this.currentStep;
|
|
194
|
+
return this.uploadYourLogoTr('stepOf', { CURRENT: currentStepDisplay, TOTAL: this.totalNumSteps });
|
|
195
|
+
}
|
|
196
|
+
return this.uploadYourLogoTr('stepOf', { CURRENT: this.currentStep - 1, TOTAL: this.totalNumSteps });
|
|
197
|
+
},
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
#### 5e. Update `currentStepTrackingLabel` (lines 170-176)
|
|
201
|
+
|
|
202
|
+
Make it keyword-step aware:
|
|
203
|
+
```js
|
|
204
|
+
currentStepTrackingLabel() {
|
|
205
|
+
const stepTwoLabel = this.currentStep === 2 && !this.canCropImage ? 'previewLogo' : 'cropLogo';
|
|
206
|
+
const steps = this.showKeywordsStep
|
|
207
|
+
? ['logoUploader', stepTwoLabel, 'businessName', 'keywords', 'brandColors']
|
|
208
|
+
: ['logoUploader', stepTwoLabel, 'businessName', 'brandColors'];
|
|
209
|
+
return steps[this.currentStep - 1];
|
|
210
|
+
},
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### 5f. Import LogoKeywords component
|
|
214
|
+
|
|
215
|
+
Add import at top of script:
|
|
216
|
+
```js
|
|
217
|
+
import LogoKeywords from './LogoKeywords.vue';
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Register in `components: { ... }`.
|
|
221
|
+
|
|
222
|
+
#### 5g. Update `onSaveBusinessText` method (lines 251-255)
|
|
223
|
+
|
|
224
|
+
No change needed — it already sets `currentStep = 4`. When `showKeywordsStep` is true, step 4 shows LogoKeywords. When false, step 4 shows LogoBusinessBrandColours (via `brandColoursStep` computed).
|
|
225
|
+
|
|
226
|
+
#### 5h. Add `onSaveKeywords` method
|
|
227
|
+
|
|
228
|
+
```js
|
|
229
|
+
onSaveKeywords(payload) {
|
|
230
|
+
this.$emit('on-save-keywords', { keywords: payload.keywords });
|
|
231
|
+
this.savedKeywords = payload.keywords;
|
|
232
|
+
this.currentStep = this.brandColoursStep;
|
|
233
|
+
},
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
#### 5i. Add `onGoBackFromBrandColours` method (or rename existing `onGoBackToBusinessText` usage on brand colours)
|
|
237
|
+
|
|
238
|
+
```js
|
|
239
|
+
onGoBackFromBrandColours() {
|
|
240
|
+
this.$emit('on-back', { currentStepTrackingLabel: this.currentStepTrackingLabel });
|
|
241
|
+
this.currentStep = this.showKeywordsStep ? 4 : 3;
|
|
242
|
+
},
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Important**: The brand colours component currently uses `@on-go-back="onGoBackToBusinessText"` (which sets `currentStep = 3`). Change this to `@on-go-back="onGoBackFromBrandColours"` so it goes back to keywords (step 4) when the keywords step is enabled.
|
|
246
|
+
|
|
247
|
+
#### 5j. Update template — add LogoKeywords between BusinessText and BrandColours
|
|
248
|
+
|
|
249
|
+
Add after the LogoBusinessText block and before LogoBusinessBrandColours:
|
|
250
|
+
|
|
251
|
+
```vue
|
|
252
|
+
<LogoKeywords
|
|
253
|
+
v-if="showKeywordsStep && !isAttemptingToExit && currentStep === 4 && uploadedLogoData"
|
|
254
|
+
:progress-label="currentStepProgressLabel"
|
|
255
|
+
:event-category="eventCategory"
|
|
256
|
+
:saved-keywords="savedKeywords"
|
|
257
|
+
:business-name="(savedBusinessText && savedBusinessText.businessText) || ''"
|
|
258
|
+
:template-type="templateType"
|
|
259
|
+
@on-go-back="onGoBackToBusinessText"
|
|
260
|
+
@on-save="onSaveKeywords"
|
|
261
|
+
/>
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### 5k. Update template — change BrandColours step condition
|
|
265
|
+
|
|
266
|
+
Change `currentStep === 4` to `currentStep === brandColoursStep`:
|
|
267
|
+
|
|
268
|
+
```vue
|
|
269
|
+
<LogoBusinessBrandColours
|
|
270
|
+
v-if="!isAttemptingToExit && currentStep === brandColoursStep && uploadedLogoData && !isCurrentlySaving"
|
|
271
|
+
...
|
|
272
|
+
@on-go-back="onGoBackFromBrandColours"
|
|
273
|
+
...
|
|
274
|
+
/>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### 5l. Update `reset()` method (lines 290-299)
|
|
278
|
+
|
|
279
|
+
Add:
|
|
280
|
+
```js
|
|
281
|
+
this.savedKeywords = null;
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### 6. Update `UploadYourLogoApplication.vue` wrapper
|
|
285
|
+
|
|
286
|
+
**File**: `src/experiences/components/UploadYourLogoApplication/UploadYourLogoApplication.vue`
|
|
287
|
+
|
|
288
|
+
#### 6a. Add pass-through props (after existing props at lines 29-45)
|
|
289
|
+
|
|
290
|
+
```js
|
|
291
|
+
showKeywordsStep: {
|
|
292
|
+
type: Boolean,
|
|
293
|
+
required: false,
|
|
294
|
+
default: false,
|
|
295
|
+
},
|
|
296
|
+
templateType: {
|
|
297
|
+
type: String,
|
|
298
|
+
required: true,
|
|
299
|
+
},
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Note: `templateType` must be provided by the consumer (fallback/defaulting happens in consumer app config, not in this component).
|
|
303
|
+
|
|
304
|
+
#### 6b. Pass props to `UploadYourLogoOnBoarding` in template
|
|
305
|
+
|
|
306
|
+
Add to the existing `<UploadYourLogoOnBoarding>` tag:
|
|
307
|
+
```vue
|
|
308
|
+
:show-keywords-step="showKeywordsStep"
|
|
309
|
+
:template-type="templateType"
|
|
310
|
+
@on-save-keywords="onSaveKeywords"
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
#### 6c. Add event handler method
|
|
314
|
+
|
|
315
|
+
```js
|
|
316
|
+
onSaveKeywords(payload) {
|
|
317
|
+
this.$emit('on-save-keywords', payload);
|
|
318
|
+
},
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### 7. Add Storybook story (required)
|
|
322
|
+
|
|
323
|
+
**File**: Create `src/experiences/components/UploadYourLogoOnBoarding/LogoKeywords.stories.js`
|
|
324
|
+
|
|
325
|
+
Create a story following standard Storybook patterns covering:
|
|
326
|
+
- Loading state (mock delayed API)
|
|
327
|
+
- Populated state (mock successful response with keywords)
|
|
328
|
+
- Empty state (mock failed response)
|
|
329
|
+
- Pre-populated state (savedKeywords prop set)
|
|
330
|
+
|
|
331
|
+
### 8. Publish package
|
|
332
|
+
|
|
333
|
+
After all changes are verified (human release process; **not** a coding-agent task):
|
|
334
|
+
1. Bump package version in `package.json`
|
|
335
|
+
2. Run `npm run bundle-translation` to regenerate i18n bundles
|
|
336
|
+
3. Perform manual validation in Storybook/integration context (no automated test runner in this repo)
|
|
337
|
+
4. Publish the new version of `@designcrowd/fe-shared-lib`
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Step Number Reference Table
|
|
342
|
+
|
|
343
|
+
### When `showKeywordsStep = false` (default, unchanged):
|
|
344
|
+
|
|
345
|
+
| currentStep | Component | Progress Display |
|
|
346
|
+
|---|---|---|
|
|
347
|
+
| 1 | LogoUploader | Step 0 of 4 |
|
|
348
|
+
| 2 | LogoCropper/Preview | Step 1 of 4 |
|
|
349
|
+
| 3 | LogoBusinessText | Step 2 of 4 |
|
|
350
|
+
| 4 | LogoBusinessBrandColours | Step 3 of 4 |
|
|
351
|
+
|
|
352
|
+
### When `showKeywordsStep = true`:
|
|
353
|
+
|
|
354
|
+
| currentStep | Component | Progress Display |
|
|
355
|
+
|---|---|---|
|
|
356
|
+
| 1 | LogoUploader | Step 0 of 5 |
|
|
357
|
+
| 2 | LogoCropper/Preview | Step 1 of 5 |
|
|
358
|
+
| 3 | LogoBusinessText | Step 2 of 5 |
|
|
359
|
+
| **4** | **LogoKeywords (NEW)** | **Step 3 of 5** |
|
|
360
|
+
| 5 | LogoBusinessBrandColours | Step 4 of 5 |
|
|
361
|
+
|
|
362
|
+
Note: The `useDropzone` variant adds step 0 (dropzone) and shifts totals by +1. The same logic applies — `totalNumSteps` handles this via the ternary in `data()`.
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## Files Changed
|
|
367
|
+
|
|
368
|
+
| File | Change |
|
|
369
|
+
|---|---|
|
|
370
|
+
| `src/experiences/constants/api.js` | Add `KEYWORD_SUGGESTIONS_API_URL` |
|
|
371
|
+
| `src/experiences/clients/brand-crowd-api.client.js` | Add `getKeywordSuggestionsAsync` method + export |
|
|
372
|
+
| `src/experiences/components/UploadYourLogoOnBoarding/LogoKeywords.vue` | **New file** — keywords step component |
|
|
373
|
+
| `src/experiences/components/UploadYourLogoOnBoarding/UploadYourLogoOnBoarding.vue` | New props, step routing, computed properties, methods, template |
|
|
374
|
+
| `src/experiences/components/UploadYourLogoApplication/UploadYourLogoApplication.vue` | Pass-through props + event |
|
|
375
|
+
| `src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.json` | Add `keywords`, `keywordsDescription` |
|
|
376
|
+
| `src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.de-DE.json` | Add `keywords`, `keywordsDescription` (English placeholder) |
|
|
377
|
+
| `src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.es-ES.json` | Add `keywords`, `keywordsDescription` (English placeholder) |
|
|
378
|
+
| `src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.fr-CA.json` | Add `keywords`, `keywordsDescription` (English placeholder) |
|
|
379
|
+
| `src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.fr-FR.json` | Add `keywords`, `keywordsDescription` (English placeholder) |
|
|
380
|
+
| `src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.pt-BR.json` | Add `keywords`, `keywordsDescription` (English placeholder) |
|
|
381
|
+
| `src/experiences/components/UploadYourLogoOnBoarding/i18n/upload-your-logo.pt-PT.json` | Add `keywords`, `keywordsDescription` (English placeholder) |
|
|
382
|
+
| `src/experiences/components/UploadYourLogoOnBoarding/LogoKeywords.stories.js` | **New file** (required) |
|