Skip to content

Commit

Permalink
Merge Staging to Main (#233)
Browse files Browse the repository at this point in the history
- accessibility
- loading states for improved streaming performance
- static pages for deal pages
  • Loading branch information
jamesqquick authored Jul 25, 2024
1 parent f5c5da0 commit 8cc3e7f
Show file tree
Hide file tree
Showing 23 changed files with 166 additions and 80 deletions.
6 changes: 6 additions & 0 deletions src/app/deals/[id]/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import LoadingPreview from '@/components/deals/loading/LoadingPreview'
import React from 'react'

export default function Loading() {
return <LoadingPreview />
}
31 changes: 19 additions & 12 deletions src/app/deals/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import { notFound } from 'next/navigation'
import { getDealById } from '@/lib/queries'
import DealPreview from '@/components/DealPreview'
import { Metadata, ResolvingMetadata } from 'next'
import { getApprovedDeals, getDealById } from '@/lib/queries'
import { Metadata } from 'next'
import DealPreview from '@/components/deals/DealPreview'

export const revalidate = 120

type Props = {
params: { id: string }
searchParams: { [key: string]: string | string[] | undefined }
}

export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
// read route params
const id = params.id
export const dynamicParams = true

// fetch data
export async function generateStaticParams() {
const deals = await getApprovedDeals()

return deals.map((deal) => ({
id: deal.xata_id,
}))
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
const deal = await getDealById(params.id)

if (!deal) {
Expand All @@ -35,10 +37,15 @@ export async function generateMetadata(
}
}

//sleep function
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
export default async function DealPage({ params }: { params: { id: string } }) {
if (!params.id) {
//not found
notFound()
}

const deal = await getDealById(params.id)
if (!deal) {
notFound()
Expand Down
13 changes: 6 additions & 7 deletions src/app/deals/category/[category]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { Category } from '@/types/Types'
import { getApprovedDealsByCategory } from '@/lib/queries'
import PageHeader from '@/components/PageHeader'
import DealsList from '@/components/deals/DealsList'
import ApprovedDealsByCategory from '@/components/deals/ApprovedDealsByCategory'
import { Suspense } from 'react'
import LoadingDealsList from '@/components/deals/loading/LoadingDealsList'

export const revalidate = 120

Expand All @@ -23,7 +26,6 @@ export default async function CategoryPage({
}
//TODO move logic for converting deals to capitalized and singular to a helper function
const category = categoryString as Category
const deals = await getApprovedDealsByCategory(category)
let capitalizedCategory = category
.split(' ')
.map((word) => word.charAt(0).toUpperCase() + word.toLowerCase().slice(1))
Expand All @@ -39,12 +41,9 @@ export default async function CategoryPage({
<div className="pb-10">
<CategoryOptions />
</div>
{deals.length === 0 && (
<div className="text-center text-xl text-gray-300">
No deals found for this category
</div>
)}
<DealsList deals={deals} />
<Suspense fallback={<LoadingDealsList count={3} />}>
<ApprovedDealsByCategory category={category} />
</Suspense>
</main>
)
}
15 changes: 6 additions & 9 deletions src/app/deals/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import CategoryOptions from '@/components/CategoryOptions'
import { getApprovedDeals } from '@/lib/queries'
import NeverMissADeal from '@/components/NeverMissADeal'
import PageHeader from '@/components/PageHeader'
import DealsList from '@/components/deals/DealsList'
import ApprovedDeals from '@/components/deals/ApprovedDeals'
import LoadingDealsList from '@/components/deals/loading/LoadingDealsList'
import { Suspense } from 'react'

export const revalidate = 120

export default async function DealsPage() {
const deals = await getApprovedDeals(20)
//TODO: handle error
return (
<main>
Expand All @@ -17,12 +17,9 @@ export default async function DealsPage() {
<div className="pb-10">
<CategoryOptions />
</div>
{deals.length === 0 && (
<div className="text-center text-xl text-gray-300">
No deals found for this category
</div>
)}
<DealsList deals={deals} />
<Suspense fallback={<LoadingDealsList count={3} />}>
<ApprovedDeals />
</Suspense>
<NeverMissADeal />
</main>
)
Expand Down
7 changes: 2 additions & 5 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import FeaturedDealsSection from '@/components/deals/FeaturedDealsSection'
import DevGiveaways from '@/components/DevGiveaways'
import FeaturedDeals from '@/components/FeaturedDeals'
import Hero from '@/components/Hero'
import NeverMissADeal from '@/components/NeverMissADeal'
import Separator from '@/components/Separator'
import { getApprovedFeaturedDeals } from '@/lib/queries'

export const revalidate = 120

export default async function Home() {
const deals = await getApprovedFeaturedDeals()
return (
<main>
<Hero />

<FeaturedDeals deals={deals} />
<FeaturedDealsSection />
<Separator className="mb-20" />
<div className="mb-20">
<NeverMissADeal />
Expand Down
19 changes: 19 additions & 0 deletions src/components/IconButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react'

export default function IconButton({
handleClick,
children,
}: {
handleClick: () => void
children: React.ReactNode
}) {
return (
<button
type="button"
className="text-brand bg-surface-1 hover:bg-surface-2 flex h-10 w-10 items-center justify-center rounded-full text-xs transition-transform hover:-translate-y-0.5"
onClick={handleClick}
>
{children}
</button>
)
}
37 changes: 22 additions & 15 deletions src/components/Overlay.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { ReactNode } from 'react'
import { ReactNode, useEffect, useRef } from 'react'
import { FaTimes } from 'react-icons/fa'

const Overlay = ({
Expand All @@ -12,22 +12,29 @@ const Overlay = ({
onClose: () => void
children: ReactNode
}) => {
const dialogRef = useRef<HTMLDialogElement>(null)

useEffect(() => {
if (isOpen) {
dialogRef.current?.showModal()
} else {
dialogRef.current?.close()
}
})
return (
<div
className={`fixed inset-0 flex items-center justify-center p-10 ${
isOpen ? 'block' : 'hidden'
} z-50 bg-gray-950/[.80] `}
<dialog
ref={dialogRef}
className="hide-scrollbar fixed inset-0 h-[90vh] w-full max-w-4xl rounded-xl bg-gray-900 px-4 pt-16 shadow-lg backdrop:bg-gray-950/[.80] md:px-8 md:pt-16"
>
<div className="hide-scrollbar relative h-[90vh] w-full max-w-4xl overflow-y-scroll rounded-xl bg-gray-900 px-4 pt-16 shadow-lg md:px-8 md:pt-16">
<button
onClick={onClose}
className="fixed right-3 top-3 text-gray-400 transition-colors hover:text-white focus:outline-none"
>
<FaTimes className="h-10" />
</button>
{children}
</div>
</div>
<button
onClick={onClose}
className="fixed right-3 top-3 text-gray-400 transition-colors hover:text-white"
aria-label="Close"
>
<FaTimes className="h-10" />
</button>
{children}
</dialog>
)
}

Expand Down
9 changes: 9 additions & 0 deletions src/components/deals/ApprovedDeals.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { getApprovedDeals } from '@/lib/queries'
import React from 'react'
import DealsList from './DealsList'

export default async function ApprovedDeals() {
const deals = await getApprovedDeals(20)

return <DealsList deals={deals} />
}
14 changes: 14 additions & 0 deletions src/components/deals/ApprovedDealsByCategory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { getApprovedDealsByCategory } from '@/lib/queries'
import React from 'react'
import DealsList from './DealsList'
import { Category } from '@/types/Types'

export default async function ApprovedDealsByCategory({
category,
}: {
category: Category
}) {
const deals = await getApprovedDealsByCategory(category)

return <DealsList deals={deals} />
}
11 changes: 1 addition & 10 deletions src/components/deals/DealCard.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import Link from 'next/link'
import { FaBeer, FaVideo, FaBook, FaCog, FaCalendar } from 'react-icons/fa'
import { Category } from '@/types/Types'
import { Deal } from '@prisma/client'
import DealImage from './DealImage'

const categoryToIcon: { [key: string]: JSX.Element } = {
Misc: <FaBeer />,
Ebook: <FaBook />,
Video: <FaVideo />,
Tool: <FaCog />,
Conference: <FaCalendar />,
}

export default function DealCard({ deal }: { deal: Deal }) {
return (
<Link
Expand All @@ -24,7 +15,7 @@ export default function DealCard({ deal }: { deal: Deal }) {
coverImageURL={deal.coverImageURL}
category={deal.category as Category}
/>
<h2 className="text-lg font-semibold tracking-tight">{deal.name}</h2>
<h2 className="mt-1 text-lg font-semibold tracking-tight">{deal.name}</h2>
{deal.coupon && deal.couponPercent && (
<p className="-gap-y-1 absolute right-3 top-3 flex h-14 w-14 -rotate-12 flex-col items-center justify-center rounded-full bg-pale-gold text-black shadow-md">
<span className="text-md -mb-1 font-bold">{deal.couponPercent}%</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import { Category } from '@/types/Types'
import React from 'react'
import {
FaBeer,
FaBook,
FaCalendar,
FaChair,
FaCog,
FaCompactDisc,
FaDeskpro,
FaDesktop,
FaMicrophone,
FaSchool,
FaTable,
FaTag,
FaVideo,
} from 'react-icons/fa'
import { twMerge } from 'tailwind-merge'

Expand Down
2 changes: 1 addition & 1 deletion src/components/deals/DealImage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Category } from '@/types/Types'
import { Deal } from '@prisma/client'
import React from 'react'
import DealGradientPlaceholder from '../DealGradientPlaceholder'
import DealGradientPlaceholder from './DealGradientPlaceholder'
import Image from 'next/image'

interface IDealImageProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { format } from 'date-fns'
import React from 'react'
import DealGradientPlaceholder from './DealGradientPlaceholder'
import { Category } from '@/types/Types'
import Image from 'next/image'
import ClickableCoupon from './ClickableCouponCode'
import DealImage from './deals/DealImage'
import DealImage from './DealImage'
import ClickableCoupon from '../ClickableCouponCode'

export default function DealPreview({
link,
Expand Down Expand Up @@ -35,8 +32,8 @@ export default function DealPreview({
category={category as Category}
/>
</div>
<div className="flex flex-col gap-y-1">
<span className="text-xl md:text-3xl">{name}</span>
<div className="flex flex-col gap-y-1">
<h1 className="text-xl md:text-3xl">{name}</h1>
<div className="mt-2 flex flex-wrap gap-2 text-sm md:mt-4 md:text-lg">
<span className="font-light text-white/70">Website:</span>
<a
Expand Down
3 changes: 3 additions & 0 deletions src/components/deals/DealsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ export default function DealsList({
}) {
return (
<div className="mx-auto py-10">
{deals.length === 0 && (
<div className="text-center text-xl text-gray-300">No deals found</div>
)}
{deals.length > 0 && (
<div className="mx-auto grid grid-cols-1 justify-items-center gap-x-4 gap-y-12 sm:grid-cols-2 lg:gap-x-12 xl:grid-cols-3">
<>
Expand Down
7 changes: 7 additions & 0 deletions src/components/deals/FeaturedDeals.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import DealsList from './DealsList'
import { getApprovedFeaturedDeals } from '@/lib/queries'

export default async function FeaturedDeals() {
const deals = await getApprovedFeaturedDeals()
return <DealsList deals={deals} />
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react'
import DealsList from './deals/DealsList'
import Link from 'next/link'
import { Deal } from '@prisma/client'
import FeaturedDeals from './FeaturedDeals'
import { Suspense } from 'react'
import LoadingDealsList from './loading/LoadingDealsList'

export default function FeaturedDeals({ deals }: { deals: Deal[] }) {
export default function FeaturedDealsSection() {
return (
<section className="py-20">
<div className="flex flex-col items-center gap-x-8 gap-y-4 pb-10 md:flex-row">
Expand All @@ -18,7 +18,9 @@ export default function FeaturedDeals({ deals }: { deals: Deal[] }) {
View all deals
</Link>
</div>
<DealsList deals={deals} />
<Suspense fallback={<LoadingDealsList count={3} />}>
<FeaturedDeals />
</Suspense>
</section>
)
}
5 changes: 5 additions & 0 deletions src/components/deals/loading/LoadingDealImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default function LoadingDealImage() {
return (
<div className=" flex aspect-video w-full animate-pulse items-center justify-center rounded-xl border-4 border-slate-500 bg-gray-100"></div>
)
}
20 changes: 20 additions & 0 deletions src/components/deals/loading/LoadingDealsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import LoadingDealImage from './LoadingDealImage'

export default function LoadingDealsList({ count }: { count: number }) {
const arr = Array.from(Array(count).keys())

return (
<div className="mx-auto py-10">
<div className="mx-auto grid grid-cols-1 justify-items-center gap-x-4 gap-y-12 sm:grid-cols-2 lg:gap-x-12 xl:grid-cols-3">
<>
{arr.map((num) => (
<div key={num} className="w-full">
<LoadingDealImage />
<div className="mt-1 h-[1.75rem]"></div>
</div>
))}
</>
</div>
</div>
)
}
Loading

0 comments on commit 8cc3e7f

Please sign in to comment.