diff --git a/.env b/.env index b6d37d99..e248afe1 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ NEXT_PUBLIC_API=http://192.168.1.250:3001/ NEXT_PUBLIC_OLD_API=https://graff.estate/api -NEXT_PUBLIC_S3_BUCKET=https://storage.yandexcloud.net/dult-faib-knac-fint +NEXT_PUBLIC_S3_BUCKET=https://storage.yandexcloud.net/dult-faib-knac-fint/ NEXT_PUBLIC_TINYMCE_API_KEY=2vf68779upg45y46o6g5gaxldy9gzr399eyaaqa0ki3mj2h2 \ No newline at end of file diff --git a/package.json b/package.json index e4a2004c..f01f1e84 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "framer-motion": "^11.3.9", "graphql": "^16.9.0", "graphql-scalars": "^1.23.0", + "html-react-parser": "^5.1.18", "jose": "^5.9.3", "ky": "^1.4.0", "libphonenumber-js": "^1.11.7", diff --git a/public/img/pages/home/stats/map_with_points.png b/public/img/pages/home/stats/map_with_points.png new file mode 100644 index 00000000..3d5bea96 Binary files /dev/null and b/public/img/pages/home/stats/map_with_points.png differ diff --git a/src/api/index.ts b/src/api/index.ts index 67be8e63..fbdf5cd7 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -5,6 +5,6 @@ export const oldApi = ky.extend({ }); export const api = ky.extend({ - prefixUrl: process.env.NEXT_PUBLIC_OLD_API, + prefixUrl: process.env.NEXT_PUBLIC_API, credentials: 'include', }); diff --git a/src/app/(admin)/dashboard/[articleId]/page.tsx b/src/app/(admin)/dashboard/[articleId]/page.tsx new file mode 100644 index 00000000..8f8aa5b3 --- /dev/null +++ b/src/app/(admin)/dashboard/[articleId]/page.tsx @@ -0,0 +1,153 @@ +'use client'; + +import { ArticleContentInput } from '@/components/articleInputs/ArticleContentInput'; +import { ArticleSliderInput } from '@/components/articleInputs/ArticleSliderInput'; +import { CloseIcon } from '@/components/icons/CloseIcon'; +import { IArticleFormInput } from '@/components/modals/ArticleFormModal'; +import { ArticleContent } from '@/components/pages/BlogPage/ArticleContent'; +import { useEditArticleMutation } from '@/queries/articles/editArticle'; +import { + GetArticleByIdDocument, + useGetArticleByIdQuery, +} from '@/queries/articles/getArticleById'; +import { Block, IArticle } from '@/types/IPost'; +import { Button } from '@/ui/Button'; +import { reorderFields } from '@/utils/reorderFields'; +import { useApolloClient } from '@apollo/client'; +import { Reorder } from 'framer-motion'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { useFieldArray, useForm } from 'react-hook-form'; + +export default function DashboardArticlePage({ + params: { articleId }, +}: { + params: { articleId: string }; +}) { + const { push } = useRouter(); + + const [showPreview, setShowPreview] = useState(false); + const [article, setArticle] = useState(); + + const client = useApolloClient(); + + useGetArticleByIdQuery({ + variables: { id: +articleId }, + onCompleted: ({ article }) => { + if (article.__typename === 'Article') { + const { __typename, id, ...other } = article; + setArticle(other as IArticle); + } + }, + }); + + const [editArticle] = useEditArticleMutation({ + onCompleted() { + client.refetchQueries({ + include: ['GetArticles', GetArticleByIdDocument], + }); + }, + }); + + const { handleSubmit, control, setValue, register, getValues, watch } = + useForm>(); + + useEffect(() => { + setValue('blocks', article?.blocks as Block[]); + }, [article, setValue]); + + const { fields, append, swap, remove } = useFieldArray({ + control, + name: 'blocks', + }); + + if (!article) return
not found
; + + return ( + <> +
+
{ + editArticle({ + variables: { + id: +articleId, + input: { + ...article, + blocks: JSON.stringify(formData.blocks), + }, + }, + }); + })} + > +
+ + +
+ + {fields.map((item, index) => + item.type === 'Slider' ? ( + + ) : ( + + ), + )} + +
+ + +
+
+
+ {showPreview && ( +
+ + +
+ )} + + ); +} diff --git a/src/app/(admin)/dashboard/blog/[articleId]/layout.tsx b/src/app/(admin)/dashboard/blog/[articleId]/layout.tsx deleted file mode 100644 index e8a9a450..00000000 --- a/src/app/(admin)/dashboard/blog/[articleId]/layout.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Layout({ children }: { children: React.ReactNode }) { - return
{children}
; -} diff --git a/src/app/(admin)/dashboard/blog/[articleId]/page.tsx b/src/app/(admin)/dashboard/blog/[articleId]/page.tsx deleted file mode 100644 index b5b0b8be..00000000 --- a/src/app/(admin)/dashboard/blog/[articleId]/page.tsx +++ /dev/null @@ -1,153 +0,0 @@ -'use client'; - -import { ArticleContentInput } from '@/components/articleInputs/ArticleContentInput'; -import { ArticleQuoteInput } from '@/components/articleInputs/ArticleQuoteInput'; -import { ArticleSliderInput } from '@/components/articleInputs/ArticleSliderInput'; -import { ArticleVideoInput } from '@/components/articleInputs/ArticleVideoInput'; -import { IArticleFormInput } from '@/components/modals/ArticleFormModal'; -import { useEditArticleMutation } from '@/queries/articles/editArticle'; -import { - GetArticleByIdDocument, - useGetArticleByIdQuery, -} from '@/queries/articles/getArticleById'; -import { Block } from '@/types/IPost'; -import { Button } from '@/ui/Button'; -import { reorderFields } from '@/utils/reorderFields'; -import { useApolloClient } from '@apollo/client'; -import { Reorder } from 'framer-motion'; -import { useEffect } from 'react'; -import { useFieldArray, useForm } from 'react-hook-form'; - -export default function DashboardArticlePage({ - params: { articleId }, -}: { - params: { articleId: string }; -}) { - const client = useApolloClient(); - - const { data } = useGetArticleByIdQuery({ - variables: { id: +articleId }, - }); - - const [editArticle] = useEditArticleMutation({ - onCompleted() { - client.refetchQueries({ - include: ['GetArticles', GetArticleByIdDocument], - }); - }, - }); - - const { handleSubmit, control, setValue, register } = - useForm>(); - - useEffect(() => { - if (data?.article.__typename === 'Article') { - const { blocks } = data.article; - setValue('blocks', blocks as Block[]); - } - }, [data, setValue]); - - const { fields, append, remove, swap } = useFieldArray({ - control, - name: 'blocks', - }); - - if (!data) return
not found
; - - return ( -
-
{ - if (data.article.__typename !== 'Article') return; - const { id, __typename, ...article } = data.article; - - editArticle({ - variables: { - id: +articleId, - input: { - ...article, - blocks: JSON.stringify(formData.blocks), - }, - }, - }); - })} - > -
- - - - -
- - {fields.map((item, index) => { - return item.type === 'Video' ? ( - - ) : item.type === 'Slider' ? ( - - ) : item.type === 'Quote' ? ( - - ) : ( - - ); - })} - - -
-
- ); -} diff --git a/src/app/(admin)/dashboard/blog/page.tsx b/src/app/(admin)/dashboard/blog/page.tsx deleted file mode 100644 index 66d8df23..00000000 --- a/src/app/(admin)/dashboard/blog/page.tsx +++ /dev/null @@ -1,138 +0,0 @@ -'use client'; - -import { ArticleFormModal } from '@/components/modals/ArticleFormModal'; -import { DeleteArticleModal } from '@/components/modals/DeleteArticleModal'; -import { ArticleCard } from '@/components/pages/BlogPage/ArticleCard'; -import { useAddArticleMutation } from '@/queries/articles/addArticle'; -import { useEditArticleMutation } from '@/queries/articles/editArticle'; -import { useGetArticlesQuery } from '@/queries/articles/getArticles'; -import { useModalStore } from '@/stores/useModalStore'; -import { Block } from '@/types/IPost'; -import { Button } from '@/ui/Button'; -import { useApolloClient } from '@apollo/client'; - -export default function DashboardBlogPage() { - const { setModal } = useModalStore(); - - const client = useApolloClient(); - - const { data } = useGetArticlesQuery({ - variables: { tags: [] }, - }); - - const [addArticle] = useAddArticleMutation({ - onCompleted() { - client.refetchQueries({ include: ['GetArticles'] }); - setModal(null, ''); - }, - }); - - const [editArticle] = useEditArticleMutation({ - onCompleted() { - client.refetchQueries({ include: ['GetArticles'] }); - setModal(null, ''); - }, - }); - - return ( -
- -
- {data?.articles.__typename === 'Articles' && - data?.articles.articles.map(({ __typename, id, ...article }) => ( -
- -
- - -
{' '} -
- ))} -
-
- ); -} diff --git a/src/app/(admin)/dashboard/layout.tsx b/src/app/(admin)/dashboard/layout.tsx index d64fa608..804fa1c0 100644 --- a/src/app/(admin)/dashboard/layout.tsx +++ b/src/app/(admin)/dashboard/layout.tsx @@ -3,7 +3,6 @@ import { useCheckAuthQuery } from '@/queries/auth/checkAuth'; import { useLogoutLazyQuery } from '@/queries/auth/logout'; import { useApolloClient } from '@apollo/client'; -import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { useEffect } from 'react'; @@ -37,16 +36,12 @@ export default function DashboardLayout({ return (
-
- Проекты - Блог - -
+ {children}
); diff --git a/src/app/(admin)/dashboard/projects/layout.tsx b/src/app/(admin)/dashboard/projects/layout.tsx deleted file mode 100644 index dea07164..00000000 --- a/src/app/(admin)/dashboard/projects/layout.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function ProjectsLayout({ - children, -}: { - children: React.ReactNode; -}) { - return
{children}
; -} diff --git a/src/app/(admin)/dashboard/projects/page.tsx b/src/app/(admin)/dashboard/projects/page.tsx deleted file mode 100644 index 46d0b5ae..00000000 --- a/src/app/(admin)/dashboard/projects/page.tsx +++ /dev/null @@ -1,126 +0,0 @@ -'use client'; - -import { DeleteProjectModal } from '@/components/modals/DeleteProjectModal'; -import { - IAddProjectFormInput, - ProjectFormModal, -} from '@/components/modals/ProjectFormModal'; -import { ProjectCard } from '@/components/pages/ProjectsPage/ProjectCard'; -import { useAddProjectMutation } from '@/queries/projects/addProject'; -import { useEditProjectMutation } from '@/queries/projects/editProject'; -import { useGetProjectsQuery } from '@/queries/projects/getProjects'; -import { useModalStore } from '@/stores/useModalStore'; -import { Device, IProject } from '@/types/IProject'; -import { Button } from '@/ui/Button'; -import { useApolloClient } from '@apollo/client'; - -export default function DashboardProjectsPage() { - const { data } = useGetProjectsQuery({ variables: { devices: [] } }); - - const { setModal } = useModalStore(); - - const client = useApolloClient(); - - const [addProject] = useAddProjectMutation({ - onCompleted() { - client.refetchQueries({ include: ['GetProjects'] }); - setModal(null, ''); - }, - }); - - const [editProject] = useEditProjectMutation({ - onCompleted() { - setModal(null, ''); - }, - }); - - return ( -
- -
- {data?.projects.__typename === 'Projects' && - data?.projects.projects.map(({ __typename, id, ...project }) => ( -
- -
- - -
-
- ))} -
-
- ); -} diff --git a/src/app/(main)/blog/[postId]/layout.tsx b/src/app/(main)/blog/[articleId]/layout.tsx similarity index 100% rename from src/app/(main)/blog/[postId]/layout.tsx rename to src/app/(main)/blog/[articleId]/layout.tsx diff --git a/src/app/(main)/blog/[articleId]/page.tsx b/src/app/(main)/blog/[articleId]/page.tsx new file mode 100644 index 00000000..bb0b6608 --- /dev/null +++ b/src/app/(main)/blog/[articleId]/page.tsx @@ -0,0 +1,25 @@ +'use client'; + +import { ArticleContent } from '@/components/pages/BlogPage/ArticleContent'; +import { useGetArticleByIdQuery } from '@/queries/articles/getArticleById'; +import { IArticle } from '@/types/IPost'; +import { useState } from 'react'; + +export default function ArticlePage({ + params: { articleId }, +}: { + params: { articleId: string }; +}) { + const [article, setArticle] = useState(); + + useGetArticleByIdQuery({ + variables: { id: +articleId }, + onCompleted: ({ article }) => { + if (article.__typename === 'Article') { + setArticle(article as IArticle); + } + }, + }); + + return
{article && }
; +} diff --git a/src/app/(main)/blog/[postId]/page.tsx b/src/app/(main)/blog/[postId]/page.tsx deleted file mode 100644 index 1fb0651c..00000000 --- a/src/app/(main)/blog/[postId]/page.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { Posts } from '@/consts/Posts'; -import dynamic from 'next/dynamic'; - -export default function PostPage({ - params: { postId }, -}: { - params: { postId: string }; -}) { - const post = Posts.find(post => post.id === +postId); - const [date = '', month = '', year = ''] = post!.createdAt.split(' '); - - const DynamicPostSlider = dynamic( - () => - import('@/components/pages/BlogPage/PostSlider').then( - mod => mod.PostSlider, - ), - { - ssr: false, - }, - ); - - return ( - post && ( - <> - {/*
-
-
- {post.tags.map(tag => ( - - ))} -
- -
-
-

{post.title}

- {post.mainImage && ( - {post.title} - )} -
-
-
-

{post.title}

-

{post.description}

-

{post.extraDesc}

- {post.video && ( -
- -
- )} -

{post.description}

-

{post.extraDesc}

-
- - {post.review && ( -
-
- {post.review.author.name} -
-

{post.review.author.name}

-

- {post.review.author.position} -

-
-
-

{post.review.text}

-
- )} - {post.extraVideo && ( -
-
- -
-
-

- Пояснялка -

- - YouTube - -
-
- )} */} - - ) - ); -} diff --git a/src/app/(admin)/dashboard/blog/layout.tsx b/src/app/(main)/blog/layout.tsx similarity index 100% rename from src/app/(admin)/dashboard/blog/layout.tsx rename to src/app/(main)/blog/layout.tsx diff --git a/src/app/(main)/blog/page.tsx b/src/app/(main)/blog/page.tsx index 19e2d9f6..04fbd61d 100644 --- a/src/app/(main)/blog/page.tsx +++ b/src/app/(main)/blog/page.tsx @@ -1,5 +1,5 @@ -import { PostsFilters } from '@/components/pages/BlogPage/PostsFilters'; -import { PostsList } from '@/components/pages/BlogPage/PostsList'; +import { ArticlesFilters } from '@/components/pages/BlogPage/ArticlesFilters'; +import { ArticlesList } from '@/components/pages/BlogPage/ArticlesList'; import { Title } from '@/ui/Title'; export default function BlogPage() { @@ -7,9 +7,9 @@ export default function BlogPage() {
Блог - +
- +
); } diff --git a/src/app/(main)/projects/page.tsx b/src/app/(main)/projects/page.tsx index 53107fc4..128e7fca 100644 --- a/src/app/(main)/projects/page.tsx +++ b/src/app/(main)/projects/page.tsx @@ -1,13 +1,55 @@ +'use client'; + +import { + IAddProjectFormInput, + ProjectFormModal, +} from '@/components/modals/ProjectFormModal'; import { ProjectsFilters } from '@/components/pages/ProjectsPage/ProjectsFilters'; import { ProjectsList } from '@/components/pages/ProjectsPage/ProjectsList'; +import { useCheckAuthQuery } from '@/queries/auth/checkAuth'; +import { useAddProjectMutation } from '@/queries/projects/addProject'; +import { useModalStore } from '@/stores/useModalStore'; +import { Button } from '@/ui/Button'; import { Title } from '@/ui/Title'; +import { useApolloClient } from '@apollo/client'; export default function ProjectsPage() { + const { setModal } = useModalStore(); + + const client = useApolloClient(); + + const { data } = useCheckAuthQuery(); + + const [addProject] = useAddProjectMutation({ + onCompleted() { + client.refetchQueries({ include: ['GetProjects'] }); + }, + }); + return (
-
- Проекты + Проекты +
+ {data?.checkAuth.__typename === 'CheckAuthResponse' && + data.checkAuth.isAuth && ( + + )}
diff --git a/src/components/Layout/ModalContainer.tsx b/src/components/Layout/ModalContainer.tsx index 90cbc6b4..a94eac6e 100644 --- a/src/components/Layout/ModalContainer.tsx +++ b/src/components/Layout/ModalContainer.tsx @@ -1,9 +1,19 @@ 'use client'; import { useModalStore } from '@/stores/useModalStore'; +import { useEffect } from 'react'; export function ModalContainer() { - const { modal, name } = useModalStore(); + const { modal, name, setModal } = useModalStore(); + + useEffect(() => { + const listener = (e: KeyboardEvent) => { + if (e.key === 'Escape') setModal(null, ''); + }; + document.addEventListener('keydown', listener); + + return () => document.removeEventListener('keydown', listener); + }, [setModal]); return ( modal && ( diff --git a/src/components/MediaUploader.tsx b/src/components/MediaUploader.tsx index 55df4bd1..9918d2ac 100644 --- a/src/components/MediaUploader.tsx +++ b/src/components/MediaUploader.tsx @@ -77,20 +77,17 @@ export function MediaUploader< {isImage(item) ? (previewFile || item.img) && ( {''} ) : (previewFile || item.video) && (
- ); -} diff --git a/src/components/YearFilterItem.tsx b/src/components/YearFilterItem.tsx deleted file mode 100644 index 8e14f79c..00000000 --- a/src/components/YearFilterItem.tsx +++ /dev/null @@ -1,38 +0,0 @@ -'use client'; - -import { usePathname, useRouter, useSearchParams } from 'next/navigation'; - -export function YearFilterItem({ - text, - chosen = false, - isAll = false, - inSelect = false, -}: { - text: string; - chosen?: boolean; - isAll?: boolean; - inSelect?: boolean; -}) { - const { push } = useRouter(); - const pathname = usePathname(); - const params = new URLSearchParams(useSearchParams()); - - function clickHandler() { - if (isAll || (params.get('year') === text && !inSelect)) - params.delete('year'); - else params.set('year', text); - push(pathname + '?' + params.toString()); - } - - return ( - - ); -} diff --git a/src/components/articleInputs/ArticleContentInput.tsx b/src/components/articleInputs/ArticleContentInput.tsx index 4bddb2a0..b4b0545d 100644 --- a/src/components/articleInputs/ArticleContentInput.tsx +++ b/src/components/articleInputs/ArticleContentInput.tsx @@ -1,91 +1,104 @@ +import { useModalStore } from '@/stores/useModalStore'; import { IContent } from '@/types/IPost'; -import { Editor } from '@tinymce/tinymce-react'; import { Reorder } from 'framer-motion'; -import { useRef } from 'react'; -import { Control, Controller } from 'react-hook-form'; -import { Editor as TinyMCEEditor } from 'tinymce'; +import parse from 'html-react-parser'; +import { useEffect, useState } from 'react'; +import { + Control, + UseFieldArrayRemove, + UseFormGetValues, + UseFormSetValue, + UseFormWatch, +} from 'react-hook-form'; +import { ArticleContentEditorModal } from '../modals/ArticleContentEditorModal'; import { IArticleFormInput } from '../modals/ArticleFormModal'; -interface IArticleContentInputProps { +export interface IArticleContentInputProps { item: IContent & Record<'id', string>; index: number; control: Control, any>; + setValue: UseFormSetValue>; + getValues: UseFormGetValues>; + watch: UseFormWatch>; + removeSlider: UseFieldArrayRemove; } export function ArticleContentInput({ control, index, item, + setValue, + getValues, + watch, + removeSlider, }: IArticleContentInputProps) { - const editorRef = useRef(null); + const { setModal } = useModalStore(); + + const [content, setContent] = useState(item.content); + + useEffect(() => { + const { unsubscribe } = watch(value => { + if (value.blocks?.[index]?.type === 'Content') + setContent(value.blocks[index].content!); + }); + + return () => { + unsubscribe(); + }; + }, [index, watch]); return ( - ( - { - editorRef.current = editor; - }} - init={{ - draggable_modal: true, - plugins: [ - 'anchor', - 'autolink', - 'charmap', - 'codesample', - 'emoticons', - 'image', - 'link', - 'lists', - 'media', - 'searchreplace', - 'table', - 'visualblocks', - 'wordcount', - 'checklist', - 'mediaembed', - 'casechange', - 'export', - 'formatpainter', - 'pageembed', - 'a11ychecker', - 'tinymcespellchecker', - 'permanentpen', - 'powerpaste', - 'advtable', - 'advcode', - 'editimage', - 'advtemplate', - 'mentions', - 'tinycomments', - 'tableofcontents', - 'footnotes', - 'mergetags', - 'autocorrect', - 'typography', - 'inlinecss', - 'markdown', - ], - toolbar: - 'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | link image media table mergetags | addcomment showcomments | spellcheckdialog a11ycheck typography | align lineheight | checklist numlist bullist indent outdent | emoticons charmap | removeformat', - tinycomments_mode: 'embedded', - tinycomments_author: 'Author name', - mergetags_list: [ - { value: 'First.Name', title: 'First Name' }, - { value: 'Email', title: 'Email' }, - ], - }} - apiKey={process.env.NEXT_PUBLIC_TINYMCE_API_KEY} - /> - )} - /> +
{parse(content)}
+
+ + +
); } diff --git a/src/components/articleInputs/ArticleQuoteInput.tsx b/src/components/articleInputs/ArticleQuoteInput.tsx deleted file mode 100644 index eddfb0dd..00000000 --- a/src/components/articleInputs/ArticleQuoteInput.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { IQuote } from '@/types/IPost'; -import { Reorder } from 'framer-motion'; -import { UseFormRegister, UseFormSetValue } from 'react-hook-form'; -import { MediaUploader } from '../MediaUploader'; -import { IArticleFormInput } from '../modals/ArticleFormModal'; - -interface IArticleQuoteInputProps { - register: UseFormRegister>; - item: IQuote & Record<'id', string>; - index: number; - setValue: UseFormSetValue>; -} - -export function ArticleQuoteInput({ - index, - item, - register, - setValue, -}: IArticleQuoteInputProps) { - return ( - -
- - -
-
- - -
- -
- - -
-
- ); -} diff --git a/src/components/articleInputs/ArticleSliderImageInput.tsx b/src/components/articleInputs/ArticleSliderImageInput.tsx index f05d7ebb..a33fd412 100644 --- a/src/components/articleInputs/ArticleSliderImageInput.tsx +++ b/src/components/articleInputs/ArticleSliderImageInput.tsx @@ -37,17 +37,14 @@ export function ArticleSliderImageInput({ label="Выберите изображение" media="img" /> -
- - -
+ +
+ + +
; - index: number; - remove: UseFieldArrayRemove; - register: UseFormRegister>; - setValue: UseFormSetValue>; -} - -export function ArticleVideoInput({ - register, - setValue, - remove, - index, - item, -}: IArticleVideoInputProps) { - return ( - - - - - - - ); -} diff --git a/src/components/icons/DeleteIcon.tsx b/src/components/icons/DeleteIcon.tsx new file mode 100644 index 00000000..1162431c --- /dev/null +++ b/src/components/icons/DeleteIcon.tsx @@ -0,0 +1,18 @@ +export function DeleteIcon() { + return ( + + + + ); +} diff --git a/src/components/icons/EditContentIcon.tsx b/src/components/icons/EditContentIcon.tsx new file mode 100644 index 00000000..6186ebbb --- /dev/null +++ b/src/components/icons/EditContentIcon.tsx @@ -0,0 +1,22 @@ +export function EditContentIcon() { + return ( + + + + + + + + ); +} diff --git a/src/components/icons/EditIcon.tsx b/src/components/icons/EditIcon.tsx new file mode 100644 index 00000000..4722e863 --- /dev/null +++ b/src/components/icons/EditIcon.tsx @@ -0,0 +1,18 @@ +export function EditIcon() { + return ( + + + + ); +} diff --git a/src/components/modals/ArticleContentEditorModal.tsx b/src/components/modals/ArticleContentEditorModal.tsx new file mode 100644 index 00000000..a592f758 --- /dev/null +++ b/src/components/modals/ArticleContentEditorModal.tsx @@ -0,0 +1,127 @@ +import { api } from '@/api'; +import { ClassNameWrapper } from '@/hocs/ClassNameWrapper'; +import { useModalStore } from '@/stores/useModalStore'; +import { Button } from '@/ui/Button'; +import { Editor } from '@tinymce/tinymce-react'; +import { useRef } from 'react'; +import { Controller } from 'react-hook-form'; +import { Editor as Tinymce } from 'tinymce'; +import { IArticleContentInputProps } from '../articleInputs/ArticleContentInput'; +import { CloseIcon } from '../icons/CloseIcon'; + +export function ArticleContentEditorModal({ + control, + index, + item, + setValue, + getValues, +}: Omit) { + const { setModal } = useModalStore(); + + const editorRef = useRef(null); + + return ( +
+ ( + (editorRef.current = editor)} + init={{ + images_upload_credentials: true, + images_upload_handler: async blobInfo => { + const formData = new FormData(); + formData.append('files', blobInfo.blob(), blobInfo.filename()); + formData.append('dest', 'blog'); + + const res = await api + .post('upload', { body: formData }) + .json<{ files: string[] }>(); + + console.log(res); + return ( + 'https://storage.yandexcloud.net/dult-faib-knac-fint/' + + res.files[0] + ); + }, + automatic_uploads: true, + plugins: [ + 'anchor', + 'autolink', + 'charmap', + 'codesample', + 'emoticons', + 'image', + 'link', + 'lists', + 'media', + 'searchreplace', + 'table', + 'visualblocks', + 'wordcount', + 'checklist', + 'mediaembed', + 'casechange', + 'export', + 'formatpainter', + 'pageembed', + 'a11ychecker', + 'tinymcespellchecker', + 'permanentpen', + 'powerpaste', + 'advtable', + 'advcode', + 'editimage', + 'advtemplate', + 'mentions', + 'tinycomments', + 'tableofcontents', + 'footnotes', + 'mergetags', + 'autocorrect', + 'typography', + 'inlinecss', + 'markdown', + ], + toolbar: + 'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | link image media table mergetags | addcomment showcomments | spellcheckdialog a11ycheck typography | align lineheight | checklist numlist bullist indent outdent | emoticons charmap | removeformat', + tinycomments_mode: 'embedded', + tinycomments_author: 'Author name', + mergetags_list: [ + { value: 'First.Name', title: 'First Name' }, + { value: 'Email', title: 'Email' }, + ], + }} + apiKey={process.env.NEXT_PUBLIC_TINYMCE_API_KEY} + /> + )} + /> + + +
+ ); +} diff --git a/src/components/modals/ArticleFormModal.tsx b/src/components/modals/ArticleFormModal.tsx index 6cab52bc..9146612e 100644 --- a/src/components/modals/ArticleFormModal.tsx +++ b/src/components/modals/ArticleFormModal.tsx @@ -100,7 +100,7 @@ export function ArticleFormModal({

- {action === 'create' ? 'Создание проекта' : 'Изменение проекта'} + {action === 'create' ? 'Создание статьи' : 'Изменение статьи'}

-
diff --git a/src/components/pages/BlogPage/ArticleCard.tsx b/src/components/pages/BlogPage/ArticleCard.tsx index 6091ff3f..5936a294 100644 --- a/src/components/pages/BlogPage/ArticleCard.tsx +++ b/src/components/pages/BlogPage/ArticleCard.tsx @@ -1,11 +1,22 @@ 'use client'; import { ArrowMoreIcon } from '@/components/icons/ArrowMoreIcon'; +import { DeleteIcon } from '@/components/icons/DeleteIcon'; +import { EditContentIcon } from '@/components/icons/EditContentIcon'; +import { EditIcon } from '@/components/icons/EditIcon'; +import { + ArticleFormModal, + IArticleFormInput, +} from '@/components/modals/ArticleFormModal'; +import { DeleteArticleModal } from '@/components/modals/DeleteArticleModal'; import { ClassNameWrapper } from '@/hocs/ClassNameWrapper'; +import { useEditArticleMutation } from '@/queries/articles/editArticle'; import { useCheckAuthQuery } from '@/queries/auth/checkAuth'; +import { useModalStore } from '@/stores/useModalStore'; import type { IArticle } from '@/types/IPost'; import { PostDate } from '@/ui/PostDate'; import { PostTag } from '@/ui/PostTag'; +import { useApolloClient } from '@apollo/client'; import Image from 'next/image'; import Link from 'next/link'; import { useSearchParams } from 'next/navigation'; @@ -17,75 +28,140 @@ export function ArticleCard({ cardImage, tags, id, -}: Omit) { - const [date, month, year] = createdAt.split('-'); + blocks, + posterImage, +}: IArticle) { + const { setModal } = useModalStore(); + + const [year, month, date] = createdAt.split('-'); const params = useSearchParams(); + const client = useApolloClient(); + const { data } = useCheckAuthQuery(); + const [editArticle] = useEditArticleMutation({ + onCompleted() { + client.refetchQueries({ include: ['GetArticles'] }); + }, + }); + return ( - - {title} - - {title} - {title} -
-
-
- {tags.map(tag => ( - - ))} +
+ + {title} + + {title} + {title} +
+
+
+ {tags.map(tag => ( + + ))} +
+

{title}

+

{description}

+
+
+ + } + />
-

{title}

-

{description}

-
- - } /> -
-
- + + {data?.checkAuth.__typename === 'CheckAuthResponse' && + data?.checkAuth.isAuth && ( +
+ + + + + +
+ )} +
); } diff --git a/src/components/pages/BlogPage/ArticleContent.tsx b/src/components/pages/BlogPage/ArticleContent.tsx new file mode 100644 index 00000000..ac834d11 --- /dev/null +++ b/src/components/pages/BlogPage/ArticleContent.tsx @@ -0,0 +1,59 @@ +import { IArticle } from '@/types/IPost'; +import { PostDate } from '@/ui/PostDate'; +import parse from 'html-react-parser'; +import Image from 'next/image'; +import { ArticleSlider } from './ArticleSlider'; + +export function ArticleContent({ + blocks, + createdAt, + description, + posterImage, + tags, + title, +}: IArticle) { + const [year, month, date] = createdAt.split('T')[0].split('-'); + + return ( + <> +
+
+
+ {tags.map(tag => ( +

+ {tag} +

+ ))} +
+ +
+
+
+

{title}

+

{description}

+
+
+ {title} +
+
+
+
+ {blocks.map((block, index) => + block.type === 'Content' ? ( +
{parse(block.content)}
+ ) : ( + + ), + )} +
+ + ); +} diff --git a/src/components/pages/BlogPage/PostSlider.tsx b/src/components/pages/BlogPage/ArticleSlider.tsx similarity index 69% rename from src/components/pages/BlogPage/PostSlider.tsx rename to src/components/pages/BlogPage/ArticleSlider.tsx index 6579f677..2912feb9 100644 --- a/src/components/pages/BlogPage/PostSlider.tsx +++ b/src/components/pages/BlogPage/ArticleSlider.tsx @@ -1,18 +1,18 @@ 'use client'; import { useWindowWidth } from '@/hooks/useWindowWidth'; -import { IArticle } from '@/types/IPost'; import { InfinitySlider } from '@/ui/InfinitySlider'; import { PostSliderImage } from '@/ui/PostSlideImage'; -export function PostSlider({ title, slides }: IArticle) { +export function ArticleSlider({ + slides, +}: { + slides: { img: string; capture?: string }[]; +}) { const width = useWindowWidth(); return (
-

- {title} -

{slides && width && (width >= 1024 ? ( @@ -21,7 +21,7 @@ export function PostSlider({ title, slides }: IArticle) { slideWidth={width * 0.47} offset={'25vw'} slides={slides.map(slide => ( - + ))} /> ) : width >= 640 ? ( @@ -31,7 +31,7 @@ export function PostSlider({ title, slides }: IArticle) { className="px-6" offset={'25vw'} slides={slides.map(slide => ( - + ))} /> ) : ( @@ -41,7 +41,7 @@ export function PostSlider({ title, slides }: IArticle) { className="px-4" offset={'25vw'} slides={slides.map(slide => ( - + ))} /> ))} diff --git a/src/components/pages/BlogPage/PostsFilters.tsx b/src/components/pages/BlogPage/ArticlesFilters.tsx similarity index 58% rename from src/components/pages/BlogPage/PostsFilters.tsx rename to src/components/pages/BlogPage/ArticlesFilters.tsx index 1c209585..3e84017c 100644 --- a/src/components/pages/BlogPage/PostsFilters.tsx +++ b/src/components/pages/BlogPage/ArticlesFilters.tsx @@ -1,17 +1,13 @@ 'use client'; import { TagFilterItem } from '@/components/TagFilterItem'; -import { YearFilterDropdown } from '@/components/YearFilterDropdown'; -import { YearFilterItem } from '@/components/YearFilterItem'; import { PostTags } from '@/consts/PostTags'; -import { PostYears } from '@/consts/PostYears'; import { Vertical } from '@/ui/Vertical'; import { useSearchParams } from 'next/navigation'; -export function PostsFilters() { +export function ArticlesFilters() { const params = useSearchParams(); const chosedTags = params.getAll('tags'); - const chosenYear = params.get('year'); return (
@@ -33,14 +29,6 @@ export function PostsFilters() { /> ))}
-
- {PostYears.map(year => ( - - ))} - - -
-
); } diff --git a/src/components/pages/BlogPage/ArticlesList.tsx b/src/components/pages/BlogPage/ArticlesList.tsx new file mode 100644 index 00000000..6fdfc92a --- /dev/null +++ b/src/components/pages/BlogPage/ArticlesList.tsx @@ -0,0 +1,48 @@ +'use client'; + +import { useGetArticlesQuery } from '@/queries/articles/getArticles'; +import { IArticle } from '@/types/IPost'; +import { useSearchParams } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { ArticleCard } from './ArticleCard'; + +export function ArticlesList() { + const params = useSearchParams(); + + const [articles, setArticles] = useState(); + const [limit, setLimit] = useState(5); + const [tags, setTags] = useState([]); + + useEffect(() => { + setTags(params.getAll('tags')); + }, [params]); + + useGetArticlesQuery({ + variables: { tags, limit, offset: 0 }, + onCompleted(data) { + if (data.articles.__typename === 'Articles') { + setArticles(data.articles.articles as IArticle[]); + } + }, + }); + + return ( +
+ {articles?.length === 0 ? ( +

No posts found

+ ) : ( +
+ {articles?.map(post => )} +
+ +
+
+ )} +
+ ); +} diff --git a/src/components/pages/BlogPage/PostsList.tsx b/src/components/pages/BlogPage/PostsList.tsx deleted file mode 100644 index 32c15f08..00000000 --- a/src/components/pages/BlogPage/PostsList.tsx +++ /dev/null @@ -1,47 +0,0 @@ -'use client'; - -import { Posts } from '@/consts/Posts'; -import { useSearchParams } from 'next/navigation'; -import { useEffect, useState } from 'react'; -import { ArticleCard } from './ArticleCard'; - -export function PostsList() { - const params = useSearchParams(); - - const [posts, setPosts] = useState(Posts); - - useEffect(() => { - setPosts( - Posts.filter( - post => - (!params.has('tags') || - params.getAll('tags').every(tag => post.tags.includes(tag))) && - (!params.has('year') || - params.get('year') === post.createdAt.split(' ')[2]), - ), - ); - }, [params]); - - // const { data } = useGetArticlesQuery({ - // variables: { tags: params.getAll('tags'), limit: 10, offset: 0 }, - // }); - - return ( -
- {posts.length === 0 ? ( -

No posts found

- ) : ( -
- {posts.map(post => ( - - ))} -
- -
-
- )} -
- ); -} diff --git a/src/components/pages/BlogPage/RelevantPost.tsx b/src/components/pages/BlogPage/RelevantArticles.tsx similarity index 94% rename from src/components/pages/BlogPage/RelevantPost.tsx rename to src/components/pages/BlogPage/RelevantArticles.tsx index 23b7008c..ac278322 100644 --- a/src/components/pages/BlogPage/RelevantPost.tsx +++ b/src/components/pages/BlogPage/RelevantArticles.tsx @@ -6,7 +6,7 @@ import { AppearanceHr } from '@/ui/AppearanceHr'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; -export function RelevantPost({ image, title, id }: IArticle) { +export function RelevantArticles({ image, title, id }: IArticle) { const { push } = useRouter(); return ( diff --git a/src/components/pages/BlogPage/RelevantSlider.tsx b/src/components/pages/BlogPage/RelevantSlider.tsx index 5c845f0e..e5c57331 100644 --- a/src/components/pages/BlogPage/RelevantSlider.tsx +++ b/src/components/pages/BlogPage/RelevantSlider.tsx @@ -6,7 +6,7 @@ import { Posts } from '@/consts/Posts'; import { useWindowWidth } from '@/hooks/useWindowWidth'; import { InfinitySlider } from '@/ui/InfinitySlider'; import { useRef } from 'react'; -import { RelevantPost } from './RelevantPost'; +import { RelevantArticles } from './RelevantArticles'; export function RelevantSlider() { const left = useRef(null); @@ -37,28 +37,31 @@ export function RelevantSlider() { ) : width >= 640 ? ( ) : ( ))}
diff --git a/src/components/pages/MainPage/Projects.tsx b/src/components/pages/MainPage/Projects.tsx index d4d2de22..df7d8017 100644 --- a/src/components/pages/MainPage/Projects.tsx +++ b/src/components/pages/MainPage/Projects.tsx @@ -1,23 +1,38 @@ 'use client'; import { ArrowMoreIcon } from '@/components/icons/ArrowMoreIcon'; +import { + IAddProjectFormInput, + ProjectFormModal, +} from '@/components/modals/ProjectFormModal'; import { ClassNameWrapper } from '@/hocs/ClassNameWrapper'; +import { useCheckAuthQuery } from '@/queries/auth/checkAuth'; +import { useAddProjectMutation } from '@/queries/projects/addProject'; import { useGetProjectsQuery } from '@/queries/projects/getProjects'; +import { useModalStore } from '@/stores/useModalStore'; import { IProject } from '@/types/IProject'; +import { Button } from '@/ui/Button'; import { Descriptor } from '@/ui/Descriptor'; import { getProjectsCount } from '@/utils/getProjectsCount'; import { getSortedProjects } from '@/utils/getSortedProjects'; +import { useApolloClient } from '@apollo/client'; import Link from 'next/link'; import { useCallback, useEffect, useState } from 'react'; import { ProjectsSection } from '../ProjectsPage/ProjectsSection'; export function Projects() { + const { setModal } = useModalStore(); + const [all, setAll] = useState(false); const [sortedProjects, setSortedProjects] = useState>(); + const client = useApolloClient(); + const { data } = useGetProjectsQuery({ variables: { devices: [] } }); + const { data: authData } = useCheckAuthQuery(); + const getProjects = useCallback(async () => { try { setSortedProjects( @@ -34,6 +49,14 @@ export function Projects() { } }, [data]); + const [addProject] = useAddProjectMutation({ + onCompleted() { + client.refetchQueries({ + include: ['GetProjects'], + }); + }, + }); + const projectsInProccess = sortedProjects?.get('В работе') ?? []; useEffect(() => { @@ -56,6 +79,27 @@ export function Projects() { в разных городах России и мира

+ {authData?.checkAuth.__typename === 'CheckAuthResponse' && + authData?.checkAuth.isAuth && ( +
+ +
+ )} +
{'Карта
)}
diff --git a/src/components/pages/ProjectsPage/ProjectsFilters.tsx b/src/components/pages/ProjectsPage/ProjectsFilters.tsx index 7a32b3b2..14aa026b 100644 --- a/src/components/pages/ProjectsPage/ProjectsFilters.tsx +++ b/src/components/pages/ProjectsPage/ProjectsFilters.tsx @@ -24,14 +24,6 @@ export function ProjectsFilters() { /> ))}
- {/*
- {ProjectYears.map(year => ( - - ))} - - -
- */}
); } diff --git a/src/consts/PostTags.ts b/src/consts/PostTags.ts index fec9addd..cc48a38f 100644 --- a/src/consts/PostTags.ts +++ b/src/consts/PostTags.ts @@ -1 +1 @@ -export const PostTags = ['недвижимость', 'награды', 'выставки']; +export const PostTags = ['Недвижимость', 'Награды', 'Выставки']; diff --git a/src/generated/graphql.ts b/src/generated/graphql.ts index 10582f76..73a2ac80 100644 --- a/src/generated/graphql.ts +++ b/src/generated/graphql.ts @@ -52,7 +52,7 @@ export type AuthResponse = { export type AuthResult = AuthResponse | Error; -export type Block = Content | Quote | Slider | Video; +export type Block = Content | Slider; export type CheckAuthResponse = { __typename?: 'CheckAuthResponse'; @@ -211,15 +211,6 @@ export type QueryProjectsArgs = { input?: InputMaybe; }; -export type Quote = { - __typename?: 'Quote'; - authorAvatar: Scalars['String']['output']; - authorName: Scalars['String']['output']; - authorRole: Scalars['String']['output']; - text: Scalars['String']['output']; - type: Scalars['String']['output']; -}; - export type Region = { __typename?: 'Region'; regionName: Scalars['String']['output']; @@ -232,10 +223,3 @@ export type Slider = { images: Array; type: Scalars['String']['output']; }; - -export type Video = { - __typename?: 'Video'; - caption?: Maybe; - type: Scalars['String']['output']; - video: Scalars['String']['output']; -}; diff --git a/src/queries/articles/addArticle/addArticle.generated.ts b/src/queries/articles/addArticle/addArticle.generated.ts index f12dad01..b8a8cf31 100644 --- a/src/queries/articles/addArticle/addArticle.generated.ts +++ b/src/queries/articles/addArticle/addArticle.generated.ts @@ -8,7 +8,7 @@ export type AddArticleMutationVariables = Types.Exact<{ }>; -export type AddArticleMutation = { __typename?: 'Mutation', createArticle: { __typename?: 'Article', id: number, title: string, description: string, posterImage: string, cardImage: string, createdAt: any, tags: Array, blocks: Array<{ __typename?: 'Content', type: string, content: string } | { __typename?: 'Quote', type: string, text: string, authorName: string, authorAvatar: string, authorRole: string } | { __typename?: 'Slider', type: string, images: Array<{ __typename?: 'Image', img: string, caption?: string | null }> } | { __typename?: 'Video', type: string, video: string, caption?: string | null }> } | { __typename?: 'Error' } }; +export type AddArticleMutation = { __typename?: 'Mutation', createArticle: { __typename?: 'Article', id: number, title: string, description: string, posterImage: string, cardImage: string, createdAt: any, tags: Array, blocks: Array<{ __typename?: 'Content', type: string, content: string } | { __typename?: 'Slider', type: string, images: Array<{ __typename?: 'Image', img: string, caption?: string | null }> }> } | { __typename?: 'Error' } }; export const AddArticleDocument = gql` @@ -27,13 +27,6 @@ export const AddArticleDocument = gql` type content } - ... on Quote { - type - text - authorName - authorAvatar - authorRole - } ... on Slider { type images { @@ -41,11 +34,6 @@ export const AddArticleDocument = gql` caption } } - ... on Video { - type - video - caption - } } } } diff --git a/src/queries/articles/addArticle/addArticle.gql b/src/queries/articles/addArticle/addArticle.gql index 445d7665..93e82b3d 100644 --- a/src/queries/articles/addArticle/addArticle.gql +++ b/src/queries/articles/addArticle/addArticle.gql @@ -13,13 +13,6 @@ mutation AddArticle($input: CreateArticleInput!) { type content } - ... on Quote { - type - text - authorName - authorAvatar - authorRole - } ... on Slider { type images { @@ -27,11 +20,6 @@ mutation AddArticle($input: CreateArticleInput!) { caption } } - ... on Video { - type - video - caption - } } } } diff --git a/src/queries/articles/deleteArticle/deleteArticle.generated.ts b/src/queries/articles/deleteArticle/deleteArticle.generated.ts index 6056e1a1..ab07d89f 100644 --- a/src/queries/articles/deleteArticle/deleteArticle.generated.ts +++ b/src/queries/articles/deleteArticle/deleteArticle.generated.ts @@ -8,7 +8,7 @@ export type DeleteArticleMutationVariables = Types.Exact<{ }>; -export type DeleteArticleMutation = { __typename?: 'Mutation', deleteArticle: { __typename?: 'Article', id: number, title: string, description: string, createdAt: any, cardImage: string, posterImage: string, tags: Array, blocks: Array<{ __typename?: 'Content', type: string, content: string } | { __typename?: 'Quote', type: string, text: string, authorName: string, authorAvatar: string, authorRole: string } | { __typename?: 'Slider', type: string, images: Array<{ __typename?: 'Image', img: string, caption?: string | null }> } | { __typename?: 'Video', type: string, video: string, caption?: string | null }> } | { __typename?: 'Error', message: string } }; +export type DeleteArticleMutation = { __typename?: 'Mutation', deleteArticle: { __typename?: 'Article', id: number, title: string, description: string, createdAt: any, cardImage: string, posterImage: string, tags: Array, blocks: Array<{ __typename?: 'Content', type: string, content: string } | { __typename?: 'Slider', type: string, images: Array<{ __typename?: 'Image', img: string, caption?: string | null }> }> } | { __typename?: 'Error', message: string } }; export const DeleteArticleDocument = gql` @@ -30,13 +30,6 @@ export const DeleteArticleDocument = gql` type content } - ... on Quote { - type - text - authorName - authorAvatar - authorRole - } ... on Slider { type images { @@ -44,11 +37,6 @@ export const DeleteArticleDocument = gql` caption } } - ... on Video { - type - video - caption - } } } } diff --git a/src/queries/articles/deleteArticle/deleteArticle.gql b/src/queries/articles/deleteArticle/deleteArticle.gql index bb477ba9..cda67f2f 100644 --- a/src/queries/articles/deleteArticle/deleteArticle.gql +++ b/src/queries/articles/deleteArticle/deleteArticle.gql @@ -16,13 +16,6 @@ mutation DeleteArticle($id: Int!) { type content } - ... on Quote { - type - text - authorName - authorAvatar - authorRole - } ... on Slider { type images { @@ -30,11 +23,6 @@ mutation DeleteArticle($id: Int!) { caption } } - ... on Video { - type - video - caption - } } } } diff --git a/src/queries/articles/editArticle/editArticle.generated.ts b/src/queries/articles/editArticle/editArticle.generated.ts index 07b3cdce..0329d5f9 100644 --- a/src/queries/articles/editArticle/editArticle.generated.ts +++ b/src/queries/articles/editArticle/editArticle.generated.ts @@ -9,7 +9,7 @@ export type EditArticleMutationVariables = Types.Exact<{ }>; -export type EditArticleMutation = { __typename?: 'Mutation', updateArticle: { __typename?: 'Article', id: number, title: string, description: string, posterImage: string, cardImage: string, createdAt: any, tags: Array, blocks: Array<{ __typename?: 'Content', type: string, content: string } | { __typename?: 'Quote', type: string, text: string, authorName: string, authorAvatar: string, authorRole: string } | { __typename?: 'Slider', type: string, images: Array<{ __typename?: 'Image', img: string, caption?: string | null }> } | { __typename?: 'Video', type: string, video: string, caption?: string | null }> } | { __typename?: 'Error', message: string } }; +export type EditArticleMutation = { __typename?: 'Mutation', updateArticle: { __typename?: 'Article', id: number, title: string, description: string, posterImage: string, cardImage: string, createdAt: any, tags: Array, blocks: Array<{ __typename?: 'Content', type: string, content: string } | { __typename?: 'Slider', type: string, images: Array<{ __typename?: 'Image', img: string, caption?: string | null }> }> } | { __typename?: 'Error', message: string } }; export const EditArticleDocument = gql` @@ -31,13 +31,6 @@ export const EditArticleDocument = gql` type content } - ... on Quote { - type - text - authorName - authorAvatar - authorRole - } ... on Slider { type images { @@ -45,11 +38,6 @@ export const EditArticleDocument = gql` caption } } - ... on Video { - type - video - caption - } } } } diff --git a/src/queries/articles/editArticle/editArticle.gql b/src/queries/articles/editArticle/editArticle.gql index afd578f5..a487e847 100644 --- a/src/queries/articles/editArticle/editArticle.gql +++ b/src/queries/articles/editArticle/editArticle.gql @@ -16,13 +16,6 @@ mutation EditArticle($id: Int!, $input: CreateArticleInput!) { type content } - ... on Quote { - type - text - authorName - authorAvatar - authorRole - } ... on Slider { type images { @@ -30,11 +23,6 @@ mutation EditArticle($id: Int!, $input: CreateArticleInput!) { caption } } - ... on Video { - type - video - caption - } } } } diff --git a/src/queries/articles/getArticleById/getArticleById.generated.ts b/src/queries/articles/getArticleById/getArticleById.generated.ts index dc4dc07f..77346bbc 100644 --- a/src/queries/articles/getArticleById/getArticleById.generated.ts +++ b/src/queries/articles/getArticleById/getArticleById.generated.ts @@ -8,7 +8,7 @@ export type GetArticleByIdQueryVariables = Types.Exact<{ }>; -export type GetArticleByIdQuery = { __typename?: 'Query', article: { __typename?: 'Article', id: number, title: string, description: string, createdAt: any, cardImage: string, posterImage: string, tags: Array, blocks: Array<{ __typename?: 'Content', type: string, content: string } | { __typename?: 'Quote', type: string, text: string, authorName: string, authorAvatar: string, authorRole: string } | { __typename?: 'Slider', type: string, images: Array<{ __typename?: 'Image', img: string, caption?: string | null }> } | { __typename?: 'Video', type: string, video: string, caption?: string | null }> } | { __typename?: 'Error', message: string } }; +export type GetArticleByIdQuery = { __typename?: 'Query', article: { __typename?: 'Article', id: number, title: string, description: string, createdAt: any, cardImage: string, posterImage: string, tags: Array, blocks: Array<{ __typename?: 'Content', type: string, content: string } | { __typename?: 'Slider', type: string, images: Array<{ __typename?: 'Image', img: string, caption?: string | null }> }> } | { __typename?: 'Error', message: string } }; export const GetArticleByIdDocument = gql` @@ -30,13 +30,6 @@ export const GetArticleByIdDocument = gql` type content } - ... on Quote { - type - text - authorName - authorAvatar - authorRole - } ... on Slider { type images { @@ -44,11 +37,6 @@ export const GetArticleByIdDocument = gql` caption } } - ... on Video { - type - video - caption - } } } } diff --git a/src/queries/articles/getArticleById/getArticleById.gql b/src/queries/articles/getArticleById/getArticleById.gql index b6d8054a..e611e0b8 100644 --- a/src/queries/articles/getArticleById/getArticleById.gql +++ b/src/queries/articles/getArticleById/getArticleById.gql @@ -16,13 +16,6 @@ query GetArticleById($id: Int!) { type content } - ... on Quote { - type - text - authorName - authorAvatar - authorRole - } ... on Slider { type images { @@ -30,11 +23,6 @@ query GetArticleById($id: Int!) { caption } } - ... on Video { - type - video - caption - } } } } diff --git a/src/queries/articles/getArticles/getArticles.generated.ts b/src/queries/articles/getArticles/getArticles.generated.ts index daaea3cf..21b18953 100644 --- a/src/queries/articles/getArticles/getArticles.generated.ts +++ b/src/queries/articles/getArticles/getArticles.generated.ts @@ -10,7 +10,7 @@ export type GetArticlesQueryVariables = Types.Exact<{ }>; -export type GetArticlesQuery = { __typename?: 'Query', articles: { __typename?: 'Articles', articles: Array<{ __typename?: 'Article', id: number, title: string, description: string, tags: Array, createdAt: any, posterImage: string, cardImage: string, blocks: Array<{ __typename?: 'Content', content: string } | { __typename?: 'Quote', text: string, authorName: string, authorAvatar: string, authorRole: string } | { __typename?: 'Slider', images: Array<{ __typename?: 'Image', img: string, caption?: string | null }> } | { __typename?: 'Video', video: string, caption?: string | null }> }> } | { __typename?: 'Error', message: string } }; +export type GetArticlesQuery = { __typename?: 'Query', articles: { __typename?: 'Articles', articles: Array<{ __typename?: 'Article', id: number, title: string, description: string, tags: Array, createdAt: any, posterImage: string, cardImage: string, blocks: Array<{ __typename?: 'Content', content: string } | { __typename?: 'Slider', images: Array<{ __typename?: 'Image', img: string, caption?: string | null }> }> }> } | { __typename?: 'Error', message: string } }; export const GetArticlesDocument = gql` @@ -32,22 +32,12 @@ export const GetArticlesDocument = gql` ... on Content { content } - ... on Quote { - text - authorName - authorAvatar - authorRole - } ... on Slider { images { img caption } } - ... on Video { - video - caption - } } } } diff --git a/src/queries/articles/getArticles/getArticles.gql b/src/queries/articles/getArticles/getArticles.gql index fbf0e79f..a8f730cf 100644 --- a/src/queries/articles/getArticles/getArticles.gql +++ b/src/queries/articles/getArticles/getArticles.gql @@ -16,22 +16,12 @@ query GetArticles($tags: [String!]!, $limit: Int, $offset: Int) { ... on Content { content } - ... on Quote { - text - authorName - authorAvatar - authorRole - } ... on Slider { images { img caption } } - ... on Video { - video - caption - } } } } diff --git a/src/types/IPost.ts b/src/types/IPost.ts index 05cdac6a..74b0ded8 100644 --- a/src/types/IPost.ts +++ b/src/types/IPost.ts @@ -13,21 +13,7 @@ export interface ISlider { images: IImage[]; } -export interface IVideo { - type: 'Video'; - video: string; - caption?: string | null; -} - -export interface IQuote { - type: 'Quote'; - text: string; - authorName: string; - authorAvatar: string; - authorRole: string; -} - -export type Block = IContent | ISlider | IVideo | IQuote; +export type Block = IContent | ISlider; export interface IArticle { id: number; diff --git a/src/ui/Button.tsx b/src/ui/Button.tsx index 852ca249..b3ad8391 100644 --- a/src/ui/Button.tsx +++ b/src/ui/Button.tsx @@ -8,6 +8,7 @@ interface ButtonProps { disabled?: boolean; className?: string; onClick?: () => void; + type?: 'submit' | 'reset' | 'button'; } export function Button({ @@ -18,11 +19,16 @@ export function Button({ disabled = false, className, onClick, + type, }: ButtonProps) { return (
- {!controlsRefs && ( -
= 1024 ? offset : 'auto', - marginTop: progressMT, - }} - className="flex items-center gap-4 lg:w-[clamp(720px,100vw-465px,1136px)] desktop-figma:w-[71vw]" - > - -
-
-
- -
+ {withControls && ( + = 640 ? 132 : (width / 360) * 196} + height={width >= 640 ? 66 : 58} + slide={slide} + onLeftClick={prevSlide} + onRightClick={nextSlide} + /> )}
); diff --git a/src/ui/PostDate.tsx b/src/ui/PostDate.tsx index 207e47d3..f3d1dbcc 100644 --- a/src/ui/PostDate.tsx +++ b/src/ui/PostDate.tsx @@ -1,28 +1,22 @@ +import { getMonthTitle } from '@/utils/getMonthTitle'; + export function PostDate({ date, month, year, - inPostCard = true, className = '', }: { date: string; month: string; year: string; - inPostCard?: boolean; className?: string; }) { return ( -
+

{date}

-

+

{date} - {month} {year} + {getMonthTitle(month)} {year}

); diff --git a/src/ui/PostSlideImage.tsx b/src/ui/PostSlideImage.tsx index 8969a163..2f33db9d 100644 --- a/src/ui/PostSlideImage.tsx +++ b/src/ui/PostSlideImage.tsx @@ -1,16 +1,10 @@ import Image from 'next/image'; -export function PostSliderImage({ - slide, - title, -}: { - slide: string; - title: string; -}) { +export function PostSliderImage({ slide }: { slide: string }) { return (