Conversation
📝 WalkthroughWalkthroughAdds localized strings across multiple languages; introduces case-study types, sample data, and UI (CaseStudyCard, StackedPreviewImage); replaces legacy get-in-touch form with a new ContactSection (ContactIntro + ContactForm); adds SectionHeading; updates service templates and imports accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant U as User (Browser)
participant CF as ContactForm (Client)
participant A as Analytics
participant API as submitGetInTouchForm (Client API)
participant S as Server (API)
U->>CF: Fill fields & submit
CF->>A: fire analytics event (form_submit_attempt) rgba(0,128,0,0.5)
CF->>API: POST form payload
API->>S: process request (validate, persist, notify) rgba(0,0,255,0.5)
S-->>API: 200 OK / error
API-->>CF: response (success/failure)
CF->>A: fire analytics event (form_submit_result) rgba(128,0,128,0.5)
CF-->>U: show success or error state
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
903c223 to
324afc4
Compare
🚀 Preview EnvironmentYour preview environment is ready!
Details
ℹ️ Preview Environment InfoIsolation:
Limitations:
Cleanup:
|
6c01981 to
2b8d0d1
Compare
2b8d0d1 to
cff3e05
Compare
69f3684 to
c787d1a
Compare
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Fix all issues with AI agents
In
`@front_end/src/app/`(main)/services/components/case_studies/case_study_card.tsx:
- Around line 50-61: The two <hr> separators render even when
card.aboutInitiative is falsy, producing orphaned or duplicate rules; fix by
conditionally rendering the separator(s) together with the aboutInitiative
block: move or wrap the first <hr> inside the conditional (the block referencing
card.aboutInitiative) or render the trailing <hr> only when card.aboutInitiative
exists so that an <hr> appears only when the aboutInitiative section is present;
update the JSX in case_study_card.tsx around the card.aboutInitiative
conditional accordingly.
In `@front_end/src/app/`(main)/services/components/case_studies/constants.tsx:
- Around line 22-56: The aboutInitiative field in the case study object with id
"nih-nsf-pro-forecasting-2" currently contains placeholder copy; replace that
string with the final initiative blurb or remove the aboutInitiative property
from the object until final copy is ready to avoid shipping placeholder text
(locate the object entry where id === "nih-nsf-pro-forecasting-2" in
constants.tsx and update the aboutInitiative key accordingly).
In
`@front_end/src/app/`(main)/services/components/contact_section/contact_form.tsx:
- Around line 82-141: The default service value set in ContactForm's useForm
(defaultValues.service) can be outside the passed serviceOptions list; update
the initialization so defaultValues.service is derived from serviceOptions (or
validate preselectedService is included) — e.g., if preselectedService is
provided use it only if serviceOptions.some(o => o.value ===
preselectedService), otherwise fall back to the first serviceOptions[0].value
(or ServiceType.GENERAL_INQUIRY only if present in serviceOptions); update the
logic around defaultValues in useForm and ensure selectOptions generation still
maps serviceOptions so the rendered select always contains the form's initial
value.
- Around line 55-58: Update the contactFormSchema to trim input and enforce a
proper email format: for the email field in contactFormSchema, chain
.trim().min(1, { message: "Email is required" }).email({ message: "Invalid email
address" }) so whitespace is normalized and invalid formats are rejected;
likewise apply .trim().min(1, { message: "Name is required" }) to the name field
and use .trim().optional() for organization to keep consistent normalization
across the schema.
In
`@front_end/src/app/`(main)/services/components/contact_section/contact_intro.tsx:
- Around line 45-50: The anchor in the ContactIntro component rendering (the <a>
created with key={p.alt}, href={p.href}, target="_blank") currently uses
rel="noreferrer" only; update that rel attribute to include "noopener" (e.g.,
"noreferrer noopener") to prevent reverse-tabnabbing when opening external links
in a new tab. Locate the anchor element in contact_intro.tsx where key={p.alt}
and target="_blank" are used and modify the rel string accordingly.
In `@front_end/src/components/ui/stacked-preview-image.tsx`:
- Around line 6-112: The Image elements in StackedPreviewImage accept src typed
as ImageProps["src"] (allowing string URLs) but only set height, which breaks
Next.js unless images are static imports; either restrict the Props to static
imports by changing src: ImageProps["src"] to StaticImageData and layerSrcs
tuple to StaticImageData, or keep URL support and add explicit width handling to
each Image (back/mid/front Image instances) — e.g., set width={200} to match
height or switch those Image usages to fill with appropriate parent sizing;
update the Props/type and the three Image components (backSrc, midSrc, frontSrc)
accordingly.
🧹 Nitpick comments (8)
front_end/src/app/(main)/services/components/contact_section/contact_section.tsx (1)
6-11: Prop type design creates potential confusion with dual input paths.The
Propstype allows the same properties (pageLabel,preselectedService,serviceOptions) to be passed both at the top level and viaformProps. While the merging logic on lines 39-43 handles precedence correctly (preferringformProps), this dual-path API can be confusing for consumers.Consider either:
- Documenting the precedence clearly with JSDoc
- Simplifying to only accept these props via
formPropsfront_end/src/app/(main)/services/components/case_studies/constants.tsx (1)
25-61: Consider locale-friendly date handling for report metadata.
publishedAtLabelis hard-coded in English, so non‑EN locales will still show English dates. Consider storing an ISO date and formatting it in the UI with the active locale (e.g., viaIntl.DateTimeFormator next‑intl utilities).front_end/src/app/(main)/services/components/case_studies/case_study_card.tsx (3)
42-46: Consider using a more stable key for list items.Using
${item}-${idx}as a key can be problematic whenitemis aReact.ReactNode(which could be an object). This will result in[object Object]-0keys. Ifitemis always a string, this is fine, but the type definition allowsReactNode.Suggested improvement
If the bullets are guaranteed to be unique strings, use just the item. Otherwise, consider using only the index or restructuring the data to include explicit keys:
<ul className="m-0 list-disc pl-5"> {card.body.bullets.map((item, idx) => ( - <li key={`${item}-${idx}`}>{item}</li> + <li key={idx}>{item}</li> ))} </ul>
71-78: Missingwidthprop on Image component may cause layout shift.The
Imagecomponent hasheight={14}but nowidthprop. Whilew-autois applied via className, Next.js Image component benefits from explicit dimensions to prevent layout shift. Consider adding awidthprop or using thefilllayout.Suggested fix
<Image key={logo.src + idx} src={logo.src} alt={logo.alt} height={14} + width={0} className="h-[14px] w-auto" unoptimized />Using
width={0}withw-autoclass allows the image to size naturally while satisfying the prop requirement.
102-108: Missingwidthprop on mobile report preview Image.Similar to the partner logos, this Image has
height={50}but nowidthprop.Suggested fix
<Image src={card.report.previewImageSrc} alt={card.report.previewImageAlt ?? t("reportPreviewAlt")} height={50} + width={0} className="h-[50px] w-auto rounded object-cover sm:hidden" unoptimized />front_end/src/app/(main)/services/components/case_studies/types.ts (1)
3-7:hrefproperty defined but not used in CaseStudyCard.The
CaseStudyPartnerLogotype includes an optionalhrefproperty, but theCaseStudyCardcomponent renders partner logos as plain images without wrapping them in links. Either remove the unused property or implement the linking functionality.If the
hrefis intended for future use, consider adding a TODO comment. Otherwise, if partner logos should be clickable:// In case_study_card.tsx, wrap the Image in a link when href is present: {logo.href ? ( <a href={logo.href} target="_blank" rel="noopener noreferrer"> <Image ... /> </a> ) : ( <Image ... /> )}front_end/src/app/(main)/services/components/templates/services_page_template.tsx (2)
166-209: EmptysecondPartrenders an empty paragraph element.When
proForecasters.secondPartis an empty string (as shown in the config snippet), an empty<p>element is still rendered with margins (mt-5), potentially causing unintended spacing.Suggested fix
<p className="m-0 mt-5 text-center text-sm font-normal text-blue-500 sm:text-start sm:text-lg sm:font-medium"> {proForecasters.firstPart} </p> - <p className="m-0 mt-5 text-center text-sm font-normal text-blue-500 sm:text-start sm:text-lg sm:font-medium"> - {proForecasters.secondPart} - </p> + {proForecasters.secondPart && ( + <p className="m-0 mt-5 text-center text-sm font-normal text-blue-500 sm:text-start sm:text-lg sm:font-medium"> + {proForecasters.secondPart} + </p> + )}
224-232: Duplicate WorkshopImage rendering for responsive display.The same
WorkshopImageis rendered twice—once for mobile/tablet (lines 226-231, hidden onlg:) and once for desktop (lines 244-249, shown only onlg:). While this achieves the layout goal, consider using CSS-only responsive approaches or extracting to a shared element to avoid duplication.This is acceptable for achieving different layout positions, but if the image markup grows more complex, consider extracting to a variable:
const workshopImageElement = ( <Image src={WorkshopImage} alt="Workshop illustration" unoptimized className="h-auto w-full max-w-[420px]" /> ); // Then use {workshopImageElement} in both placesAlso applies to: 243-250
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
front_end/src/app/(main)/services/assets/aei.svgis excluded by!**/*.svgfront_end/src/app/(main)/services/assets/coefficient-giving.svgis excluded by!**/*.svgfront_end/src/app/(main)/services/assets/forbes.svgis excluded by!**/*.svgfront_end/src/app/(main)/services/assets/nih-nsf-report-preview.pngis excluded by!**/*.pngfront_end/src/app/(main)/services/assets/workshop.svgis excluded by!**/*.svg
📒 Files selected for processing (24)
front_end/messages/cs.jsonfront_end/messages/en.jsonfront_end/messages/es.jsonfront_end/messages/pt.jsonfront_end/messages/zh-TW.jsonfront_end/messages/zh.jsonfront_end/src/app/(main)/services/(pages)/financial-services/pro-forecasters/config.tsxfront_end/src/app/(main)/services/assets/desktop.webpfront_end/src/app/(main)/services/assets/phone.webpfront_end/src/app/(main)/services/components/case_studies/case_study_card.tsxfront_end/src/app/(main)/services/components/case_studies/constants.tsxfront_end/src/app/(main)/services/components/case_studies/types.tsfront_end/src/app/(main)/services/components/contact_section/contact_form.tsxfront_end/src/app/(main)/services/components/contact_section/contact_intro.tsxfront_end/src/app/(main)/services/components/contact_section/contact_section.tsxfront_end/src/app/(main)/services/components/get_in_touch_checkbox.tsxfront_end/src/app/(main)/services/components/get_in_touch_form.tsxfront_end/src/app/(main)/services/components/section_heading.tsxfront_end/src/app/(main)/services/components/templates/private_instances_page_template.tsxfront_end/src/app/(main)/services/components/templates/pro_forecasters_page_template.tsxfront_end/src/app/(main)/services/components/templates/services_page_template.tsxfront_end/src/app/(main)/services/components/templates/tournaments_page_template.tsxfront_end/src/app/(main)/services/page.tsxfront_end/src/components/ui/stacked-preview-image.tsx
💤 Files with no reviewable changes (2)
- front_end/src/app/(main)/services/components/get_in_touch_form.tsx
- front_end/src/app/(main)/services/components/get_in_touch_checkbox.tsx
🧰 Additional context used
🧬 Code graph analysis (5)
front_end/src/app/(main)/services/components/case_studies/constants.tsx (1)
front_end/src/app/(main)/services/components/case_studies/types.ts (1)
TCaseStudyCard(17-35)
front_end/src/app/(main)/services/components/case_studies/case_study_card.tsx (2)
front_end/src/app/(main)/services/components/case_studies/types.ts (1)
TCaseStudyCard(17-35)front_end/src/components/ui/stacked-preview-image.tsx (1)
StackedPreviewImage(24-116)
front_end/src/app/(main)/services/components/templates/services_page_template.tsx (1)
front_end/src/app/(main)/services/(pages)/climate/config.ts (4)
solutions(13-17)tournaments(19-23)privateInstances(25-29)proForecasters(31-36)
front_end/src/app/(main)/services/components/contact_section/contact_form.tsx (6)
front_end/src/constants/services.ts (1)
ServiceType(1-14)front_end/src/services/api/misc/misc.shared.ts (1)
ContactForm(4-8)front_end/src/utils/analytics.ts (1)
sendAnalyticsEvent(11-17)front_end/src/utils/core/errors.ts (1)
logError(117-151)front_end/src/app/(main)/services/(pages)/financial-services/pro-forecasters/config.tsx (1)
serviceOptions(56-85)front_end/src/components/ui/form_field.tsx (3)
Input(111-128)FormErrorMessage(82-109)Textarea(167-181)
front_end/src/app/(main)/services/components/templates/tournaments_page_template.tsx (2)
front_end/src/app/(main)/services/(pages)/financial-services/config.ts (1)
tournaments(19-23)front_end/src/constants/services.ts (1)
ServiceType(1-14)
🔇 Additional comments (15)
front_end/src/app/(main)/services/components/contact_section/contact_section.tsx (1)
22-47: LGTM!The component structure is clean with proper composition of
ContactIntroandContactForm. The layout uses appropriate responsive classes and the prop delegation logic correctly handles the merge precedence.front_end/src/app/(main)/services/components/templates/tournaments_page_template.tsx (1)
43-109: LGTM!The migration from
GetInTouchFormtoContactSectionis well-executed. The fragment wrapper appropriately allowsContactSectionto be a sibling ofmainwhile maintaining semantic structure. ThepreselectedServicecorrectly usesServiceType.RUNNING_TOURNAMENTand the step rendering with conditional arrows is properly implemented.front_end/src/app/(main)/services/components/templates/private_instances_page_template.tsx (1)
97-103: LGTM!The
ContactSectionintegration follows the same pattern as the tournaments template, with appropriatepageLabelandpreselectedServicevalues for private instances. The component structure is clean and consistent.front_end/messages/es.json (1)
1892-1904: LGTM!The new Spanish localization keys are properly formatted with correct ICU message syntax for plurals and interpolation. The translations align with the UI components introduced in this PR (case studies, workshops, contact form).
front_end/messages/zh-TW.json (1)
1889-1901: LGTM!The Traditional Chinese localization keys are properly added with correct ICU message syntax. The translations are appropriate for Taiwan Chinese conventions and align with the parallel additions in other locale files.
front_end/messages/cs.json (1)
1892-1904: Czech localization additions look consistent.
Thanks for mirroring the new services/case study/workshop strings across locales.front_end/messages/en.json (1)
1885-1897: English localization additions look good.
The new strings align with the services page updates.front_end/src/app/(main)/services/page.tsx (1)
80-89: Wiring for workshop and case studies looks good.
Props align cleanly with the new template sections.front_end/src/app/(main)/services/components/templates/pro_forecasters_page_template.tsx (1)
46-114: Contact section integration and layout updates look solid.
The new ContactSection flow and the revised content layout read cleanly.front_end/src/app/(main)/services/components/case_studies/case_study_card.tsx (1)
134-139: LGTM!The Button component correctly handles the CTA with proper fallback for the label using translations. The styling is comprehensive with appropriate dark mode support.
front_end/src/app/(main)/services/components/case_studies/types.ts (1)
9-35: LGTM!The type definitions are well-structured with appropriate use of optional fields and
React.ReactNodefor flexible content. The use ofStaticImageDatafrom Next.js forpreviewImageSrcis correct for supporting both static imports and URL strings.front_end/src/app/(main)/services/components/templates/services_page_template.tsx (4)
10-21: LGTM!The imports are well-organized, bringing in the new components and assets needed for the enhanced template. The SVG import with
?urlsuffix is the correct pattern for Next.js.
36-47: LGTM!The new optional props for
caseStudiesandworkshopare well-typed and follow the existing patterns in the Props type. Making them optional ensures backward compatibility with existing usages.
255-268: LGTM!The case studies section is well-implemented with proper conditional rendering, section heading, and grid layout. Using
card.idas the key is the correct approach for stable list rendering.
113-276: Overall template structure is well-organized.The refactored template properly uses a React fragment to wrap the main content and contact section. The conditional rendering for optional sections (
workshop,caseStudies) is correctly implemented. The responsive design patterns are consistent throughout.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
front_end/src/app/(main)/services/components/case_studies/case_study_card.tsx
Show resolved
Hide resolved
| aboutInitiative: | ||
| "A short paragraph about the initiative explaining what it was all about and why this report was created in the first place.", | ||
| report: { | ||
| previewImageSrc: NihNsfPreview, | ||
| previewImageAlt: "NIH/NSF report preview", | ||
| fileName: "research-agencies-report-2", | ||
| pageCount: 8, | ||
| publishedAtLabel: "Sep 16, 2025", | ||
| }, | ||
| cta: { | ||
| label: "Read full report", | ||
| href: "/notebooks/39977/report-pro-forecasters-expect-steady-nih-and-nsf-funding/", | ||
| }, | ||
| }, | ||
| { | ||
| id: "nih-nsf-pro-forecasting-2", | ||
| title: "Pro Forecasters Expect Steady NIH and NSF Funding", | ||
| body: { | ||
| intro: "Among the key findings:", | ||
| bullets: [ | ||
| "Both NIH and NSF are expected to avoid deep cuts, with appropriations broadly stable.", | ||
| "NSF faces greater near-term risk in FY2026 due to a $2B gap between House and Senate proposals, but outcomes are expected to align more closely with the Senate’s status quo position.", | ||
| ], | ||
| }, | ||
| partners: { | ||
| label: "In partnership with", | ||
| logos: [ | ||
| { src: AEILogo, alt: "AEI" }, | ||
| { src: CoefficientGivingLogo, alt: "Coefficient Giving" }, | ||
| { src: ForbesLogo, alt: "Forbes" }, | ||
| ], | ||
| }, | ||
| aboutInitiative: | ||
| "A short paragraph about the initiative explaining what it was all about and why this report was created in the first place.", | ||
| report: { |
There was a problem hiding this comment.
Replace placeholder initiative copy before release.
aboutInitiative still uses placeholder text, which will surface to users. Either supply final copy or omit the field until it’s ready.
🛠️ Suggested interim fix (omit placeholder copy)
- aboutInitiative:
- "A short paragraph about the initiative explaining what it was all about and why this report was created in the first place.",- aboutInitiative:
- "A short paragraph about the initiative explaining what it was all about and why this report was created in the first place.",🤖 Prompt for AI Agents
In `@front_end/src/app/`(main)/services/components/case_studies/constants.tsx
around lines 22 - 56, The aboutInitiative field in the case study object with id
"nih-nsf-pro-forecasting-2" currently contains placeholder copy; replace that
string with the final initiative blurb or remove the aboutInitiative property
from the object until final copy is ready to avoid shipping placeholder text
(locate the object entry where id === "nih-nsf-pro-forecasting-2" in
constants.tsx and update the aboutInitiative key accordingly).
front_end/src/app/(main)/services/components/contact_section/contact_form.tsx
Show resolved
Hide resolved
front_end/src/app/(main)/services/components/contact_section/contact_form.tsx
Outdated
Show resolved
Hide resolved
front_end/src/app/(main)/services/components/contact_section/contact_intro.tsx
Show resolved
Hide resolved
0c5e13f to
ef0de20
Compare
ef0de20 to
38ad515
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@front_end/messages/cs.json`:
- Line 1898: The Czech plural key "pagesWithCount" needs a 'few' plural category
added so 2–4 use the correct form; update the ICU plural string for
"pagesWithCount" to include few {# stránky} alongside the existing one {#
stránka} and other {# stránek} (i.e., one {# stránka} few {# stránky} other {#
stránek}) so Czech grammar is correct for counts 2–4.
In
`@front_end/src/app/`(main)/services/components/case_studies/case_study_card.tsx:
- Around line 71-78: The partner logo Image in case_study_card.tsx is missing an
explicit width which causes layout shift; update the Image element (the instance
in the CaseStudyCard component) to provide a width prop (e.g., width={80})
matching the rendered height or alternatively switch to using fill with a sized
container around the Image so both dimensions are specified and prevent layout
shifts.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
front_end/src/app/(main)/services/assets/aei.svgis excluded by!**/*.svgfront_end/src/app/(main)/services/assets/coefficient-giving.svgis excluded by!**/*.svgfront_end/src/app/(main)/services/assets/forbes.svgis excluded by!**/*.svgfront_end/src/app/(main)/services/assets/nih-nsf-report-preview.pngis excluded by!**/*.pngfront_end/src/app/(main)/services/assets/workshop.svgis excluded by!**/*.svg
📒 Files selected for processing (24)
front_end/messages/cs.jsonfront_end/messages/en.jsonfront_end/messages/es.jsonfront_end/messages/pt.jsonfront_end/messages/zh-TW.jsonfront_end/messages/zh.jsonfront_end/src/app/(main)/services/(pages)/financial-services/pro-forecasters/config.tsxfront_end/src/app/(main)/services/assets/desktop.webpfront_end/src/app/(main)/services/assets/phone.webpfront_end/src/app/(main)/services/components/case_studies/case_study_card.tsxfront_end/src/app/(main)/services/components/case_studies/constants.tsxfront_end/src/app/(main)/services/components/case_studies/types.tsfront_end/src/app/(main)/services/components/contact_section/contact_form.tsxfront_end/src/app/(main)/services/components/contact_section/contact_intro.tsxfront_end/src/app/(main)/services/components/contact_section/contact_section.tsxfront_end/src/app/(main)/services/components/get_in_touch_checkbox.tsxfront_end/src/app/(main)/services/components/get_in_touch_form.tsxfront_end/src/app/(main)/services/components/section_heading.tsxfront_end/src/app/(main)/services/components/templates/private_instances_page_template.tsxfront_end/src/app/(main)/services/components/templates/pro_forecasters_page_template.tsxfront_end/src/app/(main)/services/components/templates/services_page_template.tsxfront_end/src/app/(main)/services/components/templates/tournaments_page_template.tsxfront_end/src/app/(main)/services/page.tsxfront_end/src/components/ui/stacked-preview-image.tsx
💤 Files with no reviewable changes (2)
- front_end/src/app/(main)/services/components/get_in_touch_form.tsx
- front_end/src/app/(main)/services/components/get_in_touch_checkbox.tsx
🚧 Files skipped from review as they are similar to previous changes (9)
- front_end/src/app/(main)/services/components/section_heading.tsx
- front_end/src/app/(main)/services/components/contact_section/contact_section.tsx
- front_end/messages/pt.json
- front_end/src/app/(main)/services/components/case_studies/types.ts
- front_end/messages/en.json
- front_end/messages/zh-TW.json
- front_end/messages/es.json
- front_end/messages/zh.json
- front_end/src/components/ui/stacked-preview-image.tsx
🧰 Additional context used
🧬 Code graph analysis (6)
front_end/src/app/(main)/services/components/case_studies/case_study_card.tsx (2)
front_end/src/app/(main)/services/components/case_studies/types.ts (1)
TCaseStudyCard(17-35)front_end/src/components/ui/stacked-preview-image.tsx (1)
StackedPreviewImage(24-119)
front_end/src/app/(main)/services/components/case_studies/constants.tsx (2)
front_end/src/app/(main)/services/components/case_studies/types.ts (1)
TCaseStudyCard(17-35)front_end/src/app/(main)/(home)/components/featured-in-logos.tsx (1)
ForbesLogo(139-151)
front_end/src/app/(main)/services/page.tsx (1)
front_end/src/app/(main)/services/components/case_studies/constants.tsx (1)
CASE_STUDIES(7-68)
front_end/src/app/(main)/services/components/templates/private_instances_page_template.tsx (2)
front_end/src/app/(main)/services/(pages)/financial-services/private-instances/config.tsx (6)
title(9-14)sinceDebut(16-17)deployedDescription(19-20)platformBlock(22-33)stepsDescription(35-35)steps(37-54)front_end/src/constants/services.ts (1)
ServiceType(1-14)
front_end/src/app/(main)/services/components/contact_section/contact_form.tsx (6)
front_end/src/constants/services.ts (1)
ServiceType(1-14)front_end/src/services/api/misc/misc.shared.ts (1)
ContactForm(4-8)front_end/src/app/(main)/services/(pages)/financial-services/pro-forecasters/config.tsx (1)
serviceOptions(56-85)front_end/src/utils/analytics.ts (1)
sendAnalyticsEvent(11-17)front_end/src/utils/core/errors.ts (1)
logError(117-151)front_end/src/components/ui/form_field.tsx (3)
Input(111-128)FormErrorMessage(82-109)Textarea(167-181)
front_end/src/app/(main)/services/components/templates/tournaments_page_template.tsx (1)
front_end/src/constants/services.ts (1)
ServiceType(1-14)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Build Docker Image / Build Docker Image
- GitHub Check: Backend Checks
- GitHub Check: Frontend Checks
- GitHub Check: integration-tests
🔇 Additional comments (8)
front_end/messages/cs.json (1)
1892-1904: LGTM!The new localization keys for case studies, workshop block, and contact form are well-translated and properly structured. The translations are grammatically correct and consistent with the existing style in the file.
front_end/src/app/(main)/services/(pages)/financial-services/pro-forecasters/config.tsx (1)
5-5: Import update looks good.Aligning
ServiceOptionwith the newcontact_sectionmodule is consistent with the refactor.front_end/src/app/(main)/services/page.tsx (1)
80-89: LGTM — new workshop and case studies wiring is clear.front_end/src/app/(main)/services/components/templates/tournaments_page_template.tsx (1)
42-109: LGTM — layout and ContactSection integration look solid.front_end/src/app/(main)/services/components/templates/pro_forecasters_page_template.tsx (1)
107-113: Nice ContactSection wiring.
PassingpreselectedServiceandserviceOptionskeeps the new contact flow aligned with the page context.front_end/src/app/(main)/services/components/contact_section/contact_form.tsx (1)
95-103: Good guard for preselected service.
TheresolvedServicelogic avoids invalid defaults whenserviceOptionsare narrowed.front_end/src/app/(main)/services/components/templates/private_instances_page_template.tsx (1)
97-102: ContactSection integration looks clean.
The anchor id and preselected service align with the page’s context.front_end/src/app/(main)/services/components/templates/services_page_template.tsx (1)
255-266: Case studies block is well-structured.
Conditional rendering + keyed cards keeps this section tidy and extensible.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
front_end/src/app/(main)/services/components/case_studies/case_study_card.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In
`@front_end/src/app/`(main)/services/components/case_studies/case_study_card.tsx:
- Around line 127-133: The Image element rendering the report preview
(src={card.report.previewImageSrc}, alt={card.report.previewImageAlt}) is
missing an explicit width which causes build warnings and layout shift; add a
numeric width prop (e.g., width={50} to match the existing height={50} or
another design-approved pixel value) to that <Image> in case_study_card.tsx so
Next.js has both dimensions for the dynamic src.
In
`@front_end/src/app/`(main)/services/components/templates/services_page_template.tsx:
- Around line 226-231: The Image usage with src={WorkshopImage} (a string URL)
must include explicit dimensions or use fill; update the Image components that
render WorkshopImage (both the mobile instance using Image with className
"h-auto w-full max-w-[420px]" and the desktop instance around the later block)
to either add width and height props matching the actual asset dimensions or
replace them with layout fill by wrapping the Image in a positioned container
with explicit size and using fill; ensure you update the Image props (width,
height or fill) rather than relying solely on unoptimized or CSS.
🧹 Nitpick comments (3)
front_end/src/app/(main)/services/components/templates/services_page_template.tsx (2)
226-231: Duplicate WorkshopImage for responsive layout is acceptable but could be simplified.The same
WorkshopImageis rendered twice with opposing visibility classes (lg:hiddenandhidden lg:flex). This is a common pattern for responsive layouts with different positioning needs. However, if the image is identical at all breakpoints, CSS-only repositioning might be cleaner.Also applies to: 244-249
90-92: Consider logging errors for observability.The
catchblocks silently swallow errors by only returning fallbacks. While graceful degradation is good for UX, consider adding server-side logging to help diagnose issues in production.Example
} catch (error) { + console.error("Failed to fetch site stats:", error); finalStatsList = []; }Also applies to: 108-110
front_end/src/app/(main)/aib/components/aib/light-dark-icon.tsx (1)
23-45: Reserve intrinsic dimensions for logo images to reduce CLS.The
<img>tags don’t set width/height, so layout may shift on load. You can useStaticImageDatadimensions when available to reserve space without changing the visible size.♻️ Possible refinement
if (variant === "logo") { const toUrl = (src: IconLike) => (typeof src === "string" ? src : src.src); + const toDims = (src: IconLike) => + typeof src === "string" ? undefined : { width: src.width, height: src.height }; + const lightDims = toDims(lightSrc); + const darkDims = toDims(darkSrc); return ( <span className={cn("inline-flex items-center", className)} style={{ height: px }} > <img src={toUrl(lightSrc)} alt={alt} + width={lightDims?.width} + height={lightDims?.height} className="h-full w-auto object-contain dark:hidden" loading="lazy" /> <img src={toUrl(darkSrc)} alt={alt} + width={darkDims?.width} + height={darkDims?.height} className="hidden h-full w-auto object-contain dark:block" loading="lazy" /> </span> ); }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
front_end/src/app/(main)/services/assets/coefficient-giving-light.svgis excluded by!**/*.svgfront_end/src/app/(main)/services/assets/forbes-light.svgis excluded by!**/*.svg
📒 Files selected for processing (5)
front_end/src/app/(main)/aib/components/aib/light-dark-icon.tsxfront_end/src/app/(main)/services/components/case_studies/case_study_card.tsxfront_end/src/app/(main)/services/components/case_studies/constants.tsxfront_end/src/app/(main)/services/components/case_studies/types.tsfront_end/src/app/(main)/services/components/templates/services_page_template.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- front_end/src/app/(main)/services/components/case_studies/types.ts
- front_end/src/app/(main)/services/components/case_studies/constants.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
front_end/src/app/(main)/aib/components/aib/light-dark-icon.tsx (1)
front_end/src/app/(main)/aib/components/aib/leaderboard/bot_meta.ts (1)
IconLike(20-20)
🪛 Biome (2.1.2)
front_end/src/app/(main)/services/components/case_studies/case_study_card.tsx
[error] 78-85: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Build Docker Image / Build Docker Image
- GitHub Check: integration-tests
- GitHub Check: Frontend Checks
- GitHub Check: Backend Checks
🔇 Additional comments (5)
front_end/src/app/(main)/services/components/case_studies/case_study_card.tsx (2)
73-104: Static analysis false positive - keys are correctly placed.The Biome linter flagged
LightDarkIconas missing a key, but keys are correctly applied to the outermost elements in the map callback (<a>on line 90,<span>on line 100). Thecontentvariable is just extracted for code reuse.
18-167: Component structure looks good.The component is well-organized with proper TypeScript typing, conditional rendering for optional content, responsive breakpoints, dark mode support, and accessibility considerations (aria-labels on logo links, alt text on images).
front_end/src/app/(main)/services/components/templates/services_page_template.tsx (2)
255-268: Case studies section implementation looks good.The conditional rendering,
SectionHeadingusage, andCaseStudyCardmapping with properkey={card.id}are all correct. The grid layout provides a clean structure for the cards.
113-276: Template structure and layout are well-organized.The async server component properly handles data fetching, the responsive layout is consistent, and the new sections (workshop, case studies, contact) integrate cleanly with the existing structure. The fragment wrapper and semantic
<main>element are appropriate.front_end/src/app/(main)/aib/components/aib/light-dark-icon.tsx (1)
57-65: Thesizesprop should reflect viewport-relative units, not fixed pixel dimensions.When using
fillwith Next.js Image, thesizesattribute should describe how wide the image renders in viewport units (e.g.,"20px","50vw", or a media query). While thepxvariable is correctly normalized as a string, passing fixed pixel values like"20px"tosizesdoesn't align with Next.js best practices. For a fixed-size icon like this, using fixedwidthandheightprops instead offillwould be more appropriate and avoid confusion about responsive sizing.Likely an incorrect or invalid review comment.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| <Image | ||
| src={card.report.previewImageSrc} | ||
| alt={card.report.previewImageAlt ?? t("reportPreviewAlt")} | ||
| height={50} | ||
| className="h-[50px] w-auto rounded object-cover sm:hidden" | ||
| unoptimized | ||
| /> |
There was a problem hiding this comment.
Add explicit width for report preview image.
The <Image> component requires both width and height when src is a dynamic string, even with unoptimized. Without an explicit width, you may see build warnings or layout shift.
Suggested fix
<Image
src={card.report.previewImageSrc}
alt={card.report.previewImageAlt ?? t("reportPreviewAlt")}
+ width={50}
height={50}
className="h-[50px] w-auto rounded object-cover sm:hidden"
unoptimized
/>🤖 Prompt for AI Agents
In
`@front_end/src/app/`(main)/services/components/case_studies/case_study_card.tsx
around lines 127 - 133, The Image element rendering the report preview
(src={card.report.previewImageSrc}, alt={card.report.previewImageAlt}) is
missing an explicit width which causes build warnings and layout shift; add a
numeric width prop (e.g., width={50} to match the existing height={50} or
another design-approved pixel value) to that <Image> in case_study_card.tsx so
Next.js has both dimensions for the dynamic src.
| <Image | ||
| src={WorkshopImage} | ||
| alt="Workshop illustration" | ||
| unoptimized | ||
| className="h-auto w-full max-w-[420px]" | ||
| /> |
There was a problem hiding this comment.
Add explicit dimensions for WorkshopImage.
WorkshopImage is imported with ?url suffix (returns a string URL, not a static import). The <Image> component requires explicit width and height when src is a string, even with unoptimized. Consider adding dimensions or using fill with a sized container.
Suggested fix
<Image
src={WorkshopImage}
alt="Workshop illustration"
unoptimized
+ width={420}
+ height={280}
className="h-auto w-full max-w-[420px]"
/>Apply the same fix to the desktop instance on lines 244-249.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Image | |
| src={WorkshopImage} | |
| alt="Workshop illustration" | |
| unoptimized | |
| className="h-auto w-full max-w-[420px]" | |
| /> | |
| <Image | |
| src={WorkshopImage} | |
| alt="Workshop illustration" | |
| unoptimized | |
| width={420} | |
| height={280} | |
| className="h-auto w-full max-w-[420px]" | |
| /> |
🤖 Prompt for AI Agents
In
`@front_end/src/app/`(main)/services/components/templates/services_page_template.tsx
around lines 226 - 231, The Image usage with src={WorkshopImage} (a string URL)
must include explicit dimensions or use fill; update the Image components that
render WorkshopImage (both the mobile instance using Image with className
"h-auto w-full max-w-[420px]" and the desktop instance around the later block)
to either add width and height props matching the actual asset dimensions or
replace them with layout fill by wrapping the Image in a positioned container
with explicit size and using fill; ensure you update the Image props (width,
height or fill) rather than relying solely on unoptimized or CSS.
There was a problem hiding this comment.
this file recently moved to futureeval folder. if we use it in multiple different pages, we may move it to components folder while resolving conflicts.

This PR updates Services page.
Added new workshop block:
Case study section with cards:
Stacked images animation:
stacked_images.mov
Updated Private instances mock device pictures:
Redesigned "Get in touch" form:
Summary by CodeRabbit
New Features
Localization
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.