Browse Source

feat(26-01): integrate WorkflowPreview into TemplateCard

- Replace static previewImage with workflow prop in TemplateCard
- Render WorkflowPreview showing node layout and connections
- Remove getTemplateContent import (no longer needed)
- Pass workflow data from PRESET_TEMPLATES to cards
handoff-20260429-1057
shrimbly 6 months ago
parent
commit
e1ade58b6f
  1. 15
      src/components/quickstart/TemplateCard.tsx
  2. 21
      src/components/quickstart/TemplateExplorerView.tsx

15
src/components/quickstart/TemplateCard.tsx

@ -1,6 +1,8 @@
"use client"; "use client";
import { Node, Edge } from "@xyflow/react";
import { TemplateCategory } from "@/types/quickstart"; import { TemplateCategory } from "@/types/quickstart";
import { WorkflowPreview } from "./WorkflowPreview";
interface TemplateCardProps { interface TemplateCardProps {
template: { template: {
@ -12,7 +14,7 @@ interface TemplateCardProps {
tags: string[]; tags: string[];
}; };
nodeCount: number; nodeCount: number;
previewImage?: string; workflow?: { nodes: Node[]; edges: Edge[] };
isLoading: boolean; isLoading: boolean;
onClick: () => void; onClick: () => void;
disabled: boolean; disabled: boolean;
@ -35,7 +37,7 @@ const CATEGORY_COLORS: Record<TemplateCategory, string> = {
export function TemplateCard({ export function TemplateCard({
template, template,
nodeCount, nodeCount,
previewImage, workflow,
isLoading, isLoading,
onClick, onClick,
disabled, disabled,
@ -87,13 +89,8 @@ export function TemplateCard({
/> />
</svg> </svg>
</div> </div>
) : previewImage ? ( ) : workflow ? (
/* eslint-disable-next-line @next/next/no-img-element */ <WorkflowPreview workflow={workflow} />
<img
src={previewImage}
alt={`${template.name} preview`}
className="w-full h-full object-cover"
/>
) : ( ) : (
<div className="absolute inset-0 flex items-center justify-center"> <div className="absolute inset-0 flex items-center justify-center">
<svg <svg

21
src/components/quickstart/TemplateExplorerView.tsx

@ -2,7 +2,7 @@
import { useState, useEffect, useCallback, useMemo, useRef } from "react"; import { useState, useEffect, useCallback, useMemo, useRef } from "react";
import { WorkflowFile } from "@/store/workflowStore"; import { WorkflowFile } from "@/store/workflowStore";
import { getAllPresets, PRESET_TEMPLATES, getTemplateContent } from "@/lib/quickstart/templates"; import { getAllPresets, PRESET_TEMPLATES } from "@/lib/quickstart/templates";
import { QuickstartBackButton } from "./QuickstartBackButton"; import { QuickstartBackButton } from "./QuickstartBackButton";
import { TemplateCard } from "./TemplateCard"; import { TemplateCard } from "./TemplateCard";
import { CommunityWorkflowMeta, TemplateCategory, TemplateMetadata } from "@/types/quickstart"; import { CommunityWorkflowMeta, TemplateCategory, TemplateMetadata } from "@/types/quickstart";
@ -69,17 +69,16 @@ export function TemplateExplorerView({
return metadata; return metadata;
}, []); }, []);
// Get preview image for each template (first image from "full" content level) // Get workflow data for each template
const previewImages = useMemo(() => { const presetWorkflows = useMemo(() => {
const images: Record<string, string | undefined> = {}; const workflows: Record<string, { nodes: typeof PRESET_TEMPLATES[0]["workflow"]["nodes"]; edges: typeof PRESET_TEMPLATES[0]["workflow"]["edges"] } | undefined> = {};
PRESET_TEMPLATES.forEach((template) => { PRESET_TEMPLATES.forEach((template) => {
const content = getTemplateContent(template.id, "full"); workflows[template.id] = {
if (content?.images) { nodes: template.workflow.nodes,
const imageUrls = Object.values(content.images).map((img) => img.url); edges: template.workflow.edges,
images[template.id] = imageUrls[0]; };
}
}); });
return images; return workflows;
}, []); }, []);
// Filter presets based on search, category, and tags // Filter presets based on search, category, and tags
@ -405,7 +404,7 @@ export function TemplateExplorerView({
key={preset.id} key={preset.id}
template={preset} template={preset}
nodeCount={presetMetadata[preset.id]?.nodeCount ?? 0} nodeCount={presetMetadata[preset.id]?.nodeCount ?? 0}
previewImage={previewImages[preset.id]} workflow={presetWorkflows[preset.id]}
isLoading={loadingWorkflowId === preset.id} isLoading={loadingWorkflowId === preset.id}
onClick={() => handlePresetSelect(preset.id)} onClick={() => handlePresetSelect(preset.id)}
disabled={isLoading} disabled={isLoading}

Loading…
Cancel
Save