upd
This commit is contained in:
+3
-4
@@ -13,8 +13,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@atlaskit/pragmatic-drag-and-drop": "^1.5.0",
|
"@atlaskit/pragmatic-drag-and-drop": "^1.5.0",
|
||||||
"@tailwindcss/postcss": "^4.0.0",
|
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
|
||||||
"@tanstack/react-query": "^5.62.7",
|
"@tanstack/react-query": "^5.62.7",
|
||||||
"@tanstack/react-query-devtools": "^5.64.2",
|
"@tanstack/react-query-devtools": "^5.64.2",
|
||||||
"@tinymce/tinymce-react": "^5.1.1",
|
"@tinymce/tinymce-react": "^5.1.1",
|
||||||
@@ -30,7 +28,6 @@
|
|||||||
"libphonenumber-js": "^1.11.7",
|
"libphonenumber-js": "^1.11.7",
|
||||||
"next": "14.2.5",
|
"next": "14.2.5",
|
||||||
"next-intl": "^4.0.2",
|
"next-intl": "^4.0.2",
|
||||||
"postcss": "^8.5.1",
|
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-circular-progressbar": "^2.1.0",
|
"react-circular-progressbar": "^2.1.0",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
@@ -46,7 +43,6 @@
|
|||||||
"react-transition-group": "^4.4.5",
|
"react-transition-group": "^4.4.5",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"sharp": "^0.33.5",
|
"sharp": "^0.33.5",
|
||||||
"tailwindcss": "^4.0.0",
|
|
||||||
"tinymce": "^7.4.1",
|
"tinymce": "^7.4.1",
|
||||||
"usehooks-ts": "^3.1.0",
|
"usehooks-ts": "^3.1.0",
|
||||||
"zustand": "^4.5.4"
|
"zustand": "^4.5.4"
|
||||||
@@ -61,8 +57,11 @@
|
|||||||
"@types/react-phone-number-input": "^3.1.37",
|
"@types/react-phone-number-input": "^3.1.37",
|
||||||
"@types/react-rangeslider": "^2.2.7",
|
"@types/react-rangeslider": "^2.2.7",
|
||||||
"@types/react-transition-group": "^4.4.11",
|
"@types/react-transition-group": "^4.4.11",
|
||||||
|
"autoprefixer": "^10.4.21",
|
||||||
"eslint": "^8",
|
"eslint": "^8",
|
||||||
"eslint-config-next": "14.2.5",
|
"eslint-config-next": "14.2.5",
|
||||||
|
"postcss": "^8.5.6",
|
||||||
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
/** @type {import('postcss-load-config').Config} */
|
|
||||||
const config = {
|
|
||||||
plugins: {
|
|
||||||
'@tailwindcss/postcss': {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default config;
|
|
||||||
@@ -2,7 +2,9 @@ import { api } from "@/api";
|
|||||||
import { IArticle } from "@/types/IArticle";
|
import { IArticle } from "@/types/IArticle";
|
||||||
import { QueryClient } from "@tanstack/react-query";
|
import { QueryClient } from "@tanstack/react-query";
|
||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
import NotFound from "@/app/not-found";
|
import Link from "next/link";
|
||||||
|
import CloseIcon from "@/components/icons/CloseIcon";
|
||||||
|
import { RelevantArticlesPreview } from "@/components/pages/ArticlePage/RelevantArticlesPreview";
|
||||||
|
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
@@ -42,17 +44,19 @@ export default async function Layout({
|
|||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// <section className="fixed inset-0 bg-[#0F101199] [backdrop-filter:blur(16px)] z-[14]">
|
<section className="fixed inset-0 bg-[#0F101199] [backdrop-filter:blur(16px)] z-[14]">
|
||||||
// <Link href={'/blog'} className="inset-0 fixed"></Link>
|
<Link href={"/blog"} className="inset-0 fixed"></Link>
|
||||||
// <RelevantArticlesPreview slug={slug} />
|
<RelevantArticlesPreview slug={slug} />
|
||||||
// {children}
|
{children}
|
||||||
// <Link
|
<Link
|
||||||
// href={'/blog'}
|
href={"/blog"}
|
||||||
// className="fixed lg:right-[1.389vw] lg:top-[1.389vw] right-5 top-5 lg:rounded-[1.111vw] rounded-2xl bg-[#37393B99] lg:p-[1.111vw] p-4 cursor-pointer"
|
className="fixed lg:right-[1.389vw] lg:top-[1.389vw] right-5 top-5 lg:rounded-[1.111vw] rounded-2xl bg-[#37393B99] lg:p-[1.111vw] p-4 cursor-pointer"
|
||||||
// >
|
>
|
||||||
// <CloseIcon className="lg:w-[1.111vw] lg:h-[1.111vw] w-4 h-4 text-white" />
|
<div className="lg:w-[1.111vw] lg:h-[1.111vw] w-4 h-4 text-white">
|
||||||
// </Link>
|
<CloseIcon />
|
||||||
// </section>
|
</div>
|
||||||
<NotFound />
|
</Link>
|
||||||
|
</section>
|
||||||
|
// <NotFound />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { api } from '@/api';
|
import { api } from "@/api";
|
||||||
import { ArticleSyncPage } from '@/components/pages/ArticlePage/ArticleSyncPage';
|
import { ArticleSyncPage } from "@/components/pages/ArticlePage/ArticleSyncPage";
|
||||||
import { IArticle } from '@/types/IArticle';
|
import { IArticle } from "@/types/IArticle";
|
||||||
import {
|
import {
|
||||||
dehydrate,
|
dehydrate,
|
||||||
HydrationBoundary,
|
HydrationBoundary,
|
||||||
QueryClient,
|
QueryClient,
|
||||||
queryOptions,
|
queryOptions,
|
||||||
} from '@tanstack/react-query';
|
} from "@tanstack/react-query";
|
||||||
|
|
||||||
export default async function ArticlePage({
|
export default async function ArticlePage({
|
||||||
params,
|
params,
|
||||||
@@ -19,7 +19,7 @@ export default async function ArticlePage({
|
|||||||
|
|
||||||
await queryClient.prefetchQuery(
|
await queryClient.prefetchQuery(
|
||||||
queryOptions({
|
queryOptions({
|
||||||
queryKey: ['articles', slug],
|
queryKey: ["articles", slug],
|
||||||
queryFn: () => api.get(`articles/${slug}`).json<IArticle>(),
|
queryFn: () => api.get(`articles/${slug}`).json<IArticle>(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -35,8 +35,11 @@ export async function generateStaticParams() {
|
|||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
const articles = await queryClient.fetchQuery<IArticle[]>({
|
const articles = await queryClient.fetchQuery<IArticle[]>({
|
||||||
queryKey: ['articles'],
|
queryKey: ["articles"],
|
||||||
queryFn: () => api.get('articles').json<IArticle[]>(),
|
queryFn: () =>
|
||||||
|
api
|
||||||
|
.get("articles", { searchParams: { locale: "en" } })
|
||||||
|
.json<IArticle[]>(),
|
||||||
});
|
});
|
||||||
|
|
||||||
return articles
|
return articles
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { NotFoundPage } from "@/components/pages/NotFoundPage";
|
|
||||||
import { StoriesButton } from "@/ui/StoriesButton";
|
import { StoriesButton } from "@/ui/StoriesButton";
|
||||||
import { Title } from "@/ui/Title";
|
import { Title } from "@/ui/Title";
|
||||||
import { Metadata, ResolvingMetadata } from "next";
|
import { Metadata, ResolvingMetadata } from "next";
|
||||||
import { InProcess } from "@/components/pages/InProcess";
|
|
||||||
|
|
||||||
export async function generateMetadata(
|
export async function generateMetadata(
|
||||||
{},
|
{},
|
||||||
@@ -19,17 +17,19 @@ export default async function BlogLayout({
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
// <section className="space-y-12">
|
<section className="space-y-12">
|
||||||
// <div className="flex flex-col gap-6 items-center">
|
<div className="flex flex-col gap-6 items-center">
|
||||||
// <Title className="text-center" headerLevel={2}>
|
<Title className="text-center" headerLevel={2}>
|
||||||
// All about company's work:
|
All about company's work:
|
||||||
// <br />
|
<br />
|
||||||
// <span className="text-[#7A7A7A]">articles, videos and publications</span>
|
<span className="text-[#7A7A7A]">
|
||||||
// </Title>
|
articles, videos and publications
|
||||||
// <StoriesButton />
|
</span>
|
||||||
// </div>
|
</Title>
|
||||||
// <div className="grid grid-cols-6 lg:gap-x-[0.833vw]">{children}</div>
|
<StoriesButton />
|
||||||
// </section>
|
</div>
|
||||||
<InProcess />
|
<div className="grid grid-cols-6 lg:gap-x-[0.833vw]">{children}</div>
|
||||||
|
</section>
|
||||||
|
// <InProcess />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,10 @@ export default async function BlogPage() {
|
|||||||
|
|
||||||
await queryClient.prefetchQuery({
|
await queryClient.prefetchQuery({
|
||||||
queryKey: ["articles"],
|
queryKey: ["articles"],
|
||||||
queryFn: () => api.get("articles").json<IArticle[]>(),
|
queryFn: () =>
|
||||||
|
api
|
||||||
|
.get("articles", { searchParams: { locale: "en" } })
|
||||||
|
.json<IArticle[]>(),
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
+54
-49
@@ -1,5 +1,8 @@
|
|||||||
@import url('/fonts/TTHovesProAll/stylesheet.css');
|
@import url("/fonts/TTHovesProAll/stylesheet.css");
|
||||||
@import 'tailwindcss';
|
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
--gradient: linear-gradient(87deg, #798fff 15%, #d375ff 100%);
|
--gradient: linear-gradient(87deg, #798fff 15%, #d375ff 100%);
|
||||||
@@ -10,7 +13,7 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'TTHovesPro';
|
font-family: "TTHovesPro";
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: #0f1011;
|
background-color: #0f1011;
|
||||||
}
|
}
|
||||||
@@ -21,7 +24,7 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bg-gradient-card {
|
.bg-gradient-card {
|
||||||
content: '';
|
content: "";
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -34,7 +37,7 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar {
|
*::-webkit-scrollbar {
|
||||||
width: 4px;
|
width: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-thumb {
|
*::-webkit-scrollbar-thumb {
|
||||||
@@ -46,62 +49,64 @@ html {
|
|||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility line1 {
|
@layer utilities {
|
||||||
@apply 2xl:text-[128px] lg:max-2xl:text-[clamp(96px,96px+(100vw-1440px)/96*32,128px)] md:max-lg:text-[clamp(56px,56px+(100vw-768px)/672*40,96px)] xs:max-md:text-[clamp(40px,40px+(100vw-360px)/408*16,56px)] text-[40px] leading-[85%];
|
.line1 {
|
||||||
}
|
@apply 2xl:text-[128px] lg:max-2xl:text-[clamp(96px,96px+(100vw-1440px)/96*32,128px)] md:max-lg:text-[clamp(56px,56px+(100vw-768px)/672*40,96px)] xs:max-md:text-[clamp(40px,40px+(100vw-360px)/408*16,56px)] text-[40px] leading-[85%];
|
||||||
|
}
|
||||||
|
|
||||||
@utility line2 {
|
.line2 {
|
||||||
@apply lg:text-[clamp(64px,4.444vw,88px)] md:max-lg:text-[clamp(40px,40px+(100vw-768px)/672*24,64px)] xs:max-md:text-[clamp(32px,32px+(100vw-360px)/408*8,40px)] max-xs:text-[32px] leading-[95%];
|
@apply lg:text-[clamp(64px,4.444vw,88px)] md:max-lg:text-[clamp(40px,40px+(100vw-768px)/672*24,64px)] xs:max-md:text-[clamp(32px,32px+(100vw-360px)/408*8,40px)] max-xs:text-[32px] leading-[95%];
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility heading1 {
|
.heading1 {
|
||||||
@apply lg:text-[clamp(28px,1.944vw,42px)] md:max-lg:text-[clamp(24px,24px+(100vw-768px)/672*4,28px)] text-2xl leading-[1.167];
|
@apply lg:text-[clamp(28px,1.944vw,42px)] md:max-lg:text-[clamp(24px,24px+(100vw-768px)/672*4,28px)] text-2xl leading-[1.167];
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility heading2 {
|
.heading2 {
|
||||||
@apply lg:text-[clamp(24px,1.667vw,36px)] md:max-lg:text-[clamp(20px,20px+(100vw-768px)/672*4,24px)] xs:max-md:text-[clamp(16px,16px+(100vw-360px)/408*4,20px)] text-base lg:leading-[1.2] leading-[1.125];
|
@apply lg:text-[clamp(24px,1.667vw,36px)] md:max-lg:text-[clamp(20px,20px+(100vw-768px)/672*4,24px)] xs:max-md:text-[clamp(16px,16px+(100vw-360px)/408*4,20px)] text-base lg:leading-[1.2] leading-[1.125];
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility accent {
|
.accent {
|
||||||
@apply lg:text-[clamp(32px,2.222vw,56px)] md:max-lg:text-[clamp(24px,24px+(100vw-768px)/672*8,32px)] text-2xl lg:leading-[1.1] leading-none;
|
@apply lg:text-[clamp(32px,2.222vw,56px)] md:max-lg:text-[clamp(24px,24px+(100vw-768px)/672*8,32px)] text-2xl lg:leading-[1.1] leading-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility text1 {
|
.text1 {
|
||||||
@apply lg:text-[clamp(18px,1.25vw,24px)] md:max-lg:text-[clamp(14px,14px+(100vw-768px)/672*4,18px)] text-sm leading-[1.35];
|
@apply lg:text-[clamp(18px,1.25vw,24px)] md:max-lg:text-[clamp(14px,14px+(100vw-768px)/672*4,18px)] text-sm leading-[1.35];
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility text2 {
|
.text2 {
|
||||||
@apply lg:text-[clamp(12px,0.972vw,20px)] md:max-lg:text-[clamp(12px,12px+(100vw-768px)/672*2,14px)] text-xs leading-[1.35];
|
@apply lg:text-[clamp(12px,0.972vw,20px)] md:max-lg:text-[clamp(12px,12px+(100vw-768px)/672*2,14px)] text-xs leading-[1.35];
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility btnl {
|
.btnl {
|
||||||
@apply lg:text-[clamp(18px,1.25vw,28px)] md:max-lg:text-[clamp(16px,16+(100vw-768px)/672*2,18px)] text-base leading-none;
|
@apply lg:text-[clamp(18px,1.25vw,28px)] md:max-lg:text-[clamp(16px,16+(100vw-768px)/672*2,18px)] text-base leading-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility btnm {
|
.btnm {
|
||||||
@apply lg:text-[clamp(16px,1.111vw,24px)] md:max-lg:text-[clamp(14px,14px+(100vw-768px)/672*2,16px)] text-sm leading-none;
|
@apply lg:text-[clamp(16px,1.111vw,24px)] md:max-lg:text-[clamp(14px,14px+(100vw-768px)/672*2,16px)] text-sm leading-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility btns {
|
.btns {
|
||||||
@apply lg:text-[clamp(14px,0.972vw,20px)] md:max-lg:text-[clamp(12px,12px+(100vw-768px)/672*2,14px)] text-xs leading-none;
|
@apply lg:text-[clamp(14px,0.972vw,20px)] md:max-lg:text-[clamp(12px,12px+(100vw-768px)/672*2,14px)] text-xs leading-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility caption {
|
.caption {
|
||||||
@apply text-[clamp(14px,14px+(100vw-360px)/1240*2,16px)] leading-none;
|
@apply text-[clamp(14px,14px+(100vw-360px)/1240*2,16px)] leading-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility text-gradient {
|
.text-gradient {
|
||||||
/* -webkit-background-clip: text;
|
/* -webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
@apply bg-gradient-to-r from-[#798FFF] to-[#D375FF] bg-clip-text; */
|
@apply bg-gradient-to-r from-[#798FFF] to-[#D375FF] bg-clip-text; */
|
||||||
background: linear-gradient(87deg, #798fff 15%, #d375ff 100%);
|
background: linear-gradient(87deg, #798fff 15%, #d375ff 100%);
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility bg-gradient {
|
.bg-gradient {
|
||||||
background: linear-gradient(87deg, #798fff 15%, #d375ff 100%);
|
background: linear-gradient(87deg, #798fff 15%, #d375ff 100%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ export function ArticleContentFormModal({
|
|||||||
drafted,
|
drafted,
|
||||||
posterImage,
|
posterImage,
|
||||||
id,
|
id,
|
||||||
|
locale: "en",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,27 +1,24 @@
|
|||||||
'use client';
|
"use client";
|
||||||
|
|
||||||
import { useArticleMutation } from '@/hooks/useArticleMutation';
|
import { useArticleMutation } from "@/hooks/useArticleMutation";
|
||||||
import { useModalStore } from '@/stores/useModalStore';
|
import { useModalStore } from "@/stores/useModalStore";
|
||||||
import { IArticle } from '@/types/IArticle';
|
import { IArticle } from "@/types/IArticle";
|
||||||
import { CheckboxesGroup } from '@/ui/CheckboxesGroup';
|
import { CheckboxesGroup } from "@/ui/CheckboxesGroup";
|
||||||
import { TextInput } from '@/ui/TextInput';
|
import { TextInput } from "@/ui/TextInput";
|
||||||
import { FormProvider, useForm, useWatch } from 'react-hook-form';
|
import { FormProvider, useForm, useWatch } from "react-hook-form";
|
||||||
import { ImageUploader } from '../ImageUploader';
|
import { ImageUploader } from "../ImageUploader";
|
||||||
import { ArticleContentFormModal } from './ArticleContentFormModal';
|
import { ArticleContentFormModal } from "./ArticleContentFormModal";
|
||||||
import { ArticleFormActions } from './ArticleFormActions';
|
import { ArticleFormActions } from "./ArticleFormActions";
|
||||||
import { FormModalHeader } from './FormModalHeader';
|
import { FormModalHeader } from "./FormModalHeader";
|
||||||
import ReactLenis, { LenisRef } from 'lenis/react';
|
|
||||||
import { useEffect, useRef } from 'react';
|
|
||||||
import { useLenis } from '@/hooks/useLenis';
|
|
||||||
|
|
||||||
interface IArticleFormModalProps<TAction extends 'create' | 'edit'> {
|
interface IArticleFormModalProps<TAction extends "create" | "edit"> {
|
||||||
action: TAction;
|
action: TAction;
|
||||||
defaultValues?: TAction extends 'edit' ? IArticle : undefined;
|
defaultValues?: TAction extends "edit" ? IArticle : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IArticleInput extends Omit<IArticle, 'id'> {}
|
export interface IArticleInput extends Omit<IArticle, "id"> {}
|
||||||
|
|
||||||
export function ArticleFormModal<TAction extends 'create' | 'edit'>({
|
export function ArticleFormModal<TAction extends "create" | "edit">({
|
||||||
action,
|
action,
|
||||||
defaultValues,
|
defaultValues,
|
||||||
}: IArticleFormModalProps<TAction>) {
|
}: IArticleFormModalProps<TAction>) {
|
||||||
@@ -34,7 +31,7 @@ export function ArticleFormModal<TAction extends 'create' | 'edit'>({
|
|||||||
tags: [],
|
tags: [],
|
||||||
drafted: true,
|
drafted: true,
|
||||||
},
|
},
|
||||||
mode: 'onChange',
|
mode: "onChange",
|
||||||
});
|
});
|
||||||
|
|
||||||
async function onSubmit(data: IArticleInput) {
|
async function onSubmit(data: IArticleInput) {
|
||||||
@@ -53,7 +50,7 @@ export function ArticleFormModal<TAction extends 'create' | 'edit'>({
|
|||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
...getValues(),
|
...getValues(),
|
||||||
blocks: JSON.stringify(
|
blocks: JSON.stringify(
|
||||||
defaultValues ? defaultValues.blocks : getValues('blocks') ?? []
|
defaultValues ? defaultValues.blocks : getValues("blocks") ?? []
|
||||||
),
|
),
|
||||||
drafted,
|
drafted,
|
||||||
});
|
});
|
||||||
@@ -61,7 +58,7 @@ export function ArticleFormModal<TAction extends 'create' | 'edit'>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { mutateAsync } = useArticleMutation(
|
const { mutateAsync } = useArticleMutation(
|
||||||
action === 'create'
|
action === "create"
|
||||||
? { action, id: undefined }
|
? { action, id: undefined }
|
||||||
: { action, id: defaultValues!.id }
|
: { action, id: defaultValues!.id }
|
||||||
);
|
);
|
||||||
@@ -101,7 +98,7 @@ export function ArticleFormModal<TAction extends 'create' | 'edit'>({
|
|||||||
</label>
|
</label>
|
||||||
<CheckboxesGroup
|
<CheckboxesGroup
|
||||||
name="tags"
|
name="tags"
|
||||||
options={['Недвижимость', 'Награды', 'Выставки']}
|
options={["Недвижимость", "Награды", "Выставки"]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ImageUploader
|
<ImageUploader
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { createRef, RefObject, useEffect, useRef, useState } from "react";
|
|||||||
import { useSwipeable } from "react-swipeable";
|
import { useSwipeable } from "react-swipeable";
|
||||||
import CloseIcon from "@/components/icons/CloseIcon";
|
import CloseIcon from "@/components/icons/CloseIcon";
|
||||||
import { ItemActions } from "../ItemActions";
|
import { ItemActions } from "../ItemActions";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
|
|
||||||
export function StoriesModal({ startIndex = 0 }: { startIndex?: number }) {
|
export function StoriesModal({ startIndex = 0 }: { startIndex?: number }) {
|
||||||
const { setModal } = useModalStore();
|
const { setModal } = useModalStore();
|
||||||
@@ -79,8 +78,6 @@ export function StoriesModal({ startIndex = 0 }: { startIndex?: number }) {
|
|||||||
onSwipedRight: () => setCurrentIndex((prev) => Math.max(0, prev - 1)),
|
onSwipedRight: () => setCurrentIndex((prev) => Math.max(0, prev - 1)),
|
||||||
});
|
});
|
||||||
|
|
||||||
const t = useTranslations("stories");
|
|
||||||
|
|
||||||
if (!stories || !stories.length) return null;
|
if (!stories || !stories.length) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -102,7 +99,7 @@ export function StoriesModal({ startIndex = 0 }: { startIndex?: number }) {
|
|||||||
className={`flex lg:gap-[1.667vw] md:max-lg:gap-6 items-center h-full relative`}
|
className={`flex lg:gap-[1.667vw] md:max-lg:gap-6 items-center h-full relative`}
|
||||||
>
|
>
|
||||||
{!!videoRefs.length &&
|
{!!videoRefs.length &&
|
||||||
stories?.map(({ id, video, preview, text, createdAt }, index) => (
|
stories.map(({ id, video, preview, text, createdAt }, index) => (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
transform: isLg
|
transform: isLg
|
||||||
@@ -113,10 +110,10 @@ export function StoriesModal({ startIndex = 0 }: { startIndex?: number }) {
|
|||||||
left: isLg || isMd ? `calc(${1 - currentIndex}*1.667vw)` : 0,
|
left: isLg || isMd ? `calc(${1 - currentIndex}*1.667vw)` : 0,
|
||||||
}}
|
}}
|
||||||
key={id}
|
key={id}
|
||||||
className={`select-none relative flex items-end group overflow-hidden lg:rounded-[0.833vw] md:max-lg:rounded-xl cursor-pointer transition-transform lg:p-[1.111vw] p-4 ${
|
className={`select-none relative flex items-end group overflow-hidden lg:rounded-[0.833vw] md:max-lg:rounded-xl cursor-pointer w-1/2 transition-transform lg:p-[1.111vw] p-4 ${
|
||||||
index === currentIndex
|
index === currentIndex
|
||||||
? "lg:min-w-[28.125vw] lg:h-[76.433vh] md:max-lg:min-w-[52.734vw] md:max-lg:h-[67.669vh] max-md:min-w-screen max-md:h-dvh"
|
? "lg:w-[28.125vw] lg:h-[76.433vh] md:max-lg:min-w-[52.734vw] md:max-lg:h-[67.669vh] max-md:min-w-screen max-md:h-dvh"
|
||||||
: "lg:min-w-[26.25vw] lg:h-[71.338vh] md:max-lg:min-w-[49.219vw] md:max-lg:h-[63.158vh] max-md:min-w-screen max-md:h-dvh"
|
: "lg:w-[26.25vw] lg:h-[71.338vh] md:max-lg:min-w-[49.219vw] md:max-lg:h-[63.158vh] max-md:min-w-screen max-md:h-dvh"
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setCurrentIndex(index)}
|
onClick={() => setCurrentIndex(index)}
|
||||||
>
|
>
|
||||||
@@ -136,7 +133,10 @@ export function StoriesModal({ startIndex = 0 }: { startIndex?: number }) {
|
|||||||
/>
|
/>
|
||||||
{currentIndex === index && (
|
{currentIndex === index && (
|
||||||
<div className="space-y-5 z-1 max-md:hidden">
|
<div className="space-y-5 z-1 max-md:hidden">
|
||||||
<p className="heading1 font-medium">{t(id)}</p>
|
<p className="heading1 font-medium">
|
||||||
|
Interactive sales tool GRAFF.estate for the Upside Towers
|
||||||
|
residential complex
|
||||||
|
</p>
|
||||||
<div className="bg-white/30 w-full h-1 rounded-[34px]">
|
<div className="bg-white/30 w-full h-1 rounded-[34px]">
|
||||||
<div
|
<div
|
||||||
className="h-1 bg-white transition-[width] rounded-[34px]"
|
className="h-1 bg-white transition-[width] rounded-[34px]"
|
||||||
@@ -152,7 +152,8 @@ export function StoriesModal({ startIndex = 0 }: { startIndex?: number }) {
|
|||||||
{stories && stories.length > 0 && (
|
{stories && stories.length > 0 && (
|
||||||
<div className="md:hidden absolute space-y-6 left-2.5 right-2.5 bottom-4 z-1 w-full">
|
<div className="md:hidden absolute space-y-6 left-2.5 right-2.5 bottom-4 z-1 w-full">
|
||||||
<p className="heading1 font-medium">
|
<p className="heading1 font-medium">
|
||||||
{stories[currentIndex]?.text}
|
Interactive sales tool GRAFF.estate for the Upside Towers
|
||||||
|
residential complex
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
{stories.map(({ id }, index) => (
|
{stories.map(({ id }, index) => (
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import ArrowMoreIcon from "@/components/icons/ArrowMoreIcon";
|
|||||||
import EditIcon from "@/components/icons/EditIcon";
|
import EditIcon from "@/components/icons/EditIcon";
|
||||||
import { ReactLenis } from "lenis/react";
|
import { ReactLenis } from "lenis/react";
|
||||||
import { useLenis } from "@/hooks/useLenis";
|
import { useLenis } from "@/hooks/useLenis";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
export function ArticleSyncPage({ slug }: { slug: string }) {
|
export function ArticleSyncPage({ slug }: { slug: string }) {
|
||||||
const { data: article } = useGetArticleById(slug);
|
const { data: article } = useGetArticleById(slug);
|
||||||
@@ -25,6 +26,8 @@ export function ArticleSyncPage({ slug }: { slug: string }) {
|
|||||||
|
|
||||||
const lenis = useLenis();
|
const lenis = useLenis();
|
||||||
|
|
||||||
|
const t = useTranslations("feedback");
|
||||||
|
|
||||||
if (!article) return null;
|
if (!article) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -68,9 +71,9 @@ export function ArticleSyncPage({ slug }: { slug: string }) {
|
|||||||
{article.tags.map((tag) => (
|
{article.tags.map((tag) => (
|
||||||
<div
|
<div
|
||||||
key={tag}
|
key={tag}
|
||||||
className="bg-[#37393B99] lg:rounded-[1.181vw] rounded-[17px] lg:px-[0.833vw] lg:py-[0.556vw] px-3 py-[7px] btns font-medium backdrop-blur-2xl"
|
className="bg-[#37393B99] text-nowrap lg:rounded-[1.181vw] rounded-[17px] lg:px-[0.833vw] lg:py-[0.556vw] px-3 py-[7px] btns font-medium backdrop-blur-2xl"
|
||||||
>
|
>
|
||||||
{tag}
|
{t(tag)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -80,7 +83,7 @@ export function ArticleSyncPage({ slug }: { slug: string }) {
|
|||||||
{article.blocks.map((block, index) => (
|
{article.blocks.map((block, index) => (
|
||||||
<Fragment key={index}>
|
<Fragment key={index}>
|
||||||
{block.type === "Content" ? (
|
{block.type === "Content" ? (
|
||||||
<div className="lg:max-w-2/3 [&_p_*]:!text1 [&_h1_*]:!heading1 [&_h2_*]:!heading2">
|
<div className="[&_p_*]:!text1 [&_h1_*]:!heading1 [&_h2_*]:!heading2">
|
||||||
{parse(block.content)}
|
{parse(block.content)}
|
||||||
</div>
|
</div>
|
||||||
) : block.type === "ButtonLink" ? (
|
) : block.type === "ButtonLink" ? (
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
/* eslint-disable @next/next/no-img-element */
|
/* eslint-disable @next/next/no-img-element */
|
||||||
'use client';
|
"use client";
|
||||||
|
|
||||||
import { ItemActions } from '@/components/ItemActions';
|
import { ItemActions } from "@/components/ItemActions";
|
||||||
import { IArticle } from '@/types/IArticle';
|
import { IArticle } from "@/types/IArticle";
|
||||||
import { PostTag } from '@/ui/PostTag';
|
import { PostTag } from "@/ui/PostTag";
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
import { useTranslations } from "next-intl";
|
||||||
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
|
|
||||||
export function ArticleCard({
|
export function ArticleCard({
|
||||||
id,
|
id,
|
||||||
@@ -22,11 +23,13 @@ export function ArticleCard({
|
|||||||
|
|
||||||
const { push } = useRouter();
|
const { push } = useRouter();
|
||||||
|
|
||||||
|
const t = useTranslations("feedback");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={() => !drafted && push('/blog/' + slug)}
|
onClick={() => !drafted && push("/blog/" + slug)}
|
||||||
className={`${
|
className={`${
|
||||||
className ? className + ' ' : ''
|
className ? className + " " : ""
|
||||||
}hover:backdrop-blur-[500px] cursor-pointer h-full group flex flex-col justify-between gap-3 overflow-hidden transition-[background-size] lg:bg-[length:100%_0%] bg-bottom hover:bg-[length:100%_100%] bg-no-repeat lg:rounded-[1.111vw] rounded-2xl lg:p-[0.833vw] p-3 relative`}
|
}hover:backdrop-blur-[500px] cursor-pointer h-full group flex flex-col justify-between gap-3 overflow-hidden transition-[background-size] lg:bg-[length:100%_0%] bg-bottom hover:bg-[length:100%_100%] bg-no-repeat lg:rounded-[1.111vw] rounded-2xl lg:p-[0.833vw] p-3 relative`}
|
||||||
>
|
>
|
||||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_bottom,#7A7A7A50,transparent)] max-lg:opacity-100 opacity-0 group-hover:opacity-100 transition-opacity" />
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_bottom,#7A7A7A50,transparent)] max-lg:opacity-100 opacity-0 group-hover:opacity-100 transition-opacity" />
|
||||||
@@ -42,9 +45,9 @@ export function ArticleCard({
|
|||||||
<div className="flex flex-wrap lg:gap-[0.278vw] gap-1">
|
<div className="flex flex-wrap lg:gap-[0.278vw] gap-1">
|
||||||
{tags.map((tag) => (
|
{tags.map((tag) => (
|
||||||
<PostTag
|
<PostTag
|
||||||
text={tag}
|
text={t(tag)}
|
||||||
key={tag}
|
key={tag}
|
||||||
active={params.getAll('tags').includes(tag)}
|
active={params.getAll("tags").includes(tag)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -58,6 +61,7 @@ export function ArticleCard({
|
|||||||
drafted,
|
drafted,
|
||||||
posterImage,
|
posterImage,
|
||||||
createdAt,
|
createdAt,
|
||||||
|
locale: "en",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export function ArticlesList() {
|
|||||||
className="lg:w-[21.435vw] lg:aspect-[308.67/352] md:max-lg:w-[47.135vw] max-md:w-full"
|
className="lg:w-[21.435vw] lg:aspect-[308.67/352] md:max-lg:w-[47.135vw] max-md:w-full"
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<div className="bg-[#37393B99] nth-[3n+1]:m-auto nth-[3n]:w-[21.25vw] max-lg:hidden lg:rounded-[1.111vw] rounded-2xl p-[1.111vw] w-[43.611vw] h-[24.444vw] bg-[url(/img/pages/blog/tg/into_lapenko.jpg)] bg-no-repeat bg-right-bottom bg-[length:calc(582.85/628*100%)] flex flex-col justify-between">
|
{/* <div className="bg-[#37393B99] nth-[3n+1]:m-auto nth-[3n]:w-[21.25vw] max-lg:hidden lg:rounded-[1.111vw] rounded-2xl p-[1.111vw] w-[43.611vw] h-[24.444vw] bg-[url(/img/pages/blog/tg/into_lapenko.jpg)] bg-no-repeat bg-right-bottom bg-[length:calc(582.85/628*100%)] flex flex-col justify-between">
|
||||||
<div className="text1 font-medium lg:max-w-[25.069vw]">
|
<div className="text1 font-medium lg:max-w-[25.069vw]">
|
||||||
We haven't moved all publications here yet, but you can find
|
We haven't moved all publications here yet, but you can find
|
||||||
the actual content in our Telegram channel{" "}
|
the actual content in our Telegram channel{" "}
|
||||||
@@ -52,7 +52,7 @@ export function ArticlesList() {
|
|||||||
<TelegramIcon />
|
<TelegramIcon />
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export function Clients() {
|
|||||||
"Центр-Инвест",
|
"Центр-Инвест",
|
||||||
"DNS",
|
"DNS",
|
||||||
"ПСК Дом девелопмент",
|
"ПСК Дом девелопмент",
|
||||||
|
"ПИК",
|
||||||
];
|
];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { enMapProject } from '@/consts/mockEnMapProject';
|
import { enMapProjects } from "@/consts/mockEnMapProject";
|
||||||
import { useLongPress } from '@/hooks/useLongPress';
|
import { useLongPress } from "@/hooks/useLongPress";
|
||||||
import { useMediaQueries } from '@/hooks/useMediaQueries';
|
import { useMediaQueries } from "@/hooks/useMediaQueries";
|
||||||
import { useGetProjectsCountQuery } from '@/queries/getProjectsCount';
|
import { useGetProjectsCountQuery } from "@/queries/getProjectsCount";
|
||||||
import { useCityPointStore } from '@/stores/useCityPointStore';
|
import { useCityPointStore } from "@/stores/useCityPointStore";
|
||||||
import { ICityProjects } from '@/types/ICityProjects';
|
import { ICityProjects } from "@/types/ICityProjects";
|
||||||
import { IMapProject } from '@/types/IMapProject';
|
import { IMapProject } from "@/types/IMapProject";
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from "next-intl";
|
||||||
import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react';
|
import { Dispatch, SetStateAction, useEffect, useRef, useState } from "react";
|
||||||
import { useHover } from 'usehooks-ts';
|
import { useHover } from "usehooks-ts";
|
||||||
|
|
||||||
export function CityPoint({
|
export function CityPoint({
|
||||||
x,
|
x,
|
||||||
@@ -25,7 +25,7 @@ export function CityPoint({
|
|||||||
setCurrentHovered: Dispatch<SetStateAction<number | undefined>>;
|
setCurrentHovered: Dispatch<SetStateAction<number | undefined>>;
|
||||||
projects?: IMapProject[];
|
projects?: IMapProject[];
|
||||||
}) {
|
}) {
|
||||||
const count = enMapProject[title as keyof typeof enMapProject]?.length || 0;
|
const count = enMapProjects.length || 0;
|
||||||
|
|
||||||
const { setCityPoint } = useCityPointStore();
|
const { setCityPoint } = useCityPointStore();
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ export function CityPoint({
|
|||||||
|
|
||||||
const [animationCompleted, setAnimationCompleted] = useState(false);
|
const [animationCompleted, setAnimationCompleted] = useState(false);
|
||||||
|
|
||||||
const t = useTranslations('cities');
|
const t = useTranslations("cities");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (animationCompleted && circleRef.current)
|
if (animationCompleted && circleRef.current)
|
||||||
@@ -87,18 +87,18 @@ export function CityPoint({
|
|||||||
ref={pointRef}
|
ref={pointRef}
|
||||||
style={{ left: `${x}%`, top: `${y}%` }}
|
style={{ left: `${x}%`, top: `${y}%` }}
|
||||||
className={`absolute outline-none lg:px-[1.111vw] lg:py-[0.625vw] flex lg:gap-[0.278vw] items-center transition-colors cursor-pointer select-none font-medium ${
|
className={`absolute outline-none lg:px-[1.111vw] lg:py-[0.625vw] flex lg:gap-[0.278vw] items-center transition-colors cursor-pointer select-none font-medium ${
|
||||||
active ? 'text-white' : 'text-[#7A7A7A]'
|
active ? "text-white" : "text-[#7A7A7A]"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
className={`heading2 font-medium${active ? ' z-2' : ''}`}
|
className={`heading2 font-medium${active ? " z-2" : ""}`}
|
||||||
ref={refTitle}
|
ref={refTitle}
|
||||||
>
|
>
|
||||||
{localeKey ? t(localeKey) : title}
|
{localeKey ? t(localeKey) : title}
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
className={`btns lg:h-[2.083vw] font-medium h-[5.114vw]${
|
className={`btns lg:h-[2.083vw] font-medium h-[5.114vw]${
|
||||||
active ? ' z-2' : ''
|
active ? " z-2" : ""
|
||||||
}`}
|
}`}
|
||||||
ref={refCount}
|
ref={refCount}
|
||||||
>
|
>
|
||||||
@@ -121,7 +121,7 @@ export function CityPoint({
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
onAnimationComplete={() => setAnimationCompleted(true)}
|
onAnimationComplete={() => setAnimationCompleted(true)}
|
||||||
className='absolute rounded-full aspect-square z-1 [backdrop-filter:blur(3.21px)] bg-[radial-gradient(#37393B00,#37393B99)] -translate-x-1/2 left-1/2'
|
className="absolute rounded-full aspect-square z-1 [backdrop-filter:blur(3.21px)] bg-[radial-gradient(#37393B00,#37393B99)] -translate-x-1/2 left-1/2"
|
||||||
/>
|
/>
|
||||||
{!!projects?.length &&
|
{!!projects?.length &&
|
||||||
circleRef.current &&
|
circleRef.current &&
|
||||||
@@ -189,8 +189,8 @@ export function LogoItem({
|
|||||||
top: -circleRadius,
|
top: -circleRadius,
|
||||||
}}
|
}}
|
||||||
exit={{ opacity: 0, transition: { delay: index * 0.1 } }}
|
exit={{ opacity: 0, transition: { delay: index * 0.1 } }}
|
||||||
transition={{ delay: index * 0.1 + 0.3, bounce: 'none' }}
|
transition={{ delay: index * 0.1 + 0.3, bounce: "none" }}
|
||||||
className='max-w-[6.264vw] w-full aspect-square absolute rounded-[1.567vw] -left-[9.049vw]'
|
className="max-w-[6.264vw] w-full aspect-square absolute rounded-[1.567vw] -left-[9.049vw]"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
'use client';
|
"use client";
|
||||||
|
|
||||||
import { cities, mobileCities } from '@/consts/cities';
|
import { cities, mobileCities } from "@/consts/cities";
|
||||||
import { useGetMapPointByCity } from '@/queries/getMapPointByCity';
|
import { useGetMapPointByCity } from "@/queries/getMapPointByCity";
|
||||||
import { useCityPointStore } from '@/stores/useCityPointStore';
|
import { useCityPointStore } from "@/stores/useCityPointStore";
|
||||||
import { useState } from 'react';
|
import { useState } from "react";
|
||||||
import { CityPoint } from './CityPoint';
|
import { CityPoint } from "./CityPoint";
|
||||||
import { Slider } from './Slider';
|
import { Slider } from "./Slider";
|
||||||
import { useMediaQueries } from '@/hooks/useMediaQueries';
|
import { useMediaQueries } from "@/hooks/useMediaQueries";
|
||||||
import { Icon } from '@/ui/Icon';
|
import { Icon } from "@/ui/Icon";
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
export function Map() {
|
export function Map() {
|
||||||
const { cityPoint } = useCityPointStore();
|
const { cityPoint } = useCityPointStore();
|
||||||
@@ -19,12 +19,12 @@ export function Map() {
|
|||||||
|
|
||||||
const { isLg } = useMediaQueries();
|
const { isLg } = useMediaQueries();
|
||||||
|
|
||||||
const t = useTranslations('map');
|
const t = useTranslations("map");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='relative'>
|
<div className="relative">
|
||||||
<div className='max-lg:overflow-x-auto overflow-y-visible h-full scrollbar-hide max-lg:aspect-[340/620] md:max-lg:-mx-4 max-md:-mx-2.5 mt-16 relative'>
|
<div className="max-lg:overflow-x-auto overflow-y-visible h-full scrollbar-hide max-lg:aspect-[340/620] md:max-lg:-mx-4 max-md:-mx-2.5 mt-16 relative">
|
||||||
<div className='lg:bg-[url(/img/pages/home/stats/map2.0.png)] bg-[url(/img/pages/home/stats/map_mobile.png)] -mt-19 bg-no-repeat bg-contain lg:aspect-[1432.4/731.98] h-full aspect-[1068.86/586.76] relative'>
|
<div className="lg:bg-[url(/img/pages/home/stats/map2.0.png)] bg-[url(/img/pages/home/stats/map_mobile.png)] -mt-19 bg-no-repeat bg-contain lg:aspect-[1432.4/731.98] h-full aspect-[1068.86/586.76] relative">
|
||||||
{(isLg ? cities : mobileCities).map((point, index) => (
|
{(isLg ? cities : mobileCities).map((point, index) => (
|
||||||
<CityPoint
|
<CityPoint
|
||||||
key={point.title}
|
key={point.title}
|
||||||
@@ -37,21 +37,21 @@ export function Map() {
|
|||||||
}
|
}
|
||||||
index={index}
|
index={index}
|
||||||
setCurrentHovered={setCurrentHovered}
|
setCurrentHovered={setCurrentHovered}
|
||||||
projects={point.title === cityPoint?.title ? mapPoint : undefined}
|
// projects={point.title === cityPoint?.title ? mapPoint : undefined}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<Slider mapPoint={mapPoint} />
|
<Slider />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='lg:hidden absolute left-[50vw] bottom-[4.444vw] translate-y-1/2 -translate-x-1/2 w-[68.611vw] aspect-[247/56] rounded-[4.444vw] bg-[#37393B99] px-[4.167vw] py-[4.444vw] flex gap-[2.222vw] justify-between items-center'>
|
<div className="lg:hidden absolute left-[50vw] bottom-[4.444vw] translate-y-1/2 -translate-x-1/2 w-[68.611vw] aspect-[247/56] rounded-[4.444vw] bg-[#37393B99] px-[4.167vw] py-[4.444vw] flex gap-[2.222vw] justify-between items-center">
|
||||||
<div className='w-[6.667vw] h-[6.667vw]'>
|
<div className="w-[6.667vw] h-[6.667vw]">
|
||||||
<Icon
|
<Icon
|
||||||
name='finger_print'
|
name="finger_print"
|
||||||
svgProp={{ className: 'w-[6.667vw] h-[6.667vw]' }}
|
svgProp={{ className: "w-[6.667vw] h-[6.667vw]" }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p className='caption leading-[120%] font-medium select-none'>
|
<p className="caption leading-[120%] font-medium select-none">
|
||||||
{t('instruction')}
|
{t("instruction")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+12
-13
@@ -4,7 +4,7 @@ import { queryOptions, useQuery } from '@tanstack/react-query';
|
|||||||
|
|
||||||
export const queryArticlesOptions = {
|
export const queryArticlesOptions = {
|
||||||
queryKey: ['articles'],
|
queryKey: ['articles'],
|
||||||
queryFn: () => api.get('articles').json<IArticle[]>(),
|
queryFn: () => api.get('articles', { searchParams: { locale: "en" } }).json<IArticle[]>(),
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useGetArticlesQuery(tags?: string | string[]) {
|
export function useGetArticlesQuery(tags?: string | string[]) {
|
||||||
@@ -12,18 +12,17 @@ export function useGetArticlesQuery(tags?: string | string[]) {
|
|||||||
queryOptions(
|
queryOptions(
|
||||||
tags && tags.length > 0
|
tags && tags.length > 0
|
||||||
? {
|
? {
|
||||||
queryKey: ['articles', tags],
|
queryKey: ['articles', tags],
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
api
|
api
|
||||||
.get(
|
.get(
|
||||||
`articles?${
|
`articles?${Array.isArray(tags)
|
||||||
Array.isArray(tags)
|
? tags.map((tag) => `tags=${tag}`).join('&')
|
||||||
? tags.map((tag) => `tags=${tag}`).join('&')
|
: 'tags=' + tags
|
||||||
: 'tags=' + tags
|
}&locale=en`
|
||||||
}`
|
)
|
||||||
)
|
.json<IArticle[]>(),
|
||||||
.json<IArticle[]>(),
|
}
|
||||||
}
|
|
||||||
: queryArticlesOptions
|
: queryArticlesOptions
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { api } from '@/api';
|
import { api } from '@/api';
|
||||||
import { enMapProject } from '@/consts/mockEnMapProject';
|
import { enMapProjects } from '@/consts/mockEnMapProject';
|
||||||
import { useCityPointStore } from '@/stores/useCityPointStore';
|
import { useCityPointStore } from '@/stores/useCityPointStore';
|
||||||
import { IMapProject } from '@/types/IMapProject';
|
import { IMapProject } from '@/types/IMapProject';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
@@ -15,6 +15,6 @@ export function useGetMapPointByCity() {
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: enMapProject[cityPoint?.title as keyof typeof enMapProject],
|
data: enMapProjects,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,6 @@ export function useGetStories() {
|
|||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ['stories'],
|
queryKey: ['stories'],
|
||||||
queryFn: () => api.get('stories').json<IStory[]>(),
|
queryFn: () => api.get('stories').json<IStory[]>(),
|
||||||
|
select: (data) => data.slice(2, 3),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,4 +44,5 @@ export interface IArticle {
|
|||||||
drafted: boolean;
|
drafted: boolean;
|
||||||
slug?: string;
|
slug?: string;
|
||||||
blocks: Block[];
|
blocks: Block[];
|
||||||
|
locale: 'ru' | 'en';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ["./src/**/*.{js,ts,jsx,tsx,mdx}"],
|
||||||
|
theme: {
|
||||||
|
screens: {
|
||||||
|
xs: "360px",
|
||||||
|
sm: "640px",
|
||||||
|
md: "768px",
|
||||||
|
lg: "1440px",
|
||||||
|
"2xl": "1536px",
|
||||||
|
},
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user