diff --git a/packages/components/src/CardList/CardList.tsx b/packages/components/src/CardList/CardList.tsx index 57a771b25f..fa1804f6c3 100644 --- a/packages/components/src/CardList/CardList.tsx +++ b/packages/components/src/CardList/CardList.tsx @@ -1,9 +1,11 @@ -import { Flex, Grid, Text } from 'theme-ui' +import Masonry from 'react-responsive-masonry' +import { Flex, Text } from 'theme-ui' import { CardListItem } from '../CardListItem/CardListItem' +import { Icon } from '../Icon/Icon' import { Loader } from '../Loader/Loader' -import type { ListItem } from '../CardListItem/CardListItem' +import type { ListItem } from '../CardListItem/types' export interface IProps { filteredList: ListItem[] | null @@ -16,40 +18,46 @@ export const CardList = (props: IProps) => { const { filteredList, list } = props const listToShow = filteredList === null ? list : filteredList - const displayItems = listToShow.map((item) => ( - - )) + const displayItems = listToShow + .sort( + (a, b) => + Date.parse(b.creator?._lastActive || '0') - + Date.parse(a.creator?._lastActive || '0'), + ) + .map((item) => ) const isListEmpty = displayItems.length === 0 const hasListLoaded = list - const results = `${displayItems.length} ${displayItems.length == 1 ? 'result' : 'results'}` + const results = `${displayItems.length} ${ + displayItems.length == 1 ? 'result' : 'results' + }` return ( {!hasListLoaded && } {hasListLoaded && ( <> - - {results} - - - {!isListEmpty && displayItems} - {isListEmpty && EMPTY_LIST} - + {results} + + Most active + + + + {isListEmpty && EMPTY_LIST} + {!isListEmpty && {displayItems}} )} diff --git a/packages/components/src/CardListItem/CardDetailsFallback.tsx b/packages/components/src/CardListItem/CardDetailsFallback.tsx new file mode 100644 index 0000000000..13fbd0e5fc --- /dev/null +++ b/packages/components/src/CardListItem/CardDetailsFallback.tsx @@ -0,0 +1,52 @@ +import { Flex } from 'theme-ui' + +import { Category } from '../Category/Category' +import { MemberBadge } from '../MemberBadge/MemberBadge' +import { Username } from '../Username/Username' + +import type { ListItem } from './types' + +interface IProps { + item: ListItem +} + +export const CardDetailsFallback = ({ item }: IProps) => { + const { _id, isSupporter, isVerified, subType, type } = item + + return ( + + + + + {subType && ( + + )} + {type === 'member' && ( + + )} + + + ) +} diff --git a/packages/components/src/CardListItem/CardDetailsMemberProfile.tsx b/packages/components/src/CardListItem/CardDetailsMemberProfile.tsx new file mode 100644 index 0000000000..a652a28b3e --- /dev/null +++ b/packages/components/src/CardListItem/CardDetailsMemberProfile.tsx @@ -0,0 +1,70 @@ +import { Avatar, Box, Flex } from 'theme-ui' + +import { Category } from '../Category/Category' +import { MemberBadge } from '../MemberBadge/MemberBadge' +import { Username } from '../Username/Username' + +import type { IProfileCreator } from './types' + +interface IProps { + creator: IProfileCreator +} + +export const CardDetailsMemberProfile = ({ creator }: IProps) => { + const { _id, badges, countryCode, profileType, userImage } = creator + return ( + + {userImage && ( + + + + + + + )} + {!userImage && } + + + + + + + ) +} diff --git a/packages/components/src/CardListItem/CardDetailsSpaceProfile.tsx b/packages/components/src/CardListItem/CardDetailsSpaceProfile.tsx new file mode 100644 index 0000000000..6a1fe50da7 --- /dev/null +++ b/packages/components/src/CardListItem/CardDetailsSpaceProfile.tsx @@ -0,0 +1,86 @@ +import { Flex, Image, Text } from 'theme-ui' + +import { Category } from '../Category/Category' +import { MemberBadge } from '../MemberBadge/MemberBadge' +import { Username } from '../Username/Username' + +import type { IProfileCreator } from './types' + +interface IProps { + creator: IProfileCreator +} + +export const CardDetailsSpaceProfile = ({ creator }: IProps) => { + const { _id, about, badges, countryCode, coverImage, profileType, subType } = + creator + + const aboutTextStart = + about && about.length > 80 ? about.slice(0, 78) + '...' : false + + return ( + + {coverImage && ( + + + + + + + )} + + + {!coverImage && } + + + {subType && ( + + )} + {about && ( + + {aboutTextStart || about} + + )} + + + ) +} diff --git a/packages/components/src/CardListItem/CardListItem.stories.tsx b/packages/components/src/CardListItem/CardListItem.stories.tsx index 1be443e35e..2349c8ae9a 100644 --- a/packages/components/src/CardListItem/CardListItem.stories.tsx +++ b/packages/components/src/CardListItem/CardListItem.stories.tsx @@ -1,3 +1,5 @@ +import { faker } from '@faker-js/faker' + import { CardListItem } from './CardListItem' import type { Meta, StoryFn } from '@storybook/react' @@ -12,16 +14,61 @@ export const DefaultMember: StoryFn = () => { const item = { _id: 'not-selected-onload', type: 'member' as ProfileTypeName, + creator: { + _id: 'member_no2', + _lastActive: 'string', + countryCode: 'br', + userImage: faker.image.avatar(), + displayName: 'member_no1', + isContactableByPublic: false, + profileType: 'member' as ProfileTypeName, + }, } - return + return ( +
+ +
+ ) } export const DefaultSpace: StoryFn = () => { const item = { _id: 'not-selected-onload', type: 'workspace' as ProfileTypeName, + creator: { + _id: 'string', + _lastActive: 'string', + about: + 'Lorem ipsum odor amet, consectetuer adipiscing elit. Lorem ipsum odor amet, consectetuer adipiscing elit.', + badges: { + supporter: true, + verified: false, + }, + countryCode: 'uk', + displayName: 'user', + isContactableByPublic: false, + profileType: 'workspace' as ProfileTypeName, + subType: 'Sheetpress', + }, + } + + return ( +
+ +
+ ) +} + +export const DefaultFallback: StoryFn = () => { + const item = { + _id: 'not-selected-onload', + type: 'member' as ProfileTypeName, } - return + return ( +
+ +
+ ) } diff --git a/packages/components/src/CardListItem/CardListItem.tsx b/packages/components/src/CardListItem/CardListItem.tsx index 2dbe8f0c45..df3eefddd2 100644 --- a/packages/components/src/CardListItem/CardListItem.tsx +++ b/packages/components/src/CardListItem/CardListItem.tsx @@ -1,22 +1,20 @@ import { Card, Flex } from 'theme-ui' import { InternalLink } from '../InternalLink/InternalLink' -import { MemberBadge } from '../MemberBadge/MemberBadge' -import { Username } from '../Username/Username' +import { CardDetailsFallback } from './CardDetailsFallback' +import { CardDetailsMemberProfile } from './CardDetailsMemberProfile' +import { CardDetailsSpaceProfile } from './CardDetailsSpaceProfile' -import type { ProfileTypeName } from 'oa-shared' - -export interface ListItem { - _id: string - type: ProfileTypeName -} +import type { ListItem } from './types' export interface IProps { item: ListItem } -export const CardListItem = (props: IProps) => { - const { item } = props +export const CardListItem = ({ item }: IProps) => { + const { creator } = item + + const isMember = creator?.profileType === 'member' return ( { to={`/u/${item._id}`} sx={{ borderRadius: 2, - marginTop: '2px', - '&:hover': { - animationSpeed: '0.3s', - cursor: 'pointer', - marginTop: '0', - borderBottom: '2px solid', - transform: 'translateY(-2px)', - transition: 'borderBottom 0.2s, transform 0.2s', - borderColor: 'black', - }, - '&:active': { - transform: 'translateY(1px)', - borderBottom: '1px solid', - borderColor: 'grey', - transition: 'borderBottom 0.2s, transform 0.2s, borderColor 0.2s', - }, + padding: 2, }} > - - - - + + + {isMember && } + + {!isMember && creator && ( + + )} + + {!creator && } diff --git a/packages/components/src/CardListItem/types.ts b/packages/components/src/CardListItem/types.ts new file mode 100644 index 0000000000..e54f9a6c27 --- /dev/null +++ b/packages/components/src/CardListItem/types.ts @@ -0,0 +1,29 @@ +import type { ProfileTypeName } from 'oa-shared' + +type UserBadges = { + verified: boolean + supporter: boolean +} + +export interface IProfileCreator { + _id: string + _lastActive: string + about?: string + badges?: UserBadges + countryCode: string + coverImage?: string + displayName: string + isContactableByPublic: boolean + profileType: ProfileTypeName + subType?: string + userImage?: string +} + +export interface ListItem { + _id: string + type: ProfileTypeName + isVerified?: boolean + isSupporter?: boolean + subType?: string + creator?: IProfileCreator +} diff --git a/packages/components/src/Username/Username.tsx b/packages/components/src/Username/Username.tsx index 00080578f0..11ebd69d4d 100644 --- a/packages/components/src/Username/Username.tsx +++ b/packages/components/src/Username/Username.tsx @@ -12,16 +12,72 @@ import type { User } from '../types/common' export interface IProps { user: User - hideFlag?: boolean sx?: ThemeUIStyleObject + isLink?: boolean } const isValidCountryCode = (str: string) => str && twoCharacterCountryCodes.has(str.toUpperCase()) -export const Username = ({ user, hideFlag, sx }: IProps) => { +export const Username = ({ user, sx, isLink = true }: IProps) => { const { countryCode, userName, isSupporter, isVerified } = user + const UserNameBody = ( + + + {countryCode && isValidCountryCode(countryCode) ? ( + + + + ) : ( + + )} + + + {userName} + {isVerified && ( + + )} + {isSupporter && !isVerified && ( + + )} + + ) + + if (!isLink) { + return UserNameBody + } + return ( { '&:hover': { borderColor: '#20B7EB', background: 'softblue', - color: 'bluetag', + textcolor: 'bluetag', }, ...(sx || {}), }} > - - {!hideFlag && ( - - {countryCode && isValidCountryCode(countryCode) ? ( - - - - ) : ( - - )} - - )} - {userName} - {isVerified && ( - - )} - {isSupporter && !isVerified && ( - - )} - + {UserNameBody} ) } diff --git a/packages/cypress/src/integration/settings.spec.ts b/packages/cypress/src/integration/settings.spec.ts index f222dc690a..594a4621f8 100644 --- a/packages/cypress/src/integration/settings.spec.ts +++ b/packages/cypress/src/integration/settings.spec.ts @@ -124,7 +124,7 @@ describe('[Settings]', () => { cy.get('[data-cy="profile-link"]').should('have.attr', 'href', url) cy.step('Can add map pin') - cy.get('[data-cy=EditYourProfile]').click({force: true}) + cy.get('[data-cy=EditYourProfile]').click({ force: true }) cy.get('[data-cy="tab-Map"]').click() cy.get('[data-cy=descriptionMember').should('be.visible') cy.contains('No map pin currently saved') diff --git a/src/pages/Maps/Content/MapView/MapWithList.tsx b/src/pages/Maps/Content/MapView/MapWithList.tsx index 2895913899..f0232a78f1 100644 --- a/src/pages/Maps/Content/MapView/MapWithList.tsx +++ b/src/pages/Maps/Content/MapView/MapWithList.tsx @@ -60,11 +60,10 @@ export const MapWithList = (props: IProps) => { background: 'white', flex: 1, overflow: 'scroll', - padding: 4, - gap: 4, + padding: 2, }} > - + Welcome to our world!{' '} {pins && `${pins.length} members (and counting...)`}