Skip to content

Commit 1d51e4f

Browse files
committed
update(web): update student settings page design
1 parent 55bc5c7 commit 1d51e4f

File tree

5 files changed

+81
-31
lines changed

5 files changed

+81
-31
lines changed

apps/web/src/components/Settings/StudentPublicInfo.tsx

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
useFindStudentById,
66
useUpdateStudent,
77
} from "@litespace/headless/student";
8-
import { useInfiniteTopics } from "@litespace/headless/topic";
8+
import { useInfiniteTopics, useUserTopics } from "@litespace/headless/topic";
9+
import { useUpdateUserTopics } from "@litespace/headless/user";
910
import { IStudent, ITopic } from "@litespace/types";
1011
import { Button } from "@litespace/ui/Button";
1112
import { Form } from "@litespace/ui/Form";
@@ -18,10 +19,10 @@ import { Select } from "@litespace/ui/Select";
1819
import { Textarea } from "@litespace/ui/Textarea";
1920
import { useToast } from "@litespace/ui/Toast";
2021
import { Typography } from "@litespace/ui/Typography";
21-
import React, { useCallback, useMemo } from "react";
22+
import React, { useCallback, useEffect, useMemo, useRef } from "react";
2223

2324
type IForm = {
24-
topics: ITopic.Self["name"]["ar"][];
25+
topics: ITopic.Self[];
2526
career: string;
2627
level: IStudent.EnglishLevel;
2728
aim: string;
@@ -31,17 +32,18 @@ export const StudentPublicInfo: React.FC<{ id: number }> = ({ id }) => {
3132
const intl = useFormatMessage();
3233
const toast = useToast();
3334

34-
const { data } = useFindStudentById(id);
35+
const { data: studentData } = useFindStudentById(id);
3536

3637
const { list: allTopics } = useInfiniteTopics();
38+
const { query: studentTopics } = useUserTopics();
3739

3840
const onSuccess = useCallback(() => {
3941
toast.success({
4042
title: intl("student-settings.updated-successfully"),
4143
});
4244
}, [intl, toast]);
4345

44-
const onError = useOnError({
46+
const studentOnError = useOnError({
4547
type: "mutation",
4648
handler: ({ messageId }) => {
4749
toast.error({
@@ -51,32 +53,62 @@ export const StudentPublicInfo: React.FC<{ id: number }> = ({ id }) => {
5153
},
5254
});
5355

54-
const updateStudent = useUpdateStudent({ onSuccess, onError });
56+
const topicOnError = useOnError({
57+
type: "mutation",
58+
handler: ({ messageId }) => {
59+
toast.error({
60+
title: intl("complete-profile.update.error"),
61+
description: intl(messageId),
62+
});
63+
},
64+
});
65+
66+
const updateStudent = useUpdateStudent({
67+
onSuccess,
68+
onError: studentOnError,
69+
});
70+
const updateStudentTopics = useUpdateUserTopics({
71+
onSuccess,
72+
onError: topicOnError,
73+
});
5574

5675
const validators = useMakeValidators<IForm>({
5776
career: { required: false },
5877
level: { required: false, validate: validateEnglishLevel },
5978
aim: { required: false },
6079
});
6180

81+
const studentTopicsIds = useMemo(
82+
() => studentTopics.data?.map((topic) => topic.id),
83+
[studentTopics.data]
84+
);
85+
6286
const form = useForm<IForm>({
6387
defaults: {
64-
topics: data?.topics.map((topic) => topic.name.ar) || [],
65-
career: data?.career || intl("labels.jobs.student"),
66-
level: data?.level || IStudent.EnglishLevel.Beginner,
67-
aim: data?.aim || "",
88+
topics: studentTopics.data || [],
89+
career: studentData?.jobTitle || intl("labels.jobs.student"),
90+
level: studentData?.englishLevel || IStudent.EnglishLevel.Beginner,
91+
aim: studentData?.learningObjective || "",
6892
},
6993
validators,
7094
onSubmit(data) {
7195
updateStudent.mutate({
72-
id,
7396
payload: {
74-
topics: data.topics,
75-
career: data.career,
76-
level: data.level,
77-
aim: data.aim,
97+
id,
98+
englishLevel: data.level,
99+
jobTitle: data.career,
100+
learningObjective: data.aim,
78101
},
79102
});
103+
updateStudentTopics.mutate({
104+
addTopics: data.topics
105+
.filter((topic) => !studentTopicsIds?.includes(topic.id))
106+
.map((topic) => topic.id),
107+
removeTopics:
108+
studentTopicsIds?.filter(
109+
(topic) => !data.topics.map((tp) => tp.id).includes(topic)
110+
) || [],
111+
});
80112
},
81113
});
82114

@@ -105,8 +137,14 @@ export const StudentPublicInfo: React.FC<{ id: number }> = ({ id }) => {
105137
})) || []
106138
}
107139
placeholder={intl("complete-profile.topics.placeholder")}
108-
values={form.state.topics}
109-
setValues={(values) => form.set("topics", values)}
140+
values={form.state.topics.map((topic) => topic.name.ar)}
141+
setValues={(values) =>
142+
form.set(
143+
"topics",
144+
allTopics?.filter((topic) => values.includes(topic.name.ar)) ||
145+
[]
146+
)
147+
}
110148
/>
111149

112150
<Input

packages/atlas/src/api/student.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export class Student extends Base {
1414
return this.patch({ route: `/api/v1/student/`, payload });
1515
}
1616

17-
async findById(id: number): Promise<IStudent.FindStudentMetaApiResponse> {
17+
async findById(id: number): Promise<IStudent.Self> {
1818
return this.get({ route: `api/v1/student/${id}` });
1919
}
2020
}

packages/headless/src/student.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,7 @@ export function useUpdateStudent({
8585
});
8686
}
8787

88-
export function useFindStudentById(
89-
id: number
90-
): UseQueryResult<IStudent.FindStudentMetaApiResponse> {
88+
export function useFindStudentById(id: number): UseQueryResult<IStudent.Self> {
9189
const api = useApi();
9290
const find = useCallback(async () => {
9391
return api.student.findById(id);

packages/headless/src/topic.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,27 @@ export function useDeleteTopic({
131131
onError,
132132
});
133133
}
134+
135+
export function useUpdateUserTopics({
136+
onSuccess,
137+
onError,
138+
}: {
139+
onSuccess: OnSuccess;
140+
onError: OnError;
141+
}) {
142+
const api = useApi();
143+
144+
const update = useCallback(
145+
async (payload: ITopic.ReplaceUserTopicsApiPayload) => {
146+
return await api.topic.replaceUserTopics(payload);
147+
},
148+
[api.topic]
149+
);
150+
151+
return useMutation({
152+
mutationFn: update,
153+
mutationKey: ["update-user-topics"],
154+
onSuccess,
155+
onError,
156+
});
157+
}

packages/types/src/student.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
<<<<<<< HEAD
21
import { IFilter, IUser, Paginated } from "@/index";
3-
=======
4-
import { IFilter, ITopic, IUser } from "@/index";
5-
>>>>>>> 9805f504 (update(web): update student settings page design)
62

73
export enum EnglishLevel {
84
Beginner = 1,
@@ -79,9 +75,3 @@ export type UpdateApiResponse = unknown;
7975
export type FindApiQuery = FindModelQuery;
8076

8177
export type FindApiResponse = Paginated<Self>;
82-
export type FindStudentMetaApiResponse = Self & {
83-
career: string;
84-
level: EnglishLevel;
85-
aim: string;
86-
topics: ITopic.Self[];
87-
};

0 commit comments

Comments
 (0)