Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 21 additions & 22 deletions frontend/app/components/redesign/components/AppearanceBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export type ToolAppearance = BannerToolAppearance | WidgetToolAppearance

interface AppearanceBuilderProps {
toolName: 'widget' | 'banner'
appearance: ToolAppearance
profile: ToolAppearance
onRefresh: () => void
positionSelector?: React.ReactNode
colorsSelector?: React.ReactNode
Expand All @@ -81,26 +81,26 @@ function getValidSlideAnimation(value: unknown): SlideAnimationType {

export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
toolName,
appearance,
profile,
onRefresh,
positionSelector,
colorsSelector
}) => {
const { min: minFontSize, max: maxFontSize } = appearance.fontSizeRange
const { min: minFontSize, max: maxFontSize } = profile.fontSizeRange

const [selectedThumbnail, setSelectedThumbnail] = useState(0)
const { actions: uiActions, state: uiState } = useUI()
const [lastSelectedAnimation, setLastSelectedAnimation] =
useState<SlideAnimationType>(() => {
const validated = getValidSlideAnimation(appearance.slideAnimation)
const validated = getValidSlideAnimation(profile.slideAnimation)
return validated === SLIDE_ANIMATION.None
? SLIDE_ANIMATION.Slide
: validated
})
const isAnimated = appearance.slideAnimation !== SLIDE_ANIMATION.None
const isAnimated = profile.slideAnimation !== SLIDE_ANIMATION.None

const defaultFontIndex = FONT_FAMILY_OPTIONS.findIndex(
(option) => option === appearance.fontName
(option) => option === profile.fontName
)
const thumbnails = [wmLogo]

Expand Down Expand Up @@ -129,7 +129,7 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
defaultValue={defaultFontIndex.toString()}
onChange={(value) => {
const fontName = FONT_FAMILY_OPTIONS[parseInt(value)]
appearance.onFontNameChange(fontName)
profile.onFontNameChange(fontName)
}}
options={FONT_FAMILY_OPTIONS.map((font, index) => ({
label: font,
Expand All @@ -144,22 +144,22 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
onClick={() => {
const newSize = Math.max(
minFontSize,
(appearance.fontSize ?? minFontSize) - 1
(profile.fontSize ?? minFontSize) - 1
)
appearance.onFontSizeChange(newSize)
profile.onFontSizeChange(newSize)
}}
aria-label="Decrease font size"
>
<span className="text-sm leading-sm text-text-primary">A</span>
</button>

<Slider
value={appearance.fontSize ?? minFontSize}
value={profile.fontSize ?? minFontSize}
min={minFontSize}
max={maxFontSize}
onChange={(value) => {
console.log('Font size changed to:', value)
appearance.onFontSizeChange(value)
profile.onFontSizeChange(value)
}}
/>

Expand All @@ -168,9 +168,9 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
onClick={() => {
const newSize = Math.min(
maxFontSize,
(appearance.fontSize ?? minFontSize) + 1
(profile.fontSize ?? minFontSize) + 1
)
appearance.onFontSizeChange(newSize)
profile.onFontSizeChange(newSize)
}}
>
<span className="text-3xl leading-3xl text-text-primary">A</span>
Expand All @@ -195,8 +195,8 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
label="Container Corner Radius"
/>
<CornerRadiusSelector
defaultValue={appearance.borderRadius}
onChange={(value) => appearance.onBorderChange(value)}
defaultValue={profile.borderRadius}
onChange={(value) => profile.onBorderChange(value)}
/>
</div>

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

{appearance.showAnimation && (
{profile.showAnimation && (
<>
<Divider />
<div className="flex flex-col gap-xs">
Expand All @@ -225,7 +225,7 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
<Checkbox
checked={isAnimated}
onChange={() => {
appearance.onSlideAnimationChange(
profile.onSlideAnimationChange(
isAnimated ? SLIDE_ANIMATION.None : lastSelectedAnimation
)
}}
Expand All @@ -237,7 +237,7 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
disabled={!isAnimated}
defaultValue={
isAnimated
? getValidSlideAnimation(appearance.slideAnimation)
? getValidSlideAnimation(profile.slideAnimation)
: lastSelectedAnimation
}
options={[
Expand All @@ -247,7 +247,7 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
onChange={(value) => {
const selectedAnimation = value as SlideAnimationType
setLastSelectedAnimation(selectedAnimation)
appearance.onSlideAnimationChange(selectedAnimation)
profile.onSlideAnimationChange(selectedAnimation)
}}
/>
</div>
Expand All @@ -269,10 +269,9 @@ export const AppearanceBuilder: React.FC<AppearanceBuilderProps> = ({
<div className="flex gap-md xl:flex-row flex-col xl:items-center items-start">
<Checkbox
checked={
typeof appearance.thumbnail === 'undefined' ||
!!appearance.thumbnail
typeof profile.thumbnail === 'undefined' || !!profile.thumbnail
}
onChange={appearance.onThumbnailVisibilityChange}
onChange={profile.onThumbnailVisibilityChange}
label="Visible"
/>
<div className="flex gap-md">
Expand Down
10 changes: 4 additions & 6 deletions frontend/app/components/redesign/components/BuilderForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ import type { ToolContent } from './ContentBuilder'
import type { ToolAppearance } from './AppearanceBuilder'

interface BuilderFormProps {
content: ToolContent
appearance: ToolAppearance
profile: ToolContent | ToolAppearance
toolName: 'widget' | 'banner'
onRefresh: (section: 'appearance' | 'content') => void
onBuildStepComplete?: (isComplete: boolean) => void
Expand All @@ -23,8 +22,7 @@ interface BuilderFormProps {
export const BuilderForm: React.FC<BuilderFormProps> = ({
onBuildStepComplete,
onRefresh,
content,
appearance,
profile,
toolName,
positionSelector,
colorsSelector
Expand Down Expand Up @@ -75,11 +73,11 @@ export const BuilderForm: React.FC<BuilderFormProps> = ({
>
<ContentBuilder
onRefresh={() => onRefresh('content')}
content={content}
profile={profile as ToolContent}
/>
<AppearanceBuilder
onRefresh={() => onRefresh('appearance')}
appearance={appearance}
profile={profile as ToolAppearance}
positionSelector={positionSelector}
colorsSelector={colorsSelector}
toolName={toolName}
Expand Down
42 changes: 21 additions & 21 deletions frontend/app/components/redesign/components/ContentBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,34 +24,34 @@ export interface ToolContent {
}

interface ContentBuilderProps {
content: ToolContent
profile: ToolContent
onRefresh: () => void
}

export const ContentBuilder: React.FC<ContentBuilderProps> = ({
content,
profile,
onRefresh
}) => {
const titleInputRef = useRef<HTMLInputElement>(null)
const messageTextareaRef = useRef<HTMLTextAreaElement>(null)
const { actions: uiActions, state: uiState } = useUI()
const isMessageVisible = content.isDescriptionVisible
const isMessageVisible = profile.isDescriptionVisible

useEffect(() => {
if (
titleInputRef.current &&
titleInputRef.current.value !== content.currentTitle
titleInputRef.current.value !== profile.currentTitle
) {
titleInputRef.current.value = content.currentTitle
titleInputRef.current.value = profile.currentTitle
}

if (
messageTextareaRef.current &&
messageTextareaRef.current.value !== content.currentMessage
messageTextareaRef.current.value !== profile.currentMessage
) {
messageTextareaRef.current.value = content.currentMessage
messageTextareaRef.current.value = profile.currentMessage
}
}, [content.currentTitle, content.currentMessage])
}, [profile.currentTitle, profile.currentMessage])

const handleToggle = (isOpen: boolean) => {
uiActions.setActiveSection(isOpen ? 'content' : null)
Expand All @@ -73,25 +73,25 @@ export const ContentBuilder: React.FC<ContentBuilderProps> = ({
>
<div className="flex flex-col gap-lg">
<TitleInput
value={content.currentTitle}
onChange={content.onTitleChange}
suggestions={content.suggestedTitles}
maxLength={content.titleMaxLength}
helpText={content.titleHelpText}
value={profile.currentTitle}
onChange={profile.onTitleChange}
suggestions={profile.suggestedTitles}
maxLength={profile.titleMaxLength}
helpText={profile.titleHelpText}
/>

<Divider />

<div className="flex flex-col gap-xs">
<h4 className="text-base leading-md font-bold text-text-primary">
{content.messageLabel}
{profile.messageLabel}
</h4>
<div className="flex gap-lg items-start xl:flex-row flex-col">
<div className="flex items-center gap-xs shrink-0">
<Checkbox
checked={isMessageVisible}
onChange={(visible) => {
content.onDescriptionVisibilityChange(visible)
profile.onDescriptionVisibilityChange(visible)
}}
label="Active"
/>
Expand All @@ -100,16 +100,16 @@ export const ContentBuilder: React.FC<ContentBuilderProps> = ({
<div className="flex-grow w-full">
<TextareaField
ref={messageTextareaRef}
defaultValue={content.currentMessage}
defaultValue={profile.currentMessage}
onChange={(e) => {
content.onMessageChange(e.target.value)
profile.onMessageChange(e.target.value)
}}
currentLength={content.currentMessage.length || 0}
maxLength={content.messageMaxLength}
currentLength={profile.currentMessage.length || 0}
maxLength={profile.messageMaxLength}
showCounter={true}
helpText={content.messageHelpText}
helpText={profile.messageHelpText}
className="h-[84px]"
placeholder={content.messagePlaceholder}
placeholder={profile.messagePlaceholder}
disabled={!isMessageVisible}
/>
</div>
Expand Down
9 changes: 3 additions & 6 deletions frontend/app/routes/banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export default function Banner() {
useLoaderData<typeof loader>()
usePathTracker()

const contentConfiguration: ToolContent = {
const profile: ToolContent | BannerToolAppearance = {
suggestedTitles: [
'How to support?',
'Fund me',
Expand All @@ -216,10 +216,8 @@ export default function Banner() {
onDescriptionVisibilityChange: (visible: boolean) =>
toolActions.setToolConfig({
bannerDescriptionVisible: visible
})
}
}),

const appearanceConfiguration: BannerToolAppearance = {
fontName: snap.currentConfig?.bannerFontName,
fontSize: snap.currentConfig?.bannerFontSize ?? BANNER_FONT_SIZES.default,
fontSizeRange: BANNER_FONT_SIZES,
Expand Down Expand Up @@ -390,8 +388,7 @@ export default function Banner() {

<BuilderForm
toolName="banner"
content={contentConfiguration}
appearance={appearanceConfiguration}
profile={profile}
onBuildStepComplete={(isComplete) =>
toolActions.setBuildCompleteStep(
isComplete ? 'filled' : 'unfilled'
Expand Down
9 changes: 3 additions & 6 deletions frontend/app/routes/widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export default function Widget() {
useLoaderData<typeof loader>()
usePathTracker()

const contentConfiguration: ToolContent = {
const profile: ToolContent | WidgetToolAppearance = {
suggestedTitles: [
'Support this content',
'Make a payment',
Expand All @@ -202,10 +202,8 @@ export default function Widget() {
onDescriptionVisibilityChange: (visible: boolean) =>
toolActions.setToolConfig({
widgetDescriptionVisible: visible
})
}
}),

const appearanceConfiguration: WidgetToolAppearance = {
fontName: snap.currentConfig?.widgetFontName,
fontSize: snap.currentConfig?.widgetFontSize ?? WIDGET_FONT_SIZES.default,
fontSizeRange: WIDGET_FONT_SIZES,
Expand Down Expand Up @@ -373,8 +371,7 @@ export default function Widget() {

<BuilderForm
toolName="widget"
content={contentConfiguration}
appearance={appearanceConfiguration}
profile={profile}
onBuildStepComplete={(isComplete) =>
toolActions.setBuildCompleteStep(
isComplete ? 'filled' : 'unfilled'
Expand Down