Sitesmith: AI site builder addon (frontend) #1
29
craft/src/panels/sitesmith/SitesmithButton.tsx
Normal file
29
craft/src/panels/sitesmith/SitesmithButton.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import { useSitesmith } from '../../hooks/useSitesmith';
|
||||
import { useEditorConfig } from '../../state/EditorConfigContext';
|
||||
|
||||
interface Props { onClick: () => void; }
|
||||
|
||||
export const SitesmithButton: React.FC<Props> = ({ onClick }) => {
|
||||
const cfg = useEditorConfig();
|
||||
const siteId = cfg.whpConfig?.siteId ?? 0;
|
||||
const { summary } = useSitesmith(siteId);
|
||||
const locked = summary?.status === 'DISABLED';
|
||||
const capped = summary?.status === 'CAP_REACHED';
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
className="topbar-btn sitesmith-btn"
|
||||
title={locked ? 'Sitesmith — paid addon (click to learn more)' : 'Sitesmith AI Builder'}
|
||||
style={{
|
||||
background: locked ? '#1f1f24' : 'linear-gradient(135deg, #6366f1, #8b5cf6)',
|
||||
color: '#fff', border: 'none', padding: '6px 12px', borderRadius: 6, cursor: 'pointer', fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
✨ Sitesmith
|
||||
{locked && <span aria-hidden style={{ marginLeft: 6, fontSize: 12 }}>🔒</span>}
|
||||
{capped && !locked && <span aria-hidden style={{ marginLeft: 6, fontSize: 11, opacity: 0.85 }}>(cap)</span>}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
@@ -6,6 +6,7 @@ import { usePages } from '../../state/PageContext';
|
||||
import { DeviceMode } from '../../types';
|
||||
import { TemplateModal } from './TemplateModal';
|
||||
import { HeadCodeModal } from './HeadCodeModal';
|
||||
import { SitesmithButton } from '../sitesmith/SitesmithButton';
|
||||
|
||||
interface TopBarProps {
|
||||
device: DeviceMode;
|
||||
@@ -26,6 +27,7 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange }) => {
|
||||
const [isDraft, setIsDraft] = useState(false);
|
||||
const [templateModalOpen, setTemplateModalOpen] = useState(false);
|
||||
const [headCodeModalOpen, setHeadCodeModalOpen] = useState(false);
|
||||
const [sitesmithOpen, setSitesmithOpen] = useState(false);
|
||||
const saveTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const publishTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const hasLoadedRef = useRef(false);
|
||||
@@ -239,6 +241,8 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange }) => {
|
||||
</span>
|
||||
)}
|
||||
|
||||
<SitesmithButton onClick={() => setSitesmithOpen(true)} />
|
||||
|
||||
<button
|
||||
className="topbar-btn primary"
|
||||
onClick={handleSave}
|
||||
@@ -269,6 +273,14 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange }) => {
|
||||
</div>
|
||||
<TemplateModal open={templateModalOpen} onClose={() => setTemplateModalOpen(false)} />
|
||||
<HeadCodeModal open={headCodeModalOpen} onClose={() => setHeadCodeModalOpen(false)} />
|
||||
{sitesmithOpen && (
|
||||
<div role="dialog" style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.6)', zIndex: 9000, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<div style={{ background: '#0f0f17', color: '#fff', padding: 32, borderRadius: 10 }}>
|
||||
<p>SitesmithModal will land in Task 20.</p>
|
||||
<button onClick={() => setSitesmithOpen(false)} style={{ background: '#7c3aed', color: '#fff', border: 'none', padding: '8px 14px', borderRadius: 6 }}>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user