random story selector
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { searchApi } from '../../lib/api';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { searchApi, storyApi } from '../../lib/api';
|
||||
import { Story, Tag, FacetCount } from '../../types/api';
|
||||
import AppLayout from '../../components/layout/AppLayout';
|
||||
import { Input } from '../../components/ui/Input';
|
||||
@@ -14,10 +15,12 @@ type ViewMode = 'grid' | 'list';
|
||||
type SortOption = 'createdAt' | 'title' | 'authorName' | 'rating' | 'wordCount' | 'lastRead';
|
||||
|
||||
export default function LibraryPage() {
|
||||
const router = useRouter();
|
||||
const [stories, setStories] = useState<Story[]>([]);
|
||||
const [tags, setTags] = useState<Tag[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [searchLoading, setSearchLoading] = useState(false);
|
||||
const [randomLoading, setRandomLoading] = useState(false);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [selectedTags, setSelectedTags] = useState<string[]>([]);
|
||||
const [viewMode, setViewMode] = useState<ViewMode>('list');
|
||||
@@ -139,6 +142,44 @@ export default function LibraryPage() {
|
||||
setRefreshTrigger(prev => prev + 1);
|
||||
};
|
||||
|
||||
const handleRandomStory = async () => {
|
||||
try {
|
||||
setRandomLoading(true);
|
||||
|
||||
// Build filter parameters based on current UI state
|
||||
const filters: Record<string, any> = {};
|
||||
|
||||
// Include search query if present
|
||||
if (searchQuery && searchQuery.trim() !== '' && searchQuery !== '*') {
|
||||
filters.searchQuery = searchQuery.trim();
|
||||
}
|
||||
|
||||
// Include all selected tags
|
||||
if (selectedTags.length > 0) {
|
||||
filters.tags = selectedTags;
|
||||
}
|
||||
|
||||
console.log('Getting random story with filters:', filters);
|
||||
|
||||
const randomStory = await storyApi.getRandomStory(filters);
|
||||
|
||||
if (!randomStory) {
|
||||
// No stories match the current filters
|
||||
alert('No stories match your current filters. Try clearing some filters or adding more stories to your library.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Navigate to the random story's reading page
|
||||
router.push(`/stories/${randomStory.id}/read`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to get random story:', error);
|
||||
alert('Failed to get a random story. Please try again.');
|
||||
} finally {
|
||||
setRandomLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<AppLayout>
|
||||
@@ -163,6 +204,13 @@ export default function LibraryPage() {
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
onClick={handleRandomStory}
|
||||
disabled={randomLoading || totalElements === 0}
|
||||
variant="secondary"
|
||||
>
|
||||
{randomLoading ? '🎲 ...' : '🎲 Random Story'}
|
||||
</Button>
|
||||
<Button href="/import">
|
||||
Add New Story
|
||||
</Button>
|
||||
|
||||
@@ -192,6 +192,22 @@ export const storyApi = {
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
getRandomStory: async (filters?: {
|
||||
searchQuery?: string;
|
||||
tags?: string[];
|
||||
}): Promise<Story | null> => {
|
||||
try {
|
||||
const response = await api.get('/stories/random', { params: filters });
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 204) {
|
||||
// No content - no stories match filters
|
||||
return null;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Author endpoints
|
||||
|
||||
Reference in New Issue
Block a user