Skip to content

Commit 31057b2

Browse files
nickvisutcanjalal
andauthored
[Closes #424] Add sort by name to assigned page (#459)
* add sort by name to assigned Co-authored-by: Vincent Shuali <vincent.shuali@gmail.com> * Move types to universal types file * Add seeds of tasks * Add second benchmark to student 2 goal in seeds * Explicitly type getMyTasks and use useEffect instead of getSortedTasks --------- Co-authored-by: Vincent Shuali <vincent.shuali@gmail.com>
1 parent 4ea9cbc commit 31057b2

File tree

4 files changed

+248
-10
lines changed

4 files changed

+248
-10
lines changed

src/backend/db/lib/seed.ts

Lines changed: 170 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const seedfile = async (databaseUrl: string) => {
1111
.select("user_id")
1212
.executeTakeFirstOrThrow();
1313

14-
await db
14+
const { student_id: student_1_id } = await db
1515
.insertInto("student")
1616
.values({
1717
first_name: "Edna",
@@ -20,9 +20,10 @@ export const seedfile = async (databaseUrl: string) => {
2020
grade: 1,
2121
assigned_case_manager_id: firstuser.user_id,
2222
})
23-
.execute();
23+
.returning("student_id")
24+
.executeTakeFirstOrThrow();
2425

25-
await db
26+
const { student_id: student_2_id } = await db
2627
.insertInto("student")
2728
.values({
2829
first_name: "Colette",
@@ -31,7 +32,8 @@ export const seedfile = async (databaseUrl: string) => {
3132
grade: 2,
3233
assigned_case_manager_id: firstuser.user_id,
3334
})
34-
.execute();
35+
.returning("student_id")
36+
.executeTakeFirstOrThrow();
3537

3638
await db
3739
.insertInto("student")
@@ -64,5 +66,169 @@ export const seedfile = async (databaseUrl: string) => {
6466
})
6567
.execute();
6668

69+
const { iep_id: student_1_iep_id } = await db
70+
.insertInto("iep")
71+
.values({
72+
case_manager_id: firstuser.user_id,
73+
student_id: student_1_id,
74+
start_date: new Date("2024-11-05"),
75+
end_date: new Date("2028-12-31"),
76+
})
77+
.returning("iep_id")
78+
.executeTakeFirstOrThrow();
79+
80+
const { iep_id: student_2_iep_id } = await db
81+
.insertInto("iep")
82+
.values({
83+
case_manager_id: firstuser.user_id,
84+
student_id: student_2_id,
85+
start_date: new Date("2024-11-04"),
86+
end_date: new Date("2028-12-30"),
87+
})
88+
.returning("iep_id")
89+
.executeTakeFirstOrThrow();
90+
91+
const { goal_id: student_1_goal_1_id } = await db
92+
.insertInto("goal")
93+
.values({
94+
iep_id: student_1_iep_id,
95+
description: "Improve Spanish grade",
96+
category: "other",
97+
})
98+
.returning("goal_id")
99+
.executeTakeFirstOrThrow();
100+
101+
const { goal_id: student_1_goal_2_id } = await db
102+
.insertInto("goal")
103+
.values({
104+
iep_id: student_1_iep_id,
105+
description: "Come to class more punctually",
106+
category: "other",
107+
})
108+
.returning("goal_id")
109+
.executeTakeFirstOrThrow();
110+
111+
const { goal_id: student_2_goal_id } = await db
112+
.insertInto("goal")
113+
.values({
114+
iep_id: student_2_iep_id,
115+
description: "Organize notebook",
116+
category: "other",
117+
})
118+
.returning("goal_id")
119+
.executeTakeFirstOrThrow();
120+
121+
const { benchmark_id: benchmark_student_1_goal_1_id } = await db
122+
.insertInto("benchmark")
123+
.values({
124+
goal_id: student_1_goal_1_id,
125+
status: "In Progress",
126+
description: "Create example sentences from vocab",
127+
setup: "Make Google Sheets from vocab list",
128+
instructions:
129+
"Have student create example sentences for each vocab word in Google Sheets",
130+
materials: "N/A",
131+
frequency: "Once per week",
132+
target_level: 60,
133+
baseline_level: 0,
134+
attempts_per_trial: 1,
135+
number_of_trials: 16,
136+
metric_name: "",
137+
})
138+
.returning("benchmark_id")
139+
.executeTakeFirstOrThrow();
140+
141+
await db
142+
.insertInto("task")
143+
.values({
144+
benchmark_id: benchmark_student_1_goal_1_id,
145+
assignee_id: firstuser.user_id,
146+
})
147+
.execute();
148+
149+
const { benchmark_id: benchmark_student_1_goal_2_id } = await db
150+
.insertInto("benchmark")
151+
.values({
152+
goal_id: student_1_goal_2_id,
153+
status: "In Progress",
154+
description: "Create morning schedule",
155+
setup: "Make Google Sheet of empty schedule",
156+
instructions:
157+
"Have student fill out schedule on Google Sheets and print it",
158+
materials: "N/A",
159+
frequency: "Once per week",
160+
target_level: 60,
161+
baseline_level: 0,
162+
attempts_per_trial: 1,
163+
number_of_trials: 16,
164+
metric_name: "",
165+
})
166+
.returning("benchmark_id")
167+
.executeTakeFirstOrThrow();
168+
169+
await db
170+
.insertInto("task")
171+
.values({
172+
benchmark_id: benchmark_student_1_goal_2_id,
173+
assignee_id: firstuser.user_id,
174+
})
175+
.execute();
176+
177+
const { benchmark_id: benchmark_1_student_2_goal_id } = await db
178+
.insertInto("benchmark")
179+
.values({
180+
goal_id: student_2_goal_id,
181+
status: "In Progress",
182+
description: "Consolidate new class handouts",
183+
setup: "N/A",
184+
instructions:
185+
"Have student write dates and sort handouts by date and class",
186+
materials: "Pen, folders for each class",
187+
frequency: "Tuesdays and Fridays",
188+
target_level: 80,
189+
baseline_level: 0,
190+
attempts_per_trial: 4,
191+
number_of_trials: 16,
192+
metric_name: "",
193+
})
194+
.returning("benchmark_id")
195+
.executeTakeFirstOrThrow();
196+
197+
await db
198+
.insertInto("task")
199+
.values({
200+
benchmark_id: benchmark_1_student_2_goal_id,
201+
assignee_id: firstuser.user_id,
202+
})
203+
.execute();
204+
205+
const { benchmark_id: benchmark_2_student_2_goal_id } = await db
206+
.insertInto("benchmark")
207+
.values({
208+
goal_id: student_2_goal_id,
209+
status: "In Progress",
210+
description: "Insert handouts into notebooks in appropriate place",
211+
setup: "N/A",
212+
instructions:
213+
"Have student insert sorted notes into notebooks in appropriate position by dates",
214+
materials: "Pen, folders for each class",
215+
frequency: "Tuesdays and Fridays",
216+
target_level: 80,
217+
baseline_level: 0,
218+
attempts_per_trial: 4,
219+
number_of_trials: 16,
220+
metric_name: "",
221+
})
222+
.returning("benchmark_id")
223+
.executeTakeFirstOrThrow();
224+
225+
await db
226+
.insertInto("task")
227+
.values({
228+
benchmark_id: benchmark_2_student_2_goal_id,
229+
assignee_id: firstuser.user_id,
230+
})
231+
.execute();
232+
67233
logger.info("Database has been seeded with test data.");
68234
};

src/backend/routers/para.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { z } from "zod";
22
import { hasCaseManager, hasPara, router } from "../trpc";
33
import { createPara } from "../lib/db_helpers/case_manager";
4+
import { TaskData } from "@/types/global";
45

56
export const para = router({
67
getParaById: hasCaseManager
@@ -60,7 +61,7 @@ export const para = router({
6061
// TODO elsewhere: add "email_verified_at" timestamp when para first signs in with their email address (entered into db by cm)
6162
}),
6263

63-
getMyTasks: hasPara.query(async (req) => {
64+
getMyTasks: hasPara.query(async (req): Promise<TaskData[]> => {
6465
const { userId } = req.ctx.auth;
6566

6667
const result = await req.ctx.db

src/pages/benchmarks/index.tsx

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,58 @@ import Sort from "@mui/icons-material/Sort";
77
import { Box, Container } from "@mui/material";
88
import Image from "next/image";
99
import Link from "next/link";
10-
import { useState } from "react";
10+
import { useEffect, useState } from "react";
1111
import $button from "../../components/design_system/button/Button.module.css";
1212
import noBenchmarks from "../../public/img/no-benchmarks.png";
1313
import SearchIcon from "@mui/icons-material/Search";
14+
import { SortDirection, SortProperty, TaskData } from "@/types/global";
1415

1516
function Benchmarks() {
1617
const [isPara, setIsPara] = useState(false);
17-
const { data: tasks, isLoading } = trpc.para.getMyTasks.useQuery();
18+
19+
const [sortProperty, setSortProperty] = useState<SortProperty>("first_name");
20+
const [sortDirection, setSortDirection] = useState<SortDirection>("asc");
21+
22+
const [displayedTasks, setDisplayedTasks] = useState<TaskData[]>([]);
23+
24+
const { data: tasksData, isLoading } = trpc.para.getMyTasks.useQuery();
1825

1926
const handleTogglePara = () => {
2027
setIsPara(!isPara);
2128
};
2229

30+
useEffect(() => {
31+
if (!tasksData) {
32+
setDisplayedTasks([]);
33+
} else {
34+
setDisplayedTasks(
35+
[...tasksData].sort((a, b) => {
36+
if (a[sortProperty] < b[sortProperty])
37+
return sortDirection === "asc" ? -1 : 1;
38+
if (a[sortProperty] > b[sortProperty])
39+
return sortDirection === "asc" ? 1 : -1;
40+
return 0;
41+
})
42+
);
43+
}
44+
}, [sortDirection, sortProperty, tasksData]);
45+
46+
const handleSort = (property: SortProperty) => {
47+
if (property === sortProperty) {
48+
setSortDirection(sortDirection === "asc" ? "desc" : "asc");
49+
} else {
50+
setSortProperty(property);
51+
setSortDirection("asc");
52+
}
53+
};
54+
2355
if (isLoading) {
2456
return <div>Loading...</div>;
2557
}
2658

2759
return (
2860
<>
29-
{tasks?.length === 0 ? (
61+
{displayedTasks?.length === 0 ? (
3062
<Container sx={{ marginTop: "4rem" }}>
3163
<Box
3264
sx={{
@@ -90,7 +122,12 @@ function Benchmarks() {
90122
<FilterAlt /> Filter <KeyboardArrowDown />
91123
</span>
92124

93-
{/* Sort Pill Placeholder*/}
125+
{
126+
// TODO: replace simple sort pill w/this sort pill placeholder
127+
/*
128+
TODO: replace simple sort pill w/this sort pill placeholder
129+
130+
Sort Pill Placeholder
94131
<span
95132
className={`${$button.pilled}`}
96133
style={{
@@ -102,11 +139,27 @@ function Benchmarks() {
102139
>
103140
<Sort /> Sort <KeyboardArrowDown />
104141
</span>
142+
*/
143+
}
144+
145+
{/* simple sort pill POC (see TODO above) */}
146+
<button
147+
onClick={() => handleSort("first_name")}
148+
className={`${$button.pilled}`}
149+
style={{
150+
display: "flex",
151+
maxWidth: "fit-content",
152+
alignItems: "center",
153+
gap: "4px",
154+
}}
155+
>
156+
<Sort /> Sort by name
157+
</button>
105158
</div>
106159
</Box>
107160

108161
<Box sx={{ height: "75vh", overflowY: "scroll" }}>
109-
{tasks?.map((task) => {
162+
{displayedTasks?.map((task) => {
110163
const completed = Math.floor(
111164
Number(task.completed_trials) / Number(task.number_of_trials)
112165
);

src/types/global.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,21 @@ export type Goal = SelectableForTable<"goal">;
44
export type Benchmark = SelectableForTable<"benchmark">;
55
export type ChangeEvent = React.ChangeEvent<HTMLInputElement>;
66
export type FormEvent = React.FormEvent<HTMLFormElement>;
7+
8+
export type SortProperty = "first_name";
9+
export type SortDirection = "asc" | "desc";
10+
11+
export interface TaskData {
12+
task_id: string;
13+
first_name: string;
14+
last_name: string;
15+
category: string;
16+
description: string;
17+
instructions: string | null;
18+
attempts_per_trial: number | null;
19+
number_of_trials: number | null;
20+
due_date: Date | null;
21+
trial_count: number | null;
22+
seen: boolean;
23+
completed_trials: string | number | bigint | null;
24+
}

0 commit comments

Comments
 (0)