diff --git a/backend/src/database/helpful_links.go b/backend/src/database/helpful_links.go index b40078df..6c247f7e 100644 --- a/backend/src/database/helpful_links.go +++ b/backend/src/database/helpful_links.go @@ -16,7 +16,8 @@ func (db *DB) GetHelpfulLinks(page, perPage int, search, orderBy string, onlyVis subQuery := db.Table("open_content_favorites f"). Select("1"). - Where("f.content_id = helpful_links.id AND f.user_id = ?", userID) + Where(`f.content_id = helpful_links.id AND f.user_id = ? + AND f.open_content_provider_id = helpful_links.open_content_provider_id`, userID) tx := db.Model(&models.HelpfulLink{}).Select("helpful_links.*, EXISTS(?) as is_favorited", subQuery) var total int64 diff --git a/frontend/src/Components/Navbar.tsx b/frontend/src/Components/Navbar.tsx index dc4a7fd2..2bbe6839 100644 --- a/frontend/src/Components/Navbar.tsx +++ b/frontend/src/Components/Navbar.tsx @@ -16,15 +16,11 @@ import { RssIcon, RectangleStackIcon, CogIcon, - LightBulbIcon + LightBulbIcon, + RocketLaunchIcon, + ArrowTrendingUpIcon } from '@heroicons/react/24/solid'; -import { - getDashboardLink, - handleLogout, - hasFeature, - isAdministrator, - useAuth -} from '@/useAuth'; +import { handleLogout, hasFeature, isAdministrator, useAuth } from '@/useAuth'; import Modal from '@/Components/Modal'; import ULIComponent from './ULIComponent'; import { Link } from 'react-router-dom'; @@ -52,12 +48,6 @@ export default function Navbar({ const confirmSeedModal = useRef(null); const [seedInProgress, setSeedInProgress] = useState(false); - const dashboardTitleStudent = new Map([ - ['/trending-content', 'Trending Content'], - ['/learning-path', 'Learning Path'], - ['/program-tracker', 'Program Tracker'] - ]); - const handleSeedDemoData = async () => { setSeedInProgress(true); const resp = await API.post(`auth/demo-seed`, {}); @@ -134,18 +124,29 @@ export default function Navbar({ Operational Insights + {hasFeature( + user, + FeatureAccess.OpenContentAccess + ) && ( +
  • + + + Knowledge Center + +
  • + )} {hasFeature(user, FeatureAccess.ProviderAccess) && ( <>
  • - + - Course Catalog + Learning Platforms
  • - + - Learning Platforms + Course Catalog
  • @@ -158,17 +159,6 @@ export default function Navbar({ )} - {hasFeature( - user, - FeatureAccess.OpenContentAccess - ) && ( -
  • - - - Knowledge Center - -
  • - )}
  • @@ -192,25 +182,54 @@ export default function Navbar({ ) : ( <> -
  • - - - {dashboardTitleStudent.get( - getDashboardLink(user) - ) ?? 'Home'} - -
  • - {hasFeature(user, FeatureAccess.ProviderAccess) && ( - <> - {getDashboardLink(user) !== - '/learning-path' && ( + {!hasFeature( + user, + FeatureAccess.OpenContentAccess + ) && + !hasFeature( + user, + FeatureAccess.ProviderAccess + ) && + !hasFeature( + user, + FeatureAccess.ProgramAccess + ) && ( + <>
  • - + - My Learning + Home
  • - )} + + )} + {hasFeature( + user, + FeatureAccess.OpenContentAccess + ) && ( + <> +
  • + + + Trending Content + +
  • +
  • + + + Knowledge Center + +
  • + + )} + {hasFeature(user, FeatureAccess.ProviderAccess) && ( + <> +
  • + + + Learning Path + +
  • )} - {hasFeature( - user, - FeatureAccess.OpenContentAccess - ) && ( - <> - {user.feature_access.length > 1 && ( -
  • - - - Trending Content - -
  • - )} -
  • - - - Knowledge Center - -
  • - - )} {hasFeature(user, FeatureAccess.ProgramAccess) && (
  • diff --git a/frontend/src/Components/cards/HelpfulLinkCard.tsx b/frontend/src/Components/cards/HelpfulLinkCard.tsx index cc49b703..bee26de2 100644 --- a/frontend/src/Components/cards/HelpfulLinkCard.tsx +++ b/frontend/src/Components/cards/HelpfulLinkCard.tsx @@ -73,11 +73,17 @@ export default function HelpfulLinkCard({ return (
    { void handleHelpfulLinkClick(link.id); }} > +
    +
    + {link.title} +
    +

    {link.title}

    +
    {AdminRoles.includes(role) ? ( showModal != undefined && (
    @@ -98,28 +104,31 @@ export default function HelpfulLinkCard({
    ) ) : ( - { - if (e) void handleToggleAction('favorite', e); - }} - /> - )} - {link.title} -

    {link.title}

    -

    {link.description}

    - - {AdminRoles.includes(role) && ( - void handleToggleAction('toggle')} - /> +
    void handleToggleAction('favorite', e)} + > + +
    )} +
    +

    + {link.description} +

    + {AdminRoles.includes(role) && ( + + void handleToggleAction('toggle') + } + /> + )} +
    ); } diff --git a/frontend/src/Pages/HelpfulLinks.tsx b/frontend/src/Pages/HelpfulLinks.tsx index f1656f7a..8891a69d 100644 --- a/frontend/src/Pages/HelpfulLinks.tsx +++ b/frontend/src/Pages/HelpfulLinks.tsx @@ -5,41 +5,68 @@ import { UserRole } from '@/common'; import HelpfulLinkCard from '@/Components/cards/HelpfulLinkCard'; +import Pagination from '@/Components/Pagination'; import { AxiosError } from 'axios'; +import { useState } from 'react'; import useSWR from 'swr'; export default function HelpfulLinks() { + const [perPage, setPerPage] = useState(20); + const [pageQuery, setPageQuery] = useState(1); const { data: helpfulLinks, mutate: mutateHelpfulFavs, isLoading, error } = useSWR, AxiosError>( - `/api/helpful-links` + `/api/helpful-links?page=${pageQuery}&per_page=${perPage}` ); function updateFavorites() { void mutateHelpfulFavs(); } + const handleSetPerPage = (perPage: number) => { + setPerPage(perPage); + setPageQuery(1); + updateFavorites(); + }; + const helpfulLinksMeta = helpfulLinks?.data?.meta ?? { + total: 0, + per_page: 20, + page: 1, + current_page: 1, + last_page: 1 + }; return ( -
    - {helpfulLinks?.data?.helpful_links.map((link: HelpfulLink) => ( - - ))} - {error && ( - - Failed to load helpful links. - - )} - {!isLoading && - !error && - helpfulLinks?.data.helpful_links.length === 0 && ( - No results + <> +
    + {helpfulLinks?.data?.helpful_links.map((link: HelpfulLink) => ( + + ))} + {error && ( + + Failed to load helpful links. + )} -
    + {!isLoading && + !error && + helpfulLinks?.data.helpful_links.length === 0 && ( + No results + )} +
    + {!isLoading && !error && helpfulLinksMeta && ( +
    + +
    + )} + ); } diff --git a/frontend/src/useAuth.ts b/frontend/src/useAuth.ts index 2f0ff30a..5661bb21 100644 --- a/frontend/src/useAuth.ts +++ b/frontend/src/useAuth.ts @@ -153,30 +153,11 @@ export async function handleLogout(): Promise { } } -const accessValues = new Map([ - [FeatureAccess.OpenContentAccess, 1], - [FeatureAccess.ProviderAccess, 2], - [FeatureAccess.ProgramAccess, 3] -]); - -export const studentAccessLinks = [ - '/home', // temporary layer 0 until implemented - '/trending-content', - '/learning-path', // temporary until layer 3 is implemented - '/learning-path' // temporary until layer 3 is implemented -]; - export const getDashboardLink = (user?: User) => { if (!user) return '/'; - - const maxFeature = - user?.feature_access - .map((ax) => accessValues.get(ax) ?? 0) - .sort((a, b) => a - b) - .pop() ?? 0; return isAdministrator(user) ? getAdminLink(user) - : studentAccessLinks[maxFeature]; + : getResidentLink(user); }; const getAdminLink = (user: User): string => { @@ -187,4 +168,14 @@ const getAdminLink = (user: User): string => { return "/learning-insights"; } return "/operational-insights"; +}; + +const getResidentLink = (user: User): string => { + if (user.feature_access.includes(FeatureAccess.OpenContentAccess)) { + return "/trending-content"; + } + if (user.feature_access.includes(FeatureAccess.ProviderAccess)) { + return "/learning-path"; + } + return "/home"; }; \ No newline at end of file