Skip to content

Commit

Permalink
fix: improve CTA (#997)
Browse files Browse the repository at this point in the history
* fix: improve CTA
* feat: add loading skeleton to recent edits
* fix: correct LCO action strs
  • Loading branch information
vnugent authored Oct 28, 2023
1 parent 92ed3fe commit 8e52db4
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 37 deletions.
24 changes: 17 additions & 7 deletions src/app/components/LandingCTA.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import clx from 'classnames'

import { LoginButtonClient } from './LoginButton'
import { ShowEmailJS } from './ShowEmailJS'
import { ReactNode } from 'react'

export const LandingCTA: React.FC = () => {
return (
<div className='w-full'>
<div className='w-full bg-gradient-to-r from-neutral/80 to-neutral/90 rounded-box p-4 md:p-10'>
<div className='flex flex-rows flex-wrap gap-6 justify-center'>
<Card4All />
<Card4Coders />
Expand All @@ -20,7 +20,12 @@ const Card4Coders: React.FC = () => {
return (
<Card
title='Coders'
body='Fix a bug. Use OpenBeta API & data in your projects.'
body={
<ul>
<li>☑️ Fix a bug.</li>
<li>☑️ Use OpenBeta API & data in your projects.</li>
</ul>
}
action={
<>
<a href='https://docs.openbeta.io/how-to-contribute/overview' className='text-sm underline'>Dev onboarding</a>
Expand All @@ -35,7 +40,12 @@ const Card4All: React.FC = () => {
return (
<Card
title='Climbers'
body='Add missing climbs. Help us make your local climbing&lsquo;s area page even better!'
body={
<ul>
<li>☑️ Add missing climbs.</li>
<li>☑️ Help us make your local climbing&#39;s area page even better!</li>
</ul>
}
action={<LoginButtonClient className='btn btn-primary btn-sm px-4 btn-outline' label='Login' />}
/>
)
Expand Down Expand Up @@ -63,18 +73,18 @@ const Donate: React.FC = () => {

interface CTACardProps {
title: string
body: string
body: string | ReactNode
action: React.ReactNode
className?: string
}

const Card: React.FC<CTACardProps> = ({ title, body, action, className }) => {
return (
<div className='px-4'>
<h2 className='font-medium text-base-content/60 uppercase'>{title}</h2>
<h2 className='px-4 font-medium text-base-200 uppercase'>{title}</h2>
<div className={clx('px-4 card card-bordered max-w-sm bg-base-100 shadow-lg', className)}>
<div className='card-body'>
<p>{body}</p>
<div>{body}</div>
<div className='card-actions justify-end items-center gap-x-4 py-2'>
{action}
</div>
Expand Down
11 changes: 3 additions & 8 deletions src/app/components/LandingHero.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import Heart from '@/assets/icons/heart-hero'

export const LandingHero: React.FC = () => {
return (
<section className='w-full rounded-box p-10 flex justify-center'>
<div className='flex flex-wrap justify-center items-center gap-10'>
<span className='text-4xl md:text-6xl tracking-tight'>Knowledge</span>
<span className='align-text-bottom font-semibold text-2xl'>+</span>
<span className='-translate-y-1 -rotate-6 font-bold text-4xl md:text-6xl tracking-tight hero-text-shadow'>You</span> <span className='font-semibold text-2xl'>=</span> <Heart className='h-16 w-16' />
</div>
<section className='w-full rounded-box pt-12 pb-24 px-16 text-center'>
<h1 className='text-2xl md:text-5xl tracking-tighter font-semibold'>Share your climbing route knowledge!</h1>
<p className=''>Join OpenBeta and help build a community resource for climbers</p>
</section>
)
}
35 changes: 32 additions & 3 deletions src/app/components/RecentEdits.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import Link from 'next/link'
import { ArrowRightIcon } from '@heroicons/react/24/outline'

import { getChangeHistoryServerSide } from '@/js/graphql/contribAPI'
import { ChangesetRow } from '@/components/edit/RecentChangeHistory'
import Link from 'next/link'
import { ChangesetCard } from '@/components/edit/RecentChangeHistory'

/**
* Cache time in seconds
*/
export const revalidate = 300

/**
* Show most recent edits
*/
export const RecentEdits: React.FC = async () => {
const history = await getChangeHistoryServerSide()
return (
Expand All @@ -15,11 +23,32 @@ export const RecentEdits: React.FC = async () => {
<hr className='mb-6 border-2 border-base-content' />
<div className='mt-4 flex justify-center flex-row flex-wrap gap-y-10 gap-x-4'>
{history.splice(0, 10).map(changetset =>
<ChangesetRow key={changetset.id} changeset={changetset} />)}
<ChangesetCard key={changetset.id} changeset={changetset} />
)}

</div>
<div className='flex justify-center py-10'>
<Link href='/edit' className='btn btn-sm btn-outline'>See more <ArrowRightIcon className='w-4 h-4' /></Link>
</div>
</section>
)
}

/**
* Loading skelton.
* Todo: somehow reuse the structure and css from the real component
*/
export const RecentEditsSkeleton: React.FC = () => {
return (
<section className='px-4 w-full'>
<div className='flex items-center justify-between'>
<h2>Recent edits</h2>
<Link href='/edit' className='text-sm hover:underline'>See more</Link>
</div>
<hr className='mb-6 border-2 border-base-content' />
<div className='mt-4 flex justify-center flex-row flex-wrap gap-y-10 gap-x-4'>
{[1, 2, 3, 4, 5].map(item => <div key={item} className='animate-pulse w-full bg-base-200/30 h-36 rounded-box' />)}
</div>
</section>
)
}
9 changes: 7 additions & 2 deletions src/app/components/RecentTags.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { RecentImageCard } from '@/components/home/RecentMediaCard'
import { getMediaForFeed } from '@/js/graphql/api'

/**
* Cache time in seconds
*/
export const revalidate = 300

/**
* Horizontal gallery of recent images with tags
*/
Expand All @@ -19,12 +24,12 @@ export const RecentTags: React.FC = async () => {
})

return (
<section className='w-full'>
<section className='w-full '>
<div className='px-4 2xl:px-0 mx-auto max-w-5xl xl:max-w-7xl'>
<h2>Recent Tags</h2>
</div>

<div className='overflow-hidden'>
<div className='overflow-hidden bg-base-200/20'>
<hr className='border-2 border-base-content' />
<div className='py-8 grid grid-flow-col auto-cols-max gap-x-4 overflow-x-auto'>
{
Expand Down
3 changes: 2 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ export const metadata: Metadata = {
openGraph: {
description: 'OpenBeta is a free climbing platform. Join the community and share your knowledge today.',
images: '/south-africa-og.jpeg'
}
},
metadataBase: new URL(`https://${process.env.VERCEL_URL ?? 'http://localhost:3000'}`)
}

export default function RootLayout ({
Expand Down
12 changes: 9 additions & 3 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { Suspense } from 'react'
import { LandingCTA } from './components/LandingCTA'
import { LandingHero } from './components/LandingHero'
import { RecentEdits } from './components/RecentEdits'
import { RecentEdits, RecentEditsSkeleton } from './components/RecentEdits'
import { RecentTags } from './components/RecentTags'
import { USAToC } from './components/USAToC'

/**
* Root home page
*/
export default async function Home (): Promise<any> {
return (
<div className='mt-8 w-full flex flex-col gap-y-24'>
<div className='lg:pl-4 lg:grid lg:grid-cols-3'>
<div className='col-span-2 pb-10 bg-gradient-to-r from-cyan-500/40 to-blue-500/60 rounded-box'>
<div className='col-span-2 pb-10 rounded-box'>
<LandingHero />
<LandingCTA />
<p className='mt-12 px-10 text-center text-sm'>Our website is undergoing a facelift. Visit the <a href='/classic' className='underline'>old home</a>. <br /><span className='text-base-content/60'>Questions or comments? <a href='mailto:[email protected]'>[email protected]</a></span></p>
</div>
<div className='mt-8 lg:mt-0 lg:overflow-y-auto lg:h-[800px] w-full'>
<RecentEdits />
<Suspense fallback={<RecentEditsSkeleton />}>
<RecentEdits />
</Suspense>
</div>
</div>
<RecentTags />
Expand Down
27 changes: 15 additions & 12 deletions src/components/edit/RecentChangeHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ import { ChangesetType, ChangeType, AreaType, ClimbType, OrganizationType, Docum
export interface RecentChangeHistoryProps {
history: ChangesetType[]
}

/**
* Show all changes
*/
export default function RecentChangeHistory ({ history }: RecentChangeHistoryProps): JSX.Element {
return (
<div className='mt-4 flex flex-col gap-y-10 w-full'>
{history.map(changetset => <ChangesetRow key={changetset.id} changeset={changetset} />)}
{history.map(changetset => <ChangesetCard key={changetset.id} changeset={changetset} />)}
</div>
)
}
Expand All @@ -21,7 +25,10 @@ interface ChangsetRowProps {
changeset: ChangesetType
}

export const ChangesetRow = ({ changeset }: ChangsetRowProps): JSX.Element => {
/**
* A card showing individual changeset
*/
export const ChangesetCard: React.FC<ChangsetRowProps> = ({ changeset }) => {
const { createdAt, editedByUser, operation, changes } = changeset

// @ts-expect-error
Expand Down Expand Up @@ -186,13 +193,6 @@ const ActionIcon = ({ icon, clz }: ActionIconProps): JSX.Element => (
<div className={`bg-opacity-60 rounded-full border border-base-300 p-2 ${clz ?? ''}`}>{icon}</div>
)

interface OpBadgeProps {
label: string
clz?: string
}

const OpBadge = ({ label, clz = 'badge-outline' }: OpBadgeProps): JSX.Element => <span className={`badge ${clz}`}>{label}</span>

const operationLabelMap = {
addArea: {
borderCue: 'border-l-green-500',
Expand Down Expand Up @@ -235,15 +235,18 @@ const operationLabelMap = {
icon: <ActionIcon icon={<PencilIcon className='w-6 h-6 stroke-base-300' />} />
},
addOrganization: {
badge: <OpBadge label='Add Organization' clz='badge-warning' />,
badge: 'added an organization',
borderCue: 'border-l-green-500',
icon: <ActionIcon icon={<PlusIcon className='w-6 h-6 stroke-base-300 stroke-2' />} clz='bg-success' />
},
updateOrganization: {
badge: <OpBadge label='Update Organization' clz='badge-warning' />,
badge: 'updated an organization',
borderCue: 'border-l-black',
icon: <ActionIcon icon={<PencilIcon className='w-6 h-6 stroke-base-300' />} />
},
deleteOrganization: {
badge: <OpBadge label='Delete Organization' clz='badge-warning' />,
badge: 'deleted an organization',
borderCue: 'border-l-pink-500',
icon: <ActionIcon icon={<MinusIcon className='w-6 h-6 stroke-base-300' />} clz='bg-error' />
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default function Card ({
bordered = false
}: CardProps): JSX.Element {
return (
<div className={clx('card card-compact', bordered ? 'border shadow-lg' : '')}>
<div className={clx('card card-compact bg-base-100', bordered ? 'border shadow-lg' : '')}>
<div className={clx('flex items-center justify-between', bordered ? 'mx-2' : '')}>{header}</div>
<figure className='overflow-hidden rounded sm:rounded-none sm:rounded-box'>
{image}
Expand Down

1 comment on commit 8e52db4

@vercel
Copy link

@vercel vercel bot commented on 8e52db4 Oct 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.