COmpoeentes standardization 2
This commit is contained in:
@@ -28,7 +28,9 @@ import {
|
||||
PageIcon,
|
||||
TableIcon,
|
||||
ChevronDownIcon,
|
||||
ChevronUpIcon
|
||||
ChevronUpIcon,
|
||||
FilterIcon,
|
||||
BoxCubeIcon as SettingsIcon
|
||||
} from '../../icons';
|
||||
import {
|
||||
fetchSites,
|
||||
@@ -67,6 +69,7 @@ export default function SiteList() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [viewType, setViewType] = useState<ViewType>('grid');
|
||||
const [showWelcomeGuide, setShowWelcomeGuide] = useState(false);
|
||||
const [showFilters, setShowFilters] = useState(false);
|
||||
|
||||
// Site Management Modals
|
||||
const [selectedSite, setSelectedSite] = useState<Site | null>(null);
|
||||
@@ -410,19 +413,16 @@ export default function SiteList() {
|
||||
{site.domain}
|
||||
</p>
|
||||
)}
|
||||
<div className="flex items-center gap-2 mb-2 flex-wrap">
|
||||
<SiteTypeBadge hostingType={site.hosting_type} />
|
||||
{/* Centered badges with uniform size */}
|
||||
<div className="flex items-center justify-center gap-2 mb-2 flex-wrap">
|
||||
<SiteTypeBadge hostingType={site.hosting_type} size="sm" />
|
||||
{site.industry_name && (
|
||||
<Badge variant="light" color="info" className="text-xs">
|
||||
<Badge variant="soft" color="warning" size="sm">
|
||||
{site.industry_name}
|
||||
</Badge>
|
||||
)}
|
||||
{site.integration_count && site.integration_count > 0 && (
|
||||
<Badge variant="soft" color="success" className="text-[10px] px-1.5 py-0.5">
|
||||
{site.integration_count} integration{site.integration_count > 1 ? 's' : ''}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
{/* Status badge and toggle in top right */}
|
||||
<div className="absolute top-4 right-4 flex items-center gap-3">
|
||||
<Switch
|
||||
checked={site.is_active}
|
||||
@@ -430,19 +430,21 @@ export default function SiteList() {
|
||||
disabled={togglingSiteId === site.id}
|
||||
/>
|
||||
<Badge
|
||||
variant={site.is_active ? "soft" : "light"}
|
||||
color={site.is_active ? "success" : "gray"}
|
||||
size="sm"
|
||||
variant="solid"
|
||||
color={site.is_active ? "success" : "error"}
|
||||
size="xs"
|
||||
>
|
||||
{site.is_active ? 'Active' : 'Inactive'}
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
{/* Centered button row */}
|
||||
<div className="border-t border-gray-200 p-3 dark:border-gray-800">
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="flex justify-center gap-2">
|
||||
<Button
|
||||
onClick={() => navigate(`/sites/${site.id}`)}
|
||||
variant="primary"
|
||||
tone="brand"
|
||||
size="sm"
|
||||
startIcon={<EyeIcon className="w-4 h-4" />}
|
||||
>
|
||||
@@ -451,6 +453,7 @@ export default function SiteList() {
|
||||
<Button
|
||||
onClick={() => navigate(`/sites/${site.id}/content`)}
|
||||
variant="secondary"
|
||||
tone="neutral"
|
||||
size="sm"
|
||||
startIcon={<FileIcon className="w-4 h-4" />}
|
||||
>
|
||||
@@ -459,9 +462,9 @@ export default function SiteList() {
|
||||
<Button
|
||||
onClick={() => navigate(`/sites/${site.id}/settings`)}
|
||||
variant="outline"
|
||||
tone="neutral"
|
||||
size="sm"
|
||||
startIcon={<PlugInIcon className="w-4 h-4" />}
|
||||
className="col-span-2"
|
||||
startIcon={<SettingsIcon className="w-4 h-4" />}
|
||||
>
|
||||
Settings
|
||||
</Button>
|
||||
@@ -497,33 +500,46 @@ export default function SiteList() {
|
||||
|
||||
{/* Custom Header Actions - Add Site button and view toggle */}
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-3">
|
||||
<Button
|
||||
onClick={() => setShowWelcomeGuide(!showWelcomeGuide)}
|
||||
variant="success"
|
||||
variant="primary"
|
||||
tone="brand"
|
||||
size="md"
|
||||
startIcon={<PlusIcon className="w-5 h-5" />}
|
||||
>
|
||||
Add New Website
|
||||
</Button>
|
||||
{viewType === 'grid' && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="md"
|
||||
onClick={() => setShowFilters(!showFilters)}
|
||||
startIcon={<FilterIcon className="w-4 h-4" />}
|
||||
>
|
||||
{showFilters ? 'Hide Filters' : 'Show Filters'}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-1 bg-gray-100 dark:bg-gray-800 rounded-lg p-1">
|
||||
<Button
|
||||
onClick={() => setViewType('table')}
|
||||
variant={viewType === 'table' ? 'secondary' : 'ghost'}
|
||||
variant={viewType === 'table' ? 'primary' : 'ghost'}
|
||||
tone="brand"
|
||||
size="sm"
|
||||
startIcon={<TableIcon className="w-4 h-4" />}
|
||||
>
|
||||
<span className="hidden sm:inline">Table</span>
|
||||
Table
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => setViewType('grid')}
|
||||
variant={viewType === 'grid' ? 'secondary' : 'ghost'}
|
||||
variant={viewType === 'grid' ? 'primary' : 'ghost'}
|
||||
tone="brand"
|
||||
size="sm"
|
||||
startIcon={<GridIcon className="w-4 h-4" />}
|
||||
>
|
||||
<span className="hidden sm:inline">Grid</span>
|
||||
Grid
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -600,59 +616,61 @@ export default function SiteList() {
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{/* Standard Filters Bar for Grid View - Matches Table View */}
|
||||
<div className="flex justify-center mb-4">
|
||||
<div
|
||||
className="w-[75%] igny8-filter-bar p-3 rounded-lg bg-transparent shadow-theme-md"
|
||||
>
|
||||
<div className="flex flex-nowrap gap-3 items-center justify-between w-full">
|
||||
<div className="flex flex-nowrap gap-3 items-center flex-1 min-w-0 w-full">
|
||||
<div className="flex-1 min-w-[200px]">
|
||||
<InputField
|
||||
type="text"
|
||||
placeholder="Search sites..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 min-w-[140px]">
|
||||
<Select
|
||||
options={SITE_TYPES}
|
||||
placeholder="Show All Types"
|
||||
defaultValue={siteTypeFilter}
|
||||
onChange={(val) => setSiteTypeFilter(val)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 min-w-[140px]">
|
||||
<Select
|
||||
options={HOSTING_TYPES}
|
||||
placeholder="Show All Hosting"
|
||||
defaultValue={hostingTypeFilter}
|
||||
onChange={(val) => setHostingTypeFilter(val)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 min-w-[140px]">
|
||||
<Select
|
||||
options={STATUS_OPTIONS}
|
||||
placeholder="Show All Status"
|
||||
defaultValue={statusFilter}
|
||||
onChange={(val) => setStatusFilter(val)}
|
||||
/>
|
||||
{/* Standard Filters Bar for Grid View - Collapsible like table view */}
|
||||
{showFilters && (
|
||||
<div className="flex justify-center mb-4">
|
||||
<div
|
||||
className="w-full igny8-filter-bar p-3 rounded-lg bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 shadow-sm"
|
||||
>
|
||||
<div className="flex flex-nowrap gap-3 items-center justify-between w-full">
|
||||
<div className="flex flex-nowrap gap-3 items-center flex-1 min-w-0 w-full">
|
||||
<div className="flex-1 min-w-[200px]">
|
||||
<InputField
|
||||
type="text"
|
||||
placeholder="Search sites..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 min-w-[140px]">
|
||||
<Select
|
||||
options={SITE_TYPES}
|
||||
placeholder="Show All Types"
|
||||
defaultValue={siteTypeFilter}
|
||||
onChange={(val) => setSiteTypeFilter(val)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 min-w-[140px]">
|
||||
<Select
|
||||
options={HOSTING_TYPES}
|
||||
placeholder="Show All Hosting"
|
||||
defaultValue={hostingTypeFilter}
|
||||
onChange={(val) => setHostingTypeFilter(val)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 min-w-[140px]">
|
||||
<Select
|
||||
options={STATUS_OPTIONS}
|
||||
placeholder="Show All Status"
|
||||
defaultValue={statusFilter}
|
||||
onChange={(val) => setStatusFilter(val)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{hasActiveFilters && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={clearFilters}
|
||||
className="flex-shrink-0"
|
||||
>
|
||||
Clear Filters
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{hasActiveFilters && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={clearFilters}
|
||||
className="flex-shrink-0"
|
||||
>
|
||||
Clear Filters
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Grid View */}
|
||||
{filteredSites.length === 0 ? (
|
||||
@@ -665,7 +683,7 @@ export default function SiteList() {
|
||||
Clear Filters
|
||||
</Button>
|
||||
) : (
|
||||
<Button onClick={() => setShowWelcomeGuide(true)} variant="success" startIcon={<PlusIcon className="w-5 h-5" />}>
|
||||
<Button onClick={() => setShowWelcomeGuide(true)} variant="primary" tone="success" startIcon={<PlusIcon className="w-5 h-5" />}>
|
||||
Add Your First Site
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -11,6 +11,7 @@ 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 IconButton from '../../components/ui/button/IconButton';
|
||||
import { useToast } from '../../components/ui/toast/ToastContainer';
|
||||
import { fetchAPI } from '../../services/api';
|
||||
import {
|
||||
@@ -94,13 +95,10 @@ const DraggablePageItem: React.FC<{
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" size="sm" onClick={() => onEdit(page.id)}>
|
||||
<PencilIcon className="w-4 h-4 mr-1" />
|
||||
<Button variant="outline" size="sm" onClick={() => onEdit(page.id)} startIcon={<PencilIcon className="w-4 h-4" />}>
|
||||
Edit
|
||||
</Button>
|
||||
<Button variant="ghost" size="sm" onClick={() => onDelete(page.id)}>
|
||||
<TrashBinIcon className="w-4 h-4" />
|
||||
</Button>
|
||||
<IconButton variant="ghost" size="sm" onClick={() => onDelete(page.id)} icon={<TrashBinIcon className="w-4 h-4" />} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -330,8 +328,8 @@ export default function PageManager() {
|
||||
size="sm"
|
||||
onClick={handleBulkDelete}
|
||||
className="text-error-600 hover:text-error-700"
|
||||
startIcon={<TrashBinIcon className="w-4 h-4" />}
|
||||
>
|
||||
<TrashBinIcon className="w-4 h-4 mr-1" />
|
||||
Delete Selected
|
||||
</Button>
|
||||
<Button variant="ghost" size="sm" onClick={() => setSelectedPages(new Set())}>
|
||||
|
||||
@@ -271,16 +271,16 @@ export default function PostEditor() {
|
||||
variant={activeTab === 'content' ? 'primary' : 'ghost'}
|
||||
size="sm"
|
||||
onClick={() => setActiveTab('content')}
|
||||
startIcon={<FileTextIcon className="w-4 h-4" />}
|
||||
>
|
||||
<FileTextIcon className="w-4 h-4" />
|
||||
Content
|
||||
</Button>
|
||||
<Button
|
||||
variant={activeTab === 'taxonomy' ? 'primary' : 'ghost'}
|
||||
size="sm"
|
||||
onClick={() => setActiveTab('taxonomy')}
|
||||
startIcon={<TagIcon className="w-4 h-4" />}
|
||||
>
|
||||
<TagIcon className="w-4 h-4" />
|
||||
Taxonomy & Cluster
|
||||
</Button>
|
||||
{content.id && (
|
||||
@@ -291,8 +291,8 @@ export default function PostEditor() {
|
||||
setActiveTab('validation');
|
||||
loadValidation();
|
||||
}}
|
||||
startIcon={<CheckCircleIcon className="w-4 h-4" />}
|
||||
>
|
||||
<CheckCircleIcon className="w-4 h-4" />
|
||||
Validation
|
||||
{validationResult && !validationResult.is_valid && (
|
||||
<span className="ml-2 px-2 py-0.5 text-xs bg-error-100 dark:bg-error-900 text-error-600 dark:text-error-400 rounded-full">
|
||||
|
||||
@@ -283,15 +283,15 @@ export default function PublishingQueue() {
|
||||
<ButtonGroupItem
|
||||
isActive={viewMode === 'list'}
|
||||
onClick={() => setViewMode('list')}
|
||||
startIcon={<ListIcon className="w-4 h-4" />}
|
||||
>
|
||||
<ListIcon className="w-4 h-4 mr-1.5" />
|
||||
List
|
||||
</ButtonGroupItem>
|
||||
<ButtonGroupItem
|
||||
isActive={viewMode === 'calendar'}
|
||||
onClick={() => setViewMode('calendar')}
|
||||
startIcon={<CalendarIcon className="w-4 h-4" />}
|
||||
>
|
||||
<CalendarIcon className="w-4 h-4 mr-1.5" />
|
||||
Calendar
|
||||
</ButtonGroupItem>
|
||||
</ButtonGroup>
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
} from '../../services/api';
|
||||
import WordPressIntegrationForm from '../../components/sites/WordPressIntegrationForm';
|
||||
import { integrationApi, SiteIntegration } from '../../services/integration.api';
|
||||
import { GridIcon, PlugInIcon, PaperPlaneIcon, DocsIcon, BoltIcon, FileIcon, ChevronDownIcon, CloseIcon, PlusIcon } from '../../icons';
|
||||
import { GridIcon, PlugInIcon, PaperPlaneIcon, DocsIcon, BoltIcon, FileIcon, ChevronDownIcon, CloseIcon, PlusIcon, RefreshCwIcon } from '../../icons';
|
||||
import Badge from '../../components/ui/badge/Badge';
|
||||
import { Dropdown } from '../../components/ui/dropdown/Dropdown';
|
||||
import { DropdownItem } from '../../components/ui/dropdown/DropdownItem';
|
||||
@@ -621,8 +621,8 @@ export default function SiteSettings() {
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
startIcon={<GridIcon className="w-4 h-4" />}
|
||||
>
|
||||
<GridIcon className="w-4 h-4 inline mr-2" />
|
||||
General
|
||||
</Button>
|
||||
<Button
|
||||
@@ -636,8 +636,8 @@ export default function SiteSettings() {
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
startIcon={<PlugInIcon className="w-4 h-4" />}
|
||||
>
|
||||
<PlugInIcon className="w-4 h-4 inline mr-2" />
|
||||
Integrations
|
||||
</Button>
|
||||
<Button
|
||||
@@ -651,8 +651,8 @@ export default function SiteSettings() {
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
startIcon={<PaperPlaneIcon className="w-4 h-4" />}
|
||||
>
|
||||
<PaperPlaneIcon className="w-4 h-4 inline mr-2" />
|
||||
Publishing
|
||||
</Button>
|
||||
{(wordPressIntegration || site?.wp_url || site?.wp_api_key || site?.hosting_type === 'wordpress') && (
|
||||
@@ -667,8 +667,8 @@ export default function SiteSettings() {
|
||||
? 'border-brand-500 text-brand-600 dark:text-brand-400'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'
|
||||
}`}
|
||||
startIcon={<FileIcon className="w-4 h-4" />}
|
||||
>
|
||||
<FileIcon className="w-4 h-4 inline mr-2" />
|
||||
Content Types
|
||||
</Button>
|
||||
)}
|
||||
@@ -951,21 +951,9 @@ export default function SiteSettings() {
|
||||
variant="outline"
|
||||
disabled={syncLoading || !(wordPressIntegration || site?.wp_url || site?.wp_api_key || site?.hosting_type === 'wordpress')}
|
||||
onClick={handleManualSync}
|
||||
className="flex items-center gap-2"
|
||||
startIcon={syncLoading ? <RefreshCwIcon className="w-4 h-4 animate-spin" /> : <RefreshCwIcon className="w-4 h-4" />}
|
||||
>
|
||||
{syncLoading ? (
|
||||
<>
|
||||
<div className="inline-block animate-spin rounded-full h-4 w-4 border-b-2 border-current"></div>
|
||||
<span>Syncing...</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
<span>Sync Structure</span>
|
||||
</>
|
||||
)}
|
||||
{syncLoading ? 'Syncing...' : 'Sync Structure'}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -252,8 +252,8 @@ export default function SyncDashboard() {
|
||||
size="sm"
|
||||
onClick={() => handleSync('to_external')}
|
||||
disabled={syncing || !integration.sync_enabled}
|
||||
startIcon={<ArrowRightIcon className="w-4 h-4" />}
|
||||
>
|
||||
<ArrowRightIcon className="w-4 h-4 mr-1" />
|
||||
Sync to WordPress
|
||||
</Button>
|
||||
<Button
|
||||
@@ -261,8 +261,8 @@ export default function SyncDashboard() {
|
||||
size="sm"
|
||||
onClick={() => handleSync('from_external')}
|
||||
disabled={syncing || !integration.sync_enabled}
|
||||
startIcon={<ArrowRightIcon className="w-4 h-4 rotate-180" />}
|
||||
>
|
||||
<ArrowRightIcon className="w-4 h-4 mr-1 rotate-180" />
|
||||
Sync from WordPress
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user