Skip to content

refactor: extract wrapper for shared screen layout#8792

Open
edmonday wants to merge 12 commits intomainfrom
edmondshen/nes-1364-media-screen-styling-changes
Open

refactor: extract wrapper for shared screen layout#8792
edmonday wants to merge 12 commits intomainfrom
edmondshen/nes-1364-media-screen-styling-changes

Conversation

@edmonday
Copy link
Contributor

@edmonday edmonday commented Mar 2, 2026

Summary by CodeRabbit

  • New Features

    • Introduced ScreenWrapper component for consistent, responsive screen layouts across the multi-step form.
    • Enhanced form-driven navigation flows in template customization screens.
  • Bug Fixes

    • Improved card preview overflow handling with responsive width adjustments.
  • UI/UX Improvements

    • Updated messaging labels: "Social Media" replaces "Final Details"; "Ready to share!" updated.
    • Simplified navigation by removing manual edit pathways.
    • Enhanced responsive design across all customization screens.

Create ScreenWrapper component with responsive title/subtitle and
migrate all 6 customization screens to use it. Fixes MediaScreen
using wrong Typography variants and broken color prop.

Refs: NES-1364

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@linear
Copy link

linear bot commented Mar 2, 2026

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 2, 2026

Walkthrough

This refactoring removes the handleScreenNavigation prop across multi-step form screens, introduces a new ScreenWrapper component for consistent layout handling, and updates overflow/spacing configuration for card previews. Changes span screen component signatures, test updates, and locale translations.

Changes

Cohort / File(s) Summary
ShareItem Enhancement
apps/journeys-admin/src/components/Editor/Toolbar/Items/ShareItem/ShareItem.tsx
Added buttonSx and buttonProps to ShareItemProps interface; spreads buttonProps into the Button component to enable external styling and prop configuration.
ScreenWrapper Component (New)
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/ScreenWrapper/*
Introduced new ScreenWrapper component with responsive title/subtitle handling, mobile variants, and footer slot. Includes comprehensive test coverage.
DoneScreen Refactoring
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/DoneScreen/*
Removed handleScreenNavigation prop; replaced custom Stack layout with ScreenWrapper; added footer button navigation to projects dashboard. Updated test expectation text casing.
LanguageScreen Refactoring
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/*
Removed handleScreenNavigation prop; restructured from static layout to Formik-driven form using ScreenWrapper; reorganized language/team selection UI with responsive CardsPreview region.
LinksScreen Refactoring
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/*, libs/journeys/ui/src/components/TemplateView/TemplatePreviewTabs/TemplateCardPreview/*
Removed handleScreenNavigation prop; wrapped with ScreenWrapper; moved Next button to footer. Exported EDGE_FADE_PX constant (value 40) from CardsPreview for external usage.
SocialScreen Refactoring
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/SocialScreen/*
Removed handleScreenNavigation prop; replaced Stack/Typography with ScreenWrapper; moved button to footer.
TextScreen Refactoring
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/TextScreen/*
Removed handleScreenNavigation prop; replaced inline layout with ScreenWrapper configuration; relocated navigation UI to footer.
MediaScreen Updates
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/MediaScreen/*
Wrapped with ScreenWrapper; moved header/button to ScreenWrapper props; updated test selectors from getByText to getAllByText()[0]. CardsSection now handles overflow with responsive width calculations.
MultiStepForm Core
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/MultiStepForm.tsx, MultiStepForm.spec.tsx
Removed handleScreenNavigation function and "Edit Manually" navigation pathway; simplified renderScreen signature to accept only handleNext; eliminated related test cases and mock setup.
TemplateCardPreview Configuration
libs/journeys/ui/src/components/TemplateView/TemplatePreviewTabs/TemplateCardPreview/*
Exported BreakpointSwiperOptions type and OVERFLOW_PX constant; added spacer slide rendering for media variant with responsive widths; updated config to use slidesOffsetBefore and responsive overflow visibility.
Locale Updates
libs/locales/en/apps-journeys-admin.json, libs/locales/en/journeys-ui.json
Updated "Ready to Share!" to "Ready to share!"; replaced "Final Details" with "Social Media"; added new keys for "Links" and "Select a team"; updated social media preview wording.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor: extract wrapper for shared screen layout' accurately summarizes the main change: extracting a ScreenWrapper component that provides shared layout functionality for multi-step form screens.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch edmondshen/nes-1364-media-screen-styling-changes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@edmonday edmonday self-assigned this Mar 2, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 2, 2026

Warnings
⚠️ ❗ Big PR (1380 changes)

(change count - 1380): Pull Request size seems relatively large. If Pull Request contains multiple changes, split each into separate PR will helps faster, easier review.

Generated by 🚫 dangerJS against f3b8f24

@nx-cloud
Copy link

nx-cloud bot commented Mar 2, 2026

View your CI Pipeline Execution ↗ for commit f3b8f24

Command Status Duration Result
nx run journeys-e2e:e2e ✅ Succeeded 21s View ↗
nx run journeys-admin-e2e:e2e ✅ Succeeded 31s View ↗
nx run watch-e2e:e2e ✅ Succeeded 19s View ↗
nx run resources-e2e:e2e ✅ Succeeded 15s View ↗
nx run watch-modern-e2e:e2e ✅ Succeeded 3s View ↗
nx run player-e2e:e2e ✅ Succeeded 3s View ↗
nx run videos-admin-e2e:e2e ✅ Succeeded 4s View ↗
nx run-many --target=vercel-alias --projects=re... ✅ Succeeded 2s View ↗
Additional runs (20) ✅ Succeeded ... View ↗

☁️ Nx Cloud last updated this comment at 2026-03-06 04:03:34 UTC

@github-actions github-actions bot requested a deployment to Preview - journeys-admin March 2, 2026 04:06 Pending
@github-actions github-actions bot temporarily deployed to Preview - journeys-admin March 2, 2026 04:10 Inactive
@github-actions
Copy link
Contributor

github-actions bot commented Mar 2, 2026

The latest updates on your projects.

Name Status Preview Updated (UTC)
journeys-admin ✅ Ready journeys-admin preview Fri Mar 6 17:00:05 NZDT 2026

@edmonday edmonday changed the title refactor: extract ScreenWrapper for shared screen layout refactor: extract wrapper for shared screen layout Mar 2, 2026
Eliminate the headerSx prop from DoneScreen, LanguageScreen, LinksScreen, and ScreenWrapper components to streamline the code. Update TextScreen to maintain consistent mobileSubtitle formatting.
@github-actions github-actions bot requested a deployment to Preview - journeys-admin March 2, 2026 22:21 Pending
@github-actions github-actions bot temporarily deployed to Preview - journeys-admin March 2, 2026 22:27 Inactive
@github-actions github-actions bot temporarily deployed to Preview - watch March 6, 2026 03:02 Inactive
@github-actions github-actions bot temporarily deployed to Preview - videos-admin March 6, 2026 03:02 Inactive
@github-actions github-actions bot temporarily deployed to Preview - resources March 6, 2026 03:02 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys-admin March 6, 2026 03:02 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys March 6, 2026 03:02 Inactive
@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

The latest updates on your projects.

Name Status Preview Updated (UTC)
journeys ✅ Ready journeys preview Fri Mar 6 16:58:53 NZDT 2026

@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

The latest updates on your projects.

Name Status Preview Updated (UTC)
videos-admin ✅ Ready videos-admin preview Fri Mar 6 16:59:12 NZDT 2026

@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

The latest updates on your projects.

Name Status Preview Updated (UTC)
watch ✅ Ready watch preview Fri Mar 6 16:59:41 NZDT 2026

@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

The latest updates on your projects.

Name Status Preview Updated (UTC)
resources ✅ Ready resources preview Fri Mar 6 17:00:20 NZDT 2026

@github-actions github-actions bot temporarily deployed to Preview - videos-admin March 6, 2026 03:14 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys March 6, 2026 03:14 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys-admin March 6, 2026 03:14 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys-admin March 6, 2026 03:25 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys March 6, 2026 03:25 Inactive
@github-actions github-actions bot temporarily deployed to Preview - resources March 6, 2026 03:25 Inactive
@edmonday edmonday requested a review from jianwei1 March 6, 2026 03:41
@edmonday edmonday marked this pull request as ready for review March 6, 2026 03:41
@github-actions github-actions bot temporarily deployed to Preview - watch March 6, 2026 03:42 Inactive
@github-actions github-actions bot temporarily deployed to Preview - resources March 6, 2026 03:42 Inactive
@github-actions github-actions bot temporarily deployed to Preview - videos-admin March 6, 2026 03:42 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys-admin March 6, 2026 03:42 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys March 6, 2026 03:42 Inactive
@github-actions github-actions bot temporarily deployed to Preview - watch March 6, 2026 03:51 Inactive
@github-actions github-actions bot temporarily deployed to Preview - videos-admin March 6, 2026 03:51 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys-admin March 6, 2026 03:51 Inactive
@github-actions github-actions bot temporarily deployed to Preview - resources March 6, 2026 03:51 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys March 6, 2026 03:51 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/MultiStepForm.tsx (1)

138-153: ⚠️ Potential issue | 🟠 Major

Keep a manual-editor escape hatch in the flow.

This block now renders only the stepper and active screen. Since DoneScreen only exposes Preview, Share, and Dashboard, the previous manual-editor route disappears entirely, which is a behavior regression rather than a layout refactor.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/MultiStepForm.tsx`
around lines 138 - 153, The change removed the manual-editor "escape hatch" by
wrapping the stepper and screen rendering in a feature-check conditional, which
hides the manual-editor route when
hasEditableText/hasCustomizableLinks/hasCustomizableMedia are false; update
MultiStepForm so the manual-editor escape hatch (the link/button that navigates
to the manual editor) is rendered even when those feature flags are false—either
render the escape hatch unconditionally alongside renderScreen(activeScreen,
handleNext) or explicitly render it when activeScreen corresponds to DoneScreen;
modify MultiStepForm to add that unconditional/DoneScreen-specific render
(referencing MultiStepForm, renderScreen, activeScreen, handleNext, screens,
DoneScreen and ProgressStepper) so the manual editor route is preserved.
🧹 Nitpick comments (6)
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/MultiStepForm.spec.tsx (1)

134-141: Trim the stale navigation button from the DoneScreen mock.

DoneScreen is prop-less now, so done-screen-go-to-language no longer represents a real interaction. Dropping that dead control will keep the test harness aligned with the simplified flow and avoid future specs depending on removed behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/MultiStepForm.spec.tsx`
around lines 134 - 141, The test mock for DoneScreen contains a stale navigation
button (data-testid "done-screen-go-to-language") that no longer matches the
component's prop-less API; remove the button element from the DoneScreen mock so
the JSX for DoneScreen only renders the container (data-testid "done-screen")
and its static content (e.g., the <h2>), ensuring tests no longer reference the
obsolete "done-screen-go-to-language" control.
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/ScreenWrapper/ScreenWrapper.tsx (1)

41-73: Render a single responsive heading/subtitle pair.

Right now both breakpoint variants stay in the DOM, which is already leaking into downstream specs—MediaScreen.spec.tsx had to switch to getAllByText(...)[0] to cope with the duplicates. A single responsive text node, or explicit data-testid/aria-hidden on the hidden copy, would keep the wrapper easier to test and less implementation-coupled.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/ScreenWrapper/ScreenWrapper.tsx`
around lines 41 - 73, The two heading/subtitle Typography nodes render
simultaneously (one hidden via CSS) causing duplicate DOM; in ScreenWrapper
replace the duplicated Typography blocks with a single responsive render (use
useMediaQuery or MUI Hidden) so only one text node exists: determine isSmUp =
useMediaQuery(theme.breakpoints.up('sm')) and render one Typography for the
title where variant = isSmUp ? 'h3' : 'h6' and content = isSmUp ? title :
(mobileTitle ?? title), and likewise render one Typography for the subtitle with
display and content chosen from subtitle/mobileSubtitle; alternatively, if you
must keep both nodes, add explicit data-testid or aria-hidden on the hidden copy
to avoid duplicate-test fallout.
apps/journeys-admin/src/components/Editor/Toolbar/Items/ShareItem/ShareItem.tsx (1)

48-57: Narrow the new buttonProps surface before exporting it.

Item spreads ButtonProps after its own props, so callers can override onClick, href, component, or variant and bypass handleShowMenu. Since the current use case is styling from DoneScreen, wire up buttonSx (currently unused) or whitelist non-behavioral button props instead of forwarding the full Button contract.

Also applies to: 70-78, 127-132

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/Editor/Toolbar/Items/ShareItem/ShareItem.tsx`
around lines 48 - 57, The ShareItem currently exposes a full buttonProps prop
which allows callers to override behavioral props (onClick, href, component,
variant) on the underlying Item and bypass handleShowMenu; instead narrow the
surface by either wiring up the unused buttonSx into the Item/Button for styling
(e.g., forward Sx only) or replace buttonProps with a whitelist of
non-behavioral props (e.g., sx, size, color, disableElevation) and drop
forwarding of onClick/href/component/variant; update the ShareItemProps type and
all places passing buttonProps (including DoneScreen and the call sites around
lines 70–78 and 127–132) to use the new narrowed prop name or buttonSx so
behavioral handlers remain controlled by handleShowMenu and handleKeepMounted.
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx (3)

235-246: Consider using a single Typography with responsive styling.

The pattern of two Typography components with opposite display breakpoints is repeated for both "Select a language" and "Select a team" labels. A single component with responsive variant or typography sx prop could reduce duplication.

Example consolidation
-                  <Typography
-                    variant="h6"
-                    display={{ xs: 'none', sm: 'block' }}
-                  >
-                    {t('Select a language')}
-                  </Typography>
-                  <Typography
-                    variant="body2"
-                    display={{ xs: 'block', sm: 'none' }}
-                  >
-                    {t('Select a language')}
-                  </Typography>
+                  <Typography
+                    sx={{
+                      typography: { xs: 'body2', sm: 'h6' }
+                    }}
+                  >
+                    {t('Select a language')}
+                  </Typography>

Same pattern applies to "Select a team" labels at lines 260-274.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx`
around lines 235 - 246, Replace the duplicated twin Typography components in
LanguageScreen that render t('Select a language') (and the similar pair for
t('Select a team')) with a single Typography that uses responsive props (variant
or sx.typography/display) to adjust presentation per breakpoint; locate the two
paired blocks that currently toggle display with display={{ xs:'none',
sm:'block' }} and display={{ xs:'block', sm:'none' }} and consolidate them into
one Typography that applies responsive styling so the text and visual weight
change correctly across breakpoints while removing the duplicate element.

28-28: Import ordering: Move Box import to group with other MUI imports.

The Box import is placed after local imports, breaking the convention of grouping external library imports before relative imports.

Suggested fix

Move the import to the MUI import group at the top:

 import FormControl from '@mui/material/FormControl'
 import Stack from '@mui/material/Stack'
 import Typography from '@mui/material/Typography'
+import Box from '@mui/material/Box'
 import { Form, Formik, FormikValues } from 'formik'

And remove line 28.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx`
at line 28, Move the stray "Box" import into the existing MUI import group at
the top of LanguageScreen.tsx so all Material-UI imports are grouped together
(e.g., alongside other `@mui/`* imports used by the LanguageScreen component);
remove the current import statement at line 28 so there is no duplicate or
out-of-order import for Box.

227-227: Avoid inline style attribute; use MUI's sx prop instead.

Per coding guidelines, avoid CSS/style tags. Formik's Form doesn't support sx, so wrap it in a Box or apply the width to an inner MUI component.

Suggested fix
-            <Form style={{ width: '100%' }}>
+            <Form>
               <FormControl
                 sx={{
-                  width: { xs: '100%' },
+                  width: '100%',
                   alignSelf: 'center'
                 }}
               >

Alternatively, wrap in a Box:

-            <Form style={{ width: '100%' }}>
+            <Box component={Form} sx={{ width: '100%' }}>
               ...
-            </Form>
+            </Box>

As per coding guidelines: "Always use MUI over HTML elements; avoid using CSS or tags."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx`
at line 227, The Formik Form in LanguageScreen currently uses an inline style
(Form style={{ width: '100%' }}); remove this inline style and instead wrap the
Form in a MUI Box (import Box from `@mui/material`) and apply the layout via Box's
sx (e.g., <Box sx={{ width: '100%' }}>), or move the width into an inner MUI
component (Box/Stack/Container) so Form remains plain Formik's Form without
style props; update imports in LanguageScreen accordingly and delete the inline
style attribute.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.tsx`:
- Around line 218-234: The phone validators currently allow a calling code alone
because valid-local returns true for empty strings; update both validators to
reference sibling fields (use a non-arrow function so you can access
this.parent) and enforce "both blank or both filled": in the `${link.id}__cc`
test (id `valid-cc`) allow empty only when the corresponding `${link.id}__local`
is also empty, otherwise validate the normalized calling code against
`countries`; in the `${link.id}__local` test (id `valid-local`) allow empty only
when the corresponding `${link.id}__cc` is also empty, but if `${link.id}__cc`
is populated require the local value to contain digits (e.g., the existing
/^[0-9\s\-()]+$/ check) and not be blank. Ensure you switch arrow tests to
function() to access this.parent and use `${link.id}__cc`/`${link.id}__local`
keys to read sibling values.

---

Outside diff comments:
In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/MultiStepForm.tsx`:
- Around line 138-153: The change removed the manual-editor "escape hatch" by
wrapping the stepper and screen rendering in a feature-check conditional, which
hides the manual-editor route when
hasEditableText/hasCustomizableLinks/hasCustomizableMedia are false; update
MultiStepForm so the manual-editor escape hatch (the link/button that navigates
to the manual editor) is rendered even when those feature flags are false—either
render the escape hatch unconditionally alongside renderScreen(activeScreen,
handleNext) or explicitly render it when activeScreen corresponds to DoneScreen;
modify MultiStepForm to add that unconditional/DoneScreen-specific render
(referencing MultiStepForm, renderScreen, activeScreen, handleNext, screens,
DoneScreen and ProgressStepper) so the manual editor route is preserved.

---

Nitpick comments:
In
`@apps/journeys-admin/src/components/Editor/Toolbar/Items/ShareItem/ShareItem.tsx`:
- Around line 48-57: The ShareItem currently exposes a full buttonProps prop
which allows callers to override behavioral props (onClick, href, component,
variant) on the underlying Item and bypass handleShowMenu; instead narrow the
surface by either wiring up the unused buttonSx into the Item/Button for styling
(e.g., forward Sx only) or replace buttonProps with a whitelist of
non-behavioral props (e.g., sx, size, color, disableElevation) and drop
forwarding of onClick/href/component/variant; update the ShareItemProps type and
all places passing buttonProps (including DoneScreen and the call sites around
lines 70–78 and 127–132) to use the new narrowed prop name or buttonSx so
behavioral handlers remain controlled by handleShowMenu and handleKeepMounted.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/MultiStepForm.spec.tsx`:
- Around line 134-141: The test mock for DoneScreen contains a stale navigation
button (data-testid "done-screen-go-to-language") that no longer matches the
component's prop-less API; remove the button element from the DoneScreen mock so
the JSX for DoneScreen only renders the container (data-testid "done-screen")
and its static content (e.g., the <h2>), ensuring tests no longer reference the
obsolete "done-screen-go-to-language" control.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx`:
- Around line 235-246: Replace the duplicated twin Typography components in
LanguageScreen that render t('Select a language') (and the similar pair for
t('Select a team')) with a single Typography that uses responsive props (variant
or sx.typography/display) to adjust presentation per breakpoint; locate the two
paired blocks that currently toggle display with display={{ xs:'none',
sm:'block' }} and display={{ xs:'block', sm:'none' }} and consolidate them into
one Typography that applies responsive styling so the text and visual weight
change correctly across breakpoints while removing the duplicate element.
- Line 28: Move the stray "Box" import into the existing MUI import group at the
top of LanguageScreen.tsx so all Material-UI imports are grouped together (e.g.,
alongside other `@mui/`* imports used by the LanguageScreen component); remove the
current import statement at line 28 so there is no duplicate or out-of-order
import for Box.
- Line 227: The Formik Form in LanguageScreen currently uses an inline style
(Form style={{ width: '100%' }}); remove this inline style and instead wrap the
Form in a MUI Box (import Box from `@mui/material`) and apply the layout via Box's
sx (e.g., <Box sx={{ width: '100%' }}>), or move the width into an inner MUI
component (Box/Stack/Container) so Form remains plain Formik's Form without
style props; update imports in LanguageScreen accordingly and delete the inline
style attribute.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/ScreenWrapper/ScreenWrapper.tsx`:
- Around line 41-73: The two heading/subtitle Typography nodes render
simultaneously (one hidden via CSS) causing duplicate DOM; in ScreenWrapper
replace the duplicated Typography blocks with a single responsive render (use
useMediaQuery or MUI Hidden) so only one text node exists: determine isSmUp =
useMediaQuery(theme.breakpoints.up('sm')) and render one Typography for the
title where variant = isSmUp ? 'h3' : 'h6' and content = isSmUp ? title :
(mobileTitle ?? title), and likewise render one Typography for the subtitle with
display and content chosen from subtitle/mobileSubtitle; alternatively, if you
must keep both nodes, add explicit data-testid or aria-hidden on the hidden copy
to avoid duplicate-test fallout.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 62fdfb46-bd49-4c84-9a95-075e9c07b3f9

📥 Commits

Reviewing files that changed from the base of the PR and between 0147f86 and 84c9135.

📒 Files selected for processing (22)
  • apps/journeys-admin/src/components/Editor/Toolbar/Items/ShareItem/ShareItem.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/MultiStepForm.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/MultiStepForm.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/DoneScreen/DoneScreen.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/DoneScreen/DoneScreen.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/CardsPreview/CardsPreview.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/CardsPreview/index.ts
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/MediaScreen/MediaScreen.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/MediaScreen/MediaScreen.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/MediaScreen/Sections/CardsSection/CardsSection.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/ScreenWrapper/ScreenWrapper.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/ScreenWrapper/ScreenWrapper.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/ScreenWrapper/index.ts
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/SocialScreen/SocialScreen.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/TextScreen/TextScreen.tsx
  • libs/journeys/ui/src/components/TemplateView/TemplatePreviewTabs/TemplateCardPreview/TemplateCardPreview.tsx
  • libs/journeys/ui/src/components/TemplateView/TemplatePreviewTabs/TemplateCardPreview/index.ts
  • libs/journeys/ui/src/components/TemplateView/TemplatePreviewTabs/TemplateCardPreview/templateCardPreviewConfig.ts
💤 Files with no reviewable changes (2)
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.spec.tsx

@github-actions github-actions bot temporarily deployed to Preview - videos-admin March 6, 2026 03:56 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys-admin March 6, 2026 03:56 Inactive
@github-actions github-actions bot temporarily deployed to Preview - player March 6, 2026 03:56 Inactive
@github-actions github-actions bot temporarily deployed to Preview - watch-modern March 6, 2026 03:56 Inactive
@github-actions github-actions bot temporarily deployed to Preview - journeys March 6, 2026 03:56 Inactive
@github-actions github-actions bot temporarily deployed to Preview - watch March 6, 2026 03:56 Inactive
@github-actions github-actions bot temporarily deployed to Preview - resources March 6, 2026 03:56 Inactive
@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

The latest updates on your projects.

Name Status Preview Updated (UTC)
watch-modern ✅ Ready watch-modern preview Fri Mar 6 16:58:19 NZDT 2026

@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

The latest updates on your projects.

Name Status Preview Updated (UTC)
player ✅ Ready player preview Fri Mar 6 16:58:29 NZDT 2026

@edmonday edmonday requested a review from jaco-brink March 6, 2026 04:00
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/TextScreen/TextScreen.spec.tsx (1)

109-133: ⚠️ Potential issue | 🟡 Minor

Assert handleNext in the save path.

Lines 129-130 say navigation should happen after the mutation, but the test only checks that the mutation mock ran. Since handleNext is now the only navigation callback on TextScreen, a regression there would still pass this spec.

🧪 Suggested assertion
     await waitFor(() =>
-      expect(journeyCustomizationFieldUpdate.result).toHaveBeenCalled()
+      expect(journeyCustomizationFieldUpdate.result).toHaveBeenCalled()
     )
+    expect(handleNext).toHaveBeenCalled()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/TextScreen/TextScreen.spec.tsx`
around lines 109 - 133, The test currently only asserts the mutation mock
(journeyCustomizationFieldUpdate) ran but not that the component navigated;
update the spec in TextScreen.spec.tsx to also assert handleNext was invoked
after the mutation resolves by adding an await waitFor(() =>
expect(handleNext).toHaveBeenCalled()) (or equivalent) after the existing
waitFor for journeyCustomizationFieldUpdate; ensure you reference the existing
TextScreen render with the mocked provider and the handleNext jest.fn so the
assertion targets that function.
♻️ Duplicate comments (1)
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.tsx (1)

217-233: ⚠️ Potential issue | 🟠 Major

Phone validation still allows partial submissions and blocks clears.

Line 221 rejects a blank calling code, but Lines 229-232 treat a blank local number as valid. That still lets users save just the country code (+1, +64, etc.), and it also makes “clear both fields” impossible even though handleFormSubmit normalizes both blank parts to ''. These two inputs need paired validation so they are either both empty or both populated.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.tsx`
around lines 217 - 233, The two validators for acc[`${link.id}__cc`] and
acc[`${link.id}__local`] must be paired so both fields are either empty or both
populated: update the string().test for each field to consult the sibling value
(via the validation context/parent) using the same keys `${link.id}__cc` and
`${link.id}__local` and enforce: if both are blank -> valid; if one is blank and
the other populated -> invalid; if both populated -> validate the calling code
format (normalize with leading '+') and the local number regex. Ensure the tests
mirror each other so clearing both passes and partial submissions are rejected.
🧹 Nitpick comments (2)
apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx (2)

228-234: Simplify single-breakpoint responsive values.

The responsive objects { xs: '100%' } and { xs: 0 } can be simplified since no other breakpoints override them.

♻️ Suggested simplification
               <FormControl
                 sx={{
-                  width: { xs: '100%' },
+                  width: '100%',
                   alignSelf: 'center'
                 }}
               >
-                <Stack gap={2} sx={{ px: { xs: 0 } }}>
+                <Stack gap={2}>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx`
around lines 228 - 234, The sx props on FormControl and Stack use
single-breakpoint objects that can be simplified: in the FormControl component
replace width: { xs: '100%' } with width: '100%', and in the Stack replace px: {
xs: 0 } with px: 0; update the JSX in LanguageScreen where the FormControl and
Stack components are defined to use these simplified values to remove
unnecessary responsive objects.

146-177: Consider adding an early return or explicit handling for the unsigned-in branch.

When shouldSkipDuplicate returns false and !isSignedIn, the function sets loading but performs no action. While the button is disabled for unsigned users (line 199), adding an explicit early return improves clarity and guards against future changes that might enable the button.

♻️ Suggested improvement
   async function handleSubmit(values: FormikValues) {
     if (journey == null) return
+    if (!isSignedIn) return

     const { teamSelect: teamId } = values
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx`
around lines 146 - 177, handleSubmit currently sets loading then does nothing
when shouldSkipDuplicate is false and isSignedIn is false; add an explicit
branch after the shouldSkipDuplicate check to handle the unsigned case (e.g. if
(!isSignedIn) { setLoading(false); return; }) so the function returns early and
clears the loading state instead of leaving the spinner active—update the logic
in handleSubmit, referencing shouldSkipDuplicate, isSignedIn, setLoading and
handleNext.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.tsx`:
- Around line 240-243: The Formik props include an unsupported validateOnSubmit
usage in the Formik wrapper inside LinksScreen.tsx; remove
validateOnSubmit={false} and instead set validateOnChange={false} and
validateOnBlur={false} on the same Formik component so validation is disabled on
change/blur but still runs on submit (leave onSubmit={handleFormSubmit} and
validateOnMount as-is).

---

Outside diff comments:
In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/TextScreen/TextScreen.spec.tsx`:
- Around line 109-133: The test currently only asserts the mutation mock
(journeyCustomizationFieldUpdate) ran but not that the component navigated;
update the spec in TextScreen.spec.tsx to also assert handleNext was invoked
after the mutation resolves by adding an await waitFor(() =>
expect(handleNext).toHaveBeenCalled()) (or equivalent) after the existing
waitFor for journeyCustomizationFieldUpdate; ensure you reference the existing
TextScreen render with the mocked provider and the handleNext jest.fn so the
assertion targets that function.

---

Duplicate comments:
In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.tsx`:
- Around line 217-233: The two validators for acc[`${link.id}__cc`] and
acc[`${link.id}__local`] must be paired so both fields are either empty or both
populated: update the string().test for each field to consult the sibling value
(via the validation context/parent) using the same keys `${link.id}__cc` and
`${link.id}__local` and enforce: if both are blank -> valid; if one is blank and
the other populated -> invalid; if both populated -> validate the calling code
format (normalize with leading '+') and the local number regex. Ensure the tests
mirror each other so clearing both passes and partial submissions are rejected.

---

Nitpick comments:
In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx`:
- Around line 228-234: The sx props on FormControl and Stack use
single-breakpoint objects that can be simplified: in the FormControl component
replace width: { xs: '100%' } with width: '100%', and in the Stack replace px: {
xs: 0 } with px: 0; update the JSX in LanguageScreen where the FormControl and
Stack components are defined to use these simplified values to remove
unnecessary responsive objects.
- Around line 146-177: handleSubmit currently sets loading then does nothing
when shouldSkipDuplicate is false and isSignedIn is false; add an explicit
branch after the shouldSkipDuplicate check to handle the unsigned case (e.g. if
(!isSignedIn) { setLoading(false); return; }) so the function returns early and
clears the loading state instead of leaving the spinner active—update the logic
in handleSubmit, referencing shouldSkipDuplicate, isSignedIn, setLoading and
handleNext.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d9949fc5-bf2d-4169-9e20-00c2fca0cd56

📥 Commits

Reviewing files that changed from the base of the PR and between 84c9135 and f3b8f24.

📒 Files selected for processing (16)
  • apps/journeys-admin/src/components/Editor/Toolbar/Items/ShareItem/ShareItem.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/MultiStepForm.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/MultiStepForm.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/MediaScreen/MediaScreen.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/MediaScreen/Sections/CardsSection/CardsSection.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/SocialScreen/SocialScreen.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/SocialScreen/SocialScreen.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/TextScreen/TextScreen.spec.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/TextScreen/TextScreen.tsx
  • libs/journeys/ui/src/components/TemplateView/TemplatePreviewTabs/TemplateCardPreview/TemplateCardPreview.tsx
  • libs/locales/en/apps-journeys-admin.json
  • libs/locales/en/journeys-ui.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/MediaScreen/Sections/CardsSection/CardsSection.tsx
  • apps/journeys-admin/src/components/Editor/Toolbar/Items/ShareItem/ShareItem.tsx
  • libs/journeys/ui/src/components/TemplateView/TemplatePreviewTabs/TemplateCardPreview/TemplateCardPreview.tsx
  • apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.spec.tsx

Comment on lines +240 to +243
validateOnSubmit={false}
onSubmit={handleFormSubmit}
validateOnMount
>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.tsx | sed -n '235,250p'

Repository: JesusFilm/core

Length of output: 652


🏁 Script executed:

find . -name "package.json" -type f | head -5 | xargs grep -l "formik" 2>/dev/null | head -3

Repository: JesusFilm/core

Length of output: 72


🏁 Script executed:

cat package.json | grep -A 2 '"formik"'

Repository: JesusFilm/core

Length of output: 132


🏁 Script executed:

find node_modules/formik -name "*.d.ts" -type f | head -5

Repository: JesusFilm/core

Length of output: 112


🏁 Script executed:

grep -r "validateOnSubmit" node_modules/formik --include="*.d.ts" --include="*.js" 2>/dev/null | head -20

Repository: JesusFilm/core

Length of output: 40


🏁 Script executed:

web_search
Formik 2.4.4 validateOnSubmit prop documentation

Repository: JesusFilm/core

Length of output: 153


🌐 Web query:

Formik 2.4.4 validateOnSubmit prop API documentation

💡 Result:

Formik 2.4.4 does not have a validateOnSubmit prop. The form-level validation timing knobs in the FormikSharedConfig/FormikConfig API are:

  • validateOnChange?: boolean
  • validateOnBlur?: boolean
  • validateOnMount?: boolean
    [1][2]

A search of the Formik API/type docs shows no validateOnSubmit entry (i.e., it’s not a supported config prop) [3]. If your goal is “validate only when the user submits”, the typical approach is:

<Formik validateOnChange={false} validateOnBlur={false} ... />

(Submission-time validation still occurs when you call/trigger submitForm/handleSubmit.) [1][2]

Sources: [1] [2] [3]


🏁 Script executed:

grep -r "validateOnSubmit" . --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" 2>/dev/null | head -20

Repository: JesusFilm/core

Length of output: 197


Remove unsupported validateOnSubmit config.

validateOnSubmit is not a documented Formik prop in version 2.4.4. Formik's <Formik /> component only supports validateOnChange, validateOnBlur, and validateOnMount. The validateOnSubmit={false} at line 240 will be ignored. To disable validation on change/blur while keeping submit-time validation, use validateOnChange={false} and validateOnBlur={false} instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LinksScreen/LinksScreen.tsx`
around lines 240 - 243, The Formik props include an unsupported validateOnSubmit
usage in the Formik wrapper inside LinksScreen.tsx; remove
validateOnSubmit={false} and instead set validateOnChange={false} and
validateOnBlur={false} on the same Formik component so validation is disabled on
change/blur but still runs on submit (leave onSubmit={handleFormSubmit} and
validateOnMount as-is).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant