Added the sample into the repository.
This commit is contained in:
Родитель
bd7878953b
Коммит
dff19006a3
|
@ -0,0 +1,7 @@
|
|||
.npmrc
|
||||
.vscode/
|
||||
node_modules/
|
||||
src/**/*.js
|
||||
dist/
|
||||
styles/*.*
|
||||
!styles/index.css
|
|
@ -0,0 +1,9 @@
|
|||
.npmrc
|
||||
.vscode/
|
||||
.npmignore
|
||||
config.json
|
||||
gulpfile.js
|
||||
tsconfig.json
|
||||
node-modules/
|
||||
Jenkinsfile
|
||||
src/**/*.js
|
|
@ -0,0 +1,28 @@
|
|||
#!groovy
|
||||
|
||||
node('EJ2Component') {
|
||||
try {
|
||||
deleteDir()
|
||||
|
||||
stage('Import') {
|
||||
git url: 'https://github.com/essential-studio/ej2-groovy-scripts.git', branch: 'master', credentialsId: env.GithubCredentialID
|
||||
shared = load 'src/shared.groovy'
|
||||
}
|
||||
|
||||
stage('Checkout') {
|
||||
checkout scm
|
||||
shared.getProjectDetails()
|
||||
shared.gitlabCommitStatus('running')
|
||||
}
|
||||
|
||||
stage('Install') {
|
||||
shared.install()
|
||||
}
|
||||
|
||||
deleteDir()
|
||||
}
|
||||
catch(Exception e) {
|
||||
shared.throwError(e)
|
||||
deleteDir()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"styleDependency": [
|
||||
"ej2"
|
||||
],
|
||||
"isShowCase": true,
|
||||
"publishSamples": [
|
||||
"./build/**"
|
||||
]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
require("@syncfusion/ej2-build");
|
|
@ -0,0 +1,10 @@
|
|||
Essential JS 2 library is available under the Syncfusion Essential Studio program, and can be licensed either under the Syncfusion Community License Program or the Syncfusion commercial license.
|
||||
|
||||
To be qualified for the Syncfusion Community License Program you must have a gross revenue of less than one (1) million U.S. dollars ($1,000,000.00 USD) per year and have less than five (5) developers in your organization, and agree to be bound by Syncfusion’s terms and conditions.
|
||||
|
||||
Customers who do not qualify for the community license can contact sales@syncfusion.com for commercial licensing options.
|
||||
|
||||
Under no circumstances can you use this product without (1) either a Community License or a commercial license and (2) without agreeing and abiding by Syncfusion’s license containing all terms and conditions.
|
||||
|
||||
The Syncfusion license that contains the terms and conditions can be found at
|
||||
https://www.syncfusion.com/content/downloads/syncfusion_license.pdf
|
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"name": "@syncfusion/ej2-react-samples-template",
|
||||
"version": "0.0.1",
|
||||
"description": "Essential JS 2 for React - Samples template",
|
||||
"author": "Syncfusion Inc.",
|
||||
"license": "SEE LICENSE IN license",
|
||||
"dependencies": {
|
||||
"@syncfusion/ej2-react-buttons": "*",
|
||||
"@syncfusion/ej2-react-calendars": "*",
|
||||
"@syncfusion/ej2-react-charts": "*",
|
||||
"@syncfusion/ej2-react-grids": "*",
|
||||
"@syncfusion/ej2-react-inputs": "*",
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/react": "^13.2.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"typescript": "^4.6.4",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@syncfusion/ej2-build": "*",
|
||||
"@types/jest": "^27.5.1",
|
||||
"@types/node": "^16.11.36",
|
||||
"@types/react": "^18.0.9",
|
||||
"@types/react-dom": "^18.0.4",
|
||||
"style-loader": "^0.23.1",
|
||||
"typescript": "^3.1.6"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject",
|
||||
"ci-publish": "gulp publish-samples"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 6.4 KiB |
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Essential JS 2 for React - Loan Calculator - You can use this application to Calculates your loan payment based on your loan amount, interest and term"
|
||||
/>
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
|
||||
<title>Essential JS 2 for React - Loan Calculator</title>
|
||||
<link rel="icon" type="image/x-icon" href="../src/favicon.ico">
|
||||
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Raleway:500,600" rel="stylesheet">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/shim.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/reflect-metadata/0.1.10/Reflect.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"short_name": "Syncfusion Loan Calculator",
|
||||
"name": "Essential JS 2 for React - Loan Calculator",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
|
@ -0,0 +1,813 @@
|
|||
import { DetailRow, GridComponent, GridModel, Inject, Page } from '@syncfusion/ej2-react-grids';
|
||||
import { ChangeEventArgs, SliderComponent, SliderTickRenderedEventArgs } from '@syncfusion/ej2-react-inputs';
|
||||
import { NumericTextBoxComponent } from '@syncfusion/ej2-react-inputs';
|
||||
import { RadioButtonComponent } from '@syncfusion/ej2-react-buttons';
|
||||
import { DatePickerComponent } from '@syncfusion/ej2-react-calendars';
|
||||
import { AccumulationChartComponent, AccumulationSeriesCollectionDirective, AccumulationSeriesDirective, AxesDirective, AxisDirective, IAccPointRenderEventArgs, IAxisLabelRenderEventArgs, PieSeries, StackingColumnSeries } from '@syncfusion/ej2-react-charts';
|
||||
import { ChartComponent, Legend, LineSeries, SeriesCollectionDirective, SeriesDirective } from '@syncfusion/ej2-react-charts';
|
||||
import { DateTime, Tooltip } from '@syncfusion/ej2-react-charts';
|
||||
import { closest, Internationalization } from '@syncfusion/ej2-base';
|
||||
import { isNullOrUndefined as isNOU } from '@syncfusion/ej2-base';
|
||||
import './index.css';
|
||||
import './styles.css';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
export default function App() {
|
||||
|
||||
const [loanTicks, setLoanTicks] = useState({});
|
||||
const [dateValue, setDateValue] = useState(new Date());
|
||||
const [interestValue, setInterestValue] = useState(5.5);
|
||||
const [yearTenure, setYearTenure] = useState(true);
|
||||
let emiAmt: string = '';
|
||||
let principalAmt: string = '';
|
||||
let interestAmt: string = '';
|
||||
let totalAmt: string = '';
|
||||
const [principalValue, setPrincipalValue] = useState(300000);
|
||||
const [loanValue, setLoanValue] = useState(15);
|
||||
let grid = useRef(null);
|
||||
let accChart = useRef(null);
|
||||
let acc1 = useRef(null);
|
||||
let principalNumRef = useRef(null);
|
||||
let principalSliderRef = useRef(null);
|
||||
let interestSliderRef = useRef(null);
|
||||
let interestNumRef = useRef(null);
|
||||
let loanSliderRef = useRef(null);
|
||||
let loanNumRef = useRef(null);
|
||||
let pie = useRef(null);
|
||||
let emi: number = 0;
|
||||
let tempPrincipalValue: number = 0;
|
||||
let beginBalance: number = 30000;
|
||||
let tent: number = 0;
|
||||
let totalPrincipalYear: number = 0;
|
||||
let totalInterestYear: number = 0;
|
||||
let tempInterest: number = 0;
|
||||
let dataUnits: Array<Object> = [];
|
||||
let yearWiseData: Array<Object> = [];
|
||||
let dateObj: Date = new Date();
|
||||
let totalInterest: number = 0;
|
||||
let totalAmount: number = 0;
|
||||
let totalPrincipal: number = 0;
|
||||
let endBalance: number = 0;
|
||||
let yearTotal: number = 0;
|
||||
let child: GridModel;
|
||||
let interestNumFormat: string = '#.##\' %\'';
|
||||
let loanNumFormat: string = '#.##';
|
||||
let monthNames: Array<string> = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];
|
||||
let intl: Internationalization = new Internationalization();
|
||||
let legendSettings: Object = {
|
||||
textStyle: {
|
||||
color: '#FFFFFF',
|
||||
fontFamily: 'Raleway, sans-serif',
|
||||
fontWeight: '600',
|
||||
opacity: 0.62,
|
||||
size: '16px',
|
||||
}
|
||||
};
|
||||
let format: string = 'c0';
|
||||
let principalTicks: Object = { placement: 'After', largeStep: 100000, smallStep: 10000, showSmallTicks: false, format: 'c0' };
|
||||
const [interestTicks, setInterestTicks] = useState({});
|
||||
let labelStyle: any;
|
||||
let titleStyle: any;
|
||||
let columns: any;
|
||||
const [loanNumMinValue, setLoanNumMinValue] = useState(1);
|
||||
const [loanNumMaxValue, setLoanNumMaxValue] = useState(40);
|
||||
const [loanMaxValue, setLoanMaxValue] = useState(40);
|
||||
const [loanNumStep, setLoanNumStep] = useState(1);
|
||||
const [loanStep, setLoanStep] = useState(1);
|
||||
const [loanMinValue, setLoanMinValue] = useState(0);
|
||||
let princAmount = useRef(null);
|
||||
let totalInt = useRef(null);
|
||||
let totalPay = useRef(null);
|
||||
let monPayment = useRef(null);
|
||||
let monthChange = useRef(null);
|
||||
let yearChange = useRef(null);
|
||||
const [paymentHideAtMedia, setPaymentHideAtMedia] = useState('(min-width: 480px)');
|
||||
|
||||
function setInitValues(): void {
|
||||
emi = calculateEMI();
|
||||
tempPrincipalValue = principalValue;
|
||||
tent = yearTenure ? (loanValue * 12) : loanValue;
|
||||
dataUnits = [];
|
||||
yearWiseData = [];
|
||||
dateObj = new Date(dateValue.getTime());
|
||||
totalInterest = 0;
|
||||
totalAmount = 0;
|
||||
totalPrincipal = 0;
|
||||
totalPrincipalYear = 0;
|
||||
totalInterestYear = 0;
|
||||
emiAmt = getCurrencyVal(tent ? Math.round(emi) : 0);
|
||||
interestAmt = getCurrencyVal(tent ? Math.round((emi * tent) - tempPrincipalValue) : 0);
|
||||
totalAmt = getCurrencyVal(tent ? Math.round((emi * tent)) : 0);
|
||||
principalAmt = getCurrencyVal(tempPrincipalValue);
|
||||
}
|
||||
|
||||
function calculateEMI(): number {
|
||||
let interestValue: number = getInterest();
|
||||
let tent: number = yearTenure ? (loanValue * 12) : loanValue;
|
||||
if (interestValue) {
|
||||
return principalValue * interestValue *
|
||||
(Math.pow((1 + interestValue), tent)) / ((Math.pow((1 + interestValue), tent)) - 1);
|
||||
}
|
||||
return principalValue / tent;
|
||||
}
|
||||
|
||||
function getInterest(): number {
|
||||
return interestValue ? parseFloat('' + interestValue / 12 / 100) : 0;
|
||||
}
|
||||
|
||||
function getCurrencyVal(value: number): string {
|
||||
return intl.formatNumber(value, { format: 'C0' });
|
||||
}
|
||||
|
||||
function principalRenderedTicks(args: SliderTickRenderedEventArgs): void {
|
||||
let li: HTMLCollectionBase = args.ticksWrapper.getElementsByClassName('e-large');
|
||||
for (let i: number = 0; i < li.length; ++i) {
|
||||
let ele: HTMLElement = (li[i].querySelectorAll('.e-tick-value')[0] as HTMLElement);
|
||||
let num: number = parseInt(ele.innerText.substring(1).replace(/,/g, ''), 10) / 1000;
|
||||
ele.innerText = num === 0 ? ('' + num) : (num + 'K');
|
||||
}
|
||||
}
|
||||
|
||||
const principalNumChange = (args: any): void => {
|
||||
(principalSliderRef.current as any).value = args.value
|
||||
setPrincipalValue(args.value);
|
||||
}
|
||||
|
||||
const principalChanged = (args: any): void => {
|
||||
(principalNumRef.current as any).value = args.value
|
||||
setPrincipalValue(args.value);
|
||||
}
|
||||
|
||||
const interestNumChange = (args: any): void => {
|
||||
(interestSliderRef.current as any) = args.value
|
||||
setInterestValue(args.value);
|
||||
}
|
||||
|
||||
const interestChanged = (args: any): void => {
|
||||
(interestNumRef.current as any).value = args.value
|
||||
setInterestValue(args.value);
|
||||
}
|
||||
|
||||
const loanNumChange = (args: any): void => {
|
||||
(loanSliderRef.current as any).value = args.value;
|
||||
setLoanValue(args.value);
|
||||
}
|
||||
|
||||
const loanChanged = (args: any): void => {
|
||||
(loanNumRef.current as any).value = args.value;
|
||||
setLoanValue(args.value);
|
||||
}
|
||||
|
||||
const updateDateValue = (args: any): void => {
|
||||
dateObj = args.value
|
||||
|
||||
if (isNOU(args.value)) {
|
||||
setDateValue(new Date());
|
||||
} else {
|
||||
setDateValue(args.value);
|
||||
}
|
||||
}
|
||||
|
||||
function monthChanged(args: ChangeEventArgs): void {
|
||||
setYearTenure(false);
|
||||
setLoanNumMinValue(12);
|
||||
setLoanNumMaxValue(480);
|
||||
setLoanNumStep(12);
|
||||
setLoanMaxValue(480);
|
||||
setLoanValue(loanValue * 12);
|
||||
setLoanStep(12);
|
||||
setLoanTicks({ placement: 'After', largeStep: 120, smallStep: 12, showSmallTicks: false });
|
||||
}
|
||||
|
||||
function yearChanged(args: ChangeEventArgs): void {
|
||||
setYearTenure(true);
|
||||
setLoanNumMinValue(1);
|
||||
setLoanNumMaxValue(40);
|
||||
setLoanNumStep(1);
|
||||
setLoanMaxValue(40);
|
||||
setLoanValue(loanValue / 12);
|
||||
setLoanStep(1);
|
||||
setLoanTicks({ placement: 'After', largeStep: 10, smallStep: 1, showSmallTicks: false });
|
||||
|
||||
}
|
||||
|
||||
function axisLabelRender(args: IAxisLabelRenderEventArgs): void {
|
||||
if (window.innerWidth < 576) {
|
||||
if (args.axis.name === 'primaryYAxis' || args.axis.name === 'yAxis1') {
|
||||
let value: number = Number(args.value) / 1000;
|
||||
args.text = value === 0 ? String(value) : (String(value) + 'K');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function calRangeValues(): void {
|
||||
for (let i: number = 0; i < tent; i++) {
|
||||
tempInterest = getInterest() ? (tempPrincipalValue * getInterest()) : tempPrincipalValue;
|
||||
totalInterest += tempInterest;
|
||||
totalAmount += emi;
|
||||
totalPrincipal += parseFloat((emi - tempInterest).toFixed(2));
|
||||
endBalance = tempPrincipalValue - (emi - tempInterest);
|
||||
yearTotal += emi;
|
||||
totalPrincipalYear += parseFloat((emi - tempInterest).toFixed(2));
|
||||
totalInterestYear += tempInterest;
|
||||
dataUnits.push({
|
||||
month: monthNames[dateObj.getMonth()],
|
||||
index: (i + 1),
|
||||
totalInterest: Math.round(totalInterest),
|
||||
totalAmount: totalAmount,
|
||||
emi: Math.round(emi),
|
||||
year: dateObj.getFullYear(),
|
||||
beginningBalance: Math.round(tempPrincipalValue),
|
||||
interest: Math.round(tempInterest),
|
||||
principalPaid: Math.round((emi - tempInterest)),
|
||||
endingBalance: Math.round(endBalance)
|
||||
});
|
||||
if (i === 0 || dateObj.getMonth() === 0) {
|
||||
beginBalance = tempPrincipalValue;
|
||||
}
|
||||
if (dateObj.getMonth() === 11 || (i === tent - 1)) {
|
||||
yearWiseData.push({
|
||||
beginningBalance: Math.round(beginBalance),
|
||||
totalInterest: Math.round(totalInterest),
|
||||
totalPrincipal: Math.round(totalPrincipal),
|
||||
totalAmount: Math.round(totalAmount),
|
||||
yearTotal: Math.round(yearTotal),
|
||||
endingBalance: Math.round(endBalance),
|
||||
yearN: new Date(dateObj.getFullYear(), 0, 1),
|
||||
year: dateObj.getFullYear(),
|
||||
yearPrincipal: totalPrincipalYear,
|
||||
yearInterest: totalInterestYear
|
||||
});
|
||||
yearTotal = 0;
|
||||
totalPrincipalYear = 0;
|
||||
totalInterestYear = 0;
|
||||
}
|
||||
tempPrincipalValue = endBalance;
|
||||
if (i < tent - 1) {
|
||||
dateObj.setMonth(dateObj.getMonth() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function gridTemplate(props: any): any {
|
||||
return (
|
||||
<div>
|
||||
<div className="e-icons e-icon-grightarrow e-row-toggle"></div>
|
||||
<span id="abc">{props.year}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function onclickEvent(args: any) {
|
||||
debugger;
|
||||
let target: any = args.target as Element;
|
||||
if (target.classList.contains('e-row-toggle') || target.parentElement.querySelector('.e-row-toggle')) {
|
||||
target = target.parentElement.querySelector('.e-row-toggle') ? target.parentElement.querySelector('.e-row-toggle') : target;
|
||||
if (target.classList.contains('e-icon-gdownarrow')) {
|
||||
target.classList.remove('e-icon-gdownarrow');
|
||||
target.classList.add('e-icon-grightarrow');
|
||||
(grid.current as any).detailRowModule.collapse(parseInt((closest(target, 'tr') as HTMLElement).getAttribute('data-rowindex')!, 10));
|
||||
} else {
|
||||
target.classList.remove('e-icon-grightarrow');
|
||||
target.classList.add('e-icon-gdownarrow');
|
||||
(grid.current as any).detailRowModule.expand(parseInt((closest(target, 'tr') as HTMLElement).getAttribute('data-rowindex')!, 10));
|
||||
}
|
||||
}
|
||||
gridHide();
|
||||
}
|
||||
|
||||
function pointRender(args: IAccPointRenderEventArgs): void {
|
||||
if (args.point.index) {
|
||||
args.border.width = 7;
|
||||
args.fill = 'url(#interest_svg)';
|
||||
} else {
|
||||
args.border.width = 7;
|
||||
args.border.color = '#162036';
|
||||
args.fill = 'url(#principal_svg)';
|
||||
}
|
||||
}
|
||||
|
||||
columns = [
|
||||
{
|
||||
headerText:'Year',
|
||||
template: gridTemplate,
|
||||
minWidth: '80px',
|
||||
textAlign:'Center',
|
||||
},
|
||||
{
|
||||
field:'yearTotal',
|
||||
headerText:'Payment',
|
||||
minWidth:'80px',
|
||||
format:format,
|
||||
textAlign:'Center',
|
||||
hideAtMedia:paymentHideAtMedia,
|
||||
},
|
||||
{
|
||||
field:'yearPrincipal',
|
||||
headerText:'Principal Paid',
|
||||
minWidth:'80px',
|
||||
format:format,
|
||||
textAlign:'Center',
|
||||
},
|
||||
{
|
||||
field:'yearInterest',
|
||||
headerText:'Interest Paid',
|
||||
minWidth:'80px',
|
||||
format:format,
|
||||
textAlign:'Center',
|
||||
},
|
||||
{
|
||||
field:'endingBalance',
|
||||
headerText:'Balance',
|
||||
minWidth:'80px',
|
||||
format:format,
|
||||
textAlign:'Center',
|
||||
}
|
||||
]
|
||||
|
||||
function gridHide() {
|
||||
if (width < 439) {
|
||||
let grid: any = document.getElementsByClassName('e-grid');
|
||||
for (let i=0; i < grid.length; i++){
|
||||
grid[i].ej2_instances[0].hideColumns('Payment');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setInitValues();
|
||||
calRangeValues();
|
||||
child = {
|
||||
queryString: 'year',
|
||||
cssClass: "child-grid-custom",
|
||||
columns: [
|
||||
{ field: 'month', headerText: 'Month', textAlign: 'Center', minWidth: '80px' },
|
||||
{ field: 'emi', headerText: 'Payment', textAlign: 'Center', format: 'C0', minWidth: '80px' },
|
||||
{ field: 'principalPaid', headerText: 'Principal Paid', textAlign: 'Center', format: 'C0', minWidth: '80px' },
|
||||
{ field: 'interest', headerText: 'Interest Paid', textAlign: 'Center', format: 'C0', minWidth: '80px' },
|
||||
{ field: 'endingBalance', headerText: 'Balance', textAlign: 'Center', format: 'C0', minWidth: '80px' }
|
||||
],
|
||||
dataSource: dataUnits
|
||||
};
|
||||
|
||||
labelStyle = {
|
||||
color: '#989CA9',
|
||||
fontFamily: 'Roboto',
|
||||
fontWeight: '400',
|
||||
size: '16px',
|
||||
};
|
||||
|
||||
titleStyle = {
|
||||
color: '#FFFFFF',
|
||||
fontFamily: 'Raleway, sans-serif',
|
||||
fontWeight: '600',
|
||||
opacity: 0.62,
|
||||
size: '16px',
|
||||
}
|
||||
|
||||
let width = window.innerWidth;
|
||||
if (width <= 350) {
|
||||
labelStyle = {
|
||||
color: '#989CA9',
|
||||
fontFamily: 'Roboto',
|
||||
fontWeight: '400',
|
||||
size: '12px',
|
||||
}
|
||||
|
||||
titleStyle = {
|
||||
color: '#FFFFFF',
|
||||
fontFamily: 'Raleway, sans-serif',
|
||||
fontWeight: '600',
|
||||
opacity: 0.62,
|
||||
size: '12px',
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setLoanTicks({
|
||||
placement: 'After',
|
||||
largeStep: 10,
|
||||
smallStep: 1,
|
||||
showSmallTicks: false
|
||||
});
|
||||
|
||||
setInterestTicks({ placement: 'After', largeStep: 5, smallStep: 1, showSmallTicks: false });
|
||||
},[]);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
gridHide();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="header-style">Loan Calculator</h1>
|
||||
<div className="container main-content" id="content">
|
||||
<div className="row left-content-wrap">
|
||||
<div className="row loan-content" >
|
||||
<div className="left-content col-lg-12">
|
||||
<div className="row form-space" >
|
||||
<div className="col-lg-12">
|
||||
<div className="content-space">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label className="principal">Loan Amount</label>
|
||||
</td>
|
||||
<td>
|
||||
<div className="editor-space">
|
||||
<NumericTextBoxComponent
|
||||
id="principal_txt"
|
||||
format='c0'
|
||||
min={1000}
|
||||
max={5000000}
|
||||
value={principalValue}
|
||||
step={10000}
|
||||
width='200px'
|
||||
change={principalNumChange}
|
||||
ref={principalNumRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div >
|
||||
<SliderComponent
|
||||
id='principal'
|
||||
min={0}
|
||||
max={500000}
|
||||
step={10000}
|
||||
value={principalValue}
|
||||
type='MinRange'
|
||||
ticks={principalTicks}
|
||||
renderedTicks={principalRenderedTicks}
|
||||
ref={principalSliderRef}
|
||||
change={principalChanged}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row form-space">
|
||||
<div className="col-lg-12">
|
||||
<div className="content-space">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label className="interestrate">Interest Rate</label>
|
||||
</td>
|
||||
<td>
|
||||
<div className="editor-space">
|
||||
<NumericTextBoxComponent
|
||||
id="interest_txt"
|
||||
format={interestNumFormat}
|
||||
min={0}
|
||||
max={20}
|
||||
value={interestValue}
|
||||
step={.25}
|
||||
width='165px'
|
||||
change={interestNumChange}
|
||||
ref={interestNumRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<SliderComponent
|
||||
id='interestrate'
|
||||
min={0}
|
||||
max={20}
|
||||
step={.25}
|
||||
value={interestValue}
|
||||
type='MinRange'
|
||||
ticks={interestTicks}
|
||||
change={interestChanged}
|
||||
ref={interestSliderRef}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row form-space">
|
||||
<div className="col-lg-12">
|
||||
<div className="content-space">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label className="loantenure">Loan Term</label>
|
||||
<ul className="tenure-value"
|
||||
>
|
||||
<li>
|
||||
<RadioButtonComponent
|
||||
id="radio1"
|
||||
label='Month'
|
||||
name='tenure'
|
||||
value="month"
|
||||
change={monthChanged}
|
||||
ref={monthChange}
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<RadioButtonComponent
|
||||
id="radio2"
|
||||
checked={true}
|
||||
label='Year'
|
||||
name='tenure'
|
||||
value="year"
|
||||
change={yearChanged}
|
||||
ref={yearChange}
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<div className="editor-space">
|
||||
<NumericTextBoxComponent
|
||||
id="loan_txt"
|
||||
format={loanNumFormat}
|
||||
min={loanNumMinValue}
|
||||
max={loanNumMaxValue}
|
||||
value={loanValue}
|
||||
step={loanNumStep}
|
||||
width='150px'
|
||||
change={loanNumChange}
|
||||
ref={loanNumRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id='loantenure'>
|
||||
<SliderComponent
|
||||
id='loantenure'
|
||||
min={loanMinValue}
|
||||
max={loanMaxValue}
|
||||
step={loanStep}
|
||||
value={loanValue}
|
||||
type='MinRange'
|
||||
ticks={loanTicks}
|
||||
change={loanChanged}
|
||||
ref={loanSliderRef}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row loan-content">
|
||||
<div className="col-lg-12 emi-content">
|
||||
<div>
|
||||
<h6 className="emi-header">Break-up of Total Payment</h6>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-7">
|
||||
<AccumulationChartComponent
|
||||
dataSource={[
|
||||
{
|
||||
'x': 'Principal Amount',
|
||||
y: principalValue
|
||||
},
|
||||
{
|
||||
'x': 'Interest Amount',
|
||||
y: ((emi * tent) - principalValue)
|
||||
}
|
||||
]}
|
||||
background='transparent'
|
||||
id="payment_pieChart"
|
||||
enableSmartLabels={true}
|
||||
height="365px"
|
||||
width='100%'
|
||||
enableAnimation={true}
|
||||
legendSettings={{ visible: false }}
|
||||
tooltip={{ enable: false }}
|
||||
pointRender={pointRender}
|
||||
ref={pie}
|
||||
>
|
||||
<Inject services={[PieSeries, Legend, Tooltip]} />
|
||||
<AccumulationSeriesCollectionDirective>
|
||||
<AccumulationSeriesDirective
|
||||
xName='x'
|
||||
yName='y'
|
||||
type='Pie'
|
||||
radius='80%'
|
||||
startAngle={290}
|
||||
endAngle={290}
|
||||
innerRadius='60%'
|
||||
explode={true}
|
||||
explodeOffset='10%'
|
||||
explodeIndex={3}
|
||||
>
|
||||
</AccumulationSeriesDirective>
|
||||
</AccumulationSeriesCollectionDirective>
|
||||
</AccumulationChartComponent>
|
||||
</div>
|
||||
<div className="col-lg-5 pie-content" id="pieContent">
|
||||
<div>
|
||||
<p><span className="pie-icon pie-principal"></span>Principal Amount</p>
|
||||
<h5 id="loan_principal" ref={princAmount} >{principalAmt}</h5>
|
||||
</div>
|
||||
<div>
|
||||
<p><span className="pie-icon pie-interest"></span>Total Interest</p>
|
||||
<h5 id="loan_interest" ref={totalInt}>{interestAmt}</h5>
|
||||
</div>
|
||||
<div className="pie-total">
|
||||
<span>
|
||||
<p>Total Payment</p>
|
||||
<p>(Principal + Interest)</p>
|
||||
</span>
|
||||
<h5 id="loan_total_payment" ref={totalPay}>{totalAmt}</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h6 className="emi-footer">Your Monthly Payment</h6>
|
||||
<h1 id="loan_emi" ref={monPayment}>{emiAmt}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<svg height='0px'>
|
||||
<defs>
|
||||
<linearGradient id="principal_svg" x1="0" x2="0" y1="0" y2="1">
|
||||
<stop offset="0"></stop>
|
||||
<stop offset="1"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient id="interest_svg" x1="0" x2="0" y1="0" y2="1">
|
||||
<stop offset="0"></stop>
|
||||
<stop offset="1"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row top-space loan-content"
|
||||
style={{ textAlign: 'center' }}>
|
||||
<div className="graph-text">Monthly payments starting from</div>
|
||||
<div className="graph-input">
|
||||
< DatePickerComponent
|
||||
id="monthStarter"
|
||||
placeholder="Enter date"
|
||||
start="Year"
|
||||
showClearButton={false}
|
||||
showTodayButton={false}
|
||||
strictMode={true}
|
||||
depth="Year"
|
||||
format='MMM yyy'
|
||||
width='250px'
|
||||
value={dateValue}
|
||||
onChange={updateDateValue}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row top-space loan-content max-content">
|
||||
<h6 className="center-heading">Amortization Chart</h6>
|
||||
<div className="col-lg-12 graph-container">
|
||||
<ChartComponent
|
||||
style={{
|
||||
textAlign: 'center', display: 'block'
|
||||
}}
|
||||
id="paymentGraph"
|
||||
primaryXAxis={{
|
||||
title: 'Years',
|
||||
valueType: 'DateTime',
|
||||
labelFormat: 'y',
|
||||
intervalType: 'Years',
|
||||
majorGridLines: { width: 0 },
|
||||
minorGridLines: { width: 0 },
|
||||
majorTickLines: { width: 0 },
|
||||
minorTickLines: { width: 0 },
|
||||
lineStyle: { width: 1, dashArray: '2', color: 'rgba(255,255,255,0.2)' },
|
||||
labelStyle: labelStyle,
|
||||
titleStyle: titleStyle
|
||||
}}
|
||||
primaryYAxis={{
|
||||
title: 'Balance',
|
||||
interval: 50000,
|
||||
minimum: 0,
|
||||
labelFormat: 'c0',
|
||||
rangePadding: 'None',
|
||||
lineStyle: { width: 0 },
|
||||
majorTickLines: { width: 0 },
|
||||
majorGridLines: { width: 1, dashArray: '2', color: 'rgba(255,255,255,0.2)' },
|
||||
minorGridLines: { width: 0 },
|
||||
minorTickLines: { width: 0 },
|
||||
labelStyle: labelStyle,
|
||||
titleStyle: titleStyle
|
||||
}}
|
||||
axisLabelRender={axisLabelRender}
|
||||
tooltip={{
|
||||
enable: true,
|
||||
shared: true,
|
||||
format: '${series.name} : ${point.y}',
|
||||
header: '<b>${point.x}<b>',
|
||||
fill: '#FFFFFF',
|
||||
opacity: 1,
|
||||
textStyle: {
|
||||
color: '#555555',
|
||||
fontFamily: 'Roboto',
|
||||
size: '12px',
|
||||
fontWeight: '400',
|
||||
},
|
||||
}}
|
||||
chartArea={{ border: { width: 0 } }}
|
||||
enableSideBySidePlacement={false}
|
||||
height="500px"
|
||||
useGroupingSeparator={true}
|
||||
background="#27304c"
|
||||
palettes={['#FB6589', '#3AC8DC', '#FFFFFF']}
|
||||
titleStyle={{
|
||||
color: 'White',
|
||||
fontFamily: 'Raleway, sans-serif',
|
||||
fontWeight: '500',
|
||||
size: '20px',
|
||||
}}
|
||||
legendSettings={legendSettings}
|
||||
ref={accChart}
|
||||
dataSource={yearWiseData}
|
||||
>
|
||||
<Inject services={[LineSeries, StackingColumnSeries, DateTime, Legend, Tooltip]} />
|
||||
|
||||
<AxesDirective>
|
||||
<AxisDirective majorGridLines={{ width: 0 }}
|
||||
minorGridLines={{ width: 0 }}
|
||||
minorTickLines={{ width: 0 }}
|
||||
rowIndex={0} opposedPosition={true}
|
||||
lineStyle={{ width: 0 }}
|
||||
majorTickLines={{ width: 0 }}
|
||||
name='yAxis1'
|
||||
title='Payment'
|
||||
labelRotation={0}
|
||||
labelIntersectAction='Hide'
|
||||
labelStyle={labelStyle}
|
||||
titleStyle={titleStyle}
|
||||
labelFormat='c0'
|
||||
>
|
||||
</AxisDirective>
|
||||
</AxesDirective>
|
||||
|
||||
<SeriesCollectionDirective>
|
||||
<SeriesDirective
|
||||
xName="yearN"
|
||||
yName="yearPrincipal"
|
||||
name="Principal Paid"
|
||||
width={2}
|
||||
colorName="rgb(255, 255, 255)"
|
||||
marker={{ visible: true, width: 10, height: 10 }}
|
||||
columnWidth={0.425}
|
||||
type="StackingColumn"
|
||||
yAxisName="yAxis1"
|
||||
ref={acc1}
|
||||
></SeriesDirective>
|
||||
<SeriesDirective
|
||||
xName="yearN"
|
||||
yName="yearInterest"
|
||||
name="Interest Paid"
|
||||
width={2}
|
||||
columnWidth={0.425}
|
||||
marker={{ visible: true, width: 10, height: 10 }}
|
||||
type="StackingColumn"
|
||||
yAxisName="yAxis1"
|
||||
></SeriesDirective>
|
||||
<SeriesDirective
|
||||
xName="yearN"
|
||||
yName="endingBalance"
|
||||
name="Balance"
|
||||
width={2}
|
||||
columnWidth={0.425}
|
||||
marker={{ visible: true, width: 10, height: 10, fill: '#60448D' }}
|
||||
type="Line"
|
||||
></SeriesDirective>
|
||||
</SeriesCollectionDirective>
|
||||
</ChartComponent>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row top-space loan-content max-content">
|
||||
<h6 className="center-heading">Amortization Schedule</h6>
|
||||
<div style={{ color: 'white' }}>
|
||||
<GridComponent
|
||||
dataSource={yearWiseData}
|
||||
childGrid={child}
|
||||
onClick={onclickEvent}
|
||||
ref={grid}
|
||||
enableHover={true}
|
||||
id='scheduleGrid'
|
||||
columns={columns}
|
||||
allowTextWrap={true}
|
||||
>
|
||||
<Inject services={[DetailRow, Page]} />
|
||||
</GridComponent>
|
||||
</div>
|
||||
</div>
|
||||
</div >
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,863 @@
|
|||
/* body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
} */
|
||||
|
||||
#abc{
|
||||
padding-left: 12px;
|
||||
color: white;
|
||||
}
|
||||
#scheduleGrid span{
|
||||
color:white;
|
||||
}
|
||||
#abcd{
|
||||
color:white;
|
||||
}
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
.e-grid .e-detailrowexpand > div,
|
||||
.e-grid .e-detailrowcollapse > div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.content-space {
|
||||
display: block;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 25px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.content-space table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.content-space label {
|
||||
float: left;
|
||||
margin-top: 6px;
|
||||
color: #E7E7E7;
|
||||
font-size: 16px;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.editor-space {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.form-space {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.form-space:not(:first-child) {
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.component-content {
|
||||
border-radius: 3px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.parent {
|
||||
min-height: 85px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.child {
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.top-space {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.top-space h6 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.emi-content {
|
||||
max-width: 634px;
|
||||
max-height: 660px;
|
||||
margin: 30px 0 5px 0;
|
||||
padding: 0 44px;
|
||||
}
|
||||
|
||||
.emi-content h6 {
|
||||
font-family: 'Raleway', sans-serif;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.emi-content .emi-header {
|
||||
font-size: 20px;
|
||||
color: #E7E7E7;
|
||||
letter-spacing: 0.7px;
|
||||
line-height: 29px;
|
||||
}
|
||||
|
||||
.emi-content .emi-footer {
|
||||
font-size: 18px;
|
||||
color: #989CA9;
|
||||
margin-top: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.emi-content h1 {
|
||||
color: #F5F5F5;
|
||||
font-size: 32px;
|
||||
font-family: "Roboto";
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.emi-content > div > h6 {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.top-margin {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.bottom-margin {
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
|
||||
.pie-content {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.pie-content p {
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
font-weight: 500;
|
||||
color: #989CA9;
|
||||
}
|
||||
|
||||
.pie-content .pie-icon {
|
||||
height: 21px;
|
||||
width: 21px;
|
||||
display: inline-block;
|
||||
border-radius: 10px;
|
||||
margin: 0 14px 0 0;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
.pie-content .pie-icon.pie-principal {
|
||||
background: linear-gradient(#3AC8DC, #5B6BC0);
|
||||
}
|
||||
|
||||
.pie-content .pie-icon.pie-interest {
|
||||
background: linear-gradient(#F3A55B, #FB6589);
|
||||
}
|
||||
|
||||
.pie-content h5 {
|
||||
font-size: 18px;
|
||||
font-family: "Roboto";
|
||||
font-weight: 500;
|
||||
color: #F5F5F5;
|
||||
padding: 5px 0 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pie-content > div {
|
||||
margin: 35px 0;
|
||||
}
|
||||
|
||||
.pie-content > div:first-child {
|
||||
margin-top: 43px;
|
||||
}
|
||||
|
||||
.pie-content > div.pie-total p:first-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.pie-content > div.pie-total p + p {
|
||||
font-size: 14px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.center-heading {
|
||||
padding: 10px;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.border-set {
|
||||
border: 1px solid #e4e2e2;
|
||||
}
|
||||
|
||||
.tenure-value {
|
||||
display: flex;
|
||||
padding: 4px 5px 4px 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tenure-value li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.tenure-value .e-radio + label::before {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
.tenure-value .e-radio + label::before, .tenure-value .e-radio + label:hover::before {
|
||||
border-color: #3B9ED4;
|
||||
background-color: #3A4360;
|
||||
}
|
||||
|
||||
.tenure-value .e-radio + label::after, .tenure-value .e-radio + label:hover::after {
|
||||
background-color: #3B9ED4 !important;
|
||||
}
|
||||
|
||||
.tenure-value .e-radio + label .e-label {
|
||||
color: #E7E7E7;
|
||||
font-size: 16px;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tenure-value .e-radio:focus + label::before {
|
||||
border-color: #3B9ED4;
|
||||
background-color: #3A4360;
|
||||
}
|
||||
|
||||
.tenure-value .e-radio:focus + label::after {
|
||||
background-color: #3B9ED4;
|
||||
}
|
||||
|
||||
.tenure-value > li {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.graph-container {
|
||||
height: 520px;
|
||||
padding: 0 33px;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.border-unset-left {
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.border-unset-right {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin-top: 40px;
|
||||
max-width: 1300px;
|
||||
}
|
||||
|
||||
.main-content .loan-content {
|
||||
background-color: #27304c;
|
||||
color: #E7E7E7;
|
||||
}
|
||||
|
||||
.main-content .e-slider-container .e-scale {
|
||||
color: #ABABAB;
|
||||
}
|
||||
|
||||
.main-content .e-slider-container .e-scale .e-tick.e-large {
|
||||
top: 14px;
|
||||
}
|
||||
|
||||
.main-content .e-slider-container .e-scale .e-tick .e-tick-value {
|
||||
font-family: "Roboto";
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
color: #ABABAB;
|
||||
}
|
||||
|
||||
.main-content .e-slider-container .e-slider .e-slider-track {
|
||||
background: #20273E;
|
||||
border-color: #20273E;
|
||||
}
|
||||
|
||||
.main-content .e-slider-container .e-slider .e-handle {
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
top: calc(50% - 13px);
|
||||
margin-left: -13px;
|
||||
}
|
||||
|
||||
.main-content .e-slider-container .e-slider .e-handle::before {
|
||||
content: '';
|
||||
background: #3B9ED4;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
position: absolute;
|
||||
border-radius: 16px;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.main-content .e-slider-container .e-slider .e-range {
|
||||
background-color: #3B9ED4;
|
||||
top: calc(50% - 5px);
|
||||
}
|
||||
|
||||
.main-content .e-slider-container .e-slider .e-slider-track, .main-content .e-slider-container .e-slider .e-range {
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.main-content .e-slider-container .e-slider .e-handle, .main-content .e-slider-container .e-slider .e-slider-track, .main-content .e-slider-container .e-slider .e-range {
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.main-content .e-input-group.e-control-wrapper:not(.e-success):not(.e-warning):not(.e-error) {
|
||||
border-color: #475274;
|
||||
background: #3A4360;
|
||||
}
|
||||
|
||||
.main-content .e-input-group.e-control-wrapper:not(.e-disabled):active:not(.e-success):not(.e-warning):not(.e-error):not(.e-input-focus) {
|
||||
border-color: #404D75 !important;
|
||||
}
|
||||
|
||||
.main-content .e-input-group.e-control-wrapper .e-input-group-icon {
|
||||
background: #3A4360;
|
||||
color: #95979c;
|
||||
border-color: #475274;
|
||||
}
|
||||
|
||||
.main-content .e-input-group.e-control-wrapper .e-input-group-icon:hover {
|
||||
background: #404D75;
|
||||
color: #95979c;
|
||||
}
|
||||
|
||||
.main-content .e-input-group.e-control-wrapper .e-spin-down {
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
.main-content .e-input-group.e-control-wrapper input.e-input {
|
||||
font-family: "Roboto";
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
height: 38px;
|
||||
background-color: #3A4360;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.main-content .graph-text {
|
||||
color: #E7E7E7;
|
||||
font-size: 20px;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.7px;
|
||||
margin: 0 22px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.main-content .graph-input {
|
||||
display: inline-block;
|
||||
margin: 34px 22px;
|
||||
|
||||
}
|
||||
|
||||
.main-content .e-grid {
|
||||
border-color: #27304c;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.main-content .e-grid .e-row {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.main-content .e-grid .e-gridheader {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.main-content .e-grid div.e-icon-grightarrow, .main-content .e-grid div.e-icon-gdownarrow {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
border: 1px solid #fff;
|
||||
margin: auto;
|
||||
text-indent: 0;
|
||||
}
|
||||
|
||||
.main-content .e-grid .e-icon-grightarrow::before, .main-content .e-grid .e-icon-gdownarrow::before {
|
||||
position: absolute;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.main-content .e-grid div.e-icon-grightarrow::before {
|
||||
content: '+';
|
||||
margin: -4px 0 0 -4px;
|
||||
}
|
||||
|
||||
.main-content .e-grid div.e-icon-gdownarrow::before {
|
||||
content: '-';
|
||||
margin: -6px 0 0 -2px;
|
||||
}
|
||||
|
||||
.main-content .e-grid .e-headercelldiv {
|
||||
font-size: 14px;
|
||||
height: 55px;
|
||||
line-height: 55px;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
font-weight: 500;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.main-content .e-grid .e-columnheader {
|
||||
background: linear-gradient(-90deg, #5B6BC0, #3AC8DC);
|
||||
}
|
||||
|
||||
.main-content .e-grid .e-headercell, .main-content .e-grid .e-detailheadercell {
|
||||
background: transparent;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.main-content .e-grid .e-rowcell, .main-content .e-grid .e-detailrowcollapse, .main-content .e-grid .e-detailrowexpand, .main-content .e-grid .e-detailindentcell, .main-content .e-grid .e-detailrow .e-altrow .e-rowcell {
|
||||
background: #27304c;
|
||||
border-width: 0;
|
||||
font-size: 13px;
|
||||
font-family: "Roboto";
|
||||
font-weight: 400;
|
||||
color:"white"
|
||||
}
|
||||
|
||||
.main-content .e-grid .e-altrow .e-rowcell, .main-content .e-grid .e-altrow .e-detailrowcollapse, .main-content .e-grid .e-altrow .e-detailrowexpand {
|
||||
background: #313B5A;
|
||||
}
|
||||
|
||||
.main-content .e-grid .e-icons, .main-content .e-grid .e-row .e-rowcell, .main-content .e-grid .e-detailrowcollapse, .main-content .e-grid .e-detailrowexpand {
|
||||
color: #fff !important ;
|
||||
}
|
||||
|
||||
.main-content .e-grid .e-detailcell {
|
||||
padding: 0;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/* .main-content .e-grid.e-gridhover tr[role='row']:not(.e-editedrow):hover .e-rowcell:not(.e-cellselectionbackground):not(.e-active):not(.e-updatedtd):not(.e-indentcell),
|
||||
.main-content .e-grid.e-gridhover tr[role='row']:hover .e-detailrowcollapse:not(.e-cellselectionbackground):not(.e-active):not(.e-updatedtd):not(.e-indentcell),
|
||||
.main-content .e-grid.e-gridhover tr[role='row']:hover .e-detailrowexpand:not(.e-cellselectionbackground):not(.e-active):not(.e-updatedtd):not(.e-indentcell) {
|
||||
background: #404D75 !important;
|
||||
color: #fff;
|
||||
} */
|
||||
/*
|
||||
.e-detailcell tr[role='row']:hover{
|
||||
background: #404D75 !important;
|
||||
} */
|
||||
|
||||
|
||||
.main-content .e-grid [aria-selected] + tr .e-detailindentcell {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
#control-container {
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
#principal_svg stop {
|
||||
stop-color: #3AC8DC;
|
||||
}
|
||||
|
||||
#principal_svg stop[offset="0"] {
|
||||
stop-color: #3AC8DC;
|
||||
}
|
||||
|
||||
#principal_svg stop[offset="1"] {
|
||||
stop-color: #5B6BC0;
|
||||
}
|
||||
|
||||
#interest_svg stop {
|
||||
stop-color: #F3A55B;
|
||||
}
|
||||
|
||||
#interest_svg stop[offset="0"] {
|
||||
stop-color: #e97c11;
|
||||
}
|
||||
|
||||
#interest_svg stop[offset="1"] {
|
||||
stop-color: #FB6589;
|
||||
}
|
||||
|
||||
.navbar-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.navbar-header {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.flex-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.flex-container .col-lg-4 {
|
||||
width: 33.33333333%;
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
.flex-container .col-lg-4 {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #162036;
|
||||
color: #E7E7E7;
|
||||
}
|
||||
|
||||
.left-content {
|
||||
background-color: #27304c;
|
||||
max-height: 660px;
|
||||
margin: 25px 0;
|
||||
padding: 0 44px;
|
||||
border-right: 1px solid #475274;
|
||||
}
|
||||
|
||||
.header-style {
|
||||
background: #27304c;
|
||||
color: white;
|
||||
margin: 0;
|
||||
padding: 15px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
font-size: 26px;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.margin-setter {
|
||||
margin: 35px;
|
||||
}
|
||||
|
||||
.start-setter {
|
||||
margin: 17px 0;
|
||||
}
|
||||
|
||||
.e-datepicker.e-popup-wrapper {
|
||||
border-color: #475274;
|
||||
background-color: #3A4360;
|
||||
}
|
||||
|
||||
.e-datepicker .e-calendar {
|
||||
background-color: #3A4360;
|
||||
}
|
||||
|
||||
.e-calendar .e-header .e-title, .e-calendar .e-content span, .e-calendar .e-header.e-decade .e-title,
|
||||
.e-calendar .e-header .e-title:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.e-calendar .e-header .e-icon-container span, .e-calendar .e-header .e-prev:hover > span, .e-calendar .e-header .e-next:hover > span,
|
||||
.e-calendar .e-header button.e-prev:active span, .e-calendar .e-header button.e-next:active span {
|
||||
color: #95979c !important;
|
||||
}
|
||||
|
||||
.e-calendar .e-content td.e-selected span.e-day, .e-calendar .e-header .e-prev:active, .e-calendar .e-header .e-next:active {
|
||||
background: #5B6BC0;
|
||||
}
|
||||
|
||||
.e-calendar .e-content.e-decade tr:first-child .e-cell:first-child span.e-day, .e-calendar .e-content.e-decade tr:last-child .e-cell:last-child span.e-day {
|
||||
color: #ABABAB;
|
||||
}
|
||||
|
||||
.e-calendar .e-header .e-prev:hover, .e-calendar .e-header .e-next:hover, .e-calendar .e-content td.e-focused-date span.e-day,
|
||||
.e-calendar .e-content.e-year td:hover span.e-day, .e-calendar .e-content.e-decade td:hover span.e-day,
|
||||
.e-calendar .e-content.e-year td.e-selected:hover span.e-day, .e-calendar .e-content.e-decade td.e-selected:hover span.e-day {
|
||||
background: #404D75;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@media (max-width: 319px) {
|
||||
.container {
|
||||
min-width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.header-style {
|
||||
font-size: 20px;
|
||||
padding: 13px 0;
|
||||
}
|
||||
.container {
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
.container .e-slider-container .e-scale .e-tick .e-tick-value {
|
||||
font-size: 12px;
|
||||
}
|
||||
.top-space {
|
||||
margin: 10px;
|
||||
}
|
||||
.row {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
.left-content-wrap .loan-content:first-child {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.left-content {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-right-width: 0;
|
||||
}
|
||||
.left-content .col-lg-12 {
|
||||
padding: 12px 12px 18px 12px;
|
||||
}
|
||||
.left-content .content-space {
|
||||
margin: 0 0 12px 0;
|
||||
}
|
||||
.left-content .content-space td {
|
||||
display: block;
|
||||
}
|
||||
.left-content .content-space label {
|
||||
font-size: 15px;
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
.left-content .content-space .tenure-value .e-radio + label {
|
||||
margin: 0;
|
||||
}
|
||||
.left-content .content-space .tenure-value .e-radio + label .e-label {
|
||||
font-size: 13px;
|
||||
}
|
||||
.left-content .editor-space {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
.left-content .form-space {
|
||||
margin-bottom: 23px;
|
||||
}
|
||||
.left-content .form-space:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.left-content .e-input-group {
|
||||
width: 100% !important;
|
||||
}
|
||||
.emi-content {
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
.emi-content .emi-header {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
}
|
||||
.tenure-value {
|
||||
padding: 0;
|
||||
float: none;
|
||||
}
|
||||
.emi-content h6 {
|
||||
font-size: 23px;
|
||||
}
|
||||
.emi-content h1 {
|
||||
font-size: 30px;
|
||||
}
|
||||
.emi-content .col-lg-7 {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
.emi-content .col-lg-5 {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
.pie-content div {
|
||||
margin: 10px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.pie-content div:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.pie-content p {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
}
|
||||
.pie-content h5 {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
}
|
||||
.pie-content .pie-total span {
|
||||
display: inline-block;
|
||||
}
|
||||
.pie-content .pie-total p {
|
||||
display: block;
|
||||
}
|
||||
.main-content .loan-content .graph-text {
|
||||
margin: 12px;
|
||||
font-size: 18px;
|
||||
}
|
||||
.main-content .loan-content .graph-input {
|
||||
padding: 0 12px 12px;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
|
||||
}
|
||||
.center-heading {
|
||||
font-size: 18px;
|
||||
}
|
||||
.graph-container {
|
||||
padding: 0 2px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 576px) and (max-width: 991px) {
|
||||
.container {
|
||||
padding: 0 30px;
|
||||
width: 100%;
|
||||
}
|
||||
.left-content-wrap .loan-content {
|
||||
width: 100%;
|
||||
float: left;
|
||||
margin: 0;
|
||||
padding-bottom: 25px;
|
||||
}
|
||||
.left-content-wrap .loan-content + .loan-content {
|
||||
margin-top: 30px;
|
||||
padding-top: 25px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
.left-content {
|
||||
border-right-width: 0;
|
||||
}
|
||||
.emi-content {
|
||||
max-width: 100%;
|
||||
}
|
||||
.emi-content .col-lg-7 {
|
||||
width: 60%;
|
||||
float: left;
|
||||
}
|
||||
.emi-content .col-lg-5 {
|
||||
width: 40%;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.main-content .graph-text {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.main-content .graph-input {
|
||||
margin: 21px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.container {
|
||||
padding: 0 35px;
|
||||
width: 100%;
|
||||
}
|
||||
.left-content-wrap .loan-content {
|
||||
width: 50%;
|
||||
float: left;
|
||||
margin: 0;
|
||||
}
|
||||
.left-content-wrap .loan-content + .loan-content {
|
||||
margin: 0;
|
||||
}
|
||||
.left-content {
|
||||
border-right-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) and (max-width: 1200px) {
|
||||
.left-content {
|
||||
min-width: 450px;
|
||||
padding: 0 20px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.emi-content {
|
||||
max-width: 100%;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.emi-content .col-lg-7 {
|
||||
width: 60%;
|
||||
float: left;
|
||||
}
|
||||
.emi-content .col-lg-5 {
|
||||
width: 40%;
|
||||
float: left;
|
||||
}
|
||||
.emi-content .emi-footer {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.graph-container {
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) and (max-width: 1329px) {
|
||||
.container {
|
||||
padding: 0 35px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1330px) {
|
||||
.container {
|
||||
width: 1300px;
|
||||
}
|
||||
}
|
||||
|
||||
.e-grid#scheduleGrid > .e-gridheader .e-headercontent .e-table colgroup col:first-child,
|
||||
.e-grid .e-content .e-table#scheduleGrid_content_table > colgroup col:first-child {
|
||||
width: 0px !important;
|
||||
|
||||
}
|
||||
|
||||
.e-grid .e-detailrowexpand > div,
|
||||
.e-grid .e-detailrowcollapse > div {
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
.e-grid .e-row .e-row-toggle {
|
||||
display: inline-block;
|
||||
color:white;
|
||||
}
|
||||
|
||||
#payment_pieChartPointHover_Border {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#js-licensing {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.e-childgrid .e-content .e-table{
|
||||
background-color: #27304c;
|
||||
}
|
||||
|
||||
.e-childgrid .e-content .e-table .e-emptyrow{
|
||||
color: #27304c !important;
|
||||
}
|
||||
|
||||
.e-grid .e-content .e-table .e-detailrow{
|
||||
background-color: #27304c ;
|
||||
}
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 6.4 KiB |
|
@ -0,0 +1,13 @@
|
|||
body {
|
||||
margin: 0;
|
||||
/* font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale; */
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
|
||||
const root = ReactDOM.createRoot(
|
||||
document.getElementById('root') as HTMLElement
|
||||
);
|
||||
root.render(
|
||||
<App />
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
|
@ -0,0 +1,2 @@
|
|||
@import "./assets/styles.css";
|
||||
@import "./assets/index.css";
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
Загрузка…
Ссылка в новой задаче