add monitoring action button for tanstak-table

This commit is contained in:
smanylov
2026-02-18 18:22:11 +07:00
parent 906b3a554c
commit c658721333
6 changed files with 180 additions and 91 deletions
+51 -3
View File
@@ -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);
return payment?.confirmation.confirmation_url; console.log('yooKasaCreatePayment')
console.log(response);
if (response) {
return payment?.confirmation.confirmation_url;
} else {
return null
}
/* return payment; */ /* return payment; */
} catch (error) { } catch (error) {
console.error(error); console.error(error);
return null
} }
} }
+16 -83
View File
@@ -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">
+27
View File
@@ -4094,4 +4094,31 @@
} }
} }
} }
}
.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;
}
}
} }
+6
View File
@@ -181,4 +181,10 @@ export function IconDiscet() {
<g fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M3 19V5a2 2 0 0 1 2-2h11.172a2 2 0 0 1 1.414.586l2.828 2.828A2 2 0 0 1 21 7.828V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z" /><path d="M8.6 9h6.8a.6.6 0 0 0 .6-.6V3.6a.6.6 0 0 0-.6-.6H8.6a.6.6 0 0 0-.6.6v4.8a.6.6 0 0 0 .6.6ZM6 13.6V21h12v-7.4a.6.6 0 0 0-.6-.6H6.6a.6.6 0 0 0-.6.6Z" /></g> <g fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M3 19V5a2 2 0 0 1 2-2h11.172a2 2 0 0 1 1.414.586l2.828 2.828A2 2 0 0 1 21 7.828V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z" /><path d="M8.6 9h6.8a.6.6 0 0 0 .6-.6V3.6a.6.6 0 0 0-.6-.6H8.6a.6.6 0 0 0-.6.6v4.8a.6.6 0 0 0 .6.6ZM6 13.6V21h12v-7.4a.6.6 0 0 0-.6-.6H6.6a.6.6 0 0 0-.6.6Z" /></g>
</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>
)
}
+6 -5
View File
@@ -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>