diff --git a/frontend/src/assets/styles/_extra.scss b/frontend/src/assets/styles/_extra.scss index 76216aaa83..21dd10646e 100644 --- a/frontend/src/assets/styles/_extra.scss +++ b/frontend/src/assets/styles/_extra.scss @@ -611,10 +611,26 @@ a[href="https://www.mapbox.com/map-feedback/"] color: rgba($blue-dark, 0.9); } +.gap-0\.625 { + gap: 0.75rem; +} + +.gap-0\.75 { + gap: 0.75rem; +} + .gap-1 { gap: 1rem; } +.gap-1\.25 { + gap: 1.25rem; +} + +.gap-1\.5 { + gap: 1.5rem; +} + // Imported from HOTOSM site to use for long texts .blue-dark-abbey { color: #4c4f56; diff --git a/frontend/src/components/button.js b/frontend/src/components/button.js index af665a7a92..41ba8bb686 100644 --- a/frontend/src/components/button.js +++ b/frontend/src/components/button.js @@ -10,7 +10,15 @@ export const AnimatedLoadingIcon = () => ( ); -export function Button({ onClick, children, icon, className, disabled, loading = false }: Object) { +export function Button({ + onClick, + children, + icon, + className, + disabled, + loading = false, + ...otherProps +}: Object) { return ( + + {/* dropdown list */} + {isActive && ( + + )} + + ); +}; diff --git a/frontend/src/components/partners/leaderboard.js b/frontend/src/components/partners/leaderboard.js new file mode 100644 index 0000000000..aeb2cb7087 --- /dev/null +++ b/frontend/src/components/partners/leaderboard.js @@ -0,0 +1,33 @@ +import { FormattedMessage } from 'react-intl'; +import messages from '../../views/messages'; + +import { StatsSection } from './partnersStats'; +import { Activity } from './partnersActivity'; +import { CurrentProjects } from './currentProjects'; + +export const Leaderboard = ({ partner, partnerStats }) => { + return ( +
+
+

+ {partner.primary_hashtag + ?.split(',') + ?.map((str) => `#${str}`) + ?.join(', ')} +

+
+ + + + + + {/* activity section */} +
+

+ +

+ +
+
+ ); +}; diff --git a/frontend/src/components/partners/partners.js b/frontend/src/components/partners/partners.js index df9e2382d2..3557a5e7d0 100644 --- a/frontend/src/components/partners/partners.js +++ b/frontend/src/components/partners/partners.js @@ -95,7 +95,7 @@ export function PartnersCard({ details }) { - + { const renderWebsiteLinks = () => { @@ -11,20 +14,23 @@ export const Resources = ({ partner }) => { name: partner[nameKey], url: partner[urlKeys[index]], })); + + const resourcesData = websiteLinks.map((link) => ({ + ...link, + label: link.name, + onClick: (item) => { + window.open(item.url, '_blank'); + }, + })); + + if (!resourcesData.length) return <>; + return ( -
- {websiteLinks.map((link, index) => ( - - {link.name} - - ))} -
+ } + data={resourcesData} + /> ); }; diff --git a/frontend/src/components/partners/styles.scss b/frontend/src/components/partners/styles.scss index fd14c119ad..e3e3295c61 100644 --- a/frontend/src/components/partners/styles.scss +++ b/frontend/src/components/partners/styles.scss @@ -23,6 +23,38 @@ } .partners-social-icon { - height: 24px; - width: 24px; + height: 20px; + width: 20px; +} + +.partners-banner-button { + padding: 0.75rem 0 !important; +} + +.partners-banner-logo { + margin: 2.25rem 0 1.75rem 0; +} + +.partners-custom-dropdown { + width: 17rem; + right: 0; + padding: 0.5rem 0; + z-index: 111; +} + +.partners-dropdown-icon { + width: 12px; +} + +.partners-tab-item { + border-radius: 3px 3px 0px 0px; + padding: 0.625rem 1.375rem; + font-weight: 500; +} + +.partners-dropdown-list-item { + padding: 0.75rem 2rem; + &:hover { + background-color: #4e5157; + } } diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index c17c7d1917..ddbf37eeec 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -1173,7 +1173,7 @@ "management.partner.edit.error": "Partner name already exists", "management.partner.learnToMap": "Learn to Map", "management.partner.currentProjects": "Current Projects", - "management.partner.newToMapping": "¿New to Mapping?", + "management.partner.newToMapping": "New to Mapping?", "management.partner.activity": "Activity", "management.partner.resources": "Resources", "management.entity.creation.success": "{entity, select, organization {Organization} partner {Partner} license {License} project {Project} category {Category} campaign {Campaign} team {Team} other {}} created successfully", diff --git a/frontend/src/routes.js b/frontend/src/routes.js index 2ca317b374..7495186182 100644 --- a/frontend/src/routes.js +++ b/frontend/src/routes.js @@ -113,7 +113,7 @@ export const router = createBrowserRouter( }} /> { const { PartnersStats } = await import( './views/partnersStats' /* webpackChunkName: "partnersStats" */ diff --git a/frontend/src/views/partnersStats.js b/frontend/src/views/partnersStats.js index 152abe8d09..5673160345 100644 --- a/frontend/src/views/partnersStats.js +++ b/frontend/src/views/partnersStats.js @@ -1,24 +1,46 @@ import React, { useEffect, useState } from 'react'; -import { Link, useParams } from 'react-router-dom'; +import { Link, useParams, useNavigate } from 'react-router-dom'; import ReactPlaceholder from 'react-placeholder'; import { FormattedMessage } from 'react-intl'; import messages from './messages'; import { NotFound } from './notFound'; import { useFetch } from '../hooks/UseFetch'; -import { StatsSection } from '../components/partners/partnersStats'; -import { Activity } from '../components/partners/partnersActivity'; -import { CurrentProjects } from '../components/partners/currentProjects'; +import { Leaderboard } from '../components/partners/leaderboard'; import { Resources } from '../components/partners/partnersResources'; import { OHSOME_STATS_BASE_URL } from '../config'; import { Button } from '../components/button'; import { TwitterIcon, FacebookIcon, InstagramIcon } from '../components/svgIcons'; +function getSocialIcons(link) { + const socialName = link.split('_')?.[1]; + switch (socialName) { + case 'x': + return ; + case 'meta': + return ; + case 'instagram': + return ; + default: + return <>; + } +} + +const tabData = [{ id: 'leaderboard', title: 'Leaderboard' }]; + export const PartnersStats = () => { - const { id } = useParams(); + const { id, tabname } = useParams(); + const navigate = useNavigate(); const [partnerStats, setPartnerStats] = useState(null); const [error, loading, partner] = useFetch(`partners/${id}/`); + // navigate to /leaderboard path when no tab param present + useEffect(() => { + if (!tabname) { + navigate('leaderboard'); + } + }, [navigate, tabname]); + const fetchData = async (name) => { try { let hashtag = name.trim(); @@ -45,6 +67,19 @@ export const PartnersStats = () => { } }, [partner]); + function getTabContent() { + switch (tabname) { + case 'leaderboard': + return ; + default: + return <>; + } + } + + const socialLinks = Object.keys(partner) + .filter((key) => key.startsWith('link')) + .filter((link) => partner[link]); + return ( { ) : (
-
+
{/* logo */} {partner.logo_url ? ( - logo +
+ logo +
) : ( -

{partner.name}

- )} - {/* new to mapping button */} - - - -
- {/* social logos */} -
-
-

- {partner.primary_hashtag - ?.split(',') - ?.map((str) => `#${str}`) - ?.join(', ')} +

+ {partner.name}

-
- {!!partner.link_x && ( - - - - )} - {!!partner.link_meta && ( - - - - )} - {!!partner.link_instagram && ( - + -
- - - - +
+ {/* new to mapping button */} + + + - {/* resources section */} - {Object.keys(partner).some((key) => key.includes('name_')) && ( -
-

- -

+ {/* resources button */} -
- )} - {/* activity section */} -
-

- -

- + {/* social logos */} + {!!socialLinks.length && ( +
+ {socialLinks.map((link) => ( + + {getSocialIcons(link)} + + ))} +
+ )} +
+ + {/* tab content */} + {getTabContent()}
)}