All checks were successful
CD / Build and push images (push) Successful in 1m59s
CI / Lint, typecheck, test (push) Successful in 1m38s
CI / Auth e2e pack (push) Successful in 1m48s
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 8s
CD / Smoke tests against Test (push) Successful in 1m10s
CD / Promote to Int (push) Successful in 9s
GET /ponds/:id/pages lists a pond's pages ordered by the pond's persisted sidebarSort setting (alpha/created; manual arrives with #45). The sidebar consumes it to show the page list with an active-page highlight, an owner-only sort switch (persists via the existing PATCH /ponds/:id), and an inline "new page" flow. The top bar gains a pond switcher; a new /p/:pondSlug route gives it somewhere to land, redirecting to the pond's first page once loaded. Sidebar collapse gains a Ctrl/Cmd+\ shortcut and a slightly refined transition. Closes #26
55 lines
1.6 KiB
TypeScript
55 lines
1.6 KiB
TypeScript
import type { PondView } from '@dorfteich/shared';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { Link } from 'react-router-dom';
|
|
|
|
import { useAuth } from '../auth/auth-context';
|
|
import { apiGet } from '../lib/api';
|
|
import { useCurrentPondRoute } from './use-pond-route';
|
|
|
|
/** Top-bar dropdown to switch between the signed-in user's ponds (issue #26). */
|
|
export function PondSwitcher(): React.JSX.Element | null {
|
|
const { t } = useTranslation();
|
|
const { user } = useAuth();
|
|
const { pondSlug } = useCurrentPondRoute();
|
|
const [open, setOpen] = useState(false);
|
|
const ponds = useQuery({
|
|
queryKey: ['ponds'],
|
|
queryFn: () => apiGet<PondView[]>('/ponds'),
|
|
enabled: Boolean(user),
|
|
});
|
|
|
|
if (!ponds.data || ponds.data.length === 0) return null;
|
|
const current = ponds.data.find((pond) => pond.slug === pondSlug);
|
|
|
|
return (
|
|
<div className="user-menu">
|
|
<button
|
|
type="button"
|
|
className="user-menu__trigger"
|
|
aria-haspopup="menu"
|
|
aria-expanded={open}
|
|
aria-label={t('layout.pondSwitcher.label')}
|
|
onClick={() => setOpen(!open)}
|
|
>
|
|
{current?.name ?? t('layout.pondSwitcher.trigger')}
|
|
</button>
|
|
{open && (
|
|
<div className="user-menu__list" role="menu">
|
|
{ponds.data.map((pond) => (
|
|
<Link
|
|
key={pond.id}
|
|
role="menuitem"
|
|
to={`/p/${pond.slug}`}
|
|
onClick={() => setOpen(false)}
|
|
>
|
|
{pond.name}
|
|
</Link>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|