almost done

This commit is contained in:
VyacheslavShtyrlin
2023-02-09 02:09:19 +05:00
parent 08d06a9c71
commit 4399757fa6
11 changed files with 345 additions and 83 deletions
+22
View File
@@ -1,8 +1,30 @@
import logo from "./logo.svg";
import { Main } from "./components/Main/Main";
import "./App.css";
import { useSelector, useDispatch } from "react-redux";
import { calcSlice } from "./store/reducers/calcSlice";
import { calculationSlice } from "./store/reducers/calculationSlice";
import { useEffect } from "react";
function App() {
const state = useSelector((state) => state.calcReducer);
const dispatch = useDispatch();
const { handleCalculation, handleResultUpdated, handleResultDefault } = calculationSlice.actions;
useEffect(() => {
dispatch(
handleCalculation({
squareApartment: state.squareApartment,
priceAvarage: state.priceAvarage,
squareRC: state.squareRC,
consultation: state.consultation,
})
);
dispatch(handleResultUpdated())
dispatch(handleResultDefault())
}, [state]);
return (
<div className="App">
<Main></Main>
@@ -5,7 +5,7 @@ export const AveragePriceApartment = () => {
const { priceAvarage, total } = useSelector((state) => state.calcReducer);
console.log(priceAvarage)
const name = "priceApartment";
const name = "priceAvarage";
const min = 30000;
const max = 200000;
const large = true
+18 -17
View File
@@ -1,20 +1,26 @@
import './InputComponent.css'
import edit from './edit.svg'
import "./InputComponent.css";
import edit from "./edit.svg";
import { useEffect, useState } from "react";
import CurrencyInput from "react-currency-input-field";
import { useDispatch } from "react-redux";
import { calcSlice } from "../../store/reducers/calcSlice";
export const InputComponent = ({ value, name, min, max, inputClass, large }) => {
export const InputComponent = ({
value,
name,
min,
max,
inputClass,
large,
}) => {
const dispatch = useDispatch();
const { handleValue, handleTotal } = calcSlice.actions;
const { handleValue } = calcSlice.actions;
const [valid, setValid] = useState(false);
const [valueInput, setValueInput] = useState(value);
useEffect(() => {
setValueInput(value)
}, [value])
setValueInput(value);
}, [value]);
const handleNumber = (number) => {
if (!number) {
@@ -25,13 +31,9 @@ export const InputComponent = ({ value, name, min, max, inputClass, large }) =>
return num;
};
useEffect(() => {
dispatch(handleTotal());
}, []);
const handleTotalValues = (value, name) => {
dispatch(handleValue({ name: name, value: value }));
dispatch(handleTotal());
const toNum = parseInt(value)
dispatch(handleValue({ name: name, value: toNum }));
};
const handleState = (e) => {
@@ -83,7 +85,6 @@ export const InputComponent = ({ value, name, min, max, inputClass, large }) =>
const handleFocusLeft = (e) => {
const { name, value } = e.target;
const number = handleNumber(value);
console.log(number, value, "valuie");
if (number === 0 && number === undefined) {
handleTotalValues(min, name);
return;
@@ -116,14 +117,14 @@ export const InputComponent = ({ value, name, min, max, inputClass, large }) =>
return (
<>
<div className='number-container'>
<div className="number-container">
<CurrencyInput
className="number-input"
decimalsLimit={3}
allowNegativeValue={false}
allowDecimals={false}
groupSeparator={" "}
style={large ? {width: '78px'} : {width: '45px'}}
style={large ? { width: "78px" } : { width: "45px" }}
min={min}
max={max}
name={name}
@@ -131,7 +132,7 @@ export const InputComponent = ({ value, name, min, max, inputClass, large }) =>
onBlur={(e) => handleFocusLeft(e)}
onValueChange={(value, name) => handleOnValueChange(value, name)}
/>
<img className='edit-icon' alt='edit/изменить' src={edit} />
<img className="edit-icon" alt="edit/изменить" src={edit} />
</div>
<div className="input-container">
+25 -33
View File
@@ -1,37 +1,29 @@
import './InputNumber.css'
import { useEffect } from 'react';
import CurrencyInput from 'react-currency-input-field';
import useFormWithValidation from "../../hooks/useFormWithValidation";
import "./InputNumber.css";
import CurrencyInput from "react-currency-input-field";
import { calcSlice } from "../../store/reducers/calcSlice";
import { useDispatch } from "react-redux";
export const InputNumber = ({ number, handleState }) => {
export const InputNumber = ({ number }) => {
const dispatch = useDispatch();
const { handleValue } = calcSlice.actions;
const { values, handleValidity, resetForm, isTrigger } =
useFormWithValidation(0, 5000);
const onValueChange = (value, name) => {
const toNum = parseInt(value)
dispatch(handleValue({ name: name, value: toNum }));
};
useEffect(() => {
if (isTrigger) {
handleState(prevState => ({ ...prevState, rcNumber: parseInt(values) }))
}
}, [values])
useEffect(() => {
handleValidity(number)
}, [])
return (<div>
<span className="input-number-caption">
Кв. м жилья в жилом комплексе
</span>
<CurrencyInput
value={values}
onValueChange={(value, name) => handleValidity(value)}
className="input-number"
name='squareRC'
decimalSeparator=' '
/>
return (
<div>
<span className="input-number-caption">
Кв. м жилья в жилом комплексе
</span>
<CurrencyInput
value={number}
onValueChange={(value, name) => onValueChange(value, name)}
className="input-number"
name="squareRC"
decimalSeparator=" "
/>
</div>
)
}
);
};
+2 -2
View File
@@ -14,7 +14,7 @@
width: 68%;
background: #1C1D22;
border-radius: 4px;
padding: 56px;
padding: 40px;
box-sizing: border-box;
@@ -27,7 +27,7 @@
gap: 32px;
max-width: 1440px;
margin: 0 auto;
padding-top: 74px;
padding: 40px;
}
.map-main-component {
+15 -19
View File
@@ -3,35 +3,33 @@ import { useEffect } from "react";
import { calcSlice } from "../../store/reducers/calcSlice";
import { useSelector, useDispatch } from "react-redux";
import { InputSelect } from "../InputSelect/InputSelect";
import { InputNumber } from "../InputNumber/InputNumber";
import { AveragePriceApartment } from '../AveragePriceApartment/AveragePriceApartment';
import { AverageSquareApartment } from '../AverageSquareApartment/AverageSquareApartment'
import { AveragePriceApartment } from "../AveragePriceApartment/AveragePriceApartment";
import { AverageSquareApartment } from "../AverageSquareApartment/AverageSquareApartment";
import { ConsultationOffice } from "../ConsultationOffice/ConsultationOffice";
import { ConsultationReserv } from "../ConsultationReserv/ConsultationReserv";
import { Sales } from "../Sales/Sales";
import { ResultBlock } from "../ResultBlock/ResultBlock";
const INITIAL_REGION = "e5b7edfb-17ec-475f-8631-bc796ad19909";
export const Main = ({ }) => {
const dispatch = useDispatch()
const { handleSelectRegion, handleOptions, handleValue } = calcSlice.actions
const { selectedRegion, options, squareRC } = useSelector((state) => state.calcReducer);
export const Main = ({}) => {
const dispatch = useDispatch();
const { handleSelectRegion, handleOptions, handleValue } = calcSlice.actions;
const { selectedRegion, options, squareRC } = useSelector(
(state) => state.calcReducer
);
useEffect(() => {
dispatch(handleSelectRegion(INITIAL_REGION))
dispatch(handleOptions())
}, [])
dispatch(handleSelectRegion(INITIAL_REGION));
dispatch(handleOptions());
}, []);
const handleSelect = (element) => {
dispatch(handleSelectRegion(element.id))
dispatch(handleSelectRegion(element.id));
};
return (
<div className="main">
<div className="input-container-main">
@@ -45,12 +43,10 @@ export const Main = ({ }) => {
<AveragePriceApartment></AveragePriceApartment>
</div>
<div className="input-container-second">
<ConsultationReserv></ConsultationReserv>
<ConsultationOffice></ConsultationOffice>
<ConsultationReserv></ConsultationReserv>
<Sales></Sales>
</div>
<div className="result-block">
<ResultBlock></ResultBlock>
</div>
</div>
);
@@ -0,0 +1,85 @@
.result-container {
display: flex;
flex-direction: column;
gap: 10px;
}
.rub-container {
}
.numbers-container {
display: flex;
align-items: flex-end;
gap: 16px;
}
.result-block {
display: flex;
flex-direction: row;
gap: 46px;
}
.result-number {
font-style: normal;
font-weight: 400;
font-size: 54px;
line-height: 100%;
/* identical to box height, or 58px */
margin: 0;
color: #219653;
}
.result-caption {
font-style: normal;
font-weight: 500;
font-size: 22px;
line-height: 120%;
/* identical to box height, or 29px */
margin: 0;
color: #219653;
}
.result-number_one {
font-style: normal;
font-weight: 400;
font-size: 24px;
line-height: 100%;
/* identical to box height, or 24px */
/* Gray/Accent */
color: #393c46;
}
.result-caption_one {
font-style: normal;
font-weight: 500;
font-size: 10px;
line-height: 120%;
/* identical to box height, or 12px */
/* Gray/Accent */
color: #393c46;
}
.result-diff-caption {
font-style: normal;
font-weight: 400;
font-size: 14px;
line-height: 140%;
/* or 20px */
/* White */
color: #f7f7f7;
}
.diff {
color: #d375ff;
}
.padding {
padding-bottom: 6px;
}
+118
View File
@@ -0,0 +1,118 @@
import "./ResultBlock.css";
import { useSelector } from "react-redux";
export const ResultBlock = () => {
const { timeUpdated, timeDefalut, priceDefault, priceUpdated } = useSelector(
(state) => state.calculationReducer
);
const handleMouthPostifx = (num) => {
num = num % 100;
if (num > 19) {
num = num % 10;
}
switch (num) {
case 1:
return 0;
case 2:
case 3:
case 4:
return 1;
default:
return 2;
}
};
const handleMounth = (num, type) => {
const monthesPostfixes = [" месяц", " месяца", " месяцев"];
let postfix = handleMouthPostifx(num);
let value1 = monthesPostfixes[postfix];
return handleNode(num, value1, type);
};
const shortenNumRu = (num, type) => {
if (isNaN(num)) throw new Error(num + " is not a Number!");
let currency = {
0: "",
1: " тыс. руб.",
2: " млн. руб",
3: " млрд. руб",
};
let thousands = Math.floor((("" + num).length - 1) / 3);
let coef = 1000 ** thousands;
console.log(thousands, "COEF");
let value = (num / coef).toFixed(1);
let value1 = currency[thousands];
return handleNode(value, value1, type);
};
const handleNode = (value, value1, type) => {
if (type === 1) {
return (
<>
<span className="result-number">{value}</span>
<span className="result-caption">{value1}</span>
</>
);
} else if (type === 0) {
return (
<>
<span className="result-number_one">{value}</span>
<span className="result-caption_one">{value1}</span>
</>
);
} else if (type === 3) {
return (
<span className="result-diff-caption">
На <span className="diff">{`${value} ${value1}`}</span> вы сократили
срок реализации проекта
</span>
);
} else {
return (
<span className="result-diff-caption">
На <span className="diff">{`${value} ${value1}`}</span> в месяц вы
заработали больше с помощью нашего инструмента продаж
</span>
);
}
};
return (
<div className="result-block">
<div className="result-container">
<div className="numbers-container">
<div className="rub-container">
{handleMounth(Math.round(timeDefalut), 1)}
</div>
<div className="rub-container padding">
{handleMounth(Math.round(timeUpdated), 0)}
</div>
</div>
<div>
{handleMounth(Math.round(timeDefalut) - Math.round(timeUpdated), 3)}
</div>
</div>
<div className="result-container">
<div className="numbers-container">
<div className="rub-container">
{shortenNumRu(Math.round(priceUpdated), 1)}
</div>
<div className="rub-container padding">
{shortenNumRu(Math.round(priceDefault), 0)}
</div>
</div>
<div>{shortenNumRu(Math.floor(priceUpdated - priceDefault), 4)}</div>
</div>
</div>
);
};
+14 -10
View File
@@ -3,15 +3,16 @@ import { regions } from "../../utils/array";
const initialState = {
squareRC: 1500,
squareApartment: 100,
squareApartment: 45,
priceAvarage: 100000,
consultation: 100,
consultationReserv: 30,
sales: 10,
total: null,
averagePriceApartment: null,
regions: regions,
selectedRegion: {},
options: []
options: [],
averageNumberApartment: null,
};
export const calcSlice = createSlice({
@@ -20,16 +21,18 @@ export const calcSlice = createSlice({
reducers: {
handleOptions(state) {
const options = state.regions.filter((i) => i.name);
return { ...state, options: options }
return { ...state, options: options };
},
handleSelectRegion(state, action) {
console.log(action)
const region = state.regions.find((i) => i.id === action.payload);
return { ...state, selectedRegion: region, priceAvarage: region.price }
return {
...state,
selectedRegion: region,
priceAvarage: parseInt(region.price),
};
},
handleValue(state, action) {
console.log(action.payload.value)
console.log(action.payload.value, "ss");
return { ...state, [action.payload.name]: action.payload.value };
},
handleInitalState(state, action) {
@@ -39,8 +42,9 @@ export const calcSlice = createSlice({
};
},
handleTotal(state) {
const number = Number(state.squareApartment)
state.total = number + 20;
console.log(state.priceAvarage, "price");
state.averagePriceApartment = state.squareApartment * state.priceAvarage;
state.averageNumberApartment = state.squareRC / state.squareApartment;
},
},
});
+43
View File
@@ -0,0 +1,43 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
averageNumberApartment: 0,
averagePriceApartment: 0,
priceDefault: 0,
priceUpdated: 0,
timeDefalut: 0,
timeUpdated: 0,
consultationNumber: 0,
};
export const calculationSlice = createSlice({
name: "calculation",
initialState,
reducers: {
handleCalculation(state, action) {
state.averagePriceApartment =
action.payload.squareApartment * action.payload.priceAvarage;
state.averageNumberApartment =
action.payload.squareRC / action.payload.squareApartment;
state.consultationNumber = action.payload.consultation;
console.log(action.payload);
},
handleResultDefault(state) {
const reserved = (state.consultationNumber / 100) * 30;
const sales = (reserved / 100) * 10;
state.timeDefalut = state.averageNumberApartment / sales;
state.priceDefault = sales * state.averagePriceApartment;
console.log(state.averageNumberApartment, sales, 'reducer')
},
handleResultUpdated(state) {
const reserved = (state.consultationNumber / 100) * 45;
const sales = (reserved / 100) * 20;
state.timeUpdated = state.averageNumberApartment / sales;
state.priceUpdated = sales * state.averagePriceApartment;
},
},
});
export default calculationSlice.reducer;
+2 -1
View File
@@ -1,7 +1,8 @@
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import calcReducer from "./reducers/calcSlice";
import calculationReducer from './reducers/calculationSlice'
const rootReducer = combineReducers({ calcReducer });
const rootReducer = combineReducers({ calcReducer, calculationReducer});
export const setupStore = () => {
return configureStore({