2413 lines
83 KiB
TypeScript
2413 lines
83 KiB
TypeScript
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,
|
||
Alert,
|
||
Card,
|
||
CardContent,
|
||
CardMedia,
|
||
CardActions,
|
||
Chip,
|
||
Divider,
|
||
InputAdornment,
|
||
Tooltip,
|
||
Fade,
|
||
Tabs,
|
||
Tab,
|
||
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,
|
||
getImageUrl,
|
||
} from "../../utils/api";
|
||
import type { Car } from "../../utils/api";
|
||
|
||
// Определяем типы здесь, так как они не экспортируются из api.ts
|
||
|
||
interface CarsResponse {
|
||
cars: Car[];
|
||
total: number;
|
||
}
|
||
|
||
const Vehicle = () => {
|
||
const { token } = useAuth();
|
||
const [cars, setCars] = useState<Car[]>([]);
|
||
const [loading, setLoading] = useState(true);
|
||
const [error, setError] = useState("");
|
||
const [totalCars, setTotalCars] = useState(0);
|
||
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<Car | null>(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: "не применимо",
|
||
});
|
||
const [imageFile, setImageFile] = useState<File | null>(null);
|
||
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);
|
||
try {
|
||
const data: CarsResponse = await fetchCars();
|
||
setCars(data.cars);
|
||
setTotalCars(data.total);
|
||
setError("");
|
||
} catch (err) {
|
||
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 handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||
const { name, value } = e.target;
|
||
const updatedData = {
|
||
...formData,
|
||
[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<HTMLInputElement>;
|
||
|
||
handleInputChange(event);
|
||
};
|
||
|
||
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||
if (e.target.files && e.target.files[0]) {
|
||
const file = e.target.files[0];
|
||
setImageFile(file);
|
||
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: "не применимо",
|
||
});
|
||
setImageFile(null);
|
||
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 || "не применимо",
|
||
});
|
||
setImagePreview(getImageUrl(car.image));
|
||
setImageFile(null);
|
||
setOpenEditDialog(true);
|
||
};
|
||
|
||
// Открытие диалога удаления
|
||
const handleOpenDeleteDialog = (car: Car) => {
|
||
setSelectedCar(car);
|
||
setOpenDeleteDialog(true);
|
||
};
|
||
|
||
// Закрытие диалогов
|
||
const handleCloseDialogs = () => {
|
||
setOpenCreateDialog(false);
|
||
setOpenEditDialog(false);
|
||
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,
|
||
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("Не удалось обновить автомобиль");
|
||
console.error(err);
|
||
}
|
||
};
|
||
|
||
// Удаление автомобиля
|
||
const handleDeleteCar = async () => {
|
||
if (!selectedCar) return;
|
||
|
||
try {
|
||
await deleteCar(selectedCar.id);
|
||
handleCloseDialogs();
|
||
loadCars();
|
||
} catch (err) {
|
||
setError("Не удалось удалить автомобиль");
|
||
console.error(err);
|
||
}
|
||
};
|
||
|
||
// Валидация формы
|
||
const isFormValid = () => {
|
||
return (
|
||
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() !== ""
|
||
);
|
||
};
|
||
|
||
// Форматирование цены
|
||
const formatPrice = (price: number) => {
|
||
return new Intl.NumberFormat("ru-RU", {
|
||
style: "currency",
|
||
currency: "RUB",
|
||
maximumFractionDigits: 0,
|
||
}).format(price);
|
||
};
|
||
|
||
// Рендер таблицы
|
||
const renderTable = () => (
|
||
<TableContainer
|
||
component={Paper}
|
||
elevation={3}
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
overflow: "hidden",
|
||
}}
|
||
>
|
||
<Table>
|
||
<TableHead sx={{ bgcolor: "#2D2D2D" }}>
|
||
<TableRow>
|
||
<TableCell sx={{ color: "white", fontWeight: "bold" }}>
|
||
ID
|
||
</TableCell>
|
||
<TableCell sx={{ color: "white", fontWeight: "bold" }}>
|
||
Изображение
|
||
</TableCell>
|
||
<TableCell sx={{ color: "white", fontWeight: "bold" }}>
|
||
Название
|
||
</TableCell>
|
||
<TableCell sx={{ color: "white", fontWeight: "bold" }}>
|
||
Год
|
||
</TableCell>
|
||
<TableCell sx={{ color: "white", fontWeight: "bold" }}>
|
||
Пробег
|
||
</TableCell>
|
||
<TableCell sx={{ color: "white", fontWeight: "bold" }}>
|
||
Цена
|
||
</TableCell>
|
||
<TableCell sx={{ color: "white", fontWeight: "bold" }}>
|
||
Действия
|
||
</TableCell>
|
||
</TableRow>
|
||
</TableHead>
|
||
<TableBody>
|
||
{filteredCars.map((car) => (
|
||
<TableRow
|
||
key={car.id}
|
||
sx={{
|
||
"&:hover": {
|
||
backgroundColor: "#f5f5f5",
|
||
},
|
||
transition: "background-color 0.3s",
|
||
}}
|
||
>
|
||
<TableCell>{car.id}</TableCell>
|
||
<TableCell>
|
||
<Box
|
||
component="img"
|
||
src={getImageUrl(car.image)}
|
||
alt={car.name}
|
||
sx={{
|
||
width: "10vw",
|
||
height: "5vw",
|
||
objectFit: "cover",
|
||
borderRadius: "0.7vw",
|
||
boxShadow: "0 0.2vw 0.4vw rgba(0,0,0,0.1)",
|
||
userSelect: "none",
|
||
pointerEvents: "none",
|
||
}}
|
||
/>
|
||
</TableCell>
|
||
<TableCell sx={{ fontWeight: "medium" }}>{car.name}</TableCell>
|
||
<TableCell>
|
||
<Chip
|
||
icon={<CalendarTodayIcon />}
|
||
label={car.year}
|
||
size="small"
|
||
sx={{ bgcolor: "#e8f5e9", color: "#2e7d32" }}
|
||
/>
|
||
</TableCell>
|
||
<TableCell>
|
||
<Chip
|
||
icon={<SpeedIcon />}
|
||
label={`${car.mileage} км`}
|
||
size="small"
|
||
sx={{ bgcolor: "#e3f2fd", color: "#1565c0" }}
|
||
/>
|
||
</TableCell>
|
||
<TableCell>
|
||
<Chip
|
||
icon={<AttachMoneyIcon />}
|
||
label={formatPrice(car.price)}
|
||
size="small"
|
||
sx={{ bgcolor: "#fce4ec", color: "#c2185b" }}
|
||
/>
|
||
</TableCell>
|
||
<TableCell>
|
||
<Tooltip
|
||
arrow
|
||
TransitionComponent={Fade}
|
||
TransitionProps={{ timeout: 600 }}
|
||
>
|
||
<IconButton
|
||
onClick={() => handleOpenEditDialog(car)}
|
||
color="primary"
|
||
sx={{
|
||
color: "black",
|
||
"&:hover": {
|
||
color: "#C27664",
|
||
bgcolor: "transparent",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<EditIcon />
|
||
</IconButton>
|
||
</Tooltip>
|
||
<Tooltip
|
||
arrow
|
||
TransitionComponent={Fade}
|
||
TransitionProps={{ timeout: 600 }}
|
||
>
|
||
<IconButton
|
||
onClick={() => handleOpenDeleteDialog(car)}
|
||
color="error"
|
||
sx={{
|
||
"&:hover": {
|
||
color: "#C27664",
|
||
bgcolor: "transparent",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<DeleteIcon />
|
||
</IconButton>
|
||
</Tooltip>
|
||
</TableCell>
|
||
</TableRow>
|
||
))}
|
||
</TableBody>
|
||
</Table>
|
||
</TableContainer>
|
||
);
|
||
|
||
// Рендер сетки карточек
|
||
const renderGrid = () => (
|
||
<Grid container spacing={3}>
|
||
{filteredCars.map((car) => (
|
||
<Grid item xs={12} sm={6} md={4} key={car.id}>
|
||
<Card
|
||
elevation={3}
|
||
sx={{
|
||
height: "100%",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
borderRadius: "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)",
|
||
},
|
||
}}
|
||
>
|
||
<CardMedia
|
||
component="img"
|
||
height="160"
|
||
image={getImageUrl(car.image)}
|
||
alt={car.name}
|
||
sx={{
|
||
objectFit: "cover",
|
||
userSelect: "none",
|
||
pointerEvents: "none",
|
||
}}
|
||
/>
|
||
<CardContent sx={{ pt: "0.5vw" }}>
|
||
<Typography
|
||
gutterBottom
|
||
variant="h6"
|
||
component="div"
|
||
sx={{
|
||
fontWeight: "bold",
|
||
mb: "0.5vw",
|
||
fontFamily: "Unbounded",
|
||
}}
|
||
>
|
||
{car.name}
|
||
</Typography>
|
||
|
||
<Box
|
||
sx={{ display: "flex", flexDirection: "column", gap: "0.5vw" }}
|
||
>
|
||
<Box
|
||
sx={{ display: "flex", alignItems: "center", gap: "0.5vw" }}
|
||
>
|
||
<CalendarTodayIcon fontSize="small" color="success" />
|
||
<Typography
|
||
variant="body2"
|
||
color="text.secondary"
|
||
sx={{ fontFamily: "Unbounded" }}
|
||
>
|
||
Год выпуска: <b>{car.year}</b>
|
||
</Typography>
|
||
</Box>
|
||
|
||
<Box
|
||
sx={{ display: "flex", alignItems: "center", gap: "0.5vw" }}
|
||
>
|
||
<SpeedIcon fontSize="small" color="primary" />
|
||
<Typography
|
||
variant="body2"
|
||
color="text.secondary"
|
||
sx={{ fontFamily: "Unbounded" }}
|
||
>
|
||
Пробег: <b>{car.mileage} км</b>
|
||
</Typography>
|
||
</Box>
|
||
|
||
<Box
|
||
sx={{ display: "flex", alignItems: "center", gap: "0.5vw" }}
|
||
>
|
||
<AttachMoneyIcon fontSize="small" color="secondary" />
|
||
<Typography
|
||
variant="body2"
|
||
color="text.secondary"
|
||
sx={{ fontFamily: "Unbounded" }}
|
||
>
|
||
Цена: <b>{formatPrice(car.price)}</b>
|
||
</Typography>
|
||
</Box>
|
||
</Box>
|
||
</CardContent>
|
||
|
||
<Divider />
|
||
|
||
<CardActions sx={{ justifyContent: "space-between", p: "1vw" }}>
|
||
<Button
|
||
size="small"
|
||
startIcon={<EditIcon />}
|
||
onClick={() => handleOpenEditDialog(car)}
|
||
sx={{
|
||
color: "black",
|
||
"&:hover": { color: "#C27664", bgcolor: "transparent" },
|
||
transition: "all 0.2s ease",
|
||
fontFamily: "Unbounded",
|
||
fontWeight: "bold",
|
||
fontSize: "0.8vw",
|
||
}}
|
||
>
|
||
Изменить
|
||
</Button>
|
||
<Button
|
||
size="small"
|
||
startIcon={<DeleteIcon />}
|
||
onClick={() => handleOpenDeleteDialog(car)}
|
||
sx={{
|
||
color: "rgb(214, 74, 74)",
|
||
"&:hover": {
|
||
color: "rgba(150, 0, 0, 1)",
|
||
bgcolor: "transparent",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
fontFamily: "Unbounded",
|
||
fontWeight: "bold",
|
||
fontSize: "0.8vw",
|
||
}}
|
||
>
|
||
Удалить
|
||
</Button>
|
||
</CardActions>
|
||
</Card>
|
||
</Grid>
|
||
))}
|
||
</Grid>
|
||
);
|
||
|
||
return (
|
||
<Box>
|
||
{/* Заголовок и кнопки управления */}
|
||
<Paper
|
||
elevation={3}
|
||
sx={{
|
||
p: "2vw",
|
||
mb: "2vw",
|
||
borderRadius: "1vw",
|
||
background: "linear-gradient(to right, #2D2D2D, #3D3D3D)",
|
||
}}
|
||
>
|
||
<Box
|
||
sx={{
|
||
display: "flex",
|
||
justifyContent: "space-between",
|
||
alignItems: "center",
|
||
flexWrap: "wrap",
|
||
gap: "1vw",
|
||
}}
|
||
>
|
||
<Box sx={{ display: "flex", alignItems: "center", gap: "1vw" }}>
|
||
<DirectionsCarIcon sx={{ fontSize: "3.5vw", color: "#C27664" }} />
|
||
<Typography
|
||
variant="h5"
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontWeight: "bold",
|
||
color: "white",
|
||
}}
|
||
>
|
||
Управление автомобилями
|
||
</Typography>
|
||
</Box>
|
||
|
||
<Box sx={{ display: "flex", gap: "1vw" }}>
|
||
<Button
|
||
variant="contained"
|
||
onClick={handleOpenCreateDialog}
|
||
startIcon={<AddIcon />}
|
||
sx={{
|
||
bgcolor: "#C27664",
|
||
color: "white",
|
||
textTransform: "none",
|
||
fontFamily: "Unbounded",
|
||
borderRadius: "1vw",
|
||
px: "2vw",
|
||
"&:hover": { bgcolor: "#945B4D" },
|
||
}}
|
||
>
|
||
Добавить автомобиль
|
||
</Button>
|
||
</Box>
|
||
</Box>
|
||
</Paper>
|
||
|
||
{/* Панель поиска и переключения вида */}
|
||
<Paper
|
||
elevation={2}
|
||
sx={{
|
||
p: "1.5vw",
|
||
mb: "2vw",
|
||
display: "flex",
|
||
justifyContent: "space-between",
|
||
alignItems: "center",
|
||
borderRadius: "1vw",
|
||
flexWrap: "wrap",
|
||
gap: "1vw",
|
||
boxShadow: "0 0.5vw 1vw rgba(0,0,0,0.15)",
|
||
}}
|
||
>
|
||
<TextField
|
||
placeholder="Поиск автомобилей..."
|
||
variant="outlined"
|
||
value={searchQuery}
|
||
onChange={(e) => setSearchQuery(e.target.value)}
|
||
size="small"
|
||
sx={{
|
||
minWidth: 300,
|
||
"& .MuiOutlinedInput-root": {
|
||
borderRadius: "1vw",
|
||
},
|
||
}}
|
||
InputProps={{
|
||
startAdornment: (
|
||
<InputAdornment position="start">
|
||
<SearchIcon />
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
|
||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||
<Typography
|
||
variant="body2"
|
||
color="text.secondary"
|
||
sx={{ mr: "1vw", fontFamily: "Unbounded" }}
|
||
>
|
||
Всего: {totalCars} автомобилей
|
||
</Typography>
|
||
|
||
<Tabs
|
||
value={viewMode}
|
||
onChange={(_, newValue) => setViewMode(newValue)}
|
||
sx={{
|
||
"& .MuiTab-root": { minWidth: "auto" },
|
||
"& .Mui-selected": { color: "#C27664 !important" },
|
||
"& .MuiTabs-indicator": { backgroundColor: "#C27664" },
|
||
}}
|
||
>
|
||
<Tab
|
||
icon={<ViewListIcon />}
|
||
value="list"
|
||
sx={{ minWidth: "auto" }}
|
||
/>
|
||
<Tab
|
||
icon={<ViewModuleIcon />}
|
||
value="grid"
|
||
sx={{ minWidth: "auto" }}
|
||
/>
|
||
</Tabs>
|
||
</Box>
|
||
</Paper>
|
||
|
||
{/* Сообщения об ошибках */}
|
||
{error && (
|
||
<Alert severity="error" sx={{ mb: "1vw", borderRadius: "1vw" }}>
|
||
{error}
|
||
</Alert>
|
||
)}
|
||
|
||
{/* Индикатор загрузки */}
|
||
{loading ? (
|
||
<Box
|
||
sx={{
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
minHeight: "10vw",
|
||
}}
|
||
>
|
||
<CircularProgress sx={{ color: "#C27664" }} />
|
||
</Box>
|
||
) : filteredCars.length === 0 ? (
|
||
<Paper
|
||
elevation={2}
|
||
sx={{
|
||
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"
|
||
sx={{ fontFamily: "Unbounded" }}
|
||
>
|
||
Автомобили не найдены
|
||
</Typography>
|
||
<Typography
|
||
variant="body2"
|
||
color="text.secondary"
|
||
sx={{ fontFamily: "Unbounded" }}
|
||
>
|
||
Попробуйте изменить параметры поиска или добавьте новый автомобиль
|
||
</Typography>
|
||
</Paper>
|
||
) : // Отображение списка автомобилей в зависимости от выбранного режима
|
||
viewMode === "list" ? (
|
||
renderTable()
|
||
) : (
|
||
renderGrid()
|
||
)}
|
||
|
||
{/* Диалог создания автомобиля */}
|
||
<Dialog
|
||
open={openCreateDialog}
|
||
onClose={handleCloseDialogs}
|
||
maxWidth="md"
|
||
fullWidth
|
||
PaperProps={{
|
||
sx: { borderRadius: "1vw" },
|
||
}}
|
||
>
|
||
<DialogTitle
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
bgcolor: "#2D2D2D",
|
||
color: "white",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: "1vw",
|
||
}}
|
||
>
|
||
<AddIcon /> Добавить автомобиль
|
||
</DialogTitle>
|
||
<DialogContent sx={{ mt: "1vw" }}>
|
||
<Grid container spacing={3}>
|
||
<Grid
|
||
component="div"
|
||
item
|
||
xs={12}
|
||
md={6}
|
||
style={{
|
||
display: "grid",
|
||
gridTemplateColumns: "repeat(2, 1fr)",
|
||
gap: "1vw",
|
||
}}
|
||
>
|
||
{/* <TextField
|
||
name="name"
|
||
label="Название автомобиля"
|
||
value={formData.name}
|
||
sx={{ label: { fontFamily: "Unbounded" }, input: { fontFamily: "Unbounded" } }}
|
||
onChange={handleInputChange}
|
||
fullWidth
|
||
margin="normal"
|
||
variant="outlined"
|
||
InputProps={{
|
||
startAdornment: (
|
||
<InputAdornment position="start">
|
||
<DirectionsCarIcon color="action" />
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/> */}
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Название автомобиля"
|
||
value={formData.name}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<DirectionsCarIcon sx={{ color: "#C27664" }} />
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
{/* <TextField
|
||
name="year"
|
||
label="Год выпуска"
|
||
type="number"
|
||
value={formData.year}
|
||
sx={{ label: { fontFamily: "Unbounded" }, input: { fontFamily: "Unbounded" } }}
|
||
onChange={handleInputChange}
|
||
fullWidth
|
||
margin="normal"
|
||
variant="outlined"
|
||
InputProps={{
|
||
startAdornment: (
|
||
<InputAdornment position="start">
|
||
<CalendarTodayIcon color="action" />
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/> */}
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Год выпуска"
|
||
value={formData.year}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<CalendarTodayIcon sx={{ color: "#C27664" }} />
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
{/* <TextField
|
||
name="mileage"
|
||
label="Пробег (км)"
|
||
type="number"
|
||
value={formData.mileage}
|
||
sx={{ label: { fontFamily: "Unbounded" }, input: { fontFamily: "Unbounded" } }}
|
||
onChange={handleInputChange}
|
||
fullWidth
|
||
margin="normal"
|
||
variant="outlined"
|
||
InputProps={{
|
||
startAdornment: (
|
||
<InputAdornment position="start">
|
||
<SpeedIcon color="action" />
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/> */}
|
||
{/* <TextField
|
||
name="price"
|
||
label="Цена (₽)"
|
||
type="number"
|
||
value={formData.price}
|
||
sx={{ label: { fontFamily: "Unbounded" }, input: { fontFamily: "Unbounded" } }}
|
||
onChange={handleInputChange}
|
||
fullWidth
|
||
margin="normal"
|
||
variant="outlined"
|
||
InputProps={{
|
||
startAdornment: (
|
||
<InputAdornment position="start">
|
||
<AttachMoneyIcon color="action" />
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/> */}
|
||
<TextField
|
||
fullWidth
|
||
name="base_price"
|
||
placeholder="Базовая цена в рублях"
|
||
value={formData.base_price}
|
||
onChange={handleInputChange}
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<Typography
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.5vw",
|
||
color: "#C27664",
|
||
}}
|
||
>
|
||
₽
|
||
</Typography>
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Итоговая цена в рублях"
|
||
value={formData.price}
|
||
disabled
|
||
variant="outlined"
|
||
sx={{
|
||
"& .MuiOutlinedInput-root": {
|
||
borderRadius: "1vw",
|
||
bgcolor: "#f5f5f5",
|
||
height: "4vw",
|
||
width: "100%",
|
||
border: "0.1vw solid #C27664",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& fieldset": {
|
||
border: "none",
|
||
},
|
||
},
|
||
}}
|
||
InputProps={{
|
||
startAdornment: (
|
||
<InputAdornment position="start">
|
||
<Typography
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.5vw",
|
||
color: "#C27664",
|
||
}}
|
||
>
|
||
₽
|
||
</Typography>
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Пробег (км)"
|
||
value={formData.mileage}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<SpeedIcon sx={{ color: "#C27664" }} />
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
<FormControl fullWidth>
|
||
<InputLabel
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
color: "#C27664",
|
||
"&.Mui-focused": { color: "#C27664" },
|
||
}}
|
||
>
|
||
Страна происхождения
|
||
</InputLabel>
|
||
<Select
|
||
value={formData.country_of_origin}
|
||
onChange={handleSelectChange}
|
||
displayEmpty
|
||
label="Страна происхождения"
|
||
name="country_of_origin"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& .MuiOutlinedInput-notchedOutline": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
"& .MuiSvgIcon-root": {
|
||
fontSize: "2vw",
|
||
color: "#C27664",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<MenuItem value="Россия">Россия</MenuItem>
|
||
<MenuItem value="Япония">Япония</MenuItem>
|
||
<MenuItem value="Китай">Китай</MenuItem>
|
||
<MenuItem value="США">США</MenuItem>
|
||
<MenuItem value="Германия">Германия</MenuItem>
|
||
<MenuItem value="Корея">Корея</MenuItem>
|
||
<MenuItem value="Италия">Италия</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
<FormControl fullWidth>
|
||
<InputLabel
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
color: "#C27664",
|
||
"&.Mui-focused": { color: "#C27664" },
|
||
}}
|
||
>
|
||
Тип привода
|
||
</InputLabel>
|
||
<Select
|
||
value={formData.drive_type}
|
||
onChange={handleSelectChange}
|
||
displayEmpty
|
||
label="Тип привода"
|
||
name="drive_type"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& .MuiOutlinedInput-notchedOutline": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
"& .MuiSvgIcon-root": {
|
||
fontSize: "2vw",
|
||
color: "#C27664",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<MenuItem value="FWD">FWD</MenuItem>
|
||
<MenuItem value="RWD">RWD</MenuItem>
|
||
<MenuItem value="4WD">4WD</MenuItem>
|
||
<MenuItem value="AWD">AWD</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
<FormControl fullWidth>
|
||
<InputLabel
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
color: "#C27664",
|
||
"&.Mui-focused": { color: "#C27664" },
|
||
}}
|
||
>
|
||
Тип двигателя
|
||
</InputLabel>
|
||
<Select
|
||
value={formData.engine_type}
|
||
onChange={(e) => {
|
||
const engineType = e.target.value as string;
|
||
const updatedFormData = {
|
||
...formData,
|
||
engine_type: engineType,
|
||
};
|
||
|
||
// Сбрасываем значения полей, которые не нужны для выбранного типа
|
||
if (
|
||
engineType === "бензиновый" ||
|
||
engineType === "дизельный"
|
||
) {
|
||
updatedFormData.electric_motor_power = "";
|
||
updatedFormData.hybrid_type = "не гибрид";
|
||
updatedFormData.power_ratio = "не применимо";
|
||
} else if (engineType === "электрический") {
|
||
updatedFormData.engine_capacity = "";
|
||
updatedFormData.engine_power = "";
|
||
updatedFormData.hybrid_type = "не гибрид";
|
||
}
|
||
|
||
setFormData(updatedFormData);
|
||
}}
|
||
displayEmpty
|
||
label="Тип двигателя"
|
||
name="engine_type"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& .MuiOutlinedInput-notchedOutline": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
"& .MuiSvgIcon-root": {
|
||
fontSize: "2vw",
|
||
color: "#C27664",
|
||
},
|
||
"& .hover": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<MenuItem value="бензиновый">Бензиновый</MenuItem>
|
||
<MenuItem value="дизельный">Дизельный</MenuItem>
|
||
<MenuItem value="электрический">Электрический</MenuItem>
|
||
<MenuItem value="гибридный">Гибридный</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
{/* Поле объёма двигателя - показываем для всех, кроме электрических */}
|
||
{formData.engine_type !== "электрический" && (
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Объём двигателя"
|
||
value={formData.engine_capacity}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<Typography
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.5vw",
|
||
color: "#C27664",
|
||
}}
|
||
>
|
||
см³
|
||
</Typography>
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
)}
|
||
{/* Поле мощности двигателя - показываем для всех, кроме электрических */}
|
||
{formData.engine_type !== "электрический" && (
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Мощность двигателя (л.с.)"
|
||
value={formData.engine_power}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<Typography
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.5vw",
|
||
color: "#C27664",
|
||
}}
|
||
>
|
||
л.с.
|
||
</Typography>
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
)}
|
||
{/* Поле мощности электромотора - показываем только для электрических и гибридных */}
|
||
{(formData.engine_type === "электрический" ||
|
||
formData.engine_type === "гибридный") && (
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Мощность электромотора (кВт)"
|
||
value={formData.electric_motor_power}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<Typography
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.5vw",
|
||
color: "#C27664",
|
||
}}
|
||
>
|
||
кВт
|
||
</Typography>
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
)}
|
||
{/* Тип гибрида - показываем только для гибридов */}
|
||
{formData.engine_type === "гибридный" && (
|
||
<FormControl fullWidth>
|
||
<InputLabel
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
color: "#C27664",
|
||
"&.Mui-focused": { color: "#C27664" },
|
||
}}
|
||
>
|
||
Тип гибрида
|
||
</InputLabel>
|
||
<Select
|
||
value={formData.hybrid_type}
|
||
onChange={(e) =>
|
||
setFormData({
|
||
...formData,
|
||
hybrid_type: e.target.value as string,
|
||
})
|
||
}
|
||
displayEmpty
|
||
label="Тип гибрида"
|
||
name="hybrid_type"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& .MuiOutlinedInput-notchedOutline": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
"& .MuiSvgIcon-root": {
|
||
fontSize: "2vw",
|
||
color: "#C27664",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<MenuItem value="мягкий">Мягкий гибрид (MHEV)</MenuItem>
|
||
<MenuItem value="полный">Полный гибрид (HEV)</MenuItem>
|
||
<MenuItem value="подключаемый">
|
||
Подключаемый гибрид (PHEV)
|
||
</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
)}
|
||
{/* Соотношение мощности - показываем только для гибридов */}
|
||
{formData.engine_type === "гибридный" && (
|
||
<FormControl fullWidth>
|
||
<InputLabel
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
color: "#C27664",
|
||
"&.Mui-focused": { color: "#C27664" },
|
||
}}
|
||
>
|
||
Соотношение мощности
|
||
</InputLabel>
|
||
<Select
|
||
value={formData.power_ratio}
|
||
onChange={(e) =>
|
||
setFormData({
|
||
...formData,
|
||
power_ratio: e.target.value as string,
|
||
})
|
||
}
|
||
displayEmpty
|
||
label="Соотношение мощности"
|
||
name="power_ratio"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& .MuiOutlinedInput-notchedOutline": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
"& .MuiSvgIcon-root": {
|
||
fontSize: "2vw",
|
||
color: "#C27664",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<MenuItem value="не применимо">Не применимо</MenuItem>
|
||
<MenuItem value="среднее">Среднее</MenuItem>
|
||
<MenuItem value="высокое">Высокое</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
)}
|
||
</Grid>
|
||
<Button
|
||
variant="outlined"
|
||
component="label"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
p: "1vw",
|
||
borderColor: "#C27664",
|
||
fontFamily: "Unbounded",
|
||
color: "#C27664",
|
||
"&:hover": {
|
||
borderColor: "#945B4D",
|
||
bgcolor: "rgba(194, 118, 100, 0.1)",
|
||
},
|
||
}}
|
||
fullWidth
|
||
>
|
||
Загрузить изображение
|
||
<input
|
||
type="file"
|
||
hidden
|
||
accept="image/*"
|
||
onChange={handleImageChange}
|
||
/>
|
||
</Button>
|
||
<Grid item xs={12} md={6}>
|
||
<Paper
|
||
elevation={2}
|
||
sx={{
|
||
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)",
|
||
}}
|
||
>
|
||
{imagePreview ? (
|
||
<Box
|
||
component="img"
|
||
src={imagePreview}
|
||
alt="Предпросмотр"
|
||
sx={{
|
||
width: "100%",
|
||
height: "100%",
|
||
objectFit: "contain",
|
||
p: "1vw",
|
||
userSelect: "none",
|
||
pointerEvents: "none",
|
||
}}
|
||
/>
|
||
) : (
|
||
<Typography
|
||
color="text.secondary"
|
||
sx={{
|
||
p: "3vw",
|
||
textAlign: "center",
|
||
color: "white",
|
||
fontFamily: "Unbounded",
|
||
}}
|
||
>
|
||
Предпросмотр изображения
|
||
</Typography>
|
||
)}
|
||
</Paper>
|
||
</Grid>
|
||
</Grid>
|
||
</DialogContent>
|
||
<DialogActions sx={{ p: "1vw", bgcolor: "#f5f5f5" }}>
|
||
<Button
|
||
onClick={handleCloseDialogs}
|
||
sx={{
|
||
color: "black",
|
||
fontFamily: "Unbounded",
|
||
borderRadius: "1vw",
|
||
px: "1vw",
|
||
"&:hover": { bgcolor: "transparent", color: "#C27664" },
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
Отмена
|
||
</Button>
|
||
<Button
|
||
onClick={handleCreateCar}
|
||
disabled={!isFormValid()}
|
||
variant="contained"
|
||
sx={{
|
||
bgcolor: "#C27664",
|
||
color: "white",
|
||
fontFamily: "Unbounded",
|
||
borderRadius: "1vw",
|
||
px: "2vw",
|
||
"&:hover": { bgcolor: "#945B4D" },
|
||
"&.Mui-disabled": {
|
||
bgcolor: "rgba(194, 118, 100, 0.5)",
|
||
},
|
||
}}
|
||
>
|
||
Создать
|
||
</Button>
|
||
</DialogActions>
|
||
</Dialog>
|
||
|
||
{/* Диалог редактирования автомобиля */}
|
||
<Dialog
|
||
open={openEditDialog}
|
||
onClose={handleCloseDialogs}
|
||
maxWidth="md"
|
||
fullWidth
|
||
PaperProps={{
|
||
sx: { borderRadius: "1vw" },
|
||
}}
|
||
>
|
||
<DialogTitle
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
bgcolor: "#2D2D2D",
|
||
color: "white",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: "1vw",
|
||
}}
|
||
>
|
||
<EditIcon /> Редактировать автомобиль
|
||
</DialogTitle>
|
||
<DialogContent sx={{ mt: "1vw" }}>
|
||
<Grid container spacing={3}>
|
||
<Grid
|
||
item
|
||
xs={12}
|
||
md={6}
|
||
style={{
|
||
display: "grid",
|
||
gridTemplateColumns: "repeat(2, 1fr)",
|
||
gap: "1vw",
|
||
}}
|
||
>
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Название автомобиля"
|
||
value={formData.name}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<DirectionsCarIcon sx={{ color: "#C27664" }} />
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Год выпуска"
|
||
value={formData.year}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<CalendarTodayIcon sx={{ color: "#C27664" }} />
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
<TextField
|
||
fullWidth
|
||
name="base_price"
|
||
placeholder="Базовая цена в рублях"
|
||
value={formData.base_price}
|
||
onChange={handleInputChange}
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<Typography
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.5vw",
|
||
color: "#C27664",
|
||
}}
|
||
>
|
||
₽
|
||
</Typography>
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Итоговая цена в рублях"
|
||
value={formData.price}
|
||
disabled
|
||
variant="outlined"
|
||
sx={{
|
||
"& .MuiOutlinedInput-root": {
|
||
borderRadius: "1vw",
|
||
bgcolor: "#f5f5f5",
|
||
height: "4vw",
|
||
width: "100%",
|
||
border: "0.1vw solid #C27664",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& fieldset": {
|
||
border: "none",
|
||
},
|
||
},
|
||
}}
|
||
InputProps={{
|
||
startAdornment: (
|
||
<InputAdornment position="start">
|
||
<Typography
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.5vw",
|
||
color: "#C27664",
|
||
}}
|
||
>
|
||
₽
|
||
</Typography>
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Пробег (км)"
|
||
value={formData.mileage}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<SpeedIcon sx={{ color: "#C27664" }} />
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
<FormControl fullWidth>
|
||
<InputLabel
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
color: "#C27664",
|
||
"&.Mui-focused": { color: "#C27664" },
|
||
}}
|
||
>
|
||
Страна происхождения
|
||
</InputLabel>
|
||
<Select
|
||
value={formData.country_of_origin}
|
||
onChange={handleSelectChange}
|
||
displayEmpty
|
||
label="Страна происхождения"
|
||
name="country_of_origin"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& .MuiOutlinedInput-notchedOutline": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
"& .MuiSvgIcon-root": {
|
||
fontSize: "2vw",
|
||
color: "#C27664",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<MenuItem value="Россия">Россия</MenuItem>
|
||
<MenuItem value="Япония">Япония</MenuItem>
|
||
<MenuItem value="Китай">Китай</MenuItem>
|
||
<MenuItem value="США">США</MenuItem>
|
||
<MenuItem value="Германия">Германия</MenuItem>
|
||
<MenuItem value="Корея">Корея</MenuItem>
|
||
<MenuItem value="Италия">Италия</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
<FormControl fullWidth>
|
||
<InputLabel
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
color: "#C27664",
|
||
"&.Mui-focused": { color: "#C27664" },
|
||
}}
|
||
>
|
||
Тип привода
|
||
</InputLabel>
|
||
<Select
|
||
value={formData.drive_type}
|
||
onChange={handleSelectChange}
|
||
displayEmpty
|
||
label="Тип привода"
|
||
name="drive_type"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& .MuiOutlinedInput-notchedOutline": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
"& .MuiSvgIcon-root": {
|
||
fontSize: "2vw",
|
||
color: "#C27664",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<MenuItem value="FWD">FWD</MenuItem>
|
||
<MenuItem value="RWD">RWD</MenuItem>
|
||
<MenuItem value="4WD">4WD</MenuItem>
|
||
<MenuItem value="AWD">AWD</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
<FormControl fullWidth>
|
||
<InputLabel
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
color: "#C27664",
|
||
"&.Mui-focused": { color: "#C27664" },
|
||
}}
|
||
>
|
||
Тип двигателя
|
||
</InputLabel>
|
||
<Select
|
||
value={formData.engine_type}
|
||
onChange={(e) => {
|
||
const engineType = e.target.value as string;
|
||
const updatedFormData = {
|
||
...formData,
|
||
engine_type: engineType,
|
||
};
|
||
|
||
// Сбрасываем значения полей, которые не нужны для выбранного типа
|
||
if (
|
||
engineType === "бензиновый" ||
|
||
engineType === "дизельный"
|
||
) {
|
||
updatedFormData.electric_motor_power = "";
|
||
updatedFormData.hybrid_type = "не гибрид";
|
||
updatedFormData.power_ratio = "не применимо";
|
||
} else if (engineType === "электрический") {
|
||
updatedFormData.engine_capacity = "";
|
||
updatedFormData.engine_power = "";
|
||
updatedFormData.hybrid_type = "не гибрид";
|
||
}
|
||
|
||
setFormData(updatedFormData);
|
||
}}
|
||
displayEmpty
|
||
label="Тип двигателя"
|
||
name="engine_type"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& .MuiOutlinedInput-notchedOutline": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
"& .MuiSvgIcon-root": {
|
||
fontSize: "2vw",
|
||
color: "#C27664",
|
||
},
|
||
"& .hover": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<MenuItem value="бензиновый">Бензиновый</MenuItem>
|
||
<MenuItem value="дизельный">Дизельный</MenuItem>
|
||
<MenuItem value="электрический">Электрический</MenuItem>
|
||
<MenuItem value="гибридный">Гибридный</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
{/* Поле объёма двигателя - показываем для всех, кроме электрических */}
|
||
{formData.engine_type !== "электрический" && (
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Объём двигателя"
|
||
value={formData.engine_capacity}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<Typography
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.5vw",
|
||
color: "#C27664",
|
||
}}
|
||
>
|
||
л
|
||
</Typography>
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
)}
|
||
{/* Поле мощности двигателя - показываем для всех, кроме электрических */}
|
||
{formData.engine_type !== "электрический" && (
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Мощность двигателя (л.с.)"
|
||
value={formData.engine_power}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<Typography
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.5vw",
|
||
color: "#C27664",
|
||
}}
|
||
>
|
||
л.с.
|
||
</Typography>
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
)}
|
||
{/* Поле мощности электромотора - показываем только для электрических и гибридных */}
|
||
{(formData.engine_type === "электрический" ||
|
||
formData.engine_type === "гибридный") && (
|
||
<TextField
|
||
fullWidth
|
||
placeholder="Мощность электромотора (кВт)"
|
||
value={formData.electric_motor_power}
|
||
onChange={(e) =>
|
||
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: (
|
||
<InputAdornment position="start">
|
||
<Typography
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.5vw",
|
||
color: "#C27664",
|
||
}}
|
||
>
|
||
кВт
|
||
</Typography>
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
)}
|
||
{/* Тип гибрида - показываем только для гибридов */}
|
||
{formData.engine_type === "гибридный" && (
|
||
<FormControl fullWidth>
|
||
<InputLabel
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
color: "#C27664",
|
||
"&.Mui-focused": { color: "#C27664" },
|
||
}}
|
||
>
|
||
Тип гибрида
|
||
</InputLabel>
|
||
<Select
|
||
value={formData.hybrid_type}
|
||
onChange={(e) =>
|
||
setFormData({
|
||
...formData,
|
||
hybrid_type: e.target.value as string,
|
||
})
|
||
}
|
||
displayEmpty
|
||
label="Тип гибрида"
|
||
name="hybrid_type"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& .MuiOutlinedInput-notchedOutline": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
"& .MuiSvgIcon-root": {
|
||
fontSize: "2vw",
|
||
color: "#C27664",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<MenuItem value="мягкий">Мягкий гибрид (MHEV)</MenuItem>
|
||
<MenuItem value="полный">Полный гибрид (HEV)</MenuItem>
|
||
<MenuItem value="подключаемый">
|
||
Подключаемый гибрид (PHEV)
|
||
</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
)}
|
||
{/* Соотношение мощности - показываем только для гибридов */}
|
||
{formData.engine_type === "гибридный" && (
|
||
<FormControl fullWidth>
|
||
<InputLabel
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
color: "#C27664",
|
||
"&.Mui-focused": { color: "#C27664" },
|
||
}}
|
||
>
|
||
Соотношение мощности
|
||
</InputLabel>
|
||
<Select
|
||
value={formData.power_ratio}
|
||
onChange={(e) =>
|
||
setFormData({
|
||
...formData,
|
||
power_ratio: e.target.value as string,
|
||
})
|
||
}
|
||
displayEmpty
|
||
label="Соотношение мощности"
|
||
name="power_ratio"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
"& .MuiOutlinedInput-notchedOutline": {
|
||
border: "0.1vw solid #C27664",
|
||
},
|
||
"& .MuiSvgIcon-root": {
|
||
fontSize: "2vw",
|
||
color: "#C27664",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
<MenuItem value="не применимо">Не применимо</MenuItem>
|
||
<MenuItem value="среднее">Среднее</MenuItem>
|
||
<MenuItem value="высокое">Высокое</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
)}
|
||
|
||
<Button
|
||
variant="outlined"
|
||
component="label"
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
borderRadius: "1vw",
|
||
p: "1vw",
|
||
borderColor: "#C27664",
|
||
color: "#C27664",
|
||
"&:hover": {
|
||
borderColor: "#945B4D",
|
||
bgcolor: "#C27664",
|
||
color: "white",
|
||
},
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
fullWidth
|
||
>
|
||
Изменить изображение
|
||
<input
|
||
type="file"
|
||
hidden
|
||
accept="image/*"
|
||
onChange={handleImageChange}
|
||
/>
|
||
</Button>
|
||
</Grid>
|
||
<Grid item xs={12} md={6}>
|
||
<Paper
|
||
elevation={2}
|
||
sx={{
|
||
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)",
|
||
}}
|
||
>
|
||
{imagePreview ? (
|
||
<Box
|
||
component="img"
|
||
src={imagePreview}
|
||
alt="Предпросмотр"
|
||
sx={{
|
||
width: "100%",
|
||
height: "100%",
|
||
objectFit: "contain",
|
||
p: "1vw",
|
||
userSelect: "none",
|
||
pointerEvents: "none",
|
||
}}
|
||
/>
|
||
) : (
|
||
<Typography
|
||
color="text.secondary"
|
||
sx={{
|
||
p: "3vw",
|
||
textAlign: "center",
|
||
color: "white",
|
||
fontFamily: "Unbounded",
|
||
}}
|
||
>
|
||
Предпросмотр изображения
|
||
</Typography>
|
||
)}
|
||
</Paper>
|
||
</Grid>
|
||
</Grid>
|
||
</DialogContent>
|
||
<DialogActions sx={{ p: "1vw", bgcolor: "#f5f5f5" }}>
|
||
<Button
|
||
onClick={handleCloseDialogs}
|
||
sx={{
|
||
color: "black",
|
||
fontFamily: "Unbounded",
|
||
borderRadius: "1vw",
|
||
px: "1vw",
|
||
"&:hover": { bgcolor: "transparent", color: "#C27664" },
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
Отмена
|
||
</Button>
|
||
<Button
|
||
onClick={handleUpdateCar}
|
||
disabled={!isFormValid()}
|
||
variant="contained"
|
||
sx={{
|
||
bgcolor: "#C27664",
|
||
color: "white",
|
||
fontFamily: "Unbounded",
|
||
borderRadius: "1vw",
|
||
px: "2vw",
|
||
"&:hover": { bgcolor: "#945B4D" },
|
||
"&.Mui-disabled": {
|
||
bgcolor: "rgba(194, 118, 100, 0.5)",
|
||
},
|
||
}}
|
||
>
|
||
Сохранить
|
||
</Button>
|
||
</DialogActions>
|
||
</Dialog>
|
||
|
||
{/* Диалог удаления автомобиля */}
|
||
<Dialog
|
||
open={openDeleteDialog}
|
||
onClose={handleCloseDialogs}
|
||
PaperProps={{
|
||
sx: { borderRadius: "1vw", maxWidth: "40vw", overflow: "hidden" },
|
||
}}
|
||
>
|
||
<DialogTitle
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
bgcolor: "#2D2D2D",
|
||
color: "white",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: "1vw",
|
||
}}
|
||
>
|
||
<DeleteIcon /> Удалить автомобиль
|
||
</DialogTitle>
|
||
<DialogContent sx={{ mt: "1vw", minWidth: "40vw" }}>
|
||
<Box sx={{ display: "flex", alignItems: "center", mb: "1vw" }}>
|
||
{selectedCar && (
|
||
<Box
|
||
component="img"
|
||
src={getImageUrl(selectedCar.image)}
|
||
alt={selectedCar.name}
|
||
sx={{
|
||
width: "10vw",
|
||
height: "5vw",
|
||
objectFit: "cover",
|
||
borderRadius: "1vw",
|
||
mr: "1vw",
|
||
pointerEvents: "none",
|
||
userSelect: "none",
|
||
}}
|
||
/>
|
||
)}
|
||
<Box>
|
||
<Typography
|
||
variant="h6"
|
||
sx={{ fontWeight: "bold", fontFamily: "Unbounded" }}
|
||
>
|
||
{selectedCar?.name}
|
||
</Typography>
|
||
{selectedCar && (
|
||
<Typography
|
||
variant="body2"
|
||
color="text.secondary"
|
||
sx={{ fontFamily: "Unbounded" }}
|
||
>
|
||
{selectedCar.year} г., {selectedCar.mileage} км,{" "}
|
||
{formatPrice(selectedCar.price)}
|
||
</Typography>
|
||
)}
|
||
</Box>
|
||
</Box>
|
||
|
||
<Alert severity="warning" sx={{ mt: "1vw", fontFamily: "Unbounded" }}>
|
||
Вы уверены, что хотите удалить этот автомобиль? Это действие нельзя
|
||
отменить.
|
||
</Alert>
|
||
</DialogContent>
|
||
<DialogActions sx={{ p: "1vw", bgcolor: "#f5f5f5" }}>
|
||
<Button
|
||
onClick={handleCloseDialogs}
|
||
sx={{
|
||
color: "black",
|
||
borderRadius: "1vw",
|
||
px: "1vw",
|
||
fontFamily: "Unbounded",
|
||
"&:hover": { bgcolor: "transparent", color: "#C27664" },
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
Отмена
|
||
</Button>
|
||
<Button
|
||
onClick={handleDeleteCar}
|
||
variant="contained"
|
||
color="error"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
px: "2vw",
|
||
fontFamily: "Unbounded",
|
||
bgcolor: "#C27664",
|
||
color: "white",
|
||
"&:hover": { bgcolor: "#945B4D" },
|
||
transition: "all 0.2s ease",
|
||
}}
|
||
>
|
||
Удалить
|
||
</Button>
|
||
</DialogActions>
|
||
</Dialog>
|
||
</Box>
|
||
);
|
||
};
|
||
|
||
export default Vehicle;
|