From 4b22d1efb74633a754e614aed7ecb87daf9deeb0 Mon Sep 17 00:00:00 2001 From: vladisluw <54843319+seelentov@users.noreply.github.com> Date: Mon, 6 May 2024 13:07:14 +0500 Subject: [PATCH] upd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Форма заявки - Подключение к тг каналу для получения заявок - Небольшие правки дизайна --- package-lock.json | 91 ++++++++++++++++++ package.json | 1 + src/app/contacts/page.tsx | 4 +- src/app/page.tsx | 2 + src/components/Banner/Banner.module.scss | 13 ++- src/components/Call/Call.tsx | 21 ++++- .../Catalog/CatalogTab/CatalogTab.module.scss | 6 ++ src/components/FAQ/FAQ.module.scss | 4 + src/components/Form/Form.module.scss | 29 ++++++ src/components/Form/Form.tsx | 65 +++++++++++++ src/components/Header/DesktopNav.tsx | 2 +- src/components/Header/Header.tsx | 12 +-- src/components/Header/Socials.tsx | 27 ++++++ .../ModalForm/ModalForm.module.scss | 15 +++ src/components/ModalForm/ModalForm.tsx | 54 +++++++++++ src/components/Stages/Stages.module.scss | 7 ++ src/components/UI/Input/Input.tsx | 12 +++ src/core/api/baseFetch.ts | 5 +- src/core/api/getSerializedServices.ts | 3 + src/core/api/getServiceLinks.ts | 4 +- src/core/api/sendtelegramMessage.ts | 31 +++++++ src/core/config/api.config.ts | 4 +- src/core/utils/forms/isEveryInFormNotEmpty.ts | 5 + src/style/modules/globals.scss | 3 + src/style/modules/layout.scss | 3 +- todolist.txt | 92 ------------------- 26 files changed, 398 insertions(+), 117 deletions(-) create mode 100644 src/components/Form/Form.module.scss create mode 100644 src/components/Form/Form.tsx create mode 100644 src/components/Header/Socials.tsx create mode 100644 src/components/ModalForm/ModalForm.module.scss create mode 100644 src/components/ModalForm/ModalForm.tsx create mode 100644 src/components/UI/Input/Input.tsx create mode 100644 src/core/api/sendtelegramMessage.ts create mode 100644 src/core/utils/forms/isEveryInFormNotEmpty.ts delete mode 100644 todolist.txt diff --git a/package-lock.json b/package-lock.json index 37de858..40e3525 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "pixel-perfect-langing", "version": "0.1.0", "dependencies": { + "axios": "^1.6.8", "classnames": "^2.5.1", "hamburger-react": "^2.5.0", "next": "14.1.0", @@ -1271,6 +1272,11 @@ "has-symbols": "^1.0.3" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/available-typed-arrays": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", @@ -1292,6 +1298,16 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/axobject-query": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", @@ -1490,6 +1506,17 @@ "simple-swizzle": "^0.2.2" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1582,6 +1609,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -2320,6 +2355,25 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -2345,6 +2399,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3281,6 +3348,25 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3739,6 +3825,11 @@ "react-is": "^16.13.1" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", diff --git a/package.json b/package.json index 5f1f0c1..2897d47 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "export": "next export" }, "dependencies": { + "axios": "^1.6.8", "classnames": "^2.5.1", "hamburger-react": "^2.5.0", "next": "14.1.0", diff --git a/src/app/contacts/page.tsx b/src/app/contacts/page.tsx index b899f2f..66e5688 100644 --- a/src/app/contacts/page.tsx +++ b/src/app/contacts/page.tsx @@ -4,6 +4,7 @@ import { INFO } from "@/core/config/info.config"; import { Metadata } from "next"; import Image from 'next/image'; import styles from './page.module.scss'; +import { Form } from "@/components/Form/Form"; export const metadata: Metadata = { @@ -45,6 +46,7 @@ export default async function Contacts() {

{INFO.PHONE}

ИНН: 745108164223

+
{'Pixel
- + ); } diff --git a/src/app/page.tsx b/src/app/page.tsx index 46cd46f..12be276 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -3,6 +3,7 @@ import { Banner } from "@/components/Banner/Banner"; import { Call } from "@/components/Call/Call"; import { Catalog } from "@/components/Catalog/Catalog"; import { FAQ } from "@/components/FAQ/FAQ"; +import { ModalForm } from "@/components/ModalForm/ModalForm"; import { Portfolio } from "@/components/Portfolio/Portfolio"; import { Stages } from "@/components/Stages/Stages"; import { baseFetch } from "@/core/api/baseFetch"; @@ -65,6 +66,7 @@ export default async function HomePage() {
{faqData && } + ); } diff --git a/src/components/Banner/Banner.module.scss b/src/components/Banner/Banner.module.scss index e22ae10..a27d466 100644 --- a/src/components/Banner/Banner.module.scss +++ b/src/components/Banner/Banner.module.scss @@ -62,9 +62,9 @@ } p { - max-height: 130px; - height: 130px; - min-height: 130px; + max-height: 126px; + height: 126px; + min-height: 126px; } @media (min-width: 1024px) { @@ -78,6 +78,7 @@ p { + font-size: 18px; } } @@ -99,7 +100,11 @@ h1, p { padding: 0 15px; - + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 6; + -webkit-box-orient: vertical; } max-width: none !important; diff --git a/src/components/Call/Call.tsx b/src/components/Call/Call.tsx index ca59b32..abec5aa 100644 --- a/src/components/Call/Call.tsx +++ b/src/components/Call/Call.tsx @@ -1,15 +1,18 @@ 'use client' -import { FC } from 'react'; +import { FC, useState } from 'react'; import { YMClick } from '../YM/YMClick'; import styles from './Call.module.scss'; import { links } from './call.config'; +import { ModalForm } from '../ModalForm/ModalForm'; +import { Form } from '../Form/Form'; export interface ICallProps { padding?: 'top' | 'bottom' | 'both' | 'none' + type?: 'default' | 'w/out-form' } -export const Call: FC = ({ padding = 'both' }) => { +export const Call: FC = ({ padding = 'both', type = 'default' }) => { const paddingProp = { paddingTop: padding === 'top' || padding === 'both' ? '60px' : '0px', @@ -20,7 +23,19 @@ export const Call: FC = ({ padding = 'both' }) => {
- {links.map((link, index) => )} + { + type === 'default' ? + <> + {links.slice(0, links.length - 1).map((link, index) => )} +
+ +
+ + : + links.map((link, index) => ) + } + { } +
); diff --git a/src/components/Catalog/CatalogTab/CatalogTab.module.scss b/src/components/Catalog/CatalogTab/CatalogTab.module.scss index 9ed0a42..d7a86f8 100644 --- a/src/components/Catalog/CatalogTab/CatalogTab.module.scss +++ b/src/components/Catalog/CatalogTab/CatalogTab.module.scss @@ -1,4 +1,10 @@ .main{ + *{ + box-sizing: content-box; + + } + box-sizing: content-box; + max-height: 340px; overflow-y: scroll; display: flex; diff --git a/src/components/FAQ/FAQ.module.scss b/src/components/FAQ/FAQ.module.scss index 0a5b9c5..cb6f018 100644 --- a/src/components/FAQ/FAQ.module.scss +++ b/src/components/FAQ/FAQ.module.scss @@ -9,7 +9,11 @@ .wrapper { display: flex; justify-content: space-between; + *{ + box-sizing: content-box; + } + box-sizing: content-box; @media (max-width: 1023px) { align-items: center; diff --git a/src/components/Form/Form.module.scss b/src/components/Form/Form.module.scss new file mode 100644 index 0000000..103bc19 --- /dev/null +++ b/src/components/Form/Form.module.scss @@ -0,0 +1,29 @@ +.form{ + display: flex; + flex-direction: column; + gap: 10px; + + + + h2{ + margin-bottom: 0; + } + + p{ + margin-bottom: 10px; + font-size: 12px; + } + + input{ + border: 2px solid black; + width: 300px; + padding: 10px; + } +} + +.default{ + align-items: center; + padding: 20px; + background-color: white; + width: 375px; +} \ No newline at end of file diff --git a/src/components/Form/Form.tsx b/src/components/Form/Form.tsx new file mode 100644 index 0000000..3bf3644 --- /dev/null +++ b/src/components/Form/Form.tsx @@ -0,0 +1,65 @@ +'use client' + +import styles from './Form.module.scss' +import { sendTelegramMessage } from '@/core/api/sendtelegramMessage'; +import { Button } from '../UI/Button/Button'; +import { useState } from 'react'; +import { usePathname } from 'next/navigation'; +import cn from 'classnames'; +interface IFormProps { + type?: 'min' | 'default' +} + +export const Form = ({ type = 'default' }) => { + + const pathname = usePathname() + + + const [formData, setFormData] = useState({ + name: '', + tel: '', + }); + + const handleChange = (e: any) => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + + const handleSubmit = async (e: any) => { + e.preventDefault(); + + const isSended = await sendTelegramMessage(formData, pathname) + if (isSended) { + setFormData({ + name: '', + tel: '', + }) + } + }; + + return ( + + {type === 'default' && + <> +

Закажите звонок

+

..и свяжусь с Вами в ближайшее время

+ } + + + + + ) +} \ No newline at end of file diff --git a/src/components/Header/DesktopNav.tsx b/src/components/Header/DesktopNav.tsx index 091c30e..84005e5 100644 --- a/src/components/Header/DesktopNav.tsx +++ b/src/components/Header/DesktopNav.tsx @@ -26,7 +26,7 @@ export const DesktopNav = ({serviceLinks}:{serviceLinks: MenuLink[]}) => { { sublist?.map(({ id, href, name }) =>
  • - {name} + {name}
  • ) } diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index fbd620b..598dd69 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -1,12 +1,9 @@ import { getServiceLinks } from '@/core/api/getServiceLinks'; -import { INFO } from '@/core/config/info.config'; -import { FC } from 'react'; -import { RiPhoneFill, RiTelegramFill, RiWhatsappFill } from "react-icons/ri"; +import { FC, useState } from 'react'; import { DesktopNav } from './DesktopNav'; import styles from './Header.module.scss'; import { MobileNav } from './MobileNav'; -import { YMClick } from '../YM/YMClick'; -import { social_links } from './header.config'; +import { Socials } from './Socials'; export interface IHeaderProps { @@ -17,6 +14,7 @@ export const Header: FC = async () => { const serviceLinks = await getServiceLinks() + return (
    @@ -25,9 +23,7 @@ export const Header: FC = async () => {
    -
    - {social_links.map((link, index) => )} -
    +
    diff --git a/src/components/Header/Socials.tsx b/src/components/Header/Socials.tsx new file mode 100644 index 0000000..fc64dee --- /dev/null +++ b/src/components/Header/Socials.tsx @@ -0,0 +1,27 @@ +'use client' + +import { FC, useState } from 'react'; +import styles from './Header.module.scss'; +import { YMClick } from '../YM/YMClick'; +import { social_links } from './header.config'; +import { ModalForm } from '../ModalForm/ModalForm'; + +export interface IHeaderProps { + +} + +export const Socials: FC = () => { + + + return ( + <> +
    + {social_links.map((link, index) => )} +
    + + ); +} + + + + diff --git a/src/components/ModalForm/ModalForm.module.scss b/src/components/ModalForm/ModalForm.module.scss new file mode 100644 index 0000000..172d4a6 --- /dev/null +++ b/src/components/ModalForm/ModalForm.module.scss @@ -0,0 +1,15 @@ +.wrapper{ + position: fixed; + height: 100vh; + width: 100%; + background: #0000004f; + display: none; + justify-content: center; + align-items: center; + z-index: 10000; +} + + +.open{ + display: flex !important; +} \ No newline at end of file diff --git a/src/components/ModalForm/ModalForm.tsx b/src/components/ModalForm/ModalForm.tsx new file mode 100644 index 0000000..e3023b2 --- /dev/null +++ b/src/components/ModalForm/ModalForm.tsx @@ -0,0 +1,54 @@ +'use client' + +import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react'; +import styles from './ModalForm.module.scss'; +import { usePathname } from 'next/navigation'; +import cn from 'classnames'; +import { Form } from '../Form/Form'; + + +export interface IModalFormProps { +} + +export const ModalForm: FC = () => { + + + const [isOpen, setIsOpen] = useState(false) + + useEffect(() => { + setTimeout(() => { + setIsOpen(true) + const html = document.querySelector('html'); + if (html) { + html.style.overflow = 'visible' + } + }, 10000) + }, []) + + + + useEffect(() => { + const handleDocumentClick = (e: any) => { + if (!e.target.closest(`.${styles.form}`)) { + setIsOpen(false); + const html = document.querySelector('html'); + if (html) { + html.style.overflow = 'scroll' + } + + } + }; + + document.addEventListener('click', handleDocumentClick); + + return () => { + document.removeEventListener('click', handleDocumentClick); + }; + }, []); + + return ( +
    +
    +
    + ); +} \ No newline at end of file diff --git a/src/components/Stages/Stages.module.scss b/src/components/Stages/Stages.module.scss index a1c2b74..5b276f0 100644 --- a/src/components/Stages/Stages.module.scss +++ b/src/components/Stages/Stages.module.scss @@ -4,6 +4,7 @@ @media (max-width: 1023px) { padding: 60px 0; } + } .list { @@ -45,6 +46,12 @@ } .item { +*{ + box-sizing: content-box; + + } + box-sizing: content-box; + position: relative; diff --git a/src/components/UI/Input/Input.tsx b/src/components/UI/Input/Input.tsx new file mode 100644 index 0000000..2ca203a --- /dev/null +++ b/src/components/UI/Input/Input.tsx @@ -0,0 +1,12 @@ +import { FC, HTMLAttributes } from 'react'; +import styles from './Input.module.scss'; + +export interface IInputProps extends HTMLAttributes { + +} + +export const Input: FC = ({ children, ...rest }) => { + return ( + + ); +} \ No newline at end of file diff --git a/src/core/api/baseFetch.ts b/src/core/api/baseFetch.ts index 8b88512..a20246d 100644 --- a/src/core/api/baseFetch.ts +++ b/src/core/api/baseFetch.ts @@ -21,11 +21,8 @@ export const baseFetch = async (url: string, single: boolean = false, cache: boo try { - const res = await fetch(API_URL + url, options) - + const res = await fetch(API_URL + url) const data = await res.json() - - serializedData = apiDataSerializer(data) if (single) { diff --git a/src/core/api/getSerializedServices.ts b/src/core/api/getSerializedServices.ts index 5d08bab..3fef512 100644 --- a/src/core/api/getSerializedServices.ts +++ b/src/core/api/getSerializedServices.ts @@ -5,8 +5,11 @@ import { getItemsByFilter } from "@/core/api/getItemsByFilter"; export const getSerializedServices = async () => { const categories = await baseFetch('/api/categories'); + const categoriesKeys = categories.map((item: any) => item.header); + + let promises = categoriesKeys.map(async (category: string) => { const data = await getItemsByFilter('services', ['category', 'header'], category, [['populate','icon']]); return [category, data]; diff --git a/src/core/api/getServiceLinks.ts b/src/core/api/getServiceLinks.ts index 9851c43..811843f 100644 --- a/src/core/api/getServiceLinks.ts +++ b/src/core/api/getServiceLinks.ts @@ -3,13 +3,13 @@ import { getItemsByFilter } from "./getItemsByFilter"; export const getServiceLinks = async () => { const categories: ICategory[] = await baseFetch('/api/categories'); - + const promises = categories.map(async ({ href: mainHref, id, header }) => { const services: IService[] = await getItemsByFilter('services', ['category', 'header'], header, [['populate','icon']]); const mappedServices = services.map(({ id, href, header }) => ({ id: id, - href: href, + href: mainHref + '/' + href, name: header, })); diff --git a/src/core/api/sendtelegramMessage.ts b/src/core/api/sendtelegramMessage.ts new file mode 100644 index 0000000..832847b --- /dev/null +++ b/src/core/api/sendtelegramMessage.ts @@ -0,0 +1,31 @@ +import axios from "axios"; +import { TELEGRAM_API_KEY, TELEGRAM_CHAT_ID } from "../config/api.config"; +import { isEveryInFormNotEmpty } from "../utils/forms/isEveryInFormNotEmpty"; + +export const sendTelegramMessage = async (formData: any, pathname: string) => { + if(!isEveryInFormNotEmpty(formData)){ + alert('Заполните все данные формы'); + return + } + + try { + const response = await axios.post( + `https://api.telegram.org/bot${TELEGRAM_API_KEY}/sendMessage`, + { + chat_id: TELEGRAM_CHAT_ID, + text: `Новая заявка:\n\n${Object.entries(formData).map(input => `${input[0]}: ${input[1]}`).join('\n')}\n\nСтраница: ${pathname}`, + parse_mode: 'Markdown', + } + ); + + if (response.status === 200) { + alert('Заявка успешно отправлена!'); + return true + } else { + alert('Не удалось отправить заявку. Пожалуйста, попробуйте позже'); + } + } catch (error) { + console.error(error); + alert('Не удалось отправить заявку. Пожалуйста, попробуйте позже'); + } + }; \ No newline at end of file diff --git a/src/core/config/api.config.ts b/src/core/config/api.config.ts index 4de487c..9dccd04 100644 --- a/src/core/config/api.config.ts +++ b/src/core/config/api.config.ts @@ -1,2 +1,4 @@ export const API_URL = process.env.API_URL || 'https://pixellperfect.ru' -export const API_TOKEN = process.env.API_TOKEN \ No newline at end of file +export const API_TOKEN = process.env.API_TOKEN +export const TELEGRAM_API_KEY = "6454568318:AAFIqVdc_oB71z24yogZOpY5fSUmmLh_q5o"; +export const TELEGRAM_CHAT_ID = 816233444; \ No newline at end of file diff --git a/src/core/utils/forms/isEveryInFormNotEmpty.ts b/src/core/utils/forms/isEveryInFormNotEmpty.ts new file mode 100644 index 0000000..82919cb --- /dev/null +++ b/src/core/utils/forms/isEveryInFormNotEmpty.ts @@ -0,0 +1,5 @@ +export const isEveryInFormNotEmpty = (formData: {[key: string]: string}) => { + const result = Object.values(formData).every(input => input.length > 0) + console.log(result) + return result +} \ No newline at end of file diff --git a/src/style/modules/globals.scss b/src/style/modules/globals.scss index fdcb16f..c6014df 100644 --- a/src/style/modules/globals.scss +++ b/src/style/modules/globals.scss @@ -151,6 +151,9 @@ input[type="reset"] { html { + *{ + box-sizing: border-box; + } font-size: 18px; &::-webkit-scrollbar { diff --git a/src/style/modules/layout.scss b/src/style/modules/layout.scss index 3709404..d824133 100644 --- a/src/style/modules/layout.scss +++ b/src/style/modules/layout.scss @@ -2,7 +2,7 @@ .container { max-width: 1449px; margin: 0 auto; - + width: 100%; @media(max-width:1460px) { max-width: 1200px; } @@ -18,6 +18,7 @@ @media(max-width:767px) { max-width: none !important; padding: 0 15px; + width: 100%; } } diff --git a/todolist.txt b/todolist.txt deleted file mode 100644 index 4b28a2c..0000000 --- a/todolist.txt +++ /dev/null @@ -1,92 +0,0 @@ -Первый блок, половину ноутбука на мобилке (слева), реализация на бумаге - -Примеры работ под баннерами - -Выделение текста на сайте - -Layout: -- header ++++++++ -- burger ++++++++ -- footer ++++++++ - -Верстка: - Структура главной: - -- Баннер (уник) ++++++++ -- Преимущества ++++++++ -- Каталог услуг (уник) ++++++++ -- Примеры работ -- Этапы заказа (уник) ++++++++ -- СТА ++++++ -- FAQ (уник) ++++++++ -- Статьи и новости ------- -- Отзывы ------- - - Структура услуги: -- Баннер (Заголовок, текст, стоимость, демка) +++++ -- Текст +++++ -- Примеры работ -- Текст +++++ -- Отзывы ------- -- СТА ++++++ - -(листинг): -- Листинг (column) ++++++ -- Текст ++++++ -- СТА ++++++ - - Структура примеры работ(листинг): -- Листинг (column) ++++++ -- Текст ----- -- СТА ++++++ - - - Структура статьи: -------------- -- Заголовок -- 1 изображение -- Текст -- 2 изображение -- Текст -- Листинг статей (- статья страницы) - -(листинг): -------------- -- Листинг (column) - -БД: -- Создание API ++++++++ -- Моделирование ++++++++ -- Создание endpoints на получение каждого из одноблочного контента** ------ -- Создание endpoints на получение категорий товаров и услуг c - -Контент: -- Баннер ++++++++ -- Преимущества -- Каталог услуг -- Примеры работ ++++++++ -- FAQ ++++++++ -- Статьи и новости --------- -- Этапы заказа ++++++++ -- Отзывы ----------- - -Тестинг: -- Семантика (мета, теги) -- Кроссбраузерность -- Производительность ++++++++ - -SEO: -- Мета ++++++++ -- openGraph ++++++++ -- schema.org -------- - -Публикация на хост: -- Приобретение хостинга и домена ++++ -- Деплой ++++ -- Тест адаптива мобильной версии ++++ -- Роботы ++++ -- sitemap ++++ -- Яндекс.Вебмастер / Google Console + тесты - -Директ: -- Создание рекламных стратегий по каждой услуге -- Создание рекламной стратегии на главную -- Пополнение \ No newline at end of file