AshameTheDestroyer commited on
Commit
bae8ec6
·
1 Parent(s): a774a10

Submitting.

Browse files
frontend/app/routes/jobs.$jid.assessments.$id.tsx CHANGED
@@ -1,12 +1,15 @@
1
  import { useParams } from "react-router";
2
  import { Loader2Icon } from "lucide-react";
 
3
  import { Label, RadioGroup } from "radix-ui";
 
4
  import { Textarea } from "~/components/ui/textarea";
5
  import { Checkbox } from "~/components/ui/checkbox";
6
  import { RadioGroupItem } from "~/components/ui/radio-group";
7
  import { AssessmentCard } from "~/components/assessment-card";
8
  import type { Route } from "./+types/jobs.$jid.assessments.$id";
9
  import { useGetJobAssessmentByID } from "~/services/useGetJobAssessmentByID";
 
10
 
11
  export function meta({}: Route.MetaArgs) {
12
  return [
@@ -21,6 +24,9 @@ export function meta({}: Route.MetaArgs) {
21
  export default function AssessmentDetailRoute() {
22
  const { jid, id } = useParams();
23
  const { data: assessment, isLoading, isError, refetch } = useGetJobAssessmentByID({ jid: jid || "", id: id || "" });
 
 
 
24
 
25
  if (isLoading) {
26
  return (
@@ -49,8 +55,29 @@ export default function AssessmentDetailRoute() {
49
  );
50
  }
51
 
 
 
 
 
 
 
 
 
 
52
  const totalWeights = assessment.questions.reduce((weights, question) => weights + question.weight, 0);
53
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  return (
55
  <main className="container mx-auto p-4 flex flex-col gap-8">
56
  <AssessmentCard jid={jid || ""} assessment={assessment} isStatic />
@@ -66,9 +93,9 @@ export default function AssessmentDetailRoute() {
66
  </span>
67
  </header>
68
  {{
69
- "text_based": <Textarea className="w-full resize-none" placeholder="Answer goes here..." />,
70
  "choose_one": (
71
- <RadioGroup.RadioGroup>
72
  {question.options.map((option, i) => (
73
  <div key={i} className="flex items-center gap-3">
74
  <RadioGroupItem value={option.value} id={`${question.id}-option-${i}`} className="cursor-pointer" />
@@ -81,7 +108,18 @@ export default function AssessmentDetailRoute() {
81
  <div>
82
  {question.options.map((option, i) => (
83
  <div key={i} className="flex items-center gap-3">
84
- <Checkbox id={`${question.id}-option-${i}`} className="cursor-pointer" />
 
 
 
 
 
 
 
 
 
 
 
85
  <Label.Label htmlFor={`${question.id}-option-${i}`} className="cursor-pointer">{option.text}</Label.Label>
86
  </div>
87
  ))}
@@ -99,6 +137,14 @@ export default function AssessmentDetailRoute() {
99
  ))}
100
  </div>
101
  </section>
 
 
 
 
 
 
 
 
102
  </main>
103
  );
104
  }
 
1
  import { useParams } from "react-router";
2
  import { Loader2Icon } from "lucide-react";
3
+ import { useEffect, useState } from "react";
4
  import { Label, RadioGroup } from "radix-ui";
5
+ import { Button } from "~/components/ui/button";
6
  import { Textarea } from "~/components/ui/textarea";
7
  import { Checkbox } from "~/components/ui/checkbox";
8
  import { RadioGroupItem } from "~/components/ui/radio-group";
9
  import { AssessmentCard } from "~/components/assessment-card";
10
  import type { Route } from "./+types/jobs.$jid.assessments.$id";
11
  import { useGetJobAssessmentByID } from "~/services/useGetJobAssessmentByID";
12
+ import { usePostAssessmentApplication } from "~/services/usePostAssessmentApplication";
13
 
14
  export function meta({}: Route.MetaArgs) {
15
  return [
 
24
  export default function AssessmentDetailRoute() {
25
  const { jid, id } = useParams();
26
  const { data: assessment, isLoading, isError, refetch } = useGetJobAssessmentByID({ jid: jid || "", id: id || "" });
27
+ const [answers, setAnswers] = useState({} as Record<string, any>);
28
+
29
+ const { mutate, isPending: isSubmittingLoading, isError: isSubmittingError } = usePostAssessmentApplication();
30
 
31
  if (isLoading) {
32
  return (
 
55
  );
56
  }
57
 
58
+ useEffect(() => {
59
+ if (assessment == null) { return }
60
+
61
+ setAnswers(assessment.questions.reduce((accumulator, question) => {
62
+ accumulator[question.id] = question.type === "choose_many" ? [] : "";
63
+ return accumulator;
64
+ }, {} as Record<string, any>));
65
+ }, [assessment]);
66
+
67
  const totalWeights = assessment.questions.reduce((weights, question) => weights + question.weight, 0);
68
 
69
+ function handleSubmit() {
70
+ mutate({
71
+ job_id: jid || "",
72
+ assessment_id: id || "",
73
+ user_id: "",
74
+ answers: Object.entries(answers).map(([question_id, answer]) => ({
75
+ question_id,
76
+ [typeof answer == "string" ? "text" : "options"]: typeof answer == "string" ? answer : Array.isArray(answer) ? answer : [answer],
77
+ })),
78
+ })
79
+ }
80
+
81
  return (
82
  <main className="container mx-auto p-4 flex flex-col gap-8">
83
  <AssessmentCard jid={jid || ""} assessment={assessment} isStatic />
 
93
  </span>
94
  </header>
95
  {{
96
+ "text_based": <Textarea className="w-full resize-none" placeholder="Answer goes here..." value={answers[question.id]} onChange={e => setAnswers(prev => ({ ...prev, [question.id]: e.target.value }))} />,
97
  "choose_one": (
98
+ <RadioGroup.RadioGroup value={answers[question.id]} onValueChange={value => setAnswers(prev => ({ ...prev, [question.id]: value }))}>
99
  {question.options.map((option, i) => (
100
  <div key={i} className="flex items-center gap-3">
101
  <RadioGroupItem value={option.value} id={`${question.id}-option-${i}`} className="cursor-pointer" />
 
108
  <div>
109
  {question.options.map((option, i) => (
110
  <div key={i} className="flex items-center gap-3">
111
+ <Checkbox id={`${question.id}-option-${i}`} className="cursor-pointer" value={answers[question.id]?.includes(option.value)}
112
+ onCheckedChange={checked => {
113
+ setAnswers(prev => {
114
+ const currentSelections = prev[question.id] || [];
115
+ if (checked) {
116
+ return { ...prev, [question.id]: [...currentSelections, option.value] };
117
+ } else {
118
+ return { ...prev, [question.id]: currentSelections.filter((v: string) => v !== option.value) };
119
+ }
120
+ });
121
+ }}
122
+ />
123
  <Label.Label htmlFor={`${question.id}-option-${i}`} className="cursor-pointer">{option.text}</Label.Label>
124
  </div>
125
  ))}
 
137
  ))}
138
  </div>
139
  </section>
140
+ <footer className="mx-auto py-4">
141
+ <Button
142
+ className="bg-indigo-600 text-white hover:bg-indigo-700 dark:bg-indigo-500 dark:hover:bg-indigo-600"
143
+ onClick={handleSubmit}
144
+ >
145
+ Submit Answers
146
+ </Button>
147
+ </footer>
148
  </main>
149
  );
150
  }
frontend/app/services/usePostAssessmentApplication.ts ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useMutation } from "@tanstack/react-query";
2
+ import { HTTPManager } from "~/managers/HTTPManager";
3
+
4
+ export const POST_ASSESSMENT_APPLICATION_KEY = "post-assessment-application";
5
+
6
+ export type PostAssessmentApplicationPayload = {
7
+ job_id: string;
8
+ user_id: string;
9
+ assessment_id: string;
10
+ answers: Array<{
11
+ question_id: string;
12
+ text?: string;
13
+ options?: Array<string>;
14
+ }>;
15
+ };
16
+
17
+ export const usePostAssessmentApplication = () => useMutation({
18
+ mutationKey: [POST_ASSESSMENT_APPLICATION_KEY],
19
+ mutationFn: async (payload: PostAssessmentApplicationPayload) =>
20
+ HTTPManager.post(`/applications/jobs/${payload.job_id}/assessments/${payload.assessment_id}`, payload).then(response => response.data),
21
+ });