1415 lines
48 KiB
TypeScript
1415 lines
48 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: '',
|
||
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 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;
|
||
setFormData({
|
||
...formData,
|
||
[name]: value
|
||
});
|
||
};
|
||
|
||
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: '',
|
||
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 || '',
|
||
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: 2,
|
||
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 sx={{ p: 3 }}>
|
||
{/* Заголовок и кнопки управления */}
|
||
<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 item xs={12} md={6}>
|
||
{/* <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",
|
||
mb: "1vw",
|
||
"& 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",
|
||
mb: "1vw",
|
||
"& 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
|
||
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",
|
||
mb: "1vw",
|
||
"& fieldset": {
|
||
border: "none",
|
||
},
|
||
},
|
||
}}
|
||
InputProps={{
|
||
startAdornment: (
|
||
<InputAdornment position="start">
|
||
<SpeedIcon sx={{ color: "#C27664" }} />
|
||
</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
|
||
placeholder="Цена в рублях"
|
||
value={formData.price}
|
||
onChange={(e) => setFormData({ ...formData, price: 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",
|
||
mb: "1vw",
|
||
"& fieldset": {
|
||
border: "none",
|
||
},
|
||
},
|
||
}}
|
||
InputProps={{
|
||
startAdornment: (
|
||
<InputAdornment position="start">
|
||
<Typography
|
||
sx={{
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.5vw",
|
||
color: "#C27664",
|
||
}}
|
||
>
|
||
₽
|
||
</Typography>
|
||
</InputAdornment>
|
||
),
|
||
}}
|
||
/>
|
||
<FormControl fullWidth>
|
||
<InputLabel sx={{ fontFamily: "Unbounded", color: "#C27664", '&.Mui-focused': { color: "#C27664" } }}>Страна происхождения</InputLabel>
|
||
<Select
|
||
value={formData.country_of_origin}
|
||
onChange={(e) => setFormData({ ...formData, country_of_origin: e.target.value as string })}
|
||
displayEmpty
|
||
label="Страна происхождения"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
mb: "1vw",
|
||
"& .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>
|
||
|
||
</Select>
|
||
</FormControl>
|
||
<FormControl fullWidth>
|
||
<InputLabel sx={{ fontFamily: "Unbounded", color: "#C27664", '&.Mui-focused': { color: "#C27664" } }}>Тип привода</InputLabel>
|
||
<Select
|
||
value={formData.drive_type}
|
||
onChange={(e) => setFormData({ ...formData, drive_type: e.target.value as string })}
|
||
displayEmpty
|
||
label="Тип привода"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
mb: "1vw",
|
||
"& .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) => setFormData({ ...formData, engine_type: e.target.value as string })}
|
||
displayEmpty
|
||
label="Тип двигателя"
|
||
sx={{
|
||
borderRadius: "1vw",
|
||
bgcolor: "white",
|
||
height: "4vw",
|
||
width: "100%",
|
||
fontFamily: "Unbounded",
|
||
fontSize: "1.2vw",
|
||
color: "#C27664",
|
||
mb: "1vw",
|
||
"& .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>
|
||
</Select>
|
||
</FormControl>
|
||
{/* <TextField
|
||
name="engine_capacity"
|
||
label="Объем двигателя (л)"
|
||
type="number"
|
||
value={formData.engine_capacity}
|
||
sx={{ label: { fontFamily: "Unbounded" }, input: { fontFamily: "Unbounded" } }}
|
||
onChange={handleInputChange}
|
||
fullWidth
|
||
margin="normal"
|
||
variant="outlined"
|
||
/> */}
|
||
<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>
|
||
),
|
||
}}
|
||
/>
|
||
<Button
|
||
variant="outlined"
|
||
component="label"
|
||
sx={{
|
||
mt: "1vw",
|
||
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>
|
||
<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}>
|
||
<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
|
||
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
|
||
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>
|
||
),
|
||
}}
|
||
/>
|
||
<Button
|
||
variant="outlined"
|
||
component="label"
|
||
sx={{
|
||
mt: "1vw",
|
||
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" }
|
||
}}
|
||
>
|
||
<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; |