Skip to content

Commit

Permalink
update(tt): experiment with book modes
Browse files Browse the repository at this point in the history
  • Loading branch information
vojtaholik committed Mar 12, 2024
1 parent ef105a0 commit 5c15ac9
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 7 deletions.
52 changes: 49 additions & 3 deletions apps/total-typescript/src/app/book/[chapter]/[resource]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import Link from 'next/link'
import {notFound} from 'next/navigation'
import {ChapterResourceList} from '@/app/book/_components/chapter-resource-list'
import {
BookOpenIcon,
BookmarkIcon,
ChevronRightIcon,
MenuAlt1Icon,
PlayIcon,
} from '@heroicons/react/outline'
import {
Menubar,
Expand All @@ -33,6 +35,9 @@ import {
TooltipProvider,
TooltipTrigger,
} from '@skillrecordings/ui/primitives/tooltip'
import {cookies} from 'next/headers'
import ModeToggle from '../../_components/mode-toggle'
import {getServerAuthSession} from '@/server/auth'

export const metadata = {
name: 'Chapter',
Expand Down Expand Up @@ -60,10 +65,18 @@ const ChapterLayout: React.FC<React.PropsWithChildren<Props>> = async ({
if (!chapter) {
notFound()
}
const session = await getServerAuthSession()
const isAdmin = session?.user.role === 'ADMIN' // TODO: use proper can can check
const {mode} = getBookMode()

return (
<div className="relative">
<div className="mx-auto flex w-full max-w-4xl flex-col items-center">
<div
className={cn('mx-auto flex w-full flex-col items-center', {
'max-w-4xl': mode === 'book',
'max-w-screen-xl': mode === 'video',
})}
>
<aside className="sticky top-0 z-20 flex h-16 w-full items-center border border-t-0 bg-background leading-none lg:w-[calc(100%+160px)]">
<Menubar className="space-x-0 border-0 p-0">
<MenubarMenu>
Expand Down Expand Up @@ -106,7 +119,26 @@ const ChapterLayout: React.FC<React.PropsWithChildren<Props>> = async ({
</div>
</div>
<div className="ml-auto flex">
<TooltipProvider>
<TooltipProvider delayDuration={0}>
{isAdmin && (
<Tooltip>
<TooltipTrigger
asChild
className="flex size-16 items-center justify-center border-l"
>
<ModeToggle mode={mode}>
{mode === 'book' ? (
<PlayIcon className="w-5" />
) : (
<BookOpenIcon className="w-5" />
)}
</ModeToggle>
</TooltipTrigger>
<TooltipContent>
Switch to {mode === 'book' ? 'Video' : 'Book'} Mode
</TooltipContent>
</Tooltip>
)}
<Tooltip>
<TooltipTrigger className="flex size-16 items-center justify-center border-l">
<BookmarkIcon className="w-5" />
Expand Down Expand Up @@ -145,7 +177,12 @@ const ChapterLayout: React.FC<React.PropsWithChildren<Props>> = async ({
</TooltipProvider>
</div>
</aside>
<article className="mx-auto w-full max-w-4xl px-5 py-8 sm:py-16">
<article
className={cn('mx-auto w-full px-5', {
'max-w-4xl py-8 sm:py-16': mode === 'book',
'max-w-screen-xl': mode === 'video',
})}
>
{children}
</article>
</div>
Expand Down Expand Up @@ -178,3 +215,12 @@ const ChapterLayout: React.FC<React.PropsWithChildren<Props>> = async ({
}

export default ChapterLayout

export function getBookMode() {
const cookieStore = cookies()

const bookPrefsCookie = cookieStore.get('bookPrefs')
const prefs = bookPrefsCookie ? JSON.parse(bookPrefsCookie.value) : {}
const mode: 'video' | 'book' = prefs.mode || 'book'
return {mode}
}
24 changes: 20 additions & 4 deletions apps/total-typescript/src/app/book/[chapter]/[resource]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {notFound} from 'next/navigation'
import {type Metadata, type ResolvingMetadata} from 'next'
import {getOgImage} from '@/utils/get-og-image'
import {Challenge} from '../../_components/challenge'
import {getBookMode} from './layout'
import {cn} from '@skillrecordings/ui/utils/cn'

type Props = {
params: {chapter: string; resource: string}
Expand Down Expand Up @@ -51,22 +53,36 @@ const ChapterResourceRoute: React.FC<Props> = async ({
}

const {title, mdx, video, solution, code, slug} = resource
const {mode} = getBookMode()

return (
<section>
<h1 className="mb-10 text-balance text-3xl font-bold sm:mb-14 sm:text-4xl lg:text-5xl">
{title}
</h1>
{mode === 'book' && (
<h1 className="mb-10 text-balance text-3xl font-bold sm:mb-14 sm:text-4xl lg:text-5xl">
{title}
</h1>
)}
<div className="prose prose-light max-w-none sm:prose-lg lg:prose-xl prose-p:font-normal">
{isAdmin && video && (
<div className="mb-5 sm:float-left sm:mr-10 sm:w-1/2">
<div
className={cn('mb-5', {
'sm:float-left sm:mr-10 sm:w-1/2': mode === 'book',
})}
>
<VideoPlayer
className="rounded"
videoResourceLoader={getVideoResource(video.videoResourceId)}
title={title}
/>
</div>
)}
{mode === 'video' && (
<div className="not-prose">
<h1 className="mb-10 text-balance text-3xl font-bold sm:mb-14 sm:text-4xl lg:text-5xl">
{title}
</h1>
</div>
)}
{mdx && <MDX contents={mdx} components={bookComponents} />}
{isAdmin && chapter.github?.repo && code?.openFile && (
<Challenge repo={chapter.github?.repo} file={code.openFile} />
Expand Down
42 changes: 42 additions & 0 deletions apps/total-typescript/src/app/book/_components/mode-toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use client'

import type {ReadonlyRequestCookies} from 'next/dist/server/web/spec-extension/adapters/request-cookies'
import React from 'react'
import {useCookies} from 'react-cookie'
import {useRouter} from 'next/navigation'

const ModeToggle = React.forwardRef<
HTMLButtonElement,
React.PropsWithChildren<{
mode: 'video' | 'book'
}>
>(({children, mode, ...props}, ref) => {
const [cookies, setCookie] = useCookies(['bookPrefs'])
const router = useRouter()

return (
<>
<button
ref={ref}
{...props}
onClick={() => {
setCookie(
'bookPrefs',
{
...cookies.bookPrefs,
mode: mode === 'book' ? 'video' : 'book',
},
{
path: '/',
},
)
return router.refresh()
}}
>
{children}
</button>
</>
)
})

export default ModeToggle

0 comments on commit 5c15ac9

Please sign in to comment.