diff --git a/src/components/AccountCard/AccountCard.tsx b/src/components/AccountCard/AccountCard.tsx index 8066c2556..db4ecd3d6 100644 --- a/src/components/AccountCard/AccountCard.tsx +++ b/src/components/AccountCard/AccountCard.tsx @@ -21,11 +21,9 @@ export function AccountCard({ ...props }: AccountCardProps): ReactNode { const [enabled, setEnabled] = useState(isEnabled); - const [favorited, setFavorited] = useState(isFavorited); const handleFavoriteChange = (): void => { - setFavorited(!favorited); - onFavoriteChange?.(!favorited); + onFavoriteChange?.(!isFavorited); }; const handleEnableChange = (): void => { @@ -33,7 +31,7 @@ export function AccountCard({ if (onEnableChange) onEnableChange(!enabled); }; - const favoriteIcon = favorited ? 'star-filled' : 'star'; + const favoriteIcon = isFavorited ? 'star-filled' : 'star'; return (
diff --git a/src/pages/home/components/Sidebar/Sidebar.components.tsx b/src/pages/home/components/Sidebar/Sidebar.components.tsx index 45ccc7100..d218e8272 100644 --- a/src/pages/home/components/Sidebar/Sidebar.components.tsx +++ b/src/pages/home/components/Sidebar/Sidebar.components.tsx @@ -9,24 +9,24 @@ import scss from './Sidebar.module.scss'; import { FilteredAccountsProps } from './Sidebar.types'; export function FilteredAccounts(props: FilteredAccountsProps): ReactNode { - const { accounts, socialMedias } = useSocialMediaStore(); + const { socialMedias } = useSocialMediaStore(); + + const socialMediasSortered = props.socialMedia.sort((a, b) => { + if (a.socialMediaId === 'FAVORITE_ACCOUNTS') return -1; + if (b.socialMediaId === 'FAVORITE_ACCOUNTS') return 1; + return 0; + }); + return (
- - {props.socialMedia.map( + {socialMediasSortered.map( ({ socialMediaAccounts, socialMediaId }): ReactNode => ( ) )} diff --git a/src/pages/home/components/Sidebar/Sidebar.spec.tsx b/src/pages/home/components/Sidebar/Sidebar.spec.tsx index 6bb659cb2..4fbe19585 100644 --- a/src/pages/home/components/Sidebar/Sidebar.spec.tsx +++ b/src/pages/home/components/Sidebar/Sidebar.spec.tsx @@ -71,7 +71,6 @@ describe('Sidebar component', () => { accounts: { data: mockedAccounts().data, error: '', - favorites: mockedAccounts().favorites, loading: false, }, addAccount: mockedAddAccount, @@ -94,7 +93,6 @@ describe('Sidebar component', () => { TWITTER_EXAMPLE_ID: [], }, error: '', - favorites: [], loading: false, }, addAccount: mockedAddAccount, 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 d9ab70a5d..25a41ccbd 100644 --- a/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.spec.tsx +++ b/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.spec.tsx @@ -40,7 +40,7 @@ describe('SocialAccordion', () => { accounts={mockDiscordData} error={false} socialMediaId={socialMediaId} - title={mockedSocialMedias().get(socialMediaId)?.name} + title={mockedSocialMedias().get(socialMediaId)?.name as string} /> ); const accordion = screen.getByText(/discord/i); @@ -56,7 +56,7 @@ describe('SocialAccordion', () => { accounts={mockDiscordData} error={false} socialMediaId={socialMediaId} - title={mockedSocialMedias().get(socialMediaId)?.name} + title={mockedSocialMedias().get(socialMediaId)?.name as string} /> ); @@ -76,7 +76,7 @@ describe('SocialAccordion', () => { accounts={[]} error socialMediaId={socialMediaId} - title={mockedSocialMedias().get(socialMediaId)?.name} + title={mockedSocialMedias().get(socialMediaId)?.name as string} /> ); const error = screen.getByText(/error/i); @@ -93,7 +93,7 @@ describe('SocialAccordion', () => { accounts={mockDiscordData} error={false} socialMediaId={socialMediaId} - title={mockedSocialMedias().get(socialMediaId)?.name} + title={mockedSocialMedias().get(socialMediaId)?.name as string} /> ); @@ -116,7 +116,7 @@ describe('SocialAccordion', () => { accounts={mockDiscordData} error={false} socialMediaId={socialMediaId} - title={mockedSocialMedias().get(socialMediaId)?.name} + title={mockedSocialMedias().get(socialMediaId)?.name as string} /> ); @@ -143,7 +143,7 @@ describe('SocialAccordion', () => { accounts={mockedAccounts().data.DISCORD_EXAMPLE_ID} error={false} socialMediaId={socialMediaId} - title={mockedSocialMedias().get(socialMediaId)?.name} + title={mockedSocialMedias().get(socialMediaId)?.name as string} /> ); @@ -171,7 +171,7 @@ describe('SocialAccordion', () => { accounts={[]} error={false} socialMediaId={socialMediaId} - title={mockedSocialMedias().get(socialMediaId)?.name} + title={mockedSocialMedias().get(socialMediaId)?.name as string} /> ); const accountQuantity = screen.getByText(/0/); @@ -188,7 +188,7 @@ describe('SocialAccordion', () => { accounts={[account]} error={false} socialMediaId={socialMediaId} - title={mockedSocialMedias().get(socialMediaId)?.name} + title={mockedSocialMedias().get(socialMediaId)?.name as string} /> ); diff --git a/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.type.ts b/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.type.ts index 055472957..9eaeb0222 100644 --- a/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.type.ts +++ b/src/pages/home/components/Sidebar/components/SocialAccordion/SocialAccordion.type.ts @@ -7,7 +7,7 @@ export type SocialAccordionProps = { error: boolean; icon?: ReactElement; socialMediaId: string; - title: string | undefined; + title: string; }; export type IAccountList = { diff --git a/src/stores/__mocks__/useSocialMediaStore.mock.ts b/src/stores/__mocks__/useSocialMediaStore.mock.ts index 840958f1c..e245c9086 100644 --- a/src/stores/__mocks__/useSocialMediaStore.mock.ts +++ b/src/stores/__mocks__/useSocialMediaStore.mock.ts @@ -98,10 +98,20 @@ export const mockedAccounts = vi.fn(() => ({ userName: 'Twitter User 6', valid: false, }, + { + avatar: 'https://example.com/image2.jpg', + expiresAt: '', + favorite: true, + generatedAt: '', + id: '7', + socialMediaId: 'TWITTER_EXAMPLE_ID', + token: 'TWITTER_EXAMPLE_TOKEN_7', + userName: 'Twitter User 7', + valid: false, + }, ], }, error: '', - favorites: mockedFavoriteAccounts, loading: false, })); diff --git a/src/stores/useSocialMediaStore/useSocialMediaStore.ts b/src/stores/useSocialMediaStore/useSocialMediaStore.ts index cab2c1e17..48049d198 100644 --- a/src/stores/useSocialMediaStore/useSocialMediaStore.ts +++ b/src/stores/useSocialMediaStore/useSocialMediaStore.ts @@ -1,4 +1,3 @@ -import isEmpty from 'lodash.isempty'; import { create } from 'zustand'; import { octopostApi } from '~services/api'; @@ -18,7 +17,6 @@ export const useSocialMediaStore = create((set) => ({ accounts: { data: {}, error: '', - favorites: [], loading: false, }, @@ -51,8 +49,38 @@ export const useSocialMediaStore = create((set) => ({ favoriteAccount: async ( accountId: Account['id'], favorite: boolean - ): Promise => - AccountsService.favorite(accountId, favorite), + ): Promise => { + const account = await AccountsService.favorite(accountId, favorite); + + if (account?.id) { + const favoritedAccount: StoreAccount = { + ...account, + favorite, + valid: false, + }; + + set((state) => { + const currentFavoriteAccounts = + state.accounts.data.FAVORITE_ACCOUNTS ?? []; + const currentSocialMediaAccounts = + state.accounts.data[account.socialMediaId] ?? []; + + return { + accounts: { + ...state.accounts, + data: { + ...state.accounts.data, + [account.socialMediaId]: [ + favoritedAccount, + ...currentSocialMediaAccounts, + ], + FAVORITE_ACCOUNTS: [favoritedAccount, ...currentFavoriteAccounts], + }, + }, + }; + }); + } + }, getAllAccounts: async (): Promise => { set((state) => ({ accounts: { ...state.accounts, loading: true } })); @@ -63,7 +91,6 @@ export const useSocialMediaStore = create((set) => ({ const accountsBySocialMedia: SocialMediaData = { data: {}, }; - let favoriteSocialMedias: StoreAccount[] = []; accountsBySocialMedia.data = fetchedAccounts.reduce( (agg, account) => ({ @@ -79,39 +106,39 @@ export const useSocialMediaStore = create((set) => ({ accountsBySocialMedia.data ); - if (!isEmpty(accountsBySocialMedia.data)) { - favoriteSocialMedias = Object.values(accountsBySocialMedia.data) - .flat() - .filter( - (socialMedia): socialMedia is StoreAccount => - socialMedia?.favorite === true - ); - } + const favoriteAccounts = fetchedAccounts + .filter((account) => account.favorite) + .map((account) => ({ + ...account, + socialMediaId: 'FAVORITE_ACCOUNTS', + valid: false, + })); + + accountsBySocialMedia.data.FAVORITE_ACCOUNTS = favoriteAccounts; const fetchedSocialMedias = await SocialMediaService.fetch(userSocialMedias); const fetchedSocialMediasMap = new Map(); - for (const socialMedia of fetchedSocialMedias) { - fetchedSocialMediasMap.set(socialMedia.id, socialMedia); - } - - const favoriteAccounts = { + const favoriteSocialMedia = { icon: 'Icon', id: 'FAVORITE_ACCOUNTS', - name: 'favorite', + name: 'Favorite Accounts', postModes: [], }; - fetchedSocialMediasMap.set('FAVORITE_ACCOUNTS', favoriteAccounts); + fetchedSocialMediasMap.set('FAVORITE_ACCOUNTS', favoriteSocialMedia); + + for (const socialMedia of fetchedSocialMedias) { + fetchedSocialMediasMap.set(socialMedia.id, socialMedia); + } set(() => ({ socialMedias: fetchedSocialMediasMap })); set(() => ({ accounts: { data: accountsBySocialMedia.data, error: '', - favorites: favoriteSocialMedias, loading: false, }, })); diff --git a/src/stores/useSocialMediaStore/useSocialMediaStore.types.ts b/src/stores/useSocialMediaStore/useSocialMediaStore.types.ts index c46a01cef..c9bd69e38 100644 --- a/src/stores/useSocialMediaStore/useSocialMediaStore.types.ts +++ b/src/stores/useSocialMediaStore/useSocialMediaStore.types.ts @@ -9,7 +9,6 @@ export type SocialMediaState = { accounts: { data: Record; error: string; - favorites: StoreAccount[]; loading: boolean; }; addAccount: (newAccount: NewAccount) => Promise; @@ -17,7 +16,7 @@ export type SocialMediaState = { favoriteAccount: ( accountId: Account['id'], favorite: boolean - ) => Promise; + ) => Promise; getAllAccounts: () => Promise;