diff --git a/.changeset/swift-experts-camp.md b/.changeset/swift-experts-camp.md
new file mode 100644
index 0000000000..1b3814269b
--- /dev/null
+++ b/.changeset/swift-experts-camp.md
@@ -0,0 +1,5 @@
+---
+"nextjs-website": minor
+---
+
+Generalise filtered grid component
diff --git a/apps/nextjs-website/src/app/[productSlug]/tutorials/page.tsx b/apps/nextjs-website/src/app/[productSlug]/tutorials/page.tsx
index 7a6de18ca1..fb4035bf58 100644
--- a/apps/nextjs-website/src/app/[productSlug]/tutorials/page.tsx
+++ b/apps/nextjs-website/src/app/[productSlug]/tutorials/page.tsx
@@ -18,7 +18,7 @@ import {
breadcrumbItemByProduct,
productToBreadcrumb,
} from '@/helpers/structuredData.helpers';
-import { TutorialsList } from '@/components/organisms/TutorialsList/TutorialsList';
+import { FilteredGridLayout } from '@/components/organisms/FilteredGridLayout/FilteredGridLayout';
export type TutorialsPageProps = {
readonly product: Product;
@@ -75,6 +75,24 @@ const TutorialsPage = async ({ params }: ProductParams) => {
],
seo: seo,
});
+ const mappedTutorials = tutorials.map((tutorial) => {
+ return {
+ tags: tutorial.tags || [],
+ title: tutorial.title,
+ date: {
+ date: tutorial.publishedAt,
+ },
+ href: {
+ label: 'shared.readTutorial',
+ link: tutorial.path,
+ translate: true,
+ },
+ img: {
+ alt: tutorial.image?.alternativeText || '',
+ src: tutorial.image?.url || '/images/news.png',
+ },
+ };
+ });
return (
{
/>
)}
{tutorials && (
-
)}
diff --git a/apps/nextjs-website/src/app/[productSlug]/use-cases/page.tsx b/apps/nextjs-website/src/app/[productSlug]/use-cases/page.tsx
index a856f8a8e5..8f3410bed5 100644
--- a/apps/nextjs-website/src/app/[productSlug]/use-cases/page.tsx
+++ b/apps/nextjs-website/src/app/[productSlug]/use-cases/page.tsx
@@ -18,7 +18,7 @@ import {
} from '@/helpers/structuredData.helpers';
import { UseCase } from '@/lib/types/useCaseData';
import { getUseCaseListPageProps } from '@/lib/api';
-import { UseCaseList } from '../../../components/organisms/UseCaseList/UseCaseList';
+import { FilteredGridLayout } from '@/components/organisms/FilteredGridLayout/FilteredGridLayout';
export type UseCasesPageProps = {
readonly product: Product;
@@ -69,6 +69,25 @@ const UseCasesPage = async ({ params }: ProductParams) => {
seo: seo,
});
+ const mappedUseCases = useCases.map((useCase) => {
+ return {
+ tags: useCase.tags || [],
+ title: useCase.title,
+ date: {
+ date: useCase.publishedAt,
+ },
+ href: {
+ label: 'shared.readUseCase',
+ link: useCase.path,
+ translate: true,
+ },
+ img: {
+ alt: useCase.coverImage?.alternativeText || '',
+ src: useCase.coverImage?.url || '/images/news.png',
+ },
+ };
+ });
+
return (
{
/>
)}
{useCases && (
-
)}
diff --git a/apps/nextjs-website/src/components/molecules/DesktopFilterSelector/DesktopFilterSelector.tsx b/apps/nextjs-website/src/components/molecules/DesktopFilterSelector/DesktopFilterSelector.tsx
index 0d730d21b2..3e6b730b77 100644
--- a/apps/nextjs-website/src/components/molecules/DesktopFilterSelector/DesktopFilterSelector.tsx
+++ b/apps/nextjs-website/src/components/molecules/DesktopFilterSelector/DesktopFilterSelector.tsx
@@ -23,6 +23,7 @@ const DesktopFilterSelector = ({
}: DesktopFilterSelectorProps) => {
return (
;
return (
{
+ noItemsMessageKey = '',
+}: FilteredGridLayoutProps) => {
const t = useTranslations();
const updatedTags = [
{
- name: t('overview.useCases.all'),
+ name: t('overview.all'),
icon: {
data: {
attributes: {
@@ -52,19 +55,17 @@ export const UseCaseList = ({
);
const [selectedTag, setSelectedTag] = useState(tagValue);
- const filteredUseCases = useCases.filter((useCase) => {
+ const filteredItems = items.filter((item) => {
return (
selectedTag === 0 ||
- useCase.tags?.some((tag) => tag.name === updatedTags[selectedTag].name)
+ item.tags?.some((tag) => tag.name === updatedTags[selectedTag].name)
);
});
// eslint-disable-next-line functional/no-return-void
const setSelectedTagFilter = (newTag: number): void => {
if (newTag === selectedTag) return;
addQueryParam('tag', `${newTag}`);
- document
- .getElementById('chatbot-page-content')
- ?.scrollIntoView({ behavior: 'smooth' });
+ document.getElementById('filters')?.scrollIntoView({ behavior: 'smooth' });
setSelectedTag(newTag);
};
@@ -76,7 +77,7 @@ export const UseCaseList = ({
const isSmallScreen = useMediaQuery('(max-width: 1000px)');
return (
- 0 ? '24px' : 0 }}>
+ 0 ? '24px' : 0 }}>
{enableFilters &&
tags.length > 0 &&
(isSmallScreen ? (
@@ -93,7 +94,7 @@ export const UseCaseList = ({
/>
))}
- {filteredUseCases.length <= 0 ? (
+ {filteredItems.length <= 0 ? (
-
+
) : (
({
- title: useCase.title,
- date: {
- date: useCase.publishedAt,
- },
- href: {
- label: 'shared.readUseCase',
- link: useCase.path,
- translate: true,
- },
- img: {
- alt: useCase.coverImage?.alternativeText || '',
- src: useCase.coverImage?.url || '/images/news.png',
- },
+ items={filteredItems.map((item) => ({
+ ...item,
}))}
/>
)}
diff --git a/apps/nextjs-website/src/components/organisms/TutorialsList/TutorialsList.tsx b/apps/nextjs-website/src/components/organisms/TutorialsList/TutorialsList.tsx
deleted file mode 100644
index 9c8aaf732e..0000000000
--- a/apps/nextjs-website/src/components/organisms/TutorialsList/TutorialsList.tsx
+++ /dev/null
@@ -1,131 +0,0 @@
-'use client';
-
-import { Tag } from '@/lib/types/tag';
-import Newsroom from '@/editorialComponents/Newsroom/Newsroom';
-import { Box, useMediaQuery } from '@mui/material';
-import React, { useState } from 'react';
-import { Tutorial } from '@/lib/types/tutorialData';
-import { useTranslations } from 'next-intl';
-import { useSearchParams } from 'next/navigation';
-import MobileFilterSelector from '@/components/molecules/MobileFilterSelector/MobileFilterSelector';
-import DesktopFilterSelector from '@/components/molecules/DesktopFilterSelector/DesktopFilterSelector';
-import SectionTitle from '@/components/molecules/SectionTitle/SectionTitle';
-
-type TutorialsListProps = {
- readonly tutorials: readonly Tutorial[];
- readonly tags: readonly Tag[];
- readonly enableFilters?: boolean;
-};
-
-export const TutorialsList = ({
- tags,
- tutorials,
- enableFilters,
-}: TutorialsListProps) => {
- const t = useTranslations();
- const updatedTags = [
- {
- name: t('overview.tutorial.all'),
- icon: {
- data: {
- attributes: {
- name: 'all.svg',
- alternativeText: '',
- caption: '',
- width: 32,
- height: 32,
- size: 32,
- ext: '.svg',
- mime: 'image/svg',
- url: '/icons/all.svg',
- },
- },
- },
- },
- ...tags,
- ];
- const searchParams = useSearchParams();
- const parsedTag = parseInt(searchParams.get('tag') || '0');
- const tagValue = Math.max(
- 0,
- Math.min(isNaN(parsedTag) ? 0 : parsedTag, updatedTags.length - 1)
- );
- const [selectedTag, setSelectedTag] = useState(tagValue);
-
- const filteredTutorials = tutorials.filter((tutorial) => {
- return (
- selectedTag === 0 ||
- tutorial.tags?.some((tag) => tag.name === updatedTags[selectedTag].name)
- );
- });
- // eslint-disable-next-line functional/no-return-void
- const setSelectedTagFilter = (newTag: number): void => {
- if (newTag === selectedTag) return;
- addQueryParam('tag', `${newTag}`);
- // eslint-disable-next-line functional/immutable-data
- //window.location.href = '#webinarsHeader';
- document
- .getElementById('chatbot-page-content')
- ?.scrollIntoView({ behavior: 'smooth' });
- setSelectedTag(newTag);
- };
-
- const addQueryParam = (key: string, value: string) => {
- const url = new URL(window.location.href);
- url.searchParams.set(key, value);
- window.history.pushState({}, '', url.toString());
- };
- const isSmallScreen = useMediaQuery('(max-width: 1000px)');
- return (
-
- 0 ? '24px' : 0 }}>
- {enableFilters &&
- tags.length > 0 &&
- (isSmallScreen ? (
-
- ) : (
-
- ))}
-
- {filteredTutorials.length <= 0 ? (
-
-
-
- ) : (
- ({
- title: tutorial.title,
- date: {
- date: tutorial.publishedAt,
- },
- href: {
- label: 'shared.readTutorial',
- link: tutorial.path,
- translate: true,
- },
- img: {
- alt: tutorial.image?.alternativeText || '',
- src: tutorial.image?.url || '/images/news.png',
- },
- }))}
- />
- )}
-
- );
-};
diff --git a/apps/nextjs-website/src/components/organisms/WebinarsTemplate/WebinarsTemplate.tsx b/apps/nextjs-website/src/components/organisms/WebinarsTemplate/WebinarsTemplate.tsx
index 423bd9f329..b4a84a085c 100644
--- a/apps/nextjs-website/src/components/organisms/WebinarsTemplate/WebinarsTemplate.tsx
+++ b/apps/nextjs-website/src/components/organisms/WebinarsTemplate/WebinarsTemplate.tsx
@@ -2,27 +2,22 @@
import React, { useEffect, useState, Suspense } from 'react';
import Hero from '@/editorialComponents/Hero/Hero';
import { useTranslations } from 'next-intl';
-import { Box, Grid, useMediaQuery, useTheme } from '@mui/material';
+import { useTheme } from '@mui/material';
import { Webinar } from '@/lib/types/webinar';
-import EContainer from '@/editorialComponents/EContainer/EContainer';
-import SectionTitle from '@/components/molecules/SectionTitle/SectionTitle';
-import WebinarListItem from '@/components/molecules/WebinarListItem/WebinarListItem';
import { getFutureWebinars, getPastWebinars } from '@/helpers/webinars.helpers';
import FutureWebinarsShowcase from '../FutureWebinarsShowcase/FutureWebinarsShowcase';
import { baseUrl } from '@/config';
import { generateStructuredDataScripts } from '@/helpers/generateStructuredDataScripts.helpers';
import { getItemFromPaths } from '@/helpers/structuredData.helpers';
-import MobileFilterSelector from '@/components/molecules/MobileFilterSelector/MobileFilterSelector';
-import DesktopFilterSelector from '@/components/molecules/DesktopFilterSelector/DesktopFilterSelector';
-import { WebinarCategory } from '@/lib/types/webinarCategory';
-import { useSearchParams } from 'next/navigation';
import Spinner from '@/components/atoms/Spinner/Spinner';
+import { FilteredGridLayout } from '@/components/organisms/FilteredGridLayout/FilteredGridLayout';
+import { Tag } from '@/lib/types/tag';
const CHECK_WEBINARS_INTERVAL_MS = 60 * 1000;
type WebinarsTemplateProps = {
webinars: readonly Webinar[];
- categories: readonly WebinarCategory[];
+ categories: readonly Tag[];
};
const WebinarsTemplateContent = ({
@@ -30,64 +25,9 @@ const WebinarsTemplateContent = ({
categories,
}: WebinarsTemplateProps) => {
const t = useTranslations();
- const updatedCategories = [
- {
- name: t('webinars.all'),
- icon: {
- data: {
- attributes: {
- name: 'all.svg',
- alternativeText: '',
- caption: '',
- width: 32,
- height: 32,
- size: 32,
- ext: '.svg',
- mime: 'image/svg',
- url: ' icons/all.svg',
- },
- },
- },
- },
- ...categories,
- ];
const { palette } = useTheme();
const [futureWebinars, setFutureWebinars] = useState([]);
const [pastWebinars, setPastWebinars] = useState([]);
- const searchParams = useSearchParams();
- const parsedCategory = parseInt(searchParams.get('category') || '0');
- const categoryValue = Math.max(
- 0,
- Math.min(
- isNaN(parsedCategory) ? 0 : parsedCategory,
- updatedCategories.length - 1
- )
- );
- const [selectedCategory, setSelectedCategory] = useState(categoryValue);
-
- const filteredWebinars = pastWebinars.filter((cat) => {
- return (
- selectedCategory === 0 ||
- cat.webinarCategory?.name === updatedCategories[selectedCategory].name
- );
- });
- // eslint-disable-next-line functional/no-return-void
- const setSelectedWebinarCategory = (newCategory: number): void => {
- if (newCategory === selectedCategory) return;
- addQueryParam('category', `${newCategory}`);
- // eslint-disable-next-line functional/immutable-data
- //window.location.href = '#webinarsHeader';
- document
- .getElementById('webinarsHeader')
- ?.scrollIntoView({ behavior: 'smooth' });
- setSelectedCategory(newCategory);
- };
-
- const addQueryParam = (key: string, value: string) => {
- const url = new URL(window.location.href);
- url.searchParams.set(key, value);
- window.history.pushState({}, '', url.toString());
- };
const webinarsListPageSEO = {
metaTitle: t('webinars.title'),
@@ -116,7 +56,21 @@ const WebinarsTemplateContent = ({
// Cleanup the interval when the component is unmounted
return () => clearInterval(intervalId);
}, [webinars]);
- const isSmallScreen = useMediaQuery('(max-width: 1000px)');
+ const mappedWebinars = webinars.map((webinar) => ({
+ tags: webinar.tag ? [webinar.tag] : [],
+ title: webinar.title,
+ date: {
+ date: new Date(Date.parse(webinar.startDateTime || '')),
+ },
+ href: {
+ label: t('webinar.goToWebinar'),
+ link: `/webinars/${webinar.slug}`,
+ },
+ img: {
+ alt: webinar.title,
+ src: webinar.imagePath || '/images/news.png',
+ },
+ }));
return (
<>
@@ -134,59 +88,12 @@ const WebinarsTemplateContent = ({
)}
{pastWebinars.length > 0 && (
- <>
-
- {categories.length <= 0 ? null : isSmallScreen ? (
-
- ) : (
-
- )}
- {filteredWebinars.length <= 0 ? (
-
-
-
- ) : (
-
-
-
- {filteredWebinars.map((webinar, i) => (
-
- ))}
-
-
-
- )}
- >
+
)}
>
);
diff --git a/apps/nextjs-website/src/lib/strapi/__tests__/fixtures/webinars.ts b/apps/nextjs-website/src/lib/strapi/__tests__/fixtures/webinars.ts
index 62cf64b904..506fbf2780 100644
--- a/apps/nextjs-website/src/lib/strapi/__tests__/fixtures/webinars.ts
+++ b/apps/nextjs-website/src/lib/strapi/__tests__/fixtures/webinars.ts
@@ -187,7 +187,7 @@ export const webinarProps = {
subscribeCtaLabel: 'Subscribe Now',
imagePath: 'https://example.com/example.jpg',
seo: { metaTitle: 'SEO Webinar', metaDescription: 'SEO Description' },
- webinarCategory: {
+ tag: {
name: 'Category 1',
icon: {
data: {
diff --git a/apps/nextjs-website/src/lib/strapi/makeProps/makeWebinars.ts b/apps/nextjs-website/src/lib/strapi/makeProps/makeWebinars.ts
index 57fd13404e..af1f5a6225 100644
--- a/apps/nextjs-website/src/lib/strapi/makeProps/makeWebinars.ts
+++ b/apps/nextjs-website/src/lib/strapi/makeProps/makeWebinars.ts
@@ -56,8 +56,7 @@ export const makeWebinarProps = (
subscribeCtaLabel: strapiWebinar.attributes.subscribeParagraphLabel,
imagePath: strapiWebinar.attributes.coverImage.data.attributes.url,
seo: strapiWebinar.attributes.seo,
- webinarCategory:
- strapiWebinar.attributes.webinarCategory?.data?.attributes,
+ tag: strapiWebinar.attributes.webinarCategory?.data?.attributes,
headerImage: strapiWebinar.attributes.headerImage?.data?.attributes,
updatedAt: strapiWebinar.attributes.updatedAt,
} satisfies Webinar;
diff --git a/apps/nextjs-website/src/lib/types/webinar.ts b/apps/nextjs-website/src/lib/types/webinar.ts
index 3bb0961369..331a0563f3 100644
--- a/apps/nextjs-website/src/lib/types/webinar.ts
+++ b/apps/nextjs-website/src/lib/types/webinar.ts
@@ -3,6 +3,7 @@ import { BlocksContent } from '@strapi/blocks-react-renderer';
import { SEO } from './seo';
import { WebinarCategory } from '@/lib/types/webinarCategory';
import { Media } from '@/lib/types/media';
+import { Tag } from '@/lib/types/tag';
export type QuestionsAndAnswer = {
readonly question: string;
@@ -47,7 +48,7 @@ export type Webinar = {
readonly imagePath: string;
readonly questionsAndAnswers?: readonly QuestionsAndAnswer[];
readonly seo?: SEO;
- readonly webinarCategory?: WebinarCategory;
+ readonly tag?: Tag;
readonly headerImage?: Media;
readonly updatedAt: string;
};
diff --git a/apps/nextjs-website/src/messages/it.json b/apps/nextjs-website/src/messages/it.json
index 01b69bb61f..149732ff14 100644
--- a/apps/nextjs-website/src/messages/it.json
+++ b/apps/nextjs-website/src/messages/it.json
@@ -439,7 +439,8 @@
}
},
"overview": {
- "startInfo": {
+ "all": "Tutti",
+ "startInfo": {
"title": "Si comincia da qui"
},
"tutorialsList": {
@@ -448,7 +449,6 @@
"tutorial": {
"title": "Esplora i tutorial",
"ctaLabel": "Vedi tutti i tutorial",
- "all": "Tutti",
"noTutorialMessage": "Non sono presenti tutorial della categoria selezionata"
},
"postIntegration": {
@@ -460,7 +460,6 @@
"useCases": {
"title": "Casi d'uso",
"ctaLabel": "Vedi tutti i casi d'uso",
- "all": "Tutti",
"noUseCaseMessage": "Non sono presenti casi d'uso della categoria selezionata"
}
},