/
nsstnc
/
lab3
Обзор
Документация
Войти
/
nsstnc
/
lab3
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/components/TaskDetail.tsx
149 строк
6 KB
nsstnc
Добавил компоненты
21 ноя 2025, 18:14
21 ноя 2025, 18:14
510bd3d
Код
Авторство
О чём код?
import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query' import {getTaskById} from '@/api/tasks' import {getComments, addComment, updateComment, deleteComment} from '@/api/comments' import {format} from 'date-fns' import {ru} from 'date-fns/locale' import {useState} from 'react' interface TaskDetailProps { taskId: number onClose: () => void } export default function TaskDetail({taskId, onClose}: TaskDetailProps) { const [message, setMessage] = useState('') const [editingId, setEditingId] = useState<number | null>(null) const [editText, setEditText] = useState('') const queryClient = useQueryClient() const {data: task} = useQuery({ queryKey: ['task', taskId], queryFn: () => getTaskById(taskId), }) const {data: comments = []} = useQuery({ queryKey: ['comments', taskId], queryFn: () => getComments(taskId, true), }) const addMut = useMutation({ mutationFn: (msg: string) => addComment(taskId, msg), onSuccess: () => { queryClient.invalidateQueries({queryKey: ['comments', taskId]}) setMessage('') }, }) const updateMut = useMutation({ mutationFn: ({id, msg}: { id: number; msg: string }) => updateComment(id, msg), onSuccess: () => { queryClient.invalidateQueries({queryKey: ['comments', taskId]}) setEditingId(null) }, }) const deleteMut = useMutation({ mutationFn: deleteComment, onSuccess: () => queryClient.invalidateQueries({queryKey: ['comments', taskId]}), }) if (!task) return null return ( <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"> <div className="bg-white rounded-xl shadow-2xl max-w-3xl w-full max-h-screen overflow-y-auto"> <div className="p-6"> <div className="flex justify-between items-start mb-6"> <div> <h2 className="text-3xl font-bold">{task.title}</h2> <p className="text-gray-600 mt-2"> ID: {task.taskId} • Назначена: пользователю {task.assignedToUserId} </p> {task.completedAt && ( <p className="text-sm text-gray-500"> Закрыта: {format(new Date(task.completedAt), 'dd MMMM yyyy, HH:mm', {locale: ru})} </p> )} </div> <button onClick={onClose} className="text-3xl text-gray-500 hover:text-gray-700">×</button> </div> {/* Добавление комментария */} <div className="mb-8 p-5 bg-gray-50 rounded-lg"> <textarea value={message} onChange={(e) => setMessage(e.target.value)} placeholder="Написать комментарий..." className="w-full p-4 border rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-blue-500" rows={3} /> <button onClick={() => message.trim() && addMut.mutate(message.trim())} disabled={addMut.isPending} className="mt-3 bg-blue-600 hover:bg-blue-700 text-white px-6 py-3 rounded-lg disabled:opacity-50" > Отправить </button> </div> {/* Список комментариев */} <div className="space-y-4"> <h3 className="text-xl font-semibold">Комментарии ({comments.length})</h3> {comments.map((c: any) => ( <div key={c.id} className={`p-4 rounded-lg border ${c.deletedAt ? 'bg-gray-100 opacity-60' : 'bg-gray-50'}`}> {editingId === c.id ? ( <div> <textarea value={editText} onChange={(e) => setEditText(e.target.value)} className="w-full p-3 border rounded" rows={2} /> <div className="mt-2 space-x-2"> <button onClick={() => updateMut.mutate({id: c.id, msg: editText})} className="text-green-600 font-medium">Сохранить </button> <button onClick={() => setEditingId(null)} className="text-gray-600">Отмена</button> </div> </div> ) : ( <div> <p className="text-gray-800">{c.message}</p> <div className="mt-2 text-xs text-gray-500 flex justify-between"> <span> Автор {c.authorUserId} • {format(new Date(c.at), 'dd MMM yyyy, HH:mm', {locale: ru})} {c.modifiedAt && ' (изменён)'} {c.deletedAt && ' • Удалён'} </span> {!c.deletedAt && ( <div className="space-x-4"> <button onClick={() => { setEditingId(c.id); setEditText(c.message) }} className="text-blue-600 hover:underline" > Изменить </button> <button onClick={() => deleteMut.mutate(c.id)} className="text-red-600 hover:underline" > Удалить </button> </div> )} </div> </div> )} </div> ))} </div> </div> </div> </div> ) }