Skip to content

Commit

Permalink
Improve layout (#4)
Browse files Browse the repository at this point in the history
* add loader

* add header conditional rendering

* add style
  • Loading branch information
julienbrg authored Aug 1, 2024
1 parent e685ee2 commit dfe0e65
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 37 deletions.
57 changes: 57 additions & 0 deletions public/loader.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: 5 additions & 1 deletion src/components/layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ import { Web3Modal } from '../../context/web3modal'
import { ReactNode } from 'react'
import { Box, Container } from '@chakra-ui/react'
import { Header } from './Header'
import { useRouter } from 'next/router'

interface Props {
children?: ReactNode
}

export default function RootLayout({ children }: Props) {
const router = useRouter()
const isHomePage = router.pathname === '/' || router.pathname === '/index'

return (
<Web3Modal>
<Box margin="0 auto" minH="100vh">
<Header />
{isHomePage && <Header />}
<Container maxW="container.lg">{children}</Container>
</Box>
</Web3Modal>
Expand Down
116 changes: 80 additions & 36 deletions src/pages/play/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { ReactNode } from 'react'
import React, { ReactNode, useState, useEffect, useCallback } from 'react'
import { Text, Button, useToast, Box, VStack, Flex } from '@chakra-ui/react'
import { useRouter } from 'next/router'
import { HeadingComponent } from '../../components/layout/HeadingComponent'
import { LinkComponent } from '../../components/layout/LinkComponent'
import { useState, useEffect } from 'react'
import Image from 'next/image'
import styled from '@emotion/styled'

interface Props {
href: string
Expand All @@ -20,13 +21,48 @@ interface StoryCard {
paths: number[]
}

const TypingText = styled.div`
white-space: pre-wrap;
overflow: hidden;
border-right: 0px solid;
`

interface TypingEffectProps {
text: string
speed?: number
onComplete: () => void
}

const TypingEffect: React.FC<TypingEffectProps> = ({ text, speed = 10, onComplete }) => {
const [displayedText, setDisplayedText] = useState('')

useEffect(() => {
setDisplayedText('') // Reset text when input changes
let i = 0
const typingInterval = setInterval(() => {
if (i < text.length) {
setDisplayedText(text.slice(0, i + 1))
i++
} else {
clearInterval(typingInterval)
onComplete()
}
}, speed)

return () => clearInterval(typingInterval)
}, [text, speed, onComplete])

return <TypingText>{displayedText}</TypingText>
}

export default function Play() {
const router = useRouter()
const toast = useToast()

const [currentStep, setCurrentStep] = useState<number | null>(null)
const [isLoading, setIsLoading] = useState<boolean>(true)
const [story, setStory] = useState<StoryCard | null>(null)
const [showOptions, setShowOptions] = useState<boolean>(false)

const fetchInitialStep = async () => {
try {
Expand Down Expand Up @@ -54,6 +90,7 @@ export default function Play() {

const fetchCard = async (step: number) => {
setIsLoading(true)
setShowOptions(false)
try {
const response = await fetch(`/api/fetchCard?id=${step}`)
if (!response.ok) {
Expand All @@ -79,8 +116,8 @@ export default function Play() {
const nextStep = async (choice: number) => {
console.log('next step:', choice)
setIsLoading(true)
setShowOptions(false)
try {
// Update the game state
const updateResponse = await fetch('/api/updateGameStep', {
method: 'POST',
headers: {
Expand All @@ -93,10 +130,7 @@ export default function Play() {
throw new Error('Failed to update game state')
}

// Update the current step
setCurrentStep(choice)

// Fetch the new story card
await fetchCard(choice)
} catch (error) {
console.error('Error advancing to next step:', error)
Expand All @@ -107,17 +141,27 @@ export default function Play() {
duration: 9000,
isClosable: true,
})
} finally {
setIsLoading(false)
}
}

useEffect(() => {
fetchInitialStep()
}, [])

const handleTypingComplete = useCallback(() => {
console.log('Typing complete, setting timeout for options')
setTimeout(() => {
console.log('Timeout complete, showing options')
setShowOptions(true)
}, 500) // DELAY
}, [])

if (isLoading) {
return <div> </div>
return (
<Box display="flex" justifyContent="center" alignItems="center">
<Image priority width="200" height="200" alt="loader" src="/loader.svg" />
</Box>
)
}

if (!story || currentStep === null) {
Expand All @@ -127,34 +171,34 @@ export default function Play() {
return (
<Flex flexDirection="column" height="100vh" padding={4}>
<VStack spacing={4} flex={1} width="100%">
<Box
width="100%"
height="100px" // Adjust this value as needed for 5 lines
overflowY="auto"
marginBottom={4}>
<HeadingComponent as="h4">{story.desc}</HeadingComponent>
<Box width="100%" maxHeight="180px" overflowY="auto" marginBottom={4} marginTop={10}>
<HeadingComponent as="h4">
<TypingEffect text={story.desc} onComplete={handleTypingComplete} />
</HeadingComponent>
</Box>
<VStack spacing={4} width="100%">
{story.options.map((option, index) => (
<Box
key={index}
width="100%"
borderRadius="lg"
p={4}
borderWidth="2px"
onClick={() => nextStep(story.paths[index])}
cursor="pointer"
_hover={{
borderColor: '#8c1c84',
boxShadow: 'md',
}}
transition="all 0.2s">
<Text fontSize="xl" fontWeight="medium" color={'#45a2f8'} _hover={{ color: '#45a2f8' }}>
{option}
</Text>
</Box>
))}
</VStack>
{showOptions && (
<VStack spacing={4} width="100%">
{story.options.map((option, index) => (
<Box
key={index}
width="100%"
borderRadius="lg"
p={4}
borderWidth="2px"
onClick={() => nextStep(story.paths[index])}
cursor="pointer"
_hover={{
borderColor: '#8c1c84',
boxShadow: 'md',
}}
transition="all 0.2s">
<Text fontSize="lg" fontWeight="medium" color={'#45a2f8'} _hover={{ color: '#45a2f8' }}>
{option}
</Text>
</Box>
))}
</VStack>
)}
</VStack>
</Flex>
)
Expand Down

0 comments on commit dfe0e65

Please sign in to comment.