From f74949836ac801c8dcaa71156075991e791ee8e1 Mon Sep 17 00:00:00 2001 From: aurinex Date: Mon, 14 Jul 2025 17:30:13 +0500 Subject: [PATCH] fix --- package-lock.json | 49 + package.json | 1 + src/pages/admin/AdminMainPage.tsx | 54 +- src/pages/admin/Vehicle.tsx | 2377 ++++++++++++++++++++--------- 4 files changed, 1763 insertions(+), 718 deletions(-) diff --git a/package-lock.json b/package-lock.json index ad1da57..6b0a30b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@emotion/styled": "^11.14.1", "@mui/icons-material": "^7.2.0", "@mui/material": "^7.2.0", + "framer-motion": "^12.23.3", "react": "^19.1.0", "react-dom": "^19.1.0", "react-icons": "^5.5.0", @@ -2862,6 +2863,33 @@ "dev": true, "license": "ISC" }, + "node_modules/framer-motion": { + "version": "12.23.3", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.3.tgz", + "integrity": "sha512-llmLkf44zuIZOPSrE4bl4J0UTg6bav+rlKEfMRKgvDMXqBrUtMg6cspoQeRVK3nqRLxTmAJhfGXk39UDdZD7Kw==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.23.2", + "motion-utils": "^12.23.2", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3258,6 +3286,21 @@ "node": "*" } }, + "node_modules/motion-dom": { + "version": "12.23.2", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.2.tgz", + "integrity": "sha512-73j6xDHX/NvVh5L5oS1ouAVnshsvmApOq4F3VZo5MkYSD/YVsVLal4Qp9wvVgJM9uU2bLZyc0Sn8B9c/MMKk4g==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.23.2" + } + }, + "node_modules/motion-utils": { + "version": "12.23.2", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.2.tgz", + "integrity": "sha512-cIEXlBlXAOUyiAtR0S+QPQUM9L3Diz23Bo+zM420NvSd/oPQJwg6U+rT+WRTpp0rizMsBGQOsAwhWIfglUcZfA==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3926,6 +3969,12 @@ "typescript": ">=4.8.4" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 8df1524..0ea0e34 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@emotion/styled": "^11.14.1", "@mui/icons-material": "^7.2.0", "@mui/material": "^7.2.0", + "framer-motion": "^12.23.3", "react": "^19.1.0", "react-dom": "^19.1.0", "react-icons": "^5.5.0", diff --git a/src/pages/admin/AdminMainPage.tsx b/src/pages/admin/AdminMainPage.tsx index 5a7f163..852aec1 100644 --- a/src/pages/admin/AdminMainPage.tsx +++ b/src/pages/admin/AdminMainPage.tsx @@ -1,45 +1,43 @@ -import { Box, Typography, Container } from '@mui/material'; -import Vehicle from './Vehicle'; -import Personal from './Personal'; -import { Navigate } from 'react-router-dom'; -import Divider from '../../components/Divider'; +import { Box, Typography, Container } from "@mui/material"; +import Vehicle from "./Vehicle"; +import Personal from "./Personal"; +import { Navigate } from "react-router-dom"; +import Divider from "../../components/Divider"; const AdminMainPage = () => { - const isAuth = localStorage.getItem('token') !== null; - + const isAuth = localStorage.getItem("token") !== null; + // Перенаправление на страницу логина, если пользователь не авторизован if (!isAuth) { return ; } return ( - - + + - - + > - - - + + + - - + > diff --git a/src/pages/admin/Vehicle.tsx b/src/pages/admin/Vehicle.tsx index f7c7ab4..ea6c576 100644 --- a/src/pages/admin/Vehicle.tsx +++ b/src/pages/admin/Vehicle.tsx @@ -1,20 +1,20 @@ -import React, { useState, useEffect } from 'react'; -import { - Box, - Typography, - Button, - TextField, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - Paper, - Dialog, - DialogActions, - DialogContent, - DialogTitle, +import React, { useState, useEffect } from "react"; +import { + Box, + Typography, + Button, + TextField, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Paper, + Dialog, + DialogActions, + DialogContent, + DialogTitle, IconButton, Grid, CircularProgress, @@ -33,31 +33,30 @@ import { MenuItem, Select, InputLabel, - FormControl -} from '@mui/material'; -import EditIcon from '@mui/icons-material/Edit'; -import DeleteIcon from '@mui/icons-material/Delete'; -import AddIcon from '@mui/icons-material/Add'; -import SearchIcon from '@mui/icons-material/Search'; -import ViewListIcon from '@mui/icons-material/ViewList'; -import ViewModuleIcon from '@mui/icons-material/ViewModule'; -import DirectionsCarIcon from '@mui/icons-material/DirectionsCar'; -import CalendarTodayIcon from '@mui/icons-material/CalendarToday'; -import SpeedIcon from '@mui/icons-material/Speed'; -import AttachMoneyIcon from '@mui/icons-material/AttachMoney'; -import { useAuth } from '../../context/AuthContext'; -import { - fetchCars, - createCar, - updateCar, - deleteCar, + FormControl, +} from "@mui/material"; +import EditIcon from "@mui/icons-material/Edit"; +import DeleteIcon from "@mui/icons-material/Delete"; +import AddIcon from "@mui/icons-material/Add"; +import SearchIcon from "@mui/icons-material/Search"; +import ViewListIcon from "@mui/icons-material/ViewList"; +import ViewModuleIcon from "@mui/icons-material/ViewModule"; +import DirectionsCarIcon from "@mui/icons-material/DirectionsCar"; +import CalendarTodayIcon from "@mui/icons-material/CalendarToday"; +import SpeedIcon from "@mui/icons-material/Speed"; +import AttachMoneyIcon from "@mui/icons-material/AttachMoney"; +import { useAuth } from "../../context/AuthContext"; +import { + fetchCars, + createCar, + updateCar, + deleteCar, getImageUrl, -} from '../../utils/api'; -import type { Car } from '../../utils/api'; +} from "../../utils/api"; +import type { Car } from "../../utils/api"; // Определяем типы здесь, так как они не экспортируются из api.ts - interface CarsResponse { cars: Car[]; total: number; @@ -67,38 +66,57 @@ const Vehicle = () => { const { token } = useAuth(); const [cars, setCars] = useState([]); const [loading, setLoading] = useState(true); - const [error, setError] = useState(''); + const [error, setError] = useState(""); const [totalCars, setTotalCars] = useState(0); - const [viewMode, setViewMode] = useState<'list' | 'grid'>('grid'); - const [searchQuery, setSearchQuery] = useState(''); - + const [viewMode, setViewMode] = useState<"list" | "grid">("grid"); + const [searchQuery, setSearchQuery] = useState(""); + // Состояния для модальных окон const [openCreateDialog, setOpenCreateDialog] = useState(false); const [openEditDialog, setOpenEditDialog] = useState(false); const [openDeleteDialog, setOpenDeleteDialog] = useState(false); - + // Состояние для выбранного автомобиля const [selectedCar, setSelectedCar] = useState(null); - + // Состояния для формы const [formData, setFormData] = useState({ - name: '', - year: '', - mileage: '', - price: '', - base_price: '', - country_of_origin: 'Россия', - drive_type: 'AWD', - engine_type: 'бензиновый', - engine_capacity: '', - engine_power: '', - electric_motor_power: '', - hybrid_type: 'не гибрид', - power_ratio: 'не применимо', + name: "", + year: "", + mileage: "", + price: "", + base_price: "", + country_of_origin: "Россия", + drive_type: "AWD", + engine_type: "бензиновый", + engine_capacity: "", + engine_power: "", + electric_motor_power: "", + hybrid_type: "не гибрид", + power_ratio: "не применимо", }); const [imageFile, setImageFile] = useState(null); - const [imagePreview, setImagePreview] = useState(''); - + const [imagePreview, setImagePreview] = useState(""); + + const translateWheelDrive = (wheelDrive: string) => { + switch (wheelDrive) { + case "4WD": + return "Четырехколесный"; + case "AWD": + return "Полный"; + case "RWD": + return "Задний"; + case "FWD": + return "Передний"; + case "передний": + return "Передний"; + case "задний": + return "Задний"; + case "полный": + return "Полный"; + } + }; + // Загрузка списка автомобилей const loadCars = async () => { setLoading(true); @@ -106,35 +124,129 @@ const Vehicle = () => { const data: CarsResponse = await fetchCars(); setCars(data.cars); setTotalCars(data.total); - setError(''); + setError(""); } catch (err) { - setError('Не удалось загрузить список автомобилей'); + setError("Не удалось загрузить список автомобилей"); console.error(err); } finally { setLoading(false); } }; - + useEffect(() => { loadCars(); }, []); - + // Фильтрация автомобилей по поисковому запросу - const filteredCars = cars.filter(car => - car.name.toLowerCase().includes(searchQuery.toLowerCase()) || - car.year.toString().includes(searchQuery) || - car.price.toString().includes(searchQuery) + const filteredCars = cars.filter( + (car) => + car.name.toLowerCase().includes(searchQuery.toLowerCase()) || + car.year.toString().includes(searchQuery) || + car.price.toString().includes(searchQuery) ); - + // Обработчики для формы const handleInputChange = (e: React.ChangeEvent) => { const { name, value } = e.target; - setFormData({ + const updatedData = { ...formData, - [name]: value - }); + [name]: value, + }; + + // Если изменилась базовая цена или параметры, влияющие на расчет + if ( + name === "base_price" || + name === "year" || + name === "engine_power" || + name === "engine_capacity" || + name === "engine_type" || + name === "hybrid_type" || + name === "electric_motor_power" + ) { + // Расчет таможенных платежей + const basePrice = parseFloat(updatedData.base_price) || 0; + let customDuty = 0; + let exciseTax = 0; + let vat = 0; + let utilityFee = 0; + + // Получаем числовые значения + const year = parseInt(updatedData.year) || new Date().getFullYear(); + const engineCapacity = parseFloat(updatedData.engine_capacity) || 0; + const enginePower = parseFloat(updatedData.engine_power) || 0; + const currentYear = new Date().getFullYear(); + const age = currentYear - year; + + // Расчет пошлины в зависимости от возраста + if (updatedData.engine_type === "электрический") { + customDuty = 0; // Пошлина 0% для электромобилей + } else { + // Определяем коэффициент для возраста + let ageCoef = 0.54; // По умолчанию для авто < 3 лет + + if (age > 5) { + ageCoef = 0.48; + // Для авто старше 5 лет используем фиксированную ставку + const dutyPerCm3 = 2.5 * 100; // примерный курс евро * 2.5 евро за см3 + const dutyFixed = engineCapacity * dutyPerCm3; + customDuty = Math.max(dutyFixed, basePrice * ageCoef); + } else if (age >= 3) { + ageCoef = 0.48; + customDuty = basePrice * ageCoef; + } else { + customDuty = basePrice * ageCoef; + } + } + + // Расчет акциза в зависимости от мощности + if (updatedData.engine_type !== "электрический") { + if (enginePower <= 90) { + exciseTax = 0; + } else if (enginePower <= 150) { + exciseTax = enginePower * 53; + } else if (enginePower <= 200) { + exciseTax = enginePower * 511; + } else if (enginePower <= 300) { + exciseTax = enginePower * 836; + } else if (enginePower <= 400) { + exciseTax = enginePower * 1425; + } else { + exciseTax = enginePower * 1475; + } + } + + // НДС 20% + vat = (basePrice + customDuty + exciseTax) * 0.2; + + // Утилизационный сбор + utilityFee = updatedData.engine_type === "электрический" ? 3400 : 5000; + + // Итоговая цена + const totalFees = customDuty + exciseTax + vat + utilityFee; + const calculatedPrice = Math.round(basePrice + totalFees); + + // Обновляем цену в форме + updatedData.price = calculatedPrice.toString(); + } + + setFormData(updatedData); }; - + + // Обработчик для select полей + const handleSelectChange = ( + e: React.ChangeEvent<{ name?: string; value: unknown }> + ) => { + const name = e.target.name as string; + const value = e.target.value as string; + + // Используем тот же обработчик, что и для текстовых полей + const event = { + target: { name, value }, + } as React.ChangeEvent; + + handleInputChange(event); + }; + const handleImageChange = (e: React.ChangeEvent) => { if (e.target.files && e.target.files[0]) { const file = e.target.files[0]; @@ -142,58 +254,58 @@ const Vehicle = () => { setImagePreview(URL.createObjectURL(file)); } }; - + // Открытие диалога создания const handleOpenCreateDialog = () => { setFormData({ - name: '', - year: '', - mileage: '', - price: '', - base_price: '', - country_of_origin: 'Россия', - drive_type: 'AWD', - engine_type: 'бензиновый', - engine_capacity: '', - engine_power: '', - electric_motor_power: '', - hybrid_type: 'не гибрид', - power_ratio: 'не применимо', + name: "", + year: "", + mileage: "", + price: "", + base_price: "", + country_of_origin: "Россия", + drive_type: "AWD", + engine_type: "бензиновый", + engine_capacity: "", + engine_power: "", + electric_motor_power: "", + hybrid_type: "не гибрид", + power_ratio: "не применимо", }); setImageFile(null); - setImagePreview(''); + setImagePreview(""); setOpenCreateDialog(true); }; - + // Открытие диалога редактирования const handleOpenEditDialog = (car: Car) => { setSelectedCar(car); setFormData({ - name: car.name, - year: car.year.toString(), - mileage: car.mileage.toString(), - price: car.price.toString(), - base_price: car.base_price?.toString() || '', - country_of_origin: car.country_of_origin || 'Россия', - drive_type: car.drive_type || 'AWD', - engine_type: car.engine_type || 'бензиновый', - engine_capacity: car.engine_capacity?.toString() || '', - engine_power: car.engine_power?.toString() || '', - electric_motor_power: car.electric_motor_power?.toString() || '', - hybrid_type: car.hybrid_type || 'не гибрид', - power_ratio: car.power_ratio || 'не применимо', - }); + name: car.name, + year: car.year.toString(), + mileage: car.mileage.toString(), + price: car.price.toString(), + base_price: car.base_price?.toString() || "", + country_of_origin: car.country_of_origin || "Россия", + drive_type: car.drive_type || "AWD", + engine_type: car.engine_type || "бензиновый", + engine_capacity: car.engine_capacity?.toString() || "", + engine_power: car.engine_power?.toString() || "", + electric_motor_power: car.electric_motor_power?.toString() || "", + hybrid_type: car.hybrid_type || "не гибрид", + power_ratio: car.power_ratio || "не применимо", + }); setImagePreview(getImageUrl(car.image)); setImageFile(null); setOpenEditDialog(true); }; - + // Открытие диалога удаления const handleOpenDeleteDialog = (car: Car) => { setSelectedCar(car); setOpenDeleteDialog(true); }; - + // Закрытие диалогов const handleCloseDialogs = () => { setOpenCreateDialog(false); @@ -201,40 +313,9 @@ const Vehicle = () => { setOpenDeleteDialog(false); setSelectedCar(null); }; - + // Создание автомобиля const handleCreateCar = async () => { - try { - const carData = { - name: formData.name, - year: parseInt(formData.year), - mileage: parseInt(formData.mileage), - price: parseInt(formData.price), - base_price: parseInt(formData.base_price), - country_of_origin: formData.country_of_origin, - drive_type: formData.drive_type, - engine_type: formData.engine_type, - engine_capacity: formData.engine_capacity ? parseInt(formData.engine_capacity) : undefined, - engine_power: formData.engine_power ? parseInt(formData.engine_power) : undefined, - electric_motor_power: formData.electric_motor_power ? parseInt(formData.electric_motor_power) : undefined, - hybrid_type: formData.hybrid_type || 'не гибрид', - power_ratio: formData.power_ratio || 'не применимо', - image: '' - }; - - await createCar(carData, imageFile || undefined); - handleCloseDialogs(); - loadCars(); - } catch (err) { - setError('Не удалось создать автомобиль'); - console.error(err); - } - }; - - // Обновление автомобиля - const handleUpdateCar = async () => { - if (!selectedCar) return; - try { const carData = { name: formData.name, @@ -245,144 +326,205 @@ const Vehicle = () => { country_of_origin: formData.country_of_origin, drive_type: formData.drive_type, engine_type: formData.engine_type, - engine_capacity: formData.engine_capacity ? parseInt(formData.engine_capacity) : undefined, - engine_power: formData.engine_power ? parseInt(formData.engine_power) : undefined, - electric_motor_power: formData.electric_motor_power ? parseInt(formData.electric_motor_power) : undefined, - hybrid_type: formData.hybrid_type || 'не гибрид', - power_ratio: formData.power_ratio || 'не применимо', + engine_capacity: formData.engine_capacity + ? parseInt(formData.engine_capacity) + : undefined, + engine_power: formData.engine_power + ? parseInt(formData.engine_power) + : undefined, + electric_motor_power: formData.electric_motor_power + ? parseInt(formData.electric_motor_power) + : undefined, + hybrid_type: formData.hybrid_type || "не гибрид", + power_ratio: formData.power_ratio || "не применимо", + image: "", }; - + + await createCar(carData, imageFile || undefined); + handleCloseDialogs(); + loadCars(); + } catch (err) { + setError("Не удалось создать автомобиль"); + console.error(err); + } + }; + + // Обновление автомобиля + const handleUpdateCar = async () => { + if (!selectedCar) return; + + try { + const carData = { + name: formData.name, + year: parseInt(formData.year), + mileage: parseInt(formData.mileage), + price: parseInt(formData.price), + base_price: parseInt(formData.base_price), + country_of_origin: formData.country_of_origin, + drive_type: formData.drive_type, + engine_type: formData.engine_type, + engine_capacity: formData.engine_capacity + ? parseInt(formData.engine_capacity) + : undefined, + engine_power: formData.engine_power + ? parseInt(formData.engine_power) + : undefined, + electric_motor_power: formData.electric_motor_power + ? parseInt(formData.electric_motor_power) + : undefined, + hybrid_type: formData.hybrid_type || "не гибрид", + power_ratio: formData.power_ratio || "не применимо", + }; + await updateCar(selectedCar.id, carData, imageFile || undefined); handleCloseDialogs(); loadCars(); } catch (err) { - setError('Не удалось обновить автомобиль'); + setError("Не удалось обновить автомобиль"); console.error(err); } }; - + // Удаление автомобиля const handleDeleteCar = async () => { if (!selectedCar) return; - + try { await deleteCar(selectedCar.id); handleCloseDialogs(); loadCars(); } catch (err) { - setError('Не удалось удалить автомобиль'); + setError("Не удалось удалить автомобиль"); console.error(err); } }; - + // Валидация формы const isFormValid = () => { return ( - formData.name.trim() !== '' && - !isNaN(parseInt(formData.year)) && - !isNaN(parseInt(formData.mileage)) && + formData.name.trim() !== "" && + !isNaN(parseInt(formData.year)) && + !isNaN(parseInt(formData.mileage)) && !isNaN(parseInt(formData.price)) && !isNaN(parseInt(formData.base_price)) && - formData.country_of_origin.trim() !== '' && - formData.drive_type.trim() !== '' && - formData.engine_type.trim() !== '' + formData.country_of_origin.trim() !== "" && + formData.drive_type.trim() !== "" && + formData.engine_type.trim() !== "" ); }; - + // Форматирование цены const formatPrice = (price: number) => { - return new Intl.NumberFormat('ru-RU', { - style: 'currency', - currency: 'RUB', - maximumFractionDigits: 0 + return new Intl.NumberFormat("ru-RU", { + style: "currency", + currency: "RUB", + maximumFractionDigits: 0, }).format(price); }; - + // Рендер таблицы const renderTable = () => ( - - + - ID - Изображение - Название - Год - Пробег - Цена - Действия + + ID + + + Изображение + + + Название + + + Год + + + Пробег + + + Цена + + + Действия + {filteredCars.map((car) => ( - {car.id} - - {car.name} + {car.name} - } - label={car.year} - size="small" - sx={{ bgcolor: '#e8f5e9', color: '#2e7d32' }} + } + label={car.year} + size="small" + sx={{ bgcolor: "#e8f5e9", color: "#2e7d32" }} /> - } - label={`${car.mileage} км`} - size="small" - sx={{ bgcolor: '#e3f2fd', color: '#1565c0' }} + } + label={`${car.mileage} км`} + size="small" + sx={{ bgcolor: "#e3f2fd", color: "#1565c0" }} /> - } - label={formatPrice(car.price)} - size="small" - sx={{ bgcolor: '#fce4ec', color: '#c2185b' }} + } + label={formatPrice(car.price)} + size="small" + sx={{ bgcolor: "#fce4ec", color: "#c2185b" }} /> - - handleOpenEditDialog(car)} + + handleOpenEditDialog(car)} color="primary" - sx={{ + sx={{ color: "black", - '&:hover': { - color: '#C27664', - bgcolor: "transparent" + "&:hover": { + color: "#C27664", + bgcolor: "transparent", }, transition: "all 0.2s ease", }} @@ -390,14 +532,18 @@ const Vehicle = () => { - - handleOpenDeleteDialog(car)} + + handleOpenDeleteDialog(car)} color="error" - sx={{ - '&:hover': { - color: '#C27664', - bgcolor: 'transparent', + sx={{ + "&:hover": { + color: "#C27664", + bgcolor: "transparent", }, transition: "all 0.2s ease", }} @@ -412,25 +558,25 @@ const Vehicle = () => {
); - + // Рендер сетки карточек const renderGrid = () => ( {filteredCars.map((car) => ( - { height="160" image={getImageUrl(car.image)} alt={car.name} - sx={{ objectFit: 'cover', + sx={{ + objectFit: "cover", userSelect: "none", pointerEvents: "none", }} /> - + {car.name} - - - + + + - + Год выпуска: {car.year} - - + + - + Пробег: {car.mileage} км - - + + - + Цена: {formatPrice(car.price)} - + - - - - + )} + {/* Поле мощности двигателя - показываем для всех, кроме электрических */} + {formData.engine_type !== "электрический" && ( + + setFormData({ ...formData, engine_power: e.target.value }) + } + variant="outlined" + sx={{ + "& .MuiOutlinedInput-root": { + borderRadius: "1vw", + bgcolor: "white", + height: "4vw", + width: "100%", + border: "0.1vw solid #C27664", + fontFamily: "Unbounded", + fontSize: "1.2vw", + color: "#C27664", + "& fieldset": { + border: "none", + }, + }, + }} + InputProps={{ + startAdornment: ( + + + л.с. + + + ), + }} + /> + )} + {/* Поле мощности электромотора - показываем только для электрических и гибридных */} + {(formData.engine_type === "электрический" || + formData.engine_type === "гибридный") && ( + + setFormData({ + ...formData, + electric_motor_power: e.target.value, + }) + } + variant="outlined" + sx={{ + "& .MuiOutlinedInput-root": { + borderRadius: "1vw", + bgcolor: "white", + height: "4vw", + width: "100%", + border: "0.1vw solid #C27664", + fontFamily: "Unbounded", + fontSize: "1.2vw", + color: "#C27664", + "& fieldset": { + border: "none", + }, + }, + }} + InputProps={{ + startAdornment: ( + + + кВт + + + ), + }} + /> + )} + {/* Тип гибрида - показываем только для гибридов */} + {formData.engine_type === "гибридный" && ( + + + Тип гибрида + + + + )} + {/* Соотношение мощности - показываем только для гибридов */} + {formData.engine_type === "гибридный" && ( + + + Соотношение мощности + + + + )} + - {imagePreview ? ( @@ -1077,17 +1562,25 @@ const Vehicle = () => { component="img" src={imagePreview} alt="Предпросмотр" - sx={{ - width: '100%', - height: '100%', - objectFit: 'contain', + sx={{ + width: "100%", + height: "100%", + objectFit: "contain", p: "1vw", userSelect: "none", pointerEvents: "none", }} /> ) : ( - + Предпросмотр изображения )} @@ -1095,22 +1588,22 @@ const Vehicle = () => { - - - - + {/* Диалог редактирования автомобиля */} - - + Редактировать автомобиль - + + setFormData({ ...formData, name: e.target.value }) + } variant="outlined" + sx={{ + "& .MuiOutlinedInput-root": { + borderRadius: "1vw", + bgcolor: "white", + height: "4vw", + width: "100%", + border: "0.1vw solid #C27664", + fontFamily: "Unbounded", + fontSize: "1.2vw", + color: "#C27664", + "& fieldset": { + border: "none", + }, + }, + }} InputProps={{ startAdornment: ( - + ), }} /> + setFormData({ ...formData, year: e.target.value }) + } variant="outlined" + sx={{ + "& .MuiOutlinedInput-root": { + borderRadius: "1vw", + bgcolor: "white", + height: "4vw", + width: "100%", + border: "0.1vw solid #C27664", + fontFamily: "Unbounded", + fontSize: "1.2vw", + color: "#C27664", + "& fieldset": { + border: "none", + }, + }, + }} InputProps={{ startAdornment: ( - + ), }} /> - + + ₽ + ), }} /> - + + ₽ + ), }} /> + + setFormData({ ...formData, mileage: e.target.value }) + } + variant="outlined" + sx={{ + "& .MuiOutlinedInput-root": { + borderRadius: "1vw", + bgcolor: "white", + height: "4vw", + width: "100%", + border: "0.1vw solid #C27664", + fontFamily: "Unbounded", + fontSize: "1.2vw", + color: "#C27664", + "& fieldset": { + border: "none", + }, + }, + }} + InputProps={{ + startAdornment: ( + + + + ), + }} + /> + + + Страна происхождения + + + + + + Тип привода + + + + + + Тип двигателя + + + + {/* Поле объёма двигателя - показываем для всех, кроме электрических */} + {formData.engine_type !== "электрический" && ( + + setFormData({ + ...formData, + engine_capacity: e.target.value, + }) + } + variant="outlined" + sx={{ + "& .MuiOutlinedInput-root": { + borderRadius: "1vw", + bgcolor: "white", + height: "4vw", + width: "100%", + border: "0.1vw solid #C27664", + fontFamily: "Unbounded", + fontSize: "1.2vw", + color: "#C27664", + "& fieldset": { + border: "none", + }, + }, + }} + InputProps={{ + startAdornment: ( + + + л + + + ), + }} + /> + )} + {/* Поле мощности двигателя - показываем для всех, кроме электрических */} + {formData.engine_type !== "электрический" && ( + + setFormData({ ...formData, engine_power: e.target.value }) + } + variant="outlined" + sx={{ + "& .MuiOutlinedInput-root": { + borderRadius: "1vw", + bgcolor: "white", + height: "4vw", + width: "100%", + border: "0.1vw solid #C27664", + fontFamily: "Unbounded", + fontSize: "1.2vw", + color: "#C27664", + "& fieldset": { + border: "none", + }, + }, + }} + InputProps={{ + startAdornment: ( + + + л.с. + + + ), + }} + /> + )} + {/* Поле мощности электромотора - показываем только для электрических и гибридных */} + {(formData.engine_type === "электрический" || + formData.engine_type === "гибридный") && ( + + setFormData({ + ...formData, + electric_motor_power: e.target.value, + }) + } + variant="outlined" + sx={{ + "& .MuiOutlinedInput-root": { + borderRadius: "1vw", + bgcolor: "white", + height: "4vw", + width: "100%", + border: "0.1vw solid #C27664", + fontFamily: "Unbounded", + fontSize: "1.2vw", + color: "#C27664", + "& fieldset": { + border: "none", + }, + }, + }} + InputProps={{ + startAdornment: ( + + + кВт + + + ), + }} + /> + )} + {/* Тип гибрида - показываем только для гибридов */} + {formData.engine_type === "гибридный" && ( + + + Тип гибрида + + + + )} + {/* Соотношение мощности - показываем только для гибридов */} + {formData.engine_type === "гибридный" && ( + + + Соотношение мощности + + + + )} + - {imagePreview ? ( @@ -1271,17 +2249,25 @@ const Vehicle = () => { component="img" src={imagePreview} alt="Предпросмотр" - sx={{ - width: '100%', - height: '100%', - objectFit: 'contain', + sx={{ + width: "100%", + height: "100%", + objectFit: "contain", p: "1vw", userSelect: "none", pointerEvents: "none", }} /> ) : ( - + Предпросмотр изображения )} @@ -1289,22 +2275,22 @@ const Vehicle = () => { - - - - + {/* Диалог удаления автомобиля */} - - + Удалить автомобиль - + {selectedCar && ( - { /> )} - + {selectedCar?.name} {selectedCar && ( - - {selectedCar.year} г., {selectedCar.mileage} км, {formatPrice(selectedCar.price)} + + {selectedCar.year} г., {selectedCar.mileage} км,{" "} + {formatPrice(selectedCar.price)} )} - + - Вы уверены, что хотите удалить этот автомобиль? Это действие нельзя отменить. + Вы уверены, что хотите удалить этот автомобиль? Это действие нельзя + отменить. - - -