fixes upds

This commit is contained in:
2024-10-24 18:58:46 +05:00
parent 3c341aa00a
commit 94efdfef72
12 changed files with 252 additions and 232 deletions
+48 -44
View File
@@ -5,7 +5,6 @@ import { ArticleHeader } from '@/components/ArticleHeader';
import { ArticleContentInput } from '@/components/articleInputs/ArticleContentInput';
import { ArticleSliderInput } from '@/components/articleInputs/ArticleSliderInput';
import { IArticleFormInput } from '@/components/modals/ArticleFormModal';
import { ArticleCard } from '@/components/pages/BlogPage/ArticleCard';
import { ArticleContent } from '@/components/pages/BlogPage/ArticleContent';
import { useEditArticleMutation } from '@/queries/articles/editArticle';
import {
@@ -28,48 +27,45 @@ export default function DashboardArticlePage() {
const [showPreview, setShowPreview] = useState(false);
const [article, setArticle] = useState<IArticle>();
const { data } = useGetArticleByIdQuery({
variables: { id: +articleId },
});
useEffect(() => {
if (data?.article.__typename === 'Article') {
const { __typename, blocks, ...article } = data.article;
setArticle({
...article,
blocks: blocks.map(block =>
block.__typename === 'Content'
? { type: 'Content', content: block.content }
: {
type: 'Slider',
images: block.images.map(({ __typename, ...image }) => image),
},
),
});
}
}, [data]);
const [editArticle] = useEditArticleMutation({
refetchQueries: ['GetArticles', GetArticleByIdDocument],
});
const { control, handleSubmit, setValue, getValues, watch } =
useForm<IArticleFormInput>({
defaultValues: article,
});
useEffect(() => {
if (article) {
setValue('blocks', article.blocks);
}
}, [article, setValue]);
useForm<IArticleFormInput>();
const { fields, append, swap, remove, insert } = useFieldArray({
name: 'blocks',
control,
});
const [title, description, createdAt, posterImage, cardImage, tags] =
useGetArticleByIdQuery({
variables: { id: +articleId },
onCompleted(data) {
if (data?.article.__typename === 'Article') {
setValue(
'blocks',
data.article.blocks.map(block =>
block.__typename === 'Content'
? { content: block.content, type: 'Content' }
: {
type: 'Slider',
images: block.images.map(({ __typename, ...image }) => image),
},
) as [],
);
setValue('title', data.article.title);
setValue('description', data.article.description);
setValue('tags', data.article.tags);
setValue('posterImage', data.article.posterImage);
setValue('cardImage', data.article.cardImage);
setValue('createdAt', data.article.createdAt);
}
},
fetchPolicy: 'no-cache',
});
const [editArticle] = useEditArticleMutation({
refetchQueries: ['GetArticles', GetArticleByIdDocument],
});
const [title, description, createdAt, posterImage, cardImage, tags, blocks] =
useWatch({
name: [
'title',
@@ -78,6 +74,7 @@ export default function DashboardArticlePage() {
'posterImage',
'cardImage',
'tags',
'blocks',
],
control,
});
@@ -91,8 +88,19 @@ export default function DashboardArticlePage() {
posterImage,
cardImage,
tags,
blocks,
id: +articleId,
}));
}, [title, description, createdAt, posterImage, cardImage, tags]);
}, [
title,
description,
createdAt,
posterImage,
cardImage,
tags,
blocks,
articleId,
]);
if (!article) return <div>not found</div>;
@@ -104,11 +112,12 @@ export default function DashboardArticlePage() {
<Button onClick={() => setShowPreview(false)}>Назад</Button>
<Button
onClick={() => {
const { id, ...other } = article;
editArticle({
variables: {
id: +articleId,
input: {
...article,
...other,
blocks: JSON.stringify(getValues('blocks')),
},
},
@@ -124,12 +133,7 @@ export default function DashboardArticlePage() {
) : (
<div className="space-y-4">
<ArticleActions {...{ ...article, setValue }} />
{article.title && (
<>
<ArticleCard {...article} draft />
<ArticleHeader {...article} />
</>
)}
{article.title && <ArticleHeader {...article} />}
<form
className="space-y-5"
onSubmit={handleSubmit(formData => {
+56 -59
View File
@@ -1,11 +1,53 @@
@import url('/fonts/TTHovesProAll/stylesheet.css');
@tailwind base;
@layer base {
.tailwind-preflight span {
font-size: inherit !important;
.no-tailwindcss-base {
word-break: normal;
h1 {
font-size: 24px;
}
h2 {
font-size: 18px;
}
h3 {
font-size: 14px;
}
h4 {
font-size: 12px;
}
h5 {
font-size: 10px;
}
h6 {
font-size: 8px;
}
p {
font-size: 12px;
}
pre {
font-size: 10px;
}
h1,
h2,
h3,
h4,
h5,
h6,
p {
font-weight: revert;
}
ol,
ul {
list-style: revert;
margin: revert;
padding: revert;
}
}
}
@tailwind components;
@tailwind utilities;
@@ -36,58 +78,10 @@ body {
);
}
.reset-tailwind {
all: initial;
display: block;
}
.content {
@apply text-lg break-words;
word-break: break-word;
h1 {
@apply text-2xl font-bold;
}
h2 {
@apply text-lg font-bold;
}
h3 {
@apply text-sm font-bold;
}
h4 {
@apply text-xs;
}
h5 {
@apply text-[10px];
}
h6 {
@apply text-[8px];
}
p {
@apply text-xs;
}
pre {
@apply text-[10px];
}
ul {
@apply pl-4 mb-8 list-inside;
list-style: unset;
li {
display: list-item;
}
}
}
/* :where(.tailwind-preflight h1) {
font-size: revert !important;
color: red !important;
} */
*::-webkit-scrollbar {
width: 4px;
@@ -95,7 +89,6 @@ body {
*::-webkit-scrollbar-thumb {
background-color: #798fff;
/* border: 3.5px solid transparent; */
border-radius: 4px;
}
@@ -108,7 +101,7 @@ body {
@apply -tracking-[.02em] 2xl:text-[clamp(96px,96px+(100vw-1560px)/360*16,112px)] text-[clamp(40px,40px+(100vw-360px)/1240*56,96px)] leading-[clamp(36px,36px+(100vw-360px)/1240*50.4,86.4px)];
}
.h2 {
@apply -tracking-[.02em] 2xl:text-[clamp(64px,64px+(100vw-1560px)/360*48,112px)] text-[clamp(28px,28px+(100vw-360px)/1240*36,64px)] leading-none;
@apply -tracking-[.02em] 2xl:text-[clamp(64px,64px+(100vw-1560px)/360*12,76px)] text-[clamp(28px,28px+(100vw-360px)/1240*36,64px)] leading-none;
}
.h3 {
@@ -124,11 +117,15 @@ body {
}
.l-text {
@apply text-[clamp(16px,16px+(100vw-360px)/1240*4,20px)] leading-[clamp(21.6px,21.6px+(100vw-360px)/1240*5.4,27px)];
@apply 2xl:text-[clamp(20px,20px+(100vw-1560px)/360*4,24px)] text-[clamp(16px,16px+(100vw-360px)/1240*4,20px)] leading-[clamp(21.6px,21.6px+(100vw-360px)/1240*5.4,27px)];
}
.m-text {
@apply text-[clamp(14px,14px+(100vw-360px)/1240*2,16px)] leading-[clamp(19.6px,19.6px+(100vw-360px)/1240*2.4,22.4px)];
@apply 2xl:text-[clamp(16px,16px+(100vw-1560px)/360*4,20px)] text-[clamp(14px,14px+(100vw-360px)/1240*2,16px)] leading-[clamp(19.6px,19.6px+(100vw-360px)/1240*2.4,22.4px)];
}
.s-text {
@apply text-base;
}
.l-caption {
@@ -136,7 +133,7 @@ body {
}
.m-caption {
@apply text-[clamp(10px,10px+(100vw-360px)/1240*2,12px)] leading-[clamp(12px,12px+(100vw-360px)/1240*2.4,14.4px)];
@apply 2xl:text-[clamp(12px,12px+(100vw-1560px)/360*2,14px)] text-[clamp(10px,10px+(100vw-360px)/1240*2,12px)] leading-[clamp(12px,12px+(100vw-360px)/1240*2.4,14.4px)];
}
.btn-text {
+2 -2
View File
@@ -31,12 +31,12 @@ export function ArticleHeader({
<h1 className="lg:h2 h1 font-medium">{title}</h1>
<p className="h4 font-medium">{description}</p>
</div>
<div className="aspect-[768/400] relative">
<div className="relative">
<Image
fill
src={process.env.NEXT_PUBLIC_S3_BUCKET + posterImage}
alt={title}
className="!relative object-cover object-center"
className="!relative object-cover object-center max-w-[67%] aspect-[768/400]"
/>
</div>
</div>
+1 -1
View File
@@ -29,7 +29,7 @@ export function BlockActions({
const { setModal } = useModalStore();
return (
<div className="flex gap-x-4 absolute -right-[150px]">
<div className="flex gap-x-4 absolute lg:-right-[150px] sm:max-lg:bottom-[100px]">
<button
onClick={e => {
e.preventDefault();
@@ -36,9 +36,8 @@ export function ArticleContentInput({
useEffect(
() =>
watch(value => {
if (value.blocks?.[index]?.type === 'Content') {
if (value.blocks?.[index]?.type === 'Content')
setContent(value.blocks[index].content!);
}
}).unsubscribe,
[index, setValue, watch],
);
@@ -46,9 +45,9 @@ export function ArticleContentInput({
return (
<Reorder.Item
value={item}
className="border-[#3D425C] border p-4 rounded-3xl relative flex col-start-2 col-span-2"
className="border-[#3D425C] border p-4 rounded-3xl relative flex lg:col-start-2 lg:col-span-2 sm:col-span-3 col-span-full"
>
<div className="tailwind-preflight">{parse(content)}</div>
<div className="no-tailwindcss-base">{parse(content)}</div>
<BlockActions
{...{ control, index, remove, insert }}
item={{ ...item, content }}
@@ -21,16 +21,14 @@ export function ArticleSliderImageInput({
}: IArticleSliderImageInputProps) {
return (
<Reorder.Item value={item} className="flex items-center" drag>
<div>
<MediaUploader
dest="blog"
setValue={setValue}
fieldName={`blocks.${index}.images.${imgIndex}`}
item={item}
label="Выберите изображение"
media="img"
/>
</div>
<MediaUploader
dest="blog"
setValue={setValue}
fieldName={`blocks.${index}.images.${imgIndex}.img`}
item={item}
label="Выберите изображение"
media="img"
/>
<button
className="self-start z-[1]"
onClick={e => {
@@ -38,10 +38,20 @@ export function ArticleSliderInput({
className="border border-[#3D425C] rounded-3xl p-4 col-span-full space-y-4"
>
<div className="flex gap-x-4 justify-center">
<button onClick={() => append({ img: '' })}>
<button
onClick={e => {
e.preventDefault();
append({ img: '' });
}}
>
<PlusIcon />
</button>
<button onClick={() => removeSlider(index)}>
<button
onClick={e => {
e.preventDefault();
removeSlider(index);
}}
>
<TrashIcon />
</button>
</div>
+13 -11
View File
@@ -100,17 +100,19 @@ export function ArticleFormModal({ defaultValues, set }: IArticleFormProps) {
</button>
</div>
<form
onSubmit={handleSubmit(data => {
setModal(null, '');
if (set) {
set('title', data.title);
set('description', data.description);
set('tags', data.tags);
set('posterImage', data.posterImage);
set('cardImage', data.cardImage);
set('createdAt', defaultValues.createdAt);
}
})}
onSubmit={handleSubmit(
({ cardImage, posterImage, description, tags, title }) => {
setModal(null, '');
if (set) {
set('title', title);
set('description', description);
set('tags', tags);
set('posterImage', posterImage);
set('cardImage', cardImage);
set('createdAt', defaultValues.createdAt);
}
},
)}
className="space-y-4"
>
<label htmlFor="blog_title" className="flex flex-col">
@@ -20,7 +20,7 @@ export function ArticleContent({
{blocks.map((block, index) =>
block.type === 'Content' ? (
<div className="lg:col-span-2 lg:col-start-2" key={index}>
<div className="content">{parse(block.content)}</div>
<div className="no-tailwindcss-base">{parse(block.content)}</div>
</div>
) : (
<div className="col-span-full lg:-mx-8 sm:-mx-6 -mx-4" key={index}>
@@ -4,11 +4,7 @@ import { useWindowWidth } from '@/hooks/useWindowWidth';
import { InfinitySlider } from '@/ui/InfinitySlider';
import { PostSliderImage } from '@/ui/PostSlideImage';
export function ArticleSlider({
slides,
}: {
slides: { img: string; capture?: string }[];
}) {
export function ArticleSlider({ slides }: { slides: { img: string }[] }) {
const width = useWindowWidth();
return (
+85 -83
View File
@@ -22,96 +22,98 @@ export function Datamining() {
и&nbsp;собирает данные о&nbsp;пользователе и&nbsp;его поведении
</span>
</Title>
<div className="grid xl:grid-cols-4 lg:grid-cols-3 sm:grid-cols-2 gap-x-4 border-y border-[#3D425C] relative">
<div className="xl:col-span-1 lg:col-span-full sm:max-lg:col-span-full max-xl:border-b border-[#3D425C] xl:border-r">
<div className="grid lg:grid-cols-4 border-y border-[#3D425C] relative">
<div className="lg:col-span-1 col-span-full max-lg:border-b border-[#3D425C] lg:border-r">
<p className="xl:pt-10 sm:py-8 py-6 pr-4 text-left accent font-medium sm:max-lg:w-3/4">
Graff.estate легко встраивается в&nbsp;существующую цепочку продаж
</p>
</div>
<div
ref={ref1}
className="p-6 my-4 w-full bg-[url(/img/pages/home/projectmanagment/Ellipse.png)] lg:flex flex-col justify-between gap-x-4 sm:max-lg:col-start-1 col-span-1 space-y-[140px]"
>
<div className="flex max-w-16 relative">
<Image
src={'/img/components/datamining/2k.png'}
alt="room2"
width={64}
height={64}
className="!relative z-[2]"
/>
<motion.img
src={'/img/components/datamining/room1.png'}
alt="room1"
width={64}
height={64}
className="!relative z-[1]"
initial={{ x: -64 }}
animate={isInView1 ? { x: -16 } : { x: -64 }}
/>
<motion.img
src={'/img/components/datamining/room2.png'}
alt="room1"
width={64}
height={64}
className="!relative"
initial={{ x: -128 }}
animate={isInView1 ? { x: -32 } : { x: -128 }}
/>
<div className="grid lg:grid-cols-3 sm:grid-cols-2 lg:col-span-3 col-s gap-x-4 lg:pl-4">
<div
ref={ref1}
className="sm:aspect-square max-sm:space-y-10 p-6 my-4 w-full bg-[url(/img/pages/home/projectmanagment/Ellipse.png)] flex flex-col justify-between gap-x-4 sm:max-lg:col-start-1 col-span-1 qspace-y-[140px]"
>
<div className="flex max-w-16 relative">
<Image
src={'/img/components/datamining/2k.png'}
alt="room2"
width={64}
height={64}
className="!relative z-[2]"
/>
<motion.img
src={'/img/components/datamining/room1.png'}
alt="room1"
width={64}
height={64}
className="!relative z-[1]"
initial={{ x: -64 }}
animate={isInView1 ? { x: -16 } : { x: -64 }}
/>
<motion.img
src={'/img/components/datamining/room2.png'}
alt="room1"
width={64}
height={64}
className="!relative"
initial={{ x: -128 }}
animate={isInView1 ? { x: -32 } : { x: -128 }}
/>
</div>
<div className="space-y-6">
<p className="font-medium sm:max-lg:h3 h4">
Актуальная информация о&nbsp;квартирах
</p>
<p className="lg:m-text sm:l-text m-text">
Клиент всегда видит актуальные данные об&nbsp;интересующем его
лоте, включая статус и стоимость
</p>
</div>
</div>
<div className="space-y-6">
<p className="font-medium sm:max-lg:h3 h4">
Актуальная информация о&nbsp;квартирах
</p>
<p className="lg:m-text sm:l-text m-text">
Клиент всегда видит актуальные данные об&nbsp;интересующем его
лоте, включая статус и стоимость
</p>
<div
ref={ref2}
className="sm:aspect-square max-sm:space-y-10 p-6 sm:my-4 max-sm:mb-4 w-full bg-[url(/img/pages/home/projectmanagment/Ellipse.png)] flex flex-col justify-between sm:max-lg:col-start-2 col-span-1 qspace-y-[140px]"
>
<div className="flex max-h-16 relative">
<Image
src={'/img/components/datamining/vova.png'}
alt="vova"
width={64}
height={64}
className="!relative z-[2]"
/>
<motion.div
className="p-[18px] rounded-full bg-[#33353E] max-h-[60px] relative z-[1] drop-shadow-[0_4px_4px_rgba(0,0,0,0.25)]"
initial={{ x: -64 }}
animate={isInView2 ? { x: -16 } : { x: -64 }}
>
<MailIcon />
</motion.div>
<motion.div
className="p-[18px] rounded-full bg-[#33353E] max-h-[60px] relative"
initial={{ x: -128 }}
animate={isInView2 ? { x: -32 } : { x: -128 }}
>
<PhoneIcon />
</motion.div>
</div>
<div className="space-y-6">
<p className="font-medium sm:max-lg:h3 h4">
Создание карточки клиента
</p>
<p className="lg:m-text sm:l-text m-text">
Инструмент продаж сам создаст карточку клиента в вашей
CRM-системе и&nbsp;назначит ответственного менеджера
</p>
</div>
</div>
<Image
fill
className="!relative w-full lg:col-span-1 sm:max-xl:col-span-full lg:py-4 max-lg:pb-4 object-cover sm:aspect-square"
src={'/img/pages/home/projectmanagment/Datamining 1.png'}
alt="Datamining"
/>
</div>
<div
ref={ref2}
className="p-6 sm:my-4 max-sm:mb-4 w-full bg-[url(/img/pages/home/projectmanagment/Ellipse.png)] flex flex-col justify-between sm:max-lg:col-start-2 col-span-1 space-y-[140px]"
>
<div className="flex max-h-16 relative">
<Image
src={'/img/components/datamining/vova.png'}
alt="vova"
width={64}
height={64}
className="!relative z-[2]"
/>
<motion.div
className="p-[18px] rounded-full bg-[#33353E] max-h-[60px] relative z-[1] drop-shadow-[0_4px_4px_rgba(0,0,0,0.25)]"
initial={{ x: -64 }}
animate={isInView2 ? { x: -16 } : { x: -64 }}
>
<MailIcon />
</motion.div>
<motion.div
className="p-[18px] rounded-full bg-[#33353E] max-h-[60px] relative"
initial={{ x: -128 }}
animate={isInView2 ? { x: -32 } : { x: -128 }}
>
<PhoneIcon />
</motion.div>
</div>
<div className="space-y-6">
<p className="font-medium sm:max-lg:h3 h4">
Создание карточки клиента
</p>
<p className="lg:m-text sm:l-text m-text">
Инструмент продаж сам создаст карточку клиента в вашей CRM-системе
и&nbsp;назначит ответственного менеджера
</p>
</div>
</div>
<Image
fill
className="!relative w-full lg:col-span-1 sm:max-lg:col-span-full lg:py-4 max-lg:pb-4 object-cover"
src={'/img/pages/home/projectmanagment/Datamining 1.png'}
alt="Datamining"
/>
</div>
</div>
);
+22 -10
View File
@@ -1,4 +1,6 @@
import type { Config } from 'tailwindcss';
import fs from 'fs';
import postcss from 'postcss';
import { type Config } from 'tailwindcss';
const config: Config = {
content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'],
@@ -38,16 +40,26 @@ const config: Config = {
},
},
},
// corePlugins: {
// preflight: true,
// },
plugins: [
// function ({ addBase }: { addBase: any }) {
// const preflightStyles = postcss.parse(
// fs.readFileSync(path.join(__dirname, './src/app/globals.css'), 'utf8'),
// );
// preflightStyles.walkRules(rule => {
// rule.selector = '.tailwind-preflight ' + rule.selector;
// });
// addBase(preflightStyles.nodes);
// },
function ({ addBase }: { addBase: any }) {
const preflightStyles = postcss.parse(
fs.readFileSync(
require.resolve('tailwindcss/lib/css/preflight.css'),
'utf8',
),
);
preflightStyles.walkRules(rule => {
// rule.selector = rule.selector
// .split(',')
// .map(selector => `tailwind-preflight ${selector}`)
// .join(',');
rule.selector = '.no-tailwind-base ' + rule.selector;
});
addBase(preflightStyles.nodes);
},
],
};