- Deleted redundant components (`AddActionButton`, `AlertBox`, `AlertStack`, `BackButton`, `CancelButton`, and `CollapsableArea`) and related files. - Removed unused models (`Book`, `BookSerie`, `BookTables`, `Character`, and `Chapter`) to reduce codebase clutter. - Updated project structure and references to reflect these removals.
172 lines
9.3 KiB
TypeScript
172 lines
9.3 KiB
TypeScript
import React, {useState} from 'react';
|
|
import {ChevronDown, ChevronUp, Plus, Trash2} from 'lucide-react';
|
|
import {Incident} from '@/lib/types/book';
|
|
import {ActChapter, ChapterListProps} from '@/lib/types/chapter';
|
|
import ActChapterItem from './ActChapter';
|
|
import IconButton from '@/components/ui/IconButton';
|
|
import Collapse from '@/components/ui/Collapse';
|
|
import SelectBox, {SelectBoxProps} from '@/components/form/SelectBox';
|
|
import InputField from '@/components/form/InputField';
|
|
import TextInput from '@/components/form/TextInput';
|
|
import {useTranslations} from '@/lib/i18n';
|
|
|
|
interface ActIncidentsProps {
|
|
incidents: Incident[];
|
|
actId: number;
|
|
mainChapters: ChapterListProps[];
|
|
newIncidentTitle: string;
|
|
setNewIncidentTitle: (title: string) => void;
|
|
onAddIncident: (actId: number) => Promise<void>;
|
|
onDeleteIncident: (actId: number, incidentId: string) => Promise<void>;
|
|
onLinkChapter: (actId: number, chapterId: string, incidentId: string) => Promise<void>;
|
|
onUpdateChapterSummary: (chapterId: string, summary: string, incidentId: string) => void;
|
|
onUnlinkChapter: (chapterInfoId: string, chapterId: string, incidentId: string) => Promise<void>;
|
|
sectionKey: string;
|
|
isExpanded: boolean;
|
|
onToggleSection: (sectionKey: string) => void;
|
|
}
|
|
|
|
export default function ActIncidents({
|
|
incidents,
|
|
actId,
|
|
mainChapters,
|
|
newIncidentTitle,
|
|
setNewIncidentTitle,
|
|
onAddIncident,
|
|
onDeleteIncident,
|
|
onLinkChapter,
|
|
onUpdateChapterSummary,
|
|
onUnlinkChapter,
|
|
sectionKey,
|
|
isExpanded,
|
|
onToggleSection,
|
|
}: ActIncidentsProps) {
|
|
const t = useTranslations('actComponent');
|
|
const [expandedItems, setExpandedItems] = useState<{ [key: string]: boolean }>({});
|
|
const [selectedChapterId, setSelectedChapterId] = useState<string>('');
|
|
|
|
function toggleItem(itemKey: string): void {
|
|
setExpandedItems(prev => ({
|
|
...prev,
|
|
[itemKey]: !prev[itemKey],
|
|
}));
|
|
}
|
|
|
|
function mainChaptersData(): SelectBoxProps[] {
|
|
return mainChapters.map(function (chapter: ChapterListProps): SelectBoxProps {
|
|
return {
|
|
value: chapter.chapterId,
|
|
label: `${chapter.chapterOrder}. ${chapter.title}`,
|
|
};
|
|
});
|
|
}
|
|
|
|
return (
|
|
<Collapse title={t('incidentsTitle')} defaultOpen={isExpanded}>
|
|
<div className="space-y-3">
|
|
{incidents && incidents.length > 0 ? (
|
|
incidents.map(function (item: Incident): React.JSX.Element {
|
|
const itemKey: string = `incident_${item.incidentId}`;
|
|
const isItemExpanded: boolean = expandedItems[itemKey];
|
|
|
|
return (
|
|
<div key={`incident-${item.incidentId}`}
|
|
className="bg-secondary rounded-xl overflow-hidden">
|
|
<button
|
|
className="flex justify-between items-center w-full p-3 text-left"
|
|
onClick={function (): void {
|
|
toggleItem(itemKey);
|
|
}}
|
|
>
|
|
<span className="font-bold text-text-primary">{item.title}</span>
|
|
<div className="flex items-center gap-1">
|
|
{isItemExpanded
|
|
? <ChevronUp className="text-primary w-3.5 h-3.5" strokeWidth={1.75}/>
|
|
: <ChevronDown className="text-primary w-3.5 h-3.5" strokeWidth={1.75}/>
|
|
}
|
|
<div onClick={function (e: React.MouseEvent): void {
|
|
e.stopPropagation();
|
|
}}>
|
|
<IconButton
|
|
icon={Trash2}
|
|
variant="danger"
|
|
size="sm"
|
|
onClick={async function (): Promise<void> {
|
|
await onDeleteIncident(actId, item.incidentId);
|
|
}}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
|
|
{isItemExpanded && (
|
|
<div className="p-3">
|
|
{item.chapters && item.chapters.length > 0 ? (
|
|
item.chapters.map(function (chapter: ActChapter): React.JSX.Element {
|
|
return (
|
|
<ActChapterItem
|
|
key={`inc-chapter-${chapter.chapterId}-${chapter.chapterInfoId}`}
|
|
chapter={chapter}
|
|
onUpdateSummary={function (chapterId: string, summary: string): void {
|
|
onUpdateChapterSummary(chapterId, summary, item.incidentId);
|
|
}}
|
|
onUnlink={function (chapterInfoId: string, chapterId: string): Promise<void> {
|
|
return onUnlinkChapter(chapterInfoId, chapterId, item.incidentId);
|
|
}}
|
|
/>
|
|
);
|
|
})
|
|
) : (
|
|
<p className="text-text-secondary text-center text-sm p-2">
|
|
{t('noLinkedChapter')}
|
|
</p>
|
|
)}
|
|
|
|
<InputField
|
|
input={
|
|
<SelectBox
|
|
defaultValue={null}
|
|
onChangeCallBack={function (e: React.ChangeEvent<HTMLSelectElement>): void {
|
|
setSelectedChapterId(e.target.value);
|
|
}}
|
|
data={mainChaptersData()}
|
|
placeholder={t('selectChapterPlaceholder')}
|
|
/>
|
|
}
|
|
addButtonCallBack={function (): Promise<void> {
|
|
return onLinkChapter(actId, selectedChapterId, item.incidentId);
|
|
}}
|
|
isAddButtonDisabled={selectedChapterId.length === 0}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
})
|
|
) : (
|
|
<p className="text-text-secondary text-center text-sm p-2">
|
|
{t('noIncidentAdded')}
|
|
</p>
|
|
)}
|
|
|
|
<InputField
|
|
input={
|
|
<TextInput
|
|
value={newIncidentTitle}
|
|
setValue={function (e: React.ChangeEvent<HTMLInputElement>): void {
|
|
setNewIncidentTitle(e.target.value);
|
|
}}
|
|
placeholder={t('newIncidentPlaceholder')}
|
|
/>
|
|
}
|
|
actionIcon={Plus}
|
|
addButtonCallBack={function (): Promise<void> {
|
|
return onAddIncident(actId);
|
|
}}
|
|
isAddButtonDisabled={newIncidentTitle.trim() === ''}
|
|
/>
|
|
</div>
|
|
</Collapse>
|
|
);
|
|
}
|