diff --git a/src/app/(authenticated)/forms/[id]/responses/[responseId]/page.tsx b/src/app/(authenticated)/forms/[id]/responses/[responseId]/page.tsx
index 0aea2b06..39464cb9 100644
--- a/src/app/(authenticated)/forms/[id]/responses/[responseId]/page.tsx
+++ b/src/app/(authenticated)/forms/[id]/responses/[responseId]/page.tsx
@@ -10,6 +10,7 @@ import { Badge } from "@/components/ui/badge"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { StatusUpdateButton } from "@/components/forms/status-update-button"
import { ResponseDetails } from "@/components/forms/response-details"
+import { EditResponseButton } from "@/components/forms/edit-response-button"
import { type Field } from "@/lib/form-types"
import { DashboardShell } from "@/components/dashboard-shell"
import { canAccessForm } from "@/lib/access-control"
@@ -47,6 +48,7 @@ export default async function ResponseDetailsPage({ params }: ResponseDetailsPag
}
const isOwner = response.form.userId === userData?.id
+ const isAuthor = response.userId === userData?.id
function getStatusBadge(status: string) {
switch (status) {
@@ -135,7 +137,13 @@ export default async function ResponseDetailsPage({ params }: ResponseDetailsPag
-
+
+
{isOwner && (
- {response.form.title}
+
+ {response.form.title}
+
+
{getStatusBadge(response.status)}
diff --git a/src/app/(authenticated)/forms/kanban/page.tsx b/src/app/(authenticated)/forms/kanban/page.tsx
index 9cc2cf1c..f71a9030 100644
--- a/src/app/(authenticated)/forms/kanban/page.tsx
+++ b/src/app/(authenticated)/forms/kanban/page.tsx
@@ -8,6 +8,7 @@ import type { ResponseStatus } from "@/types/form-responses"
import { KanbanColumn } from "./_components/kanban-column"
import { ResponseDialog } from "./_components/response-dialog"
import type { FormResponse } from "@/types/form-responses"
+import { DashboardShell } from "@/components/dashboard-shell"
export default function KanbanPage() {
const [selectedResponse, setSelectedResponse] = useState(null)
@@ -77,15 +78,45 @@ export default function KanbanPage() {
if (isLoading) {
return (
-
-
-
+
+
+
+
+
+ )
+ }
+
+ if (!responses || responses.length === 0) {
+ return (
+
+
+
Kanban de Solicitações
+
+ Visualize e organize as respostas recebidas nos seus formulários.
+
+
+
+
📋
+
Nenhuma solicitação encontrada
+
+ Você ainda não recebeu nenhuma resposta em seus formulários.
+
+
+ As respostas aparecerão aqui quando alguém responder aos seus formulários.
+
+
+
)
}
return (
-
-
Kanban de Solicitações
+
+
+
Kanban de Solicitações
+
+ Visualize e organize as respostas recebidas nos seus formulários.
+
+
@@ -115,6 +146,6 @@ export default function KanbanPage() {
{selectedResponse && (
)}
-
+
)
}
diff --git a/src/app/(authenticated)/forms/page.tsx b/src/app/(authenticated)/forms/page.tsx
index 3a618105..e1129138 100644
--- a/src/app/(authenticated)/forms/page.tsx
+++ b/src/app/(authenticated)/forms/page.tsx
@@ -62,12 +62,12 @@ export default async function FormsPage() {
-
+ {/*
-
+ */}
diff --git a/src/components/forms/edit-response-button.tsx b/src/components/forms/edit-response-button.tsx
new file mode 100644
index 00000000..6b54e75b
--- /dev/null
+++ b/src/components/forms/edit-response-button.tsx
@@ -0,0 +1,43 @@
+"use client"
+
+import { useState } from "react"
+import { Button } from "@/components/ui/button"
+import { Edit } from "lucide-react"
+import { EditResponseModal } from "./edit-response-modal"
+
+interface EditResponseButtonProps {
+ responseId: string
+ formId: string
+ isOwner: boolean
+ isAuthor: boolean
+}
+
+export function EditResponseButton({ responseId, formId, isOwner, isAuthor }: EditResponseButtonProps) {
+ const [isModalOpen, setIsModalOpen] = useState(false)
+
+ // Só mostrar o botão se o usuário for o dono do formulário ou o autor da resposta
+ if (!isOwner && !isAuthor) {
+ return null
+ }
+
+ return (
+ <>
+
+
+
setIsModalOpen(false)}
+ />
+ >
+ )
+}
+
diff --git a/src/components/forms/edit-response-modal.tsx b/src/components/forms/edit-response-modal.tsx
new file mode 100644
index 00000000..caa07a73
--- /dev/null
+++ b/src/components/forms/edit-response-modal.tsx
@@ -0,0 +1,114 @@
+"use client"
+
+import { useEffect, useState } from "react"
+import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"
+import { FormResponseComponent } from "./form-response"
+import { api } from "@/trpc/react"
+import { toast } from "sonner"
+import { Button } from "@/components/ui/button"
+import { Loader2 } from "lucide-react"
+import type { Field } from "@/lib/form-types"
+import type { FormResponse } from "@/types/form-responses"
+
+interface EditResponseModalProps {
+ responseId: string
+ formId: string
+ isOpen: boolean
+ onClose: () => void
+}
+
+export function EditResponseModal({ responseId, formId, isOpen, onClose }: EditResponseModalProps) {
+ const [isLoading, setIsLoading] = useState(true)
+ const [response, setResponse] = useState(null)
+ const [fields, setFields] = useState([])
+
+ // Buscar dados da resposta e campos do formulário
+ const { data: responseData, isLoading: isResponseLoading } = api.formResponse.getById.useQuery(
+ { responseId },
+ {
+ enabled: isOpen && !!responseId,
+ }
+ )
+
+ const { data: formData } = api.form.getById.useQuery(
+ { id: formId },
+ {
+ enabled: isOpen && !!formId,
+ }
+ )
+
+ // useEffect para carregar os dados quando o modal abre
+ useEffect(() => {
+ if (isOpen && responseData && formData) {
+ setResponse(responseData)
+ // @ts-expect-error - JsonValue to Field conversion
+ setFields(formData.fields as Field[])
+ setIsLoading(false)
+ } else if (isOpen && !isResponseLoading) {
+ setIsLoading(false)
+ }
+ }, [isOpen, responseData, formData, isResponseLoading])
+
+ // Mutation para atualizar a resposta
+ const updateResponse = api.formResponse.update.useMutation({
+ onSuccess: () => {
+ toast.success("Resposta atualizada com sucesso!")
+ onClose()
+ },
+ onError: (error: unknown) => {
+ const errorMessage = error instanceof Error ? error.message : 'Erro desconhecido'
+ toast.error(`Erro ao atualizar resposta: ${errorMessage}`)
+ },
+ })
+
+ const handleSubmit = (data: Record) => {
+ updateResponse.mutate({
+ responseId,
+ responses: [data] as Record[],
+ })
+ }
+
+ const handleClose = () => {
+ setIsLoading(true)
+ setResponse(null)
+ setFields([])
+ onClose()
+ }
+
+ return (
+
+ )
+}
+
diff --git a/src/components/forms/form-response.tsx b/src/components/forms/form-response.tsx
index 9457f366..a9350ba0 100644
--- a/src/components/forms/form-response.tsx
+++ b/src/components/forms/form-response.tsx
@@ -26,9 +26,20 @@ import remarkGfm from "remark-gfm"
interface FormResponseComponentProps {
formId: string
fields: Field[]
+ existingResponse?: Record
+ isEditing?: boolean
+ onSubmit?: (data: Record) => void
+ isSubmitting?: boolean
}
-export function FormResponseComponent({ formId, fields }: FormResponseComponentProps) {
+export function FormResponseComponent({
+ formId,
+ fields,
+ existingResponse,
+ isEditing = false,
+ onSubmit: customOnSubmit,
+ isSubmitting: customIsSubmitting
+}: FormResponseComponentProps) {
const [isSubmitted, setIsSubmitted] = useState(false)
const router = useRouter()
const {data: form} = api.form.getById.useQuery({id: formId})
@@ -101,7 +112,7 @@ export function FormResponseComponent({ formId, fields }: FormResponseComponentP
formState: { errors, isSubmitting },
} = useForm>({
resolver: zodResolver(formSchema),
- defaultValues: {},
+ defaultValues: existingResponse ?? {},
})
const submitResponse = api.formResponse.create.useMutation({
@@ -134,12 +145,14 @@ export function FormResponseComponent({ formId, fields }: FormResponseComponentP
}),
)
- submitResponse.mutate({
- formId,
- responses: [processedData],
- })
-
-
+ if (isEditing && customOnSubmit) {
+ customOnSubmit(processedData)
+ } else {
+ submitResponse.mutate({
+ formId,
+ responses: [processedData],
+ })
+ }
}
// Função para renderizar mensagens de erro
@@ -148,7 +161,7 @@ export function FormResponseComponent({ formId, fields }: FormResponseComponentP
return error ? {JSON.stringify(error.message)}
: null
}
- if (isSubmitted) {
+ if (isSubmitted && !isEditing) {
return (
@@ -285,8 +298,15 @@ export function FormResponseComponent({ formId, fields }: FormResponseComponentP
))}
-