- );
-}
diff --git a/components/AIMode/DocumentPane.tsx b/components/AIMode/DocumentPane.tsx
index c99494bf3..0db8c753e 100644
--- a/components/AIMode/DocumentPane.tsx
+++ b/components/AIMode/DocumentPane.tsx
@@ -12,11 +12,7 @@ import {
usePublishingCompletion,
} from '@/components/Notebook/PublishingForm';
import { ButtonGroup } from '@/components/ui/ButtonGroup';
-import {
- PublishingHostProvider,
- type PublishingDefaultArticleType,
- type PublishingHost,
-} from '@/contexts/PublishingHostContext';
+import { PublishingHostProvider, type PublishingHost } from '@/contexts/PublishingHostContext';
import { useNoteDetailsSaver } from '@/hooks/useNoteDetailsSaver';
import { NoteReviewControls } from '@/components/Notebook/NoteReview/NoteReviewControls';
import { noteDiffPersistableDoc } from '@/components/Notebook/NoteReview/noteDiffOverlay';
@@ -48,8 +44,6 @@ interface DocumentPaneProps {
readonly chat: AgentChat | null;
readonly view: DocumentPaneView;
readonly onViewChange: (view: DocumentPaneView) => void;
- /** Work type to preselect in the details form for a note without one. */
- readonly defaultArticleType?: PublishingDefaultArticleType | null;
/**
* A column beside the chat, or the drawer below the tablet breakpoint. The
* drawer trades the block strip for a Document | Details switch and keeps
@@ -80,7 +74,6 @@ export function DocumentPane({
chat,
view,
onViewChange,
- defaultArticleType = null,
presentation = 'pane',
publishControlsSlot = null,
readOnly = false,
@@ -143,9 +136,8 @@ export function DocumentPane({
isLoading: loading,
saveDetailsSoon,
saveDetailsNow,
- defaultArticleType,
}),
- [content, editor, loading, saveDetailsSoon, saveDetailsNow, defaultArticleType]
+ [content, editor, loading, saveDetailsSoon, saveDetailsNow]
);
const persistEditorState = useCallback(async () => {
diff --git a/components/AIMode/copy.ts b/components/AIMode/copy.ts
index 93caea86f..7a992a53e 100644
--- a/components/AIMode/copy.ts
+++ b/components/AIMode/copy.ts
@@ -1,13 +1,8 @@
-import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
-import {
- faBullhorn,
- faFileSignature,
- faMagnifyingGlassDollar,
-} from '@fortawesome/pro-light-svg-icons';
+import type { FundingIntent } from '@/components/Funding/fundingDirection';
/**
* User-facing copy for AI Mode, in one place so the product name and the
- * empty-state wording can change without touching components.
+ * new-conversation wording can change without touching components.
*/
export const AI_MODE_NAME = 'ResearchHub AI';
@@ -15,46 +10,14 @@ export const AI_MODE_NAME = 'ResearchHub AI';
export const aiModeGreeting = (firstName: string | null | undefined): string =>
firstName?.trim() ? `Welcome, ${firstName.trim()}` : 'Welcome';
-export interface StarterPrompt {
- readonly id: string;
- readonly title: string;
- readonly description: string;
- /** Same icon family as the sidebar's Publish menu. */
- readonly icon: IconDefinition;
- /** Sent as the conversation's first message when the card is picked. */
- readonly message: string;
-}
-
-/**
- * Starter cards for the new-conversation screen. Picking one starts the
- * conversation with its message; the backend does not supply suggestions.
- * Titles and subtext mirror the sidebar's Publish menu.
- */
-export const AI_MODE_STARTER_PROMPTS: readonly StarterPrompt[] = [
- {
- id: 'draft-rfp',
- title: 'Draft a Request for Proposal',
- description: 'Fund specific research you care about',
- icon: faBullhorn,
- message:
- 'Help me draft a request for proposals. Ask me for anything you still need to know about ' +
- 'the work I want to fund, then create a note and write the RFP into it.',
- },
- {
- id: 'draft-proposal',
- title: 'Draft a Research Proposal',
- description: 'Raise money for your research',
- icon: faFileSignature,
- message:
- 'Help me draft a research proposal. Ask me for anything you still need to know about the ' +
- 'work, then create a note and write the proposal into it, starting with three hypotheses.',
+/** What the intent toggle calls each side, and what the composer asks for. */
+export const INTENT_COPY: Record = {
+ fund: {
+ label: 'I want to fund',
+ placeholder: 'Describe the research you want to fund…',
},
- {
- id: 'funding',
- title: 'Find me funding',
- description: 'Open RFPs that fit your work',
- icon: faMagnifyingGlassDollar,
- message:
- 'Find open RFPs I could apply to based on my expertise, and tell me why each one is a match.',
+ need_funding: {
+ label: 'I need funding',
+ placeholder: 'Describe the research you need funding for…',
},
-];
+};
diff --git a/components/AIMode/start/IntentCtas.tsx b/components/AIMode/start/IntentCtas.tsx
new file mode 100644
index 000000000..32c5b90ba
--- /dev/null
+++ b/components/AIMode/start/IntentCtas.tsx
@@ -0,0 +1,161 @@
+'use client';
+
+import { useState, type ReactNode } from 'react';
+import { BadgeCheck, Handshake, Target, X, type LucideIcon } from 'lucide-react';
+import { WHITE_GLOVE_BOOKING_URL } from '@/components/Funding/OpenFundingOpportunityModal';
+import type { FundingIntent } from '@/components/Funding/fundingDirection';
+import { SelectFundingOpportunityModal } from '@/components/modals/SelectFundingOpportunityModal';
+import { ProfileEditModal } from '@/components/profile/ProfileEditModal';
+import { useUser } from '@/contexts/UserContext';
+import type { SelectedGrantDetails } from '@/types/grant';
+import { formatCompactAmount } from '@/utils/currency';
+
+interface IntentCtasProps {
+ readonly intent: FundingIntent;
+ /** The RFP the user means to apply to, chosen before the conversation exists. */
+ readonly selectedGrant: SelectedGrantDetails | null;
+ readonly onSelectGrant: (grant: SelectedGrantDetails | null) => void;
+}
+
+/**
+ * What sits under the composer on a new conversation: for a researcher, the
+ * two things that make the assistant's draft theirs — their profile and the
+ * RFP they are answering; for a funder, a way to the team.
+ */
+export function IntentCtas({ intent, selectedGrant, onSelectGrant }: IntentCtasProps) {
+ if (intent === 'fund') {
+ return (
+
+
+ Prefer to talk it through?
+
+ Talk to the ResearchHub team
+
+
+ );
+ }
+
+ return (
+