adaptive personal to mobile / fix calculator
This commit is contained in:
@ -30,12 +30,12 @@ function CalculatorPage() {
|
||||
|
||||
// Состояния для полей формы
|
||||
const [country, setCountry] = useState("russia"); // russia или belarus
|
||||
const [age, setAge] = useState("3"); // Изменено на числовое значение для упрощения расчетов
|
||||
const [age, setAge] = useState("<3"); // Изменено на числовое значение для упрощения расчетов
|
||||
const [price, setPrice] = useState("");
|
||||
const [currency, setCurrency] = useState("USD Доллар США");
|
||||
const [engineType, setEngineType] = useState("Бензиновый");
|
||||
const [hybridType, setHybridType] = useState("Не гибрид");
|
||||
const [engineVolume, setEngineVolume] = useState("");
|
||||
const [engineVolume, setEngineVolume] = useState("2000");
|
||||
const [enginePower, setEnginePower] = useState("");
|
||||
const [enginePowerUnit, setEnginePowerUnit] = useState("л.с.");
|
||||
const [electricMotorPower, setElectricMotorPower] = useState("");
|
||||
@ -79,225 +79,403 @@ function CalculatorPage() {
|
||||
loadCurrencyRates();
|
||||
}, []);
|
||||
|
||||
// const handleCalculate = () => {
|
||||
// const calculatorResults = document.getElementById("calculator-results");
|
||||
// if (calculatorResults) {
|
||||
// calculatorResults.scrollIntoView({ behavior: "smooth" });
|
||||
// }
|
||||
// // Получаем курс выбранной валюты
|
||||
// const currencyCode = mapCurrencyCodeToApiCode(currency);
|
||||
// const exchangeRate =
|
||||
// currencyCode === "RUB" ? 1 : getCurrencyRate(currencyRates, currencyCode);
|
||||
|
||||
// // Конвертация цены в рубли для расчета
|
||||
// let priceInRub = parseFloat(price) || 0;
|
||||
|
||||
// // Конвертация из валюты пользователя в рубли
|
||||
// if (currencyCode !== "RUB") {
|
||||
// priceInRub *= exchangeRate;
|
||||
// }
|
||||
|
||||
// // Минимальная стоимость для расчета (устанавливается таможней)
|
||||
// const eurRate = getCurrencyRate(currencyRates, "EUR");
|
||||
// const minCustomValue = 8500 * eurRate; // минимальная стоимость в рублях (8500 евро)
|
||||
// const calculationValue = Math.max(priceInRub, minCustomValue);
|
||||
|
||||
// let customDuty = 0;
|
||||
// let exciseTax = 0;
|
||||
// let vat = 0;
|
||||
// let utilityFee = 0;
|
||||
// let totalFees = 0;
|
||||
|
||||
// // Расчет для физических лиц
|
||||
// if (calculationType === "Физ. лица") {
|
||||
// // Коэффициент для возраста
|
||||
// let ageCoef = 1;
|
||||
// switch (age) {
|
||||
// case "3": // менее 3 лет
|
||||
// ageCoef = 0.54; // 54% от стоимости
|
||||
// break;
|
||||
// case "3-5": // от 3 до 5 лет
|
||||
// ageCoef = 0.48; // 48% от стоимости
|
||||
// break;
|
||||
// case "5+": // более 5 лет
|
||||
// ageCoef = 0.48; // 48% от стоимости (но не менее 2.5 евро/см3)
|
||||
// break;
|
||||
// default:
|
||||
// ageCoef = 0.54;
|
||||
// }
|
||||
|
||||
// // Расчет пошлины для ДВС
|
||||
// if (engineType === "Бензиновый" || engineType === "Дизельный") {
|
||||
// const engineVolumeNum = parseFloat(engineVolume) || 0;
|
||||
|
||||
// let engineVolumeCoefficient = 1.0;
|
||||
// if (age === "3-5") {
|
||||
// if (engineVolumeNum <= 1000) {
|
||||
// engineVolumeCoefficient = 1.5;
|
||||
// } else if (engineVolumeNum <= 1500) {
|
||||
// engineVolumeCoefficient = 1.7;
|
||||
// } else if (engineVolumeNum <= 1800) {
|
||||
// engineVolumeCoefficient = 2.5;
|
||||
// } else if (engineVolumeNum <= 2300) {
|
||||
// engineVolumeCoefficient = 2.7;
|
||||
// } else if (engineVolumeNum <= 3000) {
|
||||
// engineVolumeCoefficient = 3.0;
|
||||
// } else if (engineVolumeNum > 3000) {
|
||||
// engineVolumeCoefficient = 3.6;
|
||||
// }
|
||||
// }
|
||||
|
||||
// const engineVolumeDuty = engineVolumeCoefficient * engineVolumeNum * eurRate;
|
||||
|
||||
// // Для авто менее 3 лет
|
||||
// if (age === "<3") {
|
||||
// const percentDuty = calculationValue * 0.54;
|
||||
// customDuty = Math.max(engineVolumeDuty, percentDuty);
|
||||
// }
|
||||
// // Для авто 3-5 лет
|
||||
// else if (age === "3-5") {
|
||||
// customDuty = engineVolumeDuty;
|
||||
// }
|
||||
// // Для авто старше 5 лет
|
||||
// else if (age === "5-10" || age === ">10") {
|
||||
// const ageCoefficient = 1.3; // Например, для 5-10 лет
|
||||
// customDuty = engineVolumeCoefficient * engineVolumeNum * eurRate * ageCoefficient;
|
||||
// }
|
||||
|
||||
// // Акцизы в зависимости от мощности
|
||||
// const enginePowerNum = parseFloat(enginePower) || 0;
|
||||
// let powerInHP = enginePowerNum;
|
||||
|
||||
// if (enginePowerUnit === "кВт") {
|
||||
// powerInHP = enginePowerNum * 1.35962;
|
||||
// }
|
||||
|
||||
// let ageCoefficient = 1.0;
|
||||
// if (age === "3-5") {
|
||||
// ageCoefficient = 1.1;
|
||||
// } else if (age === "5-10") {
|
||||
// ageCoefficient = 1.3;
|
||||
// } else if (age === ">10") {
|
||||
// ageCoefficient = 1.5;
|
||||
// }
|
||||
|
||||
// // Акцизные ставки на 2024 год (в рублях за 1 л.с.)
|
||||
// if (powerInHP <= 90) {
|
||||
// exciseTax = powerInHP * 0 * ageCoefficient;
|
||||
// } else if (powerInHP <= 150) {
|
||||
// exciseTax = powerInHP * 54 * ageCoefficient;
|
||||
// } else if (powerInHP <= 200) {
|
||||
// exciseTax = powerInHP * 714 * ageCoefficient;
|
||||
// } else if (powerInHP <= 300) {
|
||||
// exciseTax = powerInHP * 1218 * ageCoefficient;
|
||||
// } else if (powerInHP <= 400) {
|
||||
// exciseTax = powerInHP * 1260 * ageCoefficient;
|
||||
// } else if (powerInHP <= 500) {
|
||||
// exciseTax = powerInHP * 1302 * ageCoefficient;
|
||||
// } else if (powerInHP > 500) {
|
||||
// exciseTax = powerInHP * 1374 * ageCoefficient;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Для электромобилей
|
||||
// else if (engineType === "Электрический") {
|
||||
// customDuty = 0; // Пошлина 0% для электромобилей
|
||||
// exciseTax = 0; // Акциз 0 для электромобилей
|
||||
// }
|
||||
|
||||
// // Для гибридов
|
||||
// else if (engineType === "Гибридный") {
|
||||
// // Для гибридов применяются те же ставки, что и для ДВС
|
||||
// const engineVolumeNum = parseFloat(engineVolume) || 0;
|
||||
|
||||
// if (age === "3") {
|
||||
// customDuty = calculationValue * 0.54;
|
||||
// } else if (age === "3-5") {
|
||||
// customDuty = calculationValue * 0.48;
|
||||
// } else {
|
||||
// const dutyPerCm3 = 2.5; // евро за см3
|
||||
// const dutyInEur = engineVolumeNum * dutyPerCm3;
|
||||
// customDuty = dutyInEur * eurRate;
|
||||
// customDuty = Math.max(customDuty, calculationValue * 0.48);
|
||||
// }
|
||||
|
||||
// // Акциз для гибридов рассчитывается так же, как для ДВС
|
||||
// const enginePowerNum = parseFloat(enginePower) || 0;
|
||||
// let powerInHP = enginePowerNum;
|
||||
|
||||
// if (enginePowerUnit === "кВт") {
|
||||
// powerInHP = enginePowerNum * 1.35962;
|
||||
// }
|
||||
|
||||
// let ageCoefficient = 1.0;
|
||||
// if (age === "3-5") {
|
||||
// ageCoefficient = 1.1;
|
||||
// } else if (age === "5-10") {
|
||||
// ageCoefficient = 1.3;
|
||||
// } else if (age === ">10") {
|
||||
// ageCoefficient = 1.5;
|
||||
// }
|
||||
|
||||
// if (powerInHP <= 90) {
|
||||
// exciseTax = powerInHP * 0 * ageCoefficient;
|
||||
// } else if (powerInHP <= 150) {
|
||||
// exciseTax = powerInHP * 54 * ageCoefficient;
|
||||
// } else if (powerInHP <= 200) {
|
||||
// exciseTax = powerInHP * 714 * ageCoefficient;
|
||||
// } else if (powerInHP <= 300) {
|
||||
// exciseTax = powerInHP * 1218 * ageCoefficient;
|
||||
// } else if (powerInHP <= 400) {
|
||||
// exciseTax = powerInHP * 1260 * ageCoefficient;
|
||||
// } else if (powerInHP <= 500) {
|
||||
// exciseTax = powerInHP * 1302 * ageCoefficient;
|
||||
// } else if (powerInHP > 500) {
|
||||
// exciseTax = powerInHP * 1374 * ageCoefficient;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // НДС 20% от (стоимость + пошлина + акциз)
|
||||
// vat = (calculationValue + customDuty + exciseTax) * 0.2;
|
||||
|
||||
// // Утилизационный сбор
|
||||
// if (engineType === "Электрический") {
|
||||
// utilityFee = 3400; // Для электромобилей
|
||||
// } else {
|
||||
// utilityFee = enhancedPermeability ? 27000 : 3400; // Для внедорожников выше
|
||||
// }
|
||||
// }
|
||||
// // Расчет для юридических лиц
|
||||
// else {
|
||||
// // Здесь должна быть другая логика расчета для юр.лиц
|
||||
// // В данном примере используем упрощенный расчет, аналогичный физ.лицам
|
||||
// customDuty = calculationValue * 0.12; // Примерная ставка для юр.лиц
|
||||
|
||||
// // Акцизы в зависимости от мощности
|
||||
// const enginePowerNum = parseFloat(enginePower) || 0;
|
||||
// let powerInHP = enginePowerNum;
|
||||
|
||||
// if (enginePowerUnit === "кВт") {
|
||||
// powerInHP = enginePowerNum * 1.35962;
|
||||
// }
|
||||
|
||||
// // Акцизные ставки для юр.лиц могут отличаться
|
||||
// if (powerInHP <= 90) {
|
||||
// exciseTax = powerInHP * 0;
|
||||
// } else if (powerInHP <= 150) {
|
||||
// exciseTax = powerInHP * 55;
|
||||
// } else {
|
||||
// exciseTax = powerInHP * 531;
|
||||
// }
|
||||
|
||||
// // НДС 20%
|
||||
// vat = (calculationValue + customDuty + exciseTax) * 0.2;
|
||||
|
||||
// // Утилизационный сбор для юр.лиц
|
||||
// utilityFee = engineType === "Электрический" ? 3500 : 5000;
|
||||
// }
|
||||
|
||||
// // Итоговая сумма таможенных платежей
|
||||
// totalFees = customDuty + exciseTax + vat + utilityFee;
|
||||
|
||||
// // Сохраняем результаты расчетов
|
||||
// const results = {
|
||||
// priceInRub: priceInRub.toFixed(2),
|
||||
// customDuty: customDuty.toFixed(2),
|
||||
// exciseTax: exciseTax.toFixed(2),
|
||||
// vat: vat.toFixed(2),
|
||||
// utilityFee: utilityFee.toFixed(2),
|
||||
// totalFees: totalFees.toFixed(2),
|
||||
// totalWithCar: (priceInRub + totalFees).toFixed(2),
|
||||
// };
|
||||
|
||||
// setCalculationResults(results);
|
||||
|
||||
// // После расчетов установить флаг анимации
|
||||
// setSlideIn(true);
|
||||
|
||||
// // Выводим результаты также в консоль для отладки
|
||||
// console.log({
|
||||
// original: {
|
||||
// price,
|
||||
// currency,
|
||||
// currencyRate: exchangeRate,
|
||||
// country,
|
||||
// age,
|
||||
// engineType,
|
||||
// hybridType,
|
||||
// engineVolume,
|
||||
// enginePower,
|
||||
// enginePowerUnit,
|
||||
// electricMotorPower,
|
||||
// electricMotorPowerUnit,
|
||||
// powerRatio,
|
||||
// calculationType,
|
||||
// enhancedPermeability,
|
||||
// },
|
||||
// calculation: results,
|
||||
// });
|
||||
// };
|
||||
|
||||
const handleCalculate = () => {
|
||||
const calculatorResults = document.getElementById("calculator-results");
|
||||
if (calculatorResults) {
|
||||
calculatorResults.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
// Получаем курс выбранной валюты
|
||||
const currencyCode = mapCurrencyCodeToApiCode(currency);
|
||||
const exchangeRate =
|
||||
currencyCode === "RUB" ? 1 : getCurrencyRate(currencyRates, currencyCode);
|
||||
const calculatorResults = document.getElementById("calculator-results");
|
||||
if (calculatorResults) {
|
||||
calculatorResults.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
|
||||
// Конвертация цены в рубли для расчета
|
||||
let priceInRub = parseFloat(price) || 0;
|
||||
// Получаем курс валют
|
||||
const currencyCode = mapCurrencyCodeToApiCode(currency);
|
||||
const exchangeRate = currencyCode === "RUB" ? 1 : getCurrencyRate(currencyRates, currencyCode);
|
||||
const eurRate = getCurrencyRate(currencyRates, "EUR");
|
||||
|
||||
// Конвертация из валюты пользователя в рубли
|
||||
if (currencyCode !== "RUB") {
|
||||
priceInRub *= exchangeRate;
|
||||
// Конвертация цены в рубли
|
||||
let priceInRub = parseFloat(price) || 0;
|
||||
if (currencyCode !== "RUB") {
|
||||
priceInRub *= exchangeRate;
|
||||
}
|
||||
|
||||
// Инициализация переменных
|
||||
let customDuty = 0;
|
||||
let exciseTax = 0;
|
||||
let vat = 0;
|
||||
let utilityFee = 0;
|
||||
let totalFees = 0;
|
||||
|
||||
// Расчет только для физ. лиц
|
||||
if (calculationType === "Физ. лица") {
|
||||
const engineVolumeNum = parseFloat(engineVolume) || 0;
|
||||
const enginePowerNum = parseFloat(enginePower) || 0;
|
||||
let powerInHP = enginePowerUnit === "кВт" ? enginePowerNum * 1.35962 : enginePowerNum;
|
||||
|
||||
// Корректировка стоимости только для авто до 3 лет
|
||||
let calculationValue = priceInRub;
|
||||
if (age === "<3") {
|
||||
const minCustomValue = 8500 * eurRate;
|
||||
calculationValue = Math.max(priceInRub, minCustomValue);
|
||||
}
|
||||
|
||||
// Минимальная стоимость для расчета (устанавливается таможней)
|
||||
const eurRate = getCurrencyRate(currencyRates, "EUR");
|
||||
const minCustomValue = 8500 * eurRate; // минимальная стоимость в рублях (8500 евро)
|
||||
const calculationValue = Math.max(priceInRub, minCustomValue);
|
||||
|
||||
let customDuty = 0;
|
||||
let exciseTax = 0;
|
||||
let vat = 0;
|
||||
let utilityFee = 0;
|
||||
let totalFees = 0;
|
||||
|
||||
// Расчет для физических лиц
|
||||
if (calculationType === "Физ. лица") {
|
||||
// Коэффициент для возраста
|
||||
let ageCoef = 1;
|
||||
switch (age) {
|
||||
case "3": // менее 3 лет
|
||||
ageCoef = 0.54; // 54% от стоимости
|
||||
break;
|
||||
case "3-5": // от 3 до 5 лет
|
||||
ageCoef = 0.48; // 48% от стоимости
|
||||
break;
|
||||
case "5+": // более 5 лет
|
||||
ageCoef = 0.48; // 48% от стоимости (но не менее 2.5 евро/см3)
|
||||
break;
|
||||
default:
|
||||
ageCoef = 0.54;
|
||||
}
|
||||
|
||||
// Расчет пошлины для ДВС
|
||||
if (engineType === "Бензиновый" || engineType === "Дизельный") {
|
||||
const engineVolumeNum = parseFloat(engineVolume) || 0;
|
||||
|
||||
// Для авто менее 3 лет
|
||||
if (age === "3") {
|
||||
customDuty = calculationValue * 0.54; // 54% от стоимости
|
||||
}
|
||||
// Для авто 3-5 лет
|
||||
else if (age === "3-5") {
|
||||
customDuty = calculationValue * 0.48; // 48% от стоимости
|
||||
}
|
||||
// Для авто старше 5 лет
|
||||
else {
|
||||
const dutyPerCm3 = 2.5; // евро за см3
|
||||
const dutyInEur = engineVolumeNum * dutyPerCm3;
|
||||
customDuty = dutyInEur * eurRate; // переводим в рубли по курсу евро
|
||||
// Берем максимум между процентом и фиксированной ставкой
|
||||
customDuty = Math.max(customDuty, calculationValue * 0.48);
|
||||
}
|
||||
|
||||
// Акцизы в зависимости от мощности
|
||||
const enginePowerNum = parseFloat(enginePower) || 0;
|
||||
let powerInHP = enginePowerNum;
|
||||
|
||||
if (enginePowerUnit === "кВт") {
|
||||
powerInHP = enginePowerNum * 1.35962;
|
||||
}
|
||||
|
||||
// Акцизные ставки на 2024 год (в рублях за 1 л.с.)
|
||||
if (powerInHP <= 90) {
|
||||
exciseTax = powerInHP * 0;
|
||||
} else if (powerInHP <= 150) {
|
||||
exciseTax = powerInHP * 53;
|
||||
} else if (powerInHP <= 200) {
|
||||
exciseTax = powerInHP * 511;
|
||||
} else if (powerInHP <= 300) {
|
||||
exciseTax = powerInHP * 836;
|
||||
} else if (powerInHP <= 400) {
|
||||
exciseTax = powerInHP * 1425;
|
||||
} else {
|
||||
exciseTax = powerInHP * 1475;
|
||||
}
|
||||
}
|
||||
|
||||
// Для электромобилей
|
||||
else if (engineType === "Электрический") {
|
||||
customDuty = 0; // Пошлина 0% для электромобилей
|
||||
exciseTax = 0; // Акциз 0 для электромобилей
|
||||
}
|
||||
|
||||
// Для гибридов
|
||||
else if (engineType === "Гибридный") {
|
||||
// Для гибридов применяются те же ставки, что и для ДВС
|
||||
const engineVolumeNum = parseFloat(engineVolume) || 0;
|
||||
|
||||
if (age === "3") {
|
||||
customDuty = calculationValue * 0.54;
|
||||
} else if (age === "3-5") {
|
||||
customDuty = calculationValue * 0.48;
|
||||
} else {
|
||||
const dutyPerCm3 = 2.5; // евро за см3
|
||||
const dutyInEur = engineVolumeNum * dutyPerCm3;
|
||||
customDuty = dutyInEur * eurRate;
|
||||
customDuty = Math.max(customDuty, calculationValue * 0.48);
|
||||
}
|
||||
|
||||
// Акциз для гибридов рассчитывается так же, как для ДВС
|
||||
const enginePowerNum = parseFloat(enginePower) || 0;
|
||||
let powerInHP = enginePowerNum;
|
||||
|
||||
if (enginePowerUnit === "кВт") {
|
||||
powerInHP = enginePowerNum * 1.35962;
|
||||
}
|
||||
|
||||
if (powerInHP <= 90) {
|
||||
exciseTax = powerInHP * 0;
|
||||
} else if (powerInHP <= 150) {
|
||||
exciseTax = powerInHP * 53;
|
||||
} else if (powerInHP <= 200) {
|
||||
exciseTax = powerInHP * 511;
|
||||
} else if (powerInHP <= 300) {
|
||||
exciseTax = powerInHP * 836;
|
||||
} else if (powerInHP <= 400) {
|
||||
exciseTax = powerInHP * 1425;
|
||||
} else {
|
||||
exciseTax = powerInHP * 1475;
|
||||
}
|
||||
}
|
||||
|
||||
// НДС 20% от (стоимость + пошлина + акциз)
|
||||
vat = (calculationValue + customDuty + exciseTax) * 0.2;
|
||||
|
||||
// Утилизационный сбор
|
||||
if (engineType === "Электрический") {
|
||||
utilityFee = 3400; // Для электромобилей
|
||||
} else {
|
||||
utilityFee = enhancedPermeability ? 27000 : 3400; // Для внедорожников выше
|
||||
}
|
||||
// Расчет пошлины
|
||||
if (engineType === "Электрический") {
|
||||
customDuty = 0;
|
||||
}
|
||||
// Расчет для юридических лиц
|
||||
else {
|
||||
// Здесь должна быть другая логика расчета для юр.лиц
|
||||
// В данном примере используем упрощенный расчет, аналогичный физ.лицам
|
||||
customDuty = calculationValue * 0.12; // Примерная ставка для юр.лиц
|
||||
|
||||
// Акцизы в зависимости от мощности
|
||||
const enginePowerNum = parseFloat(enginePower) || 0;
|
||||
let powerInHP = enginePowerNum;
|
||||
|
||||
if (enginePowerUnit === "кВт") {
|
||||
powerInHP = enginePowerNum * 1.35962;
|
||||
// Для ДВС и гибридов
|
||||
if (age === "<3") {
|
||||
const percentDuty = priceInRub * 0.54;
|
||||
const volumeDuty = engineVolumeNum * 2.5 * eurRate;
|
||||
customDuty = Math.max(percentDuty, volumeDuty);
|
||||
}
|
||||
else if (age === "3-5") {
|
||||
// Ставки для авто 3-5 лет
|
||||
let rate;
|
||||
if (engineVolumeNum <= 1000) rate = 1.5;
|
||||
else if (engineVolumeNum <= 1500) rate = 1.7;
|
||||
else if (engineVolumeNum <= 1800) rate = 2.5;
|
||||
else if (engineVolumeNum <= 2300) rate = 2.7;
|
||||
else if (engineVolumeNum <= 3000) rate = 3.0;
|
||||
else rate = 3.6;
|
||||
|
||||
// Акцизные ставки для юр.лиц могут отличаться
|
||||
if (powerInHP <= 90) {
|
||||
exciseTax = powerInHP * 0;
|
||||
} else if (powerInHP <= 150) {
|
||||
exciseTax = powerInHP * 55;
|
||||
} else {
|
||||
exciseTax = powerInHP * 531;
|
||||
customDuty = engineVolumeNum * rate * eurRate;
|
||||
}
|
||||
else {
|
||||
// Ставки для авто старше 5 лет
|
||||
let rate;
|
||||
if (engineVolumeNum <= 1000) rate = 3.0;
|
||||
else if (engineVolumeNum <= 1500) rate = 3.2;
|
||||
else if (engineVolumeNum <= 1800) rate = 3.5;
|
||||
else if (engineVolumeNum <= 2300) rate = 4.8;
|
||||
else if (engineVolumeNum <= 3000) rate = 5.0;
|
||||
else rate = 5.7;
|
||||
|
||||
// НДС 20%
|
||||
vat = (calculationValue + customDuty + exciseTax) * 0.2;
|
||||
|
||||
// Утилизационный сбор для юр.лиц
|
||||
utilityFee = engineType === "Электрический" ? 3500 : 5000;
|
||||
const ageCoef = age === "5-10" ? 1.3 : 1.5;
|
||||
customDuty = engineVolumeNum * rate * eurRate * ageCoef;
|
||||
}
|
||||
}
|
||||
|
||||
// Итоговая сумма таможенных платежей
|
||||
totalFees = customDuty + exciseTax + vat + utilityFee;
|
||||
// Расчет акциза (только для ДВС и гибридов)
|
||||
if (engineType !== "Электрический") {
|
||||
let ageCoefficient = 1.0;
|
||||
if (age === "3-5") ageCoefficient = 1.1;
|
||||
else if (age === "5-10") ageCoefficient = 1.3;
|
||||
else if (age === ">10") ageCoefficient = 1.5;
|
||||
|
||||
// Сохраняем результаты расчетов
|
||||
const results = {
|
||||
priceInRub: priceInRub.toFixed(2),
|
||||
customDuty: customDuty.toFixed(2),
|
||||
exciseTax: exciseTax.toFixed(2),
|
||||
vat: vat.toFixed(2),
|
||||
utilityFee: utilityFee.toFixed(2),
|
||||
totalFees: totalFees.toFixed(2),
|
||||
totalWithCar: (priceInRub + totalFees).toFixed(2),
|
||||
};
|
||||
if (powerInHP <= 90) {
|
||||
exciseTax = 0;
|
||||
} else if (powerInHP <= 150) {
|
||||
exciseTax = powerInHP * 54 * ageCoefficient;
|
||||
} else if (powerInHP <= 200) {
|
||||
exciseTax = powerInHP * 714 * ageCoefficient;
|
||||
} else if (powerInHP <= 300) {
|
||||
exciseTax = powerInHP * 1218 * ageCoefficient;
|
||||
} else if (powerInHP <= 400) {
|
||||
exciseTax = powerInHP * 1260 * ageCoefficient;
|
||||
} else if (powerInHP <= 500) {
|
||||
exciseTax = powerInHP * 1302 * ageCoefficient;
|
||||
} else {
|
||||
exciseTax = powerInHP * 1374 * ageCoefficient;
|
||||
}
|
||||
}
|
||||
|
||||
setCalculationResults(results);
|
||||
// НДС 20%
|
||||
vat = (calculationValue + customDuty + exciseTax) * 0.2;
|
||||
|
||||
// После расчетов установить флаг анимации
|
||||
setSlideIn(true);
|
||||
// Утилизационный сбор
|
||||
utilityFee = engineType === "Электрический" ? 0 :
|
||||
enhancedPermeability ? 27000 : 3400;
|
||||
}
|
||||
|
||||
// Выводим результаты также в консоль для отладки
|
||||
console.log({
|
||||
original: {
|
||||
price,
|
||||
currency,
|
||||
currencyRate: exchangeRate,
|
||||
country,
|
||||
age,
|
||||
engineType,
|
||||
hybridType,
|
||||
engineVolume,
|
||||
enginePower,
|
||||
enginePowerUnit,
|
||||
electricMotorPower,
|
||||
electricMotorPowerUnit,
|
||||
powerRatio,
|
||||
calculationType,
|
||||
enhancedPermeability,
|
||||
},
|
||||
calculation: results,
|
||||
});
|
||||
// Итоговые расчеты
|
||||
totalFees = customDuty + exciseTax + vat + utilityFee;
|
||||
|
||||
// Округление до целых рублей
|
||||
const round = (value) => Math.round(value);
|
||||
|
||||
// Сохранение результатов
|
||||
const results = {
|
||||
priceInRub: round(priceInRub),
|
||||
customDuty: round(customDuty),
|
||||
exciseTax: round(exciseTax),
|
||||
vat: round(vat),
|
||||
utilityFee: round(utilityFee),
|
||||
totalFees: round(totalFees),
|
||||
totalWithCar: round(priceInRub + totalFees),
|
||||
};
|
||||
|
||||
setCalculationResults(results);
|
||||
setSlideIn(true);
|
||||
|
||||
// Логирование для отладки
|
||||
console.log({
|
||||
input: {
|
||||
price, currency, age, engineType,
|
||||
engineVolume, enginePower, enginePowerUnit,
|
||||
calculationType, enhancedPermeability
|
||||
},
|
||||
calculation: results,
|
||||
rates: { eurRate, exchangeRate }
|
||||
});
|
||||
};
|
||||
|
||||
// Функция для получения символа валюты
|
||||
const getCurrencySymbol = () => {
|
||||
switch (currency) {
|
||||
@ -538,9 +716,10 @@ function CalculatorPage() {
|
||||
displayEmpty
|
||||
sx={selectStyles}
|
||||
>
|
||||
<MenuItem value="3">Менее 3х лет</MenuItem>
|
||||
<MenuItem value="<3">Менее 3х лет</MenuItem>
|
||||
<MenuItem value="3-5">3-5 лет</MenuItem>
|
||||
<MenuItem value="5+">5+ лет</MenuItem>
|
||||
<MenuItem value="5-10">5-10 лет</MenuItem>
|
||||
<MenuItem value=">10">10+ лет</MenuItem>
|
||||
</Select>
|
||||
</Box>
|
||||
|
||||
|
@ -42,6 +42,7 @@ import PersonIcon from '@mui/icons-material/Person';
|
||||
import BadgeIcon from '@mui/icons-material/Badge';
|
||||
import WorkIcon from '@mui/icons-material/Work';
|
||||
import { useAuth } from '../../context/AuthContext';
|
||||
import { useResponsive } from "../../theme/useResponsive";
|
||||
import {
|
||||
fetchTeam,
|
||||
createTeamMember,
|
||||
@ -66,6 +67,7 @@ interface TeamResponse {
|
||||
|
||||
const Personal = () => {
|
||||
const { token } = useAuth();
|
||||
const { isMobile } = useResponsive();
|
||||
const [staff, setStaff] = useState<TeamMember[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState('');
|
||||
@ -246,8 +248,8 @@ const Personal = () => {
|
||||
component={Paper}
|
||||
elevation={3}
|
||||
sx={{
|
||||
borderRadius: 2,
|
||||
overflow: 'hidden'
|
||||
borderRadius: isMobile ? "2vw" : "1vw",
|
||||
overflow: isMobile ? "scroll" : "hidden"
|
||||
}}
|
||||
>
|
||||
<Table>
|
||||
@ -278,9 +280,9 @@ const Personal = () => {
|
||||
src={getImageUrl(member.photo)}
|
||||
alt={`${member.name} ${member.surname}`}
|
||||
sx={{
|
||||
width: 56,
|
||||
height: 56,
|
||||
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
|
||||
width: isMobile ? "15vw" : 56,
|
||||
height: isMobile ? "15vw" : 56,
|
||||
boxShadow: '0 0.2vw 0.4vw rgba(0,0,0,0.1)'
|
||||
}}
|
||||
>
|
||||
{getInitials(member.name, member.surname)}
|
||||
@ -302,11 +304,13 @@ const Personal = () => {
|
||||
onClick={() => handleOpenEditDialog(member)}
|
||||
color="primary"
|
||||
sx={{
|
||||
bgcolor: 'rgba(25, 118, 210, 0.1)',
|
||||
mr: 1,
|
||||
'&:hover': {
|
||||
bgcolor: 'rgba(25, 118, 210, 0.2)',
|
||||
}
|
||||
color: "black",
|
||||
"&:hover": {
|
||||
color: "#C27664",
|
||||
bgcolor: "transparent",
|
||||
},
|
||||
transition: "all 0.2s ease",
|
||||
mr: 1
|
||||
}}
|
||||
>
|
||||
<EditIcon />
|
||||
@ -317,10 +321,11 @@ const Personal = () => {
|
||||
onClick={() => handleOpenDeleteDialog(member)}
|
||||
color="error"
|
||||
sx={{
|
||||
bgcolor: 'rgba(211, 47, 47, 0.1)',
|
||||
'&:hover': {
|
||||
bgcolor: 'rgba(211, 47, 47, 0.2)',
|
||||
}
|
||||
"&:hover": {
|
||||
color: "#C27664",
|
||||
bgcolor: "transparent",
|
||||
},
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
@ -336,7 +341,7 @@ const Personal = () => {
|
||||
|
||||
// Рендер сетки карточек
|
||||
const renderGrid = () => (
|
||||
<Grid container spacing={3}>
|
||||
<Grid container spacing={3} style={{ justifyContent: isMobile ? "center" : "auto" }}>
|
||||
{filteredStaff.map((member) => (
|
||||
<Grid item xs={12} sm={6} md={4} lg={3} key={member.id}>
|
||||
<Card
|
||||
@ -345,11 +350,12 @@ const Personal = () => {
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
borderRadius: 2,
|
||||
transition: 'transform 0.3s, box-shadow 0.3s',
|
||||
'&:hover': {
|
||||
transform: 'translateY(-5px)',
|
||||
boxShadow: '0 10px 20px rgba(0,0,0,0.1)'
|
||||
borderRadius: isMobile ? "5vw" : "1vw",
|
||||
transition: "transform 0.3s, box-shadow 0.3s",
|
||||
boxShadow: "0 0.5vw 1vw rgba(0,0,0,0.15)",
|
||||
"&:hover": {
|
||||
transform: "translateY(-0.2vw)",
|
||||
boxShadow: "0 0.5vw 1vw rgba(0,0,0,0.1)",
|
||||
}
|
||||
}}
|
||||
>
|
||||
@ -364,12 +370,19 @@ const Personal = () => {
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'cover'
|
||||
objectFit: 'cover',
|
||||
userSelect: "none",
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<CardContent sx={{ flexGrow: 1, pt: 2 }}>
|
||||
<Typography gutterBottom variant="h6" component="div" sx={{ fontWeight: 'bold', mb: 0.5 }}>
|
||||
<CardContent sx={{ flexGrow: 1, pt: isMobile ? "3vw" : "2vw" }}>
|
||||
<Typography gutterBottom variant="h6" component="div" sx={{
|
||||
fontWeight: "bold",
|
||||
mb: "0.5vw",
|
||||
fontFamily: "Unbounded",
|
||||
fontSize: isMobile ? "4vw" : "1.2vw"
|
||||
}}>
|
||||
{member.name} {member.surname}
|
||||
</Typography>
|
||||
|
||||
@ -380,21 +393,26 @@ const Personal = () => {
|
||||
sx={{
|
||||
bgcolor: '#e3f2fd',
|
||||
color: '#1565c0',
|
||||
mt: 1
|
||||
mt: 1,
|
||||
fontSize: isMobile ? "3vw" : "inherit"
|
||||
}}
|
||||
/>
|
||||
</CardContent>
|
||||
|
||||
<Divider />
|
||||
|
||||
<CardActions sx={{ justifyContent: 'space-between', p: 1.5 }}>
|
||||
<CardActions sx={{ justifyContent: 'space-between', p: isMobile ? "3vw" : "1.5vw" }}>
|
||||
<Button
|
||||
size="small"
|
||||
startIcon={<EditIcon />}
|
||||
onClick={() => handleOpenEditDialog(member)}
|
||||
sx={{
|
||||
color: '#1976d2',
|
||||
'&:hover': { bgcolor: 'rgba(25, 118, 210, 0.1)' }
|
||||
color: "black",
|
||||
"&:hover": { color: "#C27664", bgcolor: "transparent" },
|
||||
transition: "all 0.2s ease",
|
||||
fontFamily: "Unbounded",
|
||||
fontWeight: "bold",
|
||||
fontSize: isMobile ? "4.5vw" : "0.8vw",
|
||||
}}
|
||||
>
|
||||
Изменить
|
||||
@ -404,8 +422,15 @@ const Personal = () => {
|
||||
startIcon={<DeleteIcon />}
|
||||
onClick={() => handleOpenDeleteDialog(member)}
|
||||
sx={{
|
||||
color: '#d32f2f',
|
||||
'&:hover': { bgcolor: 'rgba(211, 47, 47, 0.1)' }
|
||||
color: "rgb(214, 74, 74)",
|
||||
"&:hover": {
|
||||
color: "rgba(150, 0, 0, 1)",
|
||||
bgcolor: "transparent",
|
||||
},
|
||||
transition: "all 0.2s ease",
|
||||
fontFamily: "Unbounded",
|
||||
fontWeight: "bold",
|
||||
fontSize: isMobile ? "4.5vw" : "0.8vw",
|
||||
}}
|
||||
>
|
||||
Удалить
|
||||
@ -417,33 +442,57 @@ const Personal = () => {
|
||||
</Grid>
|
||||
);
|
||||
|
||||
// Общие стили для компонентов формы
|
||||
const textFieldStyles = {
|
||||
"& .MuiOutlinedInput-root": {
|
||||
borderRadius: isMobile ? "5vw" : "1vw",
|
||||
bgcolor: "white",
|
||||
height: isMobile ? "8vw" : "4vw",
|
||||
width: "100%",
|
||||
border: "0.1vw solid #C27664",
|
||||
fontFamily: "Unbounded",
|
||||
fontSize: isMobile ? "4vw" : "1.2vw",
|
||||
color: "#C27664",
|
||||
mb: isMobile ? "3vw" : "0",
|
||||
"& fieldset": {
|
||||
border: "none",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ p: 3 }}>
|
||||
<Box sx={{ p: isMobile ? "4vw" : "3vw" }}>
|
||||
{/* Заголовок и кнопки управления */}
|
||||
<Paper
|
||||
elevation={3}
|
||||
sx={{
|
||||
p: 3,
|
||||
mb: 3,
|
||||
borderRadius: 2,
|
||||
background: 'linear-gradient(to right, #2D2D2D, #3D3D3D)'
|
||||
mt: isMobile ? "3vw" : "0",
|
||||
p: isMobile ? "3vw" : "2vw",
|
||||
mb: isMobile ? "5vw" : "2vw",
|
||||
borderRadius: isMobile ? "5vw" : "1vw",
|
||||
background: "linear-gradient(to right, #2D2D2D, #3D3D3D)"
|
||||
}}
|
||||
>
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
justifyContent: isMobile ? "center" : "space-between",
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
gap: 2
|
||||
gap: isMobile ? "1vw" : "2vw"
|
||||
}}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||
<PersonIcon sx={{ fontSize: 40, color: '#C27664' }} />
|
||||
<Typography variant="h5" sx={{ fontFamily: 'Unbounded', fontWeight: 'bold', color: 'white' }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: isMobile ? "1vw" : "2vw" }}>
|
||||
<PersonIcon sx={{ fontSize: isMobile ? "9vw" : "2vw", color: "#C27664" }} />
|
||||
<Typography variant="h5" sx={{
|
||||
fontFamily: "Unbounded",
|
||||
fontWeight: "bold",
|
||||
color: "white",
|
||||
fontSize: isMobile ? "4vw" : "2vw"
|
||||
}}>
|
||||
Управление персоналом
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: 'flex', gap: 2 }}>
|
||||
<Box sx={{ display: 'flex', gap: "1vw" }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleOpenCreateDialog}
|
||||
@ -453,8 +502,9 @@ const Personal = () => {
|
||||
color: "white",
|
||||
textTransform: "none",
|
||||
fontFamily: "Unbounded",
|
||||
borderRadius: 2,
|
||||
px: 3,
|
||||
borderRadius: isMobile ? "5vw" : "1vw",
|
||||
margin: isMobile ? "2vw" : "0",
|
||||
px: isMobile ? "5vw" : "2vw",
|
||||
"&:hover": { bgcolor: "#945B4D" },
|
||||
}}
|
||||
>
|
||||
@ -468,14 +518,15 @@ const Personal = () => {
|
||||
<Paper
|
||||
elevation={2}
|
||||
sx={{
|
||||
p: 2,
|
||||
mb: 3,
|
||||
p: isMobile ? "3.5vw" : "1.5vw",
|
||||
mb: isMobile ? "5vw" : "2vw",
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
borderRadius: 2,
|
||||
borderRadius: isMobile ? "5vw" : "1vw",
|
||||
flexWrap: 'wrap',
|
||||
gap: 2
|
||||
gap: "1vw",
|
||||
boxShadow: "0 0.5vw 1vw rgba(0,0,0,0.15)",
|
||||
}}
|
||||
>
|
||||
<TextField
|
||||
@ -486,8 +537,9 @@ const Personal = () => {
|
||||
size="small"
|
||||
sx={{
|
||||
minWidth: 300,
|
||||
'& .MuiOutlinedInput-root': {
|
||||
borderRadius: 2
|
||||
"& .MuiOutlinedInput-root": {
|
||||
borderRadius: isMobile ? "5vw" : "1vw",
|
||||
width: isMobile ? "95%" : "auto",
|
||||
}
|
||||
}}
|
||||
InputProps={{
|
||||
@ -499,8 +551,12 @@ const Personal = () => {
|
||||
}}
|
||||
/>
|
||||
|
||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mr: 2 }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", flexDirection: isMobile ? "column" : "row", width: isMobile ? "100%" : "auto", justifyContent: isMobile ? "center" : "auto" }}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
sx={{ mr: isMobile ? "0" : "1vw", mt: isMobile ? "2vw" : "0", fontFamily: "Unbounded", fontSize: isMobile ? "5vw" : "1vw" }}
|
||||
>
|
||||
Всего: {totalStaff} сотрудников
|
||||
</Typography>
|
||||
|
||||
@ -529,7 +585,7 @@ const Personal = () => {
|
||||
|
||||
{/* Сообщения об ошибках */}
|
||||
{error && (
|
||||
<Alert severity="error" sx={{ mb: 2, borderRadius: 2 }}>
|
||||
<Alert severity="error" sx={{ mb: isMobile ? "5vw" : "1vw", borderRadius: isMobile ? "5vw" : "1vw", border: isMobile ? "0.1vw solid #C27664" : "none" }}>
|
||||
{error}
|
||||
</Alert>
|
||||
)}
|
||||
@ -537,10 +593,10 @@ const Personal = () => {
|
||||
{/* Индикатор загрузки */}
|
||||
{loading ? (
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
minHeight: 400
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
minHeight: "10vw"
|
||||
}}>
|
||||
<CircularProgress sx={{ color: '#C27664' }} />
|
||||
</Box>
|
||||
@ -548,16 +604,17 @@ const Personal = () => {
|
||||
<Paper
|
||||
elevation={2}
|
||||
sx={{
|
||||
p: 4,
|
||||
textAlign: 'center',
|
||||
borderRadius: 2,
|
||||
bgcolor: '#f9f9f9'
|
||||
p: "4vw",
|
||||
textAlign: "center",
|
||||
borderRadius: "1vw",
|
||||
bgcolor: "#f9f9f9",
|
||||
boxShadow: "0 0.5vw 1vw rgba(0,0,0,0.15)",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6" color="text.secondary">
|
||||
<Typography variant="h6" color="text.secondary" sx={{ fontFamily: "Unbounded" }}>
|
||||
Сотрудники не найдены
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ fontFamily: "Unbounded" }}>
|
||||
Попробуйте изменить параметры поиска или добавьте нового сотрудника
|
||||
</Typography>
|
||||
</Paper>
|
||||
@ -573,66 +630,75 @@ const Personal = () => {
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: { borderRadius: 2 }
|
||||
sx: { borderRadius: isMobile ? "5vw" : "1vw" }
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{
|
||||
fontFamily: 'Unbounded',
|
||||
bgcolor: '#2D2D2D',
|
||||
color: 'white',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 1
|
||||
fontFamily: "Unbounded",
|
||||
bgcolor: "#2D2D2D",
|
||||
color: "white",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "1vw"
|
||||
}}>
|
||||
<AddIcon /> Добавить сотрудника
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ mt: 2 }}>
|
||||
<DialogContent sx={{ mt: isMobile ? "3vw" : "1vw" }}>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
md={6}
|
||||
style={{
|
||||
display: isMobile ? "block" : "grid",
|
||||
gridTemplateColumns: isMobile ? "auto" : "repeat(1, 1fr)",
|
||||
gap: "1vw",
|
||||
}}
|
||||
>
|
||||
<TextField
|
||||
name="name"
|
||||
label="Имя"
|
||||
placeholder="Имя"
|
||||
value={formData.name}
|
||||
onChange={handleInputChange}
|
||||
fullWidth
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
sx={textFieldStyles}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<PersonIcon color="action" />
|
||||
<PersonIcon sx={{ color: "#C27664", fontSize: isMobile ? "5vw" : "2vw" }} />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
name="surname"
|
||||
label="Фамилия"
|
||||
placeholder="Фамилия"
|
||||
value={formData.surname}
|
||||
onChange={handleInputChange}
|
||||
fullWidth
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
sx={textFieldStyles}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<BadgeIcon color="action" />
|
||||
<BadgeIcon sx={{ color: "#C27664", fontSize: isMobile ? "5vw" : "2vw" }} />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
name="role"
|
||||
label="Должность"
|
||||
placeholder="Должность"
|
||||
value={formData.role}
|
||||
onChange={handleInputChange}
|
||||
fullWidth
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
sx={textFieldStyles}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<WorkIcon color="action" />
|
||||
<WorkIcon sx={{ color: "#C27664", fontSize: isMobile ? "5vw" : "2vw" }} />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
@ -641,15 +707,16 @@ const Personal = () => {
|
||||
variant="outlined"
|
||||
component="label"
|
||||
sx={{
|
||||
mt: 2,
|
||||
borderRadius: 2,
|
||||
p: 1.5,
|
||||
borderColor: '#C27664',
|
||||
color: '#C27664',
|
||||
'&:hover': {
|
||||
borderColor: '#945B4D',
|
||||
bgcolor: 'rgba(194, 118, 100, 0.1)'
|
||||
}
|
||||
borderRadius: isMobile ? "5vw" : "1vw",
|
||||
p: isMobile ? "2vw" : "1vw",
|
||||
borderColor: "#C27664",
|
||||
fontFamily: "Unbounded",
|
||||
color: "#C27664",
|
||||
fontSize: isMobile ? "3vw" : "1.2vw",
|
||||
"&:hover": {
|
||||
borderColor: "#945B4D",
|
||||
bgcolor: "rgba(194, 118, 100, 0.1)",
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
>
|
||||
@ -666,13 +733,14 @@ const Personal = () => {
|
||||
<Paper
|
||||
elevation={2}
|
||||
sx={{
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderRadius: 2,
|
||||
overflow: 'hidden',
|
||||
bgcolor: '#f5f5f5'
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
borderRadius: "1vw",
|
||||
overflow: "hidden",
|
||||
bgcolor: "#2D2D2D",
|
||||
boxShadow: "0 0.5vw 1vw rgba(0,0,0,0.15)",
|
||||
}}
|
||||
>
|
||||
{photoPreview ? (
|
||||
@ -681,14 +749,24 @@ const Personal = () => {
|
||||
src={photoPreview}
|
||||
alt="Предпросмотр"
|
||||
sx={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'contain',
|
||||
p: 2
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "contain",
|
||||
p: "1vw",
|
||||
userSelect: "none",
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Typography color="text.secondary" sx={{ p: 4, textAlign: 'center' }}>
|
||||
<Typography
|
||||
color="text.secondary"
|
||||
sx={{
|
||||
p: "3vw",
|
||||
textAlign: "center",
|
||||
color: "white",
|
||||
fontFamily: "Unbounded",
|
||||
}}
|
||||
>
|
||||
Предпросмотр фото
|
||||
</Typography>
|
||||
)}
|
||||
@ -696,13 +774,16 @@ const Personal = () => {
|
||||
</Grid>
|
||||
</Grid>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ p: 2, bgcolor: '#f5f5f5' }}>
|
||||
<DialogActions sx={{ p: "1vw", bgcolor: "#f5f5f5" }}>
|
||||
<Button
|
||||
onClick={handleCloseDialogs}
|
||||
sx={{
|
||||
color: '#666',
|
||||
borderRadius: 2,
|
||||
px: 3
|
||||
color: "black",
|
||||
fontFamily: "Unbounded",
|
||||
borderRadius: "1vw",
|
||||
px: "1vw",
|
||||
"&:hover": { bgcolor: "transparent", color: "#C27664" },
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
Отмена
|
||||
@ -714,8 +795,9 @@ const Personal = () => {
|
||||
sx={{
|
||||
bgcolor: "#C27664",
|
||||
color: "white",
|
||||
borderRadius: 2,
|
||||
px: 3,
|
||||
fontFamily: "Unbounded",
|
||||
borderRadius: isMobile ? "5vw" : "1vw",
|
||||
px: isMobile ? "4vw" : "2vw",
|
||||
"&:hover": { bgcolor: "#945B4D" },
|
||||
"&.Mui-disabled": {
|
||||
bgcolor: "rgba(194, 118, 100, 0.5)",
|
||||
@ -734,66 +816,75 @@ const Personal = () => {
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: { borderRadius: 2 }
|
||||
sx: { borderRadius: isMobile ? "5vw" : "1vw" }
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{
|
||||
fontFamily: 'Unbounded',
|
||||
bgcolor: '#2D2D2D',
|
||||
color: 'white',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 1
|
||||
fontFamily: "Unbounded",
|
||||
bgcolor: "#2D2D2D",
|
||||
color: "white",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "1vw"
|
||||
}}>
|
||||
<EditIcon /> Редактировать сотрудника
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ mt: 2 }}>
|
||||
<DialogContent sx={{ mt: isMobile ? "3vw" : "1vw" }}>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
md={6}
|
||||
style={{
|
||||
display: isMobile ? "block" : "grid",
|
||||
gridTemplateColumns: isMobile ? "auto" : "repeat(1, 1fr)",
|
||||
gap: "1vw",
|
||||
}}
|
||||
>
|
||||
<TextField
|
||||
name="name"
|
||||
label="Имя"
|
||||
placeholder="Имя"
|
||||
value={formData.name}
|
||||
onChange={handleInputChange}
|
||||
fullWidth
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
sx={textFieldStyles}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<PersonIcon color="action" />
|
||||
<PersonIcon sx={{ color: "#C27664", fontSize: isMobile ? "5vw" : "2vw" }} />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
name="surname"
|
||||
label="Фамилия"
|
||||
placeholder="Фамилия"
|
||||
value={formData.surname}
|
||||
onChange={handleInputChange}
|
||||
fullWidth
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
sx={textFieldStyles}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<BadgeIcon color="action" />
|
||||
<BadgeIcon sx={{ color: "#C27664", fontSize: isMobile ? "5vw" : "2vw" }} />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
name="role"
|
||||
label="Должность"
|
||||
placeholder="Должность"
|
||||
value={formData.role}
|
||||
onChange={handleInputChange}
|
||||
fullWidth
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
sx={textFieldStyles}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<WorkIcon color="action" />
|
||||
<WorkIcon sx={{ color: "#C27664", fontSize: isMobile ? "5vw" : "2vw" }} />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
@ -802,15 +893,18 @@ const Personal = () => {
|
||||
variant="outlined"
|
||||
component="label"
|
||||
sx={{
|
||||
mt: 2,
|
||||
borderRadius: 2,
|
||||
p: 1.5,
|
||||
borderColor: '#C27664',
|
||||
color: '#C27664',
|
||||
'&:hover': {
|
||||
borderColor: '#945B4D',
|
||||
bgcolor: 'rgba(194, 118, 100, 0.1)'
|
||||
}
|
||||
borderRadius: isMobile ? "5vw" : "1vw",
|
||||
p: isMobile ? "2vw" : "1vw",
|
||||
borderColor: "#C27664",
|
||||
fontFamily: "Unbounded",
|
||||
color: "#C27664",
|
||||
fontSize: isMobile ? "3vw" : "1.2vw",
|
||||
"&:hover": {
|
||||
borderColor: "#945B4D",
|
||||
bgcolor: "#C27664",
|
||||
color: "white",
|
||||
},
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
fullWidth
|
||||
>
|
||||
@ -827,13 +921,14 @@ const Personal = () => {
|
||||
<Paper
|
||||
elevation={2}
|
||||
sx={{
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderRadius: 2,
|
||||
overflow: 'hidden',
|
||||
bgcolor: '#f5f5f5'
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
borderRadius: "1vw",
|
||||
overflow: "hidden",
|
||||
bgcolor: "#2D2D2D",
|
||||
boxShadow: "0 0.5vw 1vw rgba(0,0,0,0.15)",
|
||||
}}
|
||||
>
|
||||
{photoPreview ? (
|
||||
@ -842,14 +937,24 @@ const Personal = () => {
|
||||
src={photoPreview}
|
||||
alt="Предпросмотр"
|
||||
sx={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'contain',
|
||||
p: 2
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "contain",
|
||||
p: "1vw",
|
||||
userSelect: "none",
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Typography color="text.secondary" sx={{ p: 4, textAlign: 'center' }}>
|
||||
<Typography
|
||||
color="text.secondary"
|
||||
sx={{
|
||||
p: "3vw",
|
||||
textAlign: "center",
|
||||
color: "white",
|
||||
fontFamily: "Unbounded",
|
||||
}}
|
||||
>
|
||||
Предпросмотр фото
|
||||
</Typography>
|
||||
)}
|
||||
@ -857,13 +962,16 @@ const Personal = () => {
|
||||
</Grid>
|
||||
</Grid>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ p: 2, bgcolor: '#f5f5f5' }}>
|
||||
<DialogActions sx={{ p: "1vw", bgcolor: "#f5f5f5" }}>
|
||||
<Button
|
||||
onClick={handleCloseDialogs}
|
||||
sx={{
|
||||
color: '#666',
|
||||
borderRadius: 2,
|
||||
px: 3
|
||||
color: "black",
|
||||
fontFamily: "Unbounded",
|
||||
borderRadius: "1vw",
|
||||
px: "1vw",
|
||||
"&:hover": { bgcolor: "transparent", color: "#C27664" },
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
Отмена
|
||||
@ -875,8 +983,9 @@ const Personal = () => {
|
||||
sx={{
|
||||
bgcolor: "#C27664",
|
||||
color: "white",
|
||||
borderRadius: 2,
|
||||
px: 3,
|
||||
fontFamily: "Unbounded",
|
||||
borderRadius: isMobile ? "5vw" : "1vw",
|
||||
px: isMobile ? "4vw" : "2vw",
|
||||
"&:hover": { bgcolor: "#945B4D" },
|
||||
"&.Mui-disabled": {
|
||||
bgcolor: "rgba(194, 118, 100, 0.5)",
|
||||
@ -893,57 +1002,61 @@ const Personal = () => {
|
||||
open={openDeleteDialog}
|
||||
onClose={handleCloseDialogs}
|
||||
PaperProps={{
|
||||
sx: { borderRadius: 2 }
|
||||
sx: { borderRadius: isMobile ? "5vw" : "1vw", maxWidth: isMobile ? "80vw" : "40vw", overflow: "hidden" }
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{
|
||||
fontFamily: 'Unbounded',
|
||||
bgcolor: '#2D2D2D',
|
||||
color: 'white',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 1
|
||||
fontFamily: "Unbounded",
|
||||
bgcolor: "#2D2D2D",
|
||||
color: "white",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "1vw"
|
||||
}}>
|
||||
<DeleteIcon /> Удалить сотрудника
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ mt: 2, minWidth: 400 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
|
||||
<DialogContent sx={{ mt: isMobile ? "3vw" : "1vw" }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", mb: isMobile ? "3vw" : "1vw", flexDirection: isMobile ? "column" : "row" }}>
|
||||
{selectedMember && (
|
||||
<Avatar
|
||||
src={getImageUrl(selectedMember.photo)}
|
||||
alt={`${selectedMember.name} ${selectedMember.surname}`}
|
||||
sx={{
|
||||
width: 64,
|
||||
height: 64,
|
||||
mr: 2
|
||||
width: isMobile ? "20vw" : "5vw",
|
||||
height: isMobile ? "20vw" : "5vw",
|
||||
mr: isMobile ? "0" : "2vw",
|
||||
mb: isMobile ? "2vw" : "0",
|
||||
}}
|
||||
>
|
||||
{selectedMember && getInitials(selectedMember.name, selectedMember.surname)}
|
||||
</Avatar>
|
||||
)}
|
||||
<Box>
|
||||
<Typography variant="h6" sx={{ fontWeight: 'bold' }}>
|
||||
<Typography variant="h6" sx={{ fontWeight: "bold", fontFamily: "Unbounded" }}>
|
||||
{selectedMember?.name} {selectedMember?.surname}
|
||||
</Typography>
|
||||
{selectedMember && (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
<Typography variant="body2" color="text.secondary" sx={{ fontFamily: "Unbounded" }}>
|
||||
{selectedMember.role}
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Alert severity="warning" sx={{ mt: 2 }}>
|
||||
<Alert severity="warning" sx={{ mt: "1vw", fontFamily: "Unbounded", borderRadius: isMobile ? "5vw" : "1vw" }}>
|
||||
Вы уверены, что хотите удалить этого сотрудника? Это действие нельзя отменить.
|
||||
</Alert>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ p: 2, bgcolor: '#f5f5f5' }}>
|
||||
<DialogActions sx={{ p: "1vw", bgcolor: "#f5f5f5" }}>
|
||||
<Button
|
||||
onClick={handleCloseDialogs}
|
||||
sx={{
|
||||
color: '#666',
|
||||
borderRadius: 2,
|
||||
px: 3
|
||||
color: "black",
|
||||
borderRadius: "1vw",
|
||||
px: "1vw",
|
||||
fontFamily: "Unbounded",
|
||||
"&:hover": { bgcolor: "transparent", color: "#C27664" },
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
Отмена
|
||||
@ -953,8 +1066,13 @@ const Personal = () => {
|
||||
variant="contained"
|
||||
color="error"
|
||||
sx={{
|
||||
borderRadius: 2,
|
||||
px: 3
|
||||
borderRadius: isMobile ? "5vw" : "1vw",
|
||||
px: isMobile ? "4vw" : "2vw",
|
||||
fontFamily: "Unbounded",
|
||||
bgcolor: "#C27664",
|
||||
color: "white",
|
||||
"&:hover": { bgcolor: "#945B4D" },
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
Удалить
|
||||
|
@ -1877,7 +1877,7 @@ const Vehicle = () => {
|
||||
>
|
||||
<DeleteIcon /> Удалить автомобиль
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ mt: isMobile ? "3vw" : "1vw", minWidth: "40vw" }}>
|
||||
<DialogContent sx={{ mt: isMobile ? "3vw" : "1vw" }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", mb: isMobile ? "3vw" : "1vw", flexDirection: isMobile ? "column" : "row" }}>
|
||||
{selectedCar && (
|
||||
<Box
|
||||
|
Reference in New Issue
Block a user