chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
'use client'
|
||||
|
||||
import { useCallback, useState } from 'react'
|
||||
import {
|
||||
Chip,
|
||||
ChipModal,
|
||||
ChipModalBody,
|
||||
ChipModalError,
|
||||
ChipModalField,
|
||||
ChipModalFooter,
|
||||
ChipModalHeader,
|
||||
} from '@sim/emcn'
|
||||
import { requestJson } from '@/lib/api/client/request'
|
||||
import { integrationRequestContract } from '@/lib/api/contracts/common'
|
||||
|
||||
type SubmitStatus = 'idle' | 'submitting' | 'success' | 'error'
|
||||
|
||||
export function RequestIntegrationModal() {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [status, setStatus] = useState<SubmitStatus>('idle')
|
||||
|
||||
const [integrationName, setIntegrationName] = useState('')
|
||||
const [email, setEmail] = useState('')
|
||||
const [useCase, setUseCase] = useState('')
|
||||
|
||||
const resetForm = useCallback(() => {
|
||||
setIntegrationName('')
|
||||
setEmail('')
|
||||
setUseCase('')
|
||||
setStatus('idle')
|
||||
}, [])
|
||||
|
||||
const handleOpenChange = useCallback(
|
||||
(nextOpen: boolean) => {
|
||||
setOpen(nextOpen)
|
||||
if (!nextOpen) resetForm()
|
||||
},
|
||||
[resetForm]
|
||||
)
|
||||
|
||||
const handleSubmit = useCallback(async () => {
|
||||
if (!integrationName.trim() || !email.trim()) return
|
||||
|
||||
setStatus('submitting')
|
||||
|
||||
try {
|
||||
await requestJson(integrationRequestContract, {
|
||||
body: {
|
||||
integrationName: integrationName.trim(),
|
||||
email: email.trim(),
|
||||
useCase: useCase.trim() || undefined,
|
||||
},
|
||||
})
|
||||
|
||||
setStatus('success')
|
||||
setTimeout(() => setOpen(false), 1500)
|
||||
} catch {
|
||||
setStatus('error')
|
||||
}
|
||||
}, [integrationName, email, useCase])
|
||||
|
||||
const canSubmit = integrationName.trim() && email.trim() && status === 'idle'
|
||||
|
||||
return (
|
||||
<>
|
||||
<Chip className='border border-[var(--border-1)]' onClick={() => setOpen(true)}>
|
||||
Request an integration
|
||||
</Chip>
|
||||
|
||||
<ChipModal open={open} onOpenChange={handleOpenChange} srTitle='Request an Integration'>
|
||||
<ChipModalHeader onClose={() => handleOpenChange(false)}>
|
||||
Request an Integration
|
||||
</ChipModalHeader>
|
||||
|
||||
<ChipModalBody>
|
||||
{status === 'success' ? (
|
||||
<div className='flex flex-col items-center gap-3 py-6 text-center'>
|
||||
<div className='flex size-10 items-center justify-center rounded-full bg-[var(--brand-accent)]/10'>
|
||||
<svg
|
||||
className='size-5 text-[var(--brand-accent)]'
|
||||
viewBox='0 0 24 24'
|
||||
fill='none'
|
||||
stroke='currentColor'
|
||||
strokeWidth={2}
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
>
|
||||
<polyline points='20 6 9 17 4 12' />
|
||||
</svg>
|
||||
</div>
|
||||
<p className='text-[14px] text-[var(--text-primary)]'>
|
||||
Request submitted. We'll follow up at <span>{email}</span>.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<ChipModalField
|
||||
type='input'
|
||||
title='Integration name'
|
||||
value={integrationName}
|
||||
onChange={(value) => setIntegrationName(value)}
|
||||
placeholder='e.g. Stripe, HubSpot, Snowflake'
|
||||
maxLength={200}
|
||||
autoComplete='off'
|
||||
required
|
||||
/>
|
||||
<ChipModalField
|
||||
type='email'
|
||||
title='Your email'
|
||||
value={email}
|
||||
onChange={(value) => setEmail(value)}
|
||||
placeholder='you@company.com'
|
||||
autoComplete='email'
|
||||
required
|
||||
/>
|
||||
<ChipModalField
|
||||
type='textarea'
|
||||
title={
|
||||
<>
|
||||
Use case <span className='text-[var(--text-subtle)]'>(optional)</span>
|
||||
</>
|
||||
}
|
||||
value={useCase}
|
||||
onChange={(value) => setUseCase(value)}
|
||||
placeholder='What would you automate with this integration?'
|
||||
rows={3}
|
||||
maxLength={2000}
|
||||
/>
|
||||
{status === 'error' && (
|
||||
<ChipModalError>Something went wrong. Please try again.</ChipModalError>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ChipModalBody>
|
||||
|
||||
{status === 'success' ? (
|
||||
<ChipModalFooter
|
||||
onCancel={() => handleOpenChange(false)}
|
||||
primaryAction={{ label: 'Done', onClick: () => handleOpenChange(false) }}
|
||||
/>
|
||||
) : (
|
||||
<ChipModalFooter
|
||||
onCancel={() => setOpen(false)}
|
||||
cancelDisabled={status === 'submitting'}
|
||||
primaryAction={{
|
||||
label: status === 'submitting' ? 'Submitting...' : 'Submit request',
|
||||
onClick: handleSubmit,
|
||||
disabled: !canSubmit && status !== 'error',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</ChipModal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user