feat: DashboardShell for all auth pages, site settings modal from home
- layout-content wraps integrations/pricing in DashboardShell - GlassTopBar derives title per page (Integrations, Pricing, etc.) - Site card gear icon opens settings modal with siteId context - Removed delete button from site cards (accessible via site settings) - Extended InitialTab to accept optional siteId for cross-page use
This commit is contained in:
17
app/page.tsx
17
app/page.tsx
@@ -33,7 +33,6 @@ export default function HomePage() {
|
||||
const [siteStats, setSiteStats] = useState<SiteStatsMap>({})
|
||||
const [subscription, setSubscription] = useState<SubscriptionDetails | null>(null)
|
||||
const [showFinishSetupBanner, setShowFinishSetupBanner] = useState(true)
|
||||
const [deleteModalSite, setDeleteModalSite] = useState<Site | null>(null)
|
||||
const [deletedSites, setDeletedSites] = useState<Site[]>([])
|
||||
const [permanentDeleteSiteModal, setPermanentDeleteSiteModal] = useState<Site | null>(null)
|
||||
|
||||
@@ -119,11 +118,6 @@ export default function HomePage() {
|
||||
}
|
||||
}
|
||||
|
||||
const handleDelete = (id: string) => {
|
||||
const site = sites.find((s) => s.id === id)
|
||||
if (site) setDeleteModalSite(site)
|
||||
}
|
||||
|
||||
const handleRestore = async (id: string) => {
|
||||
try {
|
||||
await restoreSite(id)
|
||||
@@ -312,18 +306,9 @@ export default function HomePage() {
|
||||
)}
|
||||
|
||||
{(sitesLoading || sites.length > 0) && (
|
||||
<SiteList sites={sites} siteStats={siteStats} loading={sitesLoading} onDelete={handleDelete} />
|
||||
<SiteList sites={sites} siteStats={siteStats} loading={sitesLoading} />
|
||||
)}
|
||||
|
||||
<DeleteSiteModal
|
||||
open={!!deleteModalSite}
|
||||
onClose={() => setDeleteModalSite(null)}
|
||||
onDeleted={loadSites}
|
||||
siteName={deleteModalSite?.name || ''}
|
||||
siteDomain={deleteModalSite?.domain || ''}
|
||||
siteId={deleteModalSite?.id || ''}
|
||||
/>
|
||||
|
||||
<DeleteSiteModal
|
||||
open={!!permanentDeleteSiteModal}
|
||||
onClose={() => setPermanentDeleteSiteModal(null)}
|
||||
|
||||
@@ -303,7 +303,11 @@ export default function UnifiedSettingsModal() {
|
||||
useEffect(() => {
|
||||
if (!isOpen || !user?.org_id) return
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
if (initTab?.siteId) {
|
||||
// Site ID passed explicitly (e.g. from home page site card)
|
||||
setActiveSiteId(initTab.siteId)
|
||||
if (!initTab?.context) setContext('site')
|
||||
} else if (typeof window !== 'undefined') {
|
||||
const match = window.location.pathname.match(/\/sites\/([a-f0-9-]+)/)
|
||||
if (match) {
|
||||
setActiveSiteId(match[1])
|
||||
|
||||
@@ -5,8 +5,8 @@ import Image from 'next/image'
|
||||
import { Site } from '@/lib/api/sites'
|
||||
import type { Stats } from '@/lib/api/stats'
|
||||
import { formatNumber } from '@ciphera-net/ui'
|
||||
import { BarChartIcon, SettingsIcon, TrashIcon, BookOpenIcon, ExternalLinkIcon, Button } from '@ciphera-net/ui'
|
||||
import { useAuth } from '@/lib/auth/context'
|
||||
import { BarChartIcon, SettingsIcon, BookOpenIcon, ExternalLinkIcon, Button } from '@ciphera-net/ui'
|
||||
import { useUnifiedSettings } from '@/lib/unified-settings-context'
|
||||
import { FAVICON_SERVICE_URL } from '@/lib/utils/favicon'
|
||||
|
||||
export type SiteStatsMap = Record<string, { stats: Stats }>
|
||||
@@ -15,18 +15,16 @@ interface SiteListProps {
|
||||
sites: Site[]
|
||||
siteStats: SiteStatsMap
|
||||
loading: boolean
|
||||
onDelete: (id: string) => void
|
||||
}
|
||||
|
||||
interface SiteCardProps {
|
||||
site: Site
|
||||
stats: Stats | null
|
||||
statsLoading: boolean
|
||||
onDelete: (id: string) => void
|
||||
canDelete: boolean
|
||||
}
|
||||
|
||||
function SiteCard({ site, stats, statsLoading, onDelete, canDelete }: SiteCardProps) {
|
||||
function SiteCard({ site, stats, statsLoading }: SiteCardProps) {
|
||||
const { openUnifiedSettings } = useUnifiedSettings()
|
||||
const visitors24h = stats?.visitors ?? 0
|
||||
const pageviews = stats?.pageviews ?? 0
|
||||
|
||||
@@ -104,31 +102,20 @@ function SiteCard({ site, stats, statsLoading, onDelete, canDelete }: SiteCardPr
|
||||
View Dashboard
|
||||
</Button>
|
||||
</Link>
|
||||
<Link
|
||||
href={`/sites/${site.id}/settings`}
|
||||
className="flex items-center justify-center rounded-lg border border-neutral-200 px-3 hover:bg-neutral-50 dark:border-neutral-700 dark:hover:bg-neutral-800 text-neutral-500 hover:text-neutral-300 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-orange focus-visible:ring-offset-2"
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => openUnifiedSettings({ context: 'site', tab: 'general', siteId: site.id })}
|
||||
className="flex items-center justify-center rounded-lg border border-neutral-200 px-3 hover:bg-neutral-50 dark:border-neutral-700 dark:hover:bg-neutral-800 text-neutral-500 hover:text-neutral-300 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-orange focus-visible:ring-offset-2 cursor-pointer"
|
||||
title="Site Settings"
|
||||
>
|
||||
<SettingsIcon className="h-4 w-4" />
|
||||
</Link>
|
||||
{canDelete && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onDelete(site.id)}
|
||||
className="flex items-center justify-center rounded-lg border border-neutral-200 px-3 hover:bg-neutral-50 dark:border-neutral-700 dark:hover:bg-neutral-800 text-neutral-500 hover:text-red-600 dark:hover:text-red-400 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-2"
|
||||
title="Delete Site"
|
||||
>
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function SiteList({ sites, siteStats, loading, onDelete }: SiteListProps) {
|
||||
const { user } = useAuth()
|
||||
const canDelete = user?.role === 'owner' || user?.role === 'admin'
|
||||
export default function SiteList({ sites, siteStats, loading }: SiteListProps) {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
@@ -172,8 +159,6 @@ export default function SiteList({ sites, siteStats, loading, onDelete }: SiteLi
|
||||
site={site}
|
||||
stats={data?.stats ?? null}
|
||||
statsLoading={!data}
|
||||
onDelete={onDelete}
|
||||
canDelete={canDelete}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { createContext, useContext, useState, useCallback } from 'react'
|
||||
|
||||
type InitialTab = { context?: 'site' | 'workspace' | 'account'; tab?: string } | null
|
||||
type InitialTab = { context?: 'site' | 'workspace' | 'account'; tab?: string; siteId?: string } | null
|
||||
|
||||
interface UnifiedSettingsContextType {
|
||||
isOpen: boolean
|
||||
|
||||
Reference in New Issue
Block a user