edit referrals page, add referrals fetch functions
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "no-copy-frontend",
|
"name": "no-copy-frontend",
|
||||||
"version": "0.33.0",
|
"version": "0.34.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 2999",
|
"dev": "next dev -p 2999",
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
'use server'
|
||||||
|
|
||||||
|
import { getSessionData } from '@/app/actions/session';
|
||||||
|
import { API_BASE_URL } from '@/app/actions/definitions';
|
||||||
|
|
||||||
|
export async function fetchReferralsLevels() {
|
||||||
|
const token = await getSessionData('token');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE_URL}/api/v1/data`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
version: 1,
|
||||||
|
msg_id: 30003,
|
||||||
|
message_body: {
|
||||||
|
action: 'levels',
|
||||||
|
token: token,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
let parsed = await response.json();
|
||||||
|
|
||||||
|
if (parsed.message_code === 0) {
|
||||||
|
return parsed.message_body.length ? parsed.message_body : parsed;
|
||||||
|
} else {
|
||||||
|
throw parsed;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw (`${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
error: error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchReferralUserStats() {
|
||||||
|
const token = await getSessionData('token');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE_URL}/api/v1/data`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
version: 1,
|
||||||
|
msg_id: 30003,
|
||||||
|
message_body: {
|
||||||
|
action: 'userStats',
|
||||||
|
token: token,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
let parsed = await response.json();
|
||||||
|
|
||||||
|
if (parsed.message_code === 0) {
|
||||||
|
return parsed.message_body;
|
||||||
|
} else {
|
||||||
|
throw parsed;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw (`${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
error: error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchReferralInvitees() {
|
||||||
|
const token = await getSessionData('token');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE_URL}/api/v1/data`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
version: 1,
|
||||||
|
msg_id: 30003,
|
||||||
|
message_body: {
|
||||||
|
action: 'invitees',
|
||||||
|
token: token,
|
||||||
|
pageSize: 10,
|
||||||
|
pageNumber: 0
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
let parsed = await response.json();
|
||||||
|
|
||||||
|
if (parsed.message_code === 0) {
|
||||||
|
return parsed.message_body;
|
||||||
|
} else {
|
||||||
|
throw parsed;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw (`${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
error: error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { QueryClient } from '@tanstack/react-query';
|
import { QueryClient } from '@tanstack/react-query';
|
||||||
import { getUserData, getUserFilesInfo } from '@/app/actions/action';
|
import { getUserData, getUserFilesInfo } from '@/app/actions/action';
|
||||||
import { getUserFilesData } from '@/app/actions/fileEntity';
|
import { getUserFilesData } from '@/app/actions/fileEntity';
|
||||||
|
import {fetchReferralUserStats} from '@/app/actions/referralsActions';
|
||||||
|
|
||||||
export async function prefetchLayoutQueries(queryClient: QueryClient) {
|
export async function prefetchLayoutQueries(queryClient: QueryClient) {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@@ -19,5 +20,9 @@ export async function prefetchLayoutQueries(queryClient: QueryClient) {
|
|||||||
queryKey: ['userFilesInfo'],
|
queryKey: ['userFilesInfo'],
|
||||||
queryFn: () => getUserFilesInfo()
|
queryFn: () => getUserFilesInfo()
|
||||||
}),
|
}),
|
||||||
|
queryClient.prefetchQuery({
|
||||||
|
queryKey: ['referralUserStats'],
|
||||||
|
queryFn: () => fetchReferralUserStats()
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -236,6 +236,7 @@
|
|||||||
border-bottom: 1px solid v.$b-color-1;
|
border-bottom: 1px solid v.$b-color-1;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
.stats-item {
|
.stats-item {
|
||||||
border: 1px solid v.$b-color-1;
|
border: 1px solid v.$b-color-1;
|
||||||
|
|||||||
@@ -11,8 +11,25 @@ import navigation from './navigation.json';
|
|||||||
import { useSideMenuStore } from '@/app/stores/sideMenuStore';
|
import { useSideMenuStore } from '@/app/stores/sideMenuStore';
|
||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import { useClickOutside } from '@/app/hooks/useClickOutside';
|
import { useClickOutside } from '@/app/hooks/useClickOutside';
|
||||||
|
import { fetchReferralUserStats } from '@/app/actions/referralsActions';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
export default function NavLinks() {
|
export default function NavLinks() {
|
||||||
|
const {
|
||||||
|
data: referralLink,
|
||||||
|
isLoading,
|
||||||
|
isError,
|
||||||
|
error
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ['referralUserStats'],
|
||||||
|
queryFn: () => {
|
||||||
|
return fetchReferralUserStats();
|
||||||
|
},
|
||||||
|
select: (data) => {
|
||||||
|
return data?.referralLink;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const pathname = usePathname().replace('/en/', '/').replace('/ru/', '/');
|
const pathname = usePathname().replace('/en/', '/').replace('/ru/', '/');
|
||||||
const t = useTranslations('Global');
|
const t = useTranslations('Global');
|
||||||
|
|
||||||
@@ -69,6 +86,10 @@ export default function NavLinks() {
|
|||||||
<DropDownList />
|
<DropDownList />
|
||||||
|
|
||||||
{links.map((link) => {
|
{links.map((link) => {
|
||||||
|
if (!referralLink && link.name === 'referral-program') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
key={link.name}
|
key={link.name}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default function IncomeAndPayments() {
|
|||||||
<div className="earning-card success">
|
<div className="earning-card success">
|
||||||
<h4>💰 Доступно к выводу</h4>
|
<h4>💰 Доступно к выводу</h4>
|
||||||
<p>
|
<p>
|
||||||
135.00 Б
|
0
|
||||||
</p>
|
</p>
|
||||||
<small>Минимальная сумма вывода: 100 Б</small>
|
<small>Минимальная сумма вывода: 100 Б</small>
|
||||||
</div>
|
</div>
|
||||||
@@ -18,7 +18,7 @@ export default function IncomeAndPayments() {
|
|||||||
<div className="earning-card">
|
<div className="earning-card">
|
||||||
<h4>📈 Всего заработано</h4>
|
<h4>📈 Всего заработано</h4>
|
||||||
<p>
|
<p>
|
||||||
135.00 Б
|
0
|
||||||
</p>
|
</p>
|
||||||
<small>За все время участия в программе</small>
|
<small>За все время участия в программе</small>
|
||||||
</div>
|
</div>
|
||||||
@@ -26,7 +26,7 @@ export default function IncomeAndPayments() {
|
|||||||
<div className="earning-card warning">
|
<div className="earning-card warning">
|
||||||
<h4>✅ Выплачено</h4>
|
<h4>✅ Выплачено</h4>
|
||||||
<p>
|
<p>
|
||||||
0.00 Б
|
0
|
||||||
</p>
|
</p>
|
||||||
<small>Успешно выплачено на ваши счета</small>
|
<small>Успешно выплачено на ваши счета</small>
|
||||||
</div>
|
</div>
|
||||||
@@ -70,8 +70,8 @@ export default function IncomeAndPayments() {
|
|||||||
Обработано
|
Обработано
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="stats-item first-column second-row">
|
<div className="stats-item first-column left-bottom-corner">
|
||||||
100.00
|
0
|
||||||
</div>
|
</div>
|
||||||
<div className="stats-item second-row">
|
<div className="stats-item second-row">
|
||||||
0
|
0
|
||||||
@@ -82,39 +82,7 @@ export default function IncomeAndPayments() {
|
|||||||
<div className="stats-item second-row">
|
<div className="stats-item second-row">
|
||||||
0
|
0
|
||||||
</div>
|
</div>
|
||||||
<div className="stats-item second-row last-column">
|
<div className="stats-item last-column right-bottom-corner">
|
||||||
0
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="stats-item first-column">
|
|
||||||
100.00
|
|
||||||
</div>
|
|
||||||
<div className="stats-item">
|
|
||||||
0
|
|
||||||
</div>
|
|
||||||
<div className="stats-item">
|
|
||||||
0
|
|
||||||
</div>
|
|
||||||
<div className="stats-item">
|
|
||||||
0
|
|
||||||
</div>
|
|
||||||
<div className="stats-item last-column">
|
|
||||||
0
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="stats-item last-row left-bottom-corner first-column">
|
|
||||||
100.00
|
|
||||||
</div>
|
|
||||||
<div className="stats-item last-row">
|
|
||||||
0
|
|
||||||
</div>
|
|
||||||
<div className="stats-item last-row">
|
|
||||||
0
|
|
||||||
</div>
|
|
||||||
<div className="stats-item last-row">
|
|
||||||
0
|
|
||||||
</div>
|
|
||||||
<div className="stats-item last-row last-column right-bottom-corner">
|
|
||||||
0
|
0
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,38 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { fetchReferralsLevels } from '@/app/actions/referralsActions';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
export default function CommissionLevels() {
|
export default function CommissionLevels() {
|
||||||
|
const {
|
||||||
|
data: referralsLevels,
|
||||||
|
isLoading,
|
||||||
|
isError,
|
||||||
|
error
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ['referralsLevels'],
|
||||||
|
queryFn: () => {
|
||||||
|
return fetchReferralsLevels();
|
||||||
|
},
|
||||||
|
select: (data) => {
|
||||||
|
if (data?.message_body) {
|
||||||
|
return data?.message_body
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('referralsLevels');
|
||||||
|
console.log(referralsLevels);
|
||||||
|
}, [referralsLevels])
|
||||||
|
|
||||||
|
if (!referralsLevels?.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="block-wrapper">
|
<div className="block-wrapper">
|
||||||
<h3 className="section-title">
|
<h3 className="section-title">
|
||||||
|
|||||||
@@ -17,38 +17,34 @@ import DropDownList from '@/app/components/DropDownList';
|
|||||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { pluralize } from '@/app/lib/pluralize';
|
import { pluralize } from '@/app/lib/pluralize';
|
||||||
|
import { fetchReferralInvitees } from '@/app/actions/referralsActions';
|
||||||
|
|
||||||
type FileItem = {
|
type InviteesType = {
|
||||||
status?: string;
|
status?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
registrationData: number;
|
registrationData: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ApiFile = {
|
type InviteType = {
|
||||||
status?: string;
|
active?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
registrationData: string;
|
regDate: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ApiResponse = {
|
|
||||||
files?: ApiFile[];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default function InvitationsTable() {
|
export default function InvitationsTable() {
|
||||||
const {
|
const {
|
||||||
data: testData,
|
data: referralInvitees,
|
||||||
isLoading,
|
isLoading,
|
||||||
isError,
|
isError,
|
||||||
error,
|
error,
|
||||||
} = useQuery<ApiResponse, Error, FileItem[], ['testData']>({
|
} = useQuery<InviteType[], Error, InviteesType[], ['referralInvitees']>({
|
||||||
queryKey: ['testData'],
|
queryKey: ['referralInvitees'],
|
||||||
queryFn: () => {
|
queryFn: () => {
|
||||||
return {}
|
return fetchReferralInvitees();
|
||||||
},
|
},
|
||||||
|
|
||||||
select: (data: ApiResponse): FileItem[] => {
|
select: (data: InviteType[]): InviteesType[] => {
|
||||||
if (!data?.files) return [
|
if (!data) return [
|
||||||
{
|
{
|
||||||
status: 'string1',
|
status: 'string1',
|
||||||
email: 'string1',
|
email: 'string1',
|
||||||
@@ -66,11 +62,11 @@ export default function InvitationsTable() {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return data.files.map((item: ApiFile) => {
|
return data.map((item: InviteType) => {
|
||||||
return {
|
return {
|
||||||
status: 'string',
|
status: item.active,
|
||||||
email: 'string',
|
email: item.email,
|
||||||
registrationData: 40
|
registrationData: item.regDate
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -92,7 +88,7 @@ export default function InvitationsTable() {
|
|||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
|
|
||||||
// Определение колонок
|
// Определение колонок
|
||||||
const columns = useMemo<ColumnDef<FileItem>[]>(
|
const columns = useMemo<ColumnDef<InviteesType>[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
accessorKey: 'email',
|
accessorKey: 'email',
|
||||||
@@ -207,7 +203,7 @@ export default function InvitationsTable() {
|
|||||||
|
|
||||||
// Фильтрация по типу файла и дате
|
// Фильтрация по типу файла и дате
|
||||||
const filteredData = useMemo(() => {
|
const filteredData = useMemo(() => {
|
||||||
let result = testData;
|
let result = referralInvitees;
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -263,7 +259,7 @@ export default function InvitationsTable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}, [testData, statusFilter, dateFilter]);
|
}, [referralInvitees, statusFilter, dateFilter]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const currentPageRows = table.getRowModel().rows;
|
const currentPageRows = table.getRowModel().rows;
|
||||||
|
|||||||
@@ -1,18 +1,71 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { fetchReferralUserStats } from '@/app/actions/referralsActions';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { useTranslations } from 'next-intl';
|
||||||
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
export default function ReferralLinkSection() {
|
export default function ReferralLinkSection() {
|
||||||
|
const {
|
||||||
|
data: referralUserStats,
|
||||||
|
isLoading,
|
||||||
|
isError,
|
||||||
|
error
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ['referralUserStats'],
|
||||||
|
queryFn: () => {
|
||||||
|
return fetchReferralUserStats();
|
||||||
|
},
|
||||||
|
select: (data) => {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const t = useTranslations('Global')
|
||||||
|
const [referralUrl, setReferralUrl] = useState<string>('');
|
||||||
|
const refLink = useRef<HTMLElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
setReferralUrl(`${window.location.origin}/register?ref=${referralUserStats?.referralLink}`);
|
||||||
|
}
|
||||||
|
}, [referralUserStats]);
|
||||||
|
|
||||||
|
const copyHandler = () => {
|
||||||
|
if (refLink.current?.textContent) {
|
||||||
|
navigator.clipboard.writeText(refLink.current?.textContent);
|
||||||
|
toast.success(`${t('copied')}: ${refLink.current?.textContent}`)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!referralUserStats?.referralLink) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="referral-link-section">
|
<div className="referral-link-section">
|
||||||
<h3>🔗 Ваша реферальная ссылка</h3>
|
<h3>Ваша реферальная ссылка</h3>
|
||||||
<p>Поделитесь этой ссылкой с друзьями и получайте комиссию с каждой их покупки</p>
|
<p>Поделитесь этой ссылкой с друзьями и получайте комиссию с каждой их покупки</p>
|
||||||
<div className="referral-link-input">
|
<div className="referral-link-input">
|
||||||
<span id="referral-link" >
|
<span
|
||||||
https://dashboard.no-copy.ru/register.php?ref=REFA0406AC8
|
id="referral-link"
|
||||||
|
ref={refLink}
|
||||||
|
>
|
||||||
|
{referralUrl}
|
||||||
</span >
|
</span >
|
||||||
<button className="copy-btn">📋 Копировать</button>
|
<button
|
||||||
|
className="copy-btn"
|
||||||
|
onClick={copyHandler}
|
||||||
|
>
|
||||||
|
Копировать
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p className="referral-link-footer">
|
<p className="referral-link-footer">
|
||||||
Код: <strong>REFA0406AC8</strong> •
|
Код: <strong>{referralUserStats?.referralLink}</strong> •
|
||||||
Кликов: <strong>21</strong> •
|
Приглашений: <strong>
|
||||||
Комиссия: <strong>15%</strong>
|
{referralUserStats?.totalInvitee}
|
||||||
|
</strong>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -212,7 +212,8 @@
|
|||||||
"are-no-violations": "There are no violations",
|
"are-no-violations": "There are no violations",
|
||||||
"error-reading-image": "Error reading image",
|
"error-reading-image": "Error reading image",
|
||||||
"error-user-not-have-tokens-for-protect": "User not have tokens for protect",
|
"error-user-not-have-tokens-for-protect": "User not have tokens for protect",
|
||||||
"registration-date": "Registration date"
|
"registration-date": "Registration date",
|
||||||
|
"copied": "Copied"
|
||||||
},
|
},
|
||||||
"Login-register-form": {
|
"Login-register-form": {
|
||||||
"and": "and",
|
"and": "and",
|
||||||
|
|||||||
@@ -212,7 +212,8 @@
|
|||||||
"are-no-violations": "Нарушений нет",
|
"are-no-violations": "Нарушений нет",
|
||||||
"error-reading-image": "Ошибка чтения изображения",
|
"error-reading-image": "Ошибка чтения изображения",
|
||||||
"error-user-not-have-tokens-for-protect": "У пользователя нет токенов для защиты.",
|
"error-user-not-have-tokens-for-protect": "У пользователя нет токенов для защиты.",
|
||||||
"registration-date": "Дата регистрации"
|
"registration-date": "Дата регистрации",
|
||||||
|
"copied": "Скопировано"
|
||||||
},
|
},
|
||||||
"Login-register-form": {
|
"Login-register-form": {
|
||||||
"and": "и",
|
"and": "и",
|
||||||
|
|||||||
Reference in New Issue
Block a user