Skip to content
Merged
5 changes: 1 addition & 4 deletions frontend/__tests__/unit/components/ProgramCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,8 @@ describe('ProgramCard', () => {

render(<ProgramCard program={longDescProgram} onView={mockOnView} accessLevel="user" />)

// Check that the full description is rendered (CSS handles the visual truncation)
expect(screen.getByText(longDescription)).toBeInTheDocument()

// Check that the paragraph has the line-clamp-6 class
expect(screen.getByText(longDescription)).toBeInTheDocument()
const descriptionElement = screen.getByText(longDescription)
expect(descriptionElement).toHaveClass('line-clamp-6')
})
Expand All @@ -208,7 +206,6 @@ describe('ProgramCard', () => {

expect(screen.getByText('Short description')).toBeInTheDocument()

// Check that it still has line-clamp-6 class for consistency
const descriptionElement = screen.getByText('Short description')
expect(descriptionElement).toHaveClass('line-clamp-6')
})
Expand Down
2 changes: 1 addition & 1 deletion frontend/__tests__/unit/pages/CreateModule.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ describe('CreateModulePage', () => {

await waitFor(() => {
expect(mockCreateModule).toHaveBeenCalled()
expect(mockPush).toHaveBeenCalledWith('/my/mentorship/programs/test-program?refresh=true')
expect(mockPush).toHaveBeenCalledWith('/my/mentorship/programs/test-program')
})
})
})
2 changes: 1 addition & 1 deletion frontend/__tests__/unit/pages/EditModule.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ describe('EditModulePage', () => {

await waitFor(() => {
expect(mockUpdateModule).toHaveBeenCalled()
expect(mockPush).toHaveBeenCalledWith('/my/mentorship/programs/test-program?refresh=true')
expect(mockPush).toHaveBeenCalledWith('/my/mentorship/programs/test-program')
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const EditProgramPage = () => {
timeout: 3000,
})

router.push(`/my/mentorship/programs/${slugify(formData.name)}?refresh=true`)
router.push(`/my/mentorship/programs/${slugify(formData.name)}`)
} catch (err) {
addToast({
title: 'Update Failed',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const EditModulePage = () => {
variant: 'solid',
timeout: 3000,
})
router.push(`/my/mentorship/programs/${programKey}?refresh=true`)
router.push(`/my/mentorship/programs/${programKey}`)
} catch (err) {
handleAppError(err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { addToast } from '@heroui/toast'
import { useRouter, useParams } from 'next/navigation'
import { useSession } from 'next-auth/react'
import React, { useEffect, useState } from 'react'
import { ErrorDisplay } from 'app/global-error'
import { ErrorDisplay, handleAppError } from 'app/global-error'
import { CREATE_MODULE } from 'server/mutations/moduleMutations'
import { GET_PROGRAM_ADMIN_DETAILS } from 'server/queries/programsQueries'
import { GET_PROGRAM_ADMIN_DETAILS, GET_PROGRAM_AND_MODULES } from 'server/queries/programsQueries'
import type { ExtendedSession } from 'types/auth'
import { EXPERIENCE_LEVELS } from 'types/mentorship'
import { EXPERIENCE_LEVELS, Module } from 'types/mentorship'
import { parseCommaSeparated } from 'utils/parser'
import LoadingSpinner from 'components/LoadingSpinner'
import ModuleForm from 'components/ModuleForm'
Expand Down Expand Up @@ -94,7 +94,32 @@ const CreateModulePage = () => {
mentorLogins: parseCommaSeparated(formData.mentorLogins),
}

await createModule({ variables: { input } })
await createModule({
variables: { input },
update: (cache, { data: mutationData }) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For create logic we still need to have custom update module because as stated here auto-update would not work with any new objects in a list (for example, list of modules in a program)

const created = mutationData?.createModule
if (!created) return
try {
const existing = cache.readQuery({
query: GET_PROGRAM_AND_MODULES,
variables: { programKey },
}) as { getProgramModules: Module[] }
if (existing?.getProgramModules) {
cache.writeQuery({
query: GET_PROGRAM_AND_MODULES,
variables: { programKey },
data: {
...existing,
getProgramModules: [created, ...existing.getProgramModules],
},
})
}
} catch (_err) {
handleAppError(_err)
return
}
},
})

addToast({
title: 'Module Created',
Expand All @@ -104,7 +129,7 @@ const CreateModulePage = () => {
timeout: 3000,
})

router.push(`/my/mentorship/programs/${programKey}?refresh=true`)
router.push(`/my/mentorship/programs/${programKey}`)
} catch (err) {
addToast({
title: 'Creation Failed',
Expand Down
40 changes: 7 additions & 33 deletions frontend/src/app/my/mentorship/programs/[programKey]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useQuery, useMutation } from '@apollo/client'
import { addToast } from '@heroui/toast'
import upperFirst from 'lodash/upperFirst'
import { useParams, useSearchParams, useRouter } from 'next/navigation'
import { useParams } from 'next/navigation'
import { useSession } from 'next-auth/react'
import { useEffect, useMemo, useState } from 'react'
import { ErrorDisplay, handleAppError } from 'app/global-error'
Expand All @@ -19,32 +19,24 @@ import LoadingSpinner from 'components/LoadingSpinner'

const ProgramDetailsPage = () => {
const { programKey } = useParams() as { programKey: string }
const searchParams = useSearchParams()
const router = useRouter()
const shouldRefresh = searchParams.get('refresh') === 'true'

const { data: session } = useSession()
const username = (session as ExtendedSession)?.user?.login

const [program, setProgram] = useState<Program | null>(null)
const [modules, setModules] = useState<Module[]>([])
const [isRefetching, setIsRefetching] = useState(false)

const [updateProgram] = useMutation(UPDATE_PROGRAM_STATUS_MUTATION, {
onError: handleAppError,
})

const {
data,
refetch,
loading: isQueryLoading,
} = useQuery(GET_PROGRAM_AND_MODULES, {
const { data, loading: isQueryLoading } = useQuery(GET_PROGRAM_AND_MODULES, {
variables: { programKey },
skip: !programKey,
notifyOnNetworkStatusChange: true,
})

const isLoading = isQueryLoading || isRefetching
const isLoading = isQueryLoading

const isAdmin = useMemo(
() => !!program?.admins?.some((admin) => admin.login === username),
Expand Down Expand Up @@ -77,7 +69,6 @@ const ProgramDetailsPage = () => {
status: newStatus,
},
},
refetchQueries: [{ query: GET_PROGRAM_AND_MODULES, variables: { programKey } }],
})

addToast({
Expand All @@ -93,28 +84,11 @@ const ProgramDetailsPage = () => {
}

useEffect(() => {
const processResult = async () => {
if (shouldRefresh) {
setIsRefetching(true)
try {
await refetch()
} finally {
setIsRefetching(false)
const params = new URLSearchParams(searchParams.toString())
params.delete('refresh')
const cleaned = params.toString()
router.replace(cleaned ? `?${cleaned}` : window.location.pathname, { scroll: false })
}
}

if (data?.getProgram) {
setProgram(data.getProgram)
setModules(data.getProgramModules || [])
}
if (data?.getProgram) {
setProgram(data.getProgram)
setModules(data.getProgramModules || [])
}

processResult()
}, [shouldRefresh, data, refetch, router, searchParams])
}, [data])

if (isLoading) return <LoadingSpinner />

Expand Down
15 changes: 6 additions & 9 deletions frontend/src/components/ModuleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ import {
} from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import upperFirst from 'lodash/upperFirst'
import { useRouter } from 'next/navigation'
import Link from 'next/link'
import { useState } from 'react'
import type { Module } from 'types/mentorship'
import { formatDate } from 'utils/dateFormatter'
import ActionButton from 'components/ActionButton'
import { TextInfoItem } from 'components/InfoItem'
import SingleModuleCard from 'components/SingleModuleCard'
import { TruncatedText } from 'components/TruncatedText'
Expand Down Expand Up @@ -69,16 +68,14 @@ const ModuleCard = ({ modules, accessLevel, admins }: ModuleCardProps) => {
}

const ModuleItem = ({ details }: { details: Module }) => {
const router = useRouter()
const handleClick = () => {
router.push(`${window.location.pathname}/modules/${details.key}`)
}

return (
<div className="flex h-46 w-full flex-col gap-3 rounded-lg border-1 border-gray-200 p-4 shadow-xs ease-in-out hover:shadow-md dark:border-gray-700 dark:bg-gray-800">
<ActionButton onClick={handleClick}>
<Link
href={`${window.location.pathname}/modules/${details.key}`}
className="text-start font-semibold text-blue-400 hover:underline"
>
<TruncatedText text={details?.name} />
</ActionButton>
</Link>
<TextInfoItem icon={faLevelUpAlt} label="Level" value={upperFirst(details.experienceLevel)} />
<TextInfoItem icon={faCalendarAlt} label="Start" value={formatDate(details.startedAt)} />
<TextInfoItem
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/server/mutations/moduleMutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const UPDATE_MODULE = gql`
domains
projectId
mentors {
id
login
name
avatarUrl
Expand All @@ -36,6 +37,7 @@ export const CREATE_MODULE = gql`
tags
projectId
mentors {
id
login
name
avatarUrl
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/server/mutations/programsMutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,22 @@ import { gql } from '@apollo/client'
export const UPDATE_PROGRAM = gql`
mutation UpdateProgram($input: UpdateProgramInput!) {
updateProgram(inputData: $input) {
id
key
name
description
status
menteesLimit
experienceLevels
startedAt
endedAt
tags
domains
admins {
id
login
name
avatarUrl
}
}
}
Expand All @@ -27,6 +32,7 @@ export const CREATE_PROGRAM = gql`
name
description
menteesLimit
experienceLevels
startedAt
endedAt
tags
Expand All @@ -43,6 +49,7 @@ export const CREATE_PROGRAM = gql`
export const UPDATE_PROGRAM_STATUS_MUTATION = gql`
mutation updateProgramStatus($inputData: UpdateProgramStatusInput!) {
updateProgramStatus(inputData: $inputData) {
id
key
status
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading