Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions config/webpack.common.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const path = require('path');
const root = path.join(__dirname, '../');

Expand All @@ -11,6 +13,16 @@ module.exports = {
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
sourceMap: true,
}),
new OptimizeCSSAssetsPlugin({}),
],
},
performance: {
hints: false,
maxEntrypointSize: 512000,
Expand Down
13 changes: 5 additions & 8 deletions config/webpack.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,25 @@ const config = {
output: {
publicPath: 'auto',
},
devtool: 'eval-source-map',
devtool: 'source-map',
devServer: {
port: 3000,
port: 3001,
historyApiFallback: true,
headers: {
"Access-Control-Allow-Origin": "*"
}
},
plugins: [
new ModuleFederationPlugin({
name: 'MicroFeChild',
name: 'MicroFETradePartners',
filename: 'remoteEntry.js',
exposes: {
'./Components': './src/externals/exports.tsx',
},
shared: {
...packageJson.dependencies,
react: { requiredVersion: packageJson.dependencies.react },
'react-dom': { requiredVersion: packageJson.dependencies['react-dom'] },
'react-router-dom': { requiredVersion: packageJson.dependencies['react-router-dom'] },
'react-redux': { requiredVersion: packageJson.dependencies['react-redux'] },
'react-intl': { requiredVersion: packageJson.dependencies['react-intl'] },
react: { singleton: true },
'react-dom': { singleton: true },
}
}),
]
Expand Down
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "customers-microfe",
"name": "tradepartners-microfe",
"version": "0.1.0",
"private": true,
"dependencies": {
Expand All @@ -13,12 +13,12 @@
"@types/react-dom": "^18.2.4",
"astro-actions": "1.6.17",
"astro-sso-sdk": "^1.6.17",
"cosmos-components": "2.0.0-alpha.288",
"cosmos-components": "1.35.0",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"numeral": "^2.0.6",
"react": "17",
"react-dom": "17",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-intl": "^6.4.4",
"react-redux": "^8.1.0",
"react-router-config": "4.4.0-beta.8",
Expand Down Expand Up @@ -46,7 +46,9 @@
"css-loader": "^6.7.4",
"html-webpack-plugin": "^5.5.1",
"mini-css-extract-plugin": "^2.7.6",
"optimize-css-assets-webpack-plugin": "^6.0.1",
"style-loader": "^3.3.3",
"terser-webpack-plugin": "1.4.5",
"webpack": "^5.83.1",
"webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0",
Expand Down
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function App() {

return loading ? null : (
<div className="App">
<header className="header">Customers MicroFE</header>
<header className="header">Tradepartners MicroFE</header>
{renderRoutes(routes as any)}
</div>
);
Expand Down
34 changes: 34 additions & 0 deletions src/apis/trade-partners.api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { download } from "../core/utils/download";
import { getApiSDK } from "../helpers/window.helper";

export async function listTradePartners ({ ...params }): Promise<any> {
return await getApiSDK().api.get(
'/agents',
{
params,
},
);
}

export async function exportTradePartners ({ postSearchRequestAgent }): Promise<any> {
try {
const result = await getApiSDK().api.post(
'/agents/export',
{
...postSearchRequestAgent,
subGroupIds: postSearchRequestAgent.subGroupIds?.split(','),
},
);

const blobURL =
window.URL && window.URL.createObjectURL
? window.URL.createObjectURL(
new Blob([result], { type: 'application/octet-stream' }),
)
: window.webkitURL.createObjectURL(result);

download(blobURL, 'agents.csv');
} catch (error) {
console.error(error);
}
}
15 changes: 4 additions & 11 deletions src/bootstrap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,14 @@ import React from 'react';
import { render } from 'react-dom';
import './index.css';
import App from './App';
import { Router } from 'react-router-dom';
import { Store } from './core/store/Store';
import { Internationalization } from './components/internationalization/Internationalization';
import { getHistory } from './helpers/window.helper';
import { ExternalWrapper } from './externals/external-wrapper/ExternalWrapper';

const mount = (el: HTMLElement) => {
render(
<React.StrictMode>
<Internationalization>
<Router history={getHistory()}>
<Store>
<App />
</Store>
</Router>
</Internationalization>
<ExternalWrapper>
<App />
</ExternalWrapper>
</React.StrictMode>,
el
);
Expand Down
190 changes: 190 additions & 0 deletions src/components/allocate-rate-modal/AllocateRateModalContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import {
Icon,
PrimaryButton,
TextButton,
SelectOptionProps,
} from 'cosmos-components';
import React, { useState, useEffect } from 'react';
import { useIntl } from 'react-intl';
import { useDispatch, useSelector } from 'react-redux';
import styled, { css } from 'styled-components';

import { SearchableTagSelect } from 'modules/search';

import msg from 'modules/agents/agents/messages';

import { getProductRateOptions, getAllocatRateLoading } from '../selectors';

import { actions as ratesActions } from '../ducks/productRates';
import { allocateProductRate as allocateRateAction } from '../ducks/allocateProductRate';

type ActionType = 'Add' | 'Remove';

export const AllocateRateModalContent = ({ selectedAgents }) => {
const [rateCode, setRateCode] = useState<SelectOptionProps>(null);
const [succeedNotice, setSucceedNotice] = useState(null);
const [allocateRateSucceed, setAllocateRateSucceed] = useState(false);

const intl = useIntl();
const dispatch = useDispatch();

const { options: rateOptions, loading: rateLoading } = useSelector(
getProductRateOptions,
);

const allocating = useSelector(getAllocatRateLoading);

const searchForRates = (keyword = null) => {
if (keyword) {
dispatch(
ratesActions.listRequest({
text: keyword,
}),
);
}
};

const generateNotice = (action: ActionType) => {
if (action === 'Add') {
return intl.formatMessage(msg.editProductRates.addSucceed, {
code: rateCode?.value,
});
}

return intl.formatMessage(msg.editProductRates.removeSucceed, {
code: rateCode?.value,
});
};

const allocateProductRate = (action: ActionType) => {
dispatch(
allocateRateAction({
group: {
code: rateCode?.value,
},
agents: selectedAgents.map((agent) => ({
id: agent.id,
code: agent.code,
})),
action,
onSuccess: () => {
setAllocateRateSucceed(true);
setRateCode(null);
setSucceedNotice(generateNotice(action));
},
}),
);
};

useEffect(() => {
dispatch(ratesActions.clean());
}, []);

return (
<>
<SelectTitle>
{intl.formatMessage(msg.editProductRates.code)}
</SelectTitle>
<SearchableTagSelect
placeholder={intl.formatMessage(
msg.editProductRates.selectAProductRate,
)}
isLoading={rateLoading}
isMulti={false}
isClearable
options={rateOptions}
value={rateCode}
onSearch={searchForRates}
onChange={(selected) => {
setRateCode(selected);
setAllocateRateSucceed(false);
dispatch(ratesActions.clean());
}}
isDisabled={allocating}
/>
{rateCode && (
<ModalButtonWrapper>
<ModalTextButton
size="small"
onClick={() => allocateProductRate('Remove')}
isLoading={allocating}
>
<Icon name="removeCircle" isInverted />
{intl.formatMessage(msg.editProductRates.remove)}
</ModalTextButton>
<ModalPrimaryButton
size="small"
onClick={() => allocateProductRate('Add')}
isLoading={allocating}
>
<Icon name="addCircle" isInverted />
{intl.formatMessage(msg.editProductRates.add)}
</ModalPrimaryButton>
</ModalButtonWrapper>
)}
{allocateRateSucceed && (
<AllocateRateSucceed>
<Icon name="checkCircle" isInverted />
{succeedNotice}
</AllocateRateSucceed>
)}
</>
);
};

const SelectTitle = styled.div`
color: ${({ theme: { colors } }) => colors.battleshipGrey};
margin-bottom: 0.5rem;
`;

const ModalButtonWrapper = styled.div`
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 1.5rem;
`;

const buttonStyle = css`
width: 8rem;
height: 3.8rem;
display: flex;
align-items: center;
justify-content: center;
border-radius: 0.5rem;
font-size: 1.2rem;

svg {
width: 2rem;
margin-right: 0.5rem;
}
`;

const ModalPrimaryButton = styled(PrimaryButton)`
${buttonStyle}
`;

const ModalTextButton = styled(TextButton)`
${buttonStyle}

margin-right: 1.5rem;

svg {
fill: ${({ theme: { colors } }) => colors.blueMain};
}
`;

const AllocateRateSucceed = styled.div`
margin-top: 1.5rem;
background-color: #eaf5fd;
width: 100%;
height: 4rem;
display: flex;
align-items: center;
padding-left: 5px;

svg {
fill: ${({ theme: { colors } }) => colors.green};
width: 1.5rem;
margin-right: 1rem;
}
`;
33 changes: 33 additions & 0 deletions src/components/customers/reducers/trade-partners.reducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { tradePartnerActionsConstants } from "../../tradepartners/actions/trade-partners.action";

const intialState = {
list: {
loading: false,
data: null
},
};

export default (state = intialState, { type, payload }) => {
switch (type) {
case tradePartnerActionsConstants.triggered:
return {
...intialState,
list: {
...intialState.list,
loading: true
}
};
case tradePartnerActionsConstants.loaded: {
return {
...intialState,
list: {
...intialState.list,
...payload,
data: payload.data
}
};
}
default:
return state;
}
};
2 changes: 1 addition & 1 deletion src/components/customers/view/Customers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Page } from 'cosmos-components/dist/components/Page';
import { PaginatedTableDeprecated } from 'cosmos-components/dist/components/deprecated/PaginatedTableDeprecated';
import { TextButton } from 'cosmos-components/dist/components/Button';

import SearchBox from "../../search-box";
import SearchBox from "../../search";

// hooks
import { useCustomersSearch } from "../hooks";
Expand Down
Loading