import { Button, Paper, TextField, Checkbox, Typography, Box, Table, TableBody, TableCell, TableHead, TableRow, Radio, RadioGroup, Divider, } from "@mui/material"; import { observer } from "mobx-react-lite"; import { ArrowLeft, Loader2, Save } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { toast } from "react-toastify"; import { userStore, mediaStore, isMediaIdEmpty, SelectMediaDialog, UploadMediaDialog, PreviewMediaDialog, } from "@shared"; import { useState, useEffect } from "react"; import { ImageUploadCard } from "@widgets"; const ROLE_RESOURCES = [ { key: "snapshot", label: "Экспорт" }, { key: "devices", label: "Устройства" }, { key: "vehicles", label: "Транспорт" }, { key: "users", label: "Пользователи" }, { key: "sights", label: "Достопримечательности" }, { key: "stations", label: "Остановки" }, { key: "routes", label: "Маршруты" }, { key: "countries", label: "Страны" }, { key: "cities", label: "Города" }, { key: "carriers", label: "Перевозчики" }, ] as const; type PermissionLevel = "none" | "ro" | "rw"; function getPermissionLevel(roles: string[], resource: string): PermissionLevel { if (roles.includes(`${resource}_rw`)) return "rw"; if (roles.includes(`${resource}_ro`)) return "ro"; return "none"; } function applyPermissionChange( roles: string[], resource: string, level: PermissionLevel, ): string[] { const filtered = roles.filter( (r) => r !== `${resource}_ro` && r !== `${resource}_rw`, ); if (level === "ro") return [...filtered, `${resource}_ro`]; if (level === "rw") return [...filtered, `${resource}_rw`]; return filtered; } export const UserCreatePage = observer(() => { const navigate = useNavigate(); const { createUserData, setCreateUserData, createUser } = userStore; const [isLoading, setIsLoading] = useState(false); const [isSelectMediaOpen, setIsSelectMediaOpen] = useState(false); const [isUploadMediaOpen, setIsUploadMediaOpen] = useState(false); const [isPreviewMediaOpen, setIsPreviewMediaOpen] = useState(false); const [mediaId, setMediaId] = useState(""); const [activeMenuType, setActiveMenuType] = useState< "thumbnail" | "watermark_lu" | "watermark_rd" | "image" | null >(null); const [localRoles, setLocalRoles] = useState( createUserData.roles ?? ["articles_ro", "articles_rw", "media_ro", "media_rw"] ); useEffect(() => { mediaStore.getMedia(); }, []); useEffect(() => { const allRw = ROLE_RESOURCES.every(({ key }) => localRoles.includes(`${key}_rw`)); const isAdmin = allRw && !localRoles.includes("devices_maintenance_rw"); if (isAdmin !== createUserData.is_admin) { setCreateUserData( createUserData.name || "", createUserData.email || "", createUserData.password || "", isAdmin, createUserData.icon ); } }, [localRoles]); const handleCreate = async () => { try { setIsLoading(true); // Убеждаемся, что роли в сторе обновлены перед созданием userStore.createUserData.roles = localRoles; await createUser(); toast.success("Пользователь успешно создан"); navigate("/user"); } catch (error) { toast.error("Ошибка при создании пользователя"); } finally { setIsLoading(false); } }; const handleMediaSelect = (media: { id: string; filename: string; media_name?: string; media_type: number; }) => { setCreateUserData( createUserData.name || "", createUserData.email || "", createUserData.password || "", createUserData.is_admin || false, media.id ); }; const selectedMedia = createUserData.icon && !isMediaIdEmpty(createUserData.icon) ? mediaStore.media.find((m) => m.id === createUserData.icon) : null; const effectiveIconUrl = isMediaIdEmpty(createUserData.icon) ? null : selectedMedia?.id ?? createUserData.icon ?? null; return (
Основные данные setCreateUserData( e.target.value, createUserData.email || "", createUserData.password || "", createUserData.is_admin || false, createUserData.icon ) } /> setCreateUserData( createUserData.name || "", e.target.value, createUserData.password || "", createUserData.is_admin || false, createUserData.icon ) } /> setCreateUserData( createUserData.name || "", createUserData.email || "", e.target.value, createUserData.is_admin || false, createUserData.icon ) } />
{ setIsPreviewMediaOpen(true); setMediaId(effectiveIconUrl ?? ""); }} onDeleteImageClick={() => { setCreateUserData( createUserData.name || "", createUserData.email || "", createUserData.password || "", createUserData.is_admin || false, "" ); setActiveMenuType(null); }} onSelectFileClick={() => { setActiveMenuType("image"); setIsSelectMediaOpen(true); }} setUploadMediaOpen={() => { setIsUploadMediaOpen(true); setActiveMenuType("image"); }} />
Права доступа Ресурс Нет доступа Чтение Чтение/Запись Доп. права {ROLE_RESOURCES.map(({ key, label }) => { const level = getPermissionLevel(localRoles, key); const isSnapshotResource = key === "snapshot"; const handleChange = (val: string) => { setLocalRoles((prev) => { let updated = applyPermissionChange(prev, key, val as PermissionLevel); if (key === "devices") { updated = applyPermissionChange( updated, "vehicles", val as PermissionLevel, ); } return updated; }); }; const isDevicesResource = key === "devices"; const handleSnapshotCreateChange = (checked: boolean) => { if (!isSnapshotResource) { return; } setLocalRoles((prev) => { const withoutSnapshotCreate = prev.filter( (role) => role !== "snapshot_create" ); return checked ? [...withoutSnapshotCreate, "snapshot_create"] : withoutSnapshotCreate; }); }; const handleMaintenanceChange = (checked: boolean) => { setLocalRoles((prev) => { const without = prev.filter((r) => r !== "devices_maintenance_rw"); return checked ? [...without, "devices_maintenance_rw"] : without; }); }; return ( {label} handleChange(e.target.value)} sx={{ justifyContent: "center", flexWrap: "nowrap" }} > {isSnapshotResource ? ( - ) : ( handleChange(e.target.value)} sx={{ justifyContent: "center", flexWrap: "nowrap" }} > )} handleChange(e.target.value)} sx={{ justifyContent: "center", flexWrap: "nowrap" }} > {isSnapshotResource ? ( handleSnapshotCreateChange(e.target.checked) } size="small" title="Разрешает создавать новые снапшоты" /> ) : isDevicesResource ? ( handleMaintenanceChange(e.target.checked)} size="small" title="Техническое обслуживание (ТО)" /> ) : ( - )} ); })}
setIsSelectMediaOpen(false)} onSelectMedia={handleMediaSelect} mediaType={1} /> setIsUploadMediaOpen(false)} contextObjectName={createUserData.name || "Пользователь"} contextType="user" afterUpload={handleMediaSelect} hardcodeType={activeMenuType} /> setIsPreviewMediaOpen(false)} mediaId={mediaId} />
); });