import { ArrowRight, CheckCircle2, ExternalLink, KeyRound, Plus, ShieldCheck, Smartphone, X } from 'lucide-react' import { useEffect, useState, type FormEvent } from 'react' import { useNavigate } from 'react-router-dom' import { urmiOtpApi, type UrmiOtpProject } from '../../lib/api' const PROJECT_NAME_RE = /^[a-z][a-z0-9-]{4,28}[a-z0-9]$/ const MESSAGE_LABEL_RE = /^[A-Za-z0-9][A-Za-z0-9 -]{0,18}[A-Za-z0-9]$|^[A-Za-z0-9]$/ function ProjectModal({ onClose, onCreated }: { onClose: () => void onCreated: (project: UrmiOtpProject) => void }) { const [name, setName] = useState('') const [messageLabel, setMessageLabel] = useState('') const [appType, setAppType] = useState<'web' | 'mobile'>('web') const [appUrl, setAppUrl] = useState('') const [purpose, setPurpose] = useState('') const [terms, setTerms] = useState(false) const [error, setError] = useState('') const [saving, setSaving] = useState(false) async function submit(event: FormEvent) { event.preventDefault() setError('') if (!PROJECT_NAME_RE.test(name) || name.includes('--')) { setError('Use 6–30 lowercase letters, numbers, or hyphens; start with a letter and end with a letter or number') return } const trimmedLabel = messageLabel.trim() if (!trimmedLabel || trimmedLabel.length > 20 || !MESSAGE_LABEL_RE.test(trimmedLabel)) { setError('Message label must be 1–20 characters: letters, numbers, spaces, or hyphens; start and end with a letter or number') return } if (purpose.trim().length < 20) { setError('Describe your app and OTP use case in at least 20 characters') return } if (!terms) { setError('You must agree to the terms and conditions') return } setSaving(true) try { const project = await urmiOtpApi.createProject({ project_name: name, message_label: trimmedLabel, app_type: appType, app_url: appUrl.trim(), purpose: purpose.trim(), terms_accepted: terms, }) onCreated(project) onClose() } catch (reason) { setError(reason instanceof Error ? reason.message : 'Unable to register project') } finally { setSaving(false) } } return (
One verification platform and a small set of generic templates for every app and OTP journey.
Each app must be approved before its API documentation becomes available.
{error}
}