fix: Yield dashboard + Forge UI improvements
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
Yield: - Safely handle partner relationship to prevent errors Forge: - AI mode now default for Trader/Tycoon users - AI mode button moved to left (primary position) - "Describe your..." label now bright purple - Textarea border brighter for better visibility
This commit is contained in:
@ -774,6 +774,14 @@ async def list_partners(
|
||||
|
||||
def _domain_to_response(domain: YieldDomain) -> YieldDomainResponse:
|
||||
"""Convert YieldDomain model to response schema."""
|
||||
# Safely get partner name
|
||||
partner_name = None
|
||||
try:
|
||||
if domain.partner:
|
||||
partner_name = domain.partner.name
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return YieldDomainResponse(
|
||||
id=domain.id,
|
||||
domain=domain.domain,
|
||||
@ -781,7 +789,7 @@ def _domain_to_response(domain: YieldDomain) -> YieldDomainResponse:
|
||||
detected_intent=domain.detected_intent,
|
||||
intent_confidence=domain.intent_confidence,
|
||||
active_route=domain.active_route,
|
||||
partner_name=domain.partner.name if domain.partner else None,
|
||||
partner_name=partner_name,
|
||||
landing_template=getattr(domain, "landing_template", None),
|
||||
landing_headline=getattr(domain, "landing_headline", None),
|
||||
landing_intro=getattr(domain, "landing_intro", None),
|
||||
|
||||
@ -47,8 +47,8 @@ export function BrandableForgeTab({ showToast }: { showToast: (msg: string, type
|
||||
const tier = (subscription?.tier || '').toLowerCase()
|
||||
const hasAI = tier === 'trader' || tier === 'tycoon'
|
||||
|
||||
// Mode selection
|
||||
const [mode, setMode] = useState<'pattern' | 'ai'>('pattern')
|
||||
// Mode selection - AI mode by default if available
|
||||
const [mode, setMode] = useState<'pattern' | 'ai'>(hasAI ? 'ai' : 'pattern')
|
||||
|
||||
// Config
|
||||
const [pattern, setPattern] = useState('cvcvc')
|
||||
@ -143,7 +143,35 @@ export function BrandableForgeTab({ showToast }: { showToast: (msg: string, type
|
||||
|
||||
{/* Mode Selector */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
{/* Pattern Mode */}
|
||||
{/* AI Mode - First/Left */}
|
||||
<button
|
||||
onClick={() => hasAI && setMode('ai')}
|
||||
disabled={!hasAI}
|
||||
className={clsx(
|
||||
"relative p-5 border transition-all duration-300 text-left group overflow-hidden",
|
||||
!hasAI && "opacity-50 grayscale",
|
||||
mode === 'ai'
|
||||
? "border-purple-500 bg-purple-500/5 shadow-[0_0_30px_-10px_rgba(168,85,247,0.3)]"
|
||||
: "border-white/[0.08] bg-white/[0.01] hover:border-white/20 hover:bg-white/[0.03]"
|
||||
)}
|
||||
>
|
||||
{!hasAI && <div className="absolute top-2 right-2"><Lock className="w-3 h-3 text-white/20" /></div>}
|
||||
<div className="flex items-center gap-4 relative z-10">
|
||||
<div className={clsx(
|
||||
"w-12 h-12 flex items-center justify-center border transition-colors",
|
||||
mode === 'ai' ? "border-purple-500/40 bg-purple-500/10" : "border-white/10 bg-white/5"
|
||||
)}>
|
||||
<Brain className={clsx("w-6 h-6", mode === 'ai' ? "text-purple-400" : "text-white/30")} />
|
||||
</div>
|
||||
<div>
|
||||
<p className={clsx("font-bold font-mono text-sm tracking-tight", mode === 'ai' ? "text-purple-400" : "text-white/70")}>Vision Core AI</p>
|
||||
<p className="text-[10px] font-mono text-white/30 uppercase tracking-widest mt-0.5">Concept to Name</p>
|
||||
</div>
|
||||
</div>
|
||||
{mode === 'ai' && <div className="absolute top-0 right-0 w-2 h-2 bg-purple-500" />}
|
||||
</button>
|
||||
|
||||
{/* Pattern Mode - Second/Right */}
|
||||
<button
|
||||
onClick={() => setMode('pattern')}
|
||||
className={clsx(
|
||||
@ -167,34 +195,6 @@ export function BrandableForgeTab({ showToast }: { showToast: (msg: string, type
|
||||
</div>
|
||||
{mode === 'pattern' && <div className="absolute top-0 right-0 w-2 h-2 bg-accent" />}
|
||||
</button>
|
||||
|
||||
{/* AI Mode */}
|
||||
<button
|
||||
onClick={() => hasAI && setMode('ai')}
|
||||
disabled={!hasAI}
|
||||
className={clsx(
|
||||
"relative p-5 border transition-all duration-300 text-left group overflow-hidden",
|
||||
!hasAI && "opacity-50 grayscale",
|
||||
mode === 'ai'
|
||||
? "border-purple-500 bg-purple-500/5 shadow-[0_0_30px_-10px_rgba(168,85,247,0.2)]"
|
||||
: "border-white/[0.08] bg-white/[0.01] hover:border-white/20 hover:bg-white/[0.03]"
|
||||
)}
|
||||
>
|
||||
{!hasAI && <div className="absolute top-2 right-2"><Lock className="w-3 h-3 text-white/20" /></div>}
|
||||
<div className="flex items-center gap-4 relative z-10">
|
||||
<div className={clsx(
|
||||
"w-12 h-12 flex items-center justify-center border transition-colors",
|
||||
mode === 'ai' ? "border-purple-500/30 bg-purple-500/10" : "border-white/10 bg-white/5"
|
||||
)}>
|
||||
<Brain className={clsx("w-6 h-6", mode === 'ai' ? "text-purple-400" : "text-white/30")} />
|
||||
</div>
|
||||
<div>
|
||||
<p className={clsx("font-bold font-mono text-sm tracking-tight", mode === 'ai' ? "text-purple-400" : "text-white/70")}>Vision Core AI</p>
|
||||
<p className="text-[10px] font-mono text-white/30 uppercase tracking-widest mt-0.5">Concept to Name</p>
|
||||
</div>
|
||||
</div>
|
||||
{mode === 'ai' && <div className="absolute top-0 right-0 w-2 h-2 bg-purple-500" />}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Config Panel */}
|
||||
@ -236,13 +236,13 @@ export function BrandableForgeTab({ showToast }: { showToast: (msg: string, type
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
<span className="text-[10px] font-mono text-purple-300/40 uppercase tracking-widest">Describe Your Identity Concept</span>
|
||||
<span className="text-[10px] font-mono text-purple-400 uppercase tracking-widest font-bold">Describe Your Identity Concept</span>
|
||||
<textarea
|
||||
value={concept}
|
||||
onChange={(e) => setConcept(e.target.value)}
|
||||
placeholder="e.g., A minimalist AI agent for legal risk management..."
|
||||
rows={3}
|
||||
className="w-full px-4 py-3 bg-white/[0.03] border border-purple-500/20 text-sm font-mono text-white placeholder:text-white/10 outline-none focus:border-purple-500/50 resize-none transition-all"
|
||||
className="w-full px-4 py-3 bg-white/[0.03] border border-purple-500/40 text-sm font-mono text-white placeholder:text-white/20 outline-none focus:border-purple-500 resize-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user