mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
143 lines
4.8 KiB
TypeScript
143 lines
4.8 KiB
TypeScript
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
import { useRef, useState, useEffect } from 'react'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import { toast } from 'react-toastify'
|
|
|
|
import { useAppState } from '#components/AppShell/hooks/useAppState'
|
|
import { useItems } from '#components/Map/hooks/useItems'
|
|
import { Item, ItemsApi } from '#src/types'
|
|
|
|
import { EmojiPicker } from './EmojiPicker'
|
|
import { MapOverlayPage } from './MapOverlayPage'
|
|
|
|
export const AttestationForm = ({ api }: { api?: ItemsApi<unknown> }) => {
|
|
const items = useItems()
|
|
const appState = useAppState()
|
|
const [users, setUsers] = useState<Item[]>()
|
|
const navigate = useNavigate()
|
|
|
|
useEffect(() => {
|
|
const params = new URLSearchParams(location.search)
|
|
const toUserIds = params.get('to')
|
|
setUsers(items.filter((i) => toUserIds?.includes(i.id)))
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [items, location])
|
|
|
|
const [inputValue, setInputValue] = useState('')
|
|
const inputRef = useRef<HTMLInputElement>(null)
|
|
|
|
useEffect(() => {
|
|
if (inputRef.current) {
|
|
inputRef.current.style.width = 'auto'
|
|
inputRef.current.style.width = `${inputRef.current.scrollWidth + 20}px`
|
|
}
|
|
}, [inputValue])
|
|
|
|
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
setInputValue(event.target.value)
|
|
}
|
|
|
|
const sendAttestation = async () => {
|
|
const to: any[] = []
|
|
users?.map((u) => to.push({ directus_users_id: u.user_created.id }))
|
|
|
|
api?.createItem &&
|
|
toast
|
|
.promise(
|
|
api.createItem({
|
|
text: inputValue,
|
|
emoji: selectedEmoji,
|
|
color: selectedColor,
|
|
shape: selectedShape,
|
|
to,
|
|
}),
|
|
{
|
|
pending: 'creating attestation ...',
|
|
success: 'Attestation created',
|
|
error: {
|
|
render({ data }) {
|
|
return `${data}`
|
|
},
|
|
},
|
|
},
|
|
)
|
|
.then(() =>
|
|
navigate(
|
|
'/item/' +
|
|
items.find(
|
|
(i) =>
|
|
i.user_created.id === to[0].directus_users_id &&
|
|
i.layer?.itemType.name === 'player',
|
|
)?.id +
|
|
'?tab=2',
|
|
),
|
|
)
|
|
}
|
|
|
|
const [selectedEmoji, setSelectedEmoji] = useState('select badge')
|
|
const [selectedShape, setSelectedShape] = useState('circle')
|
|
const [selectedColor, setSelectedColor] = useState('#fff0d6')
|
|
|
|
return (
|
|
<MapOverlayPage backdrop className='tw-h-fit tw-min-h-56 tw-w-96'>
|
|
<div className='tw-text-center tw-text-xl tw-font-bold'>Gratitude</div>
|
|
<div className='tw-text-center tw-text-base tw-text-gray-400'>to</div>
|
|
<div className='tw-flex tw-flex-row tw-justify-center tw-items-center tw-flex-wrap'>
|
|
{users &&
|
|
users.map(
|
|
(u, k) => (
|
|
<div key={k} className='tw-flex tw-items-center tw-space-x-3 tw-mx-2 tw-my-1'>
|
|
{u.image ? (
|
|
<div className='tw-avatar'>
|
|
<div className='tw-mask tw-mask-circle tw-w-8 tw-h-8'>
|
|
<img
|
|
src={appState.assetsApi.url + u.image + '?width=40&heigth=40'}
|
|
alt='Avatar'
|
|
/>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className='tw-mask tw-mask-circle tw-text-xl md:tw-text-2xl tw-bg-slate-200 tw-rounded-full tw-w-8 tw-h-8'></div>
|
|
)}
|
|
<div>
|
|
<div className='tw-font-bold'>{u.name}</div>
|
|
</div>
|
|
</div>
|
|
),
|
|
', ',
|
|
)}
|
|
</div>
|
|
|
|
<div className='tw-w-full'>
|
|
<div className='tw-flex tw-justify-center tw-items-center'>
|
|
<div className=' tw-flex tw-justify-center tw-items-center tw-w-28 tw-h-28 tw-m-4'>
|
|
<EmojiPicker
|
|
selectedEmoji={selectedEmoji}
|
|
selectedColor={selectedColor}
|
|
selectedShape={selectedShape}
|
|
setSelectedEmoji={setSelectedEmoji}
|
|
setSelectedColor={setSelectedColor}
|
|
setSelectedShape={setSelectedShape}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className='tw-flex tw-justify-center tw-items-center'>
|
|
<input
|
|
ref={inputRef}
|
|
value={inputValue}
|
|
onChange={handleChange}
|
|
type='text'
|
|
placeholder='... and say some words'
|
|
className='tw-input tw-min-w-0 tw-w-fit tw-resize-none tw-overflow-hidden tw-text-center '
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className='tw-w-full tw-grid tw-mt-4'>
|
|
<button onClick={sendAttestation} className='tw-btn tw-place-self-center tw-px-8'>
|
|
Next
|
|
</button>
|
|
</div>
|
|
</MapOverlayPage>
|
|
)
|
|
}
|