add icons, change styles
This commit is contained in:
Generated
-16
@@ -10,7 +10,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/postcss": "^4.1.17",
|
"@tailwindcss/postcss": "^4.1.17",
|
||||||
"@tanstack/react-query": "^5.90.11",
|
"@tanstack/react-query": "^5.90.11",
|
||||||
"@vkid/sdk": "^2.6.2",
|
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"jose": "^6.1.2",
|
"jose": "^6.1.2",
|
||||||
"next": "^16.0.7",
|
"next": "^16.0.7",
|
||||||
@@ -2543,15 +2542,6 @@
|
|||||||
"win32"
|
"win32"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@vkid/sdk": {
|
|
||||||
"version": "2.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vkid/sdk/-/sdk-2.6.2.tgz",
|
|
||||||
"integrity": "sha512-TCaGh6BvQNY8Atru0KJXdGuwm70y9WS2xBOLNripHjYMEcft0BMIiLKUvJ7pAeJOtk/15MvPaUIEmBS2Vt0NBg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"crypto-js": "^4.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.15.0",
|
"version": "8.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||||
@@ -3090,12 +3080,6 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/crypto-js": {
|
|
||||||
"version": "4.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
|
|
||||||
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.2.3",
|
"version": "3.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/postcss": "^4.1.17",
|
"@tailwindcss/postcss": "^4.1.17",
|
||||||
"@tanstack/react-query": "^5.90.11",
|
"@tanstack/react-query": "^5.90.11",
|
||||||
"@vkid/sdk": "^2.6.2",
|
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"jose": "^6.1.2",
|
"jose": "^6.1.2",
|
||||||
"next": "^16.0.7",
|
"next": "^16.0.7",
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import ProtectedFilesTable from '@/app/ui/marking-page/protected-files-table';
|
import ProtectedFilesTable from '@/app/ui/marking-page/protected-files-table';
|
||||||
import ProtectionSummary from '@/app/ui/marking-page/protection-summary';
|
import ProtectionSummary from '@/app/ui/marking-page/protection-summary';
|
||||||
import TestSection from '@/app/ui/marking-page/test-section';
|
import TestSection from '@/app/ui/marking-page/test-section';
|
||||||
|
import { IconAudioFile } from '@/app/ui/icons/icons';
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1 className="page-title">Защита аудио</h1>
|
<div className="page-title">
|
||||||
|
<h1 >Защита аудио</h1>
|
||||||
|
</div>
|
||||||
<ProtectionSummary />
|
<ProtectionSummary />
|
||||||
<TestSection />
|
<TestSection />
|
||||||
<ProtectedFilesTable />
|
<ProtectedFilesTable />
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ import ProtectedFilesTable from '@/app/ui/marking-page/protected-files-table';
|
|||||||
import ProtectionSummary from '@/app/ui/marking-page/protection-summary';
|
import ProtectionSummary from '@/app/ui/marking-page/protection-summary';
|
||||||
import TestSection from '@/app/ui/marking-page/test-section';
|
import TestSection from '@/app/ui/marking-page/test-section';
|
||||||
import UploadSectionImage from '@/app/ui/marking-page/upload-section-image';
|
import UploadSectionImage from '@/app/ui/marking-page/upload-section-image';
|
||||||
|
import { IconImageFile } from '@/app/ui/icons/icons';
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1 className="page-title">Защита изображений</h1>
|
<div className="page-title">
|
||||||
|
<h1 >Защита изображений</h1>
|
||||||
|
</div>
|
||||||
<ProtectionSummary />
|
<ProtectionSummary />
|
||||||
<UploadSectionImage />
|
<UploadSectionImage />
|
||||||
<TestSection />
|
<TestSection />
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import ProtectedFilesTable from '@/app/ui/marking-page/protected-files-table';
|
import ProtectedFilesTable from '@/app/ui/marking-page/protected-files-table';
|
||||||
import ProtectionSummary from '@/app/ui/marking-page/protection-summary';
|
import ProtectionSummary from '@/app/ui/marking-page/protection-summary';
|
||||||
import TestSection from '@/app/ui/marking-page/test-section';
|
import TestSection from '@/app/ui/marking-page/test-section';
|
||||||
|
import { IconVideoFile } from '@/app/ui/icons/icons';
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1 className="page-title">Защита видео</h1>
|
<div className="page-title">
|
||||||
|
<h1 >Защита видео</h1>
|
||||||
|
</div>
|
||||||
<ProtectionSummary />
|
<ProtectionSummary />
|
||||||
<TestSection />
|
<TestSection />
|
||||||
<ProtectedFilesTable />
|
<ProtectedFilesTable />
|
||||||
|
|||||||
@@ -6,6 +6,12 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
color: #1f2937;
|
color: #1f2937;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
color: #6366f1;
|
||||||
|
}
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
width: 8px;
|
width: 8px;
|
||||||
|
|||||||
@@ -127,6 +127,7 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
margin: 20px 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.register-link {
|
.register-link {
|
||||||
|
|||||||
@@ -177,6 +177,7 @@
|
|||||||
padding: 20px 20px 0;
|
padding: 20px 20px 0;
|
||||||
color: #111827;
|
color: #111827;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
@@ -215,6 +216,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
border: 2px solid #6366f1;
|
border: 2px solid #6366f1;
|
||||||
|
color: #6366f1;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-title {
|
&-title {
|
||||||
@@ -261,8 +263,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.btn-secondary {
|
.btn-secondary {
|
||||||
background: #6b7280;
|
background: #6366f1;
|
||||||
color: white;
|
color: white;
|
||||||
|
padding: 5px 16px 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.real-protection-badge {
|
.real-protection-badge {
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/* https://icon-sets.iconify.design/ic/ */
|
||||||
|
|
||||||
|
export function IconImageFile() {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" className="icon">
|
||||||
|
<path fill="currentColor" d="M19 5v14H5V5zm0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2m-4.86 8.86l-3 3.87L9 13.14L6 17h12z" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IconVideoFile() {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" className="icon">
|
||||||
|
<path fill="currentColor" d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8zM6 20V4h7v5h5v11zm8-6l2-1.06v4.12L14 16v1c0 .55-.45 1-1 1H9c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h4c.55 0 1 .45 1 1z" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IconAudioFile() {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" className="icon">
|
||||||
|
<path fill="currentColor" d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8zM6 20V4h7v5h5v11zm10-9h-4v3.88a2.247 2.247 0 0 0-3.5 1.87c0 1.24 1.01 2.25 2.25 2.25S13 17.99 13 16.75V13h3z" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IconShield() {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M12 22q-3.475-.875-5.738-3.988T4 11.1V5l8-3l8 3v6.1q0 3.8-2.262 6.913T12 22m0-2.1q2.6-.825 4.3-3.3t1.7-5.5V6.375l-6-2.25l-6 2.25V11.1q0 3.025 1.7 5.5t4.3 3.3M10 16h4q.425 0 .713-.288T15 15v-3q0-.425-.288-.712T14 11v-1q0-.825-.587-1.412T12 8t-1.412.588T10 10v1q-.425 0-.712.288T9 12v3q0 .425.288.713T10 16m1-5v-1q0-.425.288-.712T12 9t.713.288T13 10v1z" /></svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IconDownload() {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" className="icon">
|
||||||
|
<path fill="currentColor" d="M5 20h14v-2H5zM19 9h-4V3H9v6H5l7 7z" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { Config, OneTap } from '@vkid/sdk';
|
|
||||||
|
|
||||||
import { useEffect, useRef } from 'react';
|
|
||||||
|
|
||||||
const VKAuthDynamic = () => {
|
|
||||||
const containerRef = useRef(null);
|
|
||||||
const isInitialized = useRef(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Динамическая загрузка SDK
|
|
||||||
const loadVKIDSDK = async () => {
|
|
||||||
try {
|
|
||||||
// Проверяем, не загружен ли уже SDK
|
|
||||||
if (window.VKIDSDK) return window.VKIDSDK;
|
|
||||||
|
|
||||||
const { default: VKID } = await import('@vkid/sdk');
|
|
||||||
window.VKIDSDK = VKID;
|
|
||||||
return VKID;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to load VKID SDK:', error);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const initialize = async () => {
|
|
||||||
if (isInitialized.current) return;
|
|
||||||
|
|
||||||
const VKID = await loadVKIDSDK();
|
|
||||||
if (!VKID || !containerRef.current) return;
|
|
||||||
|
|
||||||
isInitialized.current = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Конфигурация
|
|
||||||
VKID.Config.init({
|
|
||||||
app: Number(process.env.NEXT_PUBLIC_VK_APP_ID) || 1111111,
|
|
||||||
redirectUrl: process.env.NEXT_PUBLIC_REDIRECT_URL || window.location.origin,
|
|
||||||
responseMode: VKID.ConfigResponseMode.Callback,
|
|
||||||
source: VKID.ConfigSource.LOWCODE,
|
|
||||||
scope: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
// Создание и рендеринг виджета
|
|
||||||
const oneTap = new VKID.OneTap();
|
|
||||||
|
|
||||||
oneTap
|
|
||||||
.render({
|
|
||||||
container: containerRef.current,
|
|
||||||
showAlternativeLogin: true,
|
|
||||||
})
|
|
||||||
.on(VKID.WidgetEvents.ERROR, handleError)
|
|
||||||
.on(VKID.OneTapInternalEvents.LOGIN_SUCCESS, async (payload) => {
|
|
||||||
const { code, device_id } = payload;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const authData = await VKID.Auth.exchangeCode(code, device_id);
|
|
||||||
handleSuccess(authData);
|
|
||||||
} catch (error) {
|
|
||||||
handleError(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error('VKID initialization error:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
initialize();
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
// Очистка
|
|
||||||
isInitialized.current = false;
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleSuccess = async (data) => {
|
|
||||||
try {
|
|
||||||
// Отправка данных на ваш API endpoint
|
|
||||||
const response = await fetch('/api/auth/vk-callback', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
// Успешная авторизация
|
|
||||||
console.log('Authentication successful:', result);
|
|
||||||
// Перенаправление или обновление состояния
|
|
||||||
window.location.href = '/dashboard'; // Пример редиректа
|
|
||||||
} else {
|
|
||||||
handleError(result);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Server request failed:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleError = (error) => {
|
|
||||||
console.error('Authentication error:', error);
|
|
||||||
// Можно показать уведомление пользователю
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div ref={containerRef} />
|
|
||||||
vk
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default VKAuthDynamic;
|
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
|
import { IconShield, IconDownload } from '@/app/ui/icons/icons';
|
||||||
export default function ProtectedFilesTable() {
|
export default function ProtectedFilesTable() {
|
||||||
return (
|
return (
|
||||||
<div className="protected-files-table">
|
<div className="protected-files-table">
|
||||||
<h3>
|
<h3>
|
||||||
📋 Защищенные изображения (0)
|
Защищенные изображения (0)
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ export default function ProtectedFilesTable() {
|
|||||||
<td>
|
<td>
|
||||||
<div className="files-table-file">
|
<div className="files-table-file">
|
||||||
<div className="files-table-icon">
|
<div className="files-table-icon">
|
||||||
🛡️
|
<IconShield />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="files-table-title">
|
<div className="files-table-title">
|
||||||
@@ -54,7 +55,7 @@ export default function ProtectedFilesTable() {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button className="btn btn-secondary">
|
<button className="btn btn-secondary">
|
||||||
📥 Скачать
|
<IconDownload /> Скачать
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -62,7 +63,7 @@ export default function ProtectedFilesTable() {
|
|||||||
<td>
|
<td>
|
||||||
<div className="files-table-file">
|
<div className="files-table-file">
|
||||||
<div className="files-table-icon">
|
<div className="files-table-icon">
|
||||||
🛡️
|
<IconShield />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="files-table-title">
|
<div className="files-table-title">
|
||||||
@@ -95,7 +96,7 @@ export default function ProtectedFilesTable() {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button className="btn btn-secondary">
|
<button className="btn btn-secondary">
|
||||||
📥 Скачать
|
<IconDownload /> Скачать
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -103,7 +104,7 @@ export default function ProtectedFilesTable() {
|
|||||||
<td>
|
<td>
|
||||||
<div className="files-table-file">
|
<div className="files-table-file">
|
||||||
<div className="files-table-icon">
|
<div className="files-table-icon">
|
||||||
🛡️
|
<IconShield />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="files-table-title">
|
<div className="files-table-title">
|
||||||
@@ -136,7 +137,7 @@ export default function ProtectedFilesTable() {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button className="btn btn-secondary">
|
<button className="btn btn-secondary">
|
||||||
📥 Скачать
|
<IconDownload /> Скачать
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export default function ProtectionSummary() {
|
export default function ProtectionSummary() {
|
||||||
return (
|
return (
|
||||||
<div className="protection-summary">
|
<div className="protection-summary">
|
||||||
<h3>📊 Статистика защиты</h3>
|
<h3>Статистика защиты</h3>
|
||||||
<div className="protection-stats">
|
<div className="protection-stats">
|
||||||
<div className="stat-card">
|
<div className="stat-card">
|
||||||
<div className="stat-number">0</div>
|
<div className="stat-number">0</div>
|
||||||
|
|||||||
@@ -2,14 +2,11 @@ export default function TestSection() {
|
|||||||
return (
|
return (
|
||||||
<div className="test-section">
|
<div className="test-section">
|
||||||
<h3>
|
<h3>
|
||||||
🔍 Проверить защиту изображения
|
Проверить защиту файла
|
||||||
</h3>
|
</h3>
|
||||||
<div className="test-section-content">
|
<div className="test-section-content">
|
||||||
<h4>
|
|
||||||
🔍
|
|
||||||
</h4>
|
|
||||||
<button className="btn btn-primary">
|
<button className="btn btn-primary">
|
||||||
🔍 Выбрать изображение для анализа
|
Выбрать фаил для анализа
|
||||||
</button>
|
</button>
|
||||||
<p>
|
<p>
|
||||||
При обнаружении защиты будет показана полная информация о владельце (WEBP НЕ поддерживается)
|
При обнаружении защиты будет показана полная информация о владельце (WEBP НЕ поддерживается)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import React, { useRef, useState, useCallback, ChangeEvent, DragEvent } from 'react';
|
import React, { useRef, useState, useCallback, ChangeEvent, DragEvent } from 'react';
|
||||||
|
import { IconImageFile } from '@/app/ui/icons/icons';
|
||||||
|
|
||||||
// Типы для выбранного файла
|
|
||||||
interface SelectedFile {
|
interface SelectedFile {
|
||||||
file: File;
|
file: File;
|
||||||
preview: string;
|
preview: string;
|
||||||
@@ -101,7 +101,6 @@ export default function UploadSectionImage() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Создание превью
|
|
||||||
const objectUrl = URL.createObjectURL(file);
|
const objectUrl = URL.createObjectURL(file);
|
||||||
|
|
||||||
setSelectedFile({
|
setSelectedFile({
|
||||||
@@ -174,7 +173,7 @@ export default function UploadSectionImage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="upload-section">
|
<div className="upload-section">
|
||||||
<h3>📷 Загрузить изображение для защиты</h3>
|
<h3>Загрузить изображение для защиты</h3>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={`drag-drop-zone ${isDragging ? 'dragging' : ''}`}
|
className={`drag-drop-zone ${isDragging ? 'dragging' : ''}`}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ export default function RegisterForm() {
|
|||||||
{state?.error?.server && (
|
{state?.error?.server && (
|
||||||
<p className="text-sm text-red-500">{state?.error?.server}</p>
|
<p className="text-sm text-red-500">{state?.error?.server}</p>
|
||||||
)}
|
)}
|
||||||
<button type="submit" className={`${styles['btn']}`} style={{ marginTop: "20px" }}>Создать аккаунт</button>
|
<button type="submit" className={`${styles['btn']}`}>Создать аккаунт</button>
|
||||||
</form >
|
</form >
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -28,16 +28,6 @@ export default function NotificationsMonitoringSettings() {
|
|||||||
</label>
|
</label>
|
||||||
<small>Получать уведомления о нарушениях на email</small>
|
<small>Получать уведомления о нарушениях на email</small>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-group">
|
|
||||||
<label className="form-label">
|
|
||||||
<span>📱 SMS уведомления</span>
|
|
||||||
<span className="toggle-switch">
|
|
||||||
<input type="checkbox" name="notification_sms" />
|
|
||||||
<span className="toggle-slider"></span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
<small>Критически важные уведомления по SMS</small>
|
|
||||||
</div>
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label className="form-label">
|
<label className="form-label">
|
||||||
<span>🤖 Автоматический мониторинг</span>
|
<span>🤖 Автоматический мониторинг</span>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export default function PersonalDataSettings() {
|
|||||||
<label className="form-label">Возраст:</label>
|
<label className="form-label">Возраст:</label>
|
||||||
<input type="text" name="age" className="form-input" />
|
<input type="text" name="age" className="form-input" />
|
||||||
<small>
|
<small>
|
||||||
Заполняется автоматически из даты рождения
|
Заполняется автоматически исходя из даты рождения
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -40,9 +40,6 @@ export default function SubscriptionSettings() {
|
|||||||
<button className="btn btn-outline">
|
<button className="btn btn-outline">
|
||||||
💼 ПРОФИ
|
💼 ПРОФИ
|
||||||
</button>
|
</button>
|
||||||
<button className="btn btn-outline">
|
|
||||||
🏆 МАКСИМУМ
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user