fix(workspaces): show load error before setup prompt

This commit is contained in:
2026-06-06 23:43:10 +03:30
parent 64b240bf26
commit 549f6aff86

View File

@@ -28,26 +28,32 @@ export const useOptionalWorkspace = () => useContext(WorkspaceContext)
export const WorkspaceProvider = ({ children }: { children: ReactNode }) => { export const WorkspaceProvider = ({ children }: { children: ReactNode }) => {
const { t } = useTranslation() const { t } = useTranslation()
const [workspaces, setWorkspaces] = useState<Workspace[]>([]) const [workspaces, setWorkspaces] = useState<Workspace[]>([])
const [activeWorkspace, setActiveWorkspaceState] = useState<Workspace | null>(null) const [activeWorkspace, setActiveWorkspaceState] = useState<Workspace | null>(null)
const [isLoading, setIsLoading] = useState(true) const [isLoading, setIsLoading] = useState(true)
const [newWorkspaceName, setNewWorkspaceName] = useState("") const [hasLoadedWorkspaces, setHasLoadedWorkspaces] = useState(false)
const [isCreatingFirst, setIsCreatingFirst] = useState(false) const [workspaceLoadError, setWorkspaceLoadError] = useState(false)
const [newWorkspaceName, setNewWorkspaceName] = useState("")
const [isCreatingFirst, setIsCreatingFirst] = useState(false)
const isAuthenticated = !!localStorage.getItem("accessToken") const isAuthenticated = !!localStorage.getItem("accessToken")
const rateLimited = isRateLimitActive() const rateLimited = isRateLimitActive()
const refreshWorkspaces = async () => { const refreshWorkspaces = async () => {
if (!isAuthenticated || isRateLimitActive()) { if (!isAuthenticated || isRateLimitActive()) {
setHasLoadedWorkspaces(false)
setWorkspaceLoadError(false)
setIsLoading(false) setIsLoading(false)
return return
} }
try { try {
setIsLoading(true) setIsLoading(true)
setWorkspaceLoadError(false)
const response = await fetchWorkspaces() const response = await fetchWorkspaces()
const data = Array.isArray(response) ? response : (response?.results || []) const data = Array.isArray(response) ? response : (response?.results || [])
setWorkspaces(data) setWorkspaces(data)
setHasLoadedWorkspaces(true)
if (data.length > 0) { if (data.length > 0) {
const storedId = localStorage.getItem("activeWorkspaceId") const storedId = localStorage.getItem("activeWorkspaceId")
@@ -64,6 +70,8 @@ export const WorkspaceProvider = ({ children }: { children: ReactNode }) => {
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
setWorkspaceLoadError(true)
setHasLoadedWorkspaces(false)
} finally { } finally {
setIsLoading(false) setIsLoading(false)
} }
@@ -71,6 +79,8 @@ export const WorkspaceProvider = ({ children }: { children: ReactNode }) => {
useEffect(() => { useEffect(() => {
if (!isAuthenticated || rateLimited) { if (!isAuthenticated || rateLimited) {
setHasLoadedWorkspaces(false)
setWorkspaceLoadError(false)
setIsLoading(false) setIsLoading(false)
return return
} }
@@ -90,9 +100,11 @@ export const WorkspaceProvider = ({ children }: { children: ReactNode }) => {
const addWorkspace = async (name: string) => { const addWorkspace = async (name: string) => {
try { try {
setIsCreatingFirst(true) setIsCreatingFirst(true)
const newWs = await createWorkspace({ name, description: "" }) const newWs = await createWorkspace({ name, description: "" })
setWorkspaces((prev) => [...prev, newWs]) setWorkspaces((prev) => [...prev, newWs])
setActiveWorkspace(newWs) setHasLoadedWorkspaces(true)
setWorkspaceLoadError(false)
setActiveWorkspace(newWs)
toast.success(t.workspace?.successCreate || t.workspace?.toast?.successCreate || "Workspace created!") toast.success(t.workspace?.successCreate || t.workspace?.toast?.successCreate || "Workspace created!")
} catch (error) { } catch (error) {
toast.error(t.workspace?.toast?.errorCreate || "Failed to create workspace") toast.error(t.workspace?.toast?.errorCreate || "Failed to create workspace")
@@ -101,10 +113,31 @@ export const WorkspaceProvider = ({ children }: { children: ReactNode }) => {
setIsCreatingFirst(false) setIsCreatingFirst(false)
setNewWorkspaceName("") setNewWorkspaceName("")
} }
} }
// Force workspace creation if authenticated but none exist if (!rateLimited && !isLoading && isAuthenticated && workspaceLoadError) {
if (!rateLimited && !isLoading && isAuthenticated && workspaces.length === 0) { return (
<div className="min-h-screen flex items-center justify-center bg-slate-50 dark:bg-slate-900 px-4">
<div className="w-full max-w-md bg-white dark:bg-slate-800 p-8 rounded-xl shadow-lg border border-slate-200 dark:border-slate-700">
<h2 className="text-2xl font-bold text-slate-900 dark:text-white mb-2">
{t.workspace?.fetchError || "Failed to load workspace data"}
</h2>
<p className="text-slate-600 dark:text-slate-400 mb-6">
{t.workspace?.loadErrorDescription || "The backend service may be unavailable. Please try again in a moment."}
</p>
<Button
onClick={() => void refreshWorkspaces()}
className="w-full bg-blue-600 hover:bg-blue-700 text-white"
>
{t.workspace?.retry || "Try again"}
</Button>
</div>
</div>
)
}
// Force workspace creation if authenticated but none exist
if (!rateLimited && !isLoading && isAuthenticated && hasLoadedWorkspaces && workspaces.length === 0) {
return ( return (
<div className="min-h-screen flex items-center justify-center bg-slate-50 dark:bg-slate-900 px-4"> <div className="min-h-screen flex items-center justify-center bg-slate-50 dark:bg-slate-900 px-4">
<div className="w-full max-w-md bg-white dark:bg-slate-800 p-8 rounded-xl shadow-lg border border-slate-200 dark:border-slate-700"> <div className="w-full max-w-md bg-white dark:bg-slate-800 p-8 rounded-xl shadow-lg border border-slate-200 dark:border-slate-700">