|
import { useEffect, useState } from 'react'; |
|
import { Link, matchRoutes, useLocation } from 'react-router-dom'; |
|
|
|
interface IRoute { |
|
name: string; |
|
path: string; |
|
} |
|
|
|
const routes: IRoute[] = [ |
|
{ |
|
path: '/home', |
|
name: 'Home', |
|
}, |
|
{ |
|
path: '/home/about', |
|
name: 'About', |
|
}, |
|
{ |
|
path: '/users', |
|
name: 'Users', |
|
}, |
|
{ |
|
path: '/users/:id/edit', |
|
name: 'Edit Users by Id', |
|
}, |
|
]; |
|
|
|
const Breadcrumbs = () => { |
|
const location = useLocation(); |
|
const [crumbs, setCrumbs] = useState<IRoute[]>([]); |
|
|
|
const getPaths = () => { |
|
const allRoutes = matchRoutes(routes, location); |
|
const matchedRoute = allRoutes ? allRoutes[0] : null; |
|
let breadcrumbs: IRoute[] = []; |
|
if (matchedRoute) { |
|
breadcrumbs = routes |
|
.filter((x) => matchedRoute.route.path.includes(x.path)) |
|
.map(({ path, ...rest }) => ({ |
|
path: Object.keys(matchedRoute.params).length |
|
? Object.keys(matchedRoute.params).reduce( |
|
(path, param) => path.replace(`:${param}`, matchedRoute.params[param] as string), |
|
path |
|
) |
|
: path, |
|
...rest, |
|
})); |
|
} |
|
setCrumbs(breadcrumbs); |
|
}; |
|
|
|
useEffect(() => { |
|
getPaths(); |
|
}, [location]); |
|
|
|
const goBack = () => { |
|
window.history.back(); |
|
}; |
|
|
|
return ( |
|
<div className=''> |
|
<nav aria-label='breadcrumb'> |
|
<ol className='breadcrumb'> |
|
<li className='breadcrumb-item pointer' onClick={goBack}> |
|
<span className='bi bi-arrow-left-short me-1'></span> |
|
Back |
|
</li> |
|
{crumbs.map((x: IRoute, key: number) => |
|
crumbs.length === key + 1 ? ( |
|
<li className='breadcrumb-item'>{x.name}</li> |
|
) : ( |
|
<li className='breadcrumb-item'> |
|
<Link to={x.path} className=' text-decoration-none'> |
|
{x.name} |
|
</Link> |
|
</li> |
|
) |
|
)} |
|
</ol> |
|
</nav> |
|
</div> |
|
); |
|
}; |
|
export default Breadcrumbs; |