mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
first working attestation prototype
This commit is contained in:
parent
4f92c5b4b4
commit
bc8b73451c
@ -2,7 +2,7 @@ import { MapOverlayPage } from '../Templates'
|
|||||||
import { useItems, useRemoveItem, useUpdateItem } from '../Map/hooks/useItems'
|
import { useItems, useRemoveItem, useUpdateItem } from '../Map/hooks/useItems'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Item, Tag } from '../../types';
|
import { Item, ItemsApi, Tag } from '../../types';
|
||||||
import { useMap } from 'react-leaflet';
|
import { useMap } from 'react-leaflet';
|
||||||
import { LatLng } from 'leaflet';
|
import { LatLng } from 'leaflet';
|
||||||
import { useHasUserPermission } from '../Map/hooks/usePermissions';
|
import { useHasUserPermission } from '../Map/hooks/usePermissions';
|
||||||
@ -17,7 +17,7 @@ import { SimpleView } from './Templates/SimpleView';
|
|||||||
import { handleDelete, linkItem, unlinkItem } from './itemFunctions';
|
import { handleDelete, linkItem, unlinkItem } from './itemFunctions';
|
||||||
import { useTags } from '../Map/hooks/useTags';
|
import { useTags } from '../Map/hooks/useTags';
|
||||||
|
|
||||||
export function ProfileView({ userType }: { userType: string }) {
|
export function ProfileView({ userType, attestationApi }: { userType: string , attestationApi?: ItemsApi<any>}) {
|
||||||
|
|
||||||
const [item, setItem] = useState<Item>({} as Item)
|
const [item, setItem] = useState<Item>({} as Item)
|
||||||
const [updatePermission, setUpdatePermission] = useState<boolean>(false);
|
const [updatePermission, setUpdatePermission] = useState<boolean>(false);
|
||||||
@ -40,6 +40,23 @@ export function ProfileView({ userType }: { userType: string }) {
|
|||||||
const clusterRef = useClusterRef();
|
const clusterRef = useClusterRef();
|
||||||
const leafletRefs = useLeafletRefs();
|
const leafletRefs = useLeafletRefs();
|
||||||
|
|
||||||
|
const [attestations, setAttestations] = useState<Array<any>>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (attestationApi) {
|
||||||
|
attestationApi.getItems()
|
||||||
|
.then(value => {
|
||||||
|
console.log(value);
|
||||||
|
|
||||||
|
setAttestations(value);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("Error fetching items:", error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [attestationApi])
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
@ -140,7 +157,7 @@ export function ProfileView({ userType }: { userType: string }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{template == "tabs" &&
|
{template == "tabs" &&
|
||||||
<TabsView setUrlParams={setUrlParams} item={item} loading={loading} offers={offers} needs={needs} relations={relations} updatePermission={updatePermission} linkItem={(id) => linkItem(id, item, updateItem)} unlinkItem={(id) => unlinkItem(id, item, updateItem)}/>
|
<TabsView userType={userType} attestations={attestations} setUrlParams={setUrlParams} item={item} loading={loading} offers={offers} needs={needs} relations={relations} updatePermission={updatePermission} linkItem={(id) => linkItem(id, item, updateItem)} unlinkItem={(id) => unlinkItem(id, item, updateItem)}/>
|
||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
|
|
||||||
|
|||||||
@ -6,8 +6,12 @@ import { useCallback, useEffect, useRef, useState } from 'react'
|
|||||||
import { useAddFilterTag } from '../../Map/hooks/useFilter'
|
import { useAddFilterTag } from '../../Map/hooks/useFilter'
|
||||||
import { Item, Tag } from 'utopia-ui/dist/types'
|
import { Item, Tag } from 'utopia-ui/dist/types'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import { useItems } from '../../Map/hooks/useItems'
|
||||||
|
import { useAssetApi } from '../../AppShell/hooks/useAssets'
|
||||||
|
import { timeAgo } from '../../../Utils/TimeAgo'
|
||||||
|
import { useAuth } from '../../Auth'
|
||||||
|
|
||||||
export const TabsView = ({ item, offers, needs, relations, updatePermission, loading, linkItem, unlinkItem, setUrlParams }: { 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> , setUrlParams: any}) => {
|
export const TabsView = ({ attestations, userType, item, offers, needs, relations, updatePermission, loading, linkItem, unlinkItem, setUrlParams }: { attestations: Array<any>, userType: string, 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>, setUrlParams: any }) => {
|
||||||
|
|
||||||
const addFilterTag = useAddFilterTag();
|
const addFilterTag = useAddFilterTag();
|
||||||
const [activeTab, setActiveTab] = useState<number>();
|
const [activeTab, setActiveTab] = useState<number>();
|
||||||
@ -15,12 +19,20 @@ export const TabsView = ({ item, offers, needs, relations, updatePermission, loa
|
|||||||
|
|
||||||
const [addItemPopupType, setAddItemPopupType] = useState<string>("");
|
const [addItemPopupType, setAddItemPopupType] = useState<string>("");
|
||||||
|
|
||||||
|
const items = useItems();
|
||||||
|
const assetsApi = useAssetApi();
|
||||||
|
const {user} = useAuth();
|
||||||
|
|
||||||
|
const getUserProfile = (id: string) => {
|
||||||
|
return items.find(i => i.user_created.id === id && i.layer?.itemType.name === userType)
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
scroll();
|
scroll();
|
||||||
}, [addItemPopupType])
|
}, [addItemPopupType])
|
||||||
|
|
||||||
function scroll() {
|
function scroll() {
|
||||||
tabRef.current?.scrollIntoView();
|
tabRef.current?.scrollIntoView();
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabRef = useRef<HTMLFormElement>(null);
|
const tabRef = useRef<HTMLFormElement>(null);
|
||||||
@ -42,57 +54,6 @@ export const TabsView = ({ item, offers, needs, relations, updatePermission, loa
|
|||||||
setActiveTab(urlTab ? Number(urlTab) : 1);
|
setActiveTab(urlTab ? Number(urlTab) : 1);
|
||||||
}, [location.search]);
|
}, [location.search]);
|
||||||
|
|
||||||
const attestations = [{
|
|
||||||
from: "Timo",
|
|
||||||
avatar: "https://api.utopia-lab.org/assets/262117f8-feb6-444f-9bd2-e84087285760?width=80&heigth=80",
|
|
||||||
symbol: "🥇",
|
|
||||||
text: "1. Platz im Bogenschießen",
|
|
||||||
date: "21.06.2024",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "Sebastian",
|
|
||||||
avatar: "https://api.utopia-lab.org/assets/7510a082-882b-41c3-aa7d-5a19f9502f25?width=80&heigth=80",
|
|
||||||
symbol: "🌱",
|
|
||||||
text: "danke fürs Rasen mähen",
|
|
||||||
date: "29.06.2024",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "Yurij",
|
|
||||||
avatar: "https://api.utopia-lab.org/assets/abe62291-35ad-45de-b978-e5906d8a3eb6?width=80&heigth=80",
|
|
||||||
symbol: "🏆",
|
|
||||||
text: "bester Coder ever",
|
|
||||||
date: "04.07.2024",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "Luca",
|
|
||||||
avatar: "https://api.utopia-lab.org/assets/e285e653-36e8-4211-a69d-00053c1f610e?width=80&heigth=80",
|
|
||||||
symbol: "🙏",
|
|
||||||
text: "Vielen Dank für deine Hilfe!!!",
|
|
||||||
date: "04.07.2024",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "Lisa",
|
|
||||||
avatar: "https://i.pinimg.com/originals/c0/ed/08/c0ed088cd6532d4fd27396aefddac57c.jpg",
|
|
||||||
symbol: "❤️",
|
|
||||||
text: "Vielen Dank für deine Hilfe!!!",
|
|
||||||
date: "04.07.2024",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "Timo",
|
|
||||||
avatar: "https://api.utopia-lab.org/assets/262117f8-feb6-444f-9bd2-e84087285760?width=80&heigth=80",
|
|
||||||
symbol: "🥈",
|
|
||||||
text: "2. Platz im Bogenschießen",
|
|
||||||
date: "21.06.2024",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "Anton",
|
|
||||||
avatar: "https://api.utopia-lab.org/assets/007dc678-6073-4ad1-9b47-f2cfe1dca582?width=80&heigth=80",
|
|
||||||
symbol: "🌱",
|
|
||||||
text: "danke fürs Rasen mähen",
|
|
||||||
date: "29.06.2024"
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div role="tablist" className="tw-tabs tw-tabs-lifted tw-mt-2 tw-mb-2 tw-px-6">
|
<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"
|
<input type="radio" name="my_tabs_2" role="tab"
|
||||||
@ -106,53 +67,58 @@ export const TabsView = ({ item, offers, needs, relations, updatePermission, loa
|
|||||||
}
|
}
|
||||||
<TextView item={item} />
|
<TextView item={item} />
|
||||||
<div className='tw-h-4'></div>
|
<div className='tw-h-4'></div>
|
||||||
<TextView item={item} itemTextField='contact'/>
|
<TextView item={item} itemTextField='contact' />
|
||||||
</div>
|
</div>
|
||||||
{item.layer?.itemType.questlog &&
|
{item.layer?.itemType.questlog &&
|
||||||
<>
|
<>
|
||||||
<input type="radio" name="my_tabs_2" role="tab"
|
<input type="radio" name="my_tabs_2" role="tab"
|
||||||
className={`tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]`}
|
className={`tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]`}
|
||||||
aria-label="❤️" checked={activeTab == 2 && true}
|
aria-label="❤️" checked={activeTab == 2 && true}
|
||||||
onChange={() => updateActiveTab(2)} />
|
onChange={() => updateActiveTab(2)} />
|
||||||
|
|
||||||
<div role="tabpanel"
|
<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">
|
className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto fade tw-pt-2 tw-pb-4 tw-mb-4 tw-overflow-x-hidden">
|
||||||
<table className="sm:tw-table-sm md:tw-table-md">
|
<table className="sm:tw-table-sm md:tw-table-md">
|
||||||
<tbody>
|
<tbody>
|
||||||
{attestations.map((a, i) => <tr key={i}>
|
{attestations.filter(a => a.to.some(t => t.directus_users_id == item.user_created.id)).map((a, i) => <tr key={i}>
|
||||||
<td>
|
<td>
|
||||||
<div className='tw-mask tw-mask-circle tw-text-xl md:tw-text-2xl tw-bg-slate-200 tw-rounded-full tw-p-2 tw-my-1 tw-mr-2'>{a.symbol}</div>
|
<div
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div className='tw-mr-2' ><i>{a.text}</i></div>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div className="tw-avatar">
|
|
||||||
<div className="tw-mask tw-rounded-full h-8 w-8 tw-mr-2">
|
|
||||||
<img
|
|
||||||
src={a.avatar}
|
|
||||||
alt="Avatar Tailwind CSS Component" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="font-bold">{a.from}</div>
|
|
||||||
<div className="tw-text-xs opacity-50 tw-text-zinc-500">{a.date}</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
</tr>)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
className={`tw-cursor-pointer tw-text-3xl tw-mask tw-mask-${a.shape} tw-p-3 tw-mr-2 tw-bg-[${a.color}]`}
|
||||||
|
>
|
||||||
|
{a.emoji}
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
}
|
</td>
|
||||||
|
<td>
|
||||||
|
<div className='tw-mr-2' ><i>{a.text}</i></div>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="tw-avatar">
|
||||||
|
<div className="tw-mask tw-rounded-full h-8 w-8 tw-mr-2">
|
||||||
|
<img
|
||||||
|
src={assetsApi.url + getUserProfile(a.user_created.id)?.image}
|
||||||
|
alt="Avatar Tailwind CSS Component" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="font-bold">{getUserProfile(a.user_created.id)?.name}</div>
|
||||||
|
<div className="tw-text-xs opacity-50 tw-text-zinc-500">{timeAgo(a.date_created)}</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
{item.layer?.itemType.offers_and_needs &&
|
{item.layer?.itemType.offers_and_needs &&
|
||||||
|
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -3,16 +3,17 @@ import { MapOverlayPage } from './MapOverlayPage'
|
|||||||
import { useItems } from '../Map/hooks/useItems'
|
import { useItems } from '../Map/hooks/useItems'
|
||||||
import { useAssetApi } from '../AppShell/hooks/useAssets'
|
import { useAssetApi } from '../AppShell/hooks/useAssets'
|
||||||
import { EmojiPicker } from './EmojiPicker';
|
import { EmojiPicker } from './EmojiPicker';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
import { Item, ItemsApi } from '../../types';
|
import { Item, ItemsApi } from '../../types';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
export const AttestationForm = ({api}:{api:ItemsApi<any>}) => {
|
export const AttestationForm = ({api}:{api?:ItemsApi<any>}) => {
|
||||||
|
|
||||||
const items = useItems();
|
const items = useItems();
|
||||||
const assetsApi = useAssetApi();
|
const assetsApi = useAssetApi();
|
||||||
const [users, setUsers] = useState<Array<Item>>();
|
const [users, setUsers] = useState<Array<Item>>();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let params = new URLSearchParams(location.search);
|
let params = new URLSearchParams(location.search);
|
||||||
@ -35,16 +36,22 @@ export const AttestationForm = ({api}:{api:ItemsApi<any>}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const sendAttestation = async () => {
|
const sendAttestation = async () => {
|
||||||
api.createItem && api.createItem({
|
const to : Array<any> = [];
|
||||||
|
users?.map(u => to.push({ directus_users_id: u.user_created.id }));
|
||||||
|
console.log(to);
|
||||||
|
|
||||||
|
api?.createItem && api.createItem({
|
||||||
text: inputValue,
|
text: inputValue,
|
||||||
symbol: "🔥",
|
emoji: selectedEmoji,
|
||||||
color: "",
|
color: selectedColor,
|
||||||
shape: "",
|
shape: selectedShape,
|
||||||
to: users
|
to: to
|
||||||
})
|
}).then(()=> navigate("/"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [selectedEmoji, setSelectedEmoji] = useState('select badge');
|
||||||
|
const [selectedShape, setSelectedShape] = useState('circle');
|
||||||
|
const [selectedColor, setSelectedColor] = useState('#fff0d6');
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -70,7 +77,7 @@ export const AttestationForm = ({api}:{api:ItemsApi<any>}) => {
|
|||||||
<div className='tw-w-full'>
|
<div className='tw-w-full'>
|
||||||
<div className='tw-flex tw-justify-center tw-items-center'>
|
<div className='tw-flex tw-justify-center tw-items-center'>
|
||||||
<div className=' tw-flex tw-justify-center tw-items-center tw-w-28 tw-h-28 tw-m-4'>
|
<div className=' tw-flex tw-justify-center tw-items-center tw-w-28 tw-h-28 tw-m-4'>
|
||||||
<EmojiPicker />
|
<EmojiPicker selectedEmoji={selectedEmoji} selectedColor={selectedColor} selectedShape={selectedShape} setSelectedEmoji={setSelectedEmoji} setSelectedColor={setSelectedColor} setSelectedShape={setSelectedShape} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='tw-flex tw-justify-center tw-items-center'>
|
<div className='tw-flex tw-justify-center tw-items-center'>
|
||||||
@ -82,7 +89,7 @@ export const AttestationForm = ({api}:{api:ItemsApi<any>}) => {
|
|||||||
className="tw-input tw-min-w-0 tw-w-fit tw-resize-none tw-overflow-hidden tw-text-center " />
|
className="tw-input tw-min-w-0 tw-w-fit tw-resize-none tw-overflow-hidden tw-text-center " />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='tw-w-full tw-grid tw-mt-4'><Link className="tw-place-self-center" to="/item/b42a1404-fe08-4d84-8404-47ce623c3cf2?tab=2"><button className="tw-btn tw-px-8">Next</button></Link></div>
|
<div className='tw-w-full tw-grid tw-mt-4'><button onClick={sendAttestation} className="tw-btn tw-place-self-center tw-px-8">Next</button></div>
|
||||||
</MapOverlayPage>
|
</MapOverlayPage>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -1,9 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
export const EmojiPicker = () => {
|
export const EmojiPicker = ({selectedEmoji, selectedColor, selectedShape, setSelectedEmoji, setSelectedColor, setSelectedShape}) => {
|
||||||
const [selectedEmoji, setSelectedEmoji] = useState('select badge');
|
|
||||||
const [selectedShape, setSelectedShape] = useState('circle');
|
|
||||||
const [selectedColor, setSelectedColor] = useState('#fff0d6');
|
|
||||||
|
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user