{projects.length === 0 ? (
- Drop projects here
+ {isReadOnly ? 'No projects' : 'Drop projects here'}
) : useWideLayout ? (
{projects.map((p) => (
-
+
))}
) : (
projects.map((p) => (
-
+
))
)}
@@ -595,6 +599,7 @@ export function CapitalProjectsPage() {
isDragOver={dragOverYear === year}
onDragOverHandler={handleDragOver}
onDragLeave={handleDragLeave}
+ isReadOnly={isReadOnly}
/>
);
})}
diff --git a/frontend/src/pages/dashboard/DashboardPage.tsx b/frontend/src/pages/dashboard/DashboardPage.tsx
index c5546a2..21c20e4 100644
--- a/frontend/src/pages/dashboard/DashboardPage.tsx
+++ b/frontend/src/pages/dashboard/DashboardPage.tsx
@@ -18,7 +18,7 @@ import {
} from '@tabler/icons-react';
import { useState, useCallback } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
-import { useAuthStore } from '../../stores/authStore';
+import { useAuthStore, useIsReadOnly } from '../../stores/authStore';
import api from '../../services/api';
interface HealthScore {
@@ -311,6 +311,7 @@ interface DashboardData {
export function DashboardPage() {
const currentOrg = useAuthStore((s) => s.currentOrg);
+ const isReadOnly = useIsReadOnly();
const queryClient = useQueryClient();
// Track whether a refresh is in progress (per score type) for async polling
@@ -424,7 +425,7 @@ export function DashboardPage() {
}
isRefreshing={operatingRefreshing}
- onRefresh={handleRefreshOperating}
+ onRefresh={!isReadOnly ? handleRefreshOperating : undefined}
lastFailed={!!healthScores?.operating_last_failed}
/>