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

inv-54 참석 여부 조회 #6

Merged
merged 5 commits into from
Jul 26, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"use client";

import { useQuery } from "@tanstack/react-query";
import { useParams } from "next/navigation";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import { getInvitationResponseById } from "~/lib/db/schema/invitation_response.query";

export default function InvitationResponseInfo() {
const { responseId } = useParams<{ responseId: string }>();

const { data, isLoading, error } = useQuery({
queryKey: ["invitationResponse", responseId],
queryFn: () => getInvitationResponseById(responseId),
});

if (isLoading) return <div>로딩중...</div>;
if (error) return <div>에러가 발생했습니다: {error.message}</div>;
if (!data) return <div>데이터를 찾을 수 없습니다.</div>;

return (
<Card>
<CardHeader>
<CardTitle>{data.participant_name}</CardTitle>
<CardDescription>{data.attendance ? "참석" : "불참"}</CardDescription>
</CardHeader>
<CardContent>
<CardDescription>ID: {data.id}</CardDescription>
<CardDescription>사유: {data.reason || "없음"}</CardDescription>
<CardDescription>
생성일: {new Date(data.created_at).toLocaleString()}
</CardDescription>
</CardContent>
</Card>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
dehydrate,
HydrationBoundary,
QueryClient,
} from "@tanstack/react-query";
import { cache } from "react";
import { ALink, AMain } from "~/app/(playground)/playground/inner-tools";
import InvitationResponseInfo from "~/app/(playground)/playground/invitation-response/[responseId]/invitation-response-info";
import { getInvitationResponseById } from "~/lib/db/schema/invitation_response.query";

const getQueryClient = cache(() => new QueryClient());

export default async function Page({
params,
}: {
params: { responseId: string };
}) {
const { responseId } = params;

const queryClient = getQueryClient();

await queryClient.prefetchQuery({
queryKey: ["invitationResponse", responseId],
queryFn: () => getInvitationResponseById(responseId),
});

return (
<HydrationBoundary state={dehydrate(queryClient)}>
<AMain>
<ALink href="/playground/invitation-response">뒤로가기</ALink>
<InvitationResponseInfo />
</AMain>
</HydrationBoundary>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"use client";

import { useQuery } from "@tanstack/react-query";
import Link from "next/link";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import type { InvitationResponse } from "~/lib/db/schema/invitation_response";
import {
getAllInvitationResponses,
getInvitationResponseStats,
} from "~/lib/db/schema/invitation_response.query";

export default function InvitationResponseList() {
const {
data: responses,
isLoading: isLoadingResponses,
error: responsesError,
} = useQuery<InvitationResponse[]>({
queryKey: ["invitationResponses"],
queryFn: async () => await getAllInvitationResponses(),
});

const {
data: stats,
isLoading: isLoadingStats,
error: statsError,
} = useQuery({
queryKey: ["invitationResponseStats"],
queryFn: () => getInvitationResponseStats(),
Comment on lines +33 to +34
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 이상하다 이건 서버 사이드에서 prefetch 안해도 괜찮나?
잘 동작하면 이 코멘트 무시해 주세요.

});

if (isLoadingResponses || isLoadingStats) return <div>로딩중...</div>;
if (responsesError || statsError)
return (
<div>
에러가 발생했습니다: {responsesError?.message || statsError?.message}
</div>
);
if (!responses || responses.length === 0)
return <div>데이터를 찾을 수 없습니다.</div>;

return (
<div>
<Card className="mb-4">
<CardHeader>
<CardTitle>초대 응답 통계</CardTitle>
</CardHeader>
<CardContent>
<CardDescription>총 응답 수: {stats?.totalResponses}</CardDescription>
<CardDescription>
참석 예정 인원: {stats?.attendingCount}
</CardDescription>
</CardContent>
</Card>

<div className="grid grid-cols-3 gap-2">
{responses.map((response) => (
<Link
href={`/playground/invitation-response/${response.id}`}
key={response.id}
>
<Card>
<CardHeader>
<CardTitle>{response.participant_name}</CardTitle>
<CardDescription>
{response.attendance ? "참석" : "불참"}
</CardDescription>
</CardHeader>
<CardContent>
<CardDescription>ID: {response.id}</CardDescription>
<CardDescription>
사유: {response.reason || "없음"}
</CardDescription>
<CardDescription>
생성일: {new Date(response.created_at).toLocaleString()}
</CardDescription>
</CardContent>
</Card>
</Link>
))}
</div>
</div>
);
}
29 changes: 29 additions & 0 deletions src/app/(playground)/playground/invitation-response/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {
dehydrate,
HydrationBoundary,
QueryClient,
} from "@tanstack/react-query";
import { cache } from "react";
import { ALink, AMain } from "~/app/(playground)/playground/inner-tools";
import InvitationResponseList from "~/app/(playground)/playground/invitation-response/invitation-response-list";
import { getAllInvitationResponses } from "~/lib/db/schema/invitation_response.query";

const getQueryClient = cache(() => new QueryClient());

export default async function Page() {
const queryClient = getQueryClient();

await queryClient.prefetchQuery({
queryKey: ["invitationResponses"],
queryFn: getAllInvitationResponses,
});

return (
<HydrationBoundary state={dehydrate(queryClient)}>
<AMain>
<ALink href="/playground">playground</ALink>
<InvitationResponseList />
</AMain>
</HydrationBoundary>
);
}
30 changes: 28 additions & 2 deletions src/lib/db/schema/invitation_response.query.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
"use server";
import { nanoid } from "nanoid";

import { count, eq, sql, sum } from "drizzle-orm";
import { nanoid } from "nanoid";
import { db } from "~/lib/db";
import {
invitationResponses,
type InvitationResponse,
type InvitationResponseInsert,
} from "~/lib/db/schema/invitation_response";

export async function getAllInvitationResponses() {
return db.select().from(invitationResponses);
return await db.select().from(invitationResponses);
}

export async function getInvitationResponseById(id: InvitationResponse["id"]) {
const responses = await db
.select()
.from(invitationResponses)
.where(eq(invitationResponses.id, id));
return responses[0];
}

export async function getInvitationResponseStats() {
const result = await db
.select({
totalResponses: count(),
attendingCount: sum(
sql`CASE WHEN ${invitationResponses.attendance} = true THEN 1 ELSE 0 END`,
).as("attending_count"),
})
.from(invitationResponses);

return {
totalResponses: Number(result[0].totalResponses),
attendingCount: Number(result[0].attendingCount),
};
}

export async function createInvitationResponses(
Expand Down