mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
code cleanup
This commit is contained in:
parent
3f88f3a801
commit
3e8ac0758f
@ -5,36 +5,32 @@ import { useEffect, useRef, useState } from 'react';
|
|||||||
import { Item, Tag } from '../../types';
|
import { Item, Tag } from '../../types';
|
||||||
import { useMap } from 'react-leaflet';
|
import { useMap } from 'react-leaflet';
|
||||||
import { LatLng } from 'leaflet';
|
import { LatLng } from 'leaflet';
|
||||||
import { StartEndView, TextView } from '../Map';
|
|
||||||
import { useAddTag, useTags } from '../Map/hooks/useTags';
|
import { useAddTag, useTags } from '../Map/hooks/useTags';
|
||||||
import { useAddFilterTag, useResetFilterTags } from '../Map/hooks/useFilter';
|
import { useResetFilterTags } from '../Map/hooks/useFilter';
|
||||||
import { useHasUserPermission } from '../Map/hooks/usePermissions';
|
import { useHasUserPermission } from '../Map/hooks/usePermissions';
|
||||||
import { hashTagRegex } from '../../Utils/HashTagRegex';
|
import { hashTagRegex } from '../../Utils/HashTagRegex';
|
||||||
import { randomColor } from '../../Utils/RandomColor';
|
import { randomColor } from '../../Utils/RandomColor';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { useAuth } from '../Auth';
|
import { useAuth } from '../Auth';
|
||||||
import { useLayers } from '../Map/hooks/useLayers';
|
import { useLayers } from '../Map/hooks/useLayers';
|
||||||
import { ActionButton } from './Subcomponents/ActionsButton';
|
|
||||||
import { LinkedItemsHeaderView } from './Subcomponents/LinkedItemsHeaderView';
|
|
||||||
import { HeaderView } from '../Map/Subcomponents/ItemPopupComponents/HeaderView';
|
import { HeaderView } from '../Map/Subcomponents/ItemPopupComponents/HeaderView';
|
||||||
import { useSelectPosition, useSetSelectPosition } from '../Map/hooks/useSelectPosition';
|
import { useSelectPosition, useSetSelectPosition } from '../Map/hooks/useSelectPosition';
|
||||||
import { useClusterRef } from '../Map/hooks/useClusterRef';
|
import { useClusterRef } from '../Map/hooks/useClusterRef';
|
||||||
import { useLeafletRefs } from '../Map/hooks/useLeafletRefs';
|
import { useLeafletRefs } from '../Map/hooks/useLeafletRefs';
|
||||||
import { getValue } from '../../Utils/GetValue';
|
import { getValue } from '../../Utils/GetValue';
|
||||||
import { TagView } from '../Templates/TagView';
|
import { Tabs } from './Templates/Tabs';
|
||||||
import RelationCard from "./Subcomponents/RelationCard";
|
import { Onepager } from './Templates/Onepager';
|
||||||
import ContactInfo from "./Subcomponents/ContactInfo";
|
import { Simple } from './Templates/Simple';
|
||||||
import ProfileSubHeader from "./Subcomponents/ProfileSubHeader";
|
|
||||||
|
|
||||||
export function ProfileView({ userType }: { userType: string }) {
|
export function ProfileView({ userType }: { userType: string }) {
|
||||||
|
|
||||||
const [updatePermission, setUpdatePermission] = useState<boolean>(false);
|
const [updatePermission, setUpdatePermission] = useState<boolean>(false);
|
||||||
const [relations, setRelations] = useState<Array<Item>>([]);
|
const [relations, setRelations] = useState<Array<Item>>([]);
|
||||||
const [activeTab, setActiveTab] = useState<number>(1);
|
|
||||||
const [addItemPopupType, setAddItemPopupType] = useState<string>("");
|
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
|
||||||
const [offers, setOffers] = useState<Array<Tag>>([]);
|
const [offers, setOffers] = useState<Array<Tag>>([]);
|
||||||
const [needs, setNeeds] = useState<Array<Tag>>([]);
|
const [needs, setNeeds] = useState<Array<Tag>>([]);
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const [addItemPopupType, setAddItemPopupType] = useState<string>("");
|
||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const items = useItems();
|
const items = useItems();
|
||||||
@ -54,9 +50,6 @@ export function ProfileView({ userType }: { userType: string }) {
|
|||||||
const setSelectPosition = useSetSelectPosition();
|
const setSelectPosition = useSetSelectPosition();
|
||||||
const clusterRef = useClusterRef();
|
const clusterRef = useClusterRef();
|
||||||
const leafletRefs = useLeafletRefs();
|
const leafletRefs = useLeafletRefs();
|
||||||
const addFilterTag = useAddFilterTag();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const tabRef = useRef<HTMLFormElement>(null);
|
const tabRef = useRef<HTMLFormElement>(null);
|
||||||
|
|
||||||
@ -68,26 +61,8 @@ export function ProfileView({ userType }: { userType: string }) {
|
|||||||
scroll();
|
scroll();
|
||||||
}, [addItemPopupType])
|
}, [addItemPopupType])
|
||||||
|
|
||||||
const [profile_owner, setProfileOwner] = useState<Item>();
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setProfileOwner(items.find(i => (i.user_created?.id === item.user_created?.id) && i.layer?.itemType.name === userType));
|
|
||||||
}, [item, items])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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(() => {
|
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);
|
||||||
@ -145,7 +120,6 @@ export function ProfileView({ userType }: { userType: string }) {
|
|||||||
}
|
}
|
||||||
}, [item])
|
}, [item])
|
||||||
|
|
||||||
|
|
||||||
const getFirstAncestor = (item: Item): Item | undefined => {
|
const getFirstAncestor = (item: Item): Item | undefined => {
|
||||||
const parent = items.find(i => i.id === item.parent);
|
const parent = items.find(i => i.id === item.parent);
|
||||||
if (parent?.parent) {
|
if (parent?.parent) {
|
||||||
@ -155,17 +129,6 @@ export function ProfileView({ userType }: { userType: string }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let params = new URLSearchParams(location.search);
|
|
||||||
let urlTab = params.get("tab");
|
|
||||||
urlTab ? setActiveTab(Number(urlTab)) : setActiveTab(1);
|
|
||||||
}, [location])
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
item && hasUserPermission("items", "update", item) && setUpdatePermission(true);
|
item && hasUserPermission("items", "update", item) && setUpdatePermission(true);
|
||||||
}, [item])
|
}, [item])
|
||||||
@ -175,8 +138,6 @@ export function ProfileView({ userType }: { userType: string }) {
|
|||||||
selectPosition && map.closePopup();
|
selectPosition && map.closePopup();
|
||||||
}, [selectPosition])
|
}, [selectPosition])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const submitNewItem = async (evt: any, type: string) => {
|
const submitNewItem = async (evt: any, type: string) => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
const formItem: Item = {} as Item;
|
const formItem: Item = {} as Item;
|
||||||
@ -274,23 +235,12 @@ export function ProfileView({ userType }: { userType: string }) {
|
|||||||
navigate("/");
|
navigate("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
const typeMapping = {
|
|
||||||
'wuerdekompass': 'Regional-Gruppe',
|
|
||||||
'themenkompass': 'Themenkompass-Gruppe',
|
|
||||||
'liebevoll.jetzt': 'liebevoll.jetzt',
|
|
||||||
};
|
|
||||||
|
|
||||||
let groupType = item.group_type ? item.group_type : 'default';
|
|
||||||
let groupTypeText = typeMapping[groupType];
|
|
||||||
|
|
||||||
const [template, setTemplate] = useState<string>("")
|
const [template, setTemplate] = useState<string>("")
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTemplate(item.layer?.itemType.template || userType);
|
setTemplate(item.layer?.itemType.template || userType);
|
||||||
}, [userType, item])
|
}, [userType, item])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{item &&
|
{item &&
|
||||||
@ -302,135 +252,15 @@ export function ProfileView({ userType }: { userType: string }) {
|
|||||||
|
|
||||||
|
|
||||||
{template == "onepager" &&
|
{template == "onepager" &&
|
||||||
<div className='tw-h-full tw-overflow-y-auto fade'>
|
<Onepager item={item} userType={userType}/>
|
||||||
<div className="tw-px-6">
|
|
||||||
<ProfileSubHeader
|
|
||||||
type={groupTypeText}
|
|
||||||
status={item.status}
|
|
||||||
url={`https://www.wuerdekompass.org/aktivitaeten/gruppensuche/#/gruppe/${item.slug}`}
|
|
||||||
title={item.name}
|
|
||||||
/>
|
|
||||||
</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} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Description Section */}
|
|
||||||
<div className="tw-my-10 tw-mt-2 tw-px-6 tw-text-sm ">
|
|
||||||
<TextView rawText={item.text || 'Keine Beschreibung vorhanden'} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Next Appointment Section */}
|
|
||||||
{item.next_appointment && (
|
|
||||||
<div className="tw-my-10 tw-px-6">
|
|
||||||
<h2 className="tw-text-lg tw-font-semibold">Nächste Termine</h2>
|
|
||||||
<div className="tw-mt-2 tw-text-sm">
|
|
||||||
<TextView rawText={item.next_appointment} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)};
|
|
||||||
|
|
||||||
{/* Relations Section */}
|
|
||||||
{/*{d.relations && (*/}
|
|
||||||
{/* <div className="tw-my-10 tw-px-6">*/}
|
|
||||||
{/* <h2 className="tw-text-lg tw-font-semibold tw-mb-4">Projekte</h2>*/}
|
|
||||||
{/* {d.relations.map((project, index) => (*/}
|
|
||||||
{/* <RelationCard*/}
|
|
||||||
{/* key={index}*/}
|
|
||||||
{/* title={project.title}*/}
|
|
||||||
{/* description={project.description}*/}
|
|
||||||
{/* imageSrc={project.imageSrc}*/}
|
|
||||||
{/* />*/}
|
|
||||||
{/* ))}*/}
|
|
||||||
{/* </div>*/}
|
|
||||||
{/*)}*/}
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{template == "simple" &&
|
{template == "simple" &&
|
||||||
<div className='tw-mt-8 tw-h-full tw-overflow-y-auto fade tw-px-6'>
|
<Simple item={item}></Simple>
|
||||||
<TextView item={item} />
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{template == "tabs" &&
|
{template == "tabs" &&
|
||||||
<div role="tablist" className="tw-tabs tw-tabs-lifted tw-mt-2 tw-mb-2 tw-px-6">
|
<Tabs item={item} loading={loading} offers={offers} needs={needs} relations={relations} updatePermission={updatePermission} linkItem={linkItem} unlinkItem={unlinkItem}/>
|
||||||
<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-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">
|
|
||||||
{item.layer?.itemType.show_start_end &&
|
|
||||||
<div className='tw-max-w-xs'><StartEndView item={item}></StartEndView></div>
|
|
||||||
}
|
|
||||||
<TextView item={item} />
|
|
||||||
</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)} />
|
|
||||||
<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'>
|
|
||||||
{
|
|
||||||
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={() => {
|
|
||||||
addFilterTag(o)
|
|
||||||
}} />)
|
|
||||||
}
|
|
||||||
</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>
|
|
||||||
</>
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
{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-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'>
|
|
||||||
{relations && relations.map(i =>
|
|
||||||
|
|
||||||
|
|
||||||
<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-p-6 tw-mr-4 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>
|
|
||||||
)}
|
|
||||||
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} triggerItemSelected={linkItem} colorField={item.layer.itemColorField}></ActionButton>}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
|
|
||||||
@ -438,6 +268,4 @@ export function ProfileView({ userType }: { userType: string }) {
|
|||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1,7 +1,73 @@
|
|||||||
import * as React from 'react'
|
import { Item } from "utopia-ui/dist/types"
|
||||||
|
import { TextView } from "../../Map"
|
||||||
|
import ContactInfo from "../Subcomponents/ContactInfo"
|
||||||
|
import ProfileSubHeader from "../Subcomponents/ProfileSubHeader"
|
||||||
|
import { useEffect, useState } from "react"
|
||||||
|
import { useItems } from "../../Map/hooks/useItems"
|
||||||
|
|
||||||
|
export const Onepager = ({item, userType}:{item: Item, userType: string}) => {
|
||||||
|
|
||||||
|
const [profile_owner, setProfileOwner] = useState<Item>();
|
||||||
|
const items = useItems();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setProfileOwner(items.find(i => (i.user_created?.id === item.user_created?.id) && i.layer?.itemType.name === userType));
|
||||||
|
}, [item, items])
|
||||||
|
|
||||||
|
const typeMapping = {
|
||||||
|
'wuerdekompass': 'Regional-Gruppe',
|
||||||
|
'themenkompass': 'Themenkompass-Gruppe',
|
||||||
|
'liebevoll.jetzt': 'liebevoll.jetzt',
|
||||||
|
};
|
||||||
|
|
||||||
|
let groupType = item.group_type ? item.group_type : 'default';
|
||||||
|
let groupTypeText = typeMapping[groupType];
|
||||||
|
|
||||||
export const Onepager = () => {
|
|
||||||
return (
|
return (
|
||||||
<div>Onepager</div>
|
<div className='tw-h-full tw-overflow-y-auto fade'>
|
||||||
|
<div className="tw-px-6">
|
||||||
|
<ProfileSubHeader
|
||||||
|
type={groupTypeText}
|
||||||
|
status={item.status}
|
||||||
|
url={`https://www.wuerdekompass.org/aktivitaeten/gruppensuche/#/gruppe/${item.slug}`}
|
||||||
|
title={item.name}
|
||||||
|
/>
|
||||||
|
</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} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Description Section */}
|
||||||
|
<div className="tw-my-10 tw-mt-2 tw-px-6 tw-text-sm ">
|
||||||
|
<TextView rawText={item.text || 'Keine Beschreibung vorhanden'} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Next Appointment Section */}
|
||||||
|
{item.next_appointment && (
|
||||||
|
<div className="tw-my-10 tw-px-6">
|
||||||
|
<h2 className="tw-text-lg tw-font-semibold">Nächste Termine</h2>
|
||||||
|
<div className="tw-mt-2 tw-text-sm">
|
||||||
|
<TextView rawText={item.next_appointment} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)};
|
||||||
|
|
||||||
|
{/* Relations Section */}
|
||||||
|
{/*{d.relations && (*/}
|
||||||
|
{/* <div className="tw-my-10 tw-px-6">*/}
|
||||||
|
{/* <h2 className="tw-text-lg tw-font-semibold tw-mb-4">Projekte</h2>*/}
|
||||||
|
{/* {d.relations.map((project, index) => (*/}
|
||||||
|
{/* <RelationCard*/}
|
||||||
|
{/* key={index}*/}
|
||||||
|
{/* title={project.title}*/}
|
||||||
|
{/* description={project.description}*/}
|
||||||
|
{/* imageSrc={project.imageSrc}*/}
|
||||||
|
{/* />*/}
|
||||||
|
{/* ))}*/}
|
||||||
|
{/* </div>*/}
|
||||||
|
{/*)}*/}
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
|
import { TextView } from '../../Map'
|
||||||
|
import { Item } from '../../../types'
|
||||||
|
|
||||||
export const Simple = () => {
|
export const Simple = ({item}:{item: Item}) => {
|
||||||
return (
|
return (
|
||||||
<div>Simple</div>
|
<div className='tw-mt-8 tw-h-full tw-overflow-y-auto fade tw-px-6'>
|
||||||
|
<TextView item={item} />
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,112 @@
|
|||||||
import * as React from 'react'
|
import { StartEndView, TextView } from '../../Map'
|
||||||
|
import { TagView } from '../../Templates/TagView'
|
||||||
|
import { LinkedItemsHeaderView } from '../Subcomponents/LinkedItemsHeaderView'
|
||||||
|
import { ActionButton } from '../Subcomponents/ActionsButton'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useAddFilterTag } from '../../Map/hooks/useFilter'
|
||||||
|
import { Item, Tag } from 'utopia-ui/dist/types'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
|
export const Tabs = ({ item, offers, needs, relations, updatePermission, loading, linkItem, unlinkItem }: { item: Item, offers: Array<Tag>, needs: Array<Tag>, relations: Array<Item>, updatePermission: boolean, loading: boolean, linkItem: (id: string) => Promise<void>, unlinkItem: (id: string) => Promise<void> }) => {
|
||||||
|
|
||||||
|
const addFilterTag = useAddFilterTag();
|
||||||
|
const [activeTab, setActiveTab] = useState<number>(1);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
|
||||||
|
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])
|
||||||
|
|
||||||
export const Tabs = () => {
|
|
||||||
return (
|
return (
|
||||||
<div>Tabs</div>
|
<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 [--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-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">
|
||||||
|
{item.layer?.itemType.show_start_end &&
|
||||||
|
<div className='tw-max-w-xs'><StartEndView item={item}></StartEndView></div>
|
||||||
|
}
|
||||||
|
<TextView item={item} />
|
||||||
|
</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)} />
|
||||||
|
<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'>
|
||||||
|
{
|
||||||
|
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={() => {
|
||||||
|
addFilterTag(o)
|
||||||
|
}} />)
|
||||||
|
}
|
||||||
|
</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>
|
||||||
|
</>
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
{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-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'>
|
||||||
|
{relations && relations.map(i =>
|
||||||
|
|
||||||
|
|
||||||
|
<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-p-6 tw-mr-4 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>
|
||||||
|
)}
|
||||||
|
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} triggerItemSelected={linkItem} colorField={item.layer.itemColorField}></ActionButton>}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { toast } from 'react-toastify';
|
|||||||
import { useAuth } from '../Auth';
|
import { useAuth } from '../Auth';
|
||||||
import { TextInput } from '../Input';
|
import { TextInput } from '../Input';
|
||||||
|
|
||||||
export function OverlayUserSettings() {
|
export function UserSettings() {
|
||||||
const { user, updateUser, loading, token } = useAuth();
|
const { user, updateUser, loading, token } = useAuth();
|
||||||
|
|
||||||
const [id, setId] = useState<string>("");
|
const [id, setId] = useState<string>("");
|
||||||
@ -1,4 +1,4 @@
|
|||||||
export {OverlayUserSettings} from './OverlayUserSettings'
|
export {UserSettings} from './UserSettings'
|
||||||
export {PlusButton} from "./Subcomponents/PlusButton"
|
export {PlusButton} from "./Subcomponents/PlusButton"
|
||||||
export {ProfileView} from "./ProfileView"
|
export {ProfileView} from "./ProfileView"
|
||||||
export {ProfileForm} from "./ProfileForm"
|
export {ProfileForm} from "./ProfileForm"
|
||||||
@ -1,53 +0,0 @@
|
|||||||
import { useState, useEffect } from "react";
|
|
||||||
import { useLocation } from "react-router-dom";
|
|
||||||
import { CardPage } from "./CardPage";
|
|
||||||
import { ItemsApi } from "../../types";
|
|
||||||
import { getValue } from "../../Utils/GetValue";
|
|
||||||
|
|
||||||
|
|
||||||
type breadcrumb = {
|
|
||||||
name: string,
|
|
||||||
path: string
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const ItemViewPage = ({ api, parents, itemNameField, itemTextField, itemImageField, itemSymbolField }: { api: ItemsApi<any>, parents: Array<breadcrumb>, itemNameField: string, itemTextField: string, itemImageField: string, itemSymbolField: string }) => {
|
|
||||||
|
|
||||||
const [item, setItem] = useState<any>();
|
|
||||||
|
|
||||||
let location = useLocation();
|
|
||||||
|
|
||||||
|
|
||||||
const loadProject = async () => {
|
|
||||||
if (api?.getItem) {
|
|
||||||
const project: unknown = await api?.getItem(location.pathname.split("/")[2]);
|
|
||||||
setItem(project as any);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
loadProject();
|
|
||||||
}, [api])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<CardPage title={getValue(item, itemNameField) || ""} parents={parents}>
|
|
||||||
{item &&
|
|
||||||
<>
|
|
||||||
{getValue(item, itemImageField) ?
|
|
||||||
<div className=' tw-h-36 flex items-center justify-center '>
|
|
||||||
<img className='tw-h-24' src={`https://api.utopia-lab.org/assets/${getValue(item, itemImageField)}`}></img>
|
|
||||||
</div> :
|
|
||||||
<div className="tw-h-36 !bg-transparent tw-flex tw-items-center tw-justify-center tw-text-7xl">
|
|
||||||
{getValue(item, itemSymbolField)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<p className='text-sm mb-2'>{getValue(item, itemTextField)}</p>
|
|
||||||
</>
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
</CardPage>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,7 +1,5 @@
|
|||||||
export {CardPage} from './CardPage'
|
export {CardPage} from './CardPage'
|
||||||
export {TitleCard} from './TitleCard'
|
export {TitleCard} from './TitleCard'
|
||||||
export {MapOverlayPage} from './MapOverlayPage'
|
export {MapOverlayPage} from './MapOverlayPage'
|
||||||
export {CircleLayout} from './CircleLayout'
|
|
||||||
export {MoonCalendar} from './MoonCalendar'
|
export {MoonCalendar} from './MoonCalendar'
|
||||||
export {ItemViewPage} from "./ItemViewPage"
|
|
||||||
export {OverlayItemsIndexPage} from "./OverlayItemsIndexPage"
|
export {OverlayItemsIndexPage} from "./OverlayItemsIndexPage"
|
||||||
@ -1,9 +1,9 @@
|
|||||||
export { UtopiaMap, Layer, Tags, Permissions, ItemForm, ItemView, PopupTextAreaInput, PopupStartEndInput, PopupTextInput, PopupButton, TextView, StartEndView, PopupCheckboxInput } from './Components/Map';
|
export { UtopiaMap, Layer, Tags, Permissions, ItemForm, ItemView, PopupTextAreaInput, PopupStartEndInput, PopupTextInput, PopupButton, TextView, StartEndView, PopupCheckboxInput } from './Components/Map';
|
||||||
export {AppShell, Content, SideBar, Sitemap } from "./Components/AppShell"
|
export {AppShell, Content, SideBar, Sitemap } from "./Components/AppShell"
|
||||||
export {AuthProvider, useAuth, LoginPage, SignupPage, RequestPasswordPage, SetNewPasswordPage} from "./Components/Auth"
|
export {AuthProvider, useAuth, LoginPage, SignupPage, RequestPasswordPage, SetNewPasswordPage} from "./Components/Auth"
|
||||||
export {OverlayUserSettings, ProfileView, ProfileForm} from './Components/Profile'
|
export {UserSettings, ProfileView, ProfileForm} from './Components/Profile'
|
||||||
export {Quests, Modal} from './Components/Gaming'
|
export {Quests, Modal} from './Components/Gaming'
|
||||||
export {TitleCard, CardPage, MapOverlayPage, OverlayItemsIndexPage, CircleLayout, MoonCalendar, ItemViewPage} from './Components/Templates'
|
export {TitleCard, CardPage, MapOverlayPage, OverlayItemsIndexPage, MoonCalendar } 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