From afad1b460552141f08a26268b8eddc59384fab41 Mon Sep 17 00:00:00 2001 From: AlexSserb Date: Fri, 8 Aug 2025 15:01:10 +0400 Subject: [PATCH] feat: boards and statuses editing and creating for mobiles --- package.json | 1 + src/app/deals/components/Board/Board.tsx | 1 + src/app/deals/components/Board/BoardMenu.tsx | 7 ++- .../CreateBoardButton/CreateBoardButton.tsx | 1 + .../CreateStatusButton/CreateStatusButton.tsx | 1 + src/app/deals/components/Funnel/Funnel.tsx | 5 +- .../StatusColumnWrapper.tsx | 1 + .../ui/InPlaceInput/InPlaceInput.tsx | 22 ++++++-- src/modals/EnterNameModal/EnterNameModal.tsx | 51 +++++++++++++++++++ src/modals/TestModal/TestModal.tsx | 16 ------ src/modals/modals.ts | 4 +- yarn.lock | 22 ++++++++ 12 files changed, 109 insertions(+), 23 deletions(-) create mode 100644 src/modals/EnterNameModal/EnterNameModal.tsx delete mode 100644 src/modals/TestModal/TestModal.tsx diff --git a/package.json b/package.json index 0e70a2b..22d7dbb 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "libphonenumber-js": "^1.12.10", "next": "15.3.3", "react": "19.1.0", + "react-device-detect": "^2.2.3", "react-dom": "19.1.0", "react-imask": "^7.6.1", "react-redux": "^9.2.0", diff --git a/src/app/deals/components/Board/Board.tsx b/src/app/deals/components/Board/Board.tsx index 97392da..feee2e1 100644 --- a/src/app/deals/components/Board/Board.tsx +++ b/src/app/deals/components/Board/Board.tsx @@ -44,6 +44,7 @@ const Board: FC = ({ board }) => { /> )} + modalTitle={"Редактирование доски"} /> ); diff --git a/src/app/deals/components/Board/BoardMenu.tsx b/src/app/deals/components/Board/BoardMenu.tsx index c566512..c81cde9 100644 --- a/src/app/deals/components/Board/BoardMenu.tsx +++ b/src/app/deals/components/Board/BoardMenu.tsx @@ -1,5 +1,6 @@ import React, { FC } from "react"; import { IconDotsVertical, IconEdit, IconTrash } from "@tabler/icons-react"; +import { isMobile } from "react-device-detect"; import { Box, Group, Menu, Text } from "@mantine/core"; import { useBoardsContext } from "@/app/deals/contexts/BoardsContext"; import { BoardSchema } from "@/lib/client"; @@ -19,7 +20,11 @@ const BoardMenu: FC = ({ isHovered, board, startEditing }) => { { diff --git a/src/app/deals/components/CreateBoardButton/CreateBoardButton.tsx b/src/app/deals/components/CreateBoardButton/CreateBoardButton.tsx index 88b557f..114bd17 100644 --- a/src/app/deals/components/CreateBoardButton/CreateBoardButton.tsx +++ b/src/app/deals/components/CreateBoardButton/CreateBoardButton.tsx @@ -16,6 +16,7 @@ const CreateBoardButton = () => { )} + modalTitle={"Создание доски"} /> ); diff --git a/src/app/deals/components/CreateStatusButton/CreateStatusButton.tsx b/src/app/deals/components/CreateStatusButton/CreateStatusButton.tsx index fcef172..b38e544 100644 --- a/src/app/deals/components/CreateStatusButton/CreateStatusButton.tsx +++ b/src/app/deals/components/CreateStatusButton/CreateStatusButton.tsx @@ -26,6 +26,7 @@ const CreateStatusButton = () => { Создать колонку )} + modalTitle={"Создание колонки"} /> ); diff --git a/src/app/deals/components/Funnel/Funnel.tsx b/src/app/deals/components/Funnel/Funnel.tsx index 94f1b7d..a52b0ab 100644 --- a/src/app/deals/components/Funnel/Funnel.tsx +++ b/src/app/deals/components/Funnel/Funnel.tsx @@ -28,7 +28,10 @@ const Funnel: FC = () => { - + )} + modalTitle={"Редактирование статуса"} /> {children} diff --git a/src/components/ui/InPlaceInput/InPlaceInput.tsx b/src/components/ui/InPlaceInput/InPlaceInput.tsx index ebd6080..be61112 100644 --- a/src/components/ui/InPlaceInput/InPlaceInput.tsx +++ b/src/components/ui/InPlaceInput/InPlaceInput.tsx @@ -1,6 +1,8 @@ import React, { FC, ReactNode, useEffect, useRef, useState } from "react"; import { TextInput } from "@mantine/core"; import { Styles } from "@mantine/core/lib/core/styles-api/styles-api.types"; +import { isMobile } from "react-device-detect"; +import { modals } from "@mantine/modals"; type Props = { defaultValue?: string; @@ -8,6 +10,7 @@ type Props = { placeholder?: string; getChildren: (startEditing: () => void) => ReactNode; inputStyles?: Styles; + modalTitle?: string; }; const InPlaceInput: FC = ({ @@ -15,11 +18,11 @@ const InPlaceInput: FC = ({ placeholder, inputStyles, getChildren, + modalTitle = "", defaultValue = "", }) => { const [isWriting, setIsWriting] = useState(false); const [value, setValue] = useState(defaultValue); - console.log(value); const inputRef = useRef(null); useEffect(() => { @@ -45,8 +48,21 @@ const InPlaceInput: FC = ({ }, [isWriting, value]); const onStartCreating = () => { - setValue(defaultValue); - setIsWriting(true); + if (!isMobile) { + setValue(defaultValue); + setIsWriting(true); + return; + } + + modals.openContextModal({ + modal: "enterNameModal", + title: modalTitle, + withCloseButton: true, + innerProps: { + onComplete, + defaultValue, + }, + }); }; const onCancelCreating = () => { diff --git a/src/modals/EnterNameModal/EnterNameModal.tsx b/src/modals/EnterNameModal/EnterNameModal.tsx new file mode 100644 index 0000000..e9fa3af --- /dev/null +++ b/src/modals/EnterNameModal/EnterNameModal.tsx @@ -0,0 +1,51 @@ +"use client"; + +import { Button, Flex, rem, TextInput } from "@mantine/core"; +import { useForm } from "@mantine/form"; +import { ContextModalProps } from "@mantine/modals"; + +type Props = { + onComplete: (value: string) => void; + defaultValue?: string; +}; + +type FormType = { + name?: string; +}; + +const EnterNameModal = ({ + id, + context, + innerProps, +}: ContextModalProps) => { + const form = useForm({ + initialValues: { + name: innerProps.defaultValue, + }, + validate: { + name: name => !name && "Введите название", + }, + }); + + const onSubmit = (values: FormType) => { + innerProps.onComplete(values.name!); + context.closeModal(id); + }; + + return ( +
onSubmit(values))}> + + + + +
+ ); +}; + +export default EnterNameModal; diff --git a/src/modals/TestModal/TestModal.tsx b/src/modals/TestModal/TestModal.tsx deleted file mode 100644 index dc21255..0000000 --- a/src/modals/TestModal/TestModal.tsx +++ /dev/null @@ -1,16 +0,0 @@ -"use client" - -import { Flex, rem, Text } from "@mantine/core"; -import { ContextModalProps } from "@mantine/modals"; - -const TestModal = ({ id, context, innerProps }: ContextModalProps) => { - return ( - - Hi - - ); -}; - -export default TestModal; diff --git a/src/modals/modals.ts b/src/modals/modals.ts index c947bd4..82c72c6 100644 --- a/src/modals/modals.ts +++ b/src/modals/modals.ts @@ -1,5 +1,5 @@ -import TestModal from "@/modals/TestModal/TestModal"; +import EnterNameModal from "@/modals/EnterNameModal/EnterNameModal"; export const modals = { - testModal: TestModal, + enterNameModal: EnterNameModal, }; diff --git a/yarn.lock b/yarn.lock index 16da236..2c755d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6103,6 +6103,7 @@ __metadata: postcss-simple-vars: "npm:^7.0.1" prettier: "npm:^3.5.3" react: "npm:19.1.0" + react-device-detect: "npm:^2.2.3" react-dom: "npm:19.1.0" react-imask: "npm:^7.6.1" react-redux: "npm:^9.2.0" @@ -11543,6 +11544,18 @@ __metadata: languageName: node linkType: hard +"react-device-detect@npm:^2.2.3": + version: 2.2.3 + resolution: "react-device-detect@npm:2.2.3" + dependencies: + ua-parser-js: "npm:^1.0.33" + peerDependencies: + react: ">= 0.14.0" + react-dom: ">= 0.14.0" + checksum: 10c0/396bbeeab0cb21da084c67434d204c9cf502fad6c683903313084d3f6487950a36a34f9bf67ccf5c1772a1bb5b79a2a4403fcfe6b51d93877db4c2d9f3a3a925 + languageName: node + linkType: hard + "react-docgen-typescript@npm:^2.2.2": version: 2.4.0 resolution: "react-docgen-typescript@npm:2.4.0" @@ -13653,6 +13666,15 @@ __metadata: languageName: node linkType: hard +"ua-parser-js@npm:^1.0.33": + version: 1.0.40 + resolution: "ua-parser-js@npm:1.0.40" + bin: + ua-parser-js: script/cli.js + checksum: 10c0/2b6ac642c74323957dae142c31f72287f2420c12dced9603d989b96c132b80232779c429b296d7de4012ef8b64e0d8fadc53c639ef06633ce13d785a78b5be6c + languageName: node + linkType: hard + "ufo@npm:^1.5.4": version: 1.6.1 resolution: "ufo@npm:1.6.1"