Skip to content

Commit 4f64ab6

Browse files
committed
feat: add similar design by type
Signed-off-by: TheFaheem <faheemmushtaq89@gmail.com>
1 parent 968af22 commit 4f64ab6

9 files changed

Lines changed: 226 additions & 31 deletions

File tree

src/custom/CatalogDetail/RelatedDesigns.tsx

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1+
import { ChevronLeft, ChevronRight } from '@mui/icons-material';
2+
import { useRef } from 'react';
13
import { CatalogCardDesignLogo } from '../CustomCatalog';
24
import CustomCatalogCard, { Pattern } from '../CustomCatalog/CustomCard';
35
import { getHeadingText } from './helper';
4-
import { AdditionalContainer, ContentHeading, DesignCardContainer } from './style';
6+
import {
7+
AdditionalContainer,
8+
CarouselButton,
9+
CarouselContainer,
10+
CarouselWrapper,
11+
ContentHeading
12+
} from './style';
513
import { UserProfile } from './types';
614

715
export interface PatternsPerUser {
@@ -31,42 +39,62 @@ const RelatedDesigns: React.FC<RelatedDesignsProps> = ({
3139
orgName,
3240
fetchingOrgError
3341
}) => {
42+
const carouselRef = useRef<HTMLDivElement>(null);
3443
const filteredPatternsPerUser = patternsPerUser?.patterns?.filter(
3544
(pattern) => pattern.id !== details.id
3645
);
3746

3847
if (!filteredPatternsPerUser?.length) return null;
3948
const organizationName = fetchingOrgError || !orgName ? 'Unknown Organization' : orgName;
49+
50+
const scroll = (direction: 'left' | 'right') => {
51+
if (carouselRef.current) {
52+
const scrollAmount = 300; // Adjust scroll distance per click
53+
carouselRef.current.scrollBy({
54+
left: direction === 'left' ? -scrollAmount : scrollAmount,
55+
behavior: 'smooth'
56+
});
57+
}
58+
};
4059
return (
4160
<AdditionalContainer>
4261
<ContentHeading>
4362
<h2 style={{ margin: '0', textTransform: 'uppercase' }}>
4463
{getHeadingText({ type, userProfile, organizationName, fetchingOrgError })}
4564
</h2>
4665
</ContentHeading>
47-
<DesignCardContainer>
48-
{filteredPatternsPerUser.map((pattern, index) => (
49-
<CustomCatalogCard
50-
key={`design-${index}`}
51-
pattern={pattern}
52-
patternType={type}
53-
onCardClick={() => onSuggestedPatternClick(pattern)}
54-
UserName={`${userProfile?.first_name ?? ''} ${userProfile?.last_name ?? ''}`}
55-
avatarUrl={userProfile?.avatar_url}
56-
basePath={technologySVGPath}
57-
subBasePath={technologySVGSubpath}
58-
cardTechnologies={true}
59-
>
60-
<CatalogCardDesignLogo
61-
imgURL={pattern?.catalog_data?.imageURL}
62-
height={'7.5rem'}
63-
width={'100%'}
64-
zoomEffect={false}
65-
type={{ type: type }}
66-
/>
67-
</CustomCatalogCard>
68-
))}
69-
</DesignCardContainer>
66+
<CarouselWrapper>
67+
<CarouselButton onClick={() => scroll('left')}>
68+
<ChevronLeft />
69+
</CarouselButton>
70+
<CarouselContainer ref={carouselRef}>
71+
{filteredPatternsPerUser.map((pattern, index) => (
72+
<div key={`design-${index}`} className="carousel-item">
73+
<CustomCatalogCard
74+
pattern={pattern}
75+
patternType={type}
76+
onCardClick={() => onSuggestedPatternClick(pattern)}
77+
UserName={`${userProfile?.first_name ?? ''} ${userProfile?.last_name ?? ''}`}
78+
avatarUrl={userProfile?.avatar_url}
79+
basePath={technologySVGPath}
80+
subBasePath={technologySVGSubpath}
81+
cardTechnologies={true}
82+
>
83+
<CatalogCardDesignLogo
84+
imgURL={pattern?.catalog_data?.imageURL}
85+
height={'5.5rem'}
86+
width={'100%'}
87+
zoomEffect={false}
88+
type={{ type: type }}
89+
/>
90+
</CustomCatalogCard>
91+
</div>
92+
))}
93+
</CarouselContainer>
94+
<CarouselButton onClick={() => scroll('right')}>
95+
<ChevronRight />
96+
</CarouselButton>
97+
</CarouselWrapper>
7098
</AdditionalContainer>
7199
);
72100
};

src/custom/CatalogDetail/RightPanel.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import { VIEW_VISIBILITY } from '../VisibilityChipMenu/VisibilityChipMenu';
44
import CaveatsSection from './CaveatsSection';
55
import OverviewSection from './OverviewSection';
66
import RelatedDesigns, { PatternsPerUser } from './RelatedDesigns';
7+
import SimilarDesign, { DetailsByType } from './SimilarDesign';
78
import { Class } from './types';
89

910
interface RightPanelProps {
1011
details: Pattern;
12+
detailsByType: DetailsByType;
1113
type: string;
1214
cardId?: string;
1315
title: string;
@@ -35,6 +37,7 @@ interface RightPanelProps {
3537

3638
const RightPanel: React.FC<RightPanelProps> = ({
3739
details,
40+
detailsByType,
3841
type,
3942
cardId = details.id,
4043
title,
@@ -64,7 +67,7 @@ const RightPanel: React.FC<RightPanelProps> = ({
6467
});
6568

6669
return (
67-
<div style={{ fontFamily }}>
70+
<div>
6871
<OverviewSection
6972
details={details}
7073
type={cleanedType}
@@ -95,6 +98,18 @@ const RightPanel: React.FC<RightPanelProps> = ({
9598
technologySVGPath={technologySVGPath}
9699
technologySVGSubpath={technologySVGSubpath}
97100
/>
101+
<SimilarDesign
102+
details={details}
103+
detailsByType={detailsByType}
104+
orgName={orgName}
105+
fetchingOrgError={fetchingOrgError}
106+
type={type}
107+
patternsPerUser={patternsPerUser}
108+
onSuggestedPatternClick={onSuggestedPatternClick}
109+
userProfile={userProfile}
110+
technologySVGPath={technologySVGPath}
111+
technologySVGSubpath={technologySVGSubpath}
112+
/>
98113
</div>
99114
);
100115
};
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { ChevronLeft, ChevronRight } from '@mui/icons-material';
2+
import { useRef } from 'react';
3+
import { CatalogCardDesignLogo } from '../CustomCatalog';
4+
import CustomCatalogCard, { Pattern } from '../CustomCatalog/CustomCard';
5+
import {
6+
AdditionalContainer,
7+
CarouselButton,
8+
CarouselContainer,
9+
CarouselWrapper,
10+
ContentHeading
11+
} from './style';
12+
import { UserProfile } from './types';
13+
14+
export interface PatternsPerUser {
15+
patterns: Pattern[];
16+
}
17+
export interface DetailsByType {
18+
patterns: Pattern[];
19+
}
20+
interface SimilarDesignProps {
21+
details: Pattern;
22+
detailsByType: DetailsByType;
23+
type: string;
24+
patternsPerUser: PatternsPerUser;
25+
onSuggestedPatternClick: (pattern: Pattern) => void;
26+
userProfile?: UserProfile;
27+
technologySVGPath: string;
28+
technologySVGSubpath: string;
29+
orgName: string;
30+
fetchingOrgError: boolean;
31+
}
32+
33+
const SimilarDesign: React.FC<SimilarDesignProps> = ({
34+
details,
35+
detailsByType,
36+
type,
37+
onSuggestedPatternClick,
38+
userProfile,
39+
technologySVGPath,
40+
technologySVGSubpath
41+
}) => {
42+
const carouselRef = useRef<HTMLDivElement>(null);
43+
44+
const filteredPatterns = detailsByType?.patterns?.filter((pattern) => pattern.id !== details.id);
45+
46+
if (!filteredPatterns?.length) return null;
47+
const organizationName = 'Similar Designs by Type';
48+
49+
const scroll = (direction: 'left' | 'right') => {
50+
if (carouselRef.current) {
51+
const scrollAmount = 300; // Adjust scroll distance per click
52+
carouselRef.current.scrollBy({
53+
left: direction === 'left' ? -scrollAmount : scrollAmount,
54+
behavior: 'smooth'
55+
});
56+
}
57+
};
58+
59+
return (
60+
<AdditionalContainer>
61+
<ContentHeading>
62+
<h2 style={{ margin: '0', textTransform: 'uppercase' }}>{organizationName}</h2>
63+
</ContentHeading>
64+
<CarouselWrapper>
65+
<CarouselButton onClick={() => scroll('left')}>
66+
<ChevronLeft />
67+
</CarouselButton>
68+
<CarouselContainer ref={carouselRef}>
69+
{filteredPatterns.map((pattern, index) => (
70+
<div key={`design-${index}`} className="carousel-item">
71+
<CustomCatalogCard
72+
pattern={pattern}
73+
patternType={type}
74+
onCardClick={() => onSuggestedPatternClick(pattern)}
75+
UserName={`${userProfile?.first_name ?? ''} ${userProfile?.last_name ?? ''}`}
76+
avatarUrl={userProfile?.avatar_url}
77+
basePath={technologySVGPath}
78+
subBasePath={technologySVGSubpath}
79+
cardTechnologies={true}
80+
>
81+
<CatalogCardDesignLogo
82+
imgURL={pattern?.catalog_data?.imageURL}
83+
height={'7.5rem'}
84+
width={'100%'}
85+
zoomEffect={false}
86+
type={{ type: type }}
87+
/>
88+
</CustomCatalogCard>
89+
</div>
90+
))}
91+
</CarouselContainer>
92+
<CarouselButton onClick={() => scroll('right')}>
93+
<ChevronRight />
94+
</CarouselButton>
95+
</CarouselWrapper>
96+
</AdditionalContainer>
97+
);
98+
};
99+
100+
export default SimilarDesign;

src/custom/CatalogDetail/style.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,51 @@ export const ContentHeading = styled('div')(() => ({
6868
width: '100%',
6969
marginBottom: '1rem'
7070
}));
71+
export const CarouselContainer = styled('div')({
72+
display: 'flex',
73+
overflowX: 'auto',
74+
scrollBehavior: 'smooth',
75+
scrollSnapType: 'x mandatory',
76+
gap: '1rem',
77+
padding: '1rem 0',
78+
width: '100%',
79+
'&::-webkit-scrollbar': {
80+
display: 'none' // Hide scrollbar for a cleaner look
81+
},
82+
'.carousel-item': {
83+
flex: '0 0 auto',
84+
scrollSnapAlign: 'center',
85+
width: 'auto' // Adjust based on your card size
86+
}
87+
});
88+
export const CarouselButton = styled('button')(({ theme }) => ({
89+
position: 'absolute',
90+
top: '50%',
91+
transform: 'translateY(-50%)',
92+
zIndex: '1',
93+
background: theme.palette.background.paper,
94+
border: 'none',
95+
cursor: 'pointer',
96+
padding: '0.5rem',
97+
borderRadius: '50%',
98+
boxShadow: '0 2px 4px rgba(0, 0, 0, 0.2)',
99+
'&:hover': {
100+
background: theme.palette.primary.main,
101+
color: '#fff'
102+
},
103+
'&:first-of-type': {
104+
left: '-2rem'
105+
},
106+
'&:last-of-type': {
107+
right: '-2rem'
108+
}
109+
}));
110+
export const CarouselWrapper = styled('div')({
111+
display: 'flex',
112+
alignItems: 'center',
113+
width: '100%',
114+
position: 'relative'
115+
});
71116

72117
export const CaveatsContainer = styled('div')(({ theme }) => ({
73118
width: '100%',

src/custom/CustomCatalog/CustomCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ const ClassWrap = ({ catalogClassName }: { catalogClassName: string }) => {
114114
const CustomCatalogCard: React.FC<CatalogCardProps> = ({
115115
pattern,
116116
patternType,
117-
cardHeight = '18rem',
117+
cardHeight = '16.5rem',
118118
cardWidth = '15rem',
119119
cardStyles,
120120
shouldFlip = true,

src/custom/CustomCatalog/style.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export const DesignCard = styled('div')<DesignCardProps>(
9393
}),
9494
...(isDetailed && {
9595
[theme.breakpoints.down('lg')]: {
96-
height: '18.75rem'
96+
height: '16.75rem'
9797
}
9898
}),
9999
...outerStyles
@@ -150,7 +150,7 @@ export const DesignName = styled(Typography)(({ theme }) => ({
150150
textOverflow: 'ellipsis',
151151
textAlign: 'center',
152152
width: '100%',
153-
margin: '3rem 0 1.59rem 0',
153+
margin: '2rem 0 1.59rem 0',
154154
fontFamily: 'inherit'
155155
}));
156156

src/custom/PerformersSection/PerformersToogleButton.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@ const PerformersSectionButton: React.FC<PerformersSectionButtonProps> = ({ open,
2121
onClick={handleClick}
2222
sx={{
2323
height: '3.7rem',
24-
padding: '0rem'
24+
padding: '0.3rem'
2525
}}
2626
style={{
2727
backgroundColor: open ? undefined : theme.palette.background.constant?.disabled
2828
}}
2929
>
30-
<TropyIcon style={{ height: '2rem', width: '2rem' }} />
30+
<TropyIcon style={{ height: '2rem', width: '2rem', marginRight: '10px' }} />
31+
{open ? 'Hide Performers' : 'Show Performers'}
3132
</Button>
3233
</span>
3334
</CustomTooltip>

src/custom/ResponsiveDataTable.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,12 @@ const dataTableTheme = (theme: Theme, backgroundColor?: string) =>
243243
root: {
244244
'&.Mui-disabled': {
245245
cursor: 'not-allowed'
246+
},
247+
'&:nth-of-type(even)': {
248+
backgroundColor: theme.palette.action.hover
249+
},
250+
'&:nth-of-type(odd)': {
251+
backgroundColor: theme.palette.background.default
246252
}
247253
}
248254
}

src/icons/Copy/CopyIcon.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface CopyIconProps {
88
secondaryFill?: string;
99
}
1010

11-
const CopyIcon: React.FC<CopyIconProps> = ({ width, height, fill = 'white', style }) => (
11+
const CopyIcon: React.FC<CopyIconProps> = ({ width, height, fill = '#3C494F', style }) => (
1212
<svg
1313
xmlns="http://www.w3.org/2000/svg"
1414
width={width}

0 commit comments

Comments
 (0)