Skip to content

Commit

Permalink
[GAL-5439] add default state for web search results (#2391)
Browse files Browse the repository at this point in the history
* featured collection query working!

* much better styling for featured

* minor

* better

* refactored into sections

* some cleanup

* see all button working

* fixed layout styling

* feels better at least

* user routing working!!

* minor styling before main refactorzz

* cleaner

* still working

* lint

* lintt

* working

* better

* clean

* close

* search

* oh my

* oh my myy

* too late

* feeedback addressed
  • Loading branch information
Rohan-cp authored Apr 8, 2024
1 parent fe289b5 commit 4dbbb1a
Show file tree
Hide file tree
Showing 13 changed files with 661 additions and 26 deletions.
12 changes: 2 additions & 10 deletions apps/web/src/components/Explore/ExploreUserCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { contexts } from '~/shared/analytics/constants';
import { removeNullValues } from '~/shared/relay/removeNullValues';
import { useLoggedInUserId } from '~/shared/relay/useLoggedInUserId';
import colors from '~/shared/theme/colors';
import unescape from '~/shared/utils/unescape';
import { getUnescapedBioFirstLine } from '~/utils/sanity';

import Badge from '../Badge/Badge';
import breakpoints from '../core/breakpoints';
Expand Down Expand Up @@ -66,8 +66,7 @@ export default function ExploreUserCard({ userRef, queryRef }: Props) {
}

const { bio } = user;

const unescapedBio = useMemo(() => (bio ? unescape(bio) : ''), [bio]);
const bioFirstLine = useMemo(() => getUnescapedBioFirstLine(bio), [bio]);

const userGalleries = useMemo(() => {
return user.galleries ?? [];
Expand Down Expand Up @@ -95,13 +94,6 @@ export default function ExploreUserCard({ userRef, queryRef }: Props) {

const isMobile = useIsMobileWindowWidth();

const bioFirstLine = useMemo(() => {
if (!unescapedBio) {
return '';
}
return unescapedBio.split('\n')[0] ?? '';
}, [unescapedBio]);

return (
<StyledExploreUserCard
to={{
Expand Down
233 changes: 233 additions & 0 deletions apps/web/src/components/Feed/SuggestedProfileCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
import { useMemo } from 'react';
import { graphql, useFragment } from 'react-relay';
import styled from 'styled-components';

import { SuggestedProfileCardFollowFragment$key } from '~/generated/SuggestedProfileCardFollowFragment.graphql';
import { SuggestedProfileCardFragment$key } from '~/generated/SuggestedProfileCardFragment.graphql';
import { contexts } from '~/shared/analytics/constants';
import { removeNullValues } from '~/shared/relay/removeNullValues';
import { useLoggedInUserId } from '~/shared/relay/useLoggedInUserId';
import colors from '~/shared/theme/colors';
import { getUnescapedBioFirstLine } from '~/utils/sanity';

import Badge from '../Badge/Badge';
import breakpoints from '../core/breakpoints';
import Markdown from '../core/Markdown/Markdown';
import { HStack, VStack } from '../core/Spacer/Stack';
import { BaseM } from '../core/Text/Text';
import FollowButton from '../Follow/FollowButton';
import { ProfilePicture } from '../ProfilePicture/ProfilePicture';

type Props = {
userRef: SuggestedProfileCardFragment$key;
queryRef: SuggestedProfileCardFollowFragment$key;
showFollowButton?: boolean;
onClick?: () => void;
};

export default function SuggestedProfileCard({
userRef,
queryRef,
onClick,
showFollowButton = true,
}: Props) {
const user = useFragment(
graphql`
fragment SuggestedProfileCardFragment on GalleryUser {
id
username
badges {
name
imageURL
...BadgeFragment
}
bio
galleries {
tokenPreviews {
large
}
hidden
}
...ProfilePictureFragment
...FollowButtonUserFragment
}
`,
userRef
);

const query = useFragment(
graphql`
fragment SuggestedProfileCardFollowFragment on Query {
...FollowButtonQueryFragment
...useLoggedInUserIdFragment
}
`,
queryRef
);

const loggedInUserId = useLoggedInUserId(query);
const isOwnProfile = loggedInUserId && loggedInUserId === user?.id;

if (!user) {
throw new Error('No user available to showcase SuggestedProfileCard');
}

const bioFirstLine = useMemo(() => getUnescapedBioFirstLine(user?.bio), [user?.bio]);

const userGalleries = useMemo(() => {
return user.galleries ?? [];
}, [user.galleries]);

const tokenPreviews = useMemo(() => {
const gallery = userGalleries.find(
(gallery) => !gallery?.hidden && removeNullValues(gallery?.tokenPreviews).length > 0
);

return gallery?.tokenPreviews?.slice(0, 2) ?? [];
}, [userGalleries]);

const userBadges = useMemo(() => {
const badges = [];

for (const badge of user.badges ?? []) {
if (badge?.imageURL) {
badges.push(badge);
}
}

return badges;
}, [user.badges]);

const shouldShowFollowButton = useMemo(
() => showFollowButton && !isOwnProfile,
[showFollowButton, isOwnProfile]
);

return (
<StyledSuggestedProfileCard onClick={onClick}>
<StyledContent gap={4} justify="space-between">
<TokenPreviewContainer>
{tokenPreviews.map(
(url) => url?.large && <TokenPreview src={url.large} key={url.large} />
)}
</TokenPreviewContainer>
<ProfileDetailsContainer>
<ProfileDetailsText gap={4}>
<HStack gap={8} align="center" justify="space-between">
<HStack gap={4} align="center">
<ProfilePicture userRef={user} size="xs" />
<Username>
<strong>{user.username}</strong>
</Username>
<HStack align="center" gap={0}>
{userBadges.map((badge) => (
<Badge key={badge.name} badgeRef={badge} eventContext={contexts['Search']} />
))}
</HStack>
</HStack>
</HStack>
<VStack gap={8}>
<StyledUserBio>
<Markdown text={bioFirstLine} eventContext={contexts.Search} />
</StyledUserBio>
{shouldShowFollowButton && (
<WideFollowButton
userRef={user}
queryRef={query}
source="Search Default profile card"
/>
)}
</VStack>
</ProfileDetailsText>
</ProfileDetailsContainer>
</StyledContent>
</StyledSuggestedProfileCard>
);
}

const StyledSuggestedProfileCard = styled(HStack)`
border-radius: 4px;
background-color: ${colors.offWhite};
padding: 8px;
cursor: pointer;
text-decoration: none;
overflow: hidden;
&:hover {
background-color: ${colors.faint};
}
@media only screen and ${breakpoints.desktop} {
width: 230px;
}
`;

const StyledContent = styled(VStack)`
height: 100%;
width: 100%;
`;

const ProfileDetailsContainer = styled.div`
display: flex;
flex-direction: column;
gap: 8px;
width: 100%;
@media only screen and ${breakpoints.desktop} {
flex-direction: row;
justify-content: space-between;
align-items: center;
}
`;

const ProfileDetailsText = styled(VStack)`
overflow: hidden;
width: 100%;
`;

const StyledUserBio = styled(BaseM)`
height: 20px; // ensure consistent height even if bio is not present
font-size: 14px;
font-weight: 400;
line-clamp: 1;
overflow: hidden;
-webkit-line-clamp: 1;
display: -webkit-box;
-webkit-box-orient: vertical;
`;

export const TokenPreviewContainer = styled.div`
display: grid;
grid-template-columns: repeat(2, 1fr);
min-height: 97px;
grid-gap: 2px;
`;

export const TokenPreview = styled.img`
height: auto;
width: 100%;
aspect-ratio: 1 / 1;
object-fit: cover;
`;

const Username = styled(BaseM)`
font-size: 16px;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
`;

const WideFollowButton = styled(FollowButton)`
padding: 2px 8px;
width: 100%;
height: 24px;
line-height: 0;
@media only screen and ${breakpoints.desktop} {
width: 100%;
height: 24px;
}
`;
9 changes: 8 additions & 1 deletion apps/web/src/components/Search/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useTrack } from '~/shared/contexts/AnalyticsContext';
import { VStack } from '../core/Spacer/Stack';
import { Spinner } from '../core/Spinner/Spinner';
import { useSearchContext } from './SearchContext';
import SearchDefault from './SearchDefault';
import SearchFilter from './SearchFilter';
import SearchInput from './SearchInput';
import SearchResults from './SearchResults';
Expand Down Expand Up @@ -121,13 +122,19 @@ export default function Search() {
</StyledSpinnerContainer>
}
>
{keyword && (
{keyword ? (
<SearchResults
activeFilter={selectedFilter}
keyword={keyword}
onChangeFilter={setSelectedFilter}
onSelect={handleSelect}
/>
) : (
<SearchDefault
onSelect={handleSelect}
selectedFilter={selectedFilter}
onChangeFilter={setSelectedFilter}
/>
)}
</Suspense>
</StyledSearchContent>
Expand Down
72 changes: 72 additions & 0 deletions apps/web/src/components/Search/SearchDefault.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { graphql, useLazyLoadQuery } from 'react-relay';
import styled from 'styled-components';

import breakpoints from '~/components/core/breakpoints';
import { SearchDefaultQuery } from '~/generated/SearchDefaultQuery.graphql';

import { VStack } from '../core/Spacer/Stack';
import { SearchFilterType } from './Search';
import SearchDefaultSuggestedUsersSection from './SearchDefaultSuggestedUsersSection';
import SearchDefaultTrendingCuratorsSection from './SearchDefaultTrendingCuratorsSection';
import SearchDefaultTrendingUsersSection from './SearchDefaultTrendingUsersSection';
import { SearchItemType } from './types';

type Props = {
selectedFilter: SearchFilterType;
onChangeFilter: (filter: SearchFilterType) => void;
onSelect: (item: SearchItemType) => void;
variant?: 'default' | 'compact';
};

export default function SearchDefault({
variant = 'default',
onSelect,
selectedFilter,
onChangeFilter,
}: Props) {
const query = useLazyLoadQuery<SearchDefaultQuery>(
graphql`
query SearchDefaultQuery {
...SearchDefaultSuggestedUsersSectionFragment
...SearchDefaultTrendingUsersSectionFragment
...SearchDefaultTrendingCuratorsSectionFragment
}
`,
{}
);

return (
<SectionWrapper gap={20}>
{!selectedFilter && (
<VStack gap={16}>
<SearchDefaultSuggestedUsersSection
queryRef={query}
variant={variant}
onSelect={onSelect}
/>
<SearchDefaultTrendingUsersSection
queryRef={query}
variant={variant}
onSelect={onSelect}
/>
</VStack>
)}
<SearchDefaultTrendingCuratorsSection
queryRef={query}
variant={variant}
onSelect={onSelect}
selectedFilter={selectedFilter}
onChangeFilter={onChangeFilter}
showAllButton={true}
/>
</SectionWrapper>
);
}

const SectionWrapper = styled(VStack)`
padding: 4px;
@media only screen and ${breakpoints.desktop} {
padding: 12px;
}
`;
Loading

0 comments on commit 4dbbb1a

Please sign in to comment.