Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
48 lines
1.5 KiB
TypeScript
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]
|
|
}
|