Skip to content

Commit 4cc52dd

Browse files
committed
Refactor contact form to forms
1 parent 7d17cfd commit 4cc52dd

File tree

15 files changed

+198
-119
lines changed

15 files changed

+198
-119
lines changed

example/.bundle/config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
BUNDLE_PATH: "vendor/bundle"
2+
BUNDLE_FORCE_RUBY_PLATFORM: 1

example/.eslintrc.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
root: true,
3+
extends: '@react-native',
4+
};

example/.gitignore

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# OSX
2+
#
3+
.DS_Store
4+
5+
# Xcode
6+
#
7+
build/
8+
*.pbxuser
9+
!default.pbxuser
10+
*.mode1v3
11+
!default.mode1v3
12+
*.mode2v3
13+
!default.mode2v3
14+
*.perspectivev3
15+
!default.perspectivev3
16+
xcuserdata
17+
*.xccheckout
18+
*.moved-aside
19+
DerivedData
20+
*.hmap
21+
*.ipa
22+
*.xcuserstate
23+
**/.xcode.env.local
24+
25+
# Android/IntelliJ
26+
#
27+
build/
28+
.idea
29+
.gradle
30+
local.properties
31+
*.iml
32+
*.hprof
33+
.cxx/
34+
*.keystore
35+
!debug.keystore
36+
.kotlin/
37+
38+
# node.js
39+
#
40+
node_modules/
41+
npm-debug.log
42+
yarn-error.log
43+
44+
# fastlane
45+
#
46+
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47+
# screenshots whenever they are needed.
48+
# For more information about the recommended setup visit:
49+
# https://docs.fastlane.tools/best-practices/source-control/
50+
51+
**/fastlane/report.xml
52+
**/fastlane/Preview.html
53+
**/fastlane/screenshots
54+
**/fastlane/test_output
55+
56+
# Bundle artifact
57+
*.jsbundle
58+
59+
# Ruby / CocoaPods
60+
**/Pods/
61+
/vendor/bundle/
62+
63+
# Temporary files created by Metro to check the health of the file watcher
64+
.metro-health-check*
65+
66+
# testing
67+
/coverage
68+
69+
# Yarn
70+
.yarn/*
71+
!.yarn/patches
72+
!.yarn/plugins
73+
!.yarn/releases
74+
!.yarn/sdks
75+
!.yarn/versions

example/.prettierrc.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
arrowParens: 'avoid',
3+
singleQuote: true,
4+
trailingComma: 'all',
5+
};

example/.watchmanconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

src/client/AppgramClient.ts

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ import type {
2525
SurveyNode,
2626
SurveyResponse,
2727
SurveySubmitInput,
28-
ContactForm,
29-
ContactFormSubmission,
30-
ContactFormSubmitInput,
28+
Form,
29+
FormSubmission,
30+
FormSubmitInput,
3131
StatusPageOverview,
3232
BlogPost,
3333
BlogPostsResponse,
@@ -675,21 +675,13 @@ export class AppgramClient {
675675
}
676676

677677
// ============================================================================
678-
// Contact Forms
678+
// Forms
679679
// ============================================================================
680680

681681
/**
682-
* Get a public contact form by ID (legacy endpoint)
683-
* @deprecated Use getContactForm instead
682+
* Get a form by ID via portal endpoint
684683
*/
685-
async getPublicForm(formId: string): Promise<ApiResponse<ContactForm>> {
686-
return this.get<ContactForm>(`/api/v1/forms/${formId}`)
687-
}
688-
689-
/**
690-
* Get a contact form by ID via portal endpoint
691-
*/
692-
async getContactForm(formId: string): Promise<ApiResponse<ContactForm>> {
684+
async getForm(formId: string): Promise<ApiResponse<Form>> {
693685
const response = await this.get<{ contact_form: {
694686
id: string
695687
name: string
@@ -717,7 +709,7 @@ export class AppgramClient {
717709
if (!response.success || !response.data?.contact_form) {
718710
return {
719711
success: false,
720-
error: response.error || { code: 'NOT_FOUND', message: 'Contact form not found' },
712+
error: response.error || { code: 'NOT_FOUND', message: 'Form not found' },
721713
}
722714
}
723715

@@ -730,7 +722,7 @@ export class AppgramClient {
730722
description: raw.description,
731723
fields: raw.fields.map(f => ({
732724
id: f.id,
733-
type: f.type as ContactForm['fields'][0]['type'],
725+
type: f.type as Form['fields'][0]['type'],
734726
label: f.label,
735727
placeholder: f.placeholder,
736728
required: f.required,
@@ -749,9 +741,9 @@ export class AppgramClient {
749741
}
750742

751743
/**
752-
* Track a contact form view (call when form is displayed)
744+
* Track a form view (call when form is displayed)
753745
*/
754-
async trackContactFormView(formId: string): Promise<ApiResponse<{ tracked: boolean }>> {
746+
async trackFormView(formId: string): Promise<ApiResponse<{ tracked: boolean }>> {
755747
const endpoint = `/projects/${this.projectId}/contact-forms/${formId}/view`
756748
const url = `${this.baseUrl}${endpoint}`
757749

@@ -806,13 +798,13 @@ export class AppgramClient {
806798
}
807799

808800
/**
809-
* Submit a contact form
801+
* Submit a form
810802
*/
811-
async submitContactForm(
803+
async submitForm(
812804
projectId: string,
813805
formId: string,
814-
data: ContactFormSubmitInput
815-
): Promise<ApiResponse<ContactFormSubmission>> {
806+
data: FormSubmitInput
807+
): Promise<ApiResponse<FormSubmission>> {
816808
const url = `${this.baseUrl}/api/v1/projects/${projectId}/contact-forms/${formId}/submit`
817809

818810
try {
@@ -876,7 +868,7 @@ export class AppgramClient {
876868

877869
return {
878870
success: true,
879-
data: (result.data as ContactFormSubmission) || {
871+
data: (result.data as FormSubmission) || {
880872
id: '',
881873
form_id: formId,
882874
project_id: projectId,

src/components/feedback/SubmitWishSheet.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
} from 'react-native'
1616
import { X, Send, Sparkles } from 'lucide-react-native'
1717
import { useAppgramTheme, useAppgramContext } from '../../provider'
18-
import type { Wish, ContactForm, ContactFormField } from '../../types'
18+
import type { Wish, Form, FormField } from '../../types'
1919

2020
const { height: SCREEN_HEIGHT } = Dimensions.get('window')
2121

@@ -136,8 +136,8 @@ export function SubmitWishSheet({
136136
const [error, setError] = useState<string | null>(null)
137137

138138
// Auto-detect custom form from project customization
139-
const [customForm, setCustomForm] = useState<ContactForm | null>(null)
140-
const [customFormFields, setCustomFormFields] = useState<ContactFormField[]>([])
139+
const [customForm, setCustomForm] = useState<Form | null>(null)
140+
const [customFormFields, setCustomFormFields] = useState<FormField[]>([])
141141
const [customFieldValues, setCustomFieldValues] = useState<Record<string, string | boolean>>({})
142142
const [isLoadingCustomization, setIsLoadingCustomization] = useState(false)
143143

@@ -154,7 +154,7 @@ export function SubmitWishSheet({
154154
if (response.success && response.data?.customization_data) {
155155
const customizationData = response.data.customization_data as {
156156
content?: { feedback?: { customFormId?: string } }
157-
contactForms?: Record<string, ContactForm & { integration?: { type: string } }>
157+
contactForms?: Record<string, Form & { integration?: { type: string } }>
158158
}
159159

160160
const contactForms = customizationData.contactForms || {}
@@ -164,7 +164,7 @@ export function SubmitWishSheet({
164164
if (explicitFormId && contactForms[explicitFormId]) {
165165
const form = contactForms[explicitFormId]
166166
if (form.enabled && form.integration?.type === 'wish') {
167-
setCustomForm(form as ContactForm)
167+
setCustomForm(form as Form)
168168
// Filter out built-in fields
169169
const extraFields = form.fields.filter(
170170
(f) => !['title', 'description', 'email', 'name', 'message'].includes(f.id.toLowerCase())
@@ -184,7 +184,7 @@ export function SubmitWishSheet({
184184

185185
if (wishFormEntry) {
186186
const [, form] = wishFormEntry
187-
setCustomForm(form as ContactForm)
187+
setCustomForm(form as Form)
188188
// Filter out built-in fields
189189
const extraFields = form.fields.filter(
190190
(f) => !['title', 'description', 'email', 'name', 'message'].includes(f.id.toLowerCase())
@@ -553,7 +553,7 @@ export function SubmitWishSheet({
553553
// ============================================================================
554554

555555
interface CustomFieldInputProps {
556-
field: ContactFormField
556+
field: FormField
557557
value: string | boolean | undefined
558558
onChange: (value: string | boolean) => void
559559
colors: {

src/components/forms/ContactFormRenderer.tsx renamed to src/components/forms/FormRenderer.tsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import {
1111
type ViewStyle,
1212
} from 'react-native'
1313
import { useAppgramTheme, useAppgramContext } from '../../provider'
14-
import { useContactForm, useContactFormSubmit } from '../../hooks'
14+
import { useForm, useFormSubmit } from '../../hooks'
1515
import { Button, Card } from '../base'
16-
import type { ContactFormField } from '../../types'
16+
import type { FormField } from '../../types'
1717

18-
export interface ContactFormRendererProps {
18+
export interface FormRendererProps {
1919
formId: string
2020
projectId?: string
2121
title?: string
@@ -26,19 +26,19 @@ export interface ContactFormRendererProps {
2626
}
2727

2828
/**
29-
* ContactFormRenderer Component
29+
* FormRenderer Component
3030
*
31-
* Renders a dynamic contact form based on form configuration.
31+
* Renders a dynamic form based on form configuration.
3232
* Supports text, email, textarea, checkbox, select, and radio fields.
3333
*
3434
* @example
3535
* ```tsx
36-
* import { ContactFormRenderer } from '@appgram/react-native'
36+
* import { FormRenderer } from '@appgram/react-native'
3737
*
38-
* function ContactScreen() {
38+
* function FormScreen() {
3939
* return (
40-
* <ContactFormRenderer
41-
* formId="contact-form-id"
40+
* <FormRenderer
41+
* formId="form-id"
4242
* title="Contact Us"
4343
* description="We'd love to hear from you"
4444
* onSuccess={() => {
@@ -54,28 +54,28 @@ export interface ContactFormRendererProps {
5454
* @example
5555
* ```tsx
5656
* // With custom project ID
57-
* <ContactFormRenderer
57+
* <FormRenderer
5858
* formId="feedback-form"
5959
* projectId="custom-project-id"
6060
* onSuccess={() => setShowThankYou(true)}
6161
* />
6262
* ```
6363
*/
64-
export function ContactFormRenderer({
64+
export function FormRenderer({
6565
formId,
6666
projectId: propProjectId,
6767
title,
6868
description,
6969
onSuccess,
7070
onError,
7171
style,
72-
}: ContactFormRendererProps): React.ReactElement {
72+
}: FormRendererProps): React.ReactElement {
7373
const { colors, radius, typography, spacing } = useAppgramTheme()
7474
const { config } = useAppgramContext()
7575
const projectId = propProjectId || config.projectId
7676

77-
const { form, isLoading: formLoading, error: formError } = useContactForm(formId)
78-
const { submitForm, isSubmitting, error: submitError, successMessage } = useContactFormSubmit({
77+
const { form, isLoading: formLoading, error: formError } = useForm(formId)
78+
const { submitForm, isSubmitting, error: submitError, successMessage } = useFormSubmit({
7979
onSuccess,
8080
onError,
8181
})
@@ -148,7 +148,7 @@ export function ContactFormRenderer({
148148
paddingVertical: 12,
149149
}
150150

151-
const renderField = (field: ContactFormField) => {
151+
const renderField = (field: FormField) => {
152152
const error = fieldErrors[field.id]
153153
const value = formData[field.id]
154154

@@ -424,4 +424,4 @@ export function ContactFormRenderer({
424424
)
425425
}
426426

427-
export default ContactFormRenderer
427+
export default FormRenderer

src/components/forms/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Forms Components
33
*
4-
* Components for rendering dynamic contact forms.
4+
* Components for rendering dynamic forms.
55
*/
66

7-
export { ContactFormRenderer, type ContactFormRendererProps } from './ContactFormRenderer'
7+
export { FormRenderer, type FormRendererProps } from './FormRenderer'

src/components/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ export {
3939

4040
// Forms components
4141
export {
42-
ContactFormRenderer,
43-
type ContactFormRendererProps,
42+
FormRenderer,
43+
type FormRendererProps,
4444
} from './forms'
4545

4646
// Help components

0 commit comments

Comments
 (0)