Files
opengroupware/components/meetings/ConflictWarning.tsx
Ken Yasue 29e4bc6650 feat(m12): meetings + schedule conflict detection, tests, e2e
- MeetingRepository (CRUD, soft-delete, members, findMeetingsByUserInRange
  overlap) + CalendarRepository.findByCreatorInRange + TodoRepository.
  findHighPriorityByAssignee
- MeetingService (createMeeting tx+members, meeting_invited notify,
  meeting_created activity, SSE meeting.created; updateMeeting/updateMinutes/
  deleteMeeting; checkScheduleConflicts = other meetings overlap + calendar
  events overlap + high-priority todos due +-3d, time-overlap logic,
  excludeMeetingId; conflicts are warnings)
- APIs: meetings list/create/edit + /check conflict check
- Screens: meetings page + MeetingForm(member checkboxes, conflict display)
  + ConflictWarning, ProjectNav link
- Unit tests (MeetingRepository, MeetingService incl. conflict algorithm)
  + e2e meetings
2026-06-25 02:19:25 +02:00

47 lines
1.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export interface ScheduleConflict {
userId: number;
type: 'meeting' | 'calendar_event' | 'important_todo';
refId: number;
title: string;
startAt: string;
endAt: string | null;
}
const TYPE_LABELS: Record<string, string> = {
meeting: 'ミーティング',
calendar_event: 'カレンダーイベント',
important_todo: '期限の近い重要タスク',
};
export function ConflictWarning({
conflicts,
}: {
conflicts: ScheduleConflict[];
}) {
if (conflicts.length === 0) {
return (
<p className="text-sm text-green-600" data-testid="no-conflicts">
</p>
);
}
return (
<div
className="rounded border border-yellow-300 bg-yellow-50 p-3"
data-testid="conflict-warning"
>
<p className="text-sm font-semibold text-yellow-800">
:
</p>
<ul className="mt-1 list-inside list-disc text-sm text-yellow-800">
{conflicts.map((c, i) => (
<li key={i}>
[{TYPE_LABELS[c.type] ?? c.type}] {c.title}{c.startAt}
{c.endAt ? `${c.endAt}` : ''}
</li>
))}
</ul>
</div>
);
}