From 2c7ac9af8427d6dbb29612d336485ed78c7aabef Mon Sep 17 00:00:00 2001 From: SlimusMinus Date: Wed, 29 Jul 2026 01:24:57 +0300 Subject: [PATCH] added checkbox rules_accepted in post --- src/components/CreateUpdatePost.jsx | 51 ++++++++++++++++++++++++----- src/config/feedConstants.js | 3 +- src/styles/modal.css | 35 ++++++++++++++++++++ src/utils/validatePostForm.js | 1 + 4 files changed, 81 insertions(+), 9 deletions(-) diff --git a/src/components/CreateUpdatePost.jsx b/src/components/CreateUpdatePost.jsx index 3d433ff..0b3b2ea 100644 --- a/src/components/CreateUpdatePost.jsx +++ b/src/components/CreateUpdatePost.jsx @@ -1,5 +1,6 @@ import {useCallback, useEffect, useState} from "react"; import CloseIcon from "./icons/CloseIcon"; +import RulesModal from "./RulesModal"; import { EMPTY_FORM, CATEGORY_KEYS } from "../config/feedConstants"; import { useTranslation } from 'react-i18next'; import { usePostMutation } from "../hooks/usePostMutation"; @@ -26,18 +27,19 @@ export default function CreateUpdatePost({ onClose, onSuccess, initialData }) { const [form, setForm] = useState( isEdit ? { - type: (initialData.type || "loss").toLowerCase(), - title: initialData.title || "", - description: initialData.description || "", - category: initialData.category || "", - date: initialData.date || "", - phone: initialData.phone || "", - address: initialData.city || "" + type: (initialData.type || "loss").toLowerCase(), + title: initialData.title || "", + description: initialData.description || "", + category: initialData.category || "", + date: initialData.date || "", + phone: initialData.phone || "", + address: initialData.city || "", + rulesAccepted: true } : EMPTY_FORM ); - // Ошибки валидации — ключ совпадает с именем поля + const [rulesModalOpen, setRulesModalOpen] = useState(false); const [errors, setErrors] = useState({}); const { @@ -125,6 +127,8 @@ export default function CreateUpdatePost({ onClose, onSuccess, initialData }) { data.append("address", form.address.trim()); } + data.append("rulesAccepted", form.rulesAccepted ? "true" : "false"); + // save(id, data): id = null → POST (создание), id = string → PUT (обновление) const result = await save(isEdit ? initialData.id : null, data); if (!result) { @@ -307,6 +311,32 @@ export default function CreateUpdatePost({ onClose, onSuccess, initialData }) { {errors.phone &&

{errors.phone}

} + {/* Чекбокс согласия с правилами */} +
+ + {errors.rulesAccepted &&

{errors.rulesAccepted}

} +
+ {/* Глобальная ошибка API (не связана с конкретным полем) */} {apiError &&

{apiError}

} @@ -321,6 +351,11 @@ export default function CreateUpdatePost({ onClose, onSuccess, initialData }) { + {/* ── Модалка с правилами площадки ── */} + {rulesModalOpen && ( + setRulesModalOpen(false)} /> + )} + {/* ── Модалка-результат после отправки ── */} {resultModal && (
{ diff --git a/src/config/feedConstants.js b/src/config/feedConstants.js index 9c0fe63..46e1c8c 100644 --- a/src/config/feedConstants.js +++ b/src/config/feedConstants.js @@ -23,5 +23,6 @@ export const EMPTY_FORM = { location: "", phone: "", date: "", - address: "" + address: "", + rulesAccepted: false }; diff --git a/src/styles/modal.css b/src/styles/modal.css index 3619b91..5026b46 100644 --- a/src/styles/modal.css +++ b/src/styles/modal.css @@ -253,6 +253,41 @@ } } +/* ── Rules Checkbox ── */ +.f-rules-checkbox { + display: flex; align-items: center; gap: 10px; cursor: pointer; + user-select: none; padding: 6px 0; +} +.f-rules-input { + position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; +} +.f-rules-checkmark { + flex-shrink: 0; width: 20px; height: 20px; + border: 2px solid var(--border); border-radius: 5px; + background: var(--bg-input); transition: all .2s; + position: relative; +} +.f-rules-input:checked + .f-rules-checkmark { + background: var(--teal); border-color: var(--teal); +} +.f-rules-input:checked + .f-rules-checkmark::after { + content: ""; position: absolute; left: 5px; top: 1px; + width: 6px; height: 10px; + border: solid #082320; border-width: 0 2.5px 2.5px 0; + transform: rotate(45deg); +} +.f-rules-input:focus + .f-rules-checkmark { + box-shadow: 0 0 0 3px rgba(var(--teal-rgb), .25); +} +.f-rules-text { + font-size: .82rem; color: var(--muted); line-height: 1.4; +} +.f-rules-link { + color: var(--teal); cursor: pointer; text-decoration: underline; + text-underline-offset: 2px; transition: opacity .15s; +} +.f-rules-link:hover { opacity: .75; } + /* ── Result Modal (success / blocked) ── */ .f-modal-result { text-align: center; diff --git a/src/utils/validatePostForm.js b/src/utils/validatePostForm.js index 160e3fe..864b04f 100644 --- a/src/utils/validatePostForm.js +++ b/src/utils/validatePostForm.js @@ -6,5 +6,6 @@ export function validatePostForm(form) { if (!form.description.trim()) errors.description = i18n.t('validation.descriptionRequired'); if (!form.category) errors.category = i18n.t('validation.categoryRequired'); if (!form.phone.trim()) errors.phone = i18n.t('validation.phoneRequired'); + if (!form.rulesAccepted) errors.rulesAccepted = i18n.t('validation.rulesRequired'); return errors; }