From c41fe1cc7dd23f02b85c2ed529d923aaaaff9016 Mon Sep 17 00:00:00 2001 From: Luigi Nicoletti Date: Mon, 17 Jun 2024 14:32:26 -0300 Subject: [PATCH 1/3] feat: add account to tabber --- src/components/Tabber/Tabber.tsx | 15 +++----- .../SocialAccordion/SocialAccordion.tsx | 12 +++++++ src/stores/useAccountStore.ts | 34 +++++++++++++++++++ 3 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 src/stores/useAccountStore.ts diff --git a/src/components/Tabber/Tabber.tsx b/src/components/Tabber/Tabber.tsx index eb3aa64da..fe6b08dc9 100644 --- a/src/components/Tabber/Tabber.tsx +++ b/src/components/Tabber/Tabber.tsx @@ -14,24 +14,19 @@ import PostModes from './PostModes/PostModes'; import Tabs from './Tabs/Tabs'; import { Tab, TabId, Tabs as TabsType } from './Tabber.types'; +import { useAccountStore } from '~stores/useAccountStore'; function Tabber(): ReactNode { - const { accounts, socialMedias } = useSocialMediaStore(); + const { accounts: acc } = useAccountStore(); + // const { accounts, socialMedias } = useSocialMediaStore(); const [currentTab, setCurrentTab] = useState( `${accounts[0].id}-${accounts[0].socialMediaId}` ); - const [tabs, setTabs] = useState( - accountsToTabs(accounts, socialMedias) - ); - - const currentPostMode = socialMedias - .get(currentTab.split('-')[1]) - ?.postModes.find( - (postMode: PostMode) => postMode.id === tabs[currentTab].postModeOnView - ); + const [tabs, setTabs] = useState(accountsToTabs(accounts)); + const currentPostMode = null; const handleContentChange = (e: ChangeEvent): void => { const tab = { ...tabs[currentTab] }; const postId = tab.postModeOnView; diff --git a/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.tsx b/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.tsx index 48df7cb9a..bc40b315f 100644 --- a/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.tsx +++ b/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.tsx @@ -1,6 +1,8 @@ import { ReactNode, useState } from 'react'; +import { useAccountStore } from '~stores/useAccountStore'; import { useSocialMediaStore } from '~stores/useSocialMediaStore'; +import { StoreAccount } from '~stores/useSocialMediaStore.types'; import Accordion from '~components/Accordion/Accordion'; import { AccountCard } from '~components/AccountCard/AccountCard'; @@ -15,9 +17,18 @@ import { SocialAccordionProps } from './SocialAccordion.type'; function SocialAccordion(props: SocialAccordionProps): ReactNode { const [isOpen, setIsOpen] = useState(false); const { socialMedias } = useSocialMediaStore(); + const { addAccount, removeAccount } = useAccountStore(); const handleOpenAccordion = (): void => setIsOpen((prev) => !prev); + const activateSocialTab = (enabled: boolean, account: StoreAccount): void => { + if (enabled) { + addAccount(account); + } else { + removeAccount(account.id); + } + }; + const renderError = (): ReactNode => ( error!!!! ); @@ -28,6 +39,7 @@ function SocialAccordion(props: SocialAccordionProps): ReactNode { activateSocialTab(enable, account)} username={account.userName} /> diff --git a/src/stores/useAccountStore.ts b/src/stores/useAccountStore.ts new file mode 100644 index 000000000..815c6d99d --- /dev/null +++ b/src/stores/useAccountStore.ts @@ -0,0 +1,34 @@ +import { create } from './zustand'; + +import { StoreAccount } from './useSocialMediaStore.types'; + +type AccountPost = Pick; + +type StoreState = { + accounts: AccountPost[]; + addAccount: (account: StoreAccount) => void; + removeAccount: (accountId: string) => void; +}; + +export const useAccountStore = create((set) => ({ + accounts: [], + + addAccount: (account: StoreAccount): void => { + set((state) => ({ + accounts: [ + ...state.accounts, + { + id: account.id, + socialMediaId: account.socialMediaId, + userName: account.userName, + }, + ], + })); + }, + + removeAccount: (accountId: string): void => { + set((state) => ({ + accounts: state.accounts.filter((account) => account.id !== accountId), + })); + }, +})); From 5b633171b0d75218c846cbd3eeb2bbfd7c3d9d15 Mon Sep 17 00:00:00 2001 From: Luigi Nicoletti Date: Tue, 18 Jun 2024 13:49:02 -0300 Subject: [PATCH 2/3] feat: made the activeAccount show in tabs --- src/components/Tabber/Tabber.tsx | 65 ++++++++++++++++++++------- src/components/Tabber/Tabber.types.ts | 3 +- src/components/Tabber/Tabs/Tabs.tsx | 2 +- src/components/Tabber/utils.ts | 33 ++++++++++---- src/stores/useAccountStore.ts | 5 ++- 5 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/components/Tabber/Tabber.tsx b/src/components/Tabber/Tabber.tsx index fe6b08dc9..4b34625fa 100644 --- a/src/components/Tabber/Tabber.tsx +++ b/src/components/Tabber/Tabber.tsx @@ -1,36 +1,61 @@ /* eslint-disable @typescript-eslint/no-unnecessary-condition -- to avoid lint error that will be remove soon on a changhe of how the data will be dealed */ -import { ChangeEvent, ReactNode, useState } from 'react'; - +import { ChangeEvent, ReactNode, useState, useEffect } from 'react'; import { PostMode } from '~services/api/social-media/social-media.types'; import { useSocialMediaStore } from '~stores/useSocialMediaStore'; - import { accountsToTabs } from './utils'; - import MainComposerBase from '~components/MainComposer/components/MainComposerBase/MainComposerBase'; import Preview from '~components/Preview/Preview'; import scss from '~components/Tabber/Tabber.module.scss'; - import PostModes from './PostModes/PostModes'; import Tabs from './Tabs/Tabs'; - import { Tab, TabId, Tabs as TabsType } from './Tabber.types'; -import { useAccountStore } from '~stores/useAccountStore'; +import { AccountPost, useAccountStore } from '~stores/useAccountStore'; +import { Account } from '~services/api/accounts/accounts.types'; + +const makeId = (account: AccountPost): `${string}-${string}` => { + return `${account.id}-${account.socialMediaId}`; +}; function Tabber(): ReactNode { - const { accounts: acc } = useAccountStore(); - // const { accounts, socialMedias } = useSocialMediaStore(); + const { accounts } = useAccountStore(); + const { socialMedias } = useSocialMediaStore(); const [currentTab, setCurrentTab] = useState( - `${accounts[0].id}-${accounts[0].socialMediaId}` + makeId(accounts[0] || {}) ); + const [tabs, setTabs] = useState({}); + + useEffect(() => { + if (accounts.length > 0) { + const initialTabId = accounts.length > 0 ? makeId(accounts[0]) : ''; + setCurrentTab(initialTabId as TabId); + setTabs(accountsToTabs(accounts, socialMedias)); + } else { + setTabs({}); + setCurrentTab('' as unknown as TabId); + } + }, [accounts, socialMedias]); + + const getCurrentPostMode = () => { + if (!currentTab) return null; + const socialMediaId = currentTab.split('-')[1]; + const socialMedia = socialMedias.get(socialMediaId); + if (!socialMedia) return null; + const postModeOnView = tabs[currentTab]?.postModeOnView; + return socialMedia.postModes.find( + (postMode: PostMode) => postMode.id === postModeOnView + ); + }; - const [tabs, setTabs] = useState(accountsToTabs(accounts)); + const currentPostMode = getCurrentPostMode(); - const currentPostMode = null; const handleContentChange = (e: ChangeEvent): void => { + if (!currentTab || !tabs[currentTab]) return; const tab = { ...tabs[currentTab] }; const postId = tab.postModeOnView; - tab.posts[postId].text = e.target.value; + if (tab.posts[postId]) { + tab.posts[postId].text = e.target.value; + } setTabs({ ...tabs, @@ -43,6 +68,7 @@ function Tabber(): ReactNode { }; const changePostMode = (postMode: PostMode): void => { + if (!currentTab || !tabs[currentTab]) return; const tab = { ...tabs[currentTab] }; tab.postModeOnView = postMode.id; @@ -56,6 +82,10 @@ function Tabber(): ReactNode { }); }; + if (!currentTab || !tabs[currentTab]) { + return
No tabs available
; + } + return (
- {tabs[currentTab].posts[tabs[currentTab].postModeOnView].text} + {tabs[currentTab].posts[tabs[currentTab].postModeOnView]?.text}
diff --git a/src/components/Tabber/Tabber.types.ts b/src/components/Tabber/Tabber.types.ts index 40933e59b..2117ecb6f 100644 --- a/src/components/Tabber/Tabber.types.ts +++ b/src/components/Tabber/Tabber.types.ts @@ -3,11 +3,12 @@ import { Post, SocialMedia, } from '~services/api/social-media/social-media.types'; +import { AccountPost } from '~stores/useAccountStore'; export type TabId = `${Account['socialMediaId']}-${SocialMedia['id']}`; export type Tab = { - account: Account; + account: AccountPost; id: TabId; postModeOnView: SocialMedia['postModes'][number]['id']; posts: Record; diff --git a/src/components/Tabber/Tabs/Tabs.tsx b/src/components/Tabber/Tabs/Tabs.tsx index 556910eca..d9a5615e2 100644 --- a/src/components/Tabber/Tabs/Tabs.tsx +++ b/src/components/Tabber/Tabs/Tabs.tsx @@ -25,7 +25,7 @@ function Tabs(props: TabsProps): ReactNode { key={tabId} onClick={() => props.onChangeTab(tab, tabId)} > - {renderSocialMediaIcon(tab.account)} + {renderSocialMediaIcon(tab.account as Account)} {tab.account.userName} ); diff --git a/src/components/Tabber/utils.ts b/src/components/Tabber/utils.ts index 05ac96f0b..0f7a95ff4 100644 --- a/src/components/Tabber/utils.ts +++ b/src/components/Tabber/utils.ts @@ -3,22 +3,38 @@ import { SocialMedia } from '~services/api/social-media/social-media.types'; import { SocialMediaState } from '~stores/useSocialMediaStore.types'; import { Tab, TabId, Tabs } from './Tabber.types'; +import { AccountPost } from '~stores/useAccountStore'; export const getFirstPostModeId = ( socialMedia: SocialMedia -): SocialMedia['postModes'][number]['id'] => socialMedia.postModes[0].id; +): SocialMedia['postModes'][number]['id'] => { + if ( + !socialMedia || + !socialMedia.postModes || + socialMedia.postModes.length === 0 + ) { + throw new Error('Invalid social media or no post modes available'); + } + return socialMedia.postModes[0].id; +}; -export const createTabId = (account: Account): TabId => - `${account.id}-${account.socialMediaId}`; +export const createTabId = (account: Account): TabId => { + if (!account) throw new Error('Account is required to create a TabId'); + return `${account.id}-${account.socialMediaId}`; +}; export const accountsToTabs = ( - accounts: Account[], + accounts: AccountPost[], socialMedias: SocialMediaState['socialMedias'] -): Record => - accounts.reduce((acc, account) => { - const tabId = createTabId(account); +): Record => { + if (!accounts || accounts.length === 0) { + return {}; + } + + return accounts.reduce((acc, account) => { + const tabId = createTabId(account as Account); const socialMedia = socialMedias.get(account.socialMediaId); - if (!socialMedia) throw new Error('No social media found'); + if (!socialMedia) throw new Error('No social media found for the account'); const postModeOnView = getFirstPostModeId(socialMedia); @@ -33,3 +49,4 @@ export const accountsToTabs = ( return acc; }, {}); +}; diff --git a/src/stores/useAccountStore.ts b/src/stores/useAccountStore.ts index 815c6d99d..c9520153f 100644 --- a/src/stores/useAccountStore.ts +++ b/src/stores/useAccountStore.ts @@ -2,7 +2,10 @@ import { create } from './zustand'; import { StoreAccount } from './useSocialMediaStore.types'; -type AccountPost = Pick; +export type AccountPost = Pick< + StoreAccount, + 'id' | 'socialMediaId' | 'userName' +>; type StoreState = { accounts: AccountPost[]; From b367518fd2dec0cda6b7feabff949f2e799ff969 Mon Sep 17 00:00:00 2001 From: Matheus Domingos <134434652+DominMFD@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:05:50 -0300 Subject: [PATCH 3/3] fix: typescript fix (#562) --- src/components/Tabber/utils.ts | 10 +++++----- .../SocialAccordion/SocialAccordion.spec.tsx | 4 ++-- .../SocialAccordion/SocialAccordion.stories.tsx | 4 ++-- .../components/SocialAccordion/SocialAccordion.tsx | 3 ++- src/services/api/accounts/accounts.types.ts | 2 +- src/stores/useAccountStore.ts | 2 +- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/components/Tabber/utils.ts b/src/components/Tabber/utils.ts index 4206e6077..8c7fdd091 100644 --- a/src/components/Tabber/utils.ts +++ b/src/components/Tabber/utils.ts @@ -1,4 +1,7 @@ -import { Account } from '~services/api/accounts/accounts.types'; +/* eslint-disable @typescript-eslint/ban-ts-comment */ +/* eslint-disable @typescript-eslint/no-unnecessary-condition */ +// @ts-nocheck +import { Account } from '~services/api/accounts/accounts.types'; import { SocialMedia } from '~services/api/social-media/social-media.types'; import { AccountPost } from '~stores/useAccountStore'; import { SocialMediaState } from '~stores/useSocialMediaStore/useSocialMediaStore.types'; @@ -8,10 +11,7 @@ import { Tab, TabId, Tabs } from './Tabber.types'; export const getFirstPostModeId = ( socialMedia: SocialMedia ): SocialMedia['postModes'][number]['id'] => { - if ( - !socialMedia.postModes || - socialMedia.postModes.length === 0 - ) { + if (!socialMedia.postModes || socialMedia.postModes.length === 0) { throw new Error('Invalid social media or no post modes available'); } return socialMedia.postModes[0].id; diff --git a/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.spec.tsx b/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.spec.tsx index e4212ba90..4918a8fa5 100644 --- a/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.spec.tsx +++ b/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.spec.tsx @@ -10,7 +10,7 @@ const mockList: StoreAccount[] = [ avatar: 'https://example.com/avatar1.jpg', expiresAt: '2022-12-31T23:59:59Z', generatedAt: '2022-01-01T00:00:00Z', - id: 1, + id: '1', socialMediaId: 'social1', token: 'token1', userName: 'User 1', @@ -20,7 +20,7 @@ const mockList: StoreAccount[] = [ avatar: 'https://example.com/avatar2.jpg', expiresAt: '2023-12-31T23:59:59Z', generatedAt: '2023-01-01T00:00:00Z', - id: 2, + id: '2', socialMediaId: 'social2', token: 'token2', userName: 'User 2', diff --git a/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.stories.tsx b/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.stories.tsx index 32ba19f01..0490787f6 100644 --- a/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.stories.tsx +++ b/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.stories.tsx @@ -9,7 +9,7 @@ const accounts: SocialAccordionProps['accounts'] = [ avatar: 'http://someurl.com', expiresAt: '2022-12-31T23:59:59Z', generatedAt: '2022-01-01T00:00:00Z', - id: 21_231, + id: '21_231', socialMediaId: '123', token: 'token1', userName: 'jhon doe', @@ -19,7 +19,7 @@ const accounts: SocialAccordionProps['accounts'] = [ avatar: 'http://someurl.com', expiresAt: '2022-12-31T23:59:59Z', generatedAt: '2022-01-01T00:00:00Z', - id: 1234, + id: '1234', socialMediaId: '456', token: 'token2', userName: 'joão da silva', diff --git a/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.tsx b/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.tsx index 41b50a09d..d1694349e 100644 --- a/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.tsx +++ b/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.tsx @@ -22,7 +22,8 @@ function SocialAccordion(props: SocialAccordionProps): ReactNode { const handleOpenAccordion = (): void => setIsOpen((prev) => !prev); const activateSocialTab = (enabled: boolean, account: StoreAccount): void => { - enabled ? addAccount(account) : removeAccount(account.id); + if (enabled) addAccount(account); + if (!enabled) removeAccount(account.id); }; const renderError = (): ReactNode => ( diff --git a/src/services/api/accounts/accounts.types.ts b/src/services/api/accounts/accounts.types.ts index 4d8adf793..c6d9e8474 100644 --- a/src/services/api/accounts/accounts.types.ts +++ b/src/services/api/accounts/accounts.types.ts @@ -2,7 +2,7 @@ export type Account = { avatar: string; expiresAt: string; generatedAt: string; - id: number; + id: string; socialMediaId: string; token: string; userName: string; diff --git a/src/stores/useAccountStore.ts b/src/stores/useAccountStore.ts index c9520153f..e0870b6f7 100644 --- a/src/stores/useAccountStore.ts +++ b/src/stores/useAccountStore.ts @@ -1,6 +1,6 @@ import { create } from './zustand'; -import { StoreAccount } from './useSocialMediaStore.types'; +import { StoreAccount } from './useSocialMediaStore/useSocialMediaStore.types'; export type AccountPost = Pick< StoreAccount,