diff --git a/app/sites/[id]/page.tsx b/app/sites/[id]/page.tsx
index 517e971..bf74656 100644
--- a/app/sites/[id]/page.tsx
+++ b/app/sites/[id]/page.tsx
@@ -1,5 +1,6 @@
'use client'
+import { useAuth } from '@/lib/auth/context'
import { useEffect, useState } from 'react'
import { useParams, useRouter } from 'next/navigation'
import { getSite, type Site } from '@/lib/api/sites'
@@ -17,6 +18,9 @@ import Chart from '@/components/dashboard/Chart'
import PerformanceStats from '@/components/dashboard/PerformanceStats'
export default function SiteDashboardPage() {
+ const { user } = useAuth()
+ const canEdit = user?.role === 'owner' || user?.role === 'admin'
+
const params = useParams()
const router = useRouter()
const siteId = params.id as string
@@ -221,12 +225,14 @@ export default function SiteDashboardPage() {
className="min-w-[100px]"
/>
)}
+ {canEdit && (
+ )}
diff --git a/app/sites/[id]/settings/page.tsx b/app/sites/[id]/settings/page.tsx
index f8999df..203a0a0 100644
--- a/app/sites/[id]/settings/page.tsx
+++ b/app/sites/[id]/settings/page.tsx
@@ -12,6 +12,7 @@ import Select from '@/components/ui/Select'
import { APP_URL, API_URL } from '@/lib/api/client'
import { generatePrivacySnippet } from '@/lib/utils/privacySnippet'
import { motion, AnimatePresence } from 'framer-motion'
+import { useAuth } from '@/lib/auth/context'
import {
GearIcon,
GlobeIcon,
@@ -51,6 +52,9 @@ const TIMEZONES = [
]
export default function SiteSettingsPage() {
+ const { user } = useAuth()
+ const canEdit = user?.role === 'owner' || user?.role === 'admin'
+
const params = useParams()
const router = useRouter()
const siteId = params.id as string
@@ -302,6 +306,13 @@ export default function SiteSettingsPage() {
{/* Content Area */}
+ {!canEdit && (
+
+
+
You have read-only access to this site. Contact an admin to make changes.
+
+ )}
+
-
-
-
-
+
+ {canEdit && (
+
+ )}
+
+
-
-
-
Danger Zone
+ {canEdit && (
+
+
+
Danger Zone
Irreversible actions for your site.
@@ -450,9 +464,9 @@ export default function SiteSettingsPage() {
+ )}
-
- )}
+ )}
{activeTab === 'visibility' && (
@@ -566,21 +580,23 @@ export default function SiteSettingsPage() {
-
+ {canEdit && (
+
+ )}
@@ -819,21 +835,23 @@ export default function SiteSettingsPage() {
-
+ {canEdit && (
+
+ )}
@@ -985,21 +1003,23 @@ export default function SiteSettingsPage() {
-
+ {canEdit && (
+
+ )}
diff --git a/components/sites/SiteList.tsx b/components/sites/SiteList.tsx
index daf73bc..e619a29 100644
--- a/components/sites/SiteList.tsx
+++ b/components/sites/SiteList.tsx
@@ -5,9 +5,11 @@ import Link from 'next/link'
import { listSites, deleteSite, type Site } from '@/lib/api/sites'
import { toast } from 'sonner'
import LoadingOverlay from '../LoadingOverlay'
+import { useAuth } from '@/lib/auth/context'
import { BarChartIcon } from '@radix-ui/react-icons'
export default function SiteList() {
+ const { user } = useAuth()
const [sites, setSites] = useState([])
const [loading, setLoading] = useState(true)
@@ -72,13 +74,15 @@ export default function SiteList() {
View Dashboard
-
+ {(user?.role === 'owner' || user?.role === 'admin') && (
+
+ )}
))}
diff --git a/lib/auth/context.tsx b/lib/auth/context.tsx
index 3837d7c..61687b2 100644
--- a/lib/auth/context.tsx
+++ b/lib/auth/context.tsx
@@ -63,8 +63,16 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
const refresh = useCallback(async () => {
try {
const userData = await apiRequest('/auth/user/me')
- setUser(userData)
- localStorage.setItem('user', JSON.stringify(userData))
+
+ setUser(prev => {
+ const merged = {
+ ...userData,
+ org_id: prev?.org_id,
+ role: prev?.role
+ }
+ localStorage.setItem('user', JSON.stringify(merged))
+ return merged
+ })
} catch (e) {
console.error('Failed to refresh user data', e)
}