Skip to content

Commit

Permalink
feat: add tally matrix field representation (#244)
Browse files Browse the repository at this point in the history
Co-authored-by: stanislav <[email protected]>
  • Loading branch information
Max-vS and stanislavopeida authored Jun 27, 2024
1 parent 8f79cb7 commit a89829e
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Card, CardContent, CardHeader, CardTitle } from "@components/ui/card";
import { ApplicationField } from "@components/application/applicationField";
import { SubmitHandler, useForm } from "react-hook-form";
import { Question, QuestionSchema } from "@lib/schemas/question";
import { QuestionField } from "./_components/questionField";
import { Form } from "@components/ui/form";
import { api } from "trpc/react";
import { toast } from "sonner";
Expand All @@ -15,6 +14,8 @@ import { Tally } from "@lib/types/tally";
import { useRouter } from "next/navigation";
import { DeleteAlertDialog } from "../components/review-altert-dialog";
import Breadcrumbs from "@components/ui/breadcrumbs";
import { QuestionView } from "../../edit/_components/questionnaire/questionView";
import { QuestionField } from "./_components/questionField";

interface ReviewFormProps {
application: Application;
Expand Down Expand Up @@ -69,6 +70,8 @@ export const ReviewForm = ({
);
};

console.log(questions);

return (
<Form {...form}>
{/* eslint-disable-next-line @typescript-eslint/no-misused-promises */}
Expand Down Expand Up @@ -109,14 +112,16 @@ export const ReviewForm = ({
Application
</CardTitle>
</CardHeader>
<CardContent className="h-[80vh] overflow-y-auto">
<div className="flex flex-col gap-12">
{applicationFields
.filter((field) => !!field.value)
.map((field) => (
<ApplicationField key={field.key} field={field} />
))}
</div>
<CardContent className="flex h-[80vh] flex-col gap-12 overflow-y-auto">
{applicationFields
.filter((field) => !!field.value)
.map((field, index) => (
<ApplicationField
key={field.key}
field={field}
index={index + 1}
/>
))}
</CardContent>
</Card>

Expand All @@ -126,16 +131,14 @@ export const ReviewForm = ({
Review
</CardTitle>
</CardHeader>
<CardContent className="h-[80vh] overflow-y-auto">
<div className="flex flex-col gap-12">
{questions.map((question, index) => (
<QuestionField
question={question}
index={index}
key={question.key}
/>
))}
</div>
<CardContent className="flex h-[80vh] flex-col gap-12 overflow-y-auto">
{questions.map((question, index) => (
<QuestionField
question={question}
index={index}
key={question.key}
/>
))}
</CardContent>
</Card>
</div>
Expand Down
Binary file modified bun.lockb
Binary file not shown.
57 changes: 50 additions & 7 deletions components/application/applicationField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,20 @@ import { Checkbox } from "@components/ui/checkbox";
import { FileText, X } from "lucide-react";
import { FormLabel } from "@components/ui/form";
import { cn } from "@lib/utils";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@components/ui/table";
import { Badge } from "@components/ui/badge";

interface ApplicationFieldProps {
field: TallyField;
className?: string;
index?: number;
}

const ApplicationValue = ({ field }: ApplicationFieldProps) => {
Expand All @@ -36,7 +46,7 @@ const ApplicationValue = ({ field }: ApplicationFieldProps) => {
case "CHECKBOXES":
if (Array.isArray(field.value)) {
return (
<div className="mt-3">
<div className="mt-3 space-y-2">
{field.options!.map((option) => (
<div key={option.id} className="flex items-center space-x-2">
<Checkbox
Expand All @@ -49,7 +59,7 @@ const ApplicationValue = ({ field }: ApplicationFieldProps) => {
/>
<label
htmlFor="terms"
className="text-sm font-medium leading-none"
className="text-sm leading-none"
>
{option.text}
</label>
Expand All @@ -62,7 +72,7 @@ const ApplicationValue = ({ field }: ApplicationFieldProps) => {
return (
<div className="mt-3 flex items-center space-x-2">
<Checkbox disabled checked={field.value} />
<label htmlFor="terms" className="text-sm font-medium leading-none">
<label htmlFor="terms" className="text-sm leading-none">
Accept
</label>
</div>
Expand Down Expand Up @@ -95,7 +105,7 @@ const ApplicationValue = ({ field }: ApplicationFieldProps) => {
(opt) => opt.id === field.value?.at(0),
);
if (selected_value) {
return <p>{selected_value.text}</p>;
return <p className="text-sm">{selected_value.text}</p>;
}

return <p>No value</p>;
Expand Down Expand Up @@ -139,15 +149,48 @@ const ApplicationValue = ({ field }: ApplicationFieldProps) => {
))}
</div>
);

case "MATRIX":
return (
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-[120px]" />
{field.columns.map((col) => (
<TableHead>{col.text}</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{field.rows.map((row) => (
<TableRow key={`row-${row.id}`}>
<TableHead>{row.text}</TableHead>
{field.columns.map((col) => (
<TableCell key={`row-${row.id}-col-${col.id}`}>
<Checkbox
disabled
checked={field.value[row.id]?.includes(col.id)}
/>
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
);
}
};

export const ApplicationField = ({
field,
className,
index,
}: ApplicationFieldProps) => (
<div className={cn("flex flex-col gap-2", className)}>
<FormLabel>{field.label}</FormLabel>
<ApplicationValue field={field} />
<div className="flex w-full items-start gap-4">
{index && <Badge variant="secondary">{index}</Badge>}
<div className={cn("flex flex-col gap-1.5 mt-1", className)}>
<FormLabel>{field.label}</FormLabel>
<ApplicationValue field={field} />
</div>
</div>
);
27 changes: 27 additions & 0 deletions lib/faker/applications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ enum FieldTypes {
CHECKBOXES = "CHECKBOXES",
MULTIPLE_CHOICE = "MULTIPLE_CHOICE",
DROPDOWN = "DROPDOWN",
MATRIX = "MATRIX",
}

enum NormalFieldTypes {
Expand Down Expand Up @@ -146,6 +147,32 @@ function generateTallyFieldDetails(
options: multiple_options,
};

case FieldTypes.MATRIX:
const rows = Array.from(
{ length: faker.number.int({ min: 3, max: 5 }) },
() => ({ id: faker.string.uuid(), text: faker.lorem.word() }),
);

const columns = Array.from(
{ length: faker.number.int({ min: 3, max: 5 }) },
() => ({ id: faker.string.uuid(), text: faker.word.adjective() }),
);
const value = rows.reduce(
(acc, row) => {
acc[row.id] = [faker.helpers.arrayElement(columns).id];
return acc;
},
{} as Record<string, string[]>,
);

return {
...baseField,
type: FieldTypes.MATRIX,
value: value,
rows: rows,
columns: columns,
}

default:
if (
Object.values(NormalFieldTypes).includes(fieldType as NormalFieldTypes)
Expand Down
2 changes: 1 addition & 1 deletion lib/faker/opportunities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ function generateQuestionnaire(): Questionnaire {
name: faker.color.human(),
requiredReviews: faker.number.int({ min: 1, max: 3 }),
questions: Array.from(
{ length: faker.number.int({ min: 1, max: 5 }) },
{ length: faker.number.int({ min: 3, max: 5 }) },
generateQuestion,
),
conditions: [],
Expand Down
8 changes: 8 additions & 0 deletions lib/schemas/tally.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ const TallyDropdown = z.object({
options: z.array(z.object({ id: z.string(), text: z.string() })),
});

const TallyMatrix = z.object({
type: z.literal("MATRIX"),
value: z.record(z.array(z.string())),
columns: z.array(z.object({ id: z.string(), text: z.string() })),
rows: z.array(z.object({ id: z.string(), text: z.string() })),
});

export const TallyField = z
.object({
key: z.string(),
Expand All @@ -44,6 +51,7 @@ export const TallyField = z
TallyMultipleChoice,
TallyFileUpload,
TallyDropdown,
TallyMatrix,
z.object({
type: z
.literal("TEXTAREA")
Expand Down

0 comments on commit a89829e

Please sign in to comment.