feat: Add edit pages with cache

This commit is contained in:
2025-06-08 08:33:43 +03:00
parent e37f9e14bc
commit b09c1b3214
37 changed files with 2223 additions and 772 deletions

View File

@@ -0,0 +1,307 @@
import {
Button,
Paper,
TextField,
Select,
MenuItem,
FormControl,
InputLabel,
} from "@mui/material";
import { observer } from "mobx-react-lite";
import { ArrowLeft, Save } from "lucide-react";
import { Loader2 } from "lucide-react";
import { useNavigate, useParams } from "react-router-dom";
import { toast } from "react-toastify";
import { carrierStore, cityStore, mediaStore } from "@shared";
import { useState, useEffect } from "react";
import { MediaViewer } from "@widgets";
export const CarrierEditPage = observer(() => {
const navigate = useNavigate();
const { id } = useParams();
const { carrier, getCarrier, setEditCarrierData, editCarrierData } =
carrierStore;
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
(async () => {
await getCarrier(Number(id));
setEditCarrierData(
carrier?.[Number(id)]?.full_name as string,
carrier?.[Number(id)]?.short_name as string,
carrier?.[Number(id)]?.city as string,
carrier?.[Number(id)]?.city_id as number,
carrier?.[Number(id)]?.main_color as string,
carrier?.[Number(id)]?.left_color as string,
carrier?.[Number(id)]?.right_color as string,
carrier?.[Number(id)]?.slogan as string,
carrier?.[Number(id)]?.logo as string
);
cityStore.getCities("ru");
mediaStore.getMedia();
})();
}, [id]);
const handleEdit = async () => {
try {
setIsLoading(true);
await carrierStore.editCarrier(Number(id));
toast.success("Перевозчик успешно обновлен");
navigate("/carrier");
} catch (error) {
toast.error("Ошибка при обновлении перевозчика");
} finally {
setIsLoading(false);
}
};
return (
<Paper className="w-full h-full p-3 flex flex-col gap-10">
<div className="flex items-center gap-4">
<button
className="flex items-center gap-2"
onClick={() => navigate("/carrier")}
>
<ArrowLeft size={20} />
Назад
</button>
</div>
<div className="flex flex-col gap-10 w-full items-end">
<FormControl fullWidth>
<InputLabel>Город</InputLabel>
<Select
value={editCarrierData.city_id || ""}
label="Город"
required
onChange={(e) =>
setEditCarrierData(
editCarrierData.full_name,
editCarrierData.short_name,
editCarrierData.city,
Number(e.target.value),
editCarrierData.main_color,
editCarrierData.left_color,
editCarrierData.right_color,
editCarrierData.slogan,
editCarrierData.logo
)
}
>
{cityStore.cities.ru.map((city) => (
<MenuItem key={city.id} value={city.id}>
{city.name}
</MenuItem>
))}
</Select>
</FormControl>
<TextField
fullWidth
label="Полное название"
value={editCarrierData.full_name}
required
onChange={(e) =>
setEditCarrierData(
e.target.value,
editCarrierData.short_name,
editCarrierData.city,
editCarrierData.city_id,
editCarrierData.main_color,
editCarrierData.left_color,
editCarrierData.right_color,
editCarrierData.slogan,
editCarrierData.logo
)
}
/>
<TextField
fullWidth
label="Короткое название"
value={editCarrierData.short_name}
required
onChange={(e) =>
setEditCarrierData(
editCarrierData.full_name,
e.target.value,
editCarrierData.city,
editCarrierData.city_id,
editCarrierData.main_color,
editCarrierData.left_color,
editCarrierData.right_color,
editCarrierData.slogan,
editCarrierData.logo
)
}
/>
<div className="flex gap-4 w-full">
<TextField
fullWidth
label="Основной цвет"
value={editCarrierData.main_color}
className="flex-1 w-full"
onChange={(e) =>
setEditCarrierData(
editCarrierData.full_name,
editCarrierData.short_name,
editCarrierData.city,
editCarrierData.city_id,
e.target.value,
editCarrierData.left_color,
editCarrierData.right_color,
editCarrierData.slogan,
editCarrierData.logo
)
}
type="color"
sx={{
"& input": {
height: "50px",
paddingBlock: "14px",
paddingInline: "14px",
cursor: "pointer",
},
}}
/>
<TextField
fullWidth
label="Цвет левого виджета"
value={editCarrierData.left_color}
className="flex-1 w-full"
onChange={(e) =>
setEditCarrierData(
editCarrierData.full_name,
editCarrierData.short_name,
editCarrierData.city,
editCarrierData.city_id,
editCarrierData.main_color,
e.target.value,
editCarrierData.right_color,
editCarrierData.slogan,
editCarrierData.logo
)
}
type="color"
sx={{
"& input": {
height: "50px",
paddingBlock: "14px",
paddingInline: "14px",
cursor: "pointer",
},
}}
/>
<TextField
fullWidth
label="Цвет правого виджета"
value={editCarrierData.right_color}
className="flex-1 w-full"
onChange={(e) =>
setEditCarrierData(
editCarrierData.full_name,
editCarrierData.short_name,
editCarrierData.city,
editCarrierData.city_id,
editCarrierData.main_color,
editCarrierData.left_color,
e.target.value,
editCarrierData.slogan,
editCarrierData.logo
)
}
type="color"
sx={{
"& input": {
height: "50px",
paddingBlock: "14px",
paddingInline: "14px",
cursor: "pointer",
},
}}
/>
</div>
<TextField
fullWidth
label="Слоган"
value={editCarrierData.slogan}
onChange={(e) =>
setEditCarrierData(
editCarrierData.full_name,
editCarrierData.short_name,
editCarrierData.city,
editCarrierData.city_id,
editCarrierData.main_color,
editCarrierData.left_color,
editCarrierData.right_color,
e.target.value,
editCarrierData.logo
)
}
/>
<div className="w-full flex flex-col gap-4">
<FormControl fullWidth>
<InputLabel>Логотип</InputLabel>
<Select
value={editCarrierData.logo || ""}
label="Логотип"
required
onChange={(e) =>
setEditCarrierData(
editCarrierData.full_name,
editCarrierData.short_name,
editCarrierData.city,
editCarrierData.city_id,
editCarrierData.main_color,
editCarrierData.left_color,
editCarrierData.right_color,
editCarrierData.slogan,
e.target.value as string
)
}
>
{mediaStore.media
.filter((media) => media.media_type === 3)
.map((media) => (
<MenuItem key={media.id} value={media.id}>
{media.media_name || media.filename}
</MenuItem>
))}
</Select>
</FormControl>
{editCarrierData.logo && (
<div className="w-32 h-32">
<MediaViewer
media={{ id: editCarrierData.logo, media_type: 1 }}
/>
</div>
)}
</div>
<Button
variant="contained"
className="w-min flex gap-2 items-center"
startIcon={<Save size={20} />}
onClick={handleEdit}
disabled={
isLoading ||
!editCarrierData.full_name ||
!editCarrierData.short_name ||
!editCarrierData.city_id ||
!editCarrierData.logo
}
>
{isLoading ? (
<Loader2 size={20} className="animate-spin" />
) : (
"Обновить"
)}
</Button>
</div>
</Paper>
);
});