diff --git a/apps/rowboat/app/projects/select/app.tsx b/apps/rowboat/app/projects/select/app.tsx index 0171ba1b..0367ac3f 100644 --- a/apps/rowboat/app/projects/select/app.tsx +++ b/apps/rowboat/app/projects/select/app.tsx @@ -7,15 +7,27 @@ import { listProjects, createProject, createProjectFromPrompt } from "../../acti import { useRouter } from 'next/navigation'; import { tokens } from "@/app/styles/design-tokens"; import clsx from 'clsx'; -import { templates } from "@/app/lib/project_templates"; +import { templates, starting_copilot_prompts } from "@/app/lib/project_templates"; import { SectionHeading } from "@/components/ui/section-heading"; import { Textarea } from "@/components/ui/textarea"; -import { TemplateCardsList } from "./components/template-cards-list"; import { SearchProjects } from "./components/search-projects"; import { CustomPromptCard } from "./components/custom-prompt-card"; import { Submit } from "./components/submit-button"; import { PageHeading } from "@/components/ui/page-heading"; -import { ChevronDown, ChevronUp } from "lucide-react"; + +const sectionHeaderStyles = clsx( + "text-sm font-medium", + "text-gray-900 dark:text-gray-100" +); +const textareaStyles = clsx( + "w-full", + "rounded-lg p-3", + "border border-gray-200 dark:border-gray-700", + "bg-white dark:bg-gray-800", + "hover:bg-gray-50 dark:hover:bg-gray-750", + "focus:shadow-inner focus:ring-2 focus:ring-indigo-500/20 dark:focus:ring-indigo-400/20", + "placeholder:text-gray-400 dark:placeholder:text-gray-500" +); export default function App() { const [projects, setProjects] = useState[]>([]); @@ -24,15 +36,19 @@ export default function App() { const [selectedCard, setSelectedCard] = useState<'custom' | any>('custom'); const [customPrompt, setCustomPrompt] = useState("Create a customer support assistant with one example agent"); const [name, setName] = useState(""); - const [defaultName, setDefaultName] = useState('Untitled 1'); + const [defaultName, setDefaultName] = useState('Assistant 1'); const [isExamplesExpanded, setIsExamplesExpanded] = useState(false); + const [selectedTemplate, setSelectedTemplate] = useState('blank'); + const [showCustomPrompt, setShowCustomPrompt] = useState(false); + const [promptError, setPromptError] = useState(null); + const [hasEditedPrompt, setHasEditedPrompt] = useState(false); - const getNextUntitledNumber = (projects: z.infer[]) => { + const getNextAssistantNumber = (projects: z.infer[]) => { const untitledProjects = projects .map(p => p.name) - .filter(name => name.startsWith('Untitled ')) + .filter(name => name.startsWith('Assistant ')) .map(name => { - const num = parseInt(name.replace('Untitled ', '')); + const num = parseInt(name.replace('Assistant ', '')); return isNaN(num) ? 0 : num; }); @@ -54,8 +70,8 @@ export default function App() { setProjects(sortedProjects); setIsLoading(false); - const nextNumber = getNextUntitledNumber(sortedProjects); - const newDefaultName = `Untitled ${nextNumber}`; + const nextNumber = getNextAssistantNumber(sortedProjects); + const newDefaultName = `Assistant ${nextNumber}`; setDefaultName(newDefaultName); setName(newDefaultName); } @@ -80,44 +96,66 @@ export default function App() { const router = useRouter(); - async function handleSubmit(formData: FormData) { - // Check if it's a template (from templates object) or a copilot prompt - const isTemplate = selectedCard?.id && selectedCard.id in templates; - - if (selectedCard === 'custom' || !isTemplate) { - // Handle custom prompt or copilot starting prompts - console.log('Creating project from prompt'); - try { - const newFormData = new FormData(); - newFormData.append('name', name); - newFormData.append('prompt', selectedCard === 'custom' ? customPrompt : selectedCard.prompt); - - const response = await createProjectFromPrompt(newFormData); - - if (!response?.id) { - throw new Error('Project creation failed'); - } - - // Store prompt in local storage - const promptToStore = selectedCard === 'custom' ? customPrompt : selectedCard.prompt; - if (promptToStore) { - localStorage.setItem(`project_prompt_${response.id}`, promptToStore); - } - router.push(`/projects/${response.id}/workflow`); - } catch (error) { - console.error('Error creating project:', error); - } + const handleTemplateChange = (e: React.ChangeEvent) => { + const value = e.target.value; + setSelectedTemplate(value); + + if (value === 'blank') { + setShowCustomPrompt(false); + setCustomPrompt(''); + } else if (value === 'custom') { + setShowCustomPrompt(true); + setCustomPrompt(''); } else { - // Handle regular template - console.log('Creating template project'); - try { + // Handle example prompts + const prompt = starting_copilot_prompts[value]; + if (prompt) { + setShowCustomPrompt(true); + setCustomPrompt(prompt); + } + } + }; + + const validatePrompt = (value: string) => { + if (!value.trim()) { + return { valid: false, errorMessage: "Prompt cannot be empty" }; + } + return { valid: true }; + }; + + async function handleSubmit(formData: FormData) { + try { + // Validate prompt if custom prompt section is shown + if (showCustomPrompt && !customPrompt.trim()) { + setPromptError("Prompt cannot be empty"); + return; + } + + let response; + + if (selectedTemplate === 'blank') { const newFormData = new FormData(); newFormData.append('name', name); - newFormData.append('template', selectedCard.id); - return await createProject(newFormData); - } catch (error) { - console.error('Error creating project:', error); + newFormData.append('template', 'default'); + response = await createProject(newFormData); + } else { + const newFormData = new FormData(); + newFormData.append('name', name); + newFormData.append('prompt', customPrompt); + response = await createProjectFromPrompt(newFormData); + + if (response?.id && customPrompt) { + localStorage.setItem(`project_prompt_${response.id}`, customPrompt); + } } + + if (!response?.id) { + throw new Error('Project creation failed'); + } + + router.push(`/projects/${response.id}/workflow`); + } catch (error) { + console.error('Error creating project:', error); } } @@ -159,75 +197,124 @@ export default function App() { {/* Right side: Project Creation */}
-
-
- - Create a new project - -
-
- -
+
+ + Create a new project +
-
- Name your assistant -