-lib
| - helpers
| - utils
const fetchUsers = async () => {
setLoading(true) // mobx
try {
const response = await fetchUsers() // api
setusers(response) // mobx
} catch(e) {
setError(e.message) // mobx
} finally {
setLoading(false) // mobx
}
}
import { AnimatePresence, motion } from "framer-motion";
import { useEffect, useState } from "react";
import { MenuList } from "@features/sidebar";
import { MakeOrderButton, PersonalAccount } from "@entities/sidebar";
import { LogotypeIcon } from "@shared/images";
import { useScreenResolution } from "@shared/libs/global";
import { BurgerIcon, HorizontalLine } from "@shared/ui";
import classes from "./Sidebar.module.scss";
const initialSidebarAnimate = {
x: -100,
opacity: 0,
};
const animateSidebarAnimate = {
x: 0,
opacity: 1,
};
const exitSidebarAnimate = {
x: -100,
opacity: 0,
};
const transitionSidebarAnimate = {
x: -100,
opacity: 0,
};
export const Sidebar = () => {
const [active, setActive] = useState<boolean>(false);
const [isMobile, setIsMobile] = useState(false);
const mobile = useScreenResolution();
const handlerBurgerMenu = () => setActive((state) => !state);
useEffect(() => {
setIsMobile(mobile);
}, [mobile]);
return (
<>
<BurgerIcon onClick={handlerBurgerMenu} active={active} />
<AnimatePresence>
{(!isMobile || (isMobile && active)) && (
<motion.header
transition={transitionSidebarAnimate}
initial={initialSidebarAnimate}
animate={animateSidebarAnimate}
exit={exitSidebarAnimate}
className={classes.headerSidebar}
>
<LogotypeIcon className={classes.logotypeSidebar} />
<MakeOrderButton className={classes.orderButton} />
<HorizontalLine />
<MenuList className={classes.menuList} />
<HorizontalLine />
<PersonalAccount className={classes.personalAccount} />
</motion.header>
)}
</AnimatePresence>
</>
);
};
const handlerDropAndDrop: DragEventHandler = async (
event: DragEvent<HTMLDataElement>,
) => {
event.preventDefault();
const url = event.dataTransfer.getData("URL"); // Получаем src из фото, после чего закидываем его в функцию добавления картинки
if (url) editorApi.addImage(url);
};
import { ContentState } from "draft-js";
import * as React from "react";
import classes from "./Image.module.scss";
type LinkProps = {
contentState: ContentState;
entityKey: string;
};
const Image: React.FC<LinkProps> = ({ contentState, entityKey }) => {
/* Получаем url с помощью уникального ключа Entity */
const { url } = contentState.getEntity(entityKey).getData();
return (
<img data-key={entityKey} className={classes.imageStyle} src={url} alt="" />
);
};
export default Image;
data-key={entityKey}
через который мы будем получать entityKey и через него же будем удалять картинку. Добавим еще одну функцию обработчикconst handlerDragAndDropExit: DragEventHandler = (
event: DragEvent<HTMLDivElement>,
) => {
event.preventDefault();
const targetElement = event.target as HTMLElement; // Получаем тег img
const entityKey = targetElement.getAttribute("data-key"); // Получаем у него наш entityKey
if (entityKey) editorApi.removeImage(entityKey); передаем его в функцию удаления картинки
};
// Удаление картинки по его entityKey
const removeImage = React.useCallback(
(entityKey: string) => {
setState((currentState) => {
const contentState = currentState.getCurrentContent();
const blockMap = contentState.getBlockMap();
// Создаем новый массив блоков, исключая блок с указанным entityKey или блок без типа EntityType.image
const newBlockMap: ContentBlock[] = [];
blockMap.forEach((block) => {
if (
block &&
(block.getEntityAt(0) !== entityKey || block.getType() !== "atomic")
) {
newBlockMap.push(block);
}
});
const newContentState = ContentState.createFromBlockArray(newBlockMap);
return EditorState.push(currentState, newContentState, "remove-range");
});
},
[setState],
);
<div
className={classes.textArea}
onDrop={handlerDropAndDrop}
onDragEnd={handlerDragAndDropExit}
>
<Editor
ref={ref}
placeholder={"Описание поста"}
editorState={editorApi.state}
onChange={editorApi.onChange}
/>
</div>
// index.d.ts
declare module "custom-editor-lib" {
import { ComponentType, Dispatch, SetStateAction } from "react";
import { EditorState } from "draft-js";
export interface EditorProps {
value: EditorState;
onChange: Dispatch<SetStateAction<EditorState>>;
}
export const Editor: ComponentType<EditorProps>;
export function stateToHTML(editorState: EditorState): string;
export function HTMLtoState(html: string): EditorState;
}
import {Link, Outlet} from "react-router-dom";
<Routes>
<Route path='/settings' element={<Header />}>
<Route index path='create' element={<CreateFieldProvider/>}/>
<Route path='lists' element={<FieldsList/>}/>
</Route>
<Route path={'/work'} element={<Work/>}/>
</Routes>
<>
<header>
<div className="content">
<div className={classes.header_wrapper}>
<div className={classes.wrapper_logo}>
<img src="/image/logo.png" alt=""/>
</div>
<div className={classes.wrapper_list}>
<Link to='/settings'>Главная</Link>
<Link to='/settings/create'>Создать </Link>
<Link to='/settings/lists'>Список </Link>
</div>
</div>
</div>
</header>
{(loading_list || loading_create) && <Preloader />}
<Outlet />
</>