diff --git a/app/[page]/page-client.tsx b/app/[page]/page-client.tsx new file mode 100644 index 00000000..c43565f2 --- /dev/null +++ b/app/[page]/page-client.tsx @@ -0,0 +1,28 @@ +'use client'; + +import RenderComponents from '@/components/render-components'; +import { onEntryChange } from '@/contentstack-sdk/live-preview'; +import { Page as PageProp } from '@/typescript/pages'; +import React, { useState, useEffect } from 'react'; +import Skeleton from 'react-loading-skeleton'; + +export default function PageClient({ initialEntry }: { initialEntry: PageProp }) { + const [getEntry, setEntry] = useState(initialEntry); + + useEffect(() => { + onEntryChange(() => { + window.location.reload(); + }); + }, []); + + return getEntry?.page_components ? ( + + ) : ( + + ); +} diff --git a/app/[page]/page.tsx b/app/[page]/page.tsx index 8699a111..3c06dee9 100644 --- a/app/[page]/page.tsx +++ b/app/[page]/page.tsx @@ -1,44 +1,22 @@ -'use client'; - -import RenderComponents from '@/components/render-components'; -import { onEntryChange } from '@/contentstack-sdk'; import { getPageRes, metaData } from '@/helper'; -import { Page as PageProp } from '@/typescript/pages'; -import { usePathname } from 'next/navigation'; -import React, { useState, useEffect } from 'react'; -import Skeleton from 'react-loading-skeleton'; - -export default function Page() { - const entryUrl = usePathname(); +import PageClient from './page-client'; - const [getEntry, setEntry] = useState(); +export default async function Page({ params }: { params: { page: string } }) { + const entryUrl = `/${params.page}`; - async function fetchData() { - try { - const entryRes = await getPageRes(entryUrl); - if (!entryRes) throw new Error('Status code 404'); - setEntry(entryRes); - } catch (error) { - console.error(error); - } + let entryData; + try { + entryData = await getPageRes(entryUrl); + if (!entryData) throw new Error('Status code 404'); + } catch (error) { + console.error(error); + return
Error loading page
; } - useEffect(() => { - onEntryChange(() => fetchData()); - }, []); - - - return getEntry?.page_components ? ( + return ( <> - {getEntry.seo && getEntry.seo.enable_search_indexing && metaData(getEntry.seo)} - + {entryData.seo && entryData.seo.enable_search_indexing && metaData(entryData.seo)} + - ) : ( - ); -} \ No newline at end of file +} diff --git a/app/blog/[post]/blog-post-client.tsx b/app/blog/[post]/blog-post-client.tsx new file mode 100644 index 00000000..b9fc6b09 --- /dev/null +++ b/app/blog/[post]/blog-post-client.tsx @@ -0,0 +1,92 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; +import moment from 'moment'; +import parse from 'html-react-parser'; +import Skeleton from 'react-loading-skeleton'; +import { BlogPosts, Page } from '@/typescript/pages'; +import { onEntryChange } from '@/contentstack-sdk/live-preview'; +import RenderComponents from '@/components/render-components'; +import ArchiveRelative from '@/components/archive-relative'; + +export default function BlogPostClient({ + initialPost, + initialBanner +}: { + initialPost: BlogPosts; + initialBanner: Page; +}) { + const [blogPost, setBlogPost] = useState(initialPost); + const [page, setPage] = useState(initialBanner); + + useEffect(() => { + onEntryChange(() => { + window.location.reload(); + }); + }, []); + + return ( + <> + {page ? ( + + ) : ( + + )} +
+
+ {blogPost && blogPost.title ? ( +

{blogPost.title}

+ ) : ( +

+ +

+ )} + {blogPost && blogPost.date ? ( +

+ {moment(blogPost.date).format('ddd, MMM D YYYY')},{' '} + + {blogPost.author[0].title} + +

+ ) : ( +

+ +

+ )} + {blogPost && blogPost.body ? ( +
{parse(blogPost.body)}
+ ) : ( + + )} +
+
+
+ {page && page?.page_components[2].widget ? ( +

+ {page?.page_components[2].widget.title_h2} +

+ ) : ( +

+ +

+ )} + {blogPost && blogPost.related_post ? ( + + ) : ( + + )} +
+
+
+ + ); +} diff --git a/app/blog/[post]/page.tsx b/app/blog/[post]/page.tsx index 9e3e1e3f..b7216b46 100644 --- a/app/blog/[post]/page.tsx +++ b/app/blog/[post]/page.tsx @@ -1,104 +1,25 @@ -'use client'; - -import React, { useEffect, useState } from 'react'; -import moment from 'moment'; -import parse from 'html-react-parser'; -import Skeleton from 'react-loading-skeleton'; -import { usePathname } from 'next/navigation'; import { getBlogPostRes, getPageRes, metaData } from '@/helper'; -import { BlogPosts, Page } from '@/typescript/pages'; -import { onEntryChange } from '@/contentstack-sdk'; -import RenderComponents from '@/components/render-components'; -import ArchiveRelative from '@/components/archive-relative'; - +import BlogPostClient from './blog-post-client'; -export default function BlogPost() { - const entryUrl = usePathname(); +export default async function BlogPost({ params }: { params: { post: string } }) { + const entryUrl = `/blog/${params.post}`; - const [blogPost, setBlogPost] = useState(); - const [page, setPage] = useState(); - const [getPost, setPost] = useState({ banner: page, post: blogPost }); - async function fetchData() { - try { - const entryRes = await getBlogPostRes(entryUrl); - const bannerRes = await getPageRes('/blog'); - if (!entryRes || !bannerRes) throw new Error('Status: ' + 404); - setBlogPost(entryRes); - setPage(bannerRes); - setPost({ banner: bannerRes, post: entryRes }); - } catch (error) { - console.error(error); - } + let postData; + let bannerData; + + try { + postData = await getBlogPostRes(entryUrl); + bannerData = await getPageRes('/blog'); + if (!postData || !bannerData) throw new Error('Status: 404'); + } catch (error) { + console.error(error); + return
Error loading blog post
; } - useEffect(() => { - onEntryChange(() => fetchData()); - }, []); - - const { post, banner } = getPost; return ( <> - {blogPost?.seo && blogPost.seo.enable_search_indexing && metaData(blogPost.seo)} - {banner ? ( - - ) : ( - - )} -
-
- {post && post.title ? ( -

{post.title}

- ) : ( -

- -

- )} - {post && post.date ? ( -

- {moment(post.date).format('ddd, MMM D YYYY')},{' '} - - {post.author[0].title} - -

- ) : ( -

- -

- )} - {post && post.body ? ( -
{parse(post.body)}
- ) : ( - - )} -
-
-
- {banner && banner?.page_components[2].widget ? ( -

- {banner?.page_components[2].widget.title_h2} -

- ) : ( -

- -

- )} - {post && post.related_post ? ( - - ) : ( - - )} -
-
-
+ {postData?.seo && postData.seo.enable_search_indexing && metaData(postData.seo)} + ); -} \ No newline at end of file +} diff --git a/app/blog/blog-client.tsx b/app/blog/blog-client.tsx new file mode 100644 index 00000000..8f2945ec --- /dev/null +++ b/app/blog/blog-client.tsx @@ -0,0 +1,66 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { onEntryChange } from '../../contentstack-sdk/live-preview'; +import BlogList from '../../components/blog-list'; +import RenderComponents from '../../components/render-components'; +import ArchiveRelative from '../../components/archive-relative'; +import Skeleton from 'react-loading-skeleton'; +import { Page, PostPage } from "../../typescript/pages"; + +export default function BlogClient({ + initialBanner, + initialPosts, + initialArchivePosts +}: { + initialBanner: Page; + initialPosts: PostPage; + initialArchivePosts: PostPage; +}) { + const [getBanner, setBanner] = useState(initialBanner); + const [archivePost, setArchivePost] = useState(initialArchivePosts); + const [posts, setPosts] = useState(initialPosts); + + useEffect(() => { + onEntryChange(() => { + window.location.reload(); + }); + }, []); + + return ( + <> + {getBanner?.page_components ? ( + + ) : ( + + )} +
+
+ {posts ? ( + posts.map((blogList, index) => ( + + )) + ) : ( + + )} +
+
+ {getBanner && getBanner.page_components[1].widget && ( +

{getBanner.page_components[1].widget.title_h2}

+ )} + {archivePost ? ( + + ) : ( + + )} +
+
+ + ); +} diff --git a/app/blog/page.tsx b/app/blog/page.tsx index 857f8f61..d5148354 100644 --- a/app/blog/page.tsx +++ b/app/blog/page.tsx @@ -1,86 +1,45 @@ -'use client'; - -import React, { useState, useEffect } from 'react'; -import { onEntryChange } from '../../contentstack-sdk'; -import BlogList from '../../components/blog-list'; -import RenderComponents from '../../components/render-components'; import { getPageRes, getBlogListRes, metaData } from '../../helper'; - -import ArchiveRelative from '../../components/archive-relative'; -import Skeleton from 'react-loading-skeleton'; -import { Page, PostPage, PageUrl, Context } from "../../typescript/pages"; -import { usePathname } from 'next/navigation'; - - -export default function Blog() { - const entryUrl = usePathname(); - - const [getBanner, setBanner] = useState(); - const [archivePost, setArchivePost] = useState(); - const [posts, setPosts] = useState(); - async function fetchData() { - try { - const bannerRes = await getPageRes(entryUrl); - if (!bannerRes) throw new Error('Status code 404'); - setBanner(bannerRes); - - const result: PostPage = await getBlogListRes(); - const archivePostRes = [] as any; - const postsRes = [] as any; - - result.forEach((blogs) => { - if (blogs.is_archived) { - archivePostRes.push(blogs); - } else { - postsRes.push(blogs); - } - }); - - setArchivePost(archivePostRes); - setPosts(postsRes); - } catch (error) { - console.error(error); - } +import { PostPage } from "../../typescript/pages"; +import BlogClient from './blog-client'; + +export default async function Blog() { + const entryUrl = '/blog'; + + let bannerData; + let posts; + let archivePosts; + + try { + bannerData = await getPageRes(entryUrl); + if (!bannerData) throw new Error('Status code 404'); + + const result: PostPage = await getBlogListRes(); + const archivePostRes = [] as any; + const postsRes = [] as any; + + result.forEach((blogs) => { + if (blogs.is_archived) { + archivePostRes.push(blogs); + } else { + postsRes.push(blogs); + } + }); + + archivePosts = archivePostRes; + posts = postsRes; + } catch (error) { + console.error(error); + return
Error loading blog
; } - useEffect(() => { - onEntryChange(() => fetchData()); - }, []); return ( <> - {getBanner?.seo && getBanner.seo.enable_search_indexing && metaData(getBanner.seo)} - {getBanner?.page_components ? ( - - ) : ( - - )} -
-
- {posts ? ( - posts.map((blogList, index) => ( - - )) - ) : ( - - )} -
-
- {getBanner && getBanner.page_components[1].widget && ( -

{getBanner.page_components[1].widget.title_h2}

- )} - {archivePost ? ( - - ) : ( - - )} -
-
+ {bannerData?.seo && bannerData.seo.enable_search_indexing && metaData(bannerData.seo)} + ); -} \ No newline at end of file +} diff --git a/app/composable-heroes/[post]/hero-post-client.tsx b/app/composable-heroes/[post]/hero-post-client.tsx new file mode 100644 index 00000000..3526eee2 --- /dev/null +++ b/app/composable-heroes/[post]/hero-post-client.tsx @@ -0,0 +1,69 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import parse from 'html-react-parser'; +import { SuperHeroPosts } from '@/typescript/pages'; +import { onEntryChange } from '@/contentstack-sdk/live-preview'; + +export default function HeroPostClient({ initialPost }: { initialPost: SuperHeroPosts }) { + const [getPost, setPost] = useState(initialPost); + + useEffect(() => { + onEntryChange(() => { + window.location.reload(); + }); + }, []); + + const postData = getPost; + return ( +
+
+
+ { + postData?.image?.url ? + {postData?.image?.filename} + : '' + } +
+
+
+
+ {postData?.title ?

{postData?.title}

: ''} + {postData?.description ?

{parse(postData?.description)}

: ''} +
+
+ { + postData?.home_world?.map((homeWorld: { + title: string | undefined; + image: { url: string | undefined; $: { url: {}; }; filename: string; }; + }, + indx: {}) => ( +
+ {homeWorld?.title ?

{homeWorld?.title}

: ''} + {homeWorld?.image?.url ? + {homeWorld?.image?.filename} + : ''} +
+
+ )) + } + {postData?.contact_info?.email ?

Email : {postData?.contact_info?.email}

: ''} + {postData?.contact_info?.phone ?

Phone : {postData?.contact_info?.phone}

: ''} + {postData?.powers ?

Power : {postData?.powers}

: ''} +
+
+
+
+
+ ); +} diff --git a/app/composable-heroes/[post]/page.tsx b/app/composable-heroes/[post]/page.tsx index 11038b88..9f1f8338 100644 --- a/app/composable-heroes/[post]/page.tsx +++ b/app/composable-heroes/[post]/page.tsx @@ -1,84 +1,22 @@ -'use client'; - -import React, { useState, useEffect } from 'react'; -import parse from 'html-react-parser'; -import { usePathname } from 'next/navigation'; import { getComposableHeroSingleRes, metaData } from '@/helper'; -import { SuperHeroPosts } from '@/typescript/pages'; -import { onEntryChange } from '@/contentstack-sdk'; +import HeroPostClient from './hero-post-client'; -export default function SuperHerosPost() { - const entryUrl = usePathname(); +export default async function SuperHerosPost({ params }: { params: { post: string } }) { + const entryUrl = `/composable-heroes/${params.post}`; - const [getPost, setPost] = useState(); - async function fetchData() { - try { - const entryRes = await getComposableHeroSingleRes(entryUrl); - if (!entryRes) throw new Error('Status: ' + 404); - setPost(entryRes); - } catch (error) { - console.error(error); - } + let postData; + try { + postData = await getComposableHeroSingleRes(entryUrl); + if (!postData) throw new Error('Status: 404'); + } catch (error) { + console.error(error); + return
Error loading hero post
; } - useEffect(() => { - onEntryChange(() => fetchData()); - }, []); - - const postData = getPost return ( <> - {getPost?.seo && getPost.seo.enable_search_indexing && metaData(getPost.seo)} -
-
-
- { - postData?.image?.url ? - {postData?.image?.filename} - : '' - } -
-
-
-
- {postData?.title ?

{postData?.title}

: ''} - {postData?.description ?

{parse(postData?.description)}

: ''} -
-
- { - postData?.home_world?.map((homeWorld: { - title: string | undefined; - image: { url: string | undefined; $: { url: {}; }; filename: string; }; - }, - indx: {}) => ( -
- {homeWorld?.title ?

{homeWorld?.title}

: ''} - {homeWorld?.image?.url ? - {homeWorld?.image?.filename} - : ''} -
-
- )) - } - {postData?.contact_info?.email ?

Email : {postData?.contact_info?.email}

: ''} - {postData?.contact_info?.phone ?

Phone : {postData?.contact_info?.phone}

: ''} - {postData?.powers ?

Power : {postData?.powers}

: ''} -
-
-
-
-
- + {postData?.seo && postData.seo.enable_search_indexing && metaData(postData.seo)} + ); -} \ No newline at end of file +} diff --git a/app/composable-heroes/heroes-client.tsx b/app/composable-heroes/heroes-client.tsx new file mode 100644 index 00000000..a4a6a471 --- /dev/null +++ b/app/composable-heroes/heroes-client.tsx @@ -0,0 +1,33 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { onEntryChange } from '../../contentstack-sdk/live-preview'; +import { Page, PostPage } from "../../typescript/pages"; +import GalleryReact from '../../components/gallery'; + +export default function HeroesClient({ + initialBanner, + initialPosts +}: { + initialBanner: Page; + initialPosts: PostPage; +}) { + const [getBanner, setBanner] = useState(initialBanner); + const [posts, setPosts] = useState(initialPosts); + + useEffect(() => { + onEntryChange(() => { + window.location.reload(); + }); + }, []); + + return ( + + ); +} diff --git a/app/composable-heroes/page.tsx b/app/composable-heroes/page.tsx index 5e85052b..da434c42 100644 --- a/app/composable-heroes/page.tsx +++ b/app/composable-heroes/page.tsx @@ -1,57 +1,34 @@ -'use client'; +import { getAllComposableHeros, metaData } from '../../helper'; +import HeroesClient from './heroes-client'; -import React, { useState, useEffect } from 'react'; -import { onEntryChange } from '../../contentstack-sdk'; -import { getAllComposableHeros, getComposableHeroHomeWorld, metaData } from '../../helper'; -import { Page, PostPage } from "../../typescript/pages"; -import GalleryReact from '../../components/gallery' -import { usePathname } from 'next/navigation'; +export default async function ComposableHeroes() { + const entryUrl = '/composable-heroes'; -export default function ComposableHeroes() { - const entryUrl = usePathname(); + let bannerData; + let posts; - const [getBanner, setBanner] = useState(); - const [archivePost, setArchivePost] = useState(); - const [posts, setPosts] = useState(); - async function fetchData() { + try { + bannerData = await getAllComposableHeros(entryUrl); + if (!bannerData) throw new Error('Status code 404'); - try { - const bannerRes = await getAllComposableHeros(entryUrl); - if (!bannerRes) throw new Error('Status code 404'); - setBanner(bannerRes); - const archivePostRes = [] as any; - const postsRes = [] as any; + const postsRes = [] as any; - bannerRes?.characters?.forEach((superHero: { is_archived: any; }) => { - if (superHero.is_archived) { - archivePostRes.push(superHero); - } else { - postsRes.push(superHero); - } - }); + bannerData?.characters?.forEach((superHero: { is_archived: any; }) => { + if (!superHero.is_archived) { + postsRes.push(superHero); + } + }); - setArchivePost(archivePostRes); - setPosts(postsRes); - - } catch (error) { - console.error(error); - } + posts = postsRes; + } catch (error) { + console.error(error); + return
Error loading heroes
; } - useEffect(() => { - onEntryChange(() => fetchData()); - }, []); - return ( <> - {getBanner?.seo && getBanner.seo.enable_search_indexing && metaData(getBanner.seo)} - + {bannerData?.seo && bannerData.seo.enable_search_indexing && metaData(bannerData.seo)} + ); -} \ No newline at end of file +} diff --git a/app/gallery/gallery-client.tsx b/app/gallery/gallery-client.tsx new file mode 100644 index 00000000..c104b704 --- /dev/null +++ b/app/gallery/gallery-client.tsx @@ -0,0 +1,56 @@ +'use client'; + +import GalleryReact from '@/components/gallery'; +import HeroBanner from '@/components/hero-banner'; +import { onEntryChange } from '@/contentstack-sdk/live-preview'; +import { Banner } from '@/typescript/component'; +import React, { useEffect, useState } from 'react'; + +const renderTemplateSection = (switchData: any[], modules: { + hero_banner: Banner; + super_heroes_gallery: { + description: any; heroes: [], heading: string | undefined + }; + +}, index: any) => { + const { + super_heroes_gallery: superHeroGallery + } = modules + + switch (switchData[0]) { + case 'hero_banner': + return ( + + ) + case 'super_heroes_gallery': + return ( + + ) + + default: return null + } +} + +export default function GalleryClient({ initialGallery }: { initialGallery: any }) { + const [gallery, setGallery] = useState(initialGallery); + + useEffect(() => { + onEntryChange(() => { + window.location.reload(); + }); + }, []); + + return ( +
+ { + gallery?.modular_blocks + ?.map((ele: any, index: any) => renderTemplateSection(Object.keys(ele), ele, index)) + } +
+ ); +} diff --git a/app/gallery/page.tsx b/app/gallery/page.tsx index 3903bacd..42cc29fa 100644 --- a/app/gallery/page.tsx +++ b/app/gallery/page.tsx @@ -1,72 +1,19 @@ -'use client'; - -import GalleryReact from '@/components/gallery'; -import HeroBanner from '@/components/hero-banner'; -import { onEntryChange } from '@/contentstack-sdk'; -import { getComposableHeroGallery, getSuperheroGalleryRes, metaData } from '@/helper'; -import { Banner } from '@/typescript/component'; -import { Posts } from '@/typescript/layout'; -import { PostPage } from '@/typescript/pages'; -import { usePathname } from 'next/navigation'; -import React, { useEffect, useState } from 'react'; - -const renderTemplateSection = (switchData: any[], modules: { - hero_banner: Banner; - super_heroes_gallery: { - description: any; heroes: [], heading: string | undefined - }; - -}, index: any) => { - const { - super_heroes_gallery: superHeroGallery - } = modules - - switch (switchData[0]) { - case 'hero_banner': - return ( - - ) - case 'super_heroes_gallery': - return ( - - ) - - default: return null - } -} - -export default function SuperHerosGallery() { - const entryUrl = usePathname(); - const [gallery, setGallery] = useState(); - - async function fetchData() { - try { - const galleryRes = await getComposableHeroGallery(entryUrl); - if (!galleryRes) throw new Error('Status code 404'); - setGallery(galleryRes); - } catch (error) { - console.error(error); +import { getComposableHeroGallery } from '@/helper'; +import GalleryClient from './gallery-client'; + +export default async function SuperHerosGallery() { + const entryUrl = '/gallery'; + + let galleryData; + try { + galleryData = await getComposableHeroGallery(entryUrl); + if (!galleryData) { + throw new Error('Status code 404'); } + } catch (error) { + console.error(error); + return
Error loading gallery
; } - useEffect(() => { - onEntryChange(() => fetchData()); - }, []); - - return ( - <> - {gallery?.seo && metaData(gallery.seo)} -
- { - gallery?.modular_blocks - ?.map((ele: any, index: any) => renderTemplateSection(Object.keys(ele), ele, index)) - } -
- - ); -} \ No newline at end of file + return ; +} diff --git a/app/home-client.tsx b/app/home-client.tsx new file mode 100644 index 00000000..cd5c95f7 --- /dev/null +++ b/app/home-client.tsx @@ -0,0 +1,28 @@ +'use client'; + +import RenderComponents from "@/components/render-components"; +import { onEntryChange } from "@/contentstack-sdk/live-preview"; +import { Page } from "@/typescript/pages"; +import { useEffect, useState } from "react"; +import Skeleton from "react-loading-skeleton"; + +export default function HomeClient({ initialEntry }: { initialEntry: Page }) { + const [getEntry, setEntry] = useState(initialEntry); + + useEffect(() => { + onEntryChange(() => { + window.location.reload(); + }); + }, []); + + return getEntry ? ( + + ) : ( + + ); +} diff --git a/app/page.tsx b/app/page.tsx index 2109a7c4..25b8f899 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,44 +1,22 @@ -'use client'; - -import RenderComponents from "@/components/render-components"; -import { onEntryChange } from "@/contentstack-sdk"; import { getPageRes, metaData } from "@/helper"; -import { Page } from "@/typescript/pages"; -import { usePathname } from "next/navigation"; -import { useEffect, useState } from "react"; -import Skeleton from "react-loading-skeleton"; - -export default function Home() { - const entryUrl = usePathname(); +import HomeClient from "./home-client"; - const [getEntry, setEntry] = useState(); +export default async function Home() { + const entryUrl = '/'; - async function fetchData() { - try { - const entryRes = await getPageRes(entryUrl); - if (!entryRes) throw new Error('Status code 404'); - setEntry(entryRes); - } catch (error) { - console.error(error); - } + let entryData; + try { + entryData = await getPageRes(entryUrl); + if (!entryData) throw new Error('Status code 404'); + } catch (error) { + console.error(error); + return
Error loading page
; } - useEffect(() => { - onEntryChange(() => fetchData()); - }, []); - - - return getEntry ? ( + return ( <> - {getEntry.seo && getEntry.seo.enable_search_indexing && metaData(getEntry.seo)} - + {entryData.seo && entryData.seo.enable_search_indexing && metaData(entryData.seo)} + - ) : ( - ); } diff --git a/components/footer-client.tsx b/components/footer-client.tsx new file mode 100644 index 00000000..13c3935c --- /dev/null +++ b/components/footer-client.tsx @@ -0,0 +1,130 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import Link from 'next/link'; +import parse from 'html-react-parser'; +import { onEntryChange } from '../contentstack-sdk/live-preview'; +import Skeleton from 'react-loading-skeleton'; +import { FooterProps, Entry, Links } from "../typescript/layout"; + +export default function FooterClient({ + initialFooter, + initialEntries +}: { + initialFooter: FooterProps; + initialEntries: Entry; +}) { + const [footer, setFooterProp] = useState(initialFooter); + const [entries, setEntries] = useState(initialEntries); + const [getFooter, setFooter] = useState(footer); + + function buildNavigation(ent: Entry, ft: FooterProps) { + let newFooter = { ...ft }; + if (ent.length !== newFooter.navigation.link.length) { + ent.forEach((entry) => { + const fFound = newFooter?.navigation.link.find( + (nlink: Links) => nlink.title === entry.title + ); + if (!fFound) { + newFooter.navigation.link?.push({ + title: entry.title, + href: entry.url, + $: entry.$, + }); + } + }); + } + return newFooter; + } + + useEffect(() => { + if (footer && entries) { + const newfooter = buildNavigation(entries, footer); + setFooter(newfooter); + } + }, [footer, entries]); + + useEffect(() => { + onEntryChange(() => { + window.location.reload(); + }); + }, []); + + const footerData = getFooter ? getFooter : undefined; + + return ( +
+
+
+ {footerData && footerData.logo ? ( + + + {footerData.title} + + + ) : ( + + )} +
+
+ +
+
+
+ {footerData ? ( + footerData.social?.social_share.map((social) => ( + + {social.icon && ( + {social.link.title} + )} + + )) + ) : ( + + )} +
+
+
+ {footerData && typeof footerData.copyright === 'string' ? ( +
+ {parse(footerData.copyright)} +
+ ) : ( +
+ +
+ )} +
+ ); +} + diff --git a/components/footer.tsx b/components/footer.tsx index e92a3823..7ee9e482 100644 --- a/components/footer.tsx +++ b/components/footer.tsx @@ -1,140 +1,9 @@ -'use client'; - -import React, { useState, useEffect } from 'react'; -import Link from 'next/link'; -import parse from 'html-react-parser'; -import { onEntryChange } from '../contentstack-sdk'; import { getAllEntries, getFooterRes } from '../helper'; -import Skeleton from 'react-loading-skeleton'; -import { FooterProps, Entry, Links } from "../typescript/layout"; - -export default function Footer() { - - const [footer, setFooterProp] = useState(undefined); - const [entries, setEntries] = useState(undefined); - - const [getFooter, setFooter] = useState(footer); - - function buildNavigation(ent: Entry, ft: FooterProps) { - let newFooter = { ...ft }; - if (ent.length !== newFooter.navigation.link.length) { - ent.forEach((entry) => { - const fFound = newFooter?.navigation.link.find( - (nlink: Links) => nlink.title === entry.title - ); - if (!fFound) { - newFooter.navigation.link?.push({ - title: entry.title, - href: entry.url, - $: entry.$, - }); - } - }); - } - return newFooter; - } - - const fetchFooterAndEntries = async () => { - const footerRes = await getFooterRes(); - const entriesRes = await getAllEntries(); - setFooterProp(footerRes); - setEntries(entriesRes); - } - - async function fetchData() { - try { - if (footer && entries) { - const footerRes = await getFooterRes(); - const newfooter = buildNavigation(entries, footerRes); - setFooter(newfooter); - } - } catch (error) { - console.error(error); - } - } - - useEffect(() => { - fetchFooterAndEntries(); - }, []); - - useEffect(() => { - onEntryChange(() => fetchData()); - }, [footer]); +import FooterClient from './footer-client'; - const footerData = getFooter ? getFooter : undefined; +export default async function Footer() { + const footerRes = await getFooterRes(); + const entriesRes = await getAllEntries(); - return ( -
-
-
- {footerData && footerData.logo ? ( - - - {footerData.title} - - - ) : ( - - )} -
-
- -
-
-
- {footerData ? ( - footerData.social?.social_share.map((social) => ( - - {social.icon && ( - {social.link.title} - )} - - )) - ) : ( - - )} -
-
-
- {footerData && typeof footerData.copyright === 'string' ? ( -
- {parse(footerData.copyright)} -
- ) : ( -
- -
- )} -
- ); -} \ No newline at end of file + return ; +} diff --git a/components/header-client.tsx b/components/header-client.tsx new file mode 100644 index 00000000..a2a0dd1e --- /dev/null +++ b/components/header-client.tsx @@ -0,0 +1,121 @@ +'use client' + +import React, { useState, useEffect } from 'react'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import parse from 'html-react-parser'; +import { onEntryChange } from '../contentstack-sdk/live-preview'; +import Skeleton from 'react-loading-skeleton'; +import { HeaderProps, Entry, NavLinks } from "../typescript/layout"; + +export default function HeaderClient({ + initialHeader, + initialEntries +}: { + initialHeader: HeaderProps; + initialEntries: Entry; +}) { + const [header, setHeaderProp] = useState(initialHeader); + const [entries, setEntries] = useState(initialEntries); + const pathname = usePathname(); + const [getHeader, setHeader] = useState(header); + + function buildNavigation(ent: Entry, hd: HeaderProps) { + let newHeader={...hd}; + if (ent.length!== newHeader.navigation_menu.length) { + ent.forEach((entry) => { + const hFound = newHeader?.navigation_menu.find( + (navLink: NavLinks) => navLink.label === entry.title + ); + if (!hFound) { + newHeader.navigation_menu?.push({ + label: entry.title, + page_reference: [ + { title: entry.title, url: entry.url, $: entry.$ }, + ], + $:{} + }); + } + }); + } + return newHeader + } + + useEffect(() => { + if (header && entries) { + const newHeader = buildNavigation(entries, header); + setHeader(newHeader); + } + }, [header, entries]); + + useEffect(() => { + onEntryChange(() => { + window.location.reload(); + }); + }, []); + + const headerData = getHeader ? getHeader : undefined; + + return ( +
+
+ {headerData?.notification_bar.show_announcement ? ( + typeof headerData.notification_bar.announcement_text === 'string' && ( +
+ {parse(headerData.notification_bar.announcement_text)} +
+ ) + ) : ( + + )} +
+
+
+ {headerData ? ( + + + {headerData.title} + + + ) : ( + + )} +
+ + + +
+
+ ); +} + diff --git a/components/header.tsx b/components/header.tsx index fbd119a6..414c792b 100644 --- a/components/header.tsx +++ b/components/header.tsx @@ -1,139 +1,9 @@ -'use client' - -import React, { useState, useEffect } from 'react'; -import Link from 'next/link'; -import { usePathname } from 'next/navigation'; -import parse from 'html-react-parser'; -// import Tooltip from './tool-tip'; -import { onEntryChange } from '../contentstack-sdk'; import { getAllEntries, getHeaderRes } from '../helper'; -import Skeleton from 'react-loading-skeleton'; -import { HeaderProps, Entry, NavLinks } from "../typescript/layout"; - -export default function Header() { - const [header, setHeaderProp] = useState(undefined); - const [entries, setEntries] = useState(undefined); - const pathname = usePathname(); - const [getHeader, setHeader] = useState(header); - - const fetchHeaderAndEntries = async () => { - const headerRes = await getHeaderRes(); - const entriesRes = await getAllEntries(); - setHeaderProp(headerRes); - setEntries(entriesRes); - } - - function buildNavigation(ent: Entry, hd: HeaderProps) { - let newHeader={...hd}; - if (ent.length!== newHeader.navigation_menu.length) { - ent.forEach((entry) => { - const hFound = newHeader?.navigation_menu.find( - (navLink: NavLinks) => navLink.label === entry.title - ); - if (!hFound) { - newHeader.navigation_menu?.push({ - label: entry.title, - page_reference: [ - { title: entry.title, url: entry.url, $: entry.$ }, - ], - $:{} - }); - } - }); - } - return newHeader - } - - async function fetchData() { - try { - if (header && entries) { - const headerRes = await getHeaderRes(); - const newHeader = buildNavigation(entries,headerRes) - setHeader(newHeader); - } - } catch (error) { - console.error(error); - } - } - - useEffect(() => { - fetchHeaderAndEntries(); - }, []); +import HeaderClient from './header-client'; - useEffect(() => { - if (header && entries) { - onEntryChange(() => fetchData()); - } - }, [header]); - const headerData = getHeader ? getHeader : undefined; - - return ( -
-
- {headerData?.notification_bar.show_announcement ? ( - typeof headerData.notification_bar.announcement_text === 'string' && ( -
- {parse(headerData.notification_bar.announcement_text)} -
- ) - ) : ( - - )} -
-
-
- {headerData ? ( - - - {headerData.title} - - - ) : ( - - )} -
- - - +export default async function Header() { + const headerRes = await getHeaderRes(); + const entriesRes = await getAllEntries(); - {/*
- - - JSON Preview icon - - -
*/} -
-
- ); -} \ No newline at end of file + return ; +} diff --git a/contentstack-sdk/index.js b/contentstack-sdk/index.js index 4d5b3e6c..ab854e09 100644 --- a/contentstack-sdk/index.js +++ b/contentstack-sdk/index.js @@ -1,8 +1,6 @@ import * as contentstack from 'contentstack'; import * as Utils from '@contentstack/utils'; -import ContentstackLivePreview from '@contentstack/live-preview-utils'; - const Stack = contentstack.Stack({ api_key: process.env.CONTENTSTACK_API_KEY ? process.env.CONTENTSTACK_API_KEY @@ -21,23 +19,6 @@ if (process.env.CONTENTSTACK_API_HOST) { Stack.setHost(process.env.CONTENTSTACK_API_HOST); } -ContentstackLivePreview.init({ - stackSdk: Stack, - stackDetails: { - apiKey: process.env.CONTENTSTACK_API_KEY, - environment: process.env.CONTENTSTACK_ENVIRONMENT, - branch: process.env.CONTENTSTACK_BRANCH, -}, - - clientUrlParams: { - host: process.env.CONTENTSTACK_APP_HOST, - }, - enable: true, - ssr: false, -}); - -export const { onEntryChange } = ContentstackLivePreview; - const renderOption = { span: (node, next) => next(node.children), }; diff --git a/contentstack-sdk/live-preview.js b/contentstack-sdk/live-preview.js new file mode 100644 index 00000000..09467e9a --- /dev/null +++ b/contentstack-sdk/live-preview.js @@ -0,0 +1,19 @@ +'use client'; + +import ContentstackLivePreview from '@contentstack/live-preview-utils'; + +ContentstackLivePreview.init({ + stackDetails: { + apiKey: process.env.NEXT_PUBLIC_CONTENTSTACK_API_KEY, + environment: process.env.NEXT_PUBLIC_CONTENTSTACK_ENVIRONMENT, + branch: process.env.NEXT_PUBLIC_CONTENTSTACK_BRANCH, + }, + clientUrlParams: { + host: process.env.NEXT_PUBLIC_CONTENTSTACK_APP_HOST, + }, + enable: true, + ssr: false, +}); + +export const { onEntryChange } = ContentstackLivePreview; + diff --git a/next-env.d.ts b/next-env.d.ts index 4f11a03d..9edff1c7 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,5 +1,6 @@ /// /// +import "./.next/types/routes.d.ts"; // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/next.config.mjs b/next.config.mjs index bd7fe533..0cb87d31 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,17 +1,18 @@ /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, - env: { // available at build time + env: { CONTENTSTACK_API_KEY: process.env.CONTENTSTACK_API_KEY , CONTENTSTACK_DELIVERY_TOKEN: process.env.CONTENTSTACK_DELIVERY_TOKEN, CONTENTSTACK_BRANCH: process.env.CONTENTSTACK_BRANCH ? process.env.CONTENTSTACK_BRANCH : 'main', CONTENTSTACK_ENVIRONMENT: process.env.CONTENTSTACK_ENVIRONMENT, - CONTENTSTACK_APP_HOST: process.env.CONTENTSTACK_APP_HOST, //app host - CONTENTSTACK_PREVIEW_HOST: process.env.CONTENTSTACK_PREVIEW_HOST, // live-preview host - CONTENTSTACK_PREVIEW_TOKEN: process.env.CONTENTSTACK_PREVIEW_TOKEN, // live-preview token + CONTENTSTACK_APP_HOST: process.env.CONTENTSTACK_APP_HOST, + CONTENTSTACK_PREVIEW_HOST: process.env.CONTENTSTACK_PREVIEW_HOST, + CONTENTSTACK_PREVIEW_TOKEN: process.env.CONTENTSTACK_PREVIEW_TOKEN, CONTENTSTACK_LIVE_EDIT_TAGS: process.env.CONTENTSTACK_LIVE_EDIT_TAGS, CONTENTSTACK_API_HOST: process.env.CONTENTSTACK_API_HOST, - } + }, + serverExternalPackages: ['@contentstack/utils'], }; export default nextConfig; diff --git a/package-lock.json b/package-lock.json index b4ee4deb..6ea8d41d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@contentstack/live-preview-utils": "2.0.4", "contentstack": "3.20.1", + "fs": "^0.0.1-security", "html-react-parser": "5.1.12", "moment": "2.30.1", "next": "16.0.5", @@ -3510,6 +3511,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==", + "license": "ISC" + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", diff --git a/package.json b/package.json index c5e7c21e..a9b21e04 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "dependencies": { "@contentstack/live-preview-utils": "2.0.4", "contentstack": "3.20.1", + "fs": "^0.0.1-security", "html-react-parser": "5.1.12", "moment": "2.30.1", "next": "16.0.5", diff --git a/tsconfig.json b/tsconfig.json index e7ff90fd..9e9bbf7b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,10 @@ { "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -10,7 +14,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "plugins": [ { @@ -18,9 +22,20 @@ } ], "paths": { - "@/*": ["./*"] - } + "@/*": [ + "./*" + ] + }, + "target": "ES2017" }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] }