Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 149 additions & 36 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@radix-ui/react-dropdown-menu": "^2.1.7",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-progress": "^1.1.8",
"@radix-ui/react-radio-group": "^1.3.7",
"@radix-ui/react-scroll-area": "^1.2.9",
"@radix-ui/react-select": "^2.2.5",
Expand All @@ -38,6 +39,7 @@
"@supabase/supabase-js": "^2.49.1",
"@tailwindcss/vite": "^4.0.14",
"@tanstack/react-query": "^5.81.5",
"@tanstack/react-table": "^8.21.3",
"axios": "^1.8.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
Expand Down
10 changes: 5 additions & 5 deletions src/.test/api/classes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jest.mock("../../api/endpoints", () => ({
LOG_ENDPOINT: "http://mock-api/logs",
}));

jest.mock("../../supabaseClient", () => {
jest.mock("../../lib/supabaseClient.ts", () => {
return {
supabase: {
from: jest.fn(() => ({
Expand Down Expand Up @@ -124,7 +124,7 @@ describe("class-api", () => {
const result = await updateStudentEnrollmentStatus(
"class-1",
"student-1",
"ENROLLED" as EnrollmentStatus
"ENROLLED" as EnrollmentStatus,
);

expect(result.success).toBe(true);
Expand Down Expand Up @@ -222,7 +222,7 @@ describe("class-api", () => {

const result = await getClassActivityByClassId("class-id");
expect(result.error).toBe(
"Invalid response: expected an array of activity logs"
"Invalid response: expected an array of activity logs",
);
});

Expand All @@ -233,7 +233,7 @@ describe("class-api", () => {
eqMock.mockReturnValueOnce(errorResult); // for .eq("student_id", ...)

// eslint-disable-next-line @typescript-eslint/no-require-imports
require("../../supabaseClient").supabase.from = jest.fn(() => ({
require("../../lib/supabaseClient.ts").supabase.from = jest.fn(() => ({
update: jest.fn(() => ({
eq: jest.fn().mockReturnValue({
eq: eqMock,
Expand All @@ -244,7 +244,7 @@ describe("class-api", () => {
const result = await updateStudentEnrollmentStatus(
"c1",
"s1",
EnrollmentStatus.ENROLLED
EnrollmentStatus.ENROLLED,
);

expect(result.success).toBe(false);
Expand Down
12 changes: 6 additions & 6 deletions src/.test/hooks/useAuth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { useLocation, useNavigate } from "react-router-dom";

// Mock Supabase client
jest.mock("../../supabaseClient", () => {
jest.mock("../../lib/supabaseClient.ts", () => {
return {
supabase: {
auth: {
Expand All @@ -27,7 +27,7 @@ jest.mock("react-router-dom", () => ({
useLocation: jest.fn(),
}));

import { supabase } from "../../supabaseClient";
import { supabase } from "../../lib/supabaseClient.ts";
const mockSupabaseAuth = supabase.auth as jest.Mocked<typeof supabase.auth>;
const mockUseNavigate = useNavigate as jest.Mock;
const mockUseLocation = useLocation as jest.Mock;
Expand Down Expand Up @@ -79,7 +79,7 @@ describe("useAuth", () => {
subscription: mockSubscription,
},
};
}
},
);
});

Expand Down Expand Up @@ -116,7 +116,7 @@ describe("useAuth", () => {
it("should handle auth state changes", async () => {
let capturedCallback: (
event: AuthChangeEvent,
session: Session | null
session: Session | null,
) => void;

mockSupabaseAuth.onAuthStateChange.mockImplementation((cb) => {
Expand Down Expand Up @@ -163,7 +163,7 @@ describe("useAuth", () => {
it("should handle null session from auth state change", async () => {
let capturedCallback: (
event: AuthChangeEvent,
session: Session | null
session: Session | null,
) => void;

mockSupabaseAuth.onAuthStateChange.mockImplementation((cb) => {
Expand All @@ -189,7 +189,7 @@ describe("useAuth", () => {

it("should handle unexpected getSession error gracefully", async () => {
mockSupabaseAuth.getSession.mockRejectedValue(
new Error("Failed to fetch session")
new Error("Failed to fetch session"),
);

mockSupabaseAuth.onAuthStateChange.mockImplementation(() => ({
Expand Down
2 changes: 1 addition & 1 deletion src/.test/hooks/useInstructorClasses.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const supabaseMocks: {
};

// Supabase module mock
jest.mock("../../supabaseClient", () => ({
jest.mock("../../lib/supabaseClient.ts", () => ({
supabase: {
from: (...args: any[]) => supabaseMocks.mockFrom(...args),
select: (...args: any[]) => supabaseMocks.mockSelect(...args),
Expand Down
15 changes: 8 additions & 7 deletions src/.test/hooks/useUserClasses.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jest.mock("../../hooks/useAuth", () => ({
useAuth: jest.fn(),
}));

jest.mock("../../supabaseClient", () => ({
jest.mock("../../lib/supabaseClient.ts", () => ({
supabase: {
from: jest.fn(),
},
Expand All @@ -28,7 +28,8 @@ const mockUseAuth = require("../../hooks/useAuth").useAuth as jest.Mock;
const mockGetUserClasses = getUserClasses as jest.MockedFunction<
typeof getUserClasses
>;
const mockFrom = require("../../supabaseClient").supabase.from as jest.Mock;
const mockFrom = require("../../lib/supabaseClient.ts").supabase
.from as jest.Mock;

const mockClassInfo: UserClassInfo = {
user_class: {
Expand Down Expand Up @@ -97,7 +98,7 @@ describe("useUserClasses", () => {
expect(result.current.selectedClassId).toBe("class-1");
expect(result.current.selectedClassType).toBe("class");
expect(result.current.selectedClass?.user_class.class_title).toBe(
"Physics"
"Physics",
);
});

Expand Down Expand Up @@ -135,7 +136,7 @@ describe("useUserClassStatus", () => {
});

const { result } = renderHook(() =>
useUserClassStatus("student-1", "class-1")
useUserClassStatus("student-1", "class-1"),
);

await waitFor(() => expect(result.current.loading).toBe(false));
Expand Down Expand Up @@ -164,7 +165,7 @@ describe("useUserClassStatus", () => {
});

const { result } = renderHook(() =>
useUserClassStatus("student-1", "class-1")
useUserClassStatus("student-1", "class-1"),
);

await waitFor(() => expect(result.current.loading).toBe(false));
Expand All @@ -187,7 +188,7 @@ describe("useUserClassStatus", () => {
});

const { result } = renderHook(() =>
useUserClassStatus("student-1", "class-1")
useUserClassStatus("student-1", "class-1"),
);

await waitFor(() => expect(result.current.loading).toBe(false));
Expand Down Expand Up @@ -220,7 +221,7 @@ describe("useUserClassStatus", () => {
expect(result.current.selectedClassId).toBe("non-class");
expect(result.current.selectedClassType).toBe("non-class");
expect(result.current.selectedClass?.user_class.class_title).toBe(
"Non-class Activities"
"Non-class Activities",
);
});

Expand Down
2 changes: 1 addition & 1 deletion src/api/endpoints.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** Gets the endpoint from the .env if it is available otherwise it uses localhost */
export const BASE_ENDPOINT =
import.meta.env.VITE_API_URL || "http://127.0.0.1:8080/api/v1";
import.meta.env.VITE_API_URL || "http://127.0.0.1:8080/api/v2";

/* Endpoint for creating new AI suggestions */
export const AI_SUGGESTION_ENDPOINT: string = `${BASE_ENDPOINT}/suggestion`;
Expand Down
4 changes: 2 additions & 2 deletions src/components/CustomSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ const CustomSelect = <T extends string>({
>
<SelectTrigger
className={cn(
"text-sm text-muted-foreground border-b border-slate-400 dark:border-sidebar-accent bg-gray-100 dark:bg-transparent",
className
"text-sm text-muted-foreground border-b border-slate-300 dark:border-sidebar-accent/60 bg-gray-100 dark:bg-transparent",
className,
)}
>
<SelectValue placeholder={placeholder} />
Expand Down
2 changes: 1 addition & 1 deletion src/components/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { DoorOpen, Menu, User2 } from "lucide-react";
import { UserRole } from "@/types/user";
import { useUser } from "@/context/UserContext";
import UserAvatar from "./UserAvatar";
import { supabase } from "@/supabaseClient";
import { supabase } from "@/lib/supabaseClient.ts";
import CloverLogo from "./CloverLogo";

/**
Expand Down
4 changes: 2 additions & 2 deletions src/components/ResetPasswordButton.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from "react";
import { useForm } from "react-hook-form";
import { updateUserPassword } from "../api/user";
import { supabase } from "../supabaseClient";
import { supabase } from "../lib/supabaseClient.ts";
import {
Dialog,
DialogContent,
Expand Down Expand Up @@ -40,7 +40,7 @@ export const ResetPasswordButton = ({ userId }: { userId?: string }) => {
if (userId) {
const { error } = await updateUserPassword(
userId,
form.getValues("newPassword")
form.getValues("newPassword"),
);

if (error) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/TypingLogs.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react";
import { supabase } from "@/supabaseClient";
import { supabase } from "@/lib/supabaseClient.ts";
import { User } from "@/types/user";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import CustomSelect from "@/components/CustomSelect";
Expand Down
2 changes: 1 addition & 1 deletion src/components/TypingLogsDownloadButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import DownloadFormattedFile from "@/components/DownloadFormattedFile";
import { supabase } from "@/supabaseClient";
import { supabase } from "@/lib/supabaseClient.ts";
import { User } from "@/types/user";
import { useEffect, useState } from "react";

Expand Down
26 changes: 26 additions & 0 deletions src/components/ui/progress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from "react"
import * as ProgressPrimitive from "@radix-ui/react-progress"

import { cn } from "@/lib/utils"

const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
>(({ className, value, ...props }, ref) => (
<ProgressPrimitive.Root
ref={ref}
className={cn(
"relative h-2 w-full overflow-hidden rounded-full bg-primary/20",
className
)}
{...props}
>
<ProgressPrimitive.Indicator
className="h-full w-full flex-1 bg-primary transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>
))
Progress.displayName = ProgressPrimitive.Root.displayName

export { Progress }
10 changes: 5 additions & 5 deletions src/components/ui/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const TableFooter = React.forwardRef<
ref={ref}
className={cn(
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
className
className,
)}
{...props}
/>
Expand All @@ -59,7 +59,7 @@ const TableRow = React.forwardRef<
ref={ref}
className={cn(
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className
className,
)}
{...props}
/>
Expand All @@ -73,8 +73,8 @@ const TableHead = React.forwardRef<
<th
ref={ref}
className={cn(
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] bg-gray-200 dark:bg-transparent",
className,
)}
{...props}
/>
Expand All @@ -89,7 +89,7 @@ const TableCell = React.forwardRef<
ref={ref}
className={cn(
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
className,
)}
{...props}
/>
Expand Down
Loading