2
0

🦴 Add settings page backbone

This commit is contained in:
Baptiste Arnaud
2021-12-23 13:49:24 +01:00
parent 4d8056dfe8
commit 79aede1f3f
14 changed files with 238 additions and 12 deletions

View File

@ -0,0 +1,26 @@
import { Flex, Stack } from '@chakra-ui/react'
import { TypingEmulationSettings } from 'bot-engine'
import { useTypebot } from 'contexts/TypebotContext'
import React from 'react'
import { TypingEmulation } from './TypingEmulation'
export const SettingsContent = () => {
const { typebot, updateSettings } = useTypebot()
const handleTypingEmulationUpdate = (
typingEmulation: TypingEmulationSettings
) => {
if (!typebot) return
updateSettings({ ...typebot.settings, typingEmulation })
}
return (
<Flex h="full" w="full" justifyContent="center" align="flex-start">
<Stack p="6" rounded="md" borderWidth={1} w="600px" minH="500px" mt={10}>
<TypingEmulation
typingEmulation={typebot?.settings.typingEmulation}
onUpdate={handleTypingEmulationUpdate}
/>
</Stack>
</Flex>
)
}

View File

@ -0,0 +1,39 @@
import {
NumberInputProps,
NumberInput,
NumberInputField,
NumberInputStepper,
NumberIncrementStepper,
NumberDecrementStepper,
} from '@chakra-ui/react'
import { useState, useEffect } from 'react'
export const SmartNumberInput = ({
initialValue,
onValueChange,
...props
}: {
initialValue: number
onValueChange: (value: number) => void
} & NumberInputProps) => {
const [value, setValue] = useState(initialValue.toString())
useEffect(() => {
if (value.endsWith('.') || value.endsWith(',')) return
if (value === '') onValueChange(0)
const newValue = parseFloat(value)
if (isNaN(newValue)) return
onValueChange(newValue)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value])
return (
<NumberInput onChange={setValue} value={value} {...props}>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
)
}

View File

@ -0,0 +1,63 @@
import { Flex, Stack, Switch, Text } from '@chakra-ui/react'
import { TypingEmulationSettings } from 'bot-engine'
import React from 'react'
import { SmartNumberInput } from './SmartNumberInput'
type TypingEmulationProps = {
typingEmulation?: TypingEmulationSettings
onUpdate: (typingEmulation: TypingEmulationSettings) => void
}
export const TypingEmulation = ({
typingEmulation,
onUpdate,
}: TypingEmulationProps) => {
const handleSwitchChange = () => {
if (!typingEmulation) return
onUpdate({ ...typingEmulation, enabled: !typingEmulation.enabled })
}
const handleSpeedChange = (speed: number) => {
if (!typingEmulation) return
onUpdate({ ...typingEmulation, speed })
}
const handleMaxDelayChange = (maxDelay: number) => {
if (!typingEmulation) return
onUpdate({ ...typingEmulation, maxDelay: maxDelay })
}
return (
<Stack spacing={4}>
<Flex justifyContent="space-between" align="center">
<Text>Typing emulation</Text>
<Switch
isChecked={typingEmulation?.enabled}
onChange={handleSwitchChange}
/>
</Flex>
{typingEmulation?.enabled && (
<Stack pl={10}>
<Flex justify="space-between" align="center">
<Text>Words per minutes:</Text>
<SmartNumberInput
initialValue={typingEmulation.speed}
onValueChange={handleSpeedChange}
maxW="100px"
step={30}
/>
</Flex>
<Flex justify="space-between" align="center">
<Text>Max delay (in seconds):</Text>
<SmartNumberInput
initialValue={typingEmulation.maxDelay}
onValueChange={handleMaxDelayChange}
maxW="100px"
step={0.1}
/>
</Flex>
</Stack>
)}
</Stack>
)
}

View File

@ -53,9 +53,9 @@ export const TypebotHeader = () => {
</Button>
<Button
as={NextChakraLink}
href={`/typebots/${typebot?.id}/design`}
colorScheme={router.pathname.endsWith('share') ? 'blue' : 'gray'}
variant={router.pathname.endsWith('share') ? 'outline' : 'ghost'}
href={`/typebots/${typebot?.id}/settings`}
colorScheme={router.pathname.endsWith('settings') ? 'blue' : 'gray'}
variant={router.pathname.endsWith('settings') ? 'outline' : 'ghost'}
>
Settings
</Button>

View File

@ -1,5 +1,13 @@
import { useToast } from '@chakra-ui/react'
import { Block, Step, StepType, Target, Theme, Typebot } from 'bot-engine'
import {
Block,
Settings,
Step,
StepType,
Target,
Theme,
Typebot,
} from 'bot-engine'
import { useRouter } from 'next/router'
import {
createContext,
@ -47,6 +55,7 @@ const typebotContext = createContext<{
}) => void
undo: () => void
updateTheme: (theme: Theme) => void
updateSettings: (settings: Settings) => void
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
}>({})
@ -270,6 +279,11 @@ export const TypebotContext = ({
setLocalTypebot({ ...localTypebot, theme })
}
const updateSettings = (settings: Settings) => {
if (!localTypebot) return
setLocalTypebot({ ...localTypebot, settings })
}
return (
<typebotContext.Provider
value={{
@ -286,6 +300,7 @@ export const TypebotContext = ({
removeBlock,
undo,
updateTheme,
updateSettings,
}}
>
{children}

View File

@ -1,4 +1,10 @@
import { BackgroundType, StartBlock, StepType, Theme } from 'bot-engine'
import {
BackgroundType,
Settings,
StartBlock,
StepType,
Theme,
} from 'bot-engine'
import { Typebot, User } from 'db'
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
@ -44,8 +50,15 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
background: { type: BackgroundType.NONE, content: '#ffffff' },
},
}
const settings: Settings = {
typingEmulation: {
enabled: true,
speed: 300,
maxDelay: 1.5,
},
}
const typebot = await prisma.typebot.create({
data: { ...data, ownerId: user.id, startBlock, theme },
data: { ...data, ownerId: user.id, startBlock, theme, settings },
})
return res.send(typebot)
}

View File

@ -0,0 +1,23 @@
import { Flex } from '@chakra-ui/layout'
import withAuth from 'components/HOC/withUser'
import { Seo } from 'components/Seo'
import { SettingsContent } from 'components/settings/SettingsContent'
import { TypebotHeader } from 'components/shared/TypebotHeader'
import { TypebotContext } from 'contexts/TypebotContext'
import { useRouter } from 'next/router'
import React from 'react'
const SettingsPage = () => {
const { query } = useRouter()
return (
<TypebotContext typebotId={query.id?.toString()}>
<Seo title="Settings" />
<Flex overflow="hidden" h="100vh" flexDir="column">
<TypebotHeader />
<SettingsContent />
</Flex>
</TypebotContext>
)
}
export default withAuth(SettingsPage)

View File

@ -156,4 +156,5 @@ export const parseTypebotToPublicTypebot = (
startBlock: typebot.startBlock,
typebotId: typebot.id,
theme: typebot.theme,
settings: typebot.settings,
})