fix: feedback author display, sidebar scroll, stage sort by start date

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
EENE Dashboard
2026-06-05 22:55:11 +09:00
parent fa8ed76e22
commit 4960fe7352
6 changed files with 26 additions and 17 deletions

View File

@@ -26,7 +26,7 @@ export function FeedbackModal({
}: FeedbackModalProps) {
const [form, setForm] = useState<FeedbackFormData>({
content: detail?.content ?? '',
authorName: detail?.author?.name ?? defaultAuthorName,
authorName: detail?.authorName ?? detail?.author?.name ?? defaultAuthorName,
});
const handleSubmit = async (e: React.FormEvent) => {

View File

@@ -58,6 +58,19 @@ function sortByIsoDesc<T>(items: T[], pick: (item: T) => string) {
return [...items].sort((a, b) => new Date(pick(b)).getTime() - new Date(pick(a)).getTime());
}
/** 시작일이 늦은 단계가 상단 (시작일 없으면 종료일 → 생성일 순) */
function sortStagesByStartDesc(stages: Milestone[]) {
const pickStart = (m: Milestone) =>
m.startDate ?? m.dueDate ?? m.createdAt;
return [...stages].sort(
(a, b) => new Date(pickStart(b)).getTime() - new Date(pickStart(a)).getTime(),
);
}
function feedbackAuthorName(detail: TaskDetail) {
return detail.authorName?.trim() || detail.author?.name || '—';
}
function milestoneProgress(m: Milestone) {
if (m.completedAt) return 100;
const p = m.progress ?? 0;
@@ -215,7 +228,7 @@ function DetailView({ task }: { task: TaskWithRelations }) {
const details = task.details ?? [];
const sortedStages = useMemo(
() => sortByIsoDesc(milestones, (m) => m.updatedAt),
() => sortStagesByStartDesc(milestones),
[milestones],
);
@@ -404,7 +417,7 @@ function DetailView({ task }: { task: TaskWithRelations }) {
+
</button>
</div>
<div className="flex min-h-0 flex-1 flex-col gap-2 overflow-hidden">
<div className="flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto pr-1">
{sortedStages.length === 0 && (
<p className="text-lg text-slate-400">+ .</p>
)}
@@ -450,7 +463,7 @@ function DetailView({ task }: { task: TaskWithRelations }) {
<LeftSection>
<PanelLabel></PanelLabel>
<ul
className="min-h-0 flex-1 space-y-2 overflow-hidden"
className="min-h-0 flex-1 space-y-2 overflow-y-auto pr-1"
onContextMenu={(e) => {
if (!selected) return;
e.preventDefault();
@@ -495,7 +508,7 @@ function DetailView({ task }: { task: TaskWithRelations }) {
</button>
</div>
<div
className="flex min-h-0 flex-1 flex-col overflow-hidden"
className="flex min-h-0 flex-1 flex-col overflow-y-auto pr-1"
onContextMenu={(e) => {
if (!selectedId) return;
e.preventDefault();
@@ -505,7 +518,7 @@ function DetailView({ task }: { task: TaskWithRelations }) {
{sortedFeedbacks.length === 0 ? (
<p className="text-lg text-slate-400"> + .</p>
) : (
<div className="mb-2 min-h-0 flex-1 space-y-2 overflow-hidden">
<div className="mb-2 min-h-0 flex-1 space-y-2">
{sortedFeedbacks.map((f) => (
<div
key={f.id}
@@ -518,7 +531,7 @@ function DetailView({ task }: { task: TaskWithRelations }) {
>
<p className="truncate text-2xl font-black leading-snug text-slate-700">
{f.content}
<span className="font-bold text-slate-400"> {f.author?.name ?? '—'}</span>
<span className="font-bold text-slate-400"> {feedbackAuthorName(f)}</span>
</p>
</div>
))}

View File

@@ -47,6 +47,7 @@ export interface TaskDetail {
taskId: string;
milestoneId: string | null;
content: string;
authorName: string | null;
updatedBy: string;
createdAt: string;
updatedAt: string;