@licklist/design 0.78.21 → 0.78.26

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 (186) hide show
  1. package/dist/assets/Trend-Down.svg +3 -0
  2. package/dist/assets/Trend-Up.svg +3 -0
  3. package/dist/auth/Authorizer.d.ts.map +1 -1
  4. package/dist/auth/Authorizer.js +47 -12
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +5 -0
  8. package/dist/v2/components/EntityHeader/EntityHeader.d.ts +13 -0
  9. package/dist/v2/components/EntityHeader/EntityHeader.d.ts.map +1 -0
  10. package/dist/v2/components/EntityHeader/EntityHeader.js +85 -0
  11. package/dist/v2/components/EntityHeader/EntityHeader.scss.js +6 -0
  12. package/dist/v2/components/EntityHeader/index.d.ts +2 -0
  13. package/dist/v2/components/EntityHeader/index.d.ts.map +1 -0
  14. package/dist/v2/components/NPSScore/NPSScore.d.ts +18 -0
  15. package/dist/v2/components/NPSScore/NPSScore.d.ts.map +1 -0
  16. package/dist/v2/components/NPSScore/index.d.ts +3 -0
  17. package/dist/v2/components/NPSScore/index.d.ts.map +1 -0
  18. package/dist/v2/components/Select/Select.d.ts +10 -0
  19. package/dist/v2/components/Select/Select.d.ts.map +1 -0
  20. package/dist/v2/components/Select/index.d.ts +3 -0
  21. package/dist/v2/components/Select/index.d.ts.map +1 -0
  22. package/dist/v2/components/Tooltip/Tooltip.d.ts +21 -0
  23. package/dist/v2/components/Tooltip/Tooltip.d.ts.map +1 -0
  24. package/dist/v2/components/Tooltip/Tooltip.js +103 -0
  25. package/dist/v2/components/Tooltip/Tooltip.scss.js +6 -0
  26. package/dist/v2/components/Tooltip/index.d.ts +2 -0
  27. package/dist/v2/components/Tooltip/index.d.ts.map +1 -0
  28. package/dist/v2/components/UserAvatar/UserAvatar.d.ts +12 -0
  29. package/dist/v2/components/UserAvatar/UserAvatar.d.ts.map +1 -0
  30. package/dist/v2/components/UserAvatar/UserAvatar.js +77 -0
  31. package/dist/v2/components/UserAvatar/UserAvatar.scss.js +6 -0
  32. package/dist/v2/components/UserAvatar/index.d.ts +2 -0
  33. package/dist/v2/components/UserAvatar/index.d.ts.map +1 -0
  34. package/dist/v2/components/UserPanel/UserPanel.d.ts +17 -0
  35. package/dist/v2/components/UserPanel/UserPanel.d.ts.map +1 -0
  36. package/dist/v2/components/UserPanel/UserPanel.js +144 -0
  37. package/dist/v2/components/UserPanel/UserPanel.scss.js +6 -0
  38. package/dist/v2/components/UserPanel/index.d.ts +3 -0
  39. package/dist/v2/components/UserPanel/index.d.ts.map +1 -0
  40. package/dist/v2/dashboard-analytics/blog-posts/Blog.d.ts +15 -0
  41. package/dist/v2/dashboard-analytics/blog-posts/Blog.d.ts.map +1 -0
  42. package/dist/v2/dashboard-analytics/blog-posts/index.d.ts +3 -0
  43. package/dist/v2/dashboard-analytics/blog-posts/index.d.ts.map +1 -0
  44. package/dist/v2/dashboard-analytics/chart/Chart.d.ts +21 -0
  45. package/dist/v2/dashboard-analytics/chart/Chart.d.ts.map +1 -0
  46. package/dist/v2/dashboard-analytics/chart/index.d.ts +3 -0
  47. package/dist/v2/dashboard-analytics/chart/index.d.ts.map +1 -0
  48. package/dist/v2/dashboard-analytics/dashboard/Dashboard.d.ts +57 -0
  49. package/dist/v2/dashboard-analytics/dashboard/Dashboard.d.ts.map +1 -0
  50. package/dist/v2/dashboard-analytics/dashboard/index.d.ts +3 -0
  51. package/dist/v2/dashboard-analytics/dashboard/index.d.ts.map +1 -0
  52. package/dist/v2/dashboard-analytics/index.d.ts +13 -0
  53. package/dist/v2/dashboard-analytics/index.d.ts.map +1 -0
  54. package/dist/v2/dashboard-analytics/metric-card/MetricCard.d.ts +17 -0
  55. package/dist/v2/dashboard-analytics/metric-card/MetricCard.d.ts.map +1 -0
  56. package/dist/v2/dashboard-analytics/metric-card/index.d.ts +3 -0
  57. package/dist/v2/dashboard-analytics/metric-card/index.d.ts.map +1 -0
  58. package/dist/v2/dashboard-analytics/venue-card/VenueCard.d.ts +12 -0
  59. package/dist/v2/dashboard-analytics/venue-card/VenueCard.d.ts.map +1 -0
  60. package/dist/v2/dashboard-analytics/venue-card/index.d.ts +3 -0
  61. package/dist/v2/dashboard-analytics/venue-card/index.d.ts.map +1 -0
  62. package/dist/v2/dashboard-analytics/venue-closed-card/VenueClosedCard.d.ts +25 -0
  63. package/dist/v2/dashboard-analytics/venue-closed-card/VenueClosedCard.d.ts.map +1 -0
  64. package/dist/v2/dashboard-analytics/venue-closed-card/index.d.ts +3 -0
  65. package/dist/v2/dashboard-analytics/venue-closed-card/index.d.ts.map +1 -0
  66. package/dist/v2/index.d.ts +11 -5
  67. package/dist/v2/index.d.ts.map +1 -1
  68. package/dist/v2/navigation/DashboardLayout/AdminSidebar.d.ts +10 -0
  69. package/dist/v2/navigation/DashboardLayout/AdminSidebar.d.ts.map +1 -0
  70. package/dist/v2/navigation/DashboardLayout/AdminSidebar.js +296 -0
  71. package/dist/v2/navigation/DashboardLayout/AdminSidebar.scss.js +6 -0
  72. package/dist/v2/navigation/DashboardLayout/DashboardFooter.d.ts +7 -0
  73. package/dist/v2/navigation/DashboardLayout/DashboardFooter.d.ts.map +1 -0
  74. package/dist/v2/navigation/DashboardLayout/DashboardFooter.js +34 -0
  75. package/dist/v2/navigation/DashboardLayout/DashboardFooter.scss.js +6 -0
  76. package/dist/v2/navigation/DashboardLayout/DashboardLayout.d.ts +42 -0
  77. package/dist/v2/navigation/DashboardLayout/DashboardLayout.d.ts.map +1 -0
  78. package/dist/v2/navigation/DashboardLayout/DashboardLayout.js +176 -0
  79. package/dist/v2/navigation/DashboardLayout/DashboardLayout.scss.js +6 -0
  80. package/dist/v2/navigation/DashboardLayout/ProviderSidebar.d.ts +35 -0
  81. package/dist/v2/navigation/DashboardLayout/ProviderSidebar.d.ts.map +1 -0
  82. package/dist/v2/navigation/DashboardLayout/ProviderSidebar.js +366 -0
  83. package/dist/v2/navigation/DashboardLayout/ProviderSidebar.scss.js +6 -0
  84. package/dist/v2/navigation/DashboardLayout/TopNavigation.d.ts +26 -0
  85. package/dist/v2/navigation/DashboardLayout/TopNavigation.d.ts.map +1 -0
  86. package/dist/v2/navigation/DashboardLayout/TopNavigation.js +360 -0
  87. package/dist/v2/navigation/DashboardLayout/TopNavigation.scss.js +6 -0
  88. package/dist/v2/navigation/DashboardLayout/assets/AdminLogo.png.js +3 -0
  89. package/dist/v2/navigation/DashboardLayout/assets/BookedLogo_Mark.png.js +3 -0
  90. package/dist/v2/navigation/DashboardLayout/index.d.ts +7 -0
  91. package/dist/v2/navigation/DashboardLayout/index.d.ts.map +1 -0
  92. package/package.json +5 -3
  93. package/src/assets/Trend-Down.svg +3 -0
  94. package/src/assets/Trend-Up.svg +3 -0
  95. package/src/auth/Authorizer.tsx +49 -20
  96. package/src/index.ts +2 -1
  97. package/src/v2/components/EntityHeader/EntityHeader.scss +133 -0
  98. package/src/v2/components/EntityHeader/EntityHeader.stories.tsx +103 -0
  99. package/src/v2/components/EntityHeader/EntityHeader.tsx +76 -0
  100. package/src/v2/components/EntityHeader/index.ts +1 -0
  101. package/src/v2/components/NPSScore/NPSScore.scss +330 -0
  102. package/src/v2/components/NPSScore/NPSScore.stories.tsx +29 -0
  103. package/src/v2/components/NPSScore/NPSScore.tsx +209 -0
  104. package/src/v2/components/NPSScore/index.ts +2 -0
  105. package/src/v2/components/Select/Select.scss +188 -0
  106. package/src/v2/components/Select/Select.stories.tsx +164 -0
  107. package/src/v2/components/Select/Select.tsx +56 -0
  108. package/src/v2/components/Select/index.ts +2 -0
  109. package/src/v2/components/Tooltip/Tooltip.scss +92 -0
  110. package/src/v2/components/Tooltip/Tooltip.stories.tsx +164 -0
  111. package/src/v2/components/Tooltip/Tooltip.tsx +64 -0
  112. package/src/v2/components/Tooltip/index.ts +8 -0
  113. package/src/v2/components/UserAvatar/UserAvatar.scss +62 -0
  114. package/src/v2/components/UserAvatar/UserAvatar.stories.tsx +94 -0
  115. package/src/v2/components/UserAvatar/UserAvatar.tsx +96 -0
  116. package/src/v2/components/UserAvatar/index.ts +1 -0
  117. package/src/v2/components/UserPanel/UserPanel.scss +195 -0
  118. package/src/v2/components/UserPanel/UserPanel.stories.tsx +66 -0
  119. package/src/v2/components/UserPanel/UserPanel.tsx +126 -0
  120. package/src/v2/components/UserPanel/index.ts +2 -0
  121. package/src/v2/dashboard-analytics/blog-posts/Blog.scss +92 -0
  122. package/src/v2/dashboard-analytics/blog-posts/Blog.stories.tsx +57 -0
  123. package/src/v2/dashboard-analytics/blog-posts/Blog.tsx +91 -0
  124. package/src/v2/dashboard-analytics/blog-posts/index.ts +2 -0
  125. package/src/v2/dashboard-analytics/chart/Chart.scss +424 -0
  126. package/src/v2/dashboard-analytics/chart/Chart.stories.tsx +157 -0
  127. package/src/v2/dashboard-analytics/chart/Chart.tsx +623 -0
  128. package/src/v2/dashboard-analytics/chart/index.ts +2 -0
  129. package/src/v2/dashboard-analytics/dashboard/Dashboard.scss +254 -0
  130. package/src/v2/dashboard-analytics/dashboard/Dashboard.stories.tsx +298 -0
  131. package/src/v2/dashboard-analytics/dashboard/Dashboard.tsx +248 -0
  132. package/src/v2/dashboard-analytics/dashboard/index.ts +2 -0
  133. package/src/v2/dashboard-analytics/index.ts +12 -0
  134. package/src/v2/dashboard-analytics/metric-card/MetricCard.scss +125 -0
  135. package/src/v2/dashboard-analytics/metric-card/MetricCard.stories.tsx +106 -0
  136. package/src/v2/dashboard-analytics/metric-card/MetricCard.tsx +72 -0
  137. package/src/v2/dashboard-analytics/metric-card/index.ts +2 -0
  138. package/src/v2/dashboard-analytics/venue-card/VenueCard.scss +112 -0
  139. package/src/v2/dashboard-analytics/venue-card/VenueCard.stories.tsx +40 -0
  140. package/src/v2/dashboard-analytics/venue-card/VenueCard.tsx +62 -0
  141. package/src/v2/dashboard-analytics/venue-card/index.ts +2 -0
  142. package/src/v2/dashboard-analytics/venue-closed-card/VenueClosedCard.scss +129 -0
  143. package/src/v2/dashboard-analytics/venue-closed-card/VenueClosedCard.stories.tsx +31 -0
  144. package/src/v2/dashboard-analytics/venue-closed-card/VenueClosedCard.tsx +61 -0
  145. package/src/v2/dashboard-analytics/venue-closed-card/index.ts +2 -0
  146. package/src/v2/design-system/colors/ColorSystem.scss +439 -0
  147. package/src/v2/design-system/colors/ColorSystem.stories.tsx +730 -0
  148. package/src/v2/design-system/typography/Typography.scss +295 -0
  149. package/src/v2/design-system/typography/Typography.stories.tsx +109 -0
  150. package/src/v2/index.ts +43 -7
  151. package/src/v2/navigation/DashboardLayout/AdminSidebar.scss +207 -0
  152. package/src/v2/navigation/DashboardLayout/AdminSidebar.tsx +171 -0
  153. package/src/v2/navigation/DashboardLayout/DashboardFooter.scss +30 -0
  154. package/src/v2/navigation/DashboardLayout/DashboardFooter.tsx +25 -0
  155. package/src/v2/navigation/DashboardLayout/DashboardLayout.scss +91 -0
  156. package/src/v2/navigation/DashboardLayout/DashboardLayout.stories.tsx +370 -0
  157. package/src/v2/navigation/DashboardLayout/DashboardLayout.tsx +233 -0
  158. package/src/v2/navigation/DashboardLayout/ProviderSidebar.scss +271 -0
  159. package/src/v2/navigation/DashboardLayout/ProviderSidebar.tsx +266 -0
  160. package/src/v2/navigation/DashboardLayout/Sidebar.stories.tsx +220 -0
  161. package/src/v2/navigation/DashboardLayout/TopNavigation.scss +206 -0
  162. package/src/v2/navigation/DashboardLayout/TopNavigation.tsx +279 -0
  163. package/src/v2/navigation/DashboardLayout/assets/AdminLogo.png +0 -0
  164. package/src/v2/navigation/DashboardLayout/assets/BookedLogo_Mark.png +0 -0
  165. package/src/v2/navigation/DashboardLayout/index.ts +20 -0
  166. package/src/v2/styles/index.scss +0 -1
  167. package/src/v2/styles/tokens/_colors.scss +531 -98
  168. package/dist/v2/components/Colors/Colors.d.ts +0 -21
  169. package/dist/v2/components/Colors/Colors.d.ts.map +0 -1
  170. package/dist/v2/components/Colors/index.d.ts +0 -3
  171. package/dist/v2/components/Colors/index.d.ts.map +0 -1
  172. package/dist/v2/components/Typography/Typography.d.ts +0 -11
  173. package/dist/v2/components/Typography/Typography.d.ts.map +0 -1
  174. package/dist/v2/components/Typography/index.d.ts +0 -3
  175. package/dist/v2/components/Typography/index.d.ts.map +0 -1
  176. package/src/v2/components/Colors/Colors.scss +0 -64
  177. package/src/v2/components/Colors/Colors.stories.tsx +0 -143
  178. package/src/v2/components/Colors/Colors.tsx +0 -51
  179. package/src/v2/components/Colors/ColorsAliases.stories.tsx +0 -285
  180. package/src/v2/components/Colors/Sizes.stories.tsx +0 -141
  181. package/src/v2/components/Colors/index.ts +0 -2
  182. package/src/v2/components/Typography/Typography.scss +0 -72
  183. package/src/v2/components/Typography/Typography.stories.tsx +0 -266
  184. package/src/v2/components/Typography/Typography.tsx +0 -56
  185. package/src/v2/components/Typography/index.ts +0 -2
  186. package/src/v2/styles/tokens/_aliases.scss +0 -199
@@ -0,0 +1,330 @@
1
+ .nps-score {
2
+ width: 100%;
3
+ margin-top: 24px;
4
+
5
+ &__container {
6
+ background: var(--surfaces-main-surface-secondary, #F4F4F7);
7
+ border-radius: 16px;
8
+ padding: 24px;
9
+ border: 1px solid var(--borders-main-border-primary, #E8E9EF);
10
+ }
11
+
12
+ &__question {
13
+ font-family: var(--font-family-sans);
14
+ font-size: 18px;
15
+ font-weight: 600;
16
+ line-height: 24px;
17
+ color: var(--labels-main-label-primary, #121E52);
18
+ margin: 0 0 16px 0;
19
+ }
20
+
21
+ &__labels {
22
+ display: flex;
23
+ justify-content: space-between;
24
+ align-items: center;
25
+ margin-bottom: 12px;
26
+ }
27
+
28
+ &__label {
29
+ display: flex;
30
+ align-items: center;
31
+ gap: 8px;
32
+
33
+ span {
34
+ font-family: var(--font-family-sans);
35
+ font-size: 14px;
36
+ font-weight: 500;
37
+ color: var(--labels-main-label-secondary, #626A90);
38
+ }
39
+
40
+ &--desktop {
41
+ display: none;
42
+
43
+ @media (min-width: 768px) {
44
+ display: flex;
45
+ }
46
+ }
47
+
48
+ &--mobile {
49
+ display: flex;
50
+ justify-content: flex-end;
51
+ margin-top: 12px;
52
+
53
+ @media (min-width: 768px) {
54
+ display: none;
55
+ }
56
+ }
57
+ }
58
+
59
+ &__label-icon {
60
+ color: var(--fills-main-fill-secondary, #626A90);
61
+ flex-shrink: 0;
62
+ }
63
+
64
+ &__buttons {
65
+ display: grid;
66
+ grid-template-columns: repeat(5, 1fr);
67
+ gap: 8px;
68
+
69
+ @media (min-width: 768px) {
70
+ grid-template-columns: repeat(10, 1fr);
71
+ }
72
+ }
73
+
74
+ &__button {
75
+ height: 48px;
76
+ border-radius: 12px;
77
+ font-family: var(--font-family-sans);
78
+ font-size: 18px;
79
+ font-weight: 600;
80
+ transition: all 0.2s ease;
81
+ cursor: pointer;
82
+ background: var(--surfaces-main-surface-primary, #FFFFFF);
83
+ border: 1px solid var(--borders-main-border-primary, #E8E9EF);
84
+ color: var(--labels-main-label-primary, #121E52);
85
+
86
+ &:hover:not(&--selected) {
87
+ background: var(--surfaces-main-surface-primary-hover, #F8F8FA);
88
+ }
89
+
90
+ &--selected {
91
+ background: var(--fills-main-fill-primary, #14215A);
92
+ border-color: transparent;
93
+ color: #FFFFFF;
94
+ }
95
+ }
96
+
97
+ &__expanded {
98
+ margin-top: 16px;
99
+ display: flex;
100
+ flex-direction: column;
101
+ gap: 16px;
102
+ animation: nps-fade-in 0.2s ease;
103
+ }
104
+
105
+ &__field {
106
+ &--roles {
107
+ padding-top: 16px;
108
+ }
109
+ }
110
+
111
+ &__field-label {
112
+ display: block;
113
+ font-family: var(--font-family-sans);
114
+ font-size: 14px;
115
+ font-weight: 500;
116
+ color: var(--labels-main-label-primary, #121E52);
117
+ margin-bottom: 8px;
118
+ }
119
+
120
+ &__field-header {
121
+ display: flex;
122
+ justify-content: space-between;
123
+ align-items: center;
124
+ margin-bottom: 8px;
125
+ }
126
+
127
+ &__optional {
128
+ font-family: var(--font-family-sans);
129
+ font-size: 14px;
130
+ color: var(--labels-main-label-secondary, #626A90);
131
+ }
132
+
133
+ &__textarea {
134
+ width: 100%;
135
+ min-height: 100px;
136
+ padding: 12px;
137
+ border-radius: 8px;
138
+ border: 1px solid var(--borders-main-border-primary, #E8E9EF);
139
+ background: var(--surfaces-main-surface-primary, #FFFFFF);
140
+ font-family: var(--font-family-sans);
141
+ font-size: 14px;
142
+ color: var(--labels-main-label-primary, #121E52);
143
+ resize: vertical;
144
+ box-sizing: border-box;
145
+
146
+ &::placeholder {
147
+ color: var(--labels-main-label-tertiary, #9CA3AF);
148
+ }
149
+
150
+ &:focus {
151
+ outline: none;
152
+ border-color: var(--fills-main-fill-primary, #14215A);
153
+ }
154
+
155
+ &--error {
156
+ border-color: var(--fills-main-fill-danger, #DC2626);
157
+ }
158
+ }
159
+
160
+ &__hint {
161
+ font-family: var(--font-family-sans);
162
+ font-size: 14px;
163
+ color: var(--labels-main-label-secondary, #626A90);
164
+ margin: 4px 0 0 0;
165
+ }
166
+
167
+ &__error {
168
+ font-family: var(--font-family-sans);
169
+ font-size: 14px;
170
+ color: var(--fills-main-fill-danger, #DC2626);
171
+ margin: 4px 0 0 0;
172
+ }
173
+
174
+ &__add-comment {
175
+ font-family: var(--font-family-sans);
176
+ font-size: 14px;
177
+ font-weight: 500;
178
+ color: var(--labels-main-label-action, #2563EB);
179
+ text-decoration: underline;
180
+ background: none;
181
+ border: none;
182
+ padding: 0;
183
+ cursor: pointer;
184
+ transition: color 0.2s ease;
185
+
186
+ &:hover {
187
+ color: var(--labels-main-label-action-hover, #1D4ED8);
188
+ }
189
+ }
190
+
191
+ &__roles {
192
+ display: grid;
193
+ grid-template-columns: 1fr;
194
+ gap: 12px;
195
+
196
+ @media (min-width: 640px) {
197
+ grid-template-columns: repeat(2, 1fr);
198
+ }
199
+
200
+ @media (min-width: 1024px) {
201
+ grid-template-columns: repeat(3, 1fr);
202
+ }
203
+ }
204
+
205
+ &__role {
206
+ display: flex;
207
+ align-items: center;
208
+ gap: 8px;
209
+ cursor: pointer;
210
+ position: relative;
211
+ }
212
+
213
+ &__role-input {
214
+ appearance: none;
215
+ -webkit-appearance: none;
216
+ -moz-appearance: none;
217
+ width: 20px;
218
+ height: 20px;
219
+ border-radius: 50%;
220
+ border: 2px solid var(--borders-main-border-primary, #E8E9EF);
221
+ background: var(--surfaces-main-surface-primary, #FFFFFF);
222
+ margin: 0;
223
+ cursor: pointer;
224
+ flex-shrink: 0;
225
+ position: relative;
226
+ transition: border-color 0.2s ease;
227
+
228
+ &::before {
229
+ content: '';
230
+ position: absolute;
231
+ top: 50%;
232
+ left: 50%;
233
+ transform: translate(-50%, -50%) scale(0);
234
+ width: 10px;
235
+ height: 10px;
236
+ border-radius: 50%;
237
+ background: var(--fills-main-fill-primary, #14215A);
238
+ transition: transform 0.2s ease;
239
+ }
240
+
241
+ &:checked {
242
+ border-color: var(--fills-main-fill-primary, #14215A);
243
+
244
+ &::before {
245
+ transform: translate(-50%, -50%) scale(1);
246
+ }
247
+ }
248
+
249
+ &:focus {
250
+ outline: none;
251
+ box-shadow: 0 0 0 2px var(--fills-main-fill-primary-opacity, rgba(20, 33, 90, 0.2));
252
+ }
253
+ }
254
+
255
+ &__role-radio {
256
+ display: none;
257
+ }
258
+
259
+ &__role-label {
260
+ font-family: var(--font-family-sans);
261
+ font-size: 14px;
262
+ color: var(--labels-main-label-primary, #121E52);
263
+ }
264
+
265
+ &__submit {
266
+ display: inline-flex;
267
+ align-items: center;
268
+ justify-content: center;
269
+ padding: 12px 24px;
270
+ border-radius: 8px;
271
+ border: none;
272
+ background: var(--fills-main-fill-primary, #14215A);
273
+ color: #FFFFFF;
274
+ font-family: var(--font-family-sans);
275
+ font-size: 14px;
276
+ font-weight: 600;
277
+ cursor: pointer;
278
+ transition: background 0.2s ease;
279
+ width: fit-content;
280
+
281
+ &:hover:not(:disabled) {
282
+ background: var(--fills-main-fill-primary-hover, #1a2a6e);
283
+ }
284
+
285
+ &:disabled {
286
+ opacity: 0.6;
287
+ cursor: not-allowed;
288
+ }
289
+ }
290
+
291
+ &__success {
292
+ display: flex;
293
+ flex-direction: column;
294
+ align-items: center;
295
+ justify-content: center;
296
+ padding: 32px;
297
+ text-align: center;
298
+ }
299
+
300
+ &__success-icon {
301
+ color: var(--fills-main-fill-success, #10B981);
302
+ margin-bottom: 16px;
303
+ }
304
+
305
+ &__success-title {
306
+ font-family: var(--font-family-sans);
307
+ font-size: 24px;
308
+ font-weight: 600;
309
+ color: var(--labels-main-label-primary, #121E52);
310
+ margin: 0 0 8px 0;
311
+ }
312
+
313
+ &__success-message {
314
+ font-family: var(--font-family-sans);
315
+ font-size: 14px;
316
+ color: var(--labels-main-label-secondary, #626A90);
317
+ margin: 0;
318
+ }
319
+ }
320
+
321
+ @keyframes nps-fade-in {
322
+ from {
323
+ opacity: 0;
324
+ transform: translateY(-8px);
325
+ }
326
+ to {
327
+ opacity: 1;
328
+ transform: translateY(0);
329
+ }
330
+ }
@@ -0,0 +1,29 @@
1
+ import React from 'react'
2
+ import type { Meta, StoryObj } from '@storybook/react'
3
+ import { NPSScore } from './NPSScore'
4
+
5
+ const meta: Meta<typeof NPSScore> = {
6
+ title: 'v2/Components/NPSScore',
7
+ component: NPSScore,
8
+ parameters: {
9
+ layout: 'padded',
10
+ },
11
+ argTypes: {
12
+ firstName: { control: 'text' },
13
+ onSubmit: { action: 'submitted' },
14
+ onDismiss: { action: 'dismissed' },
15
+ },
16
+ }
17
+
18
+ export default meta
19
+ type Story = StoryObj<typeof NPSScore>
20
+
21
+ export const Default: Story = {
22
+ args: {
23
+ firstName: 'Godwin',
24
+ onSubmit: (data) => {
25
+ console.log('NPS Submitted:', data)
26
+ return Promise.resolve()
27
+ },
28
+ },
29
+ }
@@ -0,0 +1,209 @@
1
+ import React, { useState } from 'react'
2
+ import './NPSScore.scss'
3
+
4
+ export interface NPSScoreProps {
5
+ /** User's first name for personalized greeting */
6
+ firstName?: string
7
+ /** Callback when NPS is submitted */
8
+ onSubmit?: (data: NPSSubmitData) => void
9
+ /** Callback when dismissed */
10
+ onDismiss?: () => void
11
+ }
12
+
13
+ export interface NPSSubmitData {
14
+ score: number
15
+ role: string
16
+ reason?: string
17
+ }
18
+
19
+ const roleOptions = [
20
+ { value: 'owner', label: 'Business Owner' },
21
+ { value: 'manager', label: 'Manager' },
22
+ { value: 'finance', label: 'Finance' },
23
+ { value: 'marketing', label: 'Marketing' },
24
+ { value: 'staff', label: 'Staff Member' },
25
+ { value: 'other', label: 'Other' },
26
+ ]
27
+
28
+ // Icons
29
+ const IconSad = ({ size = 24, className = '' }: { size?: number; className?: string }) => (
30
+ <svg width={size} height={size} viewBox="0 0 32 32" fill="none" className={className}>
31
+ <path d="M16 6C21.5228 6 26 10.4771 26 16C26 21.5228 21.5228 26 16 26C10.4771 26 6 21.5228 6 16C6 10.4771 10.4771 6 16 6ZM16 8C11.5817 8 8 11.5817 8 16C8 20.4183 11.5817 24 16 24C20.4183 24 24 20.4183 24 16C24 11.5817 20.4183 8 16 8ZM16 16C18.7614 16 21 18.2386 21 21H19C19 19.3431 17.6569 18 16 18C14.3431 18 13 19.3431 13 21H11C11 18.2386 13.2386 16 16 16ZM13.5 12C14.3284 12 15 12.6716 15 13.5C15 14.3284 14.3284 15 13.5 15C12.6716 15 12 14.3284 12 13.5C12 12.6716 12.6716 12 13.5 12ZM18.5 12C19.3284 12 20 12.6716 20 13.5C20 14.3284 19.3284 15 18.5 15C17.6716 15 17 14.3284 17 13.5C17 12.6716 17.6716 12 18.5 12Z" fill="currentColor" />
32
+ </svg>
33
+ )
34
+
35
+ const IconBigSmile = ({ size = 24, className = '' }: { size?: number; className?: string }) => (
36
+ <svg width={size} height={size} viewBox="0 0 32 32" fill="none" className={className}>
37
+ <path d="M16 6C21.5228 6 26 10.4771 26 16C26 21.5228 21.5228 26 16 26C10.4771 26 6 21.5228 6 16C6 10.4771 10.4771 6 16 6ZM16 8C11.5817 8 8 11.5817 8 16C8 20.4183 11.5817 24 16 24C20.4183 24 24 20.4183 24 16C24 11.5817 20.4183 8 16 8ZM21 17C21 19.7614 18.7614 22 16 22C13.2386 22 11 19.7614 11 17H21ZM13.5 11C14.3284 11 15 11.6716 15 12.5C15 13.3284 14.3284 14 13.5 14C12.6716 14 12 13.3284 12 12.5C12 11.6716 12.6716 11 13.5 11ZM18.5 11C19.3284 11 20 11.6716 20 12.5C20 13.3284 19.3284 14 18.5 14C17.6716 14 17 13.3284 17 12.5C17 11.6716 17.6716 11 18.5 11Z" fill="currentColor" />
38
+ </svg>
39
+ )
40
+
41
+ export const NPSScore: React.FC<NPSScoreProps> = ({
42
+ firstName,
43
+ onSubmit,
44
+ onDismiss,
45
+ }) => {
46
+ const [selectedScore, setSelectedScore] = useState<number | null>(null)
47
+ const [reason, setReason] = useState('')
48
+ const [role, setRole] = useState('')
49
+ const [isSubmitting, setIsSubmitting] = useState(false)
50
+ const [errors, setErrors] = useState<{ reason?: string; role?: string }>({})
51
+ const [showReasonField, setShowReasonField] = useState(false)
52
+ const [isSubmitted, setIsSubmitted] = useState(false)
53
+
54
+ const handleSubmit = async () => {
55
+ if (!selectedScore) return
56
+
57
+ // Validate required fields - reason required for all scores
58
+ const newErrors: { reason?: string; role?: string } = {}
59
+ if (!reason.trim()) {
60
+ newErrors.reason = 'Please provide a reason for your score'
61
+ }
62
+ if (!role) {
63
+ newErrors.role = 'Please select your role'
64
+ }
65
+
66
+ if (Object.keys(newErrors).length > 0) {
67
+ setErrors(newErrors)
68
+ return
69
+ }
70
+
71
+ setErrors({})
72
+ setIsSubmitting(true)
73
+
74
+ try {
75
+ await onSubmit?.({
76
+ score: selectedScore,
77
+ role,
78
+ reason: reason.trim() || undefined,
79
+ })
80
+ setIsSubmitted(true)
81
+ } finally {
82
+ setIsSubmitting(false)
83
+ }
84
+ }
85
+
86
+ if (isSubmitted) {
87
+ return (
88
+ <div className="nps-score">
89
+ <div className="nps-score__container">
90
+ <div className="nps-score__success">
91
+ <IconBigSmile size={48} className="nps-score__success-icon" />
92
+ <h3 className="nps-score__success-title">Thank you!</h3>
93
+ <p className="nps-score__success-message">Your feedback has been submitted successfully.</p>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ )
98
+ }
99
+
100
+ return (
101
+ <div className="nps-score">
102
+ <div className="nps-score__container">
103
+ {/* Question */}
104
+ <h3 className="nps-score__question">
105
+ {firstName ? `Hey ${firstName}, how` : 'How'} likely would you be to recommend Booked it to a friend or colleague?
106
+ </h3>
107
+
108
+ {/* Scale labels */}
109
+ <div className="nps-score__labels">
110
+ <div className="nps-score__label">
111
+ <IconSad size={24} className="nps-score__label-icon" />
112
+ <span>Not Likely</span>
113
+ </div>
114
+ <div className="nps-score__label nps-score__label--desktop">
115
+ <span>Most Likely</span>
116
+ <IconBigSmile size={24} className="nps-score__label-icon" />
117
+ </div>
118
+ </div>
119
+
120
+ {/* Score buttons */}
121
+ <div className="nps-score__buttons">
122
+ {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((score) => (
123
+ <button
124
+ key={score}
125
+ onClick={() => setSelectedScore(score)}
126
+ className={`nps-score__button ${selectedScore === score ? 'nps-score__button--selected' : ''}`}
127
+ >
128
+ {score}
129
+ </button>
130
+ ))}
131
+ </div>
132
+
133
+ {/* Mobile label for Most Likely */}
134
+ <div className="nps-score__label nps-score__label--mobile">
135
+ <span>Most Likely</span>
136
+ <IconBigSmile size={24} className="nps-score__label-icon" />
137
+ </div>
138
+
139
+ {/* Expanded section after score selection */}
140
+ {selectedScore !== null && (
141
+ <div className="nps-score__expanded">
142
+ {/* Reason textarea - always visible */}
143
+ <div className="nps-score__field">
144
+ <label className="nps-score__field-label">
145
+ Reason for this score?
146
+ </label>
147
+ <textarea
148
+ value={reason}
149
+ onChange={(e) => {
150
+ setReason(e.target.value)
151
+ if (errors.reason) setErrors(prev => ({ ...prev, reason: undefined }))
152
+ }}
153
+ placeholder=""
154
+ className={`nps-score__textarea ${errors.reason ? 'nps-score__textarea--error' : ''}`}
155
+ />
156
+ {errors.reason ? (
157
+ <p className="nps-score__error">{errors.reason}</p>
158
+ ) : (
159
+ <p className="nps-score__hint">
160
+ Help us improve by explaining your score.
161
+ </p>
162
+ )}
163
+ </div>
164
+
165
+ {/* Role selection */}
166
+ <div className="nps-score__field nps-score__field--roles">
167
+ <label className="nps-score__field-label">
168
+ The role that best describes you?
169
+ </label>
170
+ <div className="nps-score__roles">
171
+ {roleOptions.map((option) => (
172
+ <label key={option.value} className="nps-score__role">
173
+ <input
174
+ type="radio"
175
+ name="role"
176
+ value={option.value}
177
+ checked={role === option.value}
178
+ onChange={(e) => {
179
+ setRole(e.target.value)
180
+ if (errors.role) setErrors(prev => ({ ...prev, role: undefined }))
181
+ }}
182
+ className="nps-score__role-input"
183
+ />
184
+ <span className="nps-score__role-radio"></span>
185
+ <span className="nps-score__role-label">{option.label}</span>
186
+ </label>
187
+ ))}
188
+ </div>
189
+ {errors.role && (
190
+ <p className="nps-score__error">{errors.role}</p>
191
+ )}
192
+ </div>
193
+
194
+ {/* Submit button */}
195
+ <button
196
+ onClick={handleSubmit}
197
+ disabled={isSubmitting}
198
+ className="nps-score__submit"
199
+ >
200
+ {isSubmitting ? 'Submitting...' : 'Submit'}
201
+ </button>
202
+ </div>
203
+ )}
204
+ </div>
205
+ </div>
206
+ )
207
+ }
208
+
209
+ export default NPSScore
@@ -0,0 +1,2 @@
1
+ export { NPSScore } from './NPSScore'
2
+ export type { NPSScoreProps, NPSSubmitData } from './NPSScore'