300 lines
11 KiB
TypeScript
300 lines
11 KiB
TypeScript
/**
|
||
* Demo presets — BCRG Community Flow.
|
||
*
|
||
* 2 sources → BCRG central funnel → 5 person funnels (Alice–Eve) → 11 outcomes.
|
||
*/
|
||
|
||
import type { FlowNode, FunnelNodeData, OutcomeNodeData, SourceNodeData } from "./types";
|
||
|
||
export const SPENDING_COLORS = ["#3b82f6", "#8b5cf6", "#ec4899", "#06b6d4", "#10b981", "#6366f1"];
|
||
export const OVERFLOW_COLORS = ["#f59e0b", "#ef4444", "#f97316", "#eab308", "#dc2626", "#ea580c"];
|
||
|
||
export const demoNodes: FlowNode[] = [
|
||
// ── Sources (Y=-300) ──
|
||
{
|
||
id: "source-a", type: "source", position: { x: 440, y: -300 },
|
||
data: {
|
||
label: "Grants & Donations", flowRate: 7500, sourceType: "card",
|
||
targetAllocations: [{ targetId: "bcrg", percentage: 100, color: "#10b981" }],
|
||
} as SourceNodeData,
|
||
},
|
||
{
|
||
id: "source-b", type: "source", position: { x: 880, y: -300 },
|
||
data: {
|
||
label: "Membership Fees", flowRate: 7500, sourceType: "card",
|
||
targetAllocations: [{ targetId: "bcrg", percentage: 100, color: "#10b981" }],
|
||
} as SourceNodeData,
|
||
},
|
||
|
||
// ── BCRG central funnel (Y=0) ──
|
||
{
|
||
id: "bcrg", type: "funnel", position: { x: 630, y: 0 },
|
||
data: {
|
||
label: "BCRG", currentValue: 95000, desiredOutflow: 25000,
|
||
minThreshold: 25000, sufficientThreshold: 100000, maxThreshold: 150000,
|
||
maxCapacity: 225000, inflowRate: 15000, dynamicOverflow: true,
|
||
overflowAllocations: [],
|
||
spendingAllocations: [
|
||
{ targetId: "alice", percentage: 20, color: SPENDING_COLORS[0] },
|
||
{ targetId: "bob", percentage: 20, color: SPENDING_COLORS[1] },
|
||
{ targetId: "carol", percentage: 20, color: SPENDING_COLORS[2] },
|
||
{ targetId: "dave", percentage: 20, color: SPENDING_COLORS[3] },
|
||
{ targetId: "eve", percentage: 20, color: SPENDING_COLORS[4] },
|
||
],
|
||
} as FunnelNodeData,
|
||
},
|
||
|
||
// ── Person funnels (Y=400) ──
|
||
{
|
||
id: "alice", type: "funnel", position: { x: 100, y: 400 },
|
||
data: {
|
||
label: "Alice", currentValue: 18000, desiredOutflow: 5000,
|
||
minThreshold: 5000, sufficientThreshold: 20000, maxThreshold: 30000,
|
||
maxCapacity: 45000, inflowRate: 3000,
|
||
overflowAllocations: [],
|
||
spendingAllocations: [
|
||
{ targetId: "alice-comms", percentage: 50, color: SPENDING_COLORS[0] },
|
||
{ targetId: "alice-events", percentage: 50, color: SPENDING_COLORS[1] },
|
||
],
|
||
} as FunnelNodeData,
|
||
},
|
||
{
|
||
id: "bob", type: "funnel", position: { x: 380, y: 400 },
|
||
data: {
|
||
label: "Bob", currentValue: 14000, desiredOutflow: 4000,
|
||
minThreshold: 4000, sufficientThreshold: 16000, maxThreshold: 24000,
|
||
maxCapacity: 36000, inflowRate: 3000,
|
||
overflowAllocations: [],
|
||
spendingAllocations: [
|
||
{ targetId: "bob-research", percentage: 60, color: SPENDING_COLORS[0] },
|
||
{ targetId: "bob-writing", percentage: 40, color: SPENDING_COLORS[1] },
|
||
],
|
||
} as FunnelNodeData,
|
||
},
|
||
{
|
||
id: "carol", type: "funnel", position: { x: 660, y: 400 },
|
||
data: {
|
||
label: "Carol", currentValue: 22000, desiredOutflow: 6000,
|
||
minThreshold: 6000, sufficientThreshold: 24000, maxThreshold: 36000,
|
||
maxCapacity: 54000, inflowRate: 3000,
|
||
overflowAllocations: [],
|
||
spendingAllocations: [
|
||
{ targetId: "carol-ops", percentage: 50, color: SPENDING_COLORS[0] },
|
||
{ targetId: "carol-infra", percentage: 50, color: SPENDING_COLORS[1] },
|
||
],
|
||
} as FunnelNodeData,
|
||
},
|
||
{
|
||
id: "dave", type: "funnel", position: { x: 940, y: 400 },
|
||
data: {
|
||
label: "Dave", currentValue: 10000, desiredOutflow: 5000,
|
||
minThreshold: 5000, sufficientThreshold: 20000, maxThreshold: 30000,
|
||
maxCapacity: 45000, inflowRate: 3000,
|
||
overflowAllocations: [],
|
||
spendingAllocations: [
|
||
{ targetId: "dave-design", percentage: 45, color: SPENDING_COLORS[0] },
|
||
{ targetId: "dave-prototypes", percentage: 55, color: SPENDING_COLORS[1] },
|
||
],
|
||
} as FunnelNodeData,
|
||
},
|
||
{
|
||
id: "eve", type: "funnel", position: { x: 1220, y: 400 },
|
||
data: {
|
||
label: "Eve", currentValue: 16000, desiredOutflow: 5000,
|
||
minThreshold: 5000, sufficientThreshold: 20000, maxThreshold: 30000,
|
||
maxCapacity: 45000, inflowRate: 3000,
|
||
overflowAllocations: [],
|
||
spendingAllocations: [
|
||
{ targetId: "eve-legal", percentage: 40, color: SPENDING_COLORS[0] },
|
||
{ targetId: "eve-compliance", percentage: 30, color: SPENDING_COLORS[1] },
|
||
{ targetId: "eve-governance", percentage: 30, color: SPENDING_COLORS[2] },
|
||
],
|
||
} as FunnelNodeData,
|
||
},
|
||
|
||
// ── Outcome nodes (Y=850) — 11 total ──
|
||
|
||
// Alice's outcomes
|
||
{ id: "alice-comms", type: "outcome", position: { x: -10, y: 850 },
|
||
data: {
|
||
label: "Comms Strategy", description: "Community communications and outreach",
|
||
fundingReceived: 12000, fundingTarget: 12000, status: "completed",
|
||
phases: [
|
||
{ name: "Planning", fundingThreshold: 4000, tasks: [
|
||
{ label: "Stakeholder mapping", completed: true },
|
||
{ label: "Channel audit", completed: true },
|
||
] },
|
||
{ name: "Execution", fundingThreshold: 8000, tasks: [
|
||
{ label: "Newsletter launch", completed: true },
|
||
{ label: "Social media calendar", completed: true },
|
||
] },
|
||
{ name: "Review", fundingThreshold: 12000, tasks: [
|
||
{ label: "Impact metrics report", completed: true },
|
||
] },
|
||
],
|
||
} as OutcomeNodeData },
|
||
{ id: "alice-events", type: "outcome", position: { x: 210, y: 850 },
|
||
data: {
|
||
label: "Event Series", description: "Quarterly community gatherings",
|
||
fundingReceived: 6000, fundingTarget: 15000, status: "in-progress",
|
||
phases: [
|
||
{ name: "Venue & Logistics", fundingThreshold: 5000, tasks: [
|
||
{ label: "Venue scouting", completed: true },
|
||
{ label: "Catering contracts", completed: true },
|
||
] },
|
||
{ name: "Programming", fundingThreshold: 10000, tasks: [
|
||
{ label: "Speaker invitations", completed: false },
|
||
{ label: "Workshop facilitation", completed: false },
|
||
] },
|
||
],
|
||
} as OutcomeNodeData },
|
||
|
||
// Bob's outcomes
|
||
{ id: "bob-research", type: "outcome", position: { x: 320, y: 850 },
|
||
data: {
|
||
label: "Field Research", description: "Participatory action research in partner communities",
|
||
fundingReceived: 8000, fundingTarget: 20000, status: "in-progress",
|
||
phases: [
|
||
{ name: "Literature Review", fundingThreshold: 5000, tasks: [
|
||
{ label: "Systematic review", completed: true },
|
||
{ label: "Gap analysis", completed: true },
|
||
] },
|
||
{ name: "Field Work", fundingThreshold: 15000, tasks: [
|
||
{ label: "Site visits", completed: false },
|
||
{ label: "Interviews & surveys", completed: false },
|
||
] },
|
||
],
|
||
} as OutcomeNodeData },
|
||
{ id: "bob-writing", type: "outcome", position: { x: 490, y: 850 },
|
||
data: {
|
||
label: "Publications", description: "Research papers and policy briefs",
|
||
fundingReceived: 2000, fundingTarget: 10000, status: "not-started",
|
||
phases: [
|
||
{ name: "Drafting", fundingThreshold: 5000, tasks: [
|
||
{ label: "Working paper draft", completed: false },
|
||
] },
|
||
{ name: "Peer Review", fundingThreshold: 10000, tasks: [
|
||
{ label: "Submit to journal", completed: false },
|
||
] },
|
||
],
|
||
} as OutcomeNodeData },
|
||
|
||
// Carol's outcomes
|
||
{ id: "carol-ops", type: "outcome", position: { x: 600, y: 850 },
|
||
data: {
|
||
label: "Operations", description: "Day-to-day operational management",
|
||
fundingReceived: 18000, fundingTarget: 18000, status: "completed",
|
||
phases: [
|
||
{ name: "Setup", fundingThreshold: 6000, tasks: [
|
||
{ label: "Process documentation", completed: true },
|
||
{ label: "Tool selection", completed: true },
|
||
] },
|
||
{ name: "Execution", fundingThreshold: 12000, tasks: [
|
||
{ label: "Monthly reporting", completed: true },
|
||
{ label: "Budget tracking", completed: true },
|
||
] },
|
||
{ name: "Optimization", fundingThreshold: 18000, tasks: [
|
||
{ label: "Workflow automation", completed: true },
|
||
] },
|
||
],
|
||
} as OutcomeNodeData },
|
||
{ id: "carol-infra", type: "outcome", position: { x: 760, y: 850 },
|
||
data: {
|
||
label: "Infrastructure", description: "Shared infrastructure and hosting",
|
||
fundingReceived: 10000, fundingTarget: 20000, status: "in-progress",
|
||
phases: [
|
||
{ name: "Provisioning", fundingThreshold: 8000, tasks: [
|
||
{ label: "Server setup", completed: true },
|
||
{ label: "CI/CD pipeline", completed: true },
|
||
] },
|
||
{ name: "Hardening", fundingThreshold: 20000, tasks: [
|
||
{ label: "Security audit", completed: false },
|
||
{ label: "Disaster recovery plan", completed: false },
|
||
] },
|
||
],
|
||
} as OutcomeNodeData },
|
||
|
||
// Dave's outcomes
|
||
{ id: "dave-design", type: "outcome", position: { x: 880, y: 850 },
|
||
data: {
|
||
label: "Design System", description: "Shared UI/UX design system",
|
||
fundingReceived: 15000, fundingTarget: 15000, status: "completed",
|
||
phases: [
|
||
{ name: "Foundations", fundingThreshold: 5000, tasks: [
|
||
{ label: "Color & type system", completed: true },
|
||
{ label: "Component library", completed: true },
|
||
] },
|
||
{ name: "Documentation", fundingThreshold: 10000, tasks: [
|
||
{ label: "Storybook setup", completed: true },
|
||
{ label: "Usage guidelines", completed: true },
|
||
] },
|
||
{ name: "Rollout", fundingThreshold: 15000, tasks: [
|
||
{ label: "Team training", completed: true },
|
||
] },
|
||
],
|
||
} as OutcomeNodeData },
|
||
{ id: "dave-prototypes", type: "outcome", position: { x: 1050, y: 850 },
|
||
data: {
|
||
label: "Prototypes", description: "Rapid prototyping of new tools",
|
||
fundingReceived: 3000, fundingTarget: 12000, status: "in-progress",
|
||
phases: [
|
||
{ name: "Discovery", fundingThreshold: 4000, tasks: [
|
||
{ label: "User interviews", completed: true },
|
||
] },
|
||
{ name: "Build", fundingThreshold: 8000, tasks: [
|
||
{ label: "MVP development", completed: false },
|
||
] },
|
||
{ name: "Test", fundingThreshold: 12000, tasks: [
|
||
{ label: "User testing rounds", completed: false },
|
||
] },
|
||
],
|
||
} as OutcomeNodeData },
|
||
|
||
// Eve's outcomes
|
||
{ id: "eve-legal", type: "outcome", position: { x: 1140, y: 850 },
|
||
data: {
|
||
label: "Legal Framework", description: "Legal structure and agreements",
|
||
fundingReceived: 10000, fundingTarget: 10000, status: "completed",
|
||
phases: [
|
||
{ name: "Research", fundingThreshold: 4000, tasks: [
|
||
{ label: "Jurisdiction analysis", completed: true },
|
||
{ label: "Entity comparison", completed: true },
|
||
] },
|
||
{ name: "Formation", fundingThreshold: 10000, tasks: [
|
||
{ label: "Articles of incorporation", completed: true },
|
||
{ label: "Operating agreement", completed: true },
|
||
] },
|
||
],
|
||
} as OutcomeNodeData },
|
||
{ id: "eve-compliance", type: "outcome", position: { x: 1280, y: 850 },
|
||
data: {
|
||
label: "Compliance", description: "Regulatory compliance and reporting",
|
||
fundingReceived: 4000, fundingTarget: 12000, status: "in-progress",
|
||
phases: [
|
||
{ name: "Assessment", fundingThreshold: 4000, tasks: [
|
||
{ label: "Compliance gap analysis", completed: true },
|
||
] },
|
||
{ name: "Implementation", fundingThreshold: 8000, tasks: [
|
||
{ label: "KYC/AML procedures", completed: false },
|
||
] },
|
||
{ name: "Audit", fundingThreshold: 12000, tasks: [
|
||
{ label: "External audit", completed: false },
|
||
] },
|
||
],
|
||
} as OutcomeNodeData },
|
||
{ id: "eve-governance", type: "outcome", position: { x: 1430, y: 850 },
|
||
data: {
|
||
label: "Governance Model", description: "Governance framework and voting mechanisms",
|
||
fundingReceived: 1000, fundingTarget: 8000, status: "not-started",
|
||
phases: [
|
||
{ name: "Design", fundingThreshold: 3000, tasks: [
|
||
{ label: "Governance charter draft", completed: false },
|
||
] },
|
||
{ name: "Implementation", fundingThreshold: 8000, tasks: [
|
||
{ label: "Voting mechanism setup", completed: false },
|
||
{ label: "Dispute resolution process", completed: false },
|
||
] },
|
||
],
|
||
} as OutcomeNodeData },
|
||
];
|