import { Button, Paper, TextField, Select, MenuItem, FormControl, InputLabel, Box, } 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, authStore, mediaStore, languageStore, isMediaIdEmpty, LoadingSpinner, } from "@shared"; import { useState, useEffect } from "react"; import { ImageUploadCard, LanguageSwitcher, DeleteModal } from "@widgets"; import { SelectMediaDialog, PreviewMediaDialog, UploadMediaDialog, } from "@shared"; type ColorFields = { main_color: string; left_color: string; right_color: string }; const colorFields = (data: ColorFields) => ({ main_color: data.main_color, left_color: data.left_color, right_color: data.right_color, }); const ColorPickerField = ({ label, value, onChange, }: { label: string; value: string; onChange: (val: string) => void; }) => (
onChange(e.target.value)} className="absolute inset-0 w-full h-full opacity-0 cursor-pointer" />
onChange(e.target.value)} InputProps={{ endAdornment: value ? ( ) : undefined, }} />
); export const CarrierEditPage = observer(() => { const navigate = useNavigate(); const { id } = useParams(); const { getCarrier, setEditCarrierData, editCarrierData } = carrierStore; const { language } = languageStore; const canReadCities = authStore.canRead("cities"); const [isLoading, setIsLoading] = useState(false); const [isLoadingData, setIsLoadingData] = useState(true); const [isSelectMediaOpen, setIsSelectMediaOpen] = useState(false); const [isUploadMediaOpen, setIsUploadMediaOpen] = useState(false); const [isPreviewMediaOpen, setIsPreviewMediaOpen] = useState(false); const [mediaId, setMediaId] = useState(""); const [isDeleteLogoModalOpen, setIsDeleteLogoModalOpen] = useState(false); const [initialCityName, setInitialCityName] = useState(""); const [activeMenuType, setActiveMenuType] = useState< "thumbnail" | "watermark_lu" | "watermark_rd" | "image" | null >(null); useEffect(() => { (async () => { if (!id) { setIsLoadingData(false); return; } setIsLoadingData(true); try { if (!authStore.me) { await authStore.getMeAction().catch(() => undefined); } if (authStore.canRead("cities")) { await cityStore.getCities("ru"); } else { await authStore.fetchMeCities().catch(() => undefined); } const carrierData = await getCarrier(Number(id)); if (carrierData) { const colors = { main_color: carrierData.ru?.main_color || "", left_color: carrierData.ru?.left_color || "", right_color: carrierData.ru?.right_color || "", }; setEditCarrierData( carrierData.ru?.full_name || "", carrierData.ru?.short_name || "", carrierData.ru?.city_id || 0, carrierData.ru?.slogan || "", carrierData.ru?.logo || "", "ru", colors ); setEditCarrierData( carrierData.en?.full_name || "", carrierData.en?.short_name || "", carrierData.en?.city_id || 0, carrierData.en?.slogan || "", carrierData.en?.logo || "", "en" ); setEditCarrierData( carrierData.zh?.full_name || "", carrierData.zh?.short_name || "", carrierData.zh?.city_id || 0, carrierData.zh?.slogan || "", carrierData.zh?.logo || "", "zh" ); setInitialCityName(carrierData.ru?.city || ""); } await mediaStore.getMedia(); } finally { setIsLoadingData(false); } })(); languageStore.setLanguage("ru"); }, [id]); const handleEdit = async () => { try { setIsLoading(true); await carrierStore.editCarrier(Number(id)); toast.success("Перевозчик успешно обновлен"); navigate("/carrier"); } catch (error) { toast.error("Ошибка при обновлении перевозчика"); } finally { setIsLoading(false); } }; const handleMediaSelect = (media: { id: string; filename: string; media_name?: string; media_type: number; }) => { setEditCarrierData( editCarrierData[language].full_name, editCarrierData[language].short_name, editCarrierData.city_id, editCarrierData[language].slogan, media.id, language ); }; const selectedMedia = editCarrierData.logo && !isMediaIdEmpty(editCarrierData.logo) ? mediaStore.media.find((m) => m.id === editCarrierData.logo) : null; const effectiveLogoUrl = isMediaIdEmpty(editCarrierData.logo) ? null : (selectedMedia?.id ?? editCarrierData.logo); const baseCities = canReadCities ? cityStore.cities["ru"].data : authStore.meCities["ru"].map((city) => ({ id: city.city_id, name: city.name, country: "", country_code: "", arms: "", })); const availableCities = editCarrierData.city_id && !baseCities.some((city) => city.id === editCarrierData.city_id) ? [ { id: editCarrierData.city_id, name: initialCityName || `Город ${editCarrierData.city_id}`, country: "", country_code: "", arms: "", }, ...baseCities, ] : baseCities; if (isLoadingData) { return ( ); } return (

{editCarrierData.ru.full_name}

Город setEditCarrierData( e.target.value, editCarrierData[language].short_name, editCarrierData.city_id, editCarrierData[language].slogan, editCarrierData.logo, language ) } /> setEditCarrierData( editCarrierData[language].full_name, e.target.value, editCarrierData.city_id, editCarrierData[language].slogan, editCarrierData.logo, language ) } /> setEditCarrierData( editCarrierData[language].full_name, editCarrierData[language].short_name, editCarrierData.city_id, e.target.value, editCarrierData.logo, language ) } />
setEditCarrierData( editCarrierData[language].full_name, editCarrierData[language].short_name, editCarrierData.city_id, editCarrierData[language].slogan, editCarrierData.logo, language, { ...colorFields(editCarrierData), main_color: val } ) } />

Используется в: виджет маршрута, виджет обращений, значки на карте, скопление достопримечательностей на карте, информационный виджет

setEditCarrierData( editCarrierData[language].full_name, editCarrierData[language].short_name, editCarrierData.city_id, editCarrierData[language].slogan, editCarrierData.logo, language, { ...colorFields(editCarrierData), left_color: val } ) } />

Используется в: боковое меню, левый виджет достопримечательности

setEditCarrierData( editCarrierData[language].full_name, editCarrierData[language].short_name, editCarrierData.city_id, editCarrierData[language].slogan, editCarrierData.logo, language, { ...colorFields(editCarrierData), right_color: val } ) } />

Используется в: список достопримечательностей, страница достопримечательности

{ setIsPreviewMediaOpen(true); setMediaId(effectiveLogoUrl ?? ""); }} onDeleteImageClick={() => { setIsDeleteLogoModalOpen(true); }} onSelectFileClick={() => { setActiveMenuType("image"); setIsSelectMediaOpen(true); }} setUploadMediaOpen={() => { setIsUploadMediaOpen(true); setActiveMenuType("image"); }} />
setIsSelectMediaOpen(false)} onSelectMedia={handleMediaSelect} mediaType={1} /> setIsUploadMediaOpen(false)} contextObjectName={editCarrierData[language].full_name} contextType="carrier" afterUpload={handleMediaSelect} hardcodeType={activeMenuType} /> setIsPreviewMediaOpen(false)} mediaId={mediaId} /> { setEditCarrierData( editCarrierData[language].full_name, editCarrierData[language].short_name, editCarrierData.city_id, editCarrierData[language].slogan, "", language ); setIsDeleteLogoModalOpen(false); }} onCancel={() => setIsDeleteLogoModalOpen(false)} edit />
); });