Skip to content

Commit 50687f2

Browse files
committed
update(web): update student settings page design
1 parent e99ae02 commit 50687f2

File tree

9 files changed

+85
-35
lines changed

9 files changed

+85
-35
lines changed

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

Lines changed: 54 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";
@@ -21,7 +22,7 @@ import { Typography } from "@litespace/ui/Typography";
2122
import React, { useCallback, useMemo } 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 || "",
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

@@ -101,12 +133,17 @@ export const StudentPublicInfo: React.FC<{ id: number }> = ({ id }) => {
101133
options={
102134
allTopics?.map((topic) => ({
103135
label: topic.name.ar,
104-
value: topic.name.ar,
136+
value: topic.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.id)}
141+
setValues={(values) =>
142+
form.set(
143+
"topics",
144+
allTopics?.filter((topic) => values.includes(topic.id)) || []
145+
)
146+
}
110147
/>
111148

112149
<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/constants/mutation.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export enum MutationKey {
2323
DeleteSlot = "delete-slot",
2424
UpdateUser = "update-user",
2525
UpdateUserPersonalInfo = "update-user-personal-info",
26+
UdpateUsertopics = "update-user-topics",
2627
UpdateStudent = "update-student",
2728
UpdateTutorTopics = "update-tutor-topics",
2829
CreateRoom = "create-room",

packages/headless/src/constants/query.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export enum QueryKey {
2424
FindUserById = "find-user-by-id",
2525
FindStudentStats = "find-student-stats",
2626
FindStudents = "find-students",
27+
FindStudentById = "find-student-by-id",
2728
FindPersonalizedStudentStats = "find-personalized-student-stats",
2829
FindPersonalizedTutorStats = "find-personalized-tutor-stats",
2930
FindTopic = "find-topic",

packages/headless/src/student.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,14 @@ 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);
9492
}, [api.student, id]);
9593

9694
return useQuery({
9795
queryFn: find,
98-
queryKey: ["find-student-by-id"],
96+
queryKey: [QueryKey.FindStudentById],
9997
});
10098
}

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: [MutationKey.UdpateUsertopics],
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-
};

packages/ui/src/components/Tabs/Tabs.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const Tabs = <T extends string>({
2121
setTab: (id: T) => void;
2222
}) => {
2323
return (
24-
<div className="border border-natural-200 rounded-xl flex items-center justify-between w-full max-w-[530px]">
24+
<div className="px-1 border border-natural-200 rounded-xl flex items-center justify-between w-full max-w-[530px]">
2525
{tabs.map(({ id, label, important, disabled }) => (
2626
<Tab
2727
key={id}
@@ -57,7 +57,7 @@ const Tab: React.FC<{
5757
<Typography
5858
tag="h6"
5959
className={cn(
60-
"relative font-normal md:font-medium text-tiny md:text-body whitespace-nowrap w-fit",
60+
"relative font-normal md:font-medium text-tiny md:text-body md:whitespace-nowrap w-fit",
6161
active
6262
? "text-brand-700"
6363
: "text-natural-500 group-hover:text-brand-500 group-active:text-brand-700"

packages/ui/src/locales/ar-eg.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,6 @@
925925
"payment.methods.wallet": "المحافظ الإلكترونة",
926926
"payment.methods.cards": "البطاقات",
927927
"payment.methods.fawry": "الدفع عن طريق فوري",
928-
"labels.jobs.student": "طالب",
929928
"labels.contact-us": "تواصل معنا",
930929
"labels.leave": "المغادرة",
931930
"labels.enable-notifications": "تفعيل الإشعارات",

0 commit comments

Comments
 (0)