This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import { useMemo, useState, Fragment } from 'react';
|
||||
import { useMemo, useState, Fragment, useCallback } from 'react';
|
||||
import {
|
||||
useReactTable,
|
||||
getCoreRowModel,
|
||||
@ -79,34 +79,45 @@ export function IdeasTable() {
|
||||
// AI-оценка
|
||||
const [estimatingId, setEstimatingId] = useState<string | null>(null);
|
||||
const [estimateModalOpen, setEstimateModalOpen] = useState(false);
|
||||
const [estimateResult, setEstimateResult] = useState<EstimateResult | null>(null);
|
||||
const [estimateResult, setEstimateResult] = useState<EstimateResult | null>(
|
||||
null,
|
||||
);
|
||||
// ТЗ (спецификация)
|
||||
const [specificationModalOpen, setSpecificationModalOpen] = useState(false);
|
||||
const [specificationIdea, setSpecificationIdea] = useState<Idea | null>(null);
|
||||
const [generatedSpecification, setGeneratedSpecification] = useState<string | null>(null);
|
||||
const [generatingSpecificationId, setGeneratingSpecificationId] = useState<string | null>(null);
|
||||
const [generatedSpecification, setGeneratedSpecification] = useState<
|
||||
string | null
|
||||
>(null);
|
||||
const [generatingSpecificationId, setGeneratingSpecificationId] = useState<
|
||||
string | null
|
||||
>(null);
|
||||
|
||||
// История ТЗ
|
||||
const specificationHistory = useSpecificationHistory(specificationIdea?.id ?? null);
|
||||
const specificationHistory = useSpecificationHistory(
|
||||
specificationIdea?.id ?? null,
|
||||
);
|
||||
|
||||
const handleToggleComments = (id: string) => {
|
||||
setExpandedId((prev) => (prev === id ? null : id));
|
||||
};
|
||||
|
||||
const handleEstimate = (id: string) => {
|
||||
setEstimatingId(id);
|
||||
setEstimateModalOpen(true);
|
||||
setEstimateResult(null);
|
||||
estimateIdea.mutate(id, {
|
||||
onSuccess: (result) => {
|
||||
setEstimateResult(result);
|
||||
setEstimatingId(null);
|
||||
},
|
||||
onError: () => {
|
||||
setEstimatingId(null);
|
||||
},
|
||||
});
|
||||
};
|
||||
const handleEstimate = useCallback(
|
||||
(id: string) => {
|
||||
setEstimatingId(id);
|
||||
setEstimateModalOpen(true);
|
||||
setEstimateResult(null);
|
||||
estimateIdea.mutate(id, {
|
||||
onSuccess: (result) => {
|
||||
setEstimateResult(result);
|
||||
setEstimatingId(null);
|
||||
},
|
||||
onError: () => {
|
||||
setEstimatingId(null);
|
||||
},
|
||||
});
|
||||
},
|
||||
[estimateIdea],
|
||||
);
|
||||
|
||||
const handleCloseEstimateModal = () => {
|
||||
setEstimateModalOpen(false);
|
||||
@ -121,37 +132,40 @@ export function IdeasTable() {
|
||||
ideaId: idea.id,
|
||||
ideaTitle: idea.title,
|
||||
totalHours: idea.estimatedHours,
|
||||
complexity: idea.complexity!,
|
||||
complexity: idea.complexity ?? 'medium',
|
||||
breakdown: idea.estimateDetails.breakdown,
|
||||
recommendations: idea.estimateDetails.recommendations,
|
||||
estimatedAt: idea.estimatedAt!,
|
||||
estimatedAt: idea.estimatedAt ?? new Date().toISOString(),
|
||||
});
|
||||
setEstimateModalOpen(true);
|
||||
};
|
||||
|
||||
const handleSpecification = (idea: Idea) => {
|
||||
setSpecificationIdea(idea);
|
||||
setSpecificationModalOpen(true);
|
||||
const handleSpecification = useCallback(
|
||||
(idea: Idea) => {
|
||||
setSpecificationIdea(idea);
|
||||
setSpecificationModalOpen(true);
|
||||
|
||||
// Если ТЗ уже есть — показываем его
|
||||
if (idea.specification) {
|
||||
setGeneratedSpecification(idea.specification);
|
||||
return;
|
||||
}
|
||||
// Если ТЗ уже есть — показываем его
|
||||
if (idea.specification) {
|
||||
setGeneratedSpecification(idea.specification);
|
||||
return;
|
||||
}
|
||||
|
||||
// Иначе генерируем
|
||||
setGeneratedSpecification(null);
|
||||
setGeneratingSpecificationId(idea.id);
|
||||
generateSpecification.mutate(idea.id, {
|
||||
onSuccess: (result) => {
|
||||
setGeneratedSpecification(result.specification);
|
||||
setGeneratingSpecificationId(null);
|
||||
},
|
||||
onError: () => {
|
||||
setGeneratingSpecificationId(null);
|
||||
},
|
||||
});
|
||||
};
|
||||
// Иначе генерируем
|
||||
setGeneratedSpecification(null);
|
||||
setGeneratingSpecificationId(idea.id);
|
||||
generateSpecification.mutate(idea.id, {
|
||||
onSuccess: (result) => {
|
||||
setGeneratedSpecification(result.specification);
|
||||
setGeneratingSpecificationId(null);
|
||||
},
|
||||
onError: () => {
|
||||
setGeneratingSpecificationId(null);
|
||||
},
|
||||
});
|
||||
},
|
||||
[generateSpecification],
|
||||
);
|
||||
|
||||
const handleCloseSpecificationModal = () => {
|
||||
setSpecificationModalOpen(false);
|
||||
@ -162,7 +176,7 @@ export function IdeasTable() {
|
||||
const handleSaveSpecification = (specification: string) => {
|
||||
if (!specificationIdea) return;
|
||||
updateIdea.mutate(
|
||||
{ id: specificationIdea.id, data: { specification } },
|
||||
{ id: specificationIdea.id, dto: { specification } },
|
||||
{
|
||||
onSuccess: () => {
|
||||
setGeneratedSpecification(specification);
|
||||
@ -209,7 +223,14 @@ export function IdeasTable() {
|
||||
estimatingId,
|
||||
generatingSpecificationId,
|
||||
}),
|
||||
[deleteIdea, expandedId, estimatingId, generatingSpecificationId],
|
||||
[
|
||||
deleteIdea,
|
||||
expandedId,
|
||||
estimatingId,
|
||||
generatingSpecificationId,
|
||||
handleEstimate,
|
||||
handleSpecification,
|
||||
],
|
||||
);
|
||||
|
||||
// eslint-disable-next-line react-hooks/incompatible-library
|
||||
@ -291,7 +312,10 @@ export function IdeasTable() {
|
||||
: null;
|
||||
|
||||
return (
|
||||
<Paper sx={{ width: '100%', overflow: 'hidden' }} data-testid="ideas-table-container">
|
||||
<Paper
|
||||
sx={{ width: '100%', overflow: 'hidden' }}
|
||||
data-testid="ideas-table-container"
|
||||
>
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
@ -386,9 +410,17 @@ export function IdeasTable() {
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={SKELETON_COLUMNS_COUNT}
|
||||
sx={{ p: 0, borderBottom: expandedId === row.original.id ? 1 : 0, borderColor: 'divider' }}
|
||||
sx={{
|
||||
p: 0,
|
||||
borderBottom:
|
||||
expandedId === row.original.id ? 1 : 0,
|
||||
borderColor: 'divider',
|
||||
}}
|
||||
>
|
||||
<Collapse in={expandedId === row.original.id} unmountOnExit>
|
||||
<Collapse
|
||||
in={expandedId === row.original.id}
|
||||
unmountOnExit
|
||||
>
|
||||
<CommentsPanel ideaId={row.original.id} />
|
||||
</Collapse>
|
||||
</TableCell>
|
||||
|
||||
Reference in New Issue
Block a user