diff --git a/src/custom/CustomCatalog/custom-card.tsx b/src/custom/CustomCatalog/custom-card.tsx new file mode 100644 index 00000000..a73d1b09 --- /dev/null +++ b/src/custom/CustomCatalog/custom-card.tsx @@ -0,0 +1,267 @@ +import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; +import { Avatar, Box, Typography, styled } from '@mui/material'; +import React from 'react'; +import { Grid } from '../../base'; +import { CloneIcon, CommunityClassIcon, OfficialClassIcon, OpenIcon, ShareIcon } from '../../icons'; +import VerificationClassIcon from '../../icons/ContentClassIcons/VerificationClassIcon'; +import DeploymentsIcon from '../../icons/Deployments/DeploymentsIcon'; +import { DownloadIcon } from '../../icons/Download'; +import { + CardBack, + CardFront, + DateText, + DateType, + DesignAuthorName, + DesignCard, + DesignDetailsDiv, + DesignInnerCard, + DesignName, + DesignType, + MetricsContainerFront, + MetricsCount, + MetricsDiv, + ProfileSection, + StyledClassWrapper, + StyledInnerClassWrapper, + TechnologiesSection, + VersionTag +} from './style'; + +export const DesignCardUrl = styled('a')(() => ({ + textDecoration: 'none' +})); + +interface Pattern { + name: string; + download_count: number; + clone_count: number; + view_count: number; + deployment_count: number; + share_count: number; + userData?: { + version?: string; + avatarUrl?: string; + userName?: string; + technologies?: string[]; + updatedAt?: string; + }; + catalog_data?: { + content_class?: string; + imageURL?: string; + }; + visibility: string; + updated_at: Date; +} + +type CatalogCardProps = { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + pattern: Pattern; + patternType: string; + cardLink: string; + cardHeight: string; + cardWidth: string; + cardStyles: React.CSSProperties; + type: string; + version?: string; + avatarUrl: string; + userName: string; + technologies: string[]; + updatedAt: string; + shouldFlip?: boolean; + cardTechnologies?: boolean; + isDetailed?: boolean; + cardAvatarUrl?: boolean; + date?: boolean; + cardVersion?: boolean; + UserName?: string; + children?: React.ReactNode; +}; + +export const ClassToIconMap = { + community: , + official: , + verified: +}; + +const ClassWrap = ({ catalogClassName }: { catalogClassName: string }) => { + if (!catalogClassName) return <>; + + return ( + + + {catalogClassName} + + + ); +}; + +const CustomCatalogCard: React.FC = ({ + pattern, + patternType, + cardHeight, + cardWidth, + cardStyles, + cardLink, + shouldFlip, + isDetailed, + cardAvatarUrl, + cardTechnologies, + date, + cardVersion, + avatarUrl, + UserName, + children +}) => { + const outerStyles = { + height: cardHeight, + width: cardWidth, + ...cardStyles + }; + + return ( + + + + + {isDetailed && ( + <> + + {patternType} + + + {pattern.name} + + + )} + +
+ {children} +
+
+ {isDetailed && ( + + + + {pattern.download_count} + + + + {pattern.clone_count} + + + + {pattern.view_count} + + + + {pattern.deployment_count} + + + + {pattern.share_count} + + + )} +
+ {shouldFlip && ( + + {cardAvatarUrl && ( + + + {UserName} + + )} + + + {cardTechnologies && ( + + + Technologies + + + Kubernetes + + + )} + + + {date && ( + + + +
+ + Updated At +
+ + {' '} + {new Date(pattern.updated_at.toString().slice(0, 10)).toLocaleDateString( + 'en-US', + { + day: 'numeric', + month: 'long', + year: 'numeric' + } + )} + +
+
+
+ )} + + {cardVersion && ( + + v{cardVersion} + + )} +
+ )} +
+
+
+ ); +}; + +export default CustomCatalogCard; diff --git a/src/custom/CustomCatalog/index.tsx b/src/custom/CustomCatalog/index.tsx new file mode 100644 index 00000000..09adbc5c --- /dev/null +++ b/src/custom/CustomCatalog/index.tsx @@ -0,0 +1,3 @@ +import CustomCatalogCard from './custom-card'; + +export { CustomCatalogCard }; diff --git a/src/custom/CustomCatalog/style.tsx b/src/custom/CustomCatalog/style.tsx new file mode 100644 index 00000000..ee81ec55 --- /dev/null +++ b/src/custom/CustomCatalog/style.tsx @@ -0,0 +1,342 @@ +import { styled, Typography } from '@mui/material'; + +type DesignCardProps = { + outerStyles: React.CSSProperties; + shouldFlip?: boolean; + isDetailed?: boolean; +}; +type DesignCardDivProps = { + shouldFlip?: boolean; + isDetailed?: boolean; +}; +type MetricsProps = { + isDetailed?: boolean; +}; +type CatalogProps = { + isCatalog?: boolean; +}; +type StyledInnerClassWrapperProps = { + catalogClassName: string; +}; +export const StyledClassWrapper = styled('div')(() => ({ + width: '85px', + height: '88px', + overflow: 'hidden', + position: 'absolute', + top: '-3px', + left: '-3px' +})); + +export const StyledInnerClassWrapper = styled('div')(({ + catalogClassName +}) => { + const mapToColor: Record = { + community: 'rgba(122,132,142,.8)', + official: '#EBC017', + verified: '#00B39F' + }; + return { + font: 'bold 10px sans-serif', + WebkitTransform: 'rotate(-45deg)', + textAlign: 'center', + transform: 'rotate(-45deg)', + position: 'relative', + padding: '4px 0', + top: '15px', + left: '-30px', + width: '120px', + display: 'flex', + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + backgroundColor: mapToColor[catalogClassName], + color: '#fff' + }; +}); + +export const DesignCard = styled('div')( + ({ shouldFlip, isDetailed, outerStyles, theme }) => ({ + position: 'relative', + borderRadius: '1rem', + textAlign: 'center', + transformStyle: 'preserve-3d', + display: 'block', + perspective: '1000px', + transition: 'all .9s ease-out', + ...(shouldFlip && { + '&:hover': { + cursor: 'pointer', + '& .innerCard': { + transform: 'rotateY(180deg)' + } + } + }), + ...(isDetailed && { + [theme.breakpoints.down('lg')]: { + height: '18.75rem' + } + }), + ...outerStyles + }) +); + +export const DesignInnerCard = styled('div')(({ shouldFlip, isDetailed }) => ({ + position: 'relative', + width: '100%', + height: '100%', + textAlign: 'center', + transition: 'transform 0.6s', + ...(shouldFlip && { + transformOrigin: '50% 50%', + transformStyle: 'preserve-3d' + }), + ...(isDetailed && { + boxShadow: '0 4px 8px 0 rgba(0,0,0,0.2)', + borderRadius: '0.9375rem' + }) +})); + +export const DesignType = styled('span')(({ theme }) => ({ + position: 'absolute', + top: '0', + right: '0', + minWidth: '3rem', + padding: '0 0.75rem', + fontSize: '0.875rem', + textTransform: 'capitalize', + background: theme.palette.background.brand?.default, + color: theme.palette.text.inverse, + borderRadius: '0 1rem 0 2rem' +})); +export const MetricsCount = styled('p')(({ theme }) => ({ + fontSize: '1rem', + textTransform: 'capitalize', + margin: '0rem', + lineHeight: '1.5', + textAlign: 'center', + color: theme.palette.text.secondary, + fontWeight: '600' +})); +export const DesignName = styled(Typography)(({ theme }) => ({ + fontWeight: 'bold', + textTransform: 'capitalize', + color: theme.palette.text.default, + fontSize: '1.125rem', + marginTop: '2rem', + padding: '0rem 1rem', // "0rem 1.5rem" + position: 'relative', + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + textAlign: 'center', + width: '100%' +})); +export const MetricsContainerFront = styled('div')(({ isDetailed }) => ({ + display: 'flex', + justifyContent: 'space-around', + // borderTop: "0.851px solid #C9DBE3", + fontSize: '0.2rem', + color: 'rgba(26, 26, 26, .8)', + // margin: "-0.8rem 0.7rem 0", + padding: '0.9rem 0.1rem', + background: '#E7EFF3', + ...(isDetailed && { + position: 'absolute', + bottom: '0px' + }), + ...(!isDetailed && { + marginTop: '1.2rem' + }), + borderRadius: '0 0 0.9375rem 0.9375rem', + width: '100%' +})); + +export const MetricsDiv = styled('div')(() => ({ + display: 'flex', + alignItems: 'center', + gap: '4px', + fontSize: '0.2rem', + color: 'rgba(26, 26, 26, .8)', + margin: '0rem', + padding: '0.1rem' +})); +export const DesignDetailsDiv = styled('div')(() => ({ + height: 'max-content', + display: 'flex', + marginTop: '-1rem', + flexDirection: 'column', + padding: '0rem 1rem', + justifyContent: 'start', + alignItems: 'start', + ['@media (max-width:1200px)']: { + height: 'max-content' + } +})); + +export const ImageWrapper = styled('div')(({ theme }) => ({ + background: theme.palette.mode === 'light' ? 'rgba(231, 239, 243, 0.40)' : '#212121', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + padding: '0.5rem', + width: '100%', + borderRadius: '0.5rem' +})); + +export const VersionTag = styled('div')(({ theme }) => ({ + display: 'inline-block', + backgroundColor: theme.palette.background.supplementary, + color: theme.palette.text.constant?.white, + borderRadius: '4px', + fontSize: '0.75rem', + fontWeight: 'bold', + margin: '5px 0', + padding: '2px 5px', + maxWidth: 'fit-content' +})); + +export const FlipCard = styled('div')(() => ({ + perspective: '1000px', + '&:hover .flipper': { + transform: 'rotateY(-180deg)' + } +})); + +export const Flipper = styled('div')(() => ({ + transition: '0.6s', + transformStyle: 'preserve-3d', + position: 'relative' +})); + +export const Face = styled('div')(() => ({ + backfaceVisibility: 'hidden', + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%' +})); + +export const FrontFace = styled(Face)(() => ({ + zIndex: 2, + transform: 'rotateY(0deg)' +})); + +export const BackFace = styled('div')(() => ({ + transform: 'rotateY(-180deg)', + color: '#fff', + display: 'inline-flex', + flexDirection: 'column', + padding: '16px', + height: '100%', + width: '100%', + position: 'relative', + bottom: 0, + left: 0, + backfaceVisibility: 'hidden' +})); + +export const BackFaceContent = styled('div')(({ theme }) => ({ + position: 'absolute', + background: `linear-gradient(to bottom right, black 40%, ${theme.palette.background.brand?.default})`, + width: '100%', + top: 0, + left: 0, + display: 'flex', + flexDirection: 'column', + alignItems: 'left', + padding: '16px', + boxShadow: `2px 2px 3px 0px black`, + borderRadius: '1rem' +})); + +export const ProfileSection = styled('div')({ + display: 'flex', + alignItems: 'center', + marginBottom: '16px' +}); + +export const TechnologiesSection = styled('div')(({ theme }) => ({ + backgroundColor: 'rgba(255, 255, 255, 0.25)', + padding: theme.spacing(1), + borderRadius: theme.shape.borderRadius, + marginBottom: '16px' +})); + +export const UpdatedSection = styled('div')({ + display: 'flex', + alignItems: 'center', + color: '#fff', + margin: '20px 0' +}); + +export const CardBack = styled('div')(({ isCatalog }) => ({ + boxShadow: `2px 2px 3px 0px rgba(26, 26, 26, 1)`, + position: 'absolute', + width: '100%', + height: '100%', + WebkitBackfaceVisibility: 'hidden', + borderRadius: '0.9375rem', + backfaceVisibility: 'hidden', + color: 'white', + transform: 'rotateY(180deg)', + ...(isCatalog && { + background: + 'linear-gradient(335deg, rgba(0, 179, 159, 0.80) -13.6%, rgba(0, 0, 0, 0.68) 66.8%), radial-gradient(3970.04% 147.22% at 47.5% 100%, #000 0%, #395357 100%)' + }), + ...(!isCatalog && { + background: 'linear-gradient(250deg, #477e96 0%, #00b39f 35%, rgb(60, 73, 79) 100%)' + }) +})); + +export const CardFront = styled('div')(({ shouldFlip, isDetailed, theme }) => ({ + ...(shouldFlip && { + position: 'absolute', + boxShadow: `2px 2px 3px 0px ${theme.palette.background.brand?.default}`, + background: `linear-gradient(to left bottom, #EBEFF1, #f4f5f7, #f7f7f9, white, white, white, white, white, white, #f7f7f9, #f4f5f7, #EBEFF1);` + }), + ...(isDetailed && { + boxShadow: `2px 2px 3px 0px ${theme.palette.background.brand?.default}`, + background: `linear-gradient(to left bottom, #EBEFF1, #f4f5f7, #f7f7f9, white, white, white, white, white, white, #f7f7f9, #f4f5f7, #EBEFF1);` + }), + width: '100%', + height: '100%', + WebkitBackfaceVisibility: 'hidden', + borderRadius: '0.9375rem', + backfaceVisibility: 'hidden' +})); + +export const DateText = styled('div')(() => ({ + fontSize: '0.875rem', + textTransform: 'capitalize', + color: '#eee', + margin: '0rem', + padding: '0.1rem', + fontWeight: '400', + lineHeight: '1.5' +})); + +export const DateType = styled('p')(() => ({ + fontSize: '0.876rem', + margin: '0rem', + lineHeight: '1.5', + fontWeight: '400', + color: '#eee' +})); + +export const DesignAuthorName = styled('div')(() => ({ + height: 'max-content', + display: 'flex', + margin: '0', + flexDirection: 'column', + padding: '0rem 1rem', + justifyContent: 'start', + alignItems: 'start', + fontWeight: '400', + textAlign: 'right', + color: '#E7EFF3', + textTransform: 'capitalize', + ['@media (max-width:1200px)']: { + height: 'max-content' + } +})); diff --git a/src/custom/index.tsx b/src/custom/index.tsx index b2fd178a..24b20882 100644 --- a/src/custom/index.tsx +++ b/src/custom/index.tsx @@ -3,6 +3,7 @@ import { BookmarkNotification } from './BookmarkNotification'; import CatalogFilter, { CatalogFilterProps } from './CatalogFilter/CatalogFilter'; import { ChapterCard } from './ChapterCard'; import { ConnectionChip } from './ConnectionChip'; +import { CustomCatalogCard } from './CustomCatalog'; import { CustomColumn, CustomColumnVisibilityControl, @@ -57,6 +58,7 @@ export { CatalogFilter, ChapterCard, ConnectionChip, + CustomCatalogCard, CustomColumnVisibilityControl, CustomDialog, CustomImage,