refactor-frontend-sites pages

This commit is contained in:
alorig
2025-11-20 09:14:38 +05:00
parent 8e7afa76cd
commit 09232aa1c0
5 changed files with 784 additions and 137 deletions

View File

@@ -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

View File

@@ -5,8 +5,8 @@
*/
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { PlusIcon, EditIcon, SettingsIcon, EyeIcon, TrashIcon, FilterIcon, SearchIcon, PlugIcon, FileTextIcon, MoreVerticalIcon, Building2Icon } 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 SelectDropdown from '../../components/form/SelectDropdown';
@@ -17,6 +17,17 @@ import Badge from '../../components/ui/badge/Badge';
import FormModal, { FormField } from '../../components/common/FormModal';
import Alert from '../../components/ui/alert/Alert';
import Switch from '../../components/form/switch/Switch';
import {
PlusIcon,
PencilIcon,
EyeIcon,
TrashBinIcon,
GridIcon,
PlugInIcon,
FileIcon,
MoreDotIcon,
PageIcon
} from '../../icons';
import {
fetchSites,
createSite,
@@ -503,17 +514,16 @@ export default function SiteList() {
return (
<div className="p-6">
<PageMeta title="Sites Management - IGNY8" />
<PageHeader
title="Sites Management"
badge={{ icon: <GridIcon />, color: 'blue' }}
/>
<div className="mb-6">
<div className="flex items-center justify-between mb-4">
<div>
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">
Sites Management
</h1>
<p className="text-gray-600 dark:text-gray-400 mt-1">
Manage your sites, configure industries, and select sectors. Multiple sites can be active simultaneously.
</p>
</div>
<p className="text-sm text-gray-600 dark:text-gray-400">
Manage your sites, configure industries, and select sectors. Multiple sites can be active simultaneously.
</p>
<div className="flex gap-2">
<Button onClick={() => navigate('/sites/builder')} variant="outline">
<PlusIcon className="w-4 h-4 mr-2" />
@@ -537,7 +547,9 @@ export default function SiteList() {
{/* Filters */}
<Card className="p-4 mb-6">
<div className="flex items-center gap-2 mb-4">
<FilterIcon className="w-5 h-5 text-gray-600 dark:text-gray-400" />
<div className="flex-shrink-0 size-8 rounded-lg bg-gradient-to-br from-[var(--color-primary)] to-[var(--color-primary-dark)] flex items-center justify-center text-white shadow-md">
<GridIcon className="h-4 w-4" />
</div>
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">
Filters
</h2>
@@ -560,7 +572,9 @@ export default function SiteList() {
Search
</label>
<div className="relative">
<SearchIcon className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<div className="absolute left-3 top-1/2 transform -translate-y-1/2">
<GridIcon className="w-4 h-4 text-gray-400" />
</div>
<input
type="text"
value={searchTerm}
@@ -645,14 +659,10 @@ export default function SiteList() {
) : (
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 xl:grid-cols-3">
{filteredSites.map((site) => (
<Card key={site.id} className="rounded-2xl border border-gray-200 bg-white dark:border-gray-800 dark:bg-white/3 hover:shadow-lg transition-shadow">
<Card key={site.id} className="rounded-xl border-2 border-slate-200 bg-white dark:border-gray-800 dark:bg-white/3 hover:border-[var(--color-primary)] hover:shadow-lg transition-all">
<div className="relative p-5 pb-9">
<div className="mb-5 inline-flex h-10 w-10 items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40" fill="none">
<rect width="40" height="40" rx="8" fill="#3B82F6"/>
<path d="M12 16L20 10L28 16V28C28 28.5304 27.7893 29.0391 27.4142 29.4142C27.0391 29.7893 26.5304 30 26 30H14C13.4696 30 12.9609 29.7893 12.5858 29.4142C12.2107 29.0391 12 28.5304 12 28V16Z" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M16 30V20H24V30" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<div className="mb-5 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">
<GridIcon className="h-6 w-6" />
</div>
<h3 className="mb-3 text-lg font-semibold text-gray-800 dark:text-white/90">
{site.name}
@@ -712,7 +722,7 @@ export default function SiteList() {
className="w-full justify-center text-xs"
title="View Content"
>
<FileTextIcon className="w-3 h-3 mr-1" />
<FileIcon className="w-3 h-3 mr-1" />
Content
</Button>
<Button
@@ -722,7 +732,7 @@ export default function SiteList() {
className="w-full justify-center text-xs"
title="Manage Pages"
>
<FileTextIcon className="w-3 h-3 mr-1" />
<PageIcon className="w-3 h-3 mr-1" />
Pages
</Button>
</div>
@@ -737,7 +747,7 @@ export default function SiteList() {
className="shadow-theme-xs inline-flex h-9 items-center justify-center rounded-lg border border-gray-300 text-gray-700 dark:border-gray-700 dark:text-gray-400 px-3"
title="Configure Sectors"
>
<Building2Icon className="w-4 h-4 mr-1" />
<GridIcon className="w-4 h-4 mr-1" />
<span className="text-xs">Sectors</span>
</Button>
<Button
@@ -747,7 +757,7 @@ export default function SiteList() {
className="shadow-theme-xs inline-flex h-9 items-center justify-center rounded-lg border border-gray-300 text-gray-700 dark:border-gray-700 dark:text-gray-400 px-3"
title="Site Settings"
>
<SettingsIcon className="w-4 h-4 mr-1" />
<PlugInIcon className="w-4 h-4 mr-1" />
<span className="text-xs">Settings</span>
</Button>
</div>