diff --git a/app/api/config.ts b/app/api/config.ts index d4b4e1b..75f3bc5 100644 --- a/app/api/config.ts +++ b/app/api/config.ts @@ -51,6 +51,7 @@ export const ENDPOINTS = { } }, filter: `${API_PREFIX}/filter`, + filterTypes: `${API_PREFIX}/type/all`, search: { profileList: `${API_PREFIX}/search/profile/list`, profileHistory: `${API_PREFIX}/search/history`, diff --git a/app/components/Discovery/Modal/FiltersAgeRatingModal.tsx b/app/components/Discovery/Modal/FiltersAgeRatingModal.tsx new file mode 100644 index 0000000..167a2fe --- /dev/null +++ b/app/components/Discovery/Modal/FiltersAgeRatingModal.tsx @@ -0,0 +1,106 @@ +"use client"; + +import { FilterAgeRatingToString } from "#/api/utils"; +import { + Button, + Checkbox, + Label, + Modal, + ModalBody, + ModalFooter, + ModalHeader, +} from "flowbite-react"; +import { useEffect, useState } from "react"; + +type Props = { + isOpen: boolean; + setIsOpen: (isOpen: boolean) => void; + ageRatings: number[]; + setAgeRatings: (lists: number[]) => void; +}; + +export const FiltersAgeRatingModal = ({ + isOpen, + setIsOpen, + ageRatings, + setAgeRatings, +}: Props) => { + const [newAgeRatings, setNewAgeRatings] = useState(ageRatings); + + function toggleRating(number: number) { + if (newAgeRatings.includes(number)) { + setNewAgeRatings(newAgeRatings.filter((rating) => rating != number)); + } else { + setNewAgeRatings([...newAgeRatings, number]); + } + } + + useEffect(() => { + setNewAgeRatings(ageRatings); + }, [ageRatings]); + + return ( + setIsOpen(false)} dismissible> + Выберите списки + + {Object.entries(FilterAgeRatingToString).map(([key, value]) => { + return ( +
+ toggleRating(Number(key))} + checked={newAgeRatings.includes(Number(key))} + color="blue" + /> + +
+ ); + })} +
+ + + + + +
+ ); +}; diff --git a/app/components/Discovery/Modal/FiltersModal.tsx b/app/components/Discovery/Modal/FiltersModal.tsx index 38acba5..c0069d9 100644 --- a/app/components/Discovery/Modal/FiltersModal.tsx +++ b/app/components/Discovery/Modal/FiltersModal.tsx @@ -2,6 +2,7 @@ import { Filter, + FilterAgeRatingToString, FilterCategoryIdToString, FilterCountry, FilterDefault, @@ -14,6 +15,7 @@ import { FilterStatusIdToString, FilterStudio, FilterYear, + tryCatchAPI, } from "#/api/utils"; import { Button, @@ -24,10 +26,14 @@ import { ModalFooter, ModalHeader, } from "flowbite-react"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { FiltersGenreModal } from "./FiltersGenreModal"; import { useUserStore } from "#/store/auth"; import { FiltersListExcludeModal } from "./FiltersListExcludeModal"; +import { ENDPOINTS } from "#/api/config"; +import { FiltersTypesModal } from "./FiltersTypesModal"; +import { FiltersAgeRatingModal } from "./FiltersAgeRatingModal"; +import { useRouter } from "next/navigation"; type ModalProps = { isOpen: boolean; @@ -37,20 +43,46 @@ type ModalProps = { export const FiltersModal = ({ isOpen, setIsOpen, filter }: ModalProps) => { const userStore = useUserStore(); + const router = useRouter(); const [newFilter, setNewFilter] = useState(filter || FilterDefault); const [isGenreModalOpen, setIsGenreModalOpen] = useState(false); const [isListExcludeModalOpen, setIsListExcludeModalOpen] = useState(false); + const [isTypeModalOpen, setIsTypeModalOpen] = useState(false); + const [isAgeRatingModalOpen, setIsAgeRatingModalOpen] = useState(false); + + const [types, setTypes] = useState([]); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchData = async () => { + setError(null); + + const { data, error } = await tryCatchAPI(fetch(ENDPOINTS.filterTypes)); + + if (error) { + setError(error); + } else { + setTypes(data.types); + } + }; + fetchData(); + }, []); function saveGenres(genres, is_genres_exclude_mode_enabled) { setNewFilter({ ...newFilter, genres, is_genres_exclude_mode_enabled }); } + function saveFilter() { + const _filter = JSON.stringify(newFilter); + router.push(`/discovery/filter?filter=${_filter}`); + setIsOpen(false); + } + return ( <> setIsOpen(false)} size="4xl" dismissible @@ -163,11 +195,15 @@ export const FiltersModal = ({ isOpen, setIsOpen, filter }: ModalProps) => {
@@ -443,11 +479,13 @@ export const FiltersModal = ({ isOpen, setIsOpen, filter }: ModalProps) => {
@@ -476,7 +514,11 @@ export const FiltersModal = ({ isOpen, setIsOpen, filter }: ModalProps) => {
- + + +
{ setNewFilter({ ...newFilter, profile_list_exclusions }) } /> + setNewFilter({ ...newFilter, types })} + /> + + setNewFilter({ ...newFilter, age_ratings }) + } + /> ); }; diff --git a/app/components/Discovery/Modal/FiltersTypesModal.tsx b/app/components/Discovery/Modal/FiltersTypesModal.tsx new file mode 100644 index 0000000..80b50bb --- /dev/null +++ b/app/components/Discovery/Modal/FiltersTypesModal.tsx @@ -0,0 +1,100 @@ +"use client"; + +import { + Button, + Checkbox, + Label, + Modal, + ModalBody, + ModalFooter, + ModalHeader, +} from "flowbite-react"; +import { useEffect, useState } from "react"; + +type Props = { + isOpen: boolean; + setIsOpen: (isOpen: boolean) => void; + typesData: any[]; + types: number[]; + setTypes: (types: number[]) => void; +}; + +export const FiltersTypesModal = ({ + isOpen, + setIsOpen, + typesData, + types, + setTypes, +}: Props) => { + const [newTypes, setNewTypes] = useState(types); + + function toggleType(number: number) { + if (newTypes.includes(number)) { + setNewTypes(newTypes.filter((list) => list != number)); + } else { + setNewTypes([...newTypes, number]); + } + } + + useEffect(() => { + setNewTypes(types); + }, [types]); + + return ( + setIsOpen(false)} dismissible> + Выберите списки + + {typesData.map((item) => { + return ( +
+ toggleType(Number(item.id))} + checked={newTypes.includes(Number(item.id))} + color="blue" + /> + +
+ ); + })} +
+ + + + + +
+ ); +}; diff --git a/app/pages/Discover.tsx b/app/pages/Discover.tsx index b4415c4..629658a 100644 --- a/app/pages/Discover.tsx +++ b/app/pages/Discover.tsx @@ -45,7 +45,11 @@ export const DiscoverPage = () => { Коллекции -