useEnhancedFeeds.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import { useState, useEffect } from 'react';
  2. import { supabase } from '@/integrations/supabase/client';
  3. import { Feed } from '@/types/feed';
  4. import { useAuth } from './useAuth';
  5. import { toast } from 'sonner';
  6. export function useEnhancedFeeds() {
  7. const [feeds, setFeeds] = useState<Feed[]>([]);
  8. const [loading, setLoading] = useState(true);
  9. const { user } = useAuth();
  10. const fetchFeeds = async () => {
  11. try {
  12. setLoading(true);
  13. // Fetch all feeds with article count
  14. const { data: feedsData, error: feedsError } = await supabase
  15. .from('feeds')
  16. .select(`
  17. *,
  18. articles(count)
  19. `)
  20. .order('name');
  21. if (feedsError) {
  22. toast.error('Erreur lors du chargement des flux');
  23. console.error('Error fetching feeds:', feedsError);
  24. return;
  25. }
  26. // If user is authenticated, fetch their subscriptions
  27. let userFeedsData = null;
  28. if (user) {
  29. const { data, error } = await supabase
  30. .from('user_feeds')
  31. .select('feed_id, is_followed')
  32. .eq('user_id', user.id);
  33. if (error) {
  34. console.error('Error fetching user feeds:', error);
  35. } else {
  36. userFeedsData = data;
  37. }
  38. }
  39. // Combine feeds with user subscription status
  40. const combinedFeeds = feedsData.map(feed => ({
  41. id: feed.id,
  42. name: feed.name,
  43. url: feed.url,
  44. type: feed.type as Feed['type'],
  45. description: feed.description,
  46. category: feed.category,
  47. isFollowed: userFeedsData?.find(uf => uf.feed_id === feed.id)?.is_followed || false,
  48. lastUpdated: feed.last_updated || feed.created_at,
  49. articleCount: feed.articles?.[0]?.count || 0,
  50. status: feed.status as Feed['status']
  51. }));
  52. setFeeds(combinedFeeds);
  53. } catch (error) {
  54. console.error('Error in fetchFeeds:', error);
  55. toast.error('Erreur lors du chargement des flux');
  56. } finally {
  57. setLoading(false);
  58. }
  59. };
  60. const toggleFollow = async (feedId: string) => {
  61. if (!user) {
  62. toast.error('Vous devez être connecté pour suivre un flux');
  63. return;
  64. }
  65. try {
  66. const feed = feeds.find(f => f.id === feedId);
  67. if (!feed) return;
  68. // Check if subscription exists
  69. const { data: existingSubscription } = await supabase
  70. .from('user_feeds')
  71. .select('*')
  72. .eq('user_id', user.id)
  73. .eq('feed_id', feedId)
  74. .single();
  75. if (existingSubscription) {
  76. // Update existing subscription
  77. const { error } = await supabase
  78. .from('user_feeds')
  79. .update({ is_followed: !feed.isFollowed })
  80. .eq('user_id', user.id)
  81. .eq('feed_id', feedId);
  82. if (error) {
  83. toast.error('Erreur lors de la mise à jour');
  84. return;
  85. }
  86. } else {
  87. // Create new subscription
  88. const { error } = await supabase
  89. .from('user_feeds')
  90. .insert({
  91. user_id: user.id,
  92. feed_id: feedId,
  93. is_followed: true
  94. });
  95. if (error) {
  96. toast.error('Erreur lors de l\'ajout');
  97. return;
  98. }
  99. }
  100. // Update local state
  101. setFeeds(prev => prev.map(f =>
  102. f.id === feedId
  103. ? { ...f, isFollowed: !f.isFollowed }
  104. : f
  105. ));
  106. toast.success(
  107. feed.isFollowed
  108. ? `Vous ne suivez plus "${feed.name}"`
  109. : `Vous suivez maintenant "${feed.name}"`
  110. );
  111. } catch (error) {
  112. console.error('Error toggling follow:', error);
  113. toast.error('Erreur lors de la mise à jour');
  114. }
  115. };
  116. const fetchFeedContent = async (feedId: string) => {
  117. try {
  118. const feed = feeds.find(f => f.id === feedId);
  119. if (!feed) return;
  120. toast.info(`Récupération du contenu de "${feed.name}"...`);
  121. const { data, error } = await supabase.functions.invoke('fetch-rss', {
  122. body: { feedId, feedUrl: feed.url }
  123. });
  124. if (error) {
  125. throw error;
  126. }
  127. if (data.success) {
  128. toast.success(`${data.articlesProcessed} articles récupérés pour "${feed.name}"`);
  129. await fetchFeeds(); // Refresh to update article counts
  130. } else {
  131. throw new Error(data.error || 'Erreur lors de la récupération RSS');
  132. }
  133. } catch (error) {
  134. console.error('Error fetching feed content:', error);
  135. toast.error('Erreur lors de la récupération du contenu');
  136. }
  137. };
  138. useEffect(() => {
  139. fetchFeeds();
  140. }, [user]);
  141. return {
  142. feeds,
  143. loading,
  144. toggleFollow,
  145. fetchFeedContent,
  146. refetch: fetchFeeds
  147. };
  148. }