Skip to content

Commit 0b7d689

Browse files
committed
improvement(contact): address greptile review feedback
- Map contact topic to help email type for accurate confirmation emails - Drop Zod schema details from 400 response on public /api/contact - Wire aria-describedby + aria-invalid in LandingField for both forms - Reset helpMutation on modal reopen to match demo-request pattern
1 parent 84b2a31 commit 0b7d689

5 files changed

Lines changed: 34 additions & 9 deletions

File tree

apps/sim/app/(landing)/components/contact/consts.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,18 @@ export type ContactRequestPayload = z.infer<typeof contactRequestSchema>
6565
export function getContactTopicLabel(value: ContactRequestPayload['topic']): string {
6666
return CONTACT_TOPIC_OPTIONS.find((option) => option.value === value)?.label ?? value
6767
}
68+
69+
export type HelpEmailType = 'bug' | 'feedback' | 'feature_request' | 'other'
70+
71+
export function mapContactTopicToHelpType(topic: ContactRequestPayload['topic']): HelpEmailType {
72+
switch (topic) {
73+
case 'feature_request':
74+
return 'feature_request'
75+
case 'support':
76+
return 'bug'
77+
case 'integration':
78+
return 'feedback'
79+
default:
80+
return 'other'
81+
}
82+
}

apps/sim/app/(landing)/components/contact/contact-form.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useState } from 'react'
3+
import { cloneElement, isValidElement, useState } from 'react'
44
import { useMutation } from '@tanstack/react-query'
55
import { Combobox, Input, Textarea } from '@/components/emcn'
66
import { Check } from '@/components/emcn/icons'
@@ -48,6 +48,10 @@ interface LandingFieldProps {
4848

4949
function LandingField({ label, htmlFor, optional, error, children }: LandingFieldProps) {
5050
const errorId = error ? `${htmlFor}-error` : undefined
51+
const describedChild =
52+
errorId && isValidElement<{ 'aria-describedby'?: string; 'aria-invalid'?: boolean }>(children)
53+
? cloneElement(children, { 'aria-describedby': errorId, 'aria-invalid': true })
54+
: children
5155
return (
5256
<div className='flex flex-col gap-1.5'>
5357
<label
@@ -57,7 +61,7 @@ function LandingField({ label, htmlFor, optional, error, children }: LandingFiel
5761
{label}
5862
{optional ? <span className='ml-1 text-[var(--text-muted)]'>(optional)</span> : null}
5963
</label>
60-
{children}
64+
{describedChild}
6165
{error ? (
6266
<p id={errorId} role='alert' className='text-[12px] text-[var(--text-error)]'>
6367
{error}

apps/sim/app/(landing)/components/demo-request/demo-request-modal.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useState } from 'react'
3+
import { cloneElement, isValidElement, useState } from 'react'
44
import { useMutation } from '@tanstack/react-query'
55
import {
66
Combobox,
@@ -60,6 +60,10 @@ interface LandingFieldProps {
6060

6161
function LandingField({ label, htmlFor, optional, error, children }: LandingFieldProps) {
6262
const errorId = error ? `${htmlFor}-error` : undefined
63+
const describedChild =
64+
errorId && isValidElement<{ 'aria-describedby'?: string; 'aria-invalid'?: boolean }>(children)
65+
? cloneElement(children, { 'aria-describedby': errorId, 'aria-invalid': true })
66+
: children
6367
return (
6468
<div className='flex flex-col gap-1.5'>
6569
<label
@@ -69,7 +73,7 @@ function LandingField({ label, htmlFor, optional, error, children }: LandingFiel
6973
{label}
7074
{optional ? <span className='ml-1 text-[var(--text-muted)]'>(optional)</span> : null}
7175
</label>
72-
{children}
76+
{describedChild}
7377
{error ? (
7478
<p id={errorId} role='alert' className='text-[12px] text-[var(--text-error)]'>
7579
{error}

apps/sim/app/api/contact/route.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { getFromEmailAddress } from '@/lib/messaging/email/utils'
1212
import {
1313
contactRequestSchema,
1414
getContactTopicLabel,
15+
mapContactTopicToHelpType,
1516
} from '@/app/(landing)/components/contact/consts'
1617

1718
const logger = createLogger('ContactAPI')
@@ -53,10 +54,7 @@ export const POST = withRouteHandler(async (req: NextRequest) => {
5354
logger.warn(`[${requestId}] Invalid contact request data`, {
5455
errors: validationResult.error.format(),
5556
})
56-
return NextResponse.json(
57-
{ error: 'Invalid request data', details: validationResult.error.format() },
58-
{ status: 400 }
59-
)
57+
return NextResponse.json({ error: 'Invalid request data' }, { status: 400 })
6058
}
6159

6260
const { name, email, company, topic, subject, message } = validationResult.data
@@ -98,7 +96,10 @@ ${message}
9896
logger.info(`[${requestId}] Contact request email sent successfully`)
9997

10098
try {
101-
const confirmationHtml = await renderHelpConfirmationEmail('other', 0)
99+
const confirmationHtml = await renderHelpConfirmationEmail(
100+
mapContactTopicToHelpType(topic),
101+
0
102+
)
102103

103104
await sendEmail({
104105
to: [email],

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/help-modal/help-modal.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ export function HelpModal({ open, onOpenChange, workflowId, workspaceId }: HelpM
169169
setSubmitStatus(null)
170170
setIsDragging(false)
171171
setIsProcessing(false)
172+
helpMutation.reset()
172173
reset({
173174
subject: '',
174175
message: '',

0 commit comments

Comments
 (0)