diff --git a/apps/web/src/app/(portal)/modules/tender-radar/my-sources/page.tsx b/apps/web/src/app/(portal)/modules/tender-radar/my-sources/page.tsx index 5ba8258..43b9965 100644 --- a/apps/web/src/app/(portal)/modules/tender-radar/my-sources/page.tsx +++ b/apps/web/src/app/(portal)/modules/tender-radar/my-sources/page.tsx @@ -1,31 +1,37 @@ 'use client'; import { useTranslations } from 'next-intl'; +import Link from 'next/link'; +import { useAuthStore } from '@/lib/stores/auth-store'; import { EmailAlertConfigForm } from '../settings/components/EmailAlertConfigForm'; +import { RssFeedListForm } from '../settings/components/RssFeedListForm'; +import { DigestIntervalForm } from '../settings/components/DigestIntervalForm'; /** * "Meine Quellen" — the per-user Ausschreibungs-Radar module page (Phase - * 17, Plan 01, D-01/D-05). + * 17, D-01/D-02/D-04/D-05). * - * Until this plan, the alert mailbox lived on the admin-only - * `/modules/tender-radar/settings` page, one config per TENANT — a second - * colleague with their own portal account could not connect their own - * inbox. Phase 17 moves ownership to the USER (TenderEmailConfig.userId). - * This page is where every user with module access manages their own - * mailbox, reusing the existing `EmailAlertConfigForm` UNCHANGED — it - * already talks to the same `GET`/`PUT /modules/tender-radar/email-config` - * endpoints, which now resolve ownership by userId instead of tenantId - * (TendersController.getEmailConfig/saveEmailConfig). - * - * Deliberately a SEPARATE page from `/settings` (D-01 open point 4), not a - * new section on `/settings/general`: module-specific settings stay with - * the module rather than accumulating on a generic account page as more - * modules adopt the same per-user pattern (DKV-Fleet, future modules). + * Plan 01 built this page with a single section (the mailbox). Plan 03 + * (D-04, the original backlog trigger) completes it with two more: the + * caller's own RSS feeds (`RssFeedListForm scope="personal"` — reused + * unchanged from the admin settings page, Plan 02's `isPlatformWide` split + * decides what's editable here) and the digest interval + * (`DigestIntervalForm`, extracted from the settings page — it was already + * per-user, D-01/D-03 of Phase 12, only misplaced). Together: mailbox, own + * feeds, own notification cadence — everything a normal module user is + * allowed to touch, on one page, in one scroll. * * D-05 (harte Grenze): `Tender` stays platform-global — connecting a - * mailbox here only changes WHO feeds sources in, not WHO sees hits. The - * intro text below says so explicitly, so nobody is surprised that a - * colleague's inbox produces results everyone at the tenant can see. + * mailbox or feed here only changes WHO feeds sources in, not WHO sees + * hits. The intro text says so explicitly (unchanged from Plan 01), and + * the RSS section repeats the same honesty for feeds (`mySources. + * platformFeedsNote` in `RssFeedListForm`). + * + * Administrators additionally see a link to the admin-only settings page + * (poll interval, platform-wide feeds) — everyone else does not, because + * that page rejects them anyway (Plan 03, D-03). The role comes from the + * existing auth store; while it's not loaded yet (`user === null`), the + * link is omitted rather than flashing briefly (T-17-16). * * No module-loader whitelist change needed — nested route under the * already-whitelisted `tender-radar` module page (same reasoning as @@ -33,6 +39,8 @@ import { EmailAlertConfigForm } from '../settings/components/EmailAlertConfigFor */ export default function TenderRadarMySourcesPage() { const t = useTranslations('tenderRadar'); + const user = useAuthStore((s) => s.user); + const isAdmin = user?.role === 'ADMIN' || user?.role === 'SUPER_ADMIN'; return (
+ {t('settings.digestHelp')} +
++ {t('settings.saveSuccess')} +
+ )} + {error &&{error}
} +{addError}
} + + {scope === 'personal' && readonlyPlatformFeeds.length > 0 && ( ++ {t('mySources.platformFeedsNote')} +
++ {feed.label}{' '} + + ({feed.isActive ? t('rssFeeds.activeLabel') : t('rssFeeds.inactiveLabel')}) + +
++ {feed.url} +
+{t('settings.rssSectionBody')}
-