memos/web/src/hooks/useMemoSorting.ts

53 lines
1.9 KiB
TypeScript

import { timestampDate } from "@bufbuild/protobuf/wkt";
import dayjs from "dayjs";
import { useMemo } from "react";
import { type MemoTimeBasis, useView } from "@/contexts/ViewContext";
import { State } from "@/types/proto/api/v1/common_pb";
import type { Memo } from "@/types/proto/api/v1/memo_service_pb";
export interface UseMemoSortingOptions {
pinnedFirst?: boolean;
state?: State;
}
export interface UseMemoSortingResult {
listSort: (memos: Memo[]) => Memo[];
orderBy: string;
}
const getMemoSortTime = (memo: Memo, timeBasis: MemoTimeBasis): Date | undefined => {
const timestamp = timeBasis === "update_time" ? memo.updateTime : memo.createTime;
return timestamp ? timestampDate(timestamp) : undefined;
};
export const useMemoSorting = (options: UseMemoSortingOptions = {}): UseMemoSortingResult => {
const { pinnedFirst = false, state = State.NORMAL } = options;
const { orderByTimeAsc, timeBasis } = useView();
// Generate orderBy string for API
const orderBy = useMemo(() => {
const timeOrder = orderByTimeAsc ? `${timeBasis} asc` : `${timeBasis} desc`;
return pinnedFirst ? `pinned desc, ${timeOrder}` : timeOrder;
}, [pinnedFirst, orderByTimeAsc, timeBasis]);
// Generate listSort function for client-side sorting
const listSort = useMemo(() => {
return (memos: Memo[]): Memo[] => {
return memos
.filter((memo) => memo.state === state)
.sort((a, b) => {
// First, sort by pinned status if enabled
if (pinnedFirst && a.pinned !== b.pinned) {
return b.pinned ? 1 : -1;
}
// Then sort by the selected time field.
const aTime = getMemoSortTime(a, timeBasis);
const bTime = getMemoSortTime(b, timeBasis);
return orderByTimeAsc ? dayjs(aTime).unix() - dayjs(bTime).unix() : dayjs(bTime).unix() - dayjs(aTime).unix();
});
};
}, [pinnedFirst, state, orderByTimeAsc, timeBasis]);
return { listSort, orderBy };
};