Skip to content

Commit

Permalink
Refactor components and add pagination feature
Browse files Browse the repository at this point in the history
  • Loading branch information
hasanshahriar32 committed Oct 13, 2024
1 parent 23f8e3c commit 4801c53
Show file tree
Hide file tree
Showing 10 changed files with 438 additions and 5 deletions.
7 changes: 5 additions & 2 deletions app/(personal)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import Link from 'next/link'

import { HomePage } from '@/components/pages/home/HomePage'
import { studioUrl } from '@/sanity/lib/api'
import { loadHomePage } from '@/sanity/loader/loadQuery'
import { loadAllProject,loadHomePage } from '@/sanity/loader/loadQuery'
const HomePagePreview = dynamic(
() => import('@/components/pages/home/HomePagePreview'),
)

export default async function IndexRoute() {
const initial = await loadHomePage()
const page = 1 // specify the desired page number
const limit = 100 // specify the number of items per page
const initial2 = await loadAllProject(page, limit)

if (draftMode().isEnabled) {
return <HomePagePreview initial={initial} />
Expand All @@ -28,5 +31,5 @@ export default async function IndexRoute() {
)
}

return <HomePage data={initial.data} />
return <HomePage data2={initial2?.data} data={initial.data} />
}
7 changes: 5 additions & 2 deletions components/pages/home/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@ import type { EncodeDataAttributeCallback } from '@sanity/react-loader'
import Link from 'next/link'

import { ProjectListItem } from '@/components/pages/home/ProjectListItem'
import AllProjects from '@/components/shared/allProjects'
import { Header } from '@/components/shared/Header'
import { resolveHref } from '@/sanity/lib/utils'
import type { HomePagePayload } from '@/types'

import { Gemini } from './Gemini'
import { GlobeView } from './GlobeView'
import { TimelineShowcase } from './TimelineShowcase'
import { Gemini } from './Gemini'

export interface HomePageProps {
data: HomePagePayload | null
data2: any
encodeDataAttribute?: EncodeDataAttributeCallback
}

export function HomePage({ data, encodeDataAttribute }: HomePageProps) {
export function HomePage({ data, data2, encodeDataAttribute }: HomePageProps) {
// Default to an empty object to allow previews on non-existent documents
const { overview = [], showcaseProjects = [], title = '' } = data ?? {}

Expand Down Expand Up @@ -48,6 +50,7 @@ export function HomePage({ data, encodeDataAttribute }: HomePageProps) {
</div>
)}
<TimelineShowcase />
<AllProjects data2={data2} />
<Gemini />
<GlobeView />
</div>
Expand Down
2 changes: 1 addition & 1 deletion components/pages/home/HomePagePreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ export default function HomePagePreview(props: Props) {
)
}

return <HomePage data={data} encodeDataAttribute={encodeDataAttribute} />
return <HomePage data2={undefined} data={data} encodeDataAttribute={encodeDataAttribute} />
}
47 changes: 47 additions & 0 deletions components/shared/allCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { HoverEffect } from "@/components/ui/card-hover-effect";

export async function CardHoverEffect({ data2 }: any) {
return (
<div className="mx-auto max-w-5xl px-2 md:px-4 lg:px-6">
<HoverEffect items={projects} data2={data2} />
</div>
);
}
export const projects = [
{
title: "Stripe",
description:
"A technology company that builds economic infrastructure for the internet.",
link: "https://stripe.com",
},
{
title: "Netflix",
description:
"A streaming service that offers a wide variety of award-winning TV shows, movies, anime, documentaries, and more on thousands of internet-connected devices.",
link: "https://netflix.com",
},
{
title: "Google",
description:
"A multinational technology company that specializes in Internet-related services and products.",
link: "https://google.com",
},
{
title: "Meta",
description:
"A technology company that focuses on building products that advance Facebook's mission of bringing the world closer together.",
link: "https://meta.com",
},
{
title: "Amazon",
description:
"A multinational technology company focusing on e-commerce, cloud computing, digital streaming, and artificial intelligence.",
link: "https://amazon.com",
},
{
title: "Microsoft",
description:
"A multinational technology company that develops, manufactures, licenses, supports, and sells computer software, consumer electronics, personal computers, and related services.",
link: "https://microsoft.com",
},
];
14 changes: 14 additions & 0 deletions components/shared/allProjects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";

import { CardHoverEffect } from "./allCard";

const AllProjects = ({ data2 }: any) => {
// console.log(data2);
return (
<div>
<CardHoverEffect data2={data2} />
</div>
);
};

export default AllProjects;
210 changes: 210 additions & 0 deletions components/ui/card-hover-effect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
'use client'
import type { PortableTextBlock } from '@portabletext/types'
import { CommentIcon } from '@sanity/icons'
import { CommentCount } from 'disqus-react'
import { AnimatePresence, motion } from 'framer-motion'
import Link from 'next/link'
import { useEffect,useState } from 'react'

import ImageBox from '@/components/shared/ImageBox'
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationPrevious,
} from '@/components/ui/pagination'
import { Skeleton } from '@/components/ui/skeleton'
import { cn } from '@/lib/utils'

import { CustomPortableText } from '../shared/CustomPortableText'

export const HoverEffect = ({
items,
className,
data2,
}: {
items: {
title: string
description: string
link: string
}[]
className?: string
data2: any
}) => {
const itemsPerPage = 6
const [currentPage, setCurrentPage] = useState(1)
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
const [isClient, setIsClient] = useState(false)
const pageURL = typeof window !== 'undefined' ? window.location.href : ''

useEffect(() => {
setIsClient(true)
}, [])

const startIndex = (currentPage - 1) * itemsPerPage
const endIndex = startIndex + itemsPerPage
const visibleItems = data2?.slice(startIndex, endIndex)

const handlePreviousPage = () => {
if (currentPage > 1) {
setCurrentPage((prevPage) => prevPage - 1)
}
}

const handleNextPage = () => {
const maxPage = Math.ceil(data2.length / itemsPerPage)
if (currentPage < maxPage) {
setCurrentPage((prevPage) => prevPage + 1)
}
}

const maxPage = Math.ceil(data2?.length / itemsPerPage)

return (
<div
suppressHydrationWarning
className="mt-5 rounded-xl border border-slate-300 p-3 "
>
<div
className={cn(
'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
className,
)}
>
{visibleItems?.map((item: any, idx: any) => (
<Link
href={`/blog/post/${item?.slug}`}
key={item?._id}
className="group relative block h-full w-full p-2"
onMouseEnter={() => setHoveredIndex(idx)}
onMouseLeave={() => setHoveredIndex(null)}
>
<AnimatePresence>
{hoveredIndex === idx && (
<motion.span
className="absolute inset-0 block h-full w-full rounded-3xl bg-neutral-200 dark:bg-slate-800/[0.8]"
layoutId="hoverBackground"
initial={{ opacity: 0 }}
animate={{
opacity: 1,
transition: { duration: 0.15 },
}}
exit={{
opacity: 0,
transition: { duration: 0.15, delay: 0.2 },
}}
/>
)}
</AnimatePresence>
<Card>
<div className="w-full rounded-lg">
<ImageBox
image={item?.coverImage}
alt={`Cover image from ${item?.title}`}
classesWrapper="relative aspect-[16/9]"
/>
</div>
<CardTitle>{item?.title}</CardTitle>
<div className="-mt-5 flex items-center justify-end gap-2 font-mono text-xs text-slate-500">
<CommentIcon />
<CommentCount
shortname="hstu"
config={{
url: pageURL,
identifier: item?.slug,
title: item?.title,
}}
/>
</div>

<CardDescription>
{isClient ? (
<CustomPortableText
value={item?.overview as PortableTextBlock[]}
/>
) : (
<div className="space-y-2">
<Skeleton className="h-4 w-full" />
<Skeleton className="h-4 w-3/4" />
</div>
)}
</CardDescription>
</Card>
</Link>
))}
</div>
<div className="mt-2 flex w-[100%] cursor-pointer justify-end">
<Pagination>
<PaginationContent className="font-thin">
<PaginationItem>
<PaginationPrevious
onClick={handlePreviousPage}
className={currentPage === 1 ? 'hidden' : ''}
/>
</PaginationItem>
<PaginationItem>
<PaginationNext
onClick={handleNextPage}
className={currentPage === maxPage ? 'hidden' : ''}
/>
</PaginationItem>
</PaginationContent>
</Pagination>
</div>
</div>
)
}
export const Card = ({
className,
children,
}: {
className?: string
children: React.ReactNode
}) => {
return (
<div
style={{ zIndex: 5 }}
className={cn(
'relative h-full w-full overflow-hidden rounded-2xl border border-slate-200 bg-white p-4 group-hover:border-slate-700 dark:border-white/[0.2]',
className,
)}
>
<div className="relative ">
<div className="p-4">{children}</div>
</div>
</div>
)
}
export const CardTitle = ({
className,
children,
}: {
className?: string
children: React.ReactNode
}) => {
return (
<h4 className={cn('mt-4 font-bold tracking-wide text-zinc-700', className)}>
{children}
</h4>
)
}
export const CardDescription = ({
className,
children,
}: {
className?: string
children: React.ReactNode
}) => {
return (
<p
className={cn(
'text-sm leading-relaxed tracking-wide text-zinc-600',
className,
)}
>
{children}
</p>
)
}
Loading

0 comments on commit 4801c53

Please sign in to comment.