Skip to content

Commit

Permalink
just checkpointing speakers
Browse files Browse the repository at this point in the history
  • Loading branch information
lassejaco committed Oct 23, 2024
1 parent e08484a commit c749ad8
Show file tree
Hide file tree
Showing 10 changed files with 283 additions and 29 deletions.
3 changes: 3 additions & 0 deletions devcon-app/src/assets/icons/filter-tract.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions devcon-app/src/assets/icons/heart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions devcon-app/src/assets/icons/magnifier.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions devcon-app/src/components/domain/app/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ const Navigation = () => {
className="flex md:hidden absolute left-0 bottom-0 w-full bottom-glass"
style={{ height: 'calc(72px + max(16px, env(safe-area-inset-bottom)))' }}
></div>
<div className="sticky top-[80px] flex gap-4 flex-row xl:flex-col items-center xl:-translate-x-[50%] xl:w-[60px] pointer-events-auto">
<div className="sticky top-[80px] flex gap-4 flex-row xl:flex-col items-center xl:-translate-x-[calc(50%)] xl:w-[60px] pointer-events-auto mr-16">
<div className="flex xl:flex-col gap-4 rounded-full h-[50px] xl:h-auto xl:w-[60px] justify-center items-center xl:py-2 px-2 glass-buttons border border-solid border-[#E1E4EA] border-opacity-50 shadow">
{navItems(!!accountContext.account).map((item, index) => {
const isActive = pathname === item.href
Expand Down Expand Up @@ -410,10 +410,10 @@ export const AppLayout = (
/> */}

<div className="section pt-5 relative z-10 page-background">
<div className="flex flex-col xl:flex-row gap-0 relative">
<div className="flex flex-col xl:flex-row gap-0 relative max-w-full">
<div
data-type="page-content"
className="xl:order-2 grow relative px-4 shrink-0"
className="xl:order-2 grow relative shrink-0 max-w-full"
style={{ paddingBottom: 'calc(80px + max(24px, env(safe-area-inset-bottom)))' }}
>
{props.children}
Expand Down
186 changes: 186 additions & 0 deletions devcon-app/src/components/domain/app/dc7/speakers/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import React, { useState } from 'react'
import cn from 'classnames'
import { Separator } from 'lib/components/ui/separator'
import { Speaker as SpeakerType } from 'types/Speaker'
import FilterIcon from 'assets/icons/filter-tract.svg'
import HeartIcon from 'assets/icons/heart.svg'
import MagnifierIcon from 'assets/icons/magnifier.svg'
import SwipeToScroll from 'lib/components/event-schedule/swipe-to-scroll'
import Image from 'next/image'
import css from './speakers.module.scss'
import { StandalonePrompt } from 'lib/components/ai/standalone-prompt'
import { useRecoilState } from 'recoil'
import { devaBotVisibleAtom } from 'pages/_app'

const cardClass = 'flex flex-col border border-solid border-[#E4E6EB] rounded-3xl overflow-hidden'

const useSpeakerFilter = (speakers: SpeakerType[] | null) => {
const [text, setText] = useState('')
const [type, setType] = useState('All')

if (!speakers) return { filteredSpeakers: [], filters: { text, setText, type, setType } }

return {
filteredSpeakers: speakers.filter(speaker => speaker.name.includes(text)),
filters: {
text,
setText,
type,
setType,
},
}
}

export const SpeakerFilter = ({
filters,
}: {
filters: { text: string; setText: (text: string) => void; type: string; setType: (type: string) => void }
}) => {
return (
<div data-type="speaker-filter" className="flex flex-col gap-3 p-4">
<div className="flex flex-row gap-3 justify-between w-full">
<div data-type="speaker-filter-search" className="relative">
<input
type="text"
value={filters.text}
onChange={e => filters.setText(e.target.value)}
placeholder="Find a speaker"
className="w-full py-2 px-4 pl-10 bg-white rounded-full border text-sm border-solid border-[#E1E4EA] focus:outline-none"
/>

<MagnifierIcon
className="absolute left-3 top-1/2 transform -translate-y-1/2 text-[#99A0AE] icon"
style={{ '--color-icon': '#99A0AE' }}
/>
</div>

<div data-type="speaker-filter-actions" className="flex flex-row gap-3 items-center text-xl pr-2">
<FilterIcon
className="icon cursor-pointer hover:scale-110 transition-transform duration-300"
style={{ '--color-icon': '#99A0AE' }}
/>
<HeartIcon
className="icon cursor-pointer hover:scale-110 transition-transform duration-300"
style={{ '--color-icon': '#99A0AE' }}
/>
</div>
</div>

<div className="flex flex-row gap-3 items-center text-xs border-top border-bottom py-4">
<SwipeToScroll>
<div className="flex flex-row gap-3 flex-nowrap">
<div
className={cn(
'flex shrink-0 items-center justify-center align-middle rounded-full border border-solid bg-white hover:bg-[#EFEBFF] border-transparent shadow px-4 py-1 cursor-pointer select-none transition-all duration-300',
filters.type === 'All' ? ' border-[#ac9fdf] !bg-[#EFEBFF]' : ''
)}
onClick={() => filters.setType('All')}
>
All
</div>
<Separator orientation="vertical" className="h-6" />

{['Keynote', 'Talk', 'Workshop', 'Panel', 'Lightning', 'CLS'].map(type => (
<div
key={type}
className={cn(
'flex shrink-0 items-center justify-center align-middle rounded-full border bg-white hover:bg-[#EFEBFF] border-solid border-transparent shadow px-4 py-1 cursor-pointer select-none transition-all duration-300',
filters.type === type ? ' border-[#ac9fdf] !bg-[#EFEBFF]' : ''
)}
onClick={() => filters.setType(type)}
>
{type}
</div>
))}
</div>
</SwipeToScroll>
</div>
</div>
)
}

export const SpeakerList = ({ speakers }: { speakers: SpeakerType[] | null }) => {
const { filteredSpeakers, filters } = useSpeakerFilter(speakers)
const [_, setDevaBotVisible] = useRecoilState(devaBotVisibleAtom)

console.log(speakers?.slice(0, 10))

return (
<div data-type="speaker-list" className={cn(cardClass)}>
<SpeakerFilter filters={filters} />

<div className="flex flex-col gap-3 pb-4 px-4 font-semibold">Featured Speakers</div>

<SwipeToScroll>
<div className="flex flex-row gap-3">
{filteredSpeakers.slice(0, 10).map((speaker, index) => (
<div
key={speaker.id}
className={cn(
'flex flex-col items-center justify-center gap-2 rounded-xl bg-white border border-solid border-[#E1E4EA] p-2 shrink-0',
index === 0 ? 'ml-4' : ''
)}
>
<div className="relative rounded-full w-[80px] h-[80px]">
<Image
// @ts-ignore
src={speaker.avatar}
alt={speaker.name}
width={80}
height={80}
className="rounded-full w-full h-full mb-2 object-cover"
/>
<div className={cn('absolute inset-0 rounded-full', css['speaker-gradient'])} />
</div>
<p className="text-xs font-medium">{speaker.name}</p>
</div>
))}
</div>
</SwipeToScroll>

<div data-type="speaker-prompts" className="flex gap-3 m-4 border-bottom mx-4 pb-4">
<StandalonePrompt
className="w-full"
onClick={() => setDevaBotVisible('Help me decide which keynotes to attend speaking about')}
>
<div className="truncate">Help me decide which keynotes to attend speaking about</div>
</StandalonePrompt>
<StandalonePrompt
className="w-full"
onClick={() => setDevaBotVisible('Help me find a speaker that is similar to')}
>
<div className="truncate">Help me find a speaker that is similar to</div>
</StandalonePrompt>
</div>

<div className="flex flex-col gap-3 p-4">All Speakers</div>

{filteredSpeakers.map(speaker => (
<div key={speaker.id}>{speaker.name}</div>
))}
</div>
)
}

export const SpeakerView = ({ speakers }: { speakers: SpeakerType[] | null }) => {
return (
<div data-type="speaker-view" className={cardClass}>
Speaker View
</div>
)
}

export const SpeakerLayout = ({ speakers }: { speakers: SpeakerType[] | null }) => {
if (!speakers) return null

return (
<div data-type="speaker-layout" className="flex flex-row gap-3 w-full max-w-full relative overflow-hidden">
<div className="basis-[60%] grow">
<SpeakerList speakers={speakers} />
</div>
<div className="basis-[40%] bg-yellow-500 min-w-[393px]">
<SpeakerView speakers={speakers} />
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.speaker-gradient {
mask-image: linear-gradient(to bottom, transparent 60%, black 100%);
background: #765ae4;

&:before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #765ae4;
}
}
5 changes: 3 additions & 2 deletions devcon-app/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { NotificationCard } from 'components/domain/app/dc7/profile/notification
import { useAccountContext } from 'context/account-context'

// Short on time so just doing global state here.. extract later
export const devaBotVisibleAtom = atom({
export const devaBotVisibleAtom = atom<boolean | string>({
key: 'devaBotVisible',
default: false,
})
Expand Down Expand Up @@ -199,7 +199,8 @@ function App({ Component, pageProps }: AppProps) {
<DevaBot
sessions={sessions}
onToggle={() => setDevaBotVisible(!devaBotVisible)}
toggled={devaBotVisible}
defaultPrompt={typeof devaBotVisible === 'string' ? devaBotVisible : undefined}
toggled={!!devaBotVisible}
notifications={accountContext.account ? notifications : undefined}
notificationsCount={notificationsCount}
markNotificationsAsRead={markAllAsRead}
Expand Down
48 changes: 28 additions & 20 deletions devcon-app/src/pages/speakers.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,40 @@
import { AppLayout } from 'components/domain/app/Layout'
import { Speakers } from 'components/domain/app/speakers'
// import { Speakers } from 'components/domain/app/speakers'
import { pageHOC } from 'context/pageHOC'
import React from 'react'
import { useRouter } from 'next/router'
import { Speaker as SpeakerType } from 'types/Speaker'
import {
fetchSessions,
fetchRooms,
fetchTracks,
fetchEvent,
fetchExpertiseLevels,
fetchSessionTypes,
// fetchSessions,
// fetchRooms,
// fetchTracks,
// fetchEvent,
// fetchExpertiseLevels,
// fetchSessionTypes,
useSpeakerData,
} from 'services/event-data'
import { DEFAULT_APP_PAGE } from 'utils/constants'
import { SpeakerDetails } from 'components/domain/app/speakers'
import { SEO } from 'components/domain/seo'
import { useSpeakersWithSessions } from 'services/event-data'
// import { useSpeakersWithSessions } from 'services/event-data'
import { FancyLoader } from 'lib/components/loader/loader'
import { SpeakerLayout, SpeakerList, SpeakerView } from 'components/domain/app/dc7/speakers/index'
import AppIcon from 'assets/icons/speakers.svg'

export default pageHOC((props: any) => {
const speakers = useSpeakersWithSessions()
const { query } = useRouter()
const speakers = useSpeakerData()
// const { query } = useRouter()

return (
<AppLayout pageTitle="Speakers" breadcrumbs={[{ label: 'Speakers' }]}>
<AppLayout pageTitle="Speakers" breadcrumbs={[{ label: 'icon', icon: AppIcon }, { label: 'Overview' }]}>
<SEO title="Speakers" />

{speakers &&
<SpeakerLayout speakers={speakers} />
{/* <SpeakerList {...props} speakers={speakers} />
<SpeakerView {...props} speakers={speakers} />
</SpeakerLayout> */}

{/* {speakers &&
(() => {
const speakerID = query.speaker
const speaker = speakers.find((speaker: SpeakerType) => speaker.id === speakerID)
Expand All @@ -43,9 +51,9 @@ export default pageHOC((props: any) => {
<Speakers {...props} speakers={speakers} />
</>
)
})()}
})()} */}

<div className="fixed top-0 h-full w-full flex justify-center items-center opacity-100 z-5 pointer-events-none">
<div className="fixed inset-0 h-full w-full flex justify-center items-center z-5 pointer-events-none">
<FancyLoader loading={!speakers} />
</div>
</AppLayout>
Expand Down Expand Up @@ -79,13 +87,13 @@ export async function getStaticProps(context: any) {
props: {
// ...(await getGlobalData(context.locale, true)),
// sessions,
page: DEFAULT_APP_PAGE,
// page: DEFAULT_APP_PAGE,
// speakers: speakersWithSessions,
tracks: await fetchTracks(),
// eventDays: await fetchEventDays(),
rooms: await fetchRooms(),
expertiseLevels: await fetchExpertiseLevels(),
sessionTypes: await fetchSessionTypes(),
// tracks: await fetchTracks(),
// // eventDays: await fetchEventDays(),
// rooms: await fetchRooms(),
// expertiseLevels: await fetchExpertiseLevels(),
// sessionTypes: await fetchSessionTypes(),
},
}
}
Loading

0 comments on commit c749ad8

Please sign in to comment.