FeedPage.tsx to integrate with the backend interfaces - Wiz-DevTech/prettygirllz GitHub Wiki

1. First, import the necessary types and services:

import { 
  FeedItem, 
  CreateFeedItemPayload, 
  Message, 
  SendMessagePayload,
  Product,
  ProductCategory
} from '@social-commerce-service';
import { ProductAPIResponse } from '@gateway-service';
import { getCurrentUser } from '@identity-service';

2. Update the FeedContent component to use real data:

const FeedContent = () => {
  const [postContent, setPostContent] = useState('');
  const [feedItems, setFeedItems] = useState<FeedItem[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const loadFeed = async () => {
      try {
        const user = await getCurrentUser();
        // Assuming we have a socialCommerceAPI instance available
        const feed = await socialCommerceAPI.getFeed(user.id);
        setFeedItems(feed);
      } catch (err) {
        setError('Failed to load feed');
      } finally {
        setIsLoading(false);
      }
    };
    
    loadFeed();
  }, []);

  const handleCreatePost = async () => {
    if (postContent.trim()) {
      try {
        const payload: CreateFeedItemPayload = {
          content: postContent,
          visibility: 'PUBLIC',
          mediaUrls: [] // Can be updated with actual media URLs
        };
        
        const newPost = await socialCommerceAPI.createFeedItem(payload);
        setFeedItems([newPost, ...feedItems]);
        setPostContent('');
      } catch (err) {
        setError('Failed to create post');
      }
    }
  };

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>{error}</div>;

  return (
    <div className="max-w-2xl mx-auto pb-16 md:pb-0">
      <FlashSaleBanner />
      
      {/* Create Post */}
      <div className="bg-white rounded-lg shadow mb-6">
        {/* ... existing create post UI ... */}
      </div>

      {/* Feed Posts */}
      {feedItems.map(item => (
        <FeedPost
          key={item.id}
          feedItem={item}
          onLike={handleLike}
          onComment={handleComment}
        />
      ))}

      <UpsellProducts />
      <RecommendationEngine />
    </div>
  );
};

3. Update the FeedPost component to use FeedItem interface:

interface FeedPostProps {
  feedItem: FeedItem;
  onLike: (feedItemId: string) => Promise<void>;
  onComment: (feedItemId: string, comment: string) => Promise<void>;
}

const FeedPost = ({ feedItem, onLike, onComment }: FeedPostProps) => {
  const [isLiked, setIsLiked] = useState(false);
  const [showComments, setShowComments] = useState(false);
  const [commentText, setCommentText] = useState('');

  const handleLike = async () => {
    try {
      await onLike(feedItem.id);
      setIsLiked(!isLiked);
    } catch (err) {
      console.error('Failed to like post', err);
    }
  };

  const handleCommentSubmit = async () => {
    if (commentText.trim()) {
      try {
        await onComment(feedItem.id, commentText);
        setCommentText('');
      } catch (err) {
        console.error('Failed to post comment', err);
      }
    }
  };

  return (
    <div className="bg-white rounded-lg shadow mb-6">
      {/* Post Header */}
      <div className="flex items-center p-4">
        <img
          src={feedItem.user?.avatarUrl || '/api/placeholder/40/40'}
          alt={feedItem.user?.username}
          className="w-10 h-10 rounded-full mr-3"
        />
        <div className="flex-1">
          <h3 className="font-semibold text-gray-900">{feedItem.user?.username}</h3>
          <p className="text-sm text-gray-500">
            {new Date(feedItem.timestamp).toLocaleString()}
          </p>
        </div>
      </div>

      {/* Post Content */}
      <div className="px-4 pb-3">
        <p className="text-gray-800">{feedItem.content}</p>
      </div>

      {/* Media */}
      {feedItem.mediaUrls.length > 0 && (
        <div className="relative">
          <img
            src={feedItem.mediaUrls[0]}
            alt="Post content"
            className="w-full h-96 object-cover"
          />
        </div>
      )}

      {/* Post Actions */}
      <div className="p-4">
        <div className="flex items-center space-x-4 mb-3">
          <button onClick={handleLike} className="flex items-center space-x-1">
            <Heart size={20} fill={isLiked ? 'currentColor' : 'none'} />
            <span className="text-sm">{feedItem.likeCount}</span>
          </button>
          <button 
            onClick={() => setShowComments(!showComments)}
            className="flex items-center space-x-1"
          >
            <MessageCircle size={20} />
            <span className="text-sm">{feedItem.commentCount}</span>
          </button>
          <button className="flex items-center space-x-1">
            <Share size={20} />
            <span className="text-sm">{feedItem.shareCount}</span>
          </button>
        </div>

        {showComments && (
          <div className="border-t pt-3">
            {/* Comments would be fetched separately */}
            <div className="space-y-2">
              {/* Comment list would go here */}
            </div>
            <div className="flex space-x-2 mt-3">
              <input
                type="text"
                value={commentText}
                onChange={(e) => setCommentText(e.target.value)}
                placeholder="Write a comment..."
                className="flex-1 px-3 py-2 border rounded-full"
              />
              <button onClick={handleCommentSubmit}>
                <Send size={16} />
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

4. Update ProductBubbleScroll with real product data:

const ProductBubbleScroll = () => {
  const [selectedCategory, setSelectedCategory] = useState<ProductCategory | 'all'>('all');
  const [products, setProducts] = useState<Product[]>([]);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const loadProducts = async () => {
      try {
        // Assuming we have a productAPI instance available
        const allProducts = await productAPI.listProducts();
        setProducts(allProducts);
      } catch (err) {
        console.error('Failed to load products', err);
      } finally {
        setIsLoading(false);
      }
    };
    
    loadProducts();
  }, []);

  const filteredProducts = selectedCategory === 'all'
    ? products
    : products.filter(product => product.category === selectedCategory);

  // ... rest of the component remains similar, but uses real product data
};

5. Implement caching strategy for product data:

const getProductWithCache = async (productId: string): Promise<ProductAPIResponse> => {
  try {
    // First try to get from gateway service with caching
    const response = await gatewayAPI.getProduct(productId);
    if (response.cached) {
      console.log('Served from cache');
    }
    return response.data;
  } catch (err) {
    console.error('Failed to fetch product with cache', err);
    // Fallback to direct API call
    return await productAPI.getProductById(parseInt(productId));
  }
};

6. Update MessagesContent to use Message interface:

const MessagesContent = () => {
  const [conversations, setConversations] = useState<Message[]>([]);
  const [selectedConversation, setSelectedConversation] = useState<Message | null>(null);

  useEffect(() => {
    const loadConversations = async () => {
      try {
        const user = await getCurrentUser();
        const messages = await socialCommerceAPI.getConversation(user.id);
        setConversations(messages);
      } catch (err) {
        console.error('Failed to load conversations', err);
      }
    };
    
    loadConversations();
  }, []);

  // ... rest of the component implementation
};

7. Error handling and loading states:

Add proper error boundaries and loading states throughout the components to handle API failures gracefully.

8. Implement service hooks:

Create custom hooks to manage the service interactions:

function useFeed() {
  const [feed, setFeed] = useState<FeedItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const loadFeed = async () => {
      try {
        const user = await getCurrentUser();
        const data = await socialCommerceAPI.getFeed(user.id);
        setFeed(data);
      } catch (err) {
        setError('Failed to load feed');
      } finally {
        setLoading(false);
      }
    };
    
    loadFeed();
  }, []);

  const createPost = async (content: string) => {
    try {
      const payload: CreateFeedItemPayload = {
        content,
        visibility: 'PUBLIC'
      };
      const newPost = await socialCommerceAPI.createFeedItem(payload);
      setFeed(prev => [newPost, ...prev]);
    } catch (err) {
      setError('Failed to create post');
    }
  };

  return { feed, loading, error, createPost };
}

These changes integrate the FeedPage with the backend services while maintaining the existing UI structure. The key improvements are:

  1. Type safety using the backend.d.ts interfaces
  2. Real data fetching from the social commerce and product services
  3. Caching strategy implementation
  4. Proper error handling and loading states
  5. Separation of concerns with service hooks

You'll need to ensure you have the actual service implementations available in your application context to make the API calls. The exact implementation might vary based on how you're managing your API clients and application state.

⚠️ **GitHub.com Fallback** ⚠️