201 lines
9.7 KiB
TypeScript
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();
|
|
}}
|
|
/>
|
|
</>
|
|
);
|
|
}
|