Skip to content

Commit

Permalink
fix: some search params is not preserved on search (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
kohii committed Mar 10, 2024
1 parent 674f947 commit 2727ecc
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 47 deletions.
8 changes: 4 additions & 4 deletions src/app/s/search-result.tsx
Expand Up @@ -20,10 +20,10 @@ import { parseQuery } from "@/features/search/parse-query";
import { SearchBar, SearchBarHandle } from "@/features/search/search-bar";
import { getField } from "@/features/shinryoukoui-master-fields/shinryoukoui-master-fields";
import { VersionSelect } from "@/features/shinryoukoui-master-versions/version-select";
import { useShinryoukouiSearch } from "@/hooks/use-shinryoukoui-search";
import { useShinryoukouiSearchByQuery } from "@/hooks/use-shinryoukoui-search";
import { useStateFromProp } from "@/hooks/use-state-from-props";
import { useUpdateSearchParams } from "@/hooks/use-update-search-params";

import { SEARCH_PARAM_NAMES } from "@/search-param-names";

import { Detail } from "./detail";
import { useTableColumns } from "./use-table-columns";
Expand All @@ -33,7 +33,7 @@ const nameField = getField("診療行為省略名称/省略漢字名称");

export default function SearchResult() {
const searchParams = useSearchParams();
const query = searchParams.get("q") ?? "";
const query = searchParams.get(SEARCH_PARAM_NAMES.SEARCH.QUERY) ?? "";
const selectedCode = searchParams.get("code");

const updateSearchParams = useUpdateSearchParams();
Expand All @@ -53,7 +53,7 @@ export default function SearchResult() {
const [searchInputValue, setSearchInputValue] = useStateFromProp(query ?? "");

const [advancedSearchOpen, setAdvancedSearchOpen] = useState(false);
const search = useShinryoukouiSearch();
const search = useShinryoukouiSearchByQuery();

const filterExpression = useMemo(() => {
const r = parseQuery(query);
Expand Down
7 changes: 4 additions & 3 deletions src/contexts/shinryoukoui-master-data-context.tsx
Expand Up @@ -5,8 +5,9 @@ import React, { createContext, useContext, useMemo } from "react";
import { fetchMasterData } from "@/apis/fetch-master-data";
import { getValue } from "@/features/fields/get-values";
import { getField } from "@/features/shinryoukoui-master-fields/shinryoukoui-master-fields";
import { LATEST_SHINRYOUKOUI_MASTER_VERSION, MASTER_VERSION_SEARCH_PARAM_NAME, SHINRYOUKOUI_MASTER_VERSION_KEYS } from "@/features/shinryoukoui-master-versions/constants";
import { LATEST_SHINRYOUKOUI_MASTER_VERSION, SHINRYOUKOUI_MASTER_VERSION_KEYS } from "@/features/shinryoukoui-master-versions/constants";
import { useUpdateSearchParams } from "@/hooks/use-update-search-params";
import { SEARCH_PARAM_NAMES } from "@/search-param-names";

type ShinryoukouiMasterDataContextType = {
version: string;
Expand All @@ -33,7 +34,7 @@ export function useShinryoukouiMasterData() {
export function ShinryoukouiMasterDataProvider({ children }: { children: React.ReactNode }) {
const searchParams = useSearchParams();
const updateSearchParams = useUpdateSearchParams();
const paramVersion = searchParams.get(MASTER_VERSION_SEARCH_PARAM_NAME);
const paramVersion = searchParams.get(SEARCH_PARAM_NAMES.SEARCH.MASTER_VERSION);
const version = paramVersion && SHINRYOUKOUI_MASTER_VERSION_KEYS.includes(paramVersion) ?
paramVersion :
LATEST_SHINRYOUKOUI_MASTER_VERSION;
Expand All @@ -59,7 +60,7 @@ export function ShinryoukouiMasterDataProvider({ children }: { children: React.R
return {
version,
setVersion(version: string) {
updateSearchParams({ [MASTER_VERSION_SEARCH_PARAM_NAME]: version === LATEST_SHINRYOUKOUI_MASTER_VERSION ? undefined : version });
updateSearchParams({ [SEARCH_PARAM_NAMES.SEARCH.MASTER_VERSION]: version === LATEST_SHINRYOUKOUI_MASTER_VERSION ? undefined : version });
},
data: data ?? [],
isLoading,
Expand Down
4 changes: 2 additions & 2 deletions src/features/advanced-search/advanced-search-button.tsx
Expand Up @@ -4,7 +4,7 @@ import dynamic from "next/dynamic";
import { useState } from "react";

import { Backdrop } from "@/components/backdrop";
import { useShinryoukouiSearch } from "@/hooks/use-shinryoukoui-search";
import { useShinryoukouiSearchByQuery } from "@/hooks/use-shinryoukoui-search";

type AdvancedSearchLinkProps = {
initialQuery?: string;
Expand All @@ -17,7 +17,7 @@ export function AdvancedSearchButton({ initialQuery }: AdvancedSearchLinkProps)
setAdvancedSearchOpen(true);
};

const search = useShinryoukouiSearch();
const search = useShinryoukouiSearchByQuery();

return (
<>
Expand Down
27 changes: 9 additions & 18 deletions src/features/display-fields/display-fields-modal.tsx
@@ -1,8 +1,8 @@
import { useRouter } from "next/navigation";
import { useCallback, useState } from "react";

import { Button } from "@/components/button";
import { Modal } from "@/components/modal";
import { useUpdateSearchParams } from "@/hooks/use-update-search-params";
import { SEARCH_PARAM_NAMES } from "@/search-param-names";

import { DEFAULT_DISPLAY_FIELDS } from "./constants";
Expand All @@ -15,6 +15,8 @@ type DisplayFieldsModalProps = {
onClose: () => void;
}

const DEFAULT_DISPLAY_FIELDS_STRING = stringifyDisplayFieldConfigs(DEFAULT_DISPLAY_FIELDS);

export function DisplayFieldsModal({
fields: initialFields,
onClose,
Expand All @@ -24,26 +26,15 @@ export function DisplayFieldsModal({
id: crypto.randomUUID(),
})));

const { push } = useRouter();

const updateSearchParams = useUpdateSearchParams();
const handleOk = useCallback(() => {
const searchParams = new URLSearchParams(location.search);
if (fields.length === 0) {
searchParams.delete(SEARCH_PARAM_NAMES.FIELDS);
} else {
const s = stringifyDisplayFieldConfigs(fields);
const defaults = stringifyDisplayFieldConfigs(DEFAULT_DISPLAY_FIELDS);
if (s === defaults) {
searchParams.delete(SEARCH_PARAM_NAMES.FIELDS);
} else {
searchParams.set(SEARCH_PARAM_NAMES.FIELDS, s);
}
}

push(`/s?${searchParams.toString()}`);
const s = stringifyDisplayFieldConfigs(fields);
updateSearchParams({
[SEARCH_PARAM_NAMES.SEARCH.FIELDS]: (!s || s === DEFAULT_DISPLAY_FIELDS_STRING) ? undefined : s,
});

onClose();
}, [fields, onClose, push]);
}, [fields, onClose, updateSearchParams]);

const handleReset = () => {
setFields(DEFAULT_DISPLAY_FIELDS.map((field) => ({
Expand Down
2 changes: 1 addition & 1 deletion src/features/display-fields/use-display-fields.ts
Expand Up @@ -9,7 +9,7 @@ import { DisplayFieldConfig } from "./types";

export function useDisplayFieldConfigs(): DisplayFieldConfig[] {
const searchParams = useSearchParams();
const fields = searchParams.get(SEARCH_PARAM_NAMES.FIELDS);
const fields = searchParams.get(SEARCH_PARAM_NAMES.SEARCH.FIELDS);
return useMemo(() => {
if (!fields) return DEFAULT_DISPLAY_FIELDS;
const fieldConfigs = parseDisplayFieldConfigs(fields);
Expand Down
4 changes: 2 additions & 2 deletions src/features/search/search-bar.tsx
Expand Up @@ -4,7 +4,7 @@ import { forwardRef } from "react";

import { Button } from "@/components/button";
import { SearchIcon } from "@/components/icons/search-icon";
import { useShinryoukouiSearch } from "@/hooks/use-shinryoukoui-search";
import { useShinryoukouiSearchByQuery } from "@/hooks/use-shinryoukoui-search";

import { SearchInput } from "./search-input";

Expand All @@ -20,7 +20,7 @@ export type SearchBarHandle = {
export const SearchBar = forwardRef<SearchBarHandle, SearchBarProps>(function SearchBar(
{ value, onChange }, ref
) {
const search = useShinryoukouiSearch();
const search = useShinryoukouiSearchByQuery();
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
search(event.currentTarget.q.value);
Expand Down
4 changes: 3 additions & 1 deletion src/features/search/search-input.tsx
Expand Up @@ -4,6 +4,8 @@ import { forwardRef } from "react";
import { experimental_RichInput as RichInput, RichInputHandle, createRegexRenderer } from "rich-textarea";
import { twMerge } from "tailwind-merge";

import { SEARCH_PARAM_NAMES } from "@/search-param-names";

import { shinryokouiMasterFields } from "../shinryoukoui-master-fields/shinryoukoui-master-fields";

const FIELD_NAMES = shinryokouiMasterFields.map((f) => f.name);
Expand Down Expand Up @@ -33,7 +35,7 @@ export const SearchInput = forwardRef<RichInputHandle, SearchInputProps>(functio
<>
<RichInput
ref={ref}
name="q"
name={SEARCH_PARAM_NAMES.SEARCH.QUERY}
autoFocus
placeholder="診療行為を検索"
style={{
Expand Down
2 changes: 0 additions & 2 deletions src/features/shinryoukoui-master-versions/constants.ts
Expand Up @@ -9,5 +9,3 @@ export const SHINRYOUKOUI_MASTER_VERSION_LIST = versions.map(v => ({
key: v,
label: `${+v.slice(0, 4)}${+v.slice(4, 6)}${+v.slice(6, 8)}日`
}));

export const MASTER_VERSION_SEARCH_PARAM_NAME = "v";
49 changes: 37 additions & 12 deletions src/hooks/use-shinryoukoui-search.tsx
@@ -1,23 +1,48 @@
import { useRouter } from "next/navigation";
import { useCallback } from "react";

import { MASTER_VERSION_SEARCH_PARAM_NAME, SHINRYOUKOUI_MASTER_VERSION_KEYS } from "@/features/shinryoukoui-master-versions/constants";
import { SEARCH_PARAM_NAMES } from "@/search-param-names";

export type SearchParamNames = typeof SEARCH_PARAM_NAMES["SEARCH"][keyof typeof SEARCH_PARAM_NAMES["SEARCH"]];

type Options = {
preserveExtraSearchParams: boolean
}

export function useShinryoukouiSearch() {
export function useShinryoukouiSearch({
preserveExtraSearchParams,
}: Options) {
const { push } = useRouter();

return useCallback((query: string) => {
const currentSearchParams = new URLSearchParams(location.search);
const masterVersion = currentSearchParams.get(MASTER_VERSION_SEARCH_PARAM_NAME);
return useCallback((params: {
[key in SearchParamNames]?: string | undefined
}) => {
const currentSearchParams = new URLSearchParams(window.location.search);
const searchParams = new URLSearchParams();
if (query) {
searchParams.set("q", query);
}
if (masterVersion && SHINRYOUKOUI_MASTER_VERSION_KEYS.includes(masterVersion)) {
searchParams.set(MASTER_VERSION_SEARCH_PARAM_NAME, masterVersion);
}

const searchParamNames = Object.values(SEARCH_PARAM_NAMES.SEARCH);
currentSearchParams.forEach((value, key) => {
if (preserveExtraSearchParams || searchParamNames.includes(key as SearchParamNames)) {
searchParams.set(key, value);
}
});

Object.entries(params).forEach(([key, value]) => {
if (value) {
searchParams.set(key, value);
} else {
searchParams.delete(key);
}
});
push(`/s?${searchParams.toString()}`);
}, [push]);
}, [preserveExtraSearchParams, push]);
}

export function useShinryoukouiSearchByQuery() {
const search = useShinryoukouiSearch({preserveExtraSearchParams: false});
return useCallback((q: string) => {
search({
q,
});
}, [search]);
}
8 changes: 6 additions & 2 deletions src/search-param-names.ts
@@ -1,3 +1,7 @@
export const SEARCH_PARAM_NAMES = {
FIELDS: "fields",
};
SEARCH: {
QUERY: "q",
MASTER_VERSION: "v",
FIELDS: "fields",
}
} as const;

0 comments on commit 2727ecc

Please sign in to comment.