import { useEffect, useState } from 'react'; import styled from 'styled-components'; import type { Gender, User } from '../../types/user'; import { TagsInput } from './TagsInput'; interface PersonModalProps { isOpen: boolean; user: User | null; availableTags: string[]; onClose: () => void; onSave: (user: User) => void; } interface PersonForm { name: string; gender: Gender; age: string; weight: string; height: string; avoid: string[]; favorite: string[]; } const defaultForm: PersonForm = { name: '', gender: 'm', age: '', weight: '', height: '', avoid: [], favorite: [], }; export function PersonModal({ isOpen, user, availableTags, onClose, onSave, }: PersonModalProps) { const [form, setForm] = useState(defaultForm); useEffect(() => { if (!isOpen) return; if (user) { setForm({ name: user.name, gender: user.gender, age: String(user.age), weight: user.weight ? String(user.weight) : '', height: user.height ? String(user.height) : '', avoid: user.avoid ?? [], favorite: user.favorite ?? [], }); } else { setForm(defaultForm); } }, [isOpen, user]); if (!isOpen) return null; function updateForm(name: TName, value: PersonForm[TName]) { setForm(current => ({ ...current, [name]: value, })); } function handleAvoidChange(tags: string[]) { setForm(current => ({ ...current, avoid: tags, favorite: current.favorite.filter(tag => !tags.includes(tag)), })); } function handleFavoriteChange(tags: string[]) { setForm(current => ({ ...current, favorite: tags, avoid: current.avoid.filter(tag => !tags.includes(tag)), })); } function handleSave() { const age = Number(form.age); if (!form.name.trim()) { alert('Пожалуйста, введите имя.'); return; } if (!age || age < 7) { alert('Возраст должен быть от 7 лет.'); return; } onSave({ id: user?.id, name: form.name.trim(), gender: form.gender, age, weight: form.weight ? Number(form.weight) : undefined, height: form.height ? Number(form.height) : undefined, avoid: form.avoid, favorite: form.favorite, }); } return ( event.stopPropagation()}>

{user ? 'Редактировать человека' : 'Добавить человека'}

×
updateForm('name', event.target.value)} /> updateForm('gender', 'f')} > Женский updateForm('gender', 'm')} > Мужской updateForm('age', event.target.value)} /> от 7 лет updateForm('weight', event.target.value)} /> updateForm('height', event.target.value)} /> Сохранить
); } const Overlay = styled.div` position: fixed; inset: 0; background: rgba(0, 0, 0, 0.4); backdrop-filter: blur(2px); display: flex; align-items: center; justify-content: center; z-index: 1000; padding: 20px; `; const Content = styled.div` background: #ffffff; border-radius: 24px; width: 100%; max-width: 440px; padding: 24px; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2); max-height: 95vh; overflow-y: auto; `; const Header = styled.div` display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; h2 { font-size: 20px; font-weight: 600; color: ${({ theme }) => theme.colors.darkGreen}; } `; const CloseButton = styled.button` font-size: 24px; color: #b0b0b0; cursor: pointer; line-height: 1; background: transparent; border: 0; &:hover { color: ${({ theme }) => theme.colors.darkGreen}; } `; const FormGroup = styled.div` margin-bottom: 16px; flex: 1; label { display: block; font-size: 14px; color: ${({ theme }) => theme.colors.darkGreen}; margin-bottom: 6px; } input { width: 100%; padding: 10px 12px; border: 1px solid #e1e1e1; border-radius: 8px; font-size: 14px; outline: none; transition: 0.2s; &:focus { border-color: ${({ theme }) => theme.colors.green}; } } `; const FormRow = styled.div` display: flex; gap: 16px; margin-bottom: 16px; ${FormGroup} { margin-bottom: 0; } @media (max-width: 600px) { flex-direction: column; } `; const Hint = styled.span` display: block; font-size: 12px; color: ${({ theme }) => theme.colors.gray}; margin-top: 4px; `; const GenderToggles = styled.div` display: flex; gap: 8px; margin-bottom: 16px; `; const GenderButton = styled.button<{ $active: boolean }>` flex: 1; padding: 10px; border: 1px solid ${({ $active }) => ($active ? '#e9f6d9' : '#e1e1e1')}; border-radius: 8px; background: ${({ $active }) => ($active ? '#e9f6d9' : '#ffffff')}; font-size: 14px; cursor: pointer; transition: 0.2s; font-weight: ${({ $active }) => ($active ? 500 : 400)}; `; const PrefsGrid = styled.div` display: flex; gap: 16px; margin-bottom: 20px; border-top: 1px solid #f0f0f0; padding-top: 16px; @media (max-width: 600px) { flex-direction: column; } `; const SaveButton = styled.button` width: 100%; padding: 12px; background: ${({ theme }) => theme.colors.green}; color: #fff; border: none; border-radius: 12px; font-size: 16px; font-weight: 600; cursor: pointer; transition: 0.2s; &:hover { background: #5b8f29; } `;