Files
meet/src/frontend/src/features/home/components/PersonalizeMeetingDialog.tsx
T
lebaudantoine 51dfc46e15 (frontend) introduce a new option while creating room
Display a "personalized" link modal, inspired by Whereby.
The UX and the UI are still cumberstome, however it's fully
functional and accessible.

It's a "okay" v0, allowing users creating their custom link.
Thus we can study this feature traction, and decide whether or
not prioritize this feature in the UX.
2025-01-21 21:12:28 +01:00

135 lines
3.7 KiB
TypeScript

import { FormEvent, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Button, Dialog, type DialogProps, Text } from '@/primitives'
import { HStack } from '@/styled-system/jsx'
import { RiSpam2Fill } from '@remixicon/react'
import { navigateTo } from '@/navigation/navigateTo.ts'
import { useCreateRoom } from '@/features/rooms'
import {
FieldError,
Form as RACForm,
Input,
Label,
TextField,
} from 'react-aria-components'
import { css } from '@/styled-system/css'
export const PersonalizeMeetingDialog = ({
isOpen,
...dialogProps
}: Omit<DialogProps, 'title'>) => {
const { t } = useTranslation('home', {
keyPrefix: 'personalizeMeetingDialog',
})
const { mutateAsync: createRoom } = useCreateRoom()
const [roomSlug, setRoomSlug] = useState('')
const [serverErrors, setServerErrors] = useState<Array<string>>([])
const onSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
createRoom({ slug: roomSlug })
.then((data) =>
navigateTo('room', data.slug, {
state: { create: true, initialRoomData: data },
})
)
.catch((e) => {
const msg =
e.statusCode === 400
? t('errors.server.taken')
: t('errors.server.unknown')
setServerErrors([msg])
})
}
const validationErrors = []
if (roomSlug.length < 5) {
validationErrors.push(t('errors.validation.length'))
}
if (!roomSlug.match(/^[a-z0-9]+$/)) {
validationErrors.push(t('errors.validation.spaceOrSpecialCharacter'))
}
const errors = [...validationErrors, ...serverErrors]
return (
<Dialog isOpen={!!isOpen} {...dialogProps} title={t('heading')}>
<RACForm onSubmit={onSubmit}>
<TextField
isRequired
isInvalid={errors.length > 0}
value={roomSlug}
onChange={(e) => {
setServerErrors([])
setRoomSlug(e.toLowerCase())
}}
className={css({
display: 'flex',
flexDirection: 'column',
})}
>
<Label>{t('label')}</Label>
<div
className={css({
display: 'flex',
justifyContent: 'space-between',
})}
>
<Input
className={css({
height: '46px',
border: '1px solid black',
padding: '4px 8px',
width: '80%',
borderRadius: '0.25rem',
})}
placeholder={t('placeholder')}
/>
<Button type="submit">{t('submit')}</Button>
</div>
<div
className={css({
minHeight: '72px',
})}
>
<FieldError>
<ul
className={css({
listStyle: 'square inside',
color: 'red',
marginLeft: '10px',
marginTop: '10px',
})}
>
{errors.map((error, i) => (
<li key={i}>
<Text as="span" variant={'sm'}>
{error}
</Text>
</li>
))}
</ul>
</FieldError>
</div>
</TextField>
</RACForm>
<HStack>
<div
style={{
backgroundColor: '#d9e5ff',
borderRadius: '50%',
padding: '4px',
marginTop: '1rem',
}}
>
<RiSpam2Fill size={22} style={{ fill: '#4c84fc' }} />
</div>
<Text variant="sm" style={{ marginTop: '1rem', textWrap: 'balance' }}>
{t('warning')}
</Text>
</HStack>
</Dialog>
)
}