= ({ flatPageUrl }) => {
)
) : (
- {flatPage.attachment !== null && flatPage.attachment.length > 0 && (
+ {flatPage.attachment && flatPage.attachment.length > 0 && (
= ({ flatPageUrl }) => {
)}
-
+
{(flatPage.attachment == null || flatPage.attachment.length === 0) && (
@@ -68,19 +106,19 @@ export const FlatPageUI: React.FC = ({ flatPageUrl }) => {
)}
-
-
-
+
{flatPage.content !== null && flatPage.content.length > 0 && (
-
{parse(flatPage.content)}
+
+ {parsedFlatPage}
+
)}
{flatPage.sources.length > 0 && (
<>
diff --git a/frontend/src/components/pages/flatPage/useFlatPage.tsx b/frontend/src/components/pages/flatPage/useFlatPage.tsx
index a88bc6249..2e674f22c 100644
--- a/frontend/src/components/pages/flatPage/useFlatPage.tsx
+++ b/frontend/src/components/pages/flatPage/useFlatPage.tsx
@@ -6,6 +6,9 @@ import { useRouter } from 'next/router';
import { useQuery } from '@tanstack/react-query';
import { ONE_DAY } from 'services/constants/staleTime';
import { useQueryCommonDictionaries } from 'modules/dictionaries/api';
+import { getSuggestionsFromContent } from 'modules/flatpage/utils';
+import { ActivitySuggestion } from 'modules/activitySuggestions/interface';
+import { getActivitySuggestions } from 'modules/activitySuggestions/connector';
export const useFlatPage = (flatPageUrl: string | undefined) => {
const language = useRouter().locale ?? getDefaultLanguage();
@@ -14,7 +17,12 @@ export const useFlatPage = (flatPageUrl: string | undefined) => {
const commonDictionaries = useQueryCommonDictionaries(language);
- const { data, refetch, isLoading, error } = useQuery
(
+ const {
+ data: flatPage,
+ refetch,
+ isLoading,
+ error,
+ } = useQuery(
['flatPageDetails', id, language],
() => getFlatPageDetails(id, language, commonDictionaries),
{
@@ -22,5 +30,25 @@ export const useFlatPage = (flatPageUrl: string | undefined) => {
staleTime: ONE_DAY,
},
);
- return { id, flatPage: data, refetch, isLoading, error, path };
+ const suggestions = getSuggestionsFromContent(flatPage?.content ?? '');
+
+ const activitySuggestionIds = suggestions.flatMap(suggestion =>
+ 'ids' in suggestion ? suggestion.ids : [suggestion.type],
+ );
+
+ const { data: activitySuggestions = [] } = useQuery(
+ ['activitySuggestions', ...activitySuggestionIds, id, language],
+ () => getActivitySuggestions(suggestions, language, commonDictionaries),
+ { enabled: suggestions.length > 0 && commonDictionaries !== undefined },
+ );
+
+ return {
+ id,
+ flatPage,
+ activitySuggestions,
+ refetch,
+ isLoading,
+ error,
+ path,
+ };
};
diff --git a/frontend/src/components/pages/search/components/ResultCard/ResultCard.tsx b/frontend/src/components/pages/search/components/ResultCard/ResultCard.tsx
index f2a822cfa..939b16fa1 100644
--- a/frontend/src/components/pages/search/components/ResultCard/ResultCard.tsx
+++ b/frontend/src/components/pages/search/components/ResultCard/ResultCard.tsx
@@ -56,7 +56,7 @@ export const ResultCard: React.FC = props => {
setHoveredCardId(null);
}}
className={cn(
- 'flex flex-auto flex-col items-stretch border border border-solid border-greySoft hover:border-blackSemiTransparent transition rounded-xl overflow-hidden cursor-pointer',
+ 'custo-result-card flex flex-auto flex-col items-stretch border border border-solid border-greySoft hover:border-blackSemiTransparent transition rounded-xl overflow-hidden',
asColumn !== true && 'desktop:flex-row',
className,
)}
diff --git a/frontend/src/components/pages/search/components/ResultCard/__tests__/__snapshots__/ResultCard.test.tsx.snap b/frontend/src/components/pages/search/components/ResultCard/__tests__/__snapshots__/ResultCard.test.tsx.snap
index d09c17516..4d4fba3b9 100644
--- a/frontend/src/components/pages/search/components/ResultCard/__tests__/__snapshots__/ResultCard.test.tsx.snap
+++ b/frontend/src/components/pages/search/components/ResultCard/__tests__/__snapshots__/ResultCard.test.tsx.snap
@@ -6,7 +6,7 @@ Object {
"baseElement":
@@ -219,7 +219,7 @@ Object {
,
"container":
diff --git a/frontend/src/modules/flatpage/utils.ts b/frontend/src/modules/flatpage/utils.ts
new file mode 100644
index 000000000..25d585ec4
--- /dev/null
+++ b/frontend/src/modules/flatpage/utils.ts
@@ -0,0 +1,42 @@
+import parse, { DOMNode, Element } from 'html-react-parser';
+import { Suggestion } from 'modules/home/interface';
+
+export const getSuggestionType = (rawType?: string) => {
+ switch (rawType) {
+ case 'touristicContent':
+ return 'service';
+ case 'touristicEvent':
+ return 'events';
+ case 'outdoorSite':
+ return 'outdoor';
+ default:
+ return 'trek';
+ }
+};
+export const getSuggestionsFromContent = (rawContent: string) => {
+ const content = rawContent;
+ const domNodes: Element[] = [];
+ parse(content, {
+ replace: (domNode: DOMNode) => {
+ const isSuggestionNode =
+ domNode instanceof Element &&
+ domNode.attribs &&
+ 'data-ids' in domNode.attribs &&
+ 'data-type' in domNode.attribs;
+
+ if (isSuggestionNode) {
+ domNodes.push(domNode);
+ }
+ return domNode;
+ },
+ });
+
+ const suggestions: Suggestion[] = domNodes.map(domNode => ({
+ iconUrl: '',
+ titleTranslationId: domNode.attribs['data-label'],
+ ids: domNode.attribs['data-ids'].split(','),
+ type: getSuggestionType(domNode.attribs['data-type']),
+ }));
+
+ return suggestions;
+};
diff --git a/frontend/src/pages/information/[flatPage].tsx b/frontend/src/pages/information/[flatPage].tsx
index f7e64ef9d..047151d27 100644
--- a/frontend/src/pages/information/[flatPage].tsx
+++ b/frontend/src/pages/information/[flatPage].tsx
@@ -4,9 +4,11 @@ import { FlatPageUI } from 'components/pages/flatPage';
import { dehydrate, QueryClient } from '@tanstack/react-query';
import { routes } from 'services/routes';
import { getCommonDictionaries } from 'modules/dictionaries/connector';
-import { getFlatPageDetails } from '../../modules/flatpage/connector';
-import { isUrlString } from '../../modules/utils/string';
-import { redirectIfWrongUrl } from '../../modules/utils/url';
+import { getActivitySuggestions } from 'modules/activitySuggestions/connector';
+import { getFlatPageDetails } from 'modules/flatpage/connector';
+import { getSuggestionsFromContent } from 'modules/flatpage/utils';
+import { isUrlString } from 'modules/utils/string';
+import { redirectIfWrongUrl } from 'modules/utils/url';
import Custom404 from '../404';
export const getServerSideProps: GetServerSideProps = async context => {
@@ -22,6 +24,17 @@ export const getServerSideProps: GetServerSideProps = async context => {
const details = await getFlatPageDetails(id, locale, commonDictionaries);
await queryClient.prefetchQuery(['flatPageDetails', id, locale], () => details);
+ const suggestions = getSuggestionsFromContent(details.content);
+
+ const activitySuggestionIds = suggestions.flatMap(suggestion =>
+ 'ids' in suggestion ? suggestion.ids : [suggestion.type],
+ );
+
+ await queryClient.prefetchQuery(
+ ['activitySuggestions', ...activitySuggestionIds, id, locale],
+ () => getActivitySuggestions(suggestions, locale, commonDictionaries),
+ );
+
const redirect = redirectIfWrongUrl(
id,
details.title,
diff --git a/frontend/src/public/style.css b/frontend/src/public/style.css
index 9afd23af3..24811105a 100644
--- a/frontend/src/public/style.css
+++ b/frontend/src/public/style.css
@@ -13,7 +13,9 @@
width: 10px;
height: 10px;
border: 2px solid transparent;
- box-shadow: 0 0 0 2px, inset 0 0 0 10px;
+ box-shadow:
+ 0 0 0 2px,
+ inset 0 0 0 10px;
border-radius: 100px;
}
.gg-track::after,
@@ -43,7 +45,11 @@
.elevation-div {
height: 25%;
- font: 12px/1.5 'Helvetica Neue', Arial, Helvetica, sans-serif;
+ font:
+ 12px/1.5 'Helvetica Neue',
+ Arial,
+ Helvetica,
+ sans-serif;
}
.lightblue-theme.elevation-control.elevation .background {
@@ -86,3 +92,89 @@ details > summary.list-none::-webkit-details-marker,
details > summary.list-none::marker {
display: none;
}
+
+/* Flatpage WYSIWYG */
+.custo-page-WYSIWYG a:not(.custo-suggestions a, .button-link) {
+ @apply text-primary1 transition-colors hover:text-primary1-light focus:text-primary1-light;
+}
+
+.custo-page-WYSIWYG h1:not(.custo-suggestions h1) {
+ @apply text-H2 font-bold desktop:text-H1;
+}
+
+.custo-page-WYSIWYG h2:not(.custo-suggestions h2) {
+ @apply text-H3 font-bold desktop:text-H2;
+}
+
+.custo-page-WYSIWYG h3:not(.custo-suggestions h3),
+.custo-page-WYSIWYG h4:not(.custo-suggestions h4) {
+ @apply text-H4 font-bold desktop:text-H3;
+}
+
+.custo-page-WYSIWYG p:not(.custo-suggestions p) {
+ @apply mb-4 desktop:mb-6;
+}
+
+.custo-page-WYSIWYG h1:not(.custo-suggestions h1),
+.custo-page-WYSIWYG h2:not(.custo-suggestions h2),
+.custo-page-WYSIWYG h3:not(.custo-suggestions h3) {
+ @apply clear-both;
+}
+
+.custo-page-WYSIWYG h1:not(.custo-suggestions h1),
+.custo-page-WYSIWYG h2:not(.custo-suggestions h2),
+.custo-page-WYSIWYG h3:not(.custo-suggestions h3),
+.custo-page-WYSIWYG h4:not(.custo-suggestions h4),
+.custo-page-WYSIWYG h5:not(.custo-suggestions h5) {
+ @apply my-4 desktop:my-10;
+}
+
+.custo-page-WYSIWYG h6:not(.custo-suggestions h6) {
+ @apply my-4 desktop:my-8;
+}
+
+.custo-page-WYSIWYG img:not(.custo-suggestions img) {
+ @apply w-auto my-auto mx-1;
+}
+
+.custo-page-WYSIWYG iframe:not(.custo-suggestions iframe) {
+ @apply my-8 w-full h-auto desktop:my-12;
+}
+
+.custo-page-WYSIWYG b:not(.custo-suggestions b),
+.custo-page-WYSIWYG strong:not(.custo-suggestions strong) {
+ @apply font-bold;
+}
+
+.custo-page-WYSIWYG em:not(.custo-suggestions em) {
+ @apply text-P2 italic desktop:text-P1;
+}
+
+.custo-page-WYSIWYG ul:not(.custo-suggestions ul) {
+ @apply my-4;
+}
+
+.custo-page-WYSIWYG ul:not(.custo-suggestions ul) > li {
+ @apply pl-4 list-inside list-disc desktop:mb-2;
+}
+
+.custo-page-WYSIWYG .custo-suggestions {
+ @apply clear-both mt-6 desktop:mt-10 w-full;
+}
+
+.custo-page-WYSIWYG .information {
+ @apply clear-both py-4 px-10 rounded-lg bg-greySoft;
+}
+
+.custo-page-WYSIWYG .align-left {
+ @apply mb-8 desktop:float-start desktop:mr-12 desktop:mb-12;
+}
+
+.custo-page-WYSIWYG .align-right {
+ @apply mb-8 desktop:float-end desktop:ml-12 desktop:mb-12;
+}
+
+.custo-page-WYSIWYG .button-link {
+ @apply py-3 px-4 border border-solid border-primary1 text-primary1 bg-white font-semibold transition-colors rounded-lg;
+ @apply hover:bg-primary2 focus:bg-primary2;
+}