diff --git a/client/src/api/client.ts b/client/src/api/client.ts index 791c2a5e..6d981112 100644 --- a/client/src/api/client.ts +++ b/client/src/api/client.ts @@ -322,6 +322,9 @@ export const journeyApi = { updateContributor: (id: number, userId: number, role: string) => apiClient.patch(`/journeys/${id}/contributors/${userId}`, { role }).then(r => r.data), removeContributor: (id: number, userId: number) => apiClient.delete(`/journeys/${id}/contributors/${userId}`).then(r => r.data), + // Preferences + updatePreferences: (id: number, data: { hide_skeletons?: boolean }) => apiClient.patch(`/journeys/${id}/preferences`, data).then(r => r.data), + // Share getShareLink: (id: number) => apiClient.get(`/journeys/${id}/share-link`).then(r => r.data), createShareLink: (id: number, perms: { share_timeline?: boolean; share_gallery?: boolean; share_map?: boolean }) => apiClient.post(`/journeys/${id}/share-link`, perms).then(r => r.data), diff --git a/client/src/components/Admin/AddonManager.test.tsx b/client/src/components/Admin/AddonManager.test.tsx index 51054bef..206f063d 100644 --- a/client/src/components/Admin/AddonManager.test.tsx +++ b/client/src/components/Admin/AddonManager.test.tsx @@ -190,11 +190,12 @@ describe('AddonManager', () => { expect(screen.queryByText('Bag Tracking')).not.toBeInTheDocument(); }); - it('FE-ADMIN-ADDON-010: photo provider sub-toggles shown for Memories addon', async () => { + it('FE-ADMIN-ADDON-010: photo provider sub-toggles shown under Journey addon', async () => { server.use( http.get('/api/admin/addons', () => HttpResponse.json({ addons: [ + buildAddon({ id: 'journey', name: 'Journey', type: 'global', icon: 'Compass', enabled: true }), buildAddon({ id: 'photos', name: 'Memories', type: 'trip', icon: 'Image', enabled: false }), buildAddon({ id: 'unsplash', name: 'Unsplash', type: 'photo_provider', enabled: true }), buildAddon({ id: 'pexels', name: 'Pexels', type: 'photo_provider', enabled: false }), @@ -204,18 +205,16 @@ describe('AddonManager', () => { ); render(); - // Provider sub-rows are visible + // Provider sub-rows are visible under Journey addon await screen.findByText('Unsplash'); expect(screen.getByText('Pexels')).toBeInTheDocument(); - // Memories row shows name override - expect(screen.getByText('Memories providers')).toBeInTheDocument(); + // Journey addon is rendered + expect(screen.getByText('Journey')).toBeInTheDocument(); - // The photos addon row itself has no top-level toggle (hideToggle = true) - // The toggle buttons are only for the providers + // Toggle buttons: journey toggle + 2 provider toggles const toggleBtns = screen.getAllByRole('button').filter(b => b.classList.contains('rounded-full')); - // Should be 2 provider toggles (no main toggle for the photos addon) - expect(toggleBtns.length).toBe(2); + expect(toggleBtns.length).toBe(3); }); it('FE-ADMIN-ADDON-011: icon falls back to Puzzle when icon name unknown', async () => { diff --git a/client/src/components/Admin/AddonManager.tsx b/client/src/components/Admin/AddonManager.tsx index 5d9f7887..8a564381 100644 --- a/client/src/components/Admin/AddonManager.tsx +++ b/client/src/components/Admin/AddonManager.tsx @@ -4,10 +4,10 @@ import { useTranslation } from '../../i18n' import { useSettingsStore } from '../../store/settingsStore' import { useAddonStore } from '../../store/addonStore' import { useToast } from '../shared/Toast' -import { Puzzle, ListChecks, Wallet, FileText, CalendarDays, Globe, Briefcase, Image, Terminal, Link2, Compass } from 'lucide-react' +import { Puzzle, ListChecks, Wallet, FileText, CalendarDays, Globe, Briefcase, Image, Terminal, Link2, Compass, BookOpen } from 'lucide-react' const ICON_MAP = { - ListChecks, Wallet, FileText, CalendarDays, Puzzle, Globe, Briefcase, Image, Terminal, Link2, Compass, + ListChecks, Wallet, FileText, CalendarDays, Puzzle, Globe, Briefcase, Image, Terminal, Link2, Compass, BookOpen, } interface Addon { @@ -103,11 +103,11 @@ export default function AddonManager({ bagTrackingEnabled, onToggleBagTracking } } } - const tripAddons = addons.filter(a => a.type === 'trip') - const globalAddons = addons.filter(a => a.type === 'global') const photoProviderAddons = addons.filter(isPhotoProviderAddon) + const photosAddon = addons.filter(a => a.type === 'trip').find(isPhotosAddon) + const tripAddons = addons.filter(a => a.type === 'trip' && !isPhotosAddon(a)) + const globalAddons = addons.filter(a => a.type === 'global') const integrationAddons = addons.filter(a => a.type === 'integration') - const photosAddon = tripAddons.find(isPhotosAddon) const providerOptions: ProviderOption[] = photoProviderAddons.map((provider) => ({ key: provider.id, label: provider.name, @@ -153,42 +153,7 @@ export default function AddonManager({ bagTrackingEnabled, onToggleBagTracking } {tripAddons.map(addon => (