import { useCallback, useEffect, useState } from 'react';
import { AppMode, DocType } from '../types';
interface UrlState {
mode: AppMode;
type: DocType;
offset: number;
query: string;
}
export function useUrlState() {
const [state, setState] = useState<UrlState>(() => parseUrl());
// Parse URL on mount and popstate
useEffect(() => {
const handlePopState = () => {
setState(parseUrl());
};
window.addEventListener('popstate', handlePopState);
return () => window.removeEventListener('popstate', handlePopState);
}, []);
// Update URL when state changes
const updateUrl = useCallback((updates: Partial<UrlState>) => {
const newState = { ...state, ...updates };
setState(newState);
const params = new URLSearchParams();
params.set('mode', newState.mode);
params.set('type', newState.type);
if (newState.offset > 0) params.set('offset', String(newState.offset));
if (newState.query) params.set('q', newState.query);
const hash = newState.mode === 'graph' ? '#graph' : '';
const url = `?${params.toString()}${hash}`;
window.history.replaceState({}, '', url);
}, [state]);
return {
...state,
updateUrl,
setMode: (mode: AppMode) => updateUrl({ mode, offset: 0 }),
setType: (type: DocType) => updateUrl({ type, offset: 0 }),
setOffset: (offset: number) => updateUrl({ offset }),
setQuery: (query: string) => updateUrl({ query }),
};
}
function parseUrl(): UrlState {
const params = new URLSearchParams(window.location.search);
const hash = window.location.hash;
let mode: AppMode = 'browse';
const modeParam = params.get('mode');
if (modeParam === 'search' || modeParam === 'browse' || modeParam === 'consult' || modeParam === 'reflect' || modeParam === 'graph') {
mode = modeParam;
}
if (hash === '#graph') {
mode = 'graph';
}
let type: DocType = 'all';
const typeParam = params.get('type');
if (typeParam === 'all' || typeParam === 'principle' || typeParam === 'learning' || typeParam === 'retro') {
type = typeParam;
}
const offset = parseInt(params.get('offset') || '0') || 0;
const query = params.get('q') || '';
return { mode, type, offset, query };
}