mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
* removed daisy from config * removed tw-elements artefact * removed comments from tailwind config * removed safelist * migrated to tailwind4 and daisyui5 * deleted tailwind.config.js which is not eeded anymore * 3.0.79 * version number * fixed broken layouts * more fixing * more layout fixing * tested theming * small fixes * adapt snapshots to changes * package.json: add unit test update script * more ui refactoring & theme controller * ui improvements * package-lock.json * fix linting * fixed tabs * fix linting * fixed typing --------- Co-authored-by: mahula <lenzmath@posteo.de>
225 lines
7.1 KiB
TypeScript
225 lines
7.1 KiB
TypeScript
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
import { useEffect, useState } from 'react'
|
|
import { useLocation, useNavigate } from 'react-router-dom'
|
|
import { toast } from 'react-toastify'
|
|
|
|
import { useAuth } from '#components/Auth/useAuth'
|
|
import { useItems, useUpdateItem, useAddItem } from '#components/Map/hooks/useItems'
|
|
import { useLayers } from '#components/Map/hooks/useLayers'
|
|
import { useHasUserPermission } from '#components/Map/hooks/usePermissions'
|
|
import { useAddTag, useGetItemTags, useTags } from '#components/Map/hooks/useTags'
|
|
import { MapOverlayPage } from '#components/Templates'
|
|
|
|
import { linkItem, onUpdateItem, unlinkItem } from './itemFunctions'
|
|
import { FormHeader } from './Subcomponents/FormHeader'
|
|
import { FlexForm } from './Templates/FlexForm'
|
|
import { OnepagerForm } from './Templates/OnepagerForm'
|
|
import { SimpleForm } from './Templates/SimpleForm'
|
|
import { TabsForm } from './Templates/TabsForm'
|
|
|
|
import type { FormState } from '#types/FormState'
|
|
import type { Item } from '#types/Item'
|
|
import type { Tag } from '#types/Tag'
|
|
|
|
/**
|
|
* @category Profile
|
|
*/
|
|
export function ProfileForm() {
|
|
const [state, setState] = useState<FormState>({
|
|
color: '',
|
|
id: '',
|
|
group_type: 'wuerdekompass',
|
|
status: 'active',
|
|
name: '',
|
|
subname: '',
|
|
text: '',
|
|
contact: '',
|
|
telephone: '',
|
|
next_appointment: '',
|
|
image: '',
|
|
marker_icon: '',
|
|
offers: [] as Tag[],
|
|
needs: [] as Tag[],
|
|
relations: [] as Item[],
|
|
start: '',
|
|
end: '',
|
|
openCollectiveSlug: '',
|
|
})
|
|
|
|
const [updatePermission, setUpdatePermission] = useState<boolean>(false)
|
|
const [loading, setLoading] = useState<boolean>(false)
|
|
const [item, setItem] = useState<Item>({} as Item)
|
|
const { user } = useAuth()
|
|
const updateItem = useUpdateItem()
|
|
const addItem = useAddItem()
|
|
const layers = useLayers()
|
|
const location = useLocation()
|
|
const tags = useTags()
|
|
const addTag = useAddTag()
|
|
const navigate = useNavigate()
|
|
const hasUserPermission = useHasUserPermission()
|
|
const getItemTags = useGetItemTags()
|
|
const items = useItems()
|
|
|
|
const [urlParams, setUrlParams] = useState(new URLSearchParams(location.search))
|
|
|
|
useEffect(() => {
|
|
item && hasUserPermission('items', 'update', item) && setUpdatePermission(true)
|
|
}, [hasUserPermission, item])
|
|
|
|
useEffect(() => {
|
|
const itemId = location.pathname.split('/')[2]
|
|
|
|
const item = items.find((i) => i.id === itemId)
|
|
item && setItem(item)
|
|
|
|
if (!item) {
|
|
if (items.some((i) => i.user_created?.id === user?.id && i.layer?.userProfileLayer)) {
|
|
navigate('/')
|
|
toast.error('Item does not exist')
|
|
} else {
|
|
const layer = layers.find((l) => l.userProfileLayer)
|
|
setItem({
|
|
id: crypto.randomUUID(),
|
|
name: user?.first_name ?? '',
|
|
text: '',
|
|
layer,
|
|
new: true,
|
|
})
|
|
}
|
|
}
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [items])
|
|
|
|
useEffect(() => {
|
|
const newColor =
|
|
item.color ??
|
|
(getItemTags(item) && getItemTags(item)[0]?.color
|
|
? getItemTags(item)[0].color
|
|
: item.layer?.markerDefaultColor)
|
|
|
|
const offers = (item.offers ?? []).reduce((acc: Tag[], o) => {
|
|
const offer = tags.find((t) => t.id === o.tags_id)
|
|
if (offer) acc.push(offer)
|
|
return acc
|
|
}, [])
|
|
|
|
const needs = (item.needs ?? []).reduce((acc: Tag[], o) => {
|
|
const need = tags.find((t) => t.id === o.tags_id)
|
|
if (need) acc.push(need)
|
|
return acc
|
|
}, [])
|
|
|
|
const relations = (item.relations ?? []).reduce((acc: Item[], r) => {
|
|
const relatedItem = items.find((i) => i.id === r.related_items_id)
|
|
if (relatedItem) acc.push(relatedItem)
|
|
return acc
|
|
}, [])
|
|
|
|
setState({
|
|
color: newColor ?? '',
|
|
id: item?.id ?? '',
|
|
group_type: item?.group_type ?? '',
|
|
status: item?.status ?? '',
|
|
name: item?.name ?? '',
|
|
subname: item?.subname ?? '',
|
|
text: item?.text ?? '',
|
|
contact: item?.contact ?? '',
|
|
telephone: item?.telephone ?? '',
|
|
next_appointment: item?.next_appointment ?? '',
|
|
image: item?.image ?? '',
|
|
// Do we actually mean marker_icon here?
|
|
marker_icon: item?.markerIcon ?? '',
|
|
offers,
|
|
needs,
|
|
relations,
|
|
start: item.start ?? '',
|
|
end: item.end ?? '',
|
|
openCollectiveSlug: item.openCollectiveSlug ?? '',
|
|
})
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [item, tags, items])
|
|
|
|
const [template, setTemplate] = useState<string>('')
|
|
|
|
useEffect(() => {
|
|
if (item.layer?.itemType.template) setTemplate(item.layer?.itemType.template)
|
|
else {
|
|
const userLayer = layers.find((l) => l.userProfileLayer === true)
|
|
if (userLayer) setTemplate(userLayer.itemType.template)
|
|
}
|
|
}, [item, layers])
|
|
|
|
return (
|
|
<>
|
|
<MapOverlayPage
|
|
backdrop
|
|
className='tw:mx-4 tw:mt-4 tw:mb-4 tw:overflow-x-hidden tw:w-[calc(100%-32px)] tw:md:w-[calc(50%-32px)] tw:max-w-3xl tw:left-auto! tw:top-0 tw:bottom-0'
|
|
>
|
|
<form
|
|
className='tw:h-full'
|
|
onSubmit={(e) => {
|
|
e.preventDefault()
|
|
void onUpdateItem(
|
|
state,
|
|
item,
|
|
tags,
|
|
addTag,
|
|
setLoading,
|
|
navigate,
|
|
updateItem,
|
|
addItem,
|
|
user,
|
|
urlParams,
|
|
)
|
|
}}
|
|
>
|
|
<div className='tw:flex tw:flex-col tw:h-full'>
|
|
<FormHeader item={item} state={state} setState={setState} />
|
|
|
|
{template === 'onepager' && (
|
|
<OnepagerForm item={item} state={state} setState={setState}></OnepagerForm>
|
|
)}
|
|
|
|
{template === 'simple' && <SimpleForm state={state} setState={setState}></SimpleForm>}
|
|
|
|
{template === 'flex' && (
|
|
<FlexForm item={item} state={state} setState={setState}></FlexForm>
|
|
)}
|
|
|
|
{template === 'tabs' && (
|
|
<TabsForm
|
|
loading={loading}
|
|
item={item}
|
|
state={state}
|
|
setState={setState}
|
|
updatePermission={updatePermission}
|
|
linkItem={(id) => linkItem(id, item, updateItem)}
|
|
unlinkItem={(id) => unlinkItem(id, item, updateItem)}
|
|
setUrlParams={setUrlParams}
|
|
></TabsForm>
|
|
)}
|
|
|
|
<div className='tw:mt-4 tw:flex-none'>
|
|
<button
|
|
className={`${loading ? ' tw:loading tw:btn tw:float-right' : 'tw:btn tw:float-right'}`}
|
|
type='submit'
|
|
style={{
|
|
// We could refactor this, it is used several times at different locations
|
|
backgroundColor: `${item.color ?? (getItemTags(item) && getItemTags(item)[0] && getItemTags(item)[0].color ? getItemTags(item)[0].color : item?.layer?.markerDefaultColor)}`,
|
|
color: '#fff',
|
|
}}
|
|
>
|
|
Update
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</MapOverlayPage>
|
|
</>
|
|
)
|
|
}
|