Skip to content

Commit 54add8b

Browse files
Copilotmagesoe
andcommitted
Improve Venn diagram readability: vertical component types, remove 'shared' text, add 4-solution test
Co-authored-by: magesoe <[email protected]>
1 parent 7c1ffa8 commit 54add8b

File tree

2 files changed

+386
-64
lines changed

2 files changed

+386
-64
lines changed

Website/components/solutionoverviewview/SolutionVennDiagram.tsx

Lines changed: 131 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const SolutionVennDiagram = ({ solutionOverview, onOverlapClick }: ISolut
2424
'#EC4899', // pink
2525
];
2626

27-
// Helper function to get component type summary
27+
// Helper function to get component type summary as array for vertical display
2828
const getComponentTypeSummary = (components: SolutionComponentType[]) => {
2929
const typeCounts = components.reduce((acc, component) => {
3030
const type = component.ComponentTypeName || 'Unknown';
@@ -33,8 +33,7 @@ export const SolutionVennDiagram = ({ solutionOverview, onOverlapClick }: ISolut
3333
}, {} as Record<string, number>);
3434

3535
return Object.entries(typeCounts)
36-
.map(([type, count]) => `${count} ${type}${count > 1 ? 's' : ''}`)
37-
.join(', ');
36+
.map(([type, count]) => `${count} ${type}${count > 1 ? 's' : ''}`);
3837
};
3938

4039
// For simplicity, we'll render based on the number of solutions
@@ -51,7 +50,7 @@ export const SolutionVennDiagram = ({ solutionOverview, onOverlapClick }: ISolut
5150
function renderSingleSolution() {
5251
const solution = solutions[0];
5352
const overlap = overlaps.find(o => o.SolutionNames.length === 1 && o.SolutionNames[0] === solution.UniqueName);
54-
const typeSummary = overlap ? getComponentTypeSummary(overlap.SharedComponents) : '';
53+
const typeSummary = overlap ? getComponentTypeSummary(overlap.SharedComponents) : [];
5554

5655
return (
5756
<div className="flex items-center justify-center h-80">
@@ -67,17 +66,24 @@ export const SolutionVennDiagram = ({ solutionOverview, onOverlapClick }: ISolut
6766
className="cursor-pointer hover:fillOpacity-0.8"
6867
onClick={() => overlap && onOverlapClick(overlap.SolutionNames, overlap.SharedComponents)}
6968
/>
70-
<text x="200" y="140" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-lg">
69+
<text x="200" y="130" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-lg">
7170
{solution.DisplayName}
7271
</text>
73-
<text x="200" y="160" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
72+
<text x="200" y="150" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
7473
{overlap?.ComponentCount || 0} components
7574
</text>
76-
{typeSummary && (
77-
<text x="200" y="175" textAnchor="middle" dominantBaseline="middle" className="fill-white text-xs">
78-
{typeSummary}
75+
{typeSummary.map((typeText, index) => (
76+
<text
77+
key={index}
78+
x="200"
79+
y={165 + index * 12}
80+
textAnchor="middle"
81+
dominantBaseline="middle"
82+
className="fill-white text-xs"
83+
>
84+
{typeText}
7985
</text>
80-
)}
86+
))}
8187
</svg>
8288
</div>
8389
);
@@ -89,9 +95,9 @@ export const SolutionVennDiagram = ({ solutionOverview, onOverlapClick }: ISolut
8995
const overlap2 = overlaps.find(o => o.SolutionNames.length === 1 && o.SolutionNames[0] === solution2.UniqueName);
9096
const overlapBoth = overlaps.find(o => o.SolutionNames.length === 2);
9197

92-
const typeSummary1 = overlap1 ? getComponentTypeSummary(overlap1.SharedComponents) : '';
93-
const typeSummary2 = overlap2 ? getComponentTypeSummary(overlap2.SharedComponents) : '';
94-
const typeSummaryBoth = overlapBoth ? getComponentTypeSummary(overlapBoth.SharedComponents) : '';
98+
const typeSummary1 = overlap1 ? getComponentTypeSummary(overlap1.SharedComponents) : [];
99+
const typeSummary2 = overlap2 ? getComponentTypeSummary(overlap2.SharedComponents) : [];
100+
const typeSummaryBoth = overlapBoth ? getComponentTypeSummary(overlapBoth.SharedComponents) : [];
95101

96102
return (
97103
<div className="flex items-center justify-center h-80">
@@ -134,43 +140,61 @@ export const SolutionVennDiagram = ({ solutionOverview, onOverlapClick }: ISolut
134140
/>
135141

136142
{/* Solution 1 Labels */}
137-
<text x="140" y="160" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
143+
<text x="140" y="145" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
138144
{solution1.DisplayName}
139145
</text>
140-
<text x="140" y="180" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
146+
<text x="140" y="165" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
141147
{overlap1?.ComponentCount || 0} components
142148
</text>
143-
{typeSummary1 && (
144-
<text x="140" y="195" textAnchor="middle" dominantBaseline="middle" className="fill-white text-xs">
145-
{typeSummary1}
149+
{typeSummary1.map((typeText, index) => (
150+
<text
151+
key={index}
152+
x="140"
153+
y={180 + index * 12}
154+
textAnchor="middle"
155+
dominantBaseline="middle"
156+
className="fill-white text-xs"
157+
>
158+
{typeText}
146159
</text>
147-
)}
160+
))}
148161

149162
{/* Solution 2 Labels */}
150-
<text x="460" y="160" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
163+
<text x="460" y="145" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
151164
{solution2.DisplayName}
152165
</text>
153-
<text x="460" y="180" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
166+
<text x="460" y="165" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
154167
{overlap2?.ComponentCount || 0} components
155168
</text>
156-
{typeSummary2 && (
157-
<text x="460" y="195" textAnchor="middle" dominantBaseline="middle" className="fill-white text-xs">
158-
{typeSummary2}
169+
{typeSummary2.map((typeText, index) => (
170+
<text
171+
key={index}
172+
x="460"
173+
y={180 + index * 12}
174+
textAnchor="middle"
175+
dominantBaseline="middle"
176+
className="fill-white text-xs"
177+
>
178+
{typeText}
159179
</text>
160-
)}
180+
))}
161181

162182
{/* Overlap Labels */}
163-
<text x="300" y="160" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
183+
<text x="300" y="155" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
164184
{overlapBoth?.ComponentCount || 0}
165185
</text>
166-
<text x="300" y="180" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
167-
shared
168-
</text>
169-
{typeSummaryBoth && (
170-
<text x="300" y="195" textAnchor="middle" dominantBaseline="middle" className="fill-white text-xs">
171-
{typeSummaryBoth}
186+
{typeSummaryBoth.map((typeText, index) => (
187+
<text
188+
key={index}
189+
x="300"
190+
y={175 + index * 12}
191+
textAnchor="middle"
192+
dominantBaseline="middle"
193+
className="fill-white text-xs"
194+
>
195+
{typeText}
172196
</text>
173-
)}
197+
))}
174198
</svg>
175199
</div>
176200
);
@@ -257,26 +281,74 @@ export const SolutionVennDiagram = ({ solutionOverview, onOverlapClick }: ISolut
257281
})}
258282

259283
{/* Labels */}
260-
<text x="250" y="85" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
284+
<text x="250" y="80" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
261285
{solution1.DisplayName}
262286
</text>
263-
<text x="250" y="105" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
287+
<text x="250" y="100" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
264288
{overlaps.find(o => o.SolutionNames.length === 1 && o.SolutionNames[0] === solution1.UniqueName)?.ComponentCount || 0} components
265289
</text>
290+
{(() => {
291+
const overlap = overlaps.find(o => o.SolutionNames.length === 1 && o.SolutionNames[0] === solution1.UniqueName);
292+
const typeSummary = overlap ? getComponentTypeSummary(overlap.SharedComponents) : [];
293+
return typeSummary.map((typeText, index) => (
294+
<text
295+
key={index}
296+
x="250"
297+
y={115 + index * 12}
298+
textAnchor="middle"
299+
dominantBaseline="middle"
300+
className="fill-white text-xs"
301+
>
302+
{typeText}
303+
</text>
304+
));
305+
})()}
266306

267-
<text x="130" y="305" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
307+
<text x="130" y="300" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
268308
{solution2.DisplayName}
269309
</text>
270-
<text x="130" y="325" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
310+
<text x="130" y="320" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
271311
{overlaps.find(o => o.SolutionNames.length === 1 && o.SolutionNames[0] === solution2.UniqueName)?.ComponentCount || 0} components
272312
</text>
313+
{(() => {
314+
const overlap = overlaps.find(o => o.SolutionNames.length === 1 && o.SolutionNames[0] === solution2.UniqueName);
315+
const typeSummary = overlap ? getComponentTypeSummary(overlap.SharedComponents) : [];
316+
return typeSummary.map((typeText, index) => (
317+
<text
318+
key={index}
319+
x="130"
320+
y={335 + index * 12}
321+
textAnchor="middle"
322+
dominantBaseline="middle"
323+
className="fill-white text-xs"
324+
>
325+
{typeText}
326+
</text>
327+
));
328+
})()}
273329

274-
<text x="370" y="305" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
330+
<text x="370" y="300" textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-base">
275331
{solution3.DisplayName}
276332
</text>
277-
<text x="370" y="325" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
333+
<text x="370" y="320" textAnchor="middle" dominantBaseline="middle" className="fill-white text-sm font-semibold">
278334
{overlaps.find(o => o.SolutionNames.length === 1 && o.SolutionNames[0] === solution3.UniqueName)?.ComponentCount || 0} components
279335
</text>
336+
{(() => {
337+
const overlap = overlaps.find(o => o.SolutionNames.length === 1 && o.SolutionNames[0] === solution3.UniqueName);
338+
const typeSummary = overlap ? getComponentTypeSummary(overlap.SharedComponents) : [];
339+
return typeSummary.map((typeText, index) => (
340+
<text
341+
key={index}
342+
x="370"
343+
y={335 + index * 12}
344+
textAnchor="middle"
345+
dominantBaseline="middle"
346+
className="fill-white text-xs"
347+
>
348+
{typeText}
349+
</text>
350+
));
351+
})()}
280352

281353
{/* Overlap count labels */}
282354
{overlaps.map((overlap, index) => {
@@ -293,17 +365,21 @@ export const SolutionVennDiagram = ({ solutionOverview, onOverlapClick }: ISolut
293365

294366
return (
295367
<g key={index}>
296-
<text x={centerX} y={centerY - 5} textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-sm">
368+
<text x={centerX} y={centerY - 10} textAnchor="middle" dominantBaseline="middle" className="fill-white font-bold text-sm">
297369
{overlap.ComponentCount}
298370
</text>
299-
<text x={centerX} y={centerY + 10} textAnchor="middle" dominantBaseline="middle" className="fill-white text-xs">
300-
shared
301-
</text>
302-
{typeSummary && (
303-
<text x={centerX} y={centerY + 25} textAnchor="middle" dominantBaseline="middle" className="fill-white text-xs">
304-
{typeSummary}
371+
{typeSummary.map((typeText, typeIndex) => (
372+
<text
373+
key={typeIndex}
374+
x={centerX}
375+
y={centerY + 5 + typeIndex * 12}
376+
textAnchor="middle"
377+
dominantBaseline="middle"
378+
className="fill-white text-xs"
379+
>
380+
{typeText}
305381
</text>
306-
)}
382+
))}
307383
</g>
308384
);
309385
}
@@ -322,7 +398,7 @@ export const SolutionVennDiagram = ({ solutionOverview, onOverlapClick }: ISolut
322398
<div className="grid grid-cols-2 gap-4">
323399
{solutions.map((solution, index) => {
324400
const overlap = overlaps.find(o => o.SolutionNames.length === 1 && o.SolutionNames[0] === solution.UniqueName);
325-
const typeSummary = overlap ? getComponentTypeSummary(overlap.SharedComponents) : '';
401+
const typeSummary = overlap ? getComponentTypeSummary(overlap.SharedComponents) : [];
326402
return (
327403
<div
328404
key={solution.SolutionId}
@@ -332,9 +408,9 @@ export const SolutionVennDiagram = ({ solutionOverview, onOverlapClick }: ISolut
332408
>
333409
<div className="font-bold text-lg">{solution.DisplayName}</div>
334410
<div className="text-sm text-gray-700 font-semibold">{overlap?.ComponentCount || 0} components</div>
335-
{typeSummary && (
336-
<div className="text-xs text-gray-600 mt-1">{typeSummary}</div>
337-
)}
411+
{typeSummary.map((typeText, typeIndex) => (
412+
<div key={typeIndex} className="text-xs text-gray-600 mt-1">{typeText}</div>
413+
))}
338414
</div>
339415
);
340416
})}
@@ -353,10 +429,10 @@ export const SolutionVennDiagram = ({ solutionOverview, onOverlapClick }: ISolut
353429
onClick={() => onOverlapClick(overlap.SolutionNames, overlap.SharedComponents)}
354430
>
355431
<div className="font-semibold text-base">{overlap.SolutionNames.join(' + ')}</div>
356-
<div className="text-sm text-gray-700 font-medium">{overlap.ComponentCount} shared components</div>
357-
{typeSummary && (
358-
<div className="text-xs text-gray-600 mt-1">{typeSummary}</div>
359-
)}
432+
<div className="text-sm text-gray-700 font-medium">{overlap.ComponentCount} components</div>
433+
{typeSummary.map((typeText, typeIndex) => (
434+
<div key={typeIndex} className="text-xs text-gray-600 mt-1">{typeText}</div>
435+
))}
360436
</div>
361437
);
362438
})}

0 commit comments

Comments
 (0)