()
| 188 | } |
| 189 | |
| 190 | function SubmitForm() { |
| 191 | const { user } = useUser() |
| 192 | const router = useRouter() |
| 193 | const [isSubmitting, setIsSubmitting] = useState(false) |
| 194 | const [error, setError] = useState<string | null>(null) |
| 195 | const [inputMode, setInputMode] = useState<InputMode>("manual") |
| 196 | const [jsonInput, setJsonInput] = useState("") |
| 197 | const [jsonError, setJsonError] = useState<string | null>(null) |
| 198 | const fileInputRef = useRef<HTMLInputElement>(null) |
| 199 | const [formData, setFormData] = useState<FormData>({ |
| 200 | type: "", |
| 201 | productId: "", |
| 202 | displayName: "", |
| 203 | description: "", |
| 204 | repoUrl: "", |
| 205 | homepageUrl: "", |
| 206 | tags: "", |
| 207 | installation: "", |
| 208 | }) |
| 209 | |
| 210 | // Debounce the product ID for availability check (500ms delay) |
| 211 | const debouncedProductId = useDebounce(formData.productId, 500) |
| 212 | |
| 213 | const submitExtension = useMutation(api.extensions.submit) |
| 214 | const isProductIdAvailable = useQuery( |
| 215 | api.extensions.checkProductIdAvailable, |
| 216 | debouncedProductId.length >= 2 ? { productId: debouncedProductId } : "skip" |
| 217 | ) |
| 218 | |
| 219 | // Track if user is still typing (for showing "Checking..." state) |
| 220 | const isCheckingProductId = formData.productId !== debouncedProductId && formData.productId.length >= 2 |
| 221 | |
| 222 | const updateField = (field: keyof FormData, value: string) => { |
| 223 | setFormData((prev) => ({ ...prev, [field]: value })) |
| 224 | setError(null) |
| 225 | } |
| 226 | |
| 227 | const parseAndApplyJson = (jsonString: string) => { |
| 228 | setJsonError(null) |
| 229 | |
| 230 | if (!jsonString.trim()) { |
| 231 | setJsonError("Please enter JSON data") |
| 232 | return false |
| 233 | } |
| 234 | |
| 235 | try { |
| 236 | const parsed = JSON.parse(jsonString) as JsonExtension |
| 237 | |
| 238 | // Validate type if provided |
| 239 | if (parsed.type && !VALID_TYPES.includes(parsed.type as typeof VALID_TYPES[number])) { |
| 240 | setJsonError(`Invalid type "${parsed.type}". Valid types: ${VALID_TYPES.join(", ")}`) |
| 241 | return false |
| 242 | } |
| 243 | |
| 244 | // Convert tags array to comma-separated string if needed |
| 245 | let tagsString = "" |
| 246 | if (Array.isArray(parsed.tags)) { |
| 247 | tagsString = parsed.tags.join(", ") |
nothing calls this directly
no test coverage detected