226 lines
7.5 KiB
TypeScript
226 lines
7.5 KiB
TypeScript
import { SearchedUserFilesList } from '@/app/ui/search/searched-user-files-list';
|
||
import { SearchedGlobalFilesList } from '@/app/ui/search/searched-global-files-list';
|
||
import { useCallback, useState, useImperativeHandle } from 'react';
|
||
import { searchUserFiles, searchGlobalFiles } from '@/app/actions/searchActions';
|
||
import { useQueryClient } from '@tanstack/react-query';
|
||
import { Pagination } from '@/app/components/Pagination';
|
||
|
||
export interface SearchItem {
|
||
url: string,
|
||
pageTitle: string,
|
||
height: number,
|
||
width: number,
|
||
host: string,
|
||
pageUrl: string
|
||
}
|
||
|
||
export function FileSearchPanel({ fileId, ref }: { fileId: string | null, ref: any }) {
|
||
const [searchedUserFiles, setSearchedUserFiles] = useState<string[]>([]);
|
||
const [searchedUserFilesShowNull, setSearchedUserFilesShowNull] = useState<boolean>(false);
|
||
const [searchedGlobalFiles, setSearchedGlobalFiles] = useState<SearchItem[]>([]);
|
||
const [searchedGlobalFilesShowNull, setSearchedGlobalFilesShowNull] = useState<boolean>(false);
|
||
const [loading, setLoading] = useState<boolean>(false);
|
||
const [paginationLoading, setPaginationLoading] = useState<boolean>(false);
|
||
const [showGlobalSearch, setShowGlobalSearch] = useState<boolean>(false);
|
||
const queryClient = useQueryClient();
|
||
|
||
const [searchTotalPages, setSearchTotalPages] = useState<number>(0);
|
||
const [searchCurrentPages, setSearchCurrentPages] = useState<number>(1);
|
||
|
||
useImperativeHandle(ref, () => ({
|
||
clearList: () => {
|
||
setSearchedUserFiles([]);
|
||
setSearchedGlobalFiles([]);
|
||
setSearchedUserFilesShowNull(false);
|
||
setSearchedGlobalFilesShowNull(false);
|
||
setShowGlobalSearch(false);
|
||
setSearchCurrentPages(1);
|
||
setSearchTotalPages(0);
|
||
}
|
||
}));
|
||
|
||
|
||
const handlerSearchUserFile = useCallback(async (fileId: string, page: number): Promise<void> => {
|
||
|
||
try {
|
||
let result = await searchUserFiles(fileId);
|
||
|
||
if (result.content.length) {
|
||
setSearchedUserFiles(result.content);
|
||
} else {
|
||
setSearchedUserFilesShowNull(true);
|
||
}
|
||
} catch (error) {
|
||
|
||
}
|
||
setShowGlobalSearch(true);
|
||
handlerSearchGlobalFile(fileId, page)
|
||
|
||
}, [fileId])
|
||
|
||
const handlerSearchGlobalFile = useCallback(async (fileId: string, page: number, actionFromPagination?: boolean): Promise<void> => {
|
||
if (!actionFromPagination) {
|
||
setLoading(true);
|
||
setSearchedGlobalFilesShowNull(false);
|
||
setSearchedGlobalFiles([]);
|
||
} else {
|
||
setPaginationLoading(true);
|
||
}
|
||
|
||
try {
|
||
let result = await searchGlobalFiles(fileId, page);
|
||
console.log('searchGlobalFiles');
|
||
console.log(result);
|
||
if (result.images.length) {
|
||
setSearchedGlobalFiles(result.images);
|
||
setSearchTotalPages(result.totalPages);
|
||
setSearchCurrentPages(page);
|
||
|
||
} else {
|
||
setSearchedGlobalFilesShowNull(true);
|
||
}
|
||
} catch (error) {
|
||
|
||
} finally {
|
||
await queryClient.invalidateQueries({ queryKey: ['userData'] });
|
||
await queryClient.invalidateQueries({ queryKey: ['userSearchData'] });
|
||
setLoading(false);
|
||
setPaginationLoading(false);
|
||
}
|
||
|
||
}, [fileId])
|
||
|
||
return (
|
||
<>
|
||
<div
|
||
className="mb-4"
|
||
>
|
||
<button
|
||
className="btn btn-primary btn-search"
|
||
disabled={fileId ? false : true}
|
||
onClick={() => {
|
||
if (fileId) {
|
||
handlerSearchUserFile(fileId, 1)
|
||
}
|
||
}}
|
||
>
|
||
Начать поиск
|
||
</button>
|
||
</div>
|
||
|
||
{(searchedUserFiles.length !== 0) && (
|
||
<SearchedUserFilesList list={searchedUserFiles} />
|
||
)}
|
||
|
||
{searchedUserFilesShowNull && (
|
||
<div
|
||
className="user-file-search-results"
|
||
>
|
||
<div className="results-header">
|
||
<div className="results-title">Результаты поиска</div>
|
||
<div className="results-count">
|
||
Найдено файлов: {searchedUserFiles.length}
|
||
</div>
|
||
</div>
|
||
<div
|
||
className="empty-results"
|
||
>
|
||
<h3>Похожих файлов не найдено</h3>
|
||
<p>В вашей библиотеке нет файлов, похожих на загруженный</p>
|
||
<div className="empty-results-hint">
|
||
<strong>Совет:</strong> Убедитесь, что вы загружали этот файл ранее через страницу "Маркировка"
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
)}
|
||
|
||
{showGlobalSearch && (
|
||
<div
|
||
className="global-search-section"
|
||
>
|
||
<div className="global-search-header">
|
||
<div className="global-search-title">
|
||
Глобальный поиск изображений
|
||
</div>
|
||
<div className="">
|
||
Найти где ещё используется ваше изображение в интернете
|
||
</div>
|
||
<div className="global-search-badge">
|
||
Интернет поиск
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div className="global-search-content">
|
||
<div className="global-search-info">
|
||
<div className="global-search-info-title">
|
||
Поиск по всему интернету
|
||
</div>
|
||
<div className="global-search-info-text">
|
||
Используем продвинутые технологии обратного поиска по изображению для поиска копий вашего контента
|
||
на сайтах, в социальных сетях и других источниках. Поможет обнаружить несанкционированное использование.
|
||
</div>
|
||
</div>
|
||
|
||
<div className="search-counter" id="search-counter">
|
||
<div className="counter-info">
|
||
<div className="counter-icon" id="counter-icon"></div>
|
||
<div className="counter-text">
|
||
<div className="counter-label">Глобальных поисков сегодня</div>
|
||
<div className="counter-value" id="counter-value">0 из 10</div>
|
||
</div>
|
||
</div>
|
||
<div className="progress-bar">
|
||
<div
|
||
className="progress-fill"
|
||
id="progress-fill"
|
||
style={{ width: '0%' }}
|
||
>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className={`global-loading ${loading ? 'show' : ''}`} id="global-loading">
|
||
<div className="global-spinner"></div>
|
||
<div className="global-loading-text" id="global-loading-text">
|
||
Поиск изображений в интернете...
|
||
</div>
|
||
</div>
|
||
|
||
<div className={`global-result ${searchedGlobalFiles.length ? 'show' : ''}`} id="global-result">
|
||
<div className="global-result-card">
|
||
<div className="global-result-header">
|
||
<span>Найдено в интернете</span>
|
||
{paginationLoading && (
|
||
<div className="loading-animation">
|
||
<span className="global-spinner"></span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
<div className="global-result-content">
|
||
<SearchedGlobalFilesList list={searchedGlobalFiles} />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{searchedGlobalFilesShowNull && (
|
||
<div className="global-no-result" id="global-no-result">
|
||
<div className="global-no-result-icon">‍</div>
|
||
<h4>Похожие изображения в интернете не найдены</h4>
|
||
<p>Это может означать, что ваше изображение уникально и не используется на других сайтах.</p>
|
||
</div>
|
||
)}
|
||
|
||
<div className="global-error" id="global-error">
|
||
<strong>Ошибка глобального поиска:</strong>
|
||
<span id="global-error-text"></span>
|
||
</div>
|
||
|
||
<Pagination totalPages={searchTotalPages} currentPage={searchCurrentPages} fileId={fileId} callBack={handlerSearchGlobalFile} />
|
||
</div>
|
||
</div>
|
||
)}
|
||
</>
|
||
)
|
||
} |