add PayoutMethod, getReferralPayments,
add translates
This commit is contained in:
@@ -84,7 +84,7 @@ export default function RegisterForm() {
|
||||
}
|
||||
|
||||
type SignupFormSchema = Awaited<ReturnType<typeof getSignupFormSchema>>;
|
||||
const [signupFormSchema, setSignupFormSchema] = useState<SignupFormSchema | null>(null);;
|
||||
const [signupFormSchema, setSignupFormSchema] = useState<SignupFormSchema | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
'use client'
|
||||
|
||||
import { useState, ChangeEvent, useEffect } from 'react';
|
||||
import { InputMask } from '@react-input/mask';
|
||||
import styles from '@/app/styles/module/login.module.scss';
|
||||
|
||||
interface BankCardProps {
|
||||
bankCardState: string | undefined;
|
||||
validateHandler: (e: ChangeEvent<HTMLInputElement>) => void;
|
||||
clearCondition?: string | undefined | null
|
||||
}
|
||||
|
||||
export default function BankCardInput({ bankCardState, validateHandler }: BankCardProps) {
|
||||
const [bankCard, setBankCard] = useState<string | undefined>(bankCardState ? bankCardState : '');
|
||||
|
||||
return (
|
||||
<InputMask
|
||||
type="phone"
|
||||
id="bankCard"
|
||||
name="bankCard"
|
||||
className={`${styles['form-input']}`}
|
||||
mask="____ ____ ____ ____"
|
||||
replacement={{ _: /\d/ }}
|
||||
value={bankCard}
|
||||
onChange={(e) => {
|
||||
setBankCard(e.target.value);
|
||||
validateHandler(e);
|
||||
}}
|
||||
placeholder="1234 1234 1234 1234"
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import PaymentsHistory from '@/app/ui/referral-page/table/payments-history';
|
||||
|
||||
export default function IncomeAndPayments() {
|
||||
return (
|
||||
<div className="block-wrapper income-and-payments">
|
||||
@@ -51,41 +53,7 @@ export default function IncomeAndPayments() {
|
||||
<button className="btn-success">💸 Заказать выплату</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 className="mt-[30px]">📊 История выплат</h4>
|
||||
<div className="stats-grid">
|
||||
<div className="stats-item left-top-corner stats-header">
|
||||
Сумма
|
||||
</div>
|
||||
<div className="stats-item stats-header">
|
||||
Способ
|
||||
</div>
|
||||
<div className="stats-item stats-header">
|
||||
Статус
|
||||
</div>
|
||||
<div className="stats-item stats-header">
|
||||
Дата запроса
|
||||
</div>
|
||||
<div className="stats-item last-column right-top-corner stats-header">
|
||||
Обработано
|
||||
</div>
|
||||
|
||||
<div className="stats-item first-column left-bottom-corner">
|
||||
0
|
||||
</div>
|
||||
<div className="stats-item second-row">
|
||||
0
|
||||
</div>
|
||||
<div className="stats-item second-row">
|
||||
0
|
||||
</div>
|
||||
<div className="stats-item second-row">
|
||||
0
|
||||
</div>
|
||||
<div className="stats-item last-column right-bottom-corner">
|
||||
0
|
||||
</div>
|
||||
</div>
|
||||
<PaymentsHistory />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -47,7 +47,7 @@ export default function InvitationsTable() {
|
||||
];
|
||||
|
||||
return data.map((item: InviteType) => {
|
||||
console.log(item);
|
||||
|
||||
return {
|
||||
status: item?.active ? 'active' : 'not-active',
|
||||
email: item?.email,
|
||||
|
||||
@@ -1,53 +1,159 @@
|
||||
'use client'
|
||||
|
||||
import DropDownList from '@/app/components/DropDownList';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { ChangeEvent, useState, useActionState, useEffect } from 'react';
|
||||
import BankCardInput from '@/app/ui/inputs/bank-card-inpit';
|
||||
import { addPayoutMethod, PayoutMethodFormState } from '@/app/actions/referralsActions';
|
||||
import { bankCardFormSchema } from '@/app/actions/definitions';
|
||||
|
||||
export default function SettingReferralProgram() {
|
||||
const [state, formAction, isPending] = useActionState(
|
||||
addPayoutMethod,
|
||||
undefined,
|
||||
);
|
||||
|
||||
const [formState, setFormState] = useState<PayoutMethodFormState | undefined>(undefined);
|
||||
const [paymentsType, setPaymentsType] = useState('bank-card');
|
||||
const t = useTranslations('Global');
|
||||
|
||||
useEffect(() => {
|
||||
setFormState(state);
|
||||
}, [state]);
|
||||
|
||||
async function validateField(
|
||||
fieldName: string,
|
||||
value: string,
|
||||
) {
|
||||
switch (fieldName) {
|
||||
case 'bankCard':
|
||||
const schema = bankCardFormSchema?.shape[fieldName];
|
||||
if (!schema) {
|
||||
return { success: true, data: value };
|
||||
}
|
||||
|
||||
return schema.safeParse(value);
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown field: ${fieldName}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function onChangeHandler(e: ChangeEvent<HTMLInputElement>): Promise<void> {
|
||||
const fieldName = e.target.name;
|
||||
|
||||
const validatedField = await validateField(fieldName, e.target.value);
|
||||
|
||||
if (validatedField.success) {
|
||||
setFormState(prevState => {
|
||||
if (!prevState?.error || !prevState?.error[fieldName]) {
|
||||
return {
|
||||
previousState: prevState?.previousState,
|
||||
error: {}
|
||||
};
|
||||
}
|
||||
|
||||
const { [fieldName]: _, ...newError } = prevState.error;
|
||||
|
||||
return {
|
||||
previousState: prevState?.previousState,
|
||||
error: newError
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="block-wrapper setting-referral-program">
|
||||
|
||||
<div className="section-title">
|
||||
<span className="icon">⚙️</span>
|
||||
Настройки реферальной программы
|
||||
{t('referral-program-settings')}
|
||||
</div>
|
||||
|
||||
<form className="settings-form">
|
||||
<form
|
||||
action={(e) => {
|
||||
formAction(e);
|
||||
}}
|
||||
className="settings-form"
|
||||
>
|
||||
<div className="settings-form-wrapper">
|
||||
<h4>💳 Настройки выплат</h4>
|
||||
<h4>{t('payout-settings')}</h4>
|
||||
|
||||
<div className="form-group">
|
||||
<label>Минимальная сумма для вывода (Б)</label>
|
||||
<input type="number" name="min_withdraw_amount" defaultValue="100.00" min="50" step="10" />
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label>Предпочитаемый способ выплаты</label>
|
||||
<select name="preferred_payout_method">
|
||||
<option defaultValue="BALANCE">💳 На баланс аккаунта</option>
|
||||
<option defaultValue="BANK_TRANSFER">🏦 Банковский перевод</option>
|
||||
<option defaultValue="PAYPAL">💰 PayPal</option>
|
||||
<option defaultValue="CARD">💳 Банковская карта</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="checkbox-group">
|
||||
<input type="checkbox" name="auto_withdraw" defaultValue="1" />
|
||||
<label>Автоматический вывод при достижении минимума</label>
|
||||
<label>{t('preferred-payment-method')}</label>
|
||||
<DropDownList
|
||||
value={paymentsType}
|
||||
translatedValue={
|
||||
(() => {
|
||||
switch (paymentsType) {
|
||||
case 'on-account-balance':
|
||||
return t('on-account-balance')
|
||||
case 'bank-card':
|
||||
return t('bank-card')
|
||||
case 'bank-transfer':
|
||||
return t('bank-transfer')
|
||||
}
|
||||
})()
|
||||
}
|
||||
callBack={setPaymentsType}
|
||||
>
|
||||
<li value="on-account-balance">
|
||||
{t('on-account-balance')}
|
||||
</li>
|
||||
<li value="bank-card">
|
||||
{t('bank-card')}
|
||||
</li>
|
||||
<li value="bank-transfer">
|
||||
{t('bank-transfer')}
|
||||
</li>
|
||||
</DropDownList>
|
||||
<input
|
||||
type="hidden"
|
||||
id="paymentsType"
|
||||
name="paymentsType"
|
||||
className={``}
|
||||
value={paymentsType}
|
||||
/>
|
||||
</div>
|
||||
{paymentsType === 'bank-card' && (
|
||||
<div>
|
||||
<h4>
|
||||
{t('bank-card-number')}
|
||||
</h4>
|
||||
<BankCardInput bankCardState={formState?.previousState?.bankCard} validateHandler={onChangeHandler} />
|
||||
{formState?.error?.bankCard && (
|
||||
<p className="text-sm text-red-500">
|
||||
{
|
||||
formState?.error?.bankCard.split('&').map((e, index) => {
|
||||
return (
|
||||
<span key={index}>
|
||||
{t(e)}
|
||||
<br />
|
||||
</span>
|
||||
)
|
||||
})
|
||||
}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{formState?.error?.server && (
|
||||
<p className="text-sm text-red-500 mt-4">
|
||||
{t(formState?.error?.server)}
|
||||
</p>
|
||||
)}
|
||||
<button type="submit" className="btn-primary">
|
||||
{t('save-changes')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="settings-form-wrapper">
|
||||
<h4>🔔 Уведомления</h4>
|
||||
<h4>{t('notifications')}</h4>
|
||||
|
||||
<div className="checkbox-group">
|
||||
<input type="checkbox" name="email_notifications" defaultValue="1"/>
|
||||
<label>Email уведомления о новых рефералах</label>
|
||||
<input type="checkbox" name="email_notifications" defaultValue="1" />
|
||||
<label>{t('email-notifications-about-new-referrals')}</label>
|
||||
</div>
|
||||
|
||||
<div className="checkbox-group">
|
||||
<input type="checkbox" name="marketing_emails" defaultValue="1" />
|
||||
<label>Маркетинговые рассылки о программе</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" className="btn-primary">
|
||||
💾 Сохранить настройки
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
'use client'
|
||||
|
||||
import { useGetReferralPayments } from '@/app/hooks/react-query/useGetReferralPayments';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export default function PaymentsHistory() {
|
||||
|
||||
const { data: paymentsData } = useGetReferralPayments();
|
||||
|
||||
useEffect(() => {
|
||||
console.log(paymentsData);
|
||||
}, [paymentsData])
|
||||
|
||||
return (
|
||||
<>
|
||||
<h4 className="mt-[30px]">📊 История выплат</h4>
|
||||
<div className="stats-grid">
|
||||
<div className="stats-item left-top-corner stats-header">
|
||||
Сумма
|
||||
</div>
|
||||
<div className="stats-item stats-header">
|
||||
Способ
|
||||
</div>
|
||||
<div className="stats-item stats-header">
|
||||
Статус
|
||||
</div>
|
||||
<div className="stats-item stats-header">
|
||||
Дата запроса
|
||||
</div>
|
||||
<div className="stats-item last-column right-top-corner stats-header">
|
||||
Обработано
|
||||
</div>
|
||||
|
||||
<div className="stats-item first-column left-bottom-corner">
|
||||
0
|
||||
</div>
|
||||
<div className="stats-item second-row">
|
||||
0
|
||||
</div>
|
||||
<div className="stats-item second-row">
|
||||
0
|
||||
</div>
|
||||
<div className="stats-item second-row">
|
||||
0
|
||||
</div>
|
||||
<div className="stats-item last-column right-bottom-corner">
|
||||
0
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user