refactor-frontend-sites pages
This commit is contained in:
@@ -5,22 +5,25 @@
|
||||
*/
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
EyeIcon,
|
||||
FileTextIcon,
|
||||
PlugIcon,
|
||||
TrendingUpIcon,
|
||||
CalendarIcon,
|
||||
GlobeIcon,
|
||||
RefreshCwIcon,
|
||||
RocketIcon
|
||||
} from 'lucide-react';
|
||||
import PageMeta from '../../components/common/PageMeta';
|
||||
import PageHeader from '../../components/common/PageHeader';
|
||||
import { Card } from '../../components/ui/card';
|
||||
import Button from '../../components/ui/button/Button';
|
||||
import EnhancedMetricCard from '../../components/dashboard/EnhancedMetricCard';
|
||||
import { useToast } from '../../components/ui/toast/ToastContainer';
|
||||
import { fetchAPI, fetchSiteBlueprints } from '../../services/api';
|
||||
import SiteProgressWidget from '../../components/sites/SiteProgressWidget';
|
||||
import {
|
||||
EyeIcon,
|
||||
FileIcon,
|
||||
PlugInIcon,
|
||||
ArrowUpIcon,
|
||||
CalendarIcon,
|
||||
GridIcon,
|
||||
BoltIcon,
|
||||
PageIcon,
|
||||
ArrowRightIcon
|
||||
} from '../../icons';
|
||||
|
||||
interface Site {
|
||||
id: number;
|
||||
@@ -136,70 +139,68 @@ export default function SiteDashboard() {
|
||||
|
||||
const statCards = [
|
||||
{
|
||||
label: 'Total Pages',
|
||||
title: 'Total Pages',
|
||||
value: stats?.total_pages || 0,
|
||||
icon: <FileTextIcon className="w-5 h-5" />,
|
||||
color: 'blue',
|
||||
link: `/sites/${siteId}/pages`,
|
||||
icon: <FileIcon />,
|
||||
accentColor: 'blue' as const,
|
||||
href: `/sites/${siteId}/pages`,
|
||||
},
|
||||
{
|
||||
label: 'Published Pages',
|
||||
title: 'Published Pages',
|
||||
value: stats?.published_pages || 0,
|
||||
icon: <GlobeIcon className="w-5 h-5" />,
|
||||
color: 'green',
|
||||
link: `/sites/${siteId}/pages?status=published`,
|
||||
icon: <GridIcon />,
|
||||
accentColor: 'success' as const,
|
||||
href: `/sites/${siteId}/pages?status=published`,
|
||||
},
|
||||
{
|
||||
label: 'Draft Pages',
|
||||
title: 'Draft Pages',
|
||||
value: stats?.draft_pages || 0,
|
||||
icon: <FileTextIcon className="w-5 h-5" />,
|
||||
color: 'amber',
|
||||
link: `/sites/${siteId}/pages?status=draft`,
|
||||
icon: <FileIcon />,
|
||||
accentColor: 'orange' as const,
|
||||
href: `/sites/${siteId}/pages?status=draft`,
|
||||
},
|
||||
{
|
||||
label: 'Integrations',
|
||||
title: 'Integrations',
|
||||
value: stats?.integrations_count || 0,
|
||||
icon: <PlugIcon className="w-5 h-5" />,
|
||||
color: 'purple',
|
||||
link: `/sites/${siteId}/settings?tab=integrations`,
|
||||
icon: <PlugInIcon />,
|
||||
accentColor: 'purple' as const,
|
||||
href: `/sites/${siteId}/settings?tab=integrations`,
|
||||
},
|
||||
{
|
||||
label: 'Deployments',
|
||||
title: 'Deployments',
|
||||
value: stats?.deployments_count || 0,
|
||||
icon: <TrendingUpIcon className="w-5 h-5" />,
|
||||
color: 'teal',
|
||||
link: `/sites/${siteId}/preview`,
|
||||
icon: <ArrowUpIcon />,
|
||||
accentColor: 'blue' as const,
|
||||
href: `/sites/${siteId}/preview`,
|
||||
},
|
||||
{
|
||||
label: 'Total Content',
|
||||
title: 'Total Content',
|
||||
value: stats?.total_content || 0,
|
||||
icon: <FileTextIcon className="w-5 h-5" />,
|
||||
color: 'indigo',
|
||||
link: `/sites/${siteId}/content`,
|
||||
icon: <FileIcon />,
|
||||
accentColor: 'purple' as const,
|
||||
href: `/sites/${siteId}/content`,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="p-6">
|
||||
<PageMeta title={`${site.name} - Dashboard`} />
|
||||
<PageHeader
|
||||
title={site.name}
|
||||
badge={{ icon: <GridIcon />, color: 'blue' }}
|
||||
/>
|
||||
|
||||
{/* Header */}
|
||||
<div className="mb-6 flex justify-between items-start">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">
|
||||
{site.name}
|
||||
</h1>
|
||||
<p className="text-gray-600 dark:text-gray-400 mt-1">
|
||||
{site.slug} • {site.site_type} • {site.hosting_type}
|
||||
{/* Site Info */}
|
||||
<div className="mb-6">
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
{site.slug} • {site.site_type} • {site.hosting_type}
|
||||
</p>
|
||||
{site.domain && (
|
||||
<p className="text-sm text-gray-500 dark:text-gray-500 mt-1">
|
||||
{site.domain}
|
||||
</p>
|
||||
{site.domain && (
|
||||
<p className="text-sm text-gray-500 dark:text-gray-500 mt-1">
|
||||
<GlobeIcon className="w-4 h-4 inline mr-1" />
|
||||
{site.domain}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
)}
|
||||
<div className="flex gap-2 mt-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => navigate(`/sites/${siteId}/preview`)}
|
||||
@@ -229,87 +230,98 @@ export default function SiteDashboard() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Stats Grid */}
|
||||
{/* Stats Grid - Using EnhancedMetricCard */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mb-6">
|
||||
{statCards.map((stat, index) => (
|
||||
<Card
|
||||
<EnhancedMetricCard
|
||||
key={index}
|
||||
className="p-4 hover:shadow-lg transition-shadow cursor-pointer"
|
||||
onClick={() => stat.link && navigate(stat.link)}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400 mb-1">
|
||||
{stat.label}
|
||||
</p>
|
||||
<p className="text-2xl font-bold text-gray-900 dark:text-white">
|
||||
{stat.value}
|
||||
</p>
|
||||
</div>
|
||||
<div className={`text-${stat.color}-500`}>
|
||||
{stat.icon}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
title={stat.title}
|
||||
value={stat.value}
|
||||
icon={stat.icon}
|
||||
accentColor={stat.accentColor}
|
||||
href={stat.href}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Quick Actions */}
|
||||
<Card className="p-6 mb-6">
|
||||
|
||||
{/* Quick Actions - Matching Planner Dashboard pattern */}
|
||||
<div className="mb-6">
|
||||
<h2 className="text-lg font-semibold text-gray-900 dark:text-white mb-4">
|
||||
Quick Actions
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||
<Button
|
||||
variant="outline"
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<button
|
||||
onClick={() => navigate(`/sites/${siteId}/pages`)}
|
||||
className="justify-start"
|
||||
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[var(--color-primary)] hover:shadow-lg transition-all group"
|
||||
>
|
||||
<FileTextIcon className="w-4 h-4 mr-2" />
|
||||
Manage Pages
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-[var(--color-primary)] to-[var(--color-primary-dark)] flex items-center justify-center text-white shadow-lg">
|
||||
<PageIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Manage Pages</h4>
|
||||
<p className="text-sm text-slate-600">View and edit pages</p>
|
||||
</div>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[var(--color-primary)] transition" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => navigate(`/sites/${siteId}/content`)}
|
||||
className="justify-start"
|
||||
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[var(--color-success)] hover:shadow-lg transition-all group"
|
||||
>
|
||||
<FileTextIcon className="w-4 h-4 mr-2" />
|
||||
Manage Content
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-[var(--color-success)] to-[var(--color-success-dark)] flex items-center justify-center text-white shadow-lg">
|
||||
<FileIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Manage Content</h4>
|
||||
<p className="text-sm text-slate-600">View and edit content</p>
|
||||
</div>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[var(--color-success)] transition" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => navigate(`/sites/${siteId}/settings?tab=integrations`)}
|
||||
className="justify-start"
|
||||
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[var(--color-purple)] hover:shadow-lg transition-all group"
|
||||
>
|
||||
<PlugIcon className="w-4 h-4 mr-2" />
|
||||
Manage Integrations
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => navigate(`/sites/${siteId}/editor`)}
|
||||
className="justify-start"
|
||||
>
|
||||
<FileTextIcon className="w-4 h-4 mr-2" />
|
||||
Edit Site
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-[var(--color-purple)] to-[var(--color-purple-dark)] flex items-center justify-center text-white shadow-lg">
|
||||
<PlugInIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Integrations</h4>
|
||||
<p className="text-sm text-slate-600">Manage connections</p>
|
||||
</div>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[var(--color-purple)] transition" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => navigate(`/sites/${siteId}/sync`)}
|
||||
className="justify-start"
|
||||
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[var(--color-warning)] hover:shadow-lg transition-all group"
|
||||
>
|
||||
<RefreshCwIcon className="w-4 h-4 mr-2" />
|
||||
Sync Dashboard
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-[var(--color-warning)] to-[var(--color-warning-dark)] flex items-center justify-center text-white shadow-lg">
|
||||
<BoltIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Sync Dashboard</h4>
|
||||
<p className="text-sm text-slate-600">View sync status</p>
|
||||
</div>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[var(--color-warning)] transition" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => navigate(`/sites/${siteId}/deploy`)}
|
||||
className="justify-start"
|
||||
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[var(--color-primary)] hover:shadow-lg transition-all group"
|
||||
>
|
||||
<RocketIcon className="w-4 h-4 mr-2" />
|
||||
Deploy Site
|
||||
</Button>
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-[var(--color-primary)] to-[var(--color-primary-dark)] flex items-center justify-center text-white shadow-lg">
|
||||
<ArrowUpIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Deploy Site</h4>
|
||||
<p className="text-sm text-slate-600">Deploy to production</p>
|
||||
</div>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[var(--color-primary)] transition" />
|
||||
</button>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Recent Activity */}
|
||||
<Card className="p-6">
|
||||
@@ -319,7 +331,9 @@ export default function SiteDashboard() {
|
||||
<div className="space-y-3">
|
||||
{stats?.last_deployment ? (
|
||||
<div className="flex items-center gap-3 p-3 bg-gray-50 dark:bg-gray-800 rounded-lg">
|
||||
<CalendarIcon className="w-5 h-5 text-gray-400" />
|
||||
<div className="flex-shrink-0 size-10 rounded-lg bg-gradient-to-br from-[var(--color-primary)] to-[var(--color-primary-dark)] flex items-center justify-center text-white shadow-md">
|
||||
<CalendarIcon className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-900 dark:text-white">
|
||||
Last Deployment
|
||||
|
||||
Reference in New Issue
Block a user