From 213d2936294acb27a2d473fda7359bc280be34cf Mon Sep 17 00:00:00 2001 From: Lanskikh Date: Wed, 22 Jan 2025 19:34:38 +0500 Subject: [PATCH] upd --- package.json | 1 + src/app/(main)/blog/[articleId]/edit/page.tsx | 2 +- src/app/(main)/blog/[articleId]/layout.tsx | 14 +++- src/app/(main)/blog/[articleId]/page.tsx | 13 +++- src/app/(main)/blog/layout.tsx | 11 ++- src/app/(main)/blog/page.tsx | 10 ++- src/components/ArticleActions.tsx | 5 +- src/components/BlockActions.tsx | 2 +- src/components/DeleteItemModal.tsx | 10 ++- src/components/ItemActions.tsx | 46 ++++++++++-- .../articleInputs/ArticleContentInput.tsx | 2 +- .../articleInputs/ArticleSliderImageInput.tsx | 2 +- .../articleInputs/ArticleSliderInput.tsx | 2 +- .../modals/ArticleContentFormModal.tsx | 54 +++++++------ ...aderFormModal.tsx => ArticleFormModal.tsx} | 9 ++- .../pages/ArticlePage/ArticleSyncPage.tsx | 40 +++++++++- src/components/pages/BlogPage/ArticleCard.tsx | 53 +++++++++---- .../pages/BlogPage/ArticlesList.tsx | 36 ++++++--- .../pages/BlogPage/ArticlesPageActions.tsx | 75 +++++++++++++++++++ .../pages/BlogPage/ArticlesPageHeader.tsx | 64 ---------------- .../pages/ProjectsPage/TagsFilters.tsx | 2 +- src/hooks/useArticleMutation.ts | 2 +- src/hooks/useDeleteMutation.ts | 10 ++- src/lib/Providers.tsx | 6 +- src/queries/getDraftedArticles.ts | 20 +++++ src/utils/isCompany.ts | 9 +++ src/utils/isProject.ts | 5 +- yarn.lock | 12 +++ 28 files changed, 359 insertions(+), 158 deletions(-) rename src/components/modals/{ArticleHeaderFormModal.tsx => ArticleFormModal.tsx} (94%) create mode 100644 src/components/pages/BlogPage/ArticlesPageActions.tsx delete mode 100644 src/components/pages/BlogPage/ArticlesPageHeader.tsx create mode 100644 src/queries/getDraftedArticles.ts create mode 100644 src/utils/isCompany.ts diff --git a/package.json b/package.json index 622c5bb6..86040e87 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@tanstack/react-query": "^5.62.7", + "@tanstack/react-query-devtools": "^5.64.2", "@tinymce/tinymce-react": "^5.1.1", "countries-phone-masks": "^1.1.0", "date-fns": "^3.6.0", diff --git a/src/app/(main)/blog/[articleId]/edit/page.tsx b/src/app/(main)/blog/[articleId]/edit/page.tsx index 2de8e77c..60d18f47 100644 --- a/src/app/(main)/blog/[articleId]/edit/page.tsx +++ b/src/app/(main)/blog/[articleId]/edit/page.tsx @@ -4,7 +4,7 @@ import { ArticleActions } from '@/components/ArticleActions'; import { ArticleHeader } from '@/components/ArticleHeader'; import { ArticleContentInput } from '@/components/articleInputs/ArticleContentInput'; import { ArticleSliderInput } from '@/components/articleInputs/ArticleSliderInput'; -import { IArticleFormInput } from '@/components/modals/ArticleHeaderFormModal'; +import { IArticleFormInput } from '@/components/modals/ArticleFormModal'; import { ArticleContent } from '@/components/pages/BlogPage/ArticleContent'; import { IArticle } from '@/types/IArticle'; import { Button } from '@/ui/Button'; diff --git a/src/app/(main)/blog/[articleId]/layout.tsx b/src/app/(main)/blog/[articleId]/layout.tsx index dc1192ca..04166c0e 100644 --- a/src/app/(main)/blog/[articleId]/layout.tsx +++ b/src/app/(main)/blog/[articleId]/layout.tsx @@ -1,8 +1,11 @@ import { api } from '@/api'; +import { CloseIcon } from '@/components/icons/CloseIcon'; import { RelevantArticlesPreview } from '@/components/pages/ArticlePage/RelevantArticlesPreview'; +import { ClassNameWrapper } from '@/hocs/ClassNameWrapper'; import { IArticle } from '@/types/IArticle'; import { QueryClient } from '@tanstack/react-query'; import type { Metadata } from 'next'; +import Link from 'next/link'; export async function generateMetadata({ params, @@ -41,10 +44,19 @@ export default async function Layout({ params: Promise<{ articleId: string }>; }) { const { articleId } = await params; + return ( -
+
{children} + + + + +
); } diff --git a/src/app/(main)/blog/[articleId]/page.tsx b/src/app/(main)/blog/[articleId]/page.tsx index 4e055ff0..231424b0 100644 --- a/src/app/(main)/blog/[articleId]/page.tsx +++ b/src/app/(main)/blog/[articleId]/page.tsx @@ -1,6 +1,11 @@ import { api } from '@/api'; +import { ArticleSyncPage } from '@/components/pages/ArticlePage/ArticleSyncPage'; import { IArticle } from '@/types/IArticle'; -import { HydrationBoundary, QueryClient } from '@tanstack/react-query'; +import { + dehydrate, + HydrationBoundary, + QueryClient, +} from '@tanstack/react-query'; export default async function ArticlePage({ params: { articleId }, @@ -15,5 +20,9 @@ export default async function ArticlePage({ await api.get(`articles/${articleId}`).json(), }); - return ; + return ( + + + + ); } diff --git a/src/app/(main)/blog/layout.tsx b/src/app/(main)/blog/layout.tsx index 3ea5c012..ddacbbed 100644 --- a/src/app/(main)/blog/layout.tsx +++ b/src/app/(main)/blog/layout.tsx @@ -1,4 +1,4 @@ -import { ArticlesPageHeader } from '@/components/pages/BlogPage/ArticlesPageHeader'; +import { Title } from '@/ui/Title'; import { Metadata, ResolvingMetadata } from 'next'; export async function generateMetadata( @@ -16,9 +16,12 @@ export default async function BlogLayout({ children: React.ReactNode; }) { return ( -
- - {children} +
+ + В блоге собраны все публикации о работе компании: + <span className="text-[#7A7A7A]"> новости, статьи и видео</span> + +
{children}
); } diff --git a/src/app/(main)/blog/page.tsx b/src/app/(main)/blog/page.tsx index 778eaf87..9ea306e5 100644 --- a/src/app/(main)/blog/page.tsx +++ b/src/app/(main)/blog/page.tsx @@ -1,7 +1,12 @@ import { api } from '@/api'; import { ArticlesList } from '@/components/pages/BlogPage/ArticlesList'; +import { ArticlesPageActions } from '@/components/pages/BlogPage/ArticlesPageActions'; import { IArticle } from '@/types/IArticle'; -import { HydrationBoundary, QueryClient } from '@tanstack/react-query'; +import { + dehydrate, + HydrationBoundary, + QueryClient, +} from '@tanstack/react-query'; import { Suspense } from 'react'; export default async function BlogPage({ @@ -19,7 +24,8 @@ export default async function BlogPage({ }); return ( - + + Loading...}> diff --git a/src/components/ArticleActions.tsx b/src/components/ArticleActions.tsx index 9d2d65b5..af318cba 100644 --- a/src/components/ArticleActions.tsx +++ b/src/components/ArticleActions.tsx @@ -7,10 +7,7 @@ import { usePathname, useRouter } from 'next/navigation'; import { UseFormSetValue } from 'react-hook-form'; import { DeleteIcon } from './icons/DeleteIcon'; import { EditIcon } from './icons/EditIcon'; -import { - ArticleFormModal, - IArticleFormInput, -} from './modals/ArticleHeaderFormModal'; +import { ArticleFormModal, IArticleFormInput } from './modals/ArticleFormModal'; import { DeleteArticleModal } from './modals/DeleteArticleModal'; export function ArticleActions({ diff --git a/src/components/BlockActions.tsx b/src/components/BlockActions.tsx index 2a292922..2b0e6e70 100644 --- a/src/components/BlockActions.tsx +++ b/src/components/BlockActions.tsx @@ -10,7 +10,7 @@ import { EditIcon } from './icons/EditIcon'; import { PlusIcon } from './icons/PlusIcon'; import { TrashIcon } from './icons/TrashIcon'; import { ArticleContentEditorModal } from './modals/ArticleContentEditorModal'; -import { IArticleFormInput } from './modals/ArticleHeaderFormModal'; +import { IArticleFormInput } from './modals/ArticleFormModal'; interface IBlockActionsProps { item: IContent & Record<'id', string>; diff --git a/src/components/DeleteItemModal.tsx b/src/components/DeleteItemModal.tsx index 17c87ab5..ff0085f6 100644 --- a/src/components/DeleteItemModal.tsx +++ b/src/components/DeleteItemModal.tsx @@ -9,7 +9,7 @@ export function DeleteItemModal({ id, }: { title: string; - entity: 'projects' | 'companies'; + entity: 'projects' | 'companies' | 'articles'; id: string; }) { const { setModal } = useModalStore(); @@ -27,9 +27,13 @@ export function DeleteItemModal({ - ); diff --git a/src/components/ItemActions.tsx b/src/components/ItemActions.tsx index fe3d54fd..4d097246 100644 --- a/src/components/ItemActions.tsx +++ b/src/components/ItemActions.tsx @@ -3,50 +3,80 @@ import { ClassNameWrapper } from '@/hocs/ClassNameWrapper'; import { useCheckAuthQuery } from '@/queries/checkAuth'; import { useModalStore } from '@/stores/useModalStore'; +import { IArticle } from '@/types/IArticle'; import { ICompany } from '@/types/ICompany'; import { IProject } from '@/types/IProject'; +import { isCompany } from '@/utils/isCompany'; import { isProject } from '@/utils/isProject'; +import { SyntheticEvent } from 'react'; import { DeleteItemModal } from './DeleteItemModal'; import { DeleteIcon } from './icons/DeleteIcon'; import { EditIcon } from './icons/EditIcon'; +import { ArticleFormModal } from './modals/ArticleFormModal'; import { CompanyFormModal } from './modals/CompanyFormModal'; import { ProjectFormModal } from './modals/ProjectFormModal'; -export function ItemActions({ item }: { item: IProject | ICompany }) { +export function ItemActions({ + item, +}: { + item: IProject | ICompany | IArticle; +}) { const { data: auth } = useCheckAuthQuery(); const { setModal } = useModalStore(); - function handleEdit() { + function handleEdit(e: SyntheticEvent) { + e.stopPropagation(); if (isProject(item)) { const { company, ...project } = item; setModal( , 'editProjectForm' ); - } else { + } else if (isCompany(item)) { const { projects, ...company } = item; setModal( , 'editCompanyForm' ); + } else { + setModal( + , + 'editArticleForm' + ); } } - function handleDelete() { + function handleDelete(e: SyntheticEvent) { + e.stopPropagation(); setModal( , - `delete${isProject(item) ? 'Project' : 'Company'}` + `delete${ + isProject(item) ? 'Project' : isCompany(item) ? 'Company' : 'Article' + }` ); } return ( auth && ( -
+
- ( - { - ref.current = editor; - }} - init={{ - content_style: 'body {background: #232425}', - }} - inline - /> - )} - /> + {blocks.map((block, index) => ( + ( + { + ref.current = editor; + }} + init={{ + content_style: 'body {background: #232425}', + }} + inline + /> + )} + /> + ))}
); diff --git a/src/components/modals/ArticleHeaderFormModal.tsx b/src/components/modals/ArticleFormModal.tsx similarity index 94% rename from src/components/modals/ArticleHeaderFormModal.tsx rename to src/components/modals/ArticleFormModal.tsx index eae20449..40b72ca3 100644 --- a/src/components/modals/ArticleHeaderFormModal.tsx +++ b/src/components/modals/ArticleFormModal.tsx @@ -10,8 +10,6 @@ import { MediaUploader } from '../MediaUploader'; import ArticleContentFormModal from './ArticleContentFormModal'; import { FormModalHeader } from './FormModalHeader'; -export interface IArticleFormInput extends Omit {} - interface IArticleFormModalProps { action: TAction; defaultValues?: TAction extends 'edit' ? IArticle : undefined; @@ -25,11 +23,14 @@ export function ArticleFormModal({ const { handleSubmit, register, setValue, getValues, control } = useForm({ - defaultValues: { ...defaultValues, blocks: [], drafted: true }, + defaultValues: { ...defaultValues, blocks: [], tags: [], drafted: true }, }); async function onSubmit(data: IArticle) { - const article = await mutateAsync(data); + const article = await mutateAsync({ + ...data, + blocks: JSON.stringify(data.blocks), + }); setModal( , 'articleContentFormModal' diff --git a/src/components/pages/ArticlePage/ArticleSyncPage.tsx b/src/components/pages/ArticlePage/ArticleSyncPage.tsx index 5ae34920..0ff5a04e 100644 --- a/src/components/pages/ArticlePage/ArticleSyncPage.tsx +++ b/src/components/pages/ArticlePage/ArticleSyncPage.tsx @@ -1,5 +1,41 @@ 'use client'; -export function ArticleSyncPage() { - return
; +import { useGetArticleById } from '@/queries/getArticleById'; +import Image from 'next/image'; + +export function ArticleSyncPage({ articleId }: { articleId: string }) { + const { data: article } = useGetArticleById(articleId); + + if (!article) return null; + + return ( +
+
+
+ {article.title} +
+
+
+

{article.title}

+
+ {article.tags.map((tag) => ( +
+ {tag} +
+ ))} +
+
+
+
+
+ ); } diff --git a/src/components/pages/BlogPage/ArticleCard.tsx b/src/components/pages/BlogPage/ArticleCard.tsx index 302ed51c..97b64017 100644 --- a/src/components/pages/BlogPage/ArticleCard.tsx +++ b/src/components/pages/BlogPage/ArticleCard.tsx @@ -1,34 +1,47 @@ 'use client'; +import { ItemActions } from '@/components/ItemActions'; +import { useCheckAuthQuery } from '@/queries/checkAuth'; import { IArticle } from '@/types/IArticle'; import { PostTag } from '@/ui/PostTag'; import Image from 'next/image'; -import Link from 'next/link'; -import { useSearchParams } from 'next/navigation'; +import { useRouter, useSearchParams } from 'next/navigation'; export function ArticleCard({ id, title, cardImage, tags, + blocks, + drafted, + posterImage, + createdAt, className, }: IArticle & { className?: string }) { const params = useSearchParams(); + const { push } = useRouter(); + + const { data: auth } = useCheckAuthQuery(); + return ( - push('/blog/' + id)} + className={`space-y-3${ className ? ' ' + className : '' - } hover:backdrop-blur-[500px] hover:bg-[radial-gradient(ellipse_at_bottom,#7A7A7A,transparent)] bg-cover rounded-2xl relative`} + } hover:backdrop-blur-[500px] cursor-pointer group hover:bg-[radial-gradient(ellipse_at_bottom,#7A7A7A99,transparent)] transition-[background-size] bg-[length:100%_0%] bg-bottom hover:bg-[length:100%_100%] bg-no-repeat rounded-2xl p-3 relative h-full`} > - {title} +
+ {title} + {auth && ( +
+ )} +

{title}

{tags.map((tag) => ( @@ -39,6 +52,18 @@ export function ArticleCard({ /> ))}
- + +
); } diff --git a/src/components/pages/BlogPage/ArticlesList.tsx b/src/components/pages/BlogPage/ArticlesList.tsx index 6548dabf..cde4d7e2 100644 --- a/src/components/pages/BlogPage/ArticlesList.tsx +++ b/src/components/pages/BlogPage/ArticlesList.tsx @@ -1,17 +1,35 @@ 'use client'; import { useGetArticlesQuery } from '@/queries/getArticles'; -import { TagsFilters } from '../ProjectsPage/TagsFilters'; +import { useGetDraftedArticlesQuery } from '@/queries/getDraftedArticles'; import { ArticleCard } from './ArticleCard'; export function ArticlesList({ tags }: { tags: string[] }) { const { data: articles } = useGetArticlesQuery(tags); + const { data: drafted } = useGetDraftedArticlesQuery(tags); + return ( -
- -
- {articles && articles.length > 0 ? ( +
+ {drafted && drafted.length > 0 ? ( +
+

Черновики

+
+ {drafted?.map((article, index) => ( + + ))} +
+
+ ) : ( + <> + )} + {articles && articles.length > 0 ? ( +
+

Опубликованое

{articles?.map((article, index) => ( ))}
- ) : ( -

Статьи не найдены

- )} -
+
+ ) : ( +

Статьи не найдены

+ )}
); } diff --git a/src/components/pages/BlogPage/ArticlesPageActions.tsx b/src/components/pages/BlogPage/ArticlesPageActions.tsx new file mode 100644 index 00000000..b18c898a --- /dev/null +++ b/src/components/pages/BlogPage/ArticlesPageActions.tsx @@ -0,0 +1,75 @@ +'use client'; + +import { PlusIcon } from '@/components/icons/PlusIcon'; +import { ArticleFormModal } from '@/components/modals/ArticleFormModal'; +import { ClassNameWrapper } from '@/hocs/ClassNameWrapper'; +import { OpenFormModalWrapper } from '@/hocs/OpenFormModalWrapper'; +import { useCheckAuthQuery } from '@/queries/checkAuth'; +import { useGetDraftedArticlesQuery } from '@/queries/getDraftedArticles'; +import { IArticle } from '@/types/IArticle'; +import { Button } from '@/ui/Button'; +import { useQueryClient } from '@tanstack/react-query'; +import { useEffect, useState } from 'react'; +import { TagsFilters } from '../ProjectsPage/TagsFilters'; + +export function ArticlesPageActions({ tags }: { tags: string[] }) { + const { data: drafts, refetch } = useGetDraftedArticlesQuery(tags); + + const { data: auth } = useCheckAuthQuery(); + + const queryClient = useQueryClient(); + + const [show, setShow] = useState(false); + const [hiddenDrafts, setDraftedArticles] = useState(); + + useEffect(() => { + setShow(!!drafts); + }, [drafts]); + + function handleShowDrafted() { + if (!drafts) { + refetch(); + queryClient.setQueryData(['articles', 'drafted', tags], hiddenDrafts); + setDraftedArticles([]); + } else { + setDraftedArticles(drafts); + queryClient.setQueryData(['articles', 'drafted', tags], []); + } + } + + return ( +
+
+ } + > + + + {auth && ( + + )} +
+ +
+ ); +} diff --git a/src/components/pages/BlogPage/ArticlesPageHeader.tsx b/src/components/pages/BlogPage/ArticlesPageHeader.tsx deleted file mode 100644 index 6f8ad5a4..00000000 --- a/src/components/pages/BlogPage/ArticlesPageHeader.tsx +++ /dev/null @@ -1,64 +0,0 @@ -'use client'; - -import { PlusIcon } from '@/components/icons/PlusIcon'; -import { ArticleFormModal } from '@/components/modals/ArticleHeaderFormModal'; -import { ClassNameWrapper } from '@/hocs/ClassNameWrapper'; -import { OpenFormModalWrapper } from '@/hocs/OpenFormModalWrapper'; -import { useCheckAuthQuery } from '@/queries/checkAuth'; -import { IArticle } from '@/types/IArticle'; -import { Button } from '@/ui/Button'; -import { Title } from '@/ui/Title'; -import { useQueryClient } from '@tanstack/react-query'; - -export function ArticlesPageHeader() { - const auth = useCheckAuthQuery(); - - const queryClient = useQueryClient(); - - return ( -
- - В блоге собраны все публикации о работе компании: - <span className="text-[#7A7A7A]"> новости, статьи и видео</span> - -
- } - > - - - {auth && ( - - )} -
-
- ); -} diff --git a/src/components/pages/ProjectsPage/TagsFilters.tsx b/src/components/pages/ProjectsPage/TagsFilters.tsx index 55048e05..fc61282d 100644 --- a/src/components/pages/ProjectsPage/TagsFilters.tsx +++ b/src/components/pages/ProjectsPage/TagsFilters.tsx @@ -39,7 +39,7 @@ export function TagsFilters({ return ( <> -
+
{['Все', ...(type === 'project' ? projectsTags : postTags)].map( (tag) => ( + mutationFn: async (json: Omit & { blocks: string }) => action === 'create' ? await api.post('articles', { json }).json() : await api.put(`articles/${id}`, { json }).json(), diff --git a/src/hooks/useDeleteMutation.ts b/src/hooks/useDeleteMutation.ts index a954663f..bb57ddba 100644 --- a/src/hooks/useDeleteMutation.ts +++ b/src/hooks/useDeleteMutation.ts @@ -1,10 +1,9 @@ import { api } from '@/api'; import { useModalStore } from '@/stores/useModalStore'; -import { IProject } from '@/types/IProject'; import { useMutation, useQueryClient } from '@tanstack/react-query'; export function useDeleteMutation( - entity: 'projects' | 'companies', + entity: 'projects' | 'companies' | 'articles', id: string ) { const { setModal } = useModalStore(); @@ -12,10 +11,13 @@ export function useDeleteMutation( const queryClient = useQueryClient(); const { mutateAsync: remove } = useMutation({ - mutationFn: async () => - await api.delete(`${entity}/${id}`).json(), + mutationFn: async () => await api.delete(`${entity}/${id}`).json(), onSuccess: () => { queryClient.invalidateQueries({ queryKey: [entity] }); + + if (entity === 'articles') + queryClient.setQueryData(['articles', 'drafted', []], []); + setModal(null, ''); }, }); diff --git a/src/lib/Providers.tsx b/src/lib/Providers.tsx index d163fd77..d2ede8dc 100644 --- a/src/lib/Providers.tsx +++ b/src/lib/Providers.tsx @@ -1,6 +1,7 @@ 'use client'; import { QueryClientProvider } from '@tanstack/react-query'; +import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { useState } from 'react'; import { getQueryClient } from './queryClient'; @@ -8,6 +9,9 @@ export const Providers = ({ children }: { children: React.ReactNode }) => { const [queryClient] = useState(getQueryClient); return ( - {children} + + {children} + + ); }; diff --git a/src/queries/getDraftedArticles.ts b/src/queries/getDraftedArticles.ts new file mode 100644 index 00000000..baa9f78a --- /dev/null +++ b/src/queries/getDraftedArticles.ts @@ -0,0 +1,20 @@ +import { api } from '@/api'; +import { IArticle } from '@/types/IArticle'; +import { useQuery } from '@tanstack/react-query'; + +export function useGetDraftedArticlesQuery(tags: string | string[] = []) { + return useQuery({ + enabled: false, + queryKey: ['articles', 'drafted', tags], + queryFn: async () => + await api + .get( + `articles/drafted?${ + Array.isArray(tags) + ? tags.map((tag) => `tags=${tag}`).join('&') + : 'tags=' + tags + }` + ) + .json(), + }); +} diff --git a/src/utils/isCompany.ts b/src/utils/isCompany.ts new file mode 100644 index 00000000..4d619ec2 --- /dev/null +++ b/src/utils/isCompany.ts @@ -0,0 +1,9 @@ +import { IArticle } from '@/types/IArticle'; +import { ICompany } from '@/types/ICompany'; +import { IProject } from '@/types/IProject'; + +export function isCompany( + item: IProject | ICompany | IArticle +): item is ICompany { + return 'color' in item; +} diff --git a/src/utils/isProject.ts b/src/utils/isProject.ts index 058c49cf..12dacbb6 100644 --- a/src/utils/isProject.ts +++ b/src/utils/isProject.ts @@ -1,6 +1,9 @@ +import { IArticle } from '@/types/IArticle'; import { ICompany } from '@/types/ICompany'; import { IProject } from '@/types/IProject'; -export function isProject(item: IProject | ICompany): item is IProject { +export function isProject( + item: IProject | ICompany | IArticle +): item is IProject { return 'image' in item; } diff --git a/yarn.lock b/yarn.lock index 50c9fa9f..6df3c635 100644 --- a/yarn.lock +++ b/yarn.lock @@ -335,6 +335,18 @@ resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.62.7.tgz#c7f6d0131c08cd2f60e73ec6e7b70e2e9e335def" integrity sha512-fgpfmwatsrUal6V+8EC2cxZIQVl9xvL7qYa03gsdsCy985UTUlS4N+/3hCzwR0PclYDqisca2AqR1BVgJGpUDA== +"@tanstack/query-devtools@5.64.2": + version "5.64.2" + resolved "https://registry.yarnpkg.com/@tanstack/query-devtools/-/query-devtools-5.64.2.tgz#3d8f8abb17815a7302482b67713cb933c79ed6ba" + integrity sha512-3DautR5UpVZdk/qNIhioZVF7g8fdQZ1U98sBEEk4Tzz3tihSBNMPgwlP40nzgbPEDBIrn/j/oyyvNBVSo083Vw== + +"@tanstack/react-query-devtools@^5.64.2": + version "5.64.2" + resolved "https://registry.yarnpkg.com/@tanstack/react-query-devtools/-/react-query-devtools-5.64.2.tgz#ece61dfad8032305aefd3f0eb044ccd8304ffa1b" + integrity sha512-+ZjJVnPzc8BUV/Eklu2k9T/IAyAyvwoCHqOaOrk2sbU33LFhM52BpX4eyENXn0bx5LwV3DJZgEQlIzucoemfGQ== + dependencies: + "@tanstack/query-devtools" "5.64.2" + "@tanstack/react-query@^5.62.7": version "5.62.7" resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.62.7.tgz#8f253439a38ad6ce820bc6d42d89ca2556574d1a"