componenets standardization 1
This commit is contained in:
@@ -9,10 +9,14 @@ 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 Label from '../../components/form/Label';
|
||||
import InputField from '../../components/form/input/InputField';
|
||||
import Select from '../../components/form/Select';
|
||||
import SelectDropdown from '../../components/form/SelectDropdown';
|
||||
import Checkbox from '../../components/form/input/Checkbox';
|
||||
import TextArea from '../../components/form/input/TextArea';
|
||||
import Switch from '../../components/form/switch/Switch';
|
||||
import { useToast } from '../../components/ui/toast/ToastContainer';
|
||||
import {
|
||||
fetchAPI,
|
||||
@@ -23,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 } from '../../icons';
|
||||
import { GridIcon, PlugInIcon, PaperPlaneIcon, DocsIcon, BoltIcon, FileIcon, ChevronDownIcon, CloseIcon, PlusIcon } from '../../icons';
|
||||
import Badge from '../../components/ui/badge/Badge';
|
||||
import { Dropdown } from '../../components/ui/dropdown/Dropdown';
|
||||
import { DropdownItem } from '../../components/ui/dropdown/DropdownItem';
|
||||
@@ -554,10 +558,11 @@ export default function SiteSettings() {
|
||||
{/* Site Selector - Only show if more than 1 site */}
|
||||
{!sitesLoading && sites.length > 1 && (
|
||||
<div className="relative inline-block">
|
||||
<button
|
||||
<Button
|
||||
ref={siteSelectorRef}
|
||||
onClick={() => setIsSiteSelectorOpen(!isSiteSelectorOpen)}
|
||||
className="flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-brand-200 rounded-lg hover:bg-brand-50 hover:border-brand-300 dark:bg-gray-800 dark:text-gray-300 dark:border-brand-700/50 dark:hover:bg-brand-500/10 dark:hover:border-brand-600/50 transition-colors"
|
||||
variant="outline"
|
||||
className="flex items-center gap-2"
|
||||
aria-label="Switch site"
|
||||
>
|
||||
<span className="flex items-center gap-2">
|
||||
@@ -565,7 +570,7 @@ export default function SiteSettings() {
|
||||
<span className="max-w-[150px] truncate">{site?.name || 'Select Site'}</span>
|
||||
</span>
|
||||
<ChevronDownIcon className={`w-4 h-4 text-brand-500 dark:text-brand-400 transition-transform ${isSiteSelectorOpen ? 'rotate-180' : ''}`} />
|
||||
</button>
|
||||
</Button>
|
||||
<Dropdown
|
||||
isOpen={isSiteSelectorOpen}
|
||||
onClose={() => setIsSiteSelectorOpen(false)}
|
||||
@@ -605,13 +610,13 @@ export default function SiteSettings() {
|
||||
{/* Tabs */}
|
||||
<div className="mb-6 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="flex gap-4">
|
||||
<button
|
||||
type="button"
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
setActiveTab('general');
|
||||
navigate(`/sites/${siteId}/settings`, { replace: true });
|
||||
}}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
className={`px-4 py-2 font-medium border-b-2 rounded-none transition-colors ${
|
||||
activeTab === 'general'
|
||||
? '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'
|
||||
@@ -619,14 +624,14 @@ export default function SiteSettings() {
|
||||
>
|
||||
<GridIcon className="w-4 h-4 inline mr-2" />
|
||||
General
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
setActiveTab('integrations');
|
||||
navigate(`/sites/${siteId}/settings?tab=integrations`, { replace: true });
|
||||
}}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
className={`px-4 py-2 font-medium border-b-2 rounded-none transition-colors ${
|
||||
activeTab === 'integrations'
|
||||
? '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'
|
||||
@@ -634,14 +639,14 @@ export default function SiteSettings() {
|
||||
>
|
||||
<PlugInIcon className="w-4 h-4 inline mr-2" />
|
||||
Integrations
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
setActiveTab('publishing');
|
||||
navigate(`/sites/${siteId}/settings?tab=publishing`, { replace: true });
|
||||
}}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
className={`px-4 py-2 font-medium border-b-2 rounded-none transition-colors ${
|
||||
activeTab === 'publishing'
|
||||
? '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'
|
||||
@@ -649,15 +654,15 @@ export default function SiteSettings() {
|
||||
>
|
||||
<PaperPlaneIcon className="w-4 h-4 inline mr-2" />
|
||||
Publishing
|
||||
</button>
|
||||
</Button>
|
||||
{(wordPressIntegration || site?.wp_url || site?.wp_api_key || site?.hosting_type === 'wordpress') && (
|
||||
<button
|
||||
type="button"
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
setActiveTab('content-types');
|
||||
navigate(`/sites/${siteId}/settings?tab=content-types`, { replace: true });
|
||||
}}
|
||||
className={`px-4 py-2 font-medium border-b-2 transition-colors ${
|
||||
className={`px-4 py-2 font-medium border-b-2 rounded-none transition-colors ${
|
||||
activeTab === 'content-types'
|
||||
? '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'
|
||||
@@ -665,7 +670,7 @@ export default function SiteSettings() {
|
||||
>
|
||||
<FileIcon className="w-4 h-4 inline mr-2" />
|
||||
Content Types
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -696,17 +701,15 @@ export default function SiteSettings() {
|
||||
</p>
|
||||
</div>
|
||||
<label className="relative inline-flex items-center cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
<Switch
|
||||
label=""
|
||||
checked={publishingSettings.auto_approval_enabled}
|
||||
onChange={(e) => {
|
||||
const newSettings = { ...publishingSettings, auto_approval_enabled: e.target.checked };
|
||||
onChange={(checked) => {
|
||||
const newSettings = { ...publishingSettings, auto_approval_enabled: checked };
|
||||
setPublishingSettings(newSettings);
|
||||
savePublishingSettings({ auto_approval_enabled: e.target.checked });
|
||||
savePublishingSettings({ auto_approval_enabled: checked });
|
||||
}}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-300 dark:peer-focus:ring-brand-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-brand-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -721,17 +724,15 @@ export default function SiteSettings() {
|
||||
</p>
|
||||
</div>
|
||||
<label className="relative inline-flex items-center cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
<Switch
|
||||
label=""
|
||||
checked={publishingSettings.auto_publish_enabled}
|
||||
onChange={(e) => {
|
||||
const newSettings = { ...publishingSettings, auto_publish_enabled: e.target.checked };
|
||||
onChange={(checked) => {
|
||||
const newSettings = { ...publishingSettings, auto_publish_enabled: checked };
|
||||
setPublishingSettings(newSettings);
|
||||
savePublishingSettings({ auto_publish_enabled: e.target.checked });
|
||||
savePublishingSettings({ auto_publish_enabled: checked });
|
||||
}}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-brand-300 dark:peer-focus:ring-brand-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-brand-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -745,7 +746,7 @@ export default function SiteSettings() {
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<Label>Daily Limit</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="number"
|
||||
min="1"
|
||||
max="50"
|
||||
@@ -754,14 +755,12 @@ export default function SiteSettings() {
|
||||
const value = Math.max(1, Math.min(50, parseInt(e.target.value) || 1));
|
||||
setPublishingSettings({ ...publishingSettings, daily_publish_limit: value });
|
||||
}}
|
||||
onBlur={() => savePublishingSettings({ daily_publish_limit: publishingSettings.daily_publish_limit })}
|
||||
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-brand-500 focus:border-brand-500"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">Articles per day</p>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Weekly Limit</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="number"
|
||||
min="1"
|
||||
max="200"
|
||||
@@ -770,14 +769,12 @@ export default function SiteSettings() {
|
||||
const value = Math.max(1, Math.min(200, parseInt(e.target.value) || 1));
|
||||
setPublishingSettings({ ...publishingSettings, weekly_publish_limit: value });
|
||||
}}
|
||||
onBlur={() => savePublishingSettings({ weekly_publish_limit: publishingSettings.weekly_publish_limit })}
|
||||
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-brand-500 focus:border-brand-500"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">Articles per week</p>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Monthly Limit</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="number"
|
||||
min="1"
|
||||
max="500"
|
||||
@@ -786,8 +783,6 @@ export default function SiteSettings() {
|
||||
const value = Math.max(1, Math.min(500, parseInt(e.target.value) || 1));
|
||||
setPublishingSettings({ ...publishingSettings, monthly_publish_limit: value });
|
||||
}}
|
||||
onBlur={() => savePublishingSettings({ monthly_publish_limit: publishingSettings.monthly_publish_limit })}
|
||||
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-brand-500 focus:border-brand-500"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">Articles per month</p>
|
||||
</div>
|
||||
@@ -810,9 +805,11 @@ export default function SiteSettings() {
|
||||
{ value: 'sat', label: 'Sat' },
|
||||
{ value: 'sun', label: 'Sun' },
|
||||
].map((day) => (
|
||||
<button
|
||||
<Button
|
||||
key={day.value}
|
||||
type="button"
|
||||
variant={(publishingSettings.publish_days || []).includes(day.value) ? 'primary' : 'outline'}
|
||||
tone="brand"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
const currentDays = publishingSettings.publish_days || [];
|
||||
const newDays = currentDays.includes(day.value)
|
||||
@@ -821,14 +818,9 @@ export default function SiteSettings() {
|
||||
setPublishingSettings({ ...publishingSettings, publish_days: newDays });
|
||||
savePublishingSettings({ publish_days: newDays });
|
||||
}}
|
||||
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
|
||||
(publishingSettings.publish_days || []).includes(day.value)
|
||||
? 'bg-brand-600 text-white'
|
||||
: 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'
|
||||
}`}
|
||||
>
|
||||
{day.label}
|
||||
</button>
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@@ -842,7 +834,7 @@ export default function SiteSettings() {
|
||||
<div className="space-y-3">
|
||||
{(publishingSettings.publish_time_slots || ['09:00', '14:00', '18:00']).map((time: string, index: number) => (
|
||||
<div key={index} className="flex items-center gap-2">
|
||||
<input
|
||||
<InputField
|
||||
type="time"
|
||||
value={time}
|
||||
onChange={(e) => {
|
||||
@@ -850,40 +842,36 @@ export default function SiteSettings() {
|
||||
newSlots[index] = e.target.value;
|
||||
setPublishingSettings({ ...publishingSettings, publish_time_slots: newSlots });
|
||||
}}
|
||||
onBlur={() => savePublishingSettings({ publish_time_slots: publishingSettings.publish_time_slots })}
|
||||
className="px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-brand-500 focus:border-brand-500"
|
||||
/>
|
||||
{(publishingSettings.publish_time_slots || []).length > 1 && (
|
||||
<button
|
||||
type="button"
|
||||
<IconButton
|
||||
icon={<CloseIcon className="w-5 h-5" />}
|
||||
variant="ghost"
|
||||
tone="danger"
|
||||
size="sm"
|
||||
title="Remove time slot"
|
||||
onClick={() => {
|
||||
const newSlots = (publishingSettings.publish_time_slots || []).filter((_: string, i: number) => i !== index);
|
||||
setPublishingSettings({ ...publishingSettings, publish_time_slots: newSlots });
|
||||
savePublishingSettings({ publish_time_slots: newSlots });
|
||||
}}
|
||||
className="p-2 text-gray-400 hover:text-error-500 transition-colors"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
<button
|
||||
type="button"
|
||||
<Button
|
||||
variant="ghost"
|
||||
tone="brand"
|
||||
size="sm"
|
||||
startIcon={<PlusIcon className="w-4 h-4" />}
|
||||
onClick={() => {
|
||||
const newSlots = [...(publishingSettings.publish_time_slots || []), '12:00'];
|
||||
setPublishingSettings({ ...publishingSettings, publish_time_slots: newSlots });
|
||||
savePublishingSettings({ publish_time_slots: newSlots });
|
||||
}}
|
||||
className="text-sm text-brand-600 hover:text-brand-700 font-medium flex items-center gap-1"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
Add Time Slot
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1084,32 +1072,29 @@ export default function SiteSettings() {
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label>Site Name</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.name}
|
||||
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Slug</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.slug}
|
||||
onChange={(e) => setFormData({ ...formData, slug: e.target.value })}
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Site URL</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.site_url}
|
||||
onChange={(e) => setFormData({ ...formData, site_url: e.target.value })}
|
||||
placeholder="https://example.com"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1134,7 +1119,7 @@ export default function SiteSettings() {
|
||||
<div>
|
||||
<Checkbox
|
||||
checked={formData.is_active}
|
||||
onChange={(e) => setFormData({ ...formData, is_active: e.target.checked })}
|
||||
onChange={(checked) => setFormData({ ...formData, is_active: checked })}
|
||||
label="Active"
|
||||
/>
|
||||
</div>
|
||||
@@ -1150,13 +1135,12 @@ export default function SiteSettings() {
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label>Meta Title</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.meta_title}
|
||||
onChange={(e) => setFormData({ ...formData, meta_title: e.target.value })}
|
||||
placeholder="SEO title (recommended: 50-60 characters)"
|
||||
maxLength={60}
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
max="60"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
{formData.meta_title.length}/60 characters
|
||||
@@ -1180,12 +1164,11 @@ export default function SiteSettings() {
|
||||
|
||||
<div>
|
||||
<Label>Meta Keywords (comma-separated)</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.meta_keywords}
|
||||
onChange={(e) => setFormData({ ...formData, meta_keywords: e.target.value })}
|
||||
placeholder="keyword1, keyword2, keyword3"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
Separate keywords with commas
|
||||
@@ -1203,12 +1186,11 @@ export default function SiteSettings() {
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label>OG Title</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.og_title}
|
||||
onChange={(e) => setFormData({ ...formData, og_title: e.target.value })}
|
||||
placeholder="Open Graph title"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1225,12 +1207,11 @@ export default function SiteSettings() {
|
||||
|
||||
<div>
|
||||
<Label>OG Image URL</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="url"
|
||||
value={formData.og_image}
|
||||
onChange={(e) => setFormData({ ...formData, og_image: e.target.value })}
|
||||
placeholder="https://example.com/image.jpg"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
Recommended: 1200x630px image
|
||||
@@ -1253,12 +1234,11 @@ export default function SiteSettings() {
|
||||
|
||||
<div>
|
||||
<Label>OG Site Name</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.og_site_name}
|
||||
onChange={(e) => setFormData({ ...formData, og_site_name: e.target.value })}
|
||||
placeholder="Site name for social sharing"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1288,12 +1268,11 @@ export default function SiteSettings() {
|
||||
|
||||
<div>
|
||||
<Label>Schema Name</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.schema_name}
|
||||
onChange={(e) => setFormData({ ...formData, schema_name: e.target.value })}
|
||||
placeholder="Organization name"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1310,34 +1289,31 @@ export default function SiteSettings() {
|
||||
|
||||
<div>
|
||||
<Label>Schema URL</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="url"
|
||||
value={formData.schema_url}
|
||||
onChange={(e) => setFormData({ ...formData, schema_url: e.target.value })}
|
||||
placeholder="https://example.com"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Schema Logo URL</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="url"
|
||||
value={formData.schema_logo}
|
||||
onChange={(e) => setFormData({ ...formData, schema_logo: e.target.value })}
|
||||
placeholder="https://example.com/logo.png"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Same As URLs (comma-separated)</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.schema_same_as}
|
||||
onChange={(e) => setFormData({ ...formData, schema_same_as: e.target.value })}
|
||||
placeholder="https://facebook.com/page, https://twitter.com/page"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
Social media profiles and other related URLs
|
||||
@@ -1359,21 +1335,18 @@ export default function SiteSettings() {
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
Select Industry
|
||||
</label>
|
||||
<select
|
||||
value={selectedIndustry}
|
||||
onChange={(e) => {
|
||||
setSelectedIndustry(e.target.value);
|
||||
<Select
|
||||
options={industries.map((industry) => ({
|
||||
value: industry.slug,
|
||||
label: industry.name,
|
||||
}))}
|
||||
placeholder="Select an industry..."
|
||||
defaultValue={selectedIndustry}
|
||||
onChange={(value) => {
|
||||
setSelectedIndustry(value);
|
||||
setSelectedSectors([]);
|
||||
}}
|
||||
className="h-9 w-full rounded-lg border border-gray-300 bg-transparent px-3 py-2 text-sm shadow-theme-xs text-gray-800 placeholder:text-gray-400 focus:border-brand-300 focus:outline-hidden focus:ring-3 focus:ring-brand-500/10 dark:border-gray-700 dark:bg-gray-900 dark:text-white/90 dark:placeholder:text-white/30 dark:focus:border-brand-800"
|
||||
>
|
||||
<option value="">Select an industry...</option>
|
||||
{industries.map((industry) => (
|
||||
<option key={industry.slug} value={industry.slug}>
|
||||
{industry.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
/>
|
||||
{selectedIndustry && (
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
{industries.find(i => i.slug === selectedIndustry)?.description}
|
||||
@@ -1388,15 +1361,14 @@ export default function SiteSettings() {
|
||||
</label>
|
||||
<div className="space-y-2 max-h-64 overflow-y-auto border border-gray-200 rounded-lg p-4 dark:border-gray-700">
|
||||
{getIndustrySectors().map((sector) => (
|
||||
<label
|
||||
<div
|
||||
key={sector.slug}
|
||||
className="flex items-start space-x-3 p-3 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 cursor-pointer"
|
||||
className="flex items-start space-x-3 p-3 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
<Checkbox
|
||||
checked={selectedSectors.includes(sector.slug)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
onChange={(checked) => {
|
||||
if (checked) {
|
||||
if (selectedSectors.length >= 5) {
|
||||
toast.error('Maximum 5 sectors allowed per site');
|
||||
return;
|
||||
@@ -1406,7 +1378,6 @@ export default function SiteSettings() {
|
||||
setSelectedSectors(selectedSectors.filter(s => s !== sector.slug));
|
||||
}
|
||||
}}
|
||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-brand-600 focus:ring-brand-500"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<div className="font-medium text-sm text-gray-900 dark:text-white">
|
||||
@@ -1416,7 +1387,7 @@ export default function SiteSettings() {
|
||||
{sector.description}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-2 text-xs text-gray-500 dark:text-gray-400">
|
||||
@@ -1447,13 +1418,12 @@ export default function SiteSettings() {
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label>Meta Title</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.meta_title}
|
||||
onChange={(e) => setFormData({ ...formData, meta_title: e.target.value })}
|
||||
placeholder="SEO title (recommended: 50-60 characters)"
|
||||
maxLength={60}
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
max="60"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
{formData.meta_title.length}/60 characters
|
||||
@@ -1477,12 +1447,11 @@ export default function SiteSettings() {
|
||||
|
||||
<div>
|
||||
<Label>Meta Keywords (comma-separated)</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.meta_keywords}
|
||||
onChange={(e) => setFormData({ ...formData, meta_keywords: e.target.value })}
|
||||
placeholder="keyword1, keyword2, keyword3"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
Separate keywords with commas
|
||||
@@ -1498,12 +1467,11 @@ export default function SiteSettings() {
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label>OG Title</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.og_title}
|
||||
onChange={(e) => setFormData({ ...formData, og_title: e.target.value })}
|
||||
placeholder="Open Graph title"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1520,12 +1488,11 @@ export default function SiteSettings() {
|
||||
|
||||
<div>
|
||||
<Label>OG Image URL</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="url"
|
||||
value={formData.og_image}
|
||||
onChange={(e) => setFormData({ ...formData, og_image: e.target.value })}
|
||||
placeholder="https://example.com/image.jpg"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
Recommended: 1200x630px image
|
||||
@@ -1542,18 +1509,17 @@ export default function SiteSettings() {
|
||||
{ value: 'product', label: 'Product' },
|
||||
]}
|
||||
value={formData.og_type}
|
||||
onChange={(e) => setFormData({ ...formData, og_type: e.target.value })}
|
||||
onChange={(value) => setFormData({ ...formData, og_type: value })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>OG Site Name</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.og_site_name}
|
||||
onChange={(e) => setFormData({ ...formData, og_site_name: e.target.value })}
|
||||
placeholder="Site name for social sharing"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1575,18 +1541,17 @@ export default function SiteSettings() {
|
||||
{ value: 'NGO', label: 'NGO' },
|
||||
]}
|
||||
value={formData.schema_type}
|
||||
onChange={(e) => setFormData({ ...formData, schema_type: e.target.value })}
|
||||
onChange={(value) => setFormData({ ...formData, schema_type: value })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Schema Name</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.schema_name}
|
||||
onChange={(e) => setFormData({ ...formData, schema_name: e.target.value })}
|
||||
placeholder="Organization name"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1603,34 +1568,31 @@ export default function SiteSettings() {
|
||||
|
||||
<div>
|
||||
<Label>Schema URL</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="url"
|
||||
value={formData.schema_url}
|
||||
onChange={(e) => setFormData({ ...formData, schema_url: e.target.value })}
|
||||
placeholder="https://example.com"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Schema Logo URL</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="url"
|
||||
value={formData.schema_logo}
|
||||
onChange={(e) => setFormData({ ...formData, schema_logo: e.target.value })}
|
||||
placeholder="https://example.com/logo.png"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Same As URLs (comma-separated)</Label>
|
||||
<input
|
||||
<InputField
|
||||
type="text"
|
||||
value={formData.schema_same_as}
|
||||
onChange={(e) => setFormData({ ...formData, schema_same_as: e.target.value })}
|
||||
placeholder="https://facebook.com/page, https://twitter.com/page"
|
||||
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
Social media profiles and other related URLs
|
||||
|
||||
Reference in New Issue
Block a user