Skip to content

Commit

Permalink
Merge pull request #349 from Studio-Yandex-Practicum/layout_342_footer
Browse files Browse the repository at this point in the history
Layout 342 footer
  • Loading branch information
kirill-k88 authored May 6, 2024
2 parents 5e59747 + b06f552 commit 794d2dd
Show file tree
Hide file tree
Showing 14 changed files with 334 additions and 78 deletions.
11 changes: 4 additions & 7 deletions src/entities/Payments/Payments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,19 @@ type TPayments = {

type Logo = {
image: string
title: string
url: string
}

/** платежная система
* @param {string} image - путь к картинке
* @param {string} title - название
* @param {string} url - путь к сайту
* @param {url: string, image: string} data[] массив платежных систем
*/
const Payments: FC<TPayments> = ({ data }) => {
return (
<ul className={styles.payments}>
{data.footer.additional_logos.map(logo => (
<li className={styles['payment-nav']} key={logo.title}>
<Link to={logo.url} className={styles['payment-item']}>
<img className={styles['payment-icon']} src={logo.image} title={logo.title} alt={logo.title} />
<li className={styles['payment-nav']} key={logo.url}>
<Link to={logo.url} className={styles['payment-item']} target="_blank">
<img className={styles['payment-icon']} src={logo.image} title={logo.url} alt={logo.url} />
</Link>
</li>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@
&_footer {
max-width: 570px;
row-gap: 10px;

@include media.respond-to('large') {
max-width: 100%;
margin-bottom: 70px;
}
}

&_subscribe {
max-width: 740px;
width: 740px;
row-gap: 20px;
}
}
Expand All @@ -24,9 +29,11 @@
padding: 3px 3px 3px 14px;
border-radius: 5px;
position: relative;
border: 2px solid transparent;
transition: border-color 0.4s;

&:focus-within {
outline: 2px solid var.$theme-primary-color;
border-color: var.$theme-primary-color;
}

&_footer {
Expand All @@ -36,12 +43,28 @@
&_subscribe {
background-color: var.$white;
}

@include media.respond-to('large') {
margin-top: 20px;
}
}

.form > input {
&::placeholder {
color: var.$theme-primary-color;
transition: color 0.25s ease-in-out;
.field {
width: 100%;
padding: 10px 16px;
border: none;
outline: none;
box-shadow: none;
font-size: 14px;
font-weight: 400;
line-height: 1.5;

&_footer {
color: var.$white;
}

&_subscribe {
color: var.$black;
}

&:focus {
Expand All @@ -51,6 +74,20 @@
}
}

.span {
font-size: 14px;
font-weight: 400;
line-height: 1.5;

&_footer {
color: var.$white;
}

&_subscribe {
color: var.$black;
}
}

.button {
padding: 14px 21px;
display: flex;
Expand Down Expand Up @@ -96,6 +133,11 @@
font-size: 16px;
font-weight: 500;
line-height: 16px;

@include media.respond-to('xl') {
font-size: 14.5px;
line-height: 1;
}
}

&_subscribe {
Expand All @@ -110,7 +152,7 @@

@include media.respond-to('large') {
display: flex;
font-size: 16px;
font-size: 15px;
font-weight: 400;
line-height: 16px;
}
Expand Down
23 changes: 23 additions & 0 deletions src/features/SubscribeForm/SubscribeForm.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Meta, StoryObj } from '@storybook/react'

import SubscribeForm from './SubscribeForm'

const meta = {
title: 'features/SubscribeForm',
component: SubscribeForm,
parameters: {
layout: 'centered'
}
} as Meta<typeof SubscribeForm>

export default meta
type Story = StoryObj<typeof meta>

export const Default: Story = {
args: {
type: 'footer',
onSubmit: () => {
alert('Действие по сабмиту формы')
}
}
}
109 changes: 89 additions & 20 deletions src/features/SubscribeForm/SubscribeForm.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
import classNames from 'classnames'
import { type FC, FormEvent } from 'react'
import { Field, Form, Formik, FormikErrors, FormikTouched } from 'formik'
import { FormEvent, useState, type FC } from 'react'

import SubscribeIcon from '@/assets/images/subscriptionForm/icon-subsc.svg'
import { Input, InputSize, InputTheme } from '@/shared/ui/Input/Input'
import { useResize } from '@/shared/libs/hooks/useResize'
import { FormMsg } from '@/shared/ui/FormMsg/FormMsg'
import { EMsgType } from '@/shared/ui/FormMsg/model/types/types'
import Label from '@/shared/ui/Label/Label'
import Span from '@/shared/ui/Span/Span'

import styles from './subscribeForm.module.scss'
import { validationSchema } from './model/validationSchema/validationSchema'
import styles from './SubscribeForm.module.scss'

type TSubscribeForm = {
type: 'footer' | 'subscribe'
className?: string
onSubmit: (event: FormEvent<HTMLFormElement>) => void
onSubmit: () => void
}

// @TODO: Перевести форму на Formik + Yup
// https://github.com/Studio-Yandex-Practicum/maxboom_frontend/issues/91
/**
* @param {string} type - определяет внешний вид для компонентов footer и для subscribe
* @param {string} className - нужно будет, если захотят переиспользовать компонент
* @param {string} className - для переопределения стилей <Form/>
* @param {string} onSubmit - функция для обработки формы
*/
const SubscribeForm: FC<TSubscribeForm> = ({ type, onSubmit, className = '' }) => {
const [showErrorMsg, setShowErrorMsg] = useState(false)
const { isScreenLg, isScreenMd, isScreenSm } = useResize()

const classNameContainer = classNames(styles.container, {
[styles.container]: true,
[styles.container_footer]: type === 'footer',
Expand All @@ -35,21 +42,83 @@ const SubscribeForm: FC<TSubscribeForm> = ({ type, onSubmit, className = '' }) =
[styles.form_footer]: type === 'footer',
[styles.form_subscribe]: type === 'subscribe'
})
const classNameField = classNames({
[styles.field]: true,
[styles.field_footer]: type === 'footer',
[styles.field_subscribe]: type === 'subscribe'
})
const classNameSpan = classNames({
[styles.span]: true,
[styles.span_footer]: type === 'footer',
[styles.span_subscribe]: type === 'subscribe'
})

const submitHandle = () => {
//@TODO: Доделать после появления эндпоинта на BE
onSubmit()
}

const preSubmitHandle = (
e: FormEvent<HTMLFormElement>,
touched: FormikTouched<{
email: string
}>,
errors: FormikErrors<{
email: string
}>
) => {
e.preventDefault()
setShowErrorMsg(Boolean(touched.email && errors.email))
}

return (
<div className={`${classNameContainer} ${className}`}>
{/* @TODO: Добавить компонент Label
https://github.com/Studio-Yandex-Practicum/maxboom_frontend/issues/102 */}
<label className={classNameLabel}>Подписаться на рассылку</label>
<p className={styles.caption}>Мы не будем присылать вам спам. Только скидки и выгодные предложения</p>
<form className={classNameForm} onSubmit={onSubmit}>
<Input name="subscribe" placeholder="Эл.почта" theme={InputTheme.DARK} customSize={InputSize.S} />
<button className={styles.button}>
Подписаться
<SubscribeIcon className={styles.button__img} />
</button>
</form>
</div>
<Formik
initialValues={{
email: ''
}}
validationSchema={validationSchema}
onSubmit={submitHandle}>
{({ isSubmitting, errors, touched }) => (
<Form
className={`${classNameContainer} ${className}`}
onSubmit={e => {
preSubmitHandle(e, touched, errors)
}}>
<Label htmlFor={`email_${type}`} className={classNameLabel}>
Подписаться на рассылку
</Label>
{(isScreenSm || isScreenMd) && !isScreenLg && (
<Span className={classNameSpan}>
Мы не будем присылать вам спам. Только скидки и выгодные предложения
</Span>
)}
<div className={classNameForm}>
<Field
id={`email_${type}`}
name="email"
type="text"
className={classNameField}
placeholder="Эл. почта"
/>
<button className={styles.button} type="submit" disabled={isSubmitting}>
Подписаться
<SubscribeIcon className={styles.button__img} />
</button>
</div>
{showErrorMsg && errors.email && (
<FormMsg
text={errors.email || 'Ошибка валидации email!'}
isError={true}
closeHandle={() => {
setShowErrorMsg(false)
}}
disableClose={false}
type={EMsgType.popup}
/>
)}
</Form>
)}
</Formik>
)
}

Expand Down
2 changes: 2 additions & 0 deletions src/features/SubscribeForm/model/constants/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const EMAIL_VALIDATION_ERROR = 'E-mail адрес введён неверно!'
export const EMAIL_REQUIRED_ERROR = 'Укажите E-mail адрес!'
3 changes: 3 additions & 0 deletions src/features/SubscribeForm/model/types/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface ISubscribeFormValues {
email: string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as Yup from 'yup'

import { EMAIL_REQUIRED_ERROR, EMAIL_VALIDATION_ERROR } from '../constants/constants'

export const validationSchema = Yup.object().shape({
email: Yup.string().required(EMAIL_REQUIRED_ERROR).email(EMAIL_VALIDATION_ERROR)
})
14 changes: 14 additions & 0 deletions src/shared/ui/FormMsg/FormMsg.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@
border-radius: 10px;
@include font(18px);

&_ispopup {
width: 300px;
opacity: 0;
position: fixed;
top: 50px;
left: -350px;
transition: all 0.5s;
}

&_popupIsOpen {
left: 50px;
opacity: 1;
}

&_iserror {
background-color: color.$promo-color;
}
Expand Down
4 changes: 2 additions & 2 deletions src/shared/ui/FormMsg/FormMsg.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const Succeed: Story = {
text: 'Данные успешно отправлены!',
isError: false,
disableClose: false,
closeHandel: () => {
closeHandle: () => {
alert('Выполненяются действия из переданной функции')
}
}
Expand All @@ -30,7 +30,7 @@ export const Error: Story = {
text: 'Ошибка отправки данных на сервер!',
isError: true,
disableClose: false,
closeHandel: () => {
closeHandle: () => {
alert('Выполненяются действия из переданной функции')
}
}
Expand Down
Loading

0 comments on commit 794d2dd

Please sign in to comment.