fixes, added form, some animatoins
This commit is contained in:
@@ -1 +1 @@
|
|||||||
PUBLIC_API_URL=https://graff.estate/api
|
VITE_PUBLIC_API_URL=https://graff.estate/api
|
||||||
@@ -2,6 +2,7 @@ import { Outlet } from 'react-router-dom';
|
|||||||
import { Header } from './components/Layout/Header';
|
import { Header } from './components/Layout/Header';
|
||||||
import { Navbar } from './components/Layout/Navbar';
|
import { Navbar } from './components/Layout/Navbar';
|
||||||
import { Footer } from './components/Layout/Footer';
|
import { Footer } from './components/Layout/Footer';
|
||||||
|
import ModalContainer from './components/Main/ModalContainer';
|
||||||
|
|
||||||
export default function Layout() {
|
export default function Layout() {
|
||||||
return (
|
return (
|
||||||
@@ -12,6 +13,7 @@ export default function Layout() {
|
|||||||
<Outlet />
|
<Outlet />
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
<ModalContainer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import ky from 'ky';
|
import ky from 'ky';
|
||||||
|
|
||||||
const api = ky.extend({
|
const api = ky.extend({
|
||||||
prefixUrl: process.env.PUBLIC_API_URL,
|
prefixUrl: import.meta.env.VITE_PUBLIC_API_URL,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default api;
|
export default api;
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 410 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 235 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 224 KiB |
@@ -4,10 +4,13 @@ import { Link } from 'react-router-dom';
|
|||||||
import { Lang, useLang } from '../../store/language';
|
import { Lang, useLang } from '../../store/language';
|
||||||
import { HashLink } from 'react-router-hash-link';
|
import { HashLink } from 'react-router-hash-link';
|
||||||
import { useOnClickOutside } from 'usehooks-ts';
|
import { useOnClickOutside } from 'usehooks-ts';
|
||||||
|
import useModalStore from '../../store/modal';
|
||||||
|
import ContactsForm from '../Main/ContactsForm';
|
||||||
|
|
||||||
export function Navbar() {
|
export function Navbar() {
|
||||||
const [menuOpen, setMenuOpen] = useState(false);
|
const [menuOpen, setMenuOpen] = useState(false);
|
||||||
const { value: lang } = useLang();
|
const { value: lang } = useLang();
|
||||||
|
const setModal = useModalStore(state => state.setModal);
|
||||||
|
|
||||||
const menuRef = useRef<HTMLDivElement>(null);
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
const menuBtnRef = useRef<HTMLButtonElement>(null);
|
const menuBtnRef = useRef<HTMLButtonElement>(null);
|
||||||
@@ -32,7 +35,10 @@ export function Navbar() {
|
|||||||
<NavLink route="#trainings">Варианты комплектации</NavLink>
|
<NavLink route="#trainings">Варианты комплектации</NavLink>
|
||||||
<NavLink route="#projects">Проекты</NavLink>
|
<NavLink route="#projects">Проекты</NavLink>
|
||||||
<NavLink route="#events">События</NavLink>
|
<NavLink route="#events">События</NavLink>
|
||||||
<button className="btn-text font-semibold text-[#ffffff] bg-gradient-to-r from-[#798FFF] to-[#D375FF] border-x border-[#3D425C] tablet:block mobile:hidden px-10">
|
<button
|
||||||
|
onClick={() => setModal(<ContactsForm />)}
|
||||||
|
className="btn-text font-semibold text-[#ffffff] bg-gradient-to-r from-[#798FFF] to-[#D375FF] border-x border-[#3D425C] tablet:block mobile:hidden px-10"
|
||||||
|
>
|
||||||
Оставить заявку
|
Оставить заявку
|
||||||
</button>
|
</button>
|
||||||
<LangToggler lang={lang} />
|
<LangToggler lang={lang} />
|
||||||
@@ -62,7 +68,13 @@ export function Navbar() {
|
|||||||
<BurgerLink route="#projects">Проекты</BurgerLink>
|
<BurgerLink route="#projects">Проекты</BurgerLink>
|
||||||
<BurgerLink route="#events">События</BurgerLink>
|
<BurgerLink route="#events">События</BurgerLink>
|
||||||
<div className="grid mobile:max-tablet:grid-cols-[216px_1fr_1fr] tablet:grid-cols-2">
|
<div className="grid mobile:max-tablet:grid-cols-[216px_1fr_1fr] tablet:grid-cols-2">
|
||||||
<button className="text-[#ffffff] tablet:hidden font-semibold btn-text bg-gradient-to-r from-[#798FFF] to-[#D375FF] py-[30px] px-10">
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setMenuOpen(false);
|
||||||
|
setModal(<ContactsForm />);
|
||||||
|
}}
|
||||||
|
className="text-[#ffffff] tablet:hidden font-semibold btn-text bg-gradient-to-r from-[#798FFF] to-[#D375FF] py-[30px] px-10"
|
||||||
|
>
|
||||||
Оставить заявку
|
Оставить заявку
|
||||||
</button>
|
</button>
|
||||||
<ChooseLang lang="RU" />
|
<ChooseLang lang="RU" />
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import AppearanceHr from '../../ui/AppearanceHr';
|
||||||
import { AppearanceText } from '../../ui/AppearanceText';
|
import { AppearanceText } from '../../ui/AppearanceText';
|
||||||
import { MiniTitle } from '../../ui/MiniTitle';
|
import { MiniTitle } from '../../ui/MiniTitle';
|
||||||
import { Title } from '../../ui/Title';
|
import { Title } from '../../ui/Title';
|
||||||
@@ -19,10 +20,11 @@ export function Availables() {
|
|||||||
<br />
|
<br />
|
||||||
режим обучения
|
режим обучения
|
||||||
</Title>
|
</Title>
|
||||||
<div className="flex mobile:max-desktop:flex-col items-start desktop:w-fit tablet:pt-5 tablet:border-t border-[#3D425C]">
|
<AppearanceHr className="mobile:max-tablet:hidden" />
|
||||||
|
<div className="flex mobile:max-desktop:flex-col items-start desktop:w-fit tablet:pt-5">
|
||||||
<MiniTitle text="возможности" />
|
<MiniTitle text="возможности" />
|
||||||
<div className="tablet:max-desktop-figma:mt-4 mobile:max-tablet:mt-[9px]">
|
<div className="tablet:max-desktop-figma:mt-4 mobile:max-tablet:mt-[9px]">
|
||||||
<div className="flex mobile:max-tablet:flex-col mobile:max-tablet:gap-y-2 desktop:gap-x-4 tablet:max-desktop:gap-x-3 border-b border-[#3D425C] tablet:pb-5 mobile:pb-2 mb-6 mobile:max-tablet:border-t mobile:max-tablet:pt-2">
|
<div className="flex mobile:max-tablet:flex-col mobile:max-tablet:gap-y-2 desktop:gap-x-4 tablet:max-desktop:gap-x-3 tablet:pb-5 mobile:pb-2 mobile:max-tablet:border-t mobile:max-tablet:pt-2">
|
||||||
<MultiUserFeature
|
<MultiUserFeature
|
||||||
img="src/assets/processes.svg"
|
img="src/assets/processes.svg"
|
||||||
text="отработка производственных процессов, в которых участвует группа людей"
|
text="отработка производственных процессов, в которых участвует группа людей"
|
||||||
@@ -36,6 +38,7 @@ export function Availables() {
|
|||||||
text="координация действий между несколькими сотрудниками"
|
text="координация действий между несколькими сотрудниками"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<AppearanceHr className=" mb-6" />
|
||||||
<AppearanceText
|
<AppearanceText
|
||||||
className="tablet-figma:max-w-[668px] desktop-figma:max-w-[39.25vw]"
|
className="tablet-figma:max-w-[668px] desktop-figma:max-w-[39.25vw]"
|
||||||
splits={[
|
splits={[
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
import useModalStore from '../../store/modal';
|
||||||
import { Title } from '../../ui/Title';
|
import { Title } from '../../ui/Title';
|
||||||
|
import ContactsForm from './ContactsForm';
|
||||||
|
|
||||||
export function Contacts() {
|
export function Contacts() {
|
||||||
|
const setModal = useModalStore(state => state.setModal);
|
||||||
return (
|
return (
|
||||||
<div className="desktop:py-[70px] desktop:px-10 mobile:py-14 tablet:px-6 mobile:px-4 desktop:flex justify-between gap-x-4">
|
<div className="desktop:py-[70px] desktop:px-10 mobile:py-14 tablet:px-6 mobile:px-4 desktop:flex justify-between gap-x-4">
|
||||||
<div className="tablet:max-desktop:mb-20 mobile:mb-14">
|
<div className="tablet:max-desktop:mb-20 mobile:mb-14">
|
||||||
@@ -18,7 +21,10 @@ export function Contacts() {
|
|||||||
Давайте обсудим детали.
|
Давайте обсудим детали.
|
||||||
</span>
|
</span>
|
||||||
</Title>
|
</Title>
|
||||||
<button className="bg-gradient-to-r from-[#798FFF] to-[#D375FF] rounded-[104px] py-4 px-6 flex font-semibold text-[#ffffff] justify-between desktop-figma:min-w-[23vw] desktop:max-desktop-figma:min-w-[368px] tablet:max-desktop:min-w-[332px] mobile:max-tablet:w-full items-center btn-text">
|
<button
|
||||||
|
onClick={() => setModal(<ContactsForm />)}
|
||||||
|
className="bg-gradient-to-r from-[#798FFF] to-[#D375FF] rounded-[104px] py-4 px-6 flex font-semibold text-[#ffffff] justify-between desktop-figma:min-w-[23vw] desktop:max-desktop-figma:min-w-[368px] tablet:max-desktop:min-w-[332px] mobile:max-tablet:w-full items-center btn-text"
|
||||||
|
>
|
||||||
Оставить заявку <img src="src/assets/send.svg" alt="" />
|
Оставить заявку <img src="src/assets/send.svg" alt="" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,14 +7,16 @@ import Button from '../../ui/Button';
|
|||||||
import LoaderIcon from '../icons/LoaderIcon';
|
import LoaderIcon from '../icons/LoaderIcon';
|
||||||
import SendIcon from '../icons/SendIcon';
|
import SendIcon from '../icons/SendIcon';
|
||||||
import CheckGradientIcon from '../icons/CheckGradientIcon';
|
import CheckGradientIcon from '../icons/CheckGradientIcon';
|
||||||
|
import useModalStore from '../../store/modal';
|
||||||
|
|
||||||
function ContactsForm() {
|
function ContactsForm() {
|
||||||
const [name, setName] = useState<string>('');
|
const [name, setName] = useState('');
|
||||||
const [phone, setPhone] = useState<string>('');
|
const [phone, setPhone] = useState('');
|
||||||
const [email, setEmail] = useState<string>('');
|
const [email, setEmail] = useState('');
|
||||||
const [description, setDescription] = useState<string>('');
|
const [description, setDescription] = useState('');
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [isSend, setIsSend] = useState<boolean>(false);
|
const [isSend, setIsSend] = useState(false);
|
||||||
|
const setModal = useModalStore(state => state.setModal);
|
||||||
|
|
||||||
function handleSubmit(e: FormEvent<HTMLFormElement>) {
|
function handleSubmit(e: FormEvent<HTMLFormElement>) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -50,132 +52,144 @@ function ContactsForm() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!isSend ? (
|
{!isSend ? (
|
||||||
<div className="flex flex-col gap-5">
|
<div className="fixed top-0 right-0 h-full sm:w-[408px] w-full bg-[#14161F] overflow-y-auto sm:p-8 p-6">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex flex-col gap-4">
|
||||||
<p className="font-gilroy text-gradient sm:text-2xl text-xl w-fit font-semibold">
|
<div className="flex flex-col gap-5">
|
||||||
Свяжитесь с нами
|
<div className="flex justify-between items-center">
|
||||||
</p>
|
<p
|
||||||
<button className="p-2 hover:bg-white hover:bg-opacity-10 transition-colors rounded-full">
|
className="w-fit font-semibold bg-text-gradient bg-gradient-to-r from-[#798FFF] to-[#D375FF] sm:text-2xl text-xl"
|
||||||
<Close2Icon />
|
style={{
|
||||||
</button>
|
backgroundClip: 'text',
|
||||||
</div>
|
WebkitBackgroundClip: 'text',
|
||||||
<form onSubmit={handleSubmit} className="flex flex-col gap-6">
|
WebkitTextFillColor: 'transparent',
|
||||||
<div>
|
}}
|
||||||
<div className="relative">
|
>
|
||||||
<input
|
Свяжитесь с нами
|
||||||
required
|
|
||||||
type="text"
|
|
||||||
value={name}
|
|
||||||
onChange={e => setName(e.target.value)}
|
|
||||||
className="feedback-field bg-transparent border border-[#3D425C] rounded-none sm:pt-12 sm:pb-4 sm:px-4 pt-8 pb-3 px-3 outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
|
|
||||||
/>
|
|
||||||
<p className="feedback-placeholder lg:text-base text-sm absolute sm:pt-4 sm:pb-4 sm:px-4 sm:top-4 pt-3 pb-3 px-3 top-3 w-full opacity-50 transition-all pointer-events-none flex justify-between items-center">
|
|
||||||
<span>Имя</span>
|
|
||||||
<AsteriskIcon />
|
|
||||||
</p>
|
</p>
|
||||||
|
<button
|
||||||
|
onClick={() => setModal(null)}
|
||||||
|
className="p-2 hover:bg-white hover:bg-opacity-10 transition-colors rounded-full"
|
||||||
|
>
|
||||||
|
<Close2Icon className="text-white" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<form onSubmit={handleSubmit} className="flex flex-col gap-6">
|
||||||
<div className="relative">
|
<div>
|
||||||
<InputMask
|
<div className="relative">
|
||||||
required
|
<input
|
||||||
type="tel"
|
required
|
||||||
mask={'+999999999999999'}
|
type="text"
|
||||||
maskChar={null}
|
value={name}
|
||||||
value={phone}
|
onChange={e => setName(e.target.value)}
|
||||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
className="feedback-field bg-transparent border border-[#3D425C] rounded-none sm:pt-12 sm:pb-4 sm:px-4 pt-8 pb-3 px-3 outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
|
||||||
setPhone(e.target.value)
|
/>
|
||||||
}
|
<p className="feedback-placeholder lg:text-base text-sm absolute sm:pt-4 sm:pb-4 sm:px-4 sm:top-4 pt-3 pb-3 px-3 top-3 w-full opacity-50 transition-all pointer-events-none flex justify-between items-center">
|
||||||
className={[
|
<span>Имя</span>
|
||||||
'feedback-field bg-transparent border rounded-none border-t-0 border-[#3D425C] sm:pt-12 sm:pb-4 sm:px-4 pt-8 pb-3 px-3 outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full',
|
<AsteriskIcon />
|
||||||
].join(' ')}
|
</p>
|
||||||
/>
|
|
||||||
<p className="feedback-placeholder lg:text-base text-sm absolute sm:pt-4 sm:pb-4 sm:px-4 sm:top-4 pt-3 pb-3 px-3 top-3 w-full opacity-50 transition-all pointer-events-none flex justify-between items-center">
|
|
||||||
<span>Телефон</span>
|
|
||||||
<AsteriskIcon />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="relative">
|
|
||||||
<input
|
|
||||||
required
|
|
||||||
type="text"
|
|
||||||
value={email}
|
|
||||||
onChange={e => setEmail(e.target.value)}
|
|
||||||
className="feedback-field bg-transparent border rounded-none border-t-0 border-[#3D425C] sm:pt-12 sm:pb-4 sm:px-4 pt-8 pb-3 px-3 outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
|
|
||||||
/>
|
|
||||||
<p className="feedback-placeholder lg:text-base text-sm absolute sm:pt-4 sm:pb-4 sm:px-4 sm:top-4 pt-3 pb-3 px-3 top-3 w-full opacity-50 transition-all pointer-events-none flex justify-between items-center">
|
|
||||||
<span>Email</span>
|
|
||||||
<AsteriskIcon />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="relative">
|
|
||||||
<textarea
|
|
||||||
placeholder="Опишите вашу задачу"
|
|
||||||
value={description}
|
|
||||||
onChange={e => setDescription(e.target.value)}
|
|
||||||
className="feedback-field bg-transparent resize-none border rounded-none border-t-0 border-[#3D425C] p-4 sm:min-h-[192px] min-h-[128px] outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
|
|
||||||
></textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="border border-t-0 border-[#3D425C] 2xl:p-6 p-4 sm:mt-0 flex items-center"
|
|
||||||
style={{ marginTop: '-6px' }}
|
|
||||||
>
|
|
||||||
<div className="text-xs leading-tight">
|
|
||||||
Нажимая кнопку отправить, вы принимаете{' '}
|
|
||||||
<a
|
|
||||||
href="https://graff.tech/privacypolicy"
|
|
||||||
target="_blank"
|
|
||||||
className="text-[#798FFF] cursor-pointer opacity-95 hover:opacity-100 transition-all"
|
|
||||||
>
|
|
||||||
условия использования
|
|
||||||
</a>{' '}
|
|
||||||
и{' '}
|
|
||||||
<a
|
|
||||||
href="https://graff.tech/privacypolicy"
|
|
||||||
target="_blank"
|
|
||||||
className="text-[#798FFF] cursor-pointer opacity-95 hover:opacity-100 transition-all"
|
|
||||||
>
|
|
||||||
политику конфиденциальности
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="border border-t-0 border-[#3D425C] 2xl:p-6 p-4 sm:mt-0 text-xs flex items-center gap-2">
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<div className="">
|
|
||||||
<AsteriskIcon />
|
|
||||||
</div>
|
</div>
|
||||||
<p>—</p>
|
|
||||||
<p>
|
|
||||||
Звездочкой отмечены обязательные
|
|
||||||
<br />
|
|
||||||
для заполнения поля
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button
|
<div className="relative">
|
||||||
width="full"
|
<InputMask
|
||||||
disabled={isLoading}
|
required
|
||||||
icon={
|
type="tel"
|
||||||
isLoading ? (
|
mask={'+999999999999999'}
|
||||||
<LoaderIcon className="relative 2xl:w-8 2xl:h-8 w-6 h-6 animate-spin" />
|
maskChar={null}
|
||||||
) : (
|
value={phone}
|
||||||
<SendIcon className="relative 2xl:w-8 2xl:h-8 w-6 h-6" />
|
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||||
)
|
setPhone(e.target.value)
|
||||||
}
|
}
|
||||||
className="py-4"
|
className="feedback-field bg-transparent border rounded-none border-t-0 border-[#3D425C] sm:pt-12 sm:pb-4 sm:px-4 pt-8 pb-3 px-3 outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
|
||||||
>
|
/>
|
||||||
Отправить
|
<p className="feedback-placeholder lg:text-base text-sm absolute sm:pt-4 sm:pb-4 sm:px-4 sm:top-4 pt-3 pb-3 px-3 top-3 w-full opacity-50 transition-all pointer-events-none flex justify-between items-center">
|
||||||
</Button>
|
<span>Телефон</span>
|
||||||
</form>
|
<AsteriskIcon />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative">
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
value={email}
|
||||||
|
onChange={e => setEmail(e.target.value)}
|
||||||
|
className="feedback-field bg-transparent border rounded-none border-t-0 border-[#3D425C] sm:pt-12 sm:pb-4 sm:px-4 pt-8 pb-3 px-3 outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
|
||||||
|
/>
|
||||||
|
<p className="feedback-placeholder lg:text-base text-sm absolute sm:pt-4 sm:pb-4 sm:px-4 sm:top-4 pt-3 pb-3 px-3 top-3 w-full opacity-50 transition-all pointer-events-none flex justify-between items-center">
|
||||||
|
<span>Email</span>
|
||||||
|
<AsteriskIcon />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative">
|
||||||
|
<textarea
|
||||||
|
placeholder="Опишите вашу задачу"
|
||||||
|
value={description}
|
||||||
|
onChange={e => setDescription(e.target.value)}
|
||||||
|
className="feedback-field bg-transparent resize-none border rounded-none border-t-0 border-[#3D425C] p-4 sm:min-h-[192px] min-h-[128px] outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="border border-t-0 border-[#3D425C] 2xl:p-6 p-4 sm:mt-0 flex items-center"
|
||||||
|
style={{ marginTop: '-6px' }}
|
||||||
|
>
|
||||||
|
<div className="text-xs leading-tight">
|
||||||
|
Нажимая кнопку отправить, вы принимаете{' '}
|
||||||
|
<a
|
||||||
|
href="https://graff.tech/privacypolicy"
|
||||||
|
target="_blank"
|
||||||
|
className="text-[#798FFF] cursor-pointer opacity-95 hover:opacity-100 transition-all"
|
||||||
|
>
|
||||||
|
условия использования
|
||||||
|
</a>{' '}
|
||||||
|
и{' '}
|
||||||
|
<a
|
||||||
|
href="https://graff.tech/privacypolicy"
|
||||||
|
target="_blank"
|
||||||
|
className="text-[#798FFF] cursor-pointer opacity-95 hover:opacity-100 transition-all"
|
||||||
|
>
|
||||||
|
политику конфиденциальности
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="border border-t-0 text-white border-[#3D425C] 2xl:p-6 p-4 sm:mt-0 text-xs flex items-center gap-2">
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<div>
|
||||||
|
<AsteriskIcon />
|
||||||
|
</div>
|
||||||
|
<p>—</p>
|
||||||
|
<p>
|
||||||
|
Звездочкой отмечены обязательные
|
||||||
|
<br />
|
||||||
|
для заполнения поля
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
width="full"
|
||||||
|
disabled={isLoading}
|
||||||
|
icon={
|
||||||
|
isLoading ? (
|
||||||
|
<LoaderIcon className="relative 2xl:w-8 2xl:h-8 w-6 h-6 animate-spin" />
|
||||||
|
) : (
|
||||||
|
<SendIcon className="relative 2xl:w-8 2xl:h-8 w-6 h-6" />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className="py-4"
|
||||||
|
>
|
||||||
|
Отправить
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<p className="font-gilroy text-gradient sm:text-2xl text-xl w-fit font-semibold flex items-center gap-2">
|
<p className="text-gradient sm:text-2xl text-xl w-fit font-semibold flex items-center gap-2">
|
||||||
<span>Заявка отправлена</span>
|
<span>Заявка отправлена</span>
|
||||||
<CheckGradientIcon className="lg:w-8 lg:h-8 w-6 h-6" />
|
<CheckGradientIcon className="lg:w-8 lg:h-8 w-6 h-6" />
|
||||||
</p>
|
</p>
|
||||||
@@ -185,7 +199,7 @@ function ContactsForm() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<p className="font-gilroy leading-snug lg:text-2xl text-xl font-semibold">
|
<p className="leading-snug lg:text-2xl text-xl font-semibold">
|
||||||
Спасибо за подачу заявки!
|
Спасибо за подачу заявки!
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import AppearanceHr from '../../ui/AppearanceHr';
|
||||||
import { Title } from '../../ui/Title';
|
import { Title } from '../../ui/Title';
|
||||||
|
|
||||||
export function Decreasing() {
|
export function Decreasing() {
|
||||||
@@ -32,23 +33,28 @@ export function Decreasing() {
|
|||||||
</Title>
|
</Title>
|
||||||
<div className="flex tablet-figma:flex-row mobile:max-tablet-figma:flex-col justify-normal desktop-figma:gap-x-[10vw] tablet-figma:max-desktop-figma:gap-x-[clamp(16px,16px+(100vw-1024px)/576*142,160px)] desktop-figma:max-w-[calc(70.8vw+256px)] desktop-figma:justify-between tablet:items-end xl:pl-64 desktop:mt-14 mobile:mt-6">
|
<div className="flex tablet-figma:flex-row mobile:max-tablet-figma:flex-col justify-normal desktop-figma:gap-x-[10vw] tablet-figma:max-desktop-figma:gap-x-[clamp(16px,16px+(100vw-1024px)/576*142,160px)] desktop-figma:max-w-[calc(70.8vw+256px)] desktop-figma:justify-between tablet:items-end xl:pl-64 desktop:mt-14 mobile:mt-6">
|
||||||
<ul className="xl:max-w-[47vw] w-full tablet:min-w-[318px] mobile:mb-6">
|
<ul className="xl:max-w-[47vw] w-full tablet:min-w-[318px] mobile:mb-6">
|
||||||
<li className="flex justify-between py-5 border-t border-[#3D425C] gap-x-4">
|
<AppearanceHr />
|
||||||
|
<li className="flex justify-between py-5 gap-x-4">
|
||||||
<Plus text="снижение количества несчастных случаев" />
|
<Plus text="снижение количества несчастных случаев" />
|
||||||
<Number text="[01]" />
|
<Number text="[01]" />
|
||||||
</li>
|
</li>
|
||||||
<li className="flex justify-between py-5 border-t border-[#3D425C] gap-x-4">
|
<AppearanceHr />
|
||||||
|
<li className="flex justify-between py-5 gap-x-4">
|
||||||
<Plus text="уменьшение количества ошибок при ТО и ППР" />
|
<Plus text="уменьшение количества ошибок при ТО и ППР" />
|
||||||
<Number text="[02]" />
|
<Number text="[02]" />
|
||||||
</li>
|
</li>
|
||||||
<li className="flex justify-between py-5 border-t border-[#3D425C] gap-x-4">
|
<AppearanceHr />
|
||||||
|
<li className="flex justify-between py-5 gap-x-4">
|
||||||
<Plus text="меньше случаев внеплановой остановки оборудования" />
|
<Plus text="меньше случаев внеплановой остановки оборудования" />
|
||||||
<Number text="[03]" />
|
<Number text="[03]" />
|
||||||
</li>
|
</li>
|
||||||
<li className="flex justify-between py-5 border-t border-[#3D425C] gap-x-4">
|
<AppearanceHr />
|
||||||
|
<li className="flex justify-between py-5 gap-x-4">
|
||||||
<Plus text="снижение расходов на закупку реальной техники и оборудования для обучения" />
|
<Plus text="снижение расходов на закупку реальной техники и оборудования для обучения" />
|
||||||
<Number text="[04]" />
|
<Number text="[04]" />
|
||||||
</li>
|
</li>
|
||||||
<li className="flex justify-between py-5 border-t border-[#3D425C] gap-x-4">
|
<AppearanceHr />
|
||||||
|
<li className="flex justify-between py-5 gap-x-4">
|
||||||
<Plus text="сокращение сроков обучения" />
|
<Plus text="сокращение сроков обучения" />
|
||||||
<Number text="[05]" />
|
<Number text="[05]" />
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
import { MiniTitle } from '../../ui/MiniTitle';
|
import { MiniTitle } from '../../ui/MiniTitle';
|
||||||
import { AppearanceText } from '../../ui/AppearanceText';
|
import { AppearanceText } from '../../ui/AppearanceText';
|
||||||
|
import AppearanceHr from '../../ui/AppearanceHr';
|
||||||
|
|
||||||
export function Effeciency() {
|
export function Effeciency() {
|
||||||
return (
|
return (
|
||||||
<div className="desktop:py-[70px] mobile:py-14 desktop:px-10 tablet:px-6 mobile:px-4">
|
<div className="desktop:py-[70px] mobile:py-14 desktop:px-10 tablet:px-6 mobile:px-4">
|
||||||
<div className="flex mobile:max-desktop:flex-col tablet:border-t border-[#3D425C] pt-5 tablet:max-desktop:gap-4">
|
<AppearanceHr className="mobile:max-tablet:hidden" />
|
||||||
|
<div className="flex mobile:max-desktop:flex-col pt-5 tablet:max-desktop:gap-4">
|
||||||
<MiniTitle text={'экономическая эффективность'} />
|
<MiniTitle text={'экономическая эффективность'} />
|
||||||
<div className="mobile:max-tablet:mt-4">
|
<div className="mobile:max-tablet:mt-4">
|
||||||
<div className="flex mobile:max-tablet:flex-col desktop:max-desktop-figma:w-[clamp(728px,728px+(100vw-1024px)/576*405,1133px)] justify-stretch gap-x-4 gap-y-2 mobile:max-tablet:py-5 tablet:pb-5 border-b border-[#3D425C] mb-9 tablet:border-t-0 mobile:border-t">
|
<div className="flex mobile:max-tablet:flex-col desktop:max-desktop-figma:w-[clamp(728px,728px+(100vw-1024px)/576*405,1133px)] justify-stretch gap-x-4 gap-y-2 mobile:max-tablet:py-5 tablet:pb-5">
|
||||||
<Figure
|
<Figure
|
||||||
variance={'left'}
|
variance={'left'}
|
||||||
percents={50}
|
percents={50}
|
||||||
@@ -24,6 +26,7 @@ export function Effeciency() {
|
|||||||
title={'готовность к опасным ситуациямние выше на'}
|
title={'готовность к опасным ситуациямние выше на'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<AppearanceHr className="mb-9" />
|
||||||
<AppearanceText
|
<AppearanceText
|
||||||
className="max-w-[752px] desktop-figma:max-w-[47vw]"
|
className="max-w-[752px] desktop-figma:max-w-[47vw]"
|
||||||
splits={[
|
splits={[
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { MiniTitle } from '../../ui/MiniTitle';
|
import { MiniTitle } from '../../ui/MiniTitle';
|
||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
|
import AppearanceHr from '../../ui/AppearanceHr';
|
||||||
|
|
||||||
export function Events() {
|
export function Events() {
|
||||||
return (
|
return (
|
||||||
@@ -8,10 +9,12 @@ export function Events() {
|
|||||||
className="desktop:py-[70px] desktop:px-10 tablet:py-14 tablet:px-6 mobile:px-4"
|
className="desktop:py-[70px] desktop:px-10 tablet:py-14 tablet:px-6 mobile:px-4"
|
||||||
id="events"
|
id="events"
|
||||||
>
|
>
|
||||||
<div className="flex desktop:border-t mobile:max-desktop:flex-col border-[#3D425C] pt-5 gap-x-4 w-full">
|
<AppearanceHr className="mobile:max-desktop:hidden" />
|
||||||
|
<div className="flex mobile:max-desktop:flex-col pt-5 gap-x-4 w-full">
|
||||||
<MiniTitle text="события" className="mobile:max-tablet:mb-2" />
|
<MiniTitle text="события" className="mobile:max-tablet:mb-2" />
|
||||||
<div className="desktop:max-desktop-figma:min-w-[clamp(688px,688px+(100vw-1024px)/576*425,1133px)] desktop-figma:min-w-[70.9vw]">
|
<div className="desktop:max-desktop-figma:min-w-[clamp(688px,688px+(100vw-1024px)/576*425,1133px)] desktop-figma:min-w-[70.9vw]">
|
||||||
<div className="py-7 tablet:border-b mobile:max-tablet:border-t border-[#3D425C] flex justify-between mobile:max-tablet:flex-col items-start gap-x-4">
|
<AppearanceHr className="tablet:hidden" />
|
||||||
|
<div className="desktop:py-7 tablet:max-desktop:py-6 mobile:max-tablet:py-5 flex justify-between mobile:max-tablet:flex-col items-start gap-x-4">
|
||||||
<div className="w-fit">
|
<div className="w-fit">
|
||||||
<EventTitle className="tablet:mb-8 w-fit">
|
<EventTitle className="tablet:mb-8 w-fit">
|
||||||
Макет кабины машиниста «Иволга» на выставке ВДНХ
|
Макет кабины машиниста «Иволга» на выставке ВДНХ
|
||||||
@@ -31,16 +34,19 @@ export function Events() {
|
|||||||
</div>
|
</div>
|
||||||
<LinkButton href="/" />
|
<LinkButton href="/" />
|
||||||
</div>
|
</div>
|
||||||
<div className="py-7 tablet:border-b mobile:max-tablet:border-t border-[#3D425C] flex mobile:max-tablet:flex-col tablet:items-center justify-between gap-x-4">
|
<AppearanceHr />
|
||||||
|
<div className="py-7 flex mobile:max-tablet:flex-col tablet:items-center justify-between gap-x-4">
|
||||||
<EventTitle>Победа на BuildUP 2023 в номинации IT</EventTitle>
|
<EventTitle>Победа на BuildUP 2023 в номинации IT</EventTitle>
|
||||||
<LinkButton href="/" />
|
<LinkButton href="/" />
|
||||||
</div>
|
</div>
|
||||||
<div className="py-7 tablet:border-b mobile:max-tablet:border-t border-[#3D425C] flex mobile:max-tablet:flex-col tablet:items-center justify-between gap-x-4">
|
<AppearanceHr />
|
||||||
|
<div className="py-7 flex mobile:max-tablet:flex-col tablet:items-center justify-between gap-x-4">
|
||||||
<EventTitle>
|
<EventTitle>
|
||||||
Транспортное и специальное тренажеростроение — 2023
|
Транспортное и специальное тренажеростроение — 2023
|
||||||
</EventTitle>
|
</EventTitle>
|
||||||
<LinkButton href="/" />
|
<LinkButton href="/" />
|
||||||
</div>
|
</div>
|
||||||
|
<AppearanceHr />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+35
-190
@@ -5,196 +5,41 @@ export function Marquee() {
|
|||||||
<div className="w-0 h-0 desktop:border-b-[100px] desktop:border-l-[100px] tablet:border-b-[82px] tablet:border-l-[82px] border-[transparent_transparent_#D0D6DF_transparent]" />
|
<div className="w-0 h-0 desktop:border-b-[100px] desktop:border-l-[100px] tablet:border-b-[82px] tablet:border-l-[82px] border-[transparent_transparent_#D0D6DF_transparent]" />
|
||||||
<div className="desktop:w-[260px] tablet:w-[216px] bg-[#D0D6DF]" />
|
<div className="desktop:w-[260px] tablet:w-[216px] bg-[#D0D6DF]" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-stretch overflow-clip animate-infinite-scroll">
|
<MarqueeHalf />
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C] py-[30px]">
|
<MarqueeHalf />
|
||||||
<img
|
</div>
|
||||||
src="src/assets/partners_logos/rosatom.svg"
|
);
|
||||||
className="m-auto"
|
}
|
||||||
alt=""
|
|
||||||
/>
|
function MarqueeHalf() {
|
||||||
</div>
|
const srcs = [
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
'src/assets/partners_logos/rosatom.svg',
|
||||||
<img
|
'src/assets/partners_logos/rzhd.svg',
|
||||||
src="src/assets/partners_logos/rzhd.svg"
|
'src/assets/partners_logos/npoa.svg',
|
||||||
className="m-auto"
|
'src/assets/partners_logos/dubai_police.svg',
|
||||||
alt=""
|
'src/assets/partners_logos/ugmk.svg',
|
||||||
/>
|
'src/assets/partners_logos/moscowgov.svg',
|
||||||
</div>
|
'src/assets/partners_logos/mintransrf.svg',
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
'src/assets/partners_logos/uztm.svg',
|
||||||
<img
|
'src/assets/partners_logos/uralhimmash.svg',
|
||||||
src="src/assets/partners_logos/npoa.svg"
|
'src/assets/partners_logos/elem.svg',
|
||||||
className="m-auto"
|
'src/assets/partners_logos/electrohimpribor.svg',
|
||||||
alt=""
|
'src/assets/partners_logos/uralvagonzavod.svg',
|
||||||
/>
|
'src/assets/partners_logos/croc.svg',
|
||||||
</div>
|
];
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
return (
|
||||||
<img
|
<div className="flex items-stretch overflow-clip animate-infinite-scroll">
|
||||||
src="src/assets/partners_logos/dubai_police.svg"
|
{srcs.map(src => (
|
||||||
className="m-auto"
|
<MarqueeItem src={src} key={src} />
|
||||||
alt=""
|
))}
|
||||||
/>
|
</div>
|
||||||
</div>
|
);
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
}
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/ugmk.svg"
|
function MarqueeItem({ src }: { src: string }) {
|
||||||
className="m-auto"
|
return (
|
||||||
alt=""
|
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border-l border-y border-[#3D425C] first:py-[30px]">
|
||||||
/>
|
<img src={src} className="m-auto" alt="" />
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/moscowgov.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/mintransrf.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/uztm.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/uralhimmash.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/elem.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/electrohimpribor.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/uralvagonzavod.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/croc.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="flex items-stretch overflow-clip animate-infinite-scroll"
|
|
||||||
aria-hidden
|
|
||||||
>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/rosatom.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/rzhd.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/npoa.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/dubai_police.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/ugmk.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/moscowgov.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/mintransrf.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/uztm.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/uralhimmash.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/elem.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/electrohimpribor.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/uralvagonzavod.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="desktop:min-w-[212px] tablet:min-w-[180px] mobile:min-w-[170px] flex border border-[#3D425C]">
|
|
||||||
<img
|
|
||||||
src="src/assets/partners_logos/croc.svg"
|
|
||||||
className="m-auto"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import useModalStore from '../../store/modal';
|
||||||
|
|
||||||
|
export default function ModalContainer() {
|
||||||
|
const modal = useModalStore(state => state.modal);
|
||||||
|
|
||||||
|
return (
|
||||||
|
modal && (
|
||||||
|
<div className="fixed top-0 left-0 z-50 w-full h-full flex justify-center items-center bg-black bg-opacity-40 transition-opacity">
|
||||||
|
<div onClick={e => e.stopPropagation()} className="cursor-default">
|
||||||
|
{modal}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useHover } from 'usehooks-ts';
|
import { useHover } from 'usehooks-ts';
|
||||||
import { Title } from '../../ui/Title';
|
import { Title } from '../../ui/Title';
|
||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
|
import AppearanceHr from '../../ui/AppearanceHr';
|
||||||
|
|
||||||
export function Trainings() {
|
export function Trainings() {
|
||||||
return (
|
return (
|
||||||
@@ -22,25 +23,26 @@ export function Trainings() {
|
|||||||
</span>
|
</span>
|
||||||
, основываясь на специфике вашего тренировочного процесса
|
, основываясь на специфике вашего тренировочного процесса
|
||||||
</Title>
|
</Title>
|
||||||
<div className="desktop:max-desktop-figma:pl-[16vw] desktop-figma:pl-[256px]">
|
<div className="xl:max-desktop-figma:pl-[16vw] desktop-figma:pl-[256px] w-fit">
|
||||||
<TrainingsFeature
|
<TrainingsFeature
|
||||||
order="[01]"
|
order="[01]"
|
||||||
src="src/assets/vr_1.png"
|
src="src/assets/vr_1.svg"
|
||||||
title="VR - тренажеры"
|
title="VR - тренажеры"
|
||||||
text="Обучение навыкам работы с инструментами и оборудованием. Пешее хождение по территории или между оборудованием"
|
text="Обучение навыкам работы с инструментами и оборудованием. Пешее хождение по территории или между оборудованием"
|
||||||
/>
|
/>
|
||||||
<TrainingsFeature
|
<TrainingsFeature
|
||||||
order="[02]"
|
order="[02]"
|
||||||
src="src/assets/vr_2.png"
|
src="src/assets/vr_2.svg"
|
||||||
title="Cтенды"
|
title="Cтенды"
|
||||||
text="Отработки навыков вождение и управления техникой. Работа с панелями управления"
|
text="Отработки навыков вождение и управления техникой. Работа с панелями управления"
|
||||||
/>
|
/>
|
||||||
<TrainingsFeature
|
<TrainingsFeature
|
||||||
order="[03]"
|
order="[03]"
|
||||||
src="src/assets/vr_3.png"
|
src="src/assets/vr_3.svg"
|
||||||
title="Учебные классы"
|
title="Учебные классы"
|
||||||
text="Оснащение учебных классов и центров всем необходимым для современного обучения и профессиональной подготовки кадров"
|
text="Оснащение учебных классов и центров всем необходимым для современного обучения и профессиональной подготовки кадров"
|
||||||
/>
|
/>
|
||||||
|
<AppearanceHr />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -61,43 +63,46 @@ function TrainingsFeature({
|
|||||||
const hovered = useHover(ref);
|
const hovered = useHover(ref);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="xl:max-desktop-figma:max-w-[clamp(557px,557px+(100vw-1024px)/576*576,1133px)] desktop-figma:w-[70.8vw]">
|
||||||
ref={ref}
|
<AppearanceHr />
|
||||||
className="desktop:first:h-[200px] desktop:last:h-[200px] desktop:h-[176px] tablet:flex items-stretch justify-between tablet:py-10 desktop:max-desktop-figma:max-w-[clamp(557px,557px+(100vw-1024px)/576*576,1133px)] desktop-figma:w-[70.8vw] border-b border-[#3D425C] first:border-t mobile:max-tablet:pt-5"
|
<div
|
||||||
>
|
ref={ref}
|
||||||
<div className="tablet:flex flex-col gap-y-4 mobile:max-tablet:mb-[42px] tablet-figma:max-w-[43.7%]">
|
className="desktop:first:h-[200px] desktop:last:h-[200px] desktop:h-[176px] tablet:flex items-stretch justify-between tablet:py-10 mobile:max-tablet:pt-5 "
|
||||||
<h3 className="font-medium text-[#ffffff] mobile:max-tablet:mb-2 h3">
|
>
|
||||||
{title}
|
<div className="tablet:flex flex-col gap-y-4 mobile:max-tablet:mb-[42px] tablet-figma:max-w-[43.7%]">
|
||||||
</h3>
|
<h3 className="font-medium text-[#ffffff] mobile:max-tablet:mb-2 h3">
|
||||||
<p className="text-[#ffffff] opacity-60 l-text">{text}</p>
|
{title}
|
||||||
</div>
|
</h3>
|
||||||
<div className="mobile:max-tablet:flex tablet:hidden justify-between items-end">
|
<p className="text-[#ffffff] opacity-60 l-text">{text}</p>
|
||||||
<p className="text-[#52587A] m-text mb-5">{order}</p>
|
</div>
|
||||||
<img src={src} alt="" className="w-[50vw]" />
|
<div className="mobile:max-tablet:flex tablet:hidden justify-between items-end">
|
||||||
</div>
|
<p className="text-[#52587A] m-text mb-5">{order}</p>
|
||||||
<div className="tablet-figma:flex mobile:max-tablet-figma:hidden">
|
<img src={src} alt="" className="w-[50vw]" />
|
||||||
{hovered && (
|
</div>
|
||||||
|
<div className="tablet-figma:flex mobile:max-tablet-figma:hidden">
|
||||||
|
{hovered && (
|
||||||
|
<img
|
||||||
|
src={src}
|
||||||
|
alt=""
|
||||||
|
className="relative self-center w-[27vw/1120*843] -my-10 h-[calc(27vw*0.6)] mobile:max-desktop:hidden"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<img
|
<img
|
||||||
src={src}
|
src={src}
|
||||||
alt=""
|
alt=""
|
||||||
className="relative self-center w-[27vw] -my-10 h-[calc(27vw*0.6)] mobile:max-desktop:hidden"
|
className="self-center w-[27vw] h-[calc(27vw*0.6)] desktop:hidden"
|
||||||
/>
|
/>
|
||||||
)}
|
<p className="text-[#52587A] desktop:font-medium m-text">{order}</p>
|
||||||
|
</div>
|
||||||
<img
|
<img
|
||||||
src={src}
|
src={src}
|
||||||
|
className="mobile:max-tablet:hidden tablet-figma:hidden w-[calc(280/708*100%)]"
|
||||||
alt=""
|
alt=""
|
||||||
className="self-center w-[27vw] h-[calc(27vw*0.6)] desktop:hidden"
|
|
||||||
/>
|
/>
|
||||||
<p className="text-[#52587A] desktop:font-medium m-text">{order}</p>
|
<p className="text-[#52587A] desktop:font-medium m-text mobile:max-tablet:hidden tablet-figma:hidden">
|
||||||
|
{order}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<img
|
|
||||||
src={src}
|
|
||||||
className="mobile:max-tablet:hidden tablet-figma:hidden w-[calc(280/708*100%)]"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
<p className="text-[#52587A] desktop:font-medium m-text mobile:max-tablet:hidden tablet-figma:hidden">
|
|
||||||
{order}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export function AsteriskIcon() {
|
export function AsteriskIcon({ className = '' }: { className?: string }) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width="12"
|
width="12"
|
||||||
@@ -6,6 +6,8 @@ export function AsteriskIcon() {
|
|||||||
viewBox="0 0 12 13"
|
viewBox="0 0 12 13"
|
||||||
fill="none"
|
fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className={className}
|
||||||
|
color="currentColor"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M4.81534 12.2727L4.9858 7.58523L1.02273 10.0994L0 8.30966L4.17614 6.13636L0 3.96307L1.02273 2.1733L4.9858 4.6875L4.81534 0H6.8608L6.69034 4.6875L10.6534 2.1733L11.6761 3.96307L7.5 6.13636L11.6761 8.30966L10.6534 10.0994L6.69034 7.58523L6.8608 12.2727H4.81534Z"
|
d="M4.81534 12.2727L4.9858 7.58523L1.02273 10.0994L0 8.30966L4.17614 6.13636L0 3.96307L1.02273 2.1733L4.9858 4.6875L4.81534 0H6.8608L6.69034 4.6875L10.6534 2.1733L11.6761 3.96307L7.5 6.13636L11.6761 8.30966L10.6534 10.0994L6.69034 7.58523L6.8608 12.2727H4.81534Z"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'TTHovesPro';
|
font-family: 'TTHovesPro';
|
||||||
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
@@ -44,3 +45,23 @@ body {
|
|||||||
@apply tracking-[.02em] leading-[120%] desktop-figma:text-[clamp(14px,0.875vw,16px)] desktop:max-desktop-figma:text-[clamp(12px,12px+(100vw-1024px)/576*2,14px)] tablet-figma:max-desktop:text-[clamp(12px,12px+(100vw-640px)/256*2,14px)] tablet:max-tablet-figma:text-xs mobile:max-tablet:text-[clamp(12px,12px+(100vw-360px)/280*2,14px)];
|
@apply tracking-[.02em] leading-[120%] desktop-figma:text-[clamp(14px,0.875vw,16px)] desktop:max-desktop-figma:text-[clamp(12px,12px+(100vw-1024px)/576*2,14px)] tablet-figma:max-desktop:text-[clamp(12px,12px+(100vw-640px)/256*2,14px)] tablet:max-tablet-figma:text-xs mobile:max-tablet:text-[clamp(12px,12px+(100vw-360px)/280*2,14px)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.feedback-field:focus ~ .feedback-placeholder {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback-field:focus ~ .feedback-placeholder-2 {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback-field:valid ~ .feedback-placeholder {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback-field:valid ~ .feedback-placeholder-2 {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback-field::placeholder {
|
||||||
|
@apply lg:text-base text-sm font-semibold text-[#77787d];
|
||||||
|
}
|
||||||
|
|||||||
+14
-17
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import { RouterProvider, createBrowserRouter } from 'react-router-dom';
|
import { RouterProvider, createBrowserRouter } from 'react-router-dom';
|
||||||
@@ -6,20 +5,18 @@ import { MainPage } from './pages/MainPage';
|
|||||||
import Layout from './Layout';
|
import Layout from './Layout';
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||||
<React.StrictMode>
|
<RouterProvider
|
||||||
<RouterProvider
|
router={createBrowserRouter([
|
||||||
router={createBrowserRouter([
|
{
|
||||||
{
|
path: '/',
|
||||||
path: '/',
|
Component: Layout,
|
||||||
Component: Layout,
|
children: [
|
||||||
children: [
|
{
|
||||||
{
|
index: true,
|
||||||
index: true,
|
Component: MainPage,
|
||||||
Component: MainPage,
|
},
|
||||||
},
|
],
|
||||||
],
|
},
|
||||||
},
|
])}
|
||||||
])}
|
/>,
|
||||||
/>
|
|
||||||
</React.StrictMode>,
|
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
import { create } from 'zustand';
|
||||||
|
|
||||||
|
interface IModalState {
|
||||||
|
modal: ReactNode | null;
|
||||||
|
setModal: (modal: ReactNode) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useModalStore = create<IModalState>(set => ({
|
||||||
|
modal: null,
|
||||||
|
setModal: modal => set({ modal }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default useModalStore;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { useInView } from 'framer-motion';
|
||||||
|
import { useRef } from 'react';
|
||||||
|
|
||||||
|
export default function AppearanceHr({
|
||||||
|
className = '',
|
||||||
|
}: {
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
const ref = useRef<HTMLHRElement>(null);
|
||||||
|
const isInView = useInView(ref);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<hr
|
||||||
|
ref={ref}
|
||||||
|
className={
|
||||||
|
className +
|
||||||
|
' border-[#3D425C] h-px duration-500 origin-left delay-200 ' +
|
||||||
|
(isInView ? 'scale-x-1' : 'scale-x-0')
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
+4
-2
@@ -24,14 +24,16 @@ function Button({
|
|||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className={`group relative px-6 py-2 rounded-full min-w-fit ${
|
className={`group relative px-6 py-2 rounded-full min-w-fit ${
|
||||||
(color === 'primary' ? 'bg-gradient' : '') ||
|
(color === 'primary'
|
||||||
|
? 'bg-gradient-to-r from-[#798FFF] to-[#D375FF]'
|
||||||
|
: '') ||
|
||||||
(color === 'secondary' ? 'outline outline-1 outline-[#3D425C]' : '')
|
(color === 'secondary' ? 'outline outline-1 outline-[#3D425C]' : '')
|
||||||
} ${
|
} ${
|
||||||
icon ? 'pr-4' : ''
|
icon ? 'pr-4' : ''
|
||||||
} flex justify-between gap-1 items-center overflow-hidden w-${width} ${className}`}
|
} flex justify-between gap-1 items-center overflow-hidden w-${width} ${className}`}
|
||||||
>
|
>
|
||||||
<span className="group-hover:opacity-10 opacity-0 bg-black transition-opacity absolute top-0 left-0 w-full h-full"></span>
|
<span className="group-hover:opacity-10 opacity-0 bg-black transition-opacity absolute top-0 left-0 w-full h-full"></span>
|
||||||
<span className="relative font-gilroy font-medium">{children}</span>
|
<span className="relative font-medium">{children}</span>
|
||||||
<span className="relative ">{icon}</span>
|
<span className="relative ">{icon}</span>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user