mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
reimplemented user profiles
This commit is contained in:
parent
7f711a5133
commit
4185258568
@ -2,13 +2,30 @@ import { useAuth } from "../Auth"
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import QuestionMarkIcon from '@heroicons/react/24/outline/QuestionMarkCircleIcon'
|
import QuestionMarkIcon from '@heroicons/react/24/outline/QuestionMarkCircleIcon'
|
||||||
import * as React from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { useItems } from "../Map/hooks/useItems";
|
||||||
|
import { Item } from "../../types";
|
||||||
|
|
||||||
|
|
||||||
export default function NavBar({ appName, nameWidth = 200}: { appName: string, nameWidth?: number }) {
|
export default function NavBar({ appName, nameWidth = 200}: { appName: string, nameWidth?: number }) {
|
||||||
|
|
||||||
|
|
||||||
const { isAuthenticated, user, logout, token } = useAuth();
|
const { isAuthenticated, user, logout } = useAuth();
|
||||||
|
|
||||||
|
const [userProfile, setUserProfile] = useState<Item>({}as Item);
|
||||||
|
const items = useItems();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const profile = user && items.find(i => i.user_created.id === user.id && i.type === "user");
|
||||||
|
profile ? setUserProfile(profile) : setUserProfile({id: crypto.randomUUID(), name: user?.first_name, text: ""});
|
||||||
|
|
||||||
|
}, [user, items])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
}, [userProfile])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const onLogout = () => {
|
const onLogout = () => {
|
||||||
toast.promise(
|
toast.promise(
|
||||||
@ -51,9 +68,9 @@ export default function NavBar({ appName, nameWidth = 200}: { appName: string, n
|
|||||||
|
|
||||||
{isAuthenticated ?
|
{isAuthenticated ?
|
||||||
<div className="tw-flex-none">
|
<div className="tw-flex-none">
|
||||||
{user?.avatar ? <div className="tw-avatar">
|
{ userProfile?.image? <div className="tw-avatar">
|
||||||
<div className="tw-w-10 tw-rounded-full">
|
<div className="tw-w-10 tw-rounded-full">
|
||||||
<img src={"https://api.utopia-lab.org/assets/" + user?.avatar + "?access_token=" + token} />
|
<img src={"https://api.utopia-lab.org/assets/" + userProfile.image} />
|
||||||
</div>
|
</div>
|
||||||
</div> : <></>}
|
</div> : <></>}
|
||||||
<div className='tw-ml-2 tw-mr-2'>{user?.first_name}</div>
|
<div className='tw-ml-2 tw-mr-2'>{user?.first_name}</div>
|
||||||
@ -64,7 +81,7 @@ export default function NavBar({ appName, nameWidth = 200}: { appName: string, n
|
|||||||
</svg>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
<ul tabIndex={0} className="tw-menu tw-menu-compact tw-dropdown-content tw-mt-3 tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box tw-w-52 !tw-z-[10000]">
|
<ul tabIndex={0} className="tw-menu tw-menu-compact tw-dropdown-content tw-mt-3 tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box tw-w-52 !tw-z-[10000]">
|
||||||
<li><Link to={"/profile-settings"}>Profile</Link></li>
|
<li><Link to={`${userProfile.id && "/edit-item/"+userProfile.id}`}>Profile</Link></li>
|
||||||
<li><Link to={"/user-settings"}>Settings</Link></li>
|
<li><Link to={"/user-settings"}>Settings</Link></li>
|
||||||
<li><a onClick={() => { onLogout() }}>Logout</a></li>
|
<li><a onClick={() => { onLogout() }}>Logout</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@ -64,7 +64,6 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(props.item) {
|
if(props.item) {
|
||||||
let success = false;
|
let success = false;
|
||||||
try {
|
try {
|
||||||
@ -74,6 +73,8 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
|
|||||||
toast.error(error.toString());
|
toast.error(error.toString());
|
||||||
}
|
}
|
||||||
if(success) {
|
if(success) {
|
||||||
|
console.log(props.item);
|
||||||
|
|
||||||
updateItem({...props.item, ...formItem});
|
updateItem({...props.item, ...formItem});
|
||||||
toast.success("Item updated");
|
toast.success("Item updated");
|
||||||
}
|
}
|
||||||
@ -81,10 +82,12 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
|
|||||||
map.closePopup();
|
map.closePopup();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
const item = items.find(i => i.user_created.id === user?.id && i.type === props.layer.itemType)
|
||||||
const uuid = crypto.randomUUID();
|
const uuid = crypto.randomUUID();
|
||||||
let success = false;
|
let success = false;
|
||||||
try {
|
try {
|
||||||
await props.layer.api?.createItem!({...formItem, id: uuid });
|
props.layer.onlyOnePerOwner && item && await props.layer.api?.updateItem!({...formItem, id: item?.id });
|
||||||
|
(!props.layer.onlyOnePerOwner || !item) && await props.layer.api?.createItem!({...formItem, id: uuid, name: formItem.name ? formItem.name : user?.first_name });
|
||||||
success = true;
|
success = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.error(error.toString());
|
toast.error(error.toString());
|
||||||
@ -92,11 +95,8 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
|
|||||||
if(success) {
|
if(success) {
|
||||||
console.log(props.layer);
|
console.log(props.layer);
|
||||||
|
|
||||||
if(props.layer.onlyOnePerOwner){
|
props.layer.onlyOnePerOwner && item && updateItem({...item, ...formItem});
|
||||||
const item = items.find(item => item.layer == props.layer && item.user_created?.id == user?.id);
|
(!props.layer.onlyOnePerOwner || !item) && addItem({...formItem, name: formItem.name ? formItem.name : user?.first_name , user_created: user, type: props.layer.itemType, id: uuid, layer: props.layer});
|
||||||
item && removeItem(item);
|
|
||||||
}
|
|
||||||
addItem({...formItem, id: uuid, layer: props.layer, user_created: user, type: props.layer.itemType });
|
|
||||||
toast.success("New item created");
|
toast.success("New item created");
|
||||||
resetFilterTags();
|
resetFilterTags();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,7 +80,7 @@ export function HeaderView({ item, api, editCallback, deleteCallback, setPositio
|
|||||||
</label>
|
</label>
|
||||||
<ul tabIndex={0} className="tw-dropdown-content tw-menu tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box tw-z-1000">
|
<ul tabIndex={0} className="tw-dropdown-content tw-menu tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box tw-z-1000">
|
||||||
{((api?.updateItem && hasUserPermission(api.collectionName!, "update", item)) || item.layer?.customEditLink) && editCallback && <li>
|
{((api?.updateItem && hasUserPermission(api.collectionName!, "update", item)) || item.layer?.customEditLink) && editCallback && <li>
|
||||||
<a className="!tw-text-base-content tw-cursor-pointer" onClick={(e) => item.layer?.customEditLink ? navigate(`${item.layer.customEditLink}/${item.layer.customEditParameter && getValue(item, item.layer.customEditParameter)}`) : editCallback(e)}>
|
<a className="!tw-text-base-content tw-cursor-pointer" onClick={(e) => item.layer?.customEditLink ? navigate(`${item.layer.customEditLink}${item.layer.customEditParameter ? "/"+getValue(item, item.layer.customEditParameter): ""} `) : editCallback(e)}>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||||
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
|
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { timeAgo } from '../../../Utils/TimeAgo'
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { LatLng } from 'leaflet'
|
import { LatLng } from 'leaflet'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { useRemoveItem } from '../hooks/useItems'
|
import { useRemoveItem, useUpdateItem } from '../hooks/useItems'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { useSetSelectPosition } from '../hooks/useSelectPosition'
|
import { useSetSelectPosition } from '../hooks/useSelectPosition'
|
||||||
|
|
||||||
@ -26,6 +26,7 @@ export const ItemViewPopup = React.forwardRef((props: ItemViewPopupProps, ref: a
|
|||||||
const map = useMap();
|
const map = useMap();
|
||||||
const [loading, setLoading] = React.useState<boolean>(false);
|
const [loading, setLoading] = React.useState<boolean>(false);
|
||||||
const removeItem = useRemoveItem();
|
const removeItem = useRemoveItem();
|
||||||
|
const updadateItem = useUpdateItem();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const setSelectPosition = useSetSelectPosition();
|
const setSelectPosition = useSetSelectPosition();
|
||||||
|
|
||||||
@ -43,13 +44,15 @@ export const ItemViewPopup = React.forwardRef((props: ItemViewPopupProps, ref: a
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
let success = false;
|
let success = false;
|
||||||
try {
|
try {
|
||||||
await props.item.layer?.api?.deleteItem!(props.item.id)
|
!props.item.layer?.onlyOnePerOwner && await props.item.layer?.api?.deleteItem!(props.item.id);
|
||||||
|
props.item.layer?.onlyOnePerOwner && await props.item.layer.api?.updateItem!({id: props.item.id, position: null})
|
||||||
success = true;
|
success = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.error(error.toString());
|
toast.error(error.toString());
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
removeItem(props.item);
|
!props.item.layer?.onlyOnePerOwner && removeItem(props.item);
|
||||||
|
props.item.layer?.onlyOnePerOwner && updadateItem({...props.item, position: undefined});
|
||||||
toast.success("Item deleted");
|
toast.success("Item deleted");
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import { HeaderView } from "../Map/Subcomponents/ItemPopupComponents/HeaderView"
|
|||||||
import { Item } from "../../types";
|
import { Item } from "../../types";
|
||||||
|
|
||||||
export function ActionButton({ item, triggerAddButton, triggerItemSelected, existingRelations, itemType, color = "#3D3846", collection = "items" }: {
|
export function ActionButton({ item, triggerAddButton, triggerItemSelected, existingRelations, itemType, color = "#3D3846", collection = "items" }: {
|
||||||
triggerAddButton: any,
|
triggerAddButton?: any,
|
||||||
triggerItemSelected: any,
|
triggerItemSelected?: any,
|
||||||
existingRelations: Item[],
|
existingRelations: Item[],
|
||||||
itemType: string;
|
itemType: string;
|
||||||
color: string,
|
color: string,
|
||||||
@ -23,21 +23,22 @@ export function ActionButton({ item, triggerAddButton, triggerItemSelected, exis
|
|||||||
const filterdItems = items.filter(i => i.type == itemType).filter(i => !existingRelations.some(s => s.id == i.id)).filter(i => i.id != item.id)
|
const filterdItems = items.filter(i => i.type == itemType).filter(i => !existingRelations.some(s => s.id == i.id)).filter(i => i.id != item.id)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>{hasUserPermission(collection, "update", item) &&
|
<>{hasUserPermission(collection, "update", item) &&
|
||||||
<>
|
<>
|
||||||
<div className="tw-absolute tw-right-4 tw-bottom-4 tw-flex tw-flex-col" >
|
<div className="tw-absolute tw-right-4 tw-bottom-4 tw-flex tw-flex-col" >
|
||||||
<button tabIndex={0} className="tw-z-500 tw-btn tw-btn-circle tw-shadow" onClick={() => { setModalOpen(true) }} style={{ backgroundColor: color, color: "#fff" }}>
|
{triggerItemSelected && <button tabIndex={0} className="tw-z-500 tw-btn tw-btn-circle tw-shadow" onClick={() => { setModalOpen(true) }} style={{ backgroundColor: color, color: "#fff" }}>
|
||||||
<svg className="tw-h-5 tw-w-5" stroke="currentColor" fill="currentColor" strokeWidth="0" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"></path></svg>
|
<svg className="tw-h-5 tw-w-5" stroke="currentColor" fill="currentColor" strokeWidth="0" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"></path></svg>
|
||||||
|
|
||||||
</button>
|
</button>}
|
||||||
<button tabIndex={0} className="tw-z-500 tw-btn tw-btn-circle tw-shadow tw-mt-2" onClick={() => { triggerAddButton() }} style={{ backgroundColor: color, color: "#fff" }}>
|
{triggerAddButton && <button tabIndex={0} className="tw-z-500 tw-btn tw-btn-circle tw-shadow tw-mt-2" onClick={() => { triggerAddButton() }} style={{ backgroundColor: color, color: "#fff" }}>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="4" stroke="currentColor" className="tw-w-5 tw-h-5">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="4" stroke="currentColor" className="tw-w-5 tw-h-5">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>}
|
||||||
</div>
|
</div>
|
||||||
<DialogModal title={"Select"} isOpened={modalOpen} onClose={() => (setModalOpen(false))}>
|
<DialogModal title={"Select"} isOpened={modalOpen} onClose={() => (setModalOpen(false))} className="!tw-max-w-2xl ">
|
||||||
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-2 lg:tw-grid-cols-2 xl:tw-grid-cols-2'>
|
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-2 lg:tw-grid-cols-2 xl:tw-grid-cols-2'>
|
||||||
{filterdItems.map(i => <div key={i.id} className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-4 tw-mb-4 tw-h-fit' onClick={() => { triggerItemSelected(i.id); setModalOpen(false) }}>
|
{filterdItems.map(i => <div key={i.id} className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-4 tw-mb-4 tw-h-fit' onClick={() => { triggerItemSelected(i.id); setModalOpen(false) }}>
|
||||||
<HeaderView item={i} hideMenu></HeaderView>
|
<HeaderView item={i} hideMenu></HeaderView>
|
||||||
|
|||||||
@ -146,7 +146,8 @@ export const AvatarWidget = ({avatar, setAvatar}:{avatar:string, setAvatar : Rea
|
|||||||
onClose={() => {
|
onClose={() => {
|
||||||
setCropModalOpen(false);
|
setCropModalOpen(false);
|
||||||
setImage("");
|
setImage("");
|
||||||
}}>
|
}}
|
||||||
|
closeOnClickOutside={false}>
|
||||||
<ReactCrop crop={crop} onChange={(c) => setCrop(c)} aspect={1} >
|
<ReactCrop crop={crop} onChange={(c) => setCrop(c)} aspect={1} >
|
||||||
<img src={image} ref={imgRef} onLoad={onImageLoad} />
|
<img src={image} ref={imgRef} onLoad={onImageLoad} />
|
||||||
</ReactCrop>
|
</ReactCrop>
|
||||||
|
|||||||
26
src/Components/Profile/ItemForm.tsx
Normal file
26
src/Components/Profile/ItemForm.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { Item } from "../../types";
|
||||||
|
import { useItems } from "../Map/hooks/useItems";
|
||||||
|
import { useLocation } from "react-router-dom";
|
||||||
|
|
||||||
|
|
||||||
|
export const OverlayItemProfileSettings = () => {
|
||||||
|
|
||||||
|
const items = useItems();
|
||||||
|
const [item, setItem] = useState<Item>({} as Item)
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const itemId = location.pathname.split("/")[2];
|
||||||
|
const item = items.find(i => i.id === itemId);
|
||||||
|
item && setItem(item);
|
||||||
|
|
||||||
|
}, [location, items])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -81,6 +81,11 @@ export function OverlayItemProfile() {
|
|||||||
|
|
||||||
}, [items,location])
|
}, [items,location])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
}, [item])
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (item) {
|
if (item) {
|
||||||
if(item.position) {
|
if(item.position) {
|
||||||
@ -307,7 +312,7 @@ export function OverlayItemProfile() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<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="Events" checked={activeTab == 3 && true} onChange={() => updateActiveTab(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="Events" 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-280px)] tw-overflow-y-auto tw-pt-4 tw-pb-1 -tw-mx-4 tw-overflow-x-hidden">
|
<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-mx-4 tw-overflow-x-hidden">
|
||||||
<div className='tw-h-full'>
|
<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'>
|
<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'>
|
||||||
{relations && relations.map(i => {
|
{relations && relations.map(i => {
|
||||||
@ -341,13 +346,31 @@ export function OverlayItemProfile() {
|
|||||||
</div>
|
</div>
|
||||||
</form> : <></>
|
</form> : <></>
|
||||||
}
|
}
|
||||||
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} itemType={"event"} triggerItemSelected={linkItem} triggerAddButton={() => { setAddItemPopupType("event"); scroll() }} color={item.color}></ActionButton>}
|
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} itemType={"event"} triggerItemSelected={linkItem} triggerAddButton={() => { setAddItemPopupType("user"); scroll() }} color={item.color}></ActionButton>}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<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="Friends" checked={activeTab == 4 && true} onChange={() => updateActiveTab(4)} />
|
<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="Community" checked={activeTab == 4 && true} onChange={() => updateActiveTab(4)} />
|
||||||
<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-1 tw-overflow-x-hidden">
|
<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-mx-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'>
|
||||||
|
{relations && relations.map(i => {
|
||||||
|
if (i.type == 'user') return (
|
||||||
|
|
||||||
|
<div key={i.id} className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-6 tw-mb-4' onClick={() => navigate('/item/' + i.id)}>
|
||||||
|
<LinkedItemsHeaderView unlinkPermission={updatePermission} item={i} unlinkCallback={unlinkItem} loading={loading} />
|
||||||
|
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
|
||||||
|
<TextView truncate item={i} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
else return null
|
||||||
|
})}
|
||||||
|
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} itemType={"user"} triggerItemSelected={linkItem} color={item.color}></ActionButton>}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,21 +1,21 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { useItems, useUpdateItem } from '../Map/hooks/useItems'
|
import { useItems, useUpdateItem, useAddItem } from '../Map/hooks/useItems'
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { getValue } from '../../Utils/GetValue';
|
import { getValue } from '../../Utils/GetValue';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { useAuth } from '../Auth';
|
import { useAuth } from '../Auth';
|
||||||
import { TextInput, TextAreaInput } from '../Input';
|
import { TextInput, TextAreaInput } from '../Input';
|
||||||
import { ColorPicker } from './ColorPicker';
|
import { ColorPicker } from './ColorPicker';
|
||||||
import DialogModal from '../Templates/DialogModal';
|
|
||||||
import { hashTagRegex } from '../../Utils/HashTagRegex';
|
import { hashTagRegex } from '../../Utils/HashTagRegex';
|
||||||
import { useAddTag, useTags } from '../Map/hooks/useTags';
|
import { useAddTag, useTags } from '../Map/hooks/useTags';
|
||||||
import { randomColor } from '../../Utils/RandomColor';
|
import { randomColor } from '../../Utils/RandomColor';
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { Geometry, Item, Tag, UserItem } from '../../types';
|
import { Item } from '../../types';
|
||||||
import { MapOverlayPage } from '../Templates';
|
import { MapOverlayPage } from '../Templates';
|
||||||
import { TagsWidget } from './TagsWidget';
|
|
||||||
import { decodeTag, encodeTag } from '../../Utils/FormatTags';
|
|
||||||
import { AvatarWidget } from './AvatarWidget';
|
import { AvatarWidget } from './AvatarWidget';
|
||||||
|
import { encodeTag } from '../../Utils/FormatTags';
|
||||||
|
import { useLayers } from '../Map/hooks/useLayers';
|
||||||
|
|
||||||
|
|
||||||
export function OverlayItemProfileSettings() {
|
export function OverlayItemProfileSettings() {
|
||||||
@ -31,34 +31,38 @@ export function OverlayItemProfileSettings() {
|
|||||||
const [activeTab, setActiveTab] = useState<number>(1);
|
const [activeTab, setActiveTab] = useState<number>(1);
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const { user } = useAuth();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updateItem = useUpdateItem();
|
const updateItem = useUpdateItem();
|
||||||
|
const addItem = useAddItem();
|
||||||
|
const layers = useLayers();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const items = useItems();
|
|
||||||
const [item, setItem] = useState<Item>({} as Item)
|
|
||||||
|
|
||||||
const tags = useTags();
|
const tags = useTags();
|
||||||
const addTag = useAddTag();
|
const addTag = useAddTag();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
|
||||||
|
const items = useItems();
|
||||||
|
const [item, setItem] = useState<Item>({} as Item)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const itemId = location.pathname.split("/")[2];
|
const itemId = location.pathname.split("/")[2];
|
||||||
const item = items.find(i => i.id === itemId);
|
const item = items.find(i => i.id === itemId);
|
||||||
item && setItem(item);
|
item && setItem(item);
|
||||||
|
!item && setItem({id: crypto.randomUUID(), name: user ? user.first_name : "", text: ""})
|
||||||
|
|
||||||
}, [location, items, activeTab])
|
}, [location, items, activeTab])
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (item.layer?.itemColorField) setColor(getValue(item, item.layer?.itemColorField));
|
if (item.layer?.itemColorField) setColor(getValue(item, item.layer?.itemColorField));
|
||||||
else setColor(item.layer?.markerDefaultColor || "#000")
|
else setColor(item.layer?.markerDefaultColor || "#3D3846")
|
||||||
|
|
||||||
setId(item?.id ? item.id : "");
|
setId(item?.id ? item.id : "");
|
||||||
setName(item?.name ? item.name : "");
|
setName(item?.name ? item.name : "");
|
||||||
|
setSubname(item?.subname ? item.subname : "");
|
||||||
setText(item?.text ? item.text : "");
|
setText(item?.text ? item.text : "");
|
||||||
setImage(item?.image ? item?.image : "");
|
setImage(item?.image ? item?.image : "");
|
||||||
}, [item])
|
}, [item])
|
||||||
@ -83,8 +87,10 @@ export function OverlayItemProfileSettings() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
console.log(item.layer);
|
||||||
|
|
||||||
item?.layer?.api?.updateItem && toast.promise(
|
|
||||||
|
if(item.layer) {item?.layer?.api?.updateItem && toast.promise(
|
||||||
item?.layer?.api?.updateItem(changedItem),
|
item?.layer?.api?.updateItem(changedItem),
|
||||||
{
|
{
|
||||||
pending: 'updating Item ...',
|
pending: 'updating Item ...',
|
||||||
@ -99,9 +105,32 @@ export function OverlayItemProfileSettings() {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
navigate("/item/"+item.id)});
|
navigate("/item/"+item.id)});
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const layer = layers.find(l => l.name == "People")
|
||||||
|
layer?.api?.createItem && toast.promise(
|
||||||
|
layer?.api?.createItem(changedItem),
|
||||||
|
{
|
||||||
|
pending: 'updating Item ...',
|
||||||
|
success: 'Item updated',
|
||||||
|
error: {
|
||||||
|
render({ data }) {
|
||||||
|
return `${data}`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(() => item && addItem({...item, ...changedItem, layer: layer, user_created: user, type: layer.itemType}))
|
||||||
|
.then(() => {
|
||||||
|
setLoading(false);
|
||||||
|
navigate("/")});
|
||||||
|
console.log({...item, ...changedItem, layer: layer, user_created: user, type: "User"});
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MapOverlayPage backdrop className='tw-mx-4 tw-mt-4 tw-mb-12 tw-overflow-x-hidden tw-max-h-[calc(100dvh-96px)] !tw-h-[calc(100dvh-96px)] tw-w-[calc(100%-32px)] md:tw-w-[calc(50%-32px)] tw-max-w-3xl !tw-left-auto tw-top-0 tw-bottom-0'>
|
<MapOverlayPage backdrop className='tw-mx-4 tw-mt-4 tw-mb-12 tw-overflow-x-hidden tw-max-h-[calc(100dvh-96px)] !tw-h-[calc(100dvh-96px)] tw-w-[calc(100%-32px)] md:tw-w-[calc(50%-32px)] tw-max-w-3xl !tw-left-auto tw-top-0 tw-bottom-0'>
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import * as React from 'react'
|
|
||||||
import { useItems, useUpdateItem } from '../Map/hooks/useItems'
|
import { useItems, useUpdateItem } from '../Map/hooks/useItems'
|
||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { getValue } from '../../Utils/GetValue';
|
import { getValue } from '../../Utils/GetValue';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { useAuth } from '../Auth';
|
import { useAuth } from '../Auth';
|
||||||
@ -13,7 +12,7 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
import { Tag, UserItem } from '../../types';
|
import { Tag, UserItem } from '../../types';
|
||||||
import { MapOverlayPage } from '../Templates';
|
import { MapOverlayPage } from '../Templates';
|
||||||
import { TagsWidget } from './TagsWidget';
|
import { TagsWidget } from './TagsWidget';
|
||||||
import { decodeTag, encodeTag } from '../../Utils/FormatTags';
|
import { encodeTag } from '../../Utils/FormatTags';
|
||||||
import { AvatarWidget } from './AvatarWidget';
|
import { AvatarWidget } from './AvatarWidget';
|
||||||
|
|
||||||
|
|
||||||
@ -41,12 +40,12 @@ export function OverlayProfileSettings() {
|
|||||||
const addTag = useAddTag();
|
const addTag = useAddTag();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
React.useEffect(() => {
|
useEffect(() => {
|
||||||
setId(user?.id ? user.id : "");
|
setId(user?.id ? user.id : "");
|
||||||
setName(user?.first_name ? user.first_name : "");
|
setName(user?.first_name ? user.first_name : "");
|
||||||
setText(user?.description ? user.description : "");
|
setText(user?.description ? user.description : "");
|
||||||
setAvatar(user?.avatar ? user?.avatar : "");
|
setAvatar(user?.avatar ? user?.avatar : "");
|
||||||
setColor(user?.color ? user.color : "#aabbcc");
|
setColor(user?.color ? user.color : "#3D3846");
|
||||||
setOffers([]);
|
setOffers([]);
|
||||||
setNeeds([]);
|
setNeeds([]);
|
||||||
user?.offers.map(o=> {
|
user?.offers.map(o=> {
|
||||||
|
|||||||
@ -4,7 +4,7 @@ export function PlusButton({ triggerAction, color, collection="items" }: { trigg
|
|||||||
const hasUserPermission = useHasUserPermission();
|
const hasUserPermission = useHasUserPermission();
|
||||||
return (
|
return (
|
||||||
<>{hasUserPermission(collection, "create") &&
|
<>{hasUserPermission(collection, "create") &&
|
||||||
<div className="tw-dropdown tw-dropdown-top tw-dropdown-end tw-dropdown-hover tw-z-500 tw-absolute tw-right-4 tw-bottom-4" >
|
<div className="tw-dropdown tw-dropdown-top tw-dropdown-end tw-dropdown-hover tw-z-3000 tw-absolute tw-right-4 tw-bottom-4" >
|
||||||
<button tabIndex={0} className="tw-z-500 tw-btn tw-btn-circle tw-shadow" onClick={() => { triggerAction() }} style={{ backgroundColor: color, color: "#fff"}}>
|
<button tabIndex={0} className="tw-z-500 tw-btn tw-btn-circle tw-shadow" onClick={() => { triggerAction() }} style={{ backgroundColor: color, color: "#fff"}}>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="2" stroke="currentColor" className="tw-w-5 tw-h-5">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="2" stroke="currentColor" className="tw-w-5 tw-h-5">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||||
|
|||||||
@ -18,7 +18,9 @@ type Props = {
|
|||||||
isOpened: boolean;
|
isOpened: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
showCloseButton?: boolean
|
showCloseButton?: boolean;
|
||||||
|
closeOnClickOutside?:boolean;
|
||||||
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DialogModal = ({
|
const DialogModal = ({
|
||||||
@ -26,7 +28,9 @@ const DialogModal = ({
|
|||||||
isOpened,
|
isOpened,
|
||||||
onClose,
|
onClose,
|
||||||
children,
|
children,
|
||||||
showCloseButton = true
|
showCloseButton = true,
|
||||||
|
closeOnClickOutside = true,
|
||||||
|
className,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
|
||||||
const ref = useRef<HTMLDialogElement>(null);
|
const ref = useRef<HTMLDialogElement>(null);
|
||||||
@ -45,12 +49,12 @@ const DialogModal = ({
|
|||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<dialog className='tw-card tw-shadow-xl tw-absolute tw-right-0 tw-top-0 tw-bottom-0 tw-left-0 tw-m-auto tw-transition-opacity tw-duration-300 tw-p-4 tw-max-w-xl tw-bg-base-100'
|
<dialog className={`${className ? className: ""} tw-card tw-shadow-xl tw-absolute tw-right-0 tw-top-0 tw-bottom-0 tw-left-0 tw-m-auto tw-transition-opacity tw-duration-300 tw-p-4 tw-max-w-xl tw-bg-base-100`}
|
||||||
|
|
||||||
ref={ref}
|
ref={ref}
|
||||||
onCancel={onClose}
|
onCancel={onClose}
|
||||||
onClick={(e) =>
|
onClick={(e) =>
|
||||||
ref.current && !isClickInsideRectangle(e, ref.current) && onClose()
|
ref.current && !isClickInsideRectangle(e, ref.current) && closeOnClickOutside &&onClose()
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="tw-card-body tw-p-2">
|
<div className="tw-card-body tw-p-2">
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ReactNode, useEffect, useRef, useState } from 'react'
|
import { ReactNode, useEffect, useRef, useState } from 'react'
|
||||||
import { Link, useNavigate } from 'react-router-dom';
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
import { Item, ItemsApi } from '../../types';
|
import { Item, ItemsApi, LayerProps } from '../../types';
|
||||||
import { getValue } from '../../Utils/GetValue';
|
import { getValue } from '../../Utils/GetValue';
|
||||||
import { TextView } from '../Map';
|
import { TextView } from '../Map';
|
||||||
import { PlusButton } from '../Profile/PlusButton';
|
import { PlusButton } from '../Profile/PlusButton';
|
||||||
@ -13,6 +13,7 @@ import { useAuth } from '../Auth';
|
|||||||
import { useLayers } from '../Map/hooks/useLayers';
|
import { useLayers } from '../Map/hooks/useLayers';
|
||||||
import { HeaderView } from '../Map/Subcomponents/ItemPopupComponents/HeaderView';
|
import { HeaderView } from '../Map/Subcomponents/ItemPopupComponents/HeaderView';
|
||||||
import { MapOverlayPage } from './MapOverlayPage';
|
import { MapOverlayPage } from './MapOverlayPage';
|
||||||
|
import { useAddItem, useItems, useRemoveItem } from '../Map/hooks/useItems';
|
||||||
|
|
||||||
|
|
||||||
type breadcrumb = {
|
type breadcrumb = {
|
||||||
@ -21,7 +22,7 @@ type breadcrumb = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const OverlayItemsIndexPage = ({ api, url, parameterField, breadcrumbs, itemNameField, itemTextField, itemImageField, itemSymbolField, itemSubnameField, plusButton = true, children }: { api: ItemsApi<any>, url: string, parameterField: string, breadcrumbs: Array<breadcrumb>, itemNameField: string, itemTextField: string, itemImageField: string, itemSymbolField: string, itemSubnameField: string, plusButton?: boolean, children?: ReactNode }) => {
|
export const OverlayItemsIndexPage = ({url, type, parameterField, breadcrumbs, itemNameField, itemTextField, itemImageField, itemSymbolField, itemSubnameField, plusButton = true, children }: { type: string, url: string, parameterField: string, breadcrumbs: Array<breadcrumb>, itemNameField: string, itemTextField: string, itemImageField: string, itemSymbolField: string, itemSubnameField: string, plusButton?: boolean, children?: ReactNode }) => {
|
||||||
|
|
||||||
console.log(itemSymbolField);
|
console.log(itemSymbolField);
|
||||||
|
|
||||||
@ -38,27 +39,28 @@ export const OverlayItemsIndexPage = ({ api, url, parameterField, breadcrumbs, i
|
|||||||
scroll();
|
scroll();
|
||||||
}, [addItemPopupType])
|
}, [addItemPopupType])
|
||||||
|
|
||||||
const [items, setItems] = useState<any[]>([]);
|
|
||||||
|
|
||||||
const loadProjects = async () => {
|
|
||||||
const items = await api?.getItems();
|
|
||||||
setItems(items as any);
|
|
||||||
}
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const tags = useTags();
|
const tags = useTags();
|
||||||
const addTag = useAddTag();
|
const addTag = useAddTag();
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
const items = useItems();
|
||||||
|
const addItem = useAddItem();
|
||||||
useEffect(() => {
|
const removeItem = useRemoveItem();
|
||||||
loadProjects();
|
|
||||||
}, [api])
|
|
||||||
|
|
||||||
const layers = useLayers();
|
const layers = useLayers();
|
||||||
|
|
||||||
const submitNewItem = async (evt: any, type: string) => {
|
useEffect(() => {
|
||||||
|
console.log(items);
|
||||||
|
|
||||||
|
|
||||||
|
}, [items])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const layer = layers.find(l => l.itemType == type);
|
||||||
|
|
||||||
|
const submitNewItem = async (evt: any) => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
const formItem: Item = {} as Item;
|
const formItem: Item = {} as Item;
|
||||||
Array.from(evt.target).forEach((input: HTMLInputElement) => {
|
Array.from(evt.target).forEach((input: HTMLInputElement) => {
|
||||||
@ -75,7 +77,7 @@ export const OverlayItemsIndexPage = ({ api, url, parameterField, breadcrumbs, i
|
|||||||
const uuid = crypto.randomUUID();
|
const uuid = crypto.randomUUID();
|
||||||
let success = false;
|
let success = false;
|
||||||
try {
|
try {
|
||||||
await api?.createItem!({ ...formItem, id: uuid, type: type });
|
await layer?.api?.createItem!({ ...formItem, id: uuid, type: type });
|
||||||
success = true;
|
success = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.error(error.toString());
|
toast.error(error.toString());
|
||||||
@ -83,16 +85,16 @@ export const OverlayItemsIndexPage = ({ api, url, parameterField, breadcrumbs, i
|
|||||||
if (success) {
|
if (success) {
|
||||||
toast.success("New item created");
|
toast.success("New item created");
|
||||||
}
|
}
|
||||||
|
addItem({...formItem, user_created: user, type: type, id: uuid, layer: layer});
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setAddItemPopupType("");
|
setAddItemPopupType("");
|
||||||
setItems(current => [...current, { ...formItem, id: uuid, type: type, layer: layers.find(l => l.name == addItemPopupType), user_created: user }])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteItem = async (item) => {
|
const deleteItem = async (item) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
let success = false;
|
let success = false;
|
||||||
try {
|
try {
|
||||||
await api?.deleteItem!(item.id)
|
await layer?.api?.deleteItem!(item.id)
|
||||||
success = true;
|
success = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.error(error.toString());
|
toast.error(error.toString());
|
||||||
@ -100,9 +102,8 @@ export const OverlayItemsIndexPage = ({ api, url, parameterField, breadcrumbs, i
|
|||||||
if (success) {
|
if (success) {
|
||||||
toast.success("Item deleted");
|
toast.success("Item deleted");
|
||||||
}
|
}
|
||||||
|
removeItem(item);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setItems(items.filter(i => i.id != item.id))
|
|
||||||
console.log("chaka");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -122,10 +123,10 @@ export const OverlayItemsIndexPage = ({ api, url, parameterField, breadcrumbs, i
|
|||||||
</div>
|
</div>
|
||||||
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-6 tw-pt-4">
|
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-6 tw-pt-4">
|
||||||
{
|
{
|
||||||
items?.map((i, k) => {
|
items?.filter(i=>i.type === type).map((i, k) => {
|
||||||
return (
|
return (
|
||||||
<div key={k} className='tw-cursor-pointer 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-4 tw-mb-4 tw-h-fit' onClick={() => navigate(url + getValue(i, parameterField))}>
|
<div key={k} className='tw-cursor-pointer 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-4 tw-mb-4 tw-h-fit' onClick={() => navigate(url + getValue(i, parameterField))}>
|
||||||
<HeaderView loading={loading} item={i} api={api} itemAvatarField={itemImageField} itemNameField={itemNameField} itemSubnameField={itemSubnameField} editCallback={() => navigate("/edit-item/" + i.id)} deleteCallback={() => deleteItem(i)}></HeaderView>
|
<HeaderView loading={loading} item={i} api={layer?.api} itemAvatarField={itemImageField} itemNameField={itemNameField} itemSubnameField={itemSubnameField} editCallback={() => navigate("/edit-item/" + i.id)} deleteCallback={() => deleteItem(i)}></HeaderView>
|
||||||
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
|
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
|
||||||
<TextView truncate item={i} itemTextField={itemTextField} />
|
<TextView truncate item={i} itemTextField={itemTextField} />
|
||||||
</div>
|
</div>
|
||||||
@ -137,7 +138,7 @@ export const OverlayItemsIndexPage = ({ api, url, parameterField, breadcrumbs, i
|
|||||||
}
|
}
|
||||||
{addItemPopupType == "project" ?
|
{addItemPopupType == "project" ?
|
||||||
|
|
||||||
<form ref={tabRef} autoComplete='off' onSubmit={e => submitNewItem(e, addItemPopupType)} >
|
<form ref={tabRef} autoComplete='off' onSubmit={e => submitNewItem(e)} >
|
||||||
|
|
||||||
<div className='tw-cursor-pointer 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'>
|
<div className='tw-cursor-pointer 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={() => {
|
<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={() => {
|
||||||
|
|||||||
@ -5,3 +5,4 @@ export {CircleLayout} from './CircleLayout'
|
|||||||
export {MoonCalendar} from './MoonCalendar'
|
export {MoonCalendar} from './MoonCalendar'
|
||||||
export {ItemsIndexPage} from "./ItemsIndexPage"
|
export {ItemsIndexPage} from "./ItemsIndexPage"
|
||||||
export {ItemViewPage} from "./ItemViewPage"
|
export {ItemViewPage} from "./ItemViewPage"
|
||||||
|
export {OverlayItemsIndexPage} from "./OverlayItemsIndexPage"
|
||||||
@ -1,9 +1,9 @@
|
|||||||
export { UtopiaMap, Layer, Tags, Permissions, ItemForm, ItemView, PopupTextAreaInput, PopupStartEndInput, PopupTextInput, PopupButton, TextView, StartEndView } from './Components/Map';
|
export { UtopiaMap, Layer, Tags, Permissions, ItemForm, ItemView, PopupTextAreaInput, PopupStartEndInput, PopupTextInput, PopupButton, TextView, StartEndView } from './Components/Map';
|
||||||
export {AppShell, Content, SideBar} from "./Components/AppShell"
|
export {AppShell, Content, SideBar} from "./Components/AppShell"
|
||||||
export {AuthProvider, useAuth, LoginPage, SignupPage, RequestPasswordPage, SetNewPasswordPage} from "./Components/Auth"
|
export {AuthProvider, useAuth, LoginPage, SignupPage, RequestPasswordPage, SetNewPasswordPage} from "./Components/Auth"
|
||||||
export {UserSettings, ProfileSettings, OverlayProfile, OverlayProfileSettings, OverlayUserSettings, OverlayItemProfile, OverlayItemProfileSettings, PlusButton} from './Components/Profile'
|
export {UserSettings, ProfileSettings, OverlayProfile, OverlayProfileSettings, OverlayUserSettings, OverlayItemProfile, OverlayItemProfileSettings} from './Components/Profile'
|
||||||
export {Quests, Modal} from './Components/Gaming'
|
export {Quests, Modal} from './Components/Gaming'
|
||||||
export {TitleCard, CardPage, MapOverlayPage, CircleLayout, MoonCalendar, ItemsIndexPage, ItemViewPage} from './Components/Templates'
|
export {TitleCard, CardPage, MapOverlayPage, OverlayItemsIndexPage, CircleLayout, MoonCalendar, ItemsIndexPage, ItemViewPage} from './Components/Templates'
|
||||||
export {TextInput, TextAreaInput, SelectBox} from './Components/Input'
|
export {TextInput, TextAreaInput, SelectBox} from './Components/Input'
|
||||||
|
|
||||||
import "./index.css"
|
import "./index.css"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user