Connect React workspace to backend data

This commit is contained in:
2026-07-20 13:02:26 +08:00
parent 215268e836
commit 875b326ddc
28 changed files with 1017 additions and 257 deletions

View File

@@ -1,42 +1,76 @@
import { useState } from 'react'
import { ConfigProvider } from '@arco-design/web-react'
import { ConfigProvider, Message, Spin } from '@arco-design/web-react'
import '@arco-design/web-react/dist/css/arco.css'
import '../App.css'
import { login, setApiBaseUrl, type ApiSession } from '../api/client'
import { mapWorkspace } from '../api/mappers'
import { fetchProjectWorkspace, fetchProjects } from '../api/projects'
import { LoginPage } from '../pages/login'
import { ProjectPage } from '../pages/project'
import { projects } from '../pages/projects/project-data'
import type { ChannelKey, Screen, Theme, WorkbenchView } from '../pages/projects/project-types'
import type { ChannelKey, ProjectWorkspace, Screen, Theme, WorkbenchView } from '../pages/projects/project-types'
function App() {
const [screen, setScreen] = useState<Screen>('login')
const [theme, setTheme] = useState<Theme>('light')
const [activeView, setActiveView] = useState<WorkbenchView>('workspace')
const [activeProject, setActiveProject] = useState(projects[0])
const [session, setSession] = useState<ApiSession | null>(null)
const [workspaces, setWorkspaces] = useState<ProjectWorkspace[]>([])
const [activeProjectID, setActiveProjectID] = useState<string>('')
const [activeChannel, setActiveChannel] = useState<ChannelKey>('overview')
const [, setSelectedItem] = useState('Inbox 待处理36')
const [loading, setLoading] = useState(false)
const dark = theme === 'dark'
const activeWorkspace = workspaces.find((workspace) => workspace.project.id === activeProjectID) ?? workspaces[0]
async function handleLogin(input: { server: string; email: string; password: string }) {
setLoading(true)
try {
setApiBaseUrl(input.server)
const nextSession = await login(input.email, input.password)
const backendProjects = await fetchProjects(nextSession)
const backendWorkspaces = await Promise.all(
backendProjects.map((project, index) => fetchProjectWorkspace(nextSession, project.ID ?? project.id ?? '').then((workspace) => mapWorkspace(workspace, index))),
)
setSession(nextSession)
setWorkspaces(backendWorkspaces)
setActiveProjectID(backendWorkspaces[0]?.project.id ?? '')
setActiveChannel('overview')
setActiveView('workspace')
setScreen('workbench')
} catch (error) {
Message.error(error instanceof Error ? error.message : '登录失败')
} finally {
setLoading(false)
}
}
return (
<ConfigProvider>
<main className={dark ? 'app theme-dark' : 'app'}>
{screen === 'login' ? (
<LoginPage onLogin={() => setScreen('workbench')} />
) : (
<Spin loading={loading} style={{ width: '100%' }}>
<LoginPage onLogin={handleLogin} />
</Spin>
) : activeWorkspace && session ? (
<ProjectPage
activeView={activeView}
activeProject={activeProject}
activeWorkspace={activeWorkspace}
workspaces={workspaces}
activeChannel={activeChannel}
theme={theme}
onSelectWorkspace={() => setActiveView('workspace')}
onSelectProject={(project) => {
setActiveProject(project)
setActiveProjectID(project.id)
setActiveView('project')
setActiveChannel('overview')
}}
onSelectChannel={setActiveChannel}
onSelectItem={setSelectedItem}
onToggleTheme={() => setTheme(dark ? 'light' : 'dark')}
/>
) : (
<Spin loading />
)}
</main>
</ConfigProvider>