Skip to content

Commit

Permalink
feat: hidden collections toggle for create a gallery page (#457)
Browse files Browse the repository at this point in the history
  • Loading branch information
patricio0312rev authored Nov 20, 2023
1 parent 1be672b commit 422fb7c
Show file tree
Hide file tree
Showing 21 changed files with 401 additions and 34 deletions.
7 changes: 5 additions & 2 deletions app/Http/Controllers/MyGalleryCollectionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ public function index(Request $request): JsonResponse
/** @var User $user */
$user = $request->user();

$collections = $user
->collections()
$collectionsQuery = $request->get('showHidden') === 'true'
? $user->hiddenCollections()
: $user->collections()->notHidden($user);

$collections = $collectionsQuery
->where('collections.name', 'ilike', sprintf('%%%s%%', $request->get('query')))
->withUserNftsCount($user)
->orderBy('id')
Expand Down
8 changes: 8 additions & 0 deletions app/Http/Controllers/MyGalleryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,17 @@ public function index(Request $request, GalleryRepository $galleries): Response
/** @var PaginatedDataCollection<int, GalleryCardData> */
$collection = GalleryCardData::collection($galleries);

$userCollectionsCount = $user->collections()->count();
$hiddenCollectionsCount = $user->hiddenCollections()->count();
$areAllCollectionsHidden = $userCollectionsCount > 0 && $hiddenCollectionsCount == $userCollectionsCount;

return Inertia::render('Galleries/MyGalleries/Index', [
'title' => $showDrafts ? trans('metatags.my_galleries.title_draft') : trans('metatags.my_galleries.title'),
'galleries' => $showDrafts ? null : new GalleriesCardData($collection),
'nftCount' => $user->nfts()->count(),
'galleryCount' => $user->galleries()->count(),
'showDrafts' => $showDrafts,
'areAllCollectionsHidden' => $areAllCollectionsHidden,
]);
}

Expand All @@ -49,12 +54,15 @@ public function create(Request $request): Response|RedirectResponse
/** @var User $user */
$user = $request->user();

$hiddenCollectionsCount = $user->hiddenCollections()->count();

return Inertia::render('Galleries/MyGalleries/Create', [
'title' => trans('metatags.my_galleries.create.title'),
'nftsPerPage' => (int) config('dashbrd.gallery.pagination.nfts_per_page'),
'collectionsPerPage' => (int) config('dashbrd.gallery.pagination.collections_per_page'),
'nftLimit' => config('dashbrd.gallery.nft_limit'),
'nftCount' => $user->nfts()->count(),
'hiddenCollectionsCount' => $hiddenCollectionsCount,
]);
}

Expand Down
9 changes: 9 additions & 0 deletions app/Models/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,15 @@ public function scopeWithUserNftsCount(Builder $query, User $user): Builder
]);
}

/**
* @param Builder<self> $query
* @return Builder<self>
*/
public function scopeNotHidden($query, User $user)
{
return $query->whereNotIn('collections.id', $user->hiddenCollections()->pluck('id')->toArray());
}

/**
* @return HasOne<SpamContract>
*/
Expand Down
3 changes: 3 additions & 0 deletions lang/en/pages.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,14 @@
'subtitle' => 'Manage your galleries',
'new_gallery' => 'New Gallery',
'no_galleries' => 'You have not created any galleries yet. To create a gallery, click on the "Create Gallery" button.',
'no_available_collections' => 'You have hidden all your collections. If you want to create a gallery, make sure you have at least 1 collection available.',
'no_draft_galleries' => 'You have no draft galleries yet. To create a gallery, click on the "Create Gallery" button.',
'succesfully_deleted' => 'Gallery has been successfully removed',
'draft_succesfully_deleted' => 'Draft has been successfully removed',
'successfully_created' => 'Gallery has been successfully created',
'successfully_updated' => 'Gallery has been successfully updated',
'new_gallery_no_nfts' => 'Creating a Gallery requires you to own an NFT.',
'new_gallery_all_collections_hidden' => 'Creating a Gallery requires you to have at least 1 collection available.',
'delete_modal' => [
'title' => 'Delete Draft',
'text' => 'Are you sure you want to delete the draft? Everything you\'ve done will be deleted and you won\'t be able to get it back.',
Expand All @@ -182,6 +184,7 @@
],
'copy_gallery_link' => 'Copy Gallery Link',
'my_nfts' => 'My NFTs',
'show_hidden_collections' => 'Show hidden collections',
'value' => 'Value',
'floor_price' => 'Floor Price',
'nfts' => 'NFTs',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { useGalleryNtfs } from "@/Components/Galleries/Hooks/useGalleryNtfs";
export interface GalleryNftsState {
nfts: App.Data.Gallery.GalleryNftData[];
remainingCollectionCount: () => number;
loadMoreCollections: (query?: string) => void;
loadMoreCollections: (showHidden: boolean, query?: string) => void;
loadingCollections: boolean;
isSearchingCollections: boolean;
allNftsLoaded: (nft: App.Data.Gallery.GalleryNftData) => boolean;
loadMoreNfts: (nft: App.Data.Gallery.GalleryNftData) => void;
loadingNfts: (nft: App.Data.Gallery.GalleryNftData) => boolean;
getLoadingNftsCount: (nft: App.Data.Gallery.GalleryNftData) => number;
searchNfts: (query?: string) => Promise<void>;
searchNfts: (showHidden: boolean, query?: string) => Promise<void>;
}

interface GalleryNftsProperties {
Expand Down
14 changes: 9 additions & 5 deletions resources/js/Components/Galleries/Hooks/useGalleryNtfs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,15 @@ export const useGalleryNtfs = ({ nftsPerPage, collectionsPerPage }: GalleryNftsP
: pageMeta.total - collectionsLength;
};

const loadMoreCollections = (query?: string): void => {
const loadMoreCollections = (showHidden: boolean, query?: string): void => {
const nextPageUrl = pageMeta.next_page_url;

if (!loadingCollections && nextPageUrl !== null) {
void fetchCollections(nextPageUrl, query);
void fetchCollections(nextPageUrl, showHidden, query);
}
};

const fetchCollections = async (nextPageUrl: string, query?: string): Promise<void> => {
const fetchCollections = async (nextPageUrl: string, showHidden: boolean, query?: string): Promise<void> => {
cancelPreviousRequest();

setLoadingCollections(true);
Expand All @@ -159,6 +159,10 @@ export const useGalleryNtfs = ({ nftsPerPage, collectionsPerPage }: GalleryNftsP
url.searchParams.append("query", query);
}

if (showHidden) {
url.searchParams.append("showHidden", showHidden.toString());
}

await authenticatedAction(async () => {
let data: CollectionsResponse;

Expand Down Expand Up @@ -197,9 +201,9 @@ export const useGalleryNtfs = ({ nftsPerPage, collectionsPerPage }: GalleryNftsP
});
};

const searchNfts = async (query?: string): Promise<void> => {
const searchNfts = async (showHidden: boolean, query?: string): Promise<void> => {
setIsSearchingCollections(true);
await fetchCollections(pageMeta.first_page_url, query);
await fetchCollections(pageMeta.first_page_url, showHidden, query);
setIsSearchingCollections(false);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { groupBy } from "@ardenthq/sdk-helpers";
import { act, fireEvent, screen, waitFor } from "@testing-library/react";
import axios from "axios";
import { useEffect } from "react";
import { useEffect, useState } from "react";
import { beforeEach, expect } from "vitest";
import GalleryNftData = App.Data.Gallery.GalleryNftData;
import { GalleryNfts, useGalleryNftsContext } from "@/Components/Galleries/Hooks/useGalleryNftsContext";
Expand All @@ -28,6 +28,8 @@ describe("useGalleryNftsContext", () => {
const nfts = [...firstCollectionNfts, ...secondCollectionNfts].flat();

const HookTestComponent = (): JSX.Element => {
const [showHidden, setShowHidden] = useState<boolean>(false);

const {
nfts,
remainingCollectionCount,
Expand All @@ -46,9 +48,13 @@ describe("useGalleryNftsContext", () => {
>;

useEffect(() => {
void searchNfts();
void searchNfts(showHidden);
}, []);

useEffect(() => {
void searchNfts(showHidden);
}, [showHidden]);

const collections = Object.entries(collectionGroups);

return (
Expand Down Expand Up @@ -97,13 +103,22 @@ describe("useGalleryNftsContext", () => {
{remainingCollectionCount() > 0 && (
<button
onClick={() => {
loadMoreCollections();
loadMoreCollections(showHidden);
}}
data-testid="TestGallery__loadCollections"
>
load {remainingCollectionCount()} more collections
</button>
)}

<button
onClick={() => {
setShowHidden(!showHidden);
}}
data-testid="TestGallery__toggleHidden"
>
toggle hidden
</button>
</div>
);
};
Expand Down Expand Up @@ -433,4 +448,26 @@ describe("useGalleryNftsContext", () => {
expect(screen.queryAllByTestId(`NFT_Skeleton--${newNftSlug}`).length).toBe(0);
});
});

it("should append showHidden to the collections endpoint when toggled", async () => {
const axiosSpy = vi.spyOn(axios, "get");

const { container } = render(
<Component
collectionsPerPage={10}
nftsPerPage={10}
/>,
);

await waitFor(() => {
expect(container.getElementsByClassName("TestGallery_Collection").length).toBe(2);
});

act(() => {
fireEvent.click(screen.getByTestId("TestGallery__toggleHidden"));
});

expect(axiosSpy).toHaveBeenCalled();
expect(axiosSpy).toHaveBeenCalledWith(`${BASE_URL}/my-galleries/collections`, expect.objectContaining({}));
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useDebounce } from "@/Hooks/useDebounce";

const debounceTimeout = 400;

export const NftCollectionSearch = (): JSX.Element => {
export const NftCollectionSearch = ({ showHidden }: { showHidden: boolean }): JSX.Element => {
const { t } = useTranslation();
const { clearSelection } = useNftSelectableContext();
const [searchQuery, setSearchQuery] = useState<string>("");
Expand Down Expand Up @@ -40,8 +40,8 @@ export const NftCollectionSearch = (): JSX.Element => {
const remainingCollections = remainingCollectionCount();

useEffect(() => {
void searchNfts(debouncedQuery);
}, [debouncedQuery]);
void searchNfts(showHidden, debouncedQuery);
}, [debouncedQuery, showHidden]);

return (
<>
Expand Down Expand Up @@ -79,7 +79,7 @@ export const NftCollectionSearch = (): JSX.Element => {
variant="secondary"
className="inline-flex w-full flex-1 justify-center sm:flex-none"
onClick={() => {
loadMoreCollections(debouncedQuery);
loadMoreCollections(showHidden, debouncedQuery);
}}
>
{t("pages.galleries.create.load_more_collections", {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe("NftCollectionSlider", () => {

let TestButton: () => JSX.Element;

let Component: () => JSX.Element;
let Component: ({ hiddenCollectionsCount }: { hiddenCollectionsCount?: number }) => JSX.Element;

const addToGalleryMock = vi.fn();
const removeFromGalleryMock = vi.fn();
Expand Down Expand Up @@ -82,7 +82,7 @@ describe("NftCollectionSlider", () => {
};

// eslint-disable-next-line react/display-name
Component = (): JSX.Element => {
Component = ({ hiddenCollectionsCount = 0 }: { hiddenCollectionsCount?: number }): JSX.Element => {
const [isSliderOpen, setSliderOpen] = useState(false);

return (
Expand All @@ -100,7 +100,7 @@ describe("NftCollectionSlider", () => {
>
<GalleryNfts>
<NftSelectionHook>
<NftCollectionSlider />
<NftCollectionSlider hiddenCollectionsCount={hiddenCollectionsCount} />
<TestButton />
</NftSelectionHook>
</GalleryNfts>
Expand Down Expand Up @@ -389,4 +389,24 @@ describe("NftCollectionSlider", () => {
expect(screen.queryByTestId(buttonTestId)).not.toBeInTheDocument();
},
);

it("should not render NftHiddenCollectionsToggle if there are no hidden collections", async () => {
render(<Component />);

await userEvent.click(screen.getByTestId("TestButton"));

await waitFor(() => {
expect(screen.queryByTestId("NftHiddenCollectionsToggle")).not.toBeInTheDocument();
});
});

it("should render NftHiddenCollectionsToggle if there are hidden collections", async () => {
render(<Component hiddenCollectionsCount={1} />);

await userEvent.click(screen.getByTestId("TestButton"));

await waitFor(() => {
expect(screen.queryAllByTestId("NftHiddenCollectionsToggle")).toHaveLength(2);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { NftCollectionSearch } from "./NftCollectionSearch";
import { NftHiddenCollectionsToggle } from "./NftHiddenCollectionsToggle";
import { Button } from "@/Components/Buttons";
import { useEditableGalleryContext } from "@/Components/Galleries/Hooks/useEditableGalleryContext";
import { useNftSelectableContext } from "@/Components/Galleries/Hooks/useNftSelectableContext";
import { Slider, useSliderContext } from "@/Components/Slider";
import { useMetaMaskContext } from "@/Contexts/MetaMaskContext";

export const NftCollectionSlider = (): JSX.Element => {
export const NftCollectionSlider = ({ hiddenCollectionsCount }: { hiddenCollectionsCount: number }): JSX.Element => {
const [showHidden, setShowHidden] = useState<boolean>(false);
const { t } = useTranslation();
const { isOpen, setOpen } = useSliderContext();
const { nfts } = useEditableGalleryContext();
Expand All @@ -23,10 +26,26 @@ export const NftCollectionSlider = (): JSX.Element => {
}}
>
<Slider.Header>
<span className="text-lg font-medium leading-8">{t("pages.galleries.my_nfts")}</span>
<div className="flex w-full items-center justify-between">
<span className="text-lg font-medium leading-8">{t("pages.galleries.my_nfts")}</span>
{hiddenCollectionsCount > 0 && (
<NftHiddenCollectionsToggle
setShowHidden={setShowHidden}
showHidden={showHidden}
className="hidden md:flex"
/>
)}
</div>
</Slider.Header>
<Slider.Content className="relative pb-28">
<NftCollectionSearch />
{hiddenCollectionsCount > 0 && (
<NftHiddenCollectionsToggle
setShowHidden={setShowHidden}
showHidden={showHidden}
className="mb-4 flex w-full items-center justify-between border-b border-theme-secondary-300 pb-4 dark:border-theme-dark-700 md:hidden"
/>
)}
<NftCollectionSearch showHidden={showHidden} />

<div className="fixed inset-x-0 bottom-0 flex w-full items-center justify-end space-x-3 border-t border-theme-secondary-300 bg-white px-8 py-4 dark:border-theme-dark-700 dark:bg-theme-dark-900">
<Button
Expand Down
Loading

0 comments on commit 422fb7c

Please sign in to comment.