Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: hidden collections toggle for create a gallery page #457

Merged
merged 42 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
c03acc6
chore: update language file
patricio0312rev Nov 15, 2023
944027b
feat: hidden collections support for MyGalleryCollectionController
patricio0312rev Nov 15, 2023
fcdfd45
refactor: use of showHidden variable
patricio0312rev Nov 15, 2023
ff30a9d
feat: implement showHidden variable in NftCollectionSearch
patricio0312rev Nov 15, 2023
f0c3196
feat: pass showHidden from useGalleryNfts context
patricio0312rev Nov 15, 2023
70167a3
fix: update typing for context methods
patricio0312rev Nov 15, 2023
2499ec7
feat: initial ui for show hidden toggle
patricio0312rev Nov 15, 2023
9b20944
feat: NftHiddenCollectionsToggle component
patricio0312rev Nov 15, 2023
acffebd
test: NftHiddenCollectionsToggle
patricio0312rev Nov 15, 2023
0a2b63e
test: NftHiddenCollectionsToggle
patricio0312rev Nov 15, 2023
a2e77da
feat: implement NftHiddenCollectionsToggle
patricio0312rev Nov 15, 2023
aa5e39e
fix: restore en.json
patricio0312rev Nov 15, 2023
a2bed80
Merge branch 'develop' into feat/hidden-collections-toggle-for-create…
patricio0312rev Nov 15, 2023
b09f92c
style: resolve style guide violations
patricio0312rev Nov 15, 2023
c8559f9
fix: styles for switch in desktop
patricio0312rev Nov 15, 2023
fae064e
test: useGalleryNftsContext
patricio0312rev Nov 15, 2023
73a82b6
fix: make showHidden not optional
patricio0312rev Nov 15, 2023
4e7ff47
test: MyGalleryCollectionController
patricio0312rev Nov 15, 2023
acbda54
fix: restore phpunit config
patricio0312rev Nov 15, 2023
bc93639
style: resolve style guide violations
patricio0312rev Nov 15, 2023
00c16c0
Merge branch 'develop' into feat/hidden-collections-toggle-for-create…
ItsANameToo Nov 16, 2023
e88d07a
Merge branch 'develop' into feat/hidden-collections-toggle-for-create…
patricio0312rev Nov 16, 2023
72357a4
chore: update en.json
patricio0312rev Nov 16, 2023
2db892a
Merge branch 'develop' into feat/hidden-collections-toggle-for-create…
patricio0312rev Nov 16, 2023
0a51fdd
fix: check if all collections are hidden from controller
patricio0312rev Nov 16, 2023
0d7cf2e
feat: new translations for messages
patricio0312rev Nov 16, 2023
cdffda1
fix: implement message in placeholder
patricio0312rev Nov 16, 2023
ab086ef
fix: display tooltip message in create a gallery button if there are …
patricio0312rev Nov 16, 2023
0d633cf
Merge branch 'develop' into feat/hidden-collections-toggle-for-create…
patricio0312rev Nov 16, 2023
13b4577
fix: update en.json
patricio0312rev Nov 16, 2023
b2cd29e
chore: rebuild assets
patricio0312rev Nov 16, 2023
8f18f1a
Merge branch 'feat/hidden-collections-toggle-for-create-gallery-page'…
patricio0312rev Nov 16, 2023
c8f2de2
feat: not hidden scope for collections model
patricio0312rev Nov 16, 2023
8ea4ffe
style: resolve style guide violations
patricio0312rev Nov 16, 2023
3e0ecc8
feat: return hidden collections count in my gallery controller
patricio0312rev Nov 16, 2023
8c44d8f
feat: pass hiddenCollectionsCount to NftGridEditable
patricio0312rev Nov 16, 2023
2ebf07f
feat: support for hiddenCollectionsCount in NftCollectionSlider
patricio0312rev Nov 16, 2023
6fbbfac
test: NftCollectionSlider
patricio0312rev Nov 16, 2023
ce8abe2
feat: support for hiddenCollectionsCount in NftGridEditable
patricio0312rev Nov 16, 2023
f7c4f64
fix: LayoutWrapper test
patricio0312rev Nov 16, 2023
48f500c
fix: remove console logs
patricio0312rev Nov 16, 2023
8dbf870
Merge branch 'develop' into feat/hidden-collections-toggle-for-create…
patricio0312rev Nov 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()->whereNotIn('collections.id', $user->hiddenCollections()->pluck('id')->toArray());
patricio0312rev marked this conversation as resolved.
Show resolved Hide resolved

$collections = $collectionsQuery
->where('collections.name', 'ilike', sprintf('%%%s%%', $request->get('query')))
->withUserNftsCount($user)
->orderBy('id')
Expand Down
5 changes: 5 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 Down
3 changes: 3 additions & 0 deletions lang/en/pages.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,13 @@
'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 successfully deleted',
'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 @@ -181,6 +183,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
@@ -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 => {
const [showHidden, setShowHidden] = useState<boolean>(false);
const { t } = useTranslation();
const { isOpen, setOpen } = useSliderContext();
const { nfts } = useEditableGalleryContext();
Expand All @@ -23,10 +26,22 @@ 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>
<NftHiddenCollectionsToggle
setShowHidden={setShowHidden}
showHidden={showHidden}
className="hidden md:flex"
/>
</div>
</Slider.Header>
<Slider.Content className="relative pb-28">
<NftCollectionSearch />
<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
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { NftHiddenCollectionsToggle } from "./NftHiddenCollectionsToggle";
import { render, screen } from "@/Tests/testing-library";

describe("NftHiddenCollectionsToggle", () => {
it("should render", () => {
render(
<NftHiddenCollectionsToggle
showHidden={true}
setShowHidden={vi.fn()}
/>,
);

expect(screen.getByTestId("NftHiddenCollectionsToggle")).toBeInTheDocument();
});

it("should display the toggle as checked if showHidden is true", () => {
const { asFragment } = render(
<NftHiddenCollectionsToggle
showHidden={true}
setShowHidden={vi.fn()}
/>,
);

expect(screen.getByTestId("Toggle")).toBeInTheDocument();
expect(asFragment()).toMatchSnapshot();
});

it("should display the toggle as unchecked if showHidden is false", () => {
const { asFragment } = render(
<NftHiddenCollectionsToggle
showHidden={false}
setShowHidden={vi.fn()}
/>,
);

expect(screen.getByTestId("Toggle")).toBeInTheDocument();
expect(asFragment()).toMatchSnapshot();
});

it("should call setShowHidden when the toggle is clicked", () => {
const setShowHidden = vi.fn();

render(
<NftHiddenCollectionsToggle
showHidden={false}
setShowHidden={setShowHidden}
/>,
);

screen.getByTestId("Toggle").click();

expect(setShowHidden).toHaveBeenCalled();
});

it("should render a custom class name", () => {
render(
<NftHiddenCollectionsToggle
showHidden={false}
setShowHidden={vi.fn()}
className="custom-class"
/>,
);

expect(screen.getByTestId("NftHiddenCollectionsToggle")).toHaveClass("custom-class");
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import cn from "classnames";
import React, { type Dispatch, type SetStateAction } from "react";
import { useTranslation } from "react-i18next";
import { Toggle } from "@/Components/Form/Toggle";

export const NftHiddenCollectionsToggle = ({
showHidden,
setShowHidden,
className,
}: {
showHidden: boolean;
setShowHidden: Dispatch<SetStateAction<boolean>>;
className?: string;
}): JSX.Element => {
const { t } = useTranslation();

return (
<div
className={cn("flex items-center gap-3", className)}
data-testid="NftHiddenCollectionsToggle"
>
<span className="text-base font-medium text-theme-secondary-700 dark:text-theme-dark-200">
{t("pages.galleries.show_hidden_collections")}
</span>

<Toggle
checked={showHidden}
onChange={() => {
setShowHidden(!showHidden);
}}
/>
</div>
);
};
Loading
Loading