Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/21: edit participant #56

Merged
merged 1 commit into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/app/api/events/[event]/participants/edit-participant/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { prisma } from "@/prisma"
import { NextRequest, NextResponse } from "next/server"

export async function POST(request: NextRequest) {
// TODO: validar com Zod
const {
id,
name,
email,
github,
}: { id: string; name: string; email: string; github?: string } =
await request.json()

const participant = await prisma.user.update({
where: {
id,
},
data: {
name,
email,
github: !!github ? github : undefined,
},
})

return NextResponse.json({
data: participant,
status: 201,
})
}
1 change: 1 addition & 0 deletions src/app/events/[event]/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"use client"
80 changes: 76 additions & 4 deletions src/app/events/[event]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
"use client"

import { ChangeEvent, useState } from "react"
import { ChangeEvent, useCallback, useState } from "react"
import { useRouter } from "next/navigation"
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { TableParticipants } from "./table-participants"
import {
Button,
Checkbox,
EditParticipantModal,
Input,
Modal,
ModalTrigger,
RegisterParticipantModal,
} from "@/components"
import { Filter as FilterIcon } from "lucide-react"
import { Filter as FilterIcon, Edit as EditIcon } from "lucide-react"
import {
getParticipants,
setSelectedParticipants,
checkParticipant,
registerParticipant,
removeParticipant,
editParticipant,
} from "./participants/data-participants"
import { upload } from "./participants/upload"
import { getRandomInteger } from "@/lib/get-random-integer"
import { RegisterParticipant } from "@/shared/types"
import { EditParticipant, RegisterParticipant } from "@/shared/types"

type EventProps = {
params: {
Expand Down Expand Up @@ -82,10 +84,43 @@ export default function Event({ params }: EventProps) {
},
})

const editParticipantMutation = useMutation({
mutationFn: editParticipant,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["participants", { event }] })
},
})

const handleRegisterParticipant = async (data: RegisterParticipant) => {
registerParticipantMutation.mutate({ data, event })
}

const handleEditParticipant = useCallback(
async (data: EditParticipant) => {
console.log("edit participant:", data)
await editParticipantMutation.mutateAsync({ data, event })
},
[editParticipantMutation, event],
)

const editParticipantModal = useCallback(
(participant: EditParticipant) => (
<EditParticipantModalContainer
participant={participant}
onEditParticipant={handleEditParticipant}
error={editParticipantMutation.error}
isError={editParticipantMutation.isError}
isLoading={editParticipantMutation.isLoading}
/>
),
[
editParticipantMutation.error,
editParticipantMutation.isLoading,
editParticipantMutation.isError,
handleEditParticipant,
],
)

const handleCheckParticipant = ({
id,
checked,
Expand Down Expand Up @@ -223,11 +258,48 @@ export default function Event({ params }: EventProps) {
</div>

<TableParticipants
event={event}
participants={filteredParticipants}
onCheckParticipant={handleCheckParticipant}
onRemoveParticipant={handleRemoveParticipant}
editParticipantModal={editParticipantModal}
/>
</main>
)
}

type EditParticipantModalContainerProps = {
participant: EditParticipant
onEditParticipant: (data: EditParticipant) => Promise<void>
isLoading: boolean
isError: boolean
error: unknown
}
function EditParticipantModalContainer({
participant,
onEditParticipant,
isLoading,
isError,
error,
}: EditParticipantModalContainerProps) {
const [openEditModal, setOpenEditModal] = useState(false)

const handleEditParticipant = async (participant: EditParticipant) => {
await onEditParticipant(participant)
setOpenEditModal(false)
}

return (
<Modal open={openEditModal} onOpenChange={setOpenEditModal}>
<ModalTrigger>
<EditIcon className="h-2 w-2 text-neutral-500" />
</ModalTrigger>
<EditParticipantModal
onEditParticipant={handleEditParticipant}
loading={isLoading}
success={isError}
error={typeof error === "string" ? error : null}
initialData={participant}
/>
</Modal>
)
}
12 changes: 0 additions & 12 deletions src/app/events/[event]/participants/[participantId]/edit/page.tsx

This file was deleted.

29 changes: 29 additions & 0 deletions src/app/events/[event]/participants/data-participants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
type Participant,
type ParticipantInGroup,
type RegisterParticipant,
EditParticipant,
} from "@/shared/types"

export async function getParticipants(event: string): Promise<Participant[]> {
Expand Down Expand Up @@ -91,6 +92,34 @@ export async function registerParticipant({
return { data: dataOrError }
}

type EditParticipantInput = {
event: string
data: EditParticipant
}

export async function editParticipant({ event, data }: EditParticipantInput) {
const result = await fetch(
`/api/events/${event}/participants/edit-participant`,
{
method: "POST",
body: JSON.stringify(data),
headers: {
"content-type": "application/json",
},
},
)

const dataOrError = await result.json()

if (!result.ok) {
const { message } = dataOrError
// TODO: handle the error in the future
return Promise.reject(message)
}

return { data: dataOrError }
}

type SetWinnerInput = {
userId: string
event: string
Expand Down
16 changes: 6 additions & 10 deletions src/app/events/[event]/table-participants.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Link from "next/link"
import type { Participant } from "@/shared/types"
import type { EditParticipant, Participant } from "@/shared/types"
import {
DebouncedCheckbox,
Table,
Expand All @@ -9,20 +8,20 @@ import {
TableHead,
TableCell,
} from "@/components"
import { Trash2 as RemoveIcon, Edit as EditIcon } from "lucide-react"
import { Trash2 as RemoveIcon } from "lucide-react"

type TableBodyProps = {
event: string
participants: Participant[]
onCheckParticipant: (args: { id: string; checked: boolean }) => void
onRemoveParticipant: (id: string) => void
editParticipantModal: (data: EditParticipant) => React.ReactNode
}

export function TableParticipants({
event,
participants,
onCheckParticipant,
onRemoveParticipant,
editParticipantModal,
}: TableBodyProps) {
return (
<Table>
Expand Down Expand Up @@ -69,11 +68,8 @@ export function TableParticipants({
<RemoveIcon className="h-2 w-2 text-danger-100" />
</button>
)}
<Link
href={`/events/${event}/participants/${participant.id}/edit`}
>
<EditIcon className="h-2 w-2 text-neutral-500" />
</Link>

{editParticipantModal(participant)}
</div>
</TableCell>
</TableRow>
Expand Down
1 change: 1 addition & 0 deletions src/components/edit-participant-modal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./modal"
Loading
Loading