diff --git a/userProfile/index.html b/userProfile/index.html index e7fc644..6abe956 100644 --- a/userProfile/index.html +++ b/userProfile/index.html @@ -5,7 +5,7 @@ React Interface -

Hi! I don't have React. Yet

+
\ No newline at end of file diff --git a/userProfile/src/InputRow.tsx b/userProfile/src/InputRow.tsx new file mode 100644 index 0000000..b6c382b --- /dev/null +++ b/userProfile/src/InputRow.tsx @@ -0,0 +1,19 @@ +import { RowProps } from './types'; +import { Gapped, Input } from '@skbkontur/react-ui'; +import React from 'react'; + +const InputRow = ({ title, placeholder = '', onInputChange, isError }: RowProps) => { + return ( +
+ +

{title}

+
+ onInputChange(e.target.value)} /> + {isError &&

Заполните поле

} +
+
+
+ ); +}; + +export default InputRow; diff --git a/userProfile/src/Modal.tsx b/userProfile/src/Modal.tsx new file mode 100644 index 0000000..85c7bd6 --- /dev/null +++ b/userProfile/src/Modal.tsx @@ -0,0 +1,19 @@ +import { ModeOnSaveProps } from './types'; +import { Button, Modal } from '@skbkontur/react-ui'; +import React from 'react'; + +const ModalOnSave = ({ close, changeMessage }: ModeOnSaveProps) => ( + + Пользователь сохранен + + {changeMessage.map((data, i) => ( +

{data}

+ ))} +
+ + + +
+); + +export default ModalOnSave; diff --git a/userProfile/src/SelectRow.tsx b/userProfile/src/SelectRow.tsx new file mode 100644 index 0000000..9d612d2 --- /dev/null +++ b/userProfile/src/SelectRow.tsx @@ -0,0 +1,23 @@ +import { SelectProps } from './types'; +import { Gapped, Select } from '@skbkontur/react-ui'; +import React from 'react'; + +const SelectRow = ({ title, onInputChange }: SelectProps) => { + const cities = ['Москва', 'Санкт-Петербург', 'Екатеринбург']; + return ( +
+ +

{title}

+ + items={cities} + placeholder="Выберете город" + onValueChange={value => { + onInputChange(value); + }} + /> +
+
+ ); +}; + +export default SelectRow; diff --git a/userProfile/src/index.tsx b/userProfile/src/index.tsx index df4d969..8b18078 100644 --- a/userProfile/src/index.tsx +++ b/userProfile/src/index.tsx @@ -1,59 +1,99 @@ +import { Button, Gapped } from '@skbkontur/react-ui'; +import React, { useState } from 'react'; +import ReactDom from 'react-dom'; import './style.css'; +import ModalOnSave from './Modal'; +import InputRow from './InputRow'; +import SelectRow from './SelectRow'; -/** - * Итак, перед тобой пустой проект. Давай его чем-то заполним. Не стесняйся подсматривать в уже сделанные задачи, - * чтобы оттуда что-то скопировать. - * - * 1. Создай в файле index.html (он на уровень выше в файловой структуре) div с каким-нибудь id - * 2. Импортируй сюда библиотеку React и ReactDom - * 3. Отрендери "Hello world" на странице при помощи Реакта. - * - * 4. Добавь в разметку Button из библиотеки компонентов Контура (@skbkontur/react-ui). - * npm-пакет с библиотекой уже добавлен в проект. - * - * Импортируется компонент на страницу так: - * - * import { Button } from '@skbkontur/react-ui'; - * - * Используется компонент так: - * - * const MyApp = () => ( - *
- * Click this button - *
- * ); - * - * - * Тут можно посмотреть, как компонентами пользоваться, какие у них атрибуты есть: - * http://tech.skbkontur.ru/react-ui/ - * - * 5. Теперь, когда ты знаешь все основное, сверстай при помощи react-ui форму, - * как на картинке drafts/reactForm.png (можно открыть в браузере http://localhost:8080/drafts/reactForm.png) - * Для вертикальных отступов между элементами используй компонент Gapped из библиотеки. - * Если хочешь что-то стилизовать, используй файл style.css. - * Список городов придумай сам. - * - * 6. Сделай так, чтобы при клике по кнопке "Сохранить", - * показывалось модальное окно (компонент Modal из библиотеки) с текстом "Пользователь сохранен". - * выглядеть будет примерно как на картинке drafts/reactModal.png (http://localhost:8080/drafts/reactModal.png) - * - * 7. Сделай так, чтобы в той же модалке (в теле модального окна — Modal.Body) показывались изменения в полях. - * Смотри drafts/reactDiff.png (http://localhost:8080/drafts/reactDiff.png). - * Пример сообщения: - * - * Измененные данные: - * Фамилия: было "Петров", стало "Петрова" - * - * Для этого надо хранить где-то предыдущее (и текущее) значение. Придумай, как лучше это сделать. - * - * 8*. Необязательная задача. - * Сделай так, чтобы форма не сохранялась, если поле имя или фамилия не заполнено. - * Незаполненное поле должно анимацией покачаться из стороны в сторону (или придумай любой другой эффект). - * - * 9*. Необязательная задача. - * Добавь в эту форму еще поля: пол, дата рождения, город рождения, семейное положение, - * гражданство, национальность, номер телефона и адрес электронной почты. - * Придумай, как избежать излишнего дублирования. - */ - -console.log('Hi from script!'); +// Выполнены задания 1-8 + +const fieldRepo: { [key: string]: string } = { + Имя: '', + Фамилия: '', + Город: '' +}; + +const Form = () => { + const [isOpened, setOpenedState] = useState(false); + + const [name, setName] = useState(''); + const [surname, setSurname] = useState(''); + const [city, setCity] = useState(''); + + const [nameEmpty, setNameEmpty] = useState(false); + const [surnameEmpty, setSurnameEmpty] = useState(false); + + const openModal = () => { + setOpenedState(true); + }; + const closeModal = () => { + setOpenedState(false); + }; + + const [changeMessage, setChangeMessage] = useState(Array()); + const saveChanges = () => { + if (!name) setNameEmpty(true); + if (!surname) setSurnameEmpty(true); + + if (!(name && surname)) return; + + const newChangeMessage = [ + addIfUpdated('Имя', name), + addIfUpdated('Фамилия', surname), + addIfUpdated('Город', city) + ]; + + setChangeMessage(newChangeMessage); + openModal(); + }; + + const addIfUpdated = (field_name: string, new_value: string) => { + const old_value = fieldRepo[field_name]; + fieldRepo[field_name] = new_value; + if (old_value && old_value !== new_value) { + return `${field_name}: Было ${old_value}, стало ${new_value}`; + } + return ''; + }; + + return ( +
+ +

Информация о пользователе

+ { + setName(value); + setNameEmpty(false); + }} + isError={nameEmpty} + /> + + { + setSurname(value); + setSurnameEmpty(false); + }} + isError={surnameEmpty} + /> + + { + setCity(value); + }} + /> + +
+ {isOpened && } +
+ ); +}; + +ReactDom.render(
, document.getElementById('root')); diff --git a/userProfile/src/style.css b/userProfile/src/style.css index 582e3b7..9f879f5 100644 --- a/userProfile/src/style.css +++ b/userProfile/src/style.css @@ -1,3 +1,22 @@ +p { + margin: 0 0; +} + body { font-family: "Segoe UI", Helvetica, sans-serif; } + +.form .inputRow .error-message { + color: red; + font-size: 10px; + font-style: italic; +} + +.form .form-title { + font-size: 28px; + font-weight: bold; +} + +.form .inputRow .title{ + width: 100px; +} diff --git a/userProfile/src/task.txt b/userProfile/src/task.txt new file mode 100644 index 0000000..0289051 --- /dev/null +++ b/userProfile/src/task.txt @@ -0,0 +1,55 @@ +/** + * Итак, перед тобой пустой проект. Давай его чем-то заполним. Не стесняйся подсматривать в уже сделанные задачи, + * чтобы оттуда что-то скопировать. + * + * 1. Создай в файле index.html (он на уровень выше в файловой структуре) div с каким-нибудь id + * 2. Импортируй сюда библиотеку React и ReactDom + * 3. Отрендери "Hello world" на странице при помощи Реакта. + * + * 4. Добавь в разметку Button из библиотеки компонентов Контура (@skbkontur/react-ui). + * npm-пакет с библиотекой уже добавлен в проект. + * + * Импортируется компонент на страницу так: + * + * import { Button } from '@skbkontur/react-ui'; + * + * Используется компонент так: + * + * const MyApp = () => ( + *
+ * Click this button + *
+ * ); + * + * + * Тут можно посмотреть, как компонентами пользоваться, какие у них атрибуты есть: + * http://tech.skbkontur.ru/react-ui/ + * + * 5. Теперь, когда ты знаешь все основное, сверстай при помощи react-ui форму, + * как на картинке drafts/reactForm.png (можно открыть в браузере http://localhost:8080/drafts/reactForm.png) + * Для вертикальных отступов между элементами используй компонент Gapped из библиотеки. + * Если хочешь что-то стилизовать, используй файл style.css. + * Список городов придумай сам. + * + * 6. Сделай так, чтобы при клике по кнопке "Сохранить", + * показывалось модальное окно (компонент Modal из библиотеки) с текстом "Пользователь сохранен". + * выглядеть будет примерно как на картинке drafts/reactModal.png (http://localhost:8080/drafts/reactModal.png) + * + * 7. Сделай так, чтобы в той же модалке (в теле модального окна — Modal.Body) показывались изменения в полях. + * Смотри drafts/reactDiff.png (http://localhost:8080/drafts/reactDiff.png). + * Пример сообщения: + * + * Измененные данные: + * Фамилия: было "Петров", стало "Петрова" + * + * Для этого надо хранить где-то предыдущее (и текущее) значение. Придумай, как лучше это сделать. + * + * 8*. Необязательная задача. + * Сделай так, чтобы форма не сохранялась, если поле имя или фамилия не заполнено. + * Незаполненное поле должно анимацией покачаться из стороны в сторону (или придумай любой другой эффект). + * + * 9*. Необязательная задача. + * Добавь в эту форму еще поля: пол, дата рождения, город рождения, семейное положение, + * гражданство, национальность, номер телефона и адрес электронной почты. + * Придумай, как избежать излишнего дублирования. + */ diff --git a/userProfile/src/types.tsx b/userProfile/src/types.tsx new file mode 100644 index 0000000..d8d8f46 --- /dev/null +++ b/userProfile/src/types.tsx @@ -0,0 +1,18 @@ +type InputProps = { + title: string; + onInputChange: (value: string) => void; +}; + +export interface RowProps extends InputProps { + placeholder?: string; + isError: boolean; +} + +export interface SelectProps extends InputProps { + title: string; +} + +export type ModeOnSaveProps = { + close: () => void; + changeMessage: string[]; +};