feat: Cookie-Banner Verarbeiter-Tabelle + Multi-Site UI (F9 + F3)
F9: Verarbeiter-Tabelle - VendorTable.tsx: 82+ vendors grouped by category with expandable cookie details - EmbeddableVendorHTML.tsx: Copy-pasteable HTML table for privacy policy - Tab system: Konfiguration | Verarbeiter | Einbettung F3: Multi-Site UI - SiteSelector.tsx: Domain dropdown with "Neue Seite anlegen" dialog - useCookieBanner hook extended with sites management - Config/vendors reload per selected site Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -96,13 +96,38 @@ const defaultBannerTexts: BannerTexts = {
|
||||
privacyLink: '/datenschutz',
|
||||
}
|
||||
|
||||
export interface BannerSite {
|
||||
id: string
|
||||
site_id: string
|
||||
site_name: string
|
||||
site_url: string
|
||||
is_active: boolean
|
||||
}
|
||||
|
||||
export function useCookieBanner() {
|
||||
const [categories, setCategories] = useState<CookieCategory[]>([])
|
||||
const [config, setConfig] = useState<BannerConfig>(defaultConfig)
|
||||
const [bannerTexts, setBannerTexts] = useState<BannerTexts>(defaultBannerTexts)
|
||||
const [isSaving, setIsSaving] = useState(false)
|
||||
const [exportToast, setExportToast] = useState<string | null>(null)
|
||||
const [sites, setSites] = useState<BannerSite[]>([])
|
||||
const [activeSiteId, setActiveSiteId] = useState<string | null>(null)
|
||||
|
||||
// Load sites list
|
||||
React.useEffect(() => {
|
||||
fetch('/api/sdk/v1/banner/admin/sites')
|
||||
.then(r => r.ok ? r.json() : [])
|
||||
.then(data => {
|
||||
const siteList = Array.isArray(data) ? data : []
|
||||
setSites(siteList)
|
||||
if (siteList.length > 0 && !activeSiteId) {
|
||||
setActiveSiteId(siteList[0].site_id)
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}, [])
|
||||
|
||||
// Load config for active site
|
||||
React.useEffect(() => {
|
||||
const loadConfig = async () => {
|
||||
try {
|
||||
@@ -125,7 +150,20 @@ export function useCookieBanner() {
|
||||
}
|
||||
}
|
||||
loadConfig()
|
||||
}, [])
|
||||
}, [activeSiteId])
|
||||
|
||||
const createSite = async (data: { site_id: string; site_name: string; site_url: string }) => {
|
||||
const res = await fetch('/api/sdk/v1/banner/admin/sites', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
if (res.ok) {
|
||||
const newSite = await res.json()
|
||||
setSites(prev => [...prev, newSite])
|
||||
setActiveSiteId(newSite.site_id || data.site_id)
|
||||
}
|
||||
}
|
||||
|
||||
const handleCategoryToggle = async (categoryId: string, enabled: boolean) => {
|
||||
setCategories(prev =>
|
||||
@@ -180,5 +218,6 @@ export function useCookieBanner() {
|
||||
categories, config, bannerTexts, isSaving, exportToast,
|
||||
setConfig, setBannerTexts,
|
||||
handleCategoryToggle, handleExportCode, handleSaveConfig,
|
||||
sites, activeSiteId, setActiveSiteId, createSite,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user