shlink-web-client/src/short-urls/helpers/hooks.ts

78 lines
3 KiB
TypeScript
Raw Normal View History

import { isEmpty, pipe } from 'ramda';
2023-02-18 13:11:01 +03:00
import { useMemo } from 'react';
import { useLocation, useNavigate, useParams } from 'react-router-dom';
2023-02-18 12:40:37 +03:00
import type { TagsFilteringMode } from '../../api/types';
2023-02-18 13:11:01 +03:00
import { orderToString, stringToOrder } from '../../utils/helpers/ordering';
import { parseQuery, stringifyQuery } from '../../utils/helpers/query';
2023-02-18 12:40:37 +03:00
import type { BooleanString } from '../../utils/utils';
import { parseOptionalBooleanToString } from '../../utils/utils';
2023-02-18 13:11:01 +03:00
import type { ShortUrlsOrder, ShortUrlsOrderableFields } from '../data';
2021-11-09 01:23:45 +03:00
interface ShortUrlsQueryCommon {
2021-11-09 01:23:45 +03:00
search?: string;
startDate?: string;
endDate?: string;
tagsMode?: TagsFilteringMode;
2021-11-09 01:23:45 +03:00
}
interface ShortUrlsQuery extends ShortUrlsQueryCommon {
orderBy?: string;
tags?: string;
excludeBots?: BooleanString;
excludeMaxVisitsReached?: BooleanString;
excludePastValidUntil?: BooleanString;
}
interface ShortUrlsFiltering extends ShortUrlsQueryCommon {
orderBy?: ShortUrlsOrder;
tags: string[];
excludeBots?: boolean;
excludeMaxVisitsReached?: boolean;
excludePastValidUntil?: boolean;
}
type ToFirstPage = (extra: Partial<ShortUrlsFiltering>) => void;
2022-02-06 22:07:18 +03:00
export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => {
const navigate = useNavigate();
const { search } = useLocation();
const { serverId = '' } = useParams<{ serverId: string }>();
2022-02-06 22:07:18 +03:00
const filtering = useMemo(
pipe(
() => parseQuery<ShortUrlsQuery>(search),
({ orderBy, tags, excludeBots, excludeMaxVisitsReached, excludePastValidUntil, ...rest }): ShortUrlsFiltering => {
const parsedOrderBy = orderBy ? stringToOrder<ShortUrlsOrderableFields>(orderBy) : undefined;
const parsedTags = tags?.split(',') ?? [];
return {
...rest,
orderBy: parsedOrderBy,
tags: parsedTags,
excludeBots: excludeBots !== undefined ? excludeBots === 'true' : undefined,
excludeMaxVisitsReached: excludeMaxVisitsReached !== undefined ? excludeMaxVisitsReached === 'true' : undefined,
excludePastValidUntil: excludePastValidUntil !== undefined ? excludePastValidUntil === 'true' : undefined,
};
},
),
[search],
);
const toFirstPageWithExtra = (extra: Partial<ShortUrlsFiltering>) => {
const merged = { ...filtering, ...extra };
const { orderBy, tags, excludeBots, excludeMaxVisitsReached, excludePastValidUntil, ...mergedFiltering } = merged;
const query: ShortUrlsQuery = {
...mergedFiltering,
orderBy: orderBy && orderToString(orderBy),
tags: tags.length > 0 ? tags.join(',') : undefined,
excludeBots: parseOptionalBooleanToString(excludeBots),
excludeMaxVisitsReached: parseOptionalBooleanToString(excludeMaxVisitsReached),
excludePastValidUntil: parseOptionalBooleanToString(excludePastValidUntil),
};
const stringifiedQuery = stringifyQuery(query);
const queryString = isEmpty(stringifiedQuery) ? '' : `?${stringifiedQuery}`;
2021-11-09 01:23:45 +03:00
navigate(`/server/${serverId}/list-short-urls/1${queryString}`);
2021-11-09 01:23:45 +03:00
};
return [filtering, toFirstPageWithExtra];
2021-11-09 01:23:45 +03:00
};