From bd2a450c284d8c20aaa69860f82d9ff93f4f1f38 Mon Sep 17 00:00:00 2001 From: John Ballesteros Date: Thu, 15 Aug 2024 13:32:38 +0800 Subject: [PATCH 1/8] refactor: prefetch grant-details from grant-list --- .../components/grant-list/use-grant-list.ts | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/grants/components/grant-list/use-grant-list.ts b/src/grants/components/grant-list/use-grant-list.ts index 54c6ab1..3fbbba8 100644 --- a/src/grants/components/grant-list/use-grant-list.ts +++ b/src/grants/components/grant-list/use-grant-list.ts @@ -1,10 +1,24 @@ +import { useEffect } from 'react'; import { useInView } from 'react-intersection-observer'; +import { getQueryClient } from '@/shared/utils/get-query-client'; + +import { grantQueryKeys } from '@/grants/core/query-keys'; +import { getGrantDetails } from '@/grants/data/get-grant-details'; import { useGrantListQuery } from '@/grants/hooks/use-grant-list-query'; export const useGrantList = () => { - const { data, error, fetchNextPage, hasNextPage, isPending, isFetching } = - useGrantListQuery(); + const queryClient = getQueryClient(); + + const { + data, + error, + fetchNextPage, + hasNextPage, + isPending, + isFetching, + isSuccess, + } = useGrantListQuery(); // Next page fetch on scroll const { ref: inViewRef } = useInView({ @@ -14,6 +28,20 @@ export const useGrantList = () => { }, }); + // Prefetch grant details + useEffect(() => { + if (isSuccess && data) { + const items = data.pages.flatMap((d) => d.data); + for (const item of items) { + const { id } = item; + queryClient.prefetchQuery({ + queryKey: grantQueryKeys.details(id), + queryFn: () => getGrantDetails(id), + }); + } + } + }); + return { grants: data?.pages.flatMap((d) => d.data) ?? [], error, From c9c8f037310a4608ad9f274ece4a76c7849487d3 Mon Sep 17 00:00:00 2001 From: John Ballesteros Date: Thu, 15 Aug 2024 13:46:37 +0800 Subject: [PATCH 2/8] refactor: ssr initial items for grant-list --- src/grants/pages/grant-list-page.tsx | 42 ++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/grants/pages/grant-list-page.tsx b/src/grants/pages/grant-list-page.tsx index e8b7821..856795c 100644 --- a/src/grants/pages/grant-list-page.tsx +++ b/src/grants/pages/grant-list-page.tsx @@ -1,11 +1,43 @@ +import { dehydrate, HydrationBoundary } from '@tanstack/react-query'; + +import { getQueryClient } from '@/shared/utils/get-query-client'; + +import { grantQueryKeys } from '@/grants/core/query-keys'; +import { getGrantDetails } from '@/grants/data/get-grant-details'; +import { getGrantList } from '@/grants/data/get-grant-list'; import { GrantList } from '@/grants/components/grant-list/grant-list'; -export const GrantListPage = () => { - // TODO: React-Query SSR grant list +// TODO: Check if need to use search params(filter related), if so need to force dynamic + +export const GrantListPage = async () => { + const queryClient = getQueryClient(); + + const [grantListResult] = await Promise.all([ + // Prefetch list + queryClient.fetchInfiniteQuery({ + queryKey: grantQueryKeys.list(''), + queryFn: async ({ pageParam }) => getGrantList(pageParam), + initialPageParam: 1, + }), + ]); + + // Prefetch details for each grant item + await Promise.all( + grantListResult.pages + .flatMap((page) => page.data) + .map(({ id }) => + queryClient.prefetchQuery({ + queryKey: grantQueryKeys.details(id), + queryFn: () => getGrantDetails(id), + }), + ), + ); return ( -
- -
+ +
+ +
+
); }; From 9a1727e25e1906259388c23dd132a76033d06b17 Mon Sep 17 00:00:00 2001 From: John Ballesteros Date: Thu, 15 Aug 2024 15:14:50 +0800 Subject: [PATCH 3/8] refactor: ssr initial items for grantee-list which includes default grantee-card --- src/app/grants/[grantId]/@list/page.tsx | 39 +++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/app/grants/[grantId]/@list/page.tsx b/src/app/grants/[grantId]/@list/page.tsx index 8f4ed60..b3d87e5 100644 --- a/src/app/grants/[grantId]/@list/page.tsx +++ b/src/app/grants/[grantId]/@list/page.tsx @@ -1,13 +1,46 @@ +import { dehydrate, HydrationBoundary } from '@tanstack/react-query'; + +import { getQueryClient } from '@/shared/utils/get-query-client'; + +import { grantQueryKeys } from '@/grants/core/query-keys'; +import { getGranteeDetails } from '@/grants/data/get-grantee-details'; +import { getGranteesList } from '@/grants/data/get-grantees-list'; import { GranteeList } from '@/grants/components/grantee-list'; interface Props { params: { grantId: string }; } -const ParallelGranteeList = ({}: Props) => { - // TODO: React-Query SSR grantee list +const ParallelGranteeList = async ({ params: { grantId } }: Props) => { + const queryClient = getQueryClient(); + + const [granteeListResult] = await Promise.all([ + // Prefetch list + queryClient.fetchInfiniteQuery({ + queryKey: grantQueryKeys.grantees(grantId, ''), + queryFn: async ({ pageParam: page }) => + getGranteesList({ page, grantId }), + initialPageParam: 1, + }), + ]); + + // Prefetch details for each grantee item + await Promise.all( + granteeListResult.pages + .flatMap((page) => page.data) + .map(({ id }) => + queryClient.prefetchQuery({ + queryKey: grantQueryKeys.grantee(id), + queryFn: () => getGranteeDetails(id), + }), + ), + ); - return ; + return ( + + + + ); }; export default ParallelGranteeList; From 63847d8bc03a38fb19a8643ce9e445c477fefcda Mon Sep 17 00:00:00 2001 From: John Ballesteros Date: Thu, 15 Aug 2024 15:15:34 +0800 Subject: [PATCH 4/8] chore: smol cleanup --- src/shared/utils/get-query-client.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/shared/utils/get-query-client.ts b/src/shared/utils/get-query-client.ts index dc0fa65..a925d40 100644 --- a/src/shared/utils/get-query-client.ts +++ b/src/shared/utils/get-query-client.ts @@ -17,12 +17,12 @@ export const getQueryClient = () => { if (typeof window === 'undefined') { // Server: always make a new query client return makeQueryClient(); - } else { - // Browser: make a new query client if we don't already have one - // This is very important so we don't re-make a new client if React - // supsends during the initial render. This may not be needed if we - // have a suspense boundary BELOW the creation of the query client - if (!browserQueryClient) browserQueryClient = makeQueryClient(); - return browserQueryClient; } + + // Browser: make a new query client if we don't already have one + // This is very important so we don't re-make a new client if React + // supsends during the initial render. This may not be needed if we + // have a suspense boundary BELOW the creation of the query client + if (!browserQueryClient) browserQueryClient = makeQueryClient(); + return browserQueryClient; }; From ad1df5faf1be65eed7a883fcbf18397938e9a47d Mon Sep 17 00:00:00 2001 From: cristiano cardelli Date: Thu, 15 Aug 2024 10:53:58 +0200 Subject: [PATCH 5/8] navi mobile/tablet/desktop --- src/app/layout.tsx | 2 +- src/shared/components/brand.tsx | 3 --- src/shared/components/menu-button.tsx | 2 +- src/shared/components/mobile-header.tsx | 2 +- src/shared/components/nav/index.tsx | 2 +- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 7b577ce..d83198d 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -29,7 +29,7 @@ interface RootLayoutProps { const RootLayout: React.FC = ({ children }) => ( diff --git a/src/shared/components/brand.tsx b/src/shared/components/brand.tsx index 392031e..eb837ff 100644 --- a/src/shared/components/brand.tsx +++ b/src/shared/components/brand.tsx @@ -1,14 +1,11 @@ import Image from 'next/image'; import Link from 'next/link'; -const MIN_HEIGHT_STYLE = { minHeight: 53 }; - export const Brand = () => { return (
{ return ( -
+
ecosystem.vision • ecosystem.vision • ecosystem.vision • ecosystem.vision • ecosystem.vision • ecosystem.vision • ecosystem.vision • ecosystem.vision • ecosystem.vision • @@ -53,13 +53,13 @@ export const HomePage = () => { -
+
-

+

Connect, Earn, and Grow with Verified Web3 Professionals

-

+

Accelerate your projects and earn money by connecting with verified professionals in top Web3 companies. Dynamic pricing ensures fair compensation, while rigorous verification through @@ -72,15 +72,15 @@ export const HomePage = () => { {'placeholder'}

-
+
@@ -99,11 +99,11 @@ export const HomePage = () => {
-

+

Grant Impact Analysis: A Collaboration with Ecosystem Vision and the Cartographer Syndicates

-

+

Gain deep insights into the effectiveness of grant programs with our detailed metrics and analyses. Our collaboration with ThankArb, Ecosystem Vision, and the Cartographer Syndicate @@ -125,8 +125,8 @@ export const HomePage = () => { {'placeholder'}

@@ -134,10 +134,10 @@ export const HomePage = () => {
-

+

Real Success Stories from Web3 Professionals

-

+

Read success stories of how our platform has helped users connect with verified professionals, access valuable data, and drive their projects forward. @@ -171,59 +171,76 @@ export const HomePage = () => {

-
-

- Discover Leading Organizations in Web3 -

-

- Gain access to detailed profiles of over 6,500 leading Web3 - organizations. Our data includes comprehensive company summaries, - URLs, social media handles, documentation, grant information, and - venture capital investments. Sort by recent funding, industry, and - more to discover the perfect partners and opportunities. -

- -
+
+
+
+ {'app'} +
+
+
+

+ Discover Leading Organizations in Web3 +

+

+ Gain access to detailed profiles of over 6,500 leading Web3 + organizations. Our data includes comprehensive company summaries, + URLs, social media handles, documentation, grant information, and + venture capital investments. Sort by recent funding, industry, and + more to discover the perfect partners and opportunities. +

+ +
+
+
+
{'placeholder'}
+
+

+ Explore Top Grant Programs +

+

+ Access detailed data on over 4,000 top Web3 projects, including + insights into total value locked (TVL), financial metrics, network + deployments, and ecosystem details. Utilize advanced sorting and + filtering to identify high-impact projects and understand their + significance within the Web3 landscape@/home +

+ +
-
-

- Explore Top Grant Programs -

-

- Access detailed data on over 4,000 top Web3 projects, including - insights into total value locked (TVL), financial metrics, network - deployments, and ecosystem details. Utilize advanced sorting and - filtering to identify high-impact projects and understand their - significance within the Web3 landscape@/home -

- -
-
-
+
+
{'Ecosystem.vision'} { priority />
-
+

Join Now and Start Earning

From ebebcbe30cb114cd62ad3cba4690365388e3e941 Mon Sep 17 00:00:00 2001 From: John Ballesteros Date: Thu, 15 Aug 2024 18:15:39 +0800 Subject: [PATCH 7/8] refactor: only prefetch first item on the grantee list in grant-layout page --- src/app/grants/[grantId]/@list/page.tsx | 31 ++++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/app/grants/[grantId]/@list/page.tsx b/src/app/grants/[grantId]/@list/page.tsx index b3d87e5..d2986a0 100644 --- a/src/app/grants/[grantId]/@list/page.tsx +++ b/src/app/grants/[grantId]/@list/page.tsx @@ -4,6 +4,7 @@ import { getQueryClient } from '@/shared/utils/get-query-client'; import { grantQueryKeys } from '@/grants/core/query-keys'; import { getGranteeDetails } from '@/grants/data/get-grantee-details'; +import { getGranteeProject } from '@/grants/data/get-grantee-project'; import { getGranteesList } from '@/grants/data/get-grantees-list'; import { GranteeList } from '@/grants/components/grantee-list'; @@ -24,17 +25,29 @@ const ParallelGranteeList = async ({ params: { grantId } }: Props) => { }), ]); - // Prefetch details for each grantee item - await Promise.all( - granteeListResult.pages - .flatMap((page) => page.data) - .map(({ id }) => + // Prefetch data for first item only (default for the page enough for seo) + const grantee = granteeListResult.pages.flatMap((page) => page.data).at(0); + if (grantee) { + // Prefetch grantee details + const promises = [ + queryClient.prefetchQuery({ + queryKey: grantQueryKeys.grantee(grantee.id), + queryFn: () => getGranteeDetails(grantee.id), + }), + ]; + + // Prefetch first project details + if (grantee.projects.length > 0) { + promises.push( queryClient.prefetchQuery({ - queryKey: grantQueryKeys.grantee(id), - queryFn: () => getGranteeDetails(id), + queryKey: grantQueryKeys.project(grantee.projects[0]), + queryFn: () => getGranteeProject(grantee.projects[0]), }), - ), - ); + ); + } + + await Promise.all(promises); + } return ( From 74b97741d09b6d87b778d4686f4f225dd5eb6176 Mon Sep 17 00:00:00 2001 From: cristiano cardelli Date: Thu, 15 Aug 2024 12:31:35 +0200 Subject: [PATCH 8/8] all right let's go --- src/app/globals.css | 101 +++++++++++++++++++++++--------- src/home/components/marquee.tsx | 26 ++++++++ src/home/pages/home-page.tsx | 7 +-- 3 files changed, 101 insertions(+), 33 deletions(-) create mode 100644 src/home/components/marquee.tsx diff --git a/src/app/globals.css b/src/app/globals.css index 37d42a1..ec4f4a9 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -3,49 +3,92 @@ @tailwind utilities; @layer base { - :root { - /* TODO: review values of the variables primary/secondary */ - --color-base-dark: 13 13 13; /* #0D0D0D */ - --color-dark-gray: 25 25 25; /* #191919 */ - --color-medium-gray: 32 32 32; /* #202020 */ - --color-light-gray: 153 153 153; /* #999999 */ - --color-cool-gray: 156 163 175; /* #9CA3AF */ - --color-white: 255 255 255; /* #FFFFFF */ - --color-primary: 65 54 241; /* #4136F1 */ - --color-secondary: 135 67 255; /* #8743FF */ - --color-labels: 239 239 239; /* #EFEFEF */ - --color-border: 240 238 237; /* #F0EEED */ - --color-tertiary: 219 217 251; /* #DBD9FB */ - --color-grantee-item: 117 112 141; - - /* HP variables to rearrange */ - --color-gradient-1: 117 117 117; /* #757575 */ - --color-gradient-2: 117 112 141; /* #75708D */ - --color-innovate: 31 31 38; /* #1F1F26 */ - } -} + :root { + /* TODO: review values of the variables primary/secondary */ + --color-base-dark: 13 13 13; /* #0D0D0D */ + --color-dark-gray: 25 25 25; /* #191919 */ + --color-medium-gray: 32 32 32; /* #202020 */ + --color-light-gray: 153 153 153; /* #999999 */ + --color-cool-gray: 156 163 175; /* #9CA3AF */ + --color-white: 255 255 255; /* #FFFFFF */ + --color-primary: 65 54 241; /* #4136F1 */ + --color-secondary: 135 67 255; /* #8743FF */ + --color-labels: 239 239 239; /* #EFEFEF */ + --color-border: 240 238 237; /* #F0EEED */ + --color-tertiary: 219 217 251; /* #DBD9FB */ + --color-grantee-item: 117 112 141; + /* HP variables to rearrange */ + --color-gradient-1: 117 117 117; /* #757575 */ + --color-gradient-2: 117 112 141; /* #75708D */ + --color-innovate: 31 31 38; /* #1F1F26 */ + } +} html { - overflow-y: scroll; - scrollbar-gutter: stable; + overflow-y: scroll; + scrollbar-gutter: stable; } - .hide-scrollbar { - -ms-overflow-style: none; - scrollbar-width: none; + -ms-overflow-style: none; + scrollbar-width: none; } .hide-scrollbar::-webkit-scrollbar { - display: none; + display: none; } .is-active { - @apply bg-gradient-to-r from-white/100 text-black to-light-gray + @apply bg-gradient-to-r from-white/100 text-black to-light-gray; } /* remove padding in storybook to easily work on the homepage */ .sb-main-padded { - padding: 0 !important; + padding: 0 !important; +} + +/* Marquee styles */ +.marquee { + --gap: 1px; + position: relative; + display: flex; + overflow: hidden; + user-select: none; + gap: var(--gap); +} + +.marquee__content { + flex-shrink: 0; + display: flex; + gap: var(--gap); + justify-content: space-around; + min-width: 100%; +} +.marquee__item { + width: 115px; +} +@screen md { + .marquee__item { + width: 170px; + } +} +@screen lg { + .marquee__item { + width: 228px; + } + } +/* marquee amimation */ +@keyframes scroll { + from { + transform: translateX(0); + } + to { + transform: translateX(calc(-100% - var(--gap))); + } +} + +/* Enable animation */ +.enable-animation .marquee__content { + animation: scroll 30s linear infinite; } diff --git a/src/home/components/marquee.tsx b/src/home/components/marquee.tsx new file mode 100644 index 0000000..e9d6300 --- /dev/null +++ b/src/home/components/marquee.tsx @@ -0,0 +1,26 @@ +export const Marquee = () => { + return ( +
+ +
+
+
ecosystem.vision • 
+
ecosystem.vision • 
+
ecosystem.vision • 
+
ecosystem.vision • 
+
ecosystem.vision • 
+
ecosystem.vision • 
+
+ + +
+
+ ); +}; diff --git a/src/home/pages/home-page.tsx b/src/home/pages/home-page.tsx index ba83883..47a994e 100644 --- a/src/home/pages/home-page.tsx +++ b/src/home/pages/home-page.tsx @@ -6,6 +6,7 @@ import { Button } from '@nextui-org/react'; import { FeatureSwiper } from '@/home/components/feature-swiper'; import { Footer } from '@/home/components/footer'; import { FlashIcon } from '@/home/components/icons/flash'; +import { Marquee } from '@/home/components/marquee'; import { TestimonialSwiper } from '@/home/components/testimonial-swiper'; export const HomePage = () => { @@ -45,10 +46,8 @@ export const HomePage = () => {
-
- ecosystem.vision • ecosystem.vision • ecosystem.vision • - ecosystem.vision • ecosystem.vision • ecosystem.vision • - ecosystem.vision • ecosystem.vision • ecosystem.vision • +
+