updated item profiles

This commit is contained in:
Anton Tranelis 2024-05-01 09:22:57 +02:00
parent 34dac6ec5d
commit 63fb0d3fd0
6 changed files with 261 additions and 203 deletions

View File

@ -9,7 +9,7 @@ export function ActionButton({ item, triggerAddButton, triggerItemSelected, exis
triggerAddButton?: any,
triggerItemSelected?: any,
existingRelations: Item[],
itemType: string;
itemType?: string;
color: string,
collection?: string,
item: Item
@ -19,7 +19,7 @@ export function ActionButton({ item, triggerAddButton, triggerItemSelected, exis
const items = useItems();
const filterdItems = items.filter(i => 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)
@ -37,7 +37,7 @@ export function ActionButton({ item, triggerAddButton, triggerItemSelected, exis
</svg>
</button>}
</div>
<DialogModal title={"Select"} isOpened={modalOpen} onClose={() => (setModalOpen(false))} className="!tw-max-w-2xl ">
<DialogModal title={"Select"} isOpened={modalOpen} onClose={() => (setModalOpen(false))} className="!tw-max-w-2xl tw-bg-base-200">
<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) }}>
<HeaderView item={i} hideMenu></HeaderView>

View File

@ -55,7 +55,7 @@ export function LinkedItemsHeaderView({ item, unlinkCallback, itemNameField, ite
<div className='tw-col-span-1' onClick={(e) => e.stopPropagation()}>
{unlinkPermission &&
<div className="tw-dropdown tw-dropdown-bottom">
<label tabIndex={0} className="tw-bg-base-100 tw-btn tw-m-1 tw-leading-3 tw-border-none tw-min-h-0 tw-h-6">
<label tabIndex={0} className=" tw-btn tw-m-1 tw-leading-3 tw-border-none tw-min-h-0 tw-h-6">
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
<path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
</svg>

View File

@ -2,12 +2,12 @@ import { MapOverlayPage } from '../Templates'
import { useAddItem, useItems, useRemoveItem, useUpdateItem } from '../Map/hooks/useItems'
import { useLocation, useNavigate } from 'react-router-dom'
import { useEffect, useRef, useState } from 'react';
import { Item } from '../../types';
import { Item, Tag } from '../../types';
import { useMap } from 'react-leaflet';
import { LatLng } from 'leaflet';
import { PopupStartEndInput, StartEndView, TextView } from '../Map';
import { useAddTag, useTags } from '../Map/hooks/useTags';
import { useFilterTags, useResetFilterTags } from '../Map/hooks/useFilter';
import { useAddFilterTag, useFilterTags, useResetFilterTags } from '../Map/hooks/useFilter';
import { useHasUserPermission } from '../Map/hooks/usePermissions';
import { TextAreaInput, TextInput } from '../Input';
import { hashTagRegex } from '../../Utils/HashTagRegex';
@ -21,6 +21,8 @@ import { HeaderView } from '../Map/Subcomponents/ItemPopupComponents/HeaderView'
import { useSelectPosition, useSetSelectPosition } from '../Map/hooks/useSelectPosition';
import { useClusterRef } from '../Map/hooks/useClusterRef';
import { useLeafletRefs } from '../Map/hooks/useLeafletRefs';
import { getValue } from '../../Utils/GetValue';
import { TagView } from '../Templates/TagView';
export function OverlayItemProfile() {
@ -29,6 +31,8 @@ export function OverlayItemProfile() {
const [activeTab, setActiveTab] = useState<number>(1);
const [addItemPopupType, setAddItemPopupType] = useState<string>("");
const [loading, setLoading] = useState<boolean>(false);
const [offers, setOffers] = useState<Array<Tag>>([]);
const [needs, setNeeds] = useState<Array<Tag>>([]);
const location = useLocation();
const items = useItems();
@ -49,6 +53,8 @@ export function OverlayItemProfile() {
const setSelectPosition = useSetSelectPosition();
const clusterRef = useClusterRef();
const leafletRefs = useLeafletRefs();
const addFilterTag = useAddFilterTag();
const tabRef = useRef<HTMLFormElement>(null);
@ -79,11 +85,28 @@ export function OverlayItemProfile() {
}, [items, location])
useEffect(() => {
setOffers([]);
setNeeds([]);
setRelations([]);
}, [item])
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])
})
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])
})
item.relations?.map(r => {
const item = items.find(i => i.id == r.related_items_id)
item && setRelations(current => [...current, item])
})
}, [item,items])
useEffect(() => {
@ -133,16 +156,6 @@ export function OverlayItemProfile() {
}, [location])
useEffect(() => {
setRelations([]);
item.relations?.map(r => {
const item = items.find(i => i.id == r.related_items_id)
item && setRelations(current => [...current, item])
})
}, [item, activeTab])
useEffect(() => {
item && item.user_created && hasUserPermission("items", "update", item) && setUpdatePermission(true);
}, [item])
@ -254,8 +267,6 @@ export function OverlayItemProfile() {
navigate("/");
}
return (
<>
{item &&
@ -271,107 +282,72 @@ export function OverlayItemProfile() {
<TextView item={item} />
</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="Projects" 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 tw-pt-4 tw-pb-1 -tw-mx-4 tw-overflow-x-hidden" >
{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)} />
<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 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-5'>
{relations && relations.map(i => {
if (i.layer?.itemType.name == 'project') 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-4 tw-mb-4 tw-h-fit' onClick={() => navigate('/item/' + i.id)}>
<LinkedItemsHeaderView unlinkPermission={updatePermission} loading={loading} item={i} unlinkCallback={unlinkItem} />
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
<TextView truncate item={i} />
</div>
</div>
)
else return null
})}
{addItemPopupType == "project" ?
<form ref={tabRef} autoComplete='off' onSubmit={e => submitNewItem(e, addItemPopupType)} >
<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-mx-4 tw-p-6 tw-mb-4'>
<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("")
}}>
<p className='tw-text-center '></p></label>
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={""} inputStyle='' />
<TextAreaInput placeholder="Text" dataField="text" defaultValue={""} inputStyle='tw-h-40 tw-mt-5' />
<div className='tw-flex tw-justify-center'>
<button className={loading ? 'tw-btn tw-btn-disabled tw-mt-5 tw-place-self-center' : 'tw-btn tw-mt-5 tw-place-self-center'} type='submit'>{loading ? <span className="tw-loading tw-loading-spinner"></span> : 'Save'}</button>
</div>
</div>
</form> : <></>
<div className='tw-grid tw-grid-cols-1'>
{
offers.length > 0 ?
<div className='tw-col-span-1'>
<h3 className='-tw-mb-2'>Offers</h3>
< div className='tw-flex tw-flex-wrap tw-mb-4'>
{
offers.map(o => <TagView key={o?.id} tag={o} onClick={() => {
console.log(o);
addFilterTag(o)
}} />)
}
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} itemType={"project"} triggerItemSelected={linkItem} triggerAddButton={() => { setAddItemPopupType("project"); scroll() }} color={item.color}></ActionButton>}
</div>
</div> : ""
}
{
needs.length > 0 ?
<div className='tw-col-span-1'>
<h3 className='-tw-mb-2 tw-col-span-1'>Needs</h3>
< div className='tw-flex tw-flex-wrap tw-mb-4'>
{
needs.map(n => <TagView key={n?.id} tag={n} onClick={() => addFilterTag(n)} />)
}
</div>
</div> : ""
}
</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="Events" checked={activeTab == 3 && true} onChange={() => updateActiveTab(3)} />
}
{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)} />
<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.layer?.itemType.name == 'event') return (
{relations && relations.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-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'>
<StartEndView item={i}></StartEndView>
<TextView truncate item={i} />
</div>
</div>
)
else return null
})}
{addItemPopupType == "event" ?
<form autoComplete='off' onSubmit={e => submitNewItem(e, addItemPopupType)} >
<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-mx-4 tw-p-6 tw-mb-4'>
<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("")
}}>
<p className='tw-text-center '></p></label>
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={""} inputStyle='' />
<PopupStartEndInput></PopupStartEndInput>
<TextAreaInput placeholder="Text" dataField="text" defaultValue={""} inputStyle='tw-h-40 tw-mt-5' />
<div className='tw-flex tw-justify-center'>
<button className={loading ? 'tw-btn tw-btn-disabled tw-mt-5 tw-place-self-center' : 'tw-btn tw-mt-5 tw-place-self-center'} type='submit'>{loading ? <span className="tw-loading tw-loading-spinner"></span> : 'Save'}</button>
</div>
</div>
</form> : <></>
}
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} itemType={"event"} triggerItemSelected={linkItem} triggerAddButton={() => { setAddItemPopupType("event"); scroll() }} color={item.color}></ActionButton>}
</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="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 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.layer?.itemType.name == '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)}>
<div key={i.id} className='tw-cursor-pointer tw-card tw-bg-base-200 tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl 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>}
)}
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} triggerItemSelected={linkItem} color={item.color}></ActionButton>}
</div>
</div>
</div>
</>
}
</div>
</div>
</>

View File

@ -10,12 +10,17 @@ import { hashTagRegex } from '../../Utils/HashTagRegex';
import { useAddTag, useTags } from '../Map/hooks/useTags';
import { randomColor } from '../../Utils/RandomColor';
import { useLocation, useNavigate } from 'react-router-dom';
import { Item } from '../../types';
import { Item, Tag } from '../../types';
import { MapOverlayPage } from '../Templates';
import { AvatarWidget } from './AvatarWidget';
import { encodeTag } from '../../Utils/FormatTags';
import { useLayers } from '../Map/hooks/useLayers';
import { TagsWidget } from './TagsWidget';
import { LinkedItemsHeaderView } from './LinkedItemsHeaderView';
import { TextView } from '../Map/Subcomponents/ItemPopupComponents/TextView';
import { ActionButton } from './ActionsButton';
import { useHasUserPermission } from '../Map/hooks/usePermissions';
export function OverlayItemProfileSettings() {
@ -26,6 +31,12 @@ export function OverlayItemProfileSettings() {
const [text, setText] = useState<string>("");
const [image, setImage] = useState<string>("");
const [color, setColor] = useState<string>("");
const [offers, setOffers] = useState<Array<Tag>>([]);
const [needs, setNeeds] = useState<Array<Tag>>([]);
const [updatePermission, setUpdatePermission] = useState<boolean>(false);
const [relations, setRelations] = useState<Array<Item>>([]);
const [activeTab, setActiveTab] = useState<number>(1);
@ -34,6 +45,7 @@ export function OverlayItemProfileSettings() {
const { user } = useAuth();
const hasUserPermission = useHasUserPermission();
const updateItem = useUpdateItem();
const addItem = useAddItem();
@ -56,6 +68,24 @@ export function OverlayItemProfileSettings() {
}, [location, items, activeTab])
const updateActiveTab = (id: number) => {
setActiveTab(id);
let params = new URLSearchParams(window.location.search);
let urlTab = params.get("tab");
if (!urlTab?.includes(id.toString()))
params.set("tab", `${id ? id : ""}`)
window.history.pushState('', '', "?" + params.toString());
}
useEffect(() => {
let params = new URLSearchParams(location.search);
let urlTab = params.get("tab");
urlTab ? setActiveTab(Number(urlTab)) : setActiveTab(1);
}, [location])
React.useEffect(() => {
if (item.layer?.itemColorField) setColor(getValue(item, item.layer?.itemColorField));
else setColor(item.layer?.markerDefaultColor || "#3D3846")
@ -65,21 +95,66 @@ export function OverlayItemProfileSettings() {
setSubname(item?.subname ? item.subname : "");
setText(item?.text ? item.text : "");
setImage(item?.image ? item?.image : "");
setOffers([]);
setNeeds([]);
item?.offers?.map(o => {
const offer = tags.find(t => t.id === o.tags_id);
offer && setOffers(current => [...current, offer])
})
item?.needs?.map(o => {
const need = tags.find(t => t.id === o.tags_id);
need && setNeeds(current => [...current, need])
})
setRelations([]);
item.relations?.map(r => {
const item = items.find(i => i.id == r.related_items_id)
item && setRelations(current => [...current, item])
})
item && item.user_created && hasUserPermission("items", "update", item) && setUpdatePermission(true);
}, [item])
const onUpdateItem = async () => {
let changedItem = {} as Item;
let offer_updates : Array<any> = [];
//check for new offers
offers.map(o => {
const existingOffer = item?.offers?.find(t => t.tags_id === o.id)
existingOffer && offer_updates.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})
});
let needs_updates : Array<any> = [];
needs.map(n => {
const existingNeed = user?.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 && !tags.some(t => t.id === n.id) && addTag({...n,offer_or_need: true})
});
changedItem = { id: id, name: name, subname: subname, text: text, color: color, position: item.position, ...image.length > 10 && { image: image }};
changedItem = { id: id, name: name, subname: subname, text: text, color: color, position: item.position, ...image.length > 10 && { image: image }, ... offers.length > 0 && {offers: offer_updates}, ... needs.length > 0 && {needs: needs_updates} };
// update profile item in current state
//const item = items.find(i => i.layer?.itemOwnerField && getValue(i, i.layer?.itemOwnerField).id === id);
let offers_state : Array<any> = [];
let needs_state : Array<any> = [];
await offers.map(o => {
offers_state.push({items_id: item?.id, tags_id: o.id})
});
await needs.map(n => {
needs_state.push({items_id: item?.id, tags_id: n.id})
});
changedItem = {... changedItem, offers: offers_state, needs: needs_state};
// if (item && item.layer && item.layer.itemOwnerField) item[item.layer.itemOwnerField] = {... changedUser, offers: offer_state, needs: needs_state};
// add new hashtags from profile text
text.toLocaleLowerCase().match(hashTagRegex)?.map(tag => {
if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
addTag({ id: crypto.randomUUID(), name: encodeTag(tag.slice(1).toLocaleLowerCase()), color: randomColor() })
@ -90,7 +165,8 @@ export function OverlayItemProfileSettings() {
console.log(item.layer);
if(item.layer) {item?.layer?.api?.updateItem && toast.promise(
if (item.layer) {
item?.layer?.api?.updateItem && toast.promise(
item?.layer?.api?.updateItem(changedItem),
{
pending: 'updating Item ...',
@ -104,7 +180,8 @@ export function OverlayItemProfileSettings() {
.then(() => item && updateItem({ ...item, ...changedItem }))
.then(() => {
setLoading(false);
navigate("/item/"+item.id)});
navigate("/item/" + item.id)
});
}
else {
@ -123,9 +200,8 @@ export function OverlayItemProfileSettings() {
.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"});
navigate("/")
});
}
}
@ -146,23 +222,28 @@ export function OverlayItemProfileSettings() {
<div role="tablist" className="tw-tabs tw-tabs-lifted tw-mt-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="Vision" checked={activeTab == 1 && true} onChange={() => setActiveTab(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">
<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">
<TextAreaInput placeholder="My Vision..." defaultValue={item?.text ? item.text : ""} updateFormValue={(v) => { console.log(v); setText(v) }} containerStyle='tw-h-full' inputStyle='tw-h-full tw-border-t-0 tw-rounded-tl-none' />
</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="Projects" checked={activeTab == 2 && true} onChange={() => setActiveTab(2)} />
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-pt-4 tw-h-[calc(100dvh-332px)] tw-min-h-56">
{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)} />
<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'>
<TagsWidget defaultTags={offers} onUpdate={(v) => setOffers(v)} placeholder="enter your offers" containerStyle='tw-bg-transparent tw-w-full tw-h-full tw-mt-3 tw-text-xs tw-h-[calc(100%-1rem)] tw-min-h-[5em] tw-pb-2 tw-overflow-auto' />
</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={() => setActiveTab(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">
<div className='tw-w-full tw-h-[calc(50%-0.75em)] '>
<TagsWidget defaultTags={needs} onUpdate={(v) => setNeeds(v)} placeholder="enter your needs" containerStyle='tw-bg-transparent tw-w-full tw-h-full tw-mt-3 tw-text-xs tw-h-[calc(100%-1rem)] tw-min-h-[5em] tw-pb-2 tw-overflow-auto' />
</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={() => setActiveTab(4)} />
<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">
</div>
</div>
</>
}
</div>
<div className="tw-mt-4 tw-mb-4"><button className={loading ? " tw-loading tw-btn-disabled tw-btn tw-btn-primary tw-float-right" : "tw-btn tw-btn-primary tw-float-right"} onClick={() => onUpdateItem()}>Update</button></div>

View File

@ -0,0 +1,19 @@
import { useState } from "react";
import { timeAgo } from "../../Utils/TimeAgo";
import { Item } from "../../types";
export const DateUserInfo = ({ item }: { item: Item }) => {
const [infoExpanded, setInfoExpanded] = useState<boolean>(false);
return (
<div className='tw-flex -tw-mb-1 tw-flex-row tw-mr-2 -tw-mt-2' onClick={(e) => e.stopPropagation()}>
{
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-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>
</div>
)
}

View File

@ -15,6 +15,7 @@ import { HeaderView } from '../Map/Subcomponents/ItemPopupComponents/HeaderView'
import { MapOverlayPage } from './MapOverlayPage';
import { useAddItem, useItems, useRemoveItem } from '../Map/hooks/useItems';
import { timeAgo } from '../../Utils/TimeAgo';
import { DateUserInfo } from './DateUserInfo';
type breadcrumb = {
@ -112,7 +113,7 @@ export const OverlayItemsIndexPage = ({ url, layerName, parameterField, breadcru
<>
<MapOverlayPage className='tw-rounded-none tw-overflow-y-auto'>
<MapOverlayPage className='tw-rounded-none tw-overflow-y-auto tw-to-base-200'>
<div className='tw-h-fit'>
{breadcrumbs &&
<div className="tw-text-sm tw-breadcrumbs">
@ -137,26 +138,7 @@ export const OverlayItemsIndexPage = ({ url, layerName, parameterField, breadcru
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
<TextView truncate item={i} itemTextField={itemTextField} />
</div>
<div className='tw-flex -tw-mb-1 tw-flex-row tw-mr-2 -tw-mt-2' onClick={(e) => e.stopPropagation()}>
{
infoExpanded.get(k) ?
<p className={`tw-italic tw-min-h-[21px] !tw-my-0 tw-text-gray-500`} onClick={() => setInfoExpanded(prevMap => {
const newMap = new Map(prevMap); // Create a new Map from the previous Map
newMap.set(k, false); // Set new or update existing key-value pair
return newMap; // Return the new Map to update the state
})} >{`${i.date_updated && i.date_updated != i.date_created ? "updated" : "posted"} ${i && i.user_created && i.user_created.first_name ? `by ${i.user_created.first_name}` : ""} ${i.date_updated ? timeAgo(i.date_updated) : timeAgo(i.date_created!)}`}</p>
:
<p className="!tw-my-0 tw-min-h-[21px] tw-font-bold tw-cursor-pointer tw-text-gray-500" onClick={() => setInfoExpanded(prevMap => {
const newMap = new Map(prevMap); // Create a new Map from the previous Map
newMap.set(k, true); // Set new or update existing key-value pair
return newMap; // Return the new Map to update the state
})}></p>
}
<div className='tw-grow '></div>
{ //** <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="tw-place-self-end tw-w-4 tw-h-4 tw-mb-1 tw-cursor-pointer"><path strokeLinecap="round" strokeLinejoin="round" d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15" /></svg> */
}
</div>
<DateUserInfo item={i}></DateUserInfo>
</div>
)