fiddy/apps/web/features/entries/components/entries-panel-modals.tsx

201 lines
9.7 KiB
TypeScript

"use client";
import type { Dispatch, FormEvent, MutableRefObject, SetStateAction } from "react";
import EntryDetailsModal from "@/features/entries/components/entry-details-modal";
import EntriesFilterModal, { type EntriesFilters } from "@/features/entries/components/entries-filter-modal";
import NewEntryModal from "@/features/entries/components/new-entry-modal";
import NewScheduleModal from "@/features/entries/components/new-schedule-modal";
import ScheduleDetailsModal from "@/features/entries/components/schedule-details-modal";
import type {
DeleteTarget,
EntryDetailsFormState,
EntryFormState,
ScheduleDetailsFormState,
ScheduleFormState
} from "@/features/entries/components/entries-panel.types";
import ConfirmSlideModal from "@/shared/components/modals/confirm-slide-modal";
type EntriesPanelModalsProps = {
activeGroupId: number | null;
entriesError: string;
schedulesError: string;
tagSuggestions: string[];
canManageTags: boolean;
emptyTagActionLabel: string;
handleEmptyTagAction: () => void;
filterOpen: boolean;
setFilterOpen: Dispatch<SetStateAction<boolean>>;
filters: EntriesFilters;
setFilters: Dispatch<SetStateAction<EntriesFilters>>;
activeFilterCount: number;
clearFilters: () => void;
onFilterAddTag: (tag: string) => void;
onFilterToggleTag: (tag: string) => void;
newEntryOpen: boolean;
setNewEntryOpen: Dispatch<SetStateAction<boolean>>;
entryForm: EntryFormState;
setEntryForm: Dispatch<SetStateAction<EntryFormState>>;
submitNewEntry: (event: FormEvent<HTMLFormElement>) => Promise<void>;
amountInputRef: MutableRefObject<HTMLInputElement | null>;
tagsInputRef: MutableRefObject<HTMLInputElement | null>;
newScheduleOpen: boolean;
setNewScheduleOpen: Dispatch<SetStateAction<boolean>>;
scheduleForm: ScheduleFormState;
setScheduleForm: Dispatch<SetStateAction<ScheduleFormState>>;
submitNewSchedule: (event: FormEvent<HTMLFormElement>) => Promise<void>;
entryDetailsOpen: boolean;
setEntryDetailsOpen: Dispatch<SetStateAction<boolean>>;
entryDetailsForm: EntryDetailsFormState;
setEntryDetailsForm: Dispatch<SetStateAction<EntryDetailsFormState>>;
entryDetailsOriginal: EntryDetailsFormState | null;
hasEntryChanges: () => boolean;
submitEntryUpdate: (event: FormEvent<HTMLFormElement>) => Promise<void>;
entryRemovedTags: string[];
setEntryRemovedTags: Dispatch<SetStateAction<string[]>>;
prevEntry: () => void;
nextEntry: () => void;
selectedEntryIndex: number | null;
filteredEntriesCount: number;
scheduleDetailsOpen: boolean;
setScheduleDetailsOpen: Dispatch<SetStateAction<boolean>>;
scheduleDetailsForm: ScheduleDetailsFormState;
setScheduleDetailsForm: Dispatch<SetStateAction<ScheduleDetailsFormState>>;
scheduleDetailsOriginal: ScheduleDetailsFormState | null;
hasScheduleChanges: () => boolean;
submitScheduleUpdate: (event: FormEvent<HTMLFormElement>) => Promise<void>;
scheduleRemovedTags: string[];
setScheduleRemovedTags: Dispatch<SetStateAction<string[]>>;
confirmDeleteOpen: boolean;
setConfirmDeleteOpen: Dispatch<SetStateAction<boolean>>;
deleteTarget: DeleteTarget;
setDeleteTarget: Dispatch<SetStateAction<DeleteTarget>>;
confirmDelete: () => Promise<void>;
};
export default function EntriesPanelModals(props: EntriesPanelModalsProps) {
return (
<>
<NewEntryModal
isOpen={props.newEntryOpen && Boolean(props.activeGroupId)}
form={props.entryForm}
error={props.entriesError}
onClose={() => props.setNewEntryOpen(false)}
onSubmit={props.submitNewEntry}
onChange={next => props.setEntryForm(prev => ({ ...prev, ...next }))}
tagSuggestions={props.tagSuggestions}
emptyTagActionLabel={props.emptyTagActionLabel}
emptyTagActionDisabled={!props.canManageTags}
onEmptyTagAction={props.handleEmptyTagAction}
amountInputRef={props.amountInputRef}
tagsInputRef={props.tagsInputRef}
/>
<NewScheduleModal
isOpen={props.newScheduleOpen && Boolean(props.activeGroupId)}
form={props.scheduleForm}
error={props.schedulesError}
onClose={() => props.setNewScheduleOpen(false)}
onSubmit={props.submitNewSchedule}
onChange={next => props.setScheduleForm(prev => ({ ...prev, ...next }))}
tagSuggestions={props.tagSuggestions}
emptyTagActionLabel={props.emptyTagActionLabel}
emptyTagActionDisabled={!props.canManageTags}
onEmptyTagAction={props.handleEmptyTagAction}
/>
<EntryDetailsModal
isOpen={props.entryDetailsOpen}
form={props.entryDetailsForm}
originalForm={props.entryDetailsOriginal}
isDirty={props.hasEntryChanges()}
error={props.entriesError}
onClose={() => props.setEntryDetailsOpen(false)}
onSubmit={props.submitEntryUpdate}
onRequestDelete={() => {
props.setDeleteTarget("ENTRY");
props.setConfirmDeleteOpen(true);
}}
onRevert={() => {
if (!props.entryDetailsOriginal) return;
props.setEntryDetailsForm(props.entryDetailsOriginal);
props.setEntryRemovedTags([]);
}}
onChange={next => props.setEntryDetailsForm(prev => ({ ...prev, ...next }))}
onAddTag={tag => {
props.setEntryDetailsForm(prev => ({ ...prev, tags: prev.tags.includes(tag) ? prev.tags : [...prev.tags, tag] }));
props.setEntryRemovedTags(prev => prev.filter(item => item !== tag));
}}
onToggleTag={tag => props.setEntryRemovedTags(prev => (prev.includes(tag) ? prev.filter(item => item !== tag) : [...prev, tag]))}
removedTags={props.entryRemovedTags}
tagSuggestions={props.tagSuggestions}
emptyTagActionLabel={props.emptyTagActionLabel}
emptyTagActionDisabled={!props.canManageTags}
onEmptyTagAction={props.handleEmptyTagAction}
onPrev={props.prevEntry}
onNext={props.nextEntry}
loopHintPrev={props.selectedEntryIndex === 0 && props.filteredEntriesCount > 1 ? "Loop" : ""}
loopHintNext={props.selectedEntryIndex === props.filteredEntriesCount - 1 && props.filteredEntriesCount > 1 ? "Loop" : ""}
canNavigate={props.filteredEntriesCount > 1}
/>
<ScheduleDetailsModal
isOpen={props.scheduleDetailsOpen}
form={props.scheduleDetailsForm}
originalForm={props.scheduleDetailsOriginal}
isDirty={props.hasScheduleChanges()}
error={props.schedulesError}
onClose={() => props.setScheduleDetailsOpen(false)}
onSubmit={props.submitScheduleUpdate}
onRequestDelete={() => {
props.setDeleteTarget("SCHEDULE");
props.setConfirmDeleteOpen(true);
}}
onRevert={() => {
if (!props.scheduleDetailsOriginal) return;
props.setScheduleDetailsForm(props.scheduleDetailsOriginal);
props.setScheduleRemovedTags([]);
}}
onChange={next => props.setScheduleDetailsForm(prev => ({ ...prev, ...next }))}
onAddTag={tag => {
props.setScheduleDetailsForm(prev => ({ ...prev, tags: prev.tags.includes(tag) ? prev.tags : [...prev.tags, tag] }));
props.setScheduleRemovedTags(prev => prev.filter(item => item !== tag));
}}
onToggleTag={tag => props.setScheduleRemovedTags(prev => (prev.includes(tag) ? prev.filter(item => item !== tag) : [...prev, tag]))}
removedTags={props.scheduleRemovedTags}
tagSuggestions={props.tagSuggestions}
emptyTagActionLabel={props.emptyTagActionLabel}
emptyTagActionDisabled={!props.canManageTags}
onEmptyTagAction={props.handleEmptyTagAction}
/>
<EntriesFilterModal
isOpen={props.filterOpen}
filters={props.filters}
setFilters={props.setFilters}
activeFilterCount={props.activeFilterCount}
tagSuggestions={props.tagSuggestions}
canManageTags={props.canManageTags}
emptyTagActionLabel={props.emptyTagActionLabel}
onEmptyTagAction={props.handleEmptyTagAction}
onClearFilters={props.clearFilters}
onFilterAddTag={props.onFilterAddTag}
onFilterToggleTag={props.onFilterToggleTag}
onClose={() => props.setFilterOpen(false)}
/>
<ConfirmSlideModal
isOpen={props.confirmDeleteOpen}
title={props.deleteTarget === "ENTRY" ? "Delete entry" : "Delete schedule"}
description={props.deleteTarget === "ENTRY" ? "This will permanently remove the entry and its tags." : "This will permanently remove the schedule and its tags."}
confirmLabel={props.deleteTarget === "ENTRY" ? "Delete entry" : "Delete schedule"}
onClose={() => props.setConfirmDeleteOpen(false)}
onConfirm={() => {
props.setConfirmDeleteOpen(false);
props.confirmDelete();
}}
/>
</>
);
}