mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
lint fixes
This commit is contained in:
parent
9546b2e9f4
commit
36aeda5919
@ -34,7 +34,7 @@ export default function NavBar ({ appName, userType }: { appName: string, userTy
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(location.search)
|
||||
const embedded = params.get('embedded')
|
||||
embedded != 'true' && setShowNav(true)
|
||||
embedded !== 'true' && setShowNav(true)
|
||||
}, [location])
|
||||
|
||||
const onLogout = () => {
|
||||
@ -43,7 +43,7 @@ export default function NavBar ({ appName, userType }: { appName: string, userTy
|
||||
{
|
||||
success: {
|
||||
render () {
|
||||
return `Bye bye`
|
||||
return 'Bye bye'
|
||||
},
|
||||
// other options
|
||||
icon: '👋'
|
||||
|
||||
@ -48,7 +48,7 @@ export function SideBar ({ routes, bottomRoutes }: { routes: route[], bottomRout
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(location.search)
|
||||
const embedded = params.get('embedded')
|
||||
embedded != 'true' && setEmbedded(false)
|
||||
embedded !== 'true' && setEmbedded(false)
|
||||
}, [location])
|
||||
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
|
||||
@ -35,7 +35,7 @@ function SidebarSubmenu ({ submenu, name, icon } : { path: string;
|
||||
<Link to={m.path} className='' >
|
||||
{m.icon}<span className="" data-te-sidenav-slim="false">{m.name}</span>
|
||||
{
|
||||
location.pathname == m.path
|
||||
location.pathname === m.path
|
||||
? (<span className="absolute mt-1 mb-1 inset-y-0 left-0 w-1 rounded-tr-md rounded-br-md bg-primary "
|
||||
aria-hidden="true"></span>)
|
||||
: null
|
||||
|
||||
@ -5,7 +5,7 @@ import { useAuth } from './useAuth'
|
||||
import { MapOverlayPage } from '../Templates'
|
||||
|
||||
// eslint-disable-next-line react/prop-types
|
||||
export function RequestPasswordPage ({ reset_url }) {
|
||||
export function RequestPasswordPage ({ resetUrl }) {
|
||||
const [email, setEmail] = useState<string>('')
|
||||
|
||||
const { requestPasswordReset, loading } = useAuth()
|
||||
@ -14,7 +14,7 @@ export function RequestPasswordPage ({ reset_url }) {
|
||||
|
||||
const onReset = async () => {
|
||||
await toast.promise(
|
||||
requestPasswordReset(email, reset_url),
|
||||
requestPasswordReset(email, resetUrl),
|
||||
{
|
||||
success: {
|
||||
render () {
|
||||
|
||||
@ -34,14 +34,14 @@ type AuthContextProps = {
|
||||
const AuthContext = createContext<AuthContextProps>({
|
||||
isAuthenticated: false,
|
||||
user: null,
|
||||
login: () => Promise.reject(),
|
||||
register: () => Promise.reject(),
|
||||
login: () => Promise.reject(Error('Unimplemented')),
|
||||
register: () => Promise.reject(Error('Unimplemented')),
|
||||
loading: false,
|
||||
logout: () => Promise.reject(),
|
||||
updateUser: () => Promise.reject(),
|
||||
logout: () => Promise.reject(Error('Unimplemented')),
|
||||
updateUser: () => Promise.reject(Error('Unimplemented')),
|
||||
token: '',
|
||||
requestPasswordReset: () => Promise.reject(),
|
||||
passwordReset: () => Promise.reject()
|
||||
requestPasswordReset: () => Promise.reject(Error('Unimplemented')),
|
||||
passwordReset: () => Promise.reject(Error('Unimplemented'))
|
||||
})
|
||||
|
||||
export const AuthProvider = ({ userApi, children }: AuthProviderProps) => {
|
||||
@ -123,10 +123,10 @@ export const AuthProvider = ({ userApi, children }: AuthProviderProps) => {
|
||||
}
|
||||
}
|
||||
|
||||
const requestPasswordReset = async (email: string, reset_url?: string): Promise<any> => {
|
||||
const requestPasswordReset = async (email: string, resetUrl?: string): Promise<any> => {
|
||||
setLoading(true)
|
||||
try {
|
||||
await userApi.requestPasswordReset(email, reset_url)
|
||||
await userApi.requestPasswordReset(email, resetUrl)
|
||||
return setLoading(false)
|
||||
} catch (error: any) {
|
||||
setLoading(false)
|
||||
@ -134,10 +134,10 @@ export const AuthProvider = ({ userApi, children }: AuthProviderProps) => {
|
||||
}
|
||||
}
|
||||
|
||||
const passwordReset = async (token: string, new_password:string): Promise<any> => {
|
||||
const passwordReset = async (token: string, newPassword:string): Promise<any> => {
|
||||
setLoading(true)
|
||||
try {
|
||||
await userApi.passwordReset(token, new_password)
|
||||
await userApi.passwordReset(token, newPassword)
|
||||
return setLoading(false)
|
||||
} catch (error: any) {
|
||||
setLoading(false)
|
||||
|
||||
@ -19,7 +19,7 @@ export function Quests () {
|
||||
const items = useItems()
|
||||
|
||||
useEffect(() => {
|
||||
setProfie(items.find(i => i.user_created?.id === user?.id && i.layer?.itemType.name == 'user' && i.user_created?.id != null))
|
||||
setProfie(items.find(i => i.user_created?.id === user?.id && i.layer?.itemType.name === 'user' && i.user_created?.id != null))
|
||||
}, [items, user])
|
||||
|
||||
return (
|
||||
|
||||
@ -57,7 +57,7 @@ export const Autocomplete = ({ inputProps, suggestions, onSelected, pushFiltered
|
||||
onSelected(filteredSuggestions[heighlightedSuggestion])
|
||||
setHeighlightedSuggestion(0)
|
||||
}
|
||||
filteredSuggestions.length == 0 && inputProps.onKeyDown(event)
|
||||
filteredSuggestions.length === 0 && inputProps.onKeyDown(event)
|
||||
break
|
||||
default:
|
||||
inputProps.onKeyDown(event)
|
||||
@ -70,7 +70,7 @@ export const Autocomplete = ({ inputProps, suggestions, onSelected, pushFiltered
|
||||
<input ref={inputRef} {...inputProps} type="text" onChange={(e) => handleChange(e)} tabIndex="-1" onKeyDown={handleKeyDown}/>
|
||||
<ul className={`tw-absolute tw-z-[4000] ${filteredSuggestions.length > 0 && 'tw-bg-base-100 tw-rounded-xl tw-p-2'}`}>
|
||||
{filteredSuggestions.map((suggestion, index) => (
|
||||
<li key={index} onClick={() => handleSuggestionClick(suggestion)}><TagView heighlight={index == heighlightedSuggestion} tag={suggestion}></TagView></li>
|
||||
<li key={index} onClick={() => handleSuggestionClick(suggestion)}><TagView heighlight={index === heighlightedSuggestion} tag={suggestion}></TagView></li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -26,7 +26,7 @@ const ComboBoxInput = ({ id, options, value, onValueChange }: ComboBoxProps) =>
|
||||
onChange={handleChange}
|
||||
>
|
||||
{options.map((o) =>
|
||||
<option value={o.value} key={o.value} selected={o.value == value}>{o.label}</option>
|
||||
<option value={o.value} key={o.value} selected={o.value === value}>{o.label}</option>
|
||||
)}
|
||||
</select>
|
||||
)
|
||||
|
||||
@ -44,6 +44,7 @@ export const Layer = ({
|
||||
onlyOnePerOwner = false,
|
||||
customEditLink,
|
||||
customEditParameter,
|
||||
// eslint-disable-next-line camelcase
|
||||
public_edit_items,
|
||||
listed = true,
|
||||
setItemFormPopup,
|
||||
@ -82,15 +83,17 @@ export const Layer = ({
|
||||
const visibleGroupTypes = useVisibleGroupType()
|
||||
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line camelcase
|
||||
data && setItemsData({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, markerDefaultColor2, api, itemType, itemNameField, itemSubnameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, itemTagsField, itemOffersField, itemNeedsField, onlyOnePerOwner, customEditLink, customEditParameter, public_edit_items, listed, setItemFormPopup, itemFormPopup, clusterRef })
|
||||
// eslint-disable-next-line camelcase
|
||||
api && setItemsApi({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, markerDefaultColor2, api, itemType, itemNameField, itemSubnameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, itemTagsField, itemOffersField, itemNeedsField, onlyOnePerOwner, customEditLink, customEditParameter, public_edit_items, listed, setItemFormPopup, itemFormPopup, clusterRef })
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [data, api])
|
||||
|
||||
useMapEvents({
|
||||
popupopen: (e) => {
|
||||
const item = Object.entries(leafletRefs).find(r => r[1].popup == e.popup)?.[1].item
|
||||
if (item?.layer?.name == name && window.location.pathname.split('/')[1] != item.id) {
|
||||
const item = Object.entries(leafletRefs).find(r => r[1].popup === e.popup)?.[1].item
|
||||
if (item?.layer?.name === name && window.location.pathname.split('/')[1] !== item.id) {
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
if (!location.pathname.includes('/item/')) {
|
||||
window.history.pushState({}, '', `/${item.id}` + `${params.toString() !== '' ? `?${params}` : ''}`)
|
||||
@ -138,6 +141,7 @@ export const Layer = ({
|
||||
processedTags[newtag.name] = true
|
||||
addTag(newtag)
|
||||
}
|
||||
return null
|
||||
})
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@ -149,9 +153,9 @@ export const Layer = ({
|
||||
items
|
||||
.filter(item => item.layer?.name === name)
|
||||
?.filter(item =>
|
||||
filterTags.length == 0 ? item : filterTags.some(tag => getItemTags(item).some(filterTag => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))
|
||||
filterTags.length === 0 ? item : filterTags.some(tag => getItemTags(item).some(filterTag => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))
|
||||
?.filter(item => item.layer && isLayerVisible(item.layer))
|
||||
.filter(item => item.group_type && isGroupTypeVisible(item.group_type) || visibleGroupTypes.length == 0)
|
||||
.filter(item => item.group_type && isGroupTypeVisible(item.group_type) || visibleGroupTypes.length === 0)
|
||||
.map((item: Item) => {
|
||||
if (getValue(item, itemLongitudeField) && getValue(item, itemLatitudeField)) {
|
||||
if (getValue(item, itemTextField)) item[itemTextField] = getValue(item, itemTextField)
|
||||
@ -171,6 +175,7 @@ export const Layer = ({
|
||||
const newTag = { id: crypto.randomUUID(), name: tag.slice(1), color: randomColor() }
|
||||
setNewTagsToAdd(current => [...current, newTag])
|
||||
}
|
||||
return null
|
||||
})
|
||||
!tagsReady && setTagsReady(true)
|
||||
}
|
||||
@ -192,7 +197,7 @@ export const Layer = ({
|
||||
}
|
||||
return (
|
||||
<Marker ref={(r) => {
|
||||
if (!(item.id in leafletRefs && leafletRefs[item.id].marker == r)) { r && addMarker(item, r) }
|
||||
if (!(item.id in leafletRefs && leafletRefs[item.id].marker === r)) { r && addMarker(item, r) }
|
||||
}}
|
||||
eventHandlers={{
|
||||
click: () => {
|
||||
@ -205,7 +210,7 @@ export const Layer = ({
|
||||
? React.Children.toArray(children).map((child) =>
|
||||
React.isValidElement(child) && child.props.__TYPE === 'ItemView'
|
||||
? <ItemViewPopup ref={(r) => {
|
||||
if (!(item.id in leafletRefs && leafletRefs[item.id].popup == r)) { r && addPopup(item, r as Popup) }
|
||||
if (!(item.id in leafletRefs && leafletRefs[item.id].popup === r)) { r && addPopup(item, r as Popup) }
|
||||
}} key={item.id + item.name}
|
||||
item={item}
|
||||
setItemFormPopup={setItemFormPopup}>
|
||||
@ -215,7 +220,7 @@ export const Layer = ({
|
||||
)
|
||||
: <>
|
||||
<ItemViewPopup key={item.id + item.name} ref={(r) => {
|
||||
if (!(item.id in leafletRefs && leafletRefs[item.id].popup == r)) { r && addPopup(item, r as Popup) }
|
||||
if (!(item.id in leafletRefs && leafletRefs[item.id].popup === r)) { r && addPopup(item, r as Popup) }
|
||||
}}
|
||||
item={item}
|
||||
setItemFormPopup={setItemFormPopup} />
|
||||
@ -229,7 +234,7 @@ export const Layer = ({
|
||||
}
|
||||
{// {children}}
|
||||
}
|
||||
{itemFormPopup && itemFormPopup.layer!.name == name &&
|
||||
{itemFormPopup && itemFormPopup.layer!.name === name &&
|
||||
(children && React.Children.toArray(children).some(child => React.isValidElement(child) && child.props.__TYPE === 'ItemForm')
|
||||
? React.Children.toArray(children).map((child) =>
|
||||
React.isValidElement(child) && child.props.__TYPE === 'ItemForm'
|
||||
|
||||
@ -10,6 +10,7 @@ export default function AddButton ({ triggerAction }: { triggerAction: React.Dis
|
||||
let canAdd = false
|
||||
layers.map(layer => {
|
||||
if (layer.api?.createItem && hasUserPermission(layer.api.collectionName!, 'create', undefined, layer) && layer.listed) canAdd = true
|
||||
return null
|
||||
})
|
||||
return canAdd
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ export const SearchControl = () => {
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(location.search)
|
||||
const embedded = params.get('embedded')
|
||||
embedded != 'true' && setEmbedded(false)
|
||||
embedded !== 'true' && setEmbedded(false)
|
||||
}, [location])
|
||||
|
||||
return (<>
|
||||
@ -101,7 +101,7 @@ export const SearchControl = () => {
|
||||
</div>
|
||||
<LocateControl />
|
||||
</div>
|
||||
{hideSuggestions || Array.from(geoResults).length == 0 && itemsResults.length == 0 && tagsResults.length == 0 && !isGeoCoordinate(value) || value.length == 0
|
||||
{hideSuggestions || Array.from(geoResults).length === 0 && itemsResults.length === 0 && tagsResults.length === 0 && !isGeoCoordinate(value) || value.length === 0
|
||||
? ''
|
||||
: <div className='tw-card tw-card-body tw-bg-base-100 tw-p-4 tw-mt-2 tw-shadow-xl tw-overflow-y-auto tw-max-h-[calc(100dvh-152px)] tw-absolute tw-z-3000'>
|
||||
{tagsResults.length > 0 &&
|
||||
@ -119,7 +119,7 @@ export const SearchControl = () => {
|
||||
{itemsResults.length > 0 && tagsResults.length > 0 && <hr className='tw-opacity-50'></hr>}
|
||||
{itemsResults.slice(0, 5).map(item => (
|
||||
<div key={item.id} className='tw-cursor-pointer hover:tw-font-bold' onClick={() => {
|
||||
const marker = Object.entries(leafletRefs).find(r => r[1].item == item)?.[1].marker
|
||||
const marker = Object.entries(leafletRefs).find(r => r[1].item === item)?.[1].marker
|
||||
if (marker) {
|
||||
navigate(`/${item.id}?${new URLSearchParams(window.location.search)}`)
|
||||
} else {
|
||||
|
||||
@ -59,6 +59,7 @@ export function ItemFormPopup (props: ItemFormPopupProps) {
|
||||
if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
|
||||
addTag({ id: crypto.randomUUID(), name: tag.slice(1), color: randomColor() })
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
if (props.item) {
|
||||
|
||||
@ -80,7 +80,7 @@ export const ItemViewPopup = React.forwardRef((props: ItemViewPopupProps, ref: a
|
||||
|
||||
{
|
||||
infoExpanded
|
||||
? <p className={'tw-italic tw-min-h-[21px] !tw-my-0 tw-text-gray-500'} >{`${props.item.date_updated && props.item.date_updated != props.item.date_created ? 'updated' : 'posted'} ${props.item && props.item.user_created && props.item.user_created.first_name ? `by ${props.item.user_created.first_name}` : ''} ${props.item.date_updated ? timeAgo(props.item.date_updated) : timeAgo(props.item.date_created!)}`}</p>
|
||||
? <p className={'tw-italic tw-min-h-[21px] !tw-my-0 tw-text-gray-500'} >{`${props.item.date_updated && props.item.date_updated !== props.item.date_created ? 'updated' : 'posted'} ${props.item && props.item.user_created && props.item.user_created.first_name ? `by ${props.item.user_created.first_name}` : ''} ${props.item.date_updated ? timeAgo(props.item.date_updated) : timeAgo(props.item.date_created!)}`}</p>
|
||||
: <p className="!tw-my-0 tw-min-h-[21px] tw-font-bold tw-cursor-pointer tw-text-gray-500" onClick={() => setInfoExpanded(true)}>ⓘ</p>
|
||||
}
|
||||
<div className='tw-grow'></div>
|
||||
|
||||
@ -31,6 +31,7 @@ export function Tags ({ data, api } : {data?: Tag[], api?: ItemsApi<Tag>}) {
|
||||
decodedTagsArray?.map(urlTag => {
|
||||
const tag = tags.find(t => t.name.toLocaleLowerCase() === urlTag.toLocaleLowerCase())
|
||||
tag && addFilterTag(tag)
|
||||
return null
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -105,7 +105,7 @@ function useFilterManager (initialTags: Tag[]): {
|
||||
case 'TOGGLE_LAYER':
|
||||
const exist2 = state.some((layer) =>
|
||||
layer.name === action.layer.name)
|
||||
if (exist2) return state.filter(({ name }) => name != action.layer.name)
|
||||
if (exist2) return state.filter(({ name }) => name !== action.layer.name)
|
||||
else return [...state, action.layer]
|
||||
case 'RESET_LAYERS':
|
||||
return initialLayers
|
||||
@ -129,7 +129,7 @@ function useFilterManager (initialTags: Tag[]): {
|
||||
case 'TOGGLE_GROUP_TYPE':
|
||||
const exist2 = state.some((groupType) =>
|
||||
groupType === action.groupType)
|
||||
if (exist2) return state.filter((groupType) => groupType != action.groupType)
|
||||
if (exist2) return state.filter((groupType) => groupType !== action.groupType)
|
||||
else return [...state, action.groupType]
|
||||
case 'RESET_GROUP_TYPE':
|
||||
return []
|
||||
@ -162,9 +162,10 @@ function useFilterManager (initialTags: Tag[]): {
|
||||
const urlTags = params.get('tags')
|
||||
let newUrlTags = ''
|
||||
const tags = urlTags?.split(';')
|
||||
if (tags?.length == 0 && urlTags?.length && urlTags?.length > 0) tags[0] = urlTags
|
||||
if (tags?.length === 0 && urlTags?.length && urlTags?.length > 0) tags[0] = urlTags
|
||||
tags?.map(urlTag => {
|
||||
if (!(urlTag.toLocaleLowerCase() === name.toLocaleLowerCase())) { newUrlTags = newUrlTags + `${newUrlTags === '' ? urlTag : `;${urlTag}`}` }
|
||||
return null
|
||||
})
|
||||
if (newUrlTags !== '') {
|
||||
params.set('tags', `${newUrlTags}`)
|
||||
|
||||
@ -91,6 +91,7 @@ function useItemsManager (initialItems: Item[]): {
|
||||
if (result) {
|
||||
result.map(item => {
|
||||
dispatch({ type: 'ADD', item: { ...item, layer } })
|
||||
return null
|
||||
})
|
||||
setallItemsLoaded(true)
|
||||
}
|
||||
@ -101,6 +102,7 @@ function useItemsManager (initialItems: Item[]): {
|
||||
addLayer(layer)
|
||||
layer.data?.map(item => {
|
||||
dispatch({ type: 'ADD', item: { ...item, layer } })
|
||||
return null
|
||||
})
|
||||
setallItemsLoaded(true)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
||||
@ -57,6 +57,7 @@ function usePermissionsManager (initialPermissions: Permission[]): {
|
||||
if (result) {
|
||||
result.map(permission => {
|
||||
dispatch({ type: 'ADD', permission })
|
||||
return null
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
@ -64,6 +65,7 @@ function usePermissionsManager (initialPermissions: Permission[]): {
|
||||
const setPermissionData = useCallback((data: Permission[]) => {
|
||||
data.map(permission => {
|
||||
dispatch({ type: 'ADD', permission })
|
||||
return null
|
||||
})
|
||||
}, [])
|
||||
|
||||
|
||||
@ -94,11 +94,11 @@ function useSelectPositionManager (): {
|
||||
|
||||
const linkItem = async (id: string) => {
|
||||
if (markerClicked) {
|
||||
const new_relations = markerClicked.relations || []
|
||||
const newRelations = markerClicked.relations || []
|
||||
|
||||
if (!new_relations.some(r => r.related_items_id == id)) {
|
||||
new_relations?.push({ items_id: markerClicked.id, related_items_id: id })
|
||||
const updatedItem = { id: markerClicked.id, relations: new_relations }
|
||||
if (!newRelations.some(r => r.related_items_id === id)) {
|
||||
newRelations?.push({ items_id: markerClicked.id, related_items_id: id })
|
||||
const updatedItem = { id: markerClicked.id, relations: newRelations }
|
||||
|
||||
let success = false
|
||||
try {
|
||||
@ -108,7 +108,7 @@ function useSelectPositionManager (): {
|
||||
toast.error(error.toString())
|
||||
}
|
||||
if (success) {
|
||||
updateItem({ ...markerClicked, relations: new_relations })
|
||||
updateItem({ ...markerClicked, relations: newRelations })
|
||||
toast.success('Item linked')
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ function useTagsManager (initialTags: Tag[]): {
|
||||
...state,
|
||||
{ ...action.tag }
|
||||
]
|
||||
if (tagCount == newState.length) setallTagsLoaded(true)
|
||||
if (tagCount === newState.length) setallTagsLoaded(true)
|
||||
return newState
|
||||
} else return state
|
||||
default:
|
||||
@ -57,11 +57,12 @@ function useTagsManager (initialTags: Tag[]): {
|
||||
setApi(api)
|
||||
const result = await api.getItems()
|
||||
setTagCount(result.length)
|
||||
if (tagCount == 0) setallTagsLoaded(true)
|
||||
if (tagCount === 0) setallTagsLoaded(true)
|
||||
if (result) {
|
||||
result.map(tag => {
|
||||
// tag.name = tag.name.toLocaleLowerCase();
|
||||
dispatch({ type: 'ADD', tag })
|
||||
return null
|
||||
})
|
||||
}
|
||||
|
||||
@ -72,6 +73,7 @@ function useTagsManager (initialTags: Tag[]): {
|
||||
data.map(tag => {
|
||||
// tag.name = tag.name.toLocaleLowerCase();
|
||||
dispatch({ type: 'ADD', tag })
|
||||
return null
|
||||
})
|
||||
}, [])
|
||||
|
||||
@ -93,14 +95,17 @@ function useTagsManager (initialTags: Tag[]): {
|
||||
if (tags.find(t => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
|
||||
itemTags.push(tags.find(t => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())!)
|
||||
}
|
||||
return null
|
||||
})
|
||||
item.layer?.itemOffersField && getValue(item, item.layer.itemOffersField)?.map(o => {
|
||||
const offer = tags.find(t => t.id === o.tags_id)
|
||||
offer && itemTags.push(offer)
|
||||
return null
|
||||
})
|
||||
item.layer?.itemNeedsField && getValue(item, item.layer.itemNeedsField)?.map(n => {
|
||||
const need = tags.find(t => t.id === n.tags_id)
|
||||
need && itemTags.push(need)
|
||||
return null
|
||||
})
|
||||
|
||||
return itemTags
|
||||
|
||||
@ -64,7 +64,7 @@ export function ProfileForm ({ userType }: { userType: string }) {
|
||||
const item = items.find(i => i.id === itemId)
|
||||
item && setItem(item)
|
||||
|
||||
const layer = layers.find(l => l.itemType.name == userType)
|
||||
const layer = layers.find(l => l.itemType.name === userType)
|
||||
|
||||
!item && setItem({ id: crypto.randomUUID(), name: user ? user.first_name : '', text: '', layer, new: true })
|
||||
|
||||
@ -132,15 +132,15 @@ export function ProfileForm ({ userType }: { userType: string }) {
|
||||
|
||||
<FormHeader item={item} state={state} setState={setState} />
|
||||
|
||||
{template == 'onepager' && (
|
||||
{template === 'onepager' && (
|
||||
<OnepagerForm item={item} state={state} setState={setState}></OnepagerForm>
|
||||
)}
|
||||
|
||||
{template == 'simple' &&
|
||||
{template === 'simple' &&
|
||||
<SimpleForm state={state} setState={setState}></SimpleForm>
|
||||
}
|
||||
|
||||
{template == 'tabs' &&
|
||||
{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>
|
||||
}
|
||||
|
||||
|
||||
@ -69,14 +69,17 @@ export function ProfileView ({ userType, attestationApi }: { userType: string, a
|
||||
item?.layer?.itemOffersField && getValue(item, item.layer.itemOffersField)?.map(o => {
|
||||
const tag = tags.find(t => t.id === o.tags_id)
|
||||
tag && setOffers(current => [...current, tag])
|
||||
return null
|
||||
})
|
||||
item?.layer?.itemNeedsField && getValue(item, item.layer.itemNeedsField)?.map(n => {
|
||||
const tag = tags.find(t => t.id === n.tags_id)
|
||||
tag && setNeeds(current => [...current, tag])
|
||||
return null
|
||||
})
|
||||
item?.relations?.map(r => {
|
||||
const item = items.find(i => i.id == r.related_items_id)
|
||||
const item = items.find(i => i.id === r.related_items_id)
|
||||
item && setRelations(current => [...current, item])
|
||||
return null
|
||||
})
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@ -91,7 +94,7 @@ export function ProfileView ({ userType, attestationApi }: { userType: string, a
|
||||
}
|
||||
if (item) {
|
||||
if (item.position) {
|
||||
const marker = Object.entries(leafletRefs).find(r => r[1].item == item)?.[1].marker
|
||||
const marker = Object.entries(leafletRefs).find(r => r[1].item === item)?.[1].marker
|
||||
marker && clusterRef.hasLayer(marker) && clusterRef?.zoomToShowLayer(marker, () => {
|
||||
const bounds = map.getBounds()
|
||||
const x = bounds.getEast() - bounds.getWest()
|
||||
@ -100,7 +103,7 @@ export function ProfileView ({ userType, attestationApi }: { userType: string, a
|
||||
)
|
||||
} else {
|
||||
const parent = getFirstAncestor(item)
|
||||
const marker = Object.entries(leafletRefs).find(r => r[1].item == parent)?.[1].marker
|
||||
const marker = Object.entries(leafletRefs).find(r => r[1].item === parent)?.[1].marker
|
||||
marker && clusterRef.hasLayer(marker) && clusterRef?.zoomToShowLayer(marker, () => {
|
||||
const bounds = map.getBounds()
|
||||
const x = bounds.getEast() - bounds.getWest()
|
||||
@ -146,15 +149,15 @@ export function ProfileView ({ userType, attestationApi }: { userType: string, a
|
||||
<HeaderView api={item.layer?.api} item={item} deleteCallback={(e) => handleDelete(e, item, setLoading, removeItem, map, navigate)} editCallback={() => navigate('/edit-item/' + item.id)} setPositionCallback={() => { map.closePopup(); setSelectPosition(item); navigate('/') }} big truncateSubname={false} />
|
||||
</div>
|
||||
|
||||
{template == 'onepager' &&
|
||||
{template === 'onepager' &&
|
||||
<OnepagerView item={item} userType={userType}/>
|
||||
}
|
||||
|
||||
{template == 'simple' &&
|
||||
{template === 'simple' &&
|
||||
<SimpleView item={item}/>
|
||||
}
|
||||
|
||||
{template == 'tabs' &&
|
||||
{template === 'tabs' &&
|
||||
<TabsView userType={userType} attestations={attestations} setUrlParams={setUrlParams} item={item} loading={loading} offers={offers} needs={needs} relations={relations} updatePermission={updatePermission} linkItem={(id) => linkItem(id, item, updateItem)} unlinkItem={(id) => unlinkItem(id, item, updateItem)}/>
|
||||
}
|
||||
</>
|
||||
|
||||
@ -25,7 +25,7 @@ export function ActionButton ({ item, triggerAddButton, triggerItemSelected, exi
|
||||
|
||||
const items = useItems()
|
||||
|
||||
const filterdItems = items.filter(i => !itemType || i.layer?.itemType.name == itemType).filter(i => !existingRelations.some(s => s.id == i.id)).filter(i => i.id != item.id)
|
||||
const filterdItems = items.filter(i => !itemType || i.layer?.itemType.name === itemType).filter(i => !existingRelations.some(s => s.id === i.id)).filter(i => i.id !== item.id)
|
||||
|
||||
return (
|
||||
<>{hasUserPermission(collection, 'update', item) &&
|
||||
|
||||
@ -29,7 +29,7 @@ const SubHeader = ({ type, status, url, title }) => (
|
||||
<div className='tw-float-left tw-mt-2 tw-mb-4 tw-flex tw-items-center'>
|
||||
|
||||
{status && <div className="tw-mt-1.5">
|
||||
<span className="tw-text-sm tw-text-current tw-bg-base-300 tw-rounded tw-py-0.5 tw-px-2 tw-inline-flex tw-items-center tw-mr-2"><span className={`tw-w-2 tw-h-2 ${status == 'in_planning' && 'tw-bg-blue-700'} ${status == 'paused' && 'tw-bg-orange-400'} ${status == 'active' && 'tw-bg-green-500'} tw-rounded-full tw-mr-1.5`}></span>{statusMapping[status]}</span>
|
||||
<span className="tw-text-sm tw-text-current tw-bg-base-300 tw-rounded tw-py-0.5 tw-px-2 tw-inline-flex tw-items-center tw-mr-2"><span className={`tw-w-2 tw-h-2 ${status === 'in_planning' && 'tw-bg-blue-700'} ${status === 'paused' && 'tw-bg-orange-400'} ${status === 'active' && 'tw-bg-green-500'} tw-rounded-full tw-mr-1.5`}></span>{statusMapping[status]}</span>
|
||||
</div>}
|
||||
{type && <div className="tw-mt-1.5">
|
||||
<span className="tw-text-sm tw-text-current tw-bg-base-300 tw-rounded tw-py-1 tw-px-2">{type}</span>
|
||||
|
||||
@ -6,7 +6,7 @@ import { useEffect, useState } from 'react'
|
||||
import { useItems } from '../../Map/hooks/useItems'
|
||||
|
||||
export const OnepagerView = ({ item, userType }:{item: Item, userType: string}) => {
|
||||
const [profile_owner, setProfileOwner] = useState<Item>()
|
||||
const [profileOwner, setProfileOwner] = useState<Item>()
|
||||
const items = useItems()
|
||||
|
||||
useEffect(() => {
|
||||
@ -34,7 +34,7 @@ export const OnepagerView = ({ item, userType }:{item: Item, userType: string})
|
||||
/>
|
||||
</div>
|
||||
{item.user_created.first_name && (
|
||||
<ContactInfo link={`/item/${profile_owner?.id}`} name={profile_owner?.name ? profile_owner.name : item.user_created.first_name} avatar={profile_owner?.image ? profile_owner.image : item.user_created.avatar} email={item.contact} telephone={item.telephone} />
|
||||
<ContactInfo link={`/item/${profileOwner?.id}`} name={profileOwner?.name ? profileOwner.name : item.user_created.first_name} avatar={profileOwner?.image ? profileOwner.image : item.user_created.avatar} email={item.contact} telephone={item.telephone} />
|
||||
)}
|
||||
|
||||
{/* Description Section */}
|
||||
|
||||
@ -35,7 +35,7 @@ export const TabsForm = ({ item, state, setState, updatePermission, linkItem, un
|
||||
|
||||
return (
|
||||
<div role="tablist" className="tw-tabs tw-tabs-lifted tw-mt-3">
|
||||
<input type="radio" name="my_tabs_2" role="tab" className={'tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]'} aria-label="Info" checked={activeTab == 1 && true} onChange={() => updateActiveTab(1)} />
|
||||
<input type="radio" name="my_tabs_2" role="tab" className={'tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]'} aria-label="Info" checked={activeTab === 1 && true} onChange={() => updateActiveTab(1)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-border-[var(--fallback-bc,oklch(var(--bc)/0.2))] tw-rounded-box tw-h-[calc(100dvh-332px)] tw-min-h-56 tw-border-none">
|
||||
<div className={`tw-flex tw-flex-col tw-h-full ${item.layer.itemType.show_start_end_input && 'tw-pt-4'}`}>
|
||||
{item.layer.itemType.show_start_end_input &&
|
||||
@ -76,7 +76,7 @@ export const TabsForm = ({ item, state, setState, updatePermission, linkItem, un
|
||||
</div>
|
||||
{item.layer?.itemType.offers_and_needs &&
|
||||
<>
|
||||
<input type="radio" name="my_tabs_2" role="tab" className={'tw-tab tw-min-w-[10em] [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]'} aria-label="Offers & Needs" checked={activeTab == 3 && true} onChange={() => updateActiveTab(3)} />
|
||||
<input type="radio" name="my_tabs_2" role="tab" className={'tw-tab tw-min-w-[10em] [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]'} aria-label="Offers & Needs" checked={activeTab === 3 && true} onChange={() => updateActiveTab(3)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-border-[var(--fallback-bc,oklch(var(--bc)/0.2))] tw-rounded-box tw-h-[calc(100dvh-332px)] tw-min-h-56 tw-border-none">
|
||||
<div className='tw-h-full'>
|
||||
<div className='tw-w-full tw-h-[calc(50%-0.75em)] tw-mb-4'>
|
||||
@ -97,7 +97,7 @@ export const TabsForm = ({ item, state, setState, updatePermission, linkItem, un
|
||||
}
|
||||
{item.layer?.itemType.relations &&
|
||||
<>
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Relations" checked={activeTab == 7 && true} onChange={() => updateActiveTab(7)} />
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Relations" checked={activeTab === 7 && true} onChange={() => updateActiveTab(7)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-332px)] tw-overflow-y-auto tw-pt-4 tw-pb-1 -tw-mx-4 tw-overflow-x-hidden fade">
|
||||
<div className='tw-h-full'>
|
||||
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-1 lg:tw-grid-cols-1 xl:tw-grid-cols-1 2xl:tw-grid-cols-2 tw-mb-4'>
|
||||
|
||||
@ -56,7 +56,7 @@ export const TabsView = ({ attestations, userType, item, offers, needs, relation
|
||||
<div role="tablist" className="tw-tabs tw-tabs-lifted tw-mt-2 tw-mb-2 tw-px-6">
|
||||
<input type="radio" name="my_tabs_2" role="tab"
|
||||
className={'tw-tab tw-font-bold !tw-ps-2 !tw-pe-2 [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]'}
|
||||
aria-label={`${item.layer?.itemType.icon_as_labels && activeTab != 1 ? '📝' : '📝\u00A0Info'}`} checked={activeTab == 1 && true}
|
||||
aria-label={`${item.layer?.itemType.icon_as_labels && activeTab !== 1 ? '📝' : '📝\u00A0Info'}`} checked={activeTab === 1 && true}
|
||||
onChange={() => updateActiveTab(1)} />
|
||||
<div role="tabpanel"
|
||||
className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto fade tw-pt-2 tw-pb-4 tw-mb-4 tw-overflow-x-hidden">
|
||||
@ -71,14 +71,14 @@ export const TabsView = ({ attestations, userType, item, offers, needs, relation
|
||||
<>
|
||||
<input type="radio" name="my_tabs_2" role="tab"
|
||||
className={'tw-tab tw-font-bold !tw-ps-2 !tw-pe-2 [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]'}
|
||||
aria-label={`${item.layer?.itemType.icon_as_labels && activeTab != 2 ? '❤️' : '❤️\u00A0Credibility'}`} checked={activeTab == 2 && true}
|
||||
aria-label={`${item.layer?.itemType.icon_as_labels && activeTab !== 2 ? '❤️' : '❤️\u00A0Credibility'}`} checked={activeTab === 2 && true}
|
||||
onChange={() => updateActiveTab(2)} />
|
||||
<div role="tabpanel"
|
||||
className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto fade tw-pt-2 tw-pb-4 tw-mb-4 tw-overflow-x-hidden">
|
||||
<table className="sm:tw-table-sm md:tw-table-md">
|
||||
<tbody>
|
||||
{attestations
|
||||
.filter(a => a.to.some(t => t.directus_users_id == item.user_created.id))
|
||||
.filter(a => a.to.some(t => t.directus_users_id === item.user_created.id))
|
||||
.sort((a, b) => new Date(b.date_created).getTime() - new Date(a.date_created).getTime())
|
||||
.map((a, i) => (
|
||||
<tr key={i}>
|
||||
@ -120,7 +120,7 @@ export const TabsView = ({ attestations, userType, item, offers, needs, relation
|
||||
|
||||
<>
|
||||
|
||||
<input type="radio" name="my_tabs_2" role="tab" className={`tw-tab tw-font-bold !tw-ps-2 !tw-pe-2 ${!(item.layer?.itemType.icon_as_labels && activeTab != 3) && 'tw-min-w-[10.4em]'} [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]`} aria-label={`${item.layer?.itemType.icon_as_labels && activeTab != 3 ? '♻️' : '♻️\u00A0Offers & Needs'}`} checked={activeTab == 3 && true} onChange={() => updateActiveTab(3)} />
|
||||
<input type="radio" name="my_tabs_2" role="tab" className={`tw-tab tw-font-bold !tw-ps-2 !tw-pe-2 ${!(item.layer?.itemType.icon_as_labels && activeTab !== 3) && 'tw-min-w-[10.4em]'} [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]`} aria-label={`${item.layer?.itemType.icon_as_labels && activeTab !== 3 ? '♻️' : '♻️\u00A0Offers & Needs'}`} checked={activeTab === 3 && true} onChange={() => updateActiveTab(3)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-268px)] tw-overflow-y-auto fade tw-pt-4 tw-pb-1" >
|
||||
<div className='tw-h-full'>
|
||||
<div className='tw-grid tw-grid-cols-1'>
|
||||
@ -159,7 +159,7 @@ export const TabsView = ({ attestations, userType, item, offers, needs, relation
|
||||
|
||||
{item.layer?.itemType.relations &&
|
||||
<>
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab tw-font-bold !tw-ps-2 !tw-pe-2 [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label={`${item.layer?.itemType.icon_as_labels && activeTab != 7 ? '🔗' : '🔗\u00A0Relations'}`} checked={activeTab == 7 && true} onChange={() => updateActiveTab(7)} />
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab tw-font-bold !tw-ps-2 !tw-pe-2 [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label={`${item.layer?.itemType.icon_as_labels && activeTab !== 7 ? '🔗' : '🔗\u00A0Relations'}`} checked={activeTab === 7 && true} onChange={() => updateActiveTab(7)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto tw-pt-4 tw-pb-1 -tw-mr-4 -tw-mb-4 tw-overflow-x-hidden">
|
||||
<div className='tw-h-full'>
|
||||
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-1 lg:tw-grid-cols-1 xl:tw-grid-cols-1 2xl:tw-grid-cols-2 tw-pb-4'>
|
||||
|
||||
@ -20,10 +20,11 @@ export const submitNewItem = async (evt: any, type: string, item, user, setLoadi
|
||||
if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
|
||||
addTag({ id: crypto.randomUUID(), name: tag.slice(1), color: randomColor() })
|
||||
}
|
||||
return null
|
||||
})
|
||||
const uuid = crypto.randomUUID()
|
||||
|
||||
const layer = layers.find(l => l.name.toLocaleLowerCase().replace('s', '') == addItemPopupType.toLocaleLowerCase())
|
||||
const layer = layers.find(l => l.name.toLocaleLowerCase().replace('s', '') === addItemPopupType.toLocaleLowerCase())
|
||||
|
||||
let success = false
|
||||
try {
|
||||
@ -43,9 +44,9 @@ export const submitNewItem = async (evt: any, type: string, item, user, setLoadi
|
||||
}
|
||||
|
||||
export const linkItem = async (id: string, item, updateItem) => {
|
||||
const new_relations = item.relations || []
|
||||
new_relations?.push({ items_id: item.id, related_items_id: id })
|
||||
const updatedItem = { id: item.id, relations: new_relations }
|
||||
const newRelations = item.relations || []
|
||||
newRelations?.push({ items_id: item.id, related_items_id: id })
|
||||
const updatedItem = { id: item.id, relations: newRelations }
|
||||
|
||||
let success = false
|
||||
try {
|
||||
@ -55,14 +56,14 @@ export const linkItem = async (id: string, item, updateItem) => {
|
||||
toast.error(error.toString())
|
||||
}
|
||||
if (success) {
|
||||
updateItem({ ...item, relations: new_relations })
|
||||
updateItem({ ...item, relations: newRelations })
|
||||
toast.success('Item linked')
|
||||
}
|
||||
}
|
||||
|
||||
export const unlinkItem = async (id: string, item, updateItem) => {
|
||||
const new_relations = item.relations?.filter(r => r.related_items_id !== id)
|
||||
const updatedItem = { id: item.id, relations: new_relations }
|
||||
const newRelations = item.relations?.filter(r => r.related_items_id !== id)
|
||||
const updatedItem = { id: item.id, relations: newRelations }
|
||||
|
||||
let success = false
|
||||
try {
|
||||
@ -72,7 +73,7 @@ export const unlinkItem = async (id: string, item, updateItem) => {
|
||||
toast.error(error.toString())
|
||||
}
|
||||
if (success) {
|
||||
updateItem({ ...item, relations: new_relations })
|
||||
updateItem({ ...item, relations: newRelations })
|
||||
toast.success('Item unlinked')
|
||||
}
|
||||
}
|
||||
@ -101,22 +102,24 @@ export const handleDelete = async (event: React.MouseEvent<HTMLElement>, item, s
|
||||
export const onUpdateItem = async (state, item, tags, addTag, setLoading, navigate, updateItem, addItem, user, params) => {
|
||||
let changedItem = {} as Item
|
||||
|
||||
const offer_updates: Array<any> = []
|
||||
const offerUpdates: Array<any> = []
|
||||
// check for new offers
|
||||
await state.offers?.map(o => {
|
||||
const existingOffer = item?.offers?.find(t => t.tags_id === o.id)
|
||||
existingOffer && offer_updates.push(existingOffer.id)
|
||||
existingOffer && offerUpdates.push(existingOffer.id)
|
||||
if (!existingOffer && !tags.some(t => t.id === o.id)) addTag({ ...o, offer_or_need: true })
|
||||
!existingOffer && offer_updates.push({ items_id: item?.id, tags_id: o.id })
|
||||
!existingOffer && offerUpdates.push({ items_id: item?.id, tags_id: o.id })
|
||||
return null
|
||||
})
|
||||
|
||||
const needs_updates: Array<any> = []
|
||||
const needsUpdates: Array<any> = []
|
||||
|
||||
await state.needs?.map(n => {
|
||||
const existingNeed = item?.needs?.find(t => t.tags_id === n.id)
|
||||
existingNeed && needs_updates.push(existingNeed.id)
|
||||
!existingNeed && needs_updates.push({ items_id: item?.id, tags_id: n.id })
|
||||
existingNeed && needsUpdates.push(existingNeed.id)
|
||||
!existingNeed && needsUpdates.push({ items_id: item?.id, tags_id: n.id })
|
||||
!existingNeed && !tags.some(t => t.id === n.id) && addTag({ ...n, offer_or_need: true })
|
||||
return null
|
||||
})
|
||||
|
||||
// update profile item in current state
|
||||
@ -136,22 +139,24 @@ export const onUpdateItem = async (state, item, tags, addTag, setLoading, naviga
|
||||
...state.markerIcon && { markerIcon: state.markerIcon },
|
||||
next_appointment: state.nextAppointment,
|
||||
...state.image.length > 10 && { image: state.image },
|
||||
...state.offers.length > 0 && { offers: offer_updates },
|
||||
...state.needs.length > 0 && { needs: needs_updates }
|
||||
...state.offers.length > 0 && { offers: offerUpdates },
|
||||
...state.needs.length > 0 && { needs: needsUpdates }
|
||||
}
|
||||
|
||||
const offers_state: Array<any> = []
|
||||
const needs_state: Array<any> = []
|
||||
const offersState: Array<any> = []
|
||||
const needsState: Array<any> = []
|
||||
|
||||
state.offers.map(o => {
|
||||
offers_state.push({ items_id: item?.id, tags_id: o.id })
|
||||
offersState.push({ items_id: item?.id, tags_id: o.id })
|
||||
return null
|
||||
})
|
||||
|
||||
state.needs.map(n => {
|
||||
needs_state.push({ items_id: item?.id, tags_id: n.id })
|
||||
needsState.push({ items_id: item?.id, tags_id: n.id })
|
||||
return null
|
||||
})
|
||||
|
||||
changedItem = { ...changedItem, offers: offers_state, needs: needs_state }
|
||||
changedItem = { ...changedItem, offers: offersState, needs: needsState }
|
||||
|
||||
setLoading(true)
|
||||
|
||||
@ -159,6 +164,7 @@ export const onUpdateItem = async (state, item, tags, addTag, setLoading, naviga
|
||||
if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
|
||||
addTag({ id: crypto.randomUUID(), name: encodeTag(tag.slice(1).toLocaleLowerCase()), color: randomColor() })
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
// take care that addTag request comes before item request
|
||||
|
||||
@ -16,8 +16,8 @@ export const AttestationForm = ({ api }:{api?:ItemsApi<any>}) => {
|
||||
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(location.search)
|
||||
const to_user_ids = params.get('to')
|
||||
setUsers(items.filter(i => to_user_ids?.includes(i.id)))
|
||||
const toUserIds = params.get('to')
|
||||
setUsers(items.filter(i => toUserIds?.includes(i.id)))
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [items, location])
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ export const DateUserInfo = ({ item }: { item: Item }) => {
|
||||
|
||||
{
|
||||
infoExpanded
|
||||
? <p className={'tw-italic tw-min-h-[21px] !tw-my-0 tw-text-gray-500'} onClick={() => setInfoExpanded(false)} >{`${item.date_updated && item.date_updated != item.date_created ? 'updated' : 'posted'} ${item && item.user_created && item.user_created.first_name ? `by ${item.user_created.first_name}` : ''} ${item.date_updated ? timeAgo(item.date_updated) : timeAgo(item.date_created!)}`}</p>
|
||||
? <p className={'tw-italic tw-min-h-[21px] !tw-my-0 tw-text-gray-500'} onClick={() => setInfoExpanded(false)} >{`${item.date_updated && item.date_updated !== item.date_created ? 'updated' : 'posted'} ${item && item.user_created && item.user_created.first_name ? `by ${item.user_created.first_name}` : ''} ${item.date_updated ? timeAgo(item.date_updated) : timeAgo(item.date_created!)}`}</p>
|
||||
: <p className="!tw-my-0 tw-min-h-[21px] tw-font-bold tw-cursor-pointer tw-text-gray-500" onClick={() => setInfoExpanded(true)}>ⓘ</p>
|
||||
}
|
||||
<div className='tw-grow '></div>
|
||||
|
||||
@ -39,7 +39,7 @@ export const EmojiPicker = ({ selectedEmoji, selectedColor, selectedShape, setSe
|
||||
<>
|
||||
<div
|
||||
onClick={toggleDropdown}
|
||||
className={`tw-cursor-pointer ${selectedEmoji == 'select badge' ? 'tw-text-sm !tw-p-9 tw-text-center ' : 'tw-text-6xl'} tw-mask tw-mask-${selectedShape} tw-p-6 tw-bg-[${selectedColor}]`}
|
||||
className={`tw-cursor-pointer ${selectedEmoji === 'select badge' ? 'tw-text-sm !tw-p-9 tw-text-center ' : 'tw-text-6xl'} tw-mask tw-mask-${selectedShape} tw-p-6 tw-bg-[${selectedColor}]`}
|
||||
>
|
||||
{selectedEmoji}
|
||||
</div>
|
||||
@ -51,7 +51,7 @@ export const EmojiPicker = ({ selectedEmoji, selectedColor, selectedShape, setSe
|
||||
<button
|
||||
key={emoji}
|
||||
onClick={() => selectEmoji(emoji)}
|
||||
className={`tw-cursor-pointer tw-text-2xl tw-p-2 hover:tw-bg-base-200 tw-rounded-md ${emoji == selectedEmoji && 'tw-bg-base-300'}`}
|
||||
className={`tw-cursor-pointer tw-text-2xl tw-p-2 hover:tw-bg-base-200 tw-rounded-md ${emoji === selectedEmoji && 'tw-bg-base-300'}`}
|
||||
>
|
||||
{emoji}
|
||||
</button>
|
||||
@ -62,7 +62,7 @@ export const EmojiPicker = ({ selectedEmoji, selectedColor, selectedShape, setSe
|
||||
{shapes.map(shape => (
|
||||
<div
|
||||
key={shape}
|
||||
className={`tw-cursor-pointer hover:tw-bg-base-200 tw-rounded-md tw-p-2 ${shape == selectedShape && 'tw-bg-base-300'}`}
|
||||
className={`tw-cursor-pointer hover:tw-bg-base-200 tw-rounded-md tw-p-2 ${shape === selectedShape && 'tw-bg-base-300'}`}
|
||||
onClick={() => selectShape(shape)}>
|
||||
<div className={`tw-h-12 tw-mask tw-mask-${shape} tw-bg-neutral-content`}></div>
|
||||
</div>
|
||||
@ -73,7 +73,7 @@ export const EmojiPicker = ({ selectedEmoji, selectedColor, selectedShape, setSe
|
||||
{colors.map(color => (
|
||||
<div
|
||||
key={color}
|
||||
className={`tw-cursor-pointer hover:tw-bg-base-200 tw-rounded-md tw-p-2 tw-flex tw-justify-center tw-items-center ${color == selectedColor && 'tw-bg-base-300'}`}
|
||||
className={`tw-cursor-pointer hover:tw-bg-base-200 tw-rounded-md tw-p-2 tw-flex tw-justify-center tw-items-center ${color === selectedColor && 'tw-bg-base-300'}`}
|
||||
onClick={() => selectColor(color)}>
|
||||
<div className={`tw-h-8 tw-w-8 tw-rounded-full tw-bg-[${color}]`}></div>
|
||||
</div>
|
||||
|
||||
@ -38,11 +38,14 @@ export const MarketView = () => {
|
||||
i?.layer?.itemOffersField && getValue(i, i.layer.itemOffersField)?.map(o => {
|
||||
const tag = tags.find(t => t.id === o.tags_id)
|
||||
tag && setOffers(current => [...current, tag])
|
||||
return null
|
||||
})
|
||||
i?.layer?.itemNeedsField && getValue(i, i.layer.itemNeedsField)?.map(n => {
|
||||
const tag = tags.find(t => t.id === n.tags_id)
|
||||
tag && setNeeds(current => [...current, tag])
|
||||
return null
|
||||
})
|
||||
return null
|
||||
})
|
||||
console.log(offers)
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ export const OverlayItemsIndexPage = ({ url, layerName, parameterField, plusButt
|
||||
const filterTags = useFilterTags()
|
||||
const getItemTags = useGetItemTags()
|
||||
|
||||
const layer = layers.find(l => l.name == layerName)
|
||||
const layer = layers.find(l => l.name === layerName)
|
||||
|
||||
const submitNewItem = async (evt: any) => {
|
||||
evt.preventDefault()
|
||||
@ -61,6 +61,7 @@ export const OverlayItemsIndexPage = ({ url, layerName, parameterField, plusButt
|
||||
if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
|
||||
addTag({ id: crypto.randomUUID(), name: tag.slice(1), color: randomColor() })
|
||||
}
|
||||
return null
|
||||
})
|
||||
const uuid = crypto.randomUUID()
|
||||
let success = false
|
||||
@ -109,7 +110,7 @@ export const OverlayItemsIndexPage = ({ url, layerName, parameterField, plusButt
|
||||
{
|
||||
items?.filter(i => i.layer?.name === layerName)
|
||||
.filter(item =>
|
||||
filterTags.length == 0 ? item : filterTags.some(tag => getItemTags(item).some(filterTag => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))
|
||||
filterTags.length === 0 ? item : filterTags.some(tag => getItemTags(item).some(filterTag => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))
|
||||
?.sort((a, b) => {
|
||||
// Convert date_created to milliseconds, handle undefined by converting to lowest possible date (0 milliseconds)
|
||||
const dateA = a.date_updated ? new Date(a.date_updated).getTime() : a.date_created ? new Date(a.date_created).getTime() : 0
|
||||
@ -122,7 +123,7 @@ export const OverlayItemsIndexPage = ({ url, layerName, parameterField, plusButt
|
||||
</div>
|
||||
))
|
||||
}
|
||||
{addItemPopupType == 'place' && (
|
||||
{addItemPopupType === 'place' && (
|
||||
<form ref={tabRef} autoComplete='off' onSubmit={e => submitNewItem(e)}>
|
||||
<div className='tw-cursor-pointer tw-break-inside-avoid tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-p-6 tw-mb-10'>
|
||||
<label className="tw-btn tw-btn-sm tw-rounded-2xl tw-btn-circle tw-btn-ghost hover:tw-bg-transparent tw-absolute tw-right-0 tw-top-0 tw-text-gray-600" onClick={() => setAddItemPopupType('')}>
|
||||
|
||||
@ -6,7 +6,7 @@ import { Link } from 'react-router-dom'
|
||||
|
||||
export const SelectUser = ({ userType }: { userType: string }) => {
|
||||
const items = useItems()
|
||||
const users = items.filter(i => i.layer?.itemType.name == userType)
|
||||
const users = items.filter(i => i.layer?.itemType.name === userType)
|
||||
const assetsApi = useAssetApi()
|
||||
|
||||
const [selectedUsers, setSelectedUsers] = useState<Array<string>>([])
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
export function decodeTag (string : string) {
|
||||
let formatedTag = string.replace(/_/g, '\u00A0')
|
||||
return formatedTag = formatedTag.charAt(0).toUpperCase() + formatedTag.slice(1)
|
||||
const formatedTag = string.replace(/_/g, '\u00A0')
|
||||
return formatedTag.charAt(0).toUpperCase() + formatedTag.slice(1)
|
||||
}
|
||||
|
||||
export function encodeTag (string : string) {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
export const randomColor = () => {
|
||||
return hsvToHex((Math.random() + golden_ratio_conjugate) % 1, 0.8, 0.7)
|
||||
}
|
||||
const goldenRatioConjugate = 0.618033988749895
|
||||
|
||||
const golden_ratio_conjugate = 0.618033988749895
|
||||
export const randomColor = () => {
|
||||
return hsvToHex((Math.random() + goldenRatioConjugate) % 1, 0.8, 0.7)
|
||||
}
|
||||
|
||||
function hsvToHex (h, s, v) {
|
||||
let r, g, b
|
||||
|
||||
103
src/types.ts
103
src/types.ts
@ -3,6 +3,13 @@
|
||||
import * as React from 'react'
|
||||
import { ItemFormPopupProps } from './Components/Map/Subcomponents/ItemFormPopup'
|
||||
|
||||
export interface Tag {
|
||||
color: string;
|
||||
id: string;
|
||||
name: string;
|
||||
offer_or_need?: boolean
|
||||
}
|
||||
|
||||
export interface UtopiaMapProps {
|
||||
height?: string,
|
||||
width?: string,
|
||||
@ -17,8 +24,24 @@ export interface UtopiaMapProps {
|
||||
infoText? : string
|
||||
}
|
||||
|
||||
export interface ItemType {
|
||||
name: string;
|
||||
[key: string]: any;
|
||||
|
||||
}
|
||||
|
||||
export interface ItemsApi<T> {
|
||||
getItems(): Promise<any>,
|
||||
getItem?(id: string): Promise<any>,
|
||||
createItem?(item : T): Promise<any>,
|
||||
updateItem?(item : T): Promise<any>,
|
||||
deleteItem?(id : string): Promise<any>,
|
||||
collectionName?: string
|
||||
}
|
||||
|
||||
export interface LayerProps {
|
||||
id?: string,
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
data?: Item[],
|
||||
children?: React.ReactNode,
|
||||
name: string,
|
||||
@ -53,10 +76,18 @@ export interface LayerProps {
|
||||
clusterRef?: any
|
||||
}
|
||||
|
||||
export interface ItemType {
|
||||
name: string;
|
||||
[key: string]: any;
|
||||
export class Geometry {
|
||||
type: string
|
||||
coordinates: number[]
|
||||
constructor (lng: number, lat: number) {
|
||||
this.coordinates = [lng, lat]
|
||||
this.type = 'Point'
|
||||
}
|
||||
}
|
||||
|
||||
export type Relation = {
|
||||
related_items_id: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export class Item {
|
||||
@ -87,45 +118,18 @@ export class Item {
|
||||
}
|
||||
}
|
||||
|
||||
export class Geometry {
|
||||
type: string
|
||||
coordinates: number[]
|
||||
constructor (lng: number, lat: number) {
|
||||
this.coordinates = [lng, lat]
|
||||
this.type = 'Point'
|
||||
}
|
||||
}
|
||||
|
||||
export interface Tag {
|
||||
color: string;
|
||||
id: string;
|
||||
name: string;
|
||||
offer_or_need?: boolean
|
||||
}
|
||||
|
||||
export interface ItemsApi<T> {
|
||||
getItems(): Promise<any>,
|
||||
getItem?(id: string): Promise<any>,
|
||||
createItem?(item : T): Promise<any>,
|
||||
updateItem?(item : T): Promise<any>,
|
||||
deleteItem?(id : string): Promise<any>,
|
||||
collectionName?: string
|
||||
}
|
||||
|
||||
export interface AssetsApi {
|
||||
upload(file: Blob, title: string): any,
|
||||
url: string
|
||||
}
|
||||
|
||||
export interface UserApi {
|
||||
register(email: string, password: string, userName: string): Promise<void>,
|
||||
login(email: string, password: string): Promise<any>,
|
||||
logout(): Promise<void>,
|
||||
getUser(): Promise<UserItem>,
|
||||
getToken(): Promise<any>,
|
||||
updateUser(user: UserItem): Promise<void>,
|
||||
requestPasswordReset(email:string, reset_url?:string),
|
||||
passwordReset(token:string, new_password:string)
|
||||
export type Profile = {
|
||||
id?: string;
|
||||
avatar?: string;
|
||||
color?: string;
|
||||
name: string;
|
||||
text: string;
|
||||
geoposition?: Geometry
|
||||
}
|
||||
|
||||
export type UserItem = {
|
||||
@ -138,13 +142,15 @@ export type UserItem = {
|
||||
|
||||
}
|
||||
|
||||
export type Profile = {
|
||||
id?: string;
|
||||
avatar?: string;
|
||||
color?: string;
|
||||
name: string;
|
||||
text: string;
|
||||
geoposition?: Geometry
|
||||
export interface UserApi {
|
||||
register(email: string, password: string, userName: string): Promise<void>,
|
||||
login(email: string, password: string): Promise<any>,
|
||||
logout(): Promise<void>,
|
||||
getUser(): Promise<UserItem>,
|
||||
getToken(): Promise<any>,
|
||||
updateUser(user: UserItem): Promise<void>,
|
||||
requestPasswordReset(email:string, reset_url?:string),
|
||||
passwordReset(token:string, new_password:string)
|
||||
}
|
||||
|
||||
export type PermissionCondition = {
|
||||
@ -156,6 +162,8 @@ export type PermissionCondition = {
|
||||
};
|
||||
};
|
||||
|
||||
export type PermissionAction = 'create'|'read'|'update'|'delete';
|
||||
|
||||
export type Permission = {
|
||||
id?: string;
|
||||
role: string;
|
||||
@ -165,10 +173,3 @@ export type Permission = {
|
||||
_and: PermissionCondition[];
|
||||
};
|
||||
};
|
||||
|
||||
export type PermissionAction = 'create'|'read'|'update'|'delete';
|
||||
|
||||
export type Relation = {
|
||||
related_items_id: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user