Skip to content

Commit

Permalink
Removed all instances of hardcoded CUIDs and code that was dependent …
Browse files Browse the repository at this point in the history
…of that. (#34)
  • Loading branch information
JurreBrandsenInfoSupport authored Mar 22, 2024
1 parent 378602e commit 617a68a
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 105 deletions.
155 changes: 101 additions & 54 deletions src/app/result/[role]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,85 @@
import { db } from "~/server/db";
/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
import { getServerAuthSession } from "~/server/auth";

import React, { Suspense } from "react";
import { getServerAuthSession } from "~/server/auth";
import { type QuestionResult, type Question } from "~/models/types";
import { db } from "~/server/db";
import { Login } from "../../../components/login";
import {
type Role,
type QuestionResult,
type TransformedData,
} from "~/models/types";
import { SelectRoleResults } from "../../../components/select-role-results";
import { slugify } from "~/utils/slugify";
import ResultsWrapper from "~/components/results";

import { type Metadata } from "next";
import PdfDownloadButton from "~/components/download-pdf";

export const metadata: Metadata = {
title: "Thank You",
title: "Results",
};

const ThankYou = async () => {
const Results: React.FC = async () => {
const session = await getServerAuthSession();

return (
<div className="container flex flex-col items-center justify-center gap-12 px-4 py-16">
<h1 className="text-center text-5xl font-extrabold tracking-tight">
<span className="block text-custom-primary sm:inline">
Info Support
</span>
<span className="block sm:inline"> Tech Survey - Results</span>
</h1>
<Suspense fallback={<div>Loading...</div>}>
<ShowRolesWrapper />
</Suspense>

<Suspense fallback={<div>Loading...</div>}>
<ShowResultsWrapper />
</Suspense>
{!session && (
<div>
<div className="max-w-2xl text-center">
<p>Please log in to view the results of the 2024 Tech Survey.</p>
</div>
<Login session={session} />
</div>
)}
</div>
);
};

const ShowRolesWrapper = async () => {
const roles: Role[] = await db.role.findMany();

const availableRoles = roles

// sort roles by general first
.sort((a, b) => {
const roleA = a.role.toLowerCase();
const roleB = b.role.toLowerCase();

if (roleA === "general") return -1;
if (roleB === "general") return 1;

return 0;
})
.map((role) => ({
id: role.id,
href: `/result/${slugify(role.role)}`,
label: role.role,
current: false,
completed: false,
started: false,
}));

return <SelectRoleResults roles={availableRoles} />;
};

const ShowResultsWrapper = async () => {
// retrieve all questions and answers for all users
const userAnswersForRole: QuestionResult[] = await db.questionResult.findMany(
{
where: {
userId: session?.user.id,
},
include: {
question: {
include: {
Expand All @@ -28,52 +90,37 @@ const ThankYou = async () => {
},
);

const transformedData = userAnswersForRole.reduce(
(acc, curr) => {
const existingQuestion = acc.find(
(item) => item.question.id === curr.question.id,
);

if (existingQuestion) {
existingQuestion.answers.push({
questionId: curr.questionId,
answerId: curr.answerId,
});
} else {
acc.push({
question: curr.question,
answers: [{ questionId: curr.questionId, answerId: curr.answerId }],
});
}
const answerOptions = await db.answerOption.findMany();

return acc;
},
[] as {
question: Question;
answers: { questionId: string; answerId: string }[];
}[],
);
let transformedData: TransformedData = {};

return (
<div className="container flex flex-col items-center justify-center gap-12 px-4 py-16">
<h1 className="text-center text-5xl font-extrabold tracking-tight">
Thank <span className="text-custom-primary sm:inline">You</span>
</h1>
<p className="text-center">
Your answers to the Info Support Tech Survey has been submitted
successfully. <br />
We appreciate your time and effort in completing the survey.
</p>
<div className="w-full max-w-3xl">
<Suspense fallback={<div>Loading...</div>}>
<PdfDownloadButton
userAnswersForRole={transformedData}
session={session!}
/>
</Suspense>
</div>
</div>
);
userAnswersForRole.forEach((userAnswer) => {
const { question, answerId } = userAnswer;
const questionText: string = question?.questionText ?? "";
const roles: Role[] = question.roles ?? [];

roles.forEach((role) => {
const roleName = role?.role ?? "";
if (
roleName &&
transformedData &&
!transformedData[roleName]?.[questionText]
) {
transformedData ??= {};
transformedData[roleName] ??= {};
transformedData![roleName]![questionText] ??= {};

const answerString =
answerOptions.find((option) => option.id === answerId)?.option ?? "";
const roleData = transformedData[roleName]?.[questionText] ?? {};

roleData![answerString] = roleData![answerString] ?? 0;
roleData![answerString]++;
}
});
});

return <ResultsWrapper data={transformedData} />;
};

export default ThankYou;
export default Results;
9 changes: 8 additions & 1 deletion src/app/thank-you/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { db } from "~/server/db";
import PdfDownloadButton from "../../components/download-pdf";
import React, { Suspense } from "react";
import { getServerAuthSession } from "~/server/auth";
import { type QuestionResult, type Question } from "~/models/types";
import {
type QuestionResult,
type Question,
type AnswerOption,
} from "~/models/types";

import { type Metadata } from "next";

Expand All @@ -27,6 +31,8 @@ const ThankYou = async () => {
},
);

const answerOptions: AnswerOption[] = await db.answerOption.findMany();

const transformedData = userAnswersForRole.reduce(
(acc, curr) => {
const existingQuestion = acc.find(
Expand Down Expand Up @@ -67,6 +73,7 @@ const ThankYou = async () => {
<Suspense fallback={<div>Loading...</div>}>
<PdfDownloadButton
userAnswersForRole={transformedData}
answerOptions={answerOptions}
session={session!}
/>
</Suspense>
Expand Down
29 changes: 24 additions & 5 deletions src/components/download-pdf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

import React from "react";
import { Document, Page, Text, View, StyleSheet } from "@react-pdf/renderer";
import { answerIdOrder, idToAnswerMap } from "~/utils/optionMapping";
import { type PdfTransformedData } from "~/models/types";
import { idToTextMap } from "~/utils/optionMapping";
import { type AnswerOption, type PdfTransformedData } from "~/models/types";

import dynamic from "next/dynamic";
import { Button } from "~/components/ui/button";
Expand All @@ -24,13 +24,22 @@ const PDFDownloadLink = dynamic(

const PDFDocument = ({
userAnswersForRole,
answerOptions,
session,
}: {
userAnswersForRole: PdfTransformedData[];
answerOptions: AnswerOption[];
session: Session;
}) => {
const rolesIncluded: Record<string, boolean> = {};

function getOptionFromAnswerId(answerId: string): string {
const answerOption = answerOptions.find((option) => option.id === answerId);
return answerOption
? idToTextMap[answerOption.option] ?? ""
: "Option not found";
}

// First, sort UserAnswersForRole based on alphabetical order of question text.
userAnswersForRole.sort((a, b) => {
const textA = a.question.questionText.toUpperCase();
Expand All @@ -48,8 +57,13 @@ const PDFDocument = ({

// Sort all answers based on the custom order
allAnswers.sort((a, b) => {
const positionA = answerIdOrder[a.answerId] ?? 0;
const positionB = answerIdOrder[b.answerId] ?? 0;
const positionA = answerOptions.findIndex(
(option) => option.id === a.answerId,
);
const positionB = answerOptions.findIndex(
(option) => option.id === b.answerId,
);

return positionA - positionB;
});

Expand Down Expand Up @@ -120,7 +134,9 @@ const PDFDocument = ({
{/* Render the answer */}
<Text style={styles.answerCell}>
{answers
.map(({ answerId }) => idToAnswerMap[answerId])
.map(({ answerId }) =>
getOptionFromAnswerId(answerId),
)
.join(", ")}
</Text>
</View>
Expand Down Expand Up @@ -206,9 +222,11 @@ const styles = StyleSheet.create({

const PdfDownloadButton = ({
userAnswersForRole,
answerOptions,
session,
}: {
userAnswersForRole: PdfTransformedData[];
answerOptions: AnswerOption[];
session: Session;
}) => {
return (
Expand All @@ -229,6 +247,7 @@ const PdfDownloadButton = ({
document={
<PDFDocument
userAnswersForRole={userAnswersForRole}
answerOptions={answerOptions}
session={session}
/>
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/mobile/survey-questions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export function MobileSurveyQuestionnaire({
currentRole: string;
}) {
const [responses, setResponses] = useState(
getInitialResponses(userAnswersForRole, currentRole),
getInitialResponses(userAnswersForRole, currentRole, userSelectedRoles),
);

const unansweredQuestions = filteredQuestions.filter(
Expand Down
16 changes: 12 additions & 4 deletions src/components/select-role-results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,29 @@ import { ScrollArea } from "~/components/ui/scroll-area";
import { type Section } from "~/models/types";
import Link from "next/link";
import { notFound, usePathname } from "next/navigation";
import { slugToId } from "~/utils/slugify";
import { slugify } from "~/utils/slugify";

const SelectRoleResults = ({ roles }: { roles: Section[] }) => {
const pathname = usePathname() || "";

const currentRole = pathname.split("/").pop() ?? "";
if (!slugToId[currentRole]) {
notFound();
const currentRoleBeautified = roles.find(
(section) => slugify(section.label) === currentRole,
)?.label;

// Check if the current role is in the list of roles
const roleExists = roles.some(
(section) => slugify(section.label) === currentRole,
);
if (!roleExists) {
return notFound();
}

return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button className=" bg-custom-buttonPrimary text-custom-secondary hover:bg-custom-buttonHover dark:bg-custom-buttonPrimary dark:hover:bg-custom-buttonHover">
Viewing results for: {currentRole}
Viewing results for: {currentRoleBeautified}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
Expand Down
10 changes: 7 additions & 3 deletions src/components/show-results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@ import {
Tooltip,
} from "recharts";
import { type TransformedData } from "~/models/types";
import { slugToId, slugify } from "~/utils/slugify";
import { slugify } from "~/utils/slugify";
import { ResultCommons } from "./results";

const ShowResults = ({ data }: { data: TransformedData }) => {
const pathname = usePathname() || "";

const currentRole = pathname.split("/").pop() ?? "";
if (!slugToId[currentRole]) {
notFound();

const roleExists = Object.keys(data).some(
(role) => slugify(role) === currentRole,
);
if (!roleExists) {
return notFound();
}

const { uniqueDataKeys, dataKeyColors, CustomTooltip } = ResultCommons({
Expand Down
15 changes: 13 additions & 2 deletions src/components/survey-questionnaire.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { usePathname, notFound } from "next/navigation";
import { useState } from "react";
import { type Session } from "next-auth";
import { slugToId, slugify } from "~/utils/slugify";
import { slugify } from "~/utils/slugify";

import ProgressionBar from "./progression-bar";
import useScreenSize from "./useScreenSize";
Expand Down Expand Up @@ -37,10 +37,21 @@ export function SurveyQuestionnaire({

// get the current role from the url, which is /survey/[role]
const currentRole = pathname.split("/").pop() ?? "";
if (!slugToId[currentRole]) {

const roleExists = userSelectedRoles.some(
(role) => slugify(role.role) === currentRole,
);

if (!roleExists) {
notFound();
}

// Dynamically generate the slugToId mapping
const slugToId: Record<string, string> = {};
userSelectedRoles.forEach((role) => {
slugToId[slugify(role.role)] = role.id;
});

const filteredQuestions = questions.filter(
(question) =>
question.roleIds?.some(
Expand Down
2 changes: 1 addition & 1 deletion src/components/survey-questions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export function SurveyQuestions({
currentRole: string;
}) {
const [responses, setResponses] = useState(
getInitialResponses(userAnswersForRole, currentRole),
getInitialResponses(userAnswersForRole, currentRole, userSelectedRoles),
);

const submitResponse = api.survey.setQuestionResult.useMutation({
Expand Down
Loading

0 comments on commit 617a68a

Please sign in to comment.