add search setting interface
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
'use client'
|
||||
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { getSearchSettings, putSearchSettings } from '@/app/actions/SearchSetting';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
interface SearchSettings {
|
||||
engines: {
|
||||
yandex: boolean;
|
||||
google: boolean;
|
||||
};
|
||||
proxyEnabled: boolean;
|
||||
}
|
||||
|
||||
export default function SearchSettingsBlock() {
|
||||
|
||||
const { data: searchStats } = useQuery<SearchSettings>({
|
||||
queryKey: ['searchStats'],
|
||||
queryFn: getSearchSettings,
|
||||
retry: false
|
||||
});
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const t = useTranslations('Global');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
async function changeHandler(changetItem: 'proxy' | 'yandex' | 'google') {
|
||||
if (!searchStats) {
|
||||
toast.error(t('error'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
let proxy = searchStats.proxyEnabled;
|
||||
let yandex = searchStats.engines.yandex;
|
||||
let google = searchStats.engines.google;
|
||||
|
||||
switch (changetItem) {
|
||||
case 'yandex':
|
||||
yandex = !yandex;
|
||||
break
|
||||
|
||||
case 'google':
|
||||
google = !google;
|
||||
break
|
||||
|
||||
case 'proxy':
|
||||
proxy = !proxy;
|
||||
break
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await putSearchSettings(proxy, yandex, google);
|
||||
|
||||
if (response) {
|
||||
toast.success('Succes');
|
||||
await queryClient.invalidateQueries({ queryKey: ['searchStats'] });
|
||||
} else {
|
||||
toast.warning('Not succes');
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(t('error'));
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="search-settings-wrapper"
|
||||
>
|
||||
<div
|
||||
className={`search-settings-header ${isLoading ? 'loading' : ''}`}
|
||||
>
|
||||
<div
|
||||
className={`search-settings-item`}
|
||||
onClick={() => {
|
||||
changeHandler('proxy');
|
||||
}}
|
||||
>
|
||||
{t('proxy-enabled')}:
|
||||
<span className={`${searchStats?.proxyEnabled ? 'active' : ''}`} >
|
||||
{searchStats?.proxyEnabled ? t('yes') : t('no')}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className={`search-settings-item`}
|
||||
onClick={() => {
|
||||
changeHandler('yandex');
|
||||
}}
|
||||
>
|
||||
yandex:
|
||||
<span
|
||||
className={`${searchStats?.engines?.yandex ? 'active' : ''}`}
|
||||
>
|
||||
{searchStats?.engines?.yandex ? t('yes') : t('no')}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className={`search-settings-item`}
|
||||
onClick={() => {
|
||||
changeHandler('google');
|
||||
}}
|
||||
>
|
||||
google:
|
||||
<span
|
||||
className={`${searchStats?.engines?.google ? 'active' : ''}`}
|
||||
>
|
||||
{searchStats?.engines?.google ? t('yes') : t('no')}
|
||||
</span>
|
||||
</div>
|
||||
{isLoading && (
|
||||
<div
|
||||
className="relative ml-2.5"
|
||||
>
|
||||
<div className="loading-animation">
|
||||
<div className="global-spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -9,14 +9,10 @@ export function SearchStats() {
|
||||
const { data: userSearchData, isLoading, isError, error } = useUserSearchData();
|
||||
const t = useTranslations('Global');
|
||||
|
||||
useEffect(() => {
|
||||
console.log(userSearchData);
|
||||
}, [userSearchData])
|
||||
|
||||
return (
|
||||
<div className="stats-search">
|
||||
<div className="stats-title">
|
||||
Статистика поиска
|
||||
{t('search-stats')}
|
||||
</div>
|
||||
|
||||
<div className="stat-item">
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
'use client'
|
||||
|
||||
import { useTranslations } from 'next-intl'
|
||||
|
||||
export default function SearchTitle() {
|
||||
const t = useTranslations('Global');
|
||||
|
||||
return (
|
||||
<div className="block-wrapper">
|
||||
<h1 className="page-title">
|
||||
{t('search-protected-content')}
|
||||
</h1>
|
||||
<p className="page-description">
|
||||
{t('search-title-description')}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import { removeUserFile } from '@/app/actions/fileEntity';
|
||||
import { FileSearchPanel } from '@/app/ui/search/file-search-panel';
|
||||
import { getFileType } from '@/app/lib/getFileType';
|
||||
import { useAllFilesExtensions } from '@/app/hooks/react-query/useAllFilesExtensions';
|
||||
import SearchSettingsBlock from '@/app/ui/search/search-settings-block';
|
||||
interface SelectedFile {
|
||||
file: File;
|
||||
preview: string | undefined;
|
||||
@@ -287,13 +288,16 @@ export default function SectionSearchFile() {
|
||||
return (
|
||||
<div className="upload-section">
|
||||
<div className="search-info">
|
||||
<div className="search-info-title">Как работает поиск?</div>
|
||||
<div className="search-info-title">
|
||||
{t('how-does-search-work')}
|
||||
</div>
|
||||
<div className="search-info-text">
|
||||
Наша система анализирует загруженный файл и сравнивает его с вашими защищенными файлами,
|
||||
используя алгоритмы компьютерного зрения и цифровых отпечатков.
|
||||
{t('search-info-description-text')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SearchSettingsBlock />
|
||||
|
||||
<div
|
||||
className={`drag-drop-zone ${isDragging ? 'dragging' : ''}`}
|
||||
onDragOver={handleDragOver}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
'use client'
|
||||
|
||||
import { IconImageFile, IconVideoFile, IconAudioFile, IconDocument } from '@/app/ui/icons/icons';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useAllFilesExtensions } from '@/app/hooks/react-query/useAllFilesExtensions';
|
||||
|
||||
interface supportedFormats {
|
||||
extensionVideo: string[]
|
||||
extensionAudio: string[]
|
||||
extensionImage: string[]
|
||||
extensionDocument: string[]
|
||||
}
|
||||
|
||||
export function SupportedFormats({ extensionVideo, extensionAudio, extensionImage, extensionDocument }: supportedFormats) {
|
||||
export function SupportedFormats() {
|
||||
const t = useTranslations('Global');
|
||||
|
||||
const { data: allFilesExtensions, isLoading, isError } = useAllFilesExtensions();
|
||||
|
||||
return (
|
||||
<div className="supported-formats">
|
||||
<div className="formats-title">
|
||||
Поддерживаемые форматы
|
||||
{t('supported-formats')}
|
||||
</div>
|
||||
|
||||
<div className="format-group">
|
||||
@@ -22,7 +20,7 @@ export function SupportedFormats({ extensionVideo, extensionAudio, extensionImag
|
||||
<IconImageFile /> {t('images')}
|
||||
</div>
|
||||
<div className="format-list">
|
||||
{extensionImage.join(', ')}
|
||||
{allFilesExtensions?.images?.join(', ')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -31,7 +29,7 @@ export function SupportedFormats({ extensionVideo, extensionAudio, extensionImag
|
||||
<IconVideoFile /> {t('videos')}
|
||||
</div>
|
||||
<div className="format-list">
|
||||
{extensionVideo.join(', ')}
|
||||
{allFilesExtensions?.videos?.join(', ')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -40,7 +38,7 @@ export function SupportedFormats({ extensionVideo, extensionAudio, extensionImag
|
||||
<IconAudioFile /> {t('audios')}
|
||||
</div>
|
||||
<div className="format-list">
|
||||
{extensionAudio.join(', ')}
|
||||
{allFilesExtensions?.audios?.join(', ')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -49,7 +47,7 @@ export function SupportedFormats({ extensionVideo, extensionAudio, extensionImag
|
||||
<IconDocument /> {t('documents')}
|
||||
</div>
|
||||
<div className="format-list">
|
||||
{extensionDocument.join(', ')}
|
||||
{allFilesExtensions?.documents?.join(', ')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user