Skip to content

Commit

Permalink
refactor: Move filters into log index store (#154)
Browse files Browse the repository at this point in the history
  • Loading branch information
false-spring authored Jul 7, 2024
1 parent a578afc commit 61607c3
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 102 deletions.
62 changes: 31 additions & 31 deletions src/pages/logs/Index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { FilterState } from "@/stores/useLogIndexStore";
import { useMeterSettingsStore } from "@/stores/useMeterSettingsStore";
import { Log, LogSortType, SortDirection } from "@/types";
import {
Expand Down Expand Up @@ -39,13 +40,9 @@ export const IndexPage = () => {
confirmDeleteAll,
handleSetPage,
currentPage,
setEnemyIdFilter,
setQuestIdFilter,
toggleSort,
sortType,
sortDirection,
questCompletedFilter,
setQuestCompletedFilter,
setFilters,
filters,
} = useIndex();

const { streamer_mode, show_display_names } = useMeterSettingsStore(
Expand Down Expand Up @@ -119,12 +116,9 @@ export const IndexPage = () => {
</Box>
</Group>
<Group>
<SelectableEnemy targetIds={searchResult.enemyIds} setSelectedTarget={setEnemyIdFilter} />
<SelectableQuest questIds={searchResult.questIds} setSelectedQuest={setQuestIdFilter} />
<SelectableQuestCompletion
questCompletedFilter={questCompletedFilter}
setQuestCompletionFilter={setQuestCompletedFilter}
/>
<SelectableEnemy targetIds={searchResult.enemyIds} setFilters={setFilters} filters={filters} />
<SelectableQuest questIds={searchResult.questIds} setFilters={setFilters} filters={filters} />
<SelectableQuestCompletion setFilters={setFilters} filters={filters} />
</Group>
{searchResult.logs.length === 0 && <BlankTable />}
{searchResult.logs.length > 0 && (
Expand All @@ -144,8 +138,8 @@ export const IndexPage = () => {
<Table.Th>
<SortableColumn
column="time"
sortType={sortType}
sortDirection={sortDirection}
sortType={filters.sortType}
sortDirection={filters.sortDirection}
onClick={() => toggleSort("time")}
>
{t("ui.logs.date")}
Expand All @@ -157,8 +151,8 @@ export const IndexPage = () => {
<Table.Th>
<SortableColumn
column="duration"
sortType={sortType}
sortDirection={sortDirection}
sortType={filters.sortType}
sortDirection={filters.sortDirection}
onClick={() => toggleSort("duration")}
>
{t("ui.logs.duration")}
Expand All @@ -167,8 +161,8 @@ export const IndexPage = () => {
<Table.Th>
<SortableColumn
column="quest-elapsed-time"
sortType={sortType}
sortDirection={sortDirection}
sortType={filters.sortType}
sortDirection={filters.sortDirection}
onClick={() => toggleSort("quest-elapsed-time")}
>
{t("ui.logs.quest-elapsed-time")}
Expand Down Expand Up @@ -298,10 +292,12 @@ function BlankTable() {

function SelectableEnemy({
targetIds,
setSelectedTarget,
filters,
setFilters,
}: {
targetIds: number[];
setSelectedTarget: (value: number | null) => void;
filters: FilterState;
setFilters: (filters: Partial<FilterState>) => void;
}) {
const { t } = useTranslation();
const targetOptions = useMemo(
Expand All @@ -312,7 +308,8 @@ function SelectableEnemy({
return (
<Select
data={targetOptions}
onChange={(value) => setSelectedTarget(value ? Number(value) : null)}
value={filters.filterByEnemyId?.toString() ?? null}
onChange={(value) => setFilters({ filterByEnemyId: value ? Number(value) : null })}
placeholder={t("ui.select-enemy")}
searchable
clearable
Expand All @@ -322,10 +319,12 @@ function SelectableEnemy({

function SelectableQuest({
questIds,
setSelectedQuest,
filters,
setFilters,
}: {
questIds: number[];
setSelectedQuest: (value: number | null) => void;
filters: FilterState;
setFilters: (filters: Partial<FilterState>) => void;
}) {
const { t } = useTranslation();
const questOptions = useMemo(
Expand All @@ -336,7 +335,8 @@ function SelectableQuest({
return (
<Select
data={questOptions}
onChange={(value) => setSelectedQuest(value ? Number(value) : null)}
value={filters.filterByQuestId?.toString() ?? null}
onChange={(value) => setFilters({ filterByQuestId: value ? Number(value) : null })}
placeholder={t("ui.select-quest")}
searchable
clearable
Expand All @@ -345,11 +345,11 @@ function SelectableQuest({
}

function SelectableQuestCompletion({
questCompletedFilter,
setQuestCompletionFilter,
filters,
setFilters,
}: {
questCompletedFilter: boolean | null;
setQuestCompletionFilter: (value: boolean | null) => void;
filters: FilterState;
setFilters: (filters: Partial<FilterState>) => void;
}) {
return (
<Select
Expand All @@ -358,10 +358,10 @@ function SelectableQuestCompletion({
{ value: "true", label: "Completed" },
{ value: "false", label: "Failed" },
]}
onChange={(value) => setQuestCompletionFilter(value === "null" ? null : value === "true")}
onChange={(value) => setFilters({ questCompletedFilter: value === "null" ? null : value === "true" })}
placeholder="Quest Completion"
value={questCompletedFilter === null ? "null" : questCompletedFilter ? "true" : "false"}
onClear={() => setQuestCompletionFilter(null)}
value={filters.questCompletedFilter === null ? "null" : filters.questCompletedFilter ? "true" : "false"}
onClear={() => setFilters({ questCompletedFilter: null })}
searchable
clearable
/>
Expand Down
88 changes: 18 additions & 70 deletions src/pages/logs/useIndex.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,57 @@
import { useEncounterStore } from "@/stores/useEncounterStore";
import { SearchResult, useLogIndexStore } from "@/stores/useLogIndexStore";
import { useLogIndexStore } from "@/stores/useLogIndexStore";
import { LogSortType } from "@/types";

import { Text } from "@mantine/core";
import { modals } from "@mantine/modals";
import { invoke } from "@tauri-apps/api";
import { listen } from "@tauri-apps/api/event";
import { useEffect, useState } from "react";
import { useEffect } from "react";
import { useTranslation } from "react-i18next";

export default function useIndex() {
const { t } = useTranslation();
const [filterByEnemyId, setEnemyIdFilter] = useState<number | null>(null);
const [filterByQuestId, setQuestIdFilter] = useState<number | null>(null);
const [sortDirection, setSortDirection] = useState<"asc" | "desc">("desc");
const [sortType, setSortType] = useState<LogSortType>("time");
const [questCompletedFilter, setQuestCompletedFilter] = useState<boolean | null>(null);

const {
currentPage,
setCurrentPage,
searchResult,
setSearchResult,
filters,
setFilters,
selectedLogIds,
setSelectedLogIds,
deleteSelectedLogs,
deleteAllLogs,
fetchLogs,
} = useLogIndexStore((state) => ({
currentPage: state.currentPage,
setCurrentPage: state.setCurrentPage,
searchResult: state.searchResult,
setSearchResult: state.setSearchResult,
filters: state.filters,
setFilters: state.setFilters,
selectedLogIds: state.selectedLogIds,
setSelectedLogIds: state.setSelectedLogIds,
deleteSelectedLogs: state.deleteSelectedLogs,
deleteAllLogs: state.deleteAllLogs,
fetchLogs: state.fetchLogs,
}));

const { setSelectedTargets } = useEncounterStore((state) => ({
setSelectedTargets: state.setSelectedTargets,
}));

useEffect(() => {
invoke("fetch_logs", {
page: currentPage,
filterByEnemyId,
filterByQuestId,
sortDirection,
sortType,
questCompleted: questCompletedFilter,
}).then((result) => {
setSearchResult(result as SearchResult);
});
}, [currentPage, filterByEnemyId, filterByQuestId, sortDirection, sortType, questCompletedFilter]);
fetchLogs();
}, [currentPage, filters]);

useEffect(() => {
const encounterSavedListener = listen("encounter-saved", () => {
invoke("fetch_logs", {
page: currentPage,
filterByEnemyId,
filterByQuestId,
sortDirection,
sortType,
questCompleted: questCompletedFilter,
}).then((result) => {
setSearchResult(result as SearchResult);
});
fetchLogs();
});

return () => {
encounterSavedListener.then((f) => f());
};
}, [currentPage, filterByEnemyId, filterByQuestId, sortDirection, sortType, questCompletedFilter]);
}, [currentPage, filters]);

const confirmDeleteSelected = () =>
modals.openConfirmModal({
Expand All @@ -96,42 +76,16 @@ export default function useIndex() {
const handleSetPage = (page: number) => {
setCurrentPage(page);
setSelectedLogIds([]);

invoke("fetch_logs", {
page,
filterByEnemyId,
filterByQuestId,
sortDirection,
sortType,
questCompleted: questCompletedFilter,
}).then((result) => {
setSearchResult(result as SearchResult);
});
};

const handleSetEnemyIdFilter = (enemyId: number | null) => {
setCurrentPage(1);
setEnemyIdFilter(enemyId);
};

const handleSetQuestIdFilter = (questId: number | null) => {
setCurrentPage(1);
setQuestIdFilter(questId);
};

const handleSetQuestCompletedFilter = (completed: boolean | null) => {
setCurrentPage(1);
setQuestCompletedFilter(completed);
fetchLogs();
};

const toggleSort = (newSortType: LogSortType) => {
setCurrentPage(1);

if (sortType === newSortType) {
setSortDirection(sortDirection === "asc" ? "desc" : "asc");
if (filters.sortType === newSortType) {
setFilters({ sortDirection: filters.sortDirection === "asc" ? "desc" : "asc" });
} else {
setSortType(newSortType);
setSortDirection("asc");
setFilters({ sortType: newSortType, sortDirection: "asc" });
}
};

Expand All @@ -144,14 +98,8 @@ export default function useIndex() {
confirmDeleteAll,
handleSetPage,
currentPage,
filterByEnemyId,
filterByQuestId,
setEnemyIdFilter: handleSetEnemyIdFilter,
setQuestIdFilter: handleSetQuestIdFilter,
setQuestCompletedFilter: handleSetQuestCompletedFilter,
questCompletedFilter,
filters,
setFilters,
toggleSort,
sortType,
sortDirection,
};
}
42 changes: 41 additions & 1 deletion src/stores/useLogIndexStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { invoke } from "@tauri-apps/api";
import toast from "react-hot-toast";
import { create } from "zustand";

import { Log } from "@/types";
import { Log, LogSortType, SortDirection } from "@/types";

export type SearchResult = {
logs: Log[];
Expand All @@ -25,20 +25,42 @@ const DEFAULT_SEARCH_RESULT = {
type LogIndexState = {
currentPage: number;
searchResult: SearchResult;
filters: FilterState;
selectedLogIds: number[];
setSearchResult: (result: SearchResult) => void;
setFilters: (filters: Partial<FilterState>) => void;
setCurrentPage: (page: number) => void;
setSelectedLogIds: (ids: number[]) => void;
deleteSelectedLogs: () => void;
deleteAllLogs: () => void;
fetchLogs: () => void;
};

export type FilterState = {
filterByEnemyId: number | null;
filterByQuestId: number | null;
sortDirection: SortDirection;
sortType: LogSortType;
questCompletedFilter: boolean | null;
};

const DEFAULT_FILTERS: FilterState = {
filterByEnemyId: null,
filterByQuestId: null,
sortDirection: "desc",
sortType: "time",
questCompletedFilter: null,
};

export const useLogIndexStore = create<LogIndexState>((set, get) => ({
currentPage: 1,
searchResult: DEFAULT_SEARCH_RESULT,
filters: DEFAULT_FILTERS,
selectedLogIds: [],
setCurrentPage: (page: number) => set({ currentPage: page }),
setSearchResult: (result) => set({ searchResult: result }),
setFilters: (filters: Partial<FilterState>) =>
set((state) => ({ currentPage: 1, filters: { ...state.filters, ...filters } })),
setSelectedLogIds: (ids) => set({ selectedLogIds: ids }),
deleteSelectedLogs: async () => {
const { setSearchResult, selectedLogIds: ids } = get();
Expand Down Expand Up @@ -66,4 +88,22 @@ export const useLogIndexStore = create<LogIndexState>((set, get) => ({
toast.error(`Failed to delete logs: ${e}`);
}
},
fetchLogs: async () => {
const { currentPage, filters, setSearchResult } = get();

try {
const result = await invoke("fetch_logs", {
page: currentPage,
filterByEnemyId: filters.filterByEnemyId,
filterByQuestId: filters.filterByQuestId,
sortDirection: filters.sortDirection,
sortType: filters.sortType,
questCompleted: filters.questCompletedFilter,
});

setSearchResult(result as SearchResult);
} catch (e) {
toast.error(`Failed to fetch logs: ${e}`);
}
},
}));

0 comments on commit 61607c3

Please sign in to comment.