Skip to content

Commit 077305c

Browse files
authored
refactor(BuilderForm): don't split content/appearance (#368)
1 parent 8676cd4 commit 077305c

File tree

5 files changed

+52
-61
lines changed

5 files changed

+52
-61
lines changed

frontend/app/components/redesign/components/AppearanceBuilder.tsx

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export type ToolAppearance = BannerToolAppearance | WidgetToolAppearance
6767

6868
interface AppearanceBuilderProps {
6969
toolName: 'widget' | 'banner'
70-
appearance: ToolAppearance
70+
profile: ToolAppearance
7171
onRefresh: () => void
7272
positionSelector?: React.ReactNode
7373
colorsSelector?: React.ReactNode
@@ -81,26 +81,26 @@ function getValidSlideAnimation(value: unknown): SlideAnimationType {
8181

8282
export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
8383
toolName,
84-
appearance,
84+
profile,
8585
onRefresh,
8686
positionSelector,
8787
colorsSelector
8888
}) => {
89-
const { min: minFontSize, max: maxFontSize } = appearance.fontSizeRange
89+
const { min: minFontSize, max: maxFontSize } = profile.fontSizeRange
9090

9191
const [selectedThumbnail, setSelectedThumbnail] = useState(0)
9292
const { actions: uiActions, state: uiState } = useUI()
9393
const [lastSelectedAnimation, setLastSelectedAnimation] =
9494
useState<SlideAnimationType>(() => {
95-
const validated = getValidSlideAnimation(appearance.slideAnimation)
95+
const validated = getValidSlideAnimation(profile.slideAnimation)
9696
return validated === SLIDE_ANIMATION.None
9797
? SLIDE_ANIMATION.Slide
9898
: validated
9999
})
100-
const isAnimated = appearance.slideAnimation !== SLIDE_ANIMATION.None
100+
const isAnimated = profile.slideAnimation !== SLIDE_ANIMATION.None
101101

102102
const defaultFontIndex = FONT_FAMILY_OPTIONS.findIndex(
103-
(option) => option === appearance.fontName
103+
(option) => option === profile.fontName
104104
)
105105
const thumbnails = [wmLogo]
106106

@@ -129,7 +129,7 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
129129
defaultValue={defaultFontIndex.toString()}
130130
onChange={(value) => {
131131
const fontName = FONT_FAMILY_OPTIONS[parseInt(value)]
132-
appearance.onFontNameChange(fontName)
132+
profile.onFontNameChange(fontName)
133133
}}
134134
options={FONT_FAMILY_OPTIONS.map((font, index) => ({
135135
label: font,
@@ -144,22 +144,22 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
144144
onClick={() => {
145145
const newSize = Math.max(
146146
minFontSize,
147-
(appearance.fontSize ?? minFontSize) - 1
147+
(profile.fontSize ?? minFontSize) - 1
148148
)
149-
appearance.onFontSizeChange(newSize)
149+
profile.onFontSizeChange(newSize)
150150
}}
151151
aria-label="Decrease font size"
152152
>
153153
<span className="text-sm leading-sm text-text-primary">A</span>
154154
</button>
155155

156156
<Slider
157-
value={appearance.fontSize ?? minFontSize}
157+
value={profile.fontSize ?? minFontSize}
158158
min={minFontSize}
159159
max={maxFontSize}
160160
onChange={(value) => {
161161
console.log('Font size changed to:', value)
162-
appearance.onFontSizeChange(value)
162+
profile.onFontSizeChange(value)
163163
}}
164164
/>
165165

@@ -168,9 +168,9 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
168168
onClick={() => {
169169
const newSize = Math.min(
170170
maxFontSize,
171-
(appearance.fontSize ?? minFontSize) + 1
171+
(profile.fontSize ?? minFontSize) + 1
172172
)
173-
appearance.onFontSizeChange(newSize)
173+
profile.onFontSizeChange(newSize)
174174
}}
175175
>
176176
<span className="text-3xl leading-3xl text-text-primary">A</span>
@@ -195,8 +195,8 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
195195
label="Container Corner Radius"
196196
/>
197197
<CornerRadiusSelector
198-
defaultValue={appearance.borderRadius}
199-
onChange={(value) => appearance.onBorderChange(value)}
198+
defaultValue={profile.borderRadius}
199+
onChange={(value) => profile.onBorderChange(value)}
200200
/>
201201
</div>
202202

@@ -213,7 +213,7 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
213213
</>
214214
)}
215215

216-
{appearance.showAnimation && (
216+
{profile.showAnimation && (
217217
<>
218218
<Divider />
219219
<div className="flex flex-col gap-xs">
@@ -225,7 +225,7 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
225225
<Checkbox
226226
checked={isAnimated}
227227
onChange={() => {
228-
appearance.onSlideAnimationChange(
228+
profile.onSlideAnimationChange(
229229
isAnimated ? SLIDE_ANIMATION.None : lastSelectedAnimation
230230
)
231231
}}
@@ -237,7 +237,7 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
237237
disabled={!isAnimated}
238238
defaultValue={
239239
isAnimated
240-
? getValidSlideAnimation(appearance.slideAnimation)
240+
? getValidSlideAnimation(profile.slideAnimation)
241241
: lastSelectedAnimation
242242
}
243243
options={[
@@ -247,7 +247,7 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
247247
onChange={(value) => {
248248
const selectedAnimation = value as SlideAnimationType
249249
setLastSelectedAnimation(selectedAnimation)
250-
appearance.onSlideAnimationChange(selectedAnimation)
250+
profile.onSlideAnimationChange(selectedAnimation)
251251
}}
252252
/>
253253
</div>
@@ -269,10 +269,9 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
269269
<div className="flex gap-md xl:flex-row flex-col xl:items-center items-start">
270270
<Checkbox
271271
checked={
272-
typeof appearance.thumbnail === 'undefined' ||
273-
!!appearance.thumbnail
272+
typeof profile.thumbnail === 'undefined' || !!profile.thumbnail
274273
}
275-
onChange={appearance.onThumbnailVisibilityChange}
274+
onChange={profile.onThumbnailVisibilityChange}
276275
label="Visible"
277276
/>
278277
<div className="flex gap-md">

frontend/app/components/redesign/components/BuilderForm.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ import type { ToolContent } from './ContentBuilder'
1111
import type { ToolAppearance } from './AppearanceBuilder'
1212

1313
interface BuilderFormProps {
14-
content: ToolContent
15-
appearance: ToolAppearance
14+
profile: ToolContent | ToolAppearance
1615
toolName: 'widget' | 'banner'
1716
onRefresh: (section: 'appearance' | 'content') => void
1817
onBuildStepComplete?: (isComplete: boolean) => void
@@ -23,8 +22,7 @@ interface BuilderFormProps {
2322
export const BuilderForm: React.FC<BuilderFormProps> = ({
2423
onBuildStepComplete,
2524
onRefresh,
26-
content,
27-
appearance,
25+
profile,
2826
toolName,
2927
positionSelector,
3028
colorsSelector
@@ -75,11 +73,11 @@ export const BuilderForm: React.FC<BuilderFormProps> = ({
7573
>
7674
<ContentBuilder
7775
onRefresh={() => onRefresh('content')}
78-
content={content}
76+
profile={profile as ToolContent}
7977
/>
8078
<AppearanceBuilder
8179
onRefresh={() => onRefresh('appearance')}
82-
appearance={appearance}
80+
profile={profile as ToolAppearance}
8381
positionSelector={positionSelector}
8482
colorsSelector={colorsSelector}
8583
toolName={toolName}

frontend/app/components/redesign/components/ContentBuilder.tsx

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,34 +24,34 @@ export interface ToolContent {
2424
}
2525

2626
interface ContentBuilderProps {
27-
content: ToolContent
27+
profile: ToolContent
2828
onRefresh: () => void
2929
}
3030

3131
export const ContentBuilder: React.FC<ContentBuilderProps> = ({
32-
content,
32+
profile,
3333
onRefresh
3434
}) => {
3535
const titleInputRef = useRef<HTMLInputElement>(null)
3636
const messageTextareaRef = useRef<HTMLTextAreaElement>(null)
3737
const { actions: uiActions, state: uiState } = useUI()
38-
const isMessageVisible = content.isDescriptionVisible
38+
const isMessageVisible = profile.isDescriptionVisible
3939

4040
useEffect(() => {
4141
if (
4242
titleInputRef.current &&
43-
titleInputRef.current.value !== content.currentTitle
43+
titleInputRef.current.value !== profile.currentTitle
4444
) {
45-
titleInputRef.current.value = content.currentTitle
45+
titleInputRef.current.value = profile.currentTitle
4646
}
4747

4848
if (
4949
messageTextareaRef.current &&
50-
messageTextareaRef.current.value !== content.currentMessage
50+
messageTextareaRef.current.value !== profile.currentMessage
5151
) {
52-
messageTextareaRef.current.value = content.currentMessage
52+
messageTextareaRef.current.value = profile.currentMessage
5353
}
54-
}, [content.currentTitle, content.currentMessage])
54+
}, [profile.currentTitle, profile.currentMessage])
5555

5656
const handleToggle = (isOpen: boolean) => {
5757
uiActions.setActiveSection(isOpen ? 'content' : null)
@@ -73,25 +73,25 @@ export const ContentBuilder: React.FC<ContentBuilderProps> = ({
7373
>
7474
<div className="flex flex-col gap-lg">
7575
<TitleInput
76-
value={content.currentTitle}
77-
onChange={content.onTitleChange}
78-
suggestions={content.suggestedTitles}
79-
maxLength={content.titleMaxLength}
80-
helpText={content.titleHelpText}
76+
value={profile.currentTitle}
77+
onChange={profile.onTitleChange}
78+
suggestions={profile.suggestedTitles}
79+
maxLength={profile.titleMaxLength}
80+
helpText={profile.titleHelpText}
8181
/>
8282

8383
<Divider />
8484

8585
<div className="flex flex-col gap-xs">
8686
<h4 className="text-base leading-md font-bold text-text-primary">
87-
{content.messageLabel}
87+
{profile.messageLabel}
8888
</h4>
8989
<div className="flex gap-lg items-start xl:flex-row flex-col">
9090
<div className="flex items-center gap-xs shrink-0">
9191
<Checkbox
9292
checked={isMessageVisible}
9393
onChange={(visible) => {
94-
content.onDescriptionVisibilityChange(visible)
94+
profile.onDescriptionVisibilityChange(visible)
9595
}}
9696
label="Active"
9797
/>
@@ -100,16 +100,16 @@ export const ContentBuilder: React.FC<ContentBuilderProps> = ({
100100
<div className="flex-grow w-full">
101101
<TextareaField
102102
ref={messageTextareaRef}
103-
defaultValue={content.currentMessage}
103+
defaultValue={profile.currentMessage}
104104
onChange={(e) => {
105-
content.onMessageChange(e.target.value)
105+
profile.onMessageChange(e.target.value)
106106
}}
107-
currentLength={content.currentMessage.length || 0}
108-
maxLength={content.messageMaxLength}
107+
currentLength={profile.currentMessage.length || 0}
108+
maxLength={profile.messageMaxLength}
109109
showCounter={true}
110-
helpText={content.messageHelpText}
110+
helpText={profile.messageHelpText}
111111
className="h-[84px]"
112-
placeholder={content.messagePlaceholder}
112+
placeholder={profile.messagePlaceholder}
113113
disabled={!isMessageVisible}
114114
/>
115115
</div>

frontend/app/routes/banner.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ export default function Banner() {
189189
useLoaderData<typeof loader>()
190190
usePathTracker()
191191

192-
const contentConfiguration: ToolContent = {
192+
const profile: ToolContent | BannerToolAppearance = {
193193
suggestedTitles: [
194194
'How to support?',
195195
'Fund me',
@@ -216,10 +216,8 @@ export default function Banner() {
216216
onDescriptionVisibilityChange: (visible: boolean) =>
217217
toolActions.setToolConfig({
218218
bannerDescriptionVisible: visible
219-
})
220-
}
219+
}),
221220

222-
const appearanceConfiguration: BannerToolAppearance = {
223221
fontName: snap.currentConfig?.bannerFontName,
224222
fontSize: snap.currentConfig?.bannerFontSize ?? BANNER_FONT_SIZES.default,
225223
fontSizeRange: BANNER_FONT_SIZES,
@@ -390,8 +388,7 @@ export default function Banner() {
390388

391389
<BuilderForm
392390
toolName="banner"
393-
content={contentConfiguration}
394-
appearance={appearanceConfiguration}
391+
profile={profile}
395392
onBuildStepComplete={(isComplete) =>
396393
toolActions.setBuildCompleteStep(
397394
isComplete ? 'filled' : 'unfilled'

frontend/app/routes/widget.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export default function Widget() {
176176
useLoaderData<typeof loader>()
177177
usePathTracker()
178178

179-
const contentConfiguration: ToolContent = {
179+
const profile: ToolContent | WidgetToolAppearance = {
180180
suggestedTitles: [
181181
'Support this content',
182182
'Make a payment',
@@ -202,10 +202,8 @@ export default function Widget() {
202202
onDescriptionVisibilityChange: (visible: boolean) =>
203203
toolActions.setToolConfig({
204204
widgetDescriptionVisible: visible
205-
})
206-
}
205+
}),
207206

208-
const appearanceConfiguration: WidgetToolAppearance = {
209207
fontName: snap.currentConfig?.widgetFontName,
210208
fontSize: snap.currentConfig?.widgetFontSize ?? WIDGET_FONT_SIZES.default,
211209
fontSizeRange: WIDGET_FONT_SIZES,
@@ -373,8 +371,7 @@ export default function Widget() {
373371

374372
<BuilderForm
375373
toolName="widget"
376-
content={contentConfiguration}
377-
appearance={appearanceConfiguration}
374+
profile={profile}
378375
onBuildStepComplete={(isComplete) =>
379376
toolActions.setBuildCompleteStep(
380377
isComplete ? 'filled' : 'unfilled'

0 commit comments

Comments
 (0)