[DEV-4358] Add certificates page with grid and alert banner - #2295
[DEV-4358] Add certificates page with grid and alert banner#2295MarBert wants to merge 7 commits into
Conversation
🦋 Changeset detectedLatest commit: 79f7c1f The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Jira Pull Request LinkThis Pull Request refers to the following Jira issue DEV-4358 |
There was a problem hiding this comment.
Pull request overview
Adds a new “Webinar certificate list” feature to the Next.js website, gated behind the existing isWebinarHeartbeatEnabled feature flag, and refactors some UI components to support the new page and alert/banner use cases.
Changes:
- Introduces
/profile/certificate-listand a newCertificatesListorganism to render certificate cards plus an informational banner. - Adds a reusable
GenericAlertBannerand refactorsLiveWebinarWarningBannerto use it. - Extends
CtaCard/CardsGridfor richer CTA/icon/content styling and adds i18n strings + profile menu entry.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/nextjs-website/src/messages/it.json | Adds Italian strings for the certificate list page. |
| apps/nextjs-website/src/messages/en.json | Adds English strings for the certificate list page. |
| apps/nextjs-website/src/lib/webinars/webinarSubscriptions.ts | Extends WebinarSubscription with certificateCreatedAt. |
| apps/nextjs-website/src/config.ts | Adds a conditional profile menu entry for the certificate list. |
| apps/nextjs-website/src/components/templates/WebinarDetailTemplate/WebinarDetailTemplate.tsx | Gates the certificate banner behind the feature flag. |
| apps/nextjs-website/src/components/organisms/WebinarsTemplate/WebinarsTemplate.tsx | Gates the certificate banner on the webinars list behind the feature flag. |
| apps/nextjs-website/src/components/organisms/CertificatesList/CertificatesList.tsx | New UI for rendering certificate cards and an info banner. |
| apps/nextjs-website/src/components/molecules/LiveWebinarWarningBanner/LiveWebinarWarningBanner.tsx | Refactors warning banner to use GenericAlertBanner. |
| apps/nextjs-website/src/components/molecules/GenericAlertBanner/GenericAlertBanner.tsx | Adds reusable dismissible warning banner component. |
| apps/nextjs-website/src/components/molecules/CardsGrid/CardsGrid.tsx | Extends card model to support end icons, images, and per-card styling. |
| apps/nextjs-website/src/components/atoms/CtaCard/CtaCard.tsx | Extends CTA button to support endIcon and custom styling; adds cardContentStyle. |
| apps/nextjs-website/src/app/[locale]/profile/certificate-list/page.tsx | Adds the new route and gates it behind the feature flag. |
| .changeset/wild-crews-rule.md | Declares a minor release for nextjs-website. |
| "title": "Attestati Webinar", | ||
| "warning": "Perchè non vedo il mio attestato?", | ||
| "cta": "Scarica attestato", | ||
| "body": "Gli attestati dei webinar prima di maggio 2026 non sono disponibli.<br></br><br></br> Attenzione che per ottenere gli attestati dei nuovo webinar devi attivare il monitoraggio nella sezione <strong>Consensi e privacy</strong> e guardare almeno l’80% del webinar" |
| "title": "Webinar Certifications", | ||
| "warning": "Why can't I see my certificate?", | ||
| "cta": "Download certificate", | ||
| "body": "Certificates for webinars prior to May 2026 are not available.<br></br><br></br>Please note that to obtain certificates for the new webinars, you must enable tracking in the <strong>Consents and privacy</strong> section and watch at least 80% of the webinar" |
| width: '100%', | ||
| backgroundColor: palette.primaryAction.selected, | ||
| border: `1px ${palette.primaryAction.selected}`, | ||
| borderRadius: 2, |
| const { webinarSubscriptions } = useUser(); | ||
|
|
||
| const subscribedWebinars = webinarSubscriptions?.map((webinar) => { | ||
| return webinar.certificateCreatedAt && webinar.webinarId; | ||
| }); | ||
| const filteredWebinars = webinars.filter((webinar) => { | ||
| return subscribedWebinars?.includes(webinar.slug) ? webinar : null; | ||
| }); |
| <Box | ||
| borderRadius={'16px'} | ||
| component='img' | ||
| width={'100%'} | ||
| src={webinar.imagePath} | ||
| /> |
| ctaStyle: { | ||
| fontWeight: 700, | ||
| fontSize: '16px', | ||
| letterSpacing: '0.3px', | ||
| fontStyle: 'bold', | ||
| pl: '0', | ||
| }, |
| { | ||
| t.rich('profile.certificateList.body', { | ||
| strong: (chunks) => <strong>{chunks}</strong>, | ||
| br: () => <br></br>, | ||
| }) as string | ||
| } |
| import React from 'react'; | ||
| import CertificatesList from '@/components/organisms/CertificatesList/CertificatesList'; | ||
| import { isWebinarHeartbeatEnabled } from '@/config'; | ||
| import { getVisibleInListWebinars } from '@/lib/api'; | ||
|
|
||
| const CertificateListPage = async (props: { | ||
| params: Promise<{ locale: string }>; | ||
| }) => { | ||
| const { locale } = await props.params; | ||
| const webinars = await getVisibleInListWebinars(locale); | ||
|
|
||
| return isWebinarHeartbeatEnabled ? ( | ||
| <CertificatesList webinars={webinars} /> | ||
| ) : null; | ||
| }; |
| export type WebinarSubscription = { | ||
| readonly webinarId: string; | ||
| readonly username: string; | ||
| readonly createdAt: Date; | ||
| readonly certificateCreatedAt?: Date; | ||
| }; |
| const cardsToShow = filteredWebinars.map((webinar) => { | ||
| return { | ||
| title: webinar.title, | ||
| text: '', | ||
| useSrc: false, | ||
| ctaLabel: t('profile.certificateList.cta'), | ||
| endIcon: <DownloadIcon />, |
|
This pull request is stale because it has been open for 14 days with no activity. If the pull request is still valid, please update it within 21 days to keep it open or merge it, otherwise it will be closed automatically. |
|
This pull request was closed because it has been inactive for 21 days since being marked as stale. |
List of Changes
This pull request introduces a new Webinar Certificate List feature to the Next.js website, which is conditionally displayed based on a feature flag. It also includes several UI enhancements to the card and alert components, making them more flexible and reusable. The changes ensure that the certificate list is only accessible when the relevant feature flag is enabled and integrates the new page into the profile menu. Additionally, the codebase sees improvements in component composition and internationalization support.
Webinar Certificate List Feature:
/profile/certificate-list) that displays certificates for webinars a user has attended, only if theisWebinarHeartbeatEnabledfeature flag is active. The page uses a newCertificatesListcomponent to filter and show relevant webinars, and is added to the profile menu conditionally. [1] [2] [3] apps/nextjs-website/src/app/[locale]/profile/certificate-list/page.tsxR1-R17)Component and UI Enhancements:
CtaCardandCardsGridcomponents to support additional styling and icon options, making them more versatile for use cases like the certificate cards. [1] [2] [3] [4] [5] [6] [7] [8] [9]GenericAlertBannercomponent for consistent alert messaging, and refactoredLiveWebinarWarningBannerto use it. [1] [2] [3] [4]Feature Flag Integration:
isWebinarHeartbeatEnabledflag is true, both in the webinars template and webinar detail template. [1] [2] [3]Internationalization:
Data Model Update:
WebinarSubscriptiontype to include an optionalcertificateCreatedAtfield, supporting the logic for displaying available certificates.Motivation and Context
How Has This Been Tested?
Screenshots (if appropriate):
Types of changes
Checklist: