"use client"; import { useMemo } from "react"; import EntriesList from "@/features/entries/components/entries-list"; import EntriesPanelHeader from "@/features/entries/components/entries-panel-header"; import EntriesPanelModals from "@/features/entries/components/entries-panel-modals"; import SchedulesList from "@/features/entries/components/schedules-list"; import useEntriesPanelCrud from "@/features/entries/components/use-entries-panel-crud"; import useEntriesPanelFilters from "@/features/entries/components/use-entries-panel-filters"; import useEntries from "@/features/entries/hooks/use-entries"; import useSchedules from "@/features/entries/hooks/use-schedules"; import useGroupSettings from "@/features/groups/hooks/use-group-settings"; import useTags from "@/features/tags/hooks/use-tags"; import { useEntryMutation } from "@/hooks/entry-mutation-context"; import { useGroupsContext } from "@/hooks/groups-context"; import { useNotificationsContext } from "@/hooks/notifications-context"; import useUserSettings from "@/hooks/use-user-settings"; type ListProgressSignalProps = { hasMore: boolean; shownCount: number; totalCount: number; noun: "entries" | "schedules"; }; function ListProgressSignal({ hasMore, shownCount, totalCount, noun }: ListProgressSignalProps) { if (totalCount <= 0) return null; return (
{hasMore ? "\u21e3" : "\u2713"} {hasMore ? `Keep scrolling for more ${noun} (${shownCount} of ${totalCount})` : `You have reached the end of ${noun} (${totalCount} total)`}
); } export default function EntriesPanel() { const { groups, activeGroupId } = useGroupsContext(); const { entries, loading: entriesLoading, error: entriesError, createEntry, updateEntry, deleteEntry } = useEntries(activeGroupId); const { schedules, loading: schedulesLoading, error: schedulesError, createSchedule, updateSchedule, deleteSchedule } = useSchedules(activeGroupId); const { settings: userSettings } = useUserSettings(); const { notify } = useNotificationsContext(); const { notifyEntryMutation } = useEntryMutation(); const { tags: tagSuggestions } = useTags(activeGroupId); const { settings: groupSettings } = useGroupSettings(activeGroupId); const activeGroup = groups.find(group => group.id === activeGroupId) || null; const canManageTags = Boolean(activeGroup && (activeGroup.role !== "MEMBER" || groupSettings.allowMemberTagManage)); const emptyTagActionLabel = canManageTags ? "No Tags Assigned Yet - Click To Assign Tags" : "No Tags Assigned Yet - Contact Your Group Admin"; const pageSize = Math.max(1, Number(userSettings.entryPanelPageSize || 10)); const { entryTab, setEntryTab, filters, setFilters, filterOpen, setFilterOpen, activeFilterCount, filteredEntries, filteredSchedules, visibleEntries, visibleSchedules, hasMoreEntries, hasMoreSchedules, entriesLoadSentinelRef, schedulesLoadSentinelRef, clearFilters, onFilterAddTag, onFilterToggleTag } = useEntriesPanelFilters({ entries, schedules, pageSize }); const { newEntryOpen, setNewEntryOpen, newScheduleOpen, setNewScheduleOpen, entryDetailsOpen, setEntryDetailsOpen, scheduleDetailsOpen, setScheduleDetailsOpen, confirmDeleteOpen, setConfirmDeleteOpen, deleteTarget, setDeleteTarget, selectedEntryIndex, entryRemovedTags, setEntryRemovedTags, scheduleRemovedTags, setScheduleRemovedTags, entryForm, setEntryForm, entryDetailsForm, setEntryDetailsForm, entryDetailsOriginal, scheduleForm, setScheduleForm, scheduleDetailsForm, setScheduleDetailsForm, scheduleDetailsOriginal, amountInputRef, tagsInputRef, handleEmptyTagAction, hasEntryChanges, hasScheduleChanges, submitNewEntry, submitNewSchedule, openEntryDetails, openScheduleDetails, submitEntryUpdate, submitScheduleUpdate, confirmDelete, prevEntry, nextEntry } = useEntriesPanelCrud({ filteredEntries, schedules, createEntry, updateEntry, deleteEntry, createSchedule, updateSchedule, deleteSchedule, notify, notifyEntryMutation, canManageTags }); const listCounts = useMemo(() => { return { entriesShown: visibleEntries.length, entriesTotal: filteredEntries.length, schedulesShown: visibleSchedules.length, schedulesTotal: filteredSchedules.length }; }, [filteredEntries.length, filteredSchedules.length, visibleEntries.length, visibleSchedules.length]); return ( <>
setFilterOpen(true)} onOpenCreate={() => { if (entryTab === "ENTRIES") { setNewEntryOpen(true); return; } setNewScheduleOpen(true); }} /> {entryTab === "ENTRIES" ? ( <> openEntryDetails(entry.id)} onClearFilters={clearFilters} /> ); }