import type { Meta, StoryObj } from '@storybook/nextjs' import { useEffect, useMemo, useState } from 'react' import { CredentialTypeEnum } from '@/app/components/plugins/plugin-auth/types' import { NotionPageSelector } from '.' import type { DataSourceCredential } from '@/app/components/header/account-setting/data-source-page-new/types' import type { NotionPage } from '@/models/common' const DATASET_ID = 'dataset-demo' const CREDENTIALS: DataSourceCredential[] = [ { id: 'cred-1', name: 'Marketing Workspace', type: CredentialTypeEnum.OAUTH2, is_default: true, avatar_url: '', credential: { workspace_name: 'Marketing Workspace', workspace_icon: null, workspace_id: 'workspace-1', }, }, { id: 'cred-2', name: 'Product Workspace', type: CredentialTypeEnum.OAUTH2, is_default: false, avatar_url: '', credential: { workspace_name: 'Product Workspace', workspace_icon: null, workspace_id: 'workspace-2', }, }, ] const marketingPages = { notion_info: [ { workspace_name: 'Marketing Workspace', workspace_id: 'workspace-1', workspace_icon: null, pages: [ { page_icon: { type: 'emoji', emoji: '\u{1F4CB}', url: null }, page_id: 'briefs', page_name: 'Campaign Briefs', parent_id: 'root', type: 'page', is_bound: false, }, { page_icon: { type: 'emoji', emoji: '\u{1F4DD}', url: null }, page_id: 'notes', page_name: 'Meeting Notes', parent_id: 'root', type: 'page', is_bound: true, }, { page_icon: { type: 'emoji', emoji: '\u{1F30D}', url: null }, page_id: 'localizations', page_name: 'Localization Pipeline', parent_id: 'briefs', type: 'page', is_bound: false, }, ], }, ], } const productPages = { notion_info: [ { workspace_name: 'Product Workspace', workspace_id: 'workspace-2', workspace_icon: null, pages: [ { page_icon: { type: 'emoji', emoji: '\u{1F4A1}', url: null }, page_id: 'ideas', page_name: 'Idea Backlog', parent_id: 'root', type: 'page', is_bound: false, }, { page_icon: { type: 'emoji', emoji: '\u{1F9EA}', url: null }, page_id: 'experiments', page_name: 'Experiments', parent_id: 'ideas', type: 'page', is_bound: false, }, ], }, ], } type NotionApiResponse = typeof marketingPages const emptyNotionResponse: NotionApiResponse = { notion_info: [] } const useMockNotionApi = () => { const responseMap = useMemo(() => ({ [`${DATASET_ID}:cred-1`]: marketingPages, [`${DATASET_ID}:cred-2`]: productPages, }) satisfies Record<`${typeof DATASET_ID}:${typeof CREDENTIALS[number]['id']}`, NotionApiResponse>, []) useEffect(() => { const originalFetch = globalThis.fetch?.bind(globalThis) const handler = async (input: RequestInfo | URL, init?: RequestInit) => { const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url if (url.includes('/notion/pre-import/pages')) { const parsed = new URL(url, globalThis.location.origin) const datasetId = parsed.searchParams.get('dataset_id') || '' const credentialId = parsed.searchParams.get('credential_id') || '' let payload: NotionApiResponse = emptyNotionResponse if (datasetId === DATASET_ID) { const credential = CREDENTIALS.find(item => item.id === credentialId) if (credential) { const mapKey = `${DATASET_ID}:${credential.id}` as keyof typeof responseMap payload = responseMap[mapKey] } } return new Response( JSON.stringify(payload), { headers: { 'Content-Type': 'application/json' }, status: 200 }, ) } if (originalFetch) return originalFetch(input, init) throw new Error(`Unmocked fetch call for ${url}`) } globalThis.fetch = handler as typeof globalThis.fetch return () => { if (originalFetch) globalThis.fetch = originalFetch } }, [responseMap]) } const NotionSelectorPreview = () => { const [selectedPages, setSelectedPages] = useState([]) const [credentialId, setCredentialId] = useState() useMockNotionApi() return (
page.page_id)} onSelect={setSelectedPages} onSelectCredential={setCredentialId} canPreview />
Debug state

Active credential: {credentialId || 'None'}

          {JSON.stringify(selectedPages, null, 2)}
        
) } const meta = { title: 'Base/Other/NotionPageSelector', component: NotionSelectorPreview, parameters: { layout: 'centered', docs: { description: { component: 'Credential-aware selector that fetches Notion pages and lets users choose which ones to sync.', }, }, }, tags: ['autodocs'], } satisfies Meta export default meta type Story = StoryObj export const Playground: Story = {}