> ## Documentation Index
> Fetch the complete documentation index at: https://twigz.arqqin.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Real-time Features

> Complete guide to implementing real-time functionality

# Real-time Features

This guide covers implementing real-time features using Convex in your Twigz application.

## Overview

Twigz is built on Convex, which provides automatic real-time subscriptions and live data updates.

## Basic Real-time Setup

### 1. Convex Client Setup

```typescript theme={null}
import { ConvexProvider, ConvexReactClient } from "convex/react";

const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

function App() {
  return (
    <ConvexProvider client={convex}>
      <YourApp />
    </ConvexProvider>
  );
}
```

### 2. Real-time Queries

```typescript theme={null}
import { useQuery } from "convex/react";
import { api } from "../convex/_generated/api";

// This automatically updates when data changes
const products = useQuery(api.shared.products.getProducts, {
  storeId: "store_123"
});

// This updates in real-time
const orders = useQuery(api.customers.orders.getCustomerOrders, {
  customerId: "user_123"
});
```

## Real-time Features Implementation

### 1. Live Order Tracking

```typescript theme={null}
const OrderTracker = ({ orderId }) => {
  const order = useQuery(api.customers.orders.getOrder, { orderId });
  
  if (!order) return <div>Loading...</div>;
  
  return (
    <div className="order-tracker">
      <h3>Order #{order.id}</h3>
      <div className="status">
        Status: <span className={order.status}>{order.status}</span>
      </div>
      
      <div className="timeline">
        {order.statusHistory.map((status, index) => (
          <div key={index} className={`timeline-item ${status.completed ? 'completed' : ''}`}>
            <div className="timeline-marker"></div>
            <div className="timeline-content">
              <h4>{status.status}</h4>
              <p>{status.timestamp}</p>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};
```

### 2. Live Inventory Updates

```typescript theme={null}
const ProductCard = ({ productId }) => {
  const product = useQuery(api.shared.products.getProductById, { productId });
  
  if (!product) return <div>Loading...</div>;
  
  const isInStock = product.quantity > 0;
  
  return (
    <div className={`product-card ${!isInStock ? 'out-of-stock' : ''}`}>
      <h3>{product.name}</h3>
      <p>Price: {product.price} AED</p>
      <p className={isInStock ? 'in-stock' : 'out-of-stock'}>
        {isInStock ? `${product.quantity} in stock` : 'Out of stock'}
      </p>
      
      <button 
        disabled={!isInStock}
        onClick={() => addToCart(productId)}
      >
        {isInStock ? 'Add to Cart' : 'Out of Stock'}
      </button>
    </div>
  );
};
```

### 3. Live Chat/Messaging

```typescript theme={null}
const ChatRoom = ({ storeId }) => {
  const messages = useQuery(api.stores.queries.getStoreMessages, { storeId });
  const [newMessage, setNewMessage] = useState("");
  
  const sendMessage = useMutation(api.stores.operations.sendMessage);
  
  const handleSend = async () => {
    if (newMessage.trim()) {
      await sendMessage({
        storeId,
        message: newMessage,
        senderId: currentUser.id
      });
      setNewMessage("");
    }
  };
  
  return (
    <div className="chat-room">
      <div className="messages">
        {messages?.map((message) => (
          <div key={message.id} className="message">
            <strong>{message.senderName}:</strong> {message.text}
            <span className="timestamp">{message.timestamp}</span>
          </div>
        ))}
      </div>
      
      <div className="message-input">
        <input
          value={newMessage}
          onChange={(e) => setNewMessage(e.target.value)}
          placeholder="Type a message..."
          onKeyPress={(e) => e.key === 'Enter' && handleSend()}
        />
        <button onClick={handleSend}>Send</button>
      </div>
    </div>
  );
};
```

## Real-time Notifications

### 1. Push Notifications

```typescript theme={null}
const NotificationManager = () => {
  const notifications = useQuery(api.shared.notifications.getNotifications, {
    userId: currentUser.id
  });
  
  useEffect(() => {
    // Request notification permission
    if ('Notification' in window) {
      Notification.requestPermission();
    }
  }, []);
  
  useEffect(() => {
    if (notifications?.length > 0) {
      const latestNotification = notifications[0];
      
      // Show browser notification
      if (Notification.permission === 'granted') {
        new Notification(latestNotification.title, {
          body: latestNotification.body,
          icon: '/logo.png'
        });
      }
    }
  }, [notifications]);
  
  return (
    <div className="notifications">
      {notifications?.map((notification) => (
        <div key={notification.id} className="notification">
          <h4>{notification.title}</h4>
          <p>{notification.body}</p>
          <span className="time">{notification.timestamp}</span>
        </div>
      ))}
    </div>
  );
};
```

### 2. Live Feed Updates

```typescript theme={null}
const LiveFeed = () => {
  const feed = useQuery(api.customers.feed.getFeed, {
    userId: currentUser.id,
    limit: 20
  });
  
  return (
    <div className="live-feed">
      <h2>Live Feed</h2>
      {feed?.map((item) => (
        <div key={item.id} className="feed-item">
          <div className="feed-header">
            <img src={item.storeLogo} alt={item.storeName} />
            <div>
              <h3>{item.storeName}</h3>
              <span className="time">{item.timestamp}</span>
            </div>
          </div>
          
          <div className="feed-content">
            <h4>{item.title}</h4>
            <p>{item.description}</p>
            {item.image && <img src={item.image} alt="Feed image" />}
          </div>
          
          <div className="feed-actions">
            <button onClick={() => likeItem(item.id)}>
              ❤️ {item.likes}
            </button>
            <button onClick={() => shareItem(item.id)}>
              📤 Share
            </button>
          </div>
        </div>
      ))}
    </div>
  );
};
```

## Real-time Analytics

### 1. Live Dashboard

```typescript theme={null}
const StoreDashboard = ({ storeId }) => {
  const dashboard = useQuery(api.stores.dashboard.getDashboardOverview, { storeId });
  const topProducts = useQuery(api.stores.dashboard.getTopSellingProducts, { storeId });
  const recentOrders = useQuery(api.stores.dashboard.getRecentOrders, { storeId });
  
  if (!dashboard) return <div>Loading dashboard...</div>;
  
  return (
    <div className="dashboard">
      <div className="stats-grid">
        <div className="stat-card">
          <h3>Total Sales</h3>
          <p className="stat-value">{dashboard.totalSales} AED</p>
          <span className="stat-change">+{dashboard.salesGrowth}%</span>
        </div>
        
        <div className="stat-card">
          <h3>Orders Today</h3>
          <p className="stat-value">{dashboard.ordersToday}</p>
          <span className="stat-change">+{dashboard.orderGrowth}%</span>
        </div>
        
        <div className="stat-card">
          <h3>Active Products</h3>
          <p className="stat-value">{dashboard.activeProducts}</p>
        </div>
      </div>
      
      <div className="dashboard-sections">
        <div className="top-products">
          <h3>Top Selling Products</h3>
          {topProducts?.map((product) => (
            <div key={product.id} className="product-item">
              <span>{product.name}</span>
              <span>{product.sales} sold</span>
            </div>
          ))}
        </div>
        
        <div className="recent-orders">
          <h3>Recent Orders</h3>
          {recentOrders?.map((order) => (
            <div key={order.id} className="order-item">
              <span>Order #{order.id}</span>
              <span>{order.total} AED</span>
              <span className={`status ${order.status}`}>{order.status}</span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};
```

## Performance Optimization

### 1. Selective Subscriptions

```typescript theme={null}
// Only subscribe to data you need
const ProductList = ({ storeId, category }) => {
  // This will only re-render when products in this category change
  const products = useQuery(api.shared.products.getProducts, {
    storeId,
    category,
    limit: 20
  });
  
  return (
    <div>
      {products?.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
};
```

### 2. Optimistic Updates

```typescript theme={null}
const useOptimisticLike = () => {
  const likeProduct = useMutation(api.customers.feed.likeProduct);
  
  const optimisticLike = async (productId: string) => {
    // Optimistically update UI
    setLikedProducts(prev => [...prev, productId]);
    
    try {
      await likeProduct({ productId });
    } catch (error) {
      // Revert on error
      setLikedProducts(prev => prev.filter(id => id !== productId));
    }
  };
  
  return { optimisticLike };
};
```

## Best Practices

1. **Use selective subscriptions** - only subscribe to data you need
2. **Handle loading states** - always check for undefined
3. **Implement error boundaries** - handle subscription errors gracefully
4. **Use optimistic updates** - for better perceived performance
5. **Debounce rapid updates** - to avoid excessive re-renders
6. **Clean up subscriptions** - when components unmount

<Note>
  Real-time features work automatically with Convex - no additional setup required! Just use `useQuery` and your data will update in real-time.
</Note>
