Full parallel implementation of typesense and opensearch
This commit is contained in:
@@ -17,17 +17,34 @@ interface StoryCardProps {
|
||||
onSelect?: () => void;
|
||||
}
|
||||
|
||||
export default function StoryCard({
|
||||
story,
|
||||
viewMode,
|
||||
onUpdate,
|
||||
showSelection = false,
|
||||
isSelected = false,
|
||||
onSelect
|
||||
export default function StoryCard({
|
||||
story,
|
||||
viewMode,
|
||||
onUpdate,
|
||||
showSelection = false,
|
||||
isSelected = false,
|
||||
onSelect
|
||||
}: StoryCardProps) {
|
||||
const [rating, setRating] = useState(story.rating || 0);
|
||||
const [updating, setUpdating] = useState(false);
|
||||
|
||||
// Helper function to get tags from either tags array or tagNames array
|
||||
const getTags = () => {
|
||||
if (Array.isArray(story.tags) && story.tags.length > 0) {
|
||||
return story.tags;
|
||||
}
|
||||
if (Array.isArray(story.tagNames) && story.tagNames.length > 0) {
|
||||
// Convert tagNames to Tag objects for display compatibility
|
||||
return story.tagNames.map((name, index) => ({
|
||||
id: `tag-${index}`, // Temporary ID for display
|
||||
name: name
|
||||
}));
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const displayTags = getTags();
|
||||
|
||||
const handleRatingClick = async (e: React.MouseEvent, newRating: number) => {
|
||||
// Prevent default and stop propagation to avoid triggering navigation
|
||||
e.preventDefault();
|
||||
@@ -58,7 +75,7 @@ export default function StoryCard({
|
||||
const calculateReadingPercentage = (story: Story): number => {
|
||||
if (!story.readingPosition) return 0;
|
||||
|
||||
const totalLength = story.contentPlain?.length || story.contentHtml.length;
|
||||
const totalLength = story.contentPlain?.length || story.contentHtml?.length || 0;
|
||||
if (totalLength === 0) return 0;
|
||||
|
||||
return Math.round((story.readingPosition / totalLength) * 100);
|
||||
@@ -124,9 +141,9 @@ export default function StoryCard({
|
||||
</div>
|
||||
|
||||
{/* Tags */}
|
||||
{Array.isArray(story.tags) && story.tags.length > 0 && (
|
||||
{displayTags.length > 0 && (
|
||||
<div className="flex flex-wrap gap-1 mt-2">
|
||||
{story.tags.slice(0, 3).map((tag) => (
|
||||
{displayTags.slice(0, 3).map((tag) => (
|
||||
<TagDisplay
|
||||
key={tag.id}
|
||||
tag={tag}
|
||||
@@ -134,9 +151,9 @@ export default function StoryCard({
|
||||
clickable={false}
|
||||
/>
|
||||
))}
|
||||
{story.tags.length > 3 && (
|
||||
{displayTags.length > 3 && (
|
||||
<span className="px-2 py-1 text-xs theme-text">
|
||||
+{story.tags.length - 3} more
|
||||
+{displayTags.length - 3} more
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -260,9 +277,9 @@ export default function StoryCard({
|
||||
</div>
|
||||
|
||||
{/* Tags */}
|
||||
{Array.isArray(story.tags) && story.tags.length > 0 && (
|
||||
{displayTags.length > 0 && (
|
||||
<div className="flex flex-wrap gap-1 mt-2">
|
||||
{story.tags.slice(0, 2).map((tag) => (
|
||||
{displayTags.slice(0, 2).map((tag) => (
|
||||
<TagDisplay
|
||||
key={tag.id}
|
||||
tag={tag}
|
||||
@@ -270,9 +287,9 @@ export default function StoryCard({
|
||||
clickable={false}
|
||||
/>
|
||||
))}
|
||||
{story.tags.length > 2 && (
|
||||
{displayTags.length > 2 && (
|
||||
<span className="px-2 py-1 text-xs theme-text">
|
||||
+{story.tags.length - 2}
|
||||
+{displayTags.length - 2}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user