From aff509f1dd26ee6e7244c4afd23ac5cb06a526d9 Mon Sep 17 00:00:00 2001 From: Sebastian Stein Date: Tue, 25 Jun 2024 09:46:26 +0200 Subject: [PATCH 01/42] - added new profile layout (not dynamic data linked yet) - added new components around the profile --- src/Components/Profile/ContactInfo.tsx | 35 ++++++ src/Components/Profile/OverlayItemProfile.tsx | 102 +++++++++++++----- src/Components/Profile/ProfileSubHeader.tsx | 34 ++++++ src/Components/Profile/RelationCard.tsx | 16 +++ src/Components/Profile/SocialShareBar.tsx | 20 ++++ src/Components/Profile/SocialShareButton.tsx | 80 ++++++++++++++ src/Components/Templates/MapOverlayPage.tsx | 4 +- 7 files changed, 265 insertions(+), 26 deletions(-) create mode 100644 src/Components/Profile/ContactInfo.tsx create mode 100644 src/Components/Profile/ProfileSubHeader.tsx create mode 100644 src/Components/Profile/RelationCard.tsx create mode 100644 src/Components/Profile/SocialShareBar.tsx create mode 100644 src/Components/Profile/SocialShareButton.tsx diff --git a/src/Components/Profile/ContactInfo.tsx b/src/Components/Profile/ContactInfo.tsx new file mode 100644 index 00000000..43ec9e0d --- /dev/null +++ b/src/Components/Profile/ContactInfo.tsx @@ -0,0 +1,35 @@ + +const ContactInfo = ({ contact }) => ( +
+

Du hast Fragen?

+
+
+ {contact.avatarSrc ? ( + {contact.name} + ) : ( + + + + + + )} +
+
+

{contact.name}

+ + + + + + + {contact.email} + +
+
+
+); + +export default ContactInfo; \ No newline at end of file diff --git a/src/Components/Profile/OverlayItemProfile.tsx b/src/Components/Profile/OverlayItemProfile.tsx index 3be57efe..1e3a46d2 100644 --- a/src/Components/Profile/OverlayItemProfile.tsx +++ b/src/Components/Profile/OverlayItemProfile.tsx @@ -22,6 +22,9 @@ import { useClusterRef } from '../Map/hooks/useClusterRef'; import { useLeafletRefs } from '../Map/hooks/useLeafletRefs'; import { getValue } from '../../Utils/GetValue'; import { TagView } from '../Templates/TagView'; +import RelationCard from "./RelationCard"; +import ContactInfo from "./ContactInfo"; +import ProfileSubHeader from "./ProfileSubHeader"; export function OverlayItemProfile() { @@ -270,45 +273,96 @@ export function OverlayItemProfile() { navigate("/"); } + const d = { + groupName: "Gruppe Berlin-Britz", + location: "12347 Berlin-Britz", + country: "Berlin, Deutschland", + countryCode: "de", + contact: { + name: "Lisa Mustermann", + email: "lisa.mustermann@gmx.de", + avatarSrc: "https://cdn.prod.website-files.com/65c0d5530322d3f6f5f86099/65c0d5530322d3f6f5f86781_Andr%C3%A9.jpg" // optional + }, + description: "Unsere KulturArche, ein historischer Frachtsegler...", + relations: [ + { + title: "KulturArche EALA", + description: "Durchaus beeindruckt von der Ethik und der Arbeit...", + imageSrc: "https://cdn.prod.website-files.com/65c0d5530322d3f6f5f86099/65c0d5530322d3f6f5f86767_IMG_20190302_173147.jpg" + }, + // Add more projects as needed + ], + url: window.location.href, + title: "Gruppe Berlin-Britz" + }; + + + return ( <> {item && - + <> - navigate("/edit-item/" + item.id)} setPositionCallback={() => { map.closePopup(); setSelectPosition(item); navigate("/") }} big truncateSubname={false} /> +
+ navigate("/edit-item/" + item.id)} setPositionCallback={() => { map.closePopup(); setSelectPosition(item); navigate("/") }} big truncateSubname={false} /> +
{item.layer?.itemType.onepager && - <> - -
- {relations && relations.map(i => + <> + + {d.contact && ( + + )} -
navigate('/item/' + i.id)}> - -
- -
+ {/* Description Section */} +
+

Beschreibung

+

+ {d.description ?? 'Keine Beschreibung vorhanden'} +

- )} - {updatePermission && } -
- + {/* Relations Section */} + {d.relations && ( +
+

Projekte

+ {d.relations.map((project, index) => ( + + ))} +
+ )} + } - {!item.layer?.itemType.onepager && -
- updateActiveTab(1)} /> -
- {item.layer?.itemType.show_start_end && -
- } - -
+ {!item.layer?.itemType.onepager && +
+ updateActiveTab(1)}/> +
+ {item.layer?.itemType.show_start_end && +
+ } + +
{item.layer?.itemType.offers_and_needs && diff --git a/src/Components/Profile/ProfileSubHeader.tsx b/src/Components/Profile/ProfileSubHeader.tsx new file mode 100644 index 00000000..0bec7344 --- /dev/null +++ b/src/Components/Profile/ProfileSubHeader.tsx @@ -0,0 +1,34 @@ +import SocialShareBar from './SocialShareBar'; + + +const flags = { + de: ( + + + + + + ), + at: ( + + + + + + ) +}; + +const SubHeader = ({ location, country, countryCode, url, title }) => ( +
+
+ {location} + {flags[countryCode] || null} + {country} +
+
+ +
+
+); + +export default SubHeader; \ No newline at end of file diff --git a/src/Components/Profile/RelationCard.tsx b/src/Components/Profile/RelationCard.tsx new file mode 100644 index 00000000..4d153188 --- /dev/null +++ b/src/Components/Profile/RelationCard.tsx @@ -0,0 +1,16 @@ + +const RelationCard = ({ title, description, imageSrc }) => ( +
+ {imageSrc && ( +
+ {title} +
+ )} +
+

{title}

+

{description}

+
+
+); + +export default RelationCard; \ No newline at end of file diff --git a/src/Components/Profile/SocialShareBar.tsx b/src/Components/Profile/SocialShareBar.tsx new file mode 100644 index 00000000..e66ac421 --- /dev/null +++ b/src/Components/Profile/SocialShareBar.tsx @@ -0,0 +1,20 @@ +import SocialShareButton from './SocialShareButton'; + +const SocialShareBar = ({ url, title, platforms = ['facebook', 'twitter', 'linkedin', 'xing', 'email'] }) => { + return ( +
+ Teilen: +
+ {platforms.map((platform) => ( + + ))} +
+
+ ); +}; + +export default SocialShareBar; \ No newline at end of file diff --git a/src/Components/Profile/SocialShareButton.tsx b/src/Components/Profile/SocialShareButton.tsx new file mode 100644 index 00000000..5053369f --- /dev/null +++ b/src/Components/Profile/SocialShareButton.tsx @@ -0,0 +1,80 @@ +import * as React from 'react'; + +const platformConfigs = { + facebook: { + shareUrl: 'https://www.facebook.com/sharer/sharer.php?u={url}', + icon: ( + + + + ), + bgColor: '#3b5998' + }, + twitter: { + shareUrl: 'https://twitter.com/intent/tweet?text={title}:%20{url}', + icon: ( + + + + ), + bgColor: '#55acee' + }, + linkedin: { + shareUrl: 'http://www.linkedin.com/shareArticle?mini=true&url={url}&title={title}', + icon: ( + + + + + ), + bgColor: '#4875b4' + }, + xing: { + shareUrl: 'https://www.xing-share.com/app/user?op=share;sc_p=xing-share;url={url}', + icon: ( + + + + ), + bgColor: '#026466' + }, + email: { + shareUrl: 'mailto:?subject={title}&body={url}', + icon: ( + + + + ), + bgColor: '#444444' + } +}; + +const SocialShareButton = ({ platform, url, title }) => { + const config = platformConfigs[platform]; + + if (!config) { + return null; + } + + const { shareUrl, icon, bgColor } = config; + const finalShareUrl = shareUrl + .replace('{url}', encodeURIComponent(url)) + .replace('{title}', encodeURIComponent(title)); + + return ( + + {React.cloneElement(icon, { className: 'tw-w-4 tw-h-4 tw-fill-current' })} + + ); +}; + +export default SocialShareButton; \ No newline at end of file diff --git a/src/Components/Templates/MapOverlayPage.tsx b/src/Components/Templates/MapOverlayPage.tsx index fd84d9ba..614a703e 100644 --- a/src/Components/Templates/MapOverlayPage.tsx +++ b/src/Components/Templates/MapOverlayPage.tsx @@ -3,7 +3,7 @@ import * as L from 'leaflet'; import * as React from 'react' import { useNavigate } from 'react-router-dom'; -export function MapOverlayPage({ children, className, backdrop, card = true }: { children: React.ReactNode, className?: string, backdrop?: boolean, card?:boolean }) { +export function MapOverlayPage({ children, className, backdrop, card = true, padding = true }: { children: React.ReactNode, className?: string, backdrop?: boolean, card?:boolean, padding?:boolean }) { const closeScreen = () => { @@ -32,7 +32,7 @@ export function MapOverlayPage({ children, className, backdrop, card = true }: { return (
-
+
{children}
From 3acb1c1937feba7b41f0e0cd32fd9363370731a6 Mon Sep 17 00:00:00 2001 From: Sebastian Stein Date: Tue, 25 Jun 2024 10:55:15 +0200 Subject: [PATCH 02/42] - transformed list into a masonry layout --- .../Templates/OverlayItemsIndexPage.tsx | 64 ++++++++----------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/src/Components/Templates/OverlayItemsIndexPage.tsx b/src/Components/Templates/OverlayItemsIndexPage.tsx index b9f46fc5..2ce1ce38 100644 --- a/src/Components/Templates/OverlayItemsIndexPage.tsx +++ b/src/Components/Templates/OverlayItemsIndexPage.tsx @@ -108,8 +108,6 @@ export const OverlayItemsIndexPage = ({ url, layerName, parameterField, plusButt return ( <> - -
@@ -119,55 +117,45 @@ export const OverlayItemsIndexPage = ({ url, layerName, parameterField, plusButt
-
+
{ items?.filter(i => i.layer?.name === layerName). - filter(item => - filterTags.length == 0 ? item : filterTags.every(tag => getItemTags(item).some(filterTag => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))?. - sort((a, b) => { - // Convert date_created to milliseconds, handle undefined by converting to lowest possible date (0 milliseconds) - const dateA = a.date_updated ? new Date(a.date_updated).getTime() : a.date_created ? new Date(a.date_created).getTime() : 0; - const dateB = b.date_updated ? new Date(b.date_updated).getTime() : b.date_created ? new Date(b.date_created).getTime() : 0; - return dateB - dateA; // Subtracts milliseconds which are numbers - })?. - map((i, k) => { - return ( - deleteItem(i)} > - ) - }) + filter(item => + filterTags.length == 0 ? item : filterTags.every(tag => getItemTags(item).some(filterTag => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))?. + sort((a, b) => { + // Convert date_created to milliseconds, handle undefined by converting to lowest possible date (0 milliseconds) + const dateA = a.date_updated ? new Date(a.date_updated).getTime() : a.date_created ? new Date(a.date_created).getTime() : 0; + const dateB = b.date_updated ? new Date(b.date_updated).getTime() : b.date_created ? new Date(b.date_created).getTime() : 0; + return dateB - dateA; // Subtracts milliseconds which are numbers + })?. + map((i, k) => ( +
+ deleteItem(i)} /> +
+ )) }
- {addItemPopupType == "place" ? - -
submitNewItem(e)} > - + {addItemPopupType == "place" && ( + submitNewItem(e)}>
- + - {layer?.itemType.show_start_end_input && - - } + {layer?.itemType.show_start_end_input && }
- +
-
: <> - } - + + )}
- - {plusButton && { setAddItemPopupType("place"); scroll(); }} color={'#777'} collection='items' />} - - - - ) -} + )} From fa85b372cab45a52b9b935054a515605a6281a32 Mon Sep 17 00:00:00 2001 From: Sebastian Stein Date: Tue, 25 Jun 2024 13:45:33 +0200 Subject: [PATCH 03/42] - fixed position of ChevronRightIcon --- src/Components/AppShell/SideBar.tsx | 133 ++++++++++++++-------------- 1 file changed, 65 insertions(+), 68 deletions(-) diff --git a/src/Components/AppShell/SideBar.tsx b/src/Components/AppShell/SideBar.tsx index 79f7881f..480a3c92 100644 --- a/src/Components/AppShell/SideBar.tsx +++ b/src/Components/AppShell/SideBar.tsx @@ -61,84 +61,81 @@ export function SideBar({ routes, bottomRoutes }: { routes: route[], bottomRoute let params = new URLSearchParams(window.location.search); return ( - + ) } From 1f159ac8368578e5543c88a0d707046a653d8f60 Mon Sep 17 00:00:00 2001 From: Sebastian Stein Date: Tue, 25 Jun 2024 13:52:40 +0200 Subject: [PATCH 04/42] - changed: do not show QuestControl in embedded mode --- src/Components/Map/UtopiaMap.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Components/Map/UtopiaMap.tsx b/src/Components/Map/UtopiaMap.tsx index 09fb6e1e..278949a6 100644 --- a/src/Components/Map/UtopiaMap.tsx +++ b/src/Components/Map/UtopiaMap.tsx @@ -62,9 +62,13 @@ function UtopiaMap({ const [itemFormPopup, setItemFormPopup] = useState(null); + const [embedded, setEmbedded] = useState(true) + useEffect(() => { let params = new URLSearchParams(location.search); let urlPosition = params.get("position"); + let embedded = params.get("embedded"); + embedded != "true" && setEmbedded(false) }, [location]); const onEachFeature = (feature: Feature, layer: L.Layer) => { @@ -83,7 +87,9 @@ function UtopiaMap({ - + {!embedded && ( + + )} Date: Tue, 25 Jun 2024 14:10:58 +0200 Subject: [PATCH 05/42] - changed: do not show AddButton in embedded mode or when the user is not logged in --- src/Components/Map/UtopiaMap.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Components/Map/UtopiaMap.tsx b/src/Components/Map/UtopiaMap.tsx index 278949a6..dc8dd10b 100644 --- a/src/Components/Map/UtopiaMap.tsx +++ b/src/Components/Map/UtopiaMap.tsx @@ -17,6 +17,7 @@ import { TagsControl } from "./Subcomponents/Controls/TagsControl"; import { useSelectPosition, useSetMapClicked,useSetSelectPosition } from "./hooks/useSelectPosition"; import { useClusterRef, useSetClusterRef } from "./hooks/useClusterRef"; import { Feature, Geometry as GeoJSONGeometry } from 'geojson'; +import {useAuth} from "../Auth"; // for refreshing map on resize (needs to be implemented) const mapDivRef = React.createRef(); @@ -71,6 +72,10 @@ function UtopiaMap({ embedded != "true" && setEmbedded(false) }, [location]); + const { isAuthenticated } = useAuth(); + + + const onEachFeature = (feature: Feature, layer: L.Layer) => { if (feature.properties) { layer.bindPopup(feature.properties.name); @@ -112,7 +117,9 @@ function UtopiaMap({ }} />} - + {!embedded && isAuthenticated && ( + + )} {selectNewItemPosition != null &&