Skip to content

Commit 4cdc44a

Browse files
author
Victoria Ivanova
committed
fix textarea expanding
1 parent 3c6db05 commit 4cdc44a

File tree

2 files changed

+88
-64
lines changed

2 files changed

+88
-64
lines changed

frontend/src/pages/Report/components/Bug/Bug.tsx

Lines changed: 84 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import Chat from "./components/Chat/Chat";
2222
import { uploadAttachmentFx } from "@/store/attachments";
2323
import { Bug as BugType } from "@/types/bug";
2424
import Result from "./components/Result/Result";
25-
import { ChangeEvent } from "react";
25+
import { ChangeEvent, useEffect, useRef } from "react";
2626
import Heading from "./components/Heading/Heading";
2727

2828
type BugProps = {
@@ -49,8 +49,9 @@ const Bug = ({ reportId, isNewReport, bugId }: BugProps) => {
4949
]);
5050

5151
const [newBugData, updateNewBugData] = useUnit([$newBugStore, updateNewBug]);
52-
5352
const [reportRequestState] = useUnit([$reportRequestState]);
53+
const receivedTextareaRef = useRef<HTMLTextAreaElement>(null);
54+
const expectedTextareaRef = useRef<HTMLTextAreaElement>(null);
5455

5556
const bug = useStoreMap({
5657
store: $bugsByBugId,
@@ -71,6 +72,37 @@ const Bug = ({ reportId, isNewReport, bugId }: BugProps) => {
7172
},
7273
});
7374

75+
useEffect(() => {
76+
const root = document.documentElement;
77+
const rawCssVar = getComputedStyle(root).getPropertyValue("--spacing");
78+
const spacing = parseFloat(rawCssVar);
79+
// вычисляем значение паддинга у <textarea />
80+
// 3 -- потому что className p-3 у <textarea />
81+
const calculatedTextareaPaddingEm = spacing * 3;
82+
83+
if (receivedTextareaRef.current && expectedTextareaRef.current) {
84+
const fontSizePx = parseFloat(
85+
getComputedStyle(receivedTextareaRef.current).fontSize
86+
);
87+
const calculatedTextareaPaddingPx =
88+
calculatedTextareaPaddingEm * fontSizePx;
89+
const textareaReceiveScrollHeight = `${
90+
receivedTextareaRef.current.scrollHeight + calculatedTextareaPaddingPx
91+
}px`;
92+
const textareaExpectScrollHeight = `${
93+
expectedTextareaRef.current.scrollHeight + calculatedTextareaPaddingPx
94+
}px`;
95+
96+
if (textareaReceiveScrollHeight >= textareaExpectScrollHeight) {
97+
receivedTextareaRef.current.style.height = textareaReceiveScrollHeight;
98+
expectedTextareaRef.current.style.height = "100%";
99+
} else {
100+
expectedTextareaRef.current.style.height = textareaExpectScrollHeight;
101+
receivedTextareaRef.current.style.height = "100%";
102+
}
103+
}
104+
}, [receivedTextareaRef, expectedTextareaRef, newBugData, bug]);
105+
74106
const attachments = useStoreMap({
75107
store: $attachmentsByBugId,
76108
keys: [bugId],
@@ -143,64 +175,62 @@ const Bug = ({ reportId, isNewReport, bugId }: BugProps) => {
143175

144176
return (
145177
<div
146-
className={`card card-border p-4 mb-3 shadow-lg border-gray-300 ${
178+
className={`card card-border grid grid-cols-2 gap-2 p-4 mb-3 shadow-lg border-gray-300 ${
147179
bug.status === Number(BugStatuses.READY) ? "border-success" : ""
148180
}`}
149181
>
150-
<div className="gap-2 flex flex-col">
151-
<div className="flex items-center justify-between">
152-
{reportRequestState !== RequestStates.DONE ? (
153-
<div className="skeleton min-h-[2em] min-w-[30%] shrink-0" />
154-
) : (
155-
<Heading isNewBug={isNewBug} bugId={bug.id} />
156-
)}
157-
158-
{/* Селект статуса (только для существующего бага) */}
159-
{!isNewBug && reportRequestState === RequestStates.DONE && (
160-
<Dropdown
161-
className="max-w-[150px]"
162-
onChange={(selected) => {
163-
if (bug.id) {
164-
updateBugData({ id: bug.id, status: Number(selected) });
165-
}
166-
}}
167-
value={bug.status}
168-
options={[
169-
{ label: "Исправлен", value: BugStatuses.READY },
170-
{ label: "Открыт", value: BugStatuses.IN_PROGRESS },
171-
]}
172-
/>
173-
)}
174-
{reportRequestState !== RequestStates.DONE && (
175-
<div className="skeleton min-h-[40px] min-w-[30%] shrink-0" />
176-
)}
177-
</div>
178-
<div className="flex grow-1 gap-2">
179-
<Result
180-
title="Фактический результат"
181-
value={isNewBug ? newBugData.receive : bug?.receive || ""}
182-
onChange={(event) => handleResultUpdate(event, "receive")}
183-
files={receivedFiles}
184-
onFileChange={(event) =>
185-
handleFileChange(event, AttachmentTypes.RECEIVED_RESULT)
186-
}
187-
withAttachments={!isNewBug}
188-
/>
189-
<Result
190-
title="Ожидаемый результат"
191-
value={isNewBug ? newBugData.expect : bug?.expect || ""}
192-
onChange={(event) => handleResultUpdate(event, "expect")}
193-
files={expectedFiles}
194-
onFileChange={(event) =>
195-
handleFileChange(event, AttachmentTypes.EXPECTED_RESULT)
196-
}
197-
withAttachments={!isNewBug}
182+
<div className="flex items-center justify-between col-span-2">
183+
{reportRequestState !== RequestStates.DONE ? (
184+
<div className="skeleton min-h-[2em] min-w-[30%] shrink-0" />
185+
) : (
186+
<Heading isNewBug={isNewBug} bugId={bug.id} />
187+
)}
188+
189+
{/* Селект статуса (только для существующего бага) */}
190+
{!isNewBug && reportRequestState === RequestStates.DONE && (
191+
<Dropdown
192+
className="max-w-[150px]"
193+
onChange={(selected) => {
194+
if (bug.id) {
195+
updateBugData({ id: bug.id, status: Number(selected) });
196+
}
197+
}}
198+
value={bug.status}
199+
options={[
200+
{ label: "Исправлен", value: BugStatuses.READY },
201+
{ label: "Открыт", value: BugStatuses.IN_PROGRESS },
202+
]}
198203
/>
199-
</div>
204+
)}
205+
{reportRequestState !== RequestStates.DONE && (
206+
<div className="skeleton min-h-[40px] min-w-[30%] shrink-0" />
207+
)}
200208
</div>
209+
<Result
210+
title="Фактический результат"
211+
value={isNewBug ? newBugData.receive : bug?.receive || ""}
212+
onChange={(event) => handleResultUpdate(event, "receive")}
213+
files={receivedFiles}
214+
onFileChange={(event) =>
215+
handleFileChange(event, AttachmentTypes.RECEIVED_RESULT)
216+
}
217+
withAttachments={!isNewBug}
218+
textareaRef={receivedTextareaRef}
219+
/>
220+
<Result
221+
title="Ожидаемый результат"
222+
value={isNewBug ? newBugData.expect : bug?.expect || ""}
223+
onChange={(event) => handleResultUpdate(event, "expect")}
224+
files={expectedFiles}
225+
onFileChange={(event) =>
226+
handleFileChange(event, AttachmentTypes.EXPECTED_RESULT)
227+
}
228+
withAttachments={!isNewBug}
229+
textareaRef={expectedTextareaRef}
230+
/>
201231
{/* Кнопки "Сохранить" / "Отмена" */}
202232
{!isNewReport && isBugChanged && (
203-
<div className="flex gap-2 justify-end mt-2">
233+
<div className="flex gap-2 justify-end mt-2 col-span-2">
204234
<CancelButton
205235
isChanged={isBugChanged}
206236
onReset={() => {
@@ -220,7 +250,7 @@ const Bug = ({ reportId, isNewReport, bugId }: BugProps) => {
220250
</div>
221251
)}
222252
{!isNewBug && (
223-
<div className="mt-2">
253+
<div className="mt-2 col-span-2">
224254
<Chat reportId={bug.reportId!} bugId={bug.id!} />
225255
</div>
226256
)}

frontend/src/pages/Report/components/Bug/components/Result/Result.tsx

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Attachment } from "@/types/attachement";
2-
import { ChangeEvent, useEffect, useRef } from "react";
2+
import { ChangeEvent, Ref, useRef } from "react";
33
import ImageCarousel from "./components/ImageCarousel/ImageCarousel";
44

55
type Props = {
@@ -9,6 +9,7 @@ type Props = {
99
withAttachments: boolean;
1010
files: Attachment[];
1111
onFileChange: (event: ChangeEvent<HTMLInputElement>) => void;
12+
textareaRef: Ref<HTMLTextAreaElement>;
1213
};
1314

1415
const Result = ({
@@ -18,17 +19,10 @@ const Result = ({
1819
onFileChange,
1920
withAttachments,
2021
files,
22+
textareaRef,
2123
}: Props) => {
22-
const textareaRef = useRef<HTMLTextAreaElement>(null);
2324
const fileInputRef = useRef<HTMLInputElement>(null);
2425

25-
useEffect(() => {
26-
if (textareaRef.current) {
27-
textareaRef.current.style.height = "auto";
28-
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
29-
}
30-
}, [textareaRef]);
31-
3226
return (
3327
<div className="flex grow-1 flex-col mb-1">
3428
<span className="mt-1 mb-1 font-semibold text-xs">{title}</span>
@@ -39,7 +33,7 @@ const Result = ({
3933
className="textarea w-full mb-3 p-3 bg-base-100 focus:outline-none"
4034
/>
4135
{withAttachments && (
42-
<div className="attachments w-1/2">
36+
<div className="attachments w-1/2 mt-auto">
4337
{/* Скрытый input для выбора файла */}
4438
<input
4539
ref={fileInputRef}

0 commit comments

Comments
 (0)