Skip to content

Commit 4154cd7

Browse files
fix: copilot suggestions
1 parent c66887d commit 4154cd7

12 files changed

Lines changed: 100 additions & 124 deletions

File tree

client/src/components/DropdownNotificationsMenu/DropdownNotificationsMenu.tsx

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,10 @@ export const DropdownNotificationsMenu = ({
154154
)}
155155
>
156156
<div className="flex flex-col items-start gap-1">
157-
<span className="text-sm font-medium text-light-100">
158-
<div className="flex items-center justify-center gap-1">
159-
{option.sender.name}
160-
<span>
161-
<Badge title="Messages" />
162-
</span>
163-
</div>
164-
</span>
157+
<div className="flex items-center gap-1 text-sm font-medium text-light-100">
158+
<span>{option.sender.name}</span>
159+
<Badge title="Messages" />
160+
</div>
165161
<span className="line-clamp-1 text-sm text-light-400">
166162
{option.message.text}
167163
</span>
@@ -184,14 +180,10 @@ export const DropdownNotificationsMenu = ({
184180
)}
185181
>
186182
<div className="flex flex-col items-start gap-1">
187-
<span className="text-sm font-medium text-light-100">
188-
<div className="flex items-center justify-center gap-1">
189-
{option.actor.name}
190-
<span>
191-
<Badge title="Appointments" />
192-
</span>
193-
</div>
194-
</span>
183+
<div className="flex items-center gap-1 text-sm font-medium text-light-100">
184+
<span>{option.actor.name}</span>
185+
<Badge title="Messages" />
186+
</div>
195187
<span className="text-sm text-light-400">
196188
{option.status === "approved"
197189
? "Approved your appointment"

client/src/components/controlPanel/IndicatorTrigger.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { getAvatarUrl } from "../../api/upload/upload.api";
88
import type { LinkOption } from "../../types/linkOptionsType";
99
import { useNotificationFeedStore } from "../../store/notificationFeed.store.ts";
1010
import { twMerge } from "tailwind-merge";
11-
import { lockScroll } from "../../util/modalScroll.util.ts";
11+
import { lockScroll, unlockScroll } from "../../util/modalScroll.util.ts";
1212
import { NotificationBar } from "../notificationBar/NotificationBar.tsx";
1313

1414
type Props = {
@@ -27,8 +27,17 @@ export const IndicatorTrigger = ({ options, variant = "private" }: Props) => {
2727
);
2828

2929
const onOpenNotificationsMenu = () => {
30-
setOpenNotificationMenu(!openNotificationMenu);
31-
lockScroll();
30+
setOpenNotificationMenu((prev) => {
31+
const next = !prev;
32+
33+
if (next) {
34+
lockScroll();
35+
} else {
36+
unlockScroll();
37+
}
38+
39+
return next;
40+
});
3241
};
3342

3443
const wrapperClass =

client/src/components/headerPrivate/TopBar.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ProfileIndicator } from "../profileIndicator/ProfileIndicator.tsx";
44
import { Logo } from "../logo/Logo.tsx";
55
import { NotificationBar } from "../notificationBar/NotificationBar.tsx";
66
import { useNotificationFeedStore } from "../../store/notificationFeed.store.ts";
7-
import { lockScroll } from "../../util/modalScroll.util.ts";
7+
import { lockScroll, unlockScroll } from "../../util/modalScroll.util.ts";
88
import { useAuthSessionStore } from "../../store/authSession.store.ts";
99

1010
export const TopBar = () => {
@@ -17,8 +17,17 @@ export const TopBar = () => {
1717
const user = useAuthSessionStore((s) => s.user);
1818

1919
const onOpenNotificationsMenu = () => {
20-
setOpenNotificationMenu(!openNotificationMenu);
21-
lockScroll();
20+
setOpenNotificationMenu((prev) => {
21+
const next = !prev;
22+
23+
if (next) {
24+
lockScroll();
25+
} else {
26+
unlockScroll();
27+
}
28+
29+
return next;
30+
});
2231
};
2332
return (
2433
<>

client/src/components/notificationBar/NotificationBar.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,13 @@ export const NotificationBar = ({
2727
variant="link"
2828
className="relative"
2929
onClick={onOpenNotificationsMenu}
30+
aria-label="Notifications"
31+
aria-expanded={openMenu}
32+
aria-haspopup="menu"
3033
>
3134
<div
3235
className="absolute right-2 top-1 flex items-center justify-center
33-
text-[12px] min-w-4 min-h-4 bg-danger-100 rounded-full text-light-100"
36+
text-[12px] min-w-4 min-h-4 bg-danger-100 rounded-full text-light-100"
3437
>
3538
{unreadNotifications}
3639
</div>

client/src/features/notifications/mutation/useDeleteAllReadNotifications.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import { notificationKeys } from "../../queryKeys.ts";
77

88
export const useDeleteAllReadNotifications = () => {
99
const queryClient = useQueryClient();
10-
const items = useNotificationFeedStore((s) => s.items);
11-
const setItems = useNotificationFeedStore((s) => s.setItems);
1210
const notifyError = useNotificationStore((s) => s.error);
1311

1412
return useMutation({
1513
mutationFn: deleteAllReadNotifications,
1614
onSuccess: () => {
15+
const { items, setItems } = useNotificationFeedStore.getState();
16+
1717
const unreadOnly = items.filter((item) => !item.isRead);
1818

1919
setItems(unreadOnly);

client/src/features/notifications/mutation/useMarkOneNotificationAsRead.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,17 @@ import { getErrorMessage } from "../../../util/ErrorUtil.ts";
88
export const useMarkOneNotificationAsRead = () => {
99
const queryClient = useQueryClient();
1010
const notifyError = useNotificationStore((s) => s.error);
11-
const setItems = useNotificationFeedStore((s) => s.setItems);
12-
const items = useNotificationFeedStore((s) => s.items);
1311

1412
return useMutation({
1513
mutationFn: markNotificationAsRead,
1614
onSuccess: (_, notificationId) => {
15+
const { items, setItems } = useNotificationFeedStore.getState();
16+
1717
const updated = items.map((item) =>
1818
item.id === notificationId ? { ...item, isRead: true } : item,
1919
);
2020

2121
setItems(updated);
22-
2322
queryClient.setQueryData(notificationKeys.root, updated);
2423
},
2524
onError: (error) => {

client/src/features/notifications/query/useQueryNotifications.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const useNotificationsQuery = () => {
2323
const msg = getErrorMessage(query.error);
2424
notifyError(msg ?? "Failed to load notifications");
2525
}
26-
}, [query.isError, query.isSuccess, query.error, notifyError]);
26+
}, [query.isError, query.error, notifyError]);
2727

2828
return query;
2929
};

client/src/types/notificationFeed.types.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

server/src/controllers/appointment.controller.ts

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
import { getIO } from "../socket/io.holder.js";
2222
import { TeacherQuery } from "../repositories/queryRepositories/teacher.query.js";
2323
import { NotificationService } from "../services/notifications/notifications.service.js";
24+
import { logError } from "../utils/logging.js";
2425

2526
@injectable()
2627
export class AppointmentController {
@@ -134,6 +135,7 @@ export class AppointmentController {
134135
next: NextFunction,
135136
) {
136137
const io = getIO();
138+
137139
try {
138140
const appointment = await this.appointmentService.updateAppointmentStatus(
139141
req.params.id,
@@ -144,45 +146,40 @@ export class AppointmentController {
144146
return res.status(404).json({ message: "Appointment not found" });
145147
}
146148

147-
const teacher = await this.teacherQuery.getTeacherById(
148-
appointment.teacherId,
149-
);
150-
151-
if (!teacher) {
152-
return res.status(404).json({ message: "Teacher not found" });
153-
}
154-
155149
if (
156150
appointment.status === "approved" ||
157151
appointment.status === "rejected"
158152
) {
159-
const teacher = await this.teacherQuery.getTeacherById(
160-
appointment.teacherId,
161-
);
162-
163-
if (!teacher) {
164-
return res.status(404).json({ message: "Teacher not found" });
165-
}
153+
try {
154+
const teacher = await this.teacherQuery.getTeacherById(
155+
appointment.teacherId,
156+
);
166157

167-
const notification = await this.notificationService.createNotification({
168-
userId: appointment.studentId,
169-
type: "appointmentStatus",
170-
appointmentId: appointment.id,
171-
status: appointment.status,
172-
actor: {
173-
id: teacher.id,
174-
name: `${teacher.firstName} ${teacher.lastName}`.trim(),
175-
imageUrl: teacher.profileImageUrl ?? null,
176-
},
177-
lesson: appointment.lesson,
178-
date: appointment.date,
179-
time: appointment.time,
180-
});
158+
if (teacher) {
159+
const notification =
160+
await this.notificationService.createNotification({
161+
userId: appointment.studentId,
162+
type: "appointmentStatus",
163+
appointmentId: appointment.id,
164+
status: appointment.status,
165+
actor: {
166+
id: teacher.id,
167+
name: `${teacher.firstName} ${teacher.lastName}`.trim(),
168+
imageUrl: teacher.profileImageUrl ?? null,
169+
},
170+
lesson: appointment.lesson,
171+
date: appointment.date,
172+
time: appointment.time,
173+
});
181174

182-
io?.to(`user:${appointment.studentId}`).emit(
183-
"notification:new",
184-
notification,
185-
);
175+
io?.to(`user:${appointment.studentId}`).emit(
176+
"notification:new",
177+
notification,
178+
);
179+
}
180+
} catch (notificationError) {
181+
logError(notificationError);
182+
}
186183
}
187184

188185
return res.status(200).json(appointment);

server/src/controllers/auth.controller.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export class AuthController {
9393

9494
res.cookie("refreshToken", refreshToken, {
9595
httpOnly: true,
96-
secure: false,
96+
secure: process.env.NODE_ENV === "production",
9797
path: "/",
9898
maxAge: 2 * 60 * 60 * 1000,
9999
sameSite: "lax",
@@ -142,7 +142,7 @@ export class AuthController {
142142

143143
res.cookie("refreshToken", newRefreshToken, {
144144
httpOnly: true,
145-
secure: false,
145+
secure: process.env.NODE_ENV === "production",
146146
path: "/",
147147
maxAge: 2 * 60 * 60 * 1000,
148148
});
@@ -278,7 +278,7 @@ export class AuthController {
278278

279279
res.cookie("refreshToken", refreshToken, {
280280
httpOnly: true,
281-
secure: false,
281+
secure: process.env.NODE_ENV === "production",
282282
path: "/",
283283
maxAge: 2 * 60 * 60 * 1000,
284284
sameSite: "lax",
@@ -312,7 +312,7 @@ export class AuthController {
312312

313313
res.cookie("refreshToken", refreshToken, {
314314
httpOnly: true,
315-
secure: false,
315+
secure: process.env.NODE_ENV === "production",
316316
path: "/",
317317
maxAge: 2 * 60 * 60 * 1000,
318318
sameSite: "lax",

0 commit comments

Comments
 (0)