From 62db34aed011958fdc45a53b13decd466942e5ec Mon Sep 17 00:00:00 2001 From: Monalisha Mishra <42746736+mishramonalisha76@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:56:23 +0530 Subject: [PATCH] Channels listing and details page (#1861) * in progress * added listing api * Ui in progress * fixed type * implemented listing * shifted to api call for channel list * api fixes * fixed the ui of card and category * fixed param type * added fixed * scroll implemented * fixed the pagination for channel list * added listing and search * added preview * fixed the layout * channel details page * added responsiveness support * added layout variant * Update App.tsx * fixed category scroll (#1862) * added layout variant * fixed review comments * fixed review comments * channel category implemented * filters implmented * channels listing page done * debug turned off * fixed review comments * added null state * fixed channel search hook * PR fixes done * fixed the edit channel for category * fixed channel list search query * Wrapped channel img in Link * menu item label changes * fixes done * channel details card refactor * outline button fix and category scroll fix * spacing ui fixes done * category added to channel profile * added config channels * added config channels * fixed select * fixed select * added review changes --------- Co-authored-by: rohitmalhotra1420 --- src/App.tsx | 1 - src/blocks/button/Button.tsx | 3 +- src/blocks/icons/components/CaretLeft.tsx | 7 +- src/blocks/icons/components/CaretRight.tsx | 29 +- src/blocks/icons/components/Chat.tsx | 3 +- src/blocks/icons/components/Tutotial.tsx | 37 +++ src/blocks/icons/index.ts | 1 + src/blocks/index.ts | 1 + src/blocks/pill/Pill.tsx | 53 ++++ src/blocks/pill/index.ts | 1 + src/blocks/select/Select.tsx | 12 +- src/blocks/textInput/TextInput.tsx | 9 +- src/blocks/theme/colors/colors.semantics.ts | 4 + src/blocks/theme/semantics/semantics.pill.ts | 18 ++ src/common/Common.constants.ts | 97 ++++++ src/common/Common.types.ts | 2 + src/common/Common.utils.tsx | 28 ++ src/common/components/ChannelDetailsCard.tsx | 250 +++++++++++++++ src/common/components/ContentLayout.tsx | 28 +- src/common/components/CopyButton.tsx | 30 ++ .../components/UnsubscribeChannelDropdown.tsx | 2 +- .../VerifiedChannelTooltipContent.tsx} | 5 +- src/common/components/index.ts | 3 + .../channel/NotificationSettings.tsx | 2 +- src/config/AppPaths.ts | 70 ++--- src/modules/addNewChain/AddNewChain.tsx | 2 +- src/modules/addNewChain/AddNewChain.utils.tsx | 14 - .../components/VerifyAliasChain.tsx | 53 +++- .../channelDashboard/ChannelDashboard.tsx | 8 +- .../components/ChannelDashboardHeader.tsx | 18 +- .../components/ChannelDashboardInfo.tsx | 8 + src/modules/channelDetails/ChannelDetails.tsx | 64 ++++ .../channelDetails/ChannelDetails.utils.ts | 5 + .../components/ChannelDetail.tsx | 294 ++++++++++++++++++ .../components/ChannelDetailSubscribe.tsx | 69 ++++ .../channelDetails/components/ChannelList.tsx | 104 +++++++ .../components/ChannelTutorialContent.tsx | 112 +++++++ .../components/RecentNotifications.tsx | 100 ++++++ .../components/UserJourneyPreview.tsx | 32 ++ src/modules/channelDetails/index.ts | 1 + src/modules/channels/Channels.constants.ts | 2 + src/modules/channels/Channels.tsx | 132 ++++++++ src/modules/channels/Channels.utils.ts | 23 ++ src/modules/channels/ChannelsModule.tsx | 95 ------ .../channels/components/AllChannelsList.tsx | 89 ++++++ .../components/AllChannelsListItem.tsx | 42 +++ .../channels/components/ChannelCategories.tsx | 111 +++++++ .../ChannelSearchAndChainSelection.tsx | 65 ++++ .../components/SuggestedChannelListItem.tsx | 22 ++ .../channels/hooks/useChannelsFilters.ts | 57 ++++ src/modules/channels/index.tsx | 1 + .../createChannel/CreateChannel.form.tsx | 18 +- src/modules/createChannel/CreateChannel.tsx | 3 +- .../createChannel/CreateChannel.types.ts | 1 + .../createChannel/components/ChannelInfo.tsx | 19 +- .../createChannel/components/StakeFees.tsx | 5 +- src/modules/dashboard/Dashboard.styled.ts | 7 - src/modules/dashboard/Dashboard.utils.ts | 19 -- .../dashboard/components/ChannelListItem.tsx | 15 +- .../components/FeaturedChannelsListItem.tsx | 210 +------------ src/modules/editChannel/EditChannel.form.tsx | 28 +- src/modules/editChannel/EditChannel.types.ts | 1 + .../components/EditChannelDetails.tsx | 61 +++- .../components/EditChannelFooter.tsx | 36 ++- .../components/NotificationSettingsFooter.tsx | 4 +- src/pages/ChannelDashboardPageV2.tsx | 2 +- src/pages/ChannelDetailsPage.tsx | 12 + src/pages/ChannelsPage.jsx | 38 +-- src/pages/CreateChannelPage.tsx | 2 +- src/queries/hooks/channels/index.ts | 3 + .../hooks/channels/useChannelSearch.ts | 37 +++ .../hooks/channels/useGetChannelCategories.ts | 11 + .../hooks/channels/useGetChannelsList.ts | 38 +++ .../channels/channelSearchModelCreator.ts | 6 + .../getChannelCategoriesModelCreator.ts | 10 + .../channels/getChannelsListModelCreator.ts | 5 + src/queries/models/channels/index.ts | 3 + .../getRewardsLeaderboardModalCreator.ts | 1 + src/queries/queryKeys.ts | 3 + .../services/channels/channelSearch.ts | 18 ++ .../services/channels/getChannelCategories.ts | 10 + .../services/channels/getChannelsList.ts | 12 + .../services/channels/getTrendingChannels.ts | 4 +- src/queries/services/channels/index.ts | 2 + src/queries/types/channels.ts | 41 ++- src/segments/ViewChannels.tsx | 3 +- src/structure/MasterInterfacePage.tsx | 122 +------- src/structure/MobileNavigation.tsx | 67 +++- src/structure/Navigation.tsx | 2 +- 89 files changed, 2444 insertions(+), 654 deletions(-) create mode 100644 src/blocks/icons/components/Tutotial.tsx create mode 100644 src/blocks/pill/Pill.tsx create mode 100644 src/blocks/pill/index.ts create mode 100644 src/blocks/theme/semantics/semantics.pill.ts create mode 100644 src/common/components/ChannelDetailsCard.tsx create mode 100644 src/common/components/CopyButton.tsx rename src/{modules/dashboard/components/VerifiedToolTipComponent.tsx => common/components/VerifiedChannelTooltipContent.tsx} (77%) delete mode 100644 src/modules/addNewChain/AddNewChain.utils.tsx create mode 100644 src/modules/channelDetails/ChannelDetails.tsx create mode 100644 src/modules/channelDetails/ChannelDetails.utils.ts create mode 100644 src/modules/channelDetails/components/ChannelDetail.tsx create mode 100644 src/modules/channelDetails/components/ChannelDetailSubscribe.tsx create mode 100644 src/modules/channelDetails/components/ChannelList.tsx create mode 100644 src/modules/channelDetails/components/ChannelTutorialContent.tsx create mode 100644 src/modules/channelDetails/components/RecentNotifications.tsx create mode 100644 src/modules/channelDetails/components/UserJourneyPreview.tsx create mode 100644 src/modules/channelDetails/index.ts create mode 100644 src/modules/channels/Channels.constants.ts create mode 100644 src/modules/channels/Channels.tsx create mode 100644 src/modules/channels/Channels.utils.ts delete mode 100644 src/modules/channels/ChannelsModule.tsx create mode 100644 src/modules/channels/components/AllChannelsList.tsx create mode 100644 src/modules/channels/components/AllChannelsListItem.tsx create mode 100644 src/modules/channels/components/ChannelCategories.tsx create mode 100644 src/modules/channels/components/ChannelSearchAndChainSelection.tsx create mode 100644 src/modules/channels/components/SuggestedChannelListItem.tsx create mode 100644 src/modules/channels/hooks/useChannelsFilters.ts create mode 100644 src/modules/channels/index.tsx delete mode 100644 src/modules/dashboard/Dashboard.styled.ts create mode 100644 src/pages/ChannelDetailsPage.tsx create mode 100644 src/queries/hooks/channels/useChannelSearch.ts create mode 100644 src/queries/hooks/channels/useGetChannelCategories.ts create mode 100644 src/queries/hooks/channels/useGetChannelsList.ts create mode 100644 src/queries/models/channels/channelSearchModelCreator.ts create mode 100644 src/queries/models/channels/getChannelCategoriesModelCreator.ts create mode 100644 src/queries/models/channels/getChannelsListModelCreator.ts create mode 100644 src/queries/services/channels/channelSearch.ts create mode 100644 src/queries/services/channels/getChannelCategories.ts create mode 100644 src/queries/services/channels/getChannelsList.ts diff --git a/src/App.tsx b/src/App.tsx index c61ca13394..740d8688c7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -295,7 +295,6 @@ export default function App() { }, []); const steps = UserJourneySteps({ darkMode }); - const handleJoyrideCallback = (data: CallBackProps) => { const { action, lifecycle, index } = data; if (lifecycle === 'ready') { diff --git a/src/blocks/button/Button.tsx b/src/blocks/button/Button.tsx index ceef6f8d60..9aec7345d8 100644 --- a/src/blocks/button/Button.tsx +++ b/src/blocks/button/Button.tsx @@ -40,6 +40,7 @@ const StyledButton = styled.button` font-family: var(--font-family); justify-content: center; white-space: nowrap; + flex-shrink: 0; /* Common icon css added through CSS class */ .icon { @@ -56,7 +57,7 @@ const StyledButton = styled.button` ${({ iconOnly, size }) => getButtonSizeStyles({ iconOnly: !!iconOnly, size: size || 'medium' })} /* Circular CSS for rounded icon only buttons */ - ${({ circular, iconOnly }) => circular && iconOnly && `border-radius: var(--r10)`} + ${({ circular, iconOnly }) => circular && iconOnly && `border-radius: var(--r10);`} /* Prop specific CSS */ ${({ block }) => block && 'width: 100%;'} diff --git a/src/blocks/icons/components/CaretLeft.tsx b/src/blocks/icons/components/CaretLeft.tsx index 66d011bcec..1838f57c6e 100644 --- a/src/blocks/icons/components/CaretLeft.tsx +++ b/src/blocks/icons/components/CaretLeft.tsx @@ -9,16 +9,17 @@ const CaretLeft: FC = (allProps) => { componentName="CaretLeft" icon={ diff --git a/src/blocks/icons/components/CaretRight.tsx b/src/blocks/icons/components/CaretRight.tsx index b436b3d43e..6db77ed53b 100644 --- a/src/blocks/icons/components/CaretRight.tsx +++ b/src/blocks/icons/components/CaretRight.tsx @@ -9,19 +9,32 @@ const CaretRight: FC = (allProps) => { componentName="CaretRight" icon={ - + + + + + + + + } {...restProps} diff --git a/src/blocks/icons/components/Chat.tsx b/src/blocks/icons/components/Chat.tsx index f6e6c6d278..c05a999193 100644 --- a/src/blocks/icons/components/Chat.tsx +++ b/src/blocks/icons/components/Chat.tsx @@ -9,8 +9,7 @@ const Chat: FC = (allProps) => { componentName="Chat" icon={ = (allProps) => { + const { svgProps: props, ...restProps } = allProps; + return ( + + + + + } + {...restProps} + /> + ); +}; + +export default Tutorial; diff --git a/src/blocks/icons/index.ts b/src/blocks/icons/index.ts index 3b27fe14f1..089304d5b5 100644 --- a/src/blocks/icons/index.ts +++ b/src/blocks/icons/index.ts @@ -168,6 +168,7 @@ export { default as Swap } from './components/Swap'; export { default as Tick } from './components/Tick'; export { default as TickCircleFilled } from './components/TickCircleFilled'; export { default as TickDecoratedCircleFilled } from './components/TickDecoratedCircleFilled'; +export { default as Tutorial } from './components/Tutotial'; export { default as UserFilled } from './components/UserFilled'; diff --git a/src/blocks/index.ts b/src/blocks/index.ts index bd1534fafa..20c63aa278 100644 --- a/src/blocks/index.ts +++ b/src/blocks/index.ts @@ -9,6 +9,7 @@ export { Menu, type MenuProps, MenuItem, type MenuItemComponentProps } from './m export { Modal, type ModalProps, modal } from './modal'; export { notification, Notification } from './notification'; export { Pagination, type PaginationProps } from './pagination'; +export { Pill, type PillProps } from './pill'; export { ProgressBar, type ProgressBarProps } from './progressBar'; export { Separator, type SeparatorProps } from './separator'; export { Skeleton, type SkeletonProps } from './skeleton'; diff --git a/src/blocks/pill/Pill.tsx b/src/blocks/pill/Pill.tsx new file mode 100644 index 0000000000..1688da6aed --- /dev/null +++ b/src/blocks/pill/Pill.tsx @@ -0,0 +1,53 @@ +import { FC, ReactNode } from 'react'; +import styled, { FlattenSimpleInterpolation } from 'styled-components'; +import { TransformedHTMLAttributes } from '../Blocks.types'; +import { getTextVariantStyles } from '../Blocks.utils'; + +export type PillProps = { + /* Child react nodes rendered by Pill */ + children?: ReactNode; + /* Additional prop from styled components to apply custom css to Lozenge */ + css?: FlattenSimpleInterpolation; + /* Decides the UI state of the component */ + isActive?: boolean; +} & TransformedHTMLAttributes; + +const StyledPill = styled.div` + align-items: center; + border-radius: var(--radius-xl); + background: var(--components-pill-background-${({ isActive }) => (isActive ? 'selected' : 'default')}); + cursor: pointer; + display: flex; + flex-direction: column; + height: 40px; + justify-content: center; + max-width: max-content; + padding: var(--spacing-none) var(--spacing-sm); + + ${({ isActive }) => + getTextVariantStyles('bs-semibold', isActive ? 'components-pill-text-selected' : 'components-pill-text-default')} + + &:hover { + ${({ isActive }) => + !isActive && + `background: var(--components-pill-background-hover); + color: var(--components-pill-text-default);`} + } + + /* Custom CSS applied via styled component css prop */ + ${(props) => props.css || ''} +`; + +const Pill: FC = ({ children, isActive = false, onClick, ...props }) => { + return ( + + {children} + + ); +}; + +export { Pill }; diff --git a/src/blocks/pill/index.ts b/src/blocks/pill/index.ts new file mode 100644 index 0000000000..c32b085637 --- /dev/null +++ b/src/blocks/pill/index.ts @@ -0,0 +1 @@ +export * from './Pill'; diff --git a/src/blocks/select/Select.tsx b/src/blocks/select/Select.tsx index 0b13f7a46c..14b4a777f6 100644 --- a/src/blocks/select/Select.tsx +++ b/src/blocks/select/Select.tsx @@ -41,12 +41,12 @@ export type SelectProps = { action?: ReactNode; }; -const Container = styled.div<{ css?: FlattenSimpleInterpolation }>` +const Container = styled.div<{ css?: FlattenSimpleInterpolation; label: SelectProps['label'] }>` align-items: flex-start; display: flex; flex-direction: column; flex: 1 0 0; - gap: var(--spacing-xxs, 8px); + gap: var(--spacing-${({ label }) => (label ? 'xxs' : 'none')}); /* Custom CSS applied via styled component css prop */ ${(props) => props.css || ''}; @@ -215,7 +215,7 @@ const Select: React.FC = ({ disabled, }) => { const [popoverWidth, setPopoverWidth] = useState(0); - const [viewPopover, setViewPopover] = useState(true); + const [viewPopover, setViewPopover] = useState(false); const [popoverLeft, setPopoverLeft] = useState(0); const comboboxRef = useRef(null); const parentRef = useRef(null); @@ -253,9 +253,11 @@ const Select: React.FC = ({ const handleParentFocus = () => { childRef?.current?.focus(); }; - return ( - + diff --git a/src/blocks/textInput/TextInput.tsx b/src/blocks/textInput/TextInput.tsx index 5ea294f785..79ace207fe 100644 --- a/src/blocks/textInput/TextInput.tsx +++ b/src/blocks/textInput/TextInput.tsx @@ -21,12 +21,12 @@ export type TextInputProps = { value: string | number; }; -const Container = styled.div<{ css?: FlattenSimpleInterpolation }>` +const Container = styled.div<{ css?: FlattenSimpleInterpolation; label: TextInputProps['label'] }>` align-items: flex-start; display: flex; flex-direction: column; flex: 1 0 0; - gap: var(--spacing-xxs, 8px); + gap: var(--spacing-${({ label }) => (label ? 'xxs' : 'none')}); /* Custom CSS applied via styled component css prop */ ${(props) => props.css || ''}; @@ -151,7 +151,10 @@ export const TextInput = forwardRef( ref ) => { return ( - + {label && ( = { + '0xaa940b3501176af328423d975c350d0d1baaae50': 'DeFI', + '0x0e255B1900b8cE23f8E818C7Ee08cfd5b41df748': 'DeFI', + '0x7F41abf7fDb9E4A6373EC3BAB3Df814b5CCceCC3': 'DeFI', + '0x4E15B14B9950A04370E36f2Ec05546ED5867ADeF': 'DeFI', + '0x03EAAAa48ea78d1E66eA3458364d553AD981871E': 'Tooling', + '0xe56f1D3EDFFF1f25855aEF744caFE7991c224FFF': 'Media', + '0x93A829d16DE51745Db0530A0F8E8A9B8CA5370E5': 'DeFI', + '0x76bA9825A5F707F133124E4608F1F2Dd1EF4006a': 'DeFI', + '0x30a1627fDdc0dBB7dD00b881D25A45B443f294bB': 'Service', + '0xde3e447E125FA2391DC9BCbfA0B821424422FEAF': 'Service', + '0x7239B1896ad2b6A9D3aA6C4B12D8993E78fb67Dc': 'Service', + '0xBCAc4dafB7e215f2F6cb3312aF6D5e4F9d9E7eDA': 'NFT', + '0x4BaaC83d0A68C079550142B9d792328b7C239844': 'DAO', + '0xbc7797319B3eD4246c7078CC4e8B28Ea2C6872D0': 'Service', + '0x983110309620D911731Ac0932219af06091b6744': 'Service', + '0x2B8ffb4460550Dbe8Ec1cEA9C1B61322dB56B082': 'Tooling', + '0xDBc5936E4daaE94F415C39D284f6a69c4d553F2F': 'Tooling', + '0x361Cb6BE977d0113A33914A8f952Ced95747F793': 'Gaming', + '0xf4b71ceF90736Eb644Cc678b2C795ACdeaC198E1': 'Media', + '0x9Fb3d86157a9e2dC2a771C297f88FA9784fa4e31': 'DeFi', + '0x955DE87bC52688d626930C7718232FF02522cf18': 'Gaming', + '0xef6426D522CfE5B7Ae5dB05623aB0Ef78023dBe0': 'Social', + '0x2Ee77bA42220Cb41f972b9F66088D0A9f4F156f1': 'Service', + '0x4310f4F206c9a18d8436bD0052065528771f4723': 'Service', + '0x6575A93aBdFf85e5A6b97c2DB2b83bCEbc3574eC': 'DeFI', + '0x48De2669db5C2da4bf36C29ef9CFd62057B4b6C8': 'Tooling', + '0x48608159077516aFE77A04ebC0448eC32E6670c1': 'DeFi', + '0x026B7A15ad04180aBEe7fEaf34e0F695426BD193': 'Media', + '0xfE4A6Fbd27B496855245A1e8047F693f0aDfDb08': 'DAO', + '0x991552E1C2A96D0Ae72E19552b08A1889aebCF53': 'DeFi', + '0xf198eBCc8dB86F707bAdDdBa236aB5b619c59D3c': 'DeFi', + '0x57cD6665e725232123F5250328E35Db6ABf6d80C': 'Media', + '0x6B787b16445983197bf4b291016c74363d78979a': 'Infrastructure', + '0x90A48D5CF7343B08dA12E067680B4C6dbfE551Be': 'DeFi', + '0x0D54bD457AF5b5691d1D9790746d4C95f7885CFF': 'Social', + '0x094A1ef2F50F36956a90E410Ffc143362340865c': 'Media', + '0x8C28Cf33d9Fd3D0293f963b1cd27e3FF422B425c': 'Tooling', + '0x1A17beA23DFa5D9CF5B0d0838C826Ad88537c6fb': 'Service', + '0x458E4E1877F2F0D6752bD6f6DFd2e9048C2A56b3': 'DeFi', + '0x26C8C84adDA6dbA89E93f139D48c0E39B3a6A8fF': 'Media', + '0x97E5271f2987c7A3450e21dD7FFe4D004ddE773E': 'DeFi', + '0x0f0aE1ceEBc4b5aB14A47202eD6A52D3ef698b5B': 'Tooling', + '0x554d29160f779Adf0a4328597cD33Ea1Df4D9Ee9': 'Service', + '0x5aaB02cCA6F3c89bB2E10749603387c287A115Cb': 'Infrastructure', + '0x338EF19fA2eC0fc4d1277B1307a613fA1FBbc0cb': 'DeFi', + '0x18C6A47AcA1c6a237e53eD2fc3a8fB392c97169b': 'DAO', + '0xEf0D8F546880d1D41e7F35c5BA06a43C7F42FF2f': 'Tooling', + '0x1a9dDEf485674fC60a269cf97FAbc6b8728A3497': 'DeFi', + '0x53638975BC11de3029E46DF193d64879EAeA94eB': 'DeFi', + '0x33F04Cf7fa115165aF33CEA6846AA0dbC20c318B': 'Other', + '0xFAb61bC810051F3c15f1fd1172E25fc634b25555': 'Tooling', + '0x147cDAE10Cd2f8AA87776617Cbd370B665F75eef': 'DeFi', + '0xA2dEe32662F6243dA539bf6A8613F9A9e39843D3': 'DeFi', + '0x348Eed6A95263A728954693fA0D241B5f96F2c29': 'Infrastructure', + '0xaf962c18538A6498AcC9980b3Da74E0D9A131eBa': 'Service', + '0xf995b8145F6d17AECf0d0Fb54435Dd4D6B3060e5': 'DAO', + '0x0DEFE95102FeE830aEC32A3e0927b9367Ac67043': 'Service', + '0x5aFeDeF166bd626B3043cb1D53e16EA9BF863E06': 'DeFi', + '0xE6d194fbeF9215976a80D4479A3caFf0caf14BD1': 'Other', + '0x46e6C2aADbb7c37a38a583FA2136444085DFD322': 'DeFi', + '0x9D61ae5875E89036FBf6059f3116d01a22ACe3C8': 'Service', + '0xC75378478Bf346e50845CdE0E69D18eaEdA0f5F7': 'NFT', + '0xA8aF754379d8ae406dFbDD0D6c46324aD647243E': 'Media', + '0x2cE6BD653220436eB8f35E146B0Dd1a6013E97a7': 'Service', + '0x7DBF6820D32cFBd5D656bf9BFf0deF229B37cF0E': 'Service', + '0xa643fF2599F4b117E399C17E378f8df42D144298': 'Service', + '0x9bBb9c87E1B203c8B62Bd0c91FfDAD32bc3b16bD': 'DeFi', + '0xa385B298d5Cb1051e3a34269dcC7D5Eb12fA6013': 'Service', + '0xb1676B5Ab63F01F154bb9938F5e8999d9Da5444B': 'Service', + '0x6B4D338E5b65c4F6336Ac15393735bf910CCd1a4': 'NFT', + '0x66f046d4fCeF99106cba0A450f3cD19f3C1d7323': 'NFT', + '0x67F9bdC8330bED073c87eB54C3dccE7f7DA3e146': 'Service', + '0x95de504e94cc0c85534FcCc3e640BBc9b02056Fc': 'Service', + '0x174e4Bb368B9a31661B4C35bE595369fF1A68a13': 'Service', + '0x278A2d5B5C8696882d1D2002cE107efc74704ECf': 'Other', + '0x9E3EbaA4c1714326426524328Aa1128ef4d7824f': 'Service', + '0x6da3BCF0F43051eF03266f17bcf8e9Ac38F94BF7': 'NFT', + '0xc1d457128dEcAE1CC092728262469Ee796F1Ac45': 'Service', + '0xb591b1577a38FE2b8C9adD1aB42B10461225206F': 'Other', + '0x1586bCB3088a57a97c3436867544253F3dC88937': 'Service', + '0xD1CCfb9Fbd9A8DE0cf9950eFbCFb29adcDA81C93': 'Service', + '0x069e85D4F1010DD961897dC8C095FBB5FF297434': 'DAO', + '0x436D73319d5f7d21A89489017d693a4A8D822900': 'Media', + '0xAeF69730D3210B151036C04434c2b1E551e20928': 'DeFi', + '0xF6a16a48099497C59e8abEAa37Bb37B2F9B793d4': 'Defi', + '0x8AAAa9c3a06a4A9FE7C5cCe17d8B5db1E225Eadf': 'Infrastructure', + '0x5cbDFE918c64D4630a1e5BD90c98cC8BE8f47F21': 'Service', + '0xCAEbD06d75b5F8C77A73DF27AB56964CCc64f793': 'Other', + '0x1b403ff6EB37D25dCCbA0540637D65550f84aCB3': 'DAO', + '0x54728f10F525193A61Ded237707f2d5022cA4977': 'DAO', + '0xC5d5f9cbC114E22bB23aAf10F847ECF28756dFB7': 'Marketplace', + '0x63381E4b8fE26cb1f55cc38e8369990594E017b1': 'Service', + '0x80375eAD5561e19668eb1Dd2b6A44Fa14D5eB6BF': 'Service', +}; diff --git a/src/common/Common.types.ts b/src/common/Common.types.ts index 55c548ef17..00baba42a2 100644 --- a/src/common/Common.types.ts +++ b/src/common/Common.types.ts @@ -5,3 +5,5 @@ export type ModalResponse = { }; export type UnlockProfileModalTypes = 'portal' | 'container'; + +export type EnvType = 'prod' | 'dev' | 'staging'; diff --git a/src/common/Common.utils.tsx b/src/common/Common.utils.tsx index 356d97b016..ea6c7b8c83 100644 --- a/src/common/Common.utils.tsx +++ b/src/common/Common.utils.tsx @@ -1,5 +1,11 @@ +import { appConfig } from 'config'; import { LOGO_ALIAS_CHAIN } from './Common.constants'; import { networkName } from 'helpers/UtilityHelper'; +import { EnvType } from './Common.types'; + +export const allowedNetworks = appConfig.allowedNetworks.filter( + (chain: number) => chain != appConfig.coreContractChain +); export const getSelectChains = (chainIdList: Array) => { return chainIdList?.map((key: number) => { @@ -12,6 +18,24 @@ export const getSelectChains = (chainIdList: Array) => { }); }; +/** + * @param count + * @returns returns formatted number + */ +export const formatSubscriberCount = (count?: number) => { + if (count) { + if (count >= 1000000) { + return (count / 1000000).toFixed(1) + 'M'; + } else if (count >= 1000) { + return (count / 1000).toFixed(1) + 'K'; + } else { + return count; + } + } else { + return 0; + } +}; + export const isValidURL = (str: string | undefined) => { if (!str) return false; const pattern = new RegExp( @@ -25,3 +49,7 @@ export const isValidURL = (str: string | undefined) => { ); // fragment locator return !!pattern.test(str); }; + +export const getCurrentEnv = (): EnvType => { + return appConfig.appEnv; +}; diff --git a/src/common/components/ChannelDetailsCard.tsx b/src/common/components/ChannelDetailsCard.tsx new file mode 100644 index 0000000000..cb58514427 --- /dev/null +++ b/src/common/components/ChannelDetailsCard.tsx @@ -0,0 +1,250 @@ +import { FC } from 'react'; + +import { css } from 'styled-components'; +import { Link } from 'react-router-dom'; + +import { ChannelDetails } from 'queries'; + +import { LOGO_ALIAS_CHAIN, formatSubscriberCount, VerifiedChannelTooltipContent } from 'common'; + +import { + Box, + Button, + ButtonProps, + CaretDown, + NotificationMobile, + ResponsiveProp, + Skeleton, + Text, + TickDecoratedCircleFilled, + Tooltip, +} from 'blocks'; +import APP_PATHS from 'config/AppPaths'; +import { SubscribeChannelDropdown } from 'common/components/SubscribeChannelDropdown'; +import { UnsubscribeChannelDropdown } from 'common/components/UnsubscribeChannelDropdown'; +import { UserSetting } from 'helpers/channel/types'; +import { appConfig } from 'config'; + +export type ChannelDetailsCardProps = { + channelDetails: ChannelDetails | undefined; + isLoading: boolean; + isSubscribed: boolean; + isSubscriptionLoading: boolean; + handleRefetch: () => void; + userSettings: UserSetting[]; + width?: ResponsiveProp; + subscribeButtonVariant?: ButtonProps['variant']; +}; + +const ChannelDetailsCard: FC = ({ + channelDetails, + isLoading, + isSubscribed, + isSubscriptionLoading, + handleRefetch, + userSettings, + width, + subscribeButtonVariant = 'tertiary', +}) => { + let verifiedAliasChainIds = [ + appConfig.coreContractChain, + ...(channelDetails?.aliases + ?.filter((item) => item.is_alias_verified) + .map((item) => parseInt(item.alias_blockchain_id)) || []), + ]; + return ( + + + + + {channelDetails?.name} + + + + {!isSubscribed && ( + + + + + + )} + + {!!isSubscribed && ( + + + + + + )} + + + + + + + + {channelDetails?.name} + + + + {!!channelDetails?.verified_status && ( + }> + + + + + )} + + {verifiedAliasChainIds?.length > 0 && ( + + {verifiedAliasChainIds.map((aliasChainId: number, index) => { + const LogoComponent = LOGO_ALIAS_CHAIN[aliasChainId]; + return LogoComponent ? ( + + + + ) : null; + })} + + )} + + + + + + {formatSubscriberCount(channelDetails?.subscriber_count)} subscribers + + + + + + + {channelDetails?.info} + + + + + + ); +}; + +export { ChannelDetailsCard }; diff --git a/src/common/components/ContentLayout.tsx b/src/common/components/ContentLayout.tsx index f8e9ba4ba5..79a7aeac45 100644 --- a/src/common/components/ContentLayout.tsx +++ b/src/common/components/ContentLayout.tsx @@ -9,18 +9,40 @@ import { Box } from 'blocks'; type ContentLayoutProps = { children: ReactNode; + variant?: 'basic' | 'verticalStretch'; }; -const ContentLayout: FC = ({ children }) => { +const ContentLayout: FC = ({ children, variant }) => { + if (variant === 'verticalStretch') + return ( + + {children} + + ); + return ( = ({ tooltipTitle, content }) => { + const [hover, setHover] = useState(false); + return ( + + copyToClipboard(content)} + onMouseEnter={() => setHover(true)} + onMouseLeave={() => setHover(false)} + > + + + + ); +}; + +export { CopyButton }; diff --git a/src/common/components/UnsubscribeChannelDropdown.tsx b/src/common/components/UnsubscribeChannelDropdown.tsx index c3b1e03c60..48d0bdc553 100644 --- a/src/common/components/UnsubscribeChannelDropdown.tsx +++ b/src/common/components/UnsubscribeChannelDropdown.tsx @@ -176,7 +176,7 @@ const UnsubscribeChannelDropdown: FC = ({ overlay={ } onClick={handleOptOut} /> diff --git a/src/modules/dashboard/components/VerifiedToolTipComponent.tsx b/src/common/components/VerifiedChannelTooltipContent.tsx similarity index 77% rename from src/modules/dashboard/components/VerifiedToolTipComponent.tsx rename to src/common/components/VerifiedChannelTooltipContent.tsx index e882a732ba..d675944d8b 100644 --- a/src/modules/dashboard/components/VerifiedToolTipComponent.tsx +++ b/src/common/components/VerifiedChannelTooltipContent.tsx @@ -1,8 +1,7 @@ // Components -import { Box, Text } from 'blocks'; -import PushLogo from 'blocks/illustrations/components/PushLogo'; +import { Box, Text, PushLogo } from 'blocks'; -export const VerifiedToolTipContent = () => { +export const VerifiedChannelTooltipContent = () => { return ( { - navigate(`${APP_PATHS.ChannelDashboard}/${account}`, { replace: true }); + navigate(`${APP_PATHS.ChannelDashboard(account)}`, { replace: true }); }; const addSetting = (newSetting: ChannelSetting) => { diff --git a/src/config/AppPaths.ts b/src/config/AppPaths.ts index 653953dcd6..6053968b7f 100644 --- a/src/config/AppPaths.ts +++ b/src/config/AppPaths.ts @@ -1,37 +1,37 @@ -// Define an enum for the paths -enum APP_PATHS { - WelcomeDashboard = '/welcome', - Inbox = '/inbox', - Spam = '/spam', - Chat = '/chat', - Spaces = '/spaces', - Channels = '/channels', - ChannelDashboard = '/channel', - CreateChannel = '/channel/create', - Dashboard = '/dashboard', - AddNewChain = '/add-new-chain', - DiscordVerification = '/discord/verification', - Rewards = '/points', - RewardsActivities = '/points/activity', - RewardsLeaderboard = '/points/leaderboard', - PointsVault = '/points/vault', - Send = '/send', - Receive = '/receive', - Govern = '/govern', - Snap = '/snap', - YieldV2 = '/yieldv2', - Yield = '/yield', - Rockstar = '/rockstar', - Gratitude = '/gratitude', - LiveWalkthrough = '/live_walkthrough', - ComingSoon = '/comingsoon', - NotAvailable = '/notavailable', - FAQ = '/faq', - Internal = '/internal', - Support = '/support', - UserSettings = '/user/settings', - ChannelSettings = '/channel/settings', - ClaimGalxe = 'claim/galxe', -} +const APP_PATHS = { + WelcomeDashboard: '/welcome', + Inbox: '/inbox', + Spam: '/spam', + Chat: '/chat', + Spaces: '/spaces', + Channels: '/channels', + ChannelDetails: (adr?: string) => `/channels/${adr ?? ':id'}`, + ChannelDashboard: (adr?: string) => `/channel/${adr ?? ':id'}`, + CreateChannel: '/channel/create', + Dashboard: '/dashboard', + AddNewChain: '/add-new-chain', + DiscordVerification: '/discord/verification', + Rewards: '/points', + RewardsActivities: '/points/activity', + RewardsLeaderboard: '/points/leaderboard', + PointsVault: '/points/vault', + Send: '/send', + Receive: '/receive', + Govern: '/govern', + Snap: '/snap', + Yield: '/yield', + YieldV2: '/yieldv2', + Rockstar: '/rockstar', + Gratitude: '/gratitude', + LiveWalkthrough: '/live_walkthrough', + ComingSoon: '/comingsoon', + NotAvailable: '/notavailable', + FAQ: '/faq', + Internal: '/internal', + Support: '/support', + UserSettings: '/user/settings', + ChannelSettings: '/channel/settings', + ClaimGalxe: 'claim/galxe', +}; export default APP_PATHS; diff --git a/src/modules/addNewChain/AddNewChain.tsx b/src/modules/addNewChain/AddNewChain.tsx index 7bda9164c2..f5eca26a42 100644 --- a/src/modules/addNewChain/AddNewChain.tsx +++ b/src/modules/addNewChain/AddNewChain.tsx @@ -86,7 +86,7 @@ const AddNewChain: FC = () => { }; const handleCloseAuthModal = () => { - if (channelDetails) navigate(`${APP_PATHS.ChannelDashboard}/${account}}`); + if (channelDetails) navigate(`${APP_PATHS.ChannelDashboard(account)}}`); else navigate(APP_PATHS.WelcomeDashboard); setIsAuthModalVisible(false); }; diff --git a/src/modules/addNewChain/AddNewChain.utils.tsx b/src/modules/addNewChain/AddNewChain.utils.tsx deleted file mode 100644 index 378abbc3e5..0000000000 --- a/src/modules/addNewChain/AddNewChain.utils.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { LOGO_ALIAS_CHAIN } from 'common'; -import { appConfig } from 'config'; -import { networkName } from 'helpers/UtilityHelper'; - -export const getSelectChains = () => { - return appConfig.allowedNetworks.map((key: number) => { - const Component = LOGO_ALIAS_CHAIN[key]; - return { - value: key.toString(), - label: networkName[key as keyof typeof networkName], - icon: , - }; - }); -}; diff --git a/src/modules/addNewChain/components/VerifyAliasChain.tsx b/src/modules/addNewChain/components/VerifyAliasChain.tsx index 80e4c36c4b..f0e74b556e 100644 --- a/src/modules/addNewChain/components/VerifyAliasChain.tsx +++ b/src/modules/addNewChain/components/VerifyAliasChain.tsx @@ -55,7 +55,7 @@ const VerifyAliasChain: FC = ({ alaisDetails }) => { verifyAliasChain( { userPushSDKInstance, - channelAddress: alaisDetails?.channel ?? '' + channelAddress: alaisDetails?.channel ?? '', }, { onSuccess: () => { @@ -63,10 +63,15 @@ const VerifyAliasChain: FC = ({ alaisDetails }) => { toastTitle: 'Success', toastMessage: 'Verification Successful', toastType: 'SUCCESS', - getToastIcon: (size) => + getToastIcon: (size) => ( + + ), }); refetchChannelDetails(); - navigate(`${APP_PATHS.ChannelDashboard}/${account}}`); + navigate(`${APP_PATHS.ChannelDashboard(account)}`); }, onError: (error: any) => { if (error) { @@ -74,35 +79,61 @@ const VerifyAliasChain: FC = ({ alaisDetails }) => { toastTitle: 'Error', toastMessage: error.message, toastType: 'ERROR', - getToastIcon: (size) => + getToastIcon: (size) => ( + + ), }); } - } + }, } ); }; return ( - + {errorMessage && ( navigate(`${APP_PATHS.ChannelDashboard}/${account}}`) : undefined} + onAction={isAliasNetworkVerified ? () => navigate(`${APP_PATHS.ChannelDashboard(account)}`) : undefined} actionText={isAliasNetworkVerified ? 'Back to Home' : undefined} /> )} - - + + You’re almost there!
Verify the address on the new chain to send notifications.
- +
-
diff --git a/src/modules/channelDashboard/ChannelDashboard.tsx b/src/modules/channelDashboard/ChannelDashboard.tsx index f0e2a0cf02..4069b4235c 100644 --- a/src/modules/channelDashboard/ChannelDashboard.tsx +++ b/src/modules/channelDashboard/ChannelDashboard.tsx @@ -13,12 +13,13 @@ import { UserChannelDashboard } from './components/UserChannelDashboard'; import { DashboardActiveState } from './ChannelDashboard.types'; import { EditChannelV2 } from 'modules/editChannel/EditChannelV2'; import useFetchChannelDetails from 'common/hooks/useFetchUsersChannelDetails'; +import { useGetChannelCategories } from 'queries'; const ChannelDashboard = () => { const [activeState, setActiveState] = useState('dashboard'); const { channelDetails, loadingChannelDetails, refetchChannelDetails } = useFetchChannelDetails(); - + useGetChannelCategories(); return ( {activeState === 'dashboard' && ( @@ -48,7 +49,10 @@ const ChannelDashboard = () => { )} {activeState === 'editChannel' && channelDetails && ( - + )} ); diff --git a/src/modules/channelDashboard/components/ChannelDashboardHeader.tsx b/src/modules/channelDashboard/components/ChannelDashboardHeader.tsx index 8f4aa58e76..837c2a245b 100644 --- a/src/modules/channelDashboard/components/ChannelDashboardHeader.tsx +++ b/src/modules/channelDashboard/components/ChannelDashboardHeader.tsx @@ -10,7 +10,7 @@ import { KebabMenuHorizontal, Menu, MenuItem, - Skeleton + Skeleton, } from 'blocks'; import { Alias, ChannelDetails } from 'queries'; @@ -32,7 +32,7 @@ const ChannelDashboardHeader: FC = ({ channelDetails, setActiveState, onActiveNetwork, - currentAliasDetails + currentAliasDetails, }) => { const { chainId } = useAccount(); const isAliasVerified = currentAliasDetails && currentAliasDetails?.is_alias_verified === 0; @@ -54,7 +54,12 @@ const ChannelDashboardHeader: FC = ({ {/* Edit Channel and Dropdown only visible on Core network */} {onCoreNetwork && ( - + + + )} + + {channel && !!isSubscribed && ( + + + + )} + + ); +}; + +export { ChannelDetailSubscribe }; diff --git a/src/modules/channelDetails/components/ChannelList.tsx b/src/modules/channelDetails/components/ChannelList.tsx new file mode 100644 index 0000000000..6215aa312a --- /dev/null +++ b/src/modules/channelDetails/components/ChannelList.tsx @@ -0,0 +1,104 @@ +import { FC } from 'react'; + +import { FetchNextPageOptions, InfiniteData, InfiniteQueryObserverResult } from '@tanstack/react-query'; +import InfiniteScroll from 'react-infinite-scroller'; + +import { Box, Spinner, Skeleton } from 'blocks'; + +import { ChannelDetails, ChannelsListModelledResponse } from 'queries'; +import { useNavigate } from 'react-router-dom'; +import APP_PATHS from 'config/AppPaths'; +import { css } from 'styled-components'; + +export type ChannelListProps = { + channels: Array; + hasMoreData: boolean; + isFetchingNextPage: boolean; + isLoading: boolean; + setSelectedChannelId: React.Dispatch>; + fetchNextPage: ( + options?: FetchNextPageOptions | undefined + ) => Promise, Error>>; +}; +const ChannelList: FC = ({ + channels, + fetchNextPage, + setSelectedChannelId, + isLoading, + hasMoreData, + isFetchingNextPage, +}) => { + const navigate = useNavigate(); + + const handleChannelChange = (channel: ChannelDetails) => { + setSelectedChannelId(channel?.channel); + navigate(APP_PATHS.ChannelDetails(channel?.channel)); + }; + return ( + + { + fetchNextPage(); + }} + hasMore={hasMoreData} + useWindow={false} + threshold={150} + > + + {channels?.map((channel) => ( + + handleChannelChange(channel)} + css={css` + flex-shrink: 0; + `} + > + {channel?.name} + + + ))} + + + {isFetchingNextPage && ( + + + + )} + + ); +}; + +export { ChannelList }; diff --git a/src/modules/channelDetails/components/ChannelTutorialContent.tsx b/src/modules/channelDetails/components/ChannelTutorialContent.tsx new file mode 100644 index 0000000000..1459d3c504 --- /dev/null +++ b/src/modules/channelDetails/components/ChannelTutorialContent.tsx @@ -0,0 +1,112 @@ +import { FC } from 'react'; + +import { Box, Button, Dropdown, ExternalLink, Link, Text, Tutorial } from 'blocks'; +import { UserJourney } from './UserJourneyPreview'; + +import { useBlocksTheme } from 'blocks/Blocks.hooks'; + +import { useDisclosure } from 'common'; + +export type ChannelTutorialContentProps = { tutotrialDetails: any }; +const ChannelTutorialContent: FC = ({ tutotrialDetails }) => { + const { mode } = useBlocksTheme(); + const modalControl = useDisclosure(); + + return ( + + {tutotrialDetails.userjourneyshort && ( + + + Subscribe to enable + + + + {`${tutotrialDetails?.userjourneyshort}`} + + + )} + + {tutotrialDetails?.userjourneyyoutube && ( + + )} + {tutotrialDetails?.article && ( + +