Spaces:
Running
Running
File size: 2,901 Bytes
9fbe4a1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | import React, { useState, useMemo } from 'react';
import { MessageCircle } from 'lucide-react';
import { useAppConfig } from '../contexts/AppConfigContext';
import '../styles/IntakePanel.css';
/**
* First-session intake: Jerry's greeting + chips + optional free-text.
* Chips come from /api/config → chat_page.intake, filtered by guest persona when set.
*/
const IntakePanel = ({ onSubmit, guestPersona = null }) => {
const { config } = useAppConfig();
const intake = config?.chat_page?.intake || {};
const greeting =
intake.greeting ||
"You've contacted me today — what is it that I can help you with in cybersecurity?";
const chips = useMemo(() => {
const byPersona = intake.by_persona || {};
const personaKey = (guestPersona || '').toLowerCase();
const personaChips = personaKey && Array.isArray(byPersona[personaKey])
? byPersona[personaKey]
: null;
if (personaChips && personaChips.length > 0) return personaChips;
return Array.isArray(intake.chips) ? intake.chips : [];
}, [intake, guestPersona]);
const [freeText, setFreeText] = useState('');
const [showFreeText, setShowFreeText] = useState(false);
const handleChip = (chip) => {
if (chip.free_text) {
setShowFreeText(true);
return;
}
if (chip.prompt) onSubmit(chip.prompt);
};
const handleFreeSubmit = (e) => {
e.preventDefault();
const text = freeText.trim();
if (!text) return;
onSubmit(text);
setFreeText('');
};
return (
<div className="intake-panel" role="region" aria-label="Getting started">
<div className="intake-avatar" aria-hidden="true">
<MessageCircle size={18} />
</div>
<h2 className="intake-greeting">{greeting}</h2>
<p className="intake-sub">
Pick a starting point, or tell me in your own words.
</p>
<div className="intake-chips">
{chips.map((chip) => (
<button
key={chip.id}
type="button"
className={`intake-chip${chip.free_text ? ' intake-chip--other' : ''}`}
onClick={() => handleChip(chip)}
>
{chip.label}
</button>
))}
</div>
{(showFreeText || chips.length === 0) && (
<form className="intake-freetext" onSubmit={handleFreeSubmit}>
<label htmlFor="intake-free" className="sr-only">
Describe your cybersecurity need
</label>
<textarea
id="intake-free"
rows={3}
value={freeText}
onChange={(e) => setFreeText(e.target.value)}
placeholder="Tell me about the cybersecurity problem or goal you have today…"
/>
<button type="submit" className="intake-submit" disabled={!freeText.trim()}>
Start
</button>
</form>
)}
</div>
);
};
export default IntakePanel;
|