mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 06:43:06 +00:00
react-audit(família 4): C140 leftover — dispatch manual preserva texto digitado em erro de validação (ActivityUpdateForm.tsx:34, ActivityResultForm.tsx:60, DemandWorkflowCard.tsx:104, MunicipalityUpdateDeliberation.tsx:227)
This commit is contained in:
parent
101cd5d791
commit
e273e9ecfa
4 changed files with 46 additions and 9 deletions
|
|
@ -1,7 +1,7 @@
|
|||
'use client'
|
||||
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useActionState } from 'react'
|
||||
import { startTransition, useActionState, type FormEvent } from 'react'
|
||||
|
||||
import { registerActivityResultFormAction } from '@/app/(campaign)/campanha/(app)/atividades/[slug]/resultFormActions'
|
||||
import { CampaignFormActionMessage } from '@/components/campaign/shared/CampaignFormActionMessage'
|
||||
|
|
@ -42,6 +42,14 @@ export const ActivityResultForm = ({
|
|||
.join(' ')
|
||||
: null
|
||||
|
||||
// C139 — manual dispatch: React 19 resets uncontrolled fields after any
|
||||
// settled form action, reverting the typed result to `initialSummary` on
|
||||
// a validation error. `startTransition` keeps `pending` correct.
|
||||
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault()
|
||||
startTransition(() => formAction(new FormData(event.currentTarget)))
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
|
|
@ -49,7 +57,7 @@ export const ActivityResultForm = ({
|
|||
{recordedLabel ? <p className="text-sm text-muted-foreground">{recordedLabel}</p> : null}
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form action={formAction} className="flex flex-col gap-4">
|
||||
<form onSubmit={handleSubmit} className="flex flex-col gap-4">
|
||||
<input type="hidden" name="activityId" value={activityId} />
|
||||
{state.status !== 'success' ? (
|
||||
<CampaignFormActionMessage state={state} errorTitle="Não foi possível registrar" />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use client'
|
||||
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useActionState, useRef } from 'react'
|
||||
import { startTransition, useActionState, useRef, type FormEvent } from 'react'
|
||||
|
||||
import { createActivityUpdateFormAction } from '@/app/(campaign)/campanha/(app)/atividades/[slug]/updateFormActions'
|
||||
import { CampaignFormActionMessage } from '@/components/campaign/shared/CampaignFormActionMessage'
|
||||
|
|
@ -25,13 +25,21 @@ export const ActivityUpdateForm = ({ activityId }: { activityId: number }) => {
|
|||
|
||||
const bodyError = fieldError(state.fieldErrors, 'body')
|
||||
|
||||
// C139 — manual dispatch (no `action={formAction}`): React 19 resets
|
||||
// uncontrolled fields after any settled form action, wiping the typed
|
||||
// update on a validation error. `startTransition` keeps `pending` correct.
|
||||
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault()
|
||||
startTransition(() => formAction(new FormData(event.currentTarget)))
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Nova atualização</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form ref={formRef} action={formAction} className="flex flex-col gap-4">
|
||||
<form ref={formRef} onSubmit={handleSubmit} className="flex flex-col gap-4">
|
||||
<input type="hidden" name="activityId" value={activityId} />
|
||||
{state.status !== 'success' ? (
|
||||
<CampaignFormActionMessage state={state} errorTitle="Não foi possível enviar" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use client'
|
||||
|
||||
import { useActionState } from 'react'
|
||||
import { startTransition, useActionState, type FormEvent } from 'react'
|
||||
|
||||
import { Alert, AlertDescription } from '@/components/ui/Alert'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
|
@ -63,6 +63,19 @@ export const DemandWorkflowCard = ({
|
|||
(target !== 'aprovada' && target !== 'rejeitada'),
|
||||
)
|
||||
|
||||
// C139 — manual dispatch (no `action={submitTransition}`/`action={submitCost}`):
|
||||
// React 19 resets uncontrolled fields after any settled form action, wiping
|
||||
// the typed decision note and cost on a validation error. `startTransition`
|
||||
// keeps the pending flags correct for the imperative dispatch.
|
||||
const handleTransitionSubmit = (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault()
|
||||
startTransition(() => submitTransition(new FormData(event.currentTarget)))
|
||||
}
|
||||
const handleCostSubmit = (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault()
|
||||
startTransition(() => submitCost(new FormData(event.currentTarget)))
|
||||
}
|
||||
|
||||
if (readOnly) {
|
||||
return (
|
||||
<section
|
||||
|
|
@ -101,7 +114,7 @@ export const DemandWorkflowCard = ({
|
|||
</div>
|
||||
|
||||
{availableTransitions.length ? (
|
||||
<form action={submitTransition} className="flex flex-col gap-3">
|
||||
<form onSubmit={handleTransitionSubmit} className="flex flex-col gap-3">
|
||||
<input type="hidden" name="demandId" value={demandID} />
|
||||
<Field>
|
||||
<FieldLabel htmlFor={`demand-note-${demandID}`}>Nota da decisão</FieldLabel>
|
||||
|
|
@ -144,7 +157,7 @@ export const DemandWorkflowCard = ({
|
|||
<p className="text-sm text-muted-foreground">Esta demanda já foi decidida.</p>
|
||||
)}
|
||||
|
||||
<form action={submitCost} className="flex flex-col gap-2">
|
||||
<form onSubmit={handleCostSubmit} className="flex flex-col gap-2">
|
||||
<input type="hidden" name="demandId" value={demandID} />
|
||||
<FieldLabel htmlFor={`demand-cost-${demandID}`}>
|
||||
Custo estimado (R$) — controle interno
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use client'
|
||||
|
||||
import { useActionState, useEffect, useRef } from 'react'
|
||||
import { startTransition, useActionState, useEffect, useRef, type FormEvent } from 'react'
|
||||
|
||||
import { CampaignFormActionMessage } from '@/components/campaign/shared/CampaignFormActionMessage'
|
||||
import { Badge } from '@/components/ui/Badge'
|
||||
|
|
@ -197,6 +197,14 @@ const CommentThread = ({
|
|||
if (state.status === 'success' && formRef.current) formRef.current.reset()
|
||||
}, [state])
|
||||
|
||||
// C139 — manual dispatch: React 19 resets uncontrolled fields after any
|
||||
// settled form action, wiping the typed comment on a validation error.
|
||||
// The success reset above stays explicit; `startTransition` keeps `pending`.
|
||||
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault()
|
||||
startTransition(() => submitAction(new FormData(event.currentTarget)))
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-sm font-medium">Discussão</p>
|
||||
|
|
@ -224,7 +232,7 @@ const CommentThread = ({
|
|||
</ul>
|
||||
) : null}
|
||||
{canComment ? (
|
||||
<form ref={formRef} action={submitAction} className="flex flex-col gap-2">
|
||||
<form ref={formRef} onSubmit={handleSubmit} className="flex flex-col gap-2">
|
||||
<input type="hidden" name="updateId" value={updateId} />
|
||||
<Textarea
|
||||
name="body"
|
||||
|
|
|
|||
Loading…
Reference in a new issue