add monitoring action button for tanstak-table
This commit is contained in:
@@ -2,18 +2,58 @@
|
|||||||
|
|
||||||
import { YooCheckout, ICreatePayment } from '@a2seven/yoo-checkout';
|
import { YooCheckout, ICreatePayment } from '@a2seven/yoo-checkout';
|
||||||
import { getSessionData } from '@/app/actions/session';
|
import { getSessionData } from '@/app/actions/session';
|
||||||
|
import { API_BASE_URL } from '@/app/actions/definitions';
|
||||||
|
|
||||||
const checkout = new YooCheckout({ shopId: '1276731', secretKey: 'test_0Yns_0NHV5GJf6ypJ5HC4NSfnLO8SJkw-1PwrVWsDl4' });
|
const checkout = new YooCheckout({ shopId: '1276731', secretKey: 'test_0Yns_0NHV5GJf6ypJ5HC4NSfnLO8SJkw-1PwrVWsDl4' });
|
||||||
|
|
||||||
const idempotenceKey = '02347fc4-a1f0-49db-807e-f0d67c2ed5a5';
|
const idempotenceKey = '02347fc4-a1f0-49db-807e-f0d67c2ed5a5';
|
||||||
|
|
||||||
export async function yooKasaCreatePayment(amount: number, tariff: string) {
|
export async function makePaymentOperation(email: string, tariffId: number, operationUuid: string) {
|
||||||
|
console.log('makePaymentOperation');
|
||||||
|
console.log({
|
||||||
|
email,
|
||||||
|
tariffId: tariffId,
|
||||||
|
operationType: 'TARIFF',
|
||||||
|
operationUuid,
|
||||||
|
});
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
formData.append('email', email);
|
||||||
|
formData.append('tariffId', tariffId.toString());
|
||||||
|
formData.append('operationType', 'TARIFF');
|
||||||
|
formData.append('operationUuid', operationUuid);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE_URL}/api/payments/create`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const parsed = await response.json()
|
||||||
|
console.log(parsed);
|
||||||
|
return true
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function yooKasaCreatePayment(amount: number, tariff: number) {
|
||||||
console.log(amount);
|
console.log(amount);
|
||||||
console.log(tariff);
|
console.log(tariff);
|
||||||
/* return true; */
|
/* return true; */
|
||||||
|
|
||||||
const userEmail = await getSessionData('email');
|
const userEmail = await getSessionData('email');
|
||||||
|
|
||||||
|
if (!userEmail) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const createPayload: ICreatePayment = {
|
const createPayload: ICreatePayment = {
|
||||||
amount: {
|
amount: {
|
||||||
value: amount.toLocaleString(),
|
value: amount.toLocaleString(),
|
||||||
@@ -34,10 +74,18 @@ export async function yooKasaCreatePayment(amount: number, tariff: string) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const payment = await checkout.createPayment(createPayload, Date.now().toLocaleString());
|
const payment = await checkout.createPayment(createPayload, Date.now().toLocaleString());
|
||||||
console.log(payment);
|
const response = await makePaymentOperation(userEmail, tariff, payment.id);
|
||||||
|
console.log('yooKasaCreatePayment')
|
||||||
|
console.log(response);
|
||||||
|
if (response) {
|
||||||
return payment?.confirmation.confirmation_url;
|
return payment?.confirmation.confirmation_url;
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
/* return payment; */
|
/* return payment; */
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
SortingState,
|
SortingState,
|
||||||
ColumnFiltersState,
|
ColumnFiltersState,
|
||||||
} from '@tanstack/react-table';
|
} from '@tanstack/react-table';
|
||||||
import { IconEye, IconDoubleArrowRight, IconArrowRight, IconDoubleArrowLeft, IconArrowLeft, IconArrowUp, IconArrowDown, IconFilter, IconFileDownload, IconShieldExclamation } from '@/app/ui/icons/icons';
|
import { IconEye, IconDoubleArrowRight, IconArrowRight, IconDoubleArrowLeft, IconArrowLeft, IconArrowUp, IconArrowDown, IconFilter, IconFileDownload, IconShieldExclamation, IconInfo } from '@/app/ui/icons/icons';
|
||||||
import { useTranslations, useLocale } from 'next-intl';
|
import { useTranslations, useLocale } from 'next-intl';
|
||||||
import DropDownList from '@/app/components/DropDownList';
|
import DropDownList from '@/app/components/DropDownList';
|
||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
@@ -21,6 +21,7 @@ import { toast } from 'sonner';
|
|||||||
import { pluralize } from '@/app/lib/pluralize';
|
import { pluralize } from '@/app/lib/pluralize';
|
||||||
import { convertBytes } from '@/app/lib/convertBytes';
|
import { convertBytes } from '@/app/lib/convertBytes';
|
||||||
import { FileInfoModalWindow } from '@/app/ui/modal-windows/file-info-modal-window';
|
import { FileInfoModalWindow } from '@/app/ui/modal-windows/file-info-modal-window';
|
||||||
|
import { FileMonitoringModalWindow } from '@/app/ui/modal-windows/file-monitoring-modal-window';
|
||||||
import { FileTypeIcon } from '@/app/components/FileTypeIcon';
|
import { FileTypeIcon } from '@/app/components/FileTypeIcon';
|
||||||
|
|
||||||
type FileType = 'image' | 'video' | 'audio';
|
type FileType = 'image' | 'video' | 'audio';
|
||||||
@@ -404,12 +405,13 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
|
|||||||
},
|
},
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<div className="actions">
|
<div className="actions">
|
||||||
<div className="actions-group" style={{ display: "none" }}>
|
<div className="actions-group">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleProtect(row.original)}
|
onClick={() => handleMonitoring(row.original)}
|
||||||
className="bg-violet-500 hover:bg-violet-600"
|
className="bg-violet-500 hover:bg-violet-600"
|
||||||
|
title={t('monitoring')}
|
||||||
>
|
>
|
||||||
<IconShieldExclamation />
|
<IconEye />
|
||||||
</button>
|
</button>
|
||||||
{/* <button
|
{/* <button
|
||||||
onClick={() => handleOpenWindowForRemove(row.original)}
|
onClick={() => handleOpenWindowForRemove(row.original)}
|
||||||
@@ -427,11 +429,9 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
|
|||||||
onClick={() => handleDownload(row.original)}
|
onClick={() => handleDownload(row.original)}
|
||||||
disabled={isFileLoading}
|
disabled={isFileLoading}
|
||||||
className="table-action-download"
|
className="table-action-download"
|
||||||
|
title={t('download')}
|
||||||
>
|
>
|
||||||
<IconFileDownload />
|
<IconFileDownload />
|
||||||
<span>
|
|
||||||
{t('download')}
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
@@ -439,11 +439,9 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
|
|||||||
handleView(row.original)
|
handleView(row.original)
|
||||||
}}
|
}}
|
||||||
className="table-action-view"
|
className="table-action-view"
|
||||||
|
title={t('make-check')}
|
||||||
>
|
>
|
||||||
<IconEye />
|
<IconInfo />
|
||||||
<span>
|
|
||||||
{t('make-check')}
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -461,7 +459,6 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
|
|||||||
console.log(file);
|
console.log(file);
|
||||||
|
|
||||||
const fileInfo = await viewFileInfo(file.id);
|
const fileInfo = await viewFileInfo(file.id);
|
||||||
console.log(fileInfo);
|
|
||||||
|
|
||||||
setOpenWindowChildren(() => {
|
setOpenWindowChildren(() => {
|
||||||
return (
|
return (
|
||||||
@@ -498,85 +495,19 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleProtect = (file: FileItem) => {
|
const handleMonitoring = async (file: FileItem) => {
|
||||||
console.log(`Щиток: ${file.fileName}`);
|
console.log(`Мониторинг:`, file);
|
||||||
};
|
|
||||||
|
|
||||||
const handleOpenWindowForRemove = async (file: FileItem) => {
|
const fileInfo = await viewFileInfo(file.id);
|
||||||
|
|
||||||
setOpenWindowChildren(() => {
|
setOpenWindowChildren(() => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<FileMonitoringModalWindow file={fileInfo} setWindowClose={setOpenWindow} setWindowChildren={setOpenWindowChildren} />
|
||||||
<h3 className="text-2xl">
|
|
||||||
{t('you-sure-you-want-to-delete')}
|
|
||||||
</h3>
|
|
||||||
<div className="mt-2 mb-8 text-center">{file.fileName}</div>
|
|
||||||
<div className="flex justify-center gap-4">
|
|
||||||
<button className="btn-primary btn-modal"
|
|
||||||
onClick={() => {
|
|
||||||
deleteMutation.mutate({
|
|
||||||
fileId: file.id,
|
|
||||||
removeParam: 1,
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
disabled={deleteMutation.isPending}
|
|
||||||
>
|
|
||||||
{deleteMutation.isPending ? '...' : t('yes')}
|
|
||||||
</button>
|
|
||||||
<button className="btn-primary btn-modal"
|
|
||||||
onClick={() => {
|
|
||||||
setOpenWindow(false);
|
|
||||||
setOpenWindowChildren(null);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('no')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
setOpenWindow(true);
|
setOpenWindow(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteMutation = useMutation({
|
|
||||||
mutationFn: ({ fileId, removeParam }: { fileId: string; removeParam: number }) =>
|
|
||||||
removeUserFile(fileId, removeParam),
|
|
||||||
|
|
||||||
onMutate: async ({ fileId, removeParam }: { fileId: string; removeParam: number }) => {
|
|
||||||
await queryClient.cancelQueries({ queryKey: ['userFilesData'] });
|
|
||||||
|
|
||||||
queryClient.setQueryData<ApiResponse>(['userFilesData'], (old) => {
|
|
||||||
if (!old?.files) return old;
|
|
||||||
return {
|
|
||||||
...old,
|
|
||||||
files: old.files.filter(file => file.id !== fileId)
|
|
||||||
};
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onError: () => {
|
|
||||||
queryClient.invalidateQueries({ queryKey: ['userFilesData'] });
|
|
||||||
toast.error(t('error'));
|
|
||||||
},
|
|
||||||
|
|
||||||
onSuccess: (response, { fileId }) => {
|
|
||||||
if (response === fileId) {
|
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: ['userFilesData'],
|
|
||||||
refetchType: 'active'
|
|
||||||
});
|
|
||||||
|
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: ['userFilesInfo']
|
|
||||||
});
|
|
||||||
|
|
||||||
setOpenWindow(false);
|
|
||||||
setOpenWindowChildren(null);
|
|
||||||
toast.success(t('file-has-been-deleted'));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Фильтрация по типу файла и дате
|
// Фильтрация по типу файла и дате
|
||||||
const filteredData = useMemo(() => {
|
const filteredData = useMemo(() => {
|
||||||
let result = tableData;
|
let result = tableData;
|
||||||
@@ -693,7 +624,9 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
|
|||||||
}
|
}
|
||||||
})()}
|
})()}
|
||||||
</h3>
|
</h3>
|
||||||
<ModalWindow children={openWindowChildren} state={openWindow} callBack={setOpenWindow} />
|
<ModalWindow state={openWindow} callBack={setOpenWindow}>
|
||||||
|
{openWindowChildren}
|
||||||
|
</ModalWindow>
|
||||||
{/* Фильтры */}
|
{/* Фильтры */}
|
||||||
<div className="tanstak-table-filtres">
|
<div className="tanstak-table-filtres">
|
||||||
<div className="table-filtres-wrapper">
|
<div className="table-filtres-wrapper">
|
||||||
|
|||||||
@@ -4095,3 +4095,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.monitoring {
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 800;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-status {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-actions {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
width: 100%;
|
||||||
|
color: v.$p-color;
|
||||||
|
border: 2px solid v.$p-color;
|
||||||
|
cursor: pointer;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -182,3 +182,9 @@ export function IconDiscet() {
|
|||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function IconInfo() {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" className="icon"><path fill="currentColor" d="M11 17h2v-6h-2zm1.713-8.287Q13 8.425 13 8t-.288-.712T12 7t-.712.288T11 8t.288.713T12 9t.713-.288M12 22q-2.075 0-3.9-.788t-3.175-2.137T2.788 15.9T2 12t.788-3.9t2.137-3.175T8.1 2.788T12 2t3.9.788t3.175 2.137T21.213 8.1T22 12t-.788 3.9t-2.137 3.175t-3.175 2.138T12 22m0-2q3.35 0 5.675-2.325T20 12t-2.325-5.675T12 4T6.325 6.325T4 12t2.325 5.675T12 20m0-8" /></svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
export function FileMonitoringModalWindow({ file, setWindowClose, setWindowChildren }: any) {
|
||||||
|
const [status, setStatus] = useState('null');
|
||||||
|
|
||||||
|
function closeHandler() {
|
||||||
|
setWindowChildren(null);
|
||||||
|
setWindowClose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(file);
|
||||||
|
}, [file])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="monitoring-wrapper"
|
||||||
|
>
|
||||||
|
<h3 className="monitoring-title">
|
||||||
|
Выберете интервал мониторинга<br />
|
||||||
|
для файла - {file.fileName}
|
||||||
|
</h3>
|
||||||
|
<p className="monitoring-status">
|
||||||
|
Текущий статус мониторинга - {status}
|
||||||
|
</p>
|
||||||
|
<ul
|
||||||
|
className="monitoring-actions"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={() => {
|
||||||
|
closeHandler()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Без мониторинга
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={() => {
|
||||||
|
closeHandler()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Каждый день
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={() => {
|
||||||
|
closeHandler()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Каждую неделю
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={() => {
|
||||||
|
closeHandler()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Каждый месяц
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -27,10 +27,11 @@ export default function PaymentTabTariffs() {
|
|||||||
value: number;
|
value: number;
|
||||||
tariff: string;
|
tariff: string;
|
||||||
tokens: number;
|
tokens: number;
|
||||||
|
tariffId: number
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
||||||
|
|
||||||
async function createPayment(value: number, tariff: string) {
|
async function createPayment(value: number, tariff: number) {
|
||||||
if (isProcessing) return;
|
if (isProcessing) return;
|
||||||
|
|
||||||
setIsProcessing(true);
|
setIsProcessing(true);
|
||||||
@@ -48,8 +49,8 @@ export default function PaymentTabTariffs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function openPaymentWindow(value: number, tariff: string, tokens: number) {
|
function openPaymentWindow(value: number, tariff: string, tokens: number, tariffId: number) {
|
||||||
setSelectedTariff({ value, tariff, tokens });
|
setSelectedTariff({ value, tariff, tokens, tariffId });
|
||||||
setIsProcessing(false);
|
setIsProcessing(false);
|
||||||
setOpenWindow(true);
|
setOpenWindow(true);
|
||||||
}
|
}
|
||||||
@@ -64,7 +65,7 @@ export default function PaymentTabTariffs() {
|
|||||||
if (!selectedTariff) return null;
|
if (!selectedTariff) return null;
|
||||||
|
|
||||||
const handleConfirm = () => {
|
const handleConfirm = () => {
|
||||||
createPayment(selectedTariff.value, selectedTariff.tariff);
|
createPayment(selectedTariff.value, selectedTariff.tariffId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
@@ -170,7 +171,7 @@ export default function PaymentTabTariffs() {
|
|||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<button
|
<button
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
onClick={() => openPaymentWindow(item.price, item.name, item.tokens)}
|
onClick={() => openPaymentWindow(item.price, item.name, item.tokens, item.id)}
|
||||||
>
|
>
|
||||||
Выбрать план
|
Выбрать план
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user