@@ -10,7 +10,11 @@ export default function Title(props: any) { {' '} - {props.type} •{' '} + {props.linkBack && props.linkBack !== '' ? ( + {props.type} + ) : ( + {props.type} + )} •{' '}  {props.title} @@ -1,7 +1,7 @@ import * as React from 'react' import { useEffect, useState } from 'react' import { useDispatch } from 'react-redux' -import { Box, Stack } from '@mui/material' +import { Box, Stack, Typography } from '@mui/material' import Image from 'next/image' import Link from 'next/link' import { useRouter } from 'next/router' @@ -22,13 +22,9 @@ import { SettingsBlockMock } from '@/src/shared/ui/mocks/settings-block-mock' import { CopyEndpoints } from '@/src/widgets/copy/api/copy-endpoints' import { editorEndpoints } from '@/src/widgets/copy/api/editor-endpoints' import { DraftRequestBody, EditorCopywrite } from '@/src/widgets/copy/api/models' -import { copyText } from '@/src/widgets/copy/lib/copy' import { CopyButton } from '@/src/widgets/copy/ui/buttons/copy-button' import { MobileButtons } from '@/src/widgets/copy/ui/buttons/mobile-buttons' -import { CopyDropdownMenu } from '@/src/widgets/copy/ui/dropdown/copy-dropdown-menu' import { EditorWrap } from '@/src/widgets/copy/ui/editor-wrap' -import { CopyIcon } from '@/src/widgets/copy/ui/icons/copy-icon' -import { DownloadIcon } from '@/src/widgets/copy/ui/icons/download-icon' import styles from '@/src/widgets/copy/ui/styles/copywrite.module.scss' import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css' @@ -61,7 +57,9 @@ export default function Index({ device, deviceOs }: IFuncProps) { input_content: input_content, } editorEndpoints.UpdateCopywriteContent(uuid, req_body, data?.access).then(() => { - CopyEndpoints.GenerateResponse(uuid, data?.access).then(() => addQueryParams('resp')) + CopyEndpoints.GenerateResponse(uuid, data?.access).then(() => { + addQueryParams('resp') + }) }) } } @@ -89,11 +87,11 @@ export default function Index({ device, deviceOs }: IFuncProps) { }) } - const saveEditorValue = () => { + const saveEditorValue = (content: string) => { if (data?.access && query['uuid'] !== undefined) { const uuid = query['uuid'] const req_body = { - input_content: input_content, + input_content: content, } editorEndpoints.UpdateCopywriteContent(uuid, req_body, data?.access) } @@ -121,9 +119,6 @@ export default function Index({ device, deviceOs }: IFuncProps) { } }, [query, data?.access]) - useBeforeUnload(saveEditorValue) - useChangeRouter(saveEditorValue) - return ( @@ -134,17 +129,31 @@ export default function Index({ device, deviceOs }: IFuncProps) { > <Box className={styles.sizeWrapper} sx={{ width: desktop ? '70%' : '100%', height: '75vh' }}> <Stack direction={'row'} justifyContent={'space-between'} gap={2}> - <Stack direction={'row'} gap={2} sx={{ stroke: theme === 'light' ? '#2B2B42' : '#ffffff', paddingBottom: '30px' }}> + <Stack direction={'row'} gap={2} sx={{ stroke: theme === 'light' ? '#2B2B42' : '#ffffff', paddingBottom: '25px' }}> + <Link href={'/copywriting/my'}> + <Stack alignItems={'center'} direction={'row'} gap={2} className={'pointer'}> + <svg width='10' height='17' viewBox='0 0 10 17' fill='none' xmlns='http://www.w3.org/2000/svg'> + <path + d='M8.5 15.5L1.5 8.5L8.5 1.5' + strokeWidth='1.8' + strokeLinecap='round' + strokeLinejoin='round' + stroke='#A4AAB5' + /> + </svg> + <Typography sx={{ fontSize: '15px' }}>Мои генерации</Typography> + </Stack> + </Link> + {/*<CopyIcon onClick={() => copyText('123')} />*/} {/*<CopyDropdownMenu id={'editor-dropdown-menu'}>*/} {/* <DownloadIcon />*/} {/*</CopyDropdownMenu>*/} </Stack> - <Link href={'my'} style={{ paddingBottom: '30px' }}> - <Image src={'/svg/copy/close.svg'} width={13} height={13} alt={'close'} /> - </Link> </Stack> - {copywrite && <EditorWrap id={copywrite.id} contentState={copywrite.input_content} theme={theme} />} + {copywrite && ( + <EditorWrap id={copywrite.id} saveEditorValue={saveEditorValue} contentState={copywrite.input_content} theme={theme} /> + )} </Box> <MobileSettingsDrawer desktop={desktop} open={isSettings} onClose={settingsHandler}> <Stack justifyContent={'space-between'} alignItems={'center'} sx={{ width: '25%', height: '75vh' }}> @@ -44,23 +44,6 @@ export default function Index({ device, deviceOs, uuid }: IParams) { const { error, showError } = useShowData() const { data } = useSession() - useEffect(() => { - const socket = new WebSocket(`${editorEndpoints.webSocket.url}/copywrite/copywrites/${uuid}/`) - - socket.onmessage = function (event) { - const event_data = JSON.parse(event.data).event_data - dispatch(addOutputContent(event_data.chunk)) - - if (event_data.end) { - return socket.close() - } - } - - socket.onerror = function (error) { - showError('Произошла ошибка генерации, перезагрузите страницу') - } - }, []) - const startGenerateHandler = () => { if (data?.access) { CopyEndpoints.GenerateResponse(uuid, data?.access).then(() => addQueryParams('resp')) @@ -121,7 +104,9 @@ export default function Index({ device, deviceOs, uuid }: IParams) { setEditor(res as EditorCopywrite) } setTemplateType(res.type) - if (res.output_content) dispatch(setNewOutputContent(res.output_content)) + if (res.output_content !== null) { + dispatch(setNewOutputContent(res.output_content)) + } } else { createDraftHandler() } @@ -129,6 +114,29 @@ export default function Index({ device, deviceOs, uuid }: IParams) { } }, [uuid, data?.access]) + useEffect(() => { + if (editor?.draft || copywrite?.draft) { + const socket = new WebSocket(`${editorEndpoints.webSocket.url}/copywrite/copywrites/${uuid}/`) + + socket.onopen = function (event) { + dispatch(setNewOutputContent('')) + } + + socket.onmessage = function (event) { + const event_data = JSON.parse(event.data).event_data + dispatch(addOutputContent(event_data.chunk)) + + if (event_data.end) { + return socket.close() + } + } + + socket.onerror = function (error) { + showError('Произошла ошибка генерации, перезагрузите страницу') + } + } + }, [copywrite, editor]) + return ( <Layout titlePage={'Копирайтинг'} device={device}> <Title icon={copywrite?.template.picture} title={copywrite?.template.title ?? 'Свой шаблон'} type={'Копирайтинг'} linkBack={''} /> @@ -143,15 +151,21 @@ export default function Index({ device, deviceOs, uuid }: IParams) { }} > <Box className={styles.sizeWrapper} sx={{ width: desktop && !tab ? '70%' : '100%', height: '75vh' }}> - <GenerationBlock - uuid={uuid} - favourite={copywrite?.favourite} - template_type={templateType} - input_content={editor?.input_content} - desktop={desktop} - handleChangeTab={handleChangeTab} - tab={tab} - /> + {editor || copywrite ? ( + <GenerationBlock + uuid={uuid} + isEditor={!!editor} + draft={editor?.draft ? editor.draft : copywrite?.draft ? copywrite.draft : false} + favourite={copywrite?.favourite} + template_type={templateType} + input_content={editor?.input_content} + desktop={desktop} + handleChangeTab={handleChangeTab} + tab={tab} + /> + ) : ( + <></> + )} </Box> {!tab && ( <MobileSettingsDrawer desktop={desktop} open={isSettings} onClose={settingsHandler}> @@ -3,9 +3,7 @@ import { useEffect } from 'react' export const useBeforeUnload = (handler: () => void) => { useEffect(() => { const handleBeforeUnload = (event: any) => { - event.preventDefault() handler() - return (event.returnValue = 'Are you sure you want to leave?') } window.addEventListener('beforeunload', handleBeforeUnload) @@ -15,7 +15,7 @@ export type TemplateCategory = { export type Copywrite = { id: string output_content: string | null - generated: boolean + draft: boolean favourite: boolean type: TemplateType template: CopywriteVariableTemplate @@ -10,6 +10,5 @@ const getTextFromEditor = (editorState: EditorState) => { export const getHtmlText = (editorState: EditorState) => { const contentState = editorState.getCurrentContent() const rawContent = convertToRaw(contentState) - const htmlContent = draftToHtml(rawContent) - return htmlContent + return draftToHtml(rawContent) } @@ -25,9 +25,11 @@ interface IProps { template_type: TemplateType uuid: string favourite: boolean | undefined + draft: boolean + isEditor: boolean } -export const GenerationBlock = ({ desktop, handleChangeTab, tab, input_content, template_type, uuid, favourite }: IProps) => { +export const GenerationBlock = ({ desktop, handleChangeTab, tab, input_content, template_type, uuid, favourite, draft, isEditor }: IProps) => { const theme = useAppSelector((state) => state.theme.theme) const copy = useAppSelector((state) => state.copy) const dispatch = useDispatch() @@ -45,33 +47,37 @@ export const GenerationBlock = ({ desktop, handleChangeTab, tab, input_content, } const variableHandler = (variable_id: string, value: string | null, name: string) => { - let isDefVar = copy.overridenVariables?.filter((el) => el.variable === variable_id).length === 0 + console.log(isEditor, draft) - if (value === null || value === '') { - if (!isDefVar) { - VariablesEndpoints.RemoveVariable(variable_id, uuid, data?.access).then(() => { - dispatch(updateVariable({ id: variable_id, value: null })) - dispatch(updateOverrideVariables({ action: 'remove', variable: { id: variable_id, variable: variable_id, value: '' } })) + if (!isEditor && draft) { + let isDefVar = copy.overridenVariables?.filter((el) => el.variable === variable_id).length === 0 + + if (value === null || value === '') { + if (!isDefVar) { + VariablesEndpoints.RemoveVariable(variable_id, uuid, data?.access).then(() => { + dispatch(updateVariable({ id: variable_id, value: null })) + dispatch(updateOverrideVariables({ action: 'remove', variable: { id: variable_id, variable: variable_id, value: '' } })) + }) + } + return + } + if (isDefVar) { + const req_body: OverrideVariableResponse = { + variable_id: variable_id, + value: value, + } + VariablesEndpoints.OverrideVariable(req_body, uuid, data?.access).then((res) => { + dispatch(updateVariable({ id: variable_id, value: value })) + if (res) dispatch(updateOverrideVariables({ action: 'add', variable: res })) }) + return } - return - } - if (isDefVar) { - const req_body: OverrideVariableResponse = { - variable_id: variable_id, - value: value, + if (!isDefVar) { + VariablesEndpoints.UpdateVariable(variable_id, value, uuid, data?.access).then(() => + dispatch(updateVariable({ id: variable_id, value: value })) + ) + return } - VariablesEndpoints.OverrideVariable(req_body, uuid, data?.access).then((res) => { - dispatch(updateVariable({ id: variable_id, value: value })) - if (res) dispatch(updateOverrideVariables({ action: 'add', variable: res })) - }) - return - } - if (!isDefVar) { - VariablesEndpoints.UpdateVariable(variable_id, value, uuid, data?.access).then(() => - dispatch(updateVariable({ id: variable_id, value: value })) - ) - return } } @@ -7,6 +7,8 @@ import dynamic from 'next/dynamic' import { useSession } from 'next-auth/react' import { setTextInputContent } from '@/src/features/use-copy/copy-store' +import { useBeforeUnload } from '@/src/shared/lib/hooks' +import { useChangeRouter } from '@/src/shared/lib/hooks/use-change-router' import { editorEndpoints } from '@/src/widgets/copy/api/editor-endpoints' import { toolbarOptions } from '@/src/widgets/copy/lib/constants' import { getHtmlText } from '@/src/widgets/copy/lib/getEditorHtml' @@ -16,49 +18,40 @@ interface IProps { theme: 'light' | 'dark' id: string contentState: string | null + saveEditorValue: (content: string) => void } -export const EditorWrap: React.FC<IProps> = ({ theme, id, contentState }) => { +export const EditorWrap: React.FC<IProps> = ({ theme, id, contentState, saveEditorValue }) => { const Editor = dynamic(() => import('react-draft-wysiwyg').then((res) => res.Editor), { ssr: false }) const [editorState, setEditorState] = useState(() => { if (contentState) return EditorState.createWithContent(stateFromHTML(contentState)) if (!contentState) return EditorState.createEmpty() }) - const { data } = useSession() const dispatch = useDispatch() - const [isSave, setIsSave] = useState<boolean>(false) useEffect(() => { - if (editorState !== undefined) { + if (editorState) { const htmlText = getHtmlText(editorState) - if (htmlText !== contentState) { - const req_body = { - input_content: htmlText, - } - setIsSave(false) - const saveTimeout = setTimeout(() => { - setIsSave(true) - }, 1000) - - const timeout = setTimeout(() => { - editorEndpoints.UpdateCopywriteContent(id, req_body, data?.access) - setIsSave(false) - }, 3000) - return () => { - clearTimeout(timeout) - clearTimeout(saveTimeout) - } - } + const timeout = setTimeout(() => { + dispatch(setTextInputContent(htmlText)) + }, 250) + return () => clearTimeout(timeout) } }, [editorState]) - useEffect(() => { - const timeout = setTimeout(() => { - if (editorState) dispatch(setTextInputContent(getHtmlText(editorState))) - }, 250) - return () => clearTimeout(timeout) - }, [editorState]) + useEffect(() => {}, [editorState]) + + useBeforeUnload(() => { + if (editorState) { + saveEditorValue(getHtmlText(editorState)) + } + }) + useChangeRouter(() => { + if (editorState) { + saveEditorValue(getHtmlText(editorState)) + } + }) return ( <Box sx={{ position: 'relative', height: '100%' }}> @@ -70,7 +63,7 @@ export const EditorWrap: React.FC<IProps> = ({ theme, id, contentState }) => { editorClassName='editorClassName' onEditorStateChange={setEditorState} /> - {isSave && <SaveBlock sx={{ right: 0, bottom: '30px', left: 0, margin: '0 auto' }} />} + {/*{isSave && <SaveBlock sx={{ right: 0, bottom: '30px', left: 0, margin: '0 auto' }} />}*/} </Box> ) }