Enhance WhatsApp generator with phone conversion and QR colors#1
Conversation
…hints, and include DDI in URL UX improvements for the generator: - Result panel: reorder to URL+actions first (full width), then QR (left) and chat preview (right) on wider screens; rename "Preview" to "Result"; hide chat preview when no message; recenter QR at one-column width when chat preview is hidden. - Form: full-width container, two-column on wider screens, with the UTM fieldset and action row spanning both columns; mark phone/short code as required (red asterisk via Label) and message as optional; debounce URL computation by 600ms via useWatch + useDebouncedValue, with the parent onChange wrapped in a ref so identity changes don't re-fire the effect. - Shell: hide the entire result panel until a phone (or short code, for business links) is provided, so the preview never renders empty state. - URL building: always include the country dialing code (DDI) in generated wa.me / api.whatsapp.com / whatsapp:// URLs by transforming the raw input through libphonenumber-js (with a heuristic prepend fallback for partial input). Adds src/lib/phone.test.ts with vitest coverage for empty input, valid BR/US numbers, E.164 round-trip, and partial-typing fallback. Co-authored-by: Claude Opus <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…iners Add `justify-end` to the flex rows hosting Reset/Share, Copy/Open URL, and Download PNG/SVG, so primary actions consistently anchor to the right edge of their containers across both panels. Co-authored-by: Claude Opus <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Add a color picker to the QR preview controls so users can recolor the foreground (dark cells) of the generated code. Defaults to the existing WhatsApp-deep-green (#075E54) and flows through the on-screen canvas preview as well as the PNG/SVG downloads. - src/lib/qrcode.ts: export QR_DEFAULT_DARK_COLOR / QR_DEFAULT_LIGHT_COLOR so the component shares the source of truth for defaults. - src/components/generator/QrPreview/QrPreview.tsx: add `color` state, pipe `darkColor` through drawToCanvas/downloadPng/downloadSvg, and add a native <input type="color"> sized to match the adjacent error-correction <select> for visual harmony. Controls grid relaxed to sm:grid-cols-2 lg:grid-cols-4 to host the new field. - i18n: new `qr.color` key in en, es and pt-BR. Co-authored-by: Claude Opus <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Update the repository URL referenced from the header and footer to the new canonical location under the LacusSolutions organization. Co-authored-by: Claude Opus <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThis PR enhances the WhatsApp generator app with phone number-to-WhatsApp-digits utility conversion, QR code color customization, required form field indicators, debounced URL computation to reduce re-renders, and refactored conditional preview rendering. It updates translations across three languages, adjusts layout components, and updates repository links. ChangesCore Feature: Phone Utility, QR Colors, and Enhanced Form Fields
Layout, Navigation, and Internationalization
🎯 3 (Moderate) | ⏱️ ~20 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/generator/GeneratorForm/GeneratorForm.tsx`:
- Around line 77-91: Wrap the call to phoneToWhatsAppDigits inside the useEffect
in a try-catch to guard against thrown errors or unexpected return values: when
variantRequiresPhone(v) is true, call
phoneToWhatsAppDigits(debouncedValues.phone, country) inside try, assign
phoneDigits on success and fall back to undefined on error, and ensure
buildWhatsAppUrl(...) and onChangeRef.current(url, debouncedValues) still run
with phone undefined (optionally log the caught error). This change touches the
useEffect block that references variantRequiresPhone, phoneToWhatsAppDigits,
buildWhatsAppUrl, and onChangeRef.
In `@src/components/generator/PreviewPanel/PreviewPanel.tsx`:
- Around line 54-58: Remove the redundant guard inside the onClick handler:
delete the conditional "if (!openable) return;" from the onClick anonymous
function so the handler simply calls onOpen?.() and window.open(url, '_blank',
'noopener,noreferrer'); rely on the existing disabled={!openable} prop to
prevent interaction; update the onClick in PreviewPanel to only reference onOpen
and url.
In `@src/components/ui/Label/Label.tsx`:
- Around line 17-21: Label currently renders the required asterisk with
aria-hidden="true", which makes the required state invisible to assistive tech;
update the Label component (the required prop handling) to expose semantics by
keeping the visual asterisk but also rendering screen-reader-visible text (e.g.,
a sr-only/visually-hidden <span> with the word "required") or by removing
aria-hidden and ensuring a sibling sr-only element exists, and document/ensure
consumers apply aria-required on the associated form control (or have Label
accept and forward an aria-required prop) so the required state is
programmatically exposed.
In `@src/lib/phone.test.ts`:
- Around line 1-31: Add extra unit tests to increase coverage for
phoneToWhatsAppDigits by creating cases for very short partial input (e.g.,
single or two digits like '9' or '12' with 'BR'), input that's exactly the
country calling code (e.g., '55' for BR, '1' for US), inputs mixing invalid
characters with digits (e.g., '(41' -> should strip to '5541'), and leading-zero
partials (e.g., '011' -> '5511'); add these new it(...) blocks to
src/lib/phone.test.ts alongside the existing tests so phoneToWhatsAppDigits
behavior for partial/edge inputs is explicitly asserted.
- Around line 24-30: The test is too permissive: update the test to assert exact
expected output (e.g., expect(phoneToWhatsAppDigits('415', 'US')).toBe('1415'))
so it fails with the current implementation, and then fix phoneToWhatsAppDigits
to correctly prepend the country calling code in its heuristic fallback path
(the logic currently relying on startsWith that returns "415" must produce
"1415" for country 'US'); locate and adjust the fallback branch in
phoneToWhatsAppDigits to explicitly prepend the country's DDI when the
parsed/partial national number does not already include it.
In `@src/lib/phone.ts`:
- Around line 65-76: The function phoneToWhatsAppDigits should treat inputs that
are only the country calling code (e.g., "+1" or "1") as "no phone number" and
return an empty string; after computing callingCode (from
getCountryCallingCode(country)) and digits (raw with non-digits stripped and
leading zeros removed) in phoneToWhatsAppDigits, add a check that if digits ===
callingCode or digits === `+${callingCode}` (accounting for possible formats)
then return '' before returning a value—this prevents returning a bare calling
code as a phone number while leaving existing parsed-number and normal
digit-prefix logic intact.
- Around line 54-76: The startsWith(callingCode) check in phoneToWhatsAppDigits
can mis-detect country code presence for short calling codes; update the final
branch to treat the digits as already containing the calling code only if they
start with callingCode AND are longer than just the calling code (i.e.
digits.startsWith(callingCode) && digits.length > callingCode.length), otherwise
prepend getCountryCallingCode(country); reference phoneToWhatsAppDigits, parsed,
callingCode, digits, and replace the existing startsWith logic with this
stricter prefix-length check.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: da333dfb-8c5e-470f-9239-2b6a48a993e1
📒 Files selected for processing (20)
.github/CODEOWNERSpackage.jsonsrc/app/[locale]/page.tsxsrc/components/generator/BusinessShortCodeField/BusinessShortCodeField.tsxsrc/components/generator/GeneratorForm/GeneratorForm.tsxsrc/components/generator/GeneratorShell/GeneratorShell.tsxsrc/components/generator/MessageField/MessageField.tsxsrc/components/generator/PhoneField/PhoneField.tsxsrc/components/generator/PreviewPanel/PreviewPanel.tsxsrc/components/generator/QrPreview/QrPreview.tsxsrc/components/layout/Footer/Footer.tsxsrc/components/layout/Header/Header.tsxsrc/components/ui/Label/Label.tsxsrc/i18n/messages/en.jsonsrc/i18n/messages/es.jsonsrc/i18n/messages/pt-BR.jsonsrc/lib/phone.test.tssrc/lib/phone.tssrc/lib/qrcode.tsvitest.config.mts
Adjustment as perCodeRabbit AI review comment at #1 (comment). Co-authored-by: CodeRabbit <noreply@coderabbit.ai> Co-authored-by: Cursor <cursoragent@cursor.com>
Adjustment as per CodeRabbit AI review comment at #1 (comment). Co-authored-by: CodeRabbit <noreply@coderabbit.ai> Co-authored-by: Cursor <cursoragent@cursor.com>
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/ui/Label/Label.tsx`:
- Line 22: The fallback 'required' string causes hardcoded English for screen
readers; update the Label component to avoid this by either (A) making
requiredAnnouncement mandatory when required is true via a conditional prop type
(e.g., change LabelProps so requiredAnnouncement is required if required ===
true) or (B) add a development-only runtime check inside the Label function that
detects if required && !requiredAnnouncement and emits a console.warn (and keep
announced as before) so callers are alerted; reference the announced variable
and the requiredAnnouncement/required props when implementing the chosen fix.
In `@src/lib/phone.test.ts`:
- Around line 24-45: Add a regression test to ensure explicit international
partial input like "+55 11" is handled correctly: add an assertion calling
phoneToWhatsAppDigits('+55 11', 'BR') and expect '5511'. Locate the test suite
that contains the other partial-input cases (the tests around
phoneToWhatsAppDigits) and add this new spec alongside those cases so the
function's normalization of '+' and whitespace for DDI prefixes is locked in.
In `@src/lib/phone.ts`:
- Around line 85-88: The fallback currently always returns
`${callingCode}${digits}`, which double-prefixes when the raw input was
explicitly international (e.g., started with '+' or '00') and the sanitized
digits already begin with the callingCode; update the logic in the function
around parsePhoneNumberFromString/intlParsed so that if the original raw input
contains an explicit international prefix ('+' or leading '00') and
digits.startsWith(callingCode) you return digits (or digits without any leading
'+') directly instead of prepending callingCode—otherwise keep the existing
fallback behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4b8d0f1b-d2e2-4bb6-b43e-55dc9932561d
📒 Files selected for processing (8)
src/components/generator/BusinessShortCodeField/BusinessShortCodeField.tsxsrc/components/generator/PhoneField/PhoneField.tsxsrc/components/ui/Label/Label.tsxsrc/i18n/messages/en.jsonsrc/i18n/messages/es.jsonsrc/i18n/messages/pt-BR.jsonsrc/lib/phone.test.tssrc/lib/phone.ts
Fix as per CodeRabbit AI review comment at #1 (comment). Co-authored-by: CodeRabbit <noreply@coderabbit.ai> Co-authored-by: Cursor <cursoragent@cursor.com>
Adjustment as per CodeRabbit AI review comment at #1 (comment). Co-authored-by: CodeRabbit <noreply@coderabbit.ai> Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
|
🎉 This PR is included in version 1.1.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Summary by CodeRabbit
New Features
UI/UX Improvements
Accessibility
Tests
Chores