diff --git a/apps/quick-learn-frontend/src/app/(Auth)/forgot-password/ForgotPassword.tsx b/apps/quick-learn-frontend/src/app/(Auth)/forgot-password/ForgotPassword.tsx
index 6554306e..61639196 100644
--- a/apps/quick-learn-frontend/src/app/(Auth)/forgot-password/ForgotPassword.tsx
+++ b/apps/quick-learn-frontend/src/app/(Auth)/forgot-password/ForgotPassword.tsx
@@ -1,6 +1,5 @@
'use client';
import { z } from 'zod';
-import Link from 'next/link';
import React, { useState } from 'react';
import { useRouter } from 'next/navigation';
import { forgotPasswordSchema } from './forgotPasswordSchema';
@@ -11,6 +10,7 @@ import { forgotPasswordApiCall } from '@src/apiServices/authService';
import { toast } from 'react-toastify';
import { showApiErrorInToast } from '@src/utils/toastUtils';
import { en } from '@src/constants/lang/en';
+import { SuperLink } from '@src/utils/HiLink';
const ForgotPassword = () => {
const router = useRouter();
@@ -49,12 +49,12 @@ const ForgotPassword = () => {
/>
{en.Auth.Login}
-
{en.Auth.SignIn}
-
+
>
);
diff --git a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/approvals/approvalList.tsx b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/approvals/approvalList.tsx
index 8e330078..68bd9192 100644
--- a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/approvals/approvalList.tsx
+++ b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/approvals/approvalList.tsx
@@ -3,13 +3,13 @@ import { DateFormats } from '@src/constants/dateFormats';
import { en } from '@src/constants/lang/en';
import { RouteEnum } from '@src/constants/route.enum';
import { format } from 'date-fns';
-import Link from 'next/link';
import { useEffect } from 'react';
import ApprovalListSkeleton from './ApprovalListSkeleton';
import { RootState } from '@src/store/store';
import { fetchUnapprovedLessons } from '@src/store/features/approvalSlice';
import { useAppDispatch, useAppSelector } from '@src/store/hooks';
import { updateSystemPreferencesData } from '@src/store/features/systemPreferenceSlice';
+import { SuperLink } from '@src/utils/HiLink';
const columns = [
en.common.lesson,
@@ -83,12 +83,12 @@ const ApprovalList = () => {
className="px-4 py-2 font-medium text-gray-900 whitespace-nowrap dark:text-white"
>
-
{lesson.name}
-
+
diff --git a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/content/[roadmap]/[course]/view/[lesson]/lessonDetails.tsx b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/content/[roadmap]/[course]/view/[lesson]/lessonDetails.tsx
index 72217ca2..92a70b89 100644
--- a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/content/[roadmap]/[course]/view/[lesson]/lessonDetails.tsx
+++ b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/content/[roadmap]/[course]/view/[lesson]/lessonDetails.tsx
@@ -9,9 +9,9 @@ import ViewLesson from '@src/shared/components/ViewLesson';
import { TBreadcrumb } from '@src/shared/types/breadcrumbType';
import { TLesson, TRoadmap } from '@src/shared/types/contentRepository';
import { selectUser } from '@src/store/features/userSlice';
+import { SuperLink } from '@src/utils/HiLink';
import { showApiErrorInToast } from '@src/utils/toastUtils';
import { UserTypeIdEnum } from 'lib/shared/src';
-import Link from 'next/link';
import { useParams, useRouter } from 'next/navigation';
import { useEffect, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
@@ -87,13 +87,13 @@ const LessonDetails = () => {
<>
{canEdit && (
-
| Edit
-
+
)}
>
);
diff --git a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/layout.tsx b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/layout.tsx
index e57e4d81..15d3b021 100644
--- a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/layout.tsx
+++ b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/layout.tsx
@@ -3,11 +3,16 @@ import { getUser } from '@src/apiServices/authService';
import { RouteEnum } from '@src/constants/route.enum';
import { useFetchContentRepositoryMetadata } from '@src/context/contextHelperService';
import Navbar from '@src/shared/components/Navbar';
+import { TUser } from '@src/shared/types/userTypes';
import { selectHideNavbar } from '@src/store/features/uiSlice';
import { setUser } from '@src/store/features/userSlice';
import { useAppDispatch, useAppSelector } from '@src/store/hooks';
import { usePathname } from 'next/navigation';
-import { useEffect } from 'react';
+import { useEffect, useRef } from 'react';
+
+// Create a module-level flag for the entire session
+let hasInitialFetchStarted = false;
+let currentFetchPromise: Promise | null = null;
export default function Layout({
children,
@@ -19,26 +24,38 @@ export default function Layout({
const pathname = usePathname();
const { fetchMetadata, fetchApprovalData } =
useFetchContentRepositoryMetadata();
+ const isFetching = useRef(false);
useEffect(() => {
- const fetchData = async () => {
- getUser()
- .then((res) => {
+ if (hasInitialFetchStarted || isFetching.current || currentFetchPromise) {
+ return;
+ }
+
+ isFetching.current = true;
+
+ currentFetchPromise = getUser()
+ .then(async (res) => {
+ if (!hasInitialFetchStarted) {
+ hasInitialFetchStarted = true;
dispatch(setUser(res.data));
- fetchMetadata(res?.data.user_type_id);
- fetchApprovalData(res?.data.user_type_id);
- })
- .catch((err) => console.log(err));
- };
- fetchData();
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
-
- // Add paths that should be full width
- const fullWidthPaths = [RouteEnum.MY_LEARNING_PATH];
- const isFullWidth = fullWidthPaths.some((path) => pathname?.startsWith(path));
+ await fetchMetadata(res?.data.user_type_id);
+ await fetchApprovalData(res?.data.user_type_id);
+ }
+ return res.data;
+ })
+ .catch((err) => {
+ hasInitialFetchStarted = false;
+ currentFetchPromise = null;
+ console.log(err);
+ })
+ .finally(() => {
+ isFetching.current = false;
+ });
+ }, [dispatch, fetchMetadata, fetchApprovalData]);
+ const fullWidthPaths = [RouteEnum.MY_LEARNING_PATH];
+ const isFullWidth = fullWidthPaths.some((path) => pathname?.startsWith(path));
const mainClasses = isFullWidth
? 'mt-16 w-full'
: 'max-w-screen-2xl mx-auto mt-16 py-3 px-4 sm:py-5 lg:px-8';
diff --git a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/TeamMemberListing.tsx b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/TeamMemberListing.tsx
index 7a47b906..bbdf29b7 100644
--- a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/TeamMemberListing.tsx
+++ b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/TeamMemberListing.tsx
@@ -1,6 +1,5 @@
'use client';
import { RouteEnum } from '@src/constants/route.enum';
-import Link from 'next/link';
import { useMemo, useState } from 'react';
import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
import { TUserType } from '@src/shared/types/userTypes';
@@ -15,6 +14,7 @@ import {
} from '@src/store/features/teamSlice';
import { useAppDispatch, useAppSelector } from '@src/store/hooks';
import { en } from '@src/constants/lang/en';
+import { SuperLink } from '@src/utils/HiLink';
const TeamMemberListing = () => {
const dispatch = useAppDispatch();
const [searchInputValue, setSearchInputValue] = useState(''); // Local state for input value
@@ -60,6 +60,12 @@ const TeamMemberListing = () => {
debouncedSearch(value); // Debounce the Redux update and API call
};
+ function showRange() {
+ const initial = filteredTotal === 0 ? 0 : (currentPage - 1) * 10 + 1;
+ const end = Math.min(currentPage * 10, filteredTotal);
+ return `${initial} ${en.teams.to} ${end} ${en.teams.of} ${filteredTotal}`;
+ }
+
return (
<>
@@ -81,13 +87,13 @@ const TeamMemberListing = () => {
onChange={handleSearchChange}
id="search"
/>
-
{en.teams.addNewMember}
-
+
@@ -131,22 +137,7 @@ const TeamMemberListing = () => {
{en.teams.showing}{' '}
-
- {currentPage > 1
- ? (currentPage - 1) * 10 + 1
- : filteredTotal === 0
- ? 0
- : 1}
- {' '}
- {en.teams.to}{' '}
-
- {currentPage * 10 <= filteredTotal
- ? currentPage * 10
- : filteredTotal}
- {' '}
- {en.teams.to}
-
- {filteredTotal}{' '}
+ {showRange()}{' '}
{en.teams.results}
diff --git a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/TeamTable.tsx b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/TeamTable.tsx
index 37367369..2b36519b 100644
--- a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/TeamTable.tsx
+++ b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/TeamTable.tsx
@@ -1,7 +1,6 @@
// components/TeamTable.tsx
import { useEffect } from 'react';
import { format } from 'date-fns';
-import Link from 'next/link';
import { toast } from 'react-toastify';
import { DateFormats } from '@src/constants/dateFormats';
import { CustomClipBoardIcon } from '@src/shared/components/UIElements';
@@ -11,7 +10,7 @@ import TeamMemberListingSkeleton from './TeamMemberListingSkeleton';
import { RootState } from '@src/store/store';
import { fetchTeamMembers } from '@src/store/features/teamSlice';
import { useAppDispatch, useAppSelector } from '@src/store/hooks';
-
+import { SuperLink } from '@src/utils/HiLink';
const TeamTable = () => {
const dispatch = useAppDispatch();
const {
@@ -94,10 +93,10 @@ const TeamTable = () => {
key={user.uuid}
className="border-b border-gray-200 hover:bg-gray-100"
>
-
-
+ |
+
{user.first_name} {user.last_name}
-
+
|
diff --git a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/[member]/teamMemberDetails.tsx b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/[member]/teamMemberDetails.tsx
index 1c414dca..09ac23cf 100644
--- a/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/[member]/teamMemberDetails.tsx
+++ b/apps/quick-learn-frontend/src/app/(Dashboard)/dashboard/teams/[member]/teamMemberDetails.tsx
@@ -1,6 +1,5 @@
'use client';
-import Link from 'next/link';
-import { useParams } from 'next/navigation';
+import { useParams, useRouter } from 'next/navigation';
import { useCallback, useEffect, useState } from 'react';
import {
CursorArrowRippleIcon,
@@ -31,7 +30,6 @@ import {
showApiMessageInToast,
} from '@src/utils/toastUtils';
import { Tooltip } from 'flowbite-react';
-import { useRouter } from 'next/navigation';
import EmptyState from '@src/shared/components/EmptyStatePlaceholder';
import TeamMemberDetailsSkeleton from './TeamMemberDetailsSkeleton';
import {
@@ -47,6 +45,7 @@ import {
import ActivityGraph, { Course } from '@src/shared/modals/ActivityGraph';
import { useDispatch } from 'react-redux';
import { decrementTotalUsers } from '@src/store/features/teamSlice';
+import { SuperLink } from '@src/utils/HiLink';
const defaultlinks: TBreadcrumb[] = [{ name: 'Team', link: RouteEnum.TEAM }];
@@ -65,9 +64,8 @@ const TeamMemberDetails = () => {
TRoadmapCategories[]
>([]);
const [userProgress, setUserProgress] = useState ([]);
- const [userDailyLessonProgressData, setUserDalyLessonProgressData] = useState<
- TUserDailyProgress[]
- >([]);
+ const [userDailyLessonProgressData, setUserDailyLessonProgressData] =
+ useState([]);
const [allCourses, setAllCourses] = useState([]);
const [userActivityModal, setUserActivityModal] = useState(false);
@@ -101,7 +99,7 @@ const TeamMemberDetails = () => {
// Set the user's daily lesson progress data
getUserDailyLessonProgress(Number(userId))
- .then((res) => setUserDalyLessonProgressData(res.data))
+ .then((res) => setUserDailyLessonProgressData(res.data))
.catch((e) => showApiErrorInToast(e));
setLinks([
@@ -217,19 +215,19 @@ const TeamMemberDetails = () => {
{member?.first_name} {member?.last_name}
- ({member?.assigned_roadmaps?.length || 0} {en.common.roadmaps},{' '}
+ ({member?.assigned_roadmaps?.length ?? 0} {en.common.roadmaps},{' '}
{allCourses.length} {en.common.courses})
{/* Action Buttons */}
-
-
+
diff --git a/apps/quick-learn-frontend/src/app/layout.tsx b/apps/quick-learn-frontend/src/app/layout.tsx
index 3f79b7c6..ee0f0556 100644
--- a/apps/quick-learn-frontend/src/app/layout.tsx
+++ b/apps/quick-learn-frontend/src/app/layout.tsx
@@ -1,8 +1,6 @@
-'use client';
import 'flowbite/dist/flowbite.css';
import './global.css';
import { ToastContainer } from 'react-toastify';
-import 'react-toastify/dist/ReactToastify.css';
import { ReduxProvider } from '@src/store/provider';
import { getClientIp } from '@src/apiServices/ipService';
diff --git a/apps/quick-learn-frontend/src/context/contextHelperService.ts b/apps/quick-learn-frontend/src/context/contextHelperService.ts
index 46965145..052770f0 100644
--- a/apps/quick-learn-frontend/src/context/contextHelperService.ts
+++ b/apps/quick-learn-frontend/src/context/contextHelperService.ts
@@ -1,11 +1,14 @@
'use client';
-import { getContentRepositoryMetadata } from '@src/apiServices/contentRepositoryService';
+import {
+ getContentRepositoryMetadata,
+ getSystemPreferences,
+} from '@src/apiServices/contentRepositoryService';
import { updateContentRepository } from '@src/store/features/metadataSlice';
import { UserTypeIdEnum } from 'lib/shared/src';
import { usePathname } from 'next/navigation';
import { useAppDispatch } from '@src/store/hooks';
import { RouteEnum } from '@src/constants/route.enum';
-import { fetchSystemPreferences } from '@src/store/features/systemPreferenceSlice';
+import { updateSystemPreferencesData } from '@src/store/features/systemPreferenceSlice';
// Custom hook to fetch content repository metadata
export const useFetchContentRepositoryMetadata = (forceFetch = false) => {
@@ -26,12 +29,13 @@ export const useFetchContentRepositoryMetadata = (forceFetch = false) => {
}
};
- const fetchApprovalData = (user_type: number) => {
+ const fetchApprovalData = async (user_type: number) => {
if (
path !== RouteEnum.APPROVALS &&
![UserTypeIdEnum.EDITOR, UserTypeIdEnum.MEMBER].includes(user_type)
) {
- dispatch(fetchSystemPreferences());
+ const res = await getSystemPreferences();
+ dispatch(updateSystemPreferencesData(res.data));
}
};
diff --git a/apps/quick-learn-frontend/src/shared/components/Breadcrumb.tsx b/apps/quick-learn-frontend/src/shared/components/Breadcrumb.tsx
index 1bd36886..f02a9d42 100644
--- a/apps/quick-learn-frontend/src/shared/components/Breadcrumb.tsx
+++ b/apps/quick-learn-frontend/src/shared/components/Breadcrumb.tsx
@@ -1,6 +1,6 @@
import { TBreadcrumb } from '../types/breadcrumbType';
import { FC } from 'react';
-import Link from 'next/link';
+import { SuperLink } from '@src/utils/HiLink';
import { ArrowRightIcon, HomeIcon } from './UIElements';
interface Props {
@@ -16,13 +16,13 @@ function customLink({ link, name }: TBreadcrumb, isLast = false) {
);
}
return (
-
{name}
-
+
);
}
@@ -34,7 +34,7 @@ const Breadcrumb: FC = ({ links }) => {
{links.map(({ name, link }, index) => (
{index != 0 && index != links.length && }
{index == 0 ? : ''}
diff --git a/apps/quick-learn-frontend/src/shared/components/Card.tsx b/apps/quick-learn-frontend/src/shared/components/Card.tsx
index 99da6adb..d5d45568 100644
--- a/apps/quick-learn-frontend/src/shared/components/Card.tsx
+++ b/apps/quick-learn-frontend/src/shared/components/Card.tsx
@@ -1,7 +1,7 @@
-import Link from 'next/link';
import { FC, useRef, useEffect, useState } from 'react';
import { ExclamationTriangleIcon, PlusIcon } from '@heroicons/react/20/solid';
import { en } from '@src/constants/lang/en';
+import { SuperLink } from '@src/utils/HiLink';
interface CardProps {
title: string;
description: string;
@@ -130,9 +130,9 @@ const Card: FC = ({
}
return (
-
+
-
+
);
};
diff --git a/apps/quick-learn-frontend/src/shared/components/Navbar.tsx b/apps/quick-learn-frontend/src/shared/components/Navbar.tsx
index 43a68a90..ccf3a548 100644
--- a/apps/quick-learn-frontend/src/shared/components/Navbar.tsx
+++ b/apps/quick-learn-frontend/src/shared/components/Navbar.tsx
@@ -8,8 +8,8 @@ import {
MenuItem,
MenuItems,
} from '@headlessui/react';
-import Link from 'next/link';
import Image from 'next/image';
+import { SuperLink } from '@src/utils/HiLink';
import { usePathname } from 'next/navigation';
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline';
@@ -103,7 +103,7 @@ const Navbar = () => {
async function doLogout() {
try {
- localStorage.removeItem('searchHistory');
+ localStorage.clear();
await logoutApiCall();
window.location.href = '/';
} catch (error) {
@@ -143,12 +143,12 @@ const Navbar = () => {
return (
);
};
@@ -171,19 +171,19 @@ const Navbar = () => {
-
{en.common.quickLearn}
-
+
{links.map((item, index) => (
- {
>
{item.name}
{showApprovalCount(item, 'desktop')}
-
+
))}
@@ -285,12 +285,12 @@ const Navbar = () => {
.map((item) => renderMenuItem(item))}
{user?.user_type_id !== UserTypeIdEnum.SUPERADMIN && (
)}
@@ -364,7 +364,7 @@ const Navbar = () => {
{
{menuItems.map(
(item, index) =>
item.isExtended && (
- {
className="block rounded-md px-3 py-2 text-base font-medium text-gray-400 hover:bg-gray-700 hover:text-white"
>
{item.name}
-
+
),
)}
diff --git a/apps/quick-learn-frontend/src/shared/components/ProgressCard.tsx b/apps/quick-learn-frontend/src/shared/components/ProgressCard.tsx
index a0bb8347..a3bd210c 100644
--- a/apps/quick-learn-frontend/src/shared/components/ProgressCard.tsx
+++ b/apps/quick-learn-frontend/src/shared/components/ProgressCard.tsx
@@ -1,11 +1,11 @@
'use client';
import React, { useEffect, useState, forwardRef } from 'react';
-import Link from 'next/link';
import { MdOutlineDone } from 'react-icons/md';
import { format } from 'date-fns';
import { DateFormats } from '@src/constants/dateFormats';
import { LessonProgress } from '../types/LessonProgressTypes';
import { en } from '@src/constants/lang/en';
+import { SuperLink } from '@src/utils/HiLink';
interface ProgressCardProps {
id: number;
@@ -46,7 +46,12 @@ const ProgressCard = forwardRef(
const baseClassName = `inline-block col-span-1 rounded-lg bg-white shadow-sm hover:shadow-lg border border-gray-100 group relative transition-shadow duration-200 w-full ${className}`;
return (
-
+
@@ -123,7 +128,7 @@ const ProgressCard = forwardRef(
)}
-
+
);
},
);
diff --git a/apps/quick-learn-frontend/src/shared/components/RouteTab.tsx b/apps/quick-learn-frontend/src/shared/components/RouteTab.tsx
index c05d75c4..fa447ab1 100644
--- a/apps/quick-learn-frontend/src/shared/components/RouteTab.tsx
+++ b/apps/quick-learn-frontend/src/shared/components/RouteTab.tsx
@@ -1,4 +1,4 @@
-import Link from 'next/link';
+import { SuperLink } from '@src/utils/HiLink';
import React from 'react';
interface RouteTabProps {
@@ -6,7 +6,6 @@ interface RouteTabProps {
name: string;
baseLink: string;
course_id?: number;
- roadmap_id?: number;
type: 'roadmaps' | 'courses' | 'lesson';
onClick?: () => void;
}
@@ -28,14 +27,15 @@ const RouteTab: React.FC = ({
const link = navLinks[type];
return (
-
-
+
-
+
+
);
};
diff --git a/apps/quick-learn-frontend/src/shared/components/Sidebar.tsx b/apps/quick-learn-frontend/src/shared/components/Sidebar.tsx
index 70acd35a..8446fe1c 100644
--- a/apps/quick-learn-frontend/src/shared/components/Sidebar.tsx
+++ b/apps/quick-learn-frontend/src/shared/components/Sidebar.tsx
@@ -1,8 +1,8 @@
'use client';
-import Link from 'next/link';
import React, { FC } from 'react';
import { RouteEnum } from '@src/constants/route.enum';
import { usePathname } from 'next/navigation';
+import { SuperLink } from '@src/utils/HiLink';
export type TNavLink = {
title: string;
@@ -19,7 +19,7 @@ const Sidebar: FC = ({ navLinks }) => {
return (
);
diff --git a/apps/quick-learn-frontend/src/shared/formElements/InputField.tsx b/apps/quick-learn-frontend/src/shared/formElements/InputField.tsx
index 970fd876..212cdc06 100644
--- a/apps/quick-learn-frontend/src/shared/formElements/InputField.tsx
+++ b/apps/quick-learn-frontend/src/shared/formElements/InputField.tsx
@@ -1,9 +1,9 @@
import React, { FC, useEffect, useState } from 'react';
-import Link from 'next/link';
import { FieldType } from '../types/formTypes';
import { OpenEyeIcon, ClosedEyeIcon } from '../components/UIElements';
import { FieldValues, UseFormRegister } from 'react-hook-form';
import { RouteEnum } from '@src/constants/route.enum';
+import { SuperLink } from '@src/utils/HiLink';
interface Props {
label?: string;
@@ -50,14 +50,14 @@ const InputField: FC = ({
{/* TODO: Remove this and make independent component for login */}
{name === 'rememberMe' && (
-
Forgot password?
-
+
)}
);
@@ -88,12 +88,12 @@ const InputField: FC = ({
| |