From 19f87d331c56adc837097c54c9e5f4554c966bbc Mon Sep 17 00:00:00 2001 From: gmolki Date: Mon, 10 Jun 2024 13:57:12 +0200 Subject: [PATCH 1/7] refactor: Add LoadingBlinkBox component --- src/components/LoadingBlinkBox/cmp.tsx | 14 +++++++++++ src/components/LoadingBlinkBox/index.tsx | 1 + src/components/LoadingBlinkBox/styles.tsx | 29 +++++++++++++++++++++++ src/components/LoadingBlinkBox/types.ts | 7 ++++++ 4 files changed, 51 insertions(+) create mode 100644 src/components/LoadingBlinkBox/cmp.tsx create mode 100644 src/components/LoadingBlinkBox/index.tsx create mode 100644 src/components/LoadingBlinkBox/styles.tsx create mode 100644 src/components/LoadingBlinkBox/types.ts diff --git a/src/components/LoadingBlinkBox/cmp.tsx b/src/components/LoadingBlinkBox/cmp.tsx new file mode 100644 index 0000000..843648a --- /dev/null +++ b/src/components/LoadingBlinkBox/cmp.tsx @@ -0,0 +1,14 @@ +"use client"; + +import React from "react"; +import { LoadingBlinkBoxProps } from "./types"; +import { StyledLoadingBlinkBox } from "./styles"; + +export const LoadingBlinkBox = ({ + children, + ...props +}: LoadingBlinkBoxProps) => { + return props.loading ? : children; +}; + +export default LoadingBlinkBox; diff --git a/src/components/LoadingBlinkBox/index.tsx b/src/components/LoadingBlinkBox/index.tsx new file mode 100644 index 0000000..a05ebc5 --- /dev/null +++ b/src/components/LoadingBlinkBox/index.tsx @@ -0,0 +1 @@ +export { default } from "./cmp"; diff --git a/src/components/LoadingBlinkBox/styles.tsx b/src/components/LoadingBlinkBox/styles.tsx new file mode 100644 index 0000000..51fe5e4 --- /dev/null +++ b/src/components/LoadingBlinkBox/styles.tsx @@ -0,0 +1,29 @@ +import styled, { css } from "styled-components"; +import { LoadingBlinkBoxProps } from "./types"; + +export const StyledLoadingBlinkBox = styled.div` + ${({ + theme, + loading, + loadingHeight, + loadingWidth, + color = theme.color.dark0, + }) => { + if (!loading) return css``; + + return css` + @keyframes blinker { + 50% { + opacity: 33%; + } + } + + animation: blinker 3s linear infinite; + width: ${loadingWidth}; + min-height: ${loadingHeight}; + background-color: ${color}; + border-radius: 0.5rem; + margin-bottom: 1em; + `; + }} +`; diff --git a/src/components/LoadingBlinkBox/types.ts b/src/components/LoadingBlinkBox/types.ts new file mode 100644 index 0000000..ea183dc --- /dev/null +++ b/src/components/LoadingBlinkBox/types.ts @@ -0,0 +1,7 @@ +export type LoadingBlinkBoxProps = { + children?: React.ReactNode; + loading: boolean; + loadingHeight: string; + loadingWidth: string; + color?: string; +}; From 75c55a22fcbbcce0d48ca163256cc73f42607c1f Mon Sep 17 00:00:00 2001 From: gmolki Date: Mon, 10 Jun 2024 13:58:51 +0200 Subject: [PATCH 2/7] style/refactor: improve loading state for blog article card and grid --- src/components/Blog/BlogArticleCard/cmp.tsx | 463 +++++++++++++------ src/components/Blog/BlogArticleCard/types.ts | 1 + src/components/Blog/BlogArticlesGrid/cmp.tsx | 21 +- 3 files changed, 334 insertions(+), 151 deletions(-) diff --git a/src/components/Blog/BlogArticleCard/cmp.tsx b/src/components/Blog/BlogArticleCard/cmp.tsx index c143f9c..f33b7e1 100644 --- a/src/components/Blog/BlogArticleCard/cmp.tsx +++ b/src/components/Blog/BlogArticleCard/cmp.tsx @@ -2,6 +2,7 @@ import React from "react"; import { BlogArticleCardProps } from "./types"; import Image from "next/image"; import { Button, Col, Icon, Row, TextGradient } from "@aleph-front/core"; +import LoadingBlinkBox from "@/components/LoadingBlinkBox"; // TODO: Refactor to use styled components // TODO: Move to front-core (probably) @@ -14,175 +15,307 @@ export const BlogArticleCard = ({ category, blogArticleUrl, size = "md", + loading = true, }: BlogArticleCardProps) => { switch (size) { case "md": return (
-
- Article Image +
+ +
+ Article Image +
+
-

{category}

-

- {title} -

+

{category}

+ + +

+ {title} +

+
-

- {description} -

- + +
); case "lg": return (
-
- Article Image +
+ +
+ Article Image +
+
+
-

{category}

-

- {title} -

+

{category}

+ + +

+ {title} +

+
-

- {description} -

- + +
); case "xl": return (
-
- Article Image +
+ +
+ Article Image +
+
-

{category}

- - {title} - -

- {headline} -

+

{category}

+ + + + {title} + +

+ {headline} +

+
-

- {description} -

- + +
); case "full": + const imageCmpFull = ( + +
+ Article Image +
+
+ ); + return (
-

{category}

- - {title} - + +

{category}

+
+ + + {title} + +
-

- {headline} -

-

+ {headline} +

+ +
{imageCmpFull}
+ - {description} -

+

+ {description} +

+
- + +
- -
- Article Image -
- + {imageCmpFull}
); case "highlighted": - const imageCmp = ( -
- Article Image -
+ const imageCmpHighlighted = ( + +
+ Article Image +
+
); return ( @@ -190,53 +323,83 @@ export const BlogArticleCard = ({
-

{category}

- +

{category}

+ + + + {title} + + + - {title} -
-

- {headline} -

-
-
{imageCmp}
-
-

- {description} + {headline}

+ +
+
{imageCmpHighlighted}
+
+
+ +

+ {description} +

+
- - + + +
- {imageCmp} + {imageCmpHighlighted}
); diff --git a/src/components/Blog/BlogArticleCard/types.ts b/src/components/Blog/BlogArticleCard/types.ts index 9262820..76b86f3 100644 --- a/src/components/Blog/BlogArticleCard/types.ts +++ b/src/components/Blog/BlogArticleCard/types.ts @@ -7,4 +7,5 @@ export type BlogArticleCardProps = { category: string; blogArticleUrl: string; size?: "md" | "lg" | "xl" | "full" | "highlighted"; + loading: boolean; }; diff --git a/src/components/Blog/BlogArticlesGrid/cmp.tsx b/src/components/Blog/BlogArticlesGrid/cmp.tsx index a0eeb82..dc18608 100644 --- a/src/components/Blog/BlogArticlesGrid/cmp.tsx +++ b/src/components/Blog/BlogArticlesGrid/cmp.tsx @@ -134,7 +134,25 @@ export const AllBlogArticles = ({ continueFetchingBlogArticles(); }; - if (loading && blogArticles.size === 0) return

Loading...

; + if (loading && blogArticles.size === 0) + return ( + + {Array.from({ length: articlesPerPage }).map((_, index) => ( + + ))} + + ); if (blogArticles.size === 0) return; return ( @@ -154,6 +172,7 @@ export const AllBlogArticles = ({ blogArticleUrl={blogArticle.url} size={articleSize} category={blogArticle.category.value.data.name} + loading={loading} /> ); })} From eb95929d4eb27700458d969366acde2c34fd05f0 Mon Sep 17 00:00:00 2001 From: gmolki Date: Mon, 10 Jun 2024 16:59:52 +0200 Subject: [PATCH 3/7] style/refactor: loading state for Page Categorization name --- src/components/Blog/BlogBreadcrumb/cmp.tsx | 31 +--------- .../Blog/CategorizationDisplayName/cmp.tsx | 56 ++++++++++++------- 2 files changed, 39 insertions(+), 48 deletions(-) diff --git a/src/components/Blog/BlogBreadcrumb/cmp.tsx b/src/components/Blog/BlogBreadcrumb/cmp.tsx index eb751bb..f1563a2 100644 --- a/src/components/Blog/BlogBreadcrumb/cmp.tsx +++ b/src/components/Blog/BlogBreadcrumb/cmp.tsx @@ -3,12 +3,10 @@ import { ReactNode, useEffect, useState } from "react"; import { StyledBlogBreadcrumb } from "./styles"; import { BlogBreadcrumbProps } from "./types"; import { useGetPageCategorization } from "@/hooks/blog/useGetPageCategorization"; -import { fetchAllCategories } from "@/utils/blog/fetchAllCategories"; -import { fetchAllTags } from "@/utils/blog/fetchAllTags"; +import CategorizationDisplayName from "../CategorizationDisplayName"; export const BlogBreadcrumb = (props: BlogBreadcrumbProps) => { const DEFAULT_CATEGORIZATION_TYPE = "Classification Type"; - const DEFAULT_CATEGORIZATION_DISPLAY_NAME = "Classification Display Name"; const DEFAULT_CATEGORIZATION_ID = "category"; const [links, setLinks] = useState([]); @@ -24,32 +22,7 @@ export const BlogBreadcrumb = (props: BlogBreadcrumbProps) => { , ]; - async function fetchCategorizationDisplayName() { - let allCategorizations = undefined; - - switch (pageCategorization?.type) { - case "categories": - allCategorizations = await fetchAllCategories(); - break; - case "tags": - allCategorizations = await fetchAllTags(); - break; - } - - const currentClassification = allCategorizations?.find( - (categorization) => { - return categorization.id == pageCategorization?.id; - } - ); - - return ( - currentClassification?.displayName || - DEFAULT_CATEGORIZATION_DISPLAY_NAME - ); - } - async function calculateCategorizationLinks() { - const categorizationDisplayName = await fetchCategorizationDisplayName(); const categorizationType = pageCategorization?.type || DEFAULT_CATEGORIZATION_TYPE; const categorizationId = @@ -64,7 +37,7 @@ export const BlogBreadcrumb = (props: BlogBreadcrumbProps) => { href={`/blog/${categorizationType}/${categorizationId}`} key={categorizationId} > - {categorizationDisplayName} + , ]; diff --git a/src/components/Blog/CategorizationDisplayName/cmp.tsx b/src/components/Blog/CategorizationDisplayName/cmp.tsx index e40f023..c061d78 100644 --- a/src/components/Blog/CategorizationDisplayName/cmp.tsx +++ b/src/components/Blog/CategorizationDisplayName/cmp.tsx @@ -1,3 +1,4 @@ +import LoadingBlinkBox from "@/components/LoadingBlinkBox"; import { useGetPageCategorization } from "@/hooks/blog/useGetPageCategorization"; import { fetchAllCategories } from "@/utils/blog/fetchAllCategories"; import { fetchAllTags } from "@/utils/blog/fetchAllTags"; @@ -6,38 +7,55 @@ import { useEffect, useState } from "react"; const DEFAULT_DISPLAY_NAME = "Categorization Display Name"; export const CategorizationDisplayName = () => { + const [loading, setLoading] = useState(true); const [categorizationDisplayName, setCategorizationDisplayName] = useState(DEFAULT_DISPLAY_NAME); const pageCategorization = useGetPageCategorization(); useEffect(() => { async function fetchCategorizationDisplayName() { - let allCategorizations = undefined; - - switch (pageCategorization?.type) { - case "categories": - allCategorizations = await fetchAllCategories(); - break; - case "tags": - allCategorizations = await fetchAllTags(); - break; - } - - const currentCategorization = allCategorizations?.find( - (categorization) => { - return categorization.id == pageCategorization?.id; + setLoading(true); + + try { + let allCategorizations = undefined; + + switch (pageCategorization?.type) { + case "categories": + allCategorizations = await fetchAllCategories(); + break; + case "tags": + allCategorizations = await fetchAllTags(); + break; } - ); - setCategorizationDisplayName( - currentCategorization?.displayName || DEFAULT_DISPLAY_NAME - ); + const currentCategorization = allCategorizations?.find( + (categorization) => { + return categorization.id == pageCategorization?.id; + } + ); + + setCategorizationDisplayName( + currentCategorization?.displayName || DEFAULT_DISPLAY_NAME + ); + } catch (error) { + console.error("Error fetching categorization display name", error); + } finally { + setLoading(false); + } } fetchCategorizationDisplayName(); }, [pageCategorization]); - return categorizationDisplayName; + return ( + + {categorizationDisplayName} + + ); }; export default CategorizationDisplayName; From 1a726733de05b440bfa472f48c31386efe31a2d3 Mon Sep 17 00:00:00 2001 From: gmolki Date: Mon, 10 Jun 2024 18:02:16 +0200 Subject: [PATCH 4/7] style/refactor: loading state for Tags and Categories --- src/components/Blog/BlogCategories/cmp.tsx | 61 +++++++++++----------- src/components/Blog/BlogTags/cmp.tsx | 61 +++++++++++----------- 2 files changed, 62 insertions(+), 60 deletions(-) diff --git a/src/components/Blog/BlogCategories/cmp.tsx b/src/components/Blog/BlogCategories/cmp.tsx index 4e1fbc1..f8480f0 100644 --- a/src/components/Blog/BlogCategories/cmp.tsx +++ b/src/components/Blog/BlogCategories/cmp.tsx @@ -5,6 +5,7 @@ import { getRandomUniqueElements } from "@/utils/getRandomUniqueElements"; import { Button, Icon } from "@aleph-front/core"; import React, { useCallback } from "react"; import { BlogCategoriesProps } from "./types"; +import LoadingBlinkBox from "@/components/LoadingBlinkBox"; export const BlogCategories = ({ amount = 10 }: BlogCategoriesProps) => { const { data: categories, loading } = useCachedData( @@ -12,44 +13,44 @@ export const BlogCategories = ({ amount = 10 }: BlogCategoriesProps) => { useCallback(fetchAllCategories, []) ); - if (loading) { + const titleCmp = ( +
+

Categories

+ +
+ ); + + if (loading) return ( <> -
-

Categories

- + {titleCmp} +
+ {Array.from({ length: amount }).map((_, index) => ( + + ))}
-

Loading...

); - } return ( <> -
-

Categories

- -
+ {titleCmp}
{getRandomUniqueElements(categories, amount).map( (category: BlogCategoryProps) => { diff --git a/src/components/Blog/BlogTags/cmp.tsx b/src/components/Blog/BlogTags/cmp.tsx index 8cf43d3..c98e0e1 100644 --- a/src/components/Blog/BlogTags/cmp.tsx +++ b/src/components/Blog/BlogTags/cmp.tsx @@ -5,6 +5,7 @@ import { fetchAllTags } from "@/utils/blog/fetchAllTags"; import { BlogTagProps } from "@/types/blog/BlogTagProps"; import { BlogTagsProps } from "./types"; import { getRandomUniqueElements } from "@/utils/getRandomUniqueElements"; +import LoadingBlinkBox from "@/components/LoadingBlinkBox"; export const BlogTags = ({ amount = 10 }: BlogTagsProps) => { const { data: tags, loading } = useCachedData( @@ -12,44 +13,44 @@ export const BlogTags = ({ amount = 10 }: BlogTagsProps) => { useCallback(fetchAllTags, []) ); - if (loading) { + const titleCmp = ( +
+

Tags

+ +
+ ); + + if (loading) return ( <> -
-

Tags

- + {titleCmp} +
+ {Array.from({ length: amount }).map((_, index) => ( + + ))}
-

Loading...

); - } return ( <> -
-

Tags

- -
+ {titleCmp}
{getRandomUniqueElements(tags, amount).map( (tag: BlogTagProps) => { From c9ee01c076a5fb92abd9cec4e117167e38089422 Mon Sep 17 00:00:00 2001 From: gmolki Date: Mon, 10 Jun 2024 18:19:19 +0200 Subject: [PATCH 5/7] style/refactor: loading state for Tags and Categories filters --- .../Blog/BlogCategoriesFilter/cmp.tsx | 41 ++++++++++++++----- src/components/Blog/BlogTagsFilter/cmp.tsx | 41 ++++++++++++++----- 2 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/components/Blog/BlogCategoriesFilter/cmp.tsx b/src/components/Blog/BlogCategoriesFilter/cmp.tsx index b8f6779..1e42767 100644 --- a/src/components/Blog/BlogCategoriesFilter/cmp.tsx +++ b/src/components/Blog/BlogCategoriesFilter/cmp.tsx @@ -1,3 +1,4 @@ +import LoadingBlinkBox from "@/components/LoadingBlinkBox"; import useCachedData from "@/hooks/common/useCachedData"; import { BlogCategoryProps } from "@/types/blog/BlogCategoryProps"; import { fetchAllCategories } from "@/utils/blog/fetchAllCategories"; @@ -61,7 +62,35 @@ export const BlogCategories = () => { ); }, [searchParams]); - if (loading) return

Loading...

; + const clearAllFiltersCmp = ( + + ); + + if (loading) + return ( + <> +
+ {Array.from({ length: 12 }).map((_, index) => ( + + ))} +
+ {clearAllFiltersCmp} + + ); return ( <> @@ -91,15 +120,7 @@ export const BlogCategories = () => { ); })}
- + {clearAllFiltersCmp} ); }; diff --git a/src/components/Blog/BlogTagsFilter/cmp.tsx b/src/components/Blog/BlogTagsFilter/cmp.tsx index fc8c945..14dfb95 100644 --- a/src/components/Blog/BlogTagsFilter/cmp.tsx +++ b/src/components/Blog/BlogTagsFilter/cmp.tsx @@ -1,3 +1,4 @@ +import LoadingBlinkBox from "@/components/LoadingBlinkBox"; import useCachedData from "@/hooks/common/useCachedData"; import { BlogCategoryProps } from "@/types/blog/BlogCategoryProps"; import { fetchAllTags } from "@/utils/blog/fetchAllTags"; @@ -56,7 +57,35 @@ export const BlogTags = () => { ); }, [searchParams]); - if (loading) return

Loading...

; + const clearAllFiltersCmp = ( + + ); + + if (loading) + return ( + <> +
+ {Array.from({ length: 12 }).map((_, index) => ( + + ))} +
+ {clearAllFiltersCmp} + + ); return ( <> @@ -86,15 +115,7 @@ export const BlogTags = () => { ); })}
- + {clearAllFiltersCmp} ); }; From 455d3f61d09646998dd7e90bb459e966cfc03a59 Mon Sep 17 00:00:00 2001 From: gmolki Date: Mon, 10 Jun 2024 18:57:13 +0200 Subject: [PATCH 6/7] style/refactor: spinner in load more button --- src/components/Blog/BlogArticlesGrid/cmp.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/Blog/BlogArticlesGrid/cmp.tsx b/src/components/Blog/BlogArticlesGrid/cmp.tsx index dc18608..4286236 100644 --- a/src/components/Blog/BlogArticlesGrid/cmp.tsx +++ b/src/components/Blog/BlogArticlesGrid/cmp.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useMemo, useState } from "react"; import BlogArticleCard from "../BlogArticleCard"; -import { Button } from "@aleph-front/core"; +import { Button, Spinner } from "@aleph-front/core"; import { AllBlogArticlesProps, Filters } from "./types"; import { StyledBlogArticlesGrid } from "./styles"; import { useGetPageCategorization } from "@/hooks/blog/useGetPageCategorization"; @@ -8,6 +8,7 @@ import useFetchBlogArticles from "@/hooks/blog/useFetchBlogArticles"; import { GetContentOptions } from "@builder.io/sdk"; import { useSearchParams } from "next/navigation"; import { DEFAULT_BUILDER_REQUEST_OPTIONS } from "@/constants/blog"; +import { useTheme } from "styled-components"; function buildFilters(searchParams: any, pageCategorization: any): any { const queryParams = new URLSearchParams(searchParams); @@ -45,6 +46,7 @@ export const AllBlogArticles = ({ articlesLimit, customBuilderRequestOptions, }: AllBlogArticlesProps) => { + const theme: any = useTheme(); const searchParams = useSearchParams(); const pageCategorization = useGetPageCategorization(); const [blogArticles, setBlogArticles] = useState>(new Set()); @@ -172,7 +174,6 @@ export const AllBlogArticles = ({ blogArticleUrl={blogArticle.url} size={articleSize} category={blogArticle.category.value.data.name} - loading={loading} /> ); })} @@ -187,7 +188,11 @@ export const AllBlogArticles = ({ onClick={handleLoadMore} disabled={loading} > - {loading ? "Loading..." : "Load more"} + {loading ? ( + + ) : ( + "Load more" + )}
)} From 9d969e917652c5de4a0d70767a99e0a747d94eb8 Mon Sep 17 00:00:00 2001 From: gmolki Date: Mon, 10 Jun 2024 18:57:43 +0200 Subject: [PATCH 7/7] fix: LoadingBlinkBox default loading state to false --- src/components/Blog/BlogArticleCard/cmp.tsx | 2 +- src/components/Blog/BlogArticleCard/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Blog/BlogArticleCard/cmp.tsx b/src/components/Blog/BlogArticleCard/cmp.tsx index f33b7e1..28192e4 100644 --- a/src/components/Blog/BlogArticleCard/cmp.tsx +++ b/src/components/Blog/BlogArticleCard/cmp.tsx @@ -15,7 +15,7 @@ export const BlogArticleCard = ({ category, blogArticleUrl, size = "md", - loading = true, + loading = false, }: BlogArticleCardProps) => { switch (size) { case "md": diff --git a/src/components/Blog/BlogArticleCard/types.ts b/src/components/Blog/BlogArticleCard/types.ts index 76b86f3..6a6e762 100644 --- a/src/components/Blog/BlogArticleCard/types.ts +++ b/src/components/Blog/BlogArticleCard/types.ts @@ -7,5 +7,5 @@ export type BlogArticleCardProps = { category: string; blogArticleUrl: string; size?: "md" | "lg" | "xl" | "full" | "highlighted"; - loading: boolean; + loading?: boolean; };