admin/hooks/useQueryTab.ts
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

48 lines
1.5 KiB
TypeScript

'use client'
import { useCallback } from 'react'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
interface UseQueryTabOptions<T extends string> {
/** Valid tab values, in the order they should be checked. */
values: readonly T[]
/** Falls back to this when the query param is missing or invalid; also the value that gets omitted from the URL. */
defaultValue: T
/** Query string key to read/write. Defaults to `tab`. */
param?: string
}
/**
* Keeps a tab selection in sync with the URL (`?tab=...` by default) via `router.replace`,
* so the active tab survives reloads and is shareable/bookmarkable.
*/
export const useQueryTab = <T extends string>({
values,
defaultValue,
param = 'tab',
}: UseQueryTabOptions<T>): [T, (key: React.Key) => void] => {
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()
const rawValue = searchParams.get(param)
const selectedTab = (values as readonly string[]).includes(rawValue ?? '') ? (rawValue as T) : defaultValue
const setTab = useCallback(
(key: React.Key) => {
const tab = String(key)
const params = new URLSearchParams(searchParams.toString())
if (tab === defaultValue) params.delete(param)
else params.set(param, tab)
const query = params.toString()
router.replace(query ? `${pathname}?${query}` : pathname, { scroll: false })
},
[searchParams, router, pathname, defaultValue, param]
)
return [selectedTab, setTab]
}