Skip to content

Commit

Permalink
Merge pull request #1887 from ahslr/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
abeikverdi authored Jan 19, 2023
2 parents 3928f53 + ecd6d38 commit e5ad0b1
Show file tree
Hide file tree
Showing 9 changed files with 318 additions and 34 deletions.
30 changes: 23 additions & 7 deletions web/src/actions/userAction.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import axios from 'axios';
import { PLUGIN_URL } from '../config/constants';
import { PLUGIN_URL } from 'config/constants';
import querystring from 'query-string';

export const ACTION_KEYS = {
REFERRAL_COUNT_PENDING: 'REFERRAL_COUNT_PENDING',
REFERRAL_COUNT_FULFILLED: 'REFERRAL_COUNT_FULFILLED',
REFERRAL_COUNT_REJECTED: 'REFERRAL_COUNT_REJECTED',
};

export function getMe() {
return {
Expand Down Expand Up @@ -279,24 +286,33 @@ export const cleanCreateAddress = () => ({
type: 'CLEAN_CREATE_ADDRESS',
});

export function getUserReferralCount() {
export const getUserReferrals = (page = 1, limit = 20) => {
const params = { page, limit };
const query = querystring.stringify(params);

return (dispatch) => {
dispatch({ type: ACTION_KEYS.REFERRAL_COUNT_PENDING, payload: { page } });

axios
.get('/user/affiliation')
.get(`/user/affiliation?${query}`)
.then((res) => {
dispatch({
type: 'REFERRAL_COUNT_FULFILLED',
payload: res.data,
type: ACTION_KEYS.REFERRAL_COUNT_FULFILLED,
payload: {
...res.data,
page,
isRemaining: res.data.count > page * limit,
},
});
})
.catch((err) => {
dispatch({
type: 'REFERRAL_COUNT_REJECTED',
type: ACTION_KEYS.REFERRAL_COUNT_REJECTED,
payload: err.response,
});
});
};
}
};

export const getUserLogins = ({ limit = 50, page = 1, ...rest }) => {
return (dispatch) => {
Expand Down
135 changes: 118 additions & 17 deletions web/src/components/Notification/InviteFriends.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,52 @@ import React, { Component } from 'react';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { LoadingOutlined } from '@ant-design/icons';
import DumbField from 'components/Form/FormFields/DumbField';
import { Button, IconTitle } from 'components';
import { Table, EditWrapper, Button, IconTitle } from 'components';
import STRINGS from 'config/localizedStrings';
import { getUserReferralCount } from 'actions/userAction';
import { getUserReferrals } from 'actions/userAction';
import { setSnackNotification } from 'actions/appActions';
import { EditWrapper } from 'components';

const RenderDumbField = (props) => <DumbField {...props} />;
const RECORD_LIMIT = 20;

const HEADERS = [
{
stringId: 'REFERRAL_LINK.USER',
label: STRINGS['REFERRAL_LINK.USER'],
key: 'email',
renderCell: ({ user: { email } }, key, index) => (
<td key={key}>
<div className="d-flex justify-content-start">{email}</div>
</td>
),
},
{
stringId: 'REFERRAL_LINK.TIME',
label: STRINGS['REFERRAL_LINK.TIME'],
key: 'time',
className: 'd-flex justify-content-end',
renderCell: ({ created_at }, key, index) => (
<td key={key}>
<div className="d-flex justify-content-end">{created_at}</div>
</td>
),
},
];

class InviteFriends extends Component {
constructor(props) {
super(props);
this.state = {
copied: false,
showReferrals: false,
};
}

componentDidMount() {
this.props.getUserReferralCount();
const { getUserReferrals } = this.props;
getUserReferrals();
}

handleCopy = () => {
Expand All @@ -31,12 +58,35 @@ class InviteFriends extends Component {
});
};

viewReferrals = (showReferrals) => {
this.setState({ showReferrals });
};

handleNext = (pageCount, pageNumber) => {
const { affiliation, getUserReferrals } = this.props;
const pageTemp = pageNumber % 2 === 0 ? 2 : 1;
const apiPageTemp = Math.floor((pageNumber + 1) / 2);

if (
RECORD_LIMIT === pageCount * pageTemp &&
apiPageTemp >= affiliation.page &&
affiliation.isRemaining
) {
getUserReferrals(affiliation.page + 1, RECORD_LIMIT);
}
};

render() {
const { affiliation_code } = this.props.data;
const { affiliation, icons: ICONS } = this.props;
const {
data: { affiliation_code },
affiliation,
icons: ICONS,
onBack,
} = this.props;
const referralLink = `${process.env.REACT_APP_PUBLIC_URL}/signup?affiliation_code=${affiliation_code}`;
const affiliationCount = affiliation.count ? affiliation.count : 0;
return (
const { showReferrals } = this.state;

return !showReferrals ? (
<div className="invite_friends_wrapper mx-auto">
<IconTitle
stringId="REFERRAL_LINK.TITLE"
Expand Down Expand Up @@ -65,19 +115,33 @@ class InviteFriends extends Component {
onCopy={this.handleCopy}
/>
</div>
<div className="user_refer_info p-4 d-flex align-items-center">
<EditWrapper stringId="REFERRAL_LINK.REFERRED_USER_COUT">
{STRINGS.formatString(
STRINGS['REFERRAL_LINK.REFERRED_USER_COUT'],
affiliationCount
)}
</EditWrapper>
<div className="user_refer_info p-4 d-flex align-items-center justify-content-between">
<div>
<EditWrapper stringId="REFERRAL_LINK.REFERRED_USER_COUT">
{STRINGS.formatString(
STRINGS['REFERRAL_LINK.REFERRED_USER_COUT'],
affiliation.loading ? (
<LoadingOutlined className="px-2" />
) : (
affiliation.count
)
)}
</EditWrapper>
</div>
<div
className="underline-text caps pointer"
onClick={() => this.viewReferrals(true)}
>
<EditWrapper stringId="REFERRAL_LINK.VIEW">
{STRINGS['REFERRAL_LINK.VIEW']}
</EditWrapper>
</div>
</div>
<div className="d-flex my-5">
<Button
label={STRINGS['BACK_TEXT']}
className="mr-5"
onClick={this.props.onBack}
onClick={onBack}
/>
<CopyToClipboard text={referralLink} onCopy={this.handleCopy}>
<Button
Expand All @@ -92,6 +156,43 @@ class InviteFriends extends Component {
</div>
</div>
</div>
) : (
<div className="invite_friends_wrapper mx-auto">
<IconTitle
stringId="REFERRAL_LINK.TABLE_TITLE"
text={STRINGS['REFERRAL_LINK.TABLE_TITLE']}
iconId="REFER_ICON"
iconPath={ICONS['REFER_ICON']}
textType="title"
underline={true}
/>
<div>
<div className="my-2">
<Table
rowClassName="pt-2 pb-2"
headers={HEADERS}
data={affiliation.data}
count={affiliation.count}
handleNext={this.handleNext}
pageSize={10}
displayPaginator={!affiliation.loading}
/>
{affiliation.loading && (
<div className="d-flex my-5 py-5 align-items-center justify-content-center">
<LoadingOutlined style={{ fontSize: '3rem' }} />
</div>
)}
</div>
<div className="d-flex my-5">
<Button
label={STRINGS['BACK_TEXT']}
className="mr-5"
onClick={() => this.viewReferrals(false)}
/>
<Button label={STRINGS['CLOSE_TEXT']} onClick={onBack} />
</div>
</div>
</div>
);
}
}
Expand All @@ -102,7 +203,7 @@ const mapStateToProps = (store) => ({
});

const mapDispatchToProps = (dispatch) => ({
getUserReferralCount: bindActionCreators(getUserReferralCount, dispatch),
getUserReferrals: bindActionCreators(getUserReferrals, dispatch),
setSnackNotification: bindActionCreators(setSnackNotification, dispatch),
});

Expand Down
6 changes: 5 additions & 1 deletion web/src/config/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1163,7 +1163,11 @@
"INFO_TEXT": "Refer your friends by giving out this link and receive benefits by onboarding other people.",
"COPY_FIELD_LABEL": "Share the link below with friends and earn commissions:",
"REFERRED_USER_COUT": "You have referred {0} users",
"COPY_LINK_BUTTON": "COPY REFERRAL LINK"
"COPY_LINK_BUTTON": "COPY REFERRAL LINK",
"VIEW": "view",
"TABLE_TITLE": "All successful referrals",
"USER": "User / email",
"TIME": "Time of sign up"
},
"NOT_LOGGEDIN": {
"TXT_1": "To start trading you must login",
Expand Down
89 changes: 89 additions & 0 deletions web/src/containers/Admin/User/Referrals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { useState, useEffect } from 'react';
import { Table, Spin } from 'antd';
import { getUserReferer, getUserAffiliation } from './actions';
import { formatTimestampGregorian, DATETIME_FORMAT } from 'utils/date';
import './index.css';

const COLUMNS = [
{
title: 'Time referred /signed up',
dataIndex: 'created_at',
key: 'created_at',
render: (value) => (
<div>{formatTimestampGregorian(value, DATETIME_FORMAT)}</div>
),
},
{
title: 'Refereed user',
dataIndex: 'user',
key: 'user',
render: ({ id, email }) => (
<div className="d-flex">
<div className="d-flex justify-content-center align-items-center green-badge">
{id}
</div>
<div className="px-2">{email}</div>
</div>
),
},
];

const Referrals = ({ userInformation: { id: userId, affiliation_code } }) => {
const [loading, setLoading] = useState(true);
const [invitedBy, setInvitedBy] = useState();
const [affiliation, setAffiliation] = useState({ count: 0, data: [] });
const referralLink = `${process.env.REACT_APP_PUBLIC_URL}/signup?affiliation_code=${affiliation_code}`;

useEffect(() => {
getUserReferer(userId).then(({ email }) => {
setInvitedBy(email);
getUserAffiliation(userId).then((response) => {
setAffiliation(response);
setLoading(false);
});
});
}, [userId]);

if (loading) {
return (
<div className="app_container-content">
<Spin size="large" />
</div>
);
}

return (
<div className="admin-user-container">
<div className="mt-2">
Referral affiliation information and table displaying all the successful
referrals that were onboarded onto the platform from this user.
</div>
<div className="d-flex align-items-center m-4">
<div className="d-flex">
<div className="bold">Invited by: </div>
<div className="px-2">{invitedBy}</div>
</div>
<div className="user-info-separator" />
<div className="d-flex">
<div className="bold">Total referred: </div>
<div className="px-2">{affiliation.count}</div>
</div>
<div className="user-info-separator" />
<div className="d-flex">
<div className="bold">Referral link: </div>
<div className="px-2">{referralLink}</div>
</div>
</div>
<div>
<div className="bold">Affiliation referral table</div>
<Table
className="blue-admin-table"
columns={COLUMNS}
dataSource={affiliation.data}
/>
</div>
</div>
);
};

export default Referrals;
6 changes: 6 additions & 0 deletions web/src/containers/Admin/User/UserContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
// import UserData from './UserData';
import BankData from './BankData';
import AboutData from './AboutData';
import Referrals from './Referrals';
import VerifyEmailConfirmation from './VerifyEmailConfirmation';
import { isSupport, isKYC } from '../../../utils/token';
import { STATIC_ICONS } from 'config/icons';
Expand Down Expand Up @@ -402,6 +403,11 @@ class UserContent extends Component {
/>
</TabPane>
)}
{!isSupportUser && !isKYC() && (
<TabPane tab="Referrals" key="referrals">
<Referrals userInformation={userInformation} />
</TabPane>
)}
{!isSupportUser && !isKYC() && (
<TabPane tab="Meta" key="meta">
<UserMetaForm
Expand Down
20 changes: 20 additions & 0 deletions web/src/containers/Admin/User/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,23 @@ export const updateIdData = (body, id) => {
};
return requestAuthenticated(`/admin/user?user_id=${id}`, options);
};

export const getUserAffiliation = (user_id) => {
const options = {
method: 'GET',
};
return requestAuthenticated(
`/admin/user/affiliation?user_id=${user_id}`,
options
);
};

export const getUserReferer = (user_id) => {
const options = {
method: 'GET',
};
return requestAuthenticated(
`/admin/user/referer?user_id=${user_id}`,
options
);
};
Loading

0 comments on commit e5ad0b1

Please sign in to comment.